1 /* $NetBSD: dnssec.c,v 1.12 2022/09/23 12:15:29 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 /*! \file */ 17 18 #include <ctype.h> 19 #include <inttypes.h> 20 #include <stdbool.h> 21 #include <stdlib.h> 22 23 #include <isc/buffer.h> 24 #include <isc/dir.h> 25 #include <isc/mem.h> 26 #include <isc/print.h> 27 #include <isc/serial.h> 28 #include <isc/string.h> 29 #include <isc/util.h> 30 31 #include <pk11/site.h> 32 33 #include <dns/db.h> 34 #include <dns/diff.h> 35 #include <dns/dnssec.h> 36 #include <dns/fixedname.h> 37 #include <dns/kasp.h> 38 #include <dns/keyvalues.h> 39 #include <dns/log.h> 40 #include <dns/message.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/stats.h> 47 #include <dns/tsig.h> /* for DNS_TSIG_FUDGE */ 48 49 #include <dst/result.h> 50 51 LIBDNS_EXTERNAL_DATA isc_stats_t *dns_dnssec_stats; 52 53 #define is_response(msg) ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) 54 55 #define RETERR(x) \ 56 do { \ 57 result = (x); \ 58 if (result != ISC_R_SUCCESS) \ 59 goto failure; \ 60 } while (0) 61 62 #define TYPE_SIGN 0 63 #define TYPE_VERIFY 1 64 65 static isc_result_t 66 digest_callback(void *arg, isc_region_t *data); 67 68 static int 69 rdata_compare_wrapper(const void *rdata1, const void *rdata2); 70 71 static isc_result_t 72 rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx, 73 dns_rdata_t **rdata, int *nrdata); 74 75 static isc_result_t 76 digest_callback(void *arg, isc_region_t *data) { 77 dst_context_t *ctx = arg; 78 79 return (dst_context_adddata(ctx, data)); 80 } 81 82 static void 83 inc_stat(isc_statscounter_t counter) { 84 if (dns_dnssec_stats != NULL) { 85 isc_stats_increment(dns_dnssec_stats, counter); 86 } 87 } 88 89 /* 90 * Make qsort happy. 91 */ 92 static int 93 rdata_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 */ 101 static isc_result_t 102 rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx, 103 dns_rdata_t **rdata, int *nrdata) { 104 isc_result_t ret; 105 int i = 0, n; 106 dns_rdata_t *data; 107 dns_rdataset_t rdataset; 108 109 n = dns_rdataset_count(set); 110 111 data = isc_mem_get(mctx, n * sizeof(dns_rdata_t)); 112 113 dns_rdataset_init(&rdataset); 114 dns_rdataset_clone(set, &rdataset); 115 ret = dns_rdataset_first(&rdataset); 116 if (ret != ISC_R_SUCCESS) { 117 dns_rdataset_disassociate(&rdataset); 118 isc_mem_put(mctx, data, n * sizeof(dns_rdata_t)); 119 return (ret); 120 } 121 122 /* 123 * Put them in the array. 124 */ 125 do { 126 dns_rdata_init(&data[i]); 127 dns_rdataset_current(&rdataset, &data[i++]); 128 } while (dns_rdataset_next(&rdataset) == ISC_R_SUCCESS); 129 130 /* 131 * Sort the array. 132 */ 133 qsort(data, n, sizeof(dns_rdata_t), rdata_compare_wrapper); 134 *rdata = data; 135 *nrdata = n; 136 dns_rdataset_disassociate(&rdataset); 137 return (ISC_R_SUCCESS); 138 } 139 140 isc_result_t 141 dns_dnssec_keyfromrdata(const dns_name_t *name, const dns_rdata_t *rdata, 142 isc_mem_t *mctx, dst_key_t **key) { 143 isc_buffer_t b; 144 isc_region_t r; 145 146 INSIST(name != NULL); 147 INSIST(rdata != NULL); 148 INSIST(mctx != NULL); 149 INSIST(key != NULL); 150 INSIST(*key == NULL); 151 REQUIRE(rdata->type == dns_rdatatype_key || 152 rdata->type == dns_rdatatype_dnskey); 153 154 dns_rdata_toregion(rdata, &r); 155 isc_buffer_init(&b, r.base, r.length); 156 isc_buffer_add(&b, r.length); 157 return (dst_key_fromdns(name, rdata->rdclass, &b, mctx, key)); 158 } 159 160 static isc_result_t 161 digest_sig(dst_context_t *ctx, bool downcase, dns_rdata_t *sigrdata, 162 dns_rdata_rrsig_t *rrsig) { 163 isc_region_t r; 164 isc_result_t ret; 165 dns_fixedname_t fname; 166 167 dns_rdata_toregion(sigrdata, &r); 168 INSIST(r.length >= 19); 169 170 r.length = 18; 171 ret = dst_context_adddata(ctx, &r); 172 if (ret != ISC_R_SUCCESS) { 173 return (ret); 174 } 175 if (downcase) { 176 dns_fixedname_init(&fname); 177 178 RUNTIME_CHECK(dns_name_downcase(&rrsig->signer, 179 dns_fixedname_name(&fname), 180 NULL) == ISC_R_SUCCESS); 181 dns_name_toregion(dns_fixedname_name(&fname), &r); 182 } else { 183 dns_name_toregion(&rrsig->signer, &r); 184 } 185 186 return (dst_context_adddata(ctx, &r)); 187 } 188 189 isc_result_t 190 dns_dnssec_sign(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, 191 isc_stdtime_t *inception, isc_stdtime_t *expire, 192 isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata) { 193 dns_rdata_rrsig_t sig; 194 dns_rdata_t tmpsigrdata; 195 dns_rdata_t *rdatas; 196 int nrdatas, i; 197 isc_buffer_t sigbuf, envbuf; 198 isc_region_t r; 199 dst_context_t *ctx = NULL; 200 isc_result_t ret; 201 isc_buffer_t *databuf = NULL; 202 char data[256 + 8]; 203 uint32_t flags; 204 unsigned int sigsize; 205 dns_fixedname_t fnewname; 206 dns_fixedname_t fsigner; 207 208 REQUIRE(name != NULL); 209 REQUIRE(dns_name_countlabels(name) <= 255); 210 REQUIRE(set != NULL); 211 REQUIRE(key != NULL); 212 REQUIRE(inception != NULL); 213 REQUIRE(expire != NULL); 214 REQUIRE(mctx != NULL); 215 REQUIRE(sigrdata != NULL); 216 217 if (*inception >= *expire) { 218 return (DNS_R_INVALIDTIME); 219 } 220 221 /* 222 * Is the key allowed to sign data? 223 */ 224 flags = dst_key_flags(key); 225 if ((flags & DNS_KEYTYPE_NOAUTH) != 0) { 226 return (DNS_R_KEYUNAUTHORIZED); 227 } 228 if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) { 229 return (DNS_R_KEYUNAUTHORIZED); 230 } 231 232 sig.mctx = mctx; 233 sig.common.rdclass = set->rdclass; 234 sig.common.rdtype = dns_rdatatype_rrsig; 235 ISC_LINK_INIT(&sig.common, link); 236 237 /* 238 * Downcase signer. 239 */ 240 dns_name_init(&sig.signer, NULL); 241 dns_fixedname_init(&fsigner); 242 RUNTIME_CHECK(dns_name_downcase(dst_key_name(key), 243 dns_fixedname_name(&fsigner), 244 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 } 253 sig.originalttl = set->ttl; 254 sig.timesigned = *inception; 255 sig.timeexpire = *expire; 256 sig.keyid = dst_key_id(key); 257 ret = dst_key_sigsize(key, &sigsize); 258 if (ret != ISC_R_SUCCESS) { 259 return (ret); 260 } 261 sig.siglen = sigsize; 262 /* 263 * The actual contents of sig.signature are not important yet, since 264 * they're not used in digest_sig(). 265 */ 266 sig.signature = isc_mem_get(mctx, sig.siglen); 267 268 isc_buffer_allocate(mctx, &databuf, sigsize + 256 + 18); 269 270 dns_rdata_init(&tmpsigrdata); 271 ret = dns_rdata_fromstruct(&tmpsigrdata, sig.common.rdclass, 272 sig.common.rdtype, &sig, databuf); 273 if (ret != ISC_R_SUCCESS) { 274 goto cleanup_databuf; 275 } 276 277 ret = dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, true, 0, 278 &ctx); 279 if (ret != ISC_R_SUCCESS) { 280 goto cleanup_databuf; 281 } 282 283 /* 284 * Digest the SIG rdata. 285 */ 286 ret = digest_sig(ctx, false, &tmpsigrdata, &sig); 287 if (ret != ISC_R_SUCCESS) { 288 goto cleanup_context; 289 } 290 291 dns_fixedname_init(&fnewname); 292 RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname), 293 NULL) == ISC_R_SUCCESS); 294 dns_name_toregion(dns_fixedname_name(&fnewname), &r); 295 296 /* 297 * Create an envelope for each rdata: <name|type|class|ttl>. 298 */ 299 isc_buffer_init(&envbuf, data, sizeof(data)); 300 memmove(data, r.base, r.length); 301 isc_buffer_add(&envbuf, r.length); 302 isc_buffer_putuint16(&envbuf, set->type); 303 isc_buffer_putuint16(&envbuf, set->rdclass); 304 isc_buffer_putuint32(&envbuf, set->ttl); 305 306 ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas); 307 if (ret != ISC_R_SUCCESS) { 308 goto cleanup_context; 309 } 310 isc_buffer_usedregion(&envbuf, &r); 311 312 for (i = 0; i < nrdatas; i++) { 313 uint16_t len; 314 isc_buffer_t lenbuf; 315 isc_region_t lenr; 316 317 /* 318 * Skip duplicates. 319 */ 320 if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i - 1]) == 0) 321 { 322 continue; 323 } 324 325 /* 326 * Digest the envelope. 327 */ 328 ret = dst_context_adddata(ctx, &r); 329 if (ret != ISC_R_SUCCESS) { 330 goto cleanup_array; 331 } 332 333 /* 334 * Digest the length of the rdata. 335 */ 336 isc_buffer_init(&lenbuf, &len, sizeof(len)); 337 INSIST(rdatas[i].length < 65536); 338 isc_buffer_putuint16(&lenbuf, (uint16_t)rdatas[i].length); 339 isc_buffer_usedregion(&lenbuf, &lenr); 340 ret = dst_context_adddata(ctx, &lenr); 341 if (ret != ISC_R_SUCCESS) { 342 goto cleanup_array; 343 } 344 345 /* 346 * Digest the rdata. 347 */ 348 ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx); 349 if (ret != ISC_R_SUCCESS) { 350 goto cleanup_array; 351 } 352 } 353 354 isc_buffer_init(&sigbuf, sig.signature, sig.siglen); 355 ret = dst_context_sign(ctx, &sigbuf); 356 if (ret != ISC_R_SUCCESS) { 357 goto cleanup_array; 358 } 359 isc_buffer_usedregion(&sigbuf, &r); 360 if (r.length != sig.siglen) { 361 ret = ISC_R_NOSPACE; 362 goto cleanup_array; 363 } 364 365 ret = dns_rdata_fromstruct(sigrdata, sig.common.rdclass, 366 sig.common.rdtype, &sig, buffer); 367 368 cleanup_array: 369 isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t)); 370 cleanup_context: 371 dst_context_destroy(&ctx); 372 cleanup_databuf: 373 isc_buffer_free(&databuf); 374 isc_mem_put(mctx, sig.signature, sig.siglen); 375 376 return (ret); 377 } 378 379 isc_result_t 380 dns_dnssec_verify(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, 381 bool ignoretime, unsigned int maxbits, isc_mem_t *mctx, 382 dns_rdata_t *sigrdata, dns_name_t *wild) { 383 dns_rdata_rrsig_t sig; 384 dns_fixedname_t fnewname; 385 isc_region_t r; 386 isc_buffer_t envbuf; 387 dns_rdata_t *rdatas; 388 int nrdatas, i; 389 isc_stdtime_t now; 390 isc_result_t ret; 391 unsigned char data[300]; 392 dst_context_t *ctx = NULL; 393 int labels = 0; 394 uint32_t flags; 395 bool downcase = false; 396 397 REQUIRE(name != NULL); 398 REQUIRE(set != NULL); 399 REQUIRE(key != NULL); 400 REQUIRE(mctx != NULL); 401 REQUIRE(sigrdata != NULL && sigrdata->type == dns_rdatatype_rrsig); 402 403 ret = dns_rdata_tostruct(sigrdata, &sig, NULL); 404 if (ret != ISC_R_SUCCESS) { 405 return (ret); 406 } 407 408 if (set->type != sig.covered) { 409 return (DNS_R_SIGINVALID); 410 } 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((uint32_t)now, sig.timesigned)) { 424 inc_stat(dns_dnssecstats_fail); 425 return (DNS_R_SIGFUTURE); 426 } else if (isc_serial_lt(sig.timeexpire, (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) != 0) { 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_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, false, 474 maxbits, &ctx); 475 if (ret != ISC_R_SUCCESS) { 476 goto cleanup_struct; 477 } 478 479 /* 480 * Digest the SIG rdata (not including the signature). 481 */ 482 ret = digest_sig(ctx, downcase, sigrdata, &sig); 483 if (ret != ISC_R_SUCCESS) { 484 goto cleanup_context; 485 } 486 487 /* 488 * If the name is an expanded wildcard, use the wildcard name. 489 */ 490 dns_fixedname_init(&fnewname); 491 labels = dns_name_countlabels(name) - 1; 492 RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname), 493 NULL) == ISC_R_SUCCESS); 494 if (labels - sig.labels > 0) { 495 dns_name_split(dns_fixedname_name(&fnewname), sig.labels + 1, 496 NULL, dns_fixedname_name(&fnewname)); 497 } 498 499 dns_name_toregion(dns_fixedname_name(&fnewname), &r); 500 501 /* 502 * Create an envelope for each rdata: <name|type|class|ttl>. 503 */ 504 isc_buffer_init(&envbuf, data, sizeof(data)); 505 if (labels - sig.labels > 0) { 506 isc_buffer_putuint8(&envbuf, 1); 507 isc_buffer_putuint8(&envbuf, '*'); 508 memmove(data + 2, r.base, r.length); 509 } else { 510 memmove(data, r.base, r.length); 511 } 512 isc_buffer_add(&envbuf, r.length); 513 isc_buffer_putuint16(&envbuf, set->type); 514 isc_buffer_putuint16(&envbuf, set->rdclass); 515 isc_buffer_putuint32(&envbuf, sig.originalttl); 516 517 ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas); 518 if (ret != ISC_R_SUCCESS) { 519 goto cleanup_context; 520 } 521 522 isc_buffer_usedregion(&envbuf, &r); 523 524 for (i = 0; i < nrdatas; i++) { 525 uint16_t len; 526 isc_buffer_t lenbuf; 527 isc_region_t lenr; 528 529 /* 530 * Skip duplicates. 531 */ 532 if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i - 1]) == 0) 533 { 534 continue; 535 } 536 537 /* 538 * Digest the envelope. 539 */ 540 ret = dst_context_adddata(ctx, &r); 541 if (ret != ISC_R_SUCCESS) { 542 goto cleanup_array; 543 } 544 545 /* 546 * Digest the rdata length. 547 */ 548 isc_buffer_init(&lenbuf, &len, sizeof(len)); 549 INSIST(rdatas[i].length < 65536); 550 isc_buffer_putuint16(&lenbuf, (uint16_t)rdatas[i].length); 551 isc_buffer_usedregion(&lenbuf, &lenr); 552 553 /* 554 * Digest the rdata. 555 */ 556 ret = dst_context_adddata(ctx, &lenr); 557 if (ret != ISC_R_SUCCESS) { 558 goto cleanup_array; 559 } 560 ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx); 561 if (ret != ISC_R_SUCCESS) { 562 goto cleanup_array; 563 } 564 } 565 566 r.base = sig.signature; 567 r.length = sig.siglen; 568 ret = dst_context_verify2(ctx, maxbits, &r); 569 if (ret == ISC_R_SUCCESS && downcase) { 570 char namebuf[DNS_NAME_FORMATSIZE]; 571 dns_name_format(&sig.signer, namebuf, sizeof(namebuf)); 572 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 573 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), 574 "successfully validated after lower casing " 575 "signer '%s'", 576 namebuf); 577 inc_stat(dns_dnssecstats_downcase); 578 } else if (ret == ISC_R_SUCCESS) { 579 inc_stat(dns_dnssecstats_asis); 580 } 581 582 cleanup_array: 583 isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t)); 584 cleanup_context: 585 dst_context_destroy(&ctx); 586 if (ret == DST_R_VERIFYFAILURE && !downcase) { 587 downcase = true; 588 goto again; 589 } 590 cleanup_struct: 591 dns_rdata_freestruct(&sig); 592 593 if (ret == DST_R_VERIFYFAILURE) { 594 ret = DNS_R_SIGINVALID; 595 } 596 597 if (ret != ISC_R_SUCCESS) { 598 inc_stat(dns_dnssecstats_fail); 599 } 600 601 if (ret == ISC_R_SUCCESS && labels - sig.labels > 0) { 602 if (wild != NULL) { 603 RUNTIME_CHECK(dns_name_concatenate( 604 dns_wildcardname, 605 dns_fixedname_name(&fnewname), 606 wild, NULL) == ISC_R_SUCCESS); 607 } 608 inc_stat(dns_dnssecstats_wildcard); 609 ret = DNS_R_FROMWILDCARD; 610 } 611 return (ret); 612 } 613 614 bool 615 dns_dnssec_keyactive(dst_key_t *key, isc_stdtime_t now) { 616 isc_result_t result; 617 isc_stdtime_t publish, active, revoke, remove; 618 bool hint_publish, hint_zsign, hint_ksign, hint_revoke, hint_remove; 619 int major, minor; 620 bool ksk = false, zsk = false; 621 isc_result_t ret; 622 623 /* Is this an old-style key? */ 624 result = dst_key_getprivateformat(key, &major, &minor); 625 RUNTIME_CHECK(result == ISC_R_SUCCESS); 626 627 /* Is this a KSK? */ 628 ret = dst_key_getbool(key, DST_BOOL_KSK, &ksk); 629 if (ret != ISC_R_SUCCESS) { 630 ksk = ((dst_key_flags(key) & DNS_KEYFLAG_KSK) != 0); 631 } 632 ret = dst_key_getbool(key, DST_BOOL_ZSK, &zsk); 633 if (ret != ISC_R_SUCCESS) { 634 zsk = ((dst_key_flags(key) & DNS_KEYFLAG_KSK) == 0); 635 } 636 637 /* 638 * Smart signing started with key format 1.3; prior to that, all 639 * keys are assumed active. 640 */ 641 if (major == 1 && minor <= 2) { 642 return (true); 643 } 644 645 hint_publish = dst_key_is_published(key, now, &publish); 646 hint_zsign = dst_key_is_signing(key, DST_BOOL_ZSK, now, &active); 647 hint_ksign = dst_key_is_signing(key, DST_BOOL_KSK, now, &active); 648 hint_revoke = dst_key_is_revoked(key, now, &revoke); 649 hint_remove = dst_key_is_removed(key, now, &remove); 650 651 if (hint_remove) { 652 return (false); 653 } 654 if (hint_publish && hint_revoke) { 655 return (true); 656 } 657 if (hint_zsign && zsk) { 658 return (true); 659 } 660 if (hint_ksign && ksk) { 661 return (true); 662 } 663 return (false); 664 } 665 666 /*%< 667 * Indicate whether a key is scheduled to to have CDS/CDNSKEY records 668 * published now. 669 * 670 * Returns true if. 671 * - kasp says the DS record should be published (e.g. the DS state is in 672 * RUMOURED or OMNIPRESENT state). 673 * Or: 674 * - SyncPublish is set and in the past, AND 675 * - SyncDelete is unset or in the future 676 */ 677 static bool 678 syncpublish(dst_key_t *key, isc_stdtime_t now) { 679 isc_result_t result; 680 isc_stdtime_t when; 681 dst_key_state_t state; 682 int major, minor; 683 bool publish; 684 685 /* 686 * Is this an old-style key? 687 */ 688 result = dst_key_getprivateformat(key, &major, &minor); 689 RUNTIME_CHECK(result == ISC_R_SUCCESS); 690 691 /* 692 * Smart signing started with key format 1.3 693 */ 694 if (major == 1 && minor <= 2) { 695 return (false); 696 } 697 698 /* Check kasp state first. */ 699 result = dst_key_getstate(key, DST_KEY_DS, &state); 700 if (result == ISC_R_SUCCESS) { 701 return (state == DST_KEY_STATE_RUMOURED || 702 state == DST_KEY_STATE_OMNIPRESENT); 703 } 704 705 /* If no kasp state, check timings. */ 706 publish = false; 707 result = dst_key_gettime(key, DST_TIME_SYNCPUBLISH, &when); 708 if (result == ISC_R_SUCCESS && when <= now) { 709 publish = true; 710 } 711 result = dst_key_gettime(key, DST_TIME_SYNCDELETE, &when); 712 if (result == ISC_R_SUCCESS && when < now) { 713 publish = false; 714 } 715 return (publish); 716 } 717 718 /*%< 719 * Indicate whether a key is scheduled to to have CDS/CDNSKEY records 720 * deleted now. 721 * 722 * Returns true if: 723 * - kasp says the DS record should be unpublished (e.g. the DS state is in 724 * UNRETENTIVE or HIDDEN state). 725 * Or: 726 * - SyncDelete is set and in the past. 727 */ 728 static bool 729 syncdelete(dst_key_t *key, isc_stdtime_t now) { 730 isc_result_t result; 731 isc_stdtime_t when; 732 dst_key_state_t state; 733 int major, minor; 734 735 /* 736 * Is this an old-style key? 737 */ 738 result = dst_key_getprivateformat(key, &major, &minor); 739 RUNTIME_CHECK(result == ISC_R_SUCCESS); 740 741 /* 742 * Smart signing started with key format 1.3. 743 */ 744 if (major == 1 && minor <= 2) { 745 return (false); 746 } 747 748 /* Check kasp state first. */ 749 result = dst_key_getstate(key, DST_KEY_DS, &state); 750 if (result == ISC_R_SUCCESS) { 751 return (state == DST_KEY_STATE_UNRETENTIVE || 752 state == DST_KEY_STATE_HIDDEN); 753 } 754 755 /* If no kasp state, check timings. */ 756 result = dst_key_gettime(key, DST_TIME_SYNCDELETE, &when); 757 if (result != ISC_R_SUCCESS) { 758 return (false); 759 } 760 if (when <= now) { 761 return (true); 762 } 763 return (false); 764 } 765 766 #define is_zone_key(key) \ 767 ((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE) 768 769 isc_result_t 770 dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node, 771 const dns_name_t *name, const char *directory, 772 isc_stdtime_t now, isc_mem_t *mctx, 773 unsigned int maxkeys, dst_key_t **keys, 774 unsigned int *nkeys) { 775 dns_rdataset_t rdataset; 776 dns_rdata_t rdata = DNS_RDATA_INIT; 777 isc_result_t result; 778 dst_key_t *pubkey = NULL; 779 unsigned int count = 0; 780 781 REQUIRE(nkeys != NULL); 782 REQUIRE(keys != NULL); 783 784 *nkeys = 0; 785 memset(keys, 0, sizeof(*keys) * maxkeys); 786 dns_rdataset_init(&rdataset); 787 RETERR(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0, 788 &rdataset, NULL)); 789 RETERR(dns_rdataset_first(&rdataset)); 790 while (result == ISC_R_SUCCESS && count < maxkeys) { 791 pubkey = NULL; 792 dns_rdataset_current(&rdataset, &rdata); 793 RETERR(dns_dnssec_keyfromrdata(name, &rdata, mctx, &pubkey)); 794 dst_key_setttl(pubkey, rdataset.ttl); 795 796 if (!is_zone_key(pubkey) || 797 (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0) { 798 goto next; 799 } 800 /* Corrupted .key file? */ 801 if (!dns_name_equal(name, dst_key_name(pubkey))) { 802 goto next; 803 } 804 keys[count] = NULL; 805 result = dst_key_fromfile( 806 dst_key_name(pubkey), dst_key_id(pubkey), 807 dst_key_alg(pubkey), 808 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE, 809 directory, mctx, &keys[count]); 810 811 /* 812 * If the key was revoked and the private file 813 * doesn't exist, maybe it was revoked internally 814 * by named. Try loading the unrevoked version. 815 */ 816 if (result == ISC_R_FILENOTFOUND) { 817 uint32_t flags; 818 flags = dst_key_flags(pubkey); 819 if ((flags & DNS_KEYFLAG_REVOKE) != 0) { 820 dst_key_setflags(pubkey, 821 flags & ~DNS_KEYFLAG_REVOKE); 822 result = dst_key_fromfile( 823 dst_key_name(pubkey), 824 dst_key_id(pubkey), dst_key_alg(pubkey), 825 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | 826 DST_TYPE_STATE, 827 directory, mctx, &keys[count]); 828 if (result == ISC_R_SUCCESS && 829 dst_key_pubcompare(pubkey, keys[count], 830 false)) { 831 dst_key_setflags(keys[count], flags); 832 } 833 dst_key_setflags(pubkey, flags); 834 } 835 } 836 837 if (result != ISC_R_SUCCESS) { 838 char filename[DNS_NAME_FORMATSIZE + 839 DNS_SECALG_FORMATSIZE + 840 sizeof("key file for //65535")]; 841 isc_result_t result2; 842 isc_buffer_t buf; 843 844 isc_buffer_init(&buf, filename, NAME_MAX); 845 result2 = dst_key_getfilename( 846 dst_key_name(pubkey), dst_key_id(pubkey), 847 dst_key_alg(pubkey), 848 (DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | 849 DST_TYPE_STATE), 850 directory, mctx, &buf); 851 if (result2 != ISC_R_SUCCESS) { 852 char namebuf[DNS_NAME_FORMATSIZE]; 853 char algbuf[DNS_SECALG_FORMATSIZE]; 854 855 dns_name_format(dst_key_name(pubkey), namebuf, 856 sizeof(namebuf)); 857 dns_secalg_format(dst_key_alg(pubkey), algbuf, 858 sizeof(algbuf)); 859 snprintf(filename, sizeof(filename) - 1, 860 "key file for %s/%s/%d", namebuf, 861 algbuf, dst_key_id(pubkey)); 862 } 863 864 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 865 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, 866 "dns_dnssec_findzonekeys2: error " 867 "reading %s: %s", 868 filename, isc_result_totext(result)); 869 } 870 871 if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) { 872 keys[count] = pubkey; 873 pubkey = NULL; 874 count++; 875 goto next; 876 } 877 878 if (result != ISC_R_SUCCESS) { 879 goto failure; 880 } 881 882 /* 883 * If a key is marked inactive, skip it 884 */ 885 if (!dns_dnssec_keyactive(keys[count], now)) { 886 dst_key_setinactive(pubkey, true); 887 dst_key_free(&keys[count]); 888 keys[count] = pubkey; 889 pubkey = NULL; 890 count++; 891 goto next; 892 } 893 894 /* 895 * Whatever the key's default TTL may have 896 * been, the rdataset TTL takes priority. 897 */ 898 dst_key_setttl(keys[count], rdataset.ttl); 899 900 if ((dst_key_flags(keys[count]) & DNS_KEYTYPE_NOAUTH) != 0) { 901 /* We should never get here. */ 902 dst_key_free(&keys[count]); 903 goto next; 904 } 905 count++; 906 next: 907 if (pubkey != NULL) { 908 dst_key_free(&pubkey); 909 } 910 dns_rdata_reset(&rdata); 911 result = dns_rdataset_next(&rdataset); 912 } 913 if (result != ISC_R_NOMORE) { 914 goto failure; 915 } 916 if (count == 0) { 917 result = ISC_R_NOTFOUND; 918 } else { 919 result = ISC_R_SUCCESS; 920 } 921 922 failure: 923 if (dns_rdataset_isassociated(&rdataset)) { 924 dns_rdataset_disassociate(&rdataset); 925 } 926 if (pubkey != NULL) { 927 dst_key_free(&pubkey); 928 } 929 if (result != ISC_R_SUCCESS) { 930 while (count > 0) { 931 dst_key_free(&keys[--count]); 932 } 933 } 934 *nkeys = count; 935 return (result); 936 } 937 938 isc_result_t 939 dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key) { 940 dns_rdata_sig_t sig; /* SIG(0) */ 941 unsigned char data[512]; 942 unsigned char header[DNS_MESSAGE_HEADERLEN]; 943 isc_buffer_t headerbuf, databuf, sigbuf; 944 unsigned int sigsize; 945 isc_buffer_t *dynbuf = NULL; 946 dns_rdata_t *rdata; 947 dns_rdatalist_t *datalist; 948 dns_rdataset_t *dataset; 949 isc_region_t r; 950 isc_stdtime_t now; 951 dst_context_t *ctx = NULL; 952 isc_mem_t *mctx; 953 isc_result_t result; 954 955 REQUIRE(msg != NULL); 956 REQUIRE(key != NULL); 957 958 if (is_response(msg)) { 959 REQUIRE(msg->query.base != NULL); 960 } 961 962 mctx = msg->mctx; 963 964 memset(&sig, 0, sizeof(sig)); 965 966 sig.mctx = mctx; 967 sig.common.rdclass = dns_rdataclass_any; 968 sig.common.rdtype = dns_rdatatype_sig; /* SIG(0) */ 969 ISC_LINK_INIT(&sig.common, link); 970 971 sig.covered = 0; 972 sig.algorithm = dst_key_alg(key); 973 sig.labels = 0; /* the root name */ 974 sig.originalttl = 0; 975 976 isc_stdtime_get(&now); 977 sig.timesigned = now - DNS_TSIG_FUDGE; 978 sig.timeexpire = now + DNS_TSIG_FUDGE; 979 980 sig.keyid = dst_key_id(key); 981 982 dns_name_init(&sig.signer, NULL); 983 dns_name_clone(dst_key_name(key), &sig.signer); 984 985 sig.siglen = 0; 986 sig.signature = NULL; 987 988 isc_buffer_init(&databuf, data, sizeof(data)); 989 990 RETERR(dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, true, 0, 991 &ctx)); 992 993 /* 994 * Digest the fields of the SIG - we can cheat and use 995 * dns_rdata_fromstruct. Since siglen is 0, the digested data 996 * is identical to dns format. 997 */ 998 RETERR(dns_rdata_fromstruct(NULL, dns_rdataclass_any, 999 dns_rdatatype_sig /* SIG(0) */, &sig, 1000 &databuf)); 1001 isc_buffer_usedregion(&databuf, &r); 1002 RETERR(dst_context_adddata(ctx, &r)); 1003 1004 /* 1005 * If this is a response, digest the query. 1006 */ 1007 if (is_response(msg)) { 1008 RETERR(dst_context_adddata(ctx, &msg->query)); 1009 } 1010 1011 /* 1012 * Digest the header. 1013 */ 1014 isc_buffer_init(&headerbuf, header, sizeof(header)); 1015 dns_message_renderheader(msg, &headerbuf); 1016 isc_buffer_usedregion(&headerbuf, &r); 1017 RETERR(dst_context_adddata(ctx, &r)); 1018 1019 /* 1020 * Digest the remainder of the message. 1021 */ 1022 isc_buffer_usedregion(msg->buffer, &r); 1023 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); 1024 RETERR(dst_context_adddata(ctx, &r)); 1025 1026 RETERR(dst_key_sigsize(key, &sigsize)); 1027 sig.siglen = sigsize; 1028 sig.signature = isc_mem_get(mctx, sig.siglen); 1029 1030 isc_buffer_init(&sigbuf, sig.signature, sig.siglen); 1031 RETERR(dst_context_sign(ctx, &sigbuf)); 1032 dst_context_destroy(&ctx); 1033 1034 rdata = NULL; 1035 RETERR(dns_message_gettemprdata(msg, &rdata)); 1036 isc_buffer_allocate(msg->mctx, &dynbuf, 1024); 1037 RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any, 1038 dns_rdatatype_sig /* SIG(0) */, &sig, 1039 dynbuf)); 1040 1041 isc_mem_put(mctx, sig.signature, sig.siglen); 1042 1043 dns_message_takebuffer(msg, &dynbuf); 1044 1045 datalist = NULL; 1046 RETERR(dns_message_gettemprdatalist(msg, &datalist)); 1047 datalist->rdclass = dns_rdataclass_any; 1048 datalist->type = dns_rdatatype_sig; /* SIG(0) */ 1049 ISC_LIST_APPEND(datalist->rdata, rdata, link); 1050 dataset = NULL; 1051 RETERR(dns_message_gettemprdataset(msg, &dataset)); 1052 RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset) == 1053 ISC_R_SUCCESS); 1054 msg->sig0 = dataset; 1055 1056 return (ISC_R_SUCCESS); 1057 1058 failure: 1059 if (dynbuf != NULL) { 1060 isc_buffer_free(&dynbuf); 1061 } 1062 if (sig.signature != NULL) { 1063 isc_mem_put(mctx, sig.signature, sig.siglen); 1064 } 1065 if (ctx != NULL) { 1066 dst_context_destroy(&ctx); 1067 } 1068 1069 return (result); 1070 } 1071 1072 isc_result_t 1073 dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg, 1074 dst_key_t *key) { 1075 dns_rdata_sig_t sig; /* SIG(0) */ 1076 unsigned char header[DNS_MESSAGE_HEADERLEN]; 1077 dns_rdata_t rdata = DNS_RDATA_INIT; 1078 isc_region_t r, source_r, sig_r, header_r; 1079 isc_stdtime_t now; 1080 dst_context_t *ctx = NULL; 1081 isc_mem_t *mctx; 1082 isc_result_t result; 1083 uint16_t addcount, addcount_n; 1084 bool signeedsfree = false; 1085 1086 REQUIRE(source != NULL); 1087 REQUIRE(msg != NULL); 1088 REQUIRE(key != NULL); 1089 1090 mctx = msg->mctx; 1091 1092 msg->verify_attempted = 1; 1093 msg->verified_sig = 0; 1094 msg->sig0status = dns_tsigerror_badsig; 1095 1096 if (is_response(msg)) { 1097 if (msg->query.base == NULL) { 1098 return (DNS_R_UNEXPECTEDTSIG); 1099 } 1100 } 1101 1102 isc_buffer_usedregion(source, &source_r); 1103 1104 RETERR(dns_rdataset_first(msg->sig0)); 1105 dns_rdataset_current(msg->sig0, &rdata); 1106 1107 RETERR(dns_rdata_tostruct(&rdata, &sig, NULL)); 1108 signeedsfree = true; 1109 1110 if (sig.labels != 0) { 1111 result = DNS_R_SIGINVALID; 1112 goto failure; 1113 } 1114 1115 if (isc_serial_lt(sig.timeexpire, sig.timesigned)) { 1116 result = DNS_R_SIGINVALID; 1117 msg->sig0status = dns_tsigerror_badtime; 1118 goto failure; 1119 } 1120 1121 isc_stdtime_get(&now); 1122 if (isc_serial_lt((uint32_t)now, sig.timesigned)) { 1123 result = DNS_R_SIGFUTURE; 1124 msg->sig0status = dns_tsigerror_badtime; 1125 goto failure; 1126 } else if (isc_serial_lt(sig.timeexpire, (uint32_t)now)) { 1127 result = DNS_R_SIGEXPIRED; 1128 msg->sig0status = dns_tsigerror_badtime; 1129 goto failure; 1130 } 1131 1132 if (!dns_name_equal(dst_key_name(key), &sig.signer)) { 1133 result = DNS_R_SIGINVALID; 1134 msg->sig0status = dns_tsigerror_badkey; 1135 goto failure; 1136 } 1137 1138 RETERR(dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, false, 0, 1139 &ctx)); 1140 1141 /* 1142 * Digest the SIG(0) record, except for the signature. 1143 */ 1144 dns_rdata_toregion(&rdata, &r); 1145 r.length -= sig.siglen; 1146 RETERR(dst_context_adddata(ctx, &r)); 1147 1148 /* 1149 * If this is a response, digest the query. 1150 */ 1151 if (is_response(msg)) { 1152 RETERR(dst_context_adddata(ctx, &msg->query)); 1153 } 1154 1155 /* 1156 * Extract the header. 1157 */ 1158 memmove(header, source_r.base, DNS_MESSAGE_HEADERLEN); 1159 1160 /* 1161 * Decrement the additional field counter. 1162 */ 1163 memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2); 1164 addcount_n = ntohs(addcount); 1165 addcount = htons((uint16_t)(addcount_n - 1)); 1166 memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2); 1167 1168 /* 1169 * Digest the modified header. 1170 */ 1171 header_r.base = (unsigned char *)header; 1172 header_r.length = DNS_MESSAGE_HEADERLEN; 1173 RETERR(dst_context_adddata(ctx, &header_r)); 1174 1175 /* 1176 * Digest all non-SIG(0) records. 1177 */ 1178 r.base = source_r.base + DNS_MESSAGE_HEADERLEN; 1179 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN; 1180 RETERR(dst_context_adddata(ctx, &r)); 1181 1182 sig_r.base = sig.signature; 1183 sig_r.length = sig.siglen; 1184 result = dst_context_verify(ctx, &sig_r); 1185 if (result != ISC_R_SUCCESS) { 1186 msg->sig0status = dns_tsigerror_badsig; 1187 goto failure; 1188 } 1189 1190 msg->verified_sig = 1; 1191 msg->sig0status = dns_rcode_noerror; 1192 1193 dst_context_destroy(&ctx); 1194 dns_rdata_freestruct(&sig); 1195 1196 return (ISC_R_SUCCESS); 1197 1198 failure: 1199 if (signeedsfree) { 1200 dns_rdata_freestruct(&sig); 1201 } 1202 if (ctx != NULL) { 1203 dst_context_destroy(&ctx); 1204 } 1205 1206 return (result); 1207 } 1208 1209 /*% 1210 * Does this key ('rdata') self sign the rrset ('rdataset')? 1211 */ 1212 bool 1213 dns_dnssec_selfsigns(dns_rdata_t *rdata, const dns_name_t *name, 1214 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, 1215 bool ignoretime, isc_mem_t *mctx) { 1216 INSIST(rdataset->type == dns_rdatatype_key || 1217 rdataset->type == dns_rdatatype_dnskey); 1218 if (rdataset->type == dns_rdatatype_key) { 1219 INSIST(sigrdataset->type == dns_rdatatype_sig); 1220 INSIST(sigrdataset->covers == dns_rdatatype_key); 1221 } else { 1222 INSIST(sigrdataset->type == dns_rdatatype_rrsig); 1223 INSIST(sigrdataset->covers == dns_rdatatype_dnskey); 1224 } 1225 1226 return (dns_dnssec_signs(rdata, name, rdataset, sigrdataset, ignoretime, 1227 mctx)); 1228 } 1229 1230 bool 1231 dns_dnssec_signs(dns_rdata_t *rdata, const dns_name_t *name, 1232 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, 1233 bool ignoretime, isc_mem_t *mctx) { 1234 dst_key_t *dstkey = NULL; 1235 dns_keytag_t keytag; 1236 dns_rdata_dnskey_t key; 1237 dns_rdata_rrsig_t sig; 1238 dns_rdata_t sigrdata = DNS_RDATA_INIT; 1239 isc_result_t result; 1240 1241 INSIST(sigrdataset->type == dns_rdatatype_rrsig); 1242 if (sigrdataset->covers != rdataset->type) { 1243 return (false); 1244 } 1245 1246 result = dns_dnssec_keyfromrdata(name, rdata, mctx, &dstkey); 1247 if (result != ISC_R_SUCCESS) { 1248 return (false); 1249 } 1250 result = dns_rdata_tostruct(rdata, &key, NULL); 1251 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1252 1253 keytag = dst_key_id(dstkey); 1254 for (result = dns_rdataset_first(sigrdataset); result == ISC_R_SUCCESS; 1255 result = dns_rdataset_next(sigrdataset)) 1256 { 1257 dns_rdata_reset(&sigrdata); 1258 dns_rdataset_current(sigrdataset, &sigrdata); 1259 result = dns_rdata_tostruct(&sigrdata, &sig, NULL); 1260 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1261 1262 if (sig.algorithm == key.algorithm && sig.keyid == keytag) { 1263 result = dns_dnssec_verify(name, rdataset, dstkey, 1264 ignoretime, 0, mctx, 1265 &sigrdata, NULL); 1266 if (result == ISC_R_SUCCESS) { 1267 dst_key_free(&dstkey); 1268 return (true); 1269 } 1270 } 1271 } 1272 dst_key_free(&dstkey); 1273 return (false); 1274 } 1275 1276 isc_result_t 1277 dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey, 1278 dns_dnsseckey_t **dkp) { 1279 isc_result_t result; 1280 dns_dnsseckey_t *dk; 1281 int major, minor; 1282 1283 REQUIRE(dkp != NULL && *dkp == NULL); 1284 dk = isc_mem_get(mctx, sizeof(dns_dnsseckey_t)); 1285 1286 dk->key = *dstkey; 1287 *dstkey = NULL; 1288 dk->force_publish = false; 1289 dk->force_sign = false; 1290 dk->hint_publish = false; 1291 dk->hint_sign = false; 1292 dk->hint_revoke = false; 1293 dk->hint_remove = false; 1294 dk->first_sign = false; 1295 dk->is_active = false; 1296 dk->purge = false; 1297 dk->prepublish = 0; 1298 dk->source = dns_keysource_unknown; 1299 dk->index = 0; 1300 1301 /* KSK or ZSK? */ 1302 result = dst_key_getbool(dk->key, DST_BOOL_KSK, &dk->ksk); 1303 if (result != ISC_R_SUCCESS) { 1304 dk->ksk = ((dst_key_flags(dk->key) & DNS_KEYFLAG_KSK) != 0); 1305 } 1306 result = dst_key_getbool(dk->key, DST_BOOL_ZSK, &dk->zsk); 1307 if (result != ISC_R_SUCCESS) { 1308 dk->zsk = ((dst_key_flags(dk->key) & DNS_KEYFLAG_KSK) == 0); 1309 } 1310 1311 /* Is this an old-style key? */ 1312 result = dst_key_getprivateformat(dk->key, &major, &minor); 1313 INSIST(result == ISC_R_SUCCESS); 1314 1315 /* Smart signing started with key format 1.3 */ 1316 dk->legacy = (major == 1 && minor <= 2); 1317 1318 ISC_LINK_INIT(dk, link); 1319 *dkp = dk; 1320 return (ISC_R_SUCCESS); 1321 } 1322 1323 void 1324 dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp) { 1325 dns_dnsseckey_t *dk; 1326 1327 REQUIRE(dkp != NULL && *dkp != NULL); 1328 dk = *dkp; 1329 *dkp = NULL; 1330 if (dk->key != NULL) { 1331 dst_key_free(&dk->key); 1332 } 1333 isc_mem_put(mctx, dk, sizeof(dns_dnsseckey_t)); 1334 } 1335 1336 void 1337 dns_dnssec_get_hints(dns_dnsseckey_t *key, isc_stdtime_t now) { 1338 isc_stdtime_t publish = 0, active = 0, revoke = 0, remove = 0; 1339 1340 REQUIRE(key != NULL && key->key != NULL); 1341 1342 key->hint_publish = dst_key_is_published(key->key, now, &publish); 1343 key->hint_sign = dst_key_is_signing(key->key, DST_BOOL_ZSK, now, 1344 &active); 1345 key->hint_revoke = dst_key_is_revoked(key->key, now, &revoke); 1346 key->hint_remove = dst_key_is_removed(key->key, now, &remove); 1347 1348 /* 1349 * Activation date is set (maybe in the future), but publication date 1350 * isn't. Most likely the user wants to publish now and activate later. 1351 * Most likely because this is true for most rollovers, except for: 1352 * 1. The unpopular ZSK Double-RRSIG method. 1353 * 2. When introducing a new algorithm. 1354 * These two cases are rare enough that we will set hint_publish 1355 * anyway when hint_sign is set, because BIND 9 natively does not 1356 * support the ZSK Double-RRSIG method, and when introducing a new 1357 * algorithm, we strive to publish its signatures and DNSKEY records 1358 * at the same time. 1359 */ 1360 if (key->hint_sign && publish == 0) { 1361 key->hint_publish = true; 1362 } 1363 1364 /* 1365 * If activation date is in the future, make note of how far off. 1366 */ 1367 if (key->hint_publish && active > now) { 1368 key->prepublish = active - now; 1369 } 1370 1371 /* 1372 * Metadata says revoke. If the key is published, we *have to* sign 1373 * with it per RFC5011 -- even if it was not active before. 1374 * 1375 * If it hasn't already been done, we should also revoke it now. 1376 */ 1377 if (key->hint_publish && key->hint_revoke) { 1378 uint32_t flags; 1379 key->hint_sign = true; 1380 flags = dst_key_flags(key->key); 1381 if ((flags & DNS_KEYFLAG_REVOKE) == 0) { 1382 flags |= DNS_KEYFLAG_REVOKE; 1383 dst_key_setflags(key->key, flags); 1384 } 1385 } 1386 1387 /* 1388 * Metadata says delete, so don't publish this key or sign with it 1389 * (note that signatures of a removed key may still be reused). 1390 */ 1391 if (key->hint_remove) { 1392 key->hint_publish = false; 1393 key->hint_sign = false; 1394 } 1395 } 1396 1397 /*% 1398 * Get a list of DNSSEC keys from the key repository. 1399 */ 1400 isc_result_t 1401 dns_dnssec_findmatchingkeys(const dns_name_t *origin, const char *directory, 1402 isc_stdtime_t now, isc_mem_t *mctx, 1403 dns_dnsseckeylist_t *keylist) { 1404 isc_result_t result = ISC_R_SUCCESS; 1405 bool dir_open = false; 1406 dns_dnsseckeylist_t list; 1407 isc_dir_t dir; 1408 dns_dnsseckey_t *key = NULL; 1409 dst_key_t *dstkey = NULL; 1410 char namebuf[DNS_NAME_FORMATSIZE]; 1411 isc_buffer_t b; 1412 unsigned int len, i, alg; 1413 1414 REQUIRE(keylist != NULL); 1415 ISC_LIST_INIT(list); 1416 isc_dir_init(&dir); 1417 1418 isc_buffer_init(&b, namebuf, sizeof(namebuf) - 1); 1419 RETERR(dns_name_tofilenametext(origin, false, &b)); 1420 len = isc_buffer_usedlength(&b); 1421 namebuf[len] = '\0'; 1422 1423 if (directory == NULL) { 1424 directory = "."; 1425 } 1426 RETERR(isc_dir_open(&dir, directory)); 1427 dir_open = true; 1428 1429 while (isc_dir_read(&dir) == ISC_R_SUCCESS) { 1430 if (dir.entry.name[0] != 'K' || dir.entry.length < len + 1 || 1431 dir.entry.name[len + 1] != '+' || 1432 strncasecmp(dir.entry.name + 1, namebuf, len) != 0) 1433 { 1434 continue; 1435 } 1436 1437 alg = 0; 1438 for (i = len + 1 + 1; i < dir.entry.length; i++) { 1439 if (!isdigit((unsigned char)dir.entry.name[i])) { 1440 break; 1441 } 1442 alg *= 10; 1443 alg += dir.entry.name[i] - '0'; 1444 } 1445 1446 /* 1447 * Did we not read exactly 3 digits? 1448 * Did we overflow? 1449 * Did we correctly terminate? 1450 */ 1451 if (i != len + 1 + 1 + 3 || i >= dir.entry.length || 1452 dir.entry.name[i] != '+') { 1453 continue; 1454 } 1455 1456 for (i++; i < dir.entry.length; i++) { 1457 if (!isdigit((unsigned char)dir.entry.name[i])) { 1458 break; 1459 } 1460 } 1461 1462 /* 1463 * Did we not read exactly 5 more digits? 1464 * Did we overflow? 1465 * Did we correctly terminate? 1466 */ 1467 if (i != len + 1 + 1 + 3 + 1 + 5 || i >= dir.entry.length || 1468 strcmp(dir.entry.name + i, ".private") != 0) 1469 { 1470 continue; 1471 } 1472 1473 dstkey = NULL; 1474 result = dst_key_fromnamedfile( 1475 dir.entry.name, directory, 1476 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE, 1477 mctx, &dstkey); 1478 1479 switch (alg) { 1480 case DST_ALG_HMACMD5: 1481 case DST_ALG_HMACSHA1: 1482 case DST_ALG_HMACSHA224: 1483 case DST_ALG_HMACSHA256: 1484 case DST_ALG_HMACSHA384: 1485 case DST_ALG_HMACSHA512: 1486 if (result == DST_R_BADKEYTYPE) { 1487 continue; 1488 } 1489 } 1490 1491 if (result != ISC_R_SUCCESS) { 1492 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 1493 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, 1494 "dns_dnssec_findmatchingkeys: " 1495 "error reading key file %s: %s", 1496 dir.entry.name, 1497 isc_result_totext(result)); 1498 continue; 1499 } 1500 1501 RETERR(dns_dnsseckey_create(mctx, &dstkey, &key)); 1502 key->source = dns_keysource_repository; 1503 dns_dnssec_get_hints(key, now); 1504 1505 if (key->legacy) { 1506 dns_dnsseckey_destroy(mctx, &key); 1507 } else { 1508 ISC_LIST_APPEND(list, key, link); 1509 key = NULL; 1510 } 1511 } 1512 1513 if (!ISC_LIST_EMPTY(list)) { 1514 result = ISC_R_SUCCESS; 1515 ISC_LIST_APPENDLIST(*keylist, list, link); 1516 } else { 1517 result = ISC_R_NOTFOUND; 1518 } 1519 1520 failure: 1521 if (dir_open) { 1522 isc_dir_close(&dir); 1523 } 1524 INSIST(key == NULL); 1525 while ((key = ISC_LIST_HEAD(list)) != NULL) { 1526 ISC_LIST_UNLINK(list, key, link); 1527 INSIST(key->key != NULL); 1528 dst_key_free(&key->key); 1529 dns_dnsseckey_destroy(mctx, &key); 1530 } 1531 if (dstkey != NULL) { 1532 dst_key_free(&dstkey); 1533 } 1534 return (result); 1535 } 1536 1537 /*% 1538 * Add 'newkey' to 'keylist' if it's not already there. 1539 * 1540 * If 'savekeys' is true, then we need to preserve all 1541 * the keys in the keyset, regardless of whether they have 1542 * metadata indicating they should be deactivated or removed. 1543 */ 1544 static isc_result_t 1545 addkey(dns_dnsseckeylist_t *keylist, dst_key_t **newkey, bool savekeys, 1546 isc_mem_t *mctx) { 1547 dns_dnsseckey_t *key; 1548 isc_result_t result; 1549 1550 /* Skip duplicates */ 1551 for (key = ISC_LIST_HEAD(*keylist); key != NULL; 1552 key = ISC_LIST_NEXT(key, link)) { 1553 if (dst_key_id(key->key) == dst_key_id(*newkey) && 1554 dst_key_alg(key->key) == dst_key_alg(*newkey) && 1555 dns_name_equal(dst_key_name(key->key), 1556 dst_key_name(*newkey))) 1557 { 1558 break; 1559 } 1560 } 1561 1562 if (key != NULL) { 1563 /* 1564 * Found a match. If the old key was only public and the 1565 * new key is private, replace the old one; otherwise 1566 * leave it. But either way, mark the key as having 1567 * been found in the zone. 1568 */ 1569 if (dst_key_isprivate(key->key)) { 1570 dst_key_free(newkey); 1571 } else if (dst_key_isprivate(*newkey)) { 1572 dst_key_free(&key->key); 1573 key->key = *newkey; 1574 } 1575 1576 key->source = dns_keysource_zoneapex; 1577 return (ISC_R_SUCCESS); 1578 } 1579 1580 result = dns_dnsseckey_create(mctx, newkey, &key); 1581 if (result != ISC_R_SUCCESS) { 1582 return (result); 1583 } 1584 if (key->legacy || savekeys) { 1585 key->force_publish = true; 1586 key->force_sign = dst_key_isprivate(key->key); 1587 } 1588 key->source = dns_keysource_zoneapex; 1589 ISC_LIST_APPEND(*keylist, key, link); 1590 *newkey = NULL; 1591 return (ISC_R_SUCCESS); 1592 } 1593 1594 /*% 1595 * Mark all keys which signed the DNSKEY/SOA RRsets as "active", 1596 * for future reference. 1597 */ 1598 static isc_result_t 1599 mark_active_keys(dns_dnsseckeylist_t *keylist, dns_rdataset_t *rrsigs) { 1600 isc_result_t result = ISC_R_SUCCESS; 1601 dns_rdata_t rdata = DNS_RDATA_INIT; 1602 dns_rdataset_t sigs; 1603 dns_dnsseckey_t *key; 1604 1605 REQUIRE(rrsigs != NULL && dns_rdataset_isassociated(rrsigs)); 1606 1607 dns_rdataset_init(&sigs); 1608 dns_rdataset_clone(rrsigs, &sigs); 1609 for (key = ISC_LIST_HEAD(*keylist); key != NULL; 1610 key = ISC_LIST_NEXT(key, link)) { 1611 uint16_t keyid, sigid; 1612 dns_secalg_t keyalg, sigalg; 1613 keyid = dst_key_id(key->key); 1614 keyalg = dst_key_alg(key->key); 1615 1616 for (result = dns_rdataset_first(&sigs); 1617 result == ISC_R_SUCCESS; result = dns_rdataset_next(&sigs)) 1618 { 1619 dns_rdata_rrsig_t sig; 1620 1621 dns_rdata_reset(&rdata); 1622 dns_rdataset_current(&sigs, &rdata); 1623 result = dns_rdata_tostruct(&rdata, &sig, NULL); 1624 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1625 sigalg = sig.algorithm; 1626 sigid = sig.keyid; 1627 if (keyid == sigid && keyalg == sigalg) { 1628 key->is_active = true; 1629 break; 1630 } 1631 } 1632 } 1633 1634 if (result == ISC_R_NOMORE) { 1635 result = ISC_R_SUCCESS; 1636 } 1637 1638 if (dns_rdataset_isassociated(&sigs)) { 1639 dns_rdataset_disassociate(&sigs); 1640 } 1641 return (result); 1642 } 1643 1644 /*% 1645 * Add the contents of a DNSKEY rdataset 'keyset' to 'keylist'. 1646 */ 1647 isc_result_t 1648 dns_dnssec_keylistfromrdataset(const dns_name_t *origin, const char *directory, 1649 isc_mem_t *mctx, dns_rdataset_t *keyset, 1650 dns_rdataset_t *keysigs, dns_rdataset_t *soasigs, 1651 bool savekeys, bool publickey, 1652 dns_dnsseckeylist_t *keylist) { 1653 dns_rdataset_t keys; 1654 dns_rdata_t rdata = DNS_RDATA_INIT; 1655 dst_key_t *dnskey = NULL, *pubkey = NULL, *privkey = NULL; 1656 isc_result_t result; 1657 1658 REQUIRE(keyset != NULL && dns_rdataset_isassociated(keyset)); 1659 1660 dns_rdataset_init(&keys); 1661 1662 dns_rdataset_clone(keyset, &keys); 1663 for (result = dns_rdataset_first(&keys); result == ISC_R_SUCCESS; 1664 result = dns_rdataset_next(&keys)) 1665 { 1666 dns_rdata_reset(&rdata); 1667 dns_rdataset_current(&keys, &rdata); 1668 1669 REQUIRE(rdata.type == dns_rdatatype_key || 1670 rdata.type == dns_rdatatype_dnskey); 1671 REQUIRE(rdata.length > 3); 1672 1673 /* Skip unsupported algorithms */ 1674 if (!dst_algorithm_supported(rdata.data[3])) { 1675 goto skip; 1676 } 1677 1678 RETERR(dns_dnssec_keyfromrdata(origin, &rdata, mctx, &dnskey)); 1679 dst_key_setttl(dnskey, keys.ttl); 1680 1681 if (!is_zone_key(dnskey) || 1682 (dst_key_flags(dnskey) & DNS_KEYTYPE_NOAUTH) != 0) { 1683 goto skip; 1684 } 1685 1686 /* Corrupted .key file? */ 1687 if (!dns_name_equal(origin, dst_key_name(dnskey))) { 1688 goto skip; 1689 } 1690 1691 if (publickey) { 1692 RETERR(addkey(keylist, &dnskey, savekeys, mctx)); 1693 goto skip; 1694 } 1695 1696 /* Try to read the public key. */ 1697 result = dst_key_fromfile( 1698 dst_key_name(dnskey), dst_key_id(dnskey), 1699 dst_key_alg(dnskey), (DST_TYPE_PUBLIC | DST_TYPE_STATE), 1700 directory, mctx, &pubkey); 1701 if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) { 1702 result = ISC_R_SUCCESS; 1703 } 1704 RETERR(result); 1705 1706 /* Now read the private key. */ 1707 result = dst_key_fromfile( 1708 dst_key_name(dnskey), dst_key_id(dnskey), 1709 dst_key_alg(dnskey), 1710 (DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE), 1711 directory, mctx, &privkey); 1712 1713 /* 1714 * If the key was revoked and the private file 1715 * doesn't exist, maybe it was revoked internally 1716 * by named. Try loading the unrevoked version. 1717 */ 1718 if (result == ISC_R_FILENOTFOUND) { 1719 uint32_t flags; 1720 flags = dst_key_flags(dnskey); 1721 if ((flags & DNS_KEYFLAG_REVOKE) != 0) { 1722 dst_key_setflags(dnskey, 1723 flags & ~DNS_KEYFLAG_REVOKE); 1724 result = dst_key_fromfile( 1725 dst_key_name(dnskey), 1726 dst_key_id(dnskey), dst_key_alg(dnskey), 1727 (DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | 1728 DST_TYPE_STATE), 1729 directory, mctx, &privkey); 1730 if (result == ISC_R_SUCCESS && 1731 dst_key_pubcompare(dnskey, privkey, false)) 1732 { 1733 dst_key_setflags(privkey, flags); 1734 } 1735 dst_key_setflags(dnskey, flags); 1736 } 1737 } 1738 1739 if (result != ISC_R_SUCCESS) { 1740 char filename[DNS_NAME_FORMATSIZE + 1741 DNS_SECALG_FORMATSIZE + 1742 sizeof("key file for //65535")]; 1743 isc_result_t result2; 1744 isc_buffer_t buf; 1745 1746 isc_buffer_init(&buf, filename, NAME_MAX); 1747 result2 = dst_key_getfilename( 1748 dst_key_name(dnskey), dst_key_id(dnskey), 1749 dst_key_alg(dnskey), 1750 (DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | 1751 DST_TYPE_STATE), 1752 directory, mctx, &buf); 1753 if (result2 != ISC_R_SUCCESS) { 1754 char namebuf[DNS_NAME_FORMATSIZE]; 1755 char algbuf[DNS_SECALG_FORMATSIZE]; 1756 1757 dns_name_format(dst_key_name(dnskey), namebuf, 1758 sizeof(namebuf)); 1759 dns_secalg_format(dst_key_alg(dnskey), algbuf, 1760 sizeof(algbuf)); 1761 snprintf(filename, sizeof(filename) - 1, 1762 "key file for %s/%s/%d", namebuf, 1763 algbuf, dst_key_id(dnskey)); 1764 } 1765 1766 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 1767 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, 1768 "dns_dnssec_keylistfromrdataset: error " 1769 "reading %s: %s", 1770 filename, isc_result_totext(result)); 1771 } 1772 1773 if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) { 1774 if (pubkey != NULL) { 1775 RETERR(addkey(keylist, &pubkey, savekeys, 1776 mctx)); 1777 } else { 1778 RETERR(addkey(keylist, &dnskey, savekeys, 1779 mctx)); 1780 } 1781 goto skip; 1782 } 1783 RETERR(result); 1784 1785 /* This should never happen. */ 1786 if ((dst_key_flags(privkey) & DNS_KEYTYPE_NOAUTH) != 0) { 1787 goto skip; 1788 } 1789 1790 /* 1791 * Whatever the key's default TTL may have 1792 * been, the rdataset TTL takes priority. 1793 */ 1794 dst_key_setttl(privkey, dst_key_getttl(dnskey)); 1795 1796 RETERR(addkey(keylist, &privkey, savekeys, mctx)); 1797 skip: 1798 if (dnskey != NULL) { 1799 dst_key_free(&dnskey); 1800 } 1801 if (pubkey != NULL) { 1802 dst_key_free(&pubkey); 1803 } 1804 if (privkey != NULL) { 1805 dst_key_free(&privkey); 1806 } 1807 } 1808 1809 if (result != ISC_R_NOMORE) { 1810 RETERR(result); 1811 } 1812 1813 if (keysigs != NULL && dns_rdataset_isassociated(keysigs)) { 1814 RETERR(mark_active_keys(keylist, keysigs)); 1815 } 1816 1817 if (soasigs != NULL && dns_rdataset_isassociated(soasigs)) { 1818 RETERR(mark_active_keys(keylist, soasigs)); 1819 } 1820 1821 result = ISC_R_SUCCESS; 1822 1823 failure: 1824 if (dns_rdataset_isassociated(&keys)) { 1825 dns_rdataset_disassociate(&keys); 1826 } 1827 if (dnskey != NULL) { 1828 dst_key_free(&dnskey); 1829 } 1830 if (pubkey != NULL) { 1831 dst_key_free(&pubkey); 1832 } 1833 if (privkey != NULL) { 1834 dst_key_free(&privkey); 1835 } 1836 return (result); 1837 } 1838 1839 static isc_result_t 1840 make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize, 1841 dns_rdata_t *target) { 1842 isc_result_t result; 1843 isc_buffer_t b; 1844 isc_region_t r; 1845 1846 isc_buffer_init(&b, buf, bufsize); 1847 result = dst_key_todns(key, &b); 1848 if (result != ISC_R_SUCCESS) { 1849 return (result); 1850 } 1851 1852 dns_rdata_reset(target); 1853 isc_buffer_usedregion(&b, &r); 1854 dns_rdata_fromregion(target, dst_key_class(key), dns_rdatatype_dnskey, 1855 &r); 1856 return (ISC_R_SUCCESS); 1857 } 1858 1859 static isc_result_t 1860 addrdata(dns_rdata_t *rdata, dns_diff_t *diff, const dns_name_t *origin, 1861 dns_ttl_t ttl, isc_mem_t *mctx) { 1862 isc_result_t result; 1863 dns_difftuple_t *tuple = NULL; 1864 1865 RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_ADD, origin, ttl, rdata, 1866 &tuple)); 1867 dns_diff_appendminimal(diff, &tuple); 1868 1869 failure: 1870 return (result); 1871 } 1872 1873 static isc_result_t 1874 delrdata(dns_rdata_t *rdata, dns_diff_t *diff, const dns_name_t *origin, 1875 dns_ttl_t ttl, isc_mem_t *mctx) { 1876 isc_result_t result; 1877 dns_difftuple_t *tuple = NULL; 1878 1879 RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_DEL, origin, ttl, rdata, 1880 &tuple)); 1881 dns_diff_appendminimal(diff, &tuple); 1882 1883 failure: 1884 return (result); 1885 } 1886 1887 static isc_result_t 1888 publish_key(dns_diff_t *diff, dns_dnsseckey_t *key, const dns_name_t *origin, 1889 dns_ttl_t ttl, isc_mem_t *mctx, void (*report)(const char *, ...)) { 1890 isc_result_t result; 1891 unsigned char buf[DST_KEY_MAXSIZE]; 1892 char keystr[DST_KEY_FORMATSIZE]; 1893 dns_rdata_t dnskey = DNS_RDATA_INIT; 1894 1895 dns_rdata_reset(&dnskey); 1896 RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey)); 1897 dst_key_format(key->key, keystr, sizeof(keystr)); 1898 1899 report("Fetching %s (%s) from key %s.", keystr, 1900 key->ksk ? (key->zsk ? "CSK" : "KSK") : "ZSK", 1901 key->source == dns_keysource_user ? "file" : "repository"); 1902 1903 if (key->prepublish && ttl > key->prepublish) { 1904 isc_stdtime_t now; 1905 1906 report("Key %s: Delaying activation to match the DNSKEY TTL.", 1907 keystr, ttl); 1908 1909 isc_stdtime_get(&now); 1910 dst_key_settime(key->key, DST_TIME_ACTIVATE, now + ttl); 1911 } 1912 1913 /* publish key */ 1914 result = addrdata(&dnskey, diff, origin, ttl, mctx); 1915 1916 failure: 1917 return (result); 1918 } 1919 1920 static isc_result_t 1921 remove_key(dns_diff_t *diff, dns_dnsseckey_t *key, const dns_name_t *origin, 1922 dns_ttl_t ttl, isc_mem_t *mctx, const char *reason, 1923 void (*report)(const char *, ...)) { 1924 isc_result_t result; 1925 unsigned char buf[DST_KEY_MAXSIZE]; 1926 dns_rdata_t dnskey = DNS_RDATA_INIT; 1927 char alg[80]; 1928 1929 dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg)); 1930 report("Removing %s key %d/%s from DNSKEY RRset.", reason, 1931 dst_key_id(key->key), alg); 1932 1933 RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey)); 1934 result = delrdata(&dnskey, diff, origin, ttl, mctx); 1935 1936 failure: 1937 return (result); 1938 } 1939 1940 static bool 1941 exists(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { 1942 isc_result_t result; 1943 dns_rdataset_t trdataset; 1944 1945 dns_rdataset_init(&trdataset); 1946 dns_rdataset_clone(rdataset, &trdataset); 1947 for (result = dns_rdataset_first(&trdataset); result == ISC_R_SUCCESS; 1948 result = dns_rdataset_next(&trdataset)) 1949 { 1950 dns_rdata_t current = DNS_RDATA_INIT; 1951 1952 dns_rdataset_current(&trdataset, ¤t); 1953 if (dns_rdata_compare(rdata, ¤t) == 0) { 1954 dns_rdataset_disassociate(&trdataset); 1955 return (true); 1956 } 1957 } 1958 dns_rdataset_disassociate(&trdataset); 1959 return (false); 1960 } 1961 1962 isc_result_t 1963 dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys, 1964 dns_rdataset_t *cds, dns_rdataset_t *cdnskey, 1965 isc_stdtime_t now, dns_ttl_t ttl, dns_diff_t *diff, 1966 isc_mem_t *mctx) { 1967 unsigned char dsbuf1[DNS_DS_BUFFERSIZE]; 1968 unsigned char dsbuf2[DNS_DS_BUFFERSIZE]; 1969 unsigned char keybuf[DST_KEY_MAXSIZE]; 1970 isc_result_t result; 1971 dns_dnsseckey_t *key; 1972 1973 for (key = ISC_LIST_HEAD(*keys); key != NULL; 1974 key = ISC_LIST_NEXT(key, link)) { 1975 dns_rdata_t cds_sha1 = DNS_RDATA_INIT; 1976 dns_rdata_t cds_sha256 = DNS_RDATA_INIT; 1977 dns_rdata_t cdnskeyrdata = DNS_RDATA_INIT; 1978 dns_name_t *origin = dst_key_name(key->key); 1979 1980 RETERR(make_dnskey(key->key, keybuf, sizeof(keybuf), 1981 &cdnskeyrdata)); 1982 1983 /* 1984 * We construct the SHA-1 version of the record so we can 1985 * delete any old records generated by previous versions of 1986 * BIND. We only add SHA-256 records. 1987 * 1988 * XXXMPA we need to be able to specify the DS algorithms 1989 * to be used here and below with rmkeys. 1990 */ 1991 RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata, 1992 DNS_DSDIGEST_SHA1, dsbuf1, &cds_sha1)); 1993 RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata, 1994 DNS_DSDIGEST_SHA256, dsbuf2, 1995 &cds_sha256)); 1996 1997 /* 1998 * Now that the we have created the DS records convert 1999 * the rdata to CDNSKEY and CDS for comparison. 2000 */ 2001 cdnskeyrdata.type = dns_rdatatype_cdnskey; 2002 cds_sha1.type = dns_rdatatype_cds; 2003 cds_sha256.type = dns_rdatatype_cds; 2004 2005 if (syncpublish(key->key, now)) { 2006 char keystr[DST_KEY_FORMATSIZE]; 2007 dst_key_format(key->key, keystr, sizeof(keystr)); 2008 2009 if (!dns_rdataset_isassociated(cdnskey) || 2010 !exists(cdnskey, &cdnskeyrdata)) { 2011 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 2012 DNS_LOGMODULE_DNSSEC, 2013 ISC_LOG_INFO, 2014 "CDS for key %s is now published", 2015 keystr); 2016 RETERR(addrdata(&cdnskeyrdata, diff, origin, 2017 ttl, mctx)); 2018 } 2019 /* Only publish SHA-256 (SHA-1 is deprecated) */ 2020 if (!dns_rdataset_isassociated(cds) || 2021 !exists(cds, &cds_sha256)) { 2022 isc_log_write( 2023 dns_lctx, DNS_LOGCATEGORY_GENERAL, 2024 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, 2025 "CDNSKEY for key %s is now published", 2026 keystr); 2027 RETERR(addrdata(&cds_sha256, diff, origin, ttl, 2028 mctx)); 2029 } 2030 } 2031 2032 if (syncdelete(key->key, now)) { 2033 char keystr[DST_KEY_FORMATSIZE]; 2034 dst_key_format(key->key, keystr, sizeof(keystr)); 2035 2036 if (dns_rdataset_isassociated(cds)) { 2037 /* Delete both SHA-1 and SHA-256 */ 2038 if (exists(cds, &cds_sha1)) { 2039 isc_log_write(dns_lctx, 2040 DNS_LOGCATEGORY_GENERAL, 2041 DNS_LOGMODULE_DNSSEC, 2042 ISC_LOG_INFO, 2043 "CDS (SHA-1) for key %s " 2044 "is now deleted", 2045 keystr); 2046 RETERR(delrdata(&cds_sha1, diff, origin, 2047 cds->ttl, mctx)); 2048 } 2049 if (exists(cds, &cds_sha256)) { 2050 isc_log_write(dns_lctx, 2051 DNS_LOGCATEGORY_GENERAL, 2052 DNS_LOGMODULE_DNSSEC, 2053 ISC_LOG_INFO, 2054 "CDS (SHA-256) for key " 2055 "%s is now deleted", 2056 keystr); 2057 RETERR(delrdata(&cds_sha256, diff, 2058 origin, cds->ttl, 2059 mctx)); 2060 } 2061 } 2062 2063 if (dns_rdataset_isassociated(cdnskey)) { 2064 if (exists(cdnskey, &cdnskeyrdata)) { 2065 isc_log_write(dns_lctx, 2066 DNS_LOGCATEGORY_GENERAL, 2067 DNS_LOGMODULE_DNSSEC, 2068 ISC_LOG_INFO, 2069 "CDNSKEY for key %s is " 2070 "now deleted", 2071 keystr); 2072 RETERR(delrdata(&cdnskeyrdata, diff, 2073 origin, cdnskey->ttl, 2074 mctx)); 2075 } 2076 } 2077 } 2078 } 2079 2080 if (!dns_rdataset_isassociated(cds) && 2081 !dns_rdataset_isassociated(cdnskey)) { 2082 return (ISC_R_SUCCESS); 2083 } 2084 2085 /* 2086 * Unconditionally remove CDS/DNSKEY records for removed keys. 2087 */ 2088 for (key = ISC_LIST_HEAD(*rmkeys); key != NULL; 2089 key = ISC_LIST_NEXT(key, link)) { 2090 dns_rdata_t cds_sha1 = DNS_RDATA_INIT; 2091 dns_rdata_t cds_sha256 = DNS_RDATA_INIT; 2092 dns_rdata_t cdnskeyrdata = DNS_RDATA_INIT; 2093 dns_name_t *origin = dst_key_name(key->key); 2094 2095 char keystr[DST_KEY_FORMATSIZE]; 2096 dst_key_format(key->key, keystr, sizeof(keystr)); 2097 2098 RETERR(make_dnskey(key->key, keybuf, sizeof(keybuf), 2099 &cdnskeyrdata)); 2100 2101 if (dns_rdataset_isassociated(cds)) { 2102 RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata, 2103 DNS_DSDIGEST_SHA1, dsbuf1, 2104 &cds_sha1)); 2105 RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata, 2106 DNS_DSDIGEST_SHA256, dsbuf2, 2107 &cds_sha256)); 2108 if (exists(cds, &cds_sha1)) { 2109 isc_log_write( 2110 dns_lctx, DNS_LOGCATEGORY_GENERAL, 2111 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, 2112 "CDS (SHA-1) for key %s is now deleted", 2113 keystr); 2114 RETERR(delrdata(&cds_sha1, diff, origin, 2115 cds->ttl, mctx)); 2116 } 2117 if (exists(cds, &cds_sha256)) { 2118 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 2119 DNS_LOGMODULE_DNSSEC, 2120 ISC_LOG_INFO, 2121 "CDS (SHA-256) for key %s is now " 2122 "deleted", 2123 keystr); 2124 RETERR(delrdata(&cds_sha256, diff, origin, 2125 cds->ttl, mctx)); 2126 } 2127 } 2128 2129 if (dns_rdataset_isassociated(cdnskey)) { 2130 if (exists(cdnskey, &cdnskeyrdata)) { 2131 isc_log_write( 2132 dns_lctx, DNS_LOGCATEGORY_GENERAL, 2133 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, 2134 "CDNSKEY for key %s is now deleted", 2135 keystr); 2136 RETERR(delrdata(&cdnskeyrdata, diff, origin, 2137 cdnskey->ttl, mctx)); 2138 } 2139 } 2140 } 2141 2142 result = ISC_R_SUCCESS; 2143 2144 failure: 2145 return (result); 2146 } 2147 2148 isc_result_t 2149 dns_dnssec_syncdelete(dns_rdataset_t *cds, dns_rdataset_t *cdnskey, 2150 dns_name_t *origin, dns_rdataclass_t zclass, 2151 dns_ttl_t ttl, dns_diff_t *diff, isc_mem_t *mctx, 2152 bool expect_cds_delete, bool expect_cdnskey_delete) { 2153 unsigned char dsbuf[5] = { 0, 0, 0, 0, 0 }; /* CDS DELETE rdata */ 2154 unsigned char keybuf[5] = { 0, 0, 3, 0, 0 }; /* CDNSKEY DELETE rdata */ 2155 char namebuf[DNS_NAME_FORMATSIZE]; 2156 dns_rdata_t cds_delete = DNS_RDATA_INIT; 2157 dns_rdata_t cdnskey_delete = DNS_RDATA_INIT; 2158 isc_region_t r; 2159 isc_result_t result; 2160 2161 r.base = keybuf; 2162 r.length = sizeof(keybuf); 2163 dns_rdata_fromregion(&cdnskey_delete, zclass, dns_rdatatype_cdnskey, 2164 &r); 2165 2166 r.base = dsbuf; 2167 r.length = sizeof(dsbuf); 2168 dns_rdata_fromregion(&cds_delete, zclass, dns_rdatatype_cds, &r); 2169 2170 dns_name_format(origin, namebuf, sizeof(namebuf)); 2171 2172 if (expect_cds_delete) { 2173 if (!dns_rdataset_isassociated(cds) || 2174 !exists(cds, &cds_delete)) { 2175 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 2176 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, 2177 "CDS (DELETE) for zone %s is now " 2178 "published", 2179 namebuf); 2180 RETERR(addrdata(&cds_delete, diff, origin, ttl, mctx)); 2181 } 2182 } else { 2183 if (dns_rdataset_isassociated(cds) && exists(cds, &cds_delete)) 2184 { 2185 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 2186 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, 2187 "CDS (DELETE) for zone %s is now " 2188 "deleted", 2189 namebuf); 2190 RETERR(delrdata(&cds_delete, diff, origin, cds->ttl, 2191 mctx)); 2192 } 2193 } 2194 2195 if (expect_cdnskey_delete) { 2196 if (!dns_rdataset_isassociated(cdnskey) || 2197 !exists(cdnskey, &cdnskey_delete)) { 2198 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 2199 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, 2200 "CDNSKEY (DELETE) for zone %s is now " 2201 "published", 2202 namebuf); 2203 RETERR(addrdata(&cdnskey_delete, diff, origin, ttl, 2204 mctx)); 2205 } 2206 } else { 2207 if (dns_rdataset_isassociated(cdnskey) && 2208 exists(cdnskey, &cdnskey_delete)) { 2209 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 2210 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, 2211 "CDNSKEY (DELETE) for zone %s is now " 2212 "deleted", 2213 namebuf); 2214 RETERR(delrdata(&cdnskey_delete, diff, origin, 2215 cdnskey->ttl, mctx)); 2216 } 2217 } 2218 2219 result = ISC_R_SUCCESS; 2220 2221 failure: 2222 return (result); 2223 } 2224 2225 /* 2226 * Update 'keys' with information from 'newkeys'. 2227 * 2228 * If 'removed' is not NULL, any keys that are being removed from 2229 * the zone will be added to the list for post-removal processing. 2230 */ 2231 isc_result_t 2232 dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys, 2233 dns_dnsseckeylist_t *removed, const dns_name_t *origin, 2234 dns_ttl_t hint_ttl, dns_diff_t *diff, isc_mem_t *mctx, 2235 void (*report)(const char *, ...)) { 2236 isc_result_t result; 2237 dns_dnsseckey_t *key, *key1, *key2, *next; 2238 bool found_ttl = false; 2239 dns_ttl_t ttl = hint_ttl; 2240 2241 /* 2242 * First, look through the existing key list to find keys 2243 * supplied from the command line which are not in the zone. 2244 * Update the zone to include them. 2245 * 2246 * Also, if there are keys published in the zone already, 2247 * use their TTL for all subsequent published keys. 2248 */ 2249 for (key = ISC_LIST_HEAD(*keys); key != NULL; 2250 key = ISC_LIST_NEXT(key, link)) { 2251 if (key->source == dns_keysource_user && 2252 (key->hint_publish || key->force_publish)) 2253 { 2254 RETERR(publish_key(diff, key, origin, ttl, mctx, 2255 report)); 2256 } 2257 if (key->source == dns_keysource_zoneapex) { 2258 ttl = dst_key_getttl(key->key); 2259 found_ttl = true; 2260 } 2261 } 2262 2263 /* 2264 * If there were no existing keys, use the smallest nonzero 2265 * TTL of the keys found in the repository. 2266 */ 2267 if (!found_ttl && !ISC_LIST_EMPTY(*newkeys)) { 2268 dns_ttl_t shortest = 0; 2269 2270 for (key = ISC_LIST_HEAD(*newkeys); key != NULL; 2271 key = ISC_LIST_NEXT(key, link)) { 2272 dns_ttl_t thisttl = dst_key_getttl(key->key); 2273 if (thisttl != 0 && 2274 (shortest == 0 || thisttl < shortest)) { 2275 shortest = thisttl; 2276 } 2277 } 2278 2279 if (shortest != 0) { 2280 ttl = shortest; 2281 } 2282 } 2283 2284 /* 2285 * Second, scan the list of newly found keys looking for matches 2286 * with known keys, and update accordingly. 2287 */ 2288 for (key1 = ISC_LIST_HEAD(*newkeys); key1 != NULL; key1 = next) { 2289 bool key_revoked = false; 2290 char keystr1[DST_KEY_FORMATSIZE]; 2291 char keystr2[DST_KEY_FORMATSIZE]; 2292 2293 next = ISC_LIST_NEXT(key1, link); 2294 2295 for (key2 = ISC_LIST_HEAD(*keys); key2 != NULL; 2296 key2 = ISC_LIST_NEXT(key2, link)) 2297 { 2298 int f1 = dst_key_flags(key1->key); 2299 int f2 = dst_key_flags(key2->key); 2300 int nr1 = f1 & ~DNS_KEYFLAG_REVOKE; 2301 int nr2 = f2 & ~DNS_KEYFLAG_REVOKE; 2302 if (nr1 == nr2 && 2303 dst_key_alg(key1->key) == dst_key_alg(key2->key) && 2304 dst_key_pubcompare(key1->key, key2->key, true)) 2305 { 2306 int r1, r2; 2307 r1 = dst_key_flags(key1->key) & 2308 DNS_KEYFLAG_REVOKE; 2309 r2 = dst_key_flags(key2->key) & 2310 DNS_KEYFLAG_REVOKE; 2311 key_revoked = (r1 != r2); 2312 break; 2313 } 2314 } 2315 2316 /* Printable version of key1 (the newly acquired key) */ 2317 dst_key_format(key1->key, keystr1, sizeof(keystr1)); 2318 2319 /* No match found in keys; add the new key. */ 2320 if (key2 == NULL) { 2321 ISC_LIST_UNLINK(*newkeys, key1, link); 2322 ISC_LIST_APPEND(*keys, key1, link); 2323 2324 if (key1->source != dns_keysource_zoneapex && 2325 (key1->hint_publish || key1->force_publish)) 2326 { 2327 RETERR(publish_key(diff, key1, origin, ttl, 2328 mctx, report)); 2329 isc_log_write( 2330 dns_lctx, DNS_LOGCATEGORY_DNSSEC, 2331 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, 2332 "DNSKEY %s (%s) is now published", 2333 keystr1, 2334 key1->ksk ? (key1->zsk ? "CSK" : "KSK") 2335 : "ZSK"); 2336 if (key1->hint_sign || key1->force_sign) { 2337 key1->first_sign = true; 2338 isc_log_write( 2339 dns_lctx, 2340 DNS_LOGCATEGORY_DNSSEC, 2341 DNS_LOGMODULE_DNSSEC, 2342 ISC_LOG_INFO, 2343 "DNSKEY %s (%s) is now " 2344 "active", 2345 keystr1, 2346 key1->ksk ? (key1->zsk ? "CSK" 2347 : "KSK") 2348 : "ZSK"); 2349 } 2350 } 2351 2352 continue; 2353 } 2354 2355 /* Printable version of key2 (the old key, if any) */ 2356 dst_key_format(key2->key, keystr2, sizeof(keystr2)); 2357 2358 /* Copy key metadata. */ 2359 dst_key_copy_metadata(key2->key, key1->key); 2360 2361 /* Match found: remove or update it as needed */ 2362 if (key1->hint_remove) { 2363 RETERR(remove_key(diff, key2, origin, ttl, mctx, 2364 "expired", report)); 2365 ISC_LIST_UNLINK(*keys, key2, link); 2366 2367 if (removed != NULL) { 2368 ISC_LIST_APPEND(*removed, key2, link); 2369 isc_log_write( 2370 dns_lctx, DNS_LOGCATEGORY_DNSSEC, 2371 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, 2372 "DNSKEY %s (%s) is now deleted", 2373 keystr2, 2374 key2->ksk ? (key2->zsk ? "CSK" : "KSK") 2375 : "ZSK"); 2376 } else { 2377 dns_dnsseckey_destroy(mctx, &key2); 2378 } 2379 } else if (key_revoked && 2380 (dst_key_flags(key1->key) & DNS_KEYFLAG_REVOKE) != 0) 2381 { 2382 /* 2383 * A previously valid key has been revoked. 2384 * We need to remove the old version and pull 2385 * in the new one. 2386 */ 2387 RETERR(remove_key(diff, key2, origin, ttl, mctx, 2388 "revoked", report)); 2389 ISC_LIST_UNLINK(*keys, key2, link); 2390 if (removed != NULL) { 2391 ISC_LIST_APPEND(*removed, key2, link); 2392 isc_log_write( 2393 dns_lctx, DNS_LOGCATEGORY_DNSSEC, 2394 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, 2395 "DNSKEY %s (%s) is now revoked; " 2396 "new ID is %05d", 2397 keystr2, 2398 key2->ksk ? (key2->zsk ? "CSK" : "KSK") 2399 : "ZSK", 2400 dst_key_id(key1->key)); 2401 } else { 2402 dns_dnsseckey_destroy(mctx, &key2); 2403 } 2404 2405 RETERR(publish_key(diff, key1, origin, ttl, mctx, 2406 report)); 2407 ISC_LIST_UNLINK(*newkeys, key1, link); 2408 ISC_LIST_APPEND(*keys, key1, link); 2409 2410 /* 2411 * XXX: The revoke flag is only defined for trust 2412 * anchors. Setting the flag on a non-KSK is legal, 2413 * but not defined in any RFC. It seems reasonable 2414 * to treat it the same as a KSK: keep it in the 2415 * zone, sign the DNSKEY set with it, but not 2416 * sign other records with it. 2417 */ 2418 key1->ksk = true; 2419 continue; 2420 } else { 2421 if (!key2->is_active && 2422 (key1->hint_sign || key1->force_sign)) { 2423 key2->first_sign = true; 2424 isc_log_write( 2425 dns_lctx, DNS_LOGCATEGORY_DNSSEC, 2426 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, 2427 "DNSKEY %s (%s) is now active", keystr1, 2428 key1->ksk ? (key1->zsk ? "CSK" : "KSK") 2429 : "ZSK"); 2430 } else if (key2->is_active && !key1->hint_sign && 2431 !key1->force_sign) { 2432 isc_log_write( 2433 dns_lctx, DNS_LOGCATEGORY_DNSSEC, 2434 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, 2435 "DNSKEY %s (%s) is now inactive", 2436 keystr1, 2437 key1->ksk ? (key1->zsk ? "CSK" : "KSK") 2438 : "ZSK"); 2439 } 2440 2441 key2->hint_sign = key1->hint_sign; 2442 key2->hint_publish = key1->hint_publish; 2443 } 2444 } 2445 2446 /* Free any leftover keys in newkeys */ 2447 while (!ISC_LIST_EMPTY(*newkeys)) { 2448 key1 = ISC_LIST_HEAD(*newkeys); 2449 ISC_LIST_UNLINK(*newkeys, key1, link); 2450 dns_dnsseckey_destroy(mctx, &key1); 2451 } 2452 2453 result = ISC_R_SUCCESS; 2454 2455 failure: 2456 return (result); 2457 } 2458 2459 isc_result_t 2460 dns_dnssec_matchdskey(dns_name_t *name, dns_rdata_t *dsrdata, 2461 dns_rdataset_t *keyset, dns_rdata_t *keyrdata) { 2462 isc_result_t result; 2463 unsigned char buf[DNS_DS_BUFFERSIZE]; 2464 dns_keytag_t keytag; 2465 dns_rdata_dnskey_t key; 2466 dns_rdata_ds_t ds; 2467 isc_region_t r; 2468 2469 result = dns_rdata_tostruct(dsrdata, &ds, NULL); 2470 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2471 2472 for (result = dns_rdataset_first(keyset); result == ISC_R_SUCCESS; 2473 result = dns_rdataset_next(keyset)) 2474 { 2475 dns_rdata_t newdsrdata = DNS_RDATA_INIT; 2476 2477 dns_rdata_reset(keyrdata); 2478 dns_rdataset_current(keyset, keyrdata); 2479 2480 result = dns_rdata_tostruct(keyrdata, &key, NULL); 2481 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2482 2483 dns_rdata_toregion(keyrdata, &r); 2484 keytag = dst_region_computeid(&r); 2485 2486 if (ds.key_tag != keytag || ds.algorithm != key.algorithm) { 2487 continue; 2488 } 2489 2490 result = dns_ds_buildrdata(name, keyrdata, ds.digest_type, buf, 2491 &newdsrdata); 2492 if (result != ISC_R_SUCCESS) { 2493 continue; 2494 } 2495 2496 if (dns_rdata_compare(dsrdata, &newdsrdata) == 0) { 2497 break; 2498 } 2499 } 2500 if (result == ISC_R_NOMORE) { 2501 result = ISC_R_NOTFOUND; 2502 } 2503 2504 return (result); 2505 } 2506