1 /* $NetBSD: tsig.c,v 1.15 2025/05/21 14:48:03 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 /*! \file */ 17 18 #include <inttypes.h> 19 #include <stdbool.h> 20 #include <stdlib.h> 21 22 #include <isc/buffer.h> 23 #include <isc/hashmap.h> 24 #include <isc/mem.h> 25 #include <isc/refcount.h> 26 #include <isc/result.h> 27 #include <isc/serial.h> 28 #include <isc/string.h> 29 #include <isc/time.h> 30 #include <isc/util.h> 31 32 #include <dns/fixedname.h> 33 #include <dns/keyvalues.h> 34 #include <dns/log.h> 35 #include <dns/message.h> 36 #include <dns/rdata.h> 37 #include <dns/rdatalist.h> 38 #include <dns/rdataset.h> 39 #include <dns/rdatastruct.h> 40 #include <dns/tsig.h> 41 42 #include "tsig_p.h" 43 44 #define TSIGKEYRING_MAGIC ISC_MAGIC('T', 'K', 'R', 'g') 45 #define VALID_TSIGKEYRING(x) ISC_MAGIC_VALID(x, TSIGKEYRING_MAGIC) 46 47 #define TSIG_MAGIC ISC_MAGIC('T', 'S', 'I', 'G') 48 #define VALID_TSIGKEY(x) ISC_MAGIC_VALID(x, TSIG_MAGIC) 49 50 #define is_response(msg) ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) 51 52 #define BADTIMELEN 6 53 54 static unsigned char hmacmd5_ndata[] = "\010hmac-md5\007sig-alg\003reg\003int"; 55 static unsigned char hmacmd5_offsets[] = { 0, 9, 17, 21, 25 }; 56 57 static dns_name_t const hmacmd5 = DNS_NAME_INITABSOLUTE(hmacmd5_ndata, 58 hmacmd5_offsets); 59 const dns_name_t *dns_tsig_hmacmd5_name = &hmacmd5; 60 61 static unsigned char gsstsig_ndata[] = "\010gss-tsig"; 62 static unsigned char gsstsig_offsets[] = { 0, 9 }; 63 static dns_name_t const gsstsig = DNS_NAME_INITABSOLUTE(gsstsig_ndata, 64 gsstsig_offsets); 65 const dns_name_t *dns_tsig_gssapi_name = &gsstsig; 66 67 static unsigned char hmacsha1_ndata[] = "\011hmac-sha1"; 68 static unsigned char hmacsha1_offsets[] = { 0, 10 }; 69 static dns_name_t const hmacsha1 = DNS_NAME_INITABSOLUTE(hmacsha1_ndata, 70 hmacsha1_offsets); 71 const dns_name_t *dns_tsig_hmacsha1_name = &hmacsha1; 72 73 static unsigned char hmacsha224_ndata[] = "\013hmac-sha224"; 74 static unsigned char hmacsha224_offsets[] = { 0, 12 }; 75 static dns_name_t const hmacsha224 = DNS_NAME_INITABSOLUTE(hmacsha224_ndata, 76 hmacsha224_offsets); 77 const dns_name_t *dns_tsig_hmacsha224_name = &hmacsha224; 78 79 static unsigned char hmacsha256_ndata[] = "\013hmac-sha256"; 80 static unsigned char hmacsha256_offsets[] = { 0, 12 }; 81 static dns_name_t const hmacsha256 = DNS_NAME_INITABSOLUTE(hmacsha256_ndata, 82 hmacsha256_offsets); 83 const dns_name_t *dns_tsig_hmacsha256_name = &hmacsha256; 84 85 static unsigned char hmacsha384_ndata[] = "\013hmac-sha384"; 86 static unsigned char hmacsha384_offsets[] = { 0, 12 }; 87 static dns_name_t const hmacsha384 = DNS_NAME_INITABSOLUTE(hmacsha384_ndata, 88 hmacsha384_offsets); 89 const dns_name_t *dns_tsig_hmacsha384_name = &hmacsha384; 90 91 static unsigned char hmacsha512_ndata[] = "\013hmac-sha512"; 92 static unsigned char hmacsha512_offsets[] = { 0, 12 }; 93 static dns_name_t const hmacsha512 = DNS_NAME_INITABSOLUTE(hmacsha512_ndata, 94 hmacsha512_offsets); 95 const dns_name_t *dns_tsig_hmacsha512_name = &hmacsha512; 96 97 static const struct { 98 const dns_name_t *name; 99 unsigned int dstalg; 100 } known_algs[] = { { &hmacmd5, DST_ALG_HMACMD5 }, 101 { &gsstsig, DST_ALG_GSSAPI }, 102 { &hmacsha1, DST_ALG_HMACSHA1 }, 103 { &hmacsha224, DST_ALG_HMACSHA224 }, 104 { &hmacsha256, DST_ALG_HMACSHA256 }, 105 { &hmacsha384, DST_ALG_HMACSHA384 }, 106 { &hmacsha512, DST_ALG_HMACSHA512 } }; 107 108 static isc_result_t 109 tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg); 110 111 static void 112 tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) 113 ISC_FORMAT_PRINTF(3, 4); 114 115 bool 116 dns__tsig_algvalid(unsigned int alg) { 117 return alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 || 118 alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || 119 alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512; 120 } 121 122 static void 123 tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) { 124 va_list ap; 125 char message[4096]; 126 char namestr[DNS_NAME_FORMATSIZE]; 127 char creatorstr[DNS_NAME_FORMATSIZE]; 128 129 if (!isc_log_wouldlog(dns_lctx, level)) { 130 return; 131 } 132 if (key != NULL) { 133 dns_name_format(key->name, namestr, sizeof(namestr)); 134 } else { 135 strlcpy(namestr, "<null>", sizeof(namestr)); 136 } 137 138 if (key != NULL && key->generated && key->creator != NULL) { 139 dns_name_format(key->creator, creatorstr, sizeof(creatorstr)); 140 } else { 141 strlcpy(creatorstr, "<null>", sizeof(creatorstr)); 142 } 143 144 va_start(ap, fmt); 145 vsnprintf(message, sizeof(message), fmt, ap); 146 va_end(ap); 147 if (key != NULL && key->generated) { 148 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 149 DNS_LOGMODULE_TSIG, level, 150 "tsig key '%s' (%s): %s", namestr, creatorstr, 151 message); 152 } else { 153 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 154 DNS_LOGMODULE_TSIG, level, "tsig key '%s': %s", 155 namestr, message); 156 } 157 } 158 159 static bool 160 tkey_match(void *node, const void *key) { 161 dns_tsigkey_t *tkey = node; 162 163 return dns_name_equal(tkey->name, key); 164 } 165 166 static bool 167 match_ptr(void *node, const void *key) { 168 return node == key; 169 } 170 171 static void 172 rm_hashmap(dns_tsigkey_t *tkey) { 173 REQUIRE(VALID_TSIGKEY(tkey)); 174 REQUIRE(VALID_TSIGKEYRING(tkey->ring)); 175 176 (void)isc_hashmap_delete(tkey->ring->keys, dns_name_hash(tkey->name), 177 match_ptr, tkey); 178 dns_tsigkey_detach(&tkey); 179 } 180 181 static void 182 rm_lru(dns_tsigkey_t *tkey) { 183 REQUIRE(VALID_TSIGKEY(tkey)); 184 REQUIRE(VALID_TSIGKEYRING(tkey->ring)); 185 186 if (tkey->generated && ISC_LINK_LINKED(tkey, link)) { 187 ISC_LIST_UNLINK(tkey->ring->lru, tkey, link); 188 tkey->ring->generated--; 189 dns_tsigkey_unref(tkey); 190 } 191 } 192 193 static void 194 adjust_lru(dns_tsigkey_t *tkey) { 195 if (tkey->generated) { 196 RWLOCK(&tkey->ring->lock, isc_rwlocktype_write); 197 /* 198 * We may have been removed from the LRU list between 199 * removing the read lock and acquiring the write lock. 200 */ 201 if (ISC_LINK_LINKED(tkey, link) && tkey->ring->lru.tail != tkey) 202 { 203 ISC_LIST_UNLINK(tkey->ring->lru, tkey, link); 204 ISC_LIST_APPEND(tkey->ring->lru, tkey, link); 205 } 206 RWUNLOCK(&tkey->ring->lock, isc_rwlocktype_write); 207 } 208 } 209 210 isc_result_t 211 dns_tsigkey_createfromkey(const dns_name_t *name, dst_algorithm_t algorithm, 212 dst_key_t *dstkey, bool generated, bool restored, 213 const dns_name_t *creator, isc_stdtime_t inception, 214 isc_stdtime_t expire, isc_mem_t *mctx, 215 dns_tsigkey_t **keyp) { 216 dns_tsigkey_t *tkey = NULL; 217 isc_result_t result; 218 219 REQUIRE(keyp != NULL && *keyp == NULL); 220 REQUIRE(name != NULL); 221 REQUIRE(mctx != NULL); 222 223 tkey = isc_mem_get(mctx, sizeof(dns_tsigkey_t)); 224 *tkey = (dns_tsigkey_t){ 225 .generated = generated, 226 .restored = restored, 227 .inception = inception, 228 .expire = expire, 229 .alg = algorithm, 230 .algname = DNS_NAME_INITEMPTY, 231 .link = ISC_LINK_INITIALIZER, 232 }; 233 234 tkey->name = dns_fixedname_initname(&tkey->fn); 235 dns_name_copy(name, tkey->name); 236 (void)dns_name_downcase(tkey->name, tkey->name, NULL); 237 238 if (algorithm != DST_ALG_UNKNOWN) { 239 if (dstkey != NULL && dst_key_alg(dstkey) != algorithm) { 240 result = DNS_R_BADALG; 241 goto cleanup_name; 242 } 243 } else if (dstkey != NULL) { 244 result = DNS_R_BADALG; 245 goto cleanup_name; 246 } 247 248 if (creator != NULL) { 249 tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t)); 250 dns_name_init(tkey->creator, NULL); 251 dns_name_dup(creator, mctx, tkey->creator); 252 } 253 254 if (dstkey != NULL) { 255 dst_key_attach(dstkey, &tkey->key); 256 } 257 258 isc_refcount_init(&tkey->references, 1); 259 isc_mem_attach(mctx, &tkey->mctx); 260 261 /* 262 * Ignore this if it's a GSS key, since the key size is meaningless. 263 */ 264 if (dstkey != NULL && dst_key_size(dstkey) < 64 && 265 algorithm != DST_ALG_GSSAPI) 266 { 267 char namestr[DNS_NAME_FORMATSIZE]; 268 dns_name_format(name, namestr, sizeof(namestr)); 269 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 270 DNS_LOGMODULE_TSIG, ISC_LOG_INFO, 271 "the key '%s' is too short to be secure", 272 namestr); 273 } 274 275 tkey->magic = TSIG_MAGIC; 276 277 if (tkey->restored) { 278 tsig_log(tkey, ISC_LOG_DEBUG(3), "restored from file"); 279 } else if (tkey->generated) { 280 tsig_log(tkey, ISC_LOG_DEBUG(3), "generated"); 281 } else { 282 tsig_log(tkey, ISC_LOG_DEBUG(3), "statically configured"); 283 } 284 285 SET_IF_NOT_NULL(keyp, tkey); 286 return ISC_R_SUCCESS; 287 288 cleanup_name: 289 isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t)); 290 291 return result; 292 } 293 294 static void 295 destroyring(dns_tsigkeyring_t *ring) { 296 isc_result_t result; 297 isc_hashmap_iter_t *it = NULL; 298 299 RWLOCK(&ring->lock, isc_rwlocktype_write); 300 isc_hashmap_iter_create(ring->keys, &it); 301 for (result = isc_hashmap_iter_first(it); result == ISC_R_SUCCESS; 302 result = isc_hashmap_iter_delcurrent_next(it)) 303 { 304 dns_tsigkey_t *tkey = NULL; 305 isc_hashmap_iter_current(it, (void **)&tkey); 306 rm_lru(tkey); 307 dns_tsigkey_detach(&tkey); 308 } 309 isc_hashmap_iter_destroy(&it); 310 isc_hashmap_destroy(&ring->keys); 311 RWUNLOCK(&ring->lock, isc_rwlocktype_write); 312 313 ring->magic = 0; 314 315 isc_rwlock_destroy(&ring->lock); 316 isc_mem_putanddetach(&ring->mctx, ring, sizeof(dns_tsigkeyring_t)); 317 } 318 319 #if DNS_TSIG_TRACE 320 ISC_REFCOUNT_TRACE_IMPL(dns_tsigkeyring, destroyring); 321 #else 322 ISC_REFCOUNT_IMPL(dns_tsigkeyring, destroyring); 323 #endif 324 325 /* 326 * Look up the DST_ALG_ constant for a given name. 327 */ 328 dst_algorithm_t 329 dns__tsig_algfromname(const dns_name_t *algorithm) { 330 for (size_t i = 0; i < ARRAY_SIZE(known_algs); ++i) { 331 const dns_name_t *name = known_algs[i].name; 332 if (algorithm == name || dns_name_equal(algorithm, name)) { 333 return known_algs[i].dstalg; 334 } 335 } 336 return DST_ALG_UNKNOWN; 337 } 338 339 static isc_result_t 340 restore_key(dns_tsigkeyring_t *ring, isc_stdtime_t now, FILE *fp) { 341 dst_key_t *dstkey = NULL; 342 char namestr[1024]; 343 char creatorstr[1024]; 344 char algorithmstr[1024]; 345 char keystr[4096]; 346 unsigned int inception, expire; 347 int n; 348 isc_buffer_t b; 349 dns_name_t *name = NULL, *creator = NULL, *algorithm = NULL; 350 dns_fixedname_t fname, fcreator, falgorithm; 351 isc_result_t result; 352 unsigned int dstalg; 353 dns_tsigkey_t *tkey = NULL; 354 355 n = fscanf(fp, "%1023s %1023s %u %u %1023s %4095s\n", namestr, 356 creatorstr, &inception, &expire, algorithmstr, keystr); 357 if (n == EOF) { 358 return ISC_R_NOMORE; 359 } 360 if (n != 6) { 361 return ISC_R_FAILURE; 362 } 363 364 if (isc_serial_lt(expire, now)) { 365 return DNS_R_EXPIRED; 366 } 367 368 name = dns_fixedname_initname(&fname); 369 isc_buffer_init(&b, namestr, strlen(namestr)); 370 isc_buffer_add(&b, strlen(namestr)); 371 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); 372 if (result != ISC_R_SUCCESS) { 373 return result; 374 } 375 376 creator = dns_fixedname_initname(&fcreator); 377 isc_buffer_init(&b, creatorstr, strlen(creatorstr)); 378 isc_buffer_add(&b, strlen(creatorstr)); 379 result = dns_name_fromtext(creator, &b, dns_rootname, 0, NULL); 380 if (result != ISC_R_SUCCESS) { 381 return result; 382 } 383 384 algorithm = dns_fixedname_initname(&falgorithm); 385 isc_buffer_init(&b, algorithmstr, strlen(algorithmstr)); 386 isc_buffer_add(&b, strlen(algorithmstr)); 387 result = dns_name_fromtext(algorithm, &b, dns_rootname, 0, NULL); 388 if (result != ISC_R_SUCCESS) { 389 return result; 390 } 391 392 dstalg = dns__tsig_algfromname(algorithm); 393 if (dstalg == DST_ALG_UNKNOWN) { 394 return DNS_R_BADALG; 395 } 396 397 result = dst_key_restore(name, dstalg, DNS_KEYOWNER_ENTITY, 398 DNS_KEYPROTO_DNSSEC, dns_rdataclass_in, 399 ring->mctx, keystr, &dstkey); 400 if (result != ISC_R_SUCCESS) { 401 return result; 402 } 403 404 result = dns_tsigkey_createfromkey(name, dstalg, dstkey, true, true, 405 creator, inception, expire, 406 ring->mctx, &tkey); 407 if (result == ISC_R_SUCCESS) { 408 result = dns_tsigkeyring_add(ring, tkey); 409 } 410 dns_tsigkey_detach(&tkey); 411 if (dstkey != NULL) { 412 dst_key_free(&dstkey); 413 } 414 return result; 415 } 416 417 static void 418 dump_key(dns_tsigkey_t *tkey, FILE *fp) { 419 char *buffer = NULL; 420 int length = 0; 421 char namestr[DNS_NAME_FORMATSIZE]; 422 char creatorstr[DNS_NAME_FORMATSIZE]; 423 char algorithmstr[DNS_NAME_FORMATSIZE]; 424 isc_result_t result; 425 426 REQUIRE(tkey != NULL); 427 REQUIRE(fp != NULL); 428 429 dns_name_format(tkey->name, namestr, sizeof(namestr)); 430 dns_name_format(tkey->creator, creatorstr, sizeof(creatorstr)); 431 dns_name_format(dns_tsigkey_algorithm(tkey), algorithmstr, 432 sizeof(algorithmstr)); 433 result = dst_key_dump(tkey->key, tkey->mctx, &buffer, &length); 434 if (result == ISC_R_SUCCESS) { 435 fprintf(fp, "%s %s %u %u %s %.*s\n", namestr, creatorstr, 436 tkey->inception, tkey->expire, algorithmstr, length, 437 buffer); 438 } 439 if (buffer != NULL) { 440 isc_mem_put(tkey->mctx, buffer, length); 441 } 442 } 443 444 isc_result_t 445 dns_tsigkeyring_dump(dns_tsigkeyring_t *ring, FILE *fp) { 446 isc_result_t result; 447 isc_stdtime_t now = isc_stdtime_now(); 448 isc_hashmap_iter_t *it = NULL; 449 bool found = false; 450 451 REQUIRE(VALID_TSIGKEYRING(ring)); 452 453 RWLOCK(&ring->lock, isc_rwlocktype_read); 454 isc_hashmap_iter_create(ring->keys, &it); 455 for (result = isc_hashmap_iter_first(it); result == ISC_R_SUCCESS; 456 result = isc_hashmap_iter_next(it)) 457 { 458 dns_tsigkey_t *tkey = NULL; 459 isc_hashmap_iter_current(it, (void **)&tkey); 460 461 if (tkey->generated && tkey->expire >= now) { 462 dump_key(tkey, fp); 463 found = true; 464 } 465 } 466 isc_hashmap_iter_destroy(&it); 467 RWUNLOCK(&ring->lock, isc_rwlocktype_read); 468 469 return found ? ISC_R_SUCCESS : ISC_R_NOTFOUND; 470 } 471 472 const dns_name_t * 473 dns_tsigkey_identity(const dns_tsigkey_t *tsigkey) { 474 REQUIRE(tsigkey == NULL || VALID_TSIGKEY(tsigkey)); 475 476 if (tsigkey == NULL) { 477 return NULL; 478 } 479 if (tsigkey->generated) { 480 return tsigkey->creator; 481 } else { 482 return tsigkey->name; 483 } 484 } 485 486 isc_result_t 487 dns_tsigkey_create(const dns_name_t *name, dst_algorithm_t algorithm, 488 unsigned char *secret, int length, isc_mem_t *mctx, 489 dns_tsigkey_t **key) { 490 dst_key_t *dstkey = NULL; 491 isc_result_t result; 492 493 REQUIRE(length >= 0); 494 if (length > 0) { 495 REQUIRE(secret != NULL); 496 } 497 498 if (dns__tsig_algvalid(algorithm)) { 499 if (secret != NULL) { 500 isc_buffer_t b; 501 502 isc_buffer_init(&b, secret, length); 503 isc_buffer_add(&b, length); 504 result = dst_key_frombuffer( 505 name, algorithm, DNS_KEYOWNER_ENTITY, 506 DNS_KEYPROTO_DNSSEC, dns_rdataclass_in, &b, 507 mctx, &dstkey); 508 if (result != ISC_R_SUCCESS) { 509 return result; 510 } 511 } 512 } else if (length > 0) { 513 return DNS_R_BADALG; 514 } 515 516 result = dns_tsigkey_createfromkey(name, algorithm, dstkey, false, 517 false, NULL, 0, 0, mctx, key); 518 if (dstkey != NULL) { 519 dst_key_free(&dstkey); 520 } 521 return result; 522 } 523 524 static void 525 destroy_tsigkey(dns_tsigkey_t *key) { 526 REQUIRE(VALID_TSIGKEY(key)); 527 528 key->magic = 0; 529 if (key->key != NULL) { 530 dst_key_free(&key->key); 531 } 532 if (key->creator != NULL) { 533 dns_name_free(key->creator, key->mctx); 534 isc_mem_put(key->mctx, key->creator, sizeof(dns_name_t)); 535 } 536 isc_mem_putanddetach(&key->mctx, key, sizeof(dns_tsigkey_t)); 537 } 538 539 #if DNS_TSIG_TRACE 540 ISC_REFCOUNT_TRACE_IMPL(dns_tsigkey, destroy_tsigkey); 541 #else 542 ISC_REFCOUNT_IMPL(dns_tsigkey, destroy_tsigkey); 543 #endif 544 545 void 546 dns_tsigkey_delete(dns_tsigkey_t *key) { 547 REQUIRE(VALID_TSIGKEY(key)); 548 549 RWLOCK(&key->ring->lock, isc_rwlocktype_write); 550 rm_lru(key); 551 rm_hashmap(key); 552 RWUNLOCK(&key->ring->lock, isc_rwlocktype_write); 553 } 554 555 isc_result_t 556 dns_tsig_sign(dns_message_t *msg) { 557 dns_tsigkey_t *key = NULL; 558 dns_rdata_any_tsig_t tsig, querytsig; 559 unsigned char data[128]; 560 isc_buffer_t databuf, sigbuf; 561 isc_buffer_t *dynbuf = NULL; 562 dns_name_t *owner = NULL; 563 dns_rdata_t *rdata = NULL; 564 dns_rdatalist_t *datalist = NULL; 565 dns_rdataset_t *dataset = NULL; 566 isc_region_t r; 567 isc_stdtime_t now; 568 isc_mem_t *mctx = NULL; 569 dst_context_t *ctx = NULL; 570 isc_result_t result; 571 unsigned char badtimedata[BADTIMELEN]; 572 unsigned int sigsize = 0; 573 bool response; 574 575 REQUIRE(msg != NULL); 576 key = dns_message_gettsigkey(msg); 577 REQUIRE(VALID_TSIGKEY(key)); 578 579 /* 580 * If this is a response, there should be a TSIG in the query with the 581 * the exception if this is a TKEY request (see RFC 3645, Section 2.2). 582 */ 583 response = is_response(msg); 584 if (response && msg->querytsig == NULL) { 585 if (msg->tkey != 1) { 586 return DNS_R_EXPECTEDTSIG; 587 } 588 } 589 590 mctx = msg->mctx; 591 592 now = msg->fuzzing ? msg->fuzztime : isc_stdtime_now(); 593 tsig = (dns_rdata_any_tsig_t){ 594 .mctx = mctx, 595 .common.rdclass = dns_rdataclass_any, 596 .common.rdtype = dns_rdatatype_tsig, 597 .common.link = ISC_LINK_INITIALIZER, 598 .timesigned = now + msg->timeadjust, 599 .fudge = DNS_TSIG_FUDGE, 600 .originalid = msg->id, 601 .error = response ? msg->querytsigstatus : dns_rcode_noerror, 602 }; 603 604 dns_name_init(&tsig.algorithm, NULL); 605 dns_name_clone(dns_tsigkey_algorithm(key), &tsig.algorithm); 606 607 isc_buffer_init(&databuf, data, sizeof(data)); 608 609 if (tsig.error == dns_tsigerror_badtime) { 610 isc_buffer_t otherbuf; 611 612 tsig.otherlen = BADTIMELEN; 613 tsig.other = badtimedata; 614 isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen); 615 isc_buffer_putuint48(&otherbuf, tsig.timesigned); 616 } 617 618 if ((key->key != NULL) && (tsig.error != dns_tsigerror_badsig) && 619 (tsig.error != dns_tsigerror_badkey)) 620 { 621 unsigned char header[DNS_MESSAGE_HEADERLEN]; 622 isc_buffer_t headerbuf; 623 uint16_t digestbits; 624 bool querytsig_ok = false; 625 626 /* 627 * If it is a response, we assume that the request MAC 628 * has validated at this point. This is why we include a 629 * MAC length > 0 in the reply. 630 */ 631 result = dst_context_create( 632 key->key, mctx, DNS_LOGCATEGORY_DNSSEC, true, 0, &ctx); 633 if (result != ISC_R_SUCCESS) { 634 return result; 635 } 636 637 /* 638 * If this is a response, and if there was a TSIG in 639 * the query, digest the request's MAC. 640 * 641 * (Note: querytsig should be non-NULL for all 642 * responses except TKEY responses. Those may be signed 643 * with the newly-negotiated TSIG key even if the query 644 * wasn't signed.) 645 */ 646 if (response && msg->querytsig != NULL) { 647 dns_rdata_t querytsigrdata = DNS_RDATA_INIT; 648 649 INSIST(msg->verified_sig); 650 651 result = dns_rdataset_first(msg->querytsig); 652 if (result != ISC_R_SUCCESS) { 653 goto cleanup_context; 654 } 655 dns_rdataset_current(msg->querytsig, &querytsigrdata); 656 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, 657 NULL); 658 if (result != ISC_R_SUCCESS) { 659 goto cleanup_context; 660 } 661 isc_buffer_putuint16(&databuf, querytsig.siglen); 662 if (isc_buffer_availablelength(&databuf) < 663 querytsig.siglen) 664 { 665 result = ISC_R_NOSPACE; 666 goto cleanup_context; 667 } 668 isc_buffer_putmem(&databuf, querytsig.signature, 669 querytsig.siglen); 670 isc_buffer_usedregion(&databuf, &r); 671 result = dst_context_adddata(ctx, &r); 672 if (result != ISC_R_SUCCESS) { 673 goto cleanup_context; 674 } 675 querytsig_ok = true; 676 } 677 678 /* 679 * Digest the header. 680 */ 681 isc_buffer_init(&headerbuf, header, sizeof(header)); 682 dns_message_renderheader(msg, &headerbuf); 683 isc_buffer_usedregion(&headerbuf, &r); 684 result = dst_context_adddata(ctx, &r); 685 if (result != ISC_R_SUCCESS) { 686 goto cleanup_context; 687 } 688 689 /* 690 * Digest the remainder of the message. 691 */ 692 isc_buffer_usedregion(msg->buffer, &r); 693 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); 694 result = dst_context_adddata(ctx, &r); 695 if (result != ISC_R_SUCCESS) { 696 goto cleanup_context; 697 } 698 699 if (msg->tcp_continuation == 0) { 700 /* 701 * Digest the name, class, ttl, alg. 702 */ 703 dns_name_toregion(key->name, &r); 704 result = dst_context_adddata(ctx, &r); 705 if (result != ISC_R_SUCCESS) { 706 goto cleanup_context; 707 } 708 709 isc_buffer_clear(&databuf); 710 isc_buffer_putuint16(&databuf, dns_rdataclass_any); 711 isc_buffer_putuint32(&databuf, 0); /* ttl */ 712 isc_buffer_usedregion(&databuf, &r); 713 result = dst_context_adddata(ctx, &r); 714 if (result != ISC_R_SUCCESS) { 715 goto cleanup_context; 716 } 717 718 dns_name_toregion(&tsig.algorithm, &r); 719 result = dst_context_adddata(ctx, &r); 720 if (result != ISC_R_SUCCESS) { 721 goto cleanup_context; 722 } 723 } 724 /* Digest the timesigned and fudge */ 725 isc_buffer_clear(&databuf); 726 if (tsig.error == dns_tsigerror_badtime && querytsig_ok) { 727 tsig.timesigned = querytsig.timesigned; 728 } 729 isc_buffer_putuint48(&databuf, tsig.timesigned); 730 isc_buffer_putuint16(&databuf, tsig.fudge); 731 isc_buffer_usedregion(&databuf, &r); 732 result = dst_context_adddata(ctx, &r); 733 if (result != ISC_R_SUCCESS) { 734 goto cleanup_context; 735 } 736 737 if (msg->tcp_continuation == 0) { 738 /* 739 * Digest the error and other data length. 740 */ 741 isc_buffer_clear(&databuf); 742 isc_buffer_putuint16(&databuf, tsig.error); 743 isc_buffer_putuint16(&databuf, tsig.otherlen); 744 745 isc_buffer_usedregion(&databuf, &r); 746 result = dst_context_adddata(ctx, &r); 747 if (result != ISC_R_SUCCESS) { 748 goto cleanup_context; 749 } 750 751 /* 752 * Digest other data. 753 */ 754 if (tsig.otherlen > 0) { 755 r.length = tsig.otherlen; 756 r.base = tsig.other; 757 result = dst_context_adddata(ctx, &r); 758 if (result != ISC_R_SUCCESS) { 759 goto cleanup_context; 760 } 761 } 762 } 763 764 result = dst_key_sigsize(key->key, &sigsize); 765 if (result != ISC_R_SUCCESS) { 766 goto cleanup_context; 767 } 768 tsig.signature = isc_mem_get(mctx, sigsize); 769 770 isc_buffer_init(&sigbuf, tsig.signature, sigsize); 771 result = dst_context_sign(ctx, &sigbuf); 772 if (result != ISC_R_SUCCESS) { 773 goto cleanup_signature; 774 } 775 dst_context_destroy(&ctx); 776 digestbits = dst_key_getbits(key->key); 777 if (digestbits != 0) { 778 unsigned int bytes = (digestbits + 7) / 8; 779 if (querytsig_ok && bytes < querytsig.siglen) { 780 bytes = querytsig.siglen; 781 } 782 if (bytes > isc_buffer_usedlength(&sigbuf)) { 783 bytes = isc_buffer_usedlength(&sigbuf); 784 } 785 tsig.siglen = bytes; 786 } else { 787 tsig.siglen = isc_buffer_usedlength(&sigbuf); 788 } 789 } else { 790 tsig.siglen = 0; 791 tsig.signature = NULL; 792 } 793 794 dns_message_gettemprdata(msg, &rdata); 795 isc_buffer_allocate(msg->mctx, &dynbuf, 512); 796 result = dns_rdata_fromstruct(rdata, dns_rdataclass_any, 797 dns_rdatatype_tsig, &tsig, dynbuf); 798 if (result != ISC_R_SUCCESS) { 799 goto cleanup_dynbuf; 800 } 801 802 dns_message_takebuffer(msg, &dynbuf); 803 804 if (tsig.signature != NULL) { 805 isc_mem_put(mctx, tsig.signature, sigsize); 806 tsig.signature = NULL; 807 } 808 809 dns_message_gettempname(msg, &owner); 810 dns_name_copy(key->name, owner); 811 812 dns_message_gettemprdatalist(msg, &datalist); 813 814 dns_message_gettemprdataset(msg, &dataset); 815 datalist->rdclass = dns_rdataclass_any; 816 datalist->type = dns_rdatatype_tsig; 817 ISC_LIST_APPEND(datalist->rdata, rdata, link); 818 dns_rdatalist_tordataset(datalist, dataset); 819 msg->tsig = dataset; 820 msg->tsigname = owner; 821 822 /* Windows does not like the tsig name being compressed. */ 823 msg->tsigname->attributes.nocompress = true; 824 825 return ISC_R_SUCCESS; 826 827 cleanup_dynbuf: 828 isc_buffer_free(&dynbuf); 829 dns_message_puttemprdata(msg, &rdata); 830 cleanup_signature: 831 if (tsig.signature != NULL) { 832 isc_mem_put(mctx, tsig.signature, sigsize); 833 } 834 cleanup_context: 835 if (ctx != NULL) { 836 dst_context_destroy(&ctx); 837 } 838 return result; 839 } 840 841 isc_result_t 842 dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, 843 dns_tsigkeyring_t *ring1, dns_tsigkeyring_t *ring2) { 844 dns_rdata_any_tsig_t tsig, querytsig; 845 isc_region_t r, source_r, header_r, sig_r; 846 isc_buffer_t databuf; 847 unsigned char data[32]; 848 dns_name_t *keyname = NULL; 849 dns_rdata_t rdata = DNS_RDATA_INIT; 850 isc_stdtime_t now; 851 isc_result_t result; 852 dns_tsigkey_t *tsigkey = NULL; 853 dst_key_t *key = NULL; 854 unsigned char header[DNS_MESSAGE_HEADERLEN]; 855 dst_context_t *ctx = NULL; 856 isc_mem_t *mctx = NULL; 857 uint16_t addcount, id; 858 unsigned int siglen; 859 unsigned int alg; 860 bool response; 861 862 REQUIRE(source != NULL); 863 REQUIRE(DNS_MESSAGE_VALID(msg)); 864 tsigkey = dns_message_gettsigkey(msg); 865 response = is_response(msg); 866 867 REQUIRE(tsigkey == NULL || VALID_TSIGKEY(tsigkey)); 868 869 msg->verify_attempted = 1; 870 msg->verified_sig = 0; 871 msg->tsigstatus = dns_tsigerror_badsig; 872 873 if (msg->tcp_continuation) { 874 if (tsigkey == NULL || msg->querytsig == NULL) { 875 return DNS_R_UNEXPECTEDTSIG; 876 } 877 return tsig_verify_tcp(source, msg); 878 } 879 880 /* 881 * There should be a TSIG record... 882 */ 883 if (msg->tsig == NULL) { 884 return DNS_R_EXPECTEDTSIG; 885 } 886 887 /* 888 * If this is a response and there's no key or query TSIG, there 889 * shouldn't be one on the response. 890 */ 891 if (response && (tsigkey == NULL || msg->querytsig == NULL)) { 892 return DNS_R_UNEXPECTEDTSIG; 893 } 894 895 mctx = msg->mctx; 896 897 /* 898 * If we're here, we know the message is well formed and contains a 899 * TSIG record. 900 */ 901 902 keyname = msg->tsigname; 903 result = dns_rdataset_first(msg->tsig); 904 if (result != ISC_R_SUCCESS) { 905 return result; 906 } 907 dns_rdataset_current(msg->tsig, &rdata); 908 result = dns_rdata_tostruct(&rdata, &tsig, NULL); 909 if (result != ISC_R_SUCCESS) { 910 return result; 911 } 912 dns_rdata_reset(&rdata); 913 if (response) { 914 result = dns_rdataset_first(msg->querytsig); 915 if (result != ISC_R_SUCCESS) { 916 return result; 917 } 918 dns_rdataset_current(msg->querytsig, &rdata); 919 result = dns_rdata_tostruct(&rdata, &querytsig, NULL); 920 if (result != ISC_R_SUCCESS) { 921 return result; 922 } 923 } 924 925 /* 926 * Do the key name and algorithm match that of the query? 927 */ 928 if (response && 929 (!dns_name_equal(keyname, tsigkey->name) || 930 !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) 931 { 932 msg->tsigstatus = dns_tsigerror_badkey; 933 tsig_log(msg->tsigkey, 2, 934 "key name and algorithm do not match"); 935 return DNS_R_TSIGVERIFYFAILURE; 936 } 937 938 /* 939 * Get the current time. 940 */ 941 if (msg->fuzzing) { 942 now = msg->fuzztime; 943 } else { 944 now = isc_stdtime_now(); 945 } 946 947 /* 948 * Find dns_tsigkey_t based on keyname. 949 */ 950 if (tsigkey == NULL) { 951 result = ISC_R_NOTFOUND; 952 if (ring1 != NULL) { 953 result = dns_tsigkey_find(&tsigkey, keyname, 954 &tsig.algorithm, ring1); 955 } 956 if (result == ISC_R_NOTFOUND && ring2 != NULL) { 957 result = dns_tsigkey_find(&tsigkey, keyname, 958 &tsig.algorithm, ring2); 959 } 960 if (result != ISC_R_SUCCESS) { 961 msg->tsigstatus = dns_tsigerror_badkey; 962 alg = dns__tsig_algfromname(&tsig.algorithm); 963 result = dns_tsigkey_create(keyname, alg, NULL, 0, mctx, 964 &msg->tsigkey); 965 if (result != ISC_R_SUCCESS) { 966 return result; 967 } 968 if (alg == DST_ALG_UNKNOWN) { 969 dns_name_clone(&tsig.algorithm, 970 &msg->tsigkey->algname); 971 } 972 973 tsig_log(msg->tsigkey, 2, "unknown key"); 974 return DNS_R_TSIGVERIFYFAILURE; 975 } 976 msg->tsigkey = tsigkey; 977 } 978 979 key = tsigkey->key; 980 981 /* 982 * Check digest length. 983 */ 984 alg = dst_key_alg(key); 985 result = dst_key_sigsize(key, &siglen); 986 if (result != ISC_R_SUCCESS) { 987 return result; 988 } 989 if (dns__tsig_algvalid(alg)) { 990 if (tsig.siglen > siglen) { 991 tsig_log(msg->tsigkey, 2, "signature length too big"); 992 return DNS_R_FORMERR; 993 } 994 if (tsig.siglen > 0 && 995 (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2))) 996 { 997 tsig_log(msg->tsigkey, 2, 998 "signature length below minimum"); 999 return DNS_R_FORMERR; 1000 } 1001 } 1002 1003 if (tsig.siglen > 0) { 1004 uint16_t addcount_n; 1005 1006 sig_r.base = tsig.signature; 1007 sig_r.length = tsig.siglen; 1008 1009 result = dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, 1010 false, 0, &ctx); 1011 if (result != ISC_R_SUCCESS) { 1012 return result; 1013 } 1014 1015 if (response) { 1016 isc_buffer_init(&databuf, data, sizeof(data)); 1017 isc_buffer_putuint16(&databuf, querytsig.siglen); 1018 isc_buffer_usedregion(&databuf, &r); 1019 result = dst_context_adddata(ctx, &r); 1020 if (result != ISC_R_SUCCESS) { 1021 goto cleanup_context; 1022 } 1023 if (querytsig.siglen > 0) { 1024 r.length = querytsig.siglen; 1025 r.base = querytsig.signature; 1026 result = dst_context_adddata(ctx, &r); 1027 if (result != ISC_R_SUCCESS) { 1028 goto cleanup_context; 1029 } 1030 } 1031 } 1032 1033 /* 1034 * Extract the header. 1035 */ 1036 isc_buffer_usedregion(source, &r); 1037 memmove(header, r.base, DNS_MESSAGE_HEADERLEN); 1038 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); 1039 1040 /* 1041 * Decrement the additional field counter. 1042 */ 1043 memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2); 1044 addcount_n = ntohs(addcount); 1045 addcount = htons((uint16_t)(addcount_n - 1)); 1046 memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2); 1047 1048 /* 1049 * Put in the original id. 1050 */ 1051 id = htons(tsig.originalid); 1052 memmove(&header[0], &id, 2); 1053 1054 /* 1055 * Digest the modified header. 1056 */ 1057 header_r.base = (unsigned char *)header; 1058 header_r.length = DNS_MESSAGE_HEADERLEN; 1059 result = dst_context_adddata(ctx, &header_r); 1060 if (result != ISC_R_SUCCESS) { 1061 goto cleanup_context; 1062 } 1063 1064 /* 1065 * Digest all non-TSIG records. 1066 */ 1067 isc_buffer_usedregion(source, &source_r); 1068 r.base = source_r.base + DNS_MESSAGE_HEADERLEN; 1069 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN; 1070 result = dst_context_adddata(ctx, &r); 1071 if (result != ISC_R_SUCCESS) { 1072 goto cleanup_context; 1073 } 1074 1075 /* 1076 * Digest the key name. 1077 */ 1078 dns_name_toregion(tsigkey->name, &r); 1079 result = dst_context_adddata(ctx, &r); 1080 if (result != ISC_R_SUCCESS) { 1081 goto cleanup_context; 1082 } 1083 1084 isc_buffer_init(&databuf, data, sizeof(data)); 1085 isc_buffer_putuint16(&databuf, tsig.common.rdclass); 1086 isc_buffer_putuint32(&databuf, msg->tsig->ttl); 1087 isc_buffer_usedregion(&databuf, &r); 1088 result = dst_context_adddata(ctx, &r); 1089 if (result != ISC_R_SUCCESS) { 1090 goto cleanup_context; 1091 } 1092 1093 /* 1094 * Digest the key algorithm. 1095 */ 1096 dns_name_toregion(dns_tsigkey_algorithm(tsigkey), &r); 1097 result = dst_context_adddata(ctx, &r); 1098 if (result != ISC_R_SUCCESS) { 1099 goto cleanup_context; 1100 } 1101 1102 isc_buffer_clear(&databuf); 1103 isc_buffer_putuint48(&databuf, tsig.timesigned); 1104 isc_buffer_putuint16(&databuf, tsig.fudge); 1105 isc_buffer_putuint16(&databuf, tsig.error); 1106 isc_buffer_putuint16(&databuf, tsig.otherlen); 1107 isc_buffer_usedregion(&databuf, &r); 1108 result = dst_context_adddata(ctx, &r); 1109 if (result != ISC_R_SUCCESS) { 1110 goto cleanup_context; 1111 } 1112 1113 if (tsig.otherlen > 0) { 1114 r.base = tsig.other; 1115 r.length = tsig.otherlen; 1116 result = dst_context_adddata(ctx, &r); 1117 if (result != ISC_R_SUCCESS) { 1118 goto cleanup_context; 1119 } 1120 } 1121 1122 result = dst_context_verify(ctx, &sig_r); 1123 if (result == DST_R_VERIFYFAILURE) { 1124 result = DNS_R_TSIGVERIFYFAILURE; 1125 tsig_log(msg->tsigkey, 2, 1126 "signature failed to verify(1)"); 1127 goto cleanup_context; 1128 } else if (result != ISC_R_SUCCESS) { 1129 goto cleanup_context; 1130 } 1131 msg->verified_sig = 1; 1132 } else if (!response || (tsig.error != dns_tsigerror_badsig && 1133 tsig.error != dns_tsigerror_badkey)) 1134 { 1135 tsig_log(msg->tsigkey, 2, "signature was empty"); 1136 return DNS_R_TSIGVERIFYFAILURE; 1137 } 1138 1139 /* 1140 * Here at this point, the MAC has been verified. Even if any of 1141 * the following code returns a TSIG error, the reply will be 1142 * signed and WILL always include the request MAC in the digest 1143 * computation. 1144 */ 1145 1146 /* 1147 * Is the time ok? 1148 */ 1149 if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { 1150 msg->tsigstatus = dns_tsigerror_badtime; 1151 tsig_log(msg->tsigkey, 2, "signature has expired"); 1152 result = DNS_R_CLOCKSKEW; 1153 goto cleanup_context; 1154 } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) { 1155 msg->tsigstatus = dns_tsigerror_badtime; 1156 tsig_log(msg->tsigkey, 2, "signature is in the future"); 1157 result = DNS_R_CLOCKSKEW; 1158 goto cleanup_context; 1159 } 1160 1161 if (dns__tsig_algvalid(alg)) { 1162 uint16_t digestbits = dst_key_getbits(key); 1163 1164 if (tsig.siglen > 0 && digestbits != 0 && 1165 tsig.siglen < ((digestbits + 7) / 8)) 1166 { 1167 msg->tsigstatus = dns_tsigerror_badtrunc; 1168 tsig_log(msg->tsigkey, 2, 1169 "truncated signature length too small"); 1170 result = DNS_R_TSIGVERIFYFAILURE; 1171 goto cleanup_context; 1172 } 1173 if (tsig.siglen > 0 && digestbits == 0 && tsig.siglen < siglen) 1174 { 1175 msg->tsigstatus = dns_tsigerror_badtrunc; 1176 tsig_log(msg->tsigkey, 2, "signature length too small"); 1177 result = DNS_R_TSIGVERIFYFAILURE; 1178 goto cleanup_context; 1179 } 1180 } 1181 1182 if (response && tsig.error != dns_rcode_noerror) { 1183 msg->tsigstatus = tsig.error; 1184 if (tsig.error == dns_tsigerror_badtime) { 1185 result = DNS_R_CLOCKSKEW; 1186 } else { 1187 result = DNS_R_TSIGERRORSET; 1188 } 1189 goto cleanup_context; 1190 } 1191 1192 msg->tsigstatus = dns_rcode_noerror; 1193 result = ISC_R_SUCCESS; 1194 1195 cleanup_context: 1196 if (ctx != NULL) { 1197 dst_context_destroy(&ctx); 1198 } 1199 1200 return result; 1201 } 1202 1203 static isc_result_t 1204 tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { 1205 dns_rdata_any_tsig_t tsig, querytsig; 1206 isc_region_t r, source_r, header_r, sig_r; 1207 isc_buffer_t databuf; 1208 unsigned char data[32]; 1209 dns_name_t *keyname = NULL; 1210 dns_rdata_t rdata = DNS_RDATA_INIT; 1211 isc_stdtime_t now; 1212 isc_result_t result; 1213 dns_tsigkey_t *tsigkey = NULL; 1214 dst_key_t *key = NULL; 1215 unsigned char header[DNS_MESSAGE_HEADERLEN]; 1216 uint16_t addcount, id; 1217 bool has_tsig = false; 1218 isc_mem_t *mctx = NULL; 1219 unsigned int siglen; 1220 unsigned int alg; 1221 1222 REQUIRE(source != NULL); 1223 REQUIRE(msg != NULL); 1224 REQUIRE(dns_message_gettsigkey(msg) != NULL); 1225 REQUIRE(msg->tcp_continuation == 1); 1226 REQUIRE(msg->querytsig != NULL); 1227 1228 msg->verified_sig = 0; 1229 msg->tsigstatus = dns_tsigerror_badsig; 1230 1231 if (!is_response(msg)) { 1232 return DNS_R_EXPECTEDRESPONSE; 1233 } 1234 1235 mctx = msg->mctx; 1236 1237 tsigkey = dns_message_gettsigkey(msg); 1238 key = tsigkey->key; 1239 1240 /* 1241 * Extract and parse the previous TSIG 1242 */ 1243 result = dns_rdataset_first(msg->querytsig); 1244 if (result != ISC_R_SUCCESS) { 1245 return result; 1246 } 1247 dns_rdataset_current(msg->querytsig, &rdata); 1248 result = dns_rdata_tostruct(&rdata, &querytsig, NULL); 1249 if (result != ISC_R_SUCCESS) { 1250 return result; 1251 } 1252 dns_rdata_reset(&rdata); 1253 1254 /* 1255 * If there is a TSIG in this message, do some checks. 1256 */ 1257 if (msg->tsig != NULL) { 1258 has_tsig = true; 1259 1260 keyname = msg->tsigname; 1261 result = dns_rdataset_first(msg->tsig); 1262 if (result != ISC_R_SUCCESS) { 1263 goto cleanup_querystruct; 1264 } 1265 dns_rdataset_current(msg->tsig, &rdata); 1266 result = dns_rdata_tostruct(&rdata, &tsig, NULL); 1267 if (result != ISC_R_SUCCESS) { 1268 goto cleanup_querystruct; 1269 } 1270 1271 /* 1272 * Do the key name and algorithm match that of the query? 1273 */ 1274 if (!dns_name_equal(keyname, tsigkey->name) || 1275 !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) 1276 { 1277 msg->tsigstatus = dns_tsigerror_badkey; 1278 result = DNS_R_TSIGVERIFYFAILURE; 1279 tsig_log(msg->tsigkey, 2, 1280 "key name and algorithm do not match"); 1281 goto cleanup_querystruct; 1282 } 1283 1284 /* 1285 * Check digest length. 1286 */ 1287 alg = dst_key_alg(key); 1288 result = dst_key_sigsize(key, &siglen); 1289 if (result != ISC_R_SUCCESS) { 1290 goto cleanup_querystruct; 1291 } 1292 if (dns__tsig_algvalid(alg)) { 1293 if (tsig.siglen > siglen) { 1294 tsig_log(tsigkey, 2, 1295 "signature length too big"); 1296 result = DNS_R_FORMERR; 1297 goto cleanup_querystruct; 1298 } 1299 if (tsig.siglen > 0 && 1300 (tsig.siglen < 10 || 1301 tsig.siglen < ((siglen + 1) / 2))) 1302 { 1303 tsig_log(tsigkey, 2, 1304 "signature length below minimum"); 1305 result = DNS_R_FORMERR; 1306 goto cleanup_querystruct; 1307 } 1308 } 1309 } 1310 1311 if (msg->tsigctx == NULL) { 1312 result = dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, 1313 false, 0, &msg->tsigctx); 1314 if (result != ISC_R_SUCCESS) { 1315 goto cleanup_querystruct; 1316 } 1317 1318 /* 1319 * Digest the length of the query signature 1320 */ 1321 isc_buffer_init(&databuf, data, sizeof(data)); 1322 isc_buffer_putuint16(&databuf, querytsig.siglen); 1323 isc_buffer_usedregion(&databuf, &r); 1324 result = dst_context_adddata(msg->tsigctx, &r); 1325 if (result != ISC_R_SUCCESS) { 1326 goto cleanup_context; 1327 } 1328 1329 /* 1330 * Digest the data of the query signature 1331 */ 1332 if (querytsig.siglen > 0) { 1333 r.length = querytsig.siglen; 1334 r.base = querytsig.signature; 1335 result = dst_context_adddata(msg->tsigctx, &r); 1336 if (result != ISC_R_SUCCESS) { 1337 goto cleanup_context; 1338 } 1339 } 1340 } 1341 1342 /* 1343 * Extract the header. 1344 */ 1345 isc_buffer_usedregion(source, &r); 1346 memmove(header, r.base, DNS_MESSAGE_HEADERLEN); 1347 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); 1348 1349 /* 1350 * Decrement the additional field counter if necessary. 1351 */ 1352 if (has_tsig) { 1353 uint16_t addcount_n; 1354 1355 memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2); 1356 addcount_n = ntohs(addcount); 1357 addcount = htons((uint16_t)(addcount_n - 1)); 1358 memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2); 1359 1360 /* 1361 * Put in the original id. 1362 * 1363 * XXX Can TCP transfers be forwarded? How would that 1364 * work? 1365 */ 1366 id = htons(tsig.originalid); 1367 memmove(&header[0], &id, 2); 1368 } 1369 1370 /* 1371 * Digest the modified header. 1372 */ 1373 header_r.base = (unsigned char *)header; 1374 header_r.length = DNS_MESSAGE_HEADERLEN; 1375 result = dst_context_adddata(msg->tsigctx, &header_r); 1376 if (result != ISC_R_SUCCESS) { 1377 goto cleanup_context; 1378 } 1379 1380 /* 1381 * Digest all non-TSIG records. 1382 */ 1383 isc_buffer_usedregion(source, &source_r); 1384 r.base = source_r.base + DNS_MESSAGE_HEADERLEN; 1385 if (has_tsig) { 1386 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN; 1387 } else { 1388 r.length = source_r.length - DNS_MESSAGE_HEADERLEN; 1389 } 1390 result = dst_context_adddata(msg->tsigctx, &r); 1391 if (result != ISC_R_SUCCESS) { 1392 goto cleanup_context; 1393 } 1394 1395 /* 1396 * Digest the time signed and fudge. 1397 */ 1398 if (has_tsig) { 1399 isc_buffer_init(&databuf, data, sizeof(data)); 1400 isc_buffer_putuint48(&databuf, tsig.timesigned); 1401 isc_buffer_putuint16(&databuf, tsig.fudge); 1402 isc_buffer_usedregion(&databuf, &r); 1403 result = dst_context_adddata(msg->tsigctx, &r); 1404 if (result != ISC_R_SUCCESS) { 1405 goto cleanup_context; 1406 } 1407 1408 sig_r.base = tsig.signature; 1409 sig_r.length = tsig.siglen; 1410 if (tsig.siglen == 0) { 1411 if (tsig.error != dns_rcode_noerror) { 1412 msg->tsigstatus = tsig.error; 1413 if (tsig.error == dns_tsigerror_badtime) { 1414 result = DNS_R_CLOCKSKEW; 1415 } else { 1416 result = DNS_R_TSIGERRORSET; 1417 } 1418 } else { 1419 tsig_log(msg->tsigkey, 2, "signature is empty"); 1420 result = DNS_R_TSIGVERIFYFAILURE; 1421 } 1422 goto cleanup_context; 1423 } 1424 1425 result = dst_context_verify(msg->tsigctx, &sig_r); 1426 if (result == DST_R_VERIFYFAILURE) { 1427 tsig_log(msg->tsigkey, 2, 1428 "signature failed to verify(2)"); 1429 result = DNS_R_TSIGVERIFYFAILURE; 1430 goto cleanup_context; 1431 } else if (result != ISC_R_SUCCESS) { 1432 goto cleanup_context; 1433 } 1434 msg->verified_sig = 1; 1435 1436 /* 1437 * Here at this point, the MAC has been verified. Even 1438 * if any of the following code returns a TSIG error, 1439 * the reply will be signed and WILL always include the 1440 * request MAC in the digest computation. 1441 */ 1442 1443 /* 1444 * Is the time ok? 1445 */ 1446 if (msg->fuzzing) { 1447 now = msg->fuzztime; 1448 } else { 1449 now = isc_stdtime_now(); 1450 } 1451 1452 if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { 1453 msg->tsigstatus = dns_tsigerror_badtime; 1454 tsig_log(msg->tsigkey, 2, "signature has expired"); 1455 result = DNS_R_CLOCKSKEW; 1456 goto cleanup_context; 1457 } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) 1458 { 1459 msg->tsigstatus = dns_tsigerror_badtime; 1460 tsig_log(msg->tsigkey, 2, "signature is in the future"); 1461 result = DNS_R_CLOCKSKEW; 1462 goto cleanup_context; 1463 } 1464 1465 alg = dst_key_alg(key); 1466 result = dst_key_sigsize(key, &siglen); 1467 if (result != ISC_R_SUCCESS) { 1468 goto cleanup_context; 1469 } 1470 if (dns__tsig_algvalid(alg)) { 1471 uint16_t digestbits = dst_key_getbits(key); 1472 1473 if (tsig.siglen > 0 && digestbits != 0 && 1474 tsig.siglen < ((digestbits + 7) / 8)) 1475 { 1476 msg->tsigstatus = dns_tsigerror_badtrunc; 1477 tsig_log(msg->tsigkey, 2, 1478 "truncated signature length " 1479 "too small"); 1480 result = DNS_R_TSIGVERIFYFAILURE; 1481 goto cleanup_context; 1482 } 1483 if (tsig.siglen > 0 && digestbits == 0 && 1484 tsig.siglen < siglen) 1485 { 1486 msg->tsigstatus = dns_tsigerror_badtrunc; 1487 tsig_log(msg->tsigkey, 2, 1488 "signature length too small"); 1489 result = DNS_R_TSIGVERIFYFAILURE; 1490 goto cleanup_context; 1491 } 1492 } 1493 1494 if (tsig.error != dns_rcode_noerror) { 1495 msg->tsigstatus = tsig.error; 1496 if (tsig.error == dns_tsigerror_badtime) { 1497 result = DNS_R_CLOCKSKEW; 1498 } else { 1499 result = DNS_R_TSIGERRORSET; 1500 } 1501 goto cleanup_context; 1502 } 1503 } 1504 1505 msg->tsigstatus = dns_rcode_noerror; 1506 result = ISC_R_SUCCESS; 1507 1508 cleanup_context: 1509 /* 1510 * Except in error conditions, don't destroy the DST context 1511 * for unsigned messages; it is a running sum till the next 1512 * TSIG signed message. 1513 */ 1514 if ((result != ISC_R_SUCCESS || has_tsig) && msg->tsigctx != NULL) { 1515 dst_context_destroy(&msg->tsigctx); 1516 } 1517 1518 cleanup_querystruct: 1519 dns_rdata_freestruct(&querytsig); 1520 1521 return result; 1522 } 1523 1524 isc_result_t 1525 dns_tsigkey_find(dns_tsigkey_t **tsigkey, const dns_name_t *name, 1526 const dns_name_t *algorithm, dns_tsigkeyring_t *ring) { 1527 dns_tsigkey_t *key = NULL; 1528 isc_result_t result; 1529 isc_rwlocktype_t locktype = isc_rwlocktype_read; 1530 isc_stdtime_t now = isc_stdtime_now(); 1531 1532 REQUIRE(name != NULL); 1533 REQUIRE(VALID_TSIGKEYRING(ring)); 1534 REQUIRE(tsigkey != NULL && *tsigkey == NULL); 1535 1536 again: 1537 RWLOCK(&ring->lock, locktype); 1538 result = isc_hashmap_find(ring->keys, dns_name_hash(name), tkey_match, 1539 name, (void **)&key); 1540 if (result == ISC_R_NOTFOUND) { 1541 RWUNLOCK(&ring->lock, locktype); 1542 return result; 1543 } 1544 1545 if (algorithm != NULL && key->alg != dns__tsig_algfromname(algorithm)) { 1546 RWUNLOCK(&ring->lock, locktype); 1547 return ISC_R_NOTFOUND; 1548 } 1549 if (key->inception != key->expire && isc_serial_lt(key->expire, now)) { 1550 /* 1551 * The key has expired. 1552 */ 1553 if (locktype == isc_rwlocktype_read) { 1554 RWUNLOCK(&ring->lock, locktype); 1555 locktype = isc_rwlocktype_write; 1556 key = NULL; 1557 goto again; 1558 } 1559 rm_lru(key); 1560 rm_hashmap(key); 1561 RWUNLOCK(&ring->lock, locktype); 1562 return ISC_R_NOTFOUND; 1563 } 1564 dns_tsigkey_ref(key); 1565 RWUNLOCK(&ring->lock, locktype); 1566 adjust_lru(key); 1567 *tsigkey = key; 1568 return ISC_R_SUCCESS; 1569 } 1570 1571 const dns_name_t * 1572 dns_tsigkey_algorithm(dns_tsigkey_t *tkey) { 1573 REQUIRE(VALID_TSIGKEY(tkey)); 1574 1575 switch (tkey->alg) { 1576 case DST_ALG_HMACMD5: 1577 return dns_tsig_hmacmd5_name; 1578 case DST_ALG_HMACSHA1: 1579 return dns_tsig_hmacsha1_name; 1580 case DST_ALG_HMACSHA224: 1581 return dns_tsig_hmacsha224_name; 1582 case DST_ALG_HMACSHA256: 1583 return dns_tsig_hmacsha256_name; 1584 case DST_ALG_HMACSHA384: 1585 return dns_tsig_hmacsha384_name; 1586 case DST_ALG_HMACSHA512: 1587 return dns_tsig_hmacsha512_name; 1588 case DST_ALG_GSSAPI: 1589 return dns_tsig_gssapi_name; 1590 1591 case DST_ALG_UNKNOWN: 1592 /* 1593 * If the tsigkey object was created with an 1594 * unknown algorithm, then we cloned 1595 * the algorithm name here. 1596 */ 1597 return &tkey->algname; 1598 1599 default: 1600 UNREACHABLE(); 1601 } 1602 } 1603 1604 void 1605 dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsigkeyring_t **ringp) { 1606 dns_tsigkeyring_t *ring = NULL; 1607 1608 REQUIRE(mctx != NULL); 1609 REQUIRE(ringp != NULL && *ringp == NULL); 1610 1611 ring = isc_mem_get(mctx, sizeof(dns_tsigkeyring_t)); 1612 *ring = (dns_tsigkeyring_t){ 1613 .lru = ISC_LIST_INITIALIZER, 1614 }; 1615 1616 isc_hashmap_create(mctx, 12, &ring->keys); 1617 isc_rwlock_init(&ring->lock); 1618 isc_mem_attach(mctx, &ring->mctx); 1619 isc_refcount_init(&ring->references, 1); 1620 ring->magic = TSIGKEYRING_MAGIC; 1621 1622 *ringp = ring; 1623 } 1624 1625 isc_result_t 1626 dns_tsigkeyring_add(dns_tsigkeyring_t *ring, dns_tsigkey_t *tkey) { 1627 isc_result_t result; 1628 1629 REQUIRE(VALID_TSIGKEY(tkey)); 1630 REQUIRE(VALID_TSIGKEYRING(ring)); 1631 REQUIRE(tkey->ring == NULL); 1632 1633 RWLOCK(&ring->lock, isc_rwlocktype_write); 1634 result = isc_hashmap_add(ring->keys, dns_name_hash(tkey->name), 1635 tkey_match, tkey->name, tkey, NULL); 1636 if (result == ISC_R_SUCCESS) { 1637 dns_tsigkey_ref(tkey); 1638 tkey->ring = ring; 1639 1640 /* 1641 * If this is a TKEY-generated key, add it to the LRU list, 1642 * and if we've exceeded the quota for generated keys, 1643 * remove the least recently used one from the both the 1644 * list and the RBT. 1645 */ 1646 if (tkey->generated) { 1647 ISC_LIST_APPEND(ring->lru, tkey, link); 1648 dns_tsigkey_ref(tkey); 1649 if (ring->generated++ > DNS_TSIG_MAXGENERATEDKEYS) { 1650 dns_tsigkey_t *key = ISC_LIST_HEAD(ring->lru); 1651 rm_lru(key); 1652 rm_hashmap(key); 1653 } 1654 } 1655 1656 tkey->ring = ring; 1657 } 1658 RWUNLOCK(&ring->lock, isc_rwlocktype_write); 1659 1660 return result; 1661 } 1662 1663 void 1664 dns_tsigkeyring_restore(dns_tsigkeyring_t *ring, FILE *fp) { 1665 isc_stdtime_t now = isc_stdtime_now(); 1666 isc_result_t result; 1667 1668 do { 1669 result = restore_key(ring, now, fp); 1670 if (result == ISC_R_NOMORE) { 1671 return; 1672 } 1673 if (result == DNS_R_BADALG || result == DNS_R_EXPIRED) { 1674 result = ISC_R_SUCCESS; 1675 } 1676 } while (result == ISC_R_SUCCESS); 1677 } 1678