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