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