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