1 /* $NetBSD: dnssec-signzone.c,v 1.13 2025/01/26 16:24:32 christos Exp $ */ 2 3 /* 4 * Portions 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 * Portions Copyright (C) Network Associates, Inc. 16 * 17 * Permission to use, copy, modify, and/or distribute this software for any 18 * purpose with or without fee is hereby granted, provided that the above 19 * copyright notice and this permission notice appear in all copies. 20 * 21 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS 22 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE 24 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 25 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 26 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 27 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 28 */ 29 30 /*! \file */ 31 32 #include <inttypes.h> 33 #include <stdbool.h> 34 #include <stdlib.h> 35 #include <time.h> 36 #include <unistd.h> 37 38 #include <openssl/opensslv.h> 39 40 #include <isc/async.h> 41 #include <isc/atomic.h> 42 #include <isc/attributes.h> 43 #include <isc/base32.h> 44 #include <isc/commandline.h> 45 #include <isc/dir.h> 46 #include <isc/file.h> 47 #include <isc/fips.h> 48 #include <isc/hash.h> 49 #include <isc/hex.h> 50 #include <isc/loop.h> 51 #include <isc/managers.h> 52 #include <isc/md.h> 53 #include <isc/mem.h> 54 #include <isc/mutex.h> 55 #include <isc/os.h> 56 #include <isc/random.h> 57 #include <isc/result.h> 58 #include <isc/rwlock.h> 59 #include <isc/safe.h> 60 #include <isc/serial.h> 61 #include <isc/stdio.h> 62 #include <isc/string.h> 63 #include <isc/tid.h> 64 #include <isc/time.h> 65 #include <isc/util.h> 66 67 #include <dns/db.h> 68 #include <dns/dbiterator.h> 69 #include <dns/diff.h> 70 #include <dns/dnssec.h> 71 #include <dns/ds.h> 72 #include <dns/fixedname.h> 73 #include <dns/kasp.h> 74 #include <dns/keyvalues.h> 75 #include <dns/log.h> 76 #include <dns/master.h> 77 #include <dns/masterdump.h> 78 #include <dns/nsec.h> 79 #include <dns/nsec3.h> 80 #include <dns/rdata.h> 81 #include <dns/rdataclass.h> 82 #include <dns/rdatalist.h> 83 #include <dns/rdataset.h> 84 #include <dns/rdatasetiter.h> 85 #include <dns/rdatastruct.h> 86 #include <dns/rdatatype.h> 87 #include <dns/soa.h> 88 #include <dns/time.h> 89 #include <dns/update.h> 90 #include <dns/zoneverify.h> 91 92 #include <dst/dst.h> 93 #if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 94 #include <openssl/err.h> 95 #include <openssl/provider.h> 96 #endif 97 98 #include "dnssectool.h" 99 100 const char *program = "dnssec-signzone"; 101 102 typedef struct hashlist hashlist_t; 103 104 static int nsec_datatype = dns_rdatatype_nsec; 105 106 #define check_dns_dbiterator_current(result) \ 107 check_result((result == DNS_R_NEWORIGIN) ? ISC_R_SUCCESS : result, \ 108 "dns_dbiterator_current()") 109 110 #define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3) 111 #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0) 112 113 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0) 114 115 #define BUFSIZE 2048 116 #define MAXDSKEYS 8 117 118 #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453) 119 #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0) 120 #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1) 121 122 #define SOA_SERIAL_KEEP 0 123 #define SOA_SERIAL_INCREMENT 1 124 #define SOA_SERIAL_UNIXTIME 2 125 #define SOA_SERIAL_DATE 3 126 127 static dns_dnsseckeylist_t keylist; 128 static unsigned int keycount = 0; 129 static isc_rwlock_t keylist_lock; 130 static isc_stdtime_t starttime = 0, endtime = 0, dnskey_endtime = 0, now; 131 static int cycle = -1; 132 static int jitter = 0; 133 static bool tryverify = false; 134 static bool printstats = false; 135 static isc_mem_t *mctx = NULL; 136 static dns_ttl_t zone_soa_min_ttl; 137 static dns_ttl_t soa_ttl; 138 static FILE *outfp = NULL; 139 static char *tempfile = NULL; 140 static const dns_master_style_t *masterstyle; 141 static dns_masterformat_t inputformat = dns_masterformat_text; 142 static dns_masterformat_t outputformat = dns_masterformat_text; 143 static uint32_t rawversion = 1, serialnum = 0; 144 static bool snset = false; 145 static atomic_uint_fast32_t nsigned = 0, nretained = 0, ndropped = 0; 146 static atomic_uint_fast32_t nverified = 0, nverifyfailed = 0; 147 static const char *directory = NULL, *dsdir = NULL; 148 static isc_mutex_t namelock; 149 static isc_nm_t *netmgr = NULL; 150 static isc_loopmgr_t *loopmgr = NULL; 151 static dns_db_t *gdb; /* The database */ 152 static dns_dbversion_t *gversion; /* The database version */ 153 static dns_dbiterator_t *gdbiter; /* The database iterator */ 154 static dns_rdataclass_t gclass; /* The class */ 155 static dns_name_t *gorigin; /* The database origin */ 156 static int nsec3flags = 0; 157 static dns_iterations_t nsec3iter = 0U; 158 static unsigned char saltbuf[255]; 159 static unsigned char *gsalt = saltbuf; 160 static size_t salt_length = 0; 161 static unsigned int nloops = 0; 162 static atomic_bool shuttingdown; 163 static atomic_bool finished; 164 static bool nokeys = false; 165 static bool removefile = false; 166 static bool generateds = false; 167 static bool ignore_kskflag = false; 168 static bool keyset_kskonly = false; 169 static dns_master_style_t *dsstyle = NULL; 170 static unsigned int serialformat = SOA_SERIAL_KEEP; 171 static unsigned int hash_length = 0; 172 static bool unknownalg = false; 173 static bool disable_zone_check = false; 174 static bool update_chain = false; 175 static bool set_keyttl = false; 176 static dns_ttl_t keyttl; 177 static bool smartsign = false; 178 static bool remove_orphansigs = false; 179 static bool remove_inactkeysigs = false; 180 static bool output_dnssec_only = false; 181 static bool output_stdout = false; 182 static bool set_maxttl = false; 183 static dns_ttl_t maxttl = 0; 184 static bool no_max_check = false; 185 static const char *sync_records = "cdnskey,cds:sha-256"; 186 187 #define INCSTAT(counter) \ 188 if (printstats) { \ 189 atomic_fetch_add_relaxed(&counter, 1); \ 190 } 191 192 /*% 193 * Store a copy of 'name' in 'fzonecut' and return a pointer to that copy. 194 */ 195 static dns_name_t * 196 savezonecut(dns_fixedname_t *fzonecut, dns_name_t *name) { 197 dns_name_t *result; 198 199 result = dns_fixedname_initname(fzonecut); 200 dns_name_copy(name, result); 201 202 return result; 203 } 204 205 static void 206 dumpnode(dns_name_t *name, dns_dbnode_t *node) { 207 dns_rdataset_t rds; 208 dns_rdatasetiter_t *iter = NULL; 209 isc_buffer_t *buffer = NULL; 210 isc_region_t r; 211 isc_result_t result; 212 unsigned int bufsize = 4096; 213 214 if (!output_dnssec_only) { 215 return; 216 } 217 218 result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &iter); 219 check_result(result, "dns_db_allrdatasets"); 220 221 dns_rdataset_init(&rds); 222 223 isc_buffer_allocate(mctx, &buffer, bufsize); 224 225 for (result = dns_rdatasetiter_first(iter); result == ISC_R_SUCCESS; 226 result = dns_rdatasetiter_next(iter)) 227 { 228 dns_rdatasetiter_current(iter, &rds); 229 230 if (rds.type != dns_rdatatype_rrsig && 231 rds.type != dns_rdatatype_nsec && 232 rds.type != dns_rdatatype_nsec3 && 233 rds.type != dns_rdatatype_nsec3param && 234 (!smartsign || rds.type != dns_rdatatype_dnskey)) 235 { 236 dns_rdataset_disassociate(&rds); 237 continue; 238 } 239 240 for (;;) { 241 result = dns_master_rdatasettotext( 242 name, &rds, masterstyle, NULL, buffer); 243 if (result != ISC_R_NOSPACE) { 244 break; 245 } 246 247 bufsize <<= 1; 248 isc_buffer_free(&buffer); 249 isc_buffer_allocate(mctx, &buffer, bufsize); 250 } 251 check_result(result, "dns_master_rdatasettotext"); 252 253 isc_buffer_usedregion(buffer, &r); 254 result = isc_stdio_write(r.base, 1, r.length, outfp, NULL); 255 check_result(result, "isc_stdio_write"); 256 isc_buffer_clear(buffer); 257 258 dns_rdataset_disassociate(&rds); 259 } 260 261 isc_buffer_free(&buffer); 262 dns_rdatasetiter_destroy(&iter); 263 } 264 265 static void 266 lock_and_dumpnode(dns_name_t *name, dns_dbnode_t *node) { 267 if (!output_dnssec_only) { 268 return; 269 } 270 271 LOCK(&namelock); 272 dumpnode(name, node); 273 UNLOCK(&namelock); 274 } 275 276 /*% 277 * Sign the given RRset with given key, and add the signature record to the 278 * given tuple. 279 */ 280 static void 281 signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key, 282 dns_ttl_t ttl, dns_diff_t *add, const char *logmsg) { 283 isc_result_t result; 284 isc_stdtime_t jendtime, expiry; 285 char keystr[DST_KEY_FORMATSIZE]; 286 dns_rdata_t trdata = DNS_RDATA_INIT; 287 unsigned char array[BUFSIZE]; 288 isc_buffer_t b; 289 dns_difftuple_t *tuple; 290 291 dst_key_format(key, keystr, sizeof(keystr)); 292 vbprintf(1, "\t%s %s\n", logmsg, keystr); 293 294 if (rdataset->type == dns_rdatatype_dnskey) { 295 expiry = dnskey_endtime; 296 } else { 297 expiry = endtime; 298 } 299 300 jendtime = (jitter != 0) ? expiry - isc_random_uniform(jitter) : expiry; 301 isc_buffer_init(&b, array, sizeof(array)); 302 result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime, 303 mctx, &b, &trdata); 304 if (result != ISC_R_SUCCESS) { 305 fatal("dnskey '%s' failed to sign data: %s", keystr, 306 isc_result_totext(result)); 307 } 308 INCSTAT(nsigned); 309 310 if (tryverify) { 311 result = dns_dnssec_verify(name, rdataset, key, true, 0, mctx, 312 &trdata, NULL); 313 if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) { 314 vbprintf(3, "\tsignature verified\n"); 315 INCSTAT(nverified); 316 } else { 317 vbprintf(3, "\tsignature failed to verify\n"); 318 INCSTAT(nverifyfailed); 319 } 320 } 321 322 tuple = NULL; 323 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name, ttl, 324 &trdata, &tuple); 325 check_result(result, "dns_difftuple_create"); 326 dns_diff_append(add, &tuple); 327 } 328 329 static bool 330 issigningkey(dns_dnsseckey_t *key) { 331 return key->force_sign || key->hint_sign; 332 } 333 334 static bool 335 ispublishedkey(dns_dnsseckey_t *key) { 336 return (key->force_publish || key->hint_publish) && !key->hint_remove; 337 } 338 339 static bool 340 iszonekey(dns_dnsseckey_t *key) { 341 return dns_name_equal(dst_key_name(key->key), gorigin) && 342 dst_key_iszonekey(key->key); 343 } 344 345 static bool 346 isksk(dns_dnsseckey_t *key) { 347 return key->ksk; 348 } 349 350 static bool 351 iszsk(dns_dnsseckey_t *key) { 352 return ignore_kskflag || !key->ksk; 353 } 354 355 /*% 356 * Find the key that generated an RRSIG, if it is in the key list. If 357 * so, return a pointer to it, otherwise return NULL. 358 * 359 * No locking is performed here, this must be done by the caller. 360 */ 361 static dns_dnsseckey_t * 362 keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) { 363 dns_dnsseckey_t *key; 364 365 for (key = ISC_LIST_HEAD(keylist); key != NULL; 366 key = ISC_LIST_NEXT(key, link)) 367 { 368 if (rrsig->keyid == dst_key_id(key->key) && 369 rrsig->algorithm == dst_key_alg(key->key) && 370 dns_name_equal(&rrsig->signer, dst_key_name(key->key))) 371 { 372 return key; 373 } 374 } 375 return NULL; 376 } 377 378 /*% 379 * Finds the key that generated a RRSIG, if possible. First look at the keys 380 * that we've loaded already, and then see if there's a key on disk. 381 */ 382 static dns_dnsseckey_t * 383 keythatsigned(dns_rdata_rrsig_t *rrsig) { 384 isc_result_t result; 385 dst_key_t *pubkey = NULL, *privkey = NULL; 386 dns_dnsseckey_t *key = NULL; 387 388 RWLOCK(&keylist_lock, isc_rwlocktype_read); 389 key = keythatsigned_unlocked(rrsig); 390 RWUNLOCK(&keylist_lock, isc_rwlocktype_read); 391 if (key != NULL) { 392 return key; 393 } 394 395 /* 396 * We did not find the key in our list. Get a write lock now, since 397 * we may be modifying the bits. We could do the tryupgrade() dance, 398 * but instead just get a write lock and check once again to see if 399 * it is on our list. It's possible someone else may have added it 400 * after all. 401 */ 402 isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write); 403 key = keythatsigned_unlocked(rrsig); 404 if (key != NULL) { 405 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write); 406 return key; 407 } 408 409 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid, 410 rrsig->algorithm, DST_TYPE_PUBLIC, directory, 411 mctx, &pubkey); 412 if (result != ISC_R_SUCCESS) { 413 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write); 414 return NULL; 415 } 416 417 result = dst_key_fromfile( 418 &rrsig->signer, rrsig->keyid, rrsig->algorithm, 419 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, directory, mctx, &privkey); 420 if (result == ISC_R_SUCCESS) { 421 dst_key_free(&pubkey); 422 dns_dnsseckey_create(mctx, &privkey, &key); 423 } else { 424 dns_dnsseckey_create(mctx, &pubkey, &key); 425 } 426 427 key->force_publish = false; 428 key->force_sign = false; 429 key->index = keycount++; 430 ISC_LIST_APPEND(keylist, key, link); 431 432 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write); 433 return key; 434 } 435 436 /*% 437 * Check to see if we expect to find a key at this name. If we see a RRSIG 438 * and can't find the signing key that we expect to find, we drop the rrsig. 439 * I'm not sure if this is completely correct, but it seems to work. 440 */ 441 static bool 442 expecttofindkey(dns_name_t *name) { 443 unsigned int options = DNS_DBFIND_NOWILD; 444 dns_fixedname_t fname; 445 isc_result_t result; 446 char namestr[DNS_NAME_FORMATSIZE]; 447 448 dns_fixedname_init(&fname); 449 result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options, 450 0, NULL, dns_fixedname_name(&fname), NULL, NULL); 451 switch (result) { 452 case ISC_R_SUCCESS: 453 case DNS_R_NXDOMAIN: 454 case DNS_R_NXRRSET: 455 return true; 456 case DNS_R_DELEGATION: 457 case DNS_R_CNAME: 458 case DNS_R_DNAME: 459 return false; 460 default: 461 break; 462 } 463 dns_name_format(name, namestr, sizeof(namestr)); 464 fatal("failure looking for '%s DNSKEY' in database: %s", namestr, 465 isc_result_totext(result)); 466 UNREACHABLE(); 467 return false; /* removes a warning */ 468 } 469 470 static bool 471 setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, 472 dns_rdata_t *rrsig) { 473 isc_result_t result; 474 result = dns_dnssec_verify(name, set, key, false, 0, mctx, rrsig, NULL); 475 if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) { 476 INCSTAT(nverified); 477 return true; 478 } else { 479 INCSTAT(nverifyfailed); 480 return false; 481 } 482 } 483 484 /*% 485 * Signs a set. Goes through contortions to decide if each RRSIG should 486 * be dropped or retained, and then determines if any new SIGs need to 487 * be generated. 488 */ 489 static void 490 signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, 491 dns_rdataset_t *set) { 492 dns_rdataset_t sigset; 493 dns_rdata_t sigrdata = DNS_RDATA_INIT; 494 dns_rdata_rrsig_t rrsig; 495 dns_dnsseckey_t *key; 496 isc_result_t result; 497 bool nosigs = false; 498 bool *wassignedby, *nowsignedby; 499 int arraysize; 500 dns_difftuple_t *tuple; 501 dns_ttl_t ttl; 502 int i; 503 char namestr[DNS_NAME_FORMATSIZE]; 504 char typestr[DNS_RDATATYPE_FORMATSIZE]; 505 char sigstr[SIG_FORMATSIZE]; 506 507 dns_name_format(name, namestr, sizeof(namestr)); 508 dns_rdatatype_format(set->type, typestr, sizeof(typestr)); 509 510 ttl = ISC_MIN(set->ttl, endtime - starttime); 511 512 dns_rdataset_init(&sigset); 513 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig, 514 set->type, 0, &sigset, NULL); 515 if (result == ISC_R_NOTFOUND) { 516 vbprintf(2, "no existing signatures for %s/%s\n", namestr, 517 typestr); 518 result = ISC_R_SUCCESS; 519 nosigs = true; 520 } 521 if (result != ISC_R_SUCCESS) { 522 fatal("failed while looking for '%s RRSIG %s': %s", namestr, 523 typestr, isc_result_totext(result)); 524 } 525 526 vbprintf(1, "%s/%s:\n", namestr, typestr); 527 528 arraysize = keycount; 529 if (!nosigs) { 530 arraysize += dns_rdataset_count(&sigset); 531 } 532 wassignedby = isc_mem_cget(mctx, arraysize, sizeof(bool)); 533 nowsignedby = isc_mem_cget(mctx, arraysize, sizeof(bool)); 534 535 for (i = 0; i < arraysize; i++) { 536 wassignedby[i] = nowsignedby[i] = false; 537 } 538 539 if (nosigs) { 540 result = ISC_R_NOMORE; 541 } else { 542 result = dns_rdataset_first(&sigset); 543 } 544 545 while (result == ISC_R_SUCCESS) { 546 bool expired, future; 547 bool keep = false, resign = false; 548 549 dns_rdataset_current(&sigset, &sigrdata); 550 551 result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL); 552 check_result(result, "dns_rdata_tostruct"); 553 554 future = isc_serial_lt(now, rrsig.timesigned); 555 556 key = keythatsigned(&rrsig); 557 sig_format(&rrsig, sigstr, sizeof(sigstr)); 558 expired = isc_serial_gt(now + cycle, rrsig.timeexpire); 559 560 if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) { 561 /* rrsig is dropped and not replaced */ 562 vbprintf(2, 563 "\trrsig by %s dropped - " 564 "invalid validity period\n", 565 sigstr); 566 } else if (key == NULL && !future && 567 expecttofindkey(&rrsig.signer)) 568 { 569 /* rrsig is dropped and not replaced */ 570 vbprintf(2, 571 "\trrsig by %s dropped - " 572 "private dnskey not found\n", 573 sigstr); 574 } else if (key == NULL || future) { 575 keep = (!expired && !remove_orphansigs); 576 vbprintf(2, "\trrsig by %s %s - dnskey not found\n", 577 keep ? "retained" : "dropped", sigstr); 578 } else if (!dns_dnssec_keyactive(key->key, now) && 579 remove_inactkeysigs) 580 { 581 keep = false; 582 vbprintf(2, "\trrsig by %s dropped - key inactive\n", 583 sigstr); 584 } else if (issigningkey(key)) { 585 wassignedby[key->index] = true; 586 587 if (!expired && rrsig.originalttl == set->ttl && 588 setverifies(name, set, key->key, &sigrdata)) 589 { 590 vbprintf(2, "\trrsig by %s retained\n", sigstr); 591 keep = true; 592 } else { 593 vbprintf(2, "\trrsig by %s dropped - %s\n", 594 sigstr, 595 expired ? "expired" 596 : rrsig.originalttl != set->ttl 597 ? "ttl change" 598 : "failed to " 599 "verify"); 600 resign = true; 601 } 602 } else if (!ispublishedkey(key) && remove_orphansigs) { 603 vbprintf(2, "\trrsig by %s dropped - dnskey removed\n", 604 sigstr); 605 } else if (iszonekey(key)) { 606 wassignedby[key->index] = true; 607 608 if (!expired && rrsig.originalttl == set->ttl && 609 setverifies(name, set, key->key, &sigrdata)) 610 { 611 vbprintf(2, "\trrsig by %s retained\n", sigstr); 612 keep = true; 613 } else { 614 vbprintf(2, "\trrsig by %s dropped - %s\n", 615 sigstr, 616 expired ? "expired" 617 : rrsig.originalttl != set->ttl 618 ? "ttl change" 619 : "failed to " 620 "verify"); 621 } 622 } else if (!expired) { 623 vbprintf(2, "\trrsig by %s retained\n", sigstr); 624 keep = true; 625 } else { 626 vbprintf(2, "\trrsig by %s expired\n", sigstr); 627 } 628 629 if (keep) { 630 if (key != NULL) { 631 nowsignedby[key->index] = true; 632 } 633 INCSTAT(nretained); 634 if (sigset.ttl != ttl) { 635 vbprintf(2, "\tfixing ttl %s\n", sigstr); 636 tuple = NULL; 637 result = dns_difftuple_create( 638 mctx, DNS_DIFFOP_DELRESIGN, name, 639 sigset.ttl, &sigrdata, &tuple); 640 check_result(result, "dns_difftuple_create"); 641 dns_diff_append(del, &tuple); 642 result = dns_difftuple_create( 643 mctx, DNS_DIFFOP_ADDRESIGN, name, ttl, 644 &sigrdata, &tuple); 645 check_result(result, "dns_difftuple_create"); 646 dns_diff_append(add, &tuple); 647 } 648 } else { 649 tuple = NULL; 650 vbprintf(2, "\tremoving signature by %s\n", sigstr); 651 result = dns_difftuple_create( 652 mctx, DNS_DIFFOP_DELRESIGN, name, sigset.ttl, 653 &sigrdata, &tuple); 654 check_result(result, "dns_difftuple_create"); 655 dns_diff_append(del, &tuple); 656 INCSTAT(ndropped); 657 } 658 659 if (resign) { 660 INSIST(!keep); 661 662 signwithkey(name, set, key->key, ttl, add, 663 "resigning with dnskey"); 664 nowsignedby[key->index] = true; 665 } 666 667 dns_rdata_reset(&sigrdata); 668 dns_rdata_freestruct(&rrsig); 669 result = dns_rdataset_next(&sigset); 670 } 671 if (result == ISC_R_NOMORE) { 672 result = ISC_R_SUCCESS; 673 } 674 675 check_result(result, "dns_rdataset_first/next"); 676 if (dns_rdataset_isassociated(&sigset)) { 677 dns_rdataset_disassociate(&sigset); 678 } 679 680 for (key = ISC_LIST_HEAD(keylist); key != NULL; 681 key = ISC_LIST_NEXT(key, link)) 682 { 683 if (nowsignedby[key->index]) { 684 continue; 685 } 686 687 if (!issigningkey(key)) { 688 continue; 689 } 690 691 if ((set->type == dns_rdatatype_cds || 692 set->type == dns_rdatatype_cdnskey || 693 set->type == dns_rdatatype_dnskey) && 694 dns_name_equal(name, gorigin)) 695 { 696 bool have_ksk; 697 dns_dnsseckey_t *curr; 698 699 have_ksk = isksk(key); 700 for (curr = ISC_LIST_HEAD(keylist); curr != NULL; 701 curr = ISC_LIST_NEXT(curr, link)) 702 { 703 if (dst_key_alg(key->key) != 704 dst_key_alg(curr->key)) 705 { 706 continue; 707 } 708 if (REVOKE(curr->key)) { 709 continue; 710 } 711 if (isksk(curr)) { 712 have_ksk = true; 713 } 714 } 715 if (isksk(key) || !have_ksk || 716 (iszsk(key) && !keyset_kskonly)) 717 { 718 signwithkey(name, set, key->key, ttl, add, 719 "signing with dnskey"); 720 } 721 } else if (iszsk(key)) { 722 /* 723 * Sign with the ZSK unless there is a predecessor 724 * key that already signs this RRset. 725 */ 726 bool have_pre_sig = false; 727 dns_dnsseckey_t *curr; 728 uint32_t pre; 729 isc_result_t ret = dst_key_getnum( 730 key->key, DST_NUM_PREDECESSOR, &pre); 731 if (ret == ISC_R_SUCCESS) { 732 /* 733 * This key has a predecessor, look for the 734 * corresponding key in the keylist. The 735 * key we are looking for must be: 736 * - From the same cryptographic algorithm. 737 * - Have the ZSK type (iszsk). 738 * - Have key ID equal to the predecessor id. 739 * - Have a successor that matches 'key' id. 740 */ 741 for (curr = ISC_LIST_HEAD(keylist); 742 curr != NULL; 743 curr = ISC_LIST_NEXT(curr, link)) 744 { 745 uint32_t suc; 746 747 if (dst_key_alg(key->key) != 748 dst_key_alg(curr->key) || 749 !iszsk(curr) || 750 dst_key_id(curr->key) != pre) 751 { 752 continue; 753 } 754 ret = dst_key_getnum(curr->key, 755 DST_NUM_SUCCESSOR, 756 &suc); 757 if (ret != ISC_R_SUCCESS || 758 dst_key_id(key->key) != suc) 759 { 760 continue; 761 } 762 763 /* 764 * curr is the predecessor we were 765 * looking for. Check if this key 766 * signs this RRset. 767 */ 768 if (nowsignedby[curr->index]) { 769 have_pre_sig = true; 770 } 771 } 772 } 773 774 /* 775 * If we have a signature of a predecessor key, 776 * skip signing with this key. 777 */ 778 if (!have_pre_sig) { 779 signwithkey(name, set, key->key, ttl, add, 780 "signing with dnskey"); 781 } 782 } 783 } 784 785 isc_mem_cput(mctx, wassignedby, arraysize, sizeof(bool)); 786 isc_mem_cput(mctx, nowsignedby, arraysize, sizeof(bool)); 787 } 788 789 struct hashlist { 790 unsigned char *hashbuf; 791 size_t entries; 792 size_t size; 793 size_t length; 794 }; 795 796 static void 797 hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) { 798 l->entries = 0; 799 l->length = length + 1; 800 801 if (nodes != 0) { 802 l->size = nodes; 803 l->hashbuf = malloc(l->size * l->length); 804 if (l->hashbuf == NULL) { 805 l->size = 0; 806 } 807 } else { 808 l->size = 0; 809 l->hashbuf = NULL; 810 } 811 } 812 813 static void 814 hashlist_free(hashlist_t *l) { 815 if (l->hashbuf) { 816 free(l->hashbuf); 817 l->hashbuf = NULL; 818 l->entries = 0; 819 l->length = 0; 820 l->size = 0; 821 } 822 } 823 824 static void 825 hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len) { 826 REQUIRE(len <= l->length); 827 828 if (l->entries == l->size) { 829 l->size = l->size * 2 + 100; 830 l->hashbuf = realloc(l->hashbuf, l->size * l->length); 831 if (l->hashbuf == NULL) { 832 fatal("unable to grow hashlist: out of memory"); 833 } 834 } 835 memset(l->hashbuf + l->entries * l->length, 0, l->length); 836 memmove(l->hashbuf + l->entries * l->length, hash, len); 837 l->entries++; 838 } 839 840 static void 841 hashlist_add_dns_name(hashlist_t *l, 842 /*const*/ dns_name_t *name, unsigned int hashalg, 843 unsigned int iterations, const unsigned char *salt, 844 size_t salt_len, bool speculative) { 845 char nametext[DNS_NAME_FORMATSIZE]; 846 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1]; 847 unsigned int len; 848 size_t i; 849 850 len = isc_iterated_hash(hash, hashalg, iterations, salt, (int)salt_len, 851 name->ndata, name->length); 852 if (verbose) { 853 dns_name_format(name, nametext, sizeof nametext); 854 for (i = 0; i < len; i++) { 855 fprintf(stderr, "%02x", hash[i]); 856 } 857 fprintf(stderr, " %s\n", nametext); 858 } 859 hash[len++] = speculative ? 1 : 0; 860 hashlist_add(l, hash, len); 861 } 862 863 static int 864 hashlist_comp(const void *a, const void *b) { 865 return memcmp(a, b, hash_length + 1); 866 } 867 868 static void 869 hashlist_sort(hashlist_t *l) { 870 INSIST(l->hashbuf != NULL || l->length == 0); 871 if (l->length > 0) { 872 qsort(l->hashbuf, l->entries, l->length, hashlist_comp); 873 } 874 } 875 876 static bool 877 hashlist_hasdup(hashlist_t *l) { 878 unsigned char *current; 879 unsigned char *next = l->hashbuf; 880 size_t entries = l->entries; 881 882 /* 883 * Skip initial speculative wild card hashes. 884 */ 885 while (entries > 0U && next[l->length - 1] != 0U) { 886 next += l->length; 887 entries--; 888 } 889 890 current = next; 891 while (entries-- > 1U) { 892 next += l->length; 893 if (next[l->length - 1] != 0) { 894 continue; 895 } 896 if (isc_safe_memequal(current, next, l->length - 1)) { 897 return true; 898 } 899 current = next; 900 } 901 return false; 902 } 903 904 static const unsigned char * 905 hashlist_findnext(const hashlist_t *l, 906 const unsigned char hash[NSEC3_MAX_HASH_LENGTH]) { 907 size_t entries = l->entries; 908 const unsigned char *next = bsearch(hash, l->hashbuf, l->entries, 909 l->length, hashlist_comp); 910 INSIST(next != NULL); 911 912 do { 913 if (next < l->hashbuf + (l->entries - 1) * l->length) { 914 next += l->length; 915 } else { 916 next = l->hashbuf; 917 } 918 if (next[l->length - 1] == 0) { 919 break; 920 } 921 } while (entries-- > 1U); 922 INSIST(entries != 0U); 923 return next; 924 } 925 926 static bool 927 hashlist_exists(const hashlist_t *l, 928 const unsigned char hash[NSEC3_MAX_HASH_LENGTH]) { 929 if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp)) { 930 return true; 931 } else { 932 return false; 933 } 934 } 935 936 static void 937 addnowildcardhash(hashlist_t *l, 938 /*const*/ dns_name_t *name, unsigned int hashalg, 939 unsigned int iterations, const unsigned char *salt, 940 size_t salt_len) { 941 dns_fixedname_t fixed; 942 dns_name_t *wild; 943 dns_dbnode_t *node = NULL; 944 isc_result_t result; 945 char namestr[DNS_NAME_FORMATSIZE]; 946 947 wild = dns_fixedname_initname(&fixed); 948 949 result = dns_name_concatenate(dns_wildcardname, name, wild, NULL); 950 if (result == ISC_R_NOSPACE) { 951 return; 952 } 953 check_result(result, "addnowildcardhash: dns_name_concatenate()"); 954 955 result = dns_db_findnode(gdb, wild, false, &node); 956 if (result == ISC_R_SUCCESS) { 957 dns_db_detachnode(gdb, &node); 958 return; 959 } 960 961 if (verbose) { 962 dns_name_format(wild, namestr, sizeof(namestr)); 963 fprintf(stderr, "adding no-wildcardhash for %s\n", namestr); 964 } 965 966 hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_len, 967 true); 968 } 969 970 static void 971 opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass, 972 dns_db_t **dbp) { 973 char filename[PATH_MAX]; 974 isc_buffer_t b; 975 isc_result_t result; 976 977 isc_buffer_init(&b, filename, sizeof(filename)); 978 if (dsdir != NULL) { 979 /* allow room for a trailing slash */ 980 if (strlen(dsdir) >= isc_buffer_availablelength(&b)) { 981 fatal("path '%s' is too long", dsdir); 982 } 983 isc_buffer_putstr(&b, dsdir); 984 if (dsdir[strlen(dsdir) - 1] != '/') { 985 isc_buffer_putstr(&b, "/"); 986 } 987 } 988 if (strlen(prefix) > isc_buffer_availablelength(&b)) { 989 fatal("path '%s' is too long", dsdir); 990 } 991 isc_buffer_putstr(&b, prefix); 992 result = dns_name_tofilenametext(name, false, &b); 993 check_result(result, "dns_name_tofilenametext()"); 994 if (isc_buffer_availablelength(&b) == 0) { 995 char namestr[DNS_NAME_FORMATSIZE]; 996 dns_name_format(name, namestr, sizeof(namestr)); 997 fatal("name '%s' is too long", namestr); 998 } 999 isc_buffer_putuint8(&b, 0); 1000 1001 result = dns_db_create(mctx, ZONEDB_DEFAULT, dns_rootname, 1002 dns_dbtype_zone, rdclass, 0, NULL, dbp); 1003 check_result(result, "dns_db_create()"); 1004 1005 result = dns_db_load(*dbp, filename, inputformat, DNS_MASTER_HINT); 1006 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) { 1007 dns_db_detach(dbp); 1008 } 1009 } 1010 1011 /*% 1012 * Load the DS set for a child zone, if a dsset-* file can be found. 1013 * If not, try to find a keyset-* file from an earlier version of 1014 * dnssec-signzone, and build DS records from that. 1015 */ 1016 static isc_result_t 1017 loadds(dns_name_t *name, uint32_t ttl, dns_rdataset_t *dsset) { 1018 dns_db_t *db = NULL; 1019 dns_dbversion_t *ver = NULL; 1020 dns_dbnode_t *node = NULL; 1021 isc_result_t result; 1022 dns_rdataset_t keyset; 1023 dns_rdata_t key, ds; 1024 unsigned char dsbuf[DNS_DS_BUFFERSIZE]; 1025 dns_diff_t diff; 1026 dns_difftuple_t *tuple = NULL; 1027 1028 opendb("dsset-", name, gclass, &db); 1029 if (db != NULL) { 1030 result = dns_db_findnode(db, name, false, &node); 1031 if (result == ISC_R_SUCCESS) { 1032 dns_rdataset_init(dsset); 1033 result = dns_db_findrdataset(db, node, NULL, 1034 dns_rdatatype_ds, 0, 0, 1035 dsset, NULL); 1036 dns_db_detachnode(db, &node); 1037 if (result == ISC_R_SUCCESS) { 1038 vbprintf(2, "found DS records\n"); 1039 dsset->ttl = ttl; 1040 dns_db_detach(&db); 1041 return result; 1042 } 1043 } 1044 dns_db_detach(&db); 1045 } 1046 1047 /* No DS records found; try again, looking for DNSKEY records */ 1048 opendb("keyset-", name, gclass, &db); 1049 if (db == NULL) { 1050 return ISC_R_NOTFOUND; 1051 } 1052 1053 result = dns_db_findnode(db, name, false, &node); 1054 if (result != ISC_R_SUCCESS) { 1055 dns_db_detach(&db); 1056 return result; 1057 } 1058 1059 dns_rdataset_init(&keyset); 1060 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0, 1061 &keyset, NULL); 1062 if (result != ISC_R_SUCCESS) { 1063 dns_db_detachnode(db, &node); 1064 dns_db_detach(&db); 1065 return result; 1066 } 1067 vbprintf(2, "found DNSKEY records\n"); 1068 1069 result = dns_db_newversion(db, &ver); 1070 check_result(result, "dns_db_newversion"); 1071 dns_diff_init(mctx, &diff); 1072 1073 for (result = dns_rdataset_first(&keyset); result == ISC_R_SUCCESS; 1074 result = dns_rdataset_next(&keyset)) 1075 { 1076 dns_rdata_init(&key); 1077 dns_rdata_init(&ds); 1078 dns_rdataset_current(&keyset, &key); 1079 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256, 1080 dsbuf, &ds); 1081 check_result(result, "dns_ds_buildrdata"); 1082 1083 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name, 1084 ttl, &ds, &tuple); 1085 check_result(result, "dns_difftuple_create"); 1086 dns_diff_append(&diff, &tuple); 1087 } 1088 1089 result = dns_diff_apply(&diff, db, ver); 1090 check_result(result, "dns_diff_apply"); 1091 dns_diff_clear(&diff); 1092 1093 dns_db_closeversion(db, &ver, true); 1094 1095 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0, 1096 dsset, NULL); 1097 check_result(result, "dns_db_findrdataset"); 1098 1099 dns_rdataset_disassociate(&keyset); 1100 dns_db_detachnode(db, &node); 1101 dns_db_detach(&db); 1102 return result; 1103 } 1104 1105 static bool 1106 secure(dns_name_t *name, dns_dbnode_t *node) { 1107 dns_rdataset_t dsset; 1108 isc_result_t result; 1109 1110 if (dns_name_equal(name, gorigin)) { 1111 return false; 1112 } 1113 1114 dns_rdataset_init(&dsset); 1115 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds, 0, 1116 0, &dsset, NULL); 1117 if (dns_rdataset_isassociated(&dsset)) { 1118 dns_rdataset_disassociate(&dsset); 1119 } 1120 1121 return result == ISC_R_SUCCESS; 1122 } 1123 1124 static bool 1125 is_delegation(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, 1126 dns_name_t *name, dns_dbnode_t *node, uint32_t *ttlp) { 1127 dns_rdataset_t nsset; 1128 isc_result_t result; 1129 1130 if (dns_name_equal(name, origin)) { 1131 return false; 1132 } 1133 1134 dns_rdataset_init(&nsset); 1135 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_ns, 0, 0, 1136 &nsset, NULL); 1137 if (dns_rdataset_isassociated(&nsset)) { 1138 if (ttlp != NULL) { 1139 *ttlp = nsset.ttl; 1140 } 1141 dns_rdataset_disassociate(&nsset); 1142 } 1143 1144 return result == ISC_R_SUCCESS; 1145 } 1146 1147 /*% 1148 * Return true if version 'ver' of database 'db' contains a DNAME RRset at 1149 * 'node'; return false otherwise. 1150 */ 1151 static bool 1152 has_dname(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node) { 1153 dns_rdataset_t dnameset; 1154 isc_result_t result; 1155 1156 dns_rdataset_init(&dnameset); 1157 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dname, 0, 0, 1158 &dnameset, NULL); 1159 if (dns_rdataset_isassociated(&dnameset)) { 1160 dns_rdataset_disassociate(&dnameset); 1161 } 1162 1163 return result == ISC_R_SUCCESS; 1164 } 1165 1166 /*% 1167 * Signs all records at a name. 1168 */ 1169 static void 1170 signname(dns_dbnode_t *node, bool apex, dns_name_t *name) { 1171 isc_result_t result; 1172 dns_rdataset_t rdataset; 1173 dns_rdatasetiter_t *rdsiter; 1174 bool isdelegation = false; 1175 dns_diff_t del, add; 1176 char namestr[DNS_NAME_FORMATSIZE]; 1177 1178 dns_rdataset_init(&rdataset); 1179 dns_name_format(name, namestr, sizeof(namestr)); 1180 1181 /* 1182 * Determine if this is a delegation point. 1183 */ 1184 if (is_delegation(gdb, gversion, gorigin, name, node, NULL)) { 1185 isdelegation = true; 1186 } 1187 1188 /* 1189 * Now iterate through the rdatasets. 1190 */ 1191 dns_diff_init(mctx, &del); 1192 dns_diff_init(mctx, &add); 1193 rdsiter = NULL; 1194 result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &rdsiter); 1195 check_result(result, "dns_db_allrdatasets()"); 1196 result = dns_rdatasetiter_first(rdsiter); 1197 while (result == ISC_R_SUCCESS) { 1198 dns_rdatasetiter_current(rdsiter, &rdataset); 1199 1200 /* If this is a RRSIG set, skip it. */ 1201 if (rdataset.type == dns_rdatatype_rrsig) { 1202 goto skip; 1203 } 1204 1205 /* 1206 * If this name is a delegation point, skip all records 1207 * except NSEC and DS sets. Otherwise check that there 1208 * isn't a DS record. 1209 */ 1210 if (isdelegation) { 1211 if (rdataset.type != nsec_datatype && 1212 rdataset.type != dns_rdatatype_ds) 1213 { 1214 goto skip; 1215 } 1216 } else if (rdataset.type == dns_rdatatype_ds) { 1217 char namebuf[DNS_NAME_FORMATSIZE]; 1218 dns_name_format(name, namebuf, sizeof(namebuf)); 1219 fatal("'%s': found DS RRset without NS RRset\n", 1220 namebuf); 1221 } else if (rdataset.type == dns_rdatatype_dnskey && !apex) { 1222 char namebuf[DNS_NAME_FORMATSIZE]; 1223 dns_name_format(name, namebuf, sizeof(namebuf)); 1224 fatal("'%s': Non-apex DNSKEY RRset\n", namebuf); 1225 } 1226 1227 signset(&del, &add, node, name, &rdataset); 1228 1229 skip: 1230 dns_rdataset_disassociate(&rdataset); 1231 result = dns_rdatasetiter_next(rdsiter); 1232 } 1233 if (result != ISC_R_NOMORE) { 1234 fatal("rdataset iteration for name '%s' failed: %s", namestr, 1235 isc_result_totext(result)); 1236 } 1237 1238 dns_rdatasetiter_destroy(&rdsiter); 1239 1240 result = dns_diff_applysilently(&del, gdb, gversion); 1241 if (result != ISC_R_SUCCESS) { 1242 fatal("failed to delete SIGs at node '%s': %s", namestr, 1243 isc_result_totext(result)); 1244 } 1245 1246 result = dns_diff_applysilently(&add, gdb, gversion); 1247 if (result != ISC_R_SUCCESS) { 1248 fatal("failed to add SIGs at node '%s': %s", namestr, 1249 isc_result_totext(result)); 1250 } 1251 1252 dns_diff_clear(&del); 1253 dns_diff_clear(&add); 1254 } 1255 1256 /* 1257 * See if the node contains any non RRSIG/NSEC records and report to 1258 * caller. Clean out extraneous RRSIG records for node. 1259 */ 1260 static bool 1261 active_node(dns_dbnode_t *node) { 1262 dns_rdatasetiter_t *rdsiter = NULL; 1263 dns_rdatasetiter_t *rdsiter2 = NULL; 1264 bool active = false; 1265 isc_result_t result; 1266 dns_rdataset_t rdataset; 1267 dns_rdatatype_t type; 1268 dns_rdatatype_t covers; 1269 bool found; 1270 1271 dns_rdataset_init(&rdataset); 1272 result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &rdsiter); 1273 check_result(result, "dns_db_allrdatasets()"); 1274 result = dns_rdatasetiter_first(rdsiter); 1275 while (result == ISC_R_SUCCESS) { 1276 dns_rdatasetiter_current(rdsiter, &rdataset); 1277 if (rdataset.type != dns_rdatatype_nsec && 1278 rdataset.type != dns_rdatatype_nsec3 && 1279 rdataset.type != dns_rdatatype_rrsig) 1280 { 1281 active = true; 1282 } 1283 dns_rdataset_disassociate(&rdataset); 1284 if (!active) { 1285 result = dns_rdatasetiter_next(rdsiter); 1286 } else { 1287 result = ISC_R_NOMORE; 1288 } 1289 } 1290 if (result != ISC_R_NOMORE) { 1291 fatal("rdataset iteration failed: %s", 1292 isc_result_totext(result)); 1293 } 1294 1295 if (!active && nsec_datatype == dns_rdatatype_nsec) { 1296 /*% 1297 * The node is empty of everything but NSEC / RRSIG records. 1298 */ 1299 for (result = dns_rdatasetiter_first(rdsiter); 1300 result == ISC_R_SUCCESS; 1301 result = dns_rdatasetiter_next(rdsiter)) 1302 { 1303 dns_rdatasetiter_current(rdsiter, &rdataset); 1304 result = dns_db_deleterdataset(gdb, node, gversion, 1305 rdataset.type, 1306 rdataset.covers); 1307 check_result(result, "dns_db_deleterdataset()"); 1308 dns_rdataset_disassociate(&rdataset); 1309 } 1310 if (result != ISC_R_NOMORE) { 1311 fatal("rdataset iteration failed: %s", 1312 isc_result_totext(result)); 1313 } 1314 } else { 1315 /* 1316 * Delete RRSIGs for types that no longer exist. 1317 */ 1318 result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, 1319 &rdsiter2); 1320 check_result(result, "dns_db_allrdatasets()"); 1321 for (result = dns_rdatasetiter_first(rdsiter); 1322 result == ISC_R_SUCCESS; 1323 result = dns_rdatasetiter_next(rdsiter)) 1324 { 1325 dns_rdatasetiter_current(rdsiter, &rdataset); 1326 type = rdataset.type; 1327 covers = rdataset.covers; 1328 dns_rdataset_disassociate(&rdataset); 1329 /* 1330 * Delete the NSEC chain if we are signing with 1331 * NSEC3. 1332 */ 1333 if (nsec_datatype == dns_rdatatype_nsec3 && 1334 (type == dns_rdatatype_nsec || 1335 covers == dns_rdatatype_nsec)) 1336 { 1337 result = dns_db_deleterdataset( 1338 gdb, node, gversion, type, covers); 1339 check_result(result, "dns_db_deleterdataset(" 1340 "nsec/rrsig)"); 1341 continue; 1342 } 1343 if (type != dns_rdatatype_rrsig) { 1344 continue; 1345 } 1346 found = false; 1347 for (result = dns_rdatasetiter_first(rdsiter2); 1348 !found && result == ISC_R_SUCCESS; 1349 result = dns_rdatasetiter_next(rdsiter2)) 1350 { 1351 dns_rdatasetiter_current(rdsiter2, &rdataset); 1352 if (rdataset.type == covers) { 1353 found = true; 1354 } 1355 dns_rdataset_disassociate(&rdataset); 1356 } 1357 if (!found) { 1358 if (result != ISC_R_NOMORE) { 1359 fatal("rdataset iteration failed: %s", 1360 isc_result_totext(result)); 1361 } 1362 result = dns_db_deleterdataset( 1363 gdb, node, gversion, type, covers); 1364 check_result(result, "dns_db_deleterdataset(" 1365 "rrsig)"); 1366 } else if (result != ISC_R_NOMORE && 1367 result != ISC_R_SUCCESS) 1368 { 1369 fatal("rdataset iteration failed: %s", 1370 isc_result_totext(result)); 1371 } 1372 } 1373 if (result != ISC_R_NOMORE) { 1374 fatal("rdataset iteration failed: %s", 1375 isc_result_totext(result)); 1376 } 1377 dns_rdatasetiter_destroy(&rdsiter2); 1378 } 1379 dns_rdatasetiter_destroy(&rdsiter); 1380 1381 return active; 1382 } 1383 1384 /*% 1385 * Extracts the minimum TTL from the SOA record, and the SOA record's TTL. 1386 */ 1387 static void 1388 get_soa_ttls(void) { 1389 dns_rdataset_t soaset; 1390 dns_fixedname_t fname; 1391 dns_name_t *name; 1392 isc_result_t result; 1393 dns_rdata_t rdata = DNS_RDATA_INIT; 1394 1395 name = dns_fixedname_initname(&fname); 1396 dns_rdataset_init(&soaset); 1397 result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa, 0, 0, 1398 NULL, name, &soaset, NULL); 1399 if (result != ISC_R_SUCCESS) { 1400 fatal("failed to find an SOA at the zone apex: %s", 1401 isc_result_totext(result)); 1402 } 1403 1404 result = dns_rdataset_first(&soaset); 1405 check_result(result, "dns_rdataset_first"); 1406 dns_rdataset_current(&soaset, &rdata); 1407 soa_ttl = soaset.ttl; 1408 zone_soa_min_ttl = ISC_MIN(dns_soa_getminimum(&rdata), soa_ttl); 1409 if (set_maxttl) { 1410 zone_soa_min_ttl = ISC_MIN(zone_soa_min_ttl, maxttl); 1411 soa_ttl = ISC_MIN(soa_ttl, maxttl); 1412 } 1413 dns_rdataset_disassociate(&soaset); 1414 } 1415 1416 /*% 1417 * Increment (or set if nonzero) the SOA serial 1418 */ 1419 static isc_result_t 1420 setsoaserial(uint32_t serial, dns_updatemethod_t method) { 1421 isc_result_t result; 1422 dns_dbnode_t *node = NULL; 1423 dns_rdataset_t rdataset; 1424 dns_rdata_t rdata = DNS_RDATA_INIT; 1425 uint32_t old_serial, new_serial = 0; 1426 dns_updatemethod_t used = dns_updatemethod_none; 1427 1428 result = dns_db_getoriginnode(gdb, &node); 1429 if (result != ISC_R_SUCCESS) { 1430 return result; 1431 } 1432 1433 dns_rdataset_init(&rdataset); 1434 1435 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_soa, 0, 1436 0, &rdataset, NULL); 1437 if (result != ISC_R_SUCCESS) { 1438 goto cleanup; 1439 } 1440 1441 result = dns_rdataset_first(&rdataset); 1442 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1443 1444 dns_rdataset_current(&rdataset, &rdata); 1445 1446 old_serial = dns_soa_getserial(&rdata); 1447 1448 if (method == dns_updatemethod_date || 1449 method == dns_updatemethod_unixtime) 1450 { 1451 new_serial = dns_update_soaserial(old_serial, method, &used); 1452 } else if (serial != 0 || method == dns_updatemethod_none) { 1453 /* Set SOA serial to the value provided. */ 1454 new_serial = serial; 1455 used = method; 1456 } else { 1457 new_serial = dns_update_soaserial(old_serial, method, &used); 1458 } 1459 1460 if (method != used) { 1461 fprintf(stderr, 1462 "%s: warning: Serial number would not advance, " 1463 "using increment method instead\n", 1464 program); 1465 } 1466 1467 /* If the new serial is not likely to cause a zone transfer 1468 * (a/ixfr) from servers having the old serial, warn the user. 1469 * 1470 * RFC1982 section 7 defines the maximum increment to be 1471 * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single 1472 * comparison. (5 - 6 == (2^32)-1, not negative-one) 1473 */ 1474 if (new_serial == old_serial || (new_serial - old_serial) > 0x7fffffffU) 1475 { 1476 fprintf(stderr, 1477 "%s: warning: Serial number not advanced, " 1478 "zone may not transfer\n", 1479 program); 1480 } 1481 1482 dns_soa_setserial(new_serial, &rdata); 1483 1484 result = dns_db_deleterdataset(gdb, node, gversion, dns_rdatatype_soa, 1485 0); 1486 check_result(result, "dns_db_deleterdataset"); 1487 if (result != ISC_R_SUCCESS) { 1488 goto cleanup; 1489 } 1490 1491 result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset, 0, NULL); 1492 check_result(result, "dns_db_addrdataset"); 1493 if (result != ISC_R_SUCCESS) { 1494 goto cleanup; 1495 } 1496 1497 cleanup: 1498 dns_rdataset_disassociate(&rdataset); 1499 if (node != NULL) { 1500 dns_db_detachnode(gdb, &node); 1501 } 1502 dns_rdata_reset(&rdata); 1503 1504 return result; 1505 } 1506 1507 /*% 1508 * Set up the iterator and global state before starting the tasks. 1509 */ 1510 static void 1511 presign(void) { 1512 isc_result_t result; 1513 1514 gdbiter = NULL; 1515 result = dns_db_createiterator(gdb, 0, &gdbiter); 1516 check_result(result, "dns_db_createiterator()"); 1517 } 1518 1519 /*% 1520 * Clean up the iterator and global state after the tasks complete. 1521 */ 1522 static void 1523 postsign(void) { 1524 dns_dbiterator_destroy(&gdbiter); 1525 } 1526 1527 /*% 1528 * Sign the apex of the zone. 1529 * Note the origin may not be the first node if there are out of zone 1530 * records. 1531 */ 1532 static void 1533 signapex(void) { 1534 dns_dbnode_t *node = NULL; 1535 dns_fixedname_t fixed; 1536 dns_name_t *name; 1537 isc_result_t result; 1538 1539 name = dns_fixedname_initname(&fixed); 1540 result = dns_dbiterator_seek(gdbiter, gorigin); 1541 check_result(result, "dns_dbiterator_seek()"); 1542 result = dns_dbiterator_current(gdbiter, &node, name); 1543 check_dns_dbiterator_current(result); 1544 signname(node, true, name); 1545 dumpnode(name, node); 1546 dns_db_detachnode(gdb, &node); 1547 result = dns_dbiterator_first(gdbiter); 1548 if (result == ISC_R_NOMORE) { 1549 atomic_store(&finished, true); 1550 } else if (result != ISC_R_SUCCESS) { 1551 fatal("failure iterating database: %s", 1552 isc_result_totext(result)); 1553 } 1554 } 1555 1556 static void 1557 abortwork(void *arg) { 1558 UNUSED(arg); 1559 1560 atomic_store(&shuttingdown, true); 1561 } 1562 1563 /*% 1564 * Assigns a node to a worker thread. This is protected by the main task's 1565 * lock. 1566 */ 1567 static void 1568 assignwork(void *arg) { 1569 dns_fixedname_t fname; 1570 dns_name_t *name = NULL; 1571 dns_dbnode_t *node = NULL; 1572 dns_rdataset_t nsec; 1573 bool found; 1574 isc_result_t result; 1575 static dns_name_t *zonecut = NULL; /* Protected by namelock. */ 1576 static dns_fixedname_t fzonecut; /* Protected by namelock. */ 1577 static unsigned int ended = 0; /* Protected by namelock. */ 1578 1579 UNUSED(arg); 1580 1581 if (atomic_load(&shuttingdown)) { 1582 return; 1583 } 1584 1585 LOCK(&namelock); 1586 if (atomic_load(&finished)) { 1587 ended++; 1588 if (ended == nloops) { 1589 isc_loopmgr_shutdown(loopmgr); 1590 } 1591 UNLOCK(&namelock); 1592 return; 1593 } 1594 1595 name = dns_fixedname_initname(&fname); 1596 node = NULL; 1597 found = false; 1598 while (!found) { 1599 result = dns_dbiterator_current(gdbiter, &node, name); 1600 check_dns_dbiterator_current(result); 1601 /* 1602 * The origin was handled by signapex(). 1603 */ 1604 if (dns_name_equal(name, gorigin)) { 1605 dns_db_detachnode(gdb, &node); 1606 goto next; 1607 } 1608 /* 1609 * Sort the zone data from the glue and out-of-zone data. 1610 * For NSEC zones nodes with zone data have NSEC records. 1611 * For NSEC3 zones the NSEC3 nodes are zone data but 1612 * outside of the zone name space. For the rest we need 1613 * to track the bottom of zone cuts. 1614 * Nodes which don't need to be signed are dumped here. 1615 */ 1616 dns_rdataset_init(&nsec); 1617 result = dns_db_findrdataset(gdb, node, gversion, nsec_datatype, 1618 0, 0, &nsec, NULL); 1619 if (dns_rdataset_isassociated(&nsec)) { 1620 dns_rdataset_disassociate(&nsec); 1621 } 1622 if (result == ISC_R_SUCCESS) { 1623 found = true; 1624 } else if (nsec_datatype == dns_rdatatype_nsec3) { 1625 if (dns_name_issubdomain(name, gorigin) && 1626 (zonecut == NULL || 1627 !dns_name_issubdomain(name, zonecut))) 1628 { 1629 if (is_delegation(gdb, gversion, gorigin, name, 1630 node, NULL)) 1631 { 1632 zonecut = savezonecut(&fzonecut, name); 1633 if (!OPTOUT(nsec3flags) || 1634 secure(name, node)) 1635 { 1636 found = true; 1637 } 1638 } else if (has_dname(gdb, gversion, node)) { 1639 zonecut = savezonecut(&fzonecut, name); 1640 found = true; 1641 } else { 1642 found = true; 1643 } 1644 } 1645 } 1646 1647 if (!found) { 1648 dumpnode(name, node); 1649 dns_db_detachnode(gdb, &node); 1650 } 1651 1652 next: 1653 result = dns_dbiterator_next(gdbiter); 1654 if (result == ISC_R_NOMORE) { 1655 atomic_store(&finished, true); 1656 break; 1657 } else if (result != ISC_R_SUCCESS) { 1658 fatal("failure iterating database: %s", 1659 isc_result_totext(result)); 1660 } 1661 } 1662 if (!found) { 1663 ended++; 1664 if (ended == nloops) { 1665 isc_loopmgr_shutdown(loopmgr); 1666 } 1667 UNLOCK(&namelock); 1668 return; 1669 } 1670 1671 UNLOCK(&namelock); 1672 1673 signname(node, false, dns_fixedname_name(&fname)); 1674 1675 /*% 1676 * Write a node to the output file, and restart the worker task. 1677 */ 1678 lock_and_dumpnode(dns_fixedname_name(&fname), node); 1679 dns_db_detachnode(gdb, &node); 1680 1681 isc_async_current(assignwork, NULL); 1682 } 1683 1684 /*% 1685 * Update / remove the DS RRset. Preserve RRSIG(DS) if possible. 1686 */ 1687 static void 1688 add_ds(dns_name_t *name, dns_dbnode_t *node, uint32_t nsttl) { 1689 dns_rdataset_t dsset; 1690 dns_rdataset_t sigdsset; 1691 isc_result_t result; 1692 1693 dns_rdataset_init(&dsset); 1694 dns_rdataset_init(&sigdsset); 1695 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds, 0, 1696 0, &dsset, &sigdsset); 1697 if (result == ISC_R_SUCCESS) { 1698 dns_rdataset_disassociate(&dsset); 1699 result = dns_db_deleterdataset(gdb, node, gversion, 1700 dns_rdatatype_ds, 0); 1701 check_result(result, "dns_db_deleterdataset"); 1702 } 1703 1704 result = loadds(name, nsttl, &dsset); 1705 if (result == ISC_R_SUCCESS) { 1706 result = dns_db_addrdataset(gdb, node, gversion, 0, &dsset, 0, 1707 NULL); 1708 check_result(result, "dns_db_addrdataset"); 1709 dns_rdataset_disassociate(&dsset); 1710 if (dns_rdataset_isassociated(&sigdsset)) { 1711 dns_rdataset_disassociate(&sigdsset); 1712 } 1713 } else if (dns_rdataset_isassociated(&sigdsset)) { 1714 result = dns_db_deleterdataset(gdb, node, gversion, 1715 dns_rdatatype_rrsig, 1716 dns_rdatatype_ds); 1717 check_result(result, "dns_db_deleterdataset"); 1718 dns_rdataset_disassociate(&sigdsset); 1719 } 1720 } 1721 1722 /* 1723 * Remove records of the given type and their signatures. 1724 */ 1725 static void 1726 remove_records(dns_dbnode_t *node, dns_rdatatype_t which, bool checknsec) { 1727 isc_result_t result; 1728 dns_rdatatype_t type, covers; 1729 dns_rdatasetiter_t *rdsiter = NULL; 1730 dns_rdataset_t rdataset; 1731 1732 dns_rdataset_init(&rdataset); 1733 1734 /* 1735 * Delete any records of the given type at the apex. 1736 */ 1737 result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &rdsiter); 1738 check_result(result, "dns_db_allrdatasets()"); 1739 for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; 1740 result = dns_rdatasetiter_next(rdsiter)) 1741 { 1742 dns_rdatasetiter_current(rdsiter, &rdataset); 1743 type = rdataset.type; 1744 covers = rdataset.covers; 1745 dns_rdataset_disassociate(&rdataset); 1746 if (type == which || covers == which) { 1747 if (which == dns_rdatatype_nsec && checknsec && 1748 !update_chain) 1749 { 1750 fatal("Zone contains NSEC records. Use -u " 1751 "to update to NSEC3."); 1752 } 1753 if (which == dns_rdatatype_nsec3param && checknsec && 1754 !update_chain) 1755 { 1756 fatal("Zone contains NSEC3 chains. Use -u " 1757 "to update to NSEC."); 1758 } 1759 result = dns_db_deleterdataset(gdb, node, gversion, 1760 type, covers); 1761 check_result(result, "dns_db_deleterdataset()"); 1762 } 1763 } 1764 dns_rdatasetiter_destroy(&rdsiter); 1765 } 1766 1767 /* 1768 * Remove signatures covering the given type. If type == 0, 1769 * then remove all signatures, unless this is a delegation, in 1770 * which case remove all signatures except for DS or nsec_datatype 1771 */ 1772 static void 1773 remove_sigs(dns_dbnode_t *node, bool delegation, dns_rdatatype_t which) { 1774 isc_result_t result; 1775 dns_rdatatype_t type, covers; 1776 dns_rdatasetiter_t *rdsiter = NULL; 1777 dns_rdataset_t rdataset; 1778 1779 dns_rdataset_init(&rdataset); 1780 result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &rdsiter); 1781 check_result(result, "dns_db_allrdatasets()"); 1782 for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; 1783 result = dns_rdatasetiter_next(rdsiter)) 1784 { 1785 dns_rdatasetiter_current(rdsiter, &rdataset); 1786 type = rdataset.type; 1787 covers = rdataset.covers; 1788 dns_rdataset_disassociate(&rdataset); 1789 1790 if (type != dns_rdatatype_rrsig) { 1791 continue; 1792 } 1793 1794 if (which == 0 && delegation && 1795 (dns_rdatatype_atparent(covers) || 1796 (nsec_datatype == dns_rdatatype_nsec && 1797 covers == nsec_datatype))) 1798 { 1799 continue; 1800 } 1801 1802 if (which != 0 && covers != which) { 1803 continue; 1804 } 1805 1806 result = dns_db_deleterdataset(gdb, node, gversion, type, 1807 covers); 1808 check_result(result, "dns_db_deleterdataset()"); 1809 } 1810 dns_rdatasetiter_destroy(&rdsiter); 1811 } 1812 1813 /*% 1814 * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records. 1815 */ 1816 static void 1817 nsecify(void) { 1818 dns_dbiterator_t *dbiter = NULL; 1819 dns_dbnode_t *node = NULL, *nextnode = NULL; 1820 dns_fixedname_t fname, fnextname, fzonecut; 1821 dns_name_t *name, *nextname, *zonecut; 1822 dns_rdataset_t rdataset; 1823 dns_rdatasetiter_t *rdsiter = NULL; 1824 dns_rdatatype_t type, covers; 1825 bool done = false; 1826 isc_result_t result; 1827 uint32_t nsttl = 0; 1828 1829 dns_rdataset_init(&rdataset); 1830 name = dns_fixedname_initname(&fname); 1831 nextname = dns_fixedname_initname(&fnextname); 1832 zonecut = NULL; 1833 1834 /* 1835 * Remove any NSEC3 chains. 1836 */ 1837 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter); 1838 check_result(result, "dns_db_createiterator()"); 1839 for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS; 1840 result = dns_dbiterator_next(dbiter)) 1841 { 1842 result = dns_dbiterator_current(dbiter, &node, name); 1843 check_dns_dbiterator_current(result); 1844 result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, 1845 &rdsiter); 1846 check_result(result, "dns_db_allrdatasets()"); 1847 for (result = dns_rdatasetiter_first(rdsiter); 1848 result == ISC_R_SUCCESS; 1849 result = dns_rdatasetiter_next(rdsiter)) 1850 { 1851 dns_rdatasetiter_current(rdsiter, &rdataset); 1852 type = rdataset.type; 1853 covers = rdataset.covers; 1854 dns_rdataset_disassociate(&rdataset); 1855 result = dns_db_deleterdataset(gdb, node, gversion, 1856 type, covers); 1857 check_result(result, "dns_db_deleterdataset(nsec3param/" 1858 "rrsig)"); 1859 } 1860 dns_rdatasetiter_destroy(&rdsiter); 1861 dns_db_detachnode(gdb, &node); 1862 } 1863 dns_dbiterator_destroy(&dbiter); 1864 1865 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter); 1866 check_result(result, "dns_db_createiterator()"); 1867 1868 result = dns_dbiterator_first(dbiter); 1869 check_result(result, "dns_dbiterator_first()"); 1870 1871 while (!done) { 1872 result = dns_dbiterator_current(dbiter, &node, name); 1873 check_dns_dbiterator_current(result); 1874 /* 1875 * Skip out-of-zone records. 1876 */ 1877 if (!dns_name_issubdomain(name, gorigin)) { 1878 result = dns_dbiterator_next(dbiter); 1879 if (result == ISC_R_NOMORE) { 1880 done = true; 1881 } else { 1882 check_result(result, "dns_dbiterator_next()"); 1883 } 1884 dns_db_detachnode(gdb, &node); 1885 continue; 1886 } 1887 1888 if (dns_name_equal(name, gorigin)) { 1889 remove_records(node, dns_rdatatype_nsec3param, true); 1890 /* Clean old rrsigs at apex. */ 1891 (void)active_node(node); 1892 } 1893 1894 if (is_delegation(gdb, gversion, gorigin, name, node, &nsttl)) { 1895 zonecut = savezonecut(&fzonecut, name); 1896 remove_sigs(node, true, 0); 1897 if (generateds) { 1898 add_ds(name, node, nsttl); 1899 } 1900 } else if (has_dname(gdb, gversion, node)) { 1901 zonecut = savezonecut(&fzonecut, name); 1902 } 1903 1904 result = dns_dbiterator_next(dbiter); 1905 nextnode = NULL; 1906 while (result == ISC_R_SUCCESS) { 1907 bool active = false; 1908 result = dns_dbiterator_current(dbiter, &nextnode, 1909 nextname); 1910 check_dns_dbiterator_current(result); 1911 active = active_node(nextnode); 1912 if (!active) { 1913 dns_db_detachnode(gdb, &nextnode); 1914 result = dns_dbiterator_next(dbiter); 1915 continue; 1916 } 1917 if (!dns_name_issubdomain(nextname, gorigin) || 1918 (zonecut != NULL && 1919 dns_name_issubdomain(nextname, zonecut))) 1920 { 1921 remove_sigs(nextnode, false, 0); 1922 remove_records(nextnode, dns_rdatatype_nsec, 1923 false); 1924 dns_db_detachnode(gdb, &nextnode); 1925 result = dns_dbiterator_next(dbiter); 1926 continue; 1927 } 1928 dns_db_detachnode(gdb, &nextnode); 1929 break; 1930 } 1931 if (result == ISC_R_NOMORE) { 1932 dns_name_clone(gorigin, nextname); 1933 done = true; 1934 } else if (result != ISC_R_SUCCESS) { 1935 fatal("iterating through the database failed: %s", 1936 isc_result_totext(result)); 1937 } 1938 dns_dbiterator_pause(dbiter); 1939 result = dns_nsec_build(gdb, gversion, node, nextname, 1940 zone_soa_min_ttl); 1941 check_result(result, "dns_nsec_build()"); 1942 dns_db_detachnode(gdb, &node); 1943 } 1944 1945 dns_dbiterator_destroy(&dbiter); 1946 } 1947 1948 static void 1949 addnsec3param(const unsigned char *salt, size_t salt_len, 1950 dns_iterations_t iterations) { 1951 dns_dbnode_t *node = NULL; 1952 dns_rdata_nsec3param_t nsec3param; 1953 unsigned char nsec3parambuf[5 + 255]; 1954 dns_rdatalist_t rdatalist; 1955 dns_rdataset_t rdataset; 1956 dns_rdata_t rdata = DNS_RDATA_INIT; 1957 isc_buffer_t b; 1958 isc_result_t result; 1959 1960 dns_rdataset_init(&rdataset); 1961 1962 nsec3param.common.rdclass = gclass; 1963 nsec3param.common.rdtype = dns_rdatatype_nsec3param; 1964 ISC_LINK_INIT(&nsec3param.common, link); 1965 nsec3param.mctx = NULL; 1966 nsec3param.flags = 0; 1967 nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1; 1968 nsec3param.iterations = iterations; 1969 nsec3param.salt_length = (unsigned char)salt_len; 1970 nsec3param.salt = UNCONST(salt); 1971 1972 isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf)); 1973 result = dns_rdata_fromstruct(&rdata, gclass, dns_rdatatype_nsec3param, 1974 &nsec3param, &b); 1975 check_result(result, "dns_rdata_fromstruct()"); 1976 dns_rdatalist_init(&rdatalist); 1977 rdatalist.rdclass = rdata.rdclass; 1978 rdatalist.type = rdata.type; 1979 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); 1980 dns_rdatalist_tordataset(&rdatalist, &rdataset); 1981 1982 result = dns_db_findnode(gdb, gorigin, true, &node); 1983 check_result(result, "dns_db_findnode(gorigin)"); 1984 1985 /* 1986 * Delete any current NSEC3PARAM records. 1987 */ 1988 result = dns_db_deleterdataset(gdb, node, gversion, 1989 dns_rdatatype_nsec3param, 0); 1990 if (result == DNS_R_UNCHANGED) { 1991 result = ISC_R_SUCCESS; 1992 } 1993 check_result(result, "dddnsec3param: dns_db_deleterdataset()"); 1994 1995 result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset, 1996 DNS_DBADD_MERGE, NULL); 1997 if (result == DNS_R_UNCHANGED) { 1998 result = ISC_R_SUCCESS; 1999 } 2000 check_result(result, "addnsec3param: dns_db_addrdataset()"); 2001 dns_db_detachnode(gdb, &node); 2002 } 2003 2004 static void 2005 addnsec3(dns_name_t *name, dns_dbnode_t *node, const unsigned char *salt, 2006 size_t salt_len, unsigned int iterations, hashlist_t *hashlist, 2007 dns_ttl_t ttl) { 2008 unsigned char hash[NSEC3_MAX_HASH_LENGTH]; 2009 const unsigned char *nexthash; 2010 unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE]; 2011 dns_fixedname_t hashname; 2012 dns_rdatalist_t rdatalist; 2013 dns_rdataset_t rdataset; 2014 dns_rdata_t rdata = DNS_RDATA_INIT; 2015 isc_result_t result; 2016 dns_dbnode_t *nsec3node = NULL; 2017 char namebuf[DNS_NAME_FORMATSIZE]; 2018 size_t hash_len; 2019 2020 dns_name_format(name, namebuf, sizeof(namebuf)); 2021 2022 dns_fixedname_init(&hashname); 2023 dns_rdataset_init(&rdataset); 2024 2025 dns_name_downcase(name, name, NULL); 2026 result = dns_nsec3_hashname(&hashname, hash, &hash_len, name, gorigin, 2027 dns_hash_sha1, iterations, salt, salt_len); 2028 check_result(result, "addnsec3: dns_nsec3_hashname()"); 2029 nexthash = hashlist_findnext(hashlist, hash); 2030 result = dns_nsec3_buildrdata( 2031 gdb, gversion, node, 2032 unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1, nsec3flags, 2033 iterations, salt, salt_len, nexthash, ISC_SHA1_DIGESTLENGTH, 2034 nsec3buffer, &rdata); 2035 check_result(result, "addnsec3: dns_nsec3_buildrdata()"); 2036 dns_rdatalist_init(&rdatalist); 2037 rdatalist.rdclass = rdata.rdclass; 2038 rdatalist.type = rdata.type; 2039 rdatalist.ttl = ttl; 2040 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); 2041 dns_rdatalist_tordataset(&rdatalist, &rdataset); 2042 result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname), true, 2043 &nsec3node); 2044 check_result(result, "addnsec3: dns_db_findnode()"); 2045 result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset, 0, 2046 NULL); 2047 if (result == DNS_R_UNCHANGED) { 2048 result = ISC_R_SUCCESS; 2049 } 2050 check_result(result, "addnsec3: dns_db_addrdataset()"); 2051 dns_db_detachnode(gdb, &nsec3node); 2052 } 2053 2054 /*% 2055 * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list. 2056 * 2057 * Extract the hash from the first label of 'name' then see if it 2058 * is in hashlist. If 'name' is not in the hashlist then delete the 2059 * any NSEC3 records which have the same parameters as the chain we 2060 * are building. 2061 * 2062 * XXXMPA Should we also check that it of the form <hash>.<origin>? 2063 */ 2064 static void 2065 nsec3clean(dns_name_t *name, dns_dbnode_t *node, unsigned int hashalg, 2066 unsigned int iterations, const unsigned char *salt, size_t salt_len, 2067 hashlist_t *hashlist) { 2068 dns_label_t label; 2069 dns_rdata_nsec3_t nsec3; 2070 dns_rdata_t rdata, delrdata; 2071 dns_rdatalist_t rdatalist; 2072 dns_rdataset_t rdataset, delrdataset; 2073 bool delete_rrsigs = false; 2074 isc_buffer_t target; 2075 isc_result_t result; 2076 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1]; 2077 bool exists; 2078 2079 /* 2080 * Get the first label. 2081 */ 2082 dns_name_getlabel(name, 0, &label); 2083 2084 /* 2085 * We want just the label contents. 2086 */ 2087 isc_region_consume(&label, 1); 2088 2089 /* 2090 * Decode base32hex string. 2091 */ 2092 isc_buffer_init(&target, hash, sizeof(hash) - 1); 2093 result = isc_base32hex_decoderegion(&label, &target); 2094 if (result != ISC_R_SUCCESS) { 2095 return; 2096 } 2097 2098 hash[isc_buffer_usedlength(&target)] = 0; 2099 2100 exists = hashlist_exists(hashlist, hash); 2101 2102 /* 2103 * Verify that the NSEC3 parameters match the current ones 2104 * otherwise we are dealing with a different NSEC3 chain. 2105 */ 2106 dns_rdataset_init(&rdataset); 2107 dns_rdataset_init(&delrdataset); 2108 2109 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3, 2110 0, 0, &rdataset, NULL); 2111 if (result != ISC_R_SUCCESS) { 2112 return; 2113 } 2114 2115 /* 2116 * Delete any NSEC3 records which are not part of the current 2117 * NSEC3 chain. 2118 */ 2119 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; 2120 result = dns_rdataset_next(&rdataset)) 2121 { 2122 dns_rdata_init(&rdata); 2123 dns_rdataset_current(&rdataset, &rdata); 2124 result = dns_rdata_tostruct(&rdata, &nsec3, NULL); 2125 check_result(result, "dns_rdata_tostruct"); 2126 if (exists && nsec3.hash == hashalg && 2127 nsec3.iterations == iterations && 2128 nsec3.salt_length == salt_len && 2129 isc_safe_memequal(nsec3.salt, salt, salt_len)) 2130 { 2131 continue; 2132 } 2133 dns_rdatalist_init(&rdatalist); 2134 rdatalist.rdclass = rdata.rdclass; 2135 rdatalist.type = rdata.type; 2136 if (set_maxttl) { 2137 rdatalist.ttl = ISC_MIN(rdataset.ttl, maxttl); 2138 } 2139 dns_rdata_init(&delrdata); 2140 dns_rdata_clone(&rdata, &delrdata); 2141 ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link); 2142 dns_rdatalist_tordataset(&rdatalist, &delrdataset); 2143 result = dns_db_subtractrdataset(gdb, node, gversion, 2144 &delrdataset, 0, NULL); 2145 dns_rdataset_disassociate(&delrdataset); 2146 if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET) { 2147 check_result(result, "dns_db_subtractrdataset(NSEC3)"); 2148 } 2149 delete_rrsigs = true; 2150 } 2151 dns_rdataset_disassociate(&rdataset); 2152 if (result != ISC_R_NOMORE) { 2153 check_result(result, "dns_rdataset_first/next"); 2154 } 2155 2156 if (!delete_rrsigs) { 2157 return; 2158 } 2159 /* 2160 * Delete the NSEC3 RRSIGs 2161 */ 2162 result = dns_db_deleterdataset(gdb, node, gversion, dns_rdatatype_rrsig, 2163 dns_rdatatype_nsec3); 2164 if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED) { 2165 check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))"); 2166 } 2167 } 2168 2169 static void 2170 rrset_cleanup(dns_name_t *name, dns_rdataset_t *rdataset, dns_diff_t *add, 2171 dns_diff_t *del) { 2172 isc_result_t result; 2173 unsigned int count1 = 0; 2174 dns_rdataset_t tmprdataset; 2175 char namestr[DNS_NAME_FORMATSIZE]; 2176 char typestr[DNS_RDATATYPE_FORMATSIZE]; 2177 2178 dns_name_format(name, namestr, sizeof(namestr)); 2179 dns_rdatatype_format(rdataset->type, typestr, sizeof(typestr)); 2180 2181 dns_rdataset_init(&tmprdataset); 2182 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; 2183 result = dns_rdataset_next(rdataset)) 2184 { 2185 dns_rdata_t rdata1 = DNS_RDATA_INIT; 2186 unsigned int count2 = 0; 2187 2188 count1++; 2189 dns_rdataset_current(rdataset, &rdata1); 2190 dns_rdataset_clone(rdataset, &tmprdataset); 2191 for (result = dns_rdataset_first(&tmprdataset); 2192 result == ISC_R_SUCCESS; 2193 result = dns_rdataset_next(&tmprdataset)) 2194 { 2195 dns_rdata_t rdata2 = DNS_RDATA_INIT; 2196 dns_difftuple_t *tuple = NULL; 2197 count2++; 2198 dns_rdataset_current(&tmprdataset, &rdata2); 2199 if (count1 < count2 && 2200 dns_rdata_casecompare(&rdata1, &rdata2) == 0) 2201 { 2202 vbprintf(2, "removing duplicate at %s/%s\n", 2203 namestr, typestr); 2204 result = dns_difftuple_create( 2205 mctx, DNS_DIFFOP_DELRESIGN, name, 2206 rdataset->ttl, &rdata2, &tuple); 2207 check_result(result, "dns_difftuple_create"); 2208 dns_diff_append(del, &tuple); 2209 } else if (set_maxttl && rdataset->ttl > maxttl) { 2210 vbprintf(2, 2211 "reducing ttl of %s/%s " 2212 "from %d to %d\n", 2213 namestr, typestr, rdataset->ttl, 2214 maxttl); 2215 result = dns_difftuple_create( 2216 mctx, DNS_DIFFOP_DELRESIGN, name, 2217 rdataset->ttl, &rdata2, &tuple); 2218 check_result(result, "dns_difftuple_create"); 2219 dns_diff_append(del, &tuple); 2220 tuple = NULL; 2221 result = dns_difftuple_create( 2222 mctx, DNS_DIFFOP_ADDRESIGN, name, 2223 maxttl, &rdata2, &tuple); 2224 check_result(result, "dns_difftuple_create"); 2225 dns_diff_append(add, &tuple); 2226 } 2227 } 2228 dns_rdataset_disassociate(&tmprdataset); 2229 } 2230 } 2231 2232 static void 2233 cleanup_zone(void) { 2234 isc_result_t result; 2235 dns_dbiterator_t *dbiter = NULL; 2236 dns_rdatasetiter_t *rdsiter = NULL; 2237 dns_diff_t add, del; 2238 dns_dbnode_t *node = NULL; 2239 dns_rdataset_t rdataset; 2240 dns_fixedname_t fname; 2241 dns_name_t *name; 2242 2243 dns_diff_init(mctx, &add); 2244 dns_diff_init(mctx, &del); 2245 name = dns_fixedname_initname(&fname); 2246 dns_rdataset_init(&rdataset); 2247 2248 result = dns_db_createiterator(gdb, 0, &dbiter); 2249 check_result(result, "dns_db_createiterator()"); 2250 2251 for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS; 2252 result = dns_dbiterator_next(dbiter)) 2253 { 2254 result = dns_dbiterator_current(dbiter, &node, name); 2255 check_dns_dbiterator_current(result); 2256 result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, 2257 &rdsiter); 2258 check_result(result, "dns_db_allrdatasets()"); 2259 for (result = dns_rdatasetiter_first(rdsiter); 2260 result == ISC_R_SUCCESS; 2261 result = dns_rdatasetiter_next(rdsiter)) 2262 { 2263 dns_rdatasetiter_current(rdsiter, &rdataset); 2264 rrset_cleanup(name, &rdataset, &add, &del); 2265 dns_rdataset_disassociate(&rdataset); 2266 } 2267 if (result != ISC_R_NOMORE) { 2268 fatal("rdatasets iteration failed."); 2269 } 2270 dns_rdatasetiter_destroy(&rdsiter); 2271 dns_db_detachnode(gdb, &node); 2272 } 2273 if (result != ISC_R_NOMORE) { 2274 fatal("zone iteration failed."); 2275 } 2276 2277 result = dns_diff_applysilently(&del, gdb, gversion); 2278 check_result(result, "dns_diff_applysilently"); 2279 2280 result = dns_diff_applysilently(&add, gdb, gversion); 2281 check_result(result, "dns_diff_applysilently"); 2282 2283 dns_diff_clear(&del); 2284 dns_diff_clear(&add); 2285 dns_dbiterator_destroy(&dbiter); 2286 } 2287 2288 /* 2289 * Generate NSEC3 records for the zone. 2290 */ 2291 static void 2292 nsec3ify(unsigned int hashalg, dns_iterations_t iterations, 2293 const unsigned char *salt, size_t salt_len, hashlist_t *hashlist) { 2294 dns_dbiterator_t *dbiter = NULL; 2295 dns_dbnode_t *node = NULL, *nextnode = NULL; 2296 dns_fixedname_t fname, fnextname, fzonecut; 2297 dns_name_t *name, *nextname, *zonecut; 2298 dns_rdataset_t rdataset; 2299 int order; 2300 bool active; 2301 bool done = false; 2302 isc_result_t result; 2303 uint32_t nsttl = 0; 2304 unsigned int count, nlabels; 2305 2306 dns_rdataset_init(&rdataset); 2307 name = dns_fixedname_initname(&fname); 2308 nextname = dns_fixedname_initname(&fnextname); 2309 zonecut = NULL; 2310 2311 /* 2312 * Walk the zone generating the hash names. 2313 */ 2314 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter); 2315 check_result(result, "dns_db_createiterator()"); 2316 2317 result = dns_dbiterator_first(dbiter); 2318 check_result(result, "dns_dbiterator_first()"); 2319 2320 while (!done) { 2321 result = dns_dbiterator_current(dbiter, &node, name); 2322 check_dns_dbiterator_current(result); 2323 /* 2324 * Skip out-of-zone records. 2325 */ 2326 if (!dns_name_issubdomain(name, gorigin)) { 2327 result = dns_dbiterator_next(dbiter); 2328 if (result == ISC_R_NOMORE) { 2329 done = true; 2330 } else { 2331 check_result(result, "dns_dbiterator_next()"); 2332 } 2333 dns_db_detachnode(gdb, &node); 2334 continue; 2335 } 2336 2337 if (dns_name_equal(name, gorigin)) { 2338 remove_records(node, dns_rdatatype_nsec, true); 2339 /* Clean old rrsigs at apex. */ 2340 (void)active_node(node); 2341 } 2342 2343 if (has_dname(gdb, gversion, node)) { 2344 zonecut = savezonecut(&fzonecut, name); 2345 } 2346 2347 result = dns_dbiterator_next(dbiter); 2348 nextnode = NULL; 2349 while (result == ISC_R_SUCCESS) { 2350 result = dns_dbiterator_current(dbiter, &nextnode, 2351 nextname); 2352 check_dns_dbiterator_current(result); 2353 active = active_node(nextnode); 2354 if (!active) { 2355 dns_db_detachnode(gdb, &nextnode); 2356 result = dns_dbiterator_next(dbiter); 2357 continue; 2358 } 2359 if (!dns_name_issubdomain(nextname, gorigin) || 2360 (zonecut != NULL && 2361 dns_name_issubdomain(nextname, zonecut))) 2362 { 2363 remove_sigs(nextnode, false, 0); 2364 dns_db_detachnode(gdb, &nextnode); 2365 result = dns_dbiterator_next(dbiter); 2366 continue; 2367 } 2368 if (is_delegation(gdb, gversion, gorigin, nextname, 2369 nextnode, &nsttl)) 2370 { 2371 zonecut = savezonecut(&fzonecut, nextname); 2372 remove_sigs(nextnode, true, 0); 2373 if (generateds) { 2374 add_ds(nextname, nextnode, nsttl); 2375 } 2376 if (OPTOUT(nsec3flags) && 2377 !secure(nextname, nextnode)) 2378 { 2379 dns_db_detachnode(gdb, &nextnode); 2380 result = dns_dbiterator_next(dbiter); 2381 continue; 2382 } 2383 } else if (has_dname(gdb, gversion, nextnode)) { 2384 zonecut = savezonecut(&fzonecut, nextname); 2385 } 2386 dns_db_detachnode(gdb, &nextnode); 2387 break; 2388 } 2389 if (result == ISC_R_NOMORE) { 2390 dns_name_copy(gorigin, nextname); 2391 done = true; 2392 } else if (result != ISC_R_SUCCESS) { 2393 fatal("iterating through the database failed: %s", 2394 isc_result_totext(result)); 2395 } 2396 dns_name_downcase(name, name, NULL); 2397 hashlist_add_dns_name(hashlist, name, hashalg, iterations, salt, 2398 salt_len, false); 2399 dns_db_detachnode(gdb, &node); 2400 /* 2401 * Add hashes for empty nodes. Use closest encloser logic. 2402 * The closest encloser either has data or is a empty 2403 * node for another <name,nextname> span so we don't add 2404 * it here. Empty labels on nextname are within the span. 2405 */ 2406 dns_name_downcase(nextname, nextname, NULL); 2407 dns_name_fullcompare(name, nextname, &order, &nlabels); 2408 addnowildcardhash(hashlist, name, hashalg, iterations, salt, 2409 salt_len); 2410 count = dns_name_countlabels(nextname); 2411 while (count > nlabels + 1) { 2412 count--; 2413 dns_name_split(nextname, count, NULL, nextname); 2414 hashlist_add_dns_name(hashlist, nextname, hashalg, 2415 iterations, salt, salt_len, 2416 false); 2417 addnowildcardhash(hashlist, nextname, hashalg, 2418 iterations, salt, salt_len); 2419 } 2420 } 2421 dns_dbiterator_destroy(&dbiter); 2422 2423 /* 2424 * We have all the hashes now so we can sort them. 2425 */ 2426 hashlist_sort(hashlist); 2427 2428 /* 2429 * Check for duplicate hashes. If found the salt needs to 2430 * be changed. 2431 */ 2432 if (hashlist_hasdup(hashlist)) { 2433 fatal("Duplicate hash detected. Pick a different salt."); 2434 } 2435 2436 /* 2437 * Generate the nsec3 records. 2438 */ 2439 zonecut = NULL; 2440 done = false; 2441 2442 addnsec3param(salt, salt_len, iterations); 2443 2444 /* 2445 * Clean out NSEC3 records which don't match this chain. 2446 */ 2447 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter); 2448 check_result(result, "dns_db_createiterator()"); 2449 2450 for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS; 2451 result = dns_dbiterator_next(dbiter)) 2452 { 2453 result = dns_dbiterator_current(dbiter, &node, name); 2454 check_dns_dbiterator_current(result); 2455 nsec3clean(name, node, hashalg, iterations, salt, salt_len, 2456 hashlist); 2457 dns_db_detachnode(gdb, &node); 2458 } 2459 dns_dbiterator_destroy(&dbiter); 2460 2461 /* 2462 * Generate / complete the new chain. 2463 */ 2464 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter); 2465 check_result(result, "dns_db_createiterator()"); 2466 2467 result = dns_dbiterator_first(dbiter); 2468 check_result(result, "dns_dbiterator_first()"); 2469 2470 while (!done) { 2471 result = dns_dbiterator_current(dbiter, &node, name); 2472 check_dns_dbiterator_current(result); 2473 /* 2474 * Skip out-of-zone records. 2475 */ 2476 if (!dns_name_issubdomain(name, gorigin)) { 2477 result = dns_dbiterator_next(dbiter); 2478 if (result == ISC_R_NOMORE) { 2479 done = true; 2480 } else { 2481 check_result(result, "dns_dbiterator_next()"); 2482 } 2483 dns_db_detachnode(gdb, &node); 2484 continue; 2485 } 2486 2487 if (has_dname(gdb, gversion, node)) { 2488 zonecut = savezonecut(&fzonecut, name); 2489 } 2490 2491 result = dns_dbiterator_next(dbiter); 2492 nextnode = NULL; 2493 while (result == ISC_R_SUCCESS) { 2494 result = dns_dbiterator_current(dbiter, &nextnode, 2495 nextname); 2496 check_dns_dbiterator_current(result); 2497 active = active_node(nextnode); 2498 if (!active) { 2499 dns_db_detachnode(gdb, &nextnode); 2500 result = dns_dbiterator_next(dbiter); 2501 continue; 2502 } 2503 if (!dns_name_issubdomain(nextname, gorigin) || 2504 (zonecut != NULL && 2505 dns_name_issubdomain(nextname, zonecut))) 2506 { 2507 dns_db_detachnode(gdb, &nextnode); 2508 result = dns_dbiterator_next(dbiter); 2509 continue; 2510 } 2511 if (is_delegation(gdb, gversion, gorigin, nextname, 2512 nextnode, NULL)) 2513 { 2514 zonecut = savezonecut(&fzonecut, nextname); 2515 if (OPTOUT(nsec3flags) && 2516 !secure(nextname, nextnode)) 2517 { 2518 dns_db_detachnode(gdb, &nextnode); 2519 result = dns_dbiterator_next(dbiter); 2520 continue; 2521 } 2522 } else if (has_dname(gdb, gversion, nextnode)) { 2523 zonecut = savezonecut(&fzonecut, nextname); 2524 } 2525 dns_db_detachnode(gdb, &nextnode); 2526 break; 2527 } 2528 if (result == ISC_R_NOMORE) { 2529 dns_name_copy(gorigin, nextname); 2530 done = true; 2531 } else if (result != ISC_R_SUCCESS) { 2532 fatal("iterating through the database failed: %s", 2533 isc_result_totext(result)); 2534 } 2535 /* 2536 * We need to pause here to release the lock on the database. 2537 */ 2538 dns_dbiterator_pause(dbiter); 2539 addnsec3(name, node, salt, salt_len, iterations, hashlist, 2540 zone_soa_min_ttl); 2541 dns_db_detachnode(gdb, &node); 2542 /* 2543 * Add NSEC3's for empty nodes. Use closest encloser logic. 2544 */ 2545 dns_name_fullcompare(name, nextname, &order, &nlabels); 2546 count = dns_name_countlabels(nextname); 2547 while (count > nlabels + 1) { 2548 count--; 2549 dns_name_split(nextname, count, NULL, nextname); 2550 addnsec3(nextname, NULL, salt, salt_len, iterations, 2551 hashlist, zone_soa_min_ttl); 2552 } 2553 } 2554 dns_dbiterator_destroy(&dbiter); 2555 } 2556 2557 /*% 2558 * Load the zone file from disk 2559 */ 2560 static void 2561 loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) { 2562 isc_buffer_t b; 2563 int len; 2564 dns_fixedname_t fname; 2565 dns_name_t *name; 2566 isc_result_t result; 2567 2568 len = strlen(origin); 2569 isc_buffer_init(&b, origin, len); 2570 isc_buffer_add(&b, len); 2571 2572 name = dns_fixedname_initname(&fname); 2573 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); 2574 if (result != ISC_R_SUCCESS) { 2575 fatal("failed converting name '%s' to dns format: %s", origin, 2576 isc_result_totext(result)); 2577 } 2578 2579 result = dns_db_create(mctx, ZONEDB_DEFAULT, name, dns_dbtype_zone, 2580 rdclass, 0, NULL, db); 2581 check_result(result, "dns_db_create()"); 2582 2583 result = dns_db_load(*db, file, inputformat, 0); 2584 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) { 2585 fatal("failed loading zone from '%s': %s", file, 2586 isc_result_totext(result)); 2587 } 2588 } 2589 2590 /*% 2591 * Finds all public zone keys in the zone, and attempts to load the 2592 * private keys from disk. 2593 */ 2594 static void 2595 loadzonekeys(bool preserve_keys, bool load_public) { 2596 dns_dbnode_t *node; 2597 dns_dbversion_t *currentversion = NULL; 2598 isc_result_t result; 2599 dns_rdataset_t rdataset, keysigs, soasigs; 2600 2601 node = NULL; 2602 result = dns_db_findnode(gdb, gorigin, false, &node); 2603 if (result != ISC_R_SUCCESS) { 2604 fatal("failed to find the zone's origin: %s", 2605 isc_result_totext(result)); 2606 } 2607 2608 dns_db_currentversion(gdb, ¤tversion); 2609 2610 dns_rdataset_init(&rdataset); 2611 dns_rdataset_init(&soasigs); 2612 dns_rdataset_init(&keysigs); 2613 2614 /* Make note of the keys which signed the SOA, if any */ 2615 result = dns_db_findrdataset(gdb, node, currentversion, 2616 dns_rdatatype_soa, 0, 0, &rdataset, 2617 &soasigs); 2618 if (result != ISC_R_SUCCESS) { 2619 goto cleanup; 2620 } 2621 2622 /* Preserve the TTL of the DNSKEY RRset, if any */ 2623 dns_rdataset_disassociate(&rdataset); 2624 result = dns_db_findrdataset(gdb, node, currentversion, 2625 dns_rdatatype_dnskey, 0, 0, &rdataset, 2626 &keysigs); 2627 2628 if (result != ISC_R_SUCCESS) { 2629 goto cleanup; 2630 } 2631 2632 if (set_keyttl && keyttl != rdataset.ttl) { 2633 fprintf(stderr, 2634 "User-specified TTL %u conflicts " 2635 "with existing DNSKEY RRset TTL.\n", 2636 keyttl); 2637 fprintf(stderr, 2638 "Imported keys will use the RRSet " 2639 "TTL %u instead.\n", 2640 rdataset.ttl); 2641 } 2642 keyttl = rdataset.ttl; 2643 2644 /* Load keys corresponding to the existing DNSKEY RRset. */ 2645 result = dns_dnssec_keylistfromrdataset( 2646 gorigin, NULL, directory, mctx, &rdataset, &keysigs, &soasigs, 2647 preserve_keys, load_public, &keylist); 2648 if (result != ISC_R_SUCCESS) { 2649 fatal("failed to load the zone keys: %s", 2650 isc_result_totext(result)); 2651 } 2652 2653 cleanup: 2654 if (dns_rdataset_isassociated(&rdataset)) { 2655 dns_rdataset_disassociate(&rdataset); 2656 } 2657 if (dns_rdataset_isassociated(&keysigs)) { 2658 dns_rdataset_disassociate(&keysigs); 2659 } 2660 if (dns_rdataset_isassociated(&soasigs)) { 2661 dns_rdataset_disassociate(&soasigs); 2662 } 2663 dns_db_detachnode(gdb, &node); 2664 dns_db_closeversion(gdb, ¤tversion, false); 2665 } 2666 2667 static void 2668 loadexplicitkeys(char *keyfiles[], int n, bool setksk) { 2669 isc_result_t result; 2670 int i; 2671 2672 for (i = 0; i < n; i++) { 2673 dns_dnsseckey_t *key = NULL; 2674 dst_key_t *newkey = NULL; 2675 2676 result = dst_key_fromnamedfile( 2677 keyfiles[i], directory, 2678 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, mctx, &newkey); 2679 if (result != ISC_R_SUCCESS) { 2680 fatal("cannot load dnskey %s: %s", keyfiles[i], 2681 isc_result_totext(result)); 2682 } 2683 2684 if (!dns_name_equal(gorigin, dst_key_name(newkey))) { 2685 fatal("key %s not at origin\n", keyfiles[i]); 2686 } 2687 2688 if (!dst_key_isprivate(newkey)) { 2689 fatal("cannot sign zone with non-private dnskey %s", 2690 keyfiles[i]); 2691 } 2692 2693 /* Skip any duplicates */ 2694 for (key = ISC_LIST_HEAD(keylist); key != NULL; 2695 key = ISC_LIST_NEXT(key, link)) 2696 { 2697 if (dst_key_id(key->key) == dst_key_id(newkey) && 2698 dst_key_alg(key->key) == dst_key_alg(newkey)) 2699 { 2700 break; 2701 } 2702 } 2703 2704 if (key == NULL) { 2705 /* We haven't seen this key before */ 2706 dns_dnsseckey_create(mctx, &newkey, &key); 2707 ISC_LIST_APPEND(keylist, key, link); 2708 key->source = dns_keysource_user; 2709 } else { 2710 dst_key_free(&key->key); 2711 key->key = newkey; 2712 } 2713 2714 key->force_publish = true; 2715 key->force_sign = true; 2716 2717 if (setksk) { 2718 key->ksk = true; 2719 } 2720 } 2721 } 2722 2723 static void 2724 report(const char *format, ...) { 2725 if (!quiet) { 2726 FILE *out = output_stdout ? stderr : stdout; 2727 char buf[4096]; 2728 va_list args; 2729 2730 va_start(args, format); 2731 vsnprintf(buf, sizeof(buf), format, args); 2732 va_end(args); 2733 fprintf(out, "%s\n", buf); 2734 } 2735 } 2736 2737 static void 2738 clear_keylist(dns_dnsseckeylist_t *list) { 2739 dns_dnsseckey_t *key; 2740 while (!ISC_LIST_EMPTY(*list)) { 2741 key = ISC_LIST_HEAD(*list); 2742 ISC_LIST_UNLINK(*list, key, link); 2743 dns_dnsseckey_destroy(mctx, &key); 2744 } 2745 } 2746 2747 static void 2748 add_digest(char *str, size_t dlen, dns_kasp_digestlist_t *digests, 2749 bool *cdnskey) { 2750 isc_result_t result; 2751 isc_textregion_t r; 2752 dns_dsdigest_t alg; 2753 dns_kasp_digest_t *digest; 2754 2755 if (dlen == 7 && strncmp(str, "cdnskey", dlen) == 0) { 2756 *cdnskey = true; 2757 return; 2758 } 2759 2760 if (dlen < 5 || strncmp(str, "cds:", 4) != 0) { 2761 fatal("digest must specify cds:algorithm ('%.*s')", (int)dlen, 2762 str); 2763 } 2764 2765 r.base = str + 4; 2766 r.length = dlen - 4; 2767 result = dns_dsdigest_fromtext(&alg, &r); 2768 if (result == DNS_R_UNKNOWN) { 2769 fatal("bad digest '%.*s'", (int)dlen, str); 2770 } else if (result != ISC_R_SUCCESS) { 2771 fatal("bad digest '%.*s': %s", (int)dlen, str, 2772 isc_result_totext(result)); 2773 } else if (!dst_ds_digest_supported(alg)) { 2774 fatal("unsupported digest '%.*s'", (int)dlen, str); 2775 } 2776 2777 /* Suppress duplicates */ 2778 for (dns_kasp_digest_t *d = ISC_LIST_HEAD(*digests); d != NULL; 2779 d = ISC_LIST_NEXT(d, link)) 2780 { 2781 if (d->digest == alg) { 2782 return; 2783 } 2784 } 2785 2786 digest = isc_mem_get(mctx, sizeof(*digest)); 2787 digest->digest = alg; 2788 ISC_LINK_INIT(digest, link); 2789 ISC_LIST_APPEND(*digests, digest, link); 2790 } 2791 2792 static void 2793 build_final_keylist(void) { 2794 isc_result_t result; 2795 dns_dbnode_t *node = NULL; 2796 dns_dbversion_t *ver = NULL; 2797 dns_diff_t diff; 2798 dns_dnsseckeylist_t rmkeys, matchkeys; 2799 char name[DNS_NAME_FORMATSIZE]; 2800 dns_rdataset_t cdsset, cdnskeyset, soaset; 2801 dns_kasp_digestlist_t digests; 2802 dns_kasp_digest_t *d, *d_next; 2803 bool cdnskey = false; 2804 2805 ISC_LIST_INIT(rmkeys); 2806 ISC_LIST_INIT(matchkeys); 2807 ISC_LIST_INIT(digests); 2808 2809 dns_rdataset_init(&soaset); 2810 dns_rdataset_init(&cdsset); 2811 dns_rdataset_init(&cdnskeyset); 2812 2813 if (strlen(sync_records) > 0) { 2814 const char delim = ','; 2815 char *digest; 2816 char *s; 2817 size_t dlen; 2818 2819 digest = UNCONST(sync_records); 2820 next_digest: 2821 s = strchr(digest, delim); 2822 if (s == NULL) { 2823 dlen = strlen(digest); 2824 add_digest(digest, dlen, &digests, &cdnskey); 2825 goto findkeys; 2826 } 2827 dlen = s - digest; 2828 add_digest(digest, dlen, &digests, &cdnskey); 2829 digest = s + 1; 2830 goto next_digest; 2831 } 2832 2833 findkeys: 2834 /* 2835 * Find keys that match this zone in the key repository. 2836 */ 2837 result = dns_dnssec_findmatchingkeys(gorigin, NULL, directory, NULL, 2838 now, mctx, &matchkeys); 2839 if (result == ISC_R_NOTFOUND) { 2840 result = ISC_R_SUCCESS; 2841 } 2842 check_result(result, "dns_dnssec_findmatchingkeys"); 2843 2844 result = dns_db_newversion(gdb, &ver); 2845 check_result(result, "dns_db_newversion"); 2846 2847 result = dns_db_getoriginnode(gdb, &node); 2848 check_result(result, "dns_db_getoriginnode"); 2849 2850 /* Get the CDS rdataset */ 2851 result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_cds, 2852 dns_rdatatype_none, 0, &cdsset, NULL); 2853 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset)) { 2854 dns_rdataset_disassociate(&cdsset); 2855 } 2856 2857 /* Get the CDNSKEY rdataset */ 2858 result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_cdnskey, 2859 dns_rdatatype_none, 0, &cdnskeyset, NULL); 2860 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset)) { 2861 dns_rdataset_disassociate(&cdnskeyset); 2862 } 2863 2864 dns_diff_init(mctx, &diff); 2865 2866 /* 2867 * Update keylist with information from from the key repository. 2868 */ 2869 dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl, 2870 &diff, mctx, report); 2871 2872 /* 2873 * Update keylist with sync records. 2874 */ 2875 2876 dns_dnssec_syncupdate(&keylist, &rmkeys, &cdsset, &cdnskeyset, now, 2877 &digests, cdnskey, keyttl, &diff, mctx); 2878 2879 dns_name_format(gorigin, name, sizeof(name)); 2880 2881 result = dns_diff_applysilently(&diff, gdb, ver); 2882 if (result != ISC_R_SUCCESS) { 2883 fatal("failed to update DNSKEY RRset at node '%s': %s", name, 2884 isc_result_totext(result)); 2885 } 2886 2887 dns_db_detachnode(gdb, &node); 2888 dns_db_closeversion(gdb, &ver, true); 2889 2890 dns_diff_clear(&diff); 2891 2892 if (dns_rdataset_isassociated(&cdsset)) { 2893 dns_rdataset_disassociate(&cdsset); 2894 } 2895 if (dns_rdataset_isassociated(&cdnskeyset)) { 2896 dns_rdataset_disassociate(&cdnskeyset); 2897 } 2898 2899 clear_keylist(&rmkeys); 2900 clear_keylist(&matchkeys); 2901 2902 for (d = ISC_LIST_HEAD(digests); d != NULL; d = d_next) { 2903 d_next = ISC_LIST_NEXT(d, link); 2904 ISC_LIST_UNLINK(digests, d, link); 2905 isc_mem_put(mctx, d, sizeof(*d)); 2906 } 2907 INSIST(ISC_LIST_EMPTY(digests)); 2908 } 2909 2910 static void 2911 warnifallksk(dns_db_t *db) { 2912 dns_dbversion_t *currentversion = NULL; 2913 dns_dbnode_t *node = NULL; 2914 dns_rdataset_t rdataset; 2915 dns_rdata_t rdata = DNS_RDATA_INIT; 2916 isc_result_t result; 2917 dns_rdata_dnskey_t dnskey; 2918 bool have_non_ksk = false; 2919 2920 dns_db_currentversion(db, ¤tversion); 2921 2922 result = dns_db_findnode(db, gorigin, false, &node); 2923 if (result != ISC_R_SUCCESS) { 2924 fatal("failed to find the zone's origin: %s", 2925 isc_result_totext(result)); 2926 } 2927 2928 dns_rdataset_init(&rdataset); 2929 result = dns_db_findrdataset(db, node, currentversion, 2930 dns_rdatatype_dnskey, 0, 0, &rdataset, 2931 NULL); 2932 if (result != ISC_R_SUCCESS) { 2933 fatal("failed to find keys at the zone apex: %s", 2934 isc_result_totext(result)); 2935 } 2936 result = dns_rdataset_first(&rdataset); 2937 check_result(result, "dns_rdataset_first"); 2938 while (result == ISC_R_SUCCESS) { 2939 dns_rdata_reset(&rdata); 2940 dns_rdataset_current(&rdataset, &rdata); 2941 result = dns_rdata_tostruct(&rdata, &dnskey, NULL); 2942 check_result(result, "dns_rdata_tostruct"); 2943 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) { 2944 have_non_ksk = true; 2945 result = ISC_R_NOMORE; 2946 } else { 2947 result = dns_rdataset_next(&rdataset); 2948 } 2949 dns_rdata_freestruct(&dnskey); 2950 } 2951 dns_rdataset_disassociate(&rdataset); 2952 dns_db_detachnode(db, &node); 2953 dns_db_closeversion(db, ¤tversion, false); 2954 if (!have_non_ksk && !ignore_kskflag) { 2955 if (disable_zone_check) { 2956 fprintf(stderr, 2957 "%s: warning: No non-KSK DNSKEY found; " 2958 "supply a ZSK or use '-z'.\n", 2959 program); 2960 } else { 2961 fatal("No non-KSK DNSKEY found; " 2962 "supply a ZSK or use '-z'."); 2963 } 2964 } 2965 } 2966 2967 static void 2968 set_nsec3params(bool update, bool set_salt, bool set_optout, bool set_iter) { 2969 isc_result_t result; 2970 dns_dbversion_t *ver = NULL; 2971 dns_dbnode_t *node = NULL; 2972 dns_rdataset_t rdataset; 2973 dns_rdata_t rdata = DNS_RDATA_INIT; 2974 dns_rdata_nsec3_t nsec3; 2975 dns_fixedname_t fname; 2976 dns_name_t *hashname; 2977 unsigned char orig_salt[255]; 2978 size_t orig_saltlen; 2979 dns_hash_t orig_hash; 2980 uint16_t orig_iter; 2981 2982 dns_db_currentversion(gdb, &ver); 2983 dns_rdataset_init(&rdataset); 2984 2985 orig_saltlen = sizeof(orig_salt); 2986 result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL, 2987 &orig_iter, orig_salt, 2988 &orig_saltlen); 2989 if (result != ISC_R_SUCCESS) { 2990 goto cleanup; 2991 } 2992 2993 nsec_datatype = dns_rdatatype_nsec3; 2994 2995 if (!update && set_salt) { 2996 if (salt_length != orig_saltlen || 2997 !isc_safe_memequal(saltbuf, orig_salt, salt_length)) 2998 { 2999 fatal("An NSEC3 chain exists with a different salt. " 3000 "Use -u to update it."); 3001 } 3002 } else if (!set_salt) { 3003 salt_length = orig_saltlen; 3004 memmove(saltbuf, orig_salt, orig_saltlen); 3005 gsalt = saltbuf; 3006 } 3007 3008 if (!update && set_iter) { 3009 if (nsec3iter != orig_iter) { 3010 fatal("An NSEC3 chain exists with different " 3011 "iterations. Use -u to update it."); 3012 } 3013 } else if (!set_iter) { 3014 nsec3iter = orig_iter; 3015 } 3016 3017 /* 3018 * Find an NSEC3 record to get the current OPTOUT value. 3019 * (This assumes all NSEC3 records agree.) 3020 */ 3021 3022 hashname = dns_fixedname_initname(&fname); 3023 result = dns_nsec3_hashname(&fname, NULL, NULL, gorigin, gorigin, 3024 dns_hash_sha1, orig_iter, orig_salt, 3025 orig_saltlen); 3026 check_result(result, "dns_nsec3_hashname"); 3027 3028 result = dns_db_findnsec3node(gdb, hashname, false, &node); 3029 if (result != ISC_R_SUCCESS) { 3030 goto cleanup; 3031 } 3032 3033 result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3, 0, 0, 3034 &rdataset, NULL); 3035 if (result != ISC_R_SUCCESS) { 3036 goto cleanup; 3037 } 3038 3039 result = dns_rdataset_first(&rdataset); 3040 check_result(result, "dns_rdataset_first"); 3041 dns_rdataset_current(&rdataset, &rdata); 3042 result = dns_rdata_tostruct(&rdata, &nsec3, NULL); 3043 check_result(result, "dns_rdata_tostruct"); 3044 3045 if (!update && set_optout) { 3046 if (nsec3flags != nsec3.flags) { 3047 fatal("An NSEC3 chain exists with%s OPTOUT. " 3048 "Use -u -%s to %s it.", 3049 OPTOUT(nsec3.flags) ? "" : "out", 3050 OPTOUT(nsec3.flags) ? "AA" : "A", 3051 OPTOUT(nsec3.flags) ? "clear" : "set"); 3052 } 3053 } else if (!set_optout) { 3054 nsec3flags = nsec3.flags; 3055 } 3056 3057 dns_rdata_freestruct(&nsec3); 3058 3059 cleanup: 3060 if (dns_rdataset_isassociated(&rdataset)) { 3061 dns_rdataset_disassociate(&rdataset); 3062 } 3063 if (node != NULL) { 3064 dns_db_detachnode(gdb, &node); 3065 } 3066 dns_db_closeversion(gdb, &ver, false); 3067 } 3068 3069 static void 3070 writeset(const char *prefix, dns_rdatatype_t type) { 3071 char *filename; 3072 char namestr[DNS_NAME_FORMATSIZE]; 3073 dns_db_t *db = NULL; 3074 dns_dbversion_t *dbversion = NULL; 3075 dns_diff_t diff; 3076 dns_difftuple_t *tuple = NULL; 3077 dns_name_t *name; 3078 dns_rdata_t rdata, ds; 3079 bool have_ksk = false; 3080 bool have_non_ksk = false; 3081 isc_buffer_t b; 3082 isc_buffer_t namebuf; 3083 isc_region_t r; 3084 isc_result_t result; 3085 dns_dnsseckey_t *key, *curr; 3086 unsigned char dsbuf[DNS_DS_BUFFERSIZE]; 3087 unsigned char keybuf[DST_KEY_MAXSIZE]; 3088 unsigned int filenamelen; 3089 const dns_master_style_t *style = (type == dns_rdatatype_dnskey) 3090 ? masterstyle 3091 : dsstyle; 3092 3093 isc_buffer_init(&namebuf, namestr, sizeof(namestr)); 3094 result = dns_name_tofilenametext(gorigin, false, &namebuf); 3095 check_result(result, "dns_name_tofilenametext"); 3096 isc_buffer_putuint8(&namebuf, 0); 3097 filenamelen = strlen(prefix) + strlen(namestr) + 1; 3098 if (dsdir != NULL) { 3099 filenamelen += strlen(dsdir) + 1; 3100 } 3101 filename = isc_mem_get(mctx, filenamelen); 3102 if (dsdir != NULL) { 3103 snprintf(filename, filenamelen, "%s/", dsdir); 3104 } else { 3105 filename[0] = 0; 3106 } 3107 strlcat(filename, prefix, filenamelen); 3108 strlcat(filename, namestr, filenamelen); 3109 3110 dns_diff_init(mctx, &diff); 3111 3112 name = gorigin; 3113 3114 for (key = ISC_LIST_HEAD(keylist); key != NULL; 3115 key = ISC_LIST_NEXT(key, link)) 3116 { 3117 if (REVOKE(key->key)) { 3118 continue; 3119 } 3120 if (isksk(key)) { 3121 have_ksk = true; 3122 have_non_ksk = false; 3123 } else { 3124 have_ksk = false; 3125 have_non_ksk = true; 3126 } 3127 for (curr = ISC_LIST_HEAD(keylist); curr != NULL; 3128 curr = ISC_LIST_NEXT(curr, link)) 3129 { 3130 if (dst_key_alg(key->key) != dst_key_alg(curr->key)) { 3131 continue; 3132 } 3133 if (REVOKE(curr->key)) { 3134 continue; 3135 } 3136 if (isksk(curr)) { 3137 have_ksk = true; 3138 } else { 3139 have_non_ksk = true; 3140 } 3141 } 3142 if (have_ksk && have_non_ksk && !isksk(key)) { 3143 continue; 3144 } 3145 dns_rdata_init(&rdata); 3146 dns_rdata_init(&ds); 3147 isc_buffer_init(&b, keybuf, sizeof(keybuf)); 3148 result = dst_key_todns(key->key, &b); 3149 check_result(result, "dst_key_todns"); 3150 isc_buffer_usedregion(&b, &r); 3151 dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r); 3152 if (type != dns_rdatatype_dnskey) { 3153 result = dns_ds_buildrdata(gorigin, &rdata, 3154 DNS_DSDIGEST_SHA256, dsbuf, 3155 &ds); 3156 check_result(result, "dns_ds_buildrdata"); 3157 result = dns_difftuple_create(mctx, 3158 DNS_DIFFOP_ADDRESIGN, 3159 name, 0, &ds, &tuple); 3160 } else { 3161 result = dns_difftuple_create( 3162 mctx, DNS_DIFFOP_ADDRESIGN, gorigin, 3163 zone_soa_min_ttl, &rdata, &tuple); 3164 } 3165 check_result(result, "dns_difftuple_create"); 3166 dns_diff_append(&diff, &tuple); 3167 } 3168 3169 result = dns_db_create(mctx, ZONEDB_DEFAULT, dns_rootname, 3170 dns_dbtype_zone, gclass, 0, NULL, &db); 3171 check_result(result, "dns_db_create"); 3172 3173 result = dns_db_newversion(db, &dbversion); 3174 check_result(result, "dns_db_newversion"); 3175 3176 result = dns_diff_apply(&diff, db, dbversion); 3177 check_result(result, "dns_diff_apply"); 3178 dns_diff_clear(&diff); 3179 3180 result = dns_master_dump(mctx, db, dbversion, style, filename, 3181 dns_masterformat_text, NULL); 3182 check_result(result, "dns_master_dump"); 3183 3184 isc_mem_put(mctx, filename, filenamelen); 3185 3186 dns_db_closeversion(db, &dbversion, false); 3187 dns_db_detach(&db); 3188 } 3189 3190 static void 3191 print_time(FILE *fp) { 3192 time_t currenttime = time(NULL); 3193 struct tm t, *tm = localtime_r(¤ttime, &t); 3194 unsigned int flen; 3195 char timebuf[80]; 3196 3197 if (tm == NULL || outputformat != dns_masterformat_text) { 3198 return; 3199 } 3200 3201 flen = strftime(timebuf, sizeof(timebuf), "%a %b %e %H:%M:%S %Y", tm); 3202 INSIST(flen > 0U && flen < sizeof(timebuf)); 3203 fprintf(fp, "; File written on %s\n", timebuf); 3204 } 3205 3206 static void 3207 print_version(FILE *fp) { 3208 if (outputformat != dns_masterformat_text) { 3209 return; 3210 } 3211 3212 fprintf(fp, "; %s version %s\n", program, PACKAGE_VERSION); 3213 } 3214 3215 noreturn static void 3216 usage(void); 3217 3218 static void 3219 usage(void) { 3220 fprintf(stderr, "Usage:\n"); 3221 fprintf(stderr, "\t%s [options] zonefile [keys]\n", program); 3222 3223 fprintf(stderr, "\n"); 3224 3225 fprintf(stderr, "Version: %s\n", PACKAGE_VERSION); 3226 3227 fprintf(stderr, "Options: (default value in parenthesis) \n"); 3228 fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n" 3229 "\t\tfor the zone and determines how they are to " 3230 "be used\n"); 3231 fprintf(stderr, "\t-K directory:\n"); 3232 fprintf(stderr, "\t\tdirectory to find key files (.)\n"); 3233 fprintf(stderr, "\t-d directory:\n"); 3234 fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n"); 3235 fprintf(stderr, "\t-F:\tFIPS mode\n"); 3236 fprintf(stderr, "\t-g:\t"); 3237 fprintf(stderr, "update DS records based on child zones' " 3238 "dsset-* files\n"); 3239 fprintf(stderr, "\t-G sync-records:\t"); 3240 fprintf(stderr, "what CDNSKEY and CDS to publish\n"); 3241 fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n"); 3242 fprintf(stderr, "\t\tRRSIG start time " 3243 "- absolute|offset (now - 1 hour)\n"); 3244 fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n"); 3245 fprintf(stderr, "\t\tRRSIG end time " 3246 "- absolute|from start|from now " 3247 "(now + 30 days)\n"); 3248 fprintf(stderr, "\t-X [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n"); 3249 fprintf(stderr, "\t\tDNSKEY RRSIG end " 3250 "- absolute|from start|from now " 3251 "(matches -e)\n"); 3252 fprintf(stderr, "\t-i interval:\n"); 3253 fprintf(stderr, "\t\tcycle interval - resign " 3254 "if < interval from end ( (end-start)/4 )\n"); 3255 fprintf(stderr, "\t-j jitter:\n"); 3256 fprintf(stderr, "\t\trandomize signature end time up to jitter " 3257 "seconds\n"); 3258 fprintf(stderr, "\t-v debuglevel (0)\n"); 3259 fprintf(stderr, "\t-q quiet\n"); 3260 fprintf(stderr, "\t-V:\tprint version information\n"); 3261 fprintf(stderr, "\t-o origin:\n"); 3262 fprintf(stderr, "\t\tzone origin (name of zonefile)\n"); 3263 fprintf(stderr, "\t-f outfile:\n"); 3264 fprintf(stderr, "\t\tfile the signed zone is written in " 3265 "(zonefile + .signed)\n"); 3266 fprintf(stderr, "\t-I format:\n"); 3267 fprintf(stderr, "\t\tfile format of input zonefile (text)\n"); 3268 fprintf(stderr, "\t-O format:\n"); 3269 fprintf(stderr, "\t\tfile format of signed zone file (text)\n"); 3270 fprintf(stderr, "\t-N format:\n"); 3271 fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n"); 3272 fprintf(stderr, "\t-D:\n"); 3273 fprintf(stderr, "\t\toutput only DNSSEC-related records\n"); 3274 fprintf(stderr, "\t-a:\t"); 3275 fprintf(stderr, "verify generated signatures\n"); 3276 fprintf(stderr, "\t-c class (IN)\n"); 3277 fprintf(stderr, "\t-E engine:\n"); 3278 fprintf(stderr, "\t\tname of an OpenSSL engine to use\n"); 3279 fprintf(stderr, "\t-P:\t"); 3280 fprintf(stderr, "disable post-sign verification\n"); 3281 fprintf(stderr, "\t-Q:\t"); 3282 fprintf(stderr, "remove signatures from keys that are no " 3283 "longer active\n"); 3284 fprintf(stderr, "\t-R:\t"); 3285 fprintf(stderr, "remove signatures from keys that no longer exist\n"); 3286 fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n"); 3287 fprintf(stderr, "\t-t:\t"); 3288 fprintf(stderr, "print statistics\n"); 3289 fprintf(stderr, "\t-u:\t"); 3290 fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n"); 3291 fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n"); 3292 fprintf(stderr, "\t-z:\tsign all records with KSKs\n"); 3293 fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n" 3294 "\t\twith older versions of dnssec-signzone -g\n"); 3295 fprintf(stderr, "\t-n ncpus (number of cpus present)\n"); 3296 fprintf(stderr, "\t-k key_signing_key\n"); 3297 fprintf(stderr, "\t-3 NSEC3 salt\n"); 3298 fprintf(stderr, "\t-H NSEC3 iterations (10)\n"); 3299 fprintf(stderr, "\t-A NSEC3 optout\n"); 3300 3301 fprintf(stderr, "\n"); 3302 3303 fprintf(stderr, "Signing Keys: "); 3304 fprintf(stderr, "(default: all zone keys that have private keys)\n"); 3305 fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n"); 3306 3307 exit(EXIT_FAILURE); 3308 } 3309 3310 static void 3311 removetempfile(void) { 3312 if (removefile) { 3313 isc_file_remove(tempfile); 3314 } 3315 } 3316 3317 static void 3318 print_stats(isc_time_t *timer_start, isc_time_t *timer_finish, 3319 isc_time_t *sign_start, isc_time_t *sign_finish) { 3320 uint64_t time_us; /* Time in microseconds */ 3321 uint64_t time_ms; /* Time in milliseconds */ 3322 uint64_t sig_ms; /* Signatures per millisecond */ 3323 FILE *out = output_stdout ? stderr : stdout; 3324 3325 fprintf(out, "Signatures generated: %10" PRIuFAST32 "\n", 3326 atomic_load(&nsigned)); 3327 fprintf(out, "Signatures retained: %10" PRIuFAST32 "\n", 3328 atomic_load(&nretained)); 3329 fprintf(out, "Signatures dropped: %10" PRIuFAST32 "\n", 3330 atomic_load(&ndropped)); 3331 fprintf(out, "Signatures successfully verified: %10" PRIuFAST32 "\n", 3332 atomic_load(&nverified)); 3333 fprintf(out, "Signatures unsuccessfully verified: %10" PRIuFAST32 "\n", 3334 atomic_load(&nverifyfailed)); 3335 3336 time_us = isc_time_microdiff(sign_finish, sign_start); 3337 time_ms = time_us / 1000; 3338 fprintf(out, "Signing time in seconds: %7u.%03u\n", 3339 (unsigned int)(time_ms / 1000), (unsigned int)(time_ms % 1000)); 3340 if (time_us > 0) { 3341 sig_ms = ((uint64_t)atomic_load(&nsigned) * 1000000000) / 3342 time_us; 3343 fprintf(out, "Signatures per second: %7u.%03u\n", 3344 (unsigned int)sig_ms / 1000, 3345 (unsigned int)sig_ms % 1000); 3346 } 3347 3348 time_us = isc_time_microdiff(timer_finish, timer_start); 3349 time_ms = time_us / 1000; 3350 fprintf(out, "Runtime in seconds: %7u.%03u\n", 3351 (unsigned int)(time_ms / 1000), (unsigned int)(time_ms % 1000)); 3352 } 3353 3354 int 3355 main(int argc, char *argv[]) { 3356 int ch; 3357 char *startstr = NULL, *endstr = NULL, *classname = NULL; 3358 char *dnskey_endstr = NULL; 3359 char *origin = NULL, *file = NULL, *output = NULL; 3360 char *inputformatstr = NULL, *outputformatstr = NULL; 3361 char *serialformatstr = NULL; 3362 char *dskeyfile[MAXDSKEYS]; 3363 int ndskeys = 0; 3364 char *endp; 3365 isc_time_t timer_start, timer_finish; 3366 isc_time_t sign_start, sign_finish; 3367 dns_dnsseckey_t *key; 3368 isc_result_t result, vresult; 3369 isc_log_t *log = NULL; 3370 const char *engine = NULL; 3371 bool free_output = false; 3372 int tempfilelen = 0; 3373 dns_rdataclass_t rdclass; 3374 hashlist_t hashlist; 3375 bool make_keyset = false; 3376 bool set_salt = false; 3377 bool set_optout = false; 3378 bool set_iter = false; 3379 bool nonsecify = false; 3380 bool set_fips_mode = false; 3381 #if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 3382 OSSL_PROVIDER *fips = NULL, *base = NULL; 3383 #endif 3384 3385 atomic_init(&shuttingdown, false); 3386 atomic_init(&finished, false); 3387 3388 /* Unused letters: Bb G J q Yy (and F is reserved). */ 3389 #define CMDLINE_FLAGS \ 3390 "3:AaCc:Dd:E:e:f:FgG:hH:i:I:j:J:K:k:L:l:m:M:n:N:o:O:PpQqRr:s:ST:tuUv:" \ 3391 "VX:xzZ:" 3392 3393 /* 3394 * Process memory debugging argument first. 3395 */ 3396 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { 3397 switch (ch) { 3398 case 'm': 3399 if (strcasecmp(isc_commandline_argument, "record") == 0) 3400 { 3401 isc_mem_debugging |= ISC_MEM_DEBUGRECORD; 3402 } 3403 if (strcasecmp(isc_commandline_argument, "trace") == 0) 3404 { 3405 isc_mem_debugging |= ISC_MEM_DEBUGTRACE; 3406 } 3407 if (strcasecmp(isc_commandline_argument, "usage") == 0) 3408 { 3409 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; 3410 } 3411 break; 3412 default: 3413 break; 3414 } 3415 } 3416 isc_commandline_reset = true; 3417 3418 masterstyle = &dns_master_style_explicitttl; 3419 3420 isc_commandline_errprint = false; 3421 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { 3422 switch (ch) { 3423 case '3': 3424 set_salt = true; 3425 nsec_datatype = dns_rdatatype_nsec3; 3426 if (strcmp(isc_commandline_argument, "-") != 0) { 3427 isc_buffer_t target; 3428 char *sarg; 3429 3430 sarg = isc_commandline_argument; 3431 isc_buffer_init(&target, saltbuf, 3432 sizeof(saltbuf)); 3433 result = isc_hex_decodestring(sarg, &target); 3434 check_result(result, "isc_hex_decodestring(" 3435 "salt)"); 3436 salt_length = isc_buffer_usedlength(&target); 3437 } 3438 break; 3439 3440 case 'A': 3441 set_optout = true; 3442 if (OPTOUT(nsec3flags)) { 3443 nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT; 3444 } else { 3445 nsec3flags |= DNS_NSEC3FLAG_OPTOUT; 3446 } 3447 break; 3448 3449 case 'a': 3450 tryverify = true; 3451 break; 3452 3453 case 'C': 3454 make_keyset = true; 3455 break; 3456 3457 case 'c': 3458 classname = isc_commandline_argument; 3459 break; 3460 3461 case 'd': 3462 dsdir = isc_commandline_argument; 3463 if (strlen(dsdir) == 0U) { 3464 fatal("DS directory must be non-empty string"); 3465 } 3466 result = try_dir(dsdir); 3467 if (result != ISC_R_SUCCESS) { 3468 fatal("cannot open directory %s: %s", dsdir, 3469 isc_result_totext(result)); 3470 } 3471 break; 3472 3473 case 'D': 3474 output_dnssec_only = true; 3475 break; 3476 3477 case 'E': 3478 engine = isc_commandline_argument; 3479 break; 3480 3481 case 'e': 3482 endstr = isc_commandline_argument; 3483 break; 3484 3485 case 'f': 3486 output = isc_commandline_argument; 3487 if (strcmp(output, "-") == 0) { 3488 output_stdout = true; 3489 } 3490 break; 3491 3492 case 'g': 3493 generateds = true; 3494 break; 3495 3496 case 'G': 3497 sync_records = isc_commandline_argument; 3498 break; 3499 3500 case 'H': 3501 set_iter = true; 3502 /* too-many is NOT DOCUMENTED */ 3503 if (strcmp(isc_commandline_argument, "too-many") == 0) { 3504 nsec3iter = 51; 3505 no_max_check = true; 3506 break; 3507 } 3508 nsec3iter = strtoul(isc_commandline_argument, &endp, 0); 3509 if (*endp != '\0') { 3510 fatal("iterations must be numeric"); 3511 } 3512 if (nsec3iter > 0xffffU) { 3513 fatal("iterations too big"); 3514 } 3515 break; 3516 3517 case 'I': 3518 inputformatstr = isc_commandline_argument; 3519 break; 3520 3521 case 'i': 3522 endp = NULL; 3523 cycle = strtol(isc_commandline_argument, &endp, 0); 3524 if (*endp != '\0' || cycle < 0) { 3525 fatal("cycle period must be numeric and " 3526 "positive"); 3527 } 3528 break; 3529 3530 case 'j': 3531 endp = NULL; 3532 jitter = strtol(isc_commandline_argument, &endp, 0); 3533 if (*endp != '\0' || jitter < 0) { 3534 fatal("jitter must be numeric and positive"); 3535 } 3536 break; 3537 3538 case 'J': 3539 journal = isc_commandline_argument; 3540 break; 3541 3542 case 'K': 3543 directory = isc_commandline_argument; 3544 break; 3545 3546 case 'k': 3547 if (ndskeys == MAXDSKEYS) { 3548 fatal("too many key-signing keys specified"); 3549 } 3550 dskeyfile[ndskeys++] = isc_commandline_argument; 3551 break; 3552 3553 case 'L': 3554 snset = true; 3555 endp = NULL; 3556 serialnum = strtol(isc_commandline_argument, &endp, 0); 3557 if (*endp != '\0') { 3558 fprintf(stderr, "source serial number " 3559 "must be numeric"); 3560 exit(EXIT_FAILURE); 3561 } 3562 break; 3563 3564 case 'l': 3565 fatal("-l option (DLV lookaside) is obsolete"); 3566 break; 3567 3568 case 'M': 3569 endp = NULL; 3570 set_maxttl = true; 3571 maxttl = strtol(isc_commandline_argument, &endp, 0); 3572 if (*endp != '\0') { 3573 fprintf(stderr, "maximum TTL " 3574 "must be numeric"); 3575 exit(EXIT_FAILURE); 3576 } 3577 break; 3578 3579 case 'm': 3580 break; 3581 3582 case 'N': 3583 serialformatstr = isc_commandline_argument; 3584 break; 3585 3586 case 'n': 3587 endp = NULL; 3588 nloops = strtol(isc_commandline_argument, &endp, 0); 3589 if (*endp != '\0' || nloops > INT32_MAX) { 3590 fatal("number of cpus must be numeric"); 3591 } 3592 break; 3593 3594 case 'O': 3595 outputformatstr = isc_commandline_argument; 3596 break; 3597 3598 case 'o': 3599 origin = isc_commandline_argument; 3600 break; 3601 3602 case 'P': 3603 disable_zone_check = true; 3604 break; 3605 3606 case 'p': 3607 fatal("The -p option has been deprecated.\n"); 3608 break; 3609 3610 case 'Q': 3611 remove_inactkeysigs = true; 3612 break; 3613 3614 case 'R': 3615 remove_orphansigs = true; 3616 break; 3617 3618 case 'r': 3619 fatal("The -r options has been deprecated.\n"); 3620 break; 3621 3622 case 'S': 3623 smartsign = true; 3624 break; 3625 3626 case 's': 3627 startstr = isc_commandline_argument; 3628 break; 3629 3630 case 'T': 3631 endp = NULL; 3632 set_keyttl = true; 3633 keyttl = strtottl(isc_commandline_argument); 3634 break; 3635 3636 case 't': 3637 printstats = true; 3638 break; 3639 3640 case 'U': /* Undocumented for testing only. */ 3641 unknownalg = true; 3642 break; 3643 3644 case 'u': 3645 update_chain = true; 3646 break; 3647 3648 case 'v': 3649 endp = NULL; 3650 verbose = strtol(isc_commandline_argument, &endp, 0); 3651 if (*endp != '\0') { 3652 fatal("verbose level must be numeric"); 3653 } 3654 break; 3655 3656 case 'q': 3657 quiet = true; 3658 break; 3659 3660 case 'X': 3661 dnskey_endstr = isc_commandline_argument; 3662 break; 3663 3664 case 'x': 3665 keyset_kskonly = true; 3666 break; 3667 3668 case 'z': 3669 ignore_kskflag = true; 3670 break; 3671 3672 case 'F': 3673 set_fips_mode = true; 3674 break; 3675 3676 case '?': 3677 if (isc_commandline_option != '?') { 3678 fprintf(stderr, "%s: invalid argument -%c\n", 3679 program, isc_commandline_option); 3680 } 3681 FALLTHROUGH; 3682 case 'h': 3683 /* Does not return. */ 3684 usage(); 3685 3686 case 'V': 3687 /* Does not return. */ 3688 version(program); 3689 3690 case 'Z': /* Undocumented test options */ 3691 if (!strcmp(isc_commandline_argument, "nonsecify")) { 3692 nonsecify = true; 3693 } 3694 break; 3695 3696 default: 3697 fprintf(stderr, "%s: unhandled option -%c\n", program, 3698 isc_commandline_option); 3699 exit(EXIT_FAILURE); 3700 } 3701 } 3702 3703 now = isc_stdtime_now(); 3704 3705 if (startstr != NULL) { 3706 starttime = strtotime(startstr, now, now, NULL); 3707 } else { 3708 starttime = now - 3600; /* Allow for some clock skew. */ 3709 } 3710 3711 if (endstr != NULL) { 3712 endtime = strtotime(endstr, now, starttime, NULL); 3713 } else { 3714 endtime = starttime + (30 * 24 * 60 * 60); 3715 } 3716 3717 if (dnskey_endstr != NULL) { 3718 dnskey_endtime = strtotime(dnskey_endstr, now, starttime, NULL); 3719 if (endstr != NULL && dnskey_endtime == endtime) { 3720 fprintf(stderr, "WARNING: -e and -X were both set, " 3721 "but have identical values.\n"); 3722 } 3723 } else { 3724 dnskey_endtime = endtime; 3725 } 3726 3727 if (cycle == -1) { 3728 cycle = (endtime - starttime) / 4; 3729 } 3730 3731 if (nloops == 0) { 3732 nloops = isc_os_ncpus(); 3733 } 3734 vbprintf(4, "using %d cpus\n", nloops); 3735 3736 rdclass = strtoclass(classname); 3737 3738 if (directory == NULL) { 3739 directory = "."; 3740 } 3741 3742 isc_managers_create(&mctx, nloops, &loopmgr, &netmgr); 3743 3744 if (set_fips_mode) { 3745 #if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 3746 fips = OSSL_PROVIDER_load(NULL, "fips"); 3747 if (fips == NULL) { 3748 ERR_clear_error(); 3749 fatal("Failed to load FIPS provider"); 3750 } 3751 base = OSSL_PROVIDER_load(NULL, "base"); 3752 if (base == NULL) { 3753 OSSL_PROVIDER_unload(fips); 3754 ERR_clear_error(); 3755 fatal("Failed to load base provider"); 3756 } 3757 #endif 3758 if (!isc_fips_mode()) { 3759 if (isc_fips_set_mode(1) != ISC_R_SUCCESS) { 3760 fatal("setting FIPS mode failed"); 3761 } 3762 } 3763 } 3764 3765 result = dst_lib_init(mctx, engine); 3766 if (result != ISC_R_SUCCESS) { 3767 fatal("could not initialize dst: %s", 3768 isc_result_totext(result)); 3769 } 3770 3771 setup_logging(mctx, &log); 3772 3773 argc -= isc_commandline_index; 3774 argv += isc_commandline_index; 3775 3776 if (argc < 1) { 3777 usage(); 3778 } 3779 3780 file = argv[0]; 3781 3782 argc -= 1; 3783 argv += 1; 3784 3785 if (origin == NULL) { 3786 origin = file; 3787 } 3788 3789 if (output == NULL) { 3790 size_t size; 3791 free_output = true; 3792 size = strlen(file) + strlen(".signed") + 1; 3793 output = isc_mem_allocate(mctx, size); 3794 snprintf(output, size, "%s.signed", file); 3795 } 3796 3797 if (inputformatstr != NULL) { 3798 if (strcasecmp(inputformatstr, "text") == 0) { 3799 inputformat = dns_masterformat_text; 3800 } else if (strcasecmp(inputformatstr, "raw") == 0) { 3801 inputformat = dns_masterformat_raw; 3802 } else if (strncasecmp(inputformatstr, "raw=", 4) == 0) { 3803 inputformat = dns_masterformat_raw; 3804 fprintf(stderr, "WARNING: input format version " 3805 "ignored\n"); 3806 } else { 3807 fatal("unknown file format: %s", inputformatstr); 3808 } 3809 } 3810 3811 if (outputformatstr != NULL) { 3812 if (strcasecmp(outputformatstr, "text") == 0) { 3813 outputformat = dns_masterformat_text; 3814 } else if (strcasecmp(outputformatstr, "full") == 0) { 3815 outputformat = dns_masterformat_text; 3816 masterstyle = &dns_master_style_full; 3817 } else if (strcasecmp(outputformatstr, "raw") == 0) { 3818 outputformat = dns_masterformat_raw; 3819 } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) { 3820 char *end; 3821 3822 outputformat = dns_masterformat_raw; 3823 rawversion = strtol(outputformatstr + 4, &end, 10); 3824 if (end == outputformatstr + 4 || *end != '\0' || 3825 rawversion > 1U) 3826 { 3827 fprintf(stderr, "unknown raw format version\n"); 3828 exit(EXIT_FAILURE); 3829 } 3830 } else { 3831 fatal("unknown file format: %s", outputformatstr); 3832 } 3833 } 3834 3835 if (serialformatstr != NULL) { 3836 if (strcasecmp(serialformatstr, "keep") == 0) { 3837 serialformat = SOA_SERIAL_KEEP; 3838 } else if (strcasecmp(serialformatstr, "increment") == 0 || 3839 strcasecmp(serialformatstr, "incr") == 0) 3840 { 3841 serialformat = SOA_SERIAL_INCREMENT; 3842 } else if (strcasecmp(serialformatstr, "unixtime") == 0) { 3843 serialformat = SOA_SERIAL_UNIXTIME; 3844 } else if (strcasecmp(serialformatstr, "date") == 0) { 3845 serialformat = SOA_SERIAL_DATE; 3846 } else { 3847 fatal("unknown soa serial format: %s", serialformatstr); 3848 } 3849 } 3850 3851 if (output_dnssec_only && outputformat != dns_masterformat_text) { 3852 fatal("option -D can only be used with \"-O text\""); 3853 } 3854 3855 if (output_dnssec_only && serialformat != SOA_SERIAL_KEEP) { 3856 fatal("option -D can only be used with \"-N keep\""); 3857 } 3858 3859 if (output_dnssec_only && set_maxttl) { 3860 fatal("option -D cannot be used with -M"); 3861 } 3862 3863 result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL, 0, 24, 3864 0, 0, 0, 8, 0xffffffff, mctx); 3865 check_result(result, "dns_master_stylecreate"); 3866 3867 gdb = NULL; 3868 timer_start = isc_time_now(); 3869 loadzone(file, origin, rdclass, &gdb); 3870 if (journal != NULL) { 3871 loadjournal(mctx, gdb, journal); 3872 } 3873 gorigin = dns_db_origin(gdb); 3874 gclass = dns_db_class(gdb); 3875 get_soa_ttls(); 3876 3877 if (set_maxttl && set_keyttl && keyttl > maxttl) { 3878 fprintf(stderr, 3879 "%s: warning: Specified key TTL %u " 3880 "exceeds maximum zone TTL; reducing to %u\n", 3881 program, keyttl, maxttl); 3882 keyttl = maxttl; 3883 } 3884 3885 if (!set_keyttl) { 3886 keyttl = soa_ttl; 3887 } 3888 3889 /* 3890 * Check for any existing NSEC3 parameters in the zone, 3891 * and use them as defaults if -u was not specified. 3892 */ 3893 if (update_chain && !set_optout && !set_iter && !set_salt) { 3894 nsec_datatype = dns_rdatatype_nsec; 3895 } else { 3896 set_nsec3params(update_chain, set_salt, set_optout, set_iter); 3897 } 3898 3899 /* 3900 * We need to do this early on, as we start messing with the list 3901 * of keys rather early. 3902 */ 3903 ISC_LIST_INIT(keylist); 3904 isc_rwlock_init(&keylist_lock); 3905 3906 /* 3907 * Fill keylist with: 3908 * 1) Keys listed in the DNSKEY set that have 3909 * private keys associated, *if* no keys were 3910 * set on the command line. 3911 * 2) ZSKs set on the command line 3912 * 3) KSKs set on the command line 3913 * 4) Any keys remaining in the DNSKEY set which 3914 * do not have private keys associated and were 3915 * not specified on the command line. 3916 */ 3917 if (argc == 0 || smartsign) { 3918 loadzonekeys(!smartsign, false); 3919 } 3920 loadexplicitkeys(argv, argc, false); 3921 loadexplicitkeys(dskeyfile, ndskeys, true); 3922 loadzonekeys(!smartsign, true); 3923 3924 /* 3925 * If we're doing smart signing, look in the key repository for 3926 * key files with metadata, and merge them with the keylist 3927 * we have now. 3928 */ 3929 if (smartsign) { 3930 build_final_keylist(); 3931 } 3932 3933 /* Now enumerate the key list */ 3934 for (key = ISC_LIST_HEAD(keylist); key != NULL; 3935 key = ISC_LIST_NEXT(key, link)) 3936 { 3937 key->index = keycount++; 3938 } 3939 3940 if (keycount == 0) { 3941 if (disable_zone_check) { 3942 fprintf(stderr, 3943 "%s: warning: No keys specified " 3944 "or found\n", 3945 program); 3946 } else { 3947 fatal("No signing keys specified or found."); 3948 } 3949 nokeys = true; 3950 } 3951 3952 warnifallksk(gdb); 3953 3954 if (IS_NSEC3) { 3955 bool answer; 3956 3957 hash_length = dns_nsec3_hashlength(dns_hash_sha1); 3958 hashlist_init(&hashlist, 3959 dns_db_nodecount(gdb, dns_dbtree_main) * 2, 3960 hash_length); 3961 result = dns_nsec_nseconly(gdb, gversion, NULL, &answer); 3962 if (result == ISC_R_NOTFOUND) { 3963 fprintf(stderr, 3964 "%s: warning: NSEC3 generation " 3965 "requested with no DNSKEY; ignoring\n", 3966 program); 3967 } else if (result != ISC_R_SUCCESS) { 3968 check_result(result, "dns_nsec_nseconly"); 3969 } else if (answer) { 3970 fatal("NSEC3 generation requested with " 3971 "NSEC-only DNSKEY"); 3972 } 3973 3974 if (nsec3iter > dns_nsec3_maxiterations()) { 3975 if (no_max_check) { 3976 fprintf(stderr, 3977 "Ignoring max iterations check.\n"); 3978 } else { 3979 fatal("NSEC3 iterations too big. Maximum " 3980 "iterations allowed %u.", 3981 dns_nsec3_maxiterations()); 3982 } 3983 } 3984 } else { 3985 hashlist_init(&hashlist, 0, 0); /* silence clang */ 3986 } 3987 3988 gversion = NULL; 3989 result = dns_db_newversion(gdb, &gversion); 3990 check_result(result, "dns_db_newversion()"); 3991 3992 switch (serialformat) { 3993 case SOA_SERIAL_INCREMENT: 3994 setsoaserial(0, dns_updatemethod_increment); 3995 break; 3996 case SOA_SERIAL_UNIXTIME: 3997 setsoaserial(now, dns_updatemethod_unixtime); 3998 break; 3999 case SOA_SERIAL_DATE: 4000 setsoaserial(now, dns_updatemethod_date); 4001 break; 4002 case SOA_SERIAL_KEEP: 4003 default: 4004 /* do nothing */ 4005 break; 4006 } 4007 4008 /* Remove duplicates and cap TTLs at maxttl */ 4009 cleanup_zone(); 4010 4011 if (!nonsecify) { 4012 if (IS_NSEC3) { 4013 nsec3ify(dns_hash_sha1, nsec3iter, gsalt, salt_length, 4014 &hashlist); 4015 } else { 4016 nsecify(); 4017 } 4018 } 4019 4020 if (!nokeys) { 4021 writeset("dsset-", dns_rdatatype_ds); 4022 if (make_keyset) { 4023 writeset("keyset-", dns_rdatatype_dnskey); 4024 } 4025 } 4026 4027 if (output_stdout) { 4028 outfp = stdout; 4029 if (outputformatstr == NULL) { 4030 masterstyle = &dns_master_style_full; 4031 } 4032 } else { 4033 tempfilelen = strlen(output) + 20; 4034 tempfile = isc_mem_get(mctx, tempfilelen); 4035 4036 result = isc_file_mktemplate(output, tempfile, tempfilelen); 4037 check_result(result, "isc_file_mktemplate"); 4038 4039 result = isc_file_openunique(tempfile, &outfp); 4040 if (result != ISC_R_SUCCESS) { 4041 fatal("failed to open temporary output file: %s", 4042 isc_result_totext(result)); 4043 } 4044 removefile = true; 4045 setfatalcallback(&removetempfile); 4046 } 4047 4048 print_time(outfp); 4049 print_version(outfp); 4050 4051 isc_mutex_init(&namelock); 4052 4053 presign(); 4054 sign_start = isc_time_now(); 4055 signapex(); 4056 if (!atomic_load(&finished)) { 4057 /* 4058 * There is more work to do. Spread it out over multiple 4059 * processors if possible. 4060 */ 4061 isc_loopmgr_setup(loopmgr, assignwork, NULL); 4062 isc_loopmgr_teardown(loopmgr, abortwork, NULL); 4063 isc_loopmgr_run(loopmgr); 4064 4065 if (!atomic_load(&finished)) { 4066 fatal("process aborted by user"); 4067 } 4068 } 4069 postsign(); 4070 sign_finish = isc_time_now(); 4071 4072 if (disable_zone_check) { 4073 vresult = ISC_R_SUCCESS; 4074 } else { 4075 vresult = dns_zoneverify_dnssec(NULL, gdb, gversion, gorigin, 4076 NULL, mctx, ignore_kskflag, 4077 keyset_kskonly, report); 4078 if (vresult != ISC_R_SUCCESS) { 4079 fprintf(output_stdout ? stderr : stdout, 4080 "Zone verification failed (%s)\n", 4081 isc_result_totext(vresult)); 4082 } 4083 } 4084 4085 if (!output_dnssec_only) { 4086 dns_masterrawheader_t header; 4087 dns_master_initrawheader(&header); 4088 if (rawversion == 0U) { 4089 header.flags = DNS_MASTERRAW_COMPAT; 4090 } else if (snset) { 4091 header.flags = DNS_MASTERRAW_SOURCESERIALSET; 4092 header.sourceserial = serialnum; 4093 } 4094 result = dns_master_dumptostream(mctx, gdb, gversion, 4095 masterstyle, outputformat, 4096 &header, outfp); 4097 check_result(result, "dns_master_dumptostream"); 4098 } 4099 4100 if (!output_stdout) { 4101 result = isc_stdio_close(outfp); 4102 check_result(result, "isc_stdio_close"); 4103 removefile = false; 4104 4105 if (vresult == ISC_R_SUCCESS) { 4106 result = isc_file_rename(tempfile, output); 4107 if (result != ISC_R_SUCCESS) { 4108 fatal("failed to rename temp file to %s: %s", 4109 output, isc_result_totext(result)); 4110 } 4111 printf("%s\n", output); 4112 } else { 4113 isc_file_remove(tempfile); 4114 } 4115 } 4116 4117 dns_db_closeversion(gdb, &gversion, false); 4118 dns_db_detach(&gdb); 4119 4120 hashlist_free(&hashlist); 4121 4122 while (!ISC_LIST_EMPTY(keylist)) { 4123 key = ISC_LIST_HEAD(keylist); 4124 ISC_LIST_UNLINK(keylist, key, link); 4125 dns_dnsseckey_destroy(mctx, &key); 4126 } 4127 4128 if (tempfilelen != 0) { 4129 isc_mem_put(mctx, tempfile, tempfilelen); 4130 } 4131 4132 if (free_output) { 4133 isc_mem_free(mctx, output); 4134 } 4135 4136 dns_master_styledestroy(&dsstyle, mctx); 4137 4138 cleanup_logging(&log); 4139 dst_lib_destroy(); 4140 if (verbose > 10) { 4141 isc_mem_stats(mctx, stdout); 4142 } 4143 4144 #if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 4145 if (base != NULL) { 4146 OSSL_PROVIDER_unload(base); 4147 } 4148 if (fips != NULL) { 4149 OSSL_PROVIDER_unload(fips); 4150 } 4151 #endif 4152 4153 isc_managers_destroy(&mctx, &loopmgr, &netmgr); 4154 4155 if (printstats) { 4156 timer_finish = isc_time_now(); 4157 print_stats(&timer_start, &timer_finish, &sign_start, 4158 &sign_finish); 4159 } 4160 isc_mutex_destroy(&namelock); 4161 4162 return vresult == ISC_R_SUCCESS ? 0 : 1; 4163 } 4164