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