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