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