1/* 2 * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2002 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* 19 * $Id$ 20 */ 21/*! \file */ 22#include <config.h> 23#include <stdlib.h> 24 25#include <isc/buffer.h> 26#include <isc/mem.h> 27#include <isc/print.h> 28#include <isc/refcount.h> 29#include <isc/serial.h> 30#include <isc/string.h> /* Required for HP/UX (and others?) */ 31#include <isc/util.h> 32#include <isc/time.h> 33 34#include <dns/keyvalues.h> 35#include <dns/log.h> 36#include <dns/message.h> 37#include <dns/fixedname.h> 38#include <dns/rbt.h> 39#include <dns/rdata.h> 40#include <dns/rdatalist.h> 41#include <dns/rdataset.h> 42#include <dns/rdatastruct.h> 43#include <dns/result.h> 44#include <dns/tsig.h> 45 46#include <dst/result.h> 47 48#define TSIG_MAGIC ISC_MAGIC('T', 'S', 'I', 'G') 49#define VALID_TSIG_KEY(x) ISC_MAGIC_VALID(x, TSIG_MAGIC) 50 51#ifndef DNS_TSIG_MAXGENERATEDKEYS 52#define DNS_TSIG_MAXGENERATEDKEYS 4096 53#endif 54 55#define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR) 56#define algname_is_allocated(algname) \ 57 ((algname) != dns_tsig_hmacmd5_name && \ 58 (algname) != dns_tsig_hmacsha1_name && \ 59 (algname) != dns_tsig_hmacsha224_name && \ 60 (algname) != dns_tsig_hmacsha256_name && \ 61 (algname) != dns_tsig_hmacsha384_name && \ 62 (algname) != dns_tsig_hmacsha512_name && \ 63 (algname) != dns_tsig_gssapi_name && \ 64 (algname) != dns_tsig_gssapims_name) 65 66#define BADTIMELEN 6 67 68static unsigned char hmacmd5_ndata[] = "\010hmac-md5\007sig-alg\003reg\003int"; 69static unsigned char hmacmd5_offsets[] = { 0, 9, 17, 21, 25 }; 70 71static dns_name_t hmacmd5 = { 72 DNS_NAME_MAGIC, 73 hmacmd5_ndata, 26, 5, 74 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, 75 hmacmd5_offsets, NULL, 76 {(void *)-1, (void *)-1}, 77 {NULL, NULL} 78}; 79 80dns_name_t *dns_tsig_hmacmd5_name = &hmacmd5; 81 82static unsigned char gsstsig_ndata[] = "\010gss-tsig"; 83static unsigned char gsstsig_offsets[] = { 0, 9 }; 84static dns_name_t gsstsig = { 85 DNS_NAME_MAGIC, 86 gsstsig_ndata, 10, 2, 87 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, 88 gsstsig_offsets, NULL, 89 {(void *)-1, (void *)-1}, 90 {NULL, NULL} 91}; 92LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig; 93 94/* 95 * Since Microsoft doesn't follow its own standard, we will use this 96 * alternate name as a second guess. 97 */ 98static unsigned char gsstsigms_ndata[] = "\003gss\011microsoft\003com"; 99static unsigned char gsstsigms_offsets[] = { 0, 4, 14, 18 }; 100static dns_name_t gsstsigms = { 101 DNS_NAME_MAGIC, 102 gsstsigms_ndata, 19, 4, 103 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, 104 gsstsigms_offsets, NULL, 105 {(void *)-1, (void *)-1}, 106 {NULL, NULL} 107}; 108LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapims_name = &gsstsigms; 109 110static unsigned char hmacsha1_ndata[] = "\011hmac-sha1"; 111static unsigned char hmacsha1_offsets[] = { 0, 10 }; 112 113static dns_name_t hmacsha1 = { 114 DNS_NAME_MAGIC, 115 hmacsha1_ndata, 11, 2, 116 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, 117 hmacsha1_offsets, NULL, 118 {(void *)-1, (void *)-1}, 119 {NULL, NULL} 120}; 121 122LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha1_name = &hmacsha1; 123 124static unsigned char hmacsha224_ndata[] = "\013hmac-sha224"; 125static unsigned char hmacsha224_offsets[] = { 0, 12 }; 126 127static dns_name_t hmacsha224 = { 128 DNS_NAME_MAGIC, 129 hmacsha224_ndata, 13, 2, 130 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, 131 hmacsha224_offsets, NULL, 132 {(void *)-1, (void *)-1}, 133 {NULL, NULL} 134}; 135 136LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha224_name = &hmacsha224; 137 138static unsigned char hmacsha256_ndata[] = "\013hmac-sha256"; 139static unsigned char hmacsha256_offsets[] = { 0, 12 }; 140 141static dns_name_t hmacsha256 = { 142 DNS_NAME_MAGIC, 143 hmacsha256_ndata, 13, 2, 144 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, 145 hmacsha256_offsets, NULL, 146 {(void *)-1, (void *)-1}, 147 {NULL, NULL} 148}; 149 150LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha256_name = &hmacsha256; 151 152static unsigned char hmacsha384_ndata[] = "\013hmac-sha384"; 153static unsigned char hmacsha384_offsets[] = { 0, 12 }; 154 155static dns_name_t hmacsha384 = { 156 DNS_NAME_MAGIC, 157 hmacsha384_ndata, 13, 2, 158 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, 159 hmacsha384_offsets, NULL, 160 {(void *)-1, (void *)-1}, 161 {NULL, NULL} 162}; 163 164LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha384_name = &hmacsha384; 165 166static unsigned char hmacsha512_ndata[] = "\013hmac-sha512"; 167static unsigned char hmacsha512_offsets[] = { 0, 12 }; 168 169static dns_name_t hmacsha512 = { 170 DNS_NAME_MAGIC, 171 hmacsha512_ndata, 13, 2, 172 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, 173 hmacsha512_offsets, NULL, 174 {(void *)-1, (void *)-1}, 175 {NULL, NULL} 176}; 177 178LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha512_name = &hmacsha512; 179 180static isc_result_t 181tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg); 182 183static void 184tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) 185 ISC_FORMAT_PRINTF(3, 4); 186 187static void 188cleanup_ring(dns_tsig_keyring_t *ring); 189static void 190tsigkey_free(dns_tsigkey_t *key); 191 192static void 193tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) { 194 va_list ap; 195 char message[4096]; 196 char namestr[DNS_NAME_FORMATSIZE]; 197 char creatorstr[DNS_NAME_FORMATSIZE]; 198 199 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE) 200 return; 201 if (key != NULL) 202 dns_name_format(&key->name, namestr, sizeof(namestr)); 203 else 204 strcpy(namestr, "<null>"); 205 206 if (key != NULL && key->generated && key->creator) 207 dns_name_format(key->creator, creatorstr, sizeof(creatorstr)); 208 else 209 strcpy(creatorstr, "<null>"); 210 211 va_start(ap, fmt); 212 vsnprintf(message, sizeof(message), fmt, ap); 213 va_end(ap); 214 if (key != NULL && key->generated) 215 isc_log_write(dns_lctx, 216 DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG, 217 level, "tsig key '%s' (%s): %s", 218 namestr, creatorstr, message); 219 else 220 isc_log_write(dns_lctx, 221 DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG, 222 level, "tsig key '%s': %s", namestr, message); 223} 224 225static void 226remove_fromring(dns_tsigkey_t *tkey) { 227 if (tkey->generated) { 228 ISC_LIST_UNLINK(tkey->ring->lru, tkey, link); 229 tkey->ring->generated--; 230 } 231 (void)dns_rbt_deletename(tkey->ring->keys, &tkey->name, ISC_FALSE); 232} 233 234static void 235adjust_lru(dns_tsigkey_t *tkey) { 236 if (tkey->generated) { 237 RWLOCK(&tkey->ring->lock, isc_rwlocktype_write); 238 /* 239 * We may have been removed from the LRU list between 240 * removing the read lock and aquiring the write lock. 241 */ 242 if (ISC_LINK_LINKED(tkey, link) && 243 tkey->ring->lru.tail != tkey) 244 { 245 ISC_LIST_UNLINK(tkey->ring->lru, tkey, link); 246 ISC_LIST_APPEND(tkey->ring->lru, tkey, link); 247 } 248 RWUNLOCK(&tkey->ring->lock, isc_rwlocktype_write); 249 } 250} 251 252/* 253 * A supplemental routine just to add a key to ring. Note that reference 254 * counter should be counted separately because we may be adding the key 255 * as part of creation of the key, in which case the reference counter was 256 * already initialized. Also note we don't need RWLOCK for the reference 257 * counter: it's protected by a separate lock. 258 */ 259static isc_result_t 260keyring_add(dns_tsig_keyring_t *ring, dns_name_t *name, 261 dns_tsigkey_t *tkey) 262{ 263 isc_result_t result; 264 265 RWLOCK(&ring->lock, isc_rwlocktype_write); 266 ring->writecount++; 267 268 /* 269 * Do on the fly cleaning. Find some nodes we might not 270 * want around any more. 271 */ 272 if (ring->writecount > 10) { 273 cleanup_ring(ring); 274 ring->writecount = 0; 275 } 276 277 result = dns_rbt_addname(ring->keys, name, tkey); 278 if (tkey->generated) { 279 /* 280 * Add the new key to the LRU list and remove the least 281 * recently used key if there are too many keys on the list. 282 */ 283 ISC_LIST_INITANDAPPEND(ring->lru, tkey, link); 284 if (ring->generated++ > ring->maxgenerated) 285 remove_fromring(ISC_LIST_HEAD(ring->lru)); 286 } 287 RWUNLOCK(&ring->lock, isc_rwlocktype_write); 288 289 return (result); 290} 291 292isc_result_t 293dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm, 294 dst_key_t *dstkey, isc_boolean_t generated, 295 dns_name_t *creator, isc_stdtime_t inception, 296 isc_stdtime_t expire, isc_mem_t *mctx, 297 dns_tsig_keyring_t *ring, dns_tsigkey_t **key) 298{ 299 dns_tsigkey_t *tkey; 300 isc_result_t ret; 301 unsigned int refs = 0; 302 303 REQUIRE(key == NULL || *key == NULL); 304 REQUIRE(name != NULL); 305 REQUIRE(algorithm != NULL); 306 REQUIRE(mctx != NULL); 307 REQUIRE(key != NULL || ring != NULL); 308 309 tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t)); 310 if (tkey == NULL) 311 return (ISC_R_NOMEMORY); 312 313 dns_name_init(&tkey->name, NULL); 314 ret = dns_name_dup(name, mctx, &tkey->name); 315 if (ret != ISC_R_SUCCESS) 316 goto cleanup_key; 317 (void)dns_name_downcase(&tkey->name, &tkey->name, NULL); 318 319 if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { 320 tkey->algorithm = DNS_TSIG_HMACMD5_NAME; 321 if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) { 322 ret = DNS_R_BADALG; 323 goto cleanup_name; 324 } 325 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) { 326 tkey->algorithm = DNS_TSIG_HMACSHA1_NAME; 327 if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) { 328 ret = DNS_R_BADALG; 329 goto cleanup_name; 330 } 331 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) { 332 tkey->algorithm = DNS_TSIG_HMACSHA224_NAME; 333 if (dstkey != NULL && 334 dst_key_alg(dstkey) != DST_ALG_HMACSHA224) { 335 ret = DNS_R_BADALG; 336 goto cleanup_name; 337 } 338 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) { 339 tkey->algorithm = DNS_TSIG_HMACSHA256_NAME; 340 if (dstkey != NULL && 341 dst_key_alg(dstkey) != DST_ALG_HMACSHA256) { 342 ret = DNS_R_BADALG; 343 goto cleanup_name; 344 } 345 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) { 346 tkey->algorithm = DNS_TSIG_HMACSHA384_NAME; 347 if (dstkey != NULL && 348 dst_key_alg(dstkey) != DST_ALG_HMACSHA384) { 349 ret = DNS_R_BADALG; 350 goto cleanup_name; 351 } 352 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) { 353 tkey->algorithm = DNS_TSIG_HMACSHA512_NAME; 354 if (dstkey != NULL && 355 dst_key_alg(dstkey) != DST_ALG_HMACSHA512) { 356 ret = DNS_R_BADALG; 357 goto cleanup_name; 358 } 359 } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) { 360 tkey->algorithm = DNS_TSIG_GSSAPI_NAME; 361 if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) { 362 ret = DNS_R_BADALG; 363 goto cleanup_name; 364 } 365 } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) { 366 tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME; 367 if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) { 368 ret = DNS_R_BADALG; 369 goto cleanup_name; 370 } 371 } else { 372 if (dstkey != NULL) { 373 ret = DNS_R_BADALG; 374 goto cleanup_name; 375 } 376 tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t)); 377 if (tkey->algorithm == NULL) { 378 ret = ISC_R_NOMEMORY; 379 goto cleanup_name; 380 } 381 dns_name_init(tkey->algorithm, NULL); 382 ret = dns_name_dup(algorithm, mctx, tkey->algorithm); 383 if (ret != ISC_R_SUCCESS) 384 goto cleanup_algorithm; 385 (void)dns_name_downcase(tkey->algorithm, tkey->algorithm, 386 NULL); 387 } 388 389 if (creator != NULL) { 390 tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t)); 391 if (tkey->creator == NULL) { 392 ret = ISC_R_NOMEMORY; 393 goto cleanup_algorithm; 394 } 395 dns_name_init(tkey->creator, NULL); 396 ret = dns_name_dup(creator, mctx, tkey->creator); 397 if (ret != ISC_R_SUCCESS) { 398 isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t)); 399 goto cleanup_algorithm; 400 } 401 } else 402 tkey->creator = NULL; 403 404 tkey->key = NULL; 405 if (dstkey != NULL) 406 dst_key_attach(dstkey, &tkey->key); 407 tkey->ring = ring; 408 409 if (key != NULL) 410 refs = 1; 411 if (ring != NULL) 412 refs++; 413 ret = isc_refcount_init(&tkey->refs, refs); 414 if (ret != ISC_R_SUCCESS) 415 goto cleanup_creator; 416 417 tkey->generated = generated; 418 tkey->inception = inception; 419 tkey->expire = expire; 420 tkey->mctx = NULL; 421 isc_mem_attach(mctx, &tkey->mctx); 422 423 tkey->magic = TSIG_MAGIC; 424 425 if (ring != NULL) { 426 ret = keyring_add(ring, name, tkey); 427 if (ret != ISC_R_SUCCESS) 428 goto cleanup_refs; 429 } 430 431 /* 432 * Ignore this if it's a GSS key, since the key size is meaningless. 433 */ 434 if (dstkey != NULL && dst_key_size(dstkey) < 64 && 435 !dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME) && 436 !dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) { 437 char namestr[DNS_NAME_FORMATSIZE]; 438 dns_name_format(name, namestr, sizeof(namestr)); 439 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 440 DNS_LOGMODULE_TSIG, ISC_LOG_INFO, 441 "the key '%s' is too short to be secure", 442 namestr); 443 } 444 445 if (key != NULL) 446 *key = tkey; 447 448 return (ISC_R_SUCCESS); 449 450 cleanup_refs: 451 tkey->magic = 0; 452 while (refs-- > 0) 453 isc_refcount_decrement(&tkey->refs, NULL); 454 isc_refcount_destroy(&tkey->refs); 455 cleanup_creator: 456 if (tkey->key != NULL) 457 dst_key_free(&tkey->key); 458 if (tkey->creator != NULL) { 459 dns_name_free(tkey->creator, mctx); 460 isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t)); 461 } 462 cleanup_algorithm: 463 if (algname_is_allocated(tkey->algorithm)) { 464 if (dns_name_dynamic(tkey->algorithm)) 465 dns_name_free(tkey->algorithm, mctx); 466 isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t)); 467 } 468 cleanup_name: 469 dns_name_free(&tkey->name, mctx); 470 cleanup_key: 471 isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t)); 472 473 return (ret); 474} 475 476/* 477 * Find a few nodes to destroy if possible. 478 */ 479static void 480cleanup_ring(dns_tsig_keyring_t *ring) 481{ 482 isc_result_t result; 483 dns_rbtnodechain_t chain; 484 dns_name_t foundname; 485 dns_fixedname_t fixedorigin; 486 dns_name_t *origin; 487 isc_stdtime_t now; 488 dns_rbtnode_t *node; 489 dns_tsigkey_t *tkey; 490 491 /* 492 * Start up a new iterator each time. 493 */ 494 isc_stdtime_get(&now); 495 dns_name_init(&foundname, NULL); 496 dns_fixedname_init(&fixedorigin); 497 origin = dns_fixedname_name(&fixedorigin); 498 499 again: 500 dns_rbtnodechain_init(&chain, ring->mctx); 501 result = dns_rbtnodechain_first(&chain, ring->keys, &foundname, 502 origin); 503 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 504 dns_rbtnodechain_invalidate(&chain); 505 return; 506 } 507 508 for (;;) { 509 node = NULL; 510 dns_rbtnodechain_current(&chain, &foundname, origin, &node); 511 tkey = node->data; 512 if (tkey != NULL) { 513 if (tkey->generated 514 && isc_refcount_current(&tkey->refs) == 1 515 && tkey->inception != tkey->expire 516 && tkey->expire < now) { 517 tsig_log(tkey, 2, "tsig expire: deleting"); 518 /* delete the key */ 519 dns_rbtnodechain_invalidate(&chain); 520 remove_fromring(tkey); 521 goto again; 522 } 523 } 524 result = dns_rbtnodechain_next(&chain, &foundname, 525 origin); 526 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 527 dns_rbtnodechain_invalidate(&chain); 528 return; 529 } 530 } 531} 532 533static void 534destroyring(dns_tsig_keyring_t *ring) { 535 dns_rbt_destroy(&ring->keys); 536 isc_rwlock_destroy(&ring->lock); 537 isc_mem_putanddetach(&ring->mctx, ring, sizeof(dns_tsig_keyring_t)); 538} 539 540static unsigned int 541dst_alg_fromname(dns_name_t *algorithm) { 542 if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { 543 return (DST_ALG_HMACMD5); 544 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) { 545 return (DST_ALG_HMACSHA1); 546 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) { 547 return (DST_ALG_HMACSHA224); 548 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) { 549 return (DST_ALG_HMACSHA256); 550 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) { 551 return (DST_ALG_HMACSHA384); 552 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) { 553 return (DST_ALG_HMACSHA512); 554 } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) { 555 return (DST_ALG_GSSAPI); 556 } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) { 557 return (DST_ALG_GSSAPI); 558 } else 559 return (0); 560} 561 562static isc_result_t 563restore_key(dns_tsig_keyring_t *ring, isc_stdtime_t now, FILE *fp) { 564 dst_key_t *dstkey = NULL; 565 char namestr[1024]; 566 char creatorstr[1024]; 567 char algorithmstr[1024]; 568 char keystr[4096]; 569 unsigned int inception, expire; 570 int n; 571 isc_buffer_t b; 572 dns_name_t *name, *creator, *algorithm; 573 dns_fixedname_t fname, fcreator, falgorithm; 574 isc_result_t result; 575 unsigned int dstalg; 576 577 n = fscanf(fp, "%1023s %1023s %u %u %1023s %4095s\n", namestr, 578 creatorstr, &inception, &expire, algorithmstr, keystr); 579 if (n == EOF) 580 return (ISC_R_NOMORE); 581 if (n != 6) 582 return (ISC_R_FAILURE); 583 584 if (isc_serial_lt(expire, now)) 585 return (DNS_R_EXPIRED); 586 587 dns_fixedname_init(&fname); 588 name = dns_fixedname_name(&fname); 589 isc_buffer_init(&b, namestr, strlen(namestr)); 590 isc_buffer_add(&b, strlen(namestr)); 591 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); 592 if (result != ISC_R_SUCCESS) 593 return (result); 594 595 dns_fixedname_init(&fcreator); 596 creator = dns_fixedname_name(&fcreator); 597 isc_buffer_init(&b, creatorstr, strlen(creatorstr)); 598 isc_buffer_add(&b, strlen(creatorstr)); 599 result = dns_name_fromtext(creator, &b, dns_rootname, 0, NULL); 600 if (result != ISC_R_SUCCESS) 601 return (result); 602 603 dns_fixedname_init(&falgorithm); 604 algorithm = dns_fixedname_name(&falgorithm); 605 isc_buffer_init(&b, algorithmstr, strlen(algorithmstr)); 606 isc_buffer_add(&b, strlen(algorithmstr)); 607 result = dns_name_fromtext(algorithm, &b, dns_rootname, 0, NULL); 608 if (result != ISC_R_SUCCESS) 609 return (result); 610 611 dstalg = dst_alg_fromname(algorithm); 612 if (dstalg == 0) 613 return (DNS_R_BADALG); 614 615 result = dst_key_restore(name, dstalg, DNS_KEYOWNER_ENTITY, 616 DNS_KEYPROTO_DNSSEC, dns_rdataclass_in, 617 ring->mctx, keystr, &dstkey); 618 if (result != ISC_R_SUCCESS) 619 return (result); 620 621 result = dns_tsigkey_createfromkey(name, algorithm, dstkey, 622 ISC_TRUE, creator, inception, 623 expire, ring->mctx, ring, NULL); 624 if (dstkey != NULL) 625 dst_key_free(&dstkey); 626 return (result); 627} 628 629static void 630dump_key(dns_tsigkey_t *tkey, FILE *fp) { 631 char *buffer = NULL; 632 int length = 0; 633 char namestr[DNS_NAME_FORMATSIZE]; 634 char creatorstr[DNS_NAME_FORMATSIZE]; 635 char algorithmstr[DNS_NAME_FORMATSIZE]; 636 isc_result_t result; 637 638 REQUIRE(tkey != NULL); 639 REQUIRE(fp != NULL); 640 641 dns_name_format(&tkey->name, namestr, sizeof(namestr)); 642 dns_name_format(tkey->creator, creatorstr, sizeof(creatorstr)); 643 dns_name_format(tkey->algorithm, algorithmstr, sizeof(algorithmstr)); 644 result = dst_key_dump(tkey->key, tkey->mctx, &buffer, &length); 645 if (result == ISC_R_SUCCESS) 646 fprintf(fp, "%s %s %u %u %s %.*s\n", namestr, creatorstr, 647 tkey->inception, tkey->expire, algorithmstr, 648 length, buffer); 649 if (buffer != NULL) 650 isc_mem_put(tkey->mctx, buffer, length); 651} 652 653isc_result_t 654dns_tsigkeyring_dumpanddetach(dns_tsig_keyring_t **ringp, FILE *fp) { 655 isc_result_t result; 656 dns_rbtnodechain_t chain; 657 dns_name_t foundname; 658 dns_fixedname_t fixedorigin; 659 dns_name_t *origin; 660 isc_stdtime_t now; 661 dns_rbtnode_t *node; 662 dns_tsigkey_t *tkey; 663 dns_tsig_keyring_t *ring; 664 unsigned int references; 665 666 REQUIRE(ringp != NULL && *ringp != NULL); 667 668 ring = *ringp; 669 *ringp = NULL; 670 671 RWLOCK(&ring->lock, isc_rwlocktype_write); 672 INSIST(ring->references > 0); 673 ring->references--; 674 references = ring->references; 675 RWUNLOCK(&ring->lock, isc_rwlocktype_write); 676 677 if (references != 0) 678 return (DNS_R_CONTINUE); 679 680 isc_stdtime_get(&now); 681 dns_name_init(&foundname, NULL); 682 dns_fixedname_init(&fixedorigin); 683 origin = dns_fixedname_name(&fixedorigin); 684 dns_rbtnodechain_init(&chain, ring->mctx); 685 result = dns_rbtnodechain_first(&chain, ring->keys, &foundname, 686 origin); 687 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 688 dns_rbtnodechain_invalidate(&chain); 689 goto destroy; 690 } 691 692 for (;;) { 693 node = NULL; 694 dns_rbtnodechain_current(&chain, &foundname, origin, &node); 695 tkey = node->data; 696 if (tkey != NULL && tkey->generated && tkey->expire >= now) 697 dump_key(tkey, fp); 698 result = dns_rbtnodechain_next(&chain, &foundname, 699 origin); 700 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 701 dns_rbtnodechain_invalidate(&chain); 702 if (result == ISC_R_NOMORE) 703 result = ISC_R_SUCCESS; 704 goto destroy; 705 } 706 } 707 708 destroy: 709 destroyring(ring); 710 return (result); 711} 712 713isc_result_t 714dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm, 715 unsigned char *secret, int length, isc_boolean_t generated, 716 dns_name_t *creator, isc_stdtime_t inception, 717 isc_stdtime_t expire, isc_mem_t *mctx, 718 dns_tsig_keyring_t *ring, dns_tsigkey_t **key) 719{ 720 dst_key_t *dstkey = NULL; 721 isc_result_t result; 722 723 REQUIRE(length >= 0); 724 if (length > 0) 725 REQUIRE(secret != NULL); 726 727 if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { 728 if (secret != NULL) { 729 isc_buffer_t b; 730 731 isc_buffer_init(&b, secret, length); 732 isc_buffer_add(&b, length); 733 result = dst_key_frombuffer(name, DST_ALG_HMACMD5, 734 DNS_KEYOWNER_ENTITY, 735 DNS_KEYPROTO_DNSSEC, 736 dns_rdataclass_in, 737 &b, mctx, &dstkey); 738 if (result != ISC_R_SUCCESS) 739 return (result); 740 } 741 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) { 742 if (secret != NULL) { 743 isc_buffer_t b; 744 745 isc_buffer_init(&b, secret, length); 746 isc_buffer_add(&b, length); 747 result = dst_key_frombuffer(name, DST_ALG_HMACSHA1, 748 DNS_KEYOWNER_ENTITY, 749 DNS_KEYPROTO_DNSSEC, 750 dns_rdataclass_in, 751 &b, mctx, &dstkey); 752 if (result != ISC_R_SUCCESS) 753 return (result); 754 } 755 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) { 756 if (secret != NULL) { 757 isc_buffer_t b; 758 759 isc_buffer_init(&b, secret, length); 760 isc_buffer_add(&b, length); 761 result = dst_key_frombuffer(name, DST_ALG_HMACSHA224, 762 DNS_KEYOWNER_ENTITY, 763 DNS_KEYPROTO_DNSSEC, 764 dns_rdataclass_in, 765 &b, mctx, &dstkey); 766 if (result != ISC_R_SUCCESS) 767 return (result); 768 } 769 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) { 770 if (secret != NULL) { 771 isc_buffer_t b; 772 773 isc_buffer_init(&b, secret, length); 774 isc_buffer_add(&b, length); 775 result = dst_key_frombuffer(name, DST_ALG_HMACSHA256, 776 DNS_KEYOWNER_ENTITY, 777 DNS_KEYPROTO_DNSSEC, 778 dns_rdataclass_in, 779 &b, mctx, &dstkey); 780 if (result != ISC_R_SUCCESS) 781 return (result); 782 } 783 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) { 784 if (secret != NULL) { 785 isc_buffer_t b; 786 787 isc_buffer_init(&b, secret, length); 788 isc_buffer_add(&b, length); 789 result = dst_key_frombuffer(name, DST_ALG_HMACSHA384, 790 DNS_KEYOWNER_ENTITY, 791 DNS_KEYPROTO_DNSSEC, 792 dns_rdataclass_in, 793 &b, mctx, &dstkey); 794 if (result != ISC_R_SUCCESS) 795 return (result); 796 } 797 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) { 798 if (secret != NULL) { 799 isc_buffer_t b; 800 801 isc_buffer_init(&b, secret, length); 802 isc_buffer_add(&b, length); 803 result = dst_key_frombuffer(name, DST_ALG_HMACSHA512, 804 DNS_KEYOWNER_ENTITY, 805 DNS_KEYPROTO_DNSSEC, 806 dns_rdataclass_in, 807 &b, mctx, &dstkey); 808 if (result != ISC_R_SUCCESS) 809 return (result); 810 } 811 } else if (length > 0) 812 return (DNS_R_BADALG); 813 814 result = dns_tsigkey_createfromkey(name, algorithm, dstkey, 815 generated, creator, 816 inception, expire, mctx, ring, key); 817 if (dstkey != NULL) 818 dst_key_free(&dstkey); 819 return (result); 820} 821 822void 823dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) { 824 REQUIRE(VALID_TSIG_KEY(source)); 825 REQUIRE(targetp != NULL && *targetp == NULL); 826 827 isc_refcount_increment(&source->refs, NULL); 828 *targetp = source; 829} 830 831static void 832tsigkey_free(dns_tsigkey_t *key) { 833 REQUIRE(VALID_TSIG_KEY(key)); 834 835 key->magic = 0; 836 dns_name_free(&key->name, key->mctx); 837 if (algname_is_allocated(key->algorithm)) { 838 dns_name_free(key->algorithm, key->mctx); 839 isc_mem_put(key->mctx, key->algorithm, sizeof(dns_name_t)); 840 } 841 if (key->key != NULL) 842 dst_key_free(&key->key); 843 if (key->creator != NULL) { 844 dns_name_free(key->creator, key->mctx); 845 isc_mem_put(key->mctx, key->creator, sizeof(dns_name_t)); 846 } 847 isc_refcount_destroy(&key->refs); 848 isc_mem_putanddetach(&key->mctx, key, sizeof(dns_tsigkey_t)); 849} 850 851void 852dns_tsigkey_detach(dns_tsigkey_t **keyp) { 853 dns_tsigkey_t *key; 854 unsigned int refs; 855 856 REQUIRE(keyp != NULL); 857 REQUIRE(VALID_TSIG_KEY(*keyp)); 858 859 key = *keyp; 860 isc_refcount_decrement(&key->refs, &refs); 861 862 if (refs == 0) 863 tsigkey_free(key); 864 865 *keyp = NULL; 866} 867 868void 869dns_tsigkey_setdeleted(dns_tsigkey_t *key) { 870 REQUIRE(VALID_TSIG_KEY(key)); 871 REQUIRE(key->ring != NULL); 872 873 RWLOCK(&key->ring->lock, isc_rwlocktype_write); 874 remove_fromring(key); 875 RWUNLOCK(&key->ring->lock, isc_rwlocktype_write); 876} 877 878isc_result_t 879dns_tsig_sign(dns_message_t *msg) { 880 dns_tsigkey_t *key; 881 dns_rdata_any_tsig_t tsig, querytsig; 882 unsigned char data[128]; 883 isc_buffer_t databuf, sigbuf; 884 isc_buffer_t *dynbuf; 885 dns_name_t *owner; 886 dns_rdata_t *rdata = NULL; 887 dns_rdatalist_t *datalist; 888 dns_rdataset_t *dataset; 889 isc_region_t r; 890 isc_stdtime_t now; 891 isc_mem_t *mctx; 892 dst_context_t *ctx = NULL; 893 isc_result_t ret; 894 unsigned char badtimedata[BADTIMELEN]; 895 unsigned int sigsize = 0; 896 isc_boolean_t response = is_response(msg); 897 898 REQUIRE(msg != NULL); 899 REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg))); 900 901 /* 902 * If this is a response, there should be a query tsig. 903 */ 904 if (response && msg->querytsig == NULL) 905 return (DNS_R_EXPECTEDTSIG); 906 907 dynbuf = NULL; 908 909 mctx = msg->mctx; 910 key = dns_message_gettsigkey(msg); 911 912 tsig.mctx = mctx; 913 tsig.common.rdclass = dns_rdataclass_any; 914 tsig.common.rdtype = dns_rdatatype_tsig; 915 ISC_LINK_INIT(&tsig.common, link); 916 dns_name_init(&tsig.algorithm, NULL); 917 dns_name_clone(key->algorithm, &tsig.algorithm); 918 919 isc_stdtime_get(&now); 920 tsig.timesigned = now + msg->timeadjust; 921 tsig.fudge = DNS_TSIG_FUDGE; 922 923 tsig.originalid = msg->id; 924 925 isc_buffer_init(&databuf, data, sizeof(data)); 926 927 if (response) 928 tsig.error = msg->querytsigstatus; 929 else 930 tsig.error = dns_rcode_noerror; 931 932 if (tsig.error != dns_tsigerror_badtime) { 933 tsig.otherlen = 0; 934 tsig.other = NULL; 935 } else { 936 isc_buffer_t otherbuf; 937 938 tsig.otherlen = BADTIMELEN; 939 tsig.other = badtimedata; 940 isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen); 941 isc_buffer_putuint48(&otherbuf, tsig.timesigned); 942 } 943 944 if (key->key != NULL && tsig.error != dns_tsigerror_badsig) { 945 unsigned char header[DNS_MESSAGE_HEADERLEN]; 946 isc_buffer_t headerbuf; 947 isc_uint16_t digestbits; 948 949 ret = dst_context_create2(key->key, mctx, 950 DNS_LOGCATEGORY_DNSSEC, &ctx); 951 if (ret != ISC_R_SUCCESS) 952 return (ret); 953 954 /* 955 * If this is a response, digest the query signature. 956 */ 957 if (response) { 958 dns_rdata_t querytsigrdata = DNS_RDATA_INIT; 959 960 ret = dns_rdataset_first(msg->querytsig); 961 if (ret != ISC_R_SUCCESS) 962 goto cleanup_context; 963 dns_rdataset_current(msg->querytsig, &querytsigrdata); 964 ret = dns_rdata_tostruct(&querytsigrdata, &querytsig, 965 NULL); 966 if (ret != ISC_R_SUCCESS) 967 goto cleanup_context; 968 isc_buffer_putuint16(&databuf, querytsig.siglen); 969 if (isc_buffer_availablelength(&databuf) < 970 querytsig.siglen) { 971 ret = ISC_R_NOSPACE; 972 goto cleanup_context; 973 } 974 isc_buffer_putmem(&databuf, querytsig.signature, 975 querytsig.siglen); 976 isc_buffer_usedregion(&databuf, &r); 977 ret = dst_context_adddata(ctx, &r); 978 if (ret != ISC_R_SUCCESS) 979 goto cleanup_context; 980 } 981#if defined(__clang__) && \ 982 ( __clang_major__ < 3 || \ 983 (__clang_major__ == 3 && __clang_minor__ < 2) || \ 984 (__clang_major__ == 4 && __clang_minor__ < 2)) 985 /* false positive: http://llvm.org/bugs/show_bug.cgi?id=14461 */ 986 else memset(&querytsig, 0, sizeof(querytsig)); 987#endif 988 989 /* 990 * Digest the header. 991 */ 992 isc_buffer_init(&headerbuf, header, sizeof(header)); 993 dns_message_renderheader(msg, &headerbuf); 994 isc_buffer_usedregion(&headerbuf, &r); 995 ret = dst_context_adddata(ctx, &r); 996 if (ret != ISC_R_SUCCESS) 997 goto cleanup_context; 998 999 /* 1000 * Digest the remainder of the message. 1001 */ 1002 isc_buffer_usedregion(msg->buffer, &r); 1003 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); 1004 ret = dst_context_adddata(ctx, &r); 1005 if (ret != ISC_R_SUCCESS) 1006 goto cleanup_context; 1007 1008 if (msg->tcp_continuation == 0) { 1009 /* 1010 * Digest the name, class, ttl, alg. 1011 */ 1012 dns_name_toregion(&key->name, &r); 1013 ret = dst_context_adddata(ctx, &r); 1014 if (ret != ISC_R_SUCCESS) 1015 goto cleanup_context; 1016 1017 isc_buffer_clear(&databuf); 1018 isc_buffer_putuint16(&databuf, dns_rdataclass_any); 1019 isc_buffer_putuint32(&databuf, 0); /* ttl */ 1020 isc_buffer_usedregion(&databuf, &r); 1021 ret = dst_context_adddata(ctx, &r); 1022 if (ret != ISC_R_SUCCESS) 1023 goto cleanup_context; 1024 1025 dns_name_toregion(&tsig.algorithm, &r); 1026 ret = dst_context_adddata(ctx, &r); 1027 if (ret != ISC_R_SUCCESS) 1028 goto cleanup_context; 1029 1030 } 1031 /* Digest the timesigned and fudge */ 1032 isc_buffer_clear(&databuf); 1033 if (tsig.error == dns_tsigerror_badtime) { 1034 INSIST(response); 1035 tsig.timesigned = querytsig.timesigned; 1036 } 1037 isc_buffer_putuint48(&databuf, tsig.timesigned); 1038 isc_buffer_putuint16(&databuf, tsig.fudge); 1039 isc_buffer_usedregion(&databuf, &r); 1040 ret = dst_context_adddata(ctx, &r); 1041 if (ret != ISC_R_SUCCESS) 1042 goto cleanup_context; 1043 1044 if (msg->tcp_continuation == 0) { 1045 /* 1046 * Digest the error and other data length. 1047 */ 1048 isc_buffer_clear(&databuf); 1049 isc_buffer_putuint16(&databuf, tsig.error); 1050 isc_buffer_putuint16(&databuf, tsig.otherlen); 1051 1052 isc_buffer_usedregion(&databuf, &r); 1053 ret = dst_context_adddata(ctx, &r); 1054 if (ret != ISC_R_SUCCESS) 1055 goto cleanup_context; 1056 1057 /* 1058 * Digest other data. 1059 */ 1060 if (tsig.otherlen > 0) { 1061 r.length = tsig.otherlen; 1062 r.base = tsig.other; 1063 ret = dst_context_adddata(ctx, &r); 1064 if (ret != ISC_R_SUCCESS) 1065 goto cleanup_context; 1066 } 1067 } 1068 1069 ret = dst_key_sigsize(key->key, &sigsize); 1070 if (ret != ISC_R_SUCCESS) 1071 goto cleanup_context; 1072 tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize); 1073 if (tsig.signature == NULL) { 1074 ret = ISC_R_NOMEMORY; 1075 goto cleanup_context; 1076 } 1077 1078 isc_buffer_init(&sigbuf, tsig.signature, sigsize); 1079 ret = dst_context_sign(ctx, &sigbuf); 1080 if (ret != ISC_R_SUCCESS) 1081 goto cleanup_signature; 1082 dst_context_destroy(&ctx); 1083 digestbits = dst_key_getbits(key->key); 1084 if (digestbits != 0) { 1085 unsigned int bytes = (digestbits + 1) / 8; 1086 if (response && bytes < querytsig.siglen) 1087 bytes = querytsig.siglen; 1088 if (bytes > isc_buffer_usedlength(&sigbuf)) 1089 bytes = isc_buffer_usedlength(&sigbuf); 1090 tsig.siglen = bytes; 1091 } else 1092 tsig.siglen = isc_buffer_usedlength(&sigbuf); 1093 } else { 1094 tsig.siglen = 0; 1095 tsig.signature = NULL; 1096 } 1097 1098 ret = dns_message_gettemprdata(msg, &rdata); 1099 if (ret != ISC_R_SUCCESS) 1100 goto cleanup_signature; 1101 ret = isc_buffer_allocate(msg->mctx, &dynbuf, 512); 1102 if (ret != ISC_R_SUCCESS) 1103 goto cleanup_rdata; 1104 ret = dns_rdata_fromstruct(rdata, dns_rdataclass_any, 1105 dns_rdatatype_tsig, &tsig, dynbuf); 1106 if (ret != ISC_R_SUCCESS) 1107 goto cleanup_dynbuf; 1108 1109 dns_message_takebuffer(msg, &dynbuf); 1110 1111 if (tsig.signature != NULL) { 1112 isc_mem_put(mctx, tsig.signature, sigsize); 1113 tsig.signature = NULL; 1114 } 1115 1116 owner = NULL; 1117 ret = dns_message_gettempname(msg, &owner); 1118 if (ret != ISC_R_SUCCESS) 1119 goto cleanup_rdata; 1120 dns_name_init(owner, NULL); 1121 ret = dns_name_dup(&key->name, msg->mctx, owner); 1122 if (ret != ISC_R_SUCCESS) 1123 goto cleanup_owner; 1124 1125 datalist = NULL; 1126 ret = dns_message_gettemprdatalist(msg, &datalist); 1127 if (ret != ISC_R_SUCCESS) 1128 goto cleanup_owner; 1129 dataset = NULL; 1130 ret = dns_message_gettemprdataset(msg, &dataset); 1131 if (ret != ISC_R_SUCCESS) 1132 goto cleanup_rdatalist; 1133 datalist->rdclass = dns_rdataclass_any; 1134 datalist->type = dns_rdatatype_tsig; 1135 datalist->covers = 0; 1136 datalist->ttl = 0; 1137 ISC_LIST_INIT(datalist->rdata); 1138 ISC_LIST_APPEND(datalist->rdata, rdata, link); 1139 dns_rdataset_init(dataset); 1140 RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset) 1141 == ISC_R_SUCCESS); 1142 msg->tsig = dataset; 1143 msg->tsigname = owner; 1144 1145 /* Windows does not like the tsig name being compressed. */ 1146 msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS; 1147 1148 return (ISC_R_SUCCESS); 1149 1150 cleanup_rdatalist: 1151 dns_message_puttemprdatalist(msg, &datalist); 1152 cleanup_owner: 1153 dns_message_puttempname(msg, &owner); 1154 goto cleanup_rdata; 1155 cleanup_dynbuf: 1156 isc_buffer_free(&dynbuf); 1157 cleanup_rdata: 1158 dns_message_puttemprdata(msg, &rdata); 1159 cleanup_signature: 1160 if (tsig.signature != NULL) 1161 isc_mem_put(mctx, tsig.signature, sigsize); 1162 cleanup_context: 1163 if (ctx != NULL) 1164 dst_context_destroy(&ctx); 1165 return (ret); 1166} 1167 1168isc_result_t 1169dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, 1170 dns_tsig_keyring_t *ring1, dns_tsig_keyring_t *ring2) 1171{ 1172 dns_rdata_any_tsig_t tsig, querytsig; 1173 isc_region_t r, source_r, header_r, sig_r; 1174 isc_buffer_t databuf; 1175 unsigned char data[32]; 1176 dns_name_t *keyname; 1177 dns_rdata_t rdata = DNS_RDATA_INIT; 1178 isc_stdtime_t now; 1179 isc_result_t ret; 1180 dns_tsigkey_t *tsigkey; 1181 dst_key_t *key = NULL; 1182 unsigned char header[DNS_MESSAGE_HEADERLEN]; 1183 dst_context_t *ctx = NULL; 1184 isc_mem_t *mctx; 1185 isc_uint16_t addcount, id; 1186 unsigned int siglen; 1187 unsigned int alg; 1188 isc_boolean_t response; 1189 1190 REQUIRE(source != NULL); 1191 REQUIRE(DNS_MESSAGE_VALID(msg)); 1192 tsigkey = dns_message_gettsigkey(msg); 1193 response = is_response(msg); 1194 1195 REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey)); 1196 1197 msg->verify_attempted = 1; 1198 1199 if (msg->tcp_continuation) { 1200 if (tsigkey == NULL || msg->querytsig == NULL) 1201 return (DNS_R_UNEXPECTEDTSIG); 1202 return (tsig_verify_tcp(source, msg)); 1203 } 1204 1205 /* 1206 * There should be a TSIG record... 1207 */ 1208 if (msg->tsig == NULL) 1209 return (DNS_R_EXPECTEDTSIG); 1210 1211 /* 1212 * If this is a response and there's no key or query TSIG, there 1213 * shouldn't be one on the response. 1214 */ 1215 if (response && (tsigkey == NULL || msg->querytsig == NULL)) 1216 return (DNS_R_UNEXPECTEDTSIG); 1217 1218 mctx = msg->mctx; 1219 1220 /* 1221 * If we're here, we know the message is well formed and contains a 1222 * TSIG record. 1223 */ 1224 1225 keyname = msg->tsigname; 1226 ret = dns_rdataset_first(msg->tsig); 1227 if (ret != ISC_R_SUCCESS) 1228 return (ret); 1229 dns_rdataset_current(msg->tsig, &rdata); 1230 ret = dns_rdata_tostruct(&rdata, &tsig, NULL); 1231 if (ret != ISC_R_SUCCESS) 1232 return (ret); 1233 dns_rdata_reset(&rdata); 1234 if (response) { 1235 ret = dns_rdataset_first(msg->querytsig); 1236 if (ret != ISC_R_SUCCESS) 1237 return (ret); 1238 dns_rdataset_current(msg->querytsig, &rdata); 1239 ret = dns_rdata_tostruct(&rdata, &querytsig, NULL); 1240 if (ret != ISC_R_SUCCESS) 1241 return (ret); 1242 } 1243#if defined(__clang__) && \ 1244 ( __clang_major__ < 3 || \ 1245 (__clang_major__ == 3 && __clang_minor__ < 2) || \ 1246 (__clang_major__ == 4 && __clang_minor__ < 2)) 1247 /* false positive: http://llvm.org/bugs/show_bug.cgi?id=14461 */ 1248 else memset(&querytsig, 0, sizeof(querytsig)); 1249#endif 1250 1251 /* 1252 * Do the key name and algorithm match that of the query? 1253 */ 1254 if (response && 1255 (!dns_name_equal(keyname, &tsigkey->name) || 1256 !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) { 1257 msg->tsigstatus = dns_tsigerror_badkey; 1258 tsig_log(msg->tsigkey, 2, 1259 "key name and algorithm do not match"); 1260 return (DNS_R_TSIGVERIFYFAILURE); 1261 } 1262 1263 /* 1264 * Get the current time. 1265 */ 1266 isc_stdtime_get(&now); 1267 1268 /* 1269 * Find dns_tsigkey_t based on keyname. 1270 */ 1271 if (tsigkey == NULL) { 1272 ret = ISC_R_NOTFOUND; 1273 if (ring1 != NULL) 1274 ret = dns_tsigkey_find(&tsigkey, keyname, 1275 &tsig.algorithm, ring1); 1276 if (ret == ISC_R_NOTFOUND && ring2 != NULL) 1277 ret = dns_tsigkey_find(&tsigkey, keyname, 1278 &tsig.algorithm, ring2); 1279 if (ret != ISC_R_SUCCESS) { 1280 msg->tsigstatus = dns_tsigerror_badkey; 1281 ret = dns_tsigkey_create(keyname, &tsig.algorithm, 1282 NULL, 0, ISC_FALSE, NULL, 1283 now, now, 1284 mctx, NULL, &msg->tsigkey); 1285 if (ret != ISC_R_SUCCESS) 1286 return (ret); 1287 tsig_log(msg->tsigkey, 2, "unknown key"); 1288 return (DNS_R_TSIGVERIFYFAILURE); 1289 } 1290 msg->tsigkey = tsigkey; 1291 } 1292 1293 key = tsigkey->key; 1294 1295 /* 1296 * Is the time ok? 1297 */ 1298 if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { 1299 msg->tsigstatus = dns_tsigerror_badtime; 1300 tsig_log(msg->tsigkey, 2, "signature has expired"); 1301 return (DNS_R_CLOCKSKEW); 1302 } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) { 1303 msg->tsigstatus = dns_tsigerror_badtime; 1304 tsig_log(msg->tsigkey, 2, "signature is in the future"); 1305 return (DNS_R_CLOCKSKEW); 1306 } 1307 1308 /* 1309 * Check digest length. 1310 */ 1311 alg = dst_key_alg(key); 1312 ret = dst_key_sigsize(key, &siglen); 1313 if (ret != ISC_R_SUCCESS) 1314 return (ret); 1315 if (alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 || 1316 alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || 1317 alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) { 1318 isc_uint16_t digestbits = dst_key_getbits(key); 1319 if (tsig.siglen > siglen) { 1320 tsig_log(msg->tsigkey, 2, "signature length to big"); 1321 return (DNS_R_FORMERR); 1322 } 1323 if (tsig.siglen > 0 && 1324 (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2))) { 1325 tsig_log(msg->tsigkey, 2, 1326 "signature length below minimum"); 1327 return (DNS_R_FORMERR); 1328 } 1329 if (tsig.siglen > 0 && digestbits != 0 && 1330 tsig.siglen < ((digestbits + 1) / 8)) { 1331 msg->tsigstatus = dns_tsigerror_badtrunc; 1332 tsig_log(msg->tsigkey, 2, 1333 "truncated signature length too small"); 1334 return (DNS_R_TSIGVERIFYFAILURE); 1335 } 1336 if (tsig.siglen > 0 && digestbits == 0 && 1337 tsig.siglen < siglen) { 1338 msg->tsigstatus = dns_tsigerror_badtrunc; 1339 tsig_log(msg->tsigkey, 2, "signature length too small"); 1340 return (DNS_R_TSIGVERIFYFAILURE); 1341 } 1342 } 1343 1344 if (tsig.siglen > 0) { 1345 sig_r.base = tsig.signature; 1346 sig_r.length = tsig.siglen; 1347 1348 ret = dst_context_create2(key, mctx, 1349 DNS_LOGCATEGORY_DNSSEC, &ctx); 1350 if (ret != ISC_R_SUCCESS) 1351 return (ret); 1352 1353 if (response) { 1354 isc_buffer_init(&databuf, data, sizeof(data)); 1355 isc_buffer_putuint16(&databuf, querytsig.siglen); 1356 isc_buffer_usedregion(&databuf, &r); 1357 ret = dst_context_adddata(ctx, &r); 1358 if (ret != ISC_R_SUCCESS) 1359 goto cleanup_context; 1360 if (querytsig.siglen > 0) { 1361 r.length = querytsig.siglen; 1362 r.base = querytsig.signature; 1363 ret = dst_context_adddata(ctx, &r); 1364 if (ret != ISC_R_SUCCESS) 1365 goto cleanup_context; 1366 } 1367 } 1368 1369 /* 1370 * Extract the header. 1371 */ 1372 isc_buffer_usedregion(source, &r); 1373 memmove(header, r.base, DNS_MESSAGE_HEADERLEN); 1374 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); 1375 1376 /* 1377 * Decrement the additional field counter. 1378 */ 1379 memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2); 1380 addcount = htons((isc_uint16_t)(ntohs(addcount) - 1)); 1381 memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2); 1382 1383 /* 1384 * Put in the original id. 1385 */ 1386 id = htons(tsig.originalid); 1387 memmove(&header[0], &id, 2); 1388 1389 /* 1390 * Digest the modified header. 1391 */ 1392 header_r.base = (unsigned char *) header; 1393 header_r.length = DNS_MESSAGE_HEADERLEN; 1394 ret = dst_context_adddata(ctx, &header_r); 1395 if (ret != ISC_R_SUCCESS) 1396 goto cleanup_context; 1397 1398 /* 1399 * Digest all non-TSIG records. 1400 */ 1401 isc_buffer_usedregion(source, &source_r); 1402 r.base = source_r.base + DNS_MESSAGE_HEADERLEN; 1403 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN; 1404 ret = dst_context_adddata(ctx, &r); 1405 if (ret != ISC_R_SUCCESS) 1406 goto cleanup_context; 1407 1408 /* 1409 * Digest the key name. 1410 */ 1411 dns_name_toregion(&tsigkey->name, &r); 1412 ret = dst_context_adddata(ctx, &r); 1413 if (ret != ISC_R_SUCCESS) 1414 goto cleanup_context; 1415 1416 isc_buffer_init(&databuf, data, sizeof(data)); 1417 isc_buffer_putuint16(&databuf, tsig.common.rdclass); 1418 isc_buffer_putuint32(&databuf, msg->tsig->ttl); 1419 isc_buffer_usedregion(&databuf, &r); 1420 ret = dst_context_adddata(ctx, &r); 1421 if (ret != ISC_R_SUCCESS) 1422 goto cleanup_context; 1423 1424 /* 1425 * Digest the key algorithm. 1426 */ 1427 dns_name_toregion(tsigkey->algorithm, &r); 1428 ret = dst_context_adddata(ctx, &r); 1429 if (ret != ISC_R_SUCCESS) 1430 goto cleanup_context; 1431 1432 isc_buffer_clear(&databuf); 1433 isc_buffer_putuint48(&databuf, tsig.timesigned); 1434 isc_buffer_putuint16(&databuf, tsig.fudge); 1435 isc_buffer_putuint16(&databuf, tsig.error); 1436 isc_buffer_putuint16(&databuf, tsig.otherlen); 1437 isc_buffer_usedregion(&databuf, &r); 1438 ret = dst_context_adddata(ctx, &r); 1439 if (ret != ISC_R_SUCCESS) 1440 goto cleanup_context; 1441 1442 if (tsig.otherlen > 0) { 1443 r.base = tsig.other; 1444 r.length = tsig.otherlen; 1445 ret = dst_context_adddata(ctx, &r); 1446 if (ret != ISC_R_SUCCESS) 1447 goto cleanup_context; 1448 } 1449 1450 ret = dst_context_verify(ctx, &sig_r); 1451 if (ret == DST_R_VERIFYFAILURE) { 1452 msg->tsigstatus = dns_tsigerror_badsig; 1453 ret = DNS_R_TSIGVERIFYFAILURE; 1454 tsig_log(msg->tsigkey, 2, 1455 "signature failed to verify(1)"); 1456 goto cleanup_context; 1457 } else if (ret != ISC_R_SUCCESS) 1458 goto cleanup_context; 1459 1460 dst_context_destroy(&ctx); 1461 } else if (tsig.error != dns_tsigerror_badsig && 1462 tsig.error != dns_tsigerror_badkey) { 1463 msg->tsigstatus = dns_tsigerror_badsig; 1464 tsig_log(msg->tsigkey, 2, "signature was empty"); 1465 return (DNS_R_TSIGVERIFYFAILURE); 1466 } 1467 1468 msg->tsigstatus = dns_rcode_noerror; 1469 1470 if (tsig.error != dns_rcode_noerror) { 1471 if (tsig.error == dns_tsigerror_badtime) 1472 return (DNS_R_CLOCKSKEW); 1473 else 1474 return (DNS_R_TSIGERRORSET); 1475 } 1476 1477 msg->verified_sig = 1; 1478 1479 return (ISC_R_SUCCESS); 1480 1481cleanup_context: 1482 if (ctx != NULL) 1483 dst_context_destroy(&ctx); 1484 1485 return (ret); 1486} 1487 1488static isc_result_t 1489tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { 1490 dns_rdata_any_tsig_t tsig, querytsig; 1491 isc_region_t r, source_r, header_r, sig_r; 1492 isc_buffer_t databuf; 1493 unsigned char data[32]; 1494 dns_name_t *keyname; 1495 dns_rdata_t rdata = DNS_RDATA_INIT; 1496 isc_stdtime_t now; 1497 isc_result_t ret; 1498 dns_tsigkey_t *tsigkey; 1499 dst_key_t *key = NULL; 1500 unsigned char header[DNS_MESSAGE_HEADERLEN]; 1501 isc_uint16_t addcount, id; 1502 isc_boolean_t has_tsig = ISC_FALSE; 1503 isc_mem_t *mctx; 1504 1505 REQUIRE(source != NULL); 1506 REQUIRE(msg != NULL); 1507 REQUIRE(dns_message_gettsigkey(msg) != NULL); 1508 REQUIRE(msg->tcp_continuation == 1); 1509 REQUIRE(msg->querytsig != NULL); 1510 1511 if (!is_response(msg)) 1512 return (DNS_R_EXPECTEDRESPONSE); 1513 1514 mctx = msg->mctx; 1515 1516 tsigkey = dns_message_gettsigkey(msg); 1517 1518 /* 1519 * Extract and parse the previous TSIG 1520 */ 1521 ret = dns_rdataset_first(msg->querytsig); 1522 if (ret != ISC_R_SUCCESS) 1523 return (ret); 1524 dns_rdataset_current(msg->querytsig, &rdata); 1525 ret = dns_rdata_tostruct(&rdata, &querytsig, NULL); 1526 if (ret != ISC_R_SUCCESS) 1527 return (ret); 1528 dns_rdata_reset(&rdata); 1529 1530 /* 1531 * If there is a TSIG in this message, do some checks. 1532 */ 1533 if (msg->tsig != NULL) { 1534 has_tsig = ISC_TRUE; 1535 1536 keyname = msg->tsigname; 1537 ret = dns_rdataset_first(msg->tsig); 1538 if (ret != ISC_R_SUCCESS) 1539 goto cleanup_querystruct; 1540 dns_rdataset_current(msg->tsig, &rdata); 1541 ret = dns_rdata_tostruct(&rdata, &tsig, NULL); 1542 if (ret != ISC_R_SUCCESS) 1543 goto cleanup_querystruct; 1544 1545 /* 1546 * Do the key name and algorithm match that of the query? 1547 */ 1548 if (!dns_name_equal(keyname, &tsigkey->name) || 1549 !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) { 1550 msg->tsigstatus = dns_tsigerror_badkey; 1551 ret = DNS_R_TSIGVERIFYFAILURE; 1552 tsig_log(msg->tsigkey, 2, 1553 "key name and algorithm do not match"); 1554 goto cleanup_querystruct; 1555 } 1556 1557 /* 1558 * Is the time ok? 1559 */ 1560 isc_stdtime_get(&now); 1561 1562 if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { 1563 msg->tsigstatus = dns_tsigerror_badtime; 1564 tsig_log(msg->tsigkey, 2, "signature has expired"); 1565 ret = DNS_R_CLOCKSKEW; 1566 goto cleanup_querystruct; 1567 } else if (now + msg->timeadjust < 1568 tsig.timesigned - tsig.fudge) { 1569 msg->tsigstatus = dns_tsigerror_badtime; 1570 tsig_log(msg->tsigkey, 2, 1571 "signature is in the future"); 1572 ret = DNS_R_CLOCKSKEW; 1573 goto cleanup_querystruct; 1574 } 1575 } 1576 1577 key = tsigkey->key; 1578 1579 if (msg->tsigctx == NULL) { 1580 ret = dst_context_create2(key, mctx, 1581 DNS_LOGCATEGORY_DNSSEC, 1582 &msg->tsigctx); 1583 if (ret != ISC_R_SUCCESS) 1584 goto cleanup_querystruct; 1585 1586 /* 1587 * Digest the length of the query signature 1588 */ 1589 isc_buffer_init(&databuf, data, sizeof(data)); 1590 isc_buffer_putuint16(&databuf, querytsig.siglen); 1591 isc_buffer_usedregion(&databuf, &r); 1592 ret = dst_context_adddata(msg->tsigctx, &r); 1593 if (ret != ISC_R_SUCCESS) 1594 goto cleanup_context; 1595 1596 /* 1597 * Digest the data of the query signature 1598 */ 1599 if (querytsig.siglen > 0) { 1600 r.length = querytsig.siglen; 1601 r.base = querytsig.signature; 1602 ret = dst_context_adddata(msg->tsigctx, &r); 1603 if (ret != ISC_R_SUCCESS) 1604 goto cleanup_context; 1605 } 1606 } 1607 1608 /* 1609 * Extract the header. 1610 */ 1611 isc_buffer_usedregion(source, &r); 1612 memmove(header, r.base, DNS_MESSAGE_HEADERLEN); 1613 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); 1614 1615 /* 1616 * Decrement the additional field counter if necessary. 1617 */ 1618 if (has_tsig) { 1619 memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2); 1620 addcount = htons((isc_uint16_t)(ntohs(addcount) - 1)); 1621 memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2); 1622 } 1623 1624 /* 1625 * Put in the original id. 1626 */ 1627 /* XXX Can TCP transfers be forwarded? How would that work? */ 1628 if (has_tsig) { 1629 id = htons(tsig.originalid); 1630 memmove(&header[0], &id, 2); 1631 } 1632 1633 /* 1634 * Digest the modified header. 1635 */ 1636 header_r.base = (unsigned char *) header; 1637 header_r.length = DNS_MESSAGE_HEADERLEN; 1638 ret = dst_context_adddata(msg->tsigctx, &header_r); 1639 if (ret != ISC_R_SUCCESS) 1640 goto cleanup_context; 1641 1642 /* 1643 * Digest all non-TSIG records. 1644 */ 1645 isc_buffer_usedregion(source, &source_r); 1646 r.base = source_r.base + DNS_MESSAGE_HEADERLEN; 1647 if (has_tsig) 1648 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN; 1649 else 1650 r.length = source_r.length - DNS_MESSAGE_HEADERLEN; 1651 ret = dst_context_adddata(msg->tsigctx, &r); 1652 if (ret != ISC_R_SUCCESS) 1653 goto cleanup_context; 1654 1655 /* 1656 * Digest the time signed and fudge. 1657 */ 1658 if (has_tsig) { 1659 isc_buffer_init(&databuf, data, sizeof(data)); 1660 isc_buffer_putuint48(&databuf, tsig.timesigned); 1661 isc_buffer_putuint16(&databuf, tsig.fudge); 1662 isc_buffer_usedregion(&databuf, &r); 1663 ret = dst_context_adddata(msg->tsigctx, &r); 1664 if (ret != ISC_R_SUCCESS) 1665 goto cleanup_context; 1666 1667 sig_r.base = tsig.signature; 1668 sig_r.length = tsig.siglen; 1669 if (tsig.siglen == 0) { 1670 if (tsig.error != dns_rcode_noerror) { 1671 if (tsig.error == dns_tsigerror_badtime) 1672 ret = DNS_R_CLOCKSKEW; 1673 else 1674 ret = DNS_R_TSIGERRORSET; 1675 } else { 1676 tsig_log(msg->tsigkey, 2, 1677 "signature is empty"); 1678 ret = DNS_R_TSIGVERIFYFAILURE; 1679 } 1680 goto cleanup_context; 1681 } 1682 1683 ret = dst_context_verify(msg->tsigctx, &sig_r); 1684 if (ret == DST_R_VERIFYFAILURE) { 1685 msg->tsigstatus = dns_tsigerror_badsig; 1686 tsig_log(msg->tsigkey, 2, 1687 "signature failed to verify(2)"); 1688 ret = DNS_R_TSIGVERIFYFAILURE; 1689 goto cleanup_context; 1690 } 1691 else if (ret != ISC_R_SUCCESS) 1692 goto cleanup_context; 1693 1694 dst_context_destroy(&msg->tsigctx); 1695 } 1696 1697 msg->tsigstatus = dns_rcode_noerror; 1698 return (ISC_R_SUCCESS); 1699 1700 cleanup_context: 1701 dst_context_destroy(&msg->tsigctx); 1702 1703 cleanup_querystruct: 1704 dns_rdata_freestruct(&querytsig); 1705 1706 return (ret); 1707 1708} 1709 1710isc_result_t 1711dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name, 1712 dns_name_t *algorithm, dns_tsig_keyring_t *ring) 1713{ 1714 dns_tsigkey_t *key; 1715 isc_stdtime_t now; 1716 isc_result_t result; 1717 1718 REQUIRE(tsigkey != NULL); 1719 REQUIRE(*tsigkey == NULL); 1720 REQUIRE(name != NULL); 1721 REQUIRE(ring != NULL); 1722 1723 RWLOCK(&ring->lock, isc_rwlocktype_write); 1724 cleanup_ring(ring); 1725 RWUNLOCK(&ring->lock, isc_rwlocktype_write); 1726 1727 isc_stdtime_get(&now); 1728 RWLOCK(&ring->lock, isc_rwlocktype_read); 1729 key = NULL; 1730 result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key); 1731 if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) { 1732 RWUNLOCK(&ring->lock, isc_rwlocktype_read); 1733 return (ISC_R_NOTFOUND); 1734 } 1735 if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) { 1736 RWUNLOCK(&ring->lock, isc_rwlocktype_read); 1737 return (ISC_R_NOTFOUND); 1738 } 1739 if (key->inception != key->expire && isc_serial_lt(key->expire, now)) { 1740 /* 1741 * The key has expired. 1742 */ 1743 RWUNLOCK(&ring->lock, isc_rwlocktype_read); 1744 RWLOCK(&ring->lock, isc_rwlocktype_write); 1745 remove_fromring(key); 1746 RWUNLOCK(&ring->lock, isc_rwlocktype_write); 1747 return (ISC_R_NOTFOUND); 1748 } 1749#if 0 1750 /* 1751 * MPAXXX We really should look at the inception time. 1752 */ 1753 if (key->inception != key->expire && 1754 isc_serial_lt(key->inception, now)) { 1755 RWUNLOCK(&ring->lock, isc_rwlocktype_read); 1756 adjust_lru(key); 1757 return (ISC_R_NOTFOUND); 1758 } 1759#endif 1760 isc_refcount_increment(&key->refs, NULL); 1761 RWUNLOCK(&ring->lock, isc_rwlocktype_read); 1762 adjust_lru(key); 1763 *tsigkey = key; 1764 return (ISC_R_SUCCESS); 1765} 1766 1767static void 1768free_tsignode(void *node, void *_unused) { 1769 dns_tsigkey_t *key; 1770 1771 REQUIRE(node != NULL); 1772 1773 UNUSED(_unused); 1774 1775 key = node; 1776 if (key->generated) { 1777 if (ISC_LINK_LINKED(key, link)) 1778 ISC_LIST_UNLINK(key->ring->lru, key, link); 1779 } 1780 dns_tsigkey_detach(&key); 1781} 1782 1783isc_result_t 1784dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) { 1785 isc_result_t result; 1786 dns_tsig_keyring_t *ring; 1787 1788 REQUIRE(mctx != NULL); 1789 REQUIRE(ringp != NULL); 1790 REQUIRE(*ringp == NULL); 1791 1792 ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t)); 1793 if (ring == NULL) 1794 return (ISC_R_NOMEMORY); 1795 1796 result = isc_rwlock_init(&ring->lock, 0, 0); 1797 if (result != ISC_R_SUCCESS) { 1798 isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t)); 1799 return (result); 1800 } 1801 1802 ring->keys = NULL; 1803 result = dns_rbt_create(mctx, free_tsignode, NULL, &ring->keys); 1804 if (result != ISC_R_SUCCESS) { 1805 isc_rwlock_destroy(&ring->lock); 1806 isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t)); 1807 return (result); 1808 } 1809 1810 ring->writecount = 0; 1811 ring->mctx = NULL; 1812 ring->generated = 0; 1813 ring->maxgenerated = DNS_TSIG_MAXGENERATEDKEYS; 1814 ISC_LIST_INIT(ring->lru); 1815 isc_mem_attach(mctx, &ring->mctx); 1816 ring->references = 1; 1817 1818 *ringp = ring; 1819 return (ISC_R_SUCCESS); 1820} 1821 1822isc_result_t 1823dns_tsigkeyring_add(dns_tsig_keyring_t *ring, dns_name_t *name, 1824 dns_tsigkey_t *tkey) 1825{ 1826 isc_result_t result; 1827 1828 result = keyring_add(ring, name, tkey); 1829 if (result == ISC_R_SUCCESS) 1830 isc_refcount_increment(&tkey->refs, NULL); 1831 1832 return (result); 1833} 1834 1835void 1836dns_tsigkeyring_attach(dns_tsig_keyring_t *source, dns_tsig_keyring_t **target) 1837{ 1838 REQUIRE(source != NULL); 1839 REQUIRE(target != NULL && *target == NULL); 1840 1841 RWLOCK(&source->lock, isc_rwlocktype_write); 1842 INSIST(source->references > 0); 1843 source->references++; 1844 INSIST(source->references > 0); 1845 *target = source; 1846 RWUNLOCK(&source->lock, isc_rwlocktype_write); 1847} 1848 1849void 1850dns_tsigkeyring_detach(dns_tsig_keyring_t **ringp) { 1851 dns_tsig_keyring_t *ring; 1852 unsigned int references; 1853 1854 REQUIRE(ringp != NULL); 1855 REQUIRE(*ringp != NULL); 1856 1857 ring = *ringp; 1858 *ringp = NULL; 1859 1860 RWLOCK(&ring->lock, isc_rwlocktype_write); 1861 INSIST(ring->references > 0); 1862 ring->references--; 1863 references = ring->references; 1864 RWUNLOCK(&ring->lock, isc_rwlocktype_write); 1865 1866 if (references == 0) 1867 destroyring(ring); 1868} 1869 1870void 1871dns_keyring_restore(dns_tsig_keyring_t *ring, FILE *fp) { 1872 isc_stdtime_t now; 1873 isc_result_t result; 1874 1875 isc_stdtime_get(&now); 1876 do { 1877 result = restore_key(ring, now, fp); 1878 if (result == ISC_R_NOMORE) 1879 return; 1880 if (result == DNS_R_BADALG || result == DNS_R_EXPIRED) 1881 result = ISC_R_SUCCESS; 1882 } while (result == ISC_R_SUCCESS); 1883} 1884