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