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