2 * Portions Copyright (C) 2004-2016 Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (C) 1999-2003 Internet Software Consortium.
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.
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.
17 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
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.
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.
41 #include <isc/base32.h>
42 #include <isc/commandline.h>
43 #include <isc/entropy.h>
44 #include <isc/event.h>
49 #include <isc/mutex.h>
51 #include <isc/print.h>
52 #include <isc/random.h>
53 #include <isc/rwlock.h>
54 #include <isc/serial.h>
56 #include <isc/stdio.h>
57 #include <isc/stdlib.h>
58 #include <isc/string.h>
64 #include <dns/dbiterator.h>
66 #include <dns/dnssec.h>
68 #include <dns/fixedname.h>
69 #include <dns/keyvalues.h>
71 #include <dns/master.h>
72 #include <dns/masterdump.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>
88 #include "dnssectool.h"
91 #define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */
94 const char *program = "dnssec-signzone";
97 typedef struct hashlist hashlist_t;
99 static int nsec_datatype = dns_rdatatype_nsec;
101 #define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3)
102 #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
104 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
109 #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
110 #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
111 #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
113 #define SOA_SERIAL_KEEP 0
114 #define SOA_SERIAL_INCREMENT 1
115 #define SOA_SERIAL_UNIXTIME 2
117 typedef struct signer_event sevent_t;
118 struct signer_event {
119 ISC_EVENT_COMMON(sevent_t);
120 dns_fixedname_t *fname;
124 static dns_dnsseckeylist_t keylist;
125 static unsigned int keycount = 0;
126 isc_rwlock_t keylist_lock;
127 static isc_stdtime_t starttime = 0, endtime = 0, dnskey_endtime = 0, now;
128 static int cycle = -1;
129 static int jitter = 0;
130 static isc_boolean_t tryverify = ISC_FALSE;
131 static isc_boolean_t printstats = ISC_FALSE;
132 static isc_mem_t *mctx = NULL;
133 static isc_entropy_t *ectx = NULL;
134 static dns_ttl_t zone_soa_min_ttl;
135 static dns_ttl_t soa_ttl;
136 static FILE *outfp = NULL;
137 static char *tempfile = NULL;
138 static const dns_master_style_t *masterstyle;
139 static dns_masterformat_t inputformat = dns_masterformat_text;
140 static dns_masterformat_t outputformat = dns_masterformat_text;
141 static isc_uint32_t rawversion = 1, serialnum = 0;
142 static isc_boolean_t snset = ISC_FALSE;
143 static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
144 static unsigned int nverified = 0, nverifyfailed = 0;
145 static const char *directory = NULL, *dsdir = NULL;
146 static isc_mutex_t namelock, statslock;
147 static isc_taskmgr_t *taskmgr = NULL;
148 static dns_db_t *gdb; /* The database */
149 static dns_dbversion_t *gversion; /* The database version */
150 static dns_dbiterator_t *gdbiter; /* The database iterator */
151 static dns_rdataclass_t gclass; /* The class */
152 static dns_name_t *gorigin; /* The database origin */
153 static int nsec3flags = 0;
154 static dns_iterations_t nsec3iter = 10U;
155 static unsigned char saltbuf[255];
156 static unsigned char *gsalt = saltbuf;
157 static size_t salt_length = 0;
158 static isc_task_t *master = NULL;
159 static unsigned int ntasks = 0;
160 static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE;
161 static isc_boolean_t nokeys = ISC_FALSE;
162 static isc_boolean_t removefile = ISC_FALSE;
163 static isc_boolean_t generateds = ISC_FALSE;
164 static isc_boolean_t ignore_kskflag = ISC_FALSE;
165 static isc_boolean_t keyset_kskonly = ISC_FALSE;
166 static dns_name_t *dlv = NULL;
167 static dns_fixedname_t dlv_fixed;
168 static dns_master_style_t *dsstyle = NULL;
169 static unsigned int serialformat = SOA_SERIAL_KEEP;
170 static unsigned int hash_length = 0;
171 static isc_boolean_t unknownalg = ISC_FALSE;
172 static isc_boolean_t disable_zone_check = ISC_FALSE;
173 static isc_boolean_t update_chain = ISC_FALSE;
174 static isc_boolean_t set_keyttl = ISC_FALSE;
175 static dns_ttl_t keyttl;
176 static isc_boolean_t smartsign = ISC_FALSE;
177 static isc_boolean_t remove_orphansigs = ISC_FALSE;
178 static isc_boolean_t remove_inactkeysigs = ISC_FALSE;
179 static isc_boolean_t output_dnssec_only = ISC_FALSE;
180 static isc_boolean_t output_stdout = ISC_FALSE;
182 #define INCSTAT(counter) \
186 UNLOCK(&statslock); \
190 sign(isc_task_t *task, isc_event_t *event);
193 dumpnode(dns_name_t *name, dns_dbnode_t *node) {
195 dns_rdatasetiter_t *iter = NULL;
196 isc_buffer_t *buffer = NULL;
199 unsigned bufsize = 4096;
201 if (outputformat != dns_masterformat_text)
204 if (!output_dnssec_only) {
205 result = dns_master_dumpnodetostream(mctx, gdb, gversion, node,
206 name, masterstyle, outfp);
207 check_result(result, "dns_master_dumpnodetostream");
211 result = dns_db_allrdatasets(gdb, node, gversion, 0, &iter);
212 check_result(result, "dns_db_allrdatasets");
214 dns_rdataset_init(&rds);
216 result = isc_buffer_allocate(mctx, &buffer, bufsize);
217 check_result(result, "isc_buffer_allocate");
219 for (result = dns_rdatasetiter_first(iter);
220 result == ISC_R_SUCCESS;
221 result = dns_rdatasetiter_next(iter)) {
223 dns_rdatasetiter_current(iter, &rds);
225 if (rds.type != dns_rdatatype_rrsig &&
226 rds.type != dns_rdatatype_nsec &&
227 rds.type != dns_rdatatype_nsec3 &&
228 rds.type != dns_rdatatype_nsec3param &&
229 (!smartsign || rds.type != dns_rdatatype_dnskey)) {
230 dns_rdataset_disassociate(&rds);
235 result = dns_master_rdatasettotext(name, &rds,
236 masterstyle, buffer);
237 if (result != ISC_R_NOSPACE)
241 isc_buffer_free(&buffer);
242 result = isc_buffer_allocate(mctx, &buffer, bufsize);
243 check_result(result, "isc_buffer_allocate");
245 check_result(result, "dns_master_rdatasettotext");
247 isc_buffer_usedregion(buffer, &r);
248 result = isc_stdio_write(r.base, 1, r.length, outfp, NULL);
249 check_result(result, "isc_stdio_write");
250 isc_buffer_clear(buffer);
252 dns_rdataset_disassociate(&rds);
255 isc_buffer_free(&buffer);
256 dns_rdatasetiter_destroy(&iter);
260 * Sign the given RRset with given key, and add the signature record to the
264 signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key,
265 dns_ttl_t ttl, dns_diff_t *add, const char *logmsg)
268 isc_stdtime_t jendtime, expiry;
269 char keystr[DST_KEY_FORMATSIZE];
270 dns_rdata_t trdata = DNS_RDATA_INIT;
271 unsigned char array[BUFSIZE];
273 dns_difftuple_t *tuple;
275 dst_key_format(key, keystr, sizeof(keystr));
276 vbprintf(1, "\t%s %s\n", logmsg, keystr);
278 if (rdataset->type == dns_rdatatype_dnskey)
279 expiry = dnskey_endtime;
283 jendtime = (jitter != 0) ? isc_random_jitter(expiry, jitter) : expiry;
284 isc_buffer_init(&b, array, sizeof(array));
285 result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
287 isc_entropy_stopcallbacksources(ectx);
288 if (result != ISC_R_SUCCESS) {
289 fatal("dnskey '%s' failed to sign data: %s",
290 keystr, isc_result_totext(result));
295 result = dns_dnssec_verify(name, rdataset, key,
296 ISC_TRUE, mctx, &trdata);
297 if (result == ISC_R_SUCCESS) {
298 vbprintf(3, "\tsignature verified\n");
301 vbprintf(3, "\tsignature failed to verify\n");
302 INCSTAT(nverifyfailed);
307 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name, ttl, &trdata,
309 check_result(result, "dns_difftuple_create");
310 dns_diff_append(add, &tuple);
313 static inline isc_boolean_t
314 issigningkey(dns_dnsseckey_t *key) {
315 return (key->force_sign || key->hint_sign);
318 static inline isc_boolean_t
319 ispublishedkey(dns_dnsseckey_t *key) {
320 return ((key->force_publish || key->hint_publish) &&
324 static inline isc_boolean_t
325 iszonekey(dns_dnsseckey_t *key) {
326 return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) &&
327 dst_key_iszonekey(key->key)));
330 static inline isc_boolean_t
331 isksk(dns_dnsseckey_t *key) {
335 static inline isc_boolean_t
336 iszsk(dns_dnsseckey_t *key) {
337 return (ignore_kskflag || !key->ksk);
341 * Find the key that generated an RRSIG, if it is in the key list. If
342 * so, return a pointer to it, otherwise return NULL.
344 * No locking is performed here, this must be done by the caller.
346 static dns_dnsseckey_t *
347 keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
348 dns_dnsseckey_t *key;
350 for (key = ISC_LIST_HEAD(keylist);
352 key = ISC_LIST_NEXT(key, link)) {
353 if (rrsig->keyid == dst_key_id(key->key) &&
354 rrsig->algorithm == dst_key_alg(key->key) &&
355 dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
362 * Finds the key that generated a RRSIG, if possible. First look at the keys
363 * that we've loaded already, and then see if there's a key on disk.
365 static dns_dnsseckey_t *
366 keythatsigned(dns_rdata_rrsig_t *rrsig) {
368 dst_key_t *pubkey = NULL, *privkey = NULL;
369 dns_dnsseckey_t *key = NULL;
371 isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read);
372 key = keythatsigned_unlocked(rrsig);
373 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_read);
378 * We did not find the key in our list. Get a write lock now, since
379 * we may be modifying the bits. We could do the tryupgrade() dance,
380 * but instead just get a write lock and check once again to see if
381 * it is on our list. It's possible someone else may have added it
384 isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write);
385 key = keythatsigned_unlocked(rrsig);
387 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
391 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
392 rrsig->algorithm, DST_TYPE_PUBLIC,
393 directory, mctx, &pubkey);
394 if (result != ISC_R_SUCCESS) {
395 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
399 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
401 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
402 directory, mctx, &privkey);
403 if (result == ISC_R_SUCCESS) {
404 dst_key_free(&pubkey);
405 result = dns_dnsseckey_create(mctx, &privkey, &key);
407 result = dns_dnsseckey_create(mctx, &pubkey, &key);
409 if (result == ISC_R_SUCCESS) {
410 key->force_publish = ISC_FALSE;
411 key->force_sign = ISC_FALSE;
412 key->index = keycount++;
413 ISC_LIST_APPEND(keylist, key, link);
416 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
421 * Check to see if we expect to find a key at this name. If we see a RRSIG
422 * and can't find the signing key that we expect to find, we drop the rrsig.
423 * I'm not sure if this is completely correct, but it seems to work.
426 expecttofindkey(dns_name_t *name) {
427 unsigned int options = DNS_DBFIND_NOWILD;
428 dns_fixedname_t fname;
430 char namestr[DNS_NAME_FORMATSIZE];
432 dns_fixedname_init(&fname);
433 result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
434 0, NULL, dns_fixedname_name(&fname), NULL, NULL);
440 case DNS_R_DELEGATION:
445 dns_name_format(name, namestr, sizeof(namestr));
446 fatal("failure looking for '%s DNSKEY' in database: %s",
447 namestr, isc_result_totext(result));
449 return (ISC_FALSE); /* removes a warning */
452 static inline isc_boolean_t
453 setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
457 result = dns_dnssec_verify(name, set, key, ISC_FALSE, mctx, rrsig);
458 if (result == ISC_R_SUCCESS) {
462 INCSTAT(nverifyfailed);
468 * Signs a set. Goes through contortions to decide if each RRSIG should
469 * be dropped or retained, and then determines if any new SIGs need to
473 signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
476 dns_rdataset_t sigset;
477 dns_rdata_t sigrdata = DNS_RDATA_INIT;
478 dns_rdata_rrsig_t rrsig;
479 dns_dnsseckey_t *key;
481 isc_boolean_t nosigs = ISC_FALSE;
482 isc_boolean_t *wassignedby, *nowsignedby;
484 dns_difftuple_t *tuple;
487 char namestr[DNS_NAME_FORMATSIZE];
488 char typestr[TYPE_FORMATSIZE];
489 char sigstr[SIG_FORMATSIZE];
491 dns_name_format(name, namestr, sizeof(namestr));
492 type_format(set->type, typestr, sizeof(typestr));
494 ttl = ISC_MIN(set->ttl, endtime - starttime);
496 dns_rdataset_init(&sigset);
497 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
498 set->type, 0, &sigset, NULL);
499 if (result == ISC_R_NOTFOUND) {
500 vbprintf(2, "no existing signatures for %s/%s\n",
502 result = ISC_R_SUCCESS;
505 if (result != ISC_R_SUCCESS)
506 fatal("failed while looking for '%s RRSIG %s': %s",
507 namestr, typestr, isc_result_totext(result));
509 vbprintf(1, "%s/%s:\n", namestr, typestr);
511 arraysize = keycount;
513 arraysize += dns_rdataset_count(&sigset);
514 wassignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
515 nowsignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
516 if (wassignedby == NULL || nowsignedby == NULL)
517 fatal("out of memory");
519 for (i = 0; i < arraysize; i++)
520 wassignedby[i] = nowsignedby[i] = ISC_FALSE;
523 result = ISC_R_NOMORE;
525 result = dns_rdataset_first(&sigset);
527 while (result == ISC_R_SUCCESS) {
528 isc_boolean_t expired, future;
529 isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE;
531 dns_rdataset_current(&sigset, &sigrdata);
533 result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
534 check_result(result, "dns_rdata_tostruct");
536 future = isc_serial_lt(now, rrsig.timesigned);
538 key = keythatsigned(&rrsig);
539 sig_format(&rrsig, sigstr, sizeof(sigstr));
540 if (key != NULL && issigningkey(key))
541 expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
543 expired = isc_serial_gt(now, rrsig.timeexpire);
545 if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
546 /* rrsig is dropped and not replaced */
547 vbprintf(2, "\trrsig by %s dropped - "
548 "invalid validity period\n",
550 } else if (key == NULL && !future &&
551 expecttofindkey(&rrsig.signer)) {
552 /* rrsig is dropped and not replaced */
553 vbprintf(2, "\trrsig by %s dropped - "
554 "private dnskey not found\n",
556 } else if (key == NULL || future) {
557 keep = (!expired && !remove_orphansigs);
558 vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
559 keep ? "retained" : "dropped", sigstr);
560 } else if (!dns_dnssec_keyactive(key->key, now) &&
561 remove_inactkeysigs) {
563 vbprintf(2, "\trrsig by %s dropped - key inactive\n",
565 } else if (issigningkey(key)) {
566 wassignedby[key->index] = ISC_TRUE;
568 if (!expired && rrsig.originalttl == set->ttl &&
569 setverifies(name, set, key->key, &sigrdata)) {
570 vbprintf(2, "\trrsig by %s retained\n", sigstr);
573 vbprintf(2, "\trrsig by %s dropped - %s\n",
574 sigstr, expired ? "expired" :
575 rrsig.originalttl != set->ttl ?
576 "ttl change" : "failed to verify");
579 } else if (!ispublishedkey(key) && remove_orphansigs) {
580 vbprintf(2, "\trrsig by %s dropped - dnskey removed\n",
582 } else if (iszonekey(key)) {
583 wassignedby[key->index] = ISC_TRUE;
585 if (!expired && rrsig.originalttl == set->ttl &&
586 setverifies(name, set, key->key, &sigrdata)) {
587 vbprintf(2, "\trrsig by %s retained\n", sigstr);
590 vbprintf(2, "\trrsig by %s dropped - %s\n",
591 sigstr, expired ? "expired" :
592 rrsig.originalttl != set->ttl ?
593 "ttl change" : "failed to verify");
595 } else if (!expired) {
596 vbprintf(2, "\trrsig by %s retained\n", sigstr);
599 vbprintf(2, "\trrsig by %s expired\n", sigstr);
604 nowsignedby[key->index] = ISC_TRUE;
606 if (sigset.ttl != ttl) {
607 vbprintf(2, "\tfixing ttl %s\n", sigstr);
609 result = dns_difftuple_create(mctx,
614 check_result(result, "dns_difftuple_create");
615 dns_diff_append(del, &tuple);
616 result = dns_difftuple_create(mctx,
621 check_result(result, "dns_difftuple_create");
622 dns_diff_append(add, &tuple);
626 vbprintf(2, "removing signature by %s\n", sigstr);
627 result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL,
630 check_result(result, "dns_difftuple_create");
631 dns_diff_append(del, &tuple);
638 signwithkey(name, set, key->key, ttl, add,
639 "resigning with dnskey");
640 nowsignedby[key->index] = ISC_TRUE;
643 dns_rdata_reset(&sigrdata);
644 dns_rdata_freestruct(&rrsig);
645 result = dns_rdataset_next(&sigset);
647 if (result == ISC_R_NOMORE)
648 result = ISC_R_SUCCESS;
650 check_result(result, "dns_rdataset_first/next");
651 if (dns_rdataset_isassociated(&sigset))
652 dns_rdataset_disassociate(&sigset);
654 for (key = ISC_LIST_HEAD(keylist);
656 key = ISC_LIST_NEXT(key, link))
658 if (nowsignedby[key->index])
661 if (!issigningkey(key))
664 if (set->type == dns_rdatatype_dnskey &&
665 dns_name_equal(name, gorigin)) {
666 isc_boolean_t have_ksk;
667 dns_dnsseckey_t *tmpkey;
669 have_ksk = isksk(key);
670 for (tmpkey = ISC_LIST_HEAD(keylist);
672 tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
673 if (dst_key_alg(key->key) !=
674 dst_key_alg(tmpkey->key))
676 if (REVOKE(tmpkey->key))
681 if (isksk(key) || !have_ksk ||
682 (iszsk(key) && !keyset_kskonly))
683 signwithkey(name, set, key->key, ttl, add,
684 "signing with dnskey");
685 } else if (set->type == dns_rdatatype_cds ||
686 set->type == dns_rdatatype_cdnskey ||
688 signwithkey(name, set, key->key, ttl, add,
689 "signing with dnskey");
693 isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t));
694 isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t));
698 unsigned char *hashbuf;
705 hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) {
708 l->length = length + 1;
712 l->hashbuf = malloc(l->size * l->length);
713 if (l->hashbuf == NULL)
722 hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len)
725 REQUIRE(len <= l->length);
727 if (l->entries == l->size) {
728 l->size = l->size * 2 + 100;
729 l->hashbuf = realloc(l->hashbuf, l->size * l->length);
730 if (l->hashbuf == NULL)
731 fatal("unable to grow hashlist: out of memory");
733 memset(l->hashbuf + l->entries * l->length, 0, l->length);
734 memmove(l->hashbuf + l->entries * l->length, hash, len);
739 hashlist_add_dns_name(hashlist_t *l, /*const*/ dns_name_t *name,
740 unsigned int hashalg, unsigned int iterations,
741 const unsigned char *salt, size_t salt_len,
742 isc_boolean_t speculative)
744 char nametext[DNS_NAME_FORMATSIZE];
745 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
749 len = isc_iterated_hash(hash, hashalg, iterations,
751 name->ndata, name->length);
753 dns_name_format(name, nametext, sizeof nametext);
754 for (i = 0 ; i < len; i++)
755 fprintf(stderr, "%02x", hash[i]);
756 fprintf(stderr, " %s\n", nametext);
758 hash[len++] = speculative ? 1 : 0;
759 hashlist_add(l, hash, len);
763 hashlist_comp(const void *a, const void *b) {
764 return (isc_safe_memcompare(a, b, hash_length + 1));
768 hashlist_sort(hashlist_t *l) {
769 qsort(l->hashbuf, l->entries, l->length, hashlist_comp);
773 hashlist_hasdup(hashlist_t *l) {
774 unsigned char *current;
775 unsigned char *next = l->hashbuf;
776 size_t entries = l->entries;
779 * Skip initial speculative wild card hashs.
781 while (entries > 0U && next[l->length-1] != 0U) {
787 while (entries-- > 1U) {
789 if (next[l->length-1] != 0)
791 if (isc_safe_memequal(current, next, l->length - 1))
798 static const unsigned char *
799 hashlist_findnext(const hashlist_t *l,
800 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
802 size_t entries = l->entries;
803 const unsigned char *next = bsearch(hash, l->hashbuf, l->entries,
804 l->length, hashlist_comp);
805 INSIST(next != NULL);
808 if (next < l->hashbuf + (l->entries - 1) * l->length)
812 if (next[l->length - 1] == 0)
814 } while (entries-- > 1U);
815 INSIST(entries != 0U);
820 hashlist_exists(const hashlist_t *l,
821 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
823 if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp))
830 addnowildcardhash(hashlist_t *l, /*const*/ dns_name_t *name,
831 unsigned int hashalg, unsigned int iterations,
832 const unsigned char *salt, size_t salt_len)
834 dns_fixedname_t fixed;
836 dns_dbnode_t *node = NULL;
838 char namestr[DNS_NAME_FORMATSIZE];
840 dns_fixedname_init(&fixed);
841 wild = dns_fixedname_name(&fixed);
843 result = dns_name_concatenate(dns_wildcardname, name, wild, NULL);
844 if (result == ISC_R_NOSPACE)
846 check_result(result,"addnowildcardhash: dns_name_concatenate()");
848 result = dns_db_findnode(gdb, wild, ISC_FALSE, &node);
849 if (result == ISC_R_SUCCESS) {
850 dns_db_detachnode(gdb, &node);
855 dns_name_format(wild, namestr, sizeof(namestr));
856 fprintf(stderr, "adding no-wildcardhash for %s\n", namestr);
859 hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_len,
864 opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
867 char filename[PATH_MAX];
871 isc_buffer_init(&b, filename, sizeof(filename));
873 /* allow room for a trailing slash */
874 if (strlen(dsdir) >= isc_buffer_availablelength(&b))
875 fatal("path '%s' is too long", dsdir);
876 isc_buffer_putstr(&b, dsdir);
877 if (dsdir[strlen(dsdir) - 1] != '/')
878 isc_buffer_putstr(&b, "/");
880 if (strlen(prefix) > isc_buffer_availablelength(&b))
881 fatal("path '%s' is too long", dsdir);
882 isc_buffer_putstr(&b, prefix);
883 result = dns_name_tofilenametext(name, ISC_FALSE, &b);
884 check_result(result, "dns_name_tofilenametext()");
885 if (isc_buffer_availablelength(&b) == 0) {
886 char namestr[DNS_NAME_FORMATSIZE];
887 dns_name_format(name, namestr, sizeof(namestr));
888 fatal("name '%s' is too long", namestr);
890 isc_buffer_putuint8(&b, 0);
892 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
893 rdclass, 0, NULL, dbp);
894 check_result(result, "dns_db_create()");
896 result = dns_db_load3(*dbp, filename, inputformat, DNS_MASTER_HINT);
897 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
902 * Load the DS set for a child zone, if a dsset-* file can be found.
903 * If not, try to find a keyset-* file from an earlier version of
904 * dnssec-signzone, and build DS records from that.
907 loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
909 dns_dbversion_t *ver = NULL;
910 dns_dbnode_t *node = NULL;
912 dns_rdataset_t keyset;
914 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
916 dns_difftuple_t *tuple = NULL;
918 opendb("dsset-", name, gclass, &db);
920 result = dns_db_findnode(db, name, ISC_FALSE, &node);
921 if (result == ISC_R_SUCCESS) {
922 dns_rdataset_init(dsset);
923 result = dns_db_findrdataset(db, node, NULL,
924 dns_rdatatype_ds, 0, 0,
926 dns_db_detachnode(db, &node);
927 if (result == ISC_R_SUCCESS) {
928 vbprintf(2, "found DS records\n");
937 /* No DS records found; try again, looking for DNSKEY records */
938 opendb("keyset-", name, gclass, &db);
940 return (ISC_R_NOTFOUND);
943 result = dns_db_findnode(db, name, ISC_FALSE, &node);
944 if (result != ISC_R_SUCCESS) {
949 dns_rdataset_init(&keyset);
950 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
952 if (result != ISC_R_SUCCESS) {
953 dns_db_detachnode(db, &node);
957 vbprintf(2, "found DNSKEY records\n");
959 result = dns_db_newversion(db, &ver);
960 check_result(result, "dns_db_newversion");
961 dns_diff_init(mctx, &diff);
963 for (result = dns_rdataset_first(&keyset);
964 result == ISC_R_SUCCESS;
965 result = dns_rdataset_next(&keyset))
967 dns_rdata_init(&key);
969 dns_rdataset_current(&keyset, &key);
970 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
972 check_result(result, "dns_ds_buildrdata");
974 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
976 check_result(result, "dns_difftuple_create");
977 dns_diff_append(&diff, &tuple);
979 dns_rdata_reset(&ds);
980 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
982 check_result(result, "dns_ds_buildrdata");
984 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
986 check_result(result, "dns_difftuple_create");
987 dns_diff_append(&diff, &tuple);
990 result = dns_diff_apply(&diff, db, ver);
991 check_result(result, "dns_diff_apply");
992 dns_diff_clear(&diff);
994 dns_db_closeversion(db, &ver, ISC_TRUE);
996 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
998 check_result(result, "dns_db_findrdataset");
1000 dns_rdataset_disassociate(&keyset);
1001 dns_db_detachnode(db, &node);
1006 static isc_boolean_t
1007 secure(dns_name_t *name, dns_dbnode_t *node) {
1008 dns_rdataset_t dsset;
1009 isc_result_t result;
1011 if (dns_name_equal(name, gorigin))
1014 dns_rdataset_init(&dsset);
1015 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds,
1016 0, 0, &dsset, NULL);
1017 if (dns_rdataset_isassociated(&dsset))
1018 dns_rdataset_disassociate(&dsset);
1020 return (ISC_TF(result == ISC_R_SUCCESS));
1024 * Signs all records at a name.
1027 signname(dns_dbnode_t *node, dns_name_t *name) {
1028 isc_result_t result;
1029 dns_rdataset_t rdataset;
1030 dns_rdatasetiter_t *rdsiter;
1031 isc_boolean_t isdelegation = ISC_FALSE;
1032 dns_diff_t del, add;
1033 char namestr[DNS_NAME_FORMATSIZE];
1035 dns_rdataset_init(&rdataset);
1036 dns_name_format(name, namestr, sizeof(namestr));
1039 * Determine if this is a delegation point.
1041 if (is_delegation(gdb, gversion, gorigin, name, node, NULL))
1042 isdelegation = ISC_TRUE;
1045 * Now iterate through the rdatasets.
1047 dns_diff_init(mctx, &del);
1048 dns_diff_init(mctx, &add);
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);
1056 /* If this is a RRSIG set, skip it. */
1057 if (rdataset.type == dns_rdatatype_rrsig)
1061 * If this name is a delegation point, skip all records
1062 * except NSEC and DS sets. Otherwise check that there
1063 * isn't a DS record.
1066 if (rdataset.type != nsec_datatype &&
1067 rdataset.type != dns_rdatatype_ds)
1069 } else if (rdataset.type == dns_rdatatype_ds) {
1070 char namebuf[DNS_NAME_FORMATSIZE];
1071 dns_name_format(name, namebuf, sizeof(namebuf));
1072 fatal("'%s': found DS RRset without NS RRset\n",
1076 signset(&del, &add, node, name, &rdataset);
1079 dns_rdataset_disassociate(&rdataset);
1080 result = dns_rdatasetiter_next(rdsiter);
1082 if (result != ISC_R_NOMORE)
1083 fatal("rdataset iteration for name '%s' failed: %s",
1084 namestr, isc_result_totext(result));
1086 dns_rdatasetiter_destroy(&rdsiter);
1088 result = dns_diff_applysilently(&del, gdb, gversion);
1089 if (result != ISC_R_SUCCESS)
1090 fatal("failed to delete SIGs at node '%s': %s",
1091 namestr, isc_result_totext(result));
1093 result = dns_diff_applysilently(&add, gdb, gversion);
1094 if (result != ISC_R_SUCCESS)
1095 fatal("failed to add SIGs at node '%s': %s",
1096 namestr, isc_result_totext(result));
1098 dns_diff_clear(&del);
1099 dns_diff_clear(&add);
1103 * See if the node contains any non RRSIG/NSEC records and report to
1104 * caller. Clean out extranous RRSIG records for node.
1106 static inline isc_boolean_t
1107 active_node(dns_dbnode_t *node) {
1108 dns_rdatasetiter_t *rdsiter = NULL;
1109 dns_rdatasetiter_t *rdsiter2 = NULL;
1110 isc_boolean_t active = ISC_FALSE;
1111 isc_result_t result;
1112 dns_rdataset_t rdataset;
1113 dns_rdatatype_t type;
1114 dns_rdatatype_t covers;
1115 isc_boolean_t found;
1117 dns_rdataset_init(&rdataset);
1118 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1119 check_result(result, "dns_db_allrdatasets()");
1120 result = dns_rdatasetiter_first(rdsiter);
1121 while (result == ISC_R_SUCCESS) {
1122 dns_rdatasetiter_current(rdsiter, &rdataset);
1123 if (rdataset.type != dns_rdatatype_nsec &&
1124 rdataset.type != dns_rdatatype_nsec3 &&
1125 rdataset.type != dns_rdatatype_rrsig)
1127 dns_rdataset_disassociate(&rdataset);
1129 result = dns_rdatasetiter_next(rdsiter);
1131 result = ISC_R_NOMORE;
1133 if (result != ISC_R_NOMORE)
1134 fatal("rdataset iteration failed: %s",
1135 isc_result_totext(result));
1137 if (!active && nsec_datatype == dns_rdatatype_nsec) {
1139 * The node is empty of everything but NSEC / RRSIG records.
1141 for (result = dns_rdatasetiter_first(rdsiter);
1142 result == ISC_R_SUCCESS;
1143 result = dns_rdatasetiter_next(rdsiter)) {
1144 dns_rdatasetiter_current(rdsiter, &rdataset);
1145 result = dns_db_deleterdataset(gdb, node, gversion,
1148 check_result(result, "dns_db_deleterdataset()");
1149 dns_rdataset_disassociate(&rdataset);
1151 if (result != ISC_R_NOMORE)
1152 fatal("rdataset iteration failed: %s",
1153 isc_result_totext(result));
1156 * Delete RRSIGs for types that no longer exist.
1158 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
1159 check_result(result, "dns_db_allrdatasets()");
1160 for (result = dns_rdatasetiter_first(rdsiter);
1161 result == ISC_R_SUCCESS;
1162 result = dns_rdatasetiter_next(rdsiter)) {
1163 dns_rdatasetiter_current(rdsiter, &rdataset);
1164 type = rdataset.type;
1165 covers = rdataset.covers;
1166 dns_rdataset_disassociate(&rdataset);
1168 * Delete the NSEC chain if we are signing with
1171 if (nsec_datatype == dns_rdatatype_nsec3 &&
1172 (type == dns_rdatatype_nsec ||
1173 covers == dns_rdatatype_nsec)) {
1174 result = dns_db_deleterdataset(gdb, node,
1177 check_result(result,
1178 "dns_db_deleterdataset(nsec/rrsig)");
1181 if (type != dns_rdatatype_rrsig)
1184 for (result = dns_rdatasetiter_first(rdsiter2);
1185 !found && result == ISC_R_SUCCESS;
1186 result = dns_rdatasetiter_next(rdsiter2)) {
1187 dns_rdatasetiter_current(rdsiter2, &rdataset);
1188 if (rdataset.type == covers)
1190 dns_rdataset_disassociate(&rdataset);
1193 if (result != ISC_R_NOMORE)
1194 fatal("rdataset iteration failed: %s",
1195 isc_result_totext(result));
1196 result = dns_db_deleterdataset(gdb, node,
1199 check_result(result,
1200 "dns_db_deleterdataset(rrsig)");
1201 } else if (result != ISC_R_NOMORE &&
1202 result != ISC_R_SUCCESS)
1203 fatal("rdataset iteration failed: %s",
1204 isc_result_totext(result));
1206 if (result != ISC_R_NOMORE)
1207 fatal("rdataset iteration failed: %s",
1208 isc_result_totext(result));
1209 dns_rdatasetiter_destroy(&rdsiter2);
1211 dns_rdatasetiter_destroy(&rdsiter);
1217 * Extracts the minimum TTL from the SOA record, and the SOA record's TTL.
1220 get_soa_ttls(void) {
1221 dns_rdataset_t soaset;
1222 dns_fixedname_t fname;
1224 isc_result_t result;
1225 dns_rdata_t rdata = DNS_RDATA_INIT;
1227 dns_fixedname_init(&fname);
1228 name = dns_fixedname_name(&fname);
1229 dns_rdataset_init(&soaset);
1230 result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
1231 0, 0, NULL, name, &soaset, NULL);
1232 if (result != ISC_R_SUCCESS)
1233 fatal("failed to find an SOA at the zone apex: %s",
1234 isc_result_totext(result));
1236 result = dns_rdataset_first(&soaset);
1237 check_result(result, "dns_rdataset_first");
1238 dns_rdataset_current(&soaset, &rdata);
1239 zone_soa_min_ttl = dns_soa_getminimum(&rdata);
1240 soa_ttl = soaset.ttl;
1241 dns_rdataset_disassociate(&soaset);
1245 * Increment (or set if nonzero) the SOA serial
1248 setsoaserial(isc_uint32_t serial) {
1249 isc_result_t result;
1250 dns_dbnode_t *node = NULL;
1251 dns_rdataset_t rdataset;
1252 dns_rdata_t rdata = DNS_RDATA_INIT;
1253 isc_uint32_t old_serial, new_serial;
1255 result = dns_db_getoriginnode(gdb, &node);
1256 if (result != ISC_R_SUCCESS)
1259 dns_rdataset_init(&rdataset);
1261 result = dns_db_findrdataset(gdb, node, gversion,
1262 dns_rdatatype_soa, 0,
1263 0, &rdataset, NULL);
1264 if (result != ISC_R_SUCCESS)
1267 result = dns_rdataset_first(&rdataset);
1268 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1270 dns_rdataset_current(&rdataset, &rdata);
1272 old_serial = dns_soa_getserial(&rdata);
1275 /* Set SOA serial to the value provided. */
1276 new_serial = serial;
1278 /* Increment SOA serial using RFC 1982 arithmetics */
1279 new_serial = (old_serial + 1) & 0xFFFFFFFF;
1280 if (new_serial == 0)
1284 /* If the new serial is not likely to cause a zone transfer
1285 * (a/ixfr) from servers having the old serial, warn the user.
1287 * RFC1982 section 7 defines the maximum increment to be
1288 * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
1289 * comparison. (5 - 6 == (2^32)-1, not negative-one)
1291 if (new_serial == old_serial ||
1292 (new_serial - old_serial) > 0x7fffffffU)
1293 fprintf(stderr, "%s: warning: Serial number not advanced, "
1294 "zone may not transfer\n", program);
1296 dns_soa_setserial(new_serial, &rdata);
1298 result = dns_db_deleterdataset(gdb, node, gversion,
1299 dns_rdatatype_soa, 0);
1300 check_result(result, "dns_db_deleterdataset");
1301 if (result != ISC_R_SUCCESS)
1304 result = dns_db_addrdataset(gdb, node, gversion,
1305 0, &rdataset, 0, NULL);
1306 check_result(result, "dns_db_addrdataset");
1307 if (result != ISC_R_SUCCESS)
1311 dns_rdataset_disassociate(&rdataset);
1313 dns_db_detachnode(gdb, &node);
1314 dns_rdata_reset(&rdata);
1320 * Delete any RRSIG records at a node.
1323 cleannode(dns_db_t *db, dns_dbversion_t *dbversion, dns_dbnode_t *node) {
1324 dns_rdatasetiter_t *rdsiter = NULL;
1326 isc_result_t result, dresult;
1328 if (outputformat != dns_masterformat_text || !disable_zone_check)
1331 dns_rdataset_init(&set);
1332 result = dns_db_allrdatasets(db, node, dbversion, 0, &rdsiter);
1333 check_result(result, "dns_db_allrdatasets");
1334 result = dns_rdatasetiter_first(rdsiter);
1335 while (result == ISC_R_SUCCESS) {
1336 isc_boolean_t destroy = ISC_FALSE;
1337 dns_rdatatype_t covers = 0;
1338 dns_rdatasetiter_current(rdsiter, &set);
1339 if (set.type == dns_rdatatype_rrsig) {
1340 covers = set.covers;
1343 dns_rdataset_disassociate(&set);
1344 result = dns_rdatasetiter_next(rdsiter);
1346 dresult = dns_db_deleterdataset(db, node, dbversion,
1347 dns_rdatatype_rrsig,
1349 check_result(dresult, "dns_db_deleterdataset");
1352 if (result != ISC_R_NOMORE)
1353 fatal("rdataset iteration failed: %s",
1354 isc_result_totext(result));
1355 dns_rdatasetiter_destroy(&rdsiter);
1359 * Set up the iterator and global state before starting the tasks.
1363 isc_result_t result;
1366 result = dns_db_createiterator(gdb, 0, &gdbiter);
1367 check_result(result, "dns_db_createiterator()");
1371 * Clean up the iterator and global state after the tasks complete.
1375 dns_dbiterator_destroy(&gdbiter);
1379 * Sign the apex of the zone.
1380 * Note the origin may not be the first node if there are out of zone
1385 dns_dbnode_t *node = NULL;
1386 dns_fixedname_t fixed;
1388 isc_result_t result;
1390 dns_fixedname_init(&fixed);
1391 name = dns_fixedname_name(&fixed);
1392 result = dns_dbiterator_seek(gdbiter, gorigin);
1393 check_result(result, "dns_dbiterator_seek()");
1394 result = dns_dbiterator_current(gdbiter, &node, name);
1395 check_dns_dbiterator_current(result);
1396 signname(node, name);
1397 dumpnode(name, node);
1398 cleannode(gdb, gversion, node);
1399 dns_db_detachnode(gdb, &node);
1400 result = dns_dbiterator_first(gdbiter);
1401 if (result == ISC_R_NOMORE)
1402 finished = ISC_TRUE;
1403 else if (result != ISC_R_SUCCESS)
1404 fatal("failure iterating database: %s",
1405 isc_result_totext(result));
1409 * Assigns a node to a worker thread. This is protected by the master task's
1413 assignwork(isc_task_t *task, isc_task_t *worker) {
1414 dns_fixedname_t *fname;
1418 dns_rdataset_t nsec;
1419 isc_boolean_t found;
1420 isc_result_t result;
1421 static dns_name_t *zonecut = NULL; /* Protected by namelock. */
1422 static dns_fixedname_t fzonecut; /* Protected by namelock. */
1423 static unsigned int ended = 0; /* Protected by namelock. */
1431 if (ended == ntasks) {
1432 isc_task_detach(&task);
1438 fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
1440 fatal("out of memory");
1441 dns_fixedname_init(fname);
1442 name = dns_fixedname_name(fname);
1446 result = dns_dbiterator_current(gdbiter, &node, name);
1447 check_dns_dbiterator_current(result);
1449 * The origin was handled by signapex().
1451 if (dns_name_equal(name, gorigin)) {
1452 dns_db_detachnode(gdb, &node);
1456 * Sort the zone data from the glue and out-of-zone data.
1457 * For NSEC zones nodes with zone data have NSEC records.
1458 * For NSEC3 zones the NSEC3 nodes are zone data but
1459 * outside of the zone name space. For the rest we need
1460 * to track the bottom of zone cuts.
1461 * Nodes which don't need to be signed are dumped here.
1463 dns_rdataset_init(&nsec);
1464 result = dns_db_findrdataset(gdb, node, gversion,
1465 nsec_datatype, 0, 0,
1467 if (dns_rdataset_isassociated(&nsec))
1468 dns_rdataset_disassociate(&nsec);
1469 if (result == ISC_R_SUCCESS) {
1471 } else if (nsec_datatype == dns_rdatatype_nsec3) {
1472 if (dns_name_issubdomain(name, gorigin) &&
1474 !dns_name_issubdomain(name, zonecut))) {
1475 if (is_delegation(gdb, gversion, gorigin, name, node, NULL)) {
1476 dns_fixedname_init(&fzonecut);
1477 zonecut = dns_fixedname_name(&fzonecut);
1478 dns_name_copy(name, zonecut, NULL);
1479 if (!OPTOUT(nsec3flags) ||
1488 dumpnode(name, node);
1489 dns_db_detachnode(gdb, &node);
1493 result = dns_dbiterator_next(gdbiter);
1494 if (result == ISC_R_NOMORE) {
1495 finished = ISC_TRUE;
1497 } else if (result != ISC_R_SUCCESS)
1498 fatal("failure iterating database: %s",
1499 isc_result_totext(result));
1503 if (ended == ntasks) {
1504 isc_task_detach(&task);
1507 isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
1510 sevent = (sevent_t *)
1511 isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
1512 sign, NULL, sizeof(sevent_t));
1514 fatal("failed to allocate event\n");
1516 sevent->node = node;
1517 sevent->fname = fname;
1518 isc_task_send(worker, ISC_EVENT_PTR(&sevent));
1524 * Start a worker task
1527 startworker(isc_task_t *task, isc_event_t *event) {
1530 worker = (isc_task_t *)event->ev_arg;
1531 assignwork(task, worker);
1532 isc_event_free(&event);
1536 * Write a node to the output file, and restart the worker task.
1539 writenode(isc_task_t *task, isc_event_t *event) {
1541 sevent_t *sevent = (sevent_t *)event;
1543 worker = (isc_task_t *)event->ev_sender;
1544 dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
1545 cleannode(gdb, gversion, sevent->node);
1546 dns_db_detachnode(gdb, &sevent->node);
1547 isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
1548 assignwork(task, worker);
1549 isc_event_free(&event);
1553 * Sign a database node.
1556 sign(isc_task_t *task, isc_event_t *event) {
1557 dns_fixedname_t *fname;
1559 sevent_t *sevent, *wevent;
1561 sevent = (sevent_t *)event;
1562 node = sevent->node;
1563 fname = sevent->fname;
1564 isc_event_free(&event);
1566 signname(node, dns_fixedname_name(fname));
1567 wevent = (sevent_t *)
1568 isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
1569 writenode, NULL, sizeof(sevent_t));
1571 fatal("failed to allocate event\n");
1572 wevent->node = node;
1573 wevent->fname = fname;
1574 isc_task_send(master, ISC_EVENT_PTR(&wevent));
1578 * Update / remove the DS RRset. Preserve RRSIG(DS) if possible.
1581 add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) {
1582 dns_rdataset_t dsset;
1583 dns_rdataset_t sigdsset;
1584 isc_result_t result;
1586 dns_rdataset_init(&dsset);
1587 dns_rdataset_init(&sigdsset);
1588 result = dns_db_findrdataset(gdb, node, gversion,
1590 0, 0, &dsset, &sigdsset);
1591 if (result == ISC_R_SUCCESS) {
1592 dns_rdataset_disassociate(&dsset);
1593 result = dns_db_deleterdataset(gdb, node, gversion,
1594 dns_rdatatype_ds, 0);
1595 check_result(result, "dns_db_deleterdataset");
1598 result = loadds(name, nsttl, &dsset);
1599 if (result == ISC_R_SUCCESS) {
1600 result = dns_db_addrdataset(gdb, node, gversion, 0,
1602 check_result(result, "dns_db_addrdataset");
1603 dns_rdataset_disassociate(&dsset);
1604 if (dns_rdataset_isassociated(&sigdsset))
1605 dns_rdataset_disassociate(&sigdsset);
1606 } else if (dns_rdataset_isassociated(&sigdsset)) {
1607 result = dns_db_deleterdataset(gdb, node, gversion,
1608 dns_rdatatype_rrsig,
1610 check_result(result, "dns_db_deleterdataset");
1611 dns_rdataset_disassociate(&sigdsset);
1616 * Remove records of the given type and their signatures.
1619 remove_records(dns_dbnode_t *node, dns_rdatatype_t which,
1620 isc_boolean_t checknsec)
1622 isc_result_t result;
1623 dns_rdatatype_t type, covers;
1624 dns_rdatasetiter_t *rdsiter = NULL;
1625 dns_rdataset_t rdataset;
1627 dns_rdataset_init(&rdataset);
1630 * Delete any records of the given type at the apex.
1632 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1633 check_result(result, "dns_db_allrdatasets()");
1634 for (result = dns_rdatasetiter_first(rdsiter);
1635 result == ISC_R_SUCCESS;
1636 result = dns_rdatasetiter_next(rdsiter)) {
1637 dns_rdatasetiter_current(rdsiter, &rdataset);
1638 type = rdataset.type;
1639 covers = rdataset.covers;
1640 dns_rdataset_disassociate(&rdataset);
1641 if (type == which || covers == which) {
1642 if (which == dns_rdatatype_nsec &&
1643 checknsec && !update_chain)
1644 fatal("Zone contains NSEC records. Use -u "
1645 "to update to NSEC3.");
1646 if (which == dns_rdatatype_nsec3param &&
1647 checknsec && !update_chain)
1648 fatal("Zone contains NSEC3 chains. Use -u "
1649 "to update to NSEC.");
1650 result = dns_db_deleterdataset(gdb, node, gversion,
1652 check_result(result, "dns_db_deleterdataset()");
1656 dns_rdatasetiter_destroy(&rdsiter);
1660 * Remove signatures covering the given type. If type == 0,
1661 * then remove all signatures, unless this is a delegation, in
1662 * which case remove all signatures except for DS or nsec_datatype
1665 remove_sigs(dns_dbnode_t *node, isc_boolean_t delegation,
1666 dns_rdatatype_t which)
1668 isc_result_t result;
1669 dns_rdatatype_t type, covers;
1670 dns_rdatasetiter_t *rdsiter = NULL;
1671 dns_rdataset_t rdataset;
1673 dns_rdataset_init(&rdataset);
1674 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1675 check_result(result, "dns_db_allrdatasets()");
1676 for (result = dns_rdatasetiter_first(rdsiter);
1677 result == ISC_R_SUCCESS;
1678 result = dns_rdatasetiter_next(rdsiter)) {
1679 dns_rdatasetiter_current(rdsiter, &rdataset);
1680 type = rdataset.type;
1681 covers = rdataset.covers;
1682 dns_rdataset_disassociate(&rdataset);
1684 if (type != dns_rdatatype_rrsig)
1687 if (which == 0 && delegation &&
1688 (dns_rdatatype_atparent(covers) ||
1689 (nsec_datatype == dns_rdatatype_nsec &&
1690 covers == nsec_datatype)))
1693 if (which != 0 && covers != which)
1696 result = dns_db_deleterdataset(gdb, node, gversion,
1698 check_result(result, "dns_db_deleterdataset()");
1700 dns_rdatasetiter_destroy(&rdsiter);
1704 * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records.
1708 dns_dbiterator_t *dbiter = NULL;
1709 dns_dbnode_t *node = NULL, *nextnode = NULL;
1710 dns_fixedname_t fname, fnextname, fzonecut;
1711 dns_name_t *name, *nextname, *zonecut;
1712 dns_rdataset_t rdataset;
1713 dns_rdatasetiter_t *rdsiter = NULL;
1714 dns_rdatatype_t type, covers;
1715 isc_boolean_t done = ISC_FALSE;
1716 isc_result_t result;
1717 isc_uint32_t nsttl = 0;
1719 dns_rdataset_init(&rdataset);
1720 dns_fixedname_init(&fname);
1721 name = dns_fixedname_name(&fname);
1722 dns_fixedname_init(&fnextname);
1723 nextname = dns_fixedname_name(&fnextname);
1724 dns_fixedname_init(&fzonecut);
1728 * Remove any NSEC3 chains.
1730 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
1731 check_result(result, "dns_db_createiterator()");
1732 for (result = dns_dbiterator_first(dbiter);
1733 result == ISC_R_SUCCESS;
1734 result = dns_dbiterator_next(dbiter)) {
1735 result = dns_dbiterator_current(dbiter, &node, name);
1736 check_dns_dbiterator_current(result);
1737 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1738 check_result(result, "dns_db_allrdatasets()");
1739 for (result = dns_rdatasetiter_first(rdsiter);
1740 result == ISC_R_SUCCESS;
1741 result = dns_rdatasetiter_next(rdsiter)) {
1742 dns_rdatasetiter_current(rdsiter, &rdataset);
1743 type = rdataset.type;
1744 covers = rdataset.covers;
1745 dns_rdataset_disassociate(&rdataset);
1746 result = dns_db_deleterdataset(gdb, node, gversion,
1748 check_result(result,
1749 "dns_db_deleterdataset(nsec3param/rrsig)");
1751 dns_rdatasetiter_destroy(&rdsiter);
1752 dns_db_detachnode(gdb, &node);
1754 dns_dbiterator_destroy(&dbiter);
1756 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
1757 check_result(result, "dns_db_createiterator()");
1759 result = dns_dbiterator_first(dbiter);
1760 check_result(result, "dns_dbiterator_first()");
1763 result = dns_dbiterator_current(dbiter, &node, name);
1764 check_dns_dbiterator_current(result);
1766 * Skip out-of-zone records.
1768 if (!dns_name_issubdomain(name, gorigin)) {
1769 result = dns_dbiterator_next(dbiter);
1770 if (result == ISC_R_NOMORE)
1773 check_result(result, "dns_dbiterator_next()");
1774 dns_db_detachnode(gdb, &node);
1778 if (dns_name_equal(name, gorigin)) {
1779 remove_records(node, dns_rdatatype_nsec3param,
1781 /* Clean old rrsigs at apex. */
1782 (void)active_node(node);
1785 if (is_delegation(gdb, gversion, gorigin, name, node, &nsttl)) {
1786 zonecut = dns_fixedname_name(&fzonecut);
1787 dns_name_copy(name, zonecut, NULL);
1788 remove_sigs(node, ISC_TRUE, 0);
1790 add_ds(name, node, nsttl);
1793 result = dns_dbiterator_next(dbiter);
1795 while (result == ISC_R_SUCCESS) {
1796 isc_boolean_t active = ISC_FALSE;
1797 result = dns_dbiterator_current(dbiter, &nextnode,
1799 check_dns_dbiterator_current(result);
1800 active = active_node(nextnode);
1802 dns_db_detachnode(gdb, &nextnode);
1803 result = dns_dbiterator_next(dbiter);
1806 if (!dns_name_issubdomain(nextname, gorigin) ||
1808 dns_name_issubdomain(nextname, zonecut)))
1810 remove_sigs(nextnode, ISC_FALSE, 0);
1811 remove_records(nextnode, dns_rdatatype_nsec,
1813 dns_db_detachnode(gdb, &nextnode);
1814 result = dns_dbiterator_next(dbiter);
1817 dns_db_detachnode(gdb, &nextnode);
1820 if (result == ISC_R_NOMORE) {
1821 dns_name_clone(gorigin, nextname);
1823 } else if (result != ISC_R_SUCCESS)
1824 fatal("iterating through the database failed: %s",
1825 isc_result_totext(result));
1826 dns_dbiterator_pause(dbiter);
1827 result = dns_nsec_build(gdb, gversion, node, nextname,
1829 check_result(result, "dns_nsec_build()");
1830 dns_db_detachnode(gdb, &node);
1833 dns_dbiterator_destroy(&dbiter);
1837 addnsec3param(const unsigned char *salt, size_t salt_len,
1838 dns_iterations_t iterations)
1840 dns_dbnode_t *node = NULL;
1841 dns_rdata_nsec3param_t nsec3param;
1842 unsigned char nsec3parambuf[5 + 255];
1843 dns_rdatalist_t rdatalist;
1844 dns_rdataset_t rdataset;
1845 dns_rdata_t rdata = DNS_RDATA_INIT;
1847 isc_result_t result;
1849 dns_rdataset_init(&rdataset);
1851 nsec3param.common.rdclass = gclass;
1852 nsec3param.common.rdtype = dns_rdatatype_nsec3param;
1853 ISC_LINK_INIT(&nsec3param.common, link);
1854 nsec3param.mctx = NULL;
1855 nsec3param.flags = 0;
1856 nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1;
1857 nsec3param.iterations = iterations;
1858 nsec3param.salt_length = (unsigned char)salt_len;
1859 DE_CONST(salt, nsec3param.salt);
1861 isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf));
1862 result = dns_rdata_fromstruct(&rdata, gclass,
1863 dns_rdatatype_nsec3param,
1865 check_result(result, "dns_rdata_fromstruct()");
1866 dns_rdatalist_init(&rdatalist);
1867 rdatalist.rdclass = rdata.rdclass;
1868 rdatalist.type = rdata.type;
1869 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
1870 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
1871 check_result(result, "dns_rdatalist_tordataset()");
1873 result = dns_db_findnode(gdb, gorigin, ISC_TRUE, &node);
1874 check_result(result, "dns_db_find(gorigin)");
1877 * Delete any current NSEC3PARAM records.
1879 result = dns_db_deleterdataset(gdb, node, gversion,
1880 dns_rdatatype_nsec3param, 0);
1881 if (result == DNS_R_UNCHANGED)
1882 result = ISC_R_SUCCESS;
1883 check_result(result, "dddnsec3param: dns_db_deleterdataset()");
1885 result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset,
1886 DNS_DBADD_MERGE, NULL);
1887 if (result == DNS_R_UNCHANGED)
1888 result = ISC_R_SUCCESS;
1889 check_result(result, "addnsec3param: dns_db_addrdataset()");
1890 dns_db_detachnode(gdb, &node);
1894 addnsec3(dns_name_t *name, dns_dbnode_t *node,
1895 const unsigned char *salt, size_t salt_len,
1896 unsigned int iterations, hashlist_t *hashlist,
1899 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
1900 const unsigned char *nexthash;
1901 unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE];
1902 dns_fixedname_t hashname;
1903 dns_rdatalist_t rdatalist;
1904 dns_rdataset_t rdataset;
1905 dns_rdata_t rdata = DNS_RDATA_INIT;
1906 isc_result_t result;
1907 dns_dbnode_t *nsec3node = NULL;
1908 char namebuf[DNS_NAME_FORMATSIZE];
1911 dns_name_format(name, namebuf, sizeof(namebuf));
1913 dns_fixedname_init(&hashname);
1914 dns_rdataset_init(&rdataset);
1916 dns_name_downcase(name, name, NULL);
1917 result = dns_nsec3_hashname(&hashname, hash, &hash_len,
1918 name, gorigin, dns_hash_sha1, iterations,
1920 check_result(result, "addnsec3: dns_nsec3_hashname()");
1921 nexthash = hashlist_findnext(hashlist, hash);
1922 result = dns_nsec3_buildrdata(gdb, gversion, node,
1924 DNS_NSEC3_UNKNOWNALG : dns_hash_sha1,
1925 nsec3flags, iterations,
1927 nexthash, ISC_SHA1_DIGESTLENGTH,
1928 nsec3buffer, &rdata);
1929 check_result(result, "addnsec3: dns_nsec3_buildrdata()");
1930 dns_rdatalist_init(&rdatalist);
1931 rdatalist.rdclass = rdata.rdclass;
1932 rdatalist.type = rdata.type;
1933 rdatalist.ttl = ttl;
1934 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
1935 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
1936 check_result(result, "dns_rdatalist_tordataset()");
1937 result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname),
1938 ISC_TRUE, &nsec3node);
1939 check_result(result, "addnsec3: dns_db_findnode()");
1940 result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset,
1942 if (result == DNS_R_UNCHANGED)
1943 result = ISC_R_SUCCESS;
1944 check_result(result, "addnsec3: dns_db_addrdataset()");
1945 dns_db_detachnode(gdb, &nsec3node);
1949 * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list.
1951 * Extract the hash from the first label of 'name' then see if it
1952 * is in hashlist. If 'name' is not in the hashlist then delete the
1953 * any NSEC3 records which have the same parameters as the chain we
1956 * XXXMPA Should we also check that it of the form <hash>.<origin>?
1959 nsec3clean(dns_name_t *name, dns_dbnode_t *node,
1960 unsigned int hashalg, unsigned int iterations,
1961 const unsigned char *salt, size_t salt_len, hashlist_t *hashlist)
1964 dns_rdata_nsec3_t nsec3;
1965 dns_rdata_t rdata, delrdata;
1966 dns_rdatalist_t rdatalist;
1967 dns_rdataset_t rdataset, delrdataset;
1968 isc_boolean_t delete_rrsigs = ISC_FALSE;
1969 isc_buffer_t target;
1970 isc_result_t result;
1971 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
1972 isc_boolean_t exists;
1975 * Get the first label.
1977 dns_name_getlabel(name, 0, &label);
1980 * We want just the label contents.
1982 isc_region_consume(&label, 1);
1985 * Decode base32hex string.
1987 isc_buffer_init(&target, hash, sizeof(hash) - 1);
1988 result = isc_base32hex_decoderegion(&label, &target);
1989 if (result != ISC_R_SUCCESS)
1992 hash[isc_buffer_usedlength(&target)] = 0;
1994 exists = hashlist_exists(hashlist, hash);
1997 * Verify that the NSEC3 parameters match the current ones
1998 * otherwise we are dealing with a different NSEC3 chain.
2000 dns_rdataset_init(&rdataset);
2001 dns_rdataset_init(&delrdataset);
2003 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3,
2004 0, 0, &rdataset, NULL);
2005 if (result != ISC_R_SUCCESS)
2009 * Delete any NSEC3 records which are not part of the current
2012 for (result = dns_rdataset_first(&rdataset);
2013 result == ISC_R_SUCCESS;
2014 result = dns_rdataset_next(&rdataset)) {
2015 dns_rdata_init(&rdata);
2016 dns_rdataset_current(&rdataset, &rdata);
2017 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
2018 check_result(result, "dns_rdata_tostruct");
2019 if (exists && nsec3.hash == hashalg &&
2020 nsec3.iterations == iterations &&
2021 nsec3.salt_length == salt_len &&
2022 isc_safe_memequal(nsec3.salt, salt, salt_len))
2024 dns_rdatalist_init(&rdatalist);
2025 rdatalist.rdclass = rdata.rdclass;
2026 rdatalist.type = rdata.type;
2027 rdatalist.ttl = rdataset.ttl;
2028 dns_rdata_init(&delrdata);
2029 dns_rdata_clone(&rdata, &delrdata);
2030 ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link);
2031 result = dns_rdatalist_tordataset(&rdatalist, &delrdataset);
2032 check_result(result, "dns_rdatalist_tordataset()");
2033 result = dns_db_subtractrdataset(gdb, node, gversion,
2034 &delrdataset, 0, NULL);
2035 dns_rdataset_disassociate(&delrdataset);
2036 if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET)
2037 check_result(result, "dns_db_subtractrdataset(NSEC3)");
2038 delete_rrsigs = ISC_TRUE;
2040 dns_rdataset_disassociate(&rdataset);
2041 if (result != ISC_R_NOMORE)
2042 check_result(result, "dns_rdataset_first/next");
2047 * Delete the NSEC3 RRSIGs
2049 result = dns_db_deleterdataset(gdb, node, gversion,
2050 dns_rdatatype_rrsig,
2051 dns_rdatatype_nsec3);
2052 if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
2053 check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))");
2057 rrset_remove_duplicates(dns_name_t *name, dns_rdataset_t *rdataset,
2060 dns_difftuple_t *tuple = NULL;
2061 isc_result_t result;
2062 unsigned int count1 = 0;
2063 dns_rdataset_t tmprdataset;
2065 dns_rdataset_init(&tmprdataset);
2066 for (result = dns_rdataset_first(rdataset);
2067 result == ISC_R_SUCCESS;
2068 result = dns_rdataset_next(rdataset)) {
2069 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2070 unsigned int count2 = 0;
2073 dns_rdataset_current(rdataset, &rdata1);
2074 dns_rdataset_clone(rdataset, &tmprdataset);
2075 for (result = dns_rdataset_first(&tmprdataset);
2076 result == ISC_R_SUCCESS;
2077 result = dns_rdataset_next(&tmprdataset)) {
2078 dns_rdata_t rdata2 = DNS_RDATA_INIT;
2080 if (count1 >= count2)
2082 dns_rdataset_current(&tmprdataset, &rdata2);
2083 if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2084 result = dns_difftuple_create(mctx,
2089 check_result(result, "dns_difftuple_create");
2090 dns_diff_append(diff, &tuple);
2093 dns_rdataset_disassociate(&tmprdataset);
2098 remove_duplicates(void) {
2099 isc_result_t result;
2100 dns_dbiterator_t *dbiter = NULL;
2101 dns_rdatasetiter_t *rdsiter = NULL;
2103 dns_dbnode_t *node = NULL;
2104 dns_rdataset_t rdataset;
2105 dns_fixedname_t fname;
2108 dns_diff_init(mctx, &diff);
2109 dns_fixedname_init(&fname);
2110 name = dns_fixedname_name(&fname);
2111 dns_rdataset_init(&rdataset);
2113 result = dns_db_createiterator(gdb, 0, &dbiter);
2114 check_result(result, "dns_db_createiterator()");
2116 for (result = dns_dbiterator_first(dbiter);
2117 result == ISC_R_SUCCESS;
2118 result = dns_dbiterator_next(dbiter)) {
2120 result = dns_dbiterator_current(dbiter, &node, name);
2121 check_dns_dbiterator_current(result);
2122 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
2123 check_result(result, "dns_db_allrdatasets()");
2124 for (result = dns_rdatasetiter_first(rdsiter);
2125 result == ISC_R_SUCCESS;
2126 result = dns_rdatasetiter_next(rdsiter)) {
2127 dns_rdatasetiter_current(rdsiter, &rdataset);
2128 rrset_remove_duplicates(name, &rdataset, &diff);
2129 dns_rdataset_disassociate(&rdataset);
2131 if (result != ISC_R_NOMORE)
2132 fatal("rdatasets iteration failed.");
2133 dns_rdatasetiter_destroy(&rdsiter);
2134 dns_db_detachnode(gdb, &node);
2136 if (result != ISC_R_NOMORE)
2137 fatal("zone iteration failed.");
2139 if (!ISC_LIST_EMPTY(diff.tuples)) {
2140 result = dns_diff_applysilently(&diff, gdb, gversion);
2141 check_result(result, "dns_diff_applysilently");
2143 dns_diff_clear(&diff);
2144 dns_dbiterator_destroy(&dbiter);
2148 * Generate NSEC3 records for the zone.
2151 nsec3ify(unsigned int hashalg, dns_iterations_t iterations,
2152 const unsigned char *salt, size_t salt_len, hashlist_t *hashlist)
2154 dns_dbiterator_t *dbiter = NULL;
2155 dns_dbnode_t *node = NULL, *nextnode = NULL;
2156 dns_fixedname_t fname, fnextname, fzonecut;
2157 dns_name_t *name, *nextname, *zonecut;
2158 dns_rdataset_t rdataset;
2160 isc_boolean_t active;
2161 isc_boolean_t done = ISC_FALSE;
2162 isc_result_t result;
2163 isc_uint32_t nsttl = 0;
2164 unsigned int count, nlabels;
2166 dns_rdataset_init(&rdataset);
2167 dns_fixedname_init(&fname);
2168 name = dns_fixedname_name(&fname);
2169 dns_fixedname_init(&fnextname);
2170 nextname = dns_fixedname_name(&fnextname);
2171 dns_fixedname_init(&fzonecut);
2175 * Walk the zone generating the hash names.
2177 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2178 check_result(result, "dns_db_createiterator()");
2180 result = dns_dbiterator_first(dbiter);
2181 check_result(result, "dns_dbiterator_first()");
2184 result = dns_dbiterator_current(dbiter, &node, name);
2185 check_dns_dbiterator_current(result);
2187 * Skip out-of-zone records.
2189 if (!dns_name_issubdomain(name, gorigin)) {
2190 result = dns_dbiterator_next(dbiter);
2191 if (result == ISC_R_NOMORE)
2194 check_result(result, "dns_dbiterator_next()");
2195 dns_db_detachnode(gdb, &node);
2199 if (dns_name_equal(name, gorigin)) {
2200 remove_records(node, dns_rdatatype_nsec, ISC_TRUE);
2201 /* Clean old rrsigs at apex. */
2202 (void)active_node(node);
2205 result = dns_dbiterator_next(dbiter);
2207 while (result == ISC_R_SUCCESS) {
2208 result = dns_dbiterator_current(dbiter, &nextnode,
2210 check_dns_dbiterator_current(result);
2211 active = active_node(nextnode);
2213 dns_db_detachnode(gdb, &nextnode);
2214 result = dns_dbiterator_next(dbiter);
2217 if (!dns_name_issubdomain(nextname, gorigin) ||
2219 dns_name_issubdomain(nextname, zonecut))) {
2220 remove_sigs(nextnode, ISC_FALSE, 0);
2221 dns_db_detachnode(gdb, &nextnode);
2222 result = dns_dbiterator_next(dbiter);
2225 if (is_delegation(gdb, gversion, gorigin,
2226 nextname, nextnode, &nsttl))
2228 zonecut = dns_fixedname_name(&fzonecut);
2229 dns_name_copy(nextname, zonecut, NULL);
2230 remove_sigs(nextnode, ISC_TRUE, 0);
2232 add_ds(nextname, nextnode, nsttl);
2233 if (OPTOUT(nsec3flags) &&
2234 !secure(nextname, nextnode)) {
2235 dns_db_detachnode(gdb, &nextnode);
2236 result = dns_dbiterator_next(dbiter);
2240 dns_db_detachnode(gdb, &nextnode);
2243 if (result == ISC_R_NOMORE) {
2244 dns_name_copy(gorigin, nextname, NULL);
2246 } else if (result != ISC_R_SUCCESS)
2247 fatal("iterating through the database failed: %s",
2248 isc_result_totext(result));
2249 dns_name_downcase(name, name, NULL);
2250 hashlist_add_dns_name(hashlist, name, hashalg, iterations,
2251 salt, salt_len, ISC_FALSE);
2252 dns_db_detachnode(gdb, &node);
2254 * Add hashs for empty nodes. Use closest encloser logic.
2255 * The closest encloser either has data or is a empty
2256 * node for another <name,nextname> span so we don't add
2257 * it here. Empty labels on nextname are within the span.
2259 dns_name_downcase(nextname, nextname, NULL);
2260 dns_name_fullcompare(name, nextname, &order, &nlabels);
2261 addnowildcardhash(hashlist, name, hashalg, iterations,
2263 count = dns_name_countlabels(nextname);
2264 while (count > nlabels + 1) {
2266 dns_name_split(nextname, count, NULL, nextname);
2267 hashlist_add_dns_name(hashlist, nextname, hashalg,
2268 iterations, salt, salt_len,
2270 addnowildcardhash(hashlist, nextname, hashalg,
2271 iterations, salt, salt_len);
2274 dns_dbiterator_destroy(&dbiter);
2277 * We have all the hashes now so we can sort them.
2279 hashlist_sort(hashlist);
2282 * Check for duplicate hashes. If found the salt needs to
2285 if (hashlist_hasdup(hashlist))
2286 fatal("Duplicate hash detected. Pick a different salt.");
2289 * Generate the nsec3 records.
2294 addnsec3param(salt, salt_len, iterations);
2297 * Clean out NSEC3 records which don't match this chain.
2299 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
2300 check_result(result, "dns_db_createiterator()");
2302 for (result = dns_dbiterator_first(dbiter);
2303 result == ISC_R_SUCCESS;
2304 result = dns_dbiterator_next(dbiter)) {
2305 result = dns_dbiterator_current(dbiter, &node, name);
2306 check_dns_dbiterator_current(result);
2307 nsec3clean(name, node, hashalg, iterations, salt, salt_len,
2309 dns_db_detachnode(gdb, &node);
2311 dns_dbiterator_destroy(&dbiter);
2314 * Generate / complete the new chain.
2316 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2317 check_result(result, "dns_db_createiterator()");
2319 result = dns_dbiterator_first(dbiter);
2320 check_result(result, "dns_dbiterator_first()");
2323 result = dns_dbiterator_current(dbiter, &node, name);
2324 check_dns_dbiterator_current(result);
2326 * Skip out-of-zone records.
2328 if (!dns_name_issubdomain(name, gorigin)) {
2329 result = dns_dbiterator_next(dbiter);
2330 if (result == ISC_R_NOMORE)
2333 check_result(result, "dns_dbiterator_next()");
2334 dns_db_detachnode(gdb, &node);
2337 result = dns_dbiterator_next(dbiter);
2339 while (result == ISC_R_SUCCESS) {
2340 result = dns_dbiterator_current(dbiter, &nextnode,
2342 check_dns_dbiterator_current(result);
2343 active = active_node(nextnode);
2345 dns_db_detachnode(gdb, &nextnode);
2346 result = dns_dbiterator_next(dbiter);
2349 if (!dns_name_issubdomain(nextname, gorigin) ||
2351 dns_name_issubdomain(nextname, zonecut))) {
2352 dns_db_detachnode(gdb, &nextnode);
2353 result = dns_dbiterator_next(dbiter);
2356 if (is_delegation(gdb, gversion, gorigin,
2357 nextname, nextnode, NULL))
2359 zonecut = dns_fixedname_name(&fzonecut);
2360 dns_name_copy(nextname, zonecut, NULL);
2361 if (OPTOUT(nsec3flags) &&
2362 !secure(nextname, nextnode)) {
2363 dns_db_detachnode(gdb, &nextnode);
2364 result = dns_dbiterator_next(dbiter);
2368 dns_db_detachnode(gdb, &nextnode);
2371 if (result == ISC_R_NOMORE) {
2372 dns_name_copy(gorigin, nextname, NULL);
2374 } else if (result != ISC_R_SUCCESS)
2375 fatal("iterating through the database failed: %s",
2376 isc_result_totext(result));
2378 * We need to pause here to release the lock on the database.
2380 dns_dbiterator_pause(dbiter);
2381 addnsec3(name, node, salt, salt_len, iterations,
2382 hashlist, zone_soa_min_ttl);
2383 dns_db_detachnode(gdb, &node);
2385 * Add NSEC3's for empty nodes. Use closest encloser logic.
2387 dns_name_fullcompare(name, nextname, &order, &nlabels);
2388 count = dns_name_countlabels(nextname);
2389 while (count > nlabels + 1) {
2391 dns_name_split(nextname, count, NULL, nextname);
2392 addnsec3(nextname, NULL, salt, salt_len,
2393 iterations, hashlist, zone_soa_min_ttl);
2396 dns_dbiterator_destroy(&dbiter);
2400 * Load the zone file from disk
2403 loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
2406 dns_fixedname_t fname;
2408 isc_result_t result;
2410 len = strlen(origin);
2411 isc_buffer_init(&b, origin, len);
2412 isc_buffer_add(&b, len);
2414 dns_fixedname_init(&fname);
2415 name = dns_fixedname_name(&fname);
2416 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
2417 if (result != ISC_R_SUCCESS)
2418 fatal("failed converting name '%s' to dns format: %s",
2419 origin, isc_result_totext(result));
2421 result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
2422 rdclass, 0, NULL, db);
2423 check_result(result, "dns_db_create()");
2425 result = dns_db_load2(*db, file, inputformat);
2426 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
2427 fatal("failed loading zone from '%s': %s",
2428 file, isc_result_totext(result));
2432 * Finds all public zone keys in the zone, and attempts to load the
2433 * private keys from disk.
2436 loadzonekeys(isc_boolean_t preserve_keys, isc_boolean_t load_public) {
2438 dns_dbversion_t *currentversion = NULL;
2439 isc_result_t result;
2440 dns_rdataset_t rdataset, keysigs, soasigs;
2443 result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node);
2444 if (result != ISC_R_SUCCESS)
2445 fatal("failed to find the zone's origin: %s",
2446 isc_result_totext(result));
2448 dns_db_currentversion(gdb, ¤tversion);
2450 dns_rdataset_init(&rdataset);
2451 dns_rdataset_init(&soasigs);
2452 dns_rdataset_init(&keysigs);
2454 /* Make note of the keys which signed the SOA, if any */
2455 result = dns_db_findrdataset(gdb, node, currentversion,
2456 dns_rdatatype_soa, 0, 0,
2457 &rdataset, &soasigs);
2458 if (result != ISC_R_SUCCESS)
2461 /* Preserve the TTL of the DNSKEY RRset, if any */
2462 dns_rdataset_disassociate(&rdataset);
2463 result = dns_db_findrdataset(gdb, node, currentversion,
2464 dns_rdatatype_dnskey, 0, 0,
2465 &rdataset, &keysigs);
2467 if (result != ISC_R_SUCCESS)
2470 if (set_keyttl && keyttl != rdataset.ttl) {
2471 fprintf(stderr, "User-specified TTL (%d) conflicts "
2472 "with existing DNSKEY RRset TTL.\n",
2474 fprintf(stderr, "Imported keys will use the RRSet "
2475 "TTL (%d) instead.\n",
2478 keyttl = rdataset.ttl;
2480 /* Load keys corresponding to the existing DNSKEY RRset. */
2481 result = dns_dnssec_keylistfromrdataset(gorigin, directory, mctx,
2482 &rdataset, &keysigs, &soasigs,
2483 preserve_keys, load_public,
2485 if (result != ISC_R_SUCCESS)
2486 fatal("failed to load the zone keys: %s",
2487 isc_result_totext(result));
2490 if (dns_rdataset_isassociated(&rdataset))
2491 dns_rdataset_disassociate(&rdataset);
2492 if (dns_rdataset_isassociated(&keysigs))
2493 dns_rdataset_disassociate(&keysigs);
2494 if (dns_rdataset_isassociated(&soasigs))
2495 dns_rdataset_disassociate(&soasigs);
2496 dns_db_detachnode(gdb, &node);
2497 dns_db_closeversion(gdb, ¤tversion, ISC_FALSE);
2501 loadexplicitkeys(char *keyfiles[], int n, isc_boolean_t setksk) {
2502 isc_result_t result;
2505 for (i = 0; i < n; i++) {
2506 dns_dnsseckey_t *key = NULL;
2507 dst_key_t *newkey = NULL;
2509 result = dst_key_fromnamedfile(keyfiles[i], directory,
2513 if (result != ISC_R_SUCCESS)
2514 fatal("cannot load dnskey %s: %s", keyfiles[i],
2515 isc_result_totext(result));
2517 if (!dns_name_equal(gorigin, dst_key_name(newkey)))
2518 fatal("key %s not at origin\n", keyfiles[i]);
2520 if (!dst_key_isprivate(newkey))
2521 fatal("cannot sign zone with non-private dnskey %s",
2524 /* Skip any duplicates */
2525 for (key = ISC_LIST_HEAD(keylist);
2527 key = ISC_LIST_NEXT(key, link)) {
2528 if (dst_key_id(key->key) == dst_key_id(newkey) &&
2529 dst_key_alg(key->key) == dst_key_alg(newkey))
2534 /* We haven't seen this key before */
2535 dns_dnsseckey_create(mctx, &newkey, &key);
2536 ISC_LIST_APPEND(keylist, key, link);
2537 key->source = dns_keysource_user;
2539 dst_key_free(&key->key);
2543 key->force_publish = ISC_TRUE;
2544 key->force_sign = ISC_TRUE;
2547 key->ksk = ISC_TRUE;
2552 report(const char *format, ...) {
2554 va_start(args, format);
2555 vfprintf(stderr, format, args);
2561 build_final_keylist(void) {
2562 isc_result_t result;
2563 dns_dbversion_t *ver = NULL;
2565 dns_dnsseckeylist_t matchkeys;
2566 char name[DNS_NAME_FORMATSIZE];
2569 * Find keys that match this zone in the key repository.
2571 ISC_LIST_INIT(matchkeys);
2572 result = dns_dnssec_findmatchingkeys(gorigin, directory,
2574 if (result == ISC_R_NOTFOUND)
2575 result = ISC_R_SUCCESS;
2576 check_result(result, "dns_dnssec_findmatchingkeys");
2578 result = dns_db_newversion(gdb, &ver);
2579 check_result(result, "dns_db_newversion");
2581 dns_diff_init(mctx, &diff);
2584 * Update keylist with information from from the key repository.
2586 dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl,
2587 &diff, ignore_kskflag, mctx, report);
2589 dns_name_format(gorigin, name, sizeof(name));
2591 result = dns_diff_applysilently(&diff, gdb, ver);
2592 if (result != ISC_R_SUCCESS)
2593 fatal("failed to update DNSKEY RRset at node '%s': %s",
2594 name, isc_result_totext(result));
2596 dns_db_closeversion(gdb, &ver, ISC_TRUE);
2598 dns_diff_clear(&diff);
2602 warnifallksk(dns_db_t *db) {
2603 dns_dbversion_t *currentversion = NULL;
2604 dns_dbnode_t *node = NULL;
2605 dns_rdataset_t rdataset;
2606 dns_rdata_t rdata = DNS_RDATA_INIT;
2607 isc_result_t result;
2608 dns_rdata_dnskey_t dnskey;
2609 isc_boolean_t have_non_ksk = ISC_FALSE;
2611 dns_db_currentversion(db, ¤tversion);
2613 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
2614 if (result != ISC_R_SUCCESS)
2615 fatal("failed to find the zone's origin: %s",
2616 isc_result_totext(result));
2618 dns_rdataset_init(&rdataset);
2619 result = dns_db_findrdataset(db, node, currentversion,
2620 dns_rdatatype_dnskey, 0, 0, &rdataset,
2622 if (result != ISC_R_SUCCESS)
2623 fatal("failed to find keys at the zone apex: %s",
2624 isc_result_totext(result));
2625 result = dns_rdataset_first(&rdataset);
2626 check_result(result, "dns_rdataset_first");
2627 while (result == ISC_R_SUCCESS) {
2628 dns_rdata_reset(&rdata);
2629 dns_rdataset_current(&rdataset, &rdata);
2630 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2631 check_result(result, "dns_rdata_tostruct");
2632 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
2633 have_non_ksk = ISC_TRUE;
2634 result = ISC_R_NOMORE;
2636 result = dns_rdataset_next(&rdataset);
2637 dns_rdata_freestruct(&dnskey);
2639 dns_rdataset_disassociate(&rdataset);
2640 dns_db_detachnode(db, &node);
2641 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
2642 if (!have_non_ksk && !ignore_kskflag) {
2643 if (disable_zone_check)
2644 fprintf(stderr, "%s: warning: No non-KSK DNSKEY found; "
2645 "supply a ZSK or use '-z'.\n",
2648 fatal("No non-KSK DNSKEY found; "
2649 "supply a ZSK or use '-z'.");
2654 set_nsec3params(isc_boolean_t update, isc_boolean_t set_salt,
2655 isc_boolean_t set_optout, isc_boolean_t set_iter)
2657 isc_result_t result;
2658 dns_dbversion_t *ver = NULL;
2659 dns_dbnode_t *node = NULL;
2660 dns_rdataset_t rdataset;
2661 dns_rdata_t rdata = DNS_RDATA_INIT;
2662 dns_rdata_nsec3_t nsec3;
2663 dns_fixedname_t fname;
2664 dns_name_t *hashname;
2665 unsigned char orig_salt[255];
2666 size_t orig_saltlen;
2667 dns_hash_t orig_hash;
2668 isc_uint16_t orig_iter;
2670 dns_db_currentversion(gdb, &ver);
2671 dns_rdataset_init(&rdataset);
2673 orig_saltlen = sizeof(orig_salt);
2674 result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL,
2675 &orig_iter, orig_salt,
2677 if (result != ISC_R_SUCCESS)
2680 nsec_datatype = dns_rdatatype_nsec3;
2682 if (!update && set_salt) {
2683 if (salt_length != orig_saltlen ||
2684 !isc_safe_memequal(saltbuf, orig_salt, salt_length))
2685 fatal("An NSEC3 chain exists with a different salt. "
2686 "Use -u to update it.");
2687 } else if (!set_salt) {
2688 salt_length = orig_saltlen;
2689 memmove(saltbuf, orig_salt, orig_saltlen);
2693 if (!update && set_iter) {
2694 if (nsec3iter != orig_iter)
2695 fatal("An NSEC3 chain exists with different "
2696 "iterations. Use -u to update it.");
2697 } else if (!set_iter)
2698 nsec3iter = orig_iter;
2701 * Find an NSEC3 record to get the current OPTOUT value.
2702 * (This assumes all NSEC3 records agree.)
2705 dns_fixedname_init(&fname);
2706 hashname = dns_fixedname_name(&fname);
2707 result = dns_nsec3_hashname(&fname, NULL, NULL,
2708 gorigin, gorigin, dns_hash_sha1,
2709 orig_iter, orig_salt, orig_saltlen);
2710 check_result(result, "dns_nsec3_hashname");
2712 result = dns_db_findnsec3node(gdb, hashname, ISC_FALSE, &node);
2713 if (result != ISC_R_SUCCESS)
2716 result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3,
2717 0, 0, &rdataset, NULL);
2718 if (result != ISC_R_SUCCESS)
2721 result = dns_rdataset_first(&rdataset);
2722 check_result(result, "dns_rdataset_first");
2723 dns_rdataset_current(&rdataset, &rdata);
2724 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
2725 check_result(result, "dns_rdata_tostruct");
2727 if (!update && set_optout) {
2728 if (nsec3flags != nsec3.flags)
2729 fatal("An NSEC3 chain exists with%s OPTOUT. "
2730 "Use -u -%s to %s it.",
2731 OPTOUT(nsec3.flags) ? "" : "out",
2732 OPTOUT(nsec3.flags) ? "AA" : "A",
2733 OPTOUT(nsec3.flags) ? "clear" : "set");
2734 } else if (!set_optout)
2735 nsec3flags = nsec3.flags;
2737 dns_rdata_freestruct(&nsec3);
2740 if (dns_rdataset_isassociated(&rdataset))
2741 dns_rdataset_disassociate(&rdataset);
2743 dns_db_detachnode(gdb, &node);
2744 dns_db_closeversion(gdb, &ver, ISC_FALSE);
2748 writeset(const char *prefix, dns_rdatatype_t type) {
2750 char namestr[DNS_NAME_FORMATSIZE];
2751 dns_db_t *db = NULL;
2752 dns_dbversion_t *dbversion = NULL;
2754 dns_difftuple_t *tuple = NULL;
2755 dns_fixedname_t fixed;
2757 dns_rdata_t rdata, ds;
2758 isc_boolean_t have_ksk = ISC_FALSE;
2759 isc_boolean_t have_non_ksk = ISC_FALSE;
2761 isc_buffer_t namebuf;
2763 isc_result_t result;
2764 dns_dnsseckey_t *key, *tmpkey;
2765 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
2766 unsigned char keybuf[DST_KEY_MAXSIZE];
2767 unsigned int filenamelen;
2768 const dns_master_style_t *style =
2769 (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
2771 isc_buffer_init(&namebuf, namestr, sizeof(namestr));
2772 result = dns_name_tofilenametext(gorigin, ISC_FALSE, &namebuf);
2773 check_result(result, "dns_name_tofilenametext");
2774 isc_buffer_putuint8(&namebuf, 0);
2775 filenamelen = strlen(prefix) + strlen(namestr);
2777 filenamelen += strlen(dsdir) + 1;
2778 filename = isc_mem_get(mctx, filenamelen + 1);
2779 if (filename == NULL)
2780 fatal("out of memory");
2782 sprintf(filename, "%s/", dsdir);
2785 strcat(filename, prefix);
2786 strcat(filename, namestr);
2788 dns_diff_init(mctx, &diff);
2790 if (type == dns_rdatatype_dlv) {
2792 unsigned int labels;
2794 dns_name_init(&tname, NULL);
2795 dns_fixedname_init(&fixed);
2796 name = dns_fixedname_name(&fixed);
2797 labels = dns_name_countlabels(gorigin);
2798 dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
2799 result = dns_name_concatenate(&tname, dlv, name, NULL);
2800 check_result(result, "dns_name_concatenate");
2804 for (key = ISC_LIST_HEAD(keylist);
2806 key = ISC_LIST_NEXT(key, link))
2808 if (REVOKE(key->key))
2811 have_ksk = ISC_TRUE;
2812 have_non_ksk = ISC_FALSE;
2814 have_ksk = ISC_FALSE;
2815 have_non_ksk = ISC_TRUE;
2817 for (tmpkey = ISC_LIST_HEAD(keylist);
2819 tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
2820 if (dst_key_alg(key->key) != dst_key_alg(tmpkey->key))
2822 if (REVOKE(tmpkey->key))
2825 have_ksk = ISC_TRUE;
2827 have_non_ksk = ISC_TRUE;
2829 if (have_ksk && have_non_ksk && !isksk(key))
2831 dns_rdata_init(&rdata);
2832 dns_rdata_init(&ds);
2833 isc_buffer_init(&b, keybuf, sizeof(keybuf));
2834 result = dst_key_todns(key->key, &b);
2835 check_result(result, "dst_key_todns");
2836 isc_buffer_usedregion(&b, &r);
2837 dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
2838 if (type != dns_rdatatype_dnskey) {
2839 result = dns_ds_buildrdata(gorigin, &rdata,
2842 check_result(result, "dns_ds_buildrdata");
2843 if (type == dns_rdatatype_dlv)
2844 ds.type = dns_rdatatype_dlv;
2845 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
2846 name, 0, &ds, &tuple);
2847 check_result(result, "dns_difftuple_create");
2848 dns_diff_append(&diff, &tuple);
2850 dns_rdata_reset(&ds);
2851 result = dns_ds_buildrdata(gorigin, &rdata,
2852 DNS_DSDIGEST_SHA256,
2854 check_result(result, "dns_ds_buildrdata");
2855 if (type == dns_rdatatype_dlv)
2856 ds.type = dns_rdatatype_dlv;
2857 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
2858 name, 0, &ds, &tuple);
2861 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
2862 gorigin, zone_soa_min_ttl,
2864 check_result(result, "dns_difftuple_create");
2865 dns_diff_append(&diff, &tuple);
2868 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
2869 gclass, 0, NULL, &db);
2870 check_result(result, "dns_db_create");
2872 result = dns_db_newversion(db, &dbversion);
2873 check_result(result, "dns_db_newversion");
2875 result = dns_diff_apply(&diff, db, dbversion);
2876 check_result(result, "dns_diff_apply");
2877 dns_diff_clear(&diff);
2879 result = dns_master_dump(mctx, db, dbversion, style, filename);
2880 check_result(result, "dns_master_dump");
2882 isc_mem_put(mctx, filename, filenamelen + 1);
2884 dns_db_closeversion(db, &dbversion, ISC_FALSE);
2889 print_time(FILE *fp) {
2892 if (outputformat != dns_masterformat_text)
2895 currenttime = time(NULL);
2896 fprintf(fp, "; File written on %s", ctime(¤ttime));
2900 print_version(FILE *fp) {
2901 if (outputformat != dns_masterformat_text)
2904 fprintf(fp, "; dnssec_signzone version " VERSION "\n");
2907 ISC_PLATFORM_NORETURN_PRE static void
2908 usage(void) ISC_PLATFORM_NORETURN_POST;
2912 fprintf(stderr, "Usage:\n");
2913 fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
2915 fprintf(stderr, "\n");
2917 fprintf(stderr, "Version: %s\n", VERSION);
2919 fprintf(stderr, "Options: (default value in parenthesis) \n");
2920 fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n"
2921 "\t\tfor the zone and determines how they are to "
2923 fprintf(stderr, "\t-K directory:\n");
2924 fprintf(stderr, "\t\tdirectory to find key files (.)\n");
2925 fprintf(stderr, "\t-d directory:\n");
2926 fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n");
2927 fprintf(stderr, "\t-g:\t");
2928 fprintf(stderr, "update DS records based on child zones' "
2930 fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
2931 fprintf(stderr, "\t\tRRSIG start time "
2932 "- absolute|offset (now - 1 hour)\n");
2933 fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
2934 fprintf(stderr, "\t\tRRSIG end time "
2935 "- absolute|from start|from now "
2936 "(now + 30 days)\n");
2937 fprintf(stderr, "\t-X [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
2938 fprintf(stderr, "\t\tDNSKEY RRSIG end "
2939 "- absolute|from start|from now "
2941 fprintf(stderr, "\t-i interval:\n");
2942 fprintf(stderr, "\t\tcycle interval - resign "
2943 "if < interval from end ( (end-start)/4 )\n");
2944 fprintf(stderr, "\t-j jitter:\n");
2945 fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n");
2946 fprintf(stderr, "\t-v debuglevel (0)\n");
2947 fprintf(stderr, "\t-V:\tprint version information\n");
2948 fprintf(stderr, "\t-o origin:\n");
2949 fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
2950 fprintf(stderr, "\t-f outfile:\n");
2951 fprintf(stderr, "\t\tfile the signed zone is written in "
2952 "(zonefile + .signed)\n");
2953 fprintf(stderr, "\t-I format:\n");
2954 fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
2955 fprintf(stderr, "\t-O format:\n");
2956 fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
2957 fprintf(stderr, "\t-N format:\n");
2958 fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
2959 fprintf(stderr, "\t-D:\n");
2960 fprintf(stderr, "\t\toutput only DNSSEC-related records\n");
2961 fprintf(stderr, "\t-r randomdev:\n");
2962 fprintf(stderr, "\t\ta file containing random data\n");
2963 fprintf(stderr, "\t-a:\t");
2964 fprintf(stderr, "verify generated signatures\n");
2965 fprintf(stderr, "\t-c class (IN)\n");
2966 fprintf(stderr, "\t-E engine:\n");
2968 fprintf(stderr, "\t\tname of an OpenSSL engine to use "
2969 "(default is \"pkcs11\")\n");
2971 fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
2973 fprintf(stderr, "\t-p:\t");
2974 fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
2975 fprintf(stderr, "\t-P:\t");
2976 fprintf(stderr, "disable post-sign verification\n");
2977 fprintf(stderr, "\t-Q:\t");
2978 fprintf(stderr, "remove signatures from keys that are no "
2980 fprintf(stderr, "\t-R:\t");
2981 fprintf(stderr, "remove signatures from keys that no longer exist\n");
2982 fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n");
2983 fprintf(stderr, "\t-t:\t");
2984 fprintf(stderr, "print statistics\n");
2985 fprintf(stderr, "\t-u:\t");
2986 fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n");
2987 fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n");
2988 fprintf(stderr, "\t-z:\tsign all records with KSKs\n");
2989 fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n"
2990 "\t\twith older versions of dnssec-signzone -g\n");
2991 fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
2992 fprintf(stderr, "\t-k key_signing_key\n");
2993 fprintf(stderr, "\t-l lookasidezone\n");
2994 fprintf(stderr, "\t-3 NSEC3 salt\n");
2995 fprintf(stderr, "\t-H NSEC3 iterations (10)\n");
2996 fprintf(stderr, "\t-A NSEC3 optout\n");
2998 fprintf(stderr, "\n");
3000 fprintf(stderr, "Signing Keys: ");
3001 fprintf(stderr, "(default: all zone keys that have private keys)\n");
3002 fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
3008 removetempfile(void) {
3010 isc_file_remove(tempfile);
3014 print_stats(isc_time_t *timer_start, isc_time_t *timer_finish,
3015 isc_time_t *sign_start, isc_time_t *sign_finish)
3017 isc_uint64_t time_us; /* Time in microseconds */
3018 isc_uint64_t time_ms; /* Time in milliseconds */
3019 isc_uint64_t sig_ms; /* Signatures per millisecond */
3020 FILE *out = output_stdout ? stderr : stdout;
3022 fprintf(out, "Signatures generated: %10d\n", nsigned);
3023 fprintf(out, "Signatures retained: %10d\n", nretained);
3024 fprintf(out, "Signatures dropped: %10d\n", ndropped);
3025 fprintf(out, "Signatures successfully verified: %10d\n", nverified);
3026 fprintf(out, "Signatures unsuccessfully "
3027 "verified: %10d\n", nverifyfailed);
3029 time_us = isc_time_microdiff(sign_finish, sign_start);
3030 time_ms = time_us / 1000;
3031 fprintf(out, "Signing time in seconds: %7u.%03u\n",
3032 (unsigned int) (time_ms / 1000),
3033 (unsigned int) (time_ms % 1000));
3035 sig_ms = ((isc_uint64_t)nsigned * 1000000000) / time_us;
3036 fprintf(out, "Signatures per second: %7u.%03u\n",
3037 (unsigned int) sig_ms / 1000,
3038 (unsigned int) sig_ms % 1000);
3041 time_us = isc_time_microdiff(timer_finish, timer_start);
3042 time_ms = time_us / 1000;
3043 fprintf(out, "Runtime in seconds: %7u.%03u\n",
3044 (unsigned int) (time_ms / 1000),
3045 (unsigned int) (time_ms % 1000));
3049 main(int argc, char *argv[]) {
3051 char *startstr = NULL, *endstr = NULL, *classname = NULL;
3052 char *dnskey_endstr = NULL;
3053 char *origin = NULL, *file = NULL, *output = NULL;
3054 char *inputformatstr = NULL, *outputformatstr = NULL;
3055 char *serialformatstr = NULL;
3056 char *dskeyfile[MAXDSKEYS];
3059 isc_time_t timer_start, timer_finish;
3060 isc_time_t sign_start, sign_finish;
3061 dns_dnsseckey_t *key;
3062 isc_result_t result;
3063 isc_log_t *log = NULL;
3064 isc_boolean_t pseudorandom = ISC_FALSE;
3066 const char *engine = "pkcs11";
3068 const char *engine = NULL;
3070 unsigned int eflags;
3071 isc_boolean_t free_output = ISC_FALSE;
3072 int tempfilelen = 0;
3073 dns_rdataclass_t rdclass;
3074 isc_task_t **tasks = NULL;
3077 hashlist_t hashlist;
3078 isc_boolean_t make_keyset = ISC_FALSE;
3079 isc_boolean_t set_salt = ISC_FALSE;
3080 isc_boolean_t set_optout = ISC_FALSE;
3081 isc_boolean_t set_iter = ISC_FALSE;
3082 isc_boolean_t nonsecify = ISC_FALSE;
3084 /* Unused letters: Bb G J M q Yy (and F is reserved). */
3085 #define CMDLINE_FLAGS \
3086 "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:L:l:m:n:N:o:O:PpQRr:s:ST:tuUv:VX:xzZ:"
3089 * Process memory debugging argument first.
3091 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3094 if (strcasecmp(isc_commandline_argument, "record") == 0)
3095 isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
3096 if (strcasecmp(isc_commandline_argument, "trace") == 0)
3097 isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
3098 if (strcasecmp(isc_commandline_argument, "usage") == 0)
3099 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
3100 if (strcasecmp(isc_commandline_argument, "size") == 0)
3101 isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
3102 if (strcasecmp(isc_commandline_argument, "mctx") == 0)
3103 isc_mem_debugging |= ISC_MEM_DEBUGCTX;
3109 isc_commandline_reset = ISC_TRUE;
3111 masterstyle = &dns_master_style_explicitttl;
3113 check_result(isc_app_start(), "isc_app_start");
3115 result = isc_mem_create(0, 0, &mctx);
3116 if (result != ISC_R_SUCCESS)
3117 fatal("out of memory");
3119 dns_result_register();
3121 isc_commandline_errprint = ISC_FALSE;
3123 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3126 set_salt = ISC_TRUE;
3127 nsec_datatype = dns_rdatatype_nsec3;
3128 if (strcmp(isc_commandline_argument, "-") != 0) {
3129 isc_buffer_t target;
3132 sarg = isc_commandline_argument;
3133 isc_buffer_init(&target, saltbuf,
3135 result = isc_hex_decodestring(sarg, &target);
3136 check_result(result,
3137 "isc_hex_decodestring(salt)");
3138 salt_length = isc_buffer_usedlength(&target);
3143 set_optout = ISC_TRUE;
3144 if (OPTOUT(nsec3flags))
3145 nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT;
3147 nsec3flags |= DNS_NSEC3FLAG_OPTOUT;
3151 tryverify = ISC_TRUE;
3155 make_keyset = ISC_TRUE;
3159 classname = isc_commandline_argument;
3163 dsdir = isc_commandline_argument;
3164 if (strlen(dsdir) == 0U)
3165 fatal("DS directory must be non-empty string");
3166 result = try_dir(dsdir);
3167 if (result != ISC_R_SUCCESS)
3168 fatal("cannot open directory %s: %s",
3169 dsdir, isc_result_totext(result));
3173 output_dnssec_only = ISC_TRUE;
3177 engine = isc_commandline_argument;
3181 endstr = isc_commandline_argument;
3185 output = isc_commandline_argument;
3186 if (strcmp(output, "-") == 0)
3187 output_stdout = ISC_TRUE;
3191 generateds = ISC_TRUE;
3195 set_iter = ISC_TRUE;
3196 nsec3iter = strtoul(isc_commandline_argument, &endp, 0);
3198 fatal("iterations must be numeric");
3199 if (nsec3iter > 0xffffU)
3200 fatal("iterations too big");
3204 inputformatstr = isc_commandline_argument;
3209 cycle = strtol(isc_commandline_argument, &endp, 0);
3210 if (*endp != '\0' || cycle < 0)
3211 fatal("cycle period must be numeric and "
3217 jitter = strtol(isc_commandline_argument, &endp, 0);
3218 if (*endp != '\0' || jitter < 0)
3219 fatal("jitter must be numeric and positive");
3223 directory = isc_commandline_argument;
3227 if (ndskeys == MAXDSKEYS)
3228 fatal("too many key-signing keys specified");
3229 dskeyfile[ndskeys++] = isc_commandline_argument;
3235 serialnum = strtol(isc_commandline_argument, &endp, 0);
3236 if (*endp != '\0') {
3237 fprintf(stderr, "source serial number "
3244 len = strlen(isc_commandline_argument);
3245 isc_buffer_init(&b, isc_commandline_argument, len);
3246 isc_buffer_add(&b, len);
3248 dns_fixedname_init(&dlv_fixed);
3249 dlv = dns_fixedname_name(&dlv_fixed);
3250 result = dns_name_fromtext(dlv, &b, dns_rootname, 0,
3252 check_result(result, "dns_name_fromtext(dlv)");
3259 serialformatstr = isc_commandline_argument;
3264 ntasks = strtol(isc_commandline_argument, &endp, 0);
3265 if (*endp != '\0' || ntasks > ISC_INT32_MAX)
3266 fatal("number of cpus must be numeric");
3270 outputformatstr = isc_commandline_argument;
3274 origin = isc_commandline_argument;
3278 disable_zone_check = ISC_TRUE;
3282 pseudorandom = ISC_TRUE;
3286 remove_inactkeysigs = ISC_TRUE;
3290 remove_orphansigs = ISC_TRUE;
3294 setup_entropy(mctx, isc_commandline_argument, &ectx);
3298 smartsign = ISC_TRUE;
3302 startstr = isc_commandline_argument;
3307 set_keyttl = ISC_TRUE;
3308 keyttl = strtottl(isc_commandline_argument);
3312 printstats = ISC_TRUE;
3315 case 'U': /* Undocumented for testing only. */
3316 unknownalg = ISC_TRUE;
3320 update_chain = ISC_TRUE;
3325 verbose = strtol(isc_commandline_argument, &endp, 0);
3327 fatal("verbose level must be numeric");
3331 dnskey_endstr = isc_commandline_argument;
3335 keyset_kskonly = ISC_TRUE;
3339 ignore_kskflag = ISC_TRUE;
3343 /* Reserved for FIPS mode */
3346 if (isc_commandline_option != '?')
3347 fprintf(stderr, "%s: invalid argument -%c\n",
3348 program, isc_commandline_option);
3351 /* Does not return. */
3355 /* Does not return. */
3358 case 'Z': /* Undocumented test options */
3359 if (!strcmp(isc_commandline_argument, "nonsecify"))
3360 nonsecify = ISC_TRUE;
3364 fprintf(stderr, "%s: unhandled option -%c\n",
3365 program, isc_commandline_option);
3371 setup_entropy(mctx, NULL, &ectx);
3372 eflags = ISC_ENTROPY_BLOCKING;
3374 eflags |= ISC_ENTROPY_GOODONLY;
3376 result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
3377 if (result != ISC_R_SUCCESS)
3378 fatal("could not create hash context");
3380 result = dst_lib_init2(mctx, ectx, engine, eflags);
3381 if (result != ISC_R_SUCCESS)
3382 fatal("could not initialize dst: %s",
3383 isc_result_totext(result));
3384 isc_stdtime_get(&now);
3386 if (startstr != NULL) {
3387 starttime = strtotime(startstr, now, now, NULL);
3389 starttime = now - 3600; /* Allow for some clock skew. */
3392 endtime = strtotime(endstr, now, starttime, NULL);
3394 endtime = starttime + (30 * 24 * 60 * 60);
3396 if (dnskey_endstr != NULL) {
3397 dnskey_endtime = strtotime(dnskey_endstr, now, starttime,
3399 if (endstr != NULL && dnskey_endtime == endtime)
3400 fprintf(stderr, "WARNING: -e and -X were both set, "
3401 "but have identical values.\n");
3403 dnskey_endtime = endtime;
3406 cycle = (endtime - starttime) / 4;
3409 ntasks = isc_os_ncpus() * 2;
3410 vbprintf(4, "using %d cpus\n", ntasks);
3412 rdclass = strtoclass(classname);
3414 if (directory == NULL)
3417 setup_logging(mctx, &log);
3419 argc -= isc_commandline_index;
3420 argv += isc_commandline_index;
3433 if (output == NULL) {
3434 free_output = ISC_TRUE;
3435 output = isc_mem_allocate(mctx,
3436 strlen(file) + strlen(".signed") + 1);
3438 fatal("out of memory");
3439 sprintf(output, "%s.signed", file);
3442 if (inputformatstr != NULL) {
3443 if (strcasecmp(inputformatstr, "text") == 0)
3444 inputformat = dns_masterformat_text;
3445 else if (strcasecmp(inputformatstr, "raw") == 0)
3446 inputformat = dns_masterformat_raw;
3447 else if (strncasecmp(inputformatstr, "raw=", 4) == 0) {
3448 inputformat = dns_masterformat_raw;
3450 "WARNING: input format version ignored\n");
3452 fatal("unknown file format: %s", inputformatstr);
3456 if (outputformatstr != NULL) {
3457 if (strcasecmp(outputformatstr, "text") == 0) {
3458 outputformat = dns_masterformat_text;
3459 } else if (strcasecmp(outputformatstr, "full") == 0) {
3460 outputformat = dns_masterformat_text;
3461 masterstyle = &dns_master_style_full;
3462 } else if (strcasecmp(outputformatstr, "raw") == 0) {
3463 outputformat = dns_masterformat_raw;
3464 } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
3466 outputformat = dns_masterformat_raw;
3468 outputformat = dns_masterformat_raw;
3469 rawversion = strtol(outputformatstr + 4, &end, 10);
3470 if (end == outputformatstr + 4 || *end != '\0' ||
3473 "unknown raw format version\n");
3477 fatal("unknown file format: %s\n", outputformatstr);
3480 if (serialformatstr != NULL) {
3481 if (strcasecmp(serialformatstr, "keep") == 0)
3482 serialformat = SOA_SERIAL_KEEP;
3483 else if (strcasecmp(serialformatstr, "increment") == 0 ||
3484 strcasecmp(serialformatstr, "incr") == 0)
3485 serialformat = SOA_SERIAL_INCREMENT;
3486 else if (strcasecmp(serialformatstr, "unixtime") == 0)
3487 serialformat = SOA_SERIAL_UNIXTIME;
3489 fatal("unknown soa serial format: %s\n",
3493 if (output_dnssec_only && outputformat != dns_masterformat_text)
3494 fatal("option -D can only be used with \"-O text\"\n");
3496 if (output_dnssec_only && serialformat != SOA_SERIAL_KEEP)
3497 fatal("option -D can only be used with \"-N keep\"\n");
3499 result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL,
3500 0, 24, 0, 0, 0, 8, mctx);
3501 check_result(result, "dns_master_stylecreate");
3504 TIME_NOW(&timer_start);
3505 loadzone(file, origin, rdclass, &gdb);
3506 gorigin = dns_db_origin(gdb);
3507 gclass = dns_db_class(gdb);
3514 * Check for any existing NSEC3 parameters in the zone,
3515 * and use them as defaults if -u was not specified.
3517 if (update_chain && !set_optout && !set_iter && !set_salt)
3518 nsec_datatype = dns_rdatatype_nsec;
3520 set_nsec3params(update_chain, set_salt, set_optout, set_iter);
3523 * We need to do this early on, as we start messing with the list
3524 * of keys rather early.
3526 ISC_LIST_INIT(keylist);
3527 result = isc_rwlock_init(&keylist_lock, 0, 0);
3528 if (result != ISC_R_SUCCESS)
3529 fatal("could not initialize keylist_lock: %s",
3530 isc_result_totext(result));
3533 * Fill keylist with:
3534 * 1) Keys listed in the DNSKEY set that have
3535 * private keys associated, *if* no keys were
3536 * set on the command line.
3537 * 2) ZSKs set on the command line
3538 * 3) KSKs set on the command line
3539 * 4) Any keys remaining in the DNSKEY set which
3540 * do not have private keys associated and were
3541 * not specified on the command line.
3543 if (argc == 0 || smartsign)
3544 loadzonekeys(!smartsign, ISC_FALSE);
3545 loadexplicitkeys(argv, argc, ISC_FALSE);
3546 loadexplicitkeys(dskeyfile, ndskeys, ISC_TRUE);
3547 loadzonekeys(!smartsign, ISC_TRUE);
3550 * If we're doing smart signing, look in the key repository for
3551 * key files with metadata, and merge them with the keylist
3555 build_final_keylist();
3557 /* Now enumerate the key list */
3558 for (key = ISC_LIST_HEAD(keylist);
3560 key = ISC_LIST_NEXT(key, link)) {
3561 key->index = keycount++;
3564 if (keycount == 0) {
3565 if (disable_zone_check)
3566 fprintf(stderr, "%s: warning: No keys specified "
3567 "or found\n", program);
3569 fatal("No signing keys specified or found.");
3577 isc_boolean_t answer;
3579 hash_length = dns_nsec3_hashlength(dns_hash_sha1);
3580 hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2,
3582 result = dns_nsec_nseconly(gdb, gversion, &answer);
3583 if (result == ISC_R_NOTFOUND)
3584 fprintf(stderr, "%s: warning: NSEC3 generation "
3585 "requested with no DNSKEY; ignoring\n",
3587 else if (result != ISC_R_SUCCESS)
3588 check_result(result, "dns_nsec_nseconly");
3590 fatal("NSEC3 generation requested with "
3591 "NSEC-only DNSKEY");
3593 result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max);
3594 check_result(result, "dns_nsec3_maxiterations()");
3595 if (nsec3iter > max)
3596 fatal("NSEC3 iterations too big for weakest DNSKEY "
3597 "strength. Maximum iterations allowed %u.", max);
3601 result = dns_db_newversion(gdb, &gversion);
3602 check_result(result, "dns_db_newversion()");
3604 switch (serialformat) {
3605 case SOA_SERIAL_INCREMENT:
3608 case SOA_SERIAL_UNIXTIME:
3611 case SOA_SERIAL_KEEP:
3617 remove_duplicates();
3621 nsec3ify(dns_hash_sha1, nsec3iter, gsalt, salt_length,
3628 writeset("dsset-", dns_rdatatype_ds);
3630 writeset("keyset-", dns_rdatatype_dnskey);
3632 writeset("dlvset-", dns_rdatatype_dlv);
3636 if (output_stdout) {
3638 if (outputformatstr == NULL)
3639 masterstyle = &dns_master_style_full;
3641 tempfilelen = strlen(output) + 20;
3642 tempfile = isc_mem_get(mctx, tempfilelen);
3643 if (tempfile == NULL)
3644 fatal("out of memory");
3646 result = isc_file_mktemplate(output, tempfile, tempfilelen);
3647 check_result(result, "isc_file_mktemplate");
3649 if (outputformat == dns_masterformat_text)
3650 result = isc_file_openunique(tempfile, &outfp);
3652 result = isc_file_bopenunique(tempfile, &outfp);
3653 if (result != ISC_R_SUCCESS)
3654 fatal("failed to open temporary output file: %s",
3655 isc_result_totext(result));
3656 removefile = ISC_TRUE;
3657 setfatalcallback(&removetempfile);
3661 print_version(outfp);
3663 result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
3664 if (result != ISC_R_SUCCESS)
3665 fatal("failed to create task manager: %s",
3666 isc_result_totext(result));
3669 result = isc_task_create(taskmgr, 0, &master);
3670 if (result != ISC_R_SUCCESS)
3671 fatal("failed to create task: %s", isc_result_totext(result));
3673 tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
3675 fatal("out of memory");
3676 for (i = 0; i < (int)ntasks; i++) {
3678 result = isc_task_create(taskmgr, 0, &tasks[i]);
3679 if (result != ISC_R_SUCCESS)
3680 fatal("failed to create task: %s",
3681 isc_result_totext(result));
3684 RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS);
3686 RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS);
3689 TIME_NOW(&sign_start);
3693 * There is more work to do. Spread it out over multiple
3694 * processors if possible.
3696 for (i = 0; i < (int)ntasks; i++) {
3697 result = isc_app_onrun(mctx, master, startworker,
3699 if (result != ISC_R_SUCCESS)
3700 fatal("failed to start task: %s",
3701 isc_result_totext(result));
3703 (void)isc_app_run();
3705 fatal("process aborted by user");
3707 isc_task_detach(&master);
3708 shuttingdown = ISC_TRUE;
3709 for (i = 0; i < (int)ntasks; i++)
3710 isc_task_detach(&tasks[i]);
3711 isc_taskmgr_destroy(&taskmgr);
3712 isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
3714 TIME_NOW(&sign_finish);
3716 if (!disable_zone_check)
3717 verifyzone(gdb, gversion, gorigin, mctx,
3718 ignore_kskflag, keyset_kskonly);
3720 if (outputformat != dns_masterformat_text) {
3721 dns_masterrawheader_t header;
3722 dns_master_initrawheader(&header);
3723 if (rawversion == 0U)
3724 header.flags = DNS_MASTERRAW_COMPAT;
3726 header.flags = DNS_MASTERRAW_SOURCESERIALSET;
3727 header.sourceserial = serialnum;
3729 result = dns_master_dumptostream3(mctx, gdb, gversion,
3730 masterstyle, outputformat,
3732 check_result(result, "dns_master_dumptostream3");
3735 DESTROYLOCK(&namelock);
3737 DESTROYLOCK(&statslock);
3739 if (!output_stdout) {
3740 result = isc_stdio_close(outfp);
3741 check_result(result, "isc_stdio_close");
3742 removefile = ISC_FALSE;
3744 result = isc_file_rename(tempfile, output);
3745 if (result != ISC_R_SUCCESS)
3746 fatal("failed to rename temp file to %s: %s\n",
3747 output, isc_result_totext(result));
3749 printf("%s\n", output);
3752 dns_db_closeversion(gdb, &gversion, ISC_FALSE);
3753 dns_db_detach(&gdb);
3755 while (!ISC_LIST_EMPTY(keylist)) {
3756 key = ISC_LIST_HEAD(keylist);
3757 ISC_LIST_UNLINK(keylist, key, link);
3758 dns_dnsseckey_destroy(mctx, &key);
3761 if (tempfilelen != 0)
3762 isc_mem_put(mctx, tempfile, tempfilelen);
3765 isc_mem_free(mctx, output);
3767 dns_master_styledestroy(&dsstyle, mctx);
3769 cleanup_logging(&log);
3772 cleanup_entropy(&ectx);
3775 isc_mem_stats(mctx, stdout);
3776 isc_mem_destroy(&mctx);
3778 (void) isc_app_finish();
3781 TIME_NOW(&timer_finish);
3782 print_stats(&timer_start, &timer_finish,
3783 &sign_start, &sign_finish);