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