1 /* $NetBSD: tsig.c,v 1.17 2026/09/17 18:01:15 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 tsig.error != dns_tsigerror_badtrunc) 617 { 618 unsigned char header[DNS_MESSAGE_HEADERLEN]; 619 isc_buffer_t headerbuf; 620 uint16_t digestbits; 621 bool querytsig_ok = false; 622 623 /* 624 * If it is a response, we assume that the request MAC 625 * has validated at this point. This is why we include a 626 * MAC length > 0 in the reply. 627 */ 628 result = dst_context_create( 629 key->key, mctx, DNS_LOGCATEGORY_DNSSEC, true, 0, &ctx); 630 if (result != ISC_R_SUCCESS) { 631 return result; 632 } 633 634 /* 635 * If this is a response, and if there was a TSIG in 636 * the query, digest the request's MAC. 637 * 638 * (Note: querytsig should be non-NULL for all 639 * responses except TKEY responses. Those may be signed 640 * with the newly-negotiated TSIG key even if the query 641 * wasn't signed.) 642 */ 643 if (response && msg->querytsig != NULL) { 644 dns_rdata_t querytsigrdata = DNS_RDATA_INIT; 645 646 INSIST(msg->verified_sig); 647 648 result = dns_rdataset_first(msg->querytsig); 649 if (result != ISC_R_SUCCESS) { 650 goto cleanup_context; 651 } 652 dns_rdataset_current(msg->querytsig, &querytsigrdata); 653 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, 654 NULL); 655 if (result != ISC_R_SUCCESS) { 656 goto cleanup_context; 657 } 658 isc_buffer_putuint16(&databuf, querytsig.siglen); 659 if (isc_buffer_availablelength(&databuf) < 660 querytsig.siglen) 661 { 662 result = ISC_R_NOSPACE; 663 goto cleanup_context; 664 } 665 isc_buffer_putmem(&databuf, querytsig.signature, 666 querytsig.siglen); 667 isc_buffer_usedregion(&databuf, &r); 668 result = dst_context_adddata(ctx, &r); 669 if (result != ISC_R_SUCCESS) { 670 goto cleanup_context; 671 } 672 querytsig_ok = true; 673 } 674 675 /* 676 * Digest the header. 677 */ 678 isc_buffer_init(&headerbuf, header, sizeof(header)); 679 dns_message_renderheader(msg, &headerbuf); 680 isc_buffer_usedregion(&headerbuf, &r); 681 result = dst_context_adddata(ctx, &r); 682 if (result != ISC_R_SUCCESS) { 683 goto cleanup_context; 684 } 685 686 /* 687 * Digest the remainder of the message. 688 */ 689 isc_buffer_usedregion(msg->buffer, &r); 690 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); 691 result = dst_context_adddata(ctx, &r); 692 if (result != ISC_R_SUCCESS) { 693 goto cleanup_context; 694 } 695 696 if (msg->tcp_continuation == 0) { 697 /* 698 * Digest the name, class, ttl, alg. 699 */ 700 dns_name_toregion(key->name, &r); 701 result = dst_context_adddata(ctx, &r); 702 if (result != ISC_R_SUCCESS) { 703 goto cleanup_context; 704 } 705 706 isc_buffer_clear(&databuf); 707 isc_buffer_putuint16(&databuf, dns_rdataclass_any); 708 isc_buffer_putuint32(&databuf, 0); /* ttl */ 709 isc_buffer_usedregion(&databuf, &r); 710 result = dst_context_adddata(ctx, &r); 711 if (result != ISC_R_SUCCESS) { 712 goto cleanup_context; 713 } 714 715 dns_name_toregion(&tsig.algorithm, &r); 716 result = dst_context_adddata(ctx, &r); 717 if (result != ISC_R_SUCCESS) { 718 goto cleanup_context; 719 } 720 } 721 /* Digest the timesigned and fudge */ 722 isc_buffer_clear(&databuf); 723 if (tsig.error == dns_tsigerror_badtime && querytsig_ok) { 724 tsig.timesigned = querytsig.timesigned; 725 } 726 isc_buffer_putuint48(&databuf, tsig.timesigned); 727 isc_buffer_putuint16(&databuf, tsig.fudge); 728 isc_buffer_usedregion(&databuf, &r); 729 result = dst_context_adddata(ctx, &r); 730 if (result != ISC_R_SUCCESS) { 731 goto cleanup_context; 732 } 733 734 if (msg->tcp_continuation == 0) { 735 /* 736 * Digest the error and other data length. 737 */ 738 isc_buffer_clear(&databuf); 739 isc_buffer_putuint16(&databuf, tsig.error); 740 isc_buffer_putuint16(&databuf, tsig.otherlen); 741 742 isc_buffer_usedregion(&databuf, &r); 743 result = dst_context_adddata(ctx, &r); 744 if (result != ISC_R_SUCCESS) { 745 goto cleanup_context; 746 } 747 748 /* 749 * Digest other data. 750 */ 751 if (tsig.otherlen > 0) { 752 r.length = tsig.otherlen; 753 r.base = tsig.other; 754 result = dst_context_adddata(ctx, &r); 755 if (result != ISC_R_SUCCESS) { 756 goto cleanup_context; 757 } 758 } 759 } 760 761 result = dst_key_sigsize(key->key, &sigsize); 762 if (result != ISC_R_SUCCESS) { 763 goto cleanup_context; 764 } 765 tsig.signature = isc_mem_get(mctx, sigsize); 766 767 isc_buffer_init(&sigbuf, tsig.signature, sigsize); 768 result = dst_context_sign(ctx, &sigbuf); 769 if (result != ISC_R_SUCCESS) { 770 goto cleanup_signature; 771 } 772 dst_context_destroy(&ctx); 773 digestbits = dst_key_getbits(key->key); 774 if (digestbits != 0) { 775 unsigned int bytes = (digestbits + 7) / 8; 776 if (querytsig_ok && bytes < querytsig.siglen) { 777 bytes = querytsig.siglen; 778 } 779 if (bytes > isc_buffer_usedlength(&sigbuf)) { 780 bytes = isc_buffer_usedlength(&sigbuf); 781 } 782 tsig.siglen = bytes; 783 } else { 784 tsig.siglen = isc_buffer_usedlength(&sigbuf); 785 } 786 } else { 787 tsig.siglen = 0; 788 tsig.signature = NULL; 789 } 790 791 dns_message_gettemprdata(msg, &rdata); 792 isc_buffer_allocate(msg->mctx, &dynbuf, 512); 793 result = dns_rdata_fromstruct(rdata, dns_rdataclass_any, 794 dns_rdatatype_tsig, &tsig, dynbuf); 795 if (result != ISC_R_SUCCESS) { 796 goto cleanup_dynbuf; 797 } 798 799 dns_message_takebuffer(msg, &dynbuf); 800 801 if (tsig.signature != NULL) { 802 isc_mem_put(mctx, tsig.signature, sigsize); 803 tsig.signature = NULL; 804 } 805 806 dns_message_gettempname(msg, &owner); 807 dns_name_copy(key->name, owner); 808 809 dns_message_gettemprdatalist(msg, &datalist); 810 811 dns_message_gettemprdataset(msg, &dataset); 812 datalist->rdclass = dns_rdataclass_any; 813 datalist->type = dns_rdatatype_tsig; 814 ISC_LIST_APPEND(datalist->rdata, rdata, link); 815 dns_rdatalist_tordataset(datalist, dataset); 816 msg->tsig = dataset; 817 msg->tsigname = owner; 818 819 /* Windows does not like the tsig name being compressed. */ 820 msg->tsigname->attributes.nocompress = true; 821 822 return ISC_R_SUCCESS; 823 824 cleanup_dynbuf: 825 isc_buffer_free(&dynbuf); 826 dns_message_puttemprdata(msg, &rdata); 827 cleanup_signature: 828 if (tsig.signature != NULL) { 829 isc_mem_put(mctx, tsig.signature, sigsize); 830 } 831 cleanup_context: 832 if (ctx != NULL) { 833 dst_context_destroy(&ctx); 834 } 835 return result; 836 } 837 838 isc_result_t 839 dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, 840 dns_tsigkeyring_t *ring1, dns_tsigkeyring_t *ring2) { 841 dns_rdata_any_tsig_t tsig, querytsig; 842 isc_region_t r, source_r, header_r, sig_r; 843 isc_buffer_t databuf; 844 unsigned char data[32]; 845 dns_name_t *keyname = NULL; 846 dns_rdata_t rdata = DNS_RDATA_INIT; 847 isc_stdtime_t now; 848 isc_result_t result; 849 dns_tsigkey_t *tsigkey = NULL; 850 dst_key_t *key = NULL; 851 unsigned char header[DNS_MESSAGE_HEADERLEN]; 852 dst_context_t *ctx = NULL; 853 isc_mem_t *mctx = NULL; 854 uint16_t addcount, id; 855 unsigned int siglen; 856 unsigned int alg; 857 bool response; 858 859 REQUIRE(source != NULL); 860 REQUIRE(DNS_MESSAGE_VALID(msg)); 861 tsigkey = dns_message_gettsigkey(msg); 862 response = is_response(msg); 863 864 REQUIRE(tsigkey == NULL || VALID_TSIGKEY(tsigkey)); 865 866 msg->verify_attempted = 1; 867 msg->verified_sig = 0; 868 msg->tsigstatus = dns_tsigerror_badsig; 869 870 if (msg->tcp_continuation) { 871 if (tsigkey == NULL || msg->querytsig == NULL) { 872 return DNS_R_UNEXPECTEDTSIG; 873 } 874 return tsig_verify_tcp(source, msg); 875 } 876 877 /* 878 * There should be a TSIG record... 879 */ 880 if (msg->tsig == NULL) { 881 return DNS_R_EXPECTEDTSIG; 882 } 883 884 /* 885 * If this is a response and there's no key or query TSIG, there 886 * shouldn't be one on the response. 887 */ 888 if (response && (tsigkey == NULL || msg->querytsig == NULL)) { 889 return DNS_R_UNEXPECTEDTSIG; 890 } 891 892 mctx = msg->mctx; 893 894 /* 895 * If we're here, we know the message is well formed and contains a 896 * TSIG record. 897 */ 898 899 keyname = msg->tsigname; 900 result = dns_rdataset_first(msg->tsig); 901 if (result != ISC_R_SUCCESS) { 902 return result; 903 } 904 dns_rdataset_current(msg->tsig, &rdata); 905 result = dns_rdata_tostruct(&rdata, &tsig, NULL); 906 if (result != ISC_R_SUCCESS) { 907 return result; 908 } 909 dns_rdata_reset(&rdata); 910 if (response) { 911 result = dns_rdataset_first(msg->querytsig); 912 if (result != ISC_R_SUCCESS) { 913 return result; 914 } 915 dns_rdataset_current(msg->querytsig, &rdata); 916 result = dns_rdata_tostruct(&rdata, &querytsig, NULL); 917 if (result != ISC_R_SUCCESS) { 918 return result; 919 } 920 } 921 922 /* 923 * Do the key name and algorithm match that of the query? 924 */ 925 if (response && 926 (!dns_name_equal(keyname, tsigkey->name) || 927 !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) 928 { 929 msg->tsigstatus = dns_tsigerror_badkey; 930 tsig_log(msg->tsigkey, 2, 931 "key name and algorithm do not match"); 932 return DNS_R_TSIGVERIFYFAILURE; 933 } 934 935 /* 936 * Get the current time. 937 */ 938 if (msg->fuzzing) { 939 now = msg->fuzztime; 940 } else { 941 now = isc_stdtime_now(); 942 } 943 944 /* 945 * Find dns_tsigkey_t based on keyname. 946 */ 947 if (tsigkey == NULL) { 948 result = ISC_R_NOTFOUND; 949 if (ring1 != NULL) { 950 result = dns_tsigkey_find(&tsigkey, keyname, 951 &tsig.algorithm, ring1); 952 } 953 if (result == ISC_R_NOTFOUND && ring2 != NULL) { 954 result = dns_tsigkey_find(&tsigkey, keyname, 955 &tsig.algorithm, ring2); 956 } 957 if (result != ISC_R_SUCCESS) { 958 msg->tsigstatus = dns_tsigerror_badkey; 959 alg = dns__tsig_algfromname(&tsig.algorithm); 960 result = dns_tsigkey_create(keyname, alg, NULL, 0, mctx, 961 &msg->tsigkey); 962 if (result != ISC_R_SUCCESS) { 963 return result; 964 } 965 if (alg == DST_ALG_UNKNOWN) { 966 dns_name_clone(&tsig.algorithm, 967 &msg->tsigkey->algname); 968 } 969 970 tsig_log(msg->tsigkey, 2, "unknown key"); 971 return DNS_R_TSIGVERIFYFAILURE; 972 } 973 msg->tsigkey = tsigkey; 974 } 975 976 key = tsigkey->key; 977 978 /* 979 * Check digest length. 980 */ 981 alg = dst_key_alg(key); 982 result = dst_key_sigsize(key, &siglen); 983 if (result != ISC_R_SUCCESS) { 984 return result; 985 } 986 if (dns__tsig_algvalid(alg)) { 987 uint16_t digestbits = dst_key_getbits(key); 988 989 if (tsig.siglen > siglen) { 990 tsig_log(msg->tsigkey, 2, "signature length too big"); 991 return DNS_R_FORMERR; 992 } 993 if (tsig.siglen > 0 && 994 (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2))) 995 { 996 tsig_log(msg->tsigkey, 2, 997 "signature length below minimum"); 998 return DNS_R_FORMERR; 999 } 1000 1001 if (tsig.siglen > 0 && digestbits != 0 && 1002 tsig.siglen < ((digestbits + 7) / 8)) 1003 { 1004 msg->tsigstatus = dns_tsigerror_badtrunc; 1005 tsig_log(msg->tsigkey, 2, 1006 "truncated signature length too small"); 1007 return DNS_R_TSIGVERIFYFAILURE; 1008 } 1009 if (tsig.siglen > 0 && digestbits == 0 && tsig.siglen < siglen) 1010 { 1011 msg->tsigstatus = dns_tsigerror_badtrunc; 1012 tsig_log(msg->tsigkey, 2, "signature length too small"); 1013 return DNS_R_TSIGVERIFYFAILURE; 1014 } 1015 } 1016 1017 if (tsig.siglen > 0) { 1018 uint16_t addcount_n; 1019 1020 sig_r.base = tsig.signature; 1021 sig_r.length = tsig.siglen; 1022 1023 result = dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, 1024 false, 0, &ctx); 1025 if (result != ISC_R_SUCCESS) { 1026 return result; 1027 } 1028 1029 if (response) { 1030 isc_buffer_init(&databuf, data, sizeof(data)); 1031 isc_buffer_putuint16(&databuf, querytsig.siglen); 1032 isc_buffer_usedregion(&databuf, &r); 1033 result = dst_context_adddata(ctx, &r); 1034 if (result != ISC_R_SUCCESS) { 1035 goto cleanup_context; 1036 } 1037 if (querytsig.siglen > 0) { 1038 r.length = querytsig.siglen; 1039 r.base = querytsig.signature; 1040 result = dst_context_adddata(ctx, &r); 1041 if (result != ISC_R_SUCCESS) { 1042 goto cleanup_context; 1043 } 1044 } 1045 } 1046 1047 /* 1048 * Extract the header. 1049 */ 1050 isc_buffer_usedregion(source, &r); 1051 memmove(header, r.base, DNS_MESSAGE_HEADERLEN); 1052 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); 1053 1054 /* 1055 * Decrement the additional field counter. 1056 */ 1057 memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2); 1058 addcount_n = ntohs(addcount); 1059 addcount = htons((uint16_t)(addcount_n - 1)); 1060 memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2); 1061 1062 /* 1063 * Put in the original id. 1064 */ 1065 id = htons(tsig.originalid); 1066 memmove(&header[0], &id, 2); 1067 1068 /* 1069 * Digest the modified header. 1070 */ 1071 header_r.base = (unsigned char *)header; 1072 header_r.length = DNS_MESSAGE_HEADERLEN; 1073 result = dst_context_adddata(ctx, &header_r); 1074 if (result != ISC_R_SUCCESS) { 1075 goto cleanup_context; 1076 } 1077 1078 /* 1079 * Digest all non-TSIG records. 1080 */ 1081 isc_buffer_usedregion(source, &source_r); 1082 r.base = source_r.base + DNS_MESSAGE_HEADERLEN; 1083 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN; 1084 result = dst_context_adddata(ctx, &r); 1085 if (result != ISC_R_SUCCESS) { 1086 goto cleanup_context; 1087 } 1088 1089 /* 1090 * Digest the key name. 1091 */ 1092 dns_name_toregion(tsigkey->name, &r); 1093 result = dst_context_adddata(ctx, &r); 1094 if (result != ISC_R_SUCCESS) { 1095 goto cleanup_context; 1096 } 1097 1098 isc_buffer_init(&databuf, data, sizeof(data)); 1099 isc_buffer_putuint16(&databuf, tsig.common.rdclass); 1100 isc_buffer_putuint32(&databuf, msg->tsig->ttl); 1101 isc_buffer_usedregion(&databuf, &r); 1102 result = dst_context_adddata(ctx, &r); 1103 if (result != ISC_R_SUCCESS) { 1104 goto cleanup_context; 1105 } 1106 1107 /* 1108 * Digest the key algorithm. 1109 */ 1110 dns_name_toregion(dns_tsigkey_algorithm(tsigkey), &r); 1111 result = dst_context_adddata(ctx, &r); 1112 if (result != ISC_R_SUCCESS) { 1113 goto cleanup_context; 1114 } 1115 1116 isc_buffer_clear(&databuf); 1117 isc_buffer_putuint48(&databuf, tsig.timesigned); 1118 isc_buffer_putuint16(&databuf, tsig.fudge); 1119 isc_buffer_putuint16(&databuf, tsig.error); 1120 isc_buffer_putuint16(&databuf, tsig.otherlen); 1121 isc_buffer_usedregion(&databuf, &r); 1122 result = dst_context_adddata(ctx, &r); 1123 if (result != ISC_R_SUCCESS) { 1124 goto cleanup_context; 1125 } 1126 1127 if (tsig.otherlen > 0) { 1128 r.base = tsig.other; 1129 r.length = tsig.otherlen; 1130 result = dst_context_adddata(ctx, &r); 1131 if (result != ISC_R_SUCCESS) { 1132 goto cleanup_context; 1133 } 1134 } 1135 1136 result = dst_context_verify(ctx, &sig_r); 1137 if (result == DST_R_VERIFYFAILURE) { 1138 result = DNS_R_TSIGVERIFYFAILURE; 1139 tsig_log(msg->tsigkey, 2, 1140 "signature failed to verify(1)"); 1141 goto cleanup_context; 1142 } else if (result != ISC_R_SUCCESS) { 1143 goto cleanup_context; 1144 } 1145 msg->verified_sig = 1; 1146 } else if (!response || (tsig.error != dns_tsigerror_badsig && 1147 tsig.error != dns_tsigerror_badkey)) 1148 { 1149 tsig_log(msg->tsigkey, 2, "signature was empty"); 1150 return DNS_R_TSIGVERIFYFAILURE; 1151 } 1152 1153 /* 1154 * Here at this point, the MAC has been verified. Even if any of 1155 * the following code returns a TSIG error, the reply will be 1156 * signed and WILL always include the request MAC in the digest 1157 * computation. 1158 */ 1159 1160 /* 1161 * Is the time ok? 1162 */ 1163 if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { 1164 msg->tsigstatus = dns_tsigerror_badtime; 1165 tsig_log(msg->tsigkey, 2, "signature has expired"); 1166 result = DNS_R_CLOCKSKEW; 1167 goto cleanup_context; 1168 } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) { 1169 msg->tsigstatus = dns_tsigerror_badtime; 1170 tsig_log(msg->tsigkey, 2, "signature is in the future"); 1171 result = DNS_R_CLOCKSKEW; 1172 goto cleanup_context; 1173 } 1174 1175 if (response && tsig.error != dns_rcode_noerror) { 1176 msg->tsigstatus = tsig.error; 1177 if (tsig.error == dns_tsigerror_badtime) { 1178 result = DNS_R_CLOCKSKEW; 1179 } else { 1180 result = DNS_R_TSIGERRORSET; 1181 } 1182 goto cleanup_context; 1183 } 1184 1185 msg->tsigstatus = dns_rcode_noerror; 1186 result = ISC_R_SUCCESS; 1187 1188 cleanup_context: 1189 if (ctx != NULL) { 1190 dst_context_destroy(&ctx); 1191 } 1192 1193 return result; 1194 } 1195 1196 static isc_result_t 1197 tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { 1198 dns_rdata_any_tsig_t tsig, querytsig; 1199 isc_region_t r, source_r, header_r, sig_r; 1200 isc_buffer_t databuf; 1201 unsigned char data[32]; 1202 dns_name_t *keyname = NULL; 1203 dns_rdata_t rdata = DNS_RDATA_INIT; 1204 isc_stdtime_t now; 1205 isc_result_t result; 1206 dns_tsigkey_t *tsigkey = NULL; 1207 dst_key_t *key = NULL; 1208 unsigned char header[DNS_MESSAGE_HEADERLEN]; 1209 uint16_t addcount, id; 1210 bool has_tsig = false; 1211 isc_mem_t *mctx = NULL; 1212 unsigned int siglen; 1213 unsigned int alg; 1214 1215 REQUIRE(source != NULL); 1216 REQUIRE(msg != NULL); 1217 REQUIRE(dns_message_gettsigkey(msg) != NULL); 1218 REQUIRE(msg->tcp_continuation == 1); 1219 REQUIRE(msg->querytsig != NULL); 1220 1221 msg->verified_sig = 0; 1222 msg->tsigstatus = dns_tsigerror_badsig; 1223 1224 if (!is_response(msg)) { 1225 return DNS_R_EXPECTEDRESPONSE; 1226 } 1227 1228 mctx = msg->mctx; 1229 1230 tsigkey = dns_message_gettsigkey(msg); 1231 key = tsigkey->key; 1232 1233 /* 1234 * Extract and parse the previous TSIG 1235 */ 1236 result = dns_rdataset_first(msg->querytsig); 1237 if (result != ISC_R_SUCCESS) { 1238 return result; 1239 } 1240 dns_rdataset_current(msg->querytsig, &rdata); 1241 result = dns_rdata_tostruct(&rdata, &querytsig, NULL); 1242 if (result != ISC_R_SUCCESS) { 1243 return result; 1244 } 1245 dns_rdata_reset(&rdata); 1246 1247 /* 1248 * If there is a TSIG in this message, do some checks. 1249 */ 1250 if (msg->tsig != NULL) { 1251 has_tsig = true; 1252 1253 keyname = msg->tsigname; 1254 result = dns_rdataset_first(msg->tsig); 1255 if (result != ISC_R_SUCCESS) { 1256 goto cleanup_querystruct; 1257 } 1258 dns_rdataset_current(msg->tsig, &rdata); 1259 result = dns_rdata_tostruct(&rdata, &tsig, NULL); 1260 if (result != ISC_R_SUCCESS) { 1261 goto cleanup_querystruct; 1262 } 1263 1264 /* 1265 * Do the key name and algorithm match that of the query? 1266 */ 1267 if (!dns_name_equal(keyname, tsigkey->name) || 1268 !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) 1269 { 1270 msg->tsigstatus = dns_tsigerror_badkey; 1271 result = DNS_R_TSIGVERIFYFAILURE; 1272 tsig_log(msg->tsigkey, 2, 1273 "key name and algorithm do not match"); 1274 goto cleanup_querystruct; 1275 } 1276 1277 /* 1278 * Check digest length. 1279 */ 1280 alg = dst_key_alg(key); 1281 result = dst_key_sigsize(key, &siglen); 1282 if (result != ISC_R_SUCCESS) { 1283 goto cleanup_querystruct; 1284 } 1285 if (dns__tsig_algvalid(alg)) { 1286 uint16_t digestbits = dst_key_getbits(key); 1287 1288 if (tsig.siglen > siglen) { 1289 tsig_log(tsigkey, 2, 1290 "signature length too big"); 1291 result = DNS_R_FORMERR; 1292 goto cleanup_querystruct; 1293 } 1294 if (tsig.siglen > 0 && 1295 (tsig.siglen < 10 || 1296 tsig.siglen < ((siglen + 1) / 2))) 1297 { 1298 tsig_log(tsigkey, 2, 1299 "signature length below minimum"); 1300 result = DNS_R_FORMERR; 1301 goto cleanup_querystruct; 1302 } 1303 1304 if (tsig.siglen > 0 && digestbits != 0 && 1305 tsig.siglen < ((digestbits + 7) / 8)) 1306 { 1307 msg->tsigstatus = dns_tsigerror_badtrunc; 1308 tsig_log(msg->tsigkey, 2, 1309 "truncated signature length " 1310 "too small"); 1311 result = DNS_R_TSIGVERIFYFAILURE; 1312 goto cleanup_querystruct; 1313 } 1314 if (tsig.siglen > 0 && digestbits == 0 && 1315 tsig.siglen < siglen) 1316 { 1317 msg->tsigstatus = dns_tsigerror_badtrunc; 1318 tsig_log(msg->tsigkey, 2, 1319 "signature length too small"); 1320 result = DNS_R_TSIGVERIFYFAILURE; 1321 goto cleanup_querystruct; 1322 } 1323 } 1324 } 1325 1326 if (msg->tsigctx == NULL) { 1327 result = dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, 1328 false, 0, &msg->tsigctx); 1329 if (result != ISC_R_SUCCESS) { 1330 goto cleanup_querystruct; 1331 } 1332 1333 /* 1334 * Digest the length of the query signature 1335 */ 1336 isc_buffer_init(&databuf, data, sizeof(data)); 1337 isc_buffer_putuint16(&databuf, querytsig.siglen); 1338 isc_buffer_usedregion(&databuf, &r); 1339 result = dst_context_adddata(msg->tsigctx, &r); 1340 if (result != ISC_R_SUCCESS) { 1341 goto cleanup_context; 1342 } 1343 1344 /* 1345 * Digest the data of the query signature 1346 */ 1347 if (querytsig.siglen > 0) { 1348 r.length = querytsig.siglen; 1349 r.base = querytsig.signature; 1350 result = dst_context_adddata(msg->tsigctx, &r); 1351 if (result != ISC_R_SUCCESS) { 1352 goto cleanup_context; 1353 } 1354 } 1355 } 1356 1357 /* 1358 * Extract the header. 1359 */ 1360 isc_buffer_usedregion(source, &r); 1361 memmove(header, r.base, DNS_MESSAGE_HEADERLEN); 1362 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); 1363 1364 /* 1365 * Decrement the additional field counter if necessary. 1366 */ 1367 if (has_tsig) { 1368 uint16_t addcount_n; 1369 1370 memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2); 1371 addcount_n = ntohs(addcount); 1372 addcount = htons((uint16_t)(addcount_n - 1)); 1373 memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2); 1374 1375 /* 1376 * Put in the original id. 1377 * 1378 * XXX Can TCP transfers be forwarded? How would that 1379 * work? 1380 */ 1381 id = htons(tsig.originalid); 1382 memmove(&header[0], &id, 2); 1383 } 1384 1385 /* 1386 * Digest the modified header. 1387 */ 1388 header_r.base = (unsigned char *)header; 1389 header_r.length = DNS_MESSAGE_HEADERLEN; 1390 result = dst_context_adddata(msg->tsigctx, &header_r); 1391 if (result != ISC_R_SUCCESS) { 1392 goto cleanup_context; 1393 } 1394 1395 /* 1396 * Digest all non-TSIG records. 1397 */ 1398 isc_buffer_usedregion(source, &source_r); 1399 r.base = source_r.base + DNS_MESSAGE_HEADERLEN; 1400 if (has_tsig) { 1401 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN; 1402 } else { 1403 r.length = source_r.length - DNS_MESSAGE_HEADERLEN; 1404 } 1405 result = dst_context_adddata(msg->tsigctx, &r); 1406 if (result != ISC_R_SUCCESS) { 1407 goto cleanup_context; 1408 } 1409 1410 /* 1411 * Digest the time signed and fudge. 1412 */ 1413 if (has_tsig) { 1414 isc_buffer_init(&databuf, data, sizeof(data)); 1415 isc_buffer_putuint48(&databuf, tsig.timesigned); 1416 isc_buffer_putuint16(&databuf, tsig.fudge); 1417 isc_buffer_usedregion(&databuf, &r); 1418 result = dst_context_adddata(msg->tsigctx, &r); 1419 if (result != ISC_R_SUCCESS) { 1420 goto cleanup_context; 1421 } 1422 1423 sig_r.base = tsig.signature; 1424 sig_r.length = tsig.siglen; 1425 if (tsig.siglen == 0) { 1426 if (tsig.error != dns_rcode_noerror) { 1427 msg->tsigstatus = tsig.error; 1428 if (tsig.error == dns_tsigerror_badtime) { 1429 result = DNS_R_CLOCKSKEW; 1430 } else { 1431 result = DNS_R_TSIGERRORSET; 1432 } 1433 } else { 1434 tsig_log(msg->tsigkey, 2, "signature is empty"); 1435 result = DNS_R_TSIGVERIFYFAILURE; 1436 } 1437 goto cleanup_context; 1438 } 1439 1440 result = dst_context_verify(msg->tsigctx, &sig_r); 1441 if (result == DST_R_VERIFYFAILURE) { 1442 tsig_log(msg->tsigkey, 2, 1443 "signature failed to verify(2)"); 1444 result = DNS_R_TSIGVERIFYFAILURE; 1445 goto cleanup_context; 1446 } else if (result != ISC_R_SUCCESS) { 1447 goto cleanup_context; 1448 } 1449 msg->verified_sig = 1; 1450 1451 /* 1452 * Here at this point, the MAC has been verified. Even 1453 * if any of the following code returns a TSIG error, 1454 * the reply will be signed and WILL always include the 1455 * request MAC in the digest computation. 1456 */ 1457 1458 /* 1459 * Is the time ok? 1460 */ 1461 if (msg->fuzzing) { 1462 now = msg->fuzztime; 1463 } else { 1464 now = isc_stdtime_now(); 1465 } 1466 1467 if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { 1468 msg->tsigstatus = dns_tsigerror_badtime; 1469 tsig_log(msg->tsigkey, 2, "signature has expired"); 1470 result = DNS_R_CLOCKSKEW; 1471 goto cleanup_context; 1472 } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) 1473 { 1474 msg->tsigstatus = dns_tsigerror_badtime; 1475 tsig_log(msg->tsigkey, 2, "signature is in the future"); 1476 result = DNS_R_CLOCKSKEW; 1477 goto cleanup_context; 1478 } 1479 1480 if (tsig.error != dns_rcode_noerror) { 1481 msg->tsigstatus = tsig.error; 1482 if (tsig.error == dns_tsigerror_badtime) { 1483 result = DNS_R_CLOCKSKEW; 1484 } else { 1485 result = DNS_R_TSIGERRORSET; 1486 } 1487 goto cleanup_context; 1488 } 1489 } 1490 1491 msg->tsigstatus = dns_rcode_noerror; 1492 result = ISC_R_SUCCESS; 1493 1494 cleanup_context: 1495 /* 1496 * Except in error conditions, don't destroy the DST context 1497 * for unsigned messages; it is a running sum till the next 1498 * TSIG signed message. 1499 */ 1500 if ((result != ISC_R_SUCCESS || has_tsig) && msg->tsigctx != NULL) { 1501 dst_context_destroy(&msg->tsigctx); 1502 } 1503 1504 cleanup_querystruct: 1505 dns_rdata_freestruct(&querytsig); 1506 1507 return result; 1508 } 1509 1510 isc_result_t 1511 dns_tsigkey_find(dns_tsigkey_t **tsigkey, const dns_name_t *name, 1512 const dns_name_t *algorithm, dns_tsigkeyring_t *ring) { 1513 dns_tsigkey_t *key = NULL; 1514 isc_result_t result; 1515 isc_rwlocktype_t locktype = isc_rwlocktype_read; 1516 isc_stdtime_t now = isc_stdtime_now(); 1517 1518 REQUIRE(name != NULL); 1519 REQUIRE(VALID_TSIGKEYRING(ring)); 1520 REQUIRE(tsigkey != NULL && *tsigkey == NULL); 1521 1522 again: 1523 RWLOCK(&ring->lock, locktype); 1524 result = isc_hashmap_find(ring->keys, dns_name_hash(name), tkey_match, 1525 name, (void **)&key); 1526 if (result == ISC_R_NOTFOUND) { 1527 RWUNLOCK(&ring->lock, locktype); 1528 return result; 1529 } 1530 1531 if (algorithm != NULL && key->alg != dns__tsig_algfromname(algorithm)) { 1532 RWUNLOCK(&ring->lock, locktype); 1533 return ISC_R_NOTFOUND; 1534 } 1535 if (key->inception != key->expire && isc_serial_lt(key->expire, now)) { 1536 /* 1537 * The key has expired. 1538 */ 1539 if (locktype == isc_rwlocktype_read) { 1540 RWUNLOCK(&ring->lock, locktype); 1541 locktype = isc_rwlocktype_write; 1542 key = NULL; 1543 goto again; 1544 } 1545 dns__tsigkey_delete(ring, key); 1546 RWUNLOCK(&ring->lock, locktype); 1547 return ISC_R_NOTFOUND; 1548 } 1549 dns_tsigkey_ref(key); 1550 RWUNLOCK(&ring->lock, locktype); 1551 adjust_lru(ring, key); 1552 *tsigkey = key; 1553 return ISC_R_SUCCESS; 1554 } 1555 1556 const dns_name_t * 1557 dns_tsigkey_algorithm(dns_tsigkey_t *tkey) { 1558 REQUIRE(VALID_TSIGKEY(tkey)); 1559 1560 switch (tkey->alg) { 1561 case DST_ALG_HMACMD5: 1562 return dns_tsig_hmacmd5_name; 1563 case DST_ALG_HMACSHA1: 1564 return dns_tsig_hmacsha1_name; 1565 case DST_ALG_HMACSHA224: 1566 return dns_tsig_hmacsha224_name; 1567 case DST_ALG_HMACSHA256: 1568 return dns_tsig_hmacsha256_name; 1569 case DST_ALG_HMACSHA384: 1570 return dns_tsig_hmacsha384_name; 1571 case DST_ALG_HMACSHA512: 1572 return dns_tsig_hmacsha512_name; 1573 case DST_ALG_GSSAPI: 1574 return dns_tsig_gssapi_name; 1575 1576 case DST_ALG_UNKNOWN: 1577 /* 1578 * If the tsigkey object was created with an 1579 * unknown algorithm, then we cloned 1580 * the algorithm name here. 1581 */ 1582 return &tkey->algname; 1583 1584 default: 1585 UNREACHABLE(); 1586 } 1587 } 1588 1589 void 1590 dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsigkeyring_t **ringp) { 1591 dns_tsigkeyring_t *ring = NULL; 1592 1593 REQUIRE(mctx != NULL); 1594 REQUIRE(ringp != NULL && *ringp == NULL); 1595 1596 ring = isc_mem_get(mctx, sizeof(dns_tsigkeyring_t)); 1597 *ring = (dns_tsigkeyring_t){ 1598 .lru = ISC_LIST_INITIALIZER, 1599 }; 1600 1601 isc_hashmap_create(mctx, 12, &ring->keys); 1602 isc_rwlock_init(&ring->lock); 1603 isc_mem_attach(mctx, &ring->mctx); 1604 isc_refcount_init(&ring->references, 1); 1605 ring->magic = TSIGKEYRING_MAGIC; 1606 1607 *ringp = ring; 1608 } 1609 1610 isc_result_t 1611 dns_tsigkeyring_add(dns_tsigkeyring_t *ring, dns_tsigkey_t *tkey) { 1612 isc_result_t result; 1613 1614 REQUIRE(VALID_TSIGKEY(tkey)); 1615 REQUIRE(VALID_TSIGKEYRING(ring)); 1616 1617 RWLOCK(&ring->lock, isc_rwlocktype_write); 1618 result = isc_hashmap_add(ring->keys, dns_name_hash(tkey->name), 1619 tkey_match, tkey->name, tkey, NULL); 1620 if (result == ISC_R_SUCCESS) { 1621 dns_tsigkey_ref(tkey); 1622 1623 /* 1624 * If this is a TKEY-generated key, add it to the LRU list, 1625 * and if we've exceeded the quota for generated keys, 1626 * remove the least recently used one from the both the 1627 * list and the RBT. 1628 */ 1629 if (tkey->generated) { 1630 ISC_LIST_APPEND(ring->lru, tkey, link); 1631 if (++ring->generated > DNS_TSIG_MAXGENERATEDKEYS) { 1632 dns_tsigkey_t *key = ISC_LIST_HEAD(ring->lru); 1633 dns__tsigkey_delete(ring, key); 1634 } 1635 } 1636 } 1637 RWUNLOCK(&ring->lock, isc_rwlocktype_write); 1638 1639 return result; 1640 } 1641 1642 void 1643 dns_tsigkeyring_restore(dns_tsigkeyring_t *ring, FILE *fp) { 1644 isc_stdtime_t now = isc_stdtime_now(); 1645 isc_result_t result; 1646 1647 do { 1648 result = restore_key(ring, now, fp); 1649 if (result == ISC_R_NOMORE) { 1650 return; 1651 } 1652 if (result == DNS_R_BADALG || result == DNS_R_EXPIRED) { 1653 result = ISC_R_SUCCESS; 1654 } 1655 } while (result == ISC_R_SUCCESS); 1656 } 1657