2 * Portions Copyright (C) 2004-2014 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.
32 /* $Id: dnssec-signzone.c,v 1.285 2011/12/22 07:32:39 each Exp $ */
43 #include <isc/base32.h>
44 #include <isc/commandline.h>
45 #include <isc/entropy.h>
46 #include <isc/event.h>
51 #include <isc/mutex.h>
53 #include <isc/print.h>
54 #include <isc/random.h>
55 #include <isc/rwlock.h>
56 #include <isc/serial.h>
57 #include <isc/stdio.h>
58 #include <isc/stdlib.h>
59 #include <isc/string.h>
65 #include <dns/dbiterator.h>
67 #include <dns/dnssec.h>
69 #include <dns/fixedname.h>
70 #include <dns/keyvalues.h>
72 #include <dns/master.h>
73 #include <dns/masterdump.h>
75 #include <dns/nsec3.h>
76 #include <dns/rdata.h>
77 #include <dns/rdatalist.h>
78 #include <dns/rdataset.h>
79 #include <dns/rdataclass.h>
80 #include <dns/rdatasetiter.h>
81 #include <dns/rdatastruct.h>
82 #include <dns/rdatatype.h>
83 #include <dns/result.h>
89 #include "dnssectool.h"
92 #define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */
95 const char *program = "dnssec-signzone";
98 typedef struct hashlist hashlist_t;
100 static int nsec_datatype = dns_rdatatype_nsec;
102 #define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3)
103 #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
105 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
110 #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
111 #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
112 #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
114 #define SOA_SERIAL_KEEP 0
115 #define SOA_SERIAL_INCREMENT 1
116 #define SOA_SERIAL_UNIXTIME 2
118 typedef struct signer_event sevent_t;
119 struct signer_event {
120 ISC_EVENT_COMMON(sevent_t);
121 dns_fixedname_t *fname;
125 static dns_dnsseckeylist_t keylist;
126 static unsigned int keycount = 0;
127 isc_rwlock_t keylist_lock;
128 static isc_stdtime_t starttime = 0, endtime = 0, dnskey_endtime = 0, now;
129 static int cycle = -1;
130 static int jitter = 0;
131 static isc_boolean_t tryverify = ISC_FALSE;
132 static isc_boolean_t printstats = ISC_FALSE;
133 static isc_mem_t *mctx = NULL;
134 static isc_entropy_t *ectx = NULL;
135 static dns_ttl_t zone_soa_min_ttl;
136 static dns_ttl_t soa_ttl;
137 static FILE *fp = NULL;
138 static char *tempfile = NULL;
139 static const dns_master_style_t *masterstyle;
140 static dns_masterformat_t inputformat = dns_masterformat_text;
141 static dns_masterformat_t outputformat = dns_masterformat_text;
142 static isc_uint32_t rawversion = 1, serialnum = 0;
143 static isc_boolean_t snset = ISC_FALSE;
144 static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
145 static unsigned int nverified = 0, nverifyfailed = 0;
146 static const char *directory = NULL, *dsdir = NULL;
147 static isc_mutex_t namelock, statslock;
148 static isc_taskmgr_t *taskmgr = NULL;
149 static dns_db_t *gdb; /* The database */
150 static dns_dbversion_t *gversion; /* The database version */
151 static dns_dbiterator_t *gdbiter; /* The database iterator */
152 static dns_rdataclass_t gclass; /* The class */
153 static dns_name_t *gorigin; /* The database origin */
154 static int nsec3flags = 0;
155 static dns_iterations_t nsec3iter = 10U;
156 static unsigned char saltbuf[255];
157 static unsigned char *salt = saltbuf;
158 static size_t salt_length = 0;
159 static isc_task_t *master = NULL;
160 static unsigned int ntasks = 0;
161 static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE;
162 static isc_boolean_t nokeys = ISC_FALSE;
163 static isc_boolean_t removefile = ISC_FALSE;
164 static isc_boolean_t generateds = ISC_FALSE;
165 static isc_boolean_t ignore_kskflag = ISC_FALSE;
166 static isc_boolean_t keyset_kskonly = ISC_FALSE;
167 static dns_name_t *dlv = NULL;
168 static dns_fixedname_t dlv_fixed;
169 static dns_master_style_t *dsstyle = NULL;
170 static unsigned int serialformat = SOA_SERIAL_KEEP;
171 static unsigned int hash_length = 0;
172 static isc_boolean_t unknownalg = ISC_FALSE;
173 static isc_boolean_t disable_zone_check = ISC_FALSE;
174 static isc_boolean_t update_chain = ISC_FALSE;
175 static isc_boolean_t set_keyttl = ISC_FALSE;
176 static dns_ttl_t keyttl;
177 static isc_boolean_t smartsign = ISC_FALSE;
178 static isc_boolean_t remove_orphansigs = ISC_FALSE;
179 static isc_boolean_t remove_inactkeysigs = ISC_FALSE;
180 static isc_boolean_t output_dnssec_only = ISC_FALSE;
181 static isc_boolean_t output_stdout = ISC_FALSE;
183 #define INCSTAT(counter) \
187 UNLOCK(&statslock); \
191 sign(isc_task_t *task, isc_event_t *event);
194 dumpnode(dns_name_t *name, dns_dbnode_t *node) {
196 dns_rdatasetiter_t *iter = NULL;
197 isc_buffer_t *buffer = NULL;
200 unsigned bufsize = 4096;
202 if (outputformat != dns_masterformat_text)
205 if (!output_dnssec_only) {
206 result = dns_master_dumpnodetostream(mctx, gdb, gversion, node,
207 name, masterstyle, fp);
208 check_result(result, "dns_master_dumpnodetostream");
212 result = dns_db_allrdatasets(gdb, node, gversion, 0, &iter);
213 check_result(result, "dns_db_allrdatasets");
215 dns_rdataset_init(&rds);
217 result = isc_buffer_allocate(mctx, &buffer, bufsize);
218 check_result(result, "isc_buffer_allocate");
220 for (result = dns_rdatasetiter_first(iter);
221 result == ISC_R_SUCCESS;
222 result = dns_rdatasetiter_next(iter)) {
224 dns_rdatasetiter_current(iter, &rds);
226 if (rds.type != dns_rdatatype_rrsig &&
227 rds.type != dns_rdatatype_nsec &&
228 rds.type != dns_rdatatype_nsec3 &&
229 rds.type != dns_rdatatype_nsec3param &&
230 (!smartsign || rds.type != dns_rdatatype_dnskey)) {
231 dns_rdataset_disassociate(&rds);
236 result = dns_master_rdatasettotext(name, &rds,
237 masterstyle, buffer);
238 if (result != ISC_R_NOSPACE)
242 isc_buffer_free(&buffer);
243 result = isc_buffer_allocate(mctx, &buffer, bufsize);
244 check_result(result, "isc_buffer_allocate");
246 check_result(result, "dns_master_rdatasettotext");
248 isc_buffer_usedregion(buffer, &r);
249 result = isc_stdio_write(r.base, 1, r.length, fp, NULL);
250 check_result(result, "isc_stdio_write");
251 isc_buffer_clear(buffer);
253 dns_rdataset_disassociate(&rds);
256 isc_buffer_free(&buffer);
257 dns_rdatasetiter_destroy(&iter);
261 * Sign the given RRset with given key, and add the signature record to the
265 signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key,
266 dns_ttl_t ttl, dns_diff_t *add, const char *logmsg)
269 isc_stdtime_t jendtime, expiry;
270 char keystr[DST_KEY_FORMATSIZE];
271 dns_rdata_t trdata = DNS_RDATA_INIT;
272 unsigned char array[BUFSIZE];
274 dns_difftuple_t *tuple;
276 dst_key_format(key, keystr, sizeof(keystr));
277 vbprintf(1, "\t%s %s\n", logmsg, keystr);
279 if (rdataset->type == dns_rdatatype_dnskey)
280 expiry = dnskey_endtime;
284 jendtime = (jitter != 0) ? isc_random_jitter(expiry, jitter) : expiry;
285 isc_buffer_init(&b, array, sizeof(array));
286 result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
288 isc_entropy_stopcallbacksources(ectx);
289 if (result != ISC_R_SUCCESS) {
290 char keystr[DST_KEY_FORMATSIZE];
291 dst_key_format(key, keystr, sizeof(keystr));
292 fatal("dnskey '%s' failed to sign data: %s",
293 keystr, isc_result_totext(result));
298 result = dns_dnssec_verify(name, rdataset, key,
299 ISC_TRUE, mctx, &trdata);
300 if (result == ISC_R_SUCCESS) {
301 vbprintf(3, "\tsignature verified\n");
304 vbprintf(3, "\tsignature failed to verify\n");
305 INCSTAT(nverifyfailed);
310 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name, ttl, &trdata,
312 check_result(result, "dns_difftuple_create");
313 dns_diff_append(add, &tuple);
316 static inline isc_boolean_t
317 issigningkey(dns_dnsseckey_t *key) {
318 return (key->force_sign || key->hint_sign);
321 static inline isc_boolean_t
322 ispublishedkey(dns_dnsseckey_t *key) {
323 return ((key->force_publish || key->hint_publish) &&
327 static inline isc_boolean_t
328 iszonekey(dns_dnsseckey_t *key) {
329 return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) &&
330 dst_key_iszonekey(key->key)));
333 static inline isc_boolean_t
334 isksk(dns_dnsseckey_t *key) {
338 static inline isc_boolean_t
339 iszsk(dns_dnsseckey_t *key) {
340 return (ignore_kskflag || !key->ksk);
344 * Find the key that generated an RRSIG, if it is in the key list. If
345 * so, return a pointer to it, otherwise return NULL.
347 * No locking is performed here, this must be done by the caller.
349 static dns_dnsseckey_t *
350 keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
351 dns_dnsseckey_t *key;
353 for (key = ISC_LIST_HEAD(keylist);
355 key = ISC_LIST_NEXT(key, link)) {
356 if (rrsig->keyid == dst_key_id(key->key) &&
357 rrsig->algorithm == dst_key_alg(key->key) &&
358 dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
365 * Finds the key that generated a RRSIG, if possible. First look at the keys
366 * that we've loaded already, and then see if there's a key on disk.
368 static dns_dnsseckey_t *
369 keythatsigned(dns_rdata_rrsig_t *rrsig) {
371 dst_key_t *pubkey = NULL, *privkey = NULL;
372 dns_dnsseckey_t *key = NULL;
374 isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read);
375 key = keythatsigned_unlocked(rrsig);
376 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_read);
381 * We did not find the key in our list. Get a write lock now, since
382 * we may be modifying the bits. We could do the tryupgrade() dance,
383 * but instead just get a write lock and check once again to see if
384 * it is on our list. It's possible someone else may have added it
387 isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write);
388 key = keythatsigned_unlocked(rrsig);
390 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
394 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
395 rrsig->algorithm, DST_TYPE_PUBLIC,
396 directory, mctx, &pubkey);
397 if (result != ISC_R_SUCCESS) {
398 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
402 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
404 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
405 directory, mctx, &privkey);
406 if (result == ISC_R_SUCCESS) {
407 dst_key_free(&pubkey);
408 result = dns_dnsseckey_create(mctx, &privkey, &key);
410 result = dns_dnsseckey_create(mctx, &pubkey, &key);
412 if (result == ISC_R_SUCCESS) {
413 key->force_publish = ISC_FALSE;
414 key->force_sign = ISC_FALSE;
415 key->index = keycount++;
416 ISC_LIST_APPEND(keylist, key, link);
419 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
424 * Check to see if we expect to find a key at this name. If we see a RRSIG
425 * and can't find the signing key that we expect to find, we drop the rrsig.
426 * I'm not sure if this is completely correct, but it seems to work.
429 expecttofindkey(dns_name_t *name) {
430 unsigned int options = DNS_DBFIND_NOWILD;
431 dns_fixedname_t fname;
433 char namestr[DNS_NAME_FORMATSIZE];
435 dns_fixedname_init(&fname);
436 result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
437 0, NULL, dns_fixedname_name(&fname), NULL, NULL);
443 case DNS_R_DELEGATION:
448 dns_name_format(name, namestr, sizeof(namestr));
449 fatal("failure looking for '%s DNSKEY' in database: %s",
450 namestr, isc_result_totext(result));
452 return (ISC_FALSE); /* removes a warning */
455 static inline isc_boolean_t
456 setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
460 result = dns_dnssec_verify(name, set, key, ISC_FALSE, mctx, rrsig);
461 if (result == ISC_R_SUCCESS) {
465 INCSTAT(nverifyfailed);
471 * Signs a set. Goes through contortions to decide if each RRSIG should
472 * be dropped or retained, and then determines if any new SIGs need to
476 signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
479 dns_rdataset_t sigset;
480 dns_rdata_t sigrdata = DNS_RDATA_INIT;
481 dns_rdata_rrsig_t rrsig;
482 dns_dnsseckey_t *key;
484 isc_boolean_t nosigs = ISC_FALSE;
485 isc_boolean_t *wassignedby, *nowsignedby;
487 dns_difftuple_t *tuple;
490 char namestr[DNS_NAME_FORMATSIZE];
491 char typestr[TYPE_FORMATSIZE];
492 char sigstr[SIG_FORMATSIZE];
494 dns_name_format(name, namestr, sizeof(namestr));
495 type_format(set->type, typestr, sizeof(typestr));
497 ttl = ISC_MIN(set->ttl, endtime - starttime);
499 dns_rdataset_init(&sigset);
500 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
501 set->type, 0, &sigset, NULL);
502 if (result == ISC_R_NOTFOUND) {
503 result = ISC_R_SUCCESS;
506 if (result != ISC_R_SUCCESS)
507 fatal("failed while looking for '%s RRSIG %s': %s",
508 namestr, typestr, isc_result_totext(result));
510 vbprintf(1, "%s/%s:\n", namestr, typestr);
512 arraysize = keycount;
514 arraysize += dns_rdataset_count(&sigset);
515 wassignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
516 nowsignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
517 if (wassignedby == NULL || nowsignedby == NULL)
518 fatal("out of memory");
520 for (i = 0; i < arraysize; i++)
521 wassignedby[i] = nowsignedby[i] = ISC_FALSE;
524 result = ISC_R_NOMORE;
526 result = dns_rdataset_first(&sigset);
528 while (result == ISC_R_SUCCESS) {
529 isc_boolean_t expired, future;
530 isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE;
532 dns_rdataset_current(&sigset, &sigrdata);
534 result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
535 check_result(result, "dns_rdata_tostruct");
537 future = isc_serial_lt(now, rrsig.timesigned);
539 key = keythatsigned(&rrsig);
540 sig_format(&rrsig, sigstr, sizeof(sigstr));
541 if (key != NULL && issigningkey(key))
542 expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
544 expired = isc_serial_gt(now, rrsig.timeexpire);
546 if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
547 /* rrsig is dropped and not replaced */
548 vbprintf(2, "\trrsig by %s dropped - "
549 "invalid validity period\n",
551 } else if (key == NULL && !future &&
552 expecttofindkey(&rrsig.signer)) {
553 /* rrsig is dropped and not replaced */
554 vbprintf(2, "\trrsig by %s dropped - "
555 "private dnskey not found\n",
557 } else if (key == NULL || future) {
558 keep = (!expired && !remove_orphansigs);
559 vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
560 keep ? "retained" : "dropped", sigstr);
561 } else if (!dns_dnssec_keyactive(key->key, now) &&
562 remove_inactkeysigs) {
564 vbprintf(2, "\trrsig by %s dropped - key inactive\n",
566 } else if (issigningkey(key)) {
567 wassignedby[key->index] = ISC_TRUE;
569 if (!expired && rrsig.originalttl == set->ttl &&
570 setverifies(name, set, key->key, &sigrdata)) {
571 vbprintf(2, "\trrsig by %s retained\n", sigstr);
574 vbprintf(2, "\trrsig by %s dropped - %s\n",
575 sigstr, expired ? "expired" :
576 rrsig.originalttl != set->ttl ?
577 "ttl change" : "failed to verify");
580 } else if (!ispublishedkey(key) && remove_orphansigs) {
581 vbprintf(2, "\trrsig by %s dropped - dnskey removed\n",
583 } else if (iszonekey(key)) {
584 wassignedby[key->index] = ISC_TRUE;
586 if (!expired && rrsig.originalttl == set->ttl &&
587 setverifies(name, set, key->key, &sigrdata)) {
588 vbprintf(2, "\trrsig by %s retained\n", sigstr);
591 vbprintf(2, "\trrsig by %s dropped - %s\n",
592 sigstr, expired ? "expired" :
593 rrsig.originalttl != set->ttl ?
594 "ttl change" : "failed to verify");
596 } else if (!expired) {
597 vbprintf(2, "\trrsig by %s retained\n", sigstr);
600 vbprintf(2, "\trrsig by %s expired\n", sigstr);
605 nowsignedby[key->index] = ISC_TRUE;
607 if (sigset.ttl != ttl) {
608 vbprintf(2, "\tfixing ttl %s\n", sigstr);
610 result = dns_difftuple_create(mctx,
615 check_result(result, "dns_difftuple_create");
616 dns_diff_append(del, &tuple);
617 result = dns_difftuple_create(mctx,
622 check_result(result, "dns_difftuple_create");
623 dns_diff_append(add, &tuple);
627 vbprintf(2, "removing signature by %s\n", sigstr);
628 result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL,
631 check_result(result, "dns_difftuple_create");
632 dns_diff_append(del, &tuple);
639 signwithkey(name, set, key->key, ttl, add,
640 "resigning with dnskey");
641 nowsignedby[key->index] = ISC_TRUE;
644 dns_rdata_reset(&sigrdata);
645 dns_rdata_freestruct(&rrsig);
646 result = dns_rdataset_next(&sigset);
648 if (result == ISC_R_NOMORE)
649 result = ISC_R_SUCCESS;
651 check_result(result, "dns_rdataset_first/next");
652 if (dns_rdataset_isassociated(&sigset))
653 dns_rdataset_disassociate(&sigset);
655 for (key = ISC_LIST_HEAD(keylist);
657 key = ISC_LIST_NEXT(key, link))
659 if (nowsignedby[key->index])
662 if (!issigningkey(key))
665 if (set->type == dns_rdatatype_dnskey &&
666 dns_name_equal(name, gorigin)) {
667 isc_boolean_t have_ksk;
668 dns_dnsseckey_t *tmpkey;
670 have_ksk = isksk(key);
671 for (tmpkey = ISC_LIST_HEAD(keylist);
673 tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
674 if (dst_key_alg(key->key) !=
675 dst_key_alg(tmpkey->key))
677 if (REVOKE(tmpkey->key))
682 if (isksk(key) || !have_ksk ||
683 (iszsk(key) && !keyset_kskonly))
684 signwithkey(name, set, key->key, ttl, add,
685 "signing with dnskey");
686 } else if (iszsk(key)) {
687 signwithkey(name, set, key->key, ttl, add,
688 "signing with dnskey");
692 isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t));
693 isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t));
697 unsigned char *hashbuf;
704 hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) {
707 l->length = length + 1;
711 l->hashbuf = malloc(l->size * l->length);
712 if (l->hashbuf == NULL)
721 hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len)
724 REQUIRE(len <= l->length);
726 if (l->entries == l->size) {
727 l->size = l->size * 2 + 100;
728 l->hashbuf = realloc(l->hashbuf, l->size * l->length);
729 if (l->hashbuf == NULL)
730 fatal("unable to grow hashlist: out of memory");
732 memset(l->hashbuf + l->entries * l->length, 0, l->length);
733 memmove(l->hashbuf + l->entries * l->length, hash, len);
738 hashlist_add_dns_name(hashlist_t *l, /*const*/ dns_name_t *name,
739 unsigned int hashalg, unsigned int iterations,
740 const unsigned char *salt, size_t salt_length,
741 isc_boolean_t speculative)
743 char nametext[DNS_NAME_FORMATSIZE];
744 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
748 len = isc_iterated_hash(hash, hashalg, iterations,
749 salt, (int)salt_length,
750 name->ndata, name->length);
752 dns_name_format(name, nametext, sizeof nametext);
753 for (i = 0 ; i < len; i++)
754 fprintf(stderr, "%02x", hash[i]);
755 fprintf(stderr, " %s\n", nametext);
757 hash[len++] = speculative ? 1 : 0;
758 hashlist_add(l, hash, len);
762 hashlist_comp(const void *a, const void *b) {
763 return (memcmp(a, b, hash_length + 1));
767 hashlist_sort(hashlist_t *l) {
768 qsort(l->hashbuf, l->entries, l->length, hashlist_comp);
772 hashlist_hasdup(hashlist_t *l) {
773 unsigned char *current;
774 unsigned char *next = l->hashbuf;
775 size_t entries = l->entries;
778 * Skip initial speculative wild card hashs.
780 while (entries > 0U && next[l->length-1] != 0U) {
786 while (entries-- > 1U) {
788 if (next[l->length-1] != 0)
790 if (memcmp(current, next, l->length - 1) == 0)
797 static const unsigned char *
798 hashlist_findnext(const hashlist_t *l,
799 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
801 size_t entries = l->entries;
802 const unsigned char *next = bsearch(hash, l->hashbuf, l->entries,
803 l->length, hashlist_comp);
804 INSIST(next != NULL);
807 if (next < l->hashbuf + (l->entries - 1) * l->length)
811 if (next[l->length - 1] == 0)
813 } while (entries-- > 1U);
814 INSIST(entries != 0U);
819 hashlist_exists(const hashlist_t *l,
820 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
822 if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp))
829 addnowildcardhash(hashlist_t *l, /*const*/ dns_name_t *name,
830 unsigned int hashalg, unsigned int iterations,
831 const unsigned char *salt, size_t salt_length)
833 dns_fixedname_t fixed;
835 dns_dbnode_t *node = NULL;
837 char namestr[DNS_NAME_FORMATSIZE];
839 dns_fixedname_init(&fixed);
840 wild = dns_fixedname_name(&fixed);
842 result = dns_name_concatenate(dns_wildcardname, name, wild, NULL);
843 if (result == ISC_R_NOSPACE)
845 check_result(result,"addnowildcardhash: dns_name_concatenate()");
847 result = dns_db_findnode(gdb, wild, ISC_FALSE, &node);
848 if (result == ISC_R_SUCCESS) {
849 dns_db_detachnode(gdb, &node);
854 dns_name_format(wild, namestr, sizeof(namestr));
855 fprintf(stderr, "adding no-wildcardhash for %s\n", namestr);
858 hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_length,
863 opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
866 char filename[PATH_MAX];
870 isc_buffer_init(&b, filename, sizeof(filename));
872 /* allow room for a trailing slash */
873 if (strlen(dsdir) >= isc_buffer_availablelength(&b))
874 fatal("path '%s' is too long", dsdir);
875 isc_buffer_putstr(&b, dsdir);
876 if (dsdir[strlen(dsdir) - 1] != '/')
877 isc_buffer_putstr(&b, "/");
879 if (strlen(prefix) > isc_buffer_availablelength(&b))
880 fatal("path '%s' is too long", dsdir);
881 isc_buffer_putstr(&b, prefix);
882 result = dns_name_tofilenametext(name, ISC_FALSE, &b);
883 check_result(result, "dns_name_tofilenametext()");
884 if (isc_buffer_availablelength(&b) == 0) {
885 char namestr[DNS_NAME_FORMATSIZE];
886 dns_name_format(name, namestr, sizeof(namestr));
887 fatal("name '%s' is too long", namestr);
889 isc_buffer_putuint8(&b, 0);
891 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
892 rdclass, 0, NULL, dbp);
893 check_result(result, "dns_db_create()");
895 result = dns_db_load3(*dbp, filename, inputformat, DNS_MASTER_HINT);
896 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
901 * Load the DS set for a child zone, if a dsset-* file can be found.
902 * If not, try to find a keyset-* file from an earlier version of
903 * dnssec-signzone, and build DS records from that.
906 loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
908 dns_dbversion_t *ver = NULL;
909 dns_dbnode_t *node = NULL;
911 dns_rdataset_t keyset;
913 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
915 dns_difftuple_t *tuple = NULL;
917 opendb("dsset-", name, gclass, &db);
919 result = dns_db_findnode(db, name, ISC_FALSE, &node);
920 if (result == ISC_R_SUCCESS) {
921 dns_rdataset_init(dsset);
922 result = dns_db_findrdataset(db, node, NULL,
923 dns_rdatatype_ds, 0, 0,
925 dns_db_detachnode(db, &node);
926 if (result == ISC_R_SUCCESS) {
927 vbprintf(2, "found DS records\n");
936 /* No DS records found; try again, looking for DNSKEY records */
937 opendb("keyset-", name, gclass, &db);
939 return (ISC_R_NOTFOUND);
942 result = dns_db_findnode(db, name, ISC_FALSE, &node);
943 if (result != ISC_R_SUCCESS) {
948 dns_rdataset_init(&keyset);
949 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
951 if (result != ISC_R_SUCCESS) {
952 dns_db_detachnode(db, &node);
956 vbprintf(2, "found DNSKEY records\n");
958 result = dns_db_newversion(db, &ver);
959 check_result(result, "dns_db_newversion");
960 dns_diff_init(mctx, &diff);
962 for (result = dns_rdataset_first(&keyset);
963 result == ISC_R_SUCCESS;
964 result = dns_rdataset_next(&keyset))
966 dns_rdata_init(&key);
968 dns_rdataset_current(&keyset, &key);
969 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
971 check_result(result, "dns_ds_buildrdata");
973 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
975 check_result(result, "dns_difftuple_create");
976 dns_diff_append(&diff, &tuple);
978 dns_rdata_reset(&ds);
979 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
981 check_result(result, "dns_ds_buildrdata");
983 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
985 check_result(result, "dns_difftuple_create");
986 dns_diff_append(&diff, &tuple);
989 result = dns_diff_apply(&diff, db, ver);
990 check_result(result, "dns_diff_apply");
991 dns_diff_clear(&diff);
993 dns_db_closeversion(db, &ver, ISC_TRUE);
995 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
997 check_result(result, "dns_db_findrdataset");
999 dns_rdataset_disassociate(&keyset);
1000 dns_db_detachnode(db, &node);
1005 static isc_boolean_t
1006 secure(dns_name_t *name, dns_dbnode_t *node) {
1007 dns_rdataset_t dsset;
1008 isc_result_t result;
1010 if (dns_name_equal(name, gorigin))
1013 dns_rdataset_init(&dsset);
1014 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds,
1015 0, 0, &dsset, NULL);
1016 if (dns_rdataset_isassociated(&dsset))
1017 dns_rdataset_disassociate(&dsset);
1019 return (ISC_TF(result == ISC_R_SUCCESS));
1023 * Signs all records at a name.
1026 signname(dns_dbnode_t *node, dns_name_t *name) {
1027 isc_result_t result;
1028 dns_rdataset_t rdataset;
1029 dns_rdatasetiter_t *rdsiter;
1030 isc_boolean_t isdelegation = ISC_FALSE;
1031 dns_diff_t del, add;
1032 char namestr[DNS_NAME_FORMATSIZE];
1034 dns_rdataset_init(&rdataset);
1035 dns_name_format(name, namestr, sizeof(namestr));
1038 * Determine if this is a delegation point.
1040 if (is_delegation(gdb, gversion, gorigin, name, node, NULL))
1041 isdelegation = ISC_TRUE;
1044 * Now iterate through the rdatasets.
1046 dns_diff_init(mctx, &del);
1047 dns_diff_init(mctx, &add);
1049 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1050 check_result(result, "dns_db_allrdatasets()");
1051 result = dns_rdatasetiter_first(rdsiter);
1052 while (result == ISC_R_SUCCESS) {
1053 dns_rdatasetiter_current(rdsiter, &rdataset);
1055 /* If this is a RRSIG set, skip it. */
1056 if (rdataset.type == dns_rdatatype_rrsig)
1060 * If this name is a delegation point, skip all records
1061 * except NSEC and DS sets. Otherwise check that there
1062 * isn't a DS record.
1065 if (rdataset.type != nsec_datatype &&
1066 rdataset.type != dns_rdatatype_ds)
1068 } else if (rdataset.type == dns_rdatatype_ds) {
1069 char namebuf[DNS_NAME_FORMATSIZE];
1070 dns_name_format(name, namebuf, sizeof(namebuf));
1071 fatal("'%s': found DS RRset without NS RRset\n",
1075 signset(&del, &add, node, name, &rdataset);
1078 dns_rdataset_disassociate(&rdataset);
1079 result = dns_rdatasetiter_next(rdsiter);
1081 if (result != ISC_R_NOMORE)
1082 fatal("rdataset iteration for name '%s' failed: %s",
1083 namestr, isc_result_totext(result));
1085 dns_rdatasetiter_destroy(&rdsiter);
1087 result = dns_diff_applysilently(&del, gdb, gversion);
1088 if (result != ISC_R_SUCCESS)
1089 fatal("failed to delete SIGs at node '%s': %s",
1090 namestr, isc_result_totext(result));
1092 result = dns_diff_applysilently(&add, gdb, gversion);
1093 if (result != ISC_R_SUCCESS)
1094 fatal("failed to add SIGs at node '%s': %s",
1095 namestr, isc_result_totext(result));
1097 dns_diff_clear(&del);
1098 dns_diff_clear(&add);
1101 static inline isc_boolean_t
1102 active_node(dns_dbnode_t *node) {
1103 dns_rdatasetiter_t *rdsiter = NULL;
1104 dns_rdatasetiter_t *rdsiter2 = NULL;
1105 isc_boolean_t active = ISC_FALSE;
1106 isc_result_t result;
1107 dns_rdataset_t rdataset;
1108 dns_rdatatype_t type;
1109 dns_rdatatype_t covers;
1110 isc_boolean_t found;
1112 dns_rdataset_init(&rdataset);
1113 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1114 check_result(result, "dns_db_allrdatasets()");
1115 result = dns_rdatasetiter_first(rdsiter);
1116 while (result == ISC_R_SUCCESS) {
1117 dns_rdatasetiter_current(rdsiter, &rdataset);
1118 if (rdataset.type != dns_rdatatype_nsec &&
1119 rdataset.type != dns_rdatatype_nsec3 &&
1120 rdataset.type != dns_rdatatype_rrsig)
1122 dns_rdataset_disassociate(&rdataset);
1124 result = dns_rdatasetiter_next(rdsiter);
1126 result = ISC_R_NOMORE;
1128 if (result != ISC_R_NOMORE)
1129 fatal("rdataset iteration failed: %s",
1130 isc_result_totext(result));
1132 if (!active && nsec_datatype == dns_rdatatype_nsec) {
1134 * The node is empty of everything but NSEC / RRSIG records.
1136 for (result = dns_rdatasetiter_first(rdsiter);
1137 result == ISC_R_SUCCESS;
1138 result = dns_rdatasetiter_next(rdsiter)) {
1139 dns_rdatasetiter_current(rdsiter, &rdataset);
1140 result = dns_db_deleterdataset(gdb, node, gversion,
1143 check_result(result, "dns_db_deleterdataset()");
1144 dns_rdataset_disassociate(&rdataset);
1146 if (result != ISC_R_NOMORE)
1147 fatal("rdataset iteration failed: %s",
1148 isc_result_totext(result));
1151 * Delete RRSIGs for types that no longer exist.
1153 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
1154 check_result(result, "dns_db_allrdatasets()");
1155 for (result = dns_rdatasetiter_first(rdsiter);
1156 result == ISC_R_SUCCESS;
1157 result = dns_rdatasetiter_next(rdsiter)) {
1158 dns_rdatasetiter_current(rdsiter, &rdataset);
1159 type = rdataset.type;
1160 covers = rdataset.covers;
1161 dns_rdataset_disassociate(&rdataset);
1163 * Delete the NSEC chain if we are signing with
1166 if (nsec_datatype == dns_rdatatype_nsec3 &&
1167 (type == dns_rdatatype_nsec ||
1168 covers == dns_rdatatype_nsec)) {
1169 result = dns_db_deleterdataset(gdb, node,
1172 check_result(result,
1173 "dns_db_deleterdataset(nsec/rrsig)");
1176 if (type != dns_rdatatype_rrsig)
1179 for (result = dns_rdatasetiter_first(rdsiter2);
1180 !found && result == ISC_R_SUCCESS;
1181 result = dns_rdatasetiter_next(rdsiter2)) {
1182 dns_rdatasetiter_current(rdsiter2, &rdataset);
1183 if (rdataset.type == covers)
1185 dns_rdataset_disassociate(&rdataset);
1188 if (result != ISC_R_NOMORE)
1189 fatal("rdataset iteration failed: %s",
1190 isc_result_totext(result));
1191 result = dns_db_deleterdataset(gdb, node,
1194 check_result(result,
1195 "dns_db_deleterdataset(rrsig)");
1196 } else if (result != ISC_R_NOMORE &&
1197 result != ISC_R_SUCCESS)
1198 fatal("rdataset iteration failed: %s",
1199 isc_result_totext(result));
1201 if (result != ISC_R_NOMORE)
1202 fatal("rdataset iteration failed: %s",
1203 isc_result_totext(result));
1204 dns_rdatasetiter_destroy(&rdsiter2);
1206 dns_rdatasetiter_destroy(&rdsiter);
1212 * Extracts the minimum TTL from the SOA record, and the SOA record's TTL.
1215 get_soa_ttls(void) {
1216 dns_rdataset_t soaset;
1217 dns_fixedname_t fname;
1219 isc_result_t result;
1220 dns_rdata_t rdata = DNS_RDATA_INIT;
1222 dns_fixedname_init(&fname);
1223 name = dns_fixedname_name(&fname);
1224 dns_rdataset_init(&soaset);
1225 result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
1226 0, 0, NULL, name, &soaset, NULL);
1227 if (result != ISC_R_SUCCESS)
1228 fatal("failed to find an SOA at the zone apex: %s",
1229 isc_result_totext(result));
1231 result = dns_rdataset_first(&soaset);
1232 check_result(result, "dns_rdataset_first");
1233 dns_rdataset_current(&soaset, &rdata);
1234 zone_soa_min_ttl = dns_soa_getminimum(&rdata);
1235 soa_ttl = soaset.ttl;
1236 dns_rdataset_disassociate(&soaset);
1240 * Increment (or set if nonzero) the SOA serial
1243 setsoaserial(isc_uint32_t serial) {
1244 isc_result_t result;
1245 dns_dbnode_t *node = NULL;
1246 dns_rdataset_t rdataset;
1247 dns_rdata_t rdata = DNS_RDATA_INIT;
1248 isc_uint32_t old_serial, new_serial;
1250 result = dns_db_getoriginnode(gdb, &node);
1251 if (result != ISC_R_SUCCESS)
1254 dns_rdataset_init(&rdataset);
1256 result = dns_db_findrdataset(gdb, node, gversion,
1257 dns_rdatatype_soa, 0,
1258 0, &rdataset, NULL);
1259 if (result != ISC_R_SUCCESS)
1262 result = dns_rdataset_first(&rdataset);
1263 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1265 dns_rdataset_current(&rdataset, &rdata);
1267 old_serial = dns_soa_getserial(&rdata);
1270 /* Set SOA serial to the value provided. */
1271 new_serial = serial;
1273 /* Increment SOA serial using RFC 1982 arithmetics */
1274 new_serial = (old_serial + 1) & 0xFFFFFFFF;
1275 if (new_serial == 0)
1279 /* If the new serial is not likely to cause a zone transfer
1280 * (a/ixfr) from servers having the old serial, warn the user.
1282 * RFC1982 section 7 defines the maximum increment to be
1283 * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
1284 * comparison. (5 - 6 == (2^32)-1, not negative-one)
1286 if (new_serial == old_serial ||
1287 (new_serial - old_serial) > 0x7fffffffU)
1288 fprintf(stderr, "%s: warning: Serial number not advanced, "
1289 "zone may not transfer\n", program);
1291 dns_soa_setserial(new_serial, &rdata);
1293 result = dns_db_deleterdataset(gdb, node, gversion,
1294 dns_rdatatype_soa, 0);
1295 check_result(result, "dns_db_deleterdataset");
1296 if (result != ISC_R_SUCCESS)
1299 result = dns_db_addrdataset(gdb, node, gversion,
1300 0, &rdataset, 0, NULL);
1301 check_result(result, "dns_db_addrdataset");
1302 if (result != ISC_R_SUCCESS)
1306 dns_rdataset_disassociate(&rdataset);
1308 dns_db_detachnode(gdb, &node);
1309 dns_rdata_reset(&rdata);
1315 * Delete any RRSIG records at a node.
1318 cleannode(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
1319 dns_rdatasetiter_t *rdsiter = NULL;
1321 isc_result_t result, dresult;
1323 if (outputformat != dns_masterformat_text || !disable_zone_check)
1326 dns_rdataset_init(&set);
1327 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
1328 check_result(result, "dns_db_allrdatasets");
1329 result = dns_rdatasetiter_first(rdsiter);
1330 while (result == ISC_R_SUCCESS) {
1331 isc_boolean_t destroy = ISC_FALSE;
1332 dns_rdatatype_t covers = 0;
1333 dns_rdatasetiter_current(rdsiter, &set);
1334 if (set.type == dns_rdatatype_rrsig) {
1335 covers = set.covers;
1338 dns_rdataset_disassociate(&set);
1339 result = dns_rdatasetiter_next(rdsiter);
1341 dresult = dns_db_deleterdataset(db, node, version,
1342 dns_rdatatype_rrsig,
1344 check_result(dresult, "dns_db_deleterdataset");
1347 if (result != ISC_R_NOMORE)
1348 fatal("rdataset iteration failed: %s",
1349 isc_result_totext(result));
1350 dns_rdatasetiter_destroy(&rdsiter);
1354 * Set up the iterator and global state before starting the tasks.
1358 isc_result_t result;
1361 result = dns_db_createiterator(gdb, 0, &gdbiter);
1362 check_result(result, "dns_db_createiterator()");
1366 * Clean up the iterator and global state after the tasks complete.
1370 dns_dbiterator_destroy(&gdbiter);
1374 * Sign the apex of the zone.
1375 * Note the origin may not be the first node if there are out of zone
1380 dns_dbnode_t *node = NULL;
1381 dns_fixedname_t fixed;
1383 isc_result_t result;
1385 dns_fixedname_init(&fixed);
1386 name = dns_fixedname_name(&fixed);
1387 result = dns_dbiterator_seek(gdbiter, gorigin);
1388 check_result(result, "dns_dbiterator_seek()");
1389 result = dns_dbiterator_current(gdbiter, &node, name);
1390 check_dns_dbiterator_current(result);
1391 signname(node, name);
1392 dumpnode(name, node);
1393 cleannode(gdb, gversion, node);
1394 dns_db_detachnode(gdb, &node);
1395 result = dns_dbiterator_first(gdbiter);
1396 if (result == ISC_R_NOMORE)
1397 finished = ISC_TRUE;
1398 else if (result != ISC_R_SUCCESS)
1399 fatal("failure iterating database: %s",
1400 isc_result_totext(result));
1404 * Assigns a node to a worker thread. This is protected by the master task's
1408 assignwork(isc_task_t *task, isc_task_t *worker) {
1409 dns_fixedname_t *fname;
1413 dns_rdataset_t nsec;
1414 isc_boolean_t found;
1415 isc_result_t result;
1416 static dns_name_t *zonecut = NULL; /* Protected by namelock. */
1417 static dns_fixedname_t fzonecut; /* Protected by namelock. */
1418 static unsigned int ended = 0; /* Protected by namelock. */
1426 if (ended == ntasks) {
1427 isc_task_detach(&task);
1433 fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
1435 fatal("out of memory");
1436 dns_fixedname_init(fname);
1437 name = dns_fixedname_name(fname);
1441 result = dns_dbiterator_current(gdbiter, &node, name);
1442 check_dns_dbiterator_current(result);
1444 * The origin was handled by signapex().
1446 if (dns_name_equal(name, gorigin)) {
1447 dns_db_detachnode(gdb, &node);
1451 * Sort the zone data from the glue and out-of-zone data.
1452 * For NSEC zones nodes with zone data have NSEC records.
1453 * For NSEC3 zones the NSEC3 nodes are zone data but
1454 * outside of the zone name space. For the rest we need
1455 * to track the bottom of zone cuts.
1456 * Nodes which don't need to be signed are dumped here.
1458 dns_rdataset_init(&nsec);
1459 result = dns_db_findrdataset(gdb, node, gversion,
1460 nsec_datatype, 0, 0,
1462 if (dns_rdataset_isassociated(&nsec))
1463 dns_rdataset_disassociate(&nsec);
1464 if (result == ISC_R_SUCCESS) {
1466 } else if (nsec_datatype == dns_rdatatype_nsec3) {
1467 if (dns_name_issubdomain(name, gorigin) &&
1469 !dns_name_issubdomain(name, zonecut))) {
1470 if (is_delegation(gdb, gversion, gorigin, name, node, NULL)) {
1471 dns_fixedname_init(&fzonecut);
1472 zonecut = dns_fixedname_name(&fzonecut);
1473 dns_name_copy(name, zonecut, NULL);
1474 if (!OPTOUT(nsec3flags) ||
1483 dumpnode(name, node);
1484 dns_db_detachnode(gdb, &node);
1488 result = dns_dbiterator_next(gdbiter);
1489 if (result == ISC_R_NOMORE) {
1490 finished = ISC_TRUE;
1492 } else if (result != ISC_R_SUCCESS)
1493 fatal("failure iterating database: %s",
1494 isc_result_totext(result));
1498 if (ended == ntasks) {
1499 isc_task_detach(&task);
1502 isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
1505 sevent = (sevent_t *)
1506 isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
1507 sign, NULL, sizeof(sevent_t));
1509 fatal("failed to allocate event\n");
1511 sevent->node = node;
1512 sevent->fname = fname;
1513 isc_task_send(worker, ISC_EVENT_PTR(&sevent));
1519 * Start a worker task
1522 startworker(isc_task_t *task, isc_event_t *event) {
1525 worker = (isc_task_t *)event->ev_arg;
1526 assignwork(task, worker);
1527 isc_event_free(&event);
1531 * Write a node to the output file, and restart the worker task.
1534 writenode(isc_task_t *task, isc_event_t *event) {
1536 sevent_t *sevent = (sevent_t *)event;
1538 worker = (isc_task_t *)event->ev_sender;
1539 dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
1540 cleannode(gdb, gversion, sevent->node);
1541 dns_db_detachnode(gdb, &sevent->node);
1542 isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
1543 assignwork(task, worker);
1544 isc_event_free(&event);
1548 * Sign a database node.
1551 sign(isc_task_t *task, isc_event_t *event) {
1552 dns_fixedname_t *fname;
1554 sevent_t *sevent, *wevent;
1556 sevent = (sevent_t *)event;
1557 node = sevent->node;
1558 fname = sevent->fname;
1559 isc_event_free(&event);
1561 signname(node, dns_fixedname_name(fname));
1562 wevent = (sevent_t *)
1563 isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
1564 writenode, NULL, sizeof(sevent_t));
1566 fatal("failed to allocate event\n");
1567 wevent->node = node;
1568 wevent->fname = fname;
1569 isc_task_send(master, ISC_EVENT_PTR(&wevent));
1573 * Update / remove the DS RRset. Preserve RRSIG(DS) if possible.
1576 add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) {
1577 dns_rdataset_t dsset;
1578 dns_rdataset_t sigdsset;
1579 isc_result_t result;
1581 dns_rdataset_init(&dsset);
1582 dns_rdataset_init(&sigdsset);
1583 result = dns_db_findrdataset(gdb, node, gversion,
1585 0, 0, &dsset, &sigdsset);
1586 if (result == ISC_R_SUCCESS) {
1587 dns_rdataset_disassociate(&dsset);
1588 result = dns_db_deleterdataset(gdb, node, gversion,
1589 dns_rdatatype_ds, 0);
1590 check_result(result, "dns_db_deleterdataset");
1593 result = loadds(name, nsttl, &dsset);
1594 if (result == ISC_R_SUCCESS) {
1595 result = dns_db_addrdataset(gdb, node, gversion, 0,
1597 check_result(result, "dns_db_addrdataset");
1598 dns_rdataset_disassociate(&dsset);
1599 if (dns_rdataset_isassociated(&sigdsset))
1600 dns_rdataset_disassociate(&sigdsset);
1601 } else if (dns_rdataset_isassociated(&sigdsset)) {
1602 result = dns_db_deleterdataset(gdb, node, gversion,
1603 dns_rdatatype_rrsig,
1605 check_result(result, "dns_db_deleterdataset");
1606 dns_rdataset_disassociate(&sigdsset);
1611 * Remove records of the given type and their signatures.
1614 remove_records(dns_dbnode_t *node, dns_rdatatype_t which,
1615 isc_boolean_t checknsec)
1617 isc_result_t result;
1618 dns_rdatatype_t type, covers;
1619 dns_rdatasetiter_t *rdsiter = NULL;
1620 dns_rdataset_t rdataset;
1622 dns_rdataset_init(&rdataset);
1625 * Delete any records of the given type at the apex.
1627 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1628 check_result(result, "dns_db_allrdatasets()");
1629 for (result = dns_rdatasetiter_first(rdsiter);
1630 result == ISC_R_SUCCESS;
1631 result = dns_rdatasetiter_next(rdsiter)) {
1632 dns_rdatasetiter_current(rdsiter, &rdataset);
1633 type = rdataset.type;
1634 covers = rdataset.covers;
1635 dns_rdataset_disassociate(&rdataset);
1636 if (type == which || covers == which) {
1637 if (which == dns_rdatatype_nsec &&
1638 checknsec && !update_chain)
1639 fatal("Zone contains NSEC records. Use -u "
1640 "to update to NSEC3.");
1641 if (which == dns_rdatatype_nsec3param &&
1642 checknsec && !update_chain)
1643 fatal("Zone contains NSEC3 chains. Use -u "
1644 "to update to NSEC.");
1645 result = dns_db_deleterdataset(gdb, node, gversion,
1647 check_result(result, "dns_db_deleterdataset()");
1651 dns_rdatasetiter_destroy(&rdsiter);
1655 * Remove signatures covering the given type (0 == all signatures).
1658 remove_sigs(dns_dbnode_t *node, dns_rdatatype_t which) {
1659 isc_result_t result;
1660 dns_rdatatype_t type, covers;
1661 dns_rdatasetiter_t *rdsiter = NULL;
1662 dns_rdataset_t rdataset;
1664 dns_rdataset_init(&rdataset);
1665 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1666 check_result(result, "dns_db_allrdatasets()");
1667 for (result = dns_rdatasetiter_first(rdsiter);
1668 result == ISC_R_SUCCESS;
1669 result = dns_rdatasetiter_next(rdsiter)) {
1670 dns_rdatasetiter_current(rdsiter, &rdataset);
1671 type = rdataset.type;
1672 covers = rdataset.covers;
1673 dns_rdataset_disassociate(&rdataset);
1675 if (type == dns_rdatatype_rrsig &&
1676 (covers == which || which == 0))
1678 result = dns_db_deleterdataset(gdb, node, gversion,
1680 check_result(result, "dns_db_deleterdataset()");
1684 dns_rdatasetiter_destroy(&rdsiter);
1688 * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records.
1692 dns_dbiterator_t *dbiter = NULL;
1693 dns_dbnode_t *node = NULL, *nextnode = NULL;
1694 dns_fixedname_t fname, fnextname, fzonecut;
1695 dns_name_t *name, *nextname, *zonecut;
1696 dns_rdataset_t rdataset;
1697 dns_rdatasetiter_t *rdsiter = NULL;
1698 dns_rdatatype_t type, covers;
1699 isc_boolean_t done = ISC_FALSE;
1700 isc_result_t result;
1701 isc_uint32_t nsttl = 0;
1703 dns_rdataset_init(&rdataset);
1704 dns_fixedname_init(&fname);
1705 name = dns_fixedname_name(&fname);
1706 dns_fixedname_init(&fnextname);
1707 nextname = dns_fixedname_name(&fnextname);
1708 dns_fixedname_init(&fzonecut);
1712 * Remove any NSEC3 chains.
1714 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
1715 check_result(result, "dns_db_createiterator()");
1716 for (result = dns_dbiterator_first(dbiter);
1717 result == ISC_R_SUCCESS;
1718 result = dns_dbiterator_next(dbiter)) {
1719 result = dns_dbiterator_current(dbiter, &node, name);
1720 check_dns_dbiterator_current(result);
1721 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1722 check_result(result, "dns_db_allrdatasets()");
1723 for (result = dns_rdatasetiter_first(rdsiter);
1724 result == ISC_R_SUCCESS;
1725 result = dns_rdatasetiter_next(rdsiter)) {
1726 dns_rdatasetiter_current(rdsiter, &rdataset);
1727 type = rdataset.type;
1728 covers = rdataset.covers;
1729 dns_rdataset_disassociate(&rdataset);
1730 result = dns_db_deleterdataset(gdb, node, gversion,
1732 check_result(result,
1733 "dns_db_deleterdataset(nsec3param/rrsig)");
1735 dns_rdatasetiter_destroy(&rdsiter);
1736 dns_db_detachnode(gdb, &node);
1738 dns_dbiterator_destroy(&dbiter);
1740 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
1741 check_result(result, "dns_db_createiterator()");
1743 result = dns_dbiterator_first(dbiter);
1744 check_result(result, "dns_dbiterator_first()");
1747 result = dns_dbiterator_current(dbiter, &node, name);
1748 check_dns_dbiterator_current(result);
1750 * Skip out-of-zone records.
1752 if (!dns_name_issubdomain(name, gorigin)) {
1753 result = dns_dbiterator_next(dbiter);
1754 if (result == ISC_R_NOMORE)
1757 check_result(result, "dns_dbiterator_next()");
1758 dns_db_detachnode(gdb, &node);
1762 if (dns_name_equal(name, gorigin))
1763 remove_records(node, dns_rdatatype_nsec3param,
1766 if (is_delegation(gdb, gversion, gorigin, name, node, &nsttl)) {
1767 zonecut = dns_fixedname_name(&fzonecut);
1768 dns_name_copy(name, zonecut, NULL);
1769 remove_sigs(node, 0);
1771 add_ds(name, node, nsttl);
1774 result = dns_dbiterator_next(dbiter);
1776 while (result == ISC_R_SUCCESS) {
1777 isc_boolean_t active = ISC_FALSE;
1778 result = dns_dbiterator_current(dbiter, &nextnode,
1780 check_dns_dbiterator_current(result);
1781 active = active_node(nextnode);
1783 dns_db_detachnode(gdb, &nextnode);
1784 result = dns_dbiterator_next(dbiter);
1787 if (!dns_name_issubdomain(nextname, gorigin) ||
1789 dns_name_issubdomain(nextname, zonecut)))
1791 remove_sigs(nextnode, 0);
1792 remove_records(nextnode, dns_rdatatype_nsec,
1794 dns_db_detachnode(gdb, &nextnode);
1795 result = dns_dbiterator_next(dbiter);
1798 dns_db_detachnode(gdb, &nextnode);
1801 if (result == ISC_R_NOMORE) {
1802 dns_name_clone(gorigin, nextname);
1804 } else if (result != ISC_R_SUCCESS)
1805 fatal("iterating through the database failed: %s",
1806 isc_result_totext(result));
1807 dns_dbiterator_pause(dbiter);
1808 result = dns_nsec_build(gdb, gversion, node, nextname,
1810 check_result(result, "dns_nsec_build()");
1811 dns_db_detachnode(gdb, &node);
1814 dns_dbiterator_destroy(&dbiter);
1818 addnsec3param(const unsigned char *salt, size_t salt_length,
1819 dns_iterations_t iterations)
1821 dns_dbnode_t *node = NULL;
1822 dns_rdata_nsec3param_t nsec3param;
1823 unsigned char nsec3parambuf[5 + 255];
1824 dns_rdatalist_t rdatalist;
1825 dns_rdataset_t rdataset;
1826 dns_rdata_t rdata = DNS_RDATA_INIT;
1828 isc_result_t result;
1830 dns_rdataset_init(&rdataset);
1832 nsec3param.common.rdclass = gclass;
1833 nsec3param.common.rdtype = dns_rdatatype_nsec3param;
1834 ISC_LINK_INIT(&nsec3param.common, link);
1835 nsec3param.mctx = NULL;
1836 nsec3param.flags = 0;
1837 nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1;
1838 nsec3param.iterations = iterations;
1839 nsec3param.salt_length = (unsigned char)salt_length;
1840 DE_CONST(salt, nsec3param.salt);
1842 isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf));
1843 result = dns_rdata_fromstruct(&rdata, gclass,
1844 dns_rdatatype_nsec3param,
1846 check_result(result, "dns_rdata_fromstruct()");
1847 rdatalist.rdclass = rdata.rdclass;
1848 rdatalist.type = rdata.type;
1849 rdatalist.covers = 0;
1851 ISC_LIST_INIT(rdatalist.rdata);
1852 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
1853 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
1854 check_result(result, "dns_rdatalist_tordataset()");
1856 result = dns_db_findnode(gdb, gorigin, ISC_TRUE, &node);
1857 check_result(result, "dns_db_find(gorigin)");
1860 * Delete any current NSEC3PARAM records.
1862 result = dns_db_deleterdataset(gdb, node, gversion,
1863 dns_rdatatype_nsec3param, 0);
1864 if (result == DNS_R_UNCHANGED)
1865 result = ISC_R_SUCCESS;
1866 check_result(result, "dddnsec3param: dns_db_deleterdataset()");
1868 result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset,
1869 DNS_DBADD_MERGE, NULL);
1870 if (result == DNS_R_UNCHANGED)
1871 result = ISC_R_SUCCESS;
1872 check_result(result, "addnsec3param: dns_db_addrdataset()");
1873 dns_db_detachnode(gdb, &node);
1877 addnsec3(dns_name_t *name, dns_dbnode_t *node,
1878 const unsigned char *salt, size_t salt_length,
1879 unsigned int iterations, hashlist_t *hashlist,
1882 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
1883 const unsigned char *nexthash;
1884 unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE];
1885 dns_fixedname_t hashname;
1886 dns_rdatalist_t rdatalist;
1887 dns_rdataset_t rdataset;
1888 dns_rdata_t rdata = DNS_RDATA_INIT;
1889 isc_result_t result;
1890 dns_dbnode_t *nsec3node = NULL;
1891 char namebuf[DNS_NAME_FORMATSIZE];
1894 dns_name_format(name, namebuf, sizeof(namebuf));
1896 dns_fixedname_init(&hashname);
1897 dns_rdataset_init(&rdataset);
1899 dns_name_downcase(name, name, NULL);
1900 result = dns_nsec3_hashname(&hashname, hash, &hash_length,
1901 name, gorigin, dns_hash_sha1, iterations,
1903 check_result(result, "addnsec3: dns_nsec3_hashname()");
1904 nexthash = hashlist_findnext(hashlist, hash);
1905 result = dns_nsec3_buildrdata(gdb, gversion, node,
1907 DNS_NSEC3_UNKNOWNALG : dns_hash_sha1,
1908 nsec3flags, iterations,
1910 nexthash, ISC_SHA1_DIGESTLENGTH,
1911 nsec3buffer, &rdata);
1912 check_result(result, "addnsec3: dns_nsec3_buildrdata()");
1913 rdatalist.rdclass = rdata.rdclass;
1914 rdatalist.type = rdata.type;
1915 rdatalist.covers = 0;
1916 rdatalist.ttl = ttl;
1917 ISC_LIST_INIT(rdatalist.rdata);
1918 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
1919 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
1920 check_result(result, "dns_rdatalist_tordataset()");
1921 result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname),
1922 ISC_TRUE, &nsec3node);
1923 check_result(result, "addnsec3: dns_db_findnode()");
1924 result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset,
1926 if (result == DNS_R_UNCHANGED)
1927 result = ISC_R_SUCCESS;
1928 check_result(result, "addnsec3: dns_db_addrdataset()");
1929 dns_db_detachnode(gdb, &nsec3node);
1933 * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list.
1935 * Extract the hash from the first label of 'name' then see if it
1936 * is in hashlist. If 'name' is not in the hashlist then delete the
1937 * any NSEC3 records which have the same parameters as the chain we
1940 * XXXMPA Should we also check that it of the form <hash>.<origin>?
1943 nsec3clean(dns_name_t *name, dns_dbnode_t *node,
1944 unsigned int hashalg, unsigned int iterations,
1945 const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
1948 dns_rdata_nsec3_t nsec3;
1949 dns_rdata_t rdata, delrdata;
1950 dns_rdatalist_t rdatalist;
1951 dns_rdataset_t rdataset, delrdataset;
1952 isc_boolean_t delete_rrsigs = ISC_FALSE;
1953 isc_buffer_t target;
1954 isc_result_t result;
1955 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
1956 isc_boolean_t exists;
1959 * Get the first label.
1961 dns_name_getlabel(name, 0, &label);
1964 * We want just the label contents.
1966 isc_region_consume(&label, 1);
1969 * Decode base32hex string.
1971 isc_buffer_init(&target, hash, sizeof(hash) - 1);
1972 result = isc_base32hex_decoderegion(&label, &target);
1973 if (result != ISC_R_SUCCESS)
1976 hash[isc_buffer_usedlength(&target)] = 0;
1978 exists = hashlist_exists(hashlist, hash);
1981 * Verify that the NSEC3 parameters match the current ones
1982 * otherwise we are dealing with a different NSEC3 chain.
1984 dns_rdataset_init(&rdataset);
1985 dns_rdataset_init(&delrdataset);
1987 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3,
1988 0, 0, &rdataset, NULL);
1989 if (result != ISC_R_SUCCESS)
1993 * Delete any NSEC3 records which are not part of the current
1996 for (result = dns_rdataset_first(&rdataset);
1997 result == ISC_R_SUCCESS;
1998 result = dns_rdataset_next(&rdataset)) {
1999 dns_rdata_init(&rdata);
2000 dns_rdataset_current(&rdataset, &rdata);
2001 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
2002 check_result(result, "dns_rdata_tostruct");
2003 if (exists && nsec3.hash == hashalg &&
2004 nsec3.iterations == iterations &&
2005 nsec3.salt_length == salt_length &&
2006 !memcmp(nsec3.salt, salt, salt_length))
2008 rdatalist.rdclass = rdata.rdclass;
2009 rdatalist.type = rdata.type;
2010 rdatalist.covers = 0;
2011 rdatalist.ttl = rdataset.ttl;
2012 ISC_LIST_INIT(rdatalist.rdata);
2013 dns_rdata_init(&delrdata);
2014 dns_rdata_clone(&rdata, &delrdata);
2015 ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link);
2016 result = dns_rdatalist_tordataset(&rdatalist, &delrdataset);
2017 check_result(result, "dns_rdatalist_tordataset()");
2018 result = dns_db_subtractrdataset(gdb, node, gversion,
2019 &delrdataset, 0, NULL);
2020 dns_rdataset_disassociate(&delrdataset);
2021 if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET)
2022 check_result(result, "dns_db_subtractrdataset(NSEC3)");
2023 delete_rrsigs = ISC_TRUE;
2025 dns_rdataset_disassociate(&rdataset);
2026 if (result != ISC_R_NOMORE)
2027 check_result(result, "dns_rdataset_first/next");
2032 * Delete the NSEC3 RRSIGs
2034 result = dns_db_deleterdataset(gdb, node, gversion,
2035 dns_rdatatype_rrsig,
2036 dns_rdatatype_nsec3);
2037 if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
2038 check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))");
2042 rrset_remove_duplicates(dns_name_t *name, dns_rdataset_t *rdataset,
2045 dns_difftuple_t *tuple = NULL;
2046 isc_result_t result;
2047 unsigned int count1 = 0;
2048 dns_rdataset_t tmprdataset;
2050 dns_rdataset_init(&tmprdataset);
2051 for (result = dns_rdataset_first(rdataset);
2052 result == ISC_R_SUCCESS;
2053 result = dns_rdataset_next(rdataset)) {
2054 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2055 unsigned int count2 = 0;
2058 dns_rdataset_current(rdataset, &rdata1);
2059 dns_rdataset_clone(rdataset, &tmprdataset);
2060 for (result = dns_rdataset_first(&tmprdataset);
2061 result == ISC_R_SUCCESS;
2062 result = dns_rdataset_next(&tmprdataset)) {
2063 dns_rdata_t rdata2 = DNS_RDATA_INIT;
2065 if (count1 >= count2)
2067 dns_rdataset_current(&tmprdataset, &rdata2);
2068 if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2069 result = dns_difftuple_create(mctx,
2074 check_result(result, "dns_difftuple_create");
2075 dns_diff_append(diff, &tuple);
2078 dns_rdataset_disassociate(&tmprdataset);
2083 remove_duplicates(void) {
2084 isc_result_t result;
2085 dns_dbiterator_t *dbiter = NULL;
2086 dns_rdatasetiter_t *rdsiter = NULL;
2088 dns_dbnode_t *node = NULL;
2089 dns_rdataset_t rdataset;
2090 dns_fixedname_t fname;
2093 dns_diff_init(mctx, &diff);
2094 dns_fixedname_init(&fname);
2095 name = dns_fixedname_name(&fname);
2096 dns_rdataset_init(&rdataset);
2098 result = dns_db_createiterator(gdb, 0, &dbiter);
2099 check_result(result, "dns_db_createiterator()");
2101 for (result = dns_dbiterator_first(dbiter);
2102 result == ISC_R_SUCCESS;
2103 result = dns_dbiterator_next(dbiter)) {
2105 result = dns_dbiterator_current(dbiter, &node, name);
2106 check_dns_dbiterator_current(result);
2107 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
2108 check_result(result, "dns_db_allrdatasets()");
2109 for (result = dns_rdatasetiter_first(rdsiter);
2110 result == ISC_R_SUCCESS;
2111 result = dns_rdatasetiter_next(rdsiter)) {
2112 dns_rdatasetiter_current(rdsiter, &rdataset);
2113 rrset_remove_duplicates(name, &rdataset, &diff);
2114 dns_rdataset_disassociate(&rdataset);
2116 if (result != ISC_R_NOMORE)
2117 fatal("rdatasets iteration failed.");
2118 dns_rdatasetiter_destroy(&rdsiter);
2119 dns_db_detachnode(gdb, &node);
2121 if (result != ISC_R_NOMORE)
2122 fatal("zone iteration failed.");
2124 if (!ISC_LIST_EMPTY(diff.tuples)) {
2125 result = dns_diff_applysilently(&diff, gdb, gversion);
2126 check_result(result, "dns_diff_applysilently");
2128 dns_diff_clear(&diff);
2129 dns_dbiterator_destroy(&dbiter);
2133 * Generate NSEC3 records for the zone.
2136 nsec3ify(unsigned int hashalg, dns_iterations_t iterations,
2137 const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
2139 dns_dbiterator_t *dbiter = NULL;
2140 dns_dbnode_t *node = NULL, *nextnode = NULL;
2141 dns_fixedname_t fname, fnextname, fzonecut;
2142 dns_name_t *name, *nextname, *zonecut;
2143 dns_rdataset_t rdataset;
2145 isc_boolean_t active;
2146 isc_boolean_t done = ISC_FALSE;
2147 isc_result_t result;
2148 isc_uint32_t nsttl = 0;
2149 unsigned int count, nlabels;
2151 dns_rdataset_init(&rdataset);
2152 dns_fixedname_init(&fname);
2153 name = dns_fixedname_name(&fname);
2154 dns_fixedname_init(&fnextname);
2155 nextname = dns_fixedname_name(&fnextname);
2156 dns_fixedname_init(&fzonecut);
2160 * Walk the zone generating the hash names.
2162 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2163 check_result(result, "dns_db_createiterator()");
2165 result = dns_dbiterator_first(dbiter);
2166 check_result(result, "dns_dbiterator_first()");
2169 result = dns_dbiterator_current(dbiter, &node, name);
2170 check_dns_dbiterator_current(result);
2172 * Skip out-of-zone records.
2174 if (!dns_name_issubdomain(name, gorigin)) {
2175 result = dns_dbiterator_next(dbiter);
2176 if (result == ISC_R_NOMORE)
2179 check_result(result, "dns_dbiterator_next()");
2180 dns_db_detachnode(gdb, &node);
2184 if (dns_name_equal(name, gorigin))
2185 remove_records(node, dns_rdatatype_nsec, ISC_TRUE);
2187 result = dns_dbiterator_next(dbiter);
2189 while (result == ISC_R_SUCCESS) {
2190 result = dns_dbiterator_current(dbiter, &nextnode,
2192 check_dns_dbiterator_current(result);
2193 active = active_node(nextnode);
2195 dns_db_detachnode(gdb, &nextnode);
2196 result = dns_dbiterator_next(dbiter);
2199 if (!dns_name_issubdomain(nextname, gorigin) ||
2201 dns_name_issubdomain(nextname, zonecut))) {
2202 remove_sigs(nextnode, 0);
2203 dns_db_detachnode(gdb, &nextnode);
2204 result = dns_dbiterator_next(dbiter);
2207 if (is_delegation(gdb, gversion, gorigin,
2208 nextname, nextnode, &nsttl))
2210 zonecut = dns_fixedname_name(&fzonecut);
2211 dns_name_copy(nextname, zonecut, NULL);
2212 remove_sigs(nextnode, 0);
2214 add_ds(nextname, nextnode, nsttl);
2215 if (OPTOUT(nsec3flags) &&
2216 !secure(nextname, nextnode)) {
2217 dns_db_detachnode(gdb, &nextnode);
2218 result = dns_dbiterator_next(dbiter);
2222 dns_db_detachnode(gdb, &nextnode);
2225 if (result == ISC_R_NOMORE) {
2226 dns_name_copy(gorigin, nextname, NULL);
2228 } else if (result != ISC_R_SUCCESS)
2229 fatal("iterating through the database failed: %s",
2230 isc_result_totext(result));
2231 dns_name_downcase(name, name, NULL);
2232 hashlist_add_dns_name(hashlist, name, hashalg, iterations,
2233 salt, salt_length, ISC_FALSE);
2234 dns_db_detachnode(gdb, &node);
2236 * Add hashs for empty nodes. Use closest encloser logic.
2237 * The closest encloser either has data or is a empty
2238 * node for another <name,nextname> span so we don't add
2239 * it here. Empty labels on nextname are within the span.
2241 dns_name_downcase(nextname, nextname, NULL);
2242 dns_name_fullcompare(name, nextname, &order, &nlabels);
2243 addnowildcardhash(hashlist, name, hashalg, iterations,
2245 count = dns_name_countlabels(nextname);
2246 while (count > nlabels + 1) {
2248 dns_name_split(nextname, count, NULL, nextname);
2249 hashlist_add_dns_name(hashlist, nextname, hashalg,
2250 iterations, salt, salt_length,
2252 addnowildcardhash(hashlist, nextname, hashalg,
2253 iterations, salt, salt_length);
2256 dns_dbiterator_destroy(&dbiter);
2259 * We have all the hashes now so we can sort them.
2261 hashlist_sort(hashlist);
2264 * Check for duplicate hashes. If found the salt needs to
2267 if (hashlist_hasdup(hashlist))
2268 fatal("Duplicate hash detected. Pick a different salt.");
2271 * Generate the nsec3 records.
2276 addnsec3param(salt, salt_length, iterations);
2279 * Clean out NSEC3 records which don't match this chain.
2281 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
2282 check_result(result, "dns_db_createiterator()");
2284 for (result = dns_dbiterator_first(dbiter);
2285 result == ISC_R_SUCCESS;
2286 result = dns_dbiterator_next(dbiter)) {
2287 result = dns_dbiterator_current(dbiter, &node, name);
2288 check_dns_dbiterator_current(result);
2289 nsec3clean(name, node, hashalg, iterations, salt, salt_length,
2291 dns_db_detachnode(gdb, &node);
2293 dns_dbiterator_destroy(&dbiter);
2296 * Generate / complete the new chain.
2298 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2299 check_result(result, "dns_db_createiterator()");
2301 result = dns_dbiterator_first(dbiter);
2302 check_result(result, "dns_dbiterator_first()");
2305 result = dns_dbiterator_current(dbiter, &node, name);
2306 check_dns_dbiterator_current(result);
2308 * Skip out-of-zone records.
2310 if (!dns_name_issubdomain(name, gorigin)) {
2311 result = dns_dbiterator_next(dbiter);
2312 if (result == ISC_R_NOMORE)
2315 check_result(result, "dns_dbiterator_next()");
2316 dns_db_detachnode(gdb, &node);
2319 result = dns_dbiterator_next(dbiter);
2321 while (result == ISC_R_SUCCESS) {
2322 result = dns_dbiterator_current(dbiter, &nextnode,
2324 check_dns_dbiterator_current(result);
2325 active = active_node(nextnode);
2327 dns_db_detachnode(gdb, &nextnode);
2328 result = dns_dbiterator_next(dbiter);
2331 if (!dns_name_issubdomain(nextname, gorigin) ||
2333 dns_name_issubdomain(nextname, zonecut))) {
2334 dns_db_detachnode(gdb, &nextnode);
2335 result = dns_dbiterator_next(dbiter);
2338 if (is_delegation(gdb, gversion, gorigin,
2339 nextname, nextnode, NULL))
2341 zonecut = dns_fixedname_name(&fzonecut);
2342 dns_name_copy(nextname, zonecut, NULL);
2343 if (OPTOUT(nsec3flags) &&
2344 !secure(nextname, nextnode)) {
2345 dns_db_detachnode(gdb, &nextnode);
2346 result = dns_dbiterator_next(dbiter);
2350 dns_db_detachnode(gdb, &nextnode);
2353 if (result == ISC_R_NOMORE) {
2354 dns_name_copy(gorigin, nextname, NULL);
2356 } else if (result != ISC_R_SUCCESS)
2357 fatal("iterating through the database failed: %s",
2358 isc_result_totext(result));
2360 * We need to pause here to release the lock on the database.
2362 dns_dbiterator_pause(dbiter);
2363 addnsec3(name, node, salt, salt_length, iterations,
2364 hashlist, zone_soa_min_ttl);
2365 dns_db_detachnode(gdb, &node);
2367 * Add NSEC3's for empty nodes. Use closest encloser logic.
2369 dns_name_fullcompare(name, nextname, &order, &nlabels);
2370 count = dns_name_countlabels(nextname);
2371 while (count > nlabels + 1) {
2373 dns_name_split(nextname, count, NULL, nextname);
2374 addnsec3(nextname, NULL, salt, salt_length,
2375 iterations, hashlist, zone_soa_min_ttl);
2378 dns_dbiterator_destroy(&dbiter);
2382 * Load the zone file from disk
2385 loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
2388 dns_fixedname_t fname;
2390 isc_result_t result;
2392 len = strlen(origin);
2393 isc_buffer_init(&b, origin, len);
2394 isc_buffer_add(&b, len);
2396 dns_fixedname_init(&fname);
2397 name = dns_fixedname_name(&fname);
2398 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
2399 if (result != ISC_R_SUCCESS)
2400 fatal("failed converting name '%s' to dns format: %s",
2401 origin, isc_result_totext(result));
2403 result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
2404 rdclass, 0, NULL, db);
2405 check_result(result, "dns_db_create()");
2407 result = dns_db_load2(*db, file, inputformat);
2408 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
2409 fatal("failed loading zone from '%s': %s",
2410 file, isc_result_totext(result));
2414 * Finds all public zone keys in the zone, and attempts to load the
2415 * private keys from disk.
2418 loadzonekeys(isc_boolean_t preserve_keys, isc_boolean_t load_public) {
2420 dns_dbversion_t *currentversion = NULL;
2421 isc_result_t result;
2422 dns_rdataset_t rdataset, keysigs, soasigs;
2425 result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node);
2426 if (result != ISC_R_SUCCESS)
2427 fatal("failed to find the zone's origin: %s",
2428 isc_result_totext(result));
2430 dns_db_currentversion(gdb, ¤tversion);
2432 dns_rdataset_init(&rdataset);
2433 dns_rdataset_init(&soasigs);
2434 dns_rdataset_init(&keysigs);
2436 /* Make note of the keys which signed the SOA, if any */
2437 result = dns_db_findrdataset(gdb, node, currentversion,
2438 dns_rdatatype_soa, 0, 0,
2439 &rdataset, &soasigs);
2440 if (result != ISC_R_SUCCESS)
2443 /* Preserve the TTL of the DNSKEY RRset, if any */
2444 dns_rdataset_disassociate(&rdataset);
2445 result = dns_db_findrdataset(gdb, node, currentversion,
2446 dns_rdatatype_dnskey, 0, 0,
2447 &rdataset, &keysigs);
2449 if (result != ISC_R_SUCCESS)
2452 if (set_keyttl && keyttl != rdataset.ttl) {
2453 fprintf(stderr, "User-specified TTL (%d) conflicts "
2454 "with existing DNSKEY RRset TTL.\n",
2456 fprintf(stderr, "Imported keys will use the RRSet "
2457 "TTL (%d) instead.\n",
2460 keyttl = rdataset.ttl;
2462 /* Load keys corresponding to the existing DNSKEY RRset. */
2463 result = dns_dnssec_keylistfromrdataset(gorigin, directory, mctx,
2464 &rdataset, &keysigs, &soasigs,
2465 preserve_keys, load_public,
2467 if (result != ISC_R_SUCCESS)
2468 fatal("failed to load the zone keys: %s",
2469 isc_result_totext(result));
2472 if (dns_rdataset_isassociated(&rdataset))
2473 dns_rdataset_disassociate(&rdataset);
2474 if (dns_rdataset_isassociated(&keysigs))
2475 dns_rdataset_disassociate(&keysigs);
2476 if (dns_rdataset_isassociated(&soasigs))
2477 dns_rdataset_disassociate(&soasigs);
2478 dns_db_detachnode(gdb, &node);
2479 dns_db_closeversion(gdb, ¤tversion, ISC_FALSE);
2483 loadexplicitkeys(char *keyfiles[], int n, isc_boolean_t setksk) {
2484 isc_result_t result;
2487 for (i = 0; i < n; i++) {
2488 dns_dnsseckey_t *key = NULL;
2489 dst_key_t *newkey = NULL;
2491 result = dst_key_fromnamedfile(keyfiles[i], directory,
2495 if (result != ISC_R_SUCCESS)
2496 fatal("cannot load dnskey %s: %s", keyfiles[i],
2497 isc_result_totext(result));
2499 if (!dns_name_equal(gorigin, dst_key_name(newkey)))
2500 fatal("key %s not at origin\n", keyfiles[i]);
2502 if (!dst_key_isprivate(newkey))
2503 fatal("cannot sign zone with non-private dnskey %s",
2506 /* Skip any duplicates */
2507 for (key = ISC_LIST_HEAD(keylist);
2509 key = ISC_LIST_NEXT(key, link)) {
2510 if (dst_key_id(key->key) == dst_key_id(newkey) &&
2511 dst_key_alg(key->key) == dst_key_alg(newkey))
2516 /* We haven't seen this key before */
2517 dns_dnsseckey_create(mctx, &newkey, &key);
2518 ISC_LIST_APPEND(keylist, key, link);
2519 key->source = dns_keysource_user;
2521 dst_key_free(&key->key);
2525 key->force_publish = ISC_TRUE;
2526 key->force_sign = ISC_TRUE;
2529 key->ksk = ISC_TRUE;
2534 report(const char *format, ...) {
2536 va_start(args, format);
2537 vfprintf(stderr, format, args);
2543 build_final_keylist() {
2544 isc_result_t result;
2545 dns_dbversion_t *ver = NULL;
2547 dns_dnsseckeylist_t matchkeys;
2548 char name[DNS_NAME_FORMATSIZE];
2551 * Find keys that match this zone in the key repository.
2553 ISC_LIST_INIT(matchkeys);
2554 result = dns_dnssec_findmatchingkeys(gorigin, directory,
2556 if (result == ISC_R_NOTFOUND)
2557 result = ISC_R_SUCCESS;
2558 check_result(result, "dns_dnssec_findmatchingkeys");
2560 result = dns_db_newversion(gdb, &ver);
2561 check_result(result, "dns_db_newversion");
2563 dns_diff_init(mctx, &diff);
2566 * Update keylist with information from from the key repository.
2568 dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl,
2569 &diff, ignore_kskflag, mctx, report);
2571 dns_name_format(gorigin, name, sizeof(name));
2573 result = dns_diff_applysilently(&diff, gdb, ver);
2574 if (result != ISC_R_SUCCESS)
2575 fatal("failed to update DNSKEY RRset at node '%s': %s",
2576 name, isc_result_totext(result));
2578 dns_db_closeversion(gdb, &ver, ISC_TRUE);
2580 dns_diff_clear(&diff);
2584 warnifallksk(dns_db_t *db) {
2585 dns_dbversion_t *currentversion = NULL;
2586 dns_dbnode_t *node = NULL;
2587 dns_rdataset_t rdataset;
2588 dns_rdata_t rdata = DNS_RDATA_INIT;
2589 isc_result_t result;
2590 dns_rdata_dnskey_t dnskey;
2591 isc_boolean_t have_non_ksk = ISC_FALSE;
2593 dns_db_currentversion(db, ¤tversion);
2595 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
2596 if (result != ISC_R_SUCCESS)
2597 fatal("failed to find the zone's origin: %s",
2598 isc_result_totext(result));
2600 dns_rdataset_init(&rdataset);
2601 result = dns_db_findrdataset(db, node, currentversion,
2602 dns_rdatatype_dnskey, 0, 0, &rdataset,
2604 if (result != ISC_R_SUCCESS)
2605 fatal("failed to find keys at the zone apex: %s",
2606 isc_result_totext(result));
2607 result = dns_rdataset_first(&rdataset);
2608 check_result(result, "dns_rdataset_first");
2609 while (result == ISC_R_SUCCESS) {
2610 dns_rdata_reset(&rdata);
2611 dns_rdataset_current(&rdataset, &rdata);
2612 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2613 check_result(result, "dns_rdata_tostruct");
2614 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
2615 have_non_ksk = ISC_TRUE;
2616 result = ISC_R_NOMORE;
2618 result = dns_rdataset_next(&rdataset);
2619 dns_rdata_freestruct(&dnskey);
2621 dns_rdataset_disassociate(&rdataset);
2622 dns_db_detachnode(db, &node);
2623 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
2624 if (!have_non_ksk && !ignore_kskflag) {
2625 if (disable_zone_check)
2626 fprintf(stderr, "%s: warning: No non-KSK DNSKEY found; "
2627 "supply a ZSK or use '-z'.\n",
2630 fatal("No non-KSK DNSKEY found; "
2631 "supply a ZSK or use '-z'.");
2636 set_nsec3params(isc_boolean_t update_chain, isc_boolean_t set_salt,
2637 isc_boolean_t set_optout, isc_boolean_t set_iter)
2639 isc_result_t result;
2640 dns_dbversion_t *ver = NULL;
2641 dns_dbnode_t *node = NULL;
2642 dns_rdataset_t rdataset;
2643 dns_rdata_t rdata = DNS_RDATA_INIT;
2644 dns_rdata_nsec3_t nsec3;
2645 dns_fixedname_t fname;
2646 dns_name_t *hashname;
2647 unsigned char orig_salt[255];
2648 size_t orig_saltlen;
2649 dns_hash_t orig_hash;
2650 isc_uint16_t orig_iter;
2652 dns_db_currentversion(gdb, &ver);
2653 dns_rdataset_init(&rdataset);
2655 orig_saltlen = sizeof(orig_salt);
2656 result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL,
2657 &orig_iter, orig_salt,
2659 if (result != ISC_R_SUCCESS)
2662 nsec_datatype = dns_rdatatype_nsec3;
2664 if (!update_chain && set_salt) {
2665 if (salt_length != orig_saltlen ||
2666 memcmp(saltbuf, orig_salt, salt_length) != 0)
2667 fatal("An NSEC3 chain exists with a different salt. "
2668 "Use -u to update it.");
2669 } else if (!set_salt) {
2670 salt_length = orig_saltlen;
2671 memmove(saltbuf, orig_salt, orig_saltlen);
2675 if (!update_chain && set_iter) {
2676 if (nsec3iter != orig_iter)
2677 fatal("An NSEC3 chain exists with different "
2678 "iterations. Use -u to update it.");
2679 } else if (!set_iter)
2680 nsec3iter = orig_iter;
2683 * Find an NSEC3 record to get the current OPTOUT value.
2684 * (This assumes all NSEC3 records agree.)
2687 dns_fixedname_init(&fname);
2688 hashname = dns_fixedname_name(&fname);
2689 result = dns_nsec3_hashname(&fname, NULL, NULL,
2690 gorigin, gorigin, dns_hash_sha1,
2691 orig_iter, orig_salt, orig_saltlen);
2692 check_result(result, "dns_nsec3_hashname");
2694 result = dns_db_findnsec3node(gdb, hashname, ISC_FALSE, &node);
2695 if (result != ISC_R_SUCCESS)
2698 result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3,
2699 0, 0, &rdataset, NULL);
2700 if (result != ISC_R_SUCCESS)
2703 result = dns_rdataset_first(&rdataset);
2704 check_result(result, "dns_rdataset_first");
2705 dns_rdataset_current(&rdataset, &rdata);
2706 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
2707 check_result(result, "dns_rdata_tostruct");
2709 if (!update_chain && set_optout) {
2710 if (nsec3flags != nsec3.flags)
2711 fatal("An NSEC3 chain exists with%s OPTOUT. "
2712 "Use -u -%s to %s it.",
2713 OPTOUT(nsec3.flags) ? "" : "out",
2714 OPTOUT(nsec3.flags) ? "AA" : "A",
2715 OPTOUT(nsec3.flags) ? "clear" : "set");
2716 } else if (!set_optout)
2717 nsec3flags = nsec3.flags;
2719 dns_rdata_freestruct(&nsec3);
2722 if (dns_rdataset_isassociated(&rdataset))
2723 dns_rdataset_disassociate(&rdataset);
2725 dns_db_detachnode(gdb, &node);
2726 dns_db_closeversion(gdb, &ver, ISC_FALSE);
2730 writeset(const char *prefix, dns_rdatatype_t type) {
2732 char namestr[DNS_NAME_FORMATSIZE];
2733 dns_db_t *db = NULL;
2734 dns_dbversion_t *version = NULL;
2736 dns_difftuple_t *tuple = NULL;
2737 dns_fixedname_t fixed;
2739 dns_rdata_t rdata, ds;
2740 isc_boolean_t have_ksk = ISC_FALSE;
2741 isc_boolean_t have_non_ksk = ISC_FALSE;
2743 isc_buffer_t namebuf;
2745 isc_result_t result;
2746 dns_dnsseckey_t *key, *tmpkey;
2747 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
2748 unsigned char keybuf[DST_KEY_MAXSIZE];
2749 unsigned int filenamelen;
2750 const dns_master_style_t *style =
2751 (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
2753 isc_buffer_init(&namebuf, namestr, sizeof(namestr));
2754 result = dns_name_tofilenametext(gorigin, ISC_FALSE, &namebuf);
2755 check_result(result, "dns_name_tofilenametext");
2756 isc_buffer_putuint8(&namebuf, 0);
2757 filenamelen = strlen(prefix) + strlen(namestr);
2759 filenamelen += strlen(dsdir) + 1;
2760 filename = isc_mem_get(mctx, filenamelen + 1);
2761 if (filename == NULL)
2762 fatal("out of memory");
2764 sprintf(filename, "%s/", dsdir);
2767 strcat(filename, prefix);
2768 strcat(filename, namestr);
2770 dns_diff_init(mctx, &diff);
2772 if (type == dns_rdatatype_dlv) {
2774 unsigned int labels;
2776 dns_name_init(&tname, NULL);
2777 dns_fixedname_init(&fixed);
2778 name = dns_fixedname_name(&fixed);
2779 labels = dns_name_countlabels(gorigin);
2780 dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
2781 result = dns_name_concatenate(&tname, dlv, name, NULL);
2782 check_result(result, "dns_name_concatenate");
2786 for (key = ISC_LIST_HEAD(keylist);
2788 key = ISC_LIST_NEXT(key, link))
2790 if (REVOKE(key->key))
2793 have_ksk = ISC_TRUE;
2794 have_non_ksk = ISC_FALSE;
2796 have_ksk = ISC_FALSE;
2797 have_non_ksk = ISC_TRUE;
2799 for (tmpkey = ISC_LIST_HEAD(keylist);
2801 tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
2802 if (dst_key_alg(key->key) != dst_key_alg(tmpkey->key))
2804 if (REVOKE(tmpkey->key))
2807 have_ksk = ISC_TRUE;
2809 have_non_ksk = ISC_TRUE;
2811 if (have_ksk && have_non_ksk && !isksk(key))
2813 dns_rdata_init(&rdata);
2814 dns_rdata_init(&ds);
2815 isc_buffer_init(&b, keybuf, sizeof(keybuf));
2816 result = dst_key_todns(key->key, &b);
2817 check_result(result, "dst_key_todns");
2818 isc_buffer_usedregion(&b, &r);
2819 dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
2820 if (type != dns_rdatatype_dnskey) {
2821 result = dns_ds_buildrdata(gorigin, &rdata,
2824 check_result(result, "dns_ds_buildrdata");
2825 if (type == dns_rdatatype_dlv)
2826 ds.type = dns_rdatatype_dlv;
2827 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
2828 name, 0, &ds, &tuple);
2829 check_result(result, "dns_difftuple_create");
2830 dns_diff_append(&diff, &tuple);
2832 dns_rdata_reset(&ds);
2833 result = dns_ds_buildrdata(gorigin, &rdata,
2834 DNS_DSDIGEST_SHA256,
2836 check_result(result, "dns_ds_buildrdata");
2837 if (type == dns_rdatatype_dlv)
2838 ds.type = dns_rdatatype_dlv;
2839 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
2840 name, 0, &ds, &tuple);
2843 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
2844 gorigin, zone_soa_min_ttl,
2846 check_result(result, "dns_difftuple_create");
2847 dns_diff_append(&diff, &tuple);
2850 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
2851 gclass, 0, NULL, &db);
2852 check_result(result, "dns_db_create");
2854 result = dns_db_newversion(db, &version);
2855 check_result(result, "dns_db_newversion");
2857 result = dns_diff_apply(&diff, db, version);
2858 check_result(result, "dns_diff_apply");
2859 dns_diff_clear(&diff);
2861 result = dns_master_dump(mctx, db, version, style, filename);
2862 check_result(result, "dns_master_dump");
2864 isc_mem_put(mctx, filename, filenamelen + 1);
2866 dns_db_closeversion(db, &version, ISC_FALSE);
2871 print_time(FILE *fp) {
2874 if (outputformat != dns_masterformat_text)
2877 currenttime = time(NULL);
2878 fprintf(fp, "; File written on %s", ctime(¤ttime));
2882 print_version(FILE *fp) {
2883 if (outputformat != dns_masterformat_text)
2886 fprintf(fp, "; dnssec_signzone version " VERSION "\n");
2889 ISC_PLATFORM_NORETURN_PRE static void
2890 usage(void) ISC_PLATFORM_NORETURN_POST;
2894 fprintf(stderr, "Usage:\n");
2895 fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
2897 fprintf(stderr, "\n");
2899 fprintf(stderr, "Version: %s\n", VERSION);
2901 fprintf(stderr, "Options: (default value in parenthesis) \n");
2902 fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n"
2903 "\t\tfor the zone and determines how they are to "
2905 fprintf(stderr, "\t-K directory:\n");
2906 fprintf(stderr, "\t\tdirectory to find key files (.)\n");
2907 fprintf(stderr, "\t-d directory:\n");
2908 fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n");
2909 fprintf(stderr, "\t-g:\t");
2910 fprintf(stderr, "update DS records based on child zones' "
2912 fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
2913 fprintf(stderr, "\t\tRRSIG start time "
2914 "- absolute|offset (now - 1 hour)\n");
2915 fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
2916 fprintf(stderr, "\t\tRRSIG end time "
2917 "- absolute|from start|from now "
2918 "(now + 30 days)\n");
2919 fprintf(stderr, "\t-X [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
2920 fprintf(stderr, "\t\tDNSKEY RRSIG end "
2921 "- absolute|from start|from now "
2923 fprintf(stderr, "\t-i interval:\n");
2924 fprintf(stderr, "\t\tcycle interval - resign "
2925 "if < interval from end ( (end-start)/4 )\n");
2926 fprintf(stderr, "\t-j jitter:\n");
2927 fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n");
2928 fprintf(stderr, "\t-v debuglevel (0)\n");
2929 fprintf(stderr, "\t-o origin:\n");
2930 fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
2931 fprintf(stderr, "\t-f outfile:\n");
2932 fprintf(stderr, "\t\tfile the signed zone is written in "
2933 "(zonefile + .signed)\n");
2934 fprintf(stderr, "\t-I format:\n");
2935 fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
2936 fprintf(stderr, "\t-O format:\n");
2937 fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
2938 fprintf(stderr, "\t-N format:\n");
2939 fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
2940 fprintf(stderr, "\t-D:\n");
2941 fprintf(stderr, "\t\toutput only DNSSEC-related records\n");
2942 fprintf(stderr, "\t-r randomdev:\n");
2943 fprintf(stderr, "\t\ta file containing random data\n");
2944 fprintf(stderr, "\t-a:\t");
2945 fprintf(stderr, "verify generated signatures\n");
2946 fprintf(stderr, "\t-c class (IN)\n");
2947 fprintf(stderr, "\t-E engine:\n");
2949 fprintf(stderr, "\t\tname of an OpenSSL engine to use "
2950 "(default is \"pkcs11\")\n");
2952 fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
2954 fprintf(stderr, "\t-p:\t");
2955 fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
2956 fprintf(stderr, "\t-P:\t");
2957 fprintf(stderr, "disable post-sign verification\n");
2958 fprintf(stderr, "\t-Q:\t");
2959 fprintf(stderr, "remove signatures from keys that are no "
2961 fprintf(stderr, "\t-R:\t");
2962 fprintf(stderr, "remove signatures from keys that no longer exist\n");
2963 fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n");
2964 fprintf(stderr, "\t-t:\t");
2965 fprintf(stderr, "print statistics\n");
2966 fprintf(stderr, "\t-u:\t");
2967 fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n");
2968 fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n");
2969 fprintf(stderr, "\t-z:\tsign all records with KSKs\n");
2970 fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n"
2971 "\t\twith older versions of dnssec-signzone -g\n");
2972 fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
2973 fprintf(stderr, "\t-k key_signing_key\n");
2974 fprintf(stderr, "\t-l lookasidezone\n");
2975 fprintf(stderr, "\t-3 NSEC3 salt\n");
2976 fprintf(stderr, "\t-H NSEC3 iterations (10)\n");
2977 fprintf(stderr, "\t-A NSEC3 optout\n");
2979 fprintf(stderr, "\n");
2981 fprintf(stderr, "Signing Keys: ");
2982 fprintf(stderr, "(default: all zone keys that have private keys)\n");
2983 fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
2988 removetempfile(void) {
2990 isc_file_remove(tempfile);
2994 print_stats(isc_time_t *timer_start, isc_time_t *timer_finish,
2995 isc_time_t *sign_start, isc_time_t *sign_finish)
2997 isc_uint64_t time_us; /* Time in microseconds */
2998 isc_uint64_t time_ms; /* Time in milliseconds */
2999 isc_uint64_t sig_ms; /* Signatures per millisecond */
3000 FILE *out = output_stdout ? stderr : stdout;
3002 fprintf(out, "Signatures generated: %10d\n", nsigned);
3003 fprintf(out, "Signatures retained: %10d\n", nretained);
3004 fprintf(out, "Signatures dropped: %10d\n", ndropped);
3005 fprintf(out, "Signatures successfully verified: %10d\n", nverified);
3006 fprintf(out, "Signatures unsuccessfully "
3007 "verified: %10d\n", nverifyfailed);
3009 time_us = isc_time_microdiff(sign_finish, sign_start);
3010 time_ms = time_us / 1000;
3011 fprintf(out, "Signing time in seconds: %7u.%03u\n",
3012 (unsigned int) (time_ms / 1000),
3013 (unsigned int) (time_ms % 1000));
3015 sig_ms = ((isc_uint64_t)nsigned * 1000000000) / time_us;
3016 fprintf(out, "Signatures per second: %7u.%03u\n",
3017 (unsigned int) sig_ms / 1000,
3018 (unsigned int) sig_ms % 1000);
3021 time_us = isc_time_microdiff(timer_finish, timer_start);
3022 time_ms = time_us / 1000;
3023 fprintf(out, "Runtime in seconds: %7u.%03u\n",
3024 (unsigned int) (time_ms / 1000),
3025 (unsigned int) (time_ms % 1000));
3029 main(int argc, char *argv[]) {
3031 char *startstr = NULL, *endstr = NULL, *classname = NULL;
3032 char *dnskey_endstr = NULL;
3033 char *origin = NULL, *file = NULL, *output = NULL;
3034 char *inputformatstr = NULL, *outputformatstr = NULL;
3035 char *serialformatstr = NULL;
3036 char *dskeyfile[MAXDSKEYS];
3039 isc_time_t timer_start, timer_finish;
3040 isc_time_t sign_start, sign_finish;
3041 dns_dnsseckey_t *key;
3042 isc_result_t result;
3043 isc_log_t *log = NULL;
3044 isc_boolean_t pseudorandom = ISC_FALSE;
3046 const char *engine = "pkcs11";
3048 const char *engine = NULL;
3050 unsigned int eflags;
3051 isc_boolean_t free_output = ISC_FALSE;
3052 int tempfilelen = 0;
3053 dns_rdataclass_t rdclass;
3054 isc_task_t **tasks = NULL;
3057 hashlist_t hashlist;
3058 isc_boolean_t make_keyset = ISC_FALSE;
3059 isc_boolean_t set_salt = ISC_FALSE;
3060 isc_boolean_t set_optout = ISC_FALSE;
3061 isc_boolean_t set_iter = ISC_FALSE;
3062 isc_boolean_t nonsecify = ISC_FALSE;
3064 /* Unused letters: Bb G J M q Yy (and F is reserved). */
3065 #define CMDLINE_FLAGS \
3066 "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:L:l:m:n:N:o:O:PpQRr:s:ST:tuUv:X:xzZ:"
3069 * Process memory debugging argument first.
3071 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3074 if (strcasecmp(isc_commandline_argument, "record") == 0)
3075 isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
3076 if (strcasecmp(isc_commandline_argument, "trace") == 0)
3077 isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
3078 if (strcasecmp(isc_commandline_argument, "usage") == 0)
3079 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
3080 if (strcasecmp(isc_commandline_argument, "size") == 0)
3081 isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
3082 if (strcasecmp(isc_commandline_argument, "mctx") == 0)
3083 isc_mem_debugging |= ISC_MEM_DEBUGCTX;
3089 isc_commandline_reset = ISC_TRUE;
3091 masterstyle = &dns_master_style_explicitttl;
3093 check_result(isc_app_start(), "isc_app_start");
3095 result = isc_mem_create(0, 0, &mctx);
3096 if (result != ISC_R_SUCCESS)
3097 fatal("out of memory");
3099 dns_result_register();
3101 isc_commandline_errprint = ISC_FALSE;
3103 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3106 set_salt = ISC_TRUE;
3107 nsec_datatype = dns_rdatatype_nsec3;
3108 if (strcmp(isc_commandline_argument, "-") != 0) {
3109 isc_buffer_t target;
3112 sarg = isc_commandline_argument;
3113 isc_buffer_init(&target, saltbuf,
3115 result = isc_hex_decodestring(sarg, &target);
3116 check_result(result,
3117 "isc_hex_decodestring(salt)");
3118 salt_length = isc_buffer_usedlength(&target);
3123 set_optout = ISC_TRUE;
3124 if (OPTOUT(nsec3flags))
3125 nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT;
3127 nsec3flags |= DNS_NSEC3FLAG_OPTOUT;
3131 tryverify = ISC_TRUE;
3135 make_keyset = ISC_TRUE;
3139 classname = isc_commandline_argument;
3143 dsdir = isc_commandline_argument;
3144 if (strlen(dsdir) == 0U)
3145 fatal("DS directory must be non-empty string");
3146 result = try_dir(dsdir);
3147 if (result != ISC_R_SUCCESS)
3148 fatal("cannot open directory %s: %s",
3149 dsdir, isc_result_totext(result));
3153 output_dnssec_only = ISC_TRUE;
3157 engine = isc_commandline_argument;
3161 endstr = isc_commandline_argument;
3165 output = isc_commandline_argument;
3166 if (strcmp(output, "-") == 0)
3167 output_stdout = ISC_TRUE;
3171 generateds = ISC_TRUE;
3175 set_iter = ISC_TRUE;
3176 nsec3iter = strtoul(isc_commandline_argument, &endp, 0);
3178 fatal("iterations must be numeric");
3179 if (nsec3iter > 0xffffU)
3180 fatal("iterations too big");
3188 inputformatstr = isc_commandline_argument;
3193 cycle = strtol(isc_commandline_argument, &endp, 0);
3194 if (*endp != '\0' || cycle < 0)
3195 fatal("cycle period must be numeric and "
3201 jitter = strtol(isc_commandline_argument, &endp, 0);
3202 if (*endp != '\0' || jitter < 0)
3203 fatal("jitter must be numeric and positive");
3207 directory = isc_commandline_argument;
3211 if (ndskeys == MAXDSKEYS)
3212 fatal("too many key-signing keys specified");
3213 dskeyfile[ndskeys++] = isc_commandline_argument;
3219 serialnum = strtol(isc_commandline_argument, &endp, 0);
3220 if (*endp != '\0') {
3221 fprintf(stderr, "source serial number "
3228 len = strlen(isc_commandline_argument);
3229 isc_buffer_init(&b, isc_commandline_argument, len);
3230 isc_buffer_add(&b, len);
3232 dns_fixedname_init(&dlv_fixed);
3233 dlv = dns_fixedname_name(&dlv_fixed);
3234 result = dns_name_fromtext(dlv, &b, dns_rootname, 0,
3236 check_result(result, "dns_name_fromtext(dlv)");
3243 serialformatstr = isc_commandline_argument;
3248 ntasks = strtol(isc_commandline_argument, &endp, 0);
3249 if (*endp != '\0' || ntasks > ISC_INT32_MAX)
3250 fatal("number of cpus must be numeric");
3254 outputformatstr = isc_commandline_argument;
3258 origin = isc_commandline_argument;
3262 disable_zone_check = ISC_TRUE;
3266 pseudorandom = ISC_TRUE;
3270 remove_inactkeysigs = ISC_TRUE;
3274 remove_orphansigs = ISC_TRUE;
3278 setup_entropy(mctx, isc_commandline_argument, &ectx);
3282 smartsign = ISC_TRUE;
3286 startstr = isc_commandline_argument;
3291 set_keyttl = ISC_TRUE;
3292 keyttl = strtottl(isc_commandline_argument);
3296 printstats = ISC_TRUE;
3299 case 'U': /* Undocumented for testing only. */
3300 unknownalg = ISC_TRUE;
3304 update_chain = ISC_TRUE;
3309 verbose = strtol(isc_commandline_argument, &endp, 0);
3311 fatal("verbose level must be numeric");
3315 dnskey_endstr = isc_commandline_argument;
3319 keyset_kskonly = ISC_TRUE;
3323 ignore_kskflag = ISC_TRUE;
3327 /* Reserved for FIPS mode */
3330 if (isc_commandline_option != '?')
3331 fprintf(stderr, "%s: invalid argument -%c\n",
3332 program, isc_commandline_option);
3337 fprintf(stderr, "%s: unhandled option -%c\n",
3338 program, isc_commandline_option);
3340 case 'Z': /* Undocumented test options */
3341 if (!strcmp(isc_commandline_argument, "nonsecify"))
3342 nonsecify = ISC_TRUE;
3348 setup_entropy(mctx, NULL, &ectx);
3349 eflags = ISC_ENTROPY_BLOCKING;
3351 eflags |= ISC_ENTROPY_GOODONLY;
3353 result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
3354 if (result != ISC_R_SUCCESS)
3355 fatal("could not create hash context");
3357 result = dst_lib_init2(mctx, ectx, engine, eflags);
3358 if (result != ISC_R_SUCCESS)
3359 fatal("could not initialize dst: %s",
3360 isc_result_totext(result));
3361 isc_stdtime_get(&now);
3363 if (startstr != NULL) {
3364 starttime = strtotime(startstr, now, now);
3366 starttime = now - 3600; /* Allow for some clock skew. */
3369 endtime = strtotime(endstr, now, starttime);
3371 endtime = starttime + (30 * 24 * 60 * 60);
3373 if (dnskey_endstr != NULL) {
3374 dnskey_endtime = strtotime(dnskey_endstr, now, starttime);
3375 if (endstr != NULL && dnskey_endtime == endtime)
3376 fprintf(stderr, "WARNING: -e and -X were both set, "
3377 "but have identical values.\n");
3379 dnskey_endtime = endtime;
3382 cycle = (endtime - starttime) / 4;
3385 ntasks = isc_os_ncpus() * 2;
3386 vbprintf(4, "using %d cpus\n", ntasks);
3388 rdclass = strtoclass(classname);
3390 if (directory == NULL)
3393 setup_logging(verbose, mctx, &log);
3395 argc -= isc_commandline_index;
3396 argv += isc_commandline_index;
3409 if (output == NULL) {
3410 free_output = ISC_TRUE;
3411 output = isc_mem_allocate(mctx,
3412 strlen(file) + strlen(".signed") + 1);
3414 fatal("out of memory");
3415 sprintf(output, "%s.signed", file);
3418 if (inputformatstr != NULL) {
3419 if (strcasecmp(inputformatstr, "text") == 0)
3420 inputformat = dns_masterformat_text;
3421 else if (strcasecmp(inputformatstr, "raw") == 0)
3422 inputformat = dns_masterformat_raw;
3423 else if (strncasecmp(inputformatstr, "raw=", 4) == 0) {
3424 inputformat = dns_masterformat_raw;
3426 "WARNING: input format version ignored\n");
3428 fatal("unknown file format: %s", inputformatstr);
3432 if (outputformatstr != NULL) {
3433 if (strcasecmp(outputformatstr, "text") == 0) {
3434 outputformat = dns_masterformat_text;
3435 } else if (strcasecmp(outputformatstr, "full") == 0) {
3436 outputformat = dns_masterformat_text;
3437 masterstyle = &dns_master_style_full;
3438 } else if (strcasecmp(outputformatstr, "raw") == 0) {
3439 outputformat = dns_masterformat_raw;
3440 } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
3442 outputformat = dns_masterformat_raw;
3444 outputformat = dns_masterformat_raw;
3445 rawversion = strtol(outputformatstr + 4, &end, 10);
3446 if (end == outputformatstr + 4 || *end != '\0' ||
3449 "unknown raw format version\n");
3453 fatal("unknown file format: %s\n", outputformatstr);
3456 if (serialformatstr != NULL) {
3457 if (strcasecmp(serialformatstr, "keep") == 0)
3458 serialformat = SOA_SERIAL_KEEP;
3459 else if (strcasecmp(serialformatstr, "increment") == 0 ||
3460 strcasecmp(serialformatstr, "incr") == 0)
3461 serialformat = SOA_SERIAL_INCREMENT;
3462 else if (strcasecmp(serialformatstr, "unixtime") == 0)
3463 serialformat = SOA_SERIAL_UNIXTIME;
3465 fatal("unknown soa serial format: %s\n",
3469 if (output_dnssec_only && outputformat != dns_masterformat_text)
3470 fatal("option -D can only be used with \"-O text\"\n");
3472 if (output_dnssec_only && serialformat != SOA_SERIAL_KEEP)
3473 fatal("option -D can only be used with \"-N keep\"\n");
3475 result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL,
3476 0, 24, 0, 0, 0, 8, mctx);
3477 check_result(result, "dns_master_stylecreate");
3480 TIME_NOW(&timer_start);
3481 loadzone(file, origin, rdclass, &gdb);
3482 gorigin = dns_db_origin(gdb);
3483 gclass = dns_db_class(gdb);
3490 * Check for any existing NSEC3 parameters in the zone,
3491 * and use them as defaults if -u was not specified.
3493 if (update_chain && !set_optout && !set_iter && !set_salt)
3494 nsec_datatype = dns_rdatatype_nsec;
3496 set_nsec3params(update_chain, set_salt, set_optout, set_iter);
3499 * We need to do this early on, as we start messing with the list
3500 * of keys rather early.
3502 ISC_LIST_INIT(keylist);
3503 isc_rwlock_init(&keylist_lock, 0, 0);
3506 * Fill keylist with:
3507 * 1) Keys listed in the DNSKEY set that have
3508 * private keys associated, *if* no keys were
3509 * set on the command line.
3510 * 2) ZSKs set on the command line
3511 * 3) KSKs set on the command line
3512 * 4) Any keys remaining in the DNSKEY set which
3513 * do not have private keys associated and were
3514 * not specified on the command line.
3516 if (argc == 0 || smartsign)
3517 loadzonekeys(!smartsign, ISC_FALSE);
3518 loadexplicitkeys(argv, argc, ISC_FALSE);
3519 loadexplicitkeys(dskeyfile, ndskeys, ISC_TRUE);
3520 loadzonekeys(!smartsign, ISC_TRUE);
3523 * If we're doing smart signing, look in the key repository for
3524 * key files with metadata, and merge them with the keylist
3528 build_final_keylist();
3530 /* Now enumerate the key list */
3531 for (key = ISC_LIST_HEAD(keylist);
3533 key = ISC_LIST_NEXT(key, link)) {
3534 key->index = keycount++;
3537 if (keycount == 0) {
3538 if (disable_zone_check)
3539 fprintf(stderr, "%s: warning: No keys specified "
3540 "or found\n", program);
3542 fatal("No signing keys specified or found.");
3550 isc_boolean_t answer;
3552 hash_length = dns_nsec3_hashlength(dns_hash_sha1);
3553 hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2,
3555 result = dns_nsec_nseconly(gdb, gversion, &answer);
3556 if (result == ISC_R_NOTFOUND)
3557 fprintf(stderr, "%s: warning: NSEC3 generation "
3558 "requested with no DNSKEY; ignoring\n",
3560 else if (result != ISC_R_SUCCESS)
3561 check_result(result, "dns_nsec_nseconly");
3563 fatal("NSEC3 generation requested with "
3564 "NSEC-only DNSKEY");
3566 result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max);
3567 check_result(result, "dns_nsec3_maxiterations()");
3568 if (nsec3iter > max)
3569 fatal("NSEC3 iterations too big for weakest DNSKEY "
3570 "strength. Maximum iterations allowed %u.", max);
3574 result = dns_db_newversion(gdb, &gversion);
3575 check_result(result, "dns_db_newversion()");
3577 switch (serialformat) {
3578 case SOA_SERIAL_INCREMENT:
3581 case SOA_SERIAL_UNIXTIME:
3584 case SOA_SERIAL_KEEP:
3590 remove_duplicates();
3594 nsec3ify(dns_hash_sha1, nsec3iter, salt, salt_length,
3601 writeset("dsset-", dns_rdatatype_ds);
3603 writeset("keyset-", dns_rdatatype_dnskey);
3605 writeset("dlvset-", dns_rdatatype_dlv);
3609 if (output_stdout) {
3611 if (outputformatstr == NULL)
3612 masterstyle = &dns_master_style_full;
3614 tempfilelen = strlen(output) + 20;
3615 tempfile = isc_mem_get(mctx, tempfilelen);
3616 if (tempfile == NULL)
3617 fatal("out of memory");
3619 result = isc_file_mktemplate(output, tempfile, tempfilelen);
3620 check_result(result, "isc_file_mktemplate");
3622 if (outputformat == dns_masterformat_text)
3623 result = isc_file_openunique(tempfile, &fp);
3625 result = isc_file_bopenunique(tempfile, &fp);
3626 if (result != ISC_R_SUCCESS)
3627 fatal("failed to open temporary output file: %s",
3628 isc_result_totext(result));
3629 removefile = ISC_TRUE;
3630 setfatalcallback(&removetempfile);
3636 result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
3637 if (result != ISC_R_SUCCESS)
3638 fatal("failed to create task manager: %s",
3639 isc_result_totext(result));
3642 result = isc_task_create(taskmgr, 0, &master);
3643 if (result != ISC_R_SUCCESS)
3644 fatal("failed to create task: %s", isc_result_totext(result));
3646 tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
3648 fatal("out of memory");
3649 for (i = 0; i < (int)ntasks; i++) {
3651 result = isc_task_create(taskmgr, 0, &tasks[i]);
3652 if (result != ISC_R_SUCCESS)
3653 fatal("failed to create task: %s",
3654 isc_result_totext(result));
3657 RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS);
3659 RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS);
3662 TIME_NOW(&sign_start);
3666 * There is more work to do. Spread it out over multiple
3667 * processors if possible.
3669 for (i = 0; i < (int)ntasks; i++) {
3670 result = isc_app_onrun(mctx, master, startworker,
3672 if (result != ISC_R_SUCCESS)
3673 fatal("failed to start task: %s",
3674 isc_result_totext(result));
3676 (void)isc_app_run();
3678 fatal("process aborted by user");
3680 isc_task_detach(&master);
3681 shuttingdown = ISC_TRUE;
3682 for (i = 0; i < (int)ntasks; i++)
3683 isc_task_detach(&tasks[i]);
3684 isc_taskmgr_destroy(&taskmgr);
3685 isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
3687 TIME_NOW(&sign_finish);
3689 if (!disable_zone_check)
3690 verifyzone(gdb, gversion, gorigin, mctx,
3691 ignore_kskflag, keyset_kskonly);
3693 if (outputformat != dns_masterformat_text) {
3694 dns_masterrawheader_t header;
3695 dns_master_initrawheader(&header);
3696 if (rawversion == 0U)
3697 header.flags = DNS_MASTERRAW_COMPAT;
3699 header.flags = DNS_MASTERRAW_SOURCESERIALSET;
3700 header.sourceserial = serialnum;
3702 result = dns_master_dumptostream3(mctx, gdb, gversion,
3703 masterstyle, outputformat,
3705 check_result(result, "dns_master_dumptostream3");
3708 DESTROYLOCK(&namelock);
3710 DESTROYLOCK(&statslock);
3712 if (!output_stdout) {
3713 result = isc_stdio_close(fp);
3714 check_result(result, "isc_stdio_close");
3715 removefile = ISC_FALSE;
3717 result = isc_file_rename(tempfile, output);
3718 if (result != ISC_R_SUCCESS)
3719 fatal("failed to rename temp file to %s: %s\n",
3720 output, isc_result_totext(result));
3722 printf("%s\n", output);
3725 dns_db_closeversion(gdb, &gversion, ISC_FALSE);
3726 dns_db_detach(&gdb);
3728 while (!ISC_LIST_EMPTY(keylist)) {
3729 key = ISC_LIST_HEAD(keylist);
3730 ISC_LIST_UNLINK(keylist, key, link);
3731 dns_dnsseckey_destroy(mctx, &key);
3734 if (tempfilelen != 0)
3735 isc_mem_put(mctx, tempfile, tempfilelen);
3738 isc_mem_free(mctx, output);
3740 dns_master_styledestroy(&dsstyle, mctx);
3742 cleanup_logging(&log);
3745 cleanup_entropy(&ectx);
3748 isc_mem_stats(mctx, stdout);
3749 isc_mem_destroy(&mctx);
3751 (void) isc_app_finish();
3754 TIME_NOW(&timer_finish);
3755 print_stats(&timer_start, &timer_finish,
3756 &sign_start, &sign_finish);