1/* 2 * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* 19 * $Id$ 20 */ 21 22/*! \file */ 23 24#include <config.h> 25 26#include <stdlib.h> 27 28#include <isc/buffer.h> 29#include <isc/dir.h> 30#include <isc/mem.h> 31#include <isc/serial.h> 32#include <isc/string.h> 33#include <isc/util.h> 34 35#include <dns/db.h> 36#include <dns/diff.h> 37#include <dns/dnssec.h> 38#include <dns/fixedname.h> 39#include <dns/keyvalues.h> 40#include <dns/log.h> 41#include <dns/message.h> 42#include <dns/rdata.h> 43#include <dns/rdatalist.h> 44#include <dns/rdataset.h> 45#include <dns/rdatastruct.h> 46#include <dns/result.h> 47#include <dns/stats.h> 48#include <dns/tsig.h> /* for DNS_TSIG_FUDGE */ 49 50#include <dst/result.h> 51 52LIBDNS_EXTERNAL_DATA isc_stats_t *dns_dnssec_stats; 53 54#define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR) 55 56#define RETERR(x) do { \ 57 result = (x); \ 58 if (result != ISC_R_SUCCESS) \ 59 goto failure; \ 60 } while (0) 61 62 63#define TYPE_SIGN 0 64#define TYPE_VERIFY 1 65 66static isc_result_t 67digest_callback(void *arg, isc_region_t *data); 68 69static int 70rdata_compare_wrapper(const void *rdata1, const void *rdata2); 71 72static isc_result_t 73rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx, 74 dns_rdata_t **rdata, int *nrdata); 75 76static isc_result_t 77digest_callback(void *arg, isc_region_t *data) { 78 dst_context_t *ctx = arg; 79 80 return (dst_context_adddata(ctx, data)); 81} 82 83static inline void 84inc_stat(isc_statscounter_t counter) { 85 if (dns_dnssec_stats != NULL) 86 isc_stats_increment(dns_dnssec_stats, counter); 87} 88 89/* 90 * Make qsort happy. 91 */ 92static int 93rdata_compare_wrapper(const void *rdata1, const void *rdata2) { 94 return (dns_rdata_compare((const dns_rdata_t *)rdata1, 95 (const dns_rdata_t *)rdata2)); 96} 97 98/* 99 * Sort the rdataset into an array. 100 */ 101static isc_result_t 102rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx, 103 dns_rdata_t **rdata, int *nrdata) 104{ 105 isc_result_t ret; 106 int i = 0, n; 107 dns_rdata_t *data; 108 dns_rdataset_t rdataset; 109 110 n = dns_rdataset_count(set); 111 112 data = isc_mem_get(mctx, n * sizeof(dns_rdata_t)); 113 if (data == NULL) 114 return (ISC_R_NOMEMORY); 115 116 dns_rdataset_init(&rdataset); 117 dns_rdataset_clone(set, &rdataset); 118 ret = dns_rdataset_first(&rdataset); 119 if (ret != ISC_R_SUCCESS) { 120 dns_rdataset_disassociate(&rdataset); 121 isc_mem_put(mctx, data, n * sizeof(dns_rdata_t)); 122 return (ret); 123 } 124 125 /* 126 * Put them in the array. 127 */ 128 do { 129 dns_rdata_init(&data[i]); 130 dns_rdataset_current(&rdataset, &data[i++]); 131 } while (dns_rdataset_next(&rdataset) == ISC_R_SUCCESS); 132 133 /* 134 * Sort the array. 135 */ 136 qsort(data, n, sizeof(dns_rdata_t), rdata_compare_wrapper); 137 *rdata = data; 138 *nrdata = n; 139 dns_rdataset_disassociate(&rdataset); 140 return (ISC_R_SUCCESS); 141} 142 143isc_result_t 144dns_dnssec_keyfromrdata(dns_name_t *name, dns_rdata_t *rdata, isc_mem_t *mctx, 145 dst_key_t **key) 146{ 147 isc_buffer_t b; 148 isc_region_t r; 149 150 INSIST(name != NULL); 151 INSIST(rdata != NULL); 152 INSIST(mctx != NULL); 153 INSIST(key != NULL); 154 INSIST(*key == NULL); 155 REQUIRE(rdata->type == dns_rdatatype_key || 156 rdata->type == dns_rdatatype_dnskey); 157 158 dns_rdata_toregion(rdata, &r); 159 isc_buffer_init(&b, r.base, r.length); 160 isc_buffer_add(&b, r.length); 161 return (dst_key_fromdns(name, rdata->rdclass, &b, mctx, key)); 162} 163 164static isc_result_t 165digest_sig(dst_context_t *ctx, isc_boolean_t downcase, dns_rdata_t *sigrdata, 166 dns_rdata_rrsig_t *rrsig) 167{ 168 isc_region_t r; 169 isc_result_t ret; 170 dns_fixedname_t fname; 171 172 dns_rdata_toregion(sigrdata, &r); 173 INSIST(r.length >= 19); 174 175 r.length = 18; 176 ret = dst_context_adddata(ctx, &r); 177 if (ret != ISC_R_SUCCESS) 178 return (ret); 179 if (downcase) { 180 dns_fixedname_init(&fname); 181 182 RUNTIME_CHECK(dns_name_downcase(&rrsig->signer, 183 dns_fixedname_name(&fname), 184 NULL) == ISC_R_SUCCESS); 185 dns_name_toregion(dns_fixedname_name(&fname), &r); 186 } else 187 dns_name_toregion(&rrsig->signer, &r); 188 189 return (dst_context_adddata(ctx, &r)); 190} 191 192isc_result_t 193dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, 194 isc_stdtime_t *inception, isc_stdtime_t *expire, 195 isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata) 196{ 197 dns_rdata_rrsig_t sig; 198 dns_rdata_t tmpsigrdata; 199 dns_rdata_t *rdatas; 200 int nrdatas, i; 201 isc_buffer_t sigbuf, envbuf; 202 isc_region_t r; 203 dst_context_t *ctx = NULL; 204 isc_result_t ret; 205 isc_buffer_t *databuf = NULL; 206 char data[256 + 8]; 207 isc_uint32_t flags; 208 unsigned int sigsize; 209 dns_fixedname_t fnewname; 210 dns_fixedname_t fsigner; 211 212 REQUIRE(name != NULL); 213 REQUIRE(dns_name_countlabels(name) <= 255); 214 REQUIRE(set != NULL); 215 REQUIRE(key != NULL); 216 REQUIRE(inception != NULL); 217 REQUIRE(expire != NULL); 218 REQUIRE(mctx != NULL); 219 REQUIRE(sigrdata != NULL); 220 221 if (*inception >= *expire) 222 return (DNS_R_INVALIDTIME); 223 224 /* 225 * Is the key allowed to sign data? 226 */ 227 flags = dst_key_flags(key); 228 if (flags & DNS_KEYTYPE_NOAUTH) 229 return (DNS_R_KEYUNAUTHORIZED); 230 if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) 231 return (DNS_R_KEYUNAUTHORIZED); 232 233 sig.mctx = mctx; 234 sig.common.rdclass = set->rdclass; 235 sig.common.rdtype = dns_rdatatype_rrsig; 236 ISC_LINK_INIT(&sig.common, link); 237 238 /* 239 * Downcase signer. 240 */ 241 dns_name_init(&sig.signer, NULL); 242 dns_fixedname_init(&fsigner); 243 RUNTIME_CHECK(dns_name_downcase(dst_key_name(key), 244 dns_fixedname_name(&fsigner), NULL) == ISC_R_SUCCESS); 245 dns_name_clone(dns_fixedname_name(&fsigner), &sig.signer); 246 247 sig.covered = set->type; 248 sig.algorithm = dst_key_alg(key); 249 sig.labels = dns_name_countlabels(name) - 1; 250 if (dns_name_iswildcard(name)) 251 sig.labels--; 252 sig.originalttl = set->ttl; 253 sig.timesigned = *inception; 254 sig.timeexpire = *expire; 255 sig.keyid = dst_key_id(key); 256 ret = dst_key_sigsize(key, &sigsize); 257 if (ret != ISC_R_SUCCESS) 258 return (ret); 259 sig.siglen = sigsize; 260 /* 261 * The actual contents of sig.signature are not important yet, since 262 * they're not used in digest_sig(). 263 */ 264 sig.signature = isc_mem_get(mctx, sig.siglen); 265 if (sig.signature == NULL) 266 return (ISC_R_NOMEMORY); 267 268 ret = isc_buffer_allocate(mctx, &databuf, sigsize + 256 + 18); 269 if (ret != ISC_R_SUCCESS) 270 goto cleanup_signature; 271 272 dns_rdata_init(&tmpsigrdata); 273 ret = dns_rdata_fromstruct(&tmpsigrdata, sig.common.rdclass, 274 sig.common.rdtype, &sig, databuf); 275 if (ret != ISC_R_SUCCESS) 276 goto cleanup_databuf; 277 278 ret = dst_context_create2(key, mctx, DNS_LOGCATEGORY_DNSSEC, &ctx); 279 if (ret != ISC_R_SUCCESS) 280 goto cleanup_databuf; 281 282 /* 283 * Digest the SIG rdata. 284 */ 285 ret = digest_sig(ctx, ISC_FALSE, &tmpsigrdata, &sig); 286 if (ret != ISC_R_SUCCESS) 287 goto cleanup_context; 288 289 dns_fixedname_init(&fnewname); 290 RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname), 291 NULL) == ISC_R_SUCCESS); 292 dns_name_toregion(dns_fixedname_name(&fnewname), &r); 293 294 /* 295 * Create an envelope for each rdata: <name|type|class|ttl>. 296 */ 297 isc_buffer_init(&envbuf, data, sizeof(data)); 298 memmove(data, r.base, r.length); 299 isc_buffer_add(&envbuf, r.length); 300 isc_buffer_putuint16(&envbuf, set->type); 301 isc_buffer_putuint16(&envbuf, set->rdclass); 302 isc_buffer_putuint32(&envbuf, set->ttl); 303 304 ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas); 305 if (ret != ISC_R_SUCCESS) 306 goto cleanup_context; 307 isc_buffer_usedregion(&envbuf, &r); 308 309 for (i = 0; i < nrdatas; i++) { 310 isc_uint16_t len; 311 isc_buffer_t lenbuf; 312 isc_region_t lenr; 313 314 /* 315 * Skip duplicates. 316 */ 317 if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0) 318 continue; 319 320 /* 321 * Digest the envelope. 322 */ 323 ret = dst_context_adddata(ctx, &r); 324 if (ret != ISC_R_SUCCESS) 325 goto cleanup_array; 326 327 /* 328 * Digest the length of the rdata. 329 */ 330 isc_buffer_init(&lenbuf, &len, sizeof(len)); 331 INSIST(rdatas[i].length < 65536); 332 isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length); 333 isc_buffer_usedregion(&lenbuf, &lenr); 334 ret = dst_context_adddata(ctx, &lenr); 335 if (ret != ISC_R_SUCCESS) 336 goto cleanup_array; 337 338 /* 339 * Digest the rdata. 340 */ 341 ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx); 342 if (ret != ISC_R_SUCCESS) 343 goto cleanup_array; 344 } 345 346 isc_buffer_init(&sigbuf, sig.signature, sig.siglen); 347 ret = dst_context_sign(ctx, &sigbuf); 348 if (ret != ISC_R_SUCCESS) 349 goto cleanup_array; 350 isc_buffer_usedregion(&sigbuf, &r); 351 if (r.length != sig.siglen) { 352 ret = ISC_R_NOSPACE; 353 goto cleanup_array; 354 } 355 356 ret = dns_rdata_fromstruct(sigrdata, sig.common.rdclass, 357 sig.common.rdtype, &sig, buffer); 358 359cleanup_array: 360 isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t)); 361cleanup_context: 362 dst_context_destroy(&ctx); 363cleanup_databuf: 364 isc_buffer_free(&databuf); 365cleanup_signature: 366 isc_mem_put(mctx, sig.signature, sig.siglen); 367 368 return (ret); 369} 370 371isc_result_t 372dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, 373 isc_boolean_t ignoretime, isc_mem_t *mctx, 374 dns_rdata_t *sigrdata, dns_name_t *wild) 375{ 376 return (dns_dnssec_verify3(name, set, key, ignoretime, 0, mctx, 377 sigrdata, wild)); 378} 379 380isc_result_t 381dns_dnssec_verify3(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, 382 isc_boolean_t ignoretime, unsigned int maxbits, 383 isc_mem_t *mctx, dns_rdata_t *sigrdata, dns_name_t *wild) 384{ 385 dns_rdata_rrsig_t sig; 386 dns_fixedname_t fnewname; 387 isc_region_t r; 388 isc_buffer_t envbuf; 389 dns_rdata_t *rdatas; 390 int nrdatas, i; 391 isc_stdtime_t now; 392 isc_result_t ret; 393 unsigned char data[300]; 394 dst_context_t *ctx = NULL; 395 int labels = 0; 396 isc_uint32_t flags; 397 isc_boolean_t downcase = ISC_FALSE; 398 399 REQUIRE(name != NULL); 400 REQUIRE(set != NULL); 401 REQUIRE(key != NULL); 402 REQUIRE(mctx != NULL); 403 REQUIRE(sigrdata != NULL && sigrdata->type == dns_rdatatype_rrsig); 404 405 ret = dns_rdata_tostruct(sigrdata, &sig, NULL); 406 if (ret != ISC_R_SUCCESS) 407 return (ret); 408 409 if (set->type != sig.covered) 410 return (DNS_R_SIGINVALID); 411 412 if (isc_serial_lt(sig.timeexpire, sig.timesigned)) { 413 inc_stat(dns_dnssecstats_fail); 414 return (DNS_R_SIGINVALID); 415 } 416 417 if (!ignoretime) { 418 isc_stdtime_get(&now); 419 420 /* 421 * Is SIG temporally valid? 422 */ 423 if (isc_serial_lt((isc_uint32_t)now, sig.timesigned)) { 424 inc_stat(dns_dnssecstats_fail); 425 return (DNS_R_SIGFUTURE); 426 } else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now)) { 427 inc_stat(dns_dnssecstats_fail); 428 return (DNS_R_SIGEXPIRED); 429 } 430 } 431 432 /* 433 * NS, SOA and DNSSKEY records are signed by their owner. 434 * DS records are signed by the parent. 435 */ 436 switch (set->type) { 437 case dns_rdatatype_ns: 438 case dns_rdatatype_soa: 439 case dns_rdatatype_dnskey: 440 if (!dns_name_equal(name, &sig.signer)) { 441 inc_stat(dns_dnssecstats_fail); 442 return (DNS_R_SIGINVALID); 443 } 444 break; 445 case dns_rdatatype_ds: 446 if (dns_name_equal(name, &sig.signer)) { 447 inc_stat(dns_dnssecstats_fail); 448 return (DNS_R_SIGINVALID); 449 } 450 /* FALLTHROUGH */ 451 default: 452 if (!dns_name_issubdomain(name, &sig.signer)) { 453 inc_stat(dns_dnssecstats_fail); 454 return (DNS_R_SIGINVALID); 455 } 456 break; 457 } 458 459 /* 460 * Is the key allowed to sign data? 461 */ 462 flags = dst_key_flags(key); 463 if (flags & DNS_KEYTYPE_NOAUTH) { 464 inc_stat(dns_dnssecstats_fail); 465 return (DNS_R_KEYUNAUTHORIZED); 466 } 467 if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) { 468 inc_stat(dns_dnssecstats_fail); 469 return (DNS_R_KEYUNAUTHORIZED); 470 } 471 472 again: 473 ret = dst_context_create2(key, mctx, DNS_LOGCATEGORY_DNSSEC, &ctx); 474 if (ret != ISC_R_SUCCESS) 475 goto cleanup_struct; 476 477 /* 478 * Digest the SIG rdata (not including the signature). 479 */ 480 ret = digest_sig(ctx, downcase, sigrdata, &sig); 481 if (ret != ISC_R_SUCCESS) 482 goto cleanup_context; 483 484 /* 485 * If the name is an expanded wildcard, use the wildcard name. 486 */ 487 dns_fixedname_init(&fnewname); 488 labels = dns_name_countlabels(name) - 1; 489 RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname), 490 NULL) == ISC_R_SUCCESS); 491 if (labels - sig.labels > 0) 492 dns_name_split(dns_fixedname_name(&fnewname), sig.labels + 1, 493 NULL, dns_fixedname_name(&fnewname)); 494 495 dns_name_toregion(dns_fixedname_name(&fnewname), &r); 496 497 /* 498 * Create an envelope for each rdata: <name|type|class|ttl>. 499 */ 500 isc_buffer_init(&envbuf, data, sizeof(data)); 501 if (labels - sig.labels > 0) { 502 isc_buffer_putuint8(&envbuf, 1); 503 isc_buffer_putuint8(&envbuf, '*'); 504 memmove(data + 2, r.base, r.length); 505 } 506 else 507 memmove(data, r.base, r.length); 508 isc_buffer_add(&envbuf, r.length); 509 isc_buffer_putuint16(&envbuf, set->type); 510 isc_buffer_putuint16(&envbuf, set->rdclass); 511 isc_buffer_putuint32(&envbuf, sig.originalttl); 512 513 ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas); 514 if (ret != ISC_R_SUCCESS) 515 goto cleanup_context; 516 517 isc_buffer_usedregion(&envbuf, &r); 518 519 for (i = 0; i < nrdatas; i++) { 520 isc_uint16_t len; 521 isc_buffer_t lenbuf; 522 isc_region_t lenr; 523 524 /* 525 * Skip duplicates. 526 */ 527 if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0) 528 continue; 529 530 /* 531 * Digest the envelope. 532 */ 533 ret = dst_context_adddata(ctx, &r); 534 if (ret != ISC_R_SUCCESS) 535 goto cleanup_array; 536 537 /* 538 * Digest the rdata length. 539 */ 540 isc_buffer_init(&lenbuf, &len, sizeof(len)); 541 INSIST(rdatas[i].length < 65536); 542 isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length); 543 isc_buffer_usedregion(&lenbuf, &lenr); 544 545 /* 546 * Digest the rdata. 547 */ 548 ret = dst_context_adddata(ctx, &lenr); 549 if (ret != ISC_R_SUCCESS) 550 goto cleanup_array; 551 ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx); 552 if (ret != ISC_R_SUCCESS) 553 goto cleanup_array; 554 } 555 556 r.base = sig.signature; 557 r.length = sig.siglen; 558 ret = dst_context_verify2(ctx, maxbits, &r); 559 if (ret == ISC_R_SUCCESS && downcase) { 560 char namebuf[DNS_NAME_FORMATSIZE]; 561 dns_name_format(&sig.signer, namebuf, sizeof(namebuf)); 562 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 563 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), 564 "successfully validated after lower casing " 565 "signer '%s'", namebuf); 566 inc_stat(dns_dnssecstats_downcase); 567 } else if (ret == ISC_R_SUCCESS) 568 inc_stat(dns_dnssecstats_asis); 569 570cleanup_array: 571 isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t)); 572cleanup_context: 573 dst_context_destroy(&ctx); 574 if (ret == DST_R_VERIFYFAILURE && !downcase) { 575 downcase = ISC_TRUE; 576 goto again; 577 } 578cleanup_struct: 579 dns_rdata_freestruct(&sig); 580 581 if (ret == DST_R_VERIFYFAILURE) 582 ret = DNS_R_SIGINVALID; 583 584 if (ret != ISC_R_SUCCESS) 585 inc_stat(dns_dnssecstats_fail); 586 587 if (ret == ISC_R_SUCCESS && labels - sig.labels > 0) { 588 if (wild != NULL) 589 RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, 590 dns_fixedname_name(&fnewname), 591 wild, NULL) == ISC_R_SUCCESS); 592 inc_stat(dns_dnssecstats_wildcard); 593 ret = DNS_R_FROMWILDCARD; 594 } 595 return (ret); 596} 597 598isc_result_t 599dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, 600 isc_boolean_t ignoretime, isc_mem_t *mctx, 601 dns_rdata_t *sigrdata) 602{ 603 isc_result_t result; 604 605 result = dns_dnssec_verify2(name, set, key, ignoretime, mctx, 606 sigrdata, NULL); 607 if (result == DNS_R_FROMWILDCARD) 608 result = ISC_R_SUCCESS; 609 return (result); 610} 611 612isc_boolean_t 613dns_dnssec_keyactive(dst_key_t *key, isc_stdtime_t now) { 614 isc_result_t result; 615 isc_stdtime_t publish, active, revoke, inactive, delete; 616 isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE; 617 isc_boolean_t revset = ISC_FALSE, inactset = ISC_FALSE; 618 isc_boolean_t delset = ISC_FALSE; 619 int major, minor; 620 621 /* Is this an old-style key? */ 622 result = dst_key_getprivateformat(key, &major, &minor); 623 RUNTIME_CHECK(result == ISC_R_SUCCESS); 624 625 /* 626 * Smart signing started with key format 1.3; prior to that, all 627 * keys are assumed active 628 */ 629 if (major == 1 && minor <= 2) 630 return (ISC_TRUE); 631 632 result = dst_key_gettime(key, DST_TIME_PUBLISH, &publish); 633 if (result == ISC_R_SUCCESS) 634 pubset = ISC_TRUE; 635 636 result = dst_key_gettime(key, DST_TIME_ACTIVATE, &active); 637 if (result == ISC_R_SUCCESS) 638 actset = ISC_TRUE; 639 640 result = dst_key_gettime(key, DST_TIME_REVOKE, &revoke); 641 if (result == ISC_R_SUCCESS) 642 revset = ISC_TRUE; 643 644 result = dst_key_gettime(key, DST_TIME_INACTIVE, &inactive); 645 if (result == ISC_R_SUCCESS) 646 inactset = ISC_TRUE; 647 648 result = dst_key_gettime(key, DST_TIME_DELETE, &delete); 649 if (result == ISC_R_SUCCESS) 650 delset = ISC_TRUE; 651 652 if ((inactset && inactive <= now) || (delset && delete <= now)) 653 return (ISC_FALSE); 654 655 if (revset && revoke <= now && pubset && publish <= now) 656 return (ISC_TRUE); 657 658 if (actset && active <= now) 659 return (ISC_TRUE); 660 661 return (ISC_FALSE); 662} 663 664#define is_zone_key(key) ((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) \ 665 == DNS_KEYOWNER_ZONE) 666 667isc_result_t 668dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver, 669 dns_dbnode_t *node, dns_name_t *name, 670 const char *directory, isc_mem_t *mctx, 671 unsigned int maxkeys, dst_key_t **keys, 672 unsigned int *nkeys) 673{ 674 dns_rdataset_t rdataset; 675 dns_rdata_t rdata = DNS_RDATA_INIT; 676 isc_result_t result; 677 dst_key_t *pubkey = NULL; 678 unsigned int count = 0; 679 isc_stdtime_t now; 680 681 REQUIRE(nkeys != NULL); 682 REQUIRE(keys != NULL); 683 684 isc_stdtime_get(&now); 685 686 *nkeys = 0; 687 memset(keys, 0, sizeof(*keys) * maxkeys); 688 dns_rdataset_init(&rdataset); 689 RETERR(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0, 690 &rdataset, NULL)); 691 RETERR(dns_rdataset_first(&rdataset)); 692 while (result == ISC_R_SUCCESS && count < maxkeys) { 693 pubkey = NULL; 694 dns_rdataset_current(&rdataset, &rdata); 695 RETERR(dns_dnssec_keyfromrdata(name, &rdata, mctx, &pubkey)); 696 dst_key_setttl(pubkey, rdataset.ttl); 697 698 if (!is_zone_key(pubkey) || 699 (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0) 700 goto next; 701 /* Corrupted .key file? */ 702 if (!dns_name_equal(name, dst_key_name(pubkey))) 703 goto next; 704 keys[count] = NULL; 705 result = dst_key_fromfile(dst_key_name(pubkey), 706 dst_key_id(pubkey), 707 dst_key_alg(pubkey), 708 DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, 709 directory, 710 mctx, &keys[count]); 711 712 /* 713 * If the key was revoked and the private file 714 * doesn't exist, maybe it was revoked internally 715 * by named. Try loading the unrevoked version. 716 */ 717 if (result == ISC_R_FILENOTFOUND) { 718 isc_uint32_t flags; 719 flags = dst_key_flags(pubkey); 720 if ((flags & DNS_KEYFLAG_REVOKE) != 0) { 721 dst_key_setflags(pubkey, 722 flags & ~DNS_KEYFLAG_REVOKE); 723 result = dst_key_fromfile(dst_key_name(pubkey), 724 dst_key_id(pubkey), 725 dst_key_alg(pubkey), 726 DST_TYPE_PUBLIC| 727 DST_TYPE_PRIVATE, 728 directory, 729 mctx, &keys[count]); 730 if (result == ISC_R_SUCCESS && 731 dst_key_pubcompare(pubkey, keys[count], 732 ISC_FALSE)) { 733 dst_key_setflags(keys[count], flags); 734 } 735 dst_key_setflags(pubkey, flags); 736 } 737 } 738 739 if (result != ISC_R_SUCCESS) { 740 char keybuf[DNS_NAME_FORMATSIZE]; 741 char algbuf[DNS_SECALG_FORMATSIZE]; 742 dns_name_format(dst_key_name(pubkey), keybuf, 743 sizeof(keybuf)); 744 dns_secalg_format(dst_key_alg(pubkey), algbuf, 745 sizeof(algbuf)); 746 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 747 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, 748 "dns_dnssec_findzonekeys2: error " 749 "reading private key file %s/%s/%d: %s", 750 keybuf, algbuf, dst_key_id(pubkey), 751 isc_result_totext(result)); 752 } 753 754 if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) { 755 keys[count] = pubkey; 756 pubkey = NULL; 757 count++; 758 goto next; 759 } 760 761 if (result != ISC_R_SUCCESS) 762 goto failure; 763 764 /* 765 * If a key is marked inactive, skip it 766 */ 767 if (!dns_dnssec_keyactive(keys[count], now)) { 768 dst_key_setinactive(pubkey, ISC_TRUE); 769 dst_key_free(&keys[count]); 770 keys[count] = pubkey; 771 pubkey = NULL; 772 count++; 773 goto next; 774 } 775 776 /* 777 * Whatever the key's default TTL may have 778 * been, the rdataset TTL takes priority. 779 */ 780 dst_key_setttl(keys[count], rdataset.ttl); 781 782 if ((dst_key_flags(keys[count]) & DNS_KEYTYPE_NOAUTH) != 0) { 783 /* We should never get here. */ 784 dst_key_free(&keys[count]); 785 goto next; 786 } 787 count++; 788 next: 789 if (pubkey != NULL) 790 dst_key_free(&pubkey); 791 dns_rdata_reset(&rdata); 792 result = dns_rdataset_next(&rdataset); 793 } 794 if (result != ISC_R_NOMORE) 795 goto failure; 796 if (count == 0) 797 result = ISC_R_NOTFOUND; 798 else 799 result = ISC_R_SUCCESS; 800 801 failure: 802 if (dns_rdataset_isassociated(&rdataset)) 803 dns_rdataset_disassociate(&rdataset); 804 if (pubkey != NULL) 805 dst_key_free(&pubkey); 806 if (result != ISC_R_SUCCESS) 807 while (count > 0) 808 dst_key_free(&keys[--count]); 809 *nkeys = count; 810 return (result); 811} 812 813isc_result_t 814dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver, 815 dns_dbnode_t *node, dns_name_t *name, isc_mem_t *mctx, 816 unsigned int maxkeys, dst_key_t **keys, 817 unsigned int *nkeys) 818{ 819 return (dns_dnssec_findzonekeys2(db, ver, node, name, NULL, mctx, 820 maxkeys, keys, nkeys)); 821} 822 823isc_result_t 824dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key) { 825 dns_rdata_sig_t sig; /* SIG(0) */ 826 unsigned char data[512]; 827 unsigned char header[DNS_MESSAGE_HEADERLEN]; 828 isc_buffer_t headerbuf, databuf, sigbuf; 829 unsigned int sigsize; 830 isc_buffer_t *dynbuf = NULL; 831 dns_rdata_t *rdata; 832 dns_rdatalist_t *datalist; 833 dns_rdataset_t *dataset; 834 isc_region_t r; 835 isc_stdtime_t now; 836 dst_context_t *ctx = NULL; 837 isc_mem_t *mctx; 838 isc_result_t result; 839 isc_boolean_t signeedsfree = ISC_TRUE; 840 841 REQUIRE(msg != NULL); 842 REQUIRE(key != NULL); 843 844 if (is_response(msg)) 845 REQUIRE(msg->query.base != NULL); 846 847 mctx = msg->mctx; 848 849 memset(&sig, 0, sizeof(sig)); 850 851 sig.mctx = mctx; 852 sig.common.rdclass = dns_rdataclass_any; 853 sig.common.rdtype = dns_rdatatype_sig; /* SIG(0) */ 854 ISC_LINK_INIT(&sig.common, link); 855 856 sig.covered = 0; 857 sig.algorithm = dst_key_alg(key); 858 sig.labels = 0; /* the root name */ 859 sig.originalttl = 0; 860 861 isc_stdtime_get(&now); 862 sig.timesigned = now - DNS_TSIG_FUDGE; 863 sig.timeexpire = now + DNS_TSIG_FUDGE; 864 865 sig.keyid = dst_key_id(key); 866 867 dns_name_init(&sig.signer, NULL); 868 dns_name_clone(dst_key_name(key), &sig.signer); 869 870 sig.siglen = 0; 871 sig.signature = NULL; 872 873 isc_buffer_init(&databuf, data, sizeof(data)); 874 875 RETERR(dst_context_create2(key, mctx, DNS_LOGCATEGORY_DNSSEC, &ctx)); 876 877 /* 878 * Digest the fields of the SIG - we can cheat and use 879 * dns_rdata_fromstruct. Since siglen is 0, the digested data 880 * is identical to dns format. 881 */ 882 RETERR(dns_rdata_fromstruct(NULL, dns_rdataclass_any, 883 dns_rdatatype_sig /* SIG(0) */, 884 &sig, &databuf)); 885 isc_buffer_usedregion(&databuf, &r); 886 RETERR(dst_context_adddata(ctx, &r)); 887 888 /* 889 * If this is a response, digest the query. 890 */ 891 if (is_response(msg)) 892 RETERR(dst_context_adddata(ctx, &msg->query)); 893 894 /* 895 * Digest the header. 896 */ 897 isc_buffer_init(&headerbuf, header, sizeof(header)); 898 dns_message_renderheader(msg, &headerbuf); 899 isc_buffer_usedregion(&headerbuf, &r); 900 RETERR(dst_context_adddata(ctx, &r)); 901 902 /* 903 * Digest the remainder of the message. 904 */ 905 isc_buffer_usedregion(msg->buffer, &r); 906 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); 907 RETERR(dst_context_adddata(ctx, &r)); 908 909 RETERR(dst_key_sigsize(key, &sigsize)); 910 sig.siglen = sigsize; 911 sig.signature = (unsigned char *) isc_mem_get(mctx, sig.siglen); 912 if (sig.signature == NULL) { 913 result = ISC_R_NOMEMORY; 914 goto failure; 915 } 916 917 isc_buffer_init(&sigbuf, sig.signature, sig.siglen); 918 RETERR(dst_context_sign(ctx, &sigbuf)); 919 dst_context_destroy(&ctx); 920 921 rdata = NULL; 922 RETERR(dns_message_gettemprdata(msg, &rdata)); 923 RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 1024)); 924 RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any, 925 dns_rdatatype_sig /* SIG(0) */, 926 &sig, dynbuf)); 927 928 isc_mem_put(mctx, sig.signature, sig.siglen); 929 signeedsfree = ISC_FALSE; 930 931 dns_message_takebuffer(msg, &dynbuf); 932 933 datalist = NULL; 934 RETERR(dns_message_gettemprdatalist(msg, &datalist)); 935 datalist->rdclass = dns_rdataclass_any; 936 datalist->type = dns_rdatatype_sig; /* SIG(0) */ 937 datalist->covers = 0; 938 datalist->ttl = 0; 939 ISC_LIST_INIT(datalist->rdata); 940 ISC_LIST_APPEND(datalist->rdata, rdata, link); 941 dataset = NULL; 942 RETERR(dns_message_gettemprdataset(msg, &dataset)); 943 dns_rdataset_init(dataset); 944 RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset) == ISC_R_SUCCESS); 945 msg->sig0 = dataset; 946 947 return (ISC_R_SUCCESS); 948 949failure: 950 if (dynbuf != NULL) 951 isc_buffer_free(&dynbuf); 952 if (signeedsfree) 953 isc_mem_put(mctx, sig.signature, sig.siglen); 954 if (ctx != NULL) 955 dst_context_destroy(&ctx); 956 957 return (result); 958} 959 960isc_result_t 961dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg, 962 dst_key_t *key) 963{ 964 dns_rdata_sig_t sig; /* SIG(0) */ 965 unsigned char header[DNS_MESSAGE_HEADERLEN]; 966 dns_rdata_t rdata = DNS_RDATA_INIT; 967 isc_region_t r, source_r, sig_r, header_r; 968 isc_stdtime_t now; 969 dst_context_t *ctx = NULL; 970 isc_mem_t *mctx; 971 isc_result_t result; 972 isc_uint16_t addcount; 973 isc_boolean_t signeedsfree = ISC_FALSE; 974 975 REQUIRE(source != NULL); 976 REQUIRE(msg != NULL); 977 REQUIRE(key != NULL); 978 979 mctx = msg->mctx; 980 981 msg->verify_attempted = 1; 982 983 if (is_response(msg)) { 984 if (msg->query.base == NULL) 985 return (DNS_R_UNEXPECTEDTSIG); 986 } 987 988 isc_buffer_usedregion(source, &source_r); 989 990 RETERR(dns_rdataset_first(msg->sig0)); 991 dns_rdataset_current(msg->sig0, &rdata); 992 993 RETERR(dns_rdata_tostruct(&rdata, &sig, NULL)); 994 signeedsfree = ISC_TRUE; 995 996 if (sig.labels != 0) { 997 result = DNS_R_SIGINVALID; 998 goto failure; 999 } 1000 1001 if (isc_serial_lt(sig.timeexpire, sig.timesigned)) { 1002 result = DNS_R_SIGINVALID; 1003 msg->sig0status = dns_tsigerror_badtime; 1004 goto failure; 1005 } 1006 1007 isc_stdtime_get(&now); 1008 if (isc_serial_lt((isc_uint32_t)now, sig.timesigned)) { 1009 result = DNS_R_SIGFUTURE; 1010 msg->sig0status = dns_tsigerror_badtime; 1011 goto failure; 1012 } 1013 else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now)) { 1014 result = DNS_R_SIGEXPIRED; 1015 msg->sig0status = dns_tsigerror_badtime; 1016 goto failure; 1017 } 1018 1019 if (!dns_name_equal(dst_key_name(key), &sig.signer)) { 1020 result = DNS_R_SIGINVALID; 1021 msg->sig0status = dns_tsigerror_badkey; 1022 goto failure; 1023 } 1024 1025 RETERR(dst_context_create2(key, mctx, DNS_LOGCATEGORY_DNSSEC, &ctx)); 1026 1027 /* 1028 * Digest the SIG(0) record, except for the signature. 1029 */ 1030 dns_rdata_toregion(&rdata, &r); 1031 r.length -= sig.siglen; 1032 RETERR(dst_context_adddata(ctx, &r)); 1033 1034 /* 1035 * If this is a response, digest the query. 1036 */ 1037 if (is_response(msg)) 1038 RETERR(dst_context_adddata(ctx, &msg->query)); 1039 1040 /* 1041 * Extract the header. 1042 */ 1043 memmove(header, source_r.base, DNS_MESSAGE_HEADERLEN); 1044 1045 /* 1046 * Decrement the additional field counter. 1047 */ 1048 memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2); 1049 addcount = htons((isc_uint16_t)(ntohs(addcount) - 1)); 1050 memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2); 1051 1052 /* 1053 * Digest the modified header. 1054 */ 1055 header_r.base = (unsigned char *) header; 1056 header_r.length = DNS_MESSAGE_HEADERLEN; 1057 RETERR(dst_context_adddata(ctx, &header_r)); 1058 1059 /* 1060 * Digest all non-SIG(0) records. 1061 */ 1062 r.base = source_r.base + DNS_MESSAGE_HEADERLEN; 1063 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN; 1064 RETERR(dst_context_adddata(ctx, &r)); 1065 1066 sig_r.base = sig.signature; 1067 sig_r.length = sig.siglen; 1068 result = dst_context_verify(ctx, &sig_r); 1069 if (result != ISC_R_SUCCESS) { 1070 msg->sig0status = dns_tsigerror_badsig; 1071 goto failure; 1072 } 1073 1074 msg->verified_sig = 1; 1075 1076 dst_context_destroy(&ctx); 1077 dns_rdata_freestruct(&sig); 1078 1079 return (ISC_R_SUCCESS); 1080 1081failure: 1082 if (signeedsfree) 1083 dns_rdata_freestruct(&sig); 1084 if (ctx != NULL) 1085 dst_context_destroy(&ctx); 1086 1087 return (result); 1088} 1089 1090/*% 1091 * Does this key ('rdata') self sign the rrset ('rdataset')? 1092 */ 1093isc_boolean_t 1094dns_dnssec_selfsigns(dns_rdata_t *rdata, dns_name_t *name, 1095 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, 1096 isc_boolean_t ignoretime, isc_mem_t *mctx) 1097{ 1098 INSIST(rdataset->type == dns_rdatatype_key || 1099 rdataset->type == dns_rdatatype_dnskey); 1100 if (rdataset->type == dns_rdatatype_key) { 1101 INSIST(sigrdataset->type == dns_rdatatype_sig); 1102 INSIST(sigrdataset->covers == dns_rdatatype_key); 1103 } else { 1104 INSIST(sigrdataset->type == dns_rdatatype_rrsig); 1105 INSIST(sigrdataset->covers == dns_rdatatype_dnskey); 1106 } 1107 1108 return (dns_dnssec_signs(rdata, name, rdataset, sigrdataset, 1109 ignoretime, mctx)); 1110 1111} 1112 1113isc_boolean_t 1114dns_dnssec_signs(dns_rdata_t *rdata, dns_name_t *name, 1115 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, 1116 isc_boolean_t ignoretime, isc_mem_t *mctx) 1117{ 1118 dst_key_t *dstkey = NULL; 1119 dns_keytag_t keytag; 1120 dns_rdata_dnskey_t key; 1121 dns_rdata_rrsig_t sig; 1122 dns_rdata_t sigrdata = DNS_RDATA_INIT; 1123 isc_result_t result; 1124 1125 INSIST(sigrdataset->type == dns_rdatatype_rrsig); 1126 if (sigrdataset->covers != rdataset->type) 1127 return (ISC_FALSE); 1128 1129 result = dns_dnssec_keyfromrdata(name, rdata, mctx, &dstkey); 1130 if (result != ISC_R_SUCCESS) 1131 return (ISC_FALSE); 1132 result = dns_rdata_tostruct(rdata, &key, NULL); 1133 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1134 1135 keytag = dst_key_id(dstkey); 1136 for (result = dns_rdataset_first(sigrdataset); 1137 result == ISC_R_SUCCESS; 1138 result = dns_rdataset_next(sigrdataset)) 1139 { 1140 dns_rdata_reset(&sigrdata); 1141 dns_rdataset_current(sigrdataset, &sigrdata); 1142 result = dns_rdata_tostruct(&sigrdata, &sig, NULL); 1143 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1144 1145 if (sig.algorithm == key.algorithm && 1146 sig.keyid == keytag) { 1147 result = dns_dnssec_verify2(name, rdataset, dstkey, 1148 ignoretime, mctx, 1149 &sigrdata, NULL); 1150 if (result == ISC_R_SUCCESS) { 1151 dst_key_free(&dstkey); 1152 return (ISC_TRUE); 1153 } 1154 } 1155 } 1156 dst_key_free(&dstkey); 1157 return (ISC_FALSE); 1158} 1159 1160isc_result_t 1161dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey, 1162 dns_dnsseckey_t **dkp) 1163{ 1164 isc_result_t result; 1165 dns_dnsseckey_t *dk; 1166 int major, minor; 1167 1168 REQUIRE(dkp != NULL && *dkp == NULL); 1169 dk = isc_mem_get(mctx, sizeof(dns_dnsseckey_t)); 1170 if (dk == NULL) 1171 return (ISC_R_NOMEMORY); 1172 1173 dk->key = *dstkey; 1174 *dstkey = NULL; 1175 dk->force_publish = ISC_FALSE; 1176 dk->force_sign = ISC_FALSE; 1177 dk->hint_publish = ISC_FALSE; 1178 dk->hint_sign = ISC_FALSE; 1179 dk->hint_remove = ISC_FALSE; 1180 dk->first_sign = ISC_FALSE; 1181 dk->is_active = ISC_FALSE; 1182 dk->prepublish = 0; 1183 dk->source = dns_keysource_unknown; 1184 dk->index = 0; 1185 1186 /* KSK or ZSK? */ 1187 dk->ksk = ISC_TF((dst_key_flags(dk->key) & DNS_KEYFLAG_KSK) != 0); 1188 1189 /* Is this an old-style key? */ 1190 result = dst_key_getprivateformat(dk->key, &major, &minor); 1191 INSIST(result == ISC_R_SUCCESS); 1192 1193 /* Smart signing started with key format 1.3 */ 1194 dk->legacy = ISC_TF(major == 1 && minor <= 2); 1195 1196 ISC_LINK_INIT(dk, link); 1197 *dkp = dk; 1198 return (ISC_R_SUCCESS); 1199} 1200 1201void 1202dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp) { 1203 dns_dnsseckey_t *dk; 1204 1205 REQUIRE(dkp != NULL && *dkp != NULL); 1206 dk = *dkp; 1207 if (dk->key != NULL) 1208 dst_key_free(&dk->key); 1209 isc_mem_put(mctx, dk, sizeof(dns_dnsseckey_t)); 1210 *dkp = NULL; 1211} 1212 1213static void 1214get_hints(dns_dnsseckey_t *key, isc_stdtime_t now) { 1215 isc_result_t result; 1216 isc_stdtime_t publish, active, revoke, inactive, delete; 1217 isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE; 1218 isc_boolean_t revset = ISC_FALSE, inactset = ISC_FALSE; 1219 isc_boolean_t delset = ISC_FALSE; 1220 1221 REQUIRE(key != NULL && key->key != NULL); 1222 1223 result = dst_key_gettime(key->key, DST_TIME_PUBLISH, &publish); 1224 if (result == ISC_R_SUCCESS) 1225 pubset = ISC_TRUE; 1226 1227 result = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active); 1228 if (result == ISC_R_SUCCESS) 1229 actset = ISC_TRUE; 1230 1231 result = dst_key_gettime(key->key, DST_TIME_REVOKE, &revoke); 1232 if (result == ISC_R_SUCCESS) 1233 revset = ISC_TRUE; 1234 1235 result = dst_key_gettime(key->key, DST_TIME_INACTIVE, &inactive); 1236 if (result == ISC_R_SUCCESS) 1237 inactset = ISC_TRUE; 1238 1239 result = dst_key_gettime(key->key, DST_TIME_DELETE, &delete); 1240 if (result == ISC_R_SUCCESS) 1241 delset = ISC_TRUE; 1242 1243 /* Metadata says publish (but possibly not activate) */ 1244 if (pubset && publish <= now) 1245 key->hint_publish = ISC_TRUE; 1246 1247 /* Metadata says activate (so we must also publish) */ 1248 if (actset && active <= now) { 1249 key->hint_sign = ISC_TRUE; 1250 key->hint_publish = ISC_TRUE; 1251 } 1252 1253 /* 1254 * Activation date is set (maybe in the future), but 1255 * publication date isn't. Most likely the user wants to 1256 * publish now and activate later. 1257 */ 1258 if (actset && !pubset) 1259 key->hint_publish = ISC_TRUE; 1260 1261 /* 1262 * If activation date is in the future, make note of how far off 1263 */ 1264 if (key->hint_publish && actset && active > now) { 1265 key->prepublish = active - now; 1266 } 1267 1268 /* 1269 * Key has been marked inactive: we can continue publishing, 1270 * but don't sign. 1271 */ 1272 if (key->hint_publish && inactset && inactive <= now) { 1273 key->hint_sign = ISC_FALSE; 1274 } 1275 1276 /* 1277 * Metadata says revoke. If the key is published, 1278 * we *have to* sign with it per RFC5011--even if it was 1279 * not active before. 1280 * 1281 * If it hasn't already been done, we should also revoke it now. 1282 */ 1283 if (key->hint_publish && (revset && revoke <= now)) { 1284 isc_uint32_t flags; 1285 key->hint_sign = ISC_TRUE; 1286 flags = dst_key_flags(key->key); 1287 if ((flags & DNS_KEYFLAG_REVOKE) == 0) { 1288 flags |= DNS_KEYFLAG_REVOKE; 1289 dst_key_setflags(key->key, flags); 1290 } 1291 } 1292 1293 /* 1294 * Metadata says delete, so don't publish this key or sign with it. 1295 */ 1296 if (delset && delete <= now) { 1297 key->hint_publish = ISC_FALSE; 1298 key->hint_sign = ISC_FALSE; 1299 key->hint_remove = ISC_TRUE; 1300 } 1301} 1302 1303/*% 1304 * Get a list of DNSSEC keys from the key repository 1305 */ 1306isc_result_t 1307dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory, 1308 isc_mem_t *mctx, dns_dnsseckeylist_t *keylist) 1309{ 1310 isc_result_t result = ISC_R_SUCCESS; 1311 isc_boolean_t dir_open = ISC_FALSE; 1312 dns_dnsseckeylist_t list; 1313 isc_dir_t dir; 1314 dns_dnsseckey_t *key = NULL; 1315 dst_key_t *dstkey = NULL; 1316 char namebuf[DNS_NAME_FORMATSIZE]; 1317 isc_buffer_t b; 1318 unsigned int len, i; 1319 isc_stdtime_t now; 1320 1321 REQUIRE(keylist != NULL); 1322 ISC_LIST_INIT(list); 1323 isc_dir_init(&dir); 1324 1325 isc_buffer_init(&b, namebuf, sizeof(namebuf) - 1); 1326 RETERR(dns_name_tofilenametext(origin, ISC_FALSE, &b)); 1327 len = isc_buffer_usedlength(&b); 1328 namebuf[len] = '\0'; 1329 1330 if (directory == NULL) 1331 directory = "."; 1332 RETERR(isc_dir_open(&dir, directory)); 1333 dir_open = ISC_TRUE; 1334 1335 isc_stdtime_get(&now); 1336 1337 while (isc_dir_read(&dir) == ISC_R_SUCCESS) { 1338 if (dir.entry.name[0] != 'K' || 1339 dir.entry.length < len + 1 || 1340 dir.entry.name[len + 1] != '+' || 1341 strncasecmp(dir.entry.name + 1, namebuf, len) != 0) 1342 continue; 1343 1344 for (i = len + 1 + 1; i < dir.entry.length ; i++) 1345 if (dir.entry.name[i] < '0' || dir.entry.name[i] > '9') 1346 break; 1347 1348 if (i == len + 1 + 1 || i >= dir.entry.length || 1349 dir.entry.name[i] != '+') 1350 continue; 1351 1352 for (i++ ; i < dir.entry.length ; i++) 1353 if (dir.entry.name[i] < '0' || dir.entry.name[i] > '9') 1354 break; 1355 1356 if (strcmp(dir.entry.name + i, ".private") != 0) 1357 continue; 1358 1359 dstkey = NULL; 1360 result = dst_key_fromnamedfile(dir.entry.name, 1361 directory, 1362 DST_TYPE_PUBLIC | 1363 DST_TYPE_PRIVATE, 1364 mctx, &dstkey); 1365 1366 if (result != ISC_R_SUCCESS) { 1367 isc_log_write(dns_lctx, 1368 DNS_LOGCATEGORY_GENERAL, 1369 DNS_LOGMODULE_DNSSEC, 1370 ISC_LOG_WARNING, 1371 "dns_dnssec_findmatchingkeys: " 1372 "error reading key file %s: %s", 1373 dir.entry.name, 1374 isc_result_totext(result)); 1375 continue; 1376 } 1377 1378 RETERR(dns_dnsseckey_create(mctx, &dstkey, &key)); 1379 key->source = dns_keysource_repository; 1380 get_hints(key, now); 1381 1382 if (key->legacy) { 1383 dns_dnsseckey_destroy(mctx, &key); 1384 } else { 1385 ISC_LIST_APPEND(list, key, link); 1386 key = NULL; 1387 } 1388 } 1389 1390 if (!ISC_LIST_EMPTY(list)) { 1391 result = ISC_R_SUCCESS; 1392 ISC_LIST_APPENDLIST(*keylist, list, link); 1393 } else 1394 result = ISC_R_NOTFOUND; 1395 1396 failure: 1397 if (dir_open) 1398 isc_dir_close(&dir); 1399 INSIST(key == NULL); 1400 while ((key = ISC_LIST_HEAD(list)) != NULL) { 1401 ISC_LIST_UNLINK(list, key, link); 1402 INSIST(key->key != NULL); 1403 dst_key_free(&key->key); 1404 dns_dnsseckey_destroy(mctx, &key); 1405 } 1406 if (dstkey != NULL) 1407 dst_key_free(&dstkey); 1408 return (result); 1409} 1410 1411/*% 1412 * Add 'newkey' to 'keylist' if it's not already there. 1413 * 1414 * If 'savekeys' is ISC_TRUE, then we need to preserve all 1415 * the keys in the keyset, regardless of whether they have 1416 * metadata indicating they should be deactivated or removed. 1417 */ 1418static isc_result_t 1419addkey(dns_dnsseckeylist_t *keylist, dst_key_t **newkey, 1420 isc_boolean_t savekeys, isc_mem_t *mctx) 1421{ 1422 dns_dnsseckey_t *key; 1423 isc_result_t result; 1424 1425 /* Skip duplicates */ 1426 for (key = ISC_LIST_HEAD(*keylist); 1427 key != NULL; 1428 key = ISC_LIST_NEXT(key, link)) { 1429 if (dst_key_id(key->key) == dst_key_id(*newkey) && 1430 dst_key_alg(key->key) == dst_key_alg(*newkey) && 1431 dns_name_equal(dst_key_name(key->key), 1432 dst_key_name(*newkey))) 1433 break; 1434 } 1435 1436 if (key != NULL) { 1437 /* 1438 * Found a match. If the old key was only public and the 1439 * new key is private, replace the old one; otherwise 1440 * leave it. But either way, mark the key as having 1441 * been found in the zone. 1442 */ 1443 if (dst_key_isprivate(key->key)) { 1444 dst_key_free(newkey); 1445 } else if (dst_key_isprivate(*newkey)) { 1446 dst_key_free(&key->key); 1447 key->key = *newkey; 1448 } 1449 1450 key->source = dns_keysource_zoneapex; 1451 return (ISC_R_SUCCESS); 1452 } 1453 1454 result = dns_dnsseckey_create(mctx, newkey, &key); 1455 if (result != ISC_R_SUCCESS) 1456 return (result); 1457 if (key->legacy || savekeys) { 1458 key->force_publish = ISC_TRUE; 1459 key->force_sign = dst_key_isprivate(key->key); 1460 } 1461 key->source = dns_keysource_zoneapex; 1462 ISC_LIST_APPEND(*keylist, key, link); 1463 *newkey = NULL; 1464 return (ISC_R_SUCCESS); 1465} 1466 1467 1468/*% 1469 * Mark all keys which signed the DNSKEY/SOA RRsets as "active", 1470 * for future reference. 1471 */ 1472static isc_result_t 1473mark_active_keys(dns_dnsseckeylist_t *keylist, dns_rdataset_t *rrsigs) { 1474 isc_result_t result = ISC_R_SUCCESS; 1475 dns_rdata_t rdata = DNS_RDATA_INIT; 1476 dns_rdataset_t sigs; 1477 dns_dnsseckey_t *key; 1478 1479 REQUIRE(rrsigs != NULL && dns_rdataset_isassociated(rrsigs)); 1480 1481 dns_rdataset_init(&sigs); 1482 dns_rdataset_clone(rrsigs, &sigs); 1483 for (key = ISC_LIST_HEAD(*keylist); 1484 key != NULL; 1485 key = ISC_LIST_NEXT(key, link)) { 1486 isc_uint16_t keyid, sigid; 1487 dns_secalg_t keyalg, sigalg; 1488 keyid = dst_key_id(key->key); 1489 keyalg = dst_key_alg(key->key); 1490 1491 for (result = dns_rdataset_first(&sigs); 1492 result == ISC_R_SUCCESS; 1493 result = dns_rdataset_next(&sigs)) { 1494 dns_rdata_rrsig_t sig; 1495 1496 dns_rdata_reset(&rdata); 1497 dns_rdataset_current(&sigs, &rdata); 1498 result = dns_rdata_tostruct(&rdata, &sig, NULL); 1499 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1500 sigalg = sig.algorithm; 1501 sigid = sig.keyid; 1502 if (keyid == sigid && keyalg == sigalg) { 1503 key->is_active = ISC_TRUE; 1504 break; 1505 } 1506 } 1507 } 1508 1509 if (result == ISC_R_NOMORE) 1510 result = ISC_R_SUCCESS; 1511 1512 if (dns_rdataset_isassociated(&sigs)) 1513 dns_rdataset_disassociate(&sigs); 1514 return (result); 1515} 1516 1517/*% 1518 * Add the contents of a DNSKEY rdataset 'keyset' to 'keylist'. 1519 */ 1520isc_result_t 1521dns_dnssec_keylistfromrdataset(dns_name_t *origin, 1522 const char *directory, isc_mem_t *mctx, 1523 dns_rdataset_t *keyset, dns_rdataset_t *keysigs, 1524 dns_rdataset_t *soasigs, isc_boolean_t savekeys, 1525 isc_boolean_t public, 1526 dns_dnsseckeylist_t *keylist) 1527{ 1528 dns_rdataset_t keys; 1529 dns_rdata_t rdata = DNS_RDATA_INIT; 1530 dst_key_t *pubkey = NULL, *privkey = NULL; 1531 isc_result_t result; 1532 1533 REQUIRE(keyset != NULL && dns_rdataset_isassociated(keyset)); 1534 1535 dns_rdataset_init(&keys); 1536 1537 dns_rdataset_clone(keyset, &keys); 1538 for (result = dns_rdataset_first(&keys); 1539 result == ISC_R_SUCCESS; 1540 result = dns_rdataset_next(&keys)) { 1541 dns_rdata_reset(&rdata); 1542 dns_rdataset_current(&keys, &rdata); 1543 RETERR(dns_dnssec_keyfromrdata(origin, &rdata, mctx, &pubkey)); 1544 dst_key_setttl(pubkey, keys.ttl); 1545 1546 if (!is_zone_key(pubkey) || 1547 (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0) 1548 goto skip; 1549 1550 /* Corrupted .key file? */ 1551 if (!dns_name_equal(origin, dst_key_name(pubkey))) 1552 goto skip; 1553 1554 if (public) { 1555 RETERR(addkey(keylist, &pubkey, savekeys, mctx)); 1556 goto skip; 1557 } 1558 1559 result = dst_key_fromfile(dst_key_name(pubkey), 1560 dst_key_id(pubkey), 1561 dst_key_alg(pubkey), 1562 DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, 1563 directory, mctx, &privkey); 1564 1565 /* 1566 * If the key was revoked and the private file 1567 * doesn't exist, maybe it was revoked internally 1568 * by named. Try loading the unrevoked version. 1569 */ 1570 if (result == ISC_R_FILENOTFOUND) { 1571 isc_uint32_t flags; 1572 flags = dst_key_flags(pubkey); 1573 if ((flags & DNS_KEYFLAG_REVOKE) != 0) { 1574 dst_key_setflags(pubkey, 1575 flags & ~DNS_KEYFLAG_REVOKE); 1576 result = dst_key_fromfile(dst_key_name(pubkey), 1577 dst_key_id(pubkey), 1578 dst_key_alg(pubkey), 1579 DST_TYPE_PUBLIC| 1580 DST_TYPE_PRIVATE, 1581 directory, 1582 mctx, &privkey); 1583 if (result == ISC_R_SUCCESS && 1584 dst_key_pubcompare(pubkey, privkey, 1585 ISC_FALSE)) { 1586 dst_key_setflags(privkey, flags); 1587 } 1588 dst_key_setflags(pubkey, flags); 1589 } 1590 } 1591 1592 if (result != ISC_R_SUCCESS) { 1593 char keybuf[DNS_NAME_FORMATSIZE]; 1594 char algbuf[DNS_SECALG_FORMATSIZE]; 1595 dns_name_format(dst_key_name(pubkey), keybuf, 1596 sizeof(keybuf)); 1597 dns_secalg_format(dst_key_alg(pubkey), algbuf, 1598 sizeof(algbuf)); 1599 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 1600 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, 1601 "dns_dnssec_keylistfromrdataset: error " 1602 "reading private key file %s/%s/%d: %s", 1603 keybuf, algbuf, dst_key_id(pubkey), 1604 isc_result_totext(result)); 1605 } 1606 1607 if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) { 1608 RETERR(addkey(keylist, &pubkey, savekeys, mctx)); 1609 goto skip; 1610 } 1611 RETERR(result); 1612 1613 /* This should never happen. */ 1614 if ((dst_key_flags(privkey) & DNS_KEYTYPE_NOAUTH) != 0) 1615 goto skip; 1616 1617 /* 1618 * Whatever the key's default TTL may have 1619 * been, the rdataset TTL takes priority. 1620 */ 1621 dst_key_setttl(privkey, dst_key_getttl(pubkey)); 1622 1623 RETERR(addkey(keylist, &privkey, savekeys, mctx)); 1624 skip: 1625 if (pubkey != NULL) 1626 dst_key_free(&pubkey); 1627 if (privkey != NULL) 1628 dst_key_free(&privkey); 1629 } 1630 1631 if (result != ISC_R_NOMORE) 1632 RETERR(result); 1633 1634 if (keysigs != NULL && dns_rdataset_isassociated(keysigs)) 1635 RETERR(mark_active_keys(keylist, keysigs)); 1636 1637 if (soasigs != NULL && dns_rdataset_isassociated(soasigs)) 1638 RETERR(mark_active_keys(keylist, soasigs)); 1639 1640 result = ISC_R_SUCCESS; 1641 1642 failure: 1643 if (dns_rdataset_isassociated(&keys)) 1644 dns_rdataset_disassociate(&keys); 1645 if (pubkey != NULL) 1646 dst_key_free(&pubkey); 1647 if (privkey != NULL) 1648 dst_key_free(&privkey); 1649 return (result); 1650} 1651 1652static isc_result_t 1653make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize, 1654 dns_rdata_t *target) 1655{ 1656 isc_result_t result; 1657 isc_buffer_t b; 1658 isc_region_t r; 1659 1660 isc_buffer_init(&b, buf, bufsize); 1661 result = dst_key_todns(key, &b); 1662 if (result != ISC_R_SUCCESS) 1663 return (result); 1664 1665 dns_rdata_reset(target); 1666 isc_buffer_usedregion(&b, &r); 1667 dns_rdata_fromregion(target, dst_key_class(key), 1668 dns_rdatatype_dnskey, &r); 1669 return (ISC_R_SUCCESS); 1670} 1671 1672static isc_result_t 1673publish_key(dns_diff_t *diff, dns_dnsseckey_t *key, dns_name_t *origin, 1674 dns_ttl_t ttl, isc_mem_t *mctx, isc_boolean_t allzsk, 1675 void (*report)(const char *, ...)) 1676{ 1677 isc_result_t result; 1678 dns_difftuple_t *tuple = NULL; 1679 unsigned char buf[DST_KEY_MAXSIZE]; 1680 dns_rdata_t dnskey = DNS_RDATA_INIT; 1681 char alg[80]; 1682 1683 dns_rdata_reset(&dnskey); 1684 RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey)); 1685 1686 dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg)); 1687 report("Fetching %s %d/%s from key %s.", 1688 key->ksk ? (allzsk ? "KSK/ZSK" : "KSK") : "ZSK", 1689 dst_key_id(key->key), alg, 1690 key->source == dns_keysource_user ? "file" : "repository"); 1691 1692 if (key->prepublish && ttl > key->prepublish) { 1693 char keystr[DST_KEY_FORMATSIZE]; 1694 isc_stdtime_t now; 1695 1696 dst_key_format(key->key, keystr, sizeof(keystr)); 1697 report("Key %s: Delaying activation to match the DNSKEY TTL.\n", 1698 keystr, ttl); 1699 1700 isc_stdtime_get(&now); 1701 dst_key_settime(key->key, DST_TIME_ACTIVATE, now + ttl); 1702 } 1703 1704 /* publish key */ 1705 RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_ADD, origin, ttl, 1706 &dnskey, &tuple)); 1707 dns_diff_appendminimal(diff, &tuple); 1708 result = ISC_R_SUCCESS; 1709 1710 failure: 1711 return (result); 1712} 1713 1714static isc_result_t 1715remove_key(dns_diff_t *diff, dns_dnsseckey_t *key, dns_name_t *origin, 1716 dns_ttl_t ttl, isc_mem_t *mctx, const char *reason, 1717 void (*report)(const char *, ...)) 1718{ 1719 isc_result_t result; 1720 dns_difftuple_t *tuple = NULL; 1721 unsigned char buf[DST_KEY_MAXSIZE]; 1722 dns_rdata_t dnskey = DNS_RDATA_INIT; 1723 char alg[80]; 1724 1725 dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg)); 1726 report("Removing %s key %d/%s from DNSKEY RRset.", 1727 reason, dst_key_id(key->key), alg); 1728 1729 RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey)); 1730 RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_DEL, origin, ttl, &dnskey, 1731 &tuple)); 1732 dns_diff_appendminimal(diff, &tuple); 1733 result = ISC_R_SUCCESS; 1734 1735 failure: 1736 return (result); 1737} 1738 1739/* 1740 * Update 'keys' with information from 'newkeys'. 1741 * 1742 * If 'removed' is not NULL, any keys that are being removed from 1743 * the zone will be added to the list for post-removal processing. 1744 */ 1745isc_result_t 1746dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys, 1747 dns_dnsseckeylist_t *removed, dns_name_t *origin, 1748 dns_ttl_t hint_ttl, dns_diff_t *diff, 1749 isc_boolean_t allzsk, isc_mem_t *mctx, 1750 void (*report)(const char *, ...)) 1751{ 1752 isc_result_t result; 1753 dns_dnsseckey_t *key, *key1, *key2, *next; 1754 isc_boolean_t found_ttl = ISC_FALSE; 1755 dns_ttl_t ttl = hint_ttl; 1756 1757 /* 1758 * First, look through the existing key list to find keys 1759 * supplied from the command line which are not in the zone. 1760 * Update the zone to include them. 1761 * 1762 * Also, if there are keys published in the zone already, 1763 * use their TTL for all subsequent published keys. 1764 */ 1765 for (key = ISC_LIST_HEAD(*keys); 1766 key != NULL; 1767 key = ISC_LIST_NEXT(key, link)) { 1768 if (key->source == dns_keysource_user && 1769 (key->hint_publish || key->force_publish)) { 1770 RETERR(publish_key(diff, key, origin, ttl, 1771 mctx, allzsk, report)); 1772 } 1773 if (key->source == dns_keysource_zoneapex) { 1774 ttl = dst_key_getttl(key->key); 1775 found_ttl = ISC_TRUE; 1776 } 1777 } 1778 1779 /* 1780 * If there were no existing keys, use the smallest nonzero 1781 * TTL of the keys found in the repository. 1782 */ 1783 if (!found_ttl && !ISC_LIST_EMPTY(*newkeys)) { 1784 dns_ttl_t shortest = 0; 1785 1786 for (key = ISC_LIST_HEAD(*newkeys); 1787 key != NULL; 1788 key = ISC_LIST_NEXT(key, link)) { 1789 dns_ttl_t thisttl = dst_key_getttl(key->key); 1790 if (thisttl != 0 && 1791 (shortest == 0 || thisttl < shortest)) 1792 shortest = thisttl; 1793 } 1794 1795 if (shortest != 0) 1796 ttl = shortest; 1797 } 1798 1799 /* 1800 * Second, scan the list of newly found keys looking for matches 1801 * with known keys, and update accordingly. 1802 */ 1803 for (key1 = ISC_LIST_HEAD(*newkeys); key1 != NULL; key1 = next) { 1804 isc_boolean_t key_revoked = ISC_FALSE; 1805 1806 next = ISC_LIST_NEXT(key1, link); 1807 1808 for (key2 = ISC_LIST_HEAD(*keys); 1809 key2 != NULL; 1810 key2 = ISC_LIST_NEXT(key2, link)) { 1811 int f1 = dst_key_flags(key1->key); 1812 int f2 = dst_key_flags(key2->key); 1813 int nr1 = f1 & ~DNS_KEYFLAG_REVOKE; 1814 int nr2 = f2 & ~DNS_KEYFLAG_REVOKE; 1815 if (nr1 == nr2 && 1816 dst_key_alg(key1->key) == dst_key_alg(key2->key) && 1817 dst_key_pubcompare(key1->key, key2->key, 1818 ISC_TRUE)) { 1819 int r1, r2; 1820 r1 = dst_key_flags(key1->key) & 1821 DNS_KEYFLAG_REVOKE; 1822 r2 = dst_key_flags(key2->key) & 1823 DNS_KEYFLAG_REVOKE; 1824 key_revoked = ISC_TF(r1 != r2); 1825 break; 1826 } 1827 } 1828 1829 /* No match found in keys; add the new key. */ 1830 if (key2 == NULL) { 1831 ISC_LIST_UNLINK(*newkeys, key1, link); 1832 ISC_LIST_APPEND(*keys, key1, link); 1833 1834 if (key1->source != dns_keysource_zoneapex && 1835 (key1->hint_publish || key1->force_publish)) { 1836 RETERR(publish_key(diff, key1, origin, ttl, 1837 mctx, allzsk, report)); 1838 if (key1->hint_sign || key1->force_sign) 1839 key1->first_sign = ISC_TRUE; 1840 } 1841 1842 continue; 1843 } 1844 1845 /* Match found: remove or update it as needed */ 1846 if (key1->hint_remove) { 1847 RETERR(remove_key(diff, key2, origin, ttl, mctx, 1848 "expired", report)); 1849 ISC_LIST_UNLINK(*keys, key2, link); 1850 if (removed != NULL) 1851 ISC_LIST_APPEND(*removed, key2, link); 1852 else 1853 dns_dnsseckey_destroy(mctx, &key2); 1854 } else if (key_revoked && 1855 (dst_key_flags(key1->key) & DNS_KEYFLAG_REVOKE) != 0) { 1856 1857 /* 1858 * A previously valid key has been revoked. 1859 * We need to remove the old version and pull 1860 * in the new one. 1861 */ 1862 RETERR(remove_key(diff, key2, origin, ttl, mctx, 1863 "revoked", report)); 1864 ISC_LIST_UNLINK(*keys, key2, link); 1865 if (removed != NULL) 1866 ISC_LIST_APPEND(*removed, key2, link); 1867 else 1868 dns_dnsseckey_destroy(mctx, &key2); 1869 1870 RETERR(publish_key(diff, key1, origin, ttl, 1871 mctx, allzsk, report)); 1872 ISC_LIST_UNLINK(*newkeys, key1, link); 1873 ISC_LIST_APPEND(*keys, key1, link); 1874 1875 /* 1876 * XXX: The revoke flag is only defined for trust 1877 * anchors. Setting the flag on a non-KSK is legal, 1878 * but not defined in any RFC. It seems reasonable 1879 * to treat it the same as a KSK: keep it in the 1880 * zone, sign the DNSKEY set with it, but not 1881 * sign other records with it. 1882 */ 1883 key1->ksk = ISC_TRUE; 1884 continue; 1885 } else { 1886 if (!key2->is_active && 1887 (key1->hint_sign || key1->force_sign)) 1888 key2->first_sign = ISC_TRUE; 1889 key2->hint_sign = key1->hint_sign; 1890 key2->hint_publish = key1->hint_publish; 1891 } 1892 } 1893 1894 /* Free any leftover keys in newkeys */ 1895 while (!ISC_LIST_EMPTY(*newkeys)) { 1896 key1 = ISC_LIST_HEAD(*newkeys); 1897 ISC_LIST_UNLINK(*newkeys, key1, link); 1898 dns_dnsseckey_destroy(mctx, &key1); 1899 } 1900 1901 result = ISC_R_SUCCESS; 1902 1903 failure: 1904 return (result); 1905} 1906