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