2 * Portions Copyright (C) 2004-2010 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.262 2010-06-03 23:51:04 tbox Exp $ */
42 #include <isc/base32.h>
43 #include <isc/commandline.h>
44 #include <isc/entropy.h>
45 #include <isc/event.h>
50 #include <isc/mutex.h>
52 #include <isc/print.h>
53 #include <isc/random.h>
54 #include <isc/rwlock.h>
55 #include <isc/serial.h>
56 #include <isc/stdio.h>
57 #include <isc/stdlib.h>
58 #include <isc/string.h>
64 #include <dns/dbiterator.h>
66 #include <dns/dnssec.h>
68 #include <dns/fixedname.h>
69 #include <dns/keyvalues.h>
71 #include <dns/master.h>
72 #include <dns/masterdump.h>
74 #include <dns/nsec3.h>
75 #include <dns/rdata.h>
76 #include <dns/rdatalist.h>
77 #include <dns/rdataset.h>
78 #include <dns/rdataclass.h>
79 #include <dns/rdatasetiter.h>
80 #include <dns/rdatastruct.h>
81 #include <dns/rdatatype.h>
82 #include <dns/result.h>
88 #include "dnssectool.h"
91 #define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */
94 const char *program = "dnssec-signzone";
97 typedef struct hashlist hashlist_t;
99 static int nsec_datatype = dns_rdatatype_nsec;
101 #define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3)
102 #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
104 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
109 #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
110 #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
111 #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
113 #define SOA_SERIAL_KEEP 0
114 #define SOA_SERIAL_INCREMENT 1
115 #define SOA_SERIAL_UNIXTIME 2
117 typedef struct signer_event sevent_t;
118 struct signer_event {
119 ISC_EVENT_COMMON(sevent_t);
120 dns_fixedname_t *fname;
124 static dns_dnsseckeylist_t keylist;
125 static unsigned int keycount = 0;
126 isc_rwlock_t keylist_lock;
127 static isc_stdtime_t starttime = 0, endtime = 0, now;
128 static int cycle = -1;
129 static int jitter = 0;
130 static isc_boolean_t tryverify = ISC_FALSE;
131 static isc_boolean_t printstats = ISC_FALSE;
132 static isc_mem_t *mctx = NULL;
133 static isc_entropy_t *ectx = NULL;
134 static dns_ttl_t zone_soa_min_ttl;
135 static dns_ttl_t soa_ttl;
137 static char *tempfile = NULL;
138 static const dns_master_style_t *masterstyle;
139 static dns_masterformat_t inputformat = dns_masterformat_text;
140 static dns_masterformat_t outputformat = dns_masterformat_text;
141 static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
142 static unsigned int nverified = 0, nverifyfailed = 0;
143 static const char *directory = NULL, *dsdir = NULL;
144 static isc_mutex_t namelock, statslock;
145 static isc_taskmgr_t *taskmgr = NULL;
146 static dns_db_t *gdb; /* The database */
147 static dns_dbversion_t *gversion; /* The database version */
148 static dns_dbiterator_t *gdbiter; /* The database iterator */
149 static dns_rdataclass_t gclass; /* The class */
150 static dns_name_t *gorigin; /* The database origin */
151 static int nsec3flags = 0;
152 static dns_iterations_t nsec3iter = 10U;
153 static unsigned char saltbuf[255];
154 static unsigned char *salt = saltbuf;
155 static size_t salt_length = 0;
156 static isc_task_t *master = NULL;
157 static unsigned int ntasks = 0;
158 static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE;
159 static isc_boolean_t nokeys = ISC_FALSE;
160 static isc_boolean_t removefile = ISC_FALSE;
161 static isc_boolean_t generateds = ISC_FALSE;
162 static isc_boolean_t ignore_kskflag = ISC_FALSE;
163 static isc_boolean_t keyset_kskonly = ISC_FALSE;
164 static dns_name_t *dlv = NULL;
165 static dns_fixedname_t dlv_fixed;
166 static dns_master_style_t *dsstyle = NULL;
167 static unsigned int serialformat = SOA_SERIAL_KEEP;
168 static unsigned int hash_length = 0;
169 static isc_boolean_t unknownalg = ISC_FALSE;
170 static isc_boolean_t disable_zone_check = ISC_FALSE;
171 static isc_boolean_t update_chain = ISC_FALSE;
172 static isc_boolean_t set_keyttl = ISC_FALSE;
173 static dns_ttl_t keyttl;
175 #define INCSTAT(counter) \
179 UNLOCK(&statslock); \
183 sign(isc_task_t *task, isc_event_t *event);
185 #define check_dns_dbiterator_current(result) \
186 check_result((result == DNS_R_NEWORIGIN) ? ISC_R_SUCCESS : result, \
187 "dns_dbiterator_current()")
190 dumpnode(dns_name_t *name, dns_dbnode_t *node) {
193 if (outputformat != dns_masterformat_text)
195 result = dns_master_dumpnodetostream(mctx, gdb, gversion, node, name,
197 check_result(result, "dns_master_dumpnodetostream");
201 * Sign the given RRset with given key, and add the signature record to the
205 signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key,
206 dns_ttl_t ttl, dns_diff_t *add, const char *logmsg)
209 isc_stdtime_t jendtime;
210 char keystr[DST_KEY_FORMATSIZE];
211 dns_rdata_t trdata = DNS_RDATA_INIT;
212 unsigned char array[BUFSIZE];
214 dns_difftuple_t *tuple;
216 dst_key_format(key, keystr, sizeof(keystr));
217 vbprintf(1, "\t%s %s\n", logmsg, keystr);
219 jendtime = (jitter != 0) ? isc_random_jitter(endtime, jitter) : endtime;
220 isc_buffer_init(&b, array, sizeof(array));
221 result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
223 isc_entropy_stopcallbacksources(ectx);
224 if (result != ISC_R_SUCCESS) {
225 char keystr[DST_KEY_FORMATSIZE];
226 dst_key_format(key, keystr, sizeof(keystr));
227 fatal("dnskey '%s' failed to sign data: %s",
228 keystr, isc_result_totext(result));
233 result = dns_dnssec_verify(name, rdataset, key,
234 ISC_TRUE, mctx, &trdata);
235 if (result == ISC_R_SUCCESS) {
236 vbprintf(3, "\tsignature verified\n");
239 vbprintf(3, "\tsignature failed to verify\n");
240 INCSTAT(nverifyfailed);
245 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name, ttl, &trdata,
247 check_result(result, "dns_difftuple_create");
248 dns_diff_append(add, &tuple);
251 static inline isc_boolean_t
252 issigningkey(dns_dnsseckey_t *key) {
253 return (key->force_sign || key->hint_sign);
256 static inline isc_boolean_t
257 iszonekey(dns_dnsseckey_t *key) {
258 return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) &&
259 dst_key_iszonekey(key->key)));
262 static inline isc_boolean_t
263 isksk(dns_dnsseckey_t *key) {
267 static inline isc_boolean_t
268 iszsk(dns_dnsseckey_t *key) {
269 return (ignore_kskflag || !key->ksk);
273 * Find the key that generated an RRSIG, if it is in the key list. If
274 * so, return a pointer to it, otherwise return NULL.
276 * No locking is performed here, this must be done by the caller.
278 static dns_dnsseckey_t *
279 keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
280 dns_dnsseckey_t *key;
282 for (key = ISC_LIST_HEAD(keylist);
284 key = ISC_LIST_NEXT(key, link)) {
285 if (rrsig->keyid == dst_key_id(key->key) &&
286 rrsig->algorithm == dst_key_alg(key->key) &&
287 dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
294 * Finds the key that generated a RRSIG, if possible. First look at the keys
295 * that we've loaded already, and then see if there's a key on disk.
297 static dns_dnsseckey_t *
298 keythatsigned(dns_rdata_rrsig_t *rrsig) {
300 dst_key_t *pubkey = NULL, *privkey = NULL;
301 dns_dnsseckey_t *key = NULL;
303 isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read);
304 key = keythatsigned_unlocked(rrsig);
305 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_read);
310 * We did not find the key in our list. Get a write lock now, since
311 * we may be modifying the bits. We could do the tryupgrade() dance,
312 * but instead just get a write lock and check once again to see if
313 * it is on our list. It's possible someone else may have added it
316 isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write);
317 key = keythatsigned_unlocked(rrsig);
319 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
323 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
324 rrsig->algorithm, DST_TYPE_PUBLIC,
325 directory, mctx, &pubkey);
326 if (result != ISC_R_SUCCESS) {
327 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
331 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
333 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
334 directory, mctx, &privkey);
335 if (result == ISC_R_SUCCESS) {
336 dst_key_free(&pubkey);
337 dns_dnsseckey_create(mctx, &privkey, &key);
339 dns_dnsseckey_create(mctx, &pubkey, &key);
341 key->force_publish = ISC_TRUE;
342 key->force_sign = ISC_FALSE;
343 ISC_LIST_APPEND(keylist, key, link);
345 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
350 * Check to see if we expect to find a key at this name. If we see a RRSIG
351 * and can't find the signing key that we expect to find, we drop the rrsig.
352 * I'm not sure if this is completely correct, but it seems to work.
355 expecttofindkey(dns_name_t *name) {
356 unsigned int options = DNS_DBFIND_NOWILD;
357 dns_fixedname_t fname;
359 char namestr[DNS_NAME_FORMATSIZE];
361 dns_fixedname_init(&fname);
362 result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
363 0, NULL, dns_fixedname_name(&fname), NULL, NULL);
369 case DNS_R_DELEGATION:
374 dns_name_format(name, namestr, sizeof(namestr));
375 fatal("failure looking for '%s DNSKEY' in database: %s",
376 namestr, isc_result_totext(result));
378 return (ISC_FALSE); /* removes a warning */
381 static inline isc_boolean_t
382 setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
386 result = dns_dnssec_verify(name, set, key, ISC_FALSE, mctx, rrsig);
387 if (result == ISC_R_SUCCESS) {
391 INCSTAT(nverifyfailed);
397 * Signs a set. Goes through contortions to decide if each RRSIG should
398 * be dropped or retained, and then determines if any new SIGs need to
402 signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
405 dns_rdataset_t sigset;
406 dns_rdata_t sigrdata = DNS_RDATA_INIT;
407 dns_rdata_rrsig_t rrsig;
408 dns_dnsseckey_t *key;
410 isc_boolean_t nosigs = ISC_FALSE;
411 isc_boolean_t *wassignedby, *nowsignedby;
413 dns_difftuple_t *tuple;
416 char namestr[DNS_NAME_FORMATSIZE];
417 char typestr[TYPE_FORMATSIZE];
418 char sigstr[SIG_FORMATSIZE];
420 dns_name_format(name, namestr, sizeof(namestr));
421 type_format(set->type, typestr, sizeof(typestr));
423 ttl = ISC_MIN(set->ttl, endtime - starttime);
425 dns_rdataset_init(&sigset);
426 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
427 set->type, 0, &sigset, NULL);
428 if (result == ISC_R_NOTFOUND) {
429 result = ISC_R_SUCCESS;
432 if (result != ISC_R_SUCCESS)
433 fatal("failed while looking for '%s RRSIG %s': %s",
434 namestr, typestr, isc_result_totext(result));
436 vbprintf(1, "%s/%s:\n", namestr, typestr);
438 arraysize = keycount;
440 arraysize += dns_rdataset_count(&sigset);
441 wassignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
442 nowsignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
443 if (wassignedby == NULL || nowsignedby == NULL)
444 fatal("out of memory");
446 for (i = 0; i < arraysize; i++)
447 wassignedby[i] = nowsignedby[i] = ISC_FALSE;
450 result = ISC_R_NOMORE;
452 result = dns_rdataset_first(&sigset);
454 while (result == ISC_R_SUCCESS) {
455 isc_boolean_t expired, future;
456 isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE;
458 dns_rdataset_current(&sigset, &sigrdata);
460 result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
461 check_result(result, "dns_rdata_tostruct");
463 future = isc_serial_lt(now, rrsig.timesigned);
465 key = keythatsigned(&rrsig);
466 sig_format(&rrsig, sigstr, sizeof(sigstr));
467 if (key != NULL && issigningkey(key))
468 expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
470 expired = isc_serial_gt(now, rrsig.timeexpire);
472 if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
473 /* rrsig is dropped and not replaced */
474 vbprintf(2, "\trrsig by %s dropped - "
475 "invalid validity period\n",
477 } else if (key == NULL && !future &&
478 expecttofindkey(&rrsig.signer)) {
479 /* rrsig is dropped and not replaced */
480 vbprintf(2, "\trrsig by %s dropped - "
481 "private dnskey not found\n",
483 } else if (key == NULL || future) {
484 vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
485 expired ? "retained" : "dropped", sigstr);
488 } else if (issigningkey(key)) {
489 if (!expired && setverifies(name, set, key->key,
491 vbprintf(2, "\trrsig by %s retained\n", sigstr);
493 wassignedby[key->index] = ISC_TRUE;
494 nowsignedby[key->index] = ISC_TRUE;
496 vbprintf(2, "\trrsig by %s dropped - %s\n",
498 expired ? "expired" :
500 wassignedby[key->index] = ISC_TRUE;
503 } else if (iszonekey(key)) {
504 if (!expired && setverifies(name, set, key->key,
506 vbprintf(2, "\trrsig by %s retained\n", sigstr);
508 wassignedby[key->index] = ISC_TRUE;
509 nowsignedby[key->index] = ISC_TRUE;
511 vbprintf(2, "\trrsig by %s dropped - %s\n",
513 expired ? "expired" :
515 wassignedby[key->index] = ISC_TRUE;
517 } else if (!expired) {
518 vbprintf(2, "\trrsig by %s retained\n", sigstr);
521 vbprintf(2, "\trrsig by %s expired\n", sigstr);
525 nowsignedby[key->index] = ISC_TRUE;
527 if (sigset.ttl != ttl) {
528 vbprintf(2, "\tfixing ttl %s\n", sigstr);
530 result = dns_difftuple_create(mctx,
535 check_result(result, "dns_difftuple_create");
536 dns_diff_append(del, &tuple);
537 result = dns_difftuple_create(mctx,
542 check_result(result, "dns_difftuple_create");
543 dns_diff_append(add, &tuple);
547 result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL,
550 check_result(result, "dns_difftuple_create");
551 dns_diff_append(del, &tuple);
558 signwithkey(name, set, key->key, ttl, add,
559 "resigning with dnskey");
560 nowsignedby[key->index] = ISC_TRUE;
563 dns_rdata_reset(&sigrdata);
564 dns_rdata_freestruct(&rrsig);
565 result = dns_rdataset_next(&sigset);
567 if (result == ISC_R_NOMORE)
568 result = ISC_R_SUCCESS;
570 check_result(result, "dns_rdataset_first/next");
571 if (dns_rdataset_isassociated(&sigset))
572 dns_rdataset_disassociate(&sigset);
574 for (key = ISC_LIST_HEAD(keylist);
576 key = ISC_LIST_NEXT(key, link))
578 if (nowsignedby[key->index])
581 if (!issigningkey(key))
584 if (set->type == dns_rdatatype_dnskey &&
585 dns_name_equal(name, gorigin)) {
586 isc_boolean_t have_ksk;
587 dns_dnsseckey_t *tmpkey;
589 have_ksk = isksk(key);
590 for (tmpkey = ISC_LIST_HEAD(keylist);
592 tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
593 if (dst_key_alg(key->key) !=
594 dst_key_alg(tmpkey->key))
596 if (REVOKE(tmpkey->key))
601 if (isksk(key) || !have_ksk ||
602 (iszsk(key) && !keyset_kskonly))
603 signwithkey(name, set, key->key, ttl, add,
604 "signing with dnskey");
605 } else if (iszsk(key)) {
606 signwithkey(name, set, key->key, ttl, add,
607 "signing with dnskey");
611 isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t));
612 isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t));
616 unsigned char *hashbuf;
623 hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) {
626 l->length = length + 1;
630 l->hashbuf = malloc(l->size * l->length);
631 if (l->hashbuf == NULL)
640 hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len)
643 REQUIRE(len <= l->length);
645 if (l->entries == l->size) {
646 l->size = l->size * 2 + 100;
647 l->hashbuf = realloc(l->hashbuf, l->size * l->length);
649 memset(l->hashbuf + l->entries * l->length, 0, l->length);
650 memcpy(l->hashbuf + l->entries * l->length, hash, len);
655 hashlist_add_dns_name(hashlist_t *l, /*const*/ dns_name_t *name,
656 unsigned int hashalg, unsigned int iterations,
657 const unsigned char *salt, size_t salt_length,
658 isc_boolean_t speculative)
660 char nametext[DNS_NAME_FORMATSIZE];
661 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
665 len = isc_iterated_hash(hash, hashalg, iterations, salt, salt_length,
666 name->ndata, name->length);
668 dns_name_format(name, nametext, sizeof nametext);
669 for (i = 0 ; i < len; i++)
670 fprintf(stderr, "%02x", hash[i]);
671 fprintf(stderr, " %s\n", nametext);
673 hash[len++] = speculative ? 1 : 0;
674 hashlist_add(l, hash, len);
678 hashlist_comp(const void *a, const void *b) {
679 return (memcmp(a, b, hash_length + 1));
683 hashlist_sort(hashlist_t *l) {
684 qsort(l->hashbuf, l->entries, l->length, hashlist_comp);
688 hashlist_hasdup(hashlist_t *l) {
689 unsigned char *current;
690 unsigned char *next = l->hashbuf;
691 size_t entries = l->entries;
694 * Skip initial speculative wild card hashs.
696 while (entries > 0U && next[l->length-1] != 0U) {
702 while (entries-- > 1U) {
704 if (next[l->length-1] != 0)
706 if (memcmp(current, next, l->length - 1) == 0)
713 static const unsigned char *
714 hashlist_findnext(const hashlist_t *l,
715 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
717 unsigned int entries = l->entries;
718 const unsigned char *next = bsearch(hash, l->hashbuf, l->entries,
719 l->length, hashlist_comp);
720 INSIST(next != NULL);
723 if (next < l->hashbuf + (l->entries - 1) * l->length)
727 if (next[l->length - 1] == 0)
729 } while (entries-- > 1);
730 INSIST(entries != 0);
735 hashlist_exists(const hashlist_t *l,
736 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
738 if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp))
745 addnowildcardhash(hashlist_t *l, /*const*/ dns_name_t *name,
746 unsigned int hashalg, unsigned int iterations,
747 const unsigned char *salt, size_t salt_length)
749 dns_fixedname_t fixed;
751 dns_dbnode_t *node = NULL;
753 char namestr[DNS_NAME_FORMATSIZE];
755 dns_fixedname_init(&fixed);
756 wild = dns_fixedname_name(&fixed);
758 result = dns_name_concatenate(dns_wildcardname, name, wild, NULL);
759 if (result == ISC_R_NOSPACE)
761 check_result(result,"addnowildcardhash: dns_name_concatenate()");
763 result = dns_db_findnode(gdb, wild, ISC_FALSE, &node);
764 if (result == ISC_R_SUCCESS) {
765 dns_db_detachnode(gdb, &node);
770 dns_name_format(wild, namestr, sizeof(namestr));
771 fprintf(stderr, "adding no-wildcardhash for %s\n", namestr);
774 hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_length,
779 opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
782 char filename[PATH_MAX];
786 isc_buffer_init(&b, filename, sizeof(filename));
788 /* allow room for a trailing slash */
789 if (strlen(dsdir) >= isc_buffer_availablelength(&b))
790 fatal("path '%s' is too long", dsdir);
791 isc_buffer_putstr(&b, dsdir);
792 if (dsdir[strlen(dsdir) - 1] != '/')
793 isc_buffer_putstr(&b, "/");
795 if (strlen(prefix) > isc_buffer_availablelength(&b))
796 fatal("path '%s' is too long", dsdir);
797 isc_buffer_putstr(&b, prefix);
798 result = dns_name_tofilenametext(name, ISC_FALSE, &b);
799 check_result(result, "dns_name_tofilenametext()");
800 if (isc_buffer_availablelength(&b) == 0) {
801 char namestr[DNS_NAME_FORMATSIZE];
802 dns_name_format(name, namestr, sizeof(namestr));
803 fatal("name '%s' is too long", namestr);
805 isc_buffer_putuint8(&b, 0);
807 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
808 rdclass, 0, NULL, dbp);
809 check_result(result, "dns_db_create()");
811 result = dns_db_load3(*dbp, filename, inputformat, DNS_MASTER_HINT);
812 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
817 * Load the DS set for a child zone, if a dsset-* file can be found.
818 * If not, try to find a keyset-* file from an earlier version of
819 * dnssec-signzone, and build DS records from that.
822 loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
824 dns_dbversion_t *ver = NULL;
825 dns_dbnode_t *node = NULL;
827 dns_rdataset_t keyset;
829 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
831 dns_difftuple_t *tuple = NULL;
833 opendb("dsset-", name, gclass, &db);
835 result = dns_db_findnode(db, name, ISC_FALSE, &node);
836 if (result == ISC_R_SUCCESS) {
837 dns_rdataset_init(dsset);
838 result = dns_db_findrdataset(db, node, NULL,
839 dns_rdatatype_ds, 0, 0,
841 dns_db_detachnode(db, &node);
842 if (result == ISC_R_SUCCESS) {
843 vbprintf(2, "found DS records\n");
852 /* No DS records found; try again, looking for DNSKEY records */
853 opendb("keyset-", name, gclass, &db);
855 return (ISC_R_NOTFOUND);
858 result = dns_db_findnode(db, name, ISC_FALSE, &node);
859 if (result != ISC_R_SUCCESS) {
864 dns_rdataset_init(&keyset);
865 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
867 if (result != ISC_R_SUCCESS) {
868 dns_db_detachnode(db, &node);
872 vbprintf(2, "found DNSKEY records\n");
874 result = dns_db_newversion(db, &ver);
875 check_result(result, "dns_db_newversion");
876 dns_diff_init(mctx, &diff);
878 for (result = dns_rdataset_first(&keyset);
879 result == ISC_R_SUCCESS;
880 result = dns_rdataset_next(&keyset))
882 dns_rdata_init(&key);
884 dns_rdataset_current(&keyset, &key);
885 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
887 check_result(result, "dns_ds_buildrdata");
889 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
891 check_result(result, "dns_difftuple_create");
892 dns_diff_append(&diff, &tuple);
894 dns_rdata_reset(&ds);
895 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
897 check_result(result, "dns_ds_buildrdata");
899 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
901 check_result(result, "dns_difftuple_create");
902 dns_diff_append(&diff, &tuple);
905 result = dns_diff_apply(&diff, db, ver);
906 check_result(result, "dns_diff_apply");
907 dns_diff_clear(&diff);
909 dns_db_closeversion(db, &ver, ISC_TRUE);
911 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
913 check_result(result, "dns_db_findrdataset");
915 dns_rdataset_disassociate(&keyset);
916 dns_db_detachnode(db, &node);
922 delegation(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) {
923 dns_rdataset_t nsset;
926 if (dns_name_equal(name, gorigin))
929 dns_rdataset_init(&nsset);
930 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ns,
932 if (dns_rdataset_isassociated(&nsset)) {
935 dns_rdataset_disassociate(&nsset);
938 return (ISC_TF(result == ISC_R_SUCCESS));
942 secure(dns_name_t *name, dns_dbnode_t *node) {
943 dns_rdataset_t dsset;
946 if (dns_name_equal(name, gorigin))
949 dns_rdataset_init(&dsset);
950 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds,
952 if (dns_rdataset_isassociated(&dsset))
953 dns_rdataset_disassociate(&dsset);
955 return (ISC_TF(result == ISC_R_SUCCESS));
959 * Signs all records at a name.
962 signname(dns_dbnode_t *node, dns_name_t *name) {
964 dns_rdataset_t rdataset;
965 dns_rdatasetiter_t *rdsiter;
966 isc_boolean_t isdelegation = ISC_FALSE;
968 char namestr[DNS_NAME_FORMATSIZE];
970 dns_rdataset_init(&rdataset);
971 dns_name_format(name, namestr, sizeof(namestr));
974 * Determine if this is a delegation point.
976 if (delegation(name, node, NULL))
977 isdelegation = ISC_TRUE;
980 * Now iterate through the rdatasets.
982 dns_diff_init(mctx, &del);
983 dns_diff_init(mctx, &add);
985 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
986 check_result(result, "dns_db_allrdatasets()");
987 result = dns_rdatasetiter_first(rdsiter);
988 while (result == ISC_R_SUCCESS) {
989 dns_rdatasetiter_current(rdsiter, &rdataset);
991 /* If this is a RRSIG set, skip it. */
992 if (rdataset.type == dns_rdatatype_rrsig)
996 * If this name is a delegation point, skip all records
997 * except NSEC and DS sets. Otherwise check that there
1001 if (rdataset.type != nsec_datatype &&
1002 rdataset.type != dns_rdatatype_ds)
1004 } else if (rdataset.type == dns_rdatatype_ds) {
1005 char namebuf[DNS_NAME_FORMATSIZE];
1006 dns_name_format(name, namebuf, sizeof(namebuf));
1007 fatal("'%s': found DS RRset without NS RRset\n",
1011 signset(&del, &add, node, name, &rdataset);
1014 dns_rdataset_disassociate(&rdataset);
1015 result = dns_rdatasetiter_next(rdsiter);
1017 if (result != ISC_R_NOMORE)
1018 fatal("rdataset iteration for name '%s' failed: %s",
1019 namestr, isc_result_totext(result));
1021 dns_rdatasetiter_destroy(&rdsiter);
1023 result = dns_diff_applysilently(&del, gdb, gversion);
1024 if (result != ISC_R_SUCCESS)
1025 fatal("failed to delete SIGs at node '%s': %s",
1026 namestr, isc_result_totext(result));
1028 result = dns_diff_applysilently(&add, gdb, gversion);
1029 if (result != ISC_R_SUCCESS)
1030 fatal("failed to add SIGs at node '%s': %s",
1031 namestr, isc_result_totext(result));
1033 dns_diff_clear(&del);
1034 dns_diff_clear(&add);
1037 static inline isc_boolean_t
1038 active_node(dns_dbnode_t *node) {
1039 dns_rdatasetiter_t *rdsiter = NULL;
1040 dns_rdatasetiter_t *rdsiter2 = NULL;
1041 isc_boolean_t active = ISC_FALSE;
1042 isc_result_t result;
1043 dns_rdataset_t rdataset;
1044 dns_rdatatype_t type;
1045 dns_rdatatype_t covers;
1046 isc_boolean_t found;
1048 dns_rdataset_init(&rdataset);
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);
1054 if (rdataset.type != dns_rdatatype_nsec &&
1055 rdataset.type != dns_rdatatype_nsec3 &&
1056 rdataset.type != dns_rdatatype_rrsig)
1058 dns_rdataset_disassociate(&rdataset);
1060 result = dns_rdatasetiter_next(rdsiter);
1062 result = ISC_R_NOMORE;
1064 if (result != ISC_R_NOMORE)
1065 fatal("rdataset iteration failed: %s",
1066 isc_result_totext(result));
1068 if (!active && nsec_datatype == dns_rdatatype_nsec) {
1070 * The node is empty of everything but NSEC / RRSIG records.
1072 for (result = dns_rdatasetiter_first(rdsiter);
1073 result == ISC_R_SUCCESS;
1074 result = dns_rdatasetiter_next(rdsiter)) {
1075 dns_rdatasetiter_current(rdsiter, &rdataset);
1076 result = dns_db_deleterdataset(gdb, node, gversion,
1079 check_result(result, "dns_db_deleterdataset()");
1080 dns_rdataset_disassociate(&rdataset);
1082 if (result != ISC_R_NOMORE)
1083 fatal("rdataset iteration failed: %s",
1084 isc_result_totext(result));
1087 * Delete RRSIGs for types that no longer exist.
1089 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
1090 check_result(result, "dns_db_allrdatasets()");
1091 for (result = dns_rdatasetiter_first(rdsiter);
1092 result == ISC_R_SUCCESS;
1093 result = dns_rdatasetiter_next(rdsiter)) {
1094 dns_rdatasetiter_current(rdsiter, &rdataset);
1095 type = rdataset.type;
1096 covers = rdataset.covers;
1097 dns_rdataset_disassociate(&rdataset);
1099 * Delete the NSEC chain if we are signing with
1102 if (nsec_datatype == dns_rdatatype_nsec3 &&
1103 (type == dns_rdatatype_nsec ||
1104 covers == dns_rdatatype_nsec)) {
1105 result = dns_db_deleterdataset(gdb, node,
1108 check_result(result,
1109 "dns_db_deleterdataset(nsec/rrsig)");
1112 if (type != dns_rdatatype_rrsig)
1115 for (result = dns_rdatasetiter_first(rdsiter2);
1116 !found && result == ISC_R_SUCCESS;
1117 result = dns_rdatasetiter_next(rdsiter2)) {
1118 dns_rdatasetiter_current(rdsiter2, &rdataset);
1119 if (rdataset.type == covers)
1121 dns_rdataset_disassociate(&rdataset);
1124 if (result != ISC_R_NOMORE)
1125 fatal("rdataset iteration failed: %s",
1126 isc_result_totext(result));
1127 result = dns_db_deleterdataset(gdb, node,
1130 check_result(result,
1131 "dns_db_deleterdataset(rrsig)");
1132 } else if (result != ISC_R_NOMORE &&
1133 result != ISC_R_SUCCESS)
1134 fatal("rdataset iteration failed: %s",
1135 isc_result_totext(result));
1137 if (result != ISC_R_NOMORE)
1138 fatal("rdataset iteration failed: %s",
1139 isc_result_totext(result));
1140 dns_rdatasetiter_destroy(&rdsiter2);
1142 dns_rdatasetiter_destroy(&rdsiter);
1148 * Extracts the minimum TTL from the SOA record, and the SOA record's TTL.
1151 get_soa_ttls(void) {
1152 dns_rdataset_t soaset;
1153 dns_fixedname_t fname;
1155 isc_result_t result;
1156 dns_rdata_t rdata = DNS_RDATA_INIT;
1158 dns_fixedname_init(&fname);
1159 name = dns_fixedname_name(&fname);
1160 dns_rdataset_init(&soaset);
1161 result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
1162 0, 0, NULL, name, &soaset, NULL);
1163 if (result != ISC_R_SUCCESS)
1164 fatal("failed to find an SOA at the zone apex: %s",
1165 isc_result_totext(result));
1167 result = dns_rdataset_first(&soaset);
1168 check_result(result, "dns_rdataset_first");
1169 dns_rdataset_current(&soaset, &rdata);
1170 zone_soa_min_ttl = dns_soa_getminimum(&rdata);
1171 soa_ttl = soaset.ttl;
1172 dns_rdataset_disassociate(&soaset);
1176 * Increment (or set if nonzero) the SOA serial
1179 setsoaserial(isc_uint32_t serial) {
1180 isc_result_t result;
1181 dns_dbnode_t *node = NULL;
1182 dns_rdataset_t rdataset;
1183 dns_rdata_t rdata = DNS_RDATA_INIT;
1184 isc_uint32_t old_serial, new_serial;
1186 result = dns_db_getoriginnode(gdb, &node);
1187 if (result != ISC_R_SUCCESS)
1190 dns_rdataset_init(&rdataset);
1192 result = dns_db_findrdataset(gdb, node, gversion,
1193 dns_rdatatype_soa, 0,
1194 0, &rdataset, NULL);
1195 if (result != ISC_R_SUCCESS)
1198 result = dns_rdataset_first(&rdataset);
1199 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1201 dns_rdataset_current(&rdataset, &rdata);
1203 old_serial = dns_soa_getserial(&rdata);
1206 /* Set SOA serial to the value provided. */
1207 new_serial = serial;
1209 /* Increment SOA serial using RFC 1982 arithmetics */
1210 new_serial = (old_serial + 1) & 0xFFFFFFFF;
1211 if (new_serial == 0)
1215 /* If the new serial is not likely to cause a zone transfer
1216 * (a/ixfr) from servers having the old serial, warn the user.
1218 * RFC1982 section 7 defines the maximum increment to be
1219 * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
1220 * comparison. (5 - 6 == (2^32)-1, not negative-one)
1222 if (new_serial == old_serial ||
1223 (new_serial - old_serial) > 0x7fffffffU)
1224 fprintf(stderr, "%s: warning: Serial number not advanced, "
1225 "zone may not transfer\n", program);
1227 dns_soa_setserial(new_serial, &rdata);
1229 result = dns_db_deleterdataset(gdb, node, gversion,
1230 dns_rdatatype_soa, 0);
1231 check_result(result, "dns_db_deleterdataset");
1232 if (result != ISC_R_SUCCESS)
1235 result = dns_db_addrdataset(gdb, node, gversion,
1236 0, &rdataset, 0, NULL);
1237 check_result(result, "dns_db_addrdataset");
1238 if (result != ISC_R_SUCCESS)
1242 dns_rdataset_disassociate(&rdataset);
1244 dns_db_detachnode(gdb, &node);
1245 dns_rdata_reset(&rdata);
1251 * Delete any RRSIG records at a node.
1254 cleannode(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
1255 dns_rdatasetiter_t *rdsiter = NULL;
1257 isc_result_t result, dresult;
1259 if (outputformat != dns_masterformat_text || !disable_zone_check)
1262 dns_rdataset_init(&set);
1263 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
1264 check_result(result, "dns_db_allrdatasets");
1265 result = dns_rdatasetiter_first(rdsiter);
1266 while (result == ISC_R_SUCCESS) {
1267 isc_boolean_t destroy = ISC_FALSE;
1268 dns_rdatatype_t covers = 0;
1269 dns_rdatasetiter_current(rdsiter, &set);
1270 if (set.type == dns_rdatatype_rrsig) {
1271 covers = set.covers;
1274 dns_rdataset_disassociate(&set);
1275 result = dns_rdatasetiter_next(rdsiter);
1277 dresult = dns_db_deleterdataset(db, node, version,
1278 dns_rdatatype_rrsig,
1280 check_result(dresult, "dns_db_deleterdataset");
1283 if (result != ISC_R_NOMORE)
1284 fatal("rdataset iteration failed: %s",
1285 isc_result_totext(result));
1286 dns_rdatasetiter_destroy(&rdsiter);
1290 * Set up the iterator and global state before starting the tasks.
1294 isc_result_t result;
1297 result = dns_db_createiterator(gdb, 0, &gdbiter);
1298 check_result(result, "dns_db_createiterator()");
1302 * Clean up the iterator and global state after the tasks complete.
1306 dns_dbiterator_destroy(&gdbiter);
1309 static isc_boolean_t
1310 goodsig(dns_rdata_t *sigrdata, dns_name_t *name, dns_rdataset_t *keyrdataset,
1311 dns_rdataset_t *rdataset)
1313 dns_rdata_dnskey_t key;
1314 dns_rdata_rrsig_t sig;
1315 dst_key_t *dstkey = NULL;
1316 isc_result_t result;
1318 dns_rdata_tostruct(sigrdata, &sig, NULL);
1320 for (result = dns_rdataset_first(keyrdataset);
1321 result == ISC_R_SUCCESS;
1322 result = dns_rdataset_next(keyrdataset)) {
1323 dns_rdata_t rdata = DNS_RDATA_INIT;
1324 dns_rdataset_current(keyrdataset, &rdata);
1325 dns_rdata_tostruct(&rdata, &key, NULL);
1326 result = dns_dnssec_keyfromrdata(gorigin, &rdata, mctx,
1328 if (result != ISC_R_SUCCESS)
1330 if (sig.algorithm != key.algorithm ||
1331 sig.keyid != dst_key_id(dstkey) ||
1332 !dns_name_equal(&sig.signer, gorigin)) {
1333 dst_key_free(&dstkey);
1336 result = dns_dnssec_verify(name, rdataset, dstkey, ISC_FALSE,
1338 dst_key_free(&dstkey);
1339 if (result == ISC_R_SUCCESS)
1346 verifyset(dns_rdataset_t *rdataset, dns_name_t *name, dns_dbnode_t *node,
1347 dns_rdataset_t *keyrdataset, unsigned char *ksk_algorithms,
1348 unsigned char *bad_algorithms)
1350 unsigned char set_algorithms[256];
1351 char namebuf[DNS_NAME_FORMATSIZE];
1354 dns_rdataset_t sigrdataset;
1355 dns_rdatasetiter_t *rdsiter = NULL;
1356 isc_result_t result;
1359 dns_rdataset_init(&sigrdataset);
1360 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1361 check_result(result, "dns_db_allrdatasets()");
1362 for (result = dns_rdatasetiter_first(rdsiter);
1363 result == ISC_R_SUCCESS;
1364 result = dns_rdatasetiter_next(rdsiter)) {
1365 dns_rdatasetiter_current(rdsiter, &sigrdataset);
1366 if (sigrdataset.type == dns_rdatatype_rrsig &&
1367 sigrdataset.covers == rdataset->type)
1369 dns_rdataset_disassociate(&sigrdataset);
1371 if (result != ISC_R_SUCCESS) {
1372 dns_name_format(name, namebuf, sizeof(namebuf));
1373 type_format(rdataset->type, typebuf, sizeof(typebuf));
1374 fprintf(stderr, "no signatures for %s/%s\n", namebuf, typebuf);
1375 for (i = 0; i < 256; i++)
1376 if (ksk_algorithms[i] != 0)
1377 bad_algorithms[i] = 1;
1381 memset(set_algorithms, 0, sizeof(set_algorithms));
1382 for (result = dns_rdataset_first(&sigrdataset);
1383 result == ISC_R_SUCCESS;
1384 result = dns_rdataset_next(&sigrdataset)) {
1385 dns_rdata_t rdata = DNS_RDATA_INIT;
1386 dns_rdata_rrsig_t sig;
1388 dns_rdataset_current(&sigrdataset, &rdata);
1389 dns_rdata_tostruct(&rdata, &sig, NULL);
1390 if ((set_algorithms[sig.algorithm] != 0) ||
1391 (ksk_algorithms[sig.algorithm] == 0))
1393 if (goodsig(&rdata, name, keyrdataset, rdataset))
1394 set_algorithms[sig.algorithm] = 1;
1396 dns_rdatasetiter_destroy(&rdsiter);
1397 if (memcmp(set_algorithms, ksk_algorithms, sizeof(set_algorithms))) {
1398 dns_name_format(name, namebuf, sizeof(namebuf));
1399 type_format(rdataset->type, typebuf, sizeof(typebuf));
1400 for (i = 0; i < 256; i++)
1401 if ((ksk_algorithms[i] != 0) &&
1402 (set_algorithms[i] == 0)) {
1403 dns_secalg_format(i, algbuf, sizeof(algbuf));
1404 fprintf(stderr, "Missing %s signature for "
1405 "%s %s\n", algbuf, namebuf, typebuf);
1406 bad_algorithms[i] = 1;
1409 dns_rdataset_disassociate(&sigrdataset);
1413 verifynode(dns_name_t *name, dns_dbnode_t *node, isc_boolean_t delegation,
1414 dns_rdataset_t *keyrdataset, unsigned char *ksk_algorithms,
1415 unsigned char *bad_algorithms)
1417 dns_rdataset_t rdataset;
1418 dns_rdatasetiter_t *rdsiter = NULL;
1419 isc_result_t result;
1421 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1422 check_result(result, "dns_db_allrdatasets()");
1423 result = dns_rdatasetiter_first(rdsiter);
1424 dns_rdataset_init(&rdataset);
1425 while (result == ISC_R_SUCCESS) {
1426 dns_rdatasetiter_current(rdsiter, &rdataset);
1427 if (rdataset.type != dns_rdatatype_rrsig &&
1428 rdataset.type != dns_rdatatype_dnskey &&
1429 (!delegation || rdataset.type == dns_rdatatype_ds ||
1430 rdataset.type == dns_rdatatype_nsec)) {
1431 verifyset(&rdataset, name, node, keyrdataset,
1432 ksk_algorithms, bad_algorithms);
1434 dns_rdataset_disassociate(&rdataset);
1435 result = dns_rdatasetiter_next(rdsiter);
1437 if (result != ISC_R_NOMORE)
1438 fatal("rdataset iteration failed: %s",
1439 isc_result_totext(result));
1440 dns_rdatasetiter_destroy(&rdsiter);
1444 * Verify that certain things are sane:
1446 * The apex has a DNSKEY record with at least one KSK, and at least
1447 * one ZSK if the -x flag was not used.
1449 * The DNSKEY record was signed with at least one of the KSKs in this
1452 * The rest of the zone was signed with at least one of the ZSKs
1453 * present in the DNSKEY RRSET.
1458 dns_dbiterator_t *dbiter = NULL;
1459 dns_dbnode_t *node = NULL, *nextnode = NULL;
1460 dns_fixedname_t fname, fnextname, fzonecut;
1461 dns_name_t *name, *nextname, *zonecut;
1462 dns_rdata_dnskey_t dnskey;
1463 dns_rdata_t rdata = DNS_RDATA_INIT;
1464 dns_rdataset_t rdataset;
1465 dns_rdataset_t sigrdataset;
1467 isc_boolean_t done = ISC_FALSE;
1468 isc_boolean_t first = ISC_TRUE;
1469 isc_boolean_t goodksk = ISC_FALSE;
1470 isc_boolean_t goodzsk = ISC_FALSE;
1471 isc_result_t result;
1472 unsigned char revoked_ksk[256];
1473 unsigned char revoked_zsk[256];
1474 unsigned char standby_ksk[256];
1475 unsigned char standby_zsk[256];
1476 unsigned char ksk_algorithms[256];
1477 unsigned char zsk_algorithms[256];
1478 unsigned char bad_algorithms[256];
1479 #ifdef ALLOW_KSKLESS_ZONES
1480 isc_boolean_t allzsksigned = ISC_TRUE;
1481 unsigned char self_algorithms[256];
1484 if (disable_zone_check)
1487 result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node);
1488 if (result != ISC_R_SUCCESS)
1489 fatal("failed to find the zone's origin: %s",
1490 isc_result_totext(result));
1492 dns_rdataset_init(&rdataset);
1493 dns_rdataset_init(&sigrdataset);
1494 result = dns_db_findrdataset(gdb, node, gversion,
1495 dns_rdatatype_dnskey,
1496 0, 0, &rdataset, &sigrdataset);
1497 dns_db_detachnode(gdb, &node);
1498 if (result != ISC_R_SUCCESS)
1499 fatal("cannot find DNSKEY rrset\n");
1501 if (!dns_rdataset_isassociated(&sigrdataset))
1502 fatal("cannot find DNSKEY RRSIGs\n");
1504 memset(revoked_ksk, 0, sizeof(revoked_ksk));
1505 memset(revoked_zsk, 0, sizeof(revoked_zsk));
1506 memset(standby_ksk, 0, sizeof(standby_ksk));
1507 memset(standby_zsk, 0, sizeof(standby_zsk));
1508 memset(ksk_algorithms, 0, sizeof(ksk_algorithms));
1509 memset(zsk_algorithms, 0, sizeof(zsk_algorithms));
1510 memset(bad_algorithms, 0, sizeof(bad_algorithms));
1511 #ifdef ALLOW_KSKLESS_ZONES
1512 memset(self_algorithms, 0, sizeof(self_algorithms));
1516 * Check that the DNSKEY RR has at least one self signing KSK
1517 * and one ZSK per algorithm in it (or, if -x was used, one
1518 * self-signing KSK).
1520 for (result = dns_rdataset_first(&rdataset);
1521 result == ISC_R_SUCCESS;
1522 result = dns_rdataset_next(&rdataset)) {
1523 dns_rdataset_current(&rdataset, &rdata);
1524 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
1525 check_result(result, "dns_rdata_tostruct");
1527 if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0)
1529 else if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) {
1530 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1531 !dns_dnssec_selfsigns(&rdata, gorigin, &rdataset,
1532 &sigrdataset, ISC_FALSE,
1534 char namebuf[DNS_NAME_FORMATSIZE];
1538 dns_name_format(gorigin, namebuf,
1540 isc_buffer_init(&buf, buffer, sizeof(buffer));
1541 result = dns_rdata_totext(&rdata, NULL, &buf);
1542 check_result(result, "dns_rdata_totext");
1543 fatal("revoked KSK is not self signed:\n"
1544 "%s DNSKEY %.*s", namebuf,
1545 (int)isc_buffer_usedlength(&buf), buffer);
1547 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1548 revoked_ksk[dnskey.algorithm] != 255)
1549 revoked_ksk[dnskey.algorithm]++;
1550 else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 &&
1551 revoked_zsk[dnskey.algorithm] != 255)
1552 revoked_zsk[dnskey.algorithm]++;
1553 } else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) {
1554 if (dns_dnssec_selfsigns(&rdata, gorigin, &rdataset,
1555 &sigrdataset, ISC_FALSE, mctx)) {
1556 if (ksk_algorithms[dnskey.algorithm] != 255)
1557 ksk_algorithms[dnskey.algorithm]++;
1560 if (standby_ksk[dnskey.algorithm] != 255)
1561 standby_ksk[dnskey.algorithm]++;
1563 } else if (dns_dnssec_selfsigns(&rdata, gorigin, &rdataset,
1564 &sigrdataset, ISC_FALSE,
1566 #ifdef ALLOW_KSKLESS_ZONES
1567 if (self_algorithms[dnskey.algorithm] != 255)
1568 self_algorithms[dnskey.algorithm]++;
1570 if (zsk_algorithms[dnskey.algorithm] != 255)
1571 zsk_algorithms[dnskey.algorithm]++;
1574 if (standby_zsk[dnskey.algorithm] != 255)
1575 standby_zsk[dnskey.algorithm]++;
1576 #ifdef ALLOW_KSKLESS_ZONES
1577 allzsksigned = ISC_FALSE;
1580 dns_rdata_freestruct(&dnskey);
1581 dns_rdata_reset(&rdata);
1583 dns_rdataset_disassociate(&sigrdataset);
1585 #ifdef ALLOW_KSKLESS_ZONES
1587 if (!ignore_kskflag)
1588 fprintf(stderr, "No self signing KSK found. Using "
1589 "self signed ZSK's for active "
1590 "algorithm list.\n");
1591 memcpy(ksk_algorithms, self_algorithms, sizeof(ksk_algorithms));
1593 fprintf(stderr, "warning: not all ZSK's are self "
1598 fatal("no self signed KSK's found");
1602 fprintf(stderr, "Verifying the zone using the following algorithms:");
1603 for (i = 0; i < 256; i++) {
1604 #ifdef ALLOW_KSKLESS_ZONES
1605 if (ksk_algorithms[i] != 0 || zsk_algorithms[i] != 0)
1607 if (ksk_algorithms[i] != 0)
1610 dns_secalg_format(i, algbuf, sizeof(algbuf));
1611 fprintf(stderr, " %s", algbuf);
1614 fprintf(stderr, ".\n");
1616 if (!ignore_kskflag && !keyset_kskonly) {
1617 for (i = 0; i < 256; i++) {
1619 * The counts should both be zero or both be non-zero.
1620 * Mark the algorithm as bad if this is not met.
1622 if ((ksk_algorithms[i] != 0) ==
1623 (zsk_algorithms[i] != 0))
1625 dns_secalg_format(i, algbuf, sizeof(algbuf));
1626 fprintf(stderr, "Missing %s for algorithm %s\n",
1627 (ksk_algorithms[i] != 0)
1629 : "self signing KSK",
1631 bad_algorithms[i] = 1;
1636 * Check that all the other records were signed by keys that are
1637 * present in the DNSKEY RRSET.
1640 dns_fixedname_init(&fname);
1641 name = dns_fixedname_name(&fname);
1642 dns_fixedname_init(&fnextname);
1643 nextname = dns_fixedname_name(&fnextname);
1644 dns_fixedname_init(&fzonecut);
1647 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
1648 check_result(result, "dns_db_createiterator()");
1650 result = dns_dbiterator_first(dbiter);
1651 check_result(result, "dns_dbiterator_first()");
1654 isc_boolean_t isdelegation = ISC_FALSE;
1656 result = dns_dbiterator_current(dbiter, &node, name);
1657 check_dns_dbiterator_current(result);
1658 if (!dns_name_issubdomain(name, gorigin)) {
1659 dns_db_detachnode(gdb, &node);
1660 result = dns_dbiterator_next(dbiter);
1661 if (result == ISC_R_NOMORE)
1664 check_result(result, "dns_dbiterator_next()");
1667 if (delegation(name, node, NULL)) {
1668 zonecut = dns_fixedname_name(&fzonecut);
1669 dns_name_copy(name, zonecut, NULL);
1670 isdelegation = ISC_TRUE;
1672 verifynode(name, node, isdelegation, &rdataset,
1673 ksk_algorithms, bad_algorithms);
1674 result = dns_dbiterator_next(dbiter);
1676 while (result == ISC_R_SUCCESS) {
1677 result = dns_dbiterator_current(dbiter, &nextnode,
1679 check_dns_dbiterator_current(result);
1680 if (!dns_name_issubdomain(nextname, gorigin) ||
1682 dns_name_issubdomain(nextname, zonecut)))
1684 dns_db_detachnode(gdb, &nextnode);
1685 result = dns_dbiterator_next(dbiter);
1688 dns_db_detachnode(gdb, &nextnode);
1691 if (result == ISC_R_NOMORE) {
1693 } else if (result != ISC_R_SUCCESS)
1694 fatal("iterating through the database failed: %s",
1695 isc_result_totext(result));
1696 dns_db_detachnode(gdb, &node);
1699 dns_dbiterator_destroy(&dbiter);
1701 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
1702 check_result(result, "dns_db_createiterator()");
1704 for (result = dns_dbiterator_first(dbiter);
1705 result == ISC_R_SUCCESS;
1706 result = dns_dbiterator_next(dbiter) ) {
1707 result = dns_dbiterator_current(dbiter, &node, name);
1708 check_dns_dbiterator_current(result);
1709 verifynode(name, node, ISC_FALSE, &rdataset,
1710 ksk_algorithms, bad_algorithms);
1711 dns_db_detachnode(gdb, &node);
1713 dns_dbiterator_destroy(&dbiter);
1715 dns_rdataset_disassociate(&rdataset);
1718 * If we made it this far, we have what we consider a properly signed
1719 * zone. Set the good flag.
1721 for (i = 0; i < 256; i++) {
1722 if (bad_algorithms[i] != 0) {
1724 fprintf(stderr, "The zone is not fully signed "
1725 "for the following algorithms:");
1726 dns_secalg_format(i, algbuf, sizeof(algbuf));
1727 fprintf(stderr, " %s", algbuf);
1732 fprintf(stderr, ".\n");
1733 fatal("DNSSEC completeness test failed.");
1736 if (goodksk || ignore_kskflag) {
1738 * Print the success summary.
1740 fprintf(stderr, "Zone signing complete:\n");
1741 for (i = 0; i < 256; i++) {
1742 if ((ksk_algorithms[i] != 0) ||
1743 (standby_ksk[i] != 0) ||
1744 (revoked_zsk[i] != 0) ||
1745 (zsk_algorithms[i] != 0) ||
1746 (standby_zsk[i] != 0) ||
1747 (revoked_zsk[i] != 0)) {
1748 dns_secalg_format(i, algbuf, sizeof(algbuf));
1749 fprintf(stderr, "Algorithm: %s: KSKs: "
1750 "%u active, %u stand-by, %u revoked\n",
1751 algbuf, ksk_algorithms[i],
1752 standby_ksk[i], revoked_ksk[i]);
1753 fprintf(stderr, "%*sZSKs: "
1754 "%u active, %u %s, %u revoked\n",
1755 (int) strlen(algbuf) + 13, "",
1758 keyset_kskonly ? "present" : "stand-by",
1766 * Sign the apex of the zone.
1767 * Note the origin may not be the first node if there are out of zone
1772 dns_dbnode_t *node = NULL;
1773 dns_fixedname_t fixed;
1775 isc_result_t result;
1777 dns_fixedname_init(&fixed);
1778 name = dns_fixedname_name(&fixed);
1779 result = dns_dbiterator_seek(gdbiter, gorigin);
1780 check_result(result, "dns_dbiterator_seek()");
1781 result = dns_dbiterator_current(gdbiter, &node, name);
1782 check_dns_dbiterator_current(result);
1783 signname(node, name);
1784 dumpnode(name, node);
1785 cleannode(gdb, gversion, node);
1786 dns_db_detachnode(gdb, &node);
1787 result = dns_dbiterator_first(gdbiter);
1788 if (result == ISC_R_NOMORE)
1789 finished = ISC_TRUE;
1790 else if (result != ISC_R_SUCCESS)
1791 fatal("failure iterating database: %s",
1792 isc_result_totext(result));
1796 * Assigns a node to a worker thread. This is protected by the master task's
1800 assignwork(isc_task_t *task, isc_task_t *worker) {
1801 dns_fixedname_t *fname;
1805 dns_rdataset_t nsec;
1806 isc_boolean_t found;
1807 isc_result_t result;
1808 static dns_name_t *zonecut = NULL; /* Protected by namelock. */
1809 static dns_fixedname_t fzonecut; /* Protected by namelock. */
1810 static unsigned int ended = 0; /* Protected by namelock. */
1818 if (ended == ntasks) {
1819 isc_task_detach(&task);
1825 fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
1827 fatal("out of memory");
1828 dns_fixedname_init(fname);
1829 name = dns_fixedname_name(fname);
1833 result = dns_dbiterator_current(gdbiter, &node, name);
1834 check_dns_dbiterator_current(result);
1836 * The origin was handled by signapex().
1838 if (dns_name_equal(name, gorigin)) {
1839 dns_db_detachnode(gdb, &node);
1843 * Sort the zone data from the glue and out-of-zone data.
1844 * For NSEC zones nodes with zone data have NSEC records.
1845 * For NSEC3 zones the NSEC3 nodes are zone data but
1846 * outside of the zone name space. For the rest we need
1847 * to track the bottom of zone cuts.
1848 * Nodes which don't need to be signed are dumped here.
1850 dns_rdataset_init(&nsec);
1851 result = dns_db_findrdataset(gdb, node, gversion,
1852 nsec_datatype, 0, 0,
1854 if (dns_rdataset_isassociated(&nsec))
1855 dns_rdataset_disassociate(&nsec);
1856 if (result == ISC_R_SUCCESS) {
1858 } else if (nsec_datatype == dns_rdatatype_nsec3) {
1859 if (dns_name_issubdomain(name, gorigin) &&
1861 !dns_name_issubdomain(name, zonecut))) {
1862 if (delegation(name, node, NULL)) {
1863 dns_fixedname_init(&fzonecut);
1864 zonecut = dns_fixedname_name(&fzonecut);
1865 dns_name_copy(name, zonecut, NULL);
1866 if (!OPTOUT(nsec3flags) ||
1875 dumpnode(name, node);
1876 dns_db_detachnode(gdb, &node);
1880 result = dns_dbiterator_next(gdbiter);
1881 if (result == ISC_R_NOMORE) {
1882 finished = ISC_TRUE;
1884 } else if (result != ISC_R_SUCCESS)
1885 fatal("failure iterating database: %s",
1886 isc_result_totext(result));
1890 if (ended == ntasks) {
1891 isc_task_detach(&task);
1894 isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
1897 sevent = (sevent_t *)
1898 isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
1899 sign, NULL, sizeof(sevent_t));
1901 fatal("failed to allocate event\n");
1903 sevent->node = node;
1904 sevent->fname = fname;
1905 isc_task_send(worker, ISC_EVENT_PTR(&sevent));
1911 * Start a worker task
1914 startworker(isc_task_t *task, isc_event_t *event) {
1917 worker = (isc_task_t *)event->ev_arg;
1918 assignwork(task, worker);
1919 isc_event_free(&event);
1923 * Write a node to the output file, and restart the worker task.
1926 writenode(isc_task_t *task, isc_event_t *event) {
1928 sevent_t *sevent = (sevent_t *)event;
1930 worker = (isc_task_t *)event->ev_sender;
1931 dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
1932 cleannode(gdb, gversion, sevent->node);
1933 dns_db_detachnode(gdb, &sevent->node);
1934 isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
1935 assignwork(task, worker);
1936 isc_event_free(&event);
1940 * Sign a database node.
1943 sign(isc_task_t *task, isc_event_t *event) {
1944 dns_fixedname_t *fname;
1946 sevent_t *sevent, *wevent;
1948 sevent = (sevent_t *)event;
1949 node = sevent->node;
1950 fname = sevent->fname;
1951 isc_event_free(&event);
1953 signname(node, dns_fixedname_name(fname));
1954 wevent = (sevent_t *)
1955 isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
1956 writenode, NULL, sizeof(sevent_t));
1958 fatal("failed to allocate event\n");
1959 wevent->node = node;
1960 wevent->fname = fname;
1961 isc_task_send(master, ISC_EVENT_PTR(&wevent));
1965 * Update / remove the DS RRset. Preserve RRSIG(DS) if possible.
1968 add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) {
1969 dns_rdataset_t dsset;
1970 dns_rdataset_t sigdsset;
1971 isc_result_t result;
1973 dns_rdataset_init(&dsset);
1974 dns_rdataset_init(&sigdsset);
1975 result = dns_db_findrdataset(gdb, node, gversion,
1977 0, 0, &dsset, &sigdsset);
1978 if (result == ISC_R_SUCCESS) {
1979 dns_rdataset_disassociate(&dsset);
1980 result = dns_db_deleterdataset(gdb, node, gversion,
1981 dns_rdatatype_ds, 0);
1982 check_result(result, "dns_db_deleterdataset");
1985 result = loadds(name, nsttl, &dsset);
1986 if (result == ISC_R_SUCCESS) {
1987 result = dns_db_addrdataset(gdb, node, gversion, 0,
1989 check_result(result, "dns_db_addrdataset");
1990 dns_rdataset_disassociate(&dsset);
1991 if (dns_rdataset_isassociated(&sigdsset))
1992 dns_rdataset_disassociate(&sigdsset);
1993 } else if (dns_rdataset_isassociated(&sigdsset)) {
1994 result = dns_db_deleterdataset(gdb, node, gversion,
1995 dns_rdatatype_rrsig,
1997 check_result(result, "dns_db_deleterdataset");
1998 dns_rdataset_disassociate(&sigdsset);
2003 * Remove records of the given type and their signatures.
2006 remove_records(dns_dbnode_t *node, dns_rdatatype_t which) {
2007 isc_result_t result;
2008 dns_rdatatype_t type, covers;
2009 dns_rdatasetiter_t *rdsiter = NULL;
2010 dns_rdataset_t rdataset;
2012 dns_rdataset_init(&rdataset);
2015 * Delete any records of the given type at the apex.
2017 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
2018 check_result(result, "dns_db_allrdatasets()");
2019 for (result = dns_rdatasetiter_first(rdsiter);
2020 result == ISC_R_SUCCESS;
2021 result = dns_rdatasetiter_next(rdsiter)) {
2022 dns_rdatasetiter_current(rdsiter, &rdataset);
2023 type = rdataset.type;
2024 covers = rdataset.covers;
2025 dns_rdataset_disassociate(&rdataset);
2026 if (type == which || covers == which) {
2027 if (which == dns_rdatatype_nsec && !update_chain)
2028 fatal("Zone contains NSEC records. Use -u "
2029 "to update to NSEC3.");
2030 if (which == dns_rdatatype_nsec3param && !update_chain)
2031 fatal("Zone contains NSEC3 chains. Use -u "
2032 "to update to NSEC.");
2033 result = dns_db_deleterdataset(gdb, node, gversion,
2035 check_result(result, "dns_db_deleterdataset()");
2039 dns_rdatasetiter_destroy(&rdsiter);
2043 * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records.
2047 dns_dbiterator_t *dbiter = NULL;
2048 dns_dbnode_t *node = NULL, *nextnode = NULL;
2049 dns_fixedname_t fname, fnextname, fzonecut;
2050 dns_name_t *name, *nextname, *zonecut;
2051 dns_rdataset_t rdataset;
2052 dns_rdatasetiter_t *rdsiter = NULL;
2053 dns_rdatatype_t type, covers;
2054 isc_boolean_t done = ISC_FALSE;
2055 isc_result_t result;
2056 isc_uint32_t nsttl = 0;
2058 dns_rdataset_init(&rdataset);
2059 dns_fixedname_init(&fname);
2060 name = dns_fixedname_name(&fname);
2061 dns_fixedname_init(&fnextname);
2062 nextname = dns_fixedname_name(&fnextname);
2063 dns_fixedname_init(&fzonecut);
2067 * Remove any NSEC3 chains.
2069 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
2070 check_result(result, "dns_db_createiterator()");
2071 for (result = dns_dbiterator_first(dbiter);
2072 result == ISC_R_SUCCESS;
2073 result = dns_dbiterator_next(dbiter)) {
2074 result = dns_dbiterator_current(dbiter, &node, name);
2075 check_dns_dbiterator_current(result);
2076 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
2077 check_result(result, "dns_db_allrdatasets()");
2078 for (result = dns_rdatasetiter_first(rdsiter);
2079 result == ISC_R_SUCCESS;
2080 result = dns_rdatasetiter_next(rdsiter)) {
2081 dns_rdatasetiter_current(rdsiter, &rdataset);
2082 type = rdataset.type;
2083 covers = rdataset.covers;
2084 dns_rdataset_disassociate(&rdataset);
2085 result = dns_db_deleterdataset(gdb, node, gversion,
2087 check_result(result,
2088 "dns_db_deleterdataset(nsec3param/rrsig)");
2090 dns_rdatasetiter_destroy(&rdsiter);
2091 dns_db_detachnode(gdb, &node);
2093 dns_dbiterator_destroy(&dbiter);
2095 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2096 check_result(result, "dns_db_createiterator()");
2098 result = dns_dbiterator_first(dbiter);
2099 check_result(result, "dns_dbiterator_first()");
2102 result = dns_dbiterator_current(dbiter, &node, name);
2103 check_dns_dbiterator_current(result);
2105 * Skip out-of-zone records.
2107 if (!dns_name_issubdomain(name, gorigin)) {
2108 result = dns_dbiterator_next(dbiter);
2109 if (result == ISC_R_NOMORE)
2112 check_result(result, "dns_dbiterator_next()");
2113 dns_db_detachnode(gdb, &node);
2117 if (dns_name_equal(name, gorigin))
2118 remove_records(node, dns_rdatatype_nsec3param);
2120 if (delegation(name, node, &nsttl)) {
2121 zonecut = dns_fixedname_name(&fzonecut);
2122 dns_name_copy(name, zonecut, NULL);
2124 add_ds(name, node, nsttl);
2126 result = dns_dbiterator_next(dbiter);
2128 while (result == ISC_R_SUCCESS) {
2129 isc_boolean_t active = ISC_FALSE;
2130 result = dns_dbiterator_current(dbiter, &nextnode,
2132 check_dns_dbiterator_current(result);
2133 active = active_node(nextnode);
2135 dns_db_detachnode(gdb, &nextnode);
2136 result = dns_dbiterator_next(dbiter);
2139 if (!dns_name_issubdomain(nextname, gorigin) ||
2141 dns_name_issubdomain(nextname, zonecut)))
2143 dns_db_detachnode(gdb, &nextnode);
2144 result = dns_dbiterator_next(dbiter);
2147 dns_db_detachnode(gdb, &nextnode);
2150 if (result == ISC_R_NOMORE) {
2151 dns_name_clone(gorigin, nextname);
2153 } else if (result != ISC_R_SUCCESS)
2154 fatal("iterating through the database failed: %s",
2155 isc_result_totext(result));
2156 dns_dbiterator_pause(dbiter);
2157 result = dns_nsec_build(gdb, gversion, node, nextname,
2159 check_result(result, "dns_nsec_build()");
2160 dns_db_detachnode(gdb, &node);
2163 dns_dbiterator_destroy(&dbiter);
2167 addnsec3param(const unsigned char *salt, size_t salt_length,
2168 unsigned int iterations)
2170 dns_dbnode_t *node = NULL;
2171 dns_rdata_nsec3param_t nsec3param;
2172 unsigned char nsec3parambuf[5 + 255];
2173 dns_rdatalist_t rdatalist;
2174 dns_rdataset_t rdataset;
2175 dns_rdata_t rdata = DNS_RDATA_INIT;
2177 isc_result_t result;
2179 dns_rdataset_init(&rdataset);
2181 nsec3param.common.rdclass = gclass;
2182 nsec3param.common.rdtype = dns_rdatatype_nsec3param;
2183 ISC_LINK_INIT(&nsec3param.common, link);
2184 nsec3param.mctx = NULL;
2185 nsec3param.flags = 0;
2186 nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1;
2187 nsec3param.iterations = iterations;
2188 nsec3param.salt_length = salt_length;
2189 DE_CONST(salt, nsec3param.salt);
2191 isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf));
2192 result = dns_rdata_fromstruct(&rdata, gclass,
2193 dns_rdatatype_nsec3param,
2195 rdatalist.rdclass = rdata.rdclass;
2196 rdatalist.type = rdata.type;
2197 rdatalist.covers = 0;
2199 ISC_LIST_INIT(rdatalist.rdata);
2200 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
2201 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
2202 check_result(result, "dns_rdatalist_tordataset()");
2204 result = dns_db_findnode(gdb, gorigin, ISC_TRUE, &node);
2205 check_result(result, "dns_db_find(gorigin)");
2208 * Delete any current NSEC3PARAM records.
2210 result = dns_db_deleterdataset(gdb, node, gversion,
2211 dns_rdatatype_nsec3param, 0);
2212 if (result == DNS_R_UNCHANGED)
2213 result = ISC_R_SUCCESS;
2214 check_result(result, "dddnsec3param: dns_db_deleterdataset()");
2216 result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset,
2217 DNS_DBADD_MERGE, NULL);
2218 if (result == DNS_R_UNCHANGED)
2219 result = ISC_R_SUCCESS;
2220 check_result(result, "addnsec3param: dns_db_addrdataset()");
2221 dns_db_detachnode(gdb, &node);
2225 addnsec3(dns_name_t *name, dns_dbnode_t *node,
2226 const unsigned char *salt, size_t salt_length,
2227 unsigned int iterations, hashlist_t *hashlist,
2230 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
2231 const unsigned char *nexthash;
2232 unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE];
2233 dns_fixedname_t hashname;
2234 dns_rdatalist_t rdatalist;
2235 dns_rdataset_t rdataset;
2236 dns_rdata_t rdata = DNS_RDATA_INIT;
2237 isc_result_t result;
2238 dns_dbnode_t *nsec3node = NULL;
2239 char namebuf[DNS_NAME_FORMATSIZE];
2242 dns_name_format(name, namebuf, sizeof(namebuf));
2244 dns_fixedname_init(&hashname);
2245 dns_rdataset_init(&rdataset);
2247 dns_name_downcase(name, name, NULL);
2248 result = dns_nsec3_hashname(&hashname, hash, &hash_length,
2249 name, gorigin, dns_hash_sha1, iterations,
2251 check_result(result, "addnsec3: dns_nsec3_hashname()");
2252 nexthash = hashlist_findnext(hashlist, hash);
2253 result = dns_nsec3_buildrdata(gdb, gversion, node,
2255 DNS_NSEC3_UNKNOWNALG : dns_hash_sha1,
2256 nsec3flags, iterations,
2258 nexthash, ISC_SHA1_DIGESTLENGTH,
2259 nsec3buffer, &rdata);
2260 check_result(result, "addnsec3: dns_nsec3_buildrdata()");
2261 rdatalist.rdclass = rdata.rdclass;
2262 rdatalist.type = rdata.type;
2263 rdatalist.covers = 0;
2264 rdatalist.ttl = ttl;
2265 ISC_LIST_INIT(rdatalist.rdata);
2266 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
2267 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
2268 check_result(result, "dns_rdatalist_tordataset()");
2269 result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname),
2270 ISC_TRUE, &nsec3node);
2271 check_result(result, "addnsec3: dns_db_findnode()");
2272 result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset,
2274 if (result == DNS_R_UNCHANGED)
2275 result = ISC_R_SUCCESS;
2276 check_result(result, "addnsec3: dns_db_addrdataset()");
2277 dns_db_detachnode(gdb, &nsec3node);
2281 * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list.
2283 * Extract the hash from the first label of 'name' then see if it
2284 * is in hashlist. If 'name' is not in the hashlist then delete the
2285 * any NSEC3 records which have the same parameters as the chain we
2288 * XXXMPA Should we also check that it of the form <hash>.<origin>?
2291 nsec3clean(dns_name_t *name, dns_dbnode_t *node,
2292 unsigned int hashalg, unsigned int iterations,
2293 const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
2296 dns_rdata_nsec3_t nsec3;
2297 dns_rdata_t rdata, delrdata;
2298 dns_rdatalist_t rdatalist;
2299 dns_rdataset_t rdataset, delrdataset;
2300 isc_boolean_t delete_rrsigs = ISC_FALSE;
2301 isc_buffer_t target;
2302 isc_result_t result;
2303 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
2304 isc_boolean_t exists;
2307 * Get the first label.
2309 dns_name_getlabel(name, 0, &label);
2312 * We want just the label contents.
2314 isc_region_consume(&label, 1);
2317 * Decode base32hex string.
2319 isc_buffer_init(&target, hash, sizeof(hash) - 1);
2320 result = isc_base32hex_decoderegion(&label, &target);
2321 if (result != ISC_R_SUCCESS)
2324 hash[isc_buffer_usedlength(&target)] = 0;
2326 exists = hashlist_exists(hashlist, hash);
2329 * Verify that the NSEC3 parameters match the current ones
2330 * otherwise we are dealing with a different NSEC3 chain.
2332 dns_rdataset_init(&rdataset);
2333 dns_rdataset_init(&delrdataset);
2335 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3,
2336 0, 0, &rdataset, NULL);
2337 if (result != ISC_R_SUCCESS)
2341 * Delete any NSEC3 records which are not part of the current
2344 for (result = dns_rdataset_first(&rdataset);
2345 result == ISC_R_SUCCESS;
2346 result = dns_rdataset_next(&rdataset)) {
2347 dns_rdata_init(&rdata);
2348 dns_rdataset_current(&rdataset, &rdata);
2349 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
2350 check_result(result, "dns_rdata_tostruct");
2351 if (exists && nsec3.hash == hashalg &&
2352 nsec3.iterations == iterations &&
2353 nsec3.salt_length == salt_length &&
2354 !memcmp(nsec3.salt, salt, salt_length))
2356 rdatalist.rdclass = rdata.rdclass;
2357 rdatalist.type = rdata.type;
2358 rdatalist.covers = 0;
2359 rdatalist.ttl = rdataset.ttl;
2360 ISC_LIST_INIT(rdatalist.rdata);
2361 dns_rdata_init(&delrdata);
2362 dns_rdata_clone(&rdata, &delrdata);
2363 ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link);
2364 result = dns_rdatalist_tordataset(&rdatalist, &delrdataset);
2365 check_result(result, "dns_rdatalist_tordataset()");
2366 result = dns_db_subtractrdataset(gdb, node, gversion,
2367 &delrdataset, 0, NULL);
2368 dns_rdataset_disassociate(&delrdataset);
2369 if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET)
2370 check_result(result, "dns_db_subtractrdataset(NSEC3)");
2371 delete_rrsigs = ISC_TRUE;
2373 dns_rdataset_disassociate(&rdataset);
2374 if (result != ISC_R_NOMORE)
2375 check_result(result, "dns_rdataset_first/next");
2380 * Delete the NSEC3 RRSIGs
2382 result = dns_db_deleterdataset(gdb, node, gversion,
2383 dns_rdatatype_rrsig,
2384 dns_rdatatype_nsec3);
2385 if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
2386 check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))");
2390 rrset_remove_duplicates(dns_name_t *name, dns_rdataset_t *rdataset,
2393 dns_difftuple_t *tuple = NULL;
2394 isc_result_t result;
2395 unsigned int count1 = 0;
2396 dns_rdataset_t tmprdataset;
2398 dns_rdataset_init(&tmprdataset);
2399 for (result = dns_rdataset_first(rdataset);
2400 result == ISC_R_SUCCESS;
2401 result = dns_rdataset_next(rdataset)) {
2402 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2403 unsigned int count2 = 0;
2406 dns_rdataset_current(rdataset, &rdata1);
2407 dns_rdataset_clone(rdataset, &tmprdataset);
2408 for (result = dns_rdataset_first(&tmprdataset);
2409 result == ISC_R_SUCCESS;
2410 result = dns_rdataset_next(&tmprdataset)) {
2411 dns_rdata_t rdata2 = DNS_RDATA_INIT;
2413 if (count1 >= count2)
2415 dns_rdataset_current(&tmprdataset, &rdata2);
2416 if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2417 result = dns_difftuple_create(mctx,
2422 check_result(result, "dns_difftuple_create");
2423 dns_diff_append(diff, &tuple);
2426 dns_rdataset_disassociate(&tmprdataset);
2431 remove_duplicates(void) {
2432 isc_result_t result;
2433 dns_dbiterator_t *dbiter = NULL;
2434 dns_rdatasetiter_t *rdsiter = NULL;
2436 dns_dbnode_t *node = NULL;
2437 dns_rdataset_t rdataset;
2438 dns_fixedname_t fname;
2441 dns_diff_init(mctx, &diff);
2442 dns_fixedname_init(&fname);
2443 name = dns_fixedname_name(&fname);
2444 dns_rdataset_init(&rdataset);
2446 result = dns_db_createiterator(gdb, 0, &dbiter);
2447 check_result(result, "dns_db_createiterator()");
2449 for (result = dns_dbiterator_first(dbiter);
2450 result == ISC_R_SUCCESS;
2451 result = dns_dbiterator_next(dbiter)) {
2453 result = dns_dbiterator_current(dbiter, &node, name);
2454 check_dns_dbiterator_current(result);
2455 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
2456 check_result(result, "dns_db_allrdatasets()");
2457 for (result = dns_rdatasetiter_first(rdsiter);
2458 result == ISC_R_SUCCESS;
2459 result = dns_rdatasetiter_next(rdsiter)) {
2460 dns_rdatasetiter_current(rdsiter, &rdataset);
2461 rrset_remove_duplicates(name, &rdataset, &diff);
2462 dns_rdataset_disassociate(&rdataset);
2464 if (result != ISC_R_NOMORE)
2465 fatal("rdatasets iteration failed.");
2466 dns_rdatasetiter_destroy(&rdsiter);
2467 dns_db_detachnode(gdb, &node);
2469 if (result != ISC_R_NOMORE)
2470 fatal("zone iteration failed.");
2472 if (!ISC_LIST_EMPTY(diff.tuples)) {
2473 result = dns_diff_applysilently(&diff, gdb, gversion);
2474 check_result(result, "dns_diff_applysilently");
2476 dns_diff_clear(&diff);
2477 dns_dbiterator_destroy(&dbiter);
2481 * Generate NSEC3 records for the zone.
2484 nsec3ify(unsigned int hashalg, unsigned int iterations,
2485 const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
2487 dns_dbiterator_t *dbiter = NULL;
2488 dns_dbnode_t *node = NULL, *nextnode = NULL;
2489 dns_fixedname_t fname, fnextname, fzonecut;
2490 dns_name_t *name, *nextname, *zonecut;
2491 dns_rdataset_t rdataset;
2493 isc_boolean_t active;
2494 isc_boolean_t done = ISC_FALSE;
2495 isc_result_t result;
2496 isc_uint32_t nsttl = 0;
2497 unsigned int count, nlabels;
2499 dns_rdataset_init(&rdataset);
2500 dns_fixedname_init(&fname);
2501 name = dns_fixedname_name(&fname);
2502 dns_fixedname_init(&fnextname);
2503 nextname = dns_fixedname_name(&fnextname);
2504 dns_fixedname_init(&fzonecut);
2508 * Walk the zone generating the hash names.
2510 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2511 check_result(result, "dns_db_createiterator()");
2513 result = dns_dbiterator_first(dbiter);
2514 check_result(result, "dns_dbiterator_first()");
2517 result = dns_dbiterator_current(dbiter, &node, name);
2518 check_dns_dbiterator_current(result);
2520 * Skip out-of-zone records.
2522 if (!dns_name_issubdomain(name, gorigin)) {
2523 result = dns_dbiterator_next(dbiter);
2524 if (result == ISC_R_NOMORE)
2527 check_result(result, "dns_dbiterator_next()");
2528 dns_db_detachnode(gdb, &node);
2532 if (dns_name_equal(name, gorigin))
2533 remove_records(node, dns_rdatatype_nsec);
2535 result = dns_dbiterator_next(dbiter);
2537 while (result == ISC_R_SUCCESS) {
2538 result = dns_dbiterator_current(dbiter, &nextnode,
2540 check_dns_dbiterator_current(result);
2541 active = active_node(nextnode);
2543 dns_db_detachnode(gdb, &nextnode);
2544 result = dns_dbiterator_next(dbiter);
2547 if (!dns_name_issubdomain(nextname, gorigin) ||
2549 dns_name_issubdomain(nextname, zonecut))) {
2550 dns_db_detachnode(gdb, &nextnode);
2551 result = dns_dbiterator_next(dbiter);
2554 if (delegation(nextname, nextnode, &nsttl)) {
2555 zonecut = dns_fixedname_name(&fzonecut);
2556 dns_name_copy(nextname, zonecut, NULL);
2558 add_ds(nextname, nextnode, nsttl);
2559 if (OPTOUT(nsec3flags) &&
2560 !secure(nextname, nextnode)) {
2561 dns_db_detachnode(gdb, &nextnode);
2562 result = dns_dbiterator_next(dbiter);
2566 dns_db_detachnode(gdb, &nextnode);
2569 if (result == ISC_R_NOMORE) {
2570 dns_name_copy(gorigin, nextname, NULL);
2572 } else if (result != ISC_R_SUCCESS)
2573 fatal("iterating through the database failed: %s",
2574 isc_result_totext(result));
2575 dns_name_downcase(name, name, NULL);
2576 hashlist_add_dns_name(hashlist, name, hashalg, iterations,
2577 salt, salt_length, ISC_FALSE);
2578 dns_db_detachnode(gdb, &node);
2580 * Add hashs for empty nodes. Use closest encloser logic.
2581 * The closest encloser either has data or is a empty
2582 * node for another <name,nextname> span so we don't add
2583 * it here. Empty labels on nextname are within the span.
2585 dns_name_downcase(nextname, nextname, NULL);
2586 dns_name_fullcompare(name, nextname, &order, &nlabels);
2587 addnowildcardhash(hashlist, name, hashalg, iterations,
2589 count = dns_name_countlabels(nextname);
2590 while (count > nlabels + 1) {
2592 dns_name_split(nextname, count, NULL, nextname);
2593 hashlist_add_dns_name(hashlist, nextname, hashalg,
2594 iterations, salt, salt_length,
2596 addnowildcardhash(hashlist, nextname, hashalg,
2597 iterations, salt, salt_length);
2600 dns_dbiterator_destroy(&dbiter);
2603 * We have all the hashes now so we can sort them.
2605 hashlist_sort(hashlist);
2608 * Check for duplicate hashes. If found the salt needs to
2611 if (hashlist_hasdup(hashlist))
2612 fatal("Duplicate hash detected. Pick a different salt.");
2615 * Generate the nsec3 records.
2620 addnsec3param(salt, salt_length, iterations);
2623 * Clean out NSEC3 records which don't match this chain.
2625 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
2626 check_result(result, "dns_db_createiterator()");
2628 for (result = dns_dbiterator_first(dbiter);
2629 result == ISC_R_SUCCESS;
2630 result = dns_dbiterator_next(dbiter)) {
2631 result = dns_dbiterator_current(dbiter, &node, name);
2632 check_dns_dbiterator_current(result);
2633 nsec3clean(name, node, hashalg, iterations, salt, salt_length,
2635 dns_db_detachnode(gdb, &node);
2637 dns_dbiterator_destroy(&dbiter);
2640 * Generate / complete the new chain.
2642 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2643 check_result(result, "dns_db_createiterator()");
2645 result = dns_dbiterator_first(dbiter);
2646 check_result(result, "dns_dbiterator_first()");
2649 result = dns_dbiterator_current(dbiter, &node, name);
2650 check_dns_dbiterator_current(result);
2652 * Skip out-of-zone records.
2654 if (!dns_name_issubdomain(name, gorigin)) {
2655 result = dns_dbiterator_next(dbiter);
2656 if (result == ISC_R_NOMORE)
2659 check_result(result, "dns_dbiterator_next()");
2660 dns_db_detachnode(gdb, &node);
2663 result = dns_dbiterator_next(dbiter);
2665 while (result == ISC_R_SUCCESS) {
2666 result = dns_dbiterator_current(dbiter, &nextnode,
2668 check_dns_dbiterator_current(result);
2669 active = active_node(nextnode);
2671 dns_db_detachnode(gdb, &nextnode);
2672 result = dns_dbiterator_next(dbiter);
2675 if (!dns_name_issubdomain(nextname, gorigin) ||
2677 dns_name_issubdomain(nextname, zonecut))) {
2678 dns_db_detachnode(gdb, &nextnode);
2679 result = dns_dbiterator_next(dbiter);
2682 if (delegation(nextname, nextnode, NULL)) {
2683 zonecut = dns_fixedname_name(&fzonecut);
2684 dns_name_copy(nextname, zonecut, NULL);
2685 if (OPTOUT(nsec3flags) &&
2686 !secure(nextname, nextnode)) {
2687 dns_db_detachnode(gdb, &nextnode);
2688 result = dns_dbiterator_next(dbiter);
2692 dns_db_detachnode(gdb, &nextnode);
2695 if (result == ISC_R_NOMORE) {
2696 dns_name_copy(gorigin, nextname, NULL);
2698 } else if (result != ISC_R_SUCCESS)
2699 fatal("iterating through the database failed: %s",
2700 isc_result_totext(result));
2702 * We need to pause here to release the lock on the database.
2704 dns_dbiterator_pause(dbiter);
2705 addnsec3(name, node, salt, salt_length, iterations,
2706 hashlist, zone_soa_min_ttl);
2707 dns_db_detachnode(gdb, &node);
2709 * Add NSEC3's for empty nodes. Use closest encloser logic.
2711 dns_name_fullcompare(name, nextname, &order, &nlabels);
2712 count = dns_name_countlabels(nextname);
2713 while (count > nlabels + 1) {
2715 dns_name_split(nextname, count, NULL, nextname);
2716 addnsec3(nextname, NULL, salt, salt_length,
2717 iterations, hashlist, zone_soa_min_ttl);
2720 dns_dbiterator_destroy(&dbiter);
2724 * Load the zone file from disk
2727 loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
2730 dns_fixedname_t fname;
2732 isc_result_t result;
2734 len = strlen(origin);
2735 isc_buffer_init(&b, origin, len);
2736 isc_buffer_add(&b, len);
2738 dns_fixedname_init(&fname);
2739 name = dns_fixedname_name(&fname);
2740 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
2741 if (result != ISC_R_SUCCESS)
2742 fatal("failed converting name '%s' to dns format: %s",
2743 origin, isc_result_totext(result));
2745 result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
2746 rdclass, 0, NULL, db);
2747 check_result(result, "dns_db_create()");
2749 result = dns_db_load2(*db, file, inputformat);
2750 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
2751 fatal("failed loading zone from '%s': %s",
2752 file, isc_result_totext(result));
2756 * Finds all public zone keys in the zone, and attempts to load the
2757 * private keys from disk.
2760 loadzonekeys(isc_boolean_t preserve_keys, isc_boolean_t load_public) {
2762 dns_dbversion_t *currentversion = NULL;
2763 isc_result_t result;
2764 dns_rdataset_t rdataset, keysigs, soasigs;
2767 result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node);
2768 if (result != ISC_R_SUCCESS)
2769 fatal("failed to find the zone's origin: %s",
2770 isc_result_totext(result));
2772 dns_db_currentversion(gdb, ¤tversion);
2774 dns_rdataset_init(&rdataset);
2775 dns_rdataset_init(&soasigs);
2776 dns_rdataset_init(&keysigs);
2778 /* Make note of the keys which signed the SOA, if any */
2779 result = dns_db_findrdataset(gdb, node, currentversion,
2780 dns_rdatatype_soa, 0, 0,
2781 &rdataset, &soasigs);
2782 if (result != ISC_R_SUCCESS)
2785 /* Preserve the TTL of the DNSKEY RRset, if any */
2786 dns_rdataset_disassociate(&rdataset);
2787 result = dns_db_findrdataset(gdb, node, currentversion,
2788 dns_rdatatype_dnskey, 0, 0,
2789 &rdataset, &keysigs);
2791 if (result != ISC_R_SUCCESS)
2794 if (set_keyttl && keyttl != rdataset.ttl) {
2795 fprintf(stderr, "User-specified TTL (%d) conflicts "
2796 "with existing DNSKEY RRset TTL.\n",
2798 fprintf(stderr, "Imported keys will use the RRSet "
2799 "TTL (%d) instead.\n",
2802 keyttl = rdataset.ttl;
2804 /* Load keys corresponding to the existing DNSKEY RRset */
2805 result = dns_dnssec_keylistfromrdataset(gorigin, directory, mctx,
2806 &rdataset, &keysigs, &soasigs,
2807 preserve_keys, load_public,
2809 if (result != ISC_R_SUCCESS)
2810 fatal("failed to load the zone keys: %s",
2811 isc_result_totext(result));
2814 if (dns_rdataset_isassociated(&rdataset))
2815 dns_rdataset_disassociate(&rdataset);
2816 if (dns_rdataset_isassociated(&keysigs))
2817 dns_rdataset_disassociate(&keysigs);
2818 if (dns_rdataset_isassociated(&soasigs))
2819 dns_rdataset_disassociate(&soasigs);
2820 dns_db_detachnode(gdb, &node);
2821 dns_db_closeversion(gdb, ¤tversion, ISC_FALSE);
2825 loadexplicitkeys(char *keyfiles[], int n, isc_boolean_t setksk) {
2826 isc_result_t result;
2829 for (i = 0; i < n; i++) {
2830 dns_dnsseckey_t *key = NULL;
2831 dst_key_t *newkey = NULL;
2833 result = dst_key_fromnamedfile(keyfiles[i], directory,
2837 if (result != ISC_R_SUCCESS)
2838 fatal("cannot load dnskey %s: %s", keyfiles[i],
2839 isc_result_totext(result));
2841 if (!dns_name_equal(gorigin, dst_key_name(newkey)))
2842 fatal("key %s not at origin\n", keyfiles[i]);
2844 if (!dst_key_isprivate(newkey))
2845 fatal("cannot sign zone with non-private dnskey %s",
2848 /* Skip any duplicates */
2849 for (key = ISC_LIST_HEAD(keylist);
2851 key = ISC_LIST_NEXT(key, link)) {
2852 if (dst_key_id(key->key) == dst_key_id(newkey) &&
2853 dst_key_alg(key->key) == dst_key_alg(newkey))
2858 /* We haven't seen this key before */
2859 dns_dnsseckey_create(mctx, &newkey, &key);
2860 ISC_LIST_APPEND(keylist, key, link);
2861 key->source = dns_keysource_user;
2863 dst_key_free(&key->key);
2867 key->force_publish = ISC_TRUE;
2868 key->force_sign = ISC_TRUE;
2871 key->ksk = ISC_TRUE;
2876 report(const char *format, ...) {
2878 va_start(args, format);
2879 vfprintf(stderr, format, args);
2885 build_final_keylist() {
2886 isc_result_t result;
2887 dns_dbversion_t *ver = NULL;
2889 dns_dnsseckeylist_t matchkeys;
2890 char name[DNS_NAME_FORMATSIZE];
2893 * Find keys that match this zone in the key repository.
2895 ISC_LIST_INIT(matchkeys);
2896 result = dns_dnssec_findmatchingkeys(gorigin, directory,
2898 if (result == ISC_R_NOTFOUND)
2899 result = ISC_R_SUCCESS;
2900 check_result(result, "dns_dnssec_findmatchingkeys");
2902 result = dns_db_newversion(gdb, &ver);
2903 check_result(result, "dns_db_newversion");
2905 dns_diff_init(mctx, &diff);
2908 * Update keylist with information from from the key repository.
2910 dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl,
2911 &diff, ignore_kskflag, mctx, report);
2913 dns_name_format(gorigin, name, sizeof(name));
2915 result = dns_diff_applysilently(&diff, gdb, ver);
2916 if (result != ISC_R_SUCCESS)
2917 fatal("failed to update DNSKEY RRset at node '%s': %s",
2918 name, isc_result_totext(result));
2920 dns_db_closeversion(gdb, &ver, ISC_TRUE);
2922 dns_diff_clear(&diff);
2926 warnifallksk(dns_db_t *db) {
2927 dns_dbversion_t *currentversion = NULL;
2928 dns_dbnode_t *node = NULL;
2929 dns_rdataset_t rdataset;
2930 dns_rdata_t rdata = DNS_RDATA_INIT;
2931 isc_result_t result;
2932 dns_rdata_dnskey_t dnskey;
2933 isc_boolean_t have_non_ksk = ISC_FALSE;
2935 dns_db_currentversion(db, ¤tversion);
2937 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
2938 if (result != ISC_R_SUCCESS)
2939 fatal("failed to find the zone's origin: %s",
2940 isc_result_totext(result));
2942 dns_rdataset_init(&rdataset);
2943 result = dns_db_findrdataset(db, node, currentversion,
2944 dns_rdatatype_dnskey, 0, 0, &rdataset,
2946 if (result != ISC_R_SUCCESS)
2947 fatal("failed to find keys at the zone apex: %s",
2948 isc_result_totext(result));
2949 result = dns_rdataset_first(&rdataset);
2950 check_result(result, "dns_rdataset_first");
2951 while (result == ISC_R_SUCCESS) {
2952 dns_rdata_reset(&rdata);
2953 dns_rdataset_current(&rdataset, &rdata);
2954 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2955 check_result(result, "dns_rdata_tostruct");
2956 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
2957 have_non_ksk = ISC_TRUE;
2958 result = ISC_R_NOMORE;
2960 result = dns_rdataset_next(&rdataset);
2961 dns_rdata_freestruct(&dnskey);
2963 dns_rdataset_disassociate(&rdataset);
2964 dns_db_detachnode(db, &node);
2965 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
2966 if (!have_non_ksk && !ignore_kskflag) {
2967 if (disable_zone_check)
2968 fprintf(stderr, "%s: warning: No non-KSK DNSKEY found; "
2969 "supply a ZSK or use '-z'.\n",
2972 fatal("No non-KSK DNSKEY found; "
2973 "supply a ZSK or use '-z'.");
2978 set_nsec3params(isc_boolean_t update_chain, isc_boolean_t set_salt,
2979 isc_boolean_t set_optout, isc_boolean_t set_iter)
2981 isc_result_t result;
2982 dns_dbversion_t *ver = NULL;
2983 dns_dbnode_t *node = NULL;
2984 dns_rdataset_t rdataset;
2985 dns_rdata_t rdata = DNS_RDATA_INIT;
2986 dns_rdata_nsec3_t nsec3;
2987 dns_fixedname_t fname;
2988 dns_name_t *hashname;
2989 unsigned char orig_salt[256];
2990 size_t orig_saltlen;
2991 dns_hash_t orig_hash;
2992 isc_uint16_t orig_iter;
2994 dns_db_currentversion(gdb, &ver);
2995 dns_rdataset_init(&rdataset);
2997 orig_saltlen = sizeof(orig_salt);
2998 result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL,
2999 &orig_iter, orig_salt,
3001 if (result != ISC_R_SUCCESS)
3004 nsec_datatype = dns_rdatatype_nsec3;
3006 if (!update_chain && set_salt) {
3007 if (salt_length != orig_saltlen ||
3008 memcmp(saltbuf, orig_salt, salt_length) != 0)
3009 fatal("An NSEC3 chain exists with a different salt. "
3010 "Use -u to update it.");
3011 } else if (!set_salt) {
3012 salt_length = orig_saltlen;
3013 memcpy(saltbuf, orig_salt, orig_saltlen);
3017 if (!update_chain && set_iter) {
3018 if (nsec3iter != orig_iter)
3019 fatal("An NSEC3 chain exists with different "
3020 "iterations. Use -u to update it.");
3021 } else if (!set_iter)
3022 nsec3iter = orig_iter;
3025 * Find an NSEC3 record to get the current OPTOUT value.
3026 * (This assumes all NSEC3 records agree.)
3029 dns_fixedname_init(&fname);
3030 hashname = dns_fixedname_name(&fname);
3031 result = dns_nsec3_hashname(&fname, NULL, NULL,
3032 gorigin, gorigin, dns_hash_sha1,
3033 orig_iter, orig_salt, orig_saltlen);
3034 check_result(result, "dns_nsec3_hashname");
3036 result = dns_db_findnsec3node(gdb, hashname, ISC_FALSE, &node);
3037 if (result != ISC_R_SUCCESS)
3040 result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3,
3041 0, 0, &rdataset, NULL);
3042 if (result != ISC_R_SUCCESS)
3045 result = dns_rdataset_first(&rdataset);
3046 check_result(result, "dns_rdataset_first");
3047 dns_rdataset_current(&rdataset, &rdata);
3048 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
3049 check_result(result, "dns_rdata_tostruct");
3051 if (!update_chain && set_optout) {
3052 if (nsec3flags != nsec3.flags)
3053 fatal("An NSEC3 chain exists with%s OPTOUT. "
3054 "Use -u -%s to %s it.",
3055 OPTOUT(nsec3.flags) ? "" : "out",
3056 OPTOUT(nsec3.flags) ? "AA" : "A",
3057 OPTOUT(nsec3.flags) ? "clear" : "set");
3058 } else if (!set_optout)
3059 nsec3flags = nsec3.flags;
3061 dns_rdata_freestruct(&nsec3);
3064 if (dns_rdataset_isassociated(&rdataset))
3065 dns_rdataset_disassociate(&rdataset);
3067 dns_db_detachnode(gdb, &node);
3068 dns_db_closeversion(gdb, &ver, ISC_FALSE);
3072 writeset(const char *prefix, dns_rdatatype_t type) {
3074 char namestr[DNS_NAME_FORMATSIZE];
3075 dns_db_t *db = NULL;
3076 dns_dbversion_t *version = NULL;
3078 dns_difftuple_t *tuple = NULL;
3079 dns_fixedname_t fixed;
3081 dns_rdata_t rdata, ds;
3082 isc_boolean_t have_ksk = ISC_FALSE;
3083 isc_boolean_t have_non_ksk = ISC_FALSE;
3085 isc_buffer_t namebuf;
3087 isc_result_t result;
3088 dns_dnsseckey_t *key, *tmpkey;
3089 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
3090 unsigned char keybuf[DST_KEY_MAXSIZE];
3091 unsigned int filenamelen;
3092 const dns_master_style_t *style =
3093 (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
3095 isc_buffer_init(&namebuf, namestr, sizeof(namestr));
3096 result = dns_name_tofilenametext(gorigin, ISC_FALSE, &namebuf);
3097 check_result(result, "dns_name_tofilenametext");
3098 isc_buffer_putuint8(&namebuf, 0);
3099 filenamelen = strlen(prefix) + strlen(namestr);
3101 filenamelen += strlen(dsdir) + 1;
3102 filename = isc_mem_get(mctx, filenamelen + 1);
3103 if (filename == NULL)
3104 fatal("out of memory");
3106 sprintf(filename, "%s/", dsdir);
3109 strcat(filename, prefix);
3110 strcat(filename, namestr);
3112 dns_diff_init(mctx, &diff);
3114 if (type == dns_rdatatype_dlv) {
3116 unsigned int labels;
3118 dns_name_init(&tname, NULL);
3119 dns_fixedname_init(&fixed);
3120 name = dns_fixedname_name(&fixed);
3121 labels = dns_name_countlabels(gorigin);
3122 dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
3123 result = dns_name_concatenate(&tname, dlv, name, NULL);
3124 check_result(result, "dns_name_concatenate");
3128 for (key = ISC_LIST_HEAD(keylist);
3130 key = ISC_LIST_NEXT(key, link))
3132 if (REVOKE(key->key))
3135 have_ksk = ISC_TRUE;
3136 have_non_ksk = ISC_FALSE;
3138 have_ksk = ISC_FALSE;
3139 have_non_ksk = ISC_TRUE;
3141 for (tmpkey = ISC_LIST_HEAD(keylist);
3143 tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
3144 if (dst_key_alg(key->key) != dst_key_alg(tmpkey->key))
3146 if (REVOKE(tmpkey->key))
3149 have_ksk = ISC_TRUE;
3151 have_non_ksk = ISC_TRUE;
3153 if (have_ksk && have_non_ksk && !isksk(key))
3155 dns_rdata_init(&rdata);
3156 dns_rdata_init(&ds);
3157 isc_buffer_init(&b, keybuf, sizeof(keybuf));
3158 result = dst_key_todns(key->key, &b);
3159 check_result(result, "dst_key_todns");
3160 isc_buffer_usedregion(&b, &r);
3161 dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
3162 if (type != dns_rdatatype_dnskey) {
3163 result = dns_ds_buildrdata(gorigin, &rdata,
3166 check_result(result, "dns_ds_buildrdata");
3167 if (type == dns_rdatatype_dlv)
3168 ds.type = dns_rdatatype_dlv;
3169 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
3170 name, 0, &ds, &tuple);
3171 check_result(result, "dns_difftuple_create");
3172 dns_diff_append(&diff, &tuple);
3174 dns_rdata_reset(&ds);
3175 result = dns_ds_buildrdata(gorigin, &rdata,
3176 DNS_DSDIGEST_SHA256,
3178 check_result(result, "dns_ds_buildrdata");
3179 if (type == dns_rdatatype_dlv)
3180 ds.type = dns_rdatatype_dlv;
3181 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
3182 name, 0, &ds, &tuple);
3185 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
3186 gorigin, zone_soa_min_ttl,
3188 check_result(result, "dns_difftuple_create");
3189 dns_diff_append(&diff, &tuple);
3192 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
3193 gclass, 0, NULL, &db);
3194 check_result(result, "dns_db_create");
3196 result = dns_db_newversion(db, &version);
3197 check_result(result, "dns_db_newversion");
3199 result = dns_diff_apply(&diff, db, version);
3200 check_result(result, "dns_diff_apply");
3201 dns_diff_clear(&diff);
3203 result = dns_master_dump(mctx, db, version, style, filename);
3204 check_result(result, "dns_master_dump");
3206 isc_mem_put(mctx, filename, filenamelen + 1);
3208 dns_db_closeversion(db, &version, ISC_FALSE);
3213 print_time(FILE *fp) {
3216 if (outputformat != dns_masterformat_text)
3219 currenttime = time(NULL);
3220 fprintf(fp, "; File written on %s", ctime(¤ttime));
3224 print_version(FILE *fp) {
3225 if (outputformat != dns_masterformat_text)
3228 fprintf(fp, "; dnssec_signzone version " VERSION "\n");
3231 ISC_PLATFORM_NORETURN_PRE static void
3232 usage(void) ISC_PLATFORM_NORETURN_POST;
3236 fprintf(stderr, "Usage:\n");
3237 fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
3239 fprintf(stderr, "\n");
3241 fprintf(stderr, "Version: %s\n", VERSION);
3243 fprintf(stderr, "Options: (default value in parenthesis) \n");
3244 fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n"
3245 "\t\tfor the zone and determines how they are to "
3247 fprintf(stderr, "\t-K directory:\n");
3248 fprintf(stderr, "\t\tdirectory to find key files (.)\n");
3249 fprintf(stderr, "\t-d directory:\n");
3250 fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n");
3251 fprintf(stderr, "\t-g:\t");
3252 fprintf(stderr, "update DS records based on child zones' "
3254 fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
3255 fprintf(stderr, "\t\tRRSIG start time - absolute|offset (now - 1 hour)\n");
3256 fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
3257 fprintf(stderr, "\t\tRRSIG end time - absolute|from start|from now "
3258 "(now + 30 days)\n");
3259 fprintf(stderr, "\t-i interval:\n");
3260 fprintf(stderr, "\t\tcycle interval - resign "
3261 "if < interval from end ( (end-start)/4 )\n");
3262 fprintf(stderr, "\t-j jitter:\n");
3263 fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n");
3264 fprintf(stderr, "\t-v debuglevel (0)\n");
3265 fprintf(stderr, "\t-o origin:\n");
3266 fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
3267 fprintf(stderr, "\t-f outfile:\n");
3268 fprintf(stderr, "\t\tfile the signed zone is written in "
3269 "(zonefile + .signed)\n");
3270 fprintf(stderr, "\t-I format:\n");
3271 fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
3272 fprintf(stderr, "\t-O format:\n");
3273 fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
3274 fprintf(stderr, "\t-N format:\n");
3275 fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
3276 fprintf(stderr, "\t-r randomdev:\n");
3277 fprintf(stderr, "\t\ta file containing random data\n");
3278 fprintf(stderr, "\t-a:\t");
3279 fprintf(stderr, "verify generated signatures\n");
3280 fprintf(stderr, "\t-c class (IN)\n");
3281 fprintf(stderr, "\t-E engine:\n");
3283 fprintf(stderr, "\t\tname of an OpenSSL engine to use "
3284 "(default is \"pkcs11\")\n");
3286 fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
3288 fprintf(stderr, "\t-p:\t");
3289 fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
3290 fprintf(stderr, "\t-P:\t");
3291 fprintf(stderr, "disable post-sign verification\n");
3292 fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n");
3293 fprintf(stderr, "\t-t:\t");
3294 fprintf(stderr, "print statistics\n");
3295 fprintf(stderr, "\t-u:\t");
3296 fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n");
3297 fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n");
3298 fprintf(stderr, "\t-z:\tsign all records with KSKs\n");
3299 fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n"
3300 "\t\twith older versions of dnssec-signzone -g\n");
3301 fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
3302 fprintf(stderr, "\t-k key_signing_key\n");
3303 fprintf(stderr, "\t-l lookasidezone\n");
3304 fprintf(stderr, "\t-3 NSEC3 salt\n");
3305 fprintf(stderr, "\t-H NSEC3 iterations (10)\n");
3306 fprintf(stderr, "\t-A NSEC3 optout\n");
3308 fprintf(stderr, "\n");
3310 fprintf(stderr, "Signing Keys: ");
3311 fprintf(stderr, "(default: all zone keys that have private keys)\n");
3312 fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
3317 removetempfile(void) {
3319 isc_file_remove(tempfile);
3323 print_stats(isc_time_t *timer_start, isc_time_t *timer_finish) {
3324 isc_uint64_t runtime_us; /* Runtime in microseconds */
3325 isc_uint64_t runtime_ms; /* Runtime in milliseconds */
3326 isc_uint64_t sig_ms; /* Signatures per millisecond */
3328 runtime_us = isc_time_microdiff(timer_finish, timer_start);
3330 printf("Signatures generated: %10d\n", nsigned);
3331 printf("Signatures retained: %10d\n", nretained);
3332 printf("Signatures dropped: %10d\n", ndropped);
3333 printf("Signatures successfully verified: %10d\n", nverified);
3334 printf("Signatures unsuccessfully verified: %10d\n", nverifyfailed);
3335 runtime_ms = runtime_us / 1000;
3336 printf("Runtime in seconds: %7u.%03u\n",
3337 (unsigned int) (runtime_ms / 1000),
3338 (unsigned int) (runtime_ms % 1000));
3339 if (runtime_us > 0) {
3340 sig_ms = ((isc_uint64_t)nsigned * 1000000000) / runtime_us;
3341 printf("Signatures per second: %7u.%03u\n",
3342 (unsigned int) sig_ms / 1000,
3343 (unsigned int) sig_ms % 1000);
3348 main(int argc, char *argv[]) {
3350 char *startstr = NULL, *endstr = NULL, *classname = NULL;
3351 char *origin = NULL, *file = NULL, *output = NULL;
3352 char *inputformatstr = NULL, *outputformatstr = NULL;
3353 char *serialformatstr = NULL;
3354 char *dskeyfile[MAXDSKEYS];
3357 isc_time_t timer_start, timer_finish;
3358 dns_dnsseckey_t *key;
3359 isc_result_t result;
3360 isc_log_t *log = NULL;
3361 isc_boolean_t pseudorandom = ISC_FALSE;
3363 const char *engine = "pkcs11";
3365 const char *engine = NULL;
3367 unsigned int eflags;
3368 isc_boolean_t free_output = ISC_FALSE;
3370 dns_rdataclass_t rdclass;
3371 isc_task_t **tasks = NULL;
3374 hashlist_t hashlist;
3375 isc_boolean_t smartsign = ISC_FALSE;
3376 isc_boolean_t make_keyset = ISC_FALSE;
3377 isc_boolean_t set_salt = ISC_FALSE;
3378 isc_boolean_t set_optout = ISC_FALSE;
3379 isc_boolean_t set_iter = ISC_FALSE;
3381 #define CMDLINE_FLAGS \
3382 "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:l:m:n:N:o:O:pPr:s:ST:tuUv:xz"
3385 * Process memory debugging argument first.
3387 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3390 if (strcasecmp(isc_commandline_argument, "record") == 0)
3391 isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
3392 if (strcasecmp(isc_commandline_argument, "trace") == 0)
3393 isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
3394 if (strcasecmp(isc_commandline_argument, "usage") == 0)
3395 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
3396 if (strcasecmp(isc_commandline_argument, "size") == 0)
3397 isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
3398 if (strcasecmp(isc_commandline_argument, "mctx") == 0)
3399 isc_mem_debugging |= ISC_MEM_DEBUGCTX;
3405 isc_commandline_reset = ISC_TRUE;
3407 masterstyle = &dns_master_style_explicitttl;
3409 check_result(isc_app_start(), "isc_app_start");
3411 result = isc_mem_create(0, 0, &mctx);
3412 if (result != ISC_R_SUCCESS)
3413 fatal("out of memory");
3415 dns_result_register();
3417 isc_commandline_errprint = ISC_FALSE;
3419 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3422 set_salt = ISC_TRUE;
3423 nsec_datatype = dns_rdatatype_nsec3;
3424 if (strcmp(isc_commandline_argument, "-") != 0) {
3425 isc_buffer_t target;
3428 sarg = isc_commandline_argument;
3429 isc_buffer_init(&target, saltbuf,
3431 result = isc_hex_decodestring(sarg, &target);
3432 check_result(result,
3433 "isc_hex_decodestring(salt)");
3434 salt_length = isc_buffer_usedlength(&target);
3439 set_optout = ISC_TRUE;
3440 if (OPTOUT(nsec3flags))
3441 nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT;
3443 nsec3flags |= DNS_NSEC3FLAG_OPTOUT;
3447 tryverify = ISC_TRUE;
3451 make_keyset = ISC_TRUE;
3455 classname = isc_commandline_argument;
3459 dsdir = isc_commandline_argument;
3460 if (strlen(dsdir) == 0U)
3461 fatal("DS directory must be non-empty string");
3462 result = try_dir(dsdir);
3463 if (result != ISC_R_SUCCESS)
3464 fatal("cannot open directory %s: %s",
3465 dsdir, isc_result_totext(result));
3469 engine = isc_commandline_argument;
3473 endstr = isc_commandline_argument;
3477 output = isc_commandline_argument;
3481 generateds = ISC_TRUE;
3485 set_iter = ISC_TRUE;
3486 nsec3iter = strtoul(isc_commandline_argument, &endp, 0);
3488 fatal("iterations must be numeric");
3489 if (nsec3iter > 0xffffU)
3490 fatal("iterations too big");
3498 inputformatstr = isc_commandline_argument;
3503 cycle = strtol(isc_commandline_argument, &endp, 0);
3504 if (*endp != '\0' || cycle < 0)
3505 fatal("cycle period must be numeric and "
3511 jitter = strtol(isc_commandline_argument, &endp, 0);
3512 if (*endp != '\0' || jitter < 0)
3513 fatal("jitter must be numeric and positive");
3517 directory = isc_commandline_argument;
3521 if (ndskeys == MAXDSKEYS)
3522 fatal("too many key-signing keys specified");
3523 dskeyfile[ndskeys++] = isc_commandline_argument;
3527 len = strlen(isc_commandline_argument);
3528 isc_buffer_init(&b, isc_commandline_argument, len);
3529 isc_buffer_add(&b, len);
3531 dns_fixedname_init(&dlv_fixed);
3532 dlv = dns_fixedname_name(&dlv_fixed);
3533 result = dns_name_fromtext(dlv, &b, dns_rootname, 0,
3535 check_result(result, "dns_name_fromtext(dlv)");
3542 serialformatstr = isc_commandline_argument;
3547 ntasks = strtol(isc_commandline_argument, &endp, 0);
3548 if (*endp != '\0' || ntasks > ISC_INT32_MAX)
3549 fatal("number of cpus must be numeric");
3553 outputformatstr = isc_commandline_argument;
3557 origin = isc_commandline_argument;
3561 disable_zone_check = ISC_TRUE;
3565 pseudorandom = ISC_TRUE;
3569 setup_entropy(mctx, isc_commandline_argument, &ectx);
3573 smartsign = ISC_TRUE;
3577 startstr = isc_commandline_argument;
3582 set_keyttl = ISC_TRUE;
3583 keyttl = strtottl(isc_commandline_argument);
3587 printstats = ISC_TRUE;
3590 case 'U': /* Undocumented for testing only. */
3591 unknownalg = ISC_TRUE;
3595 update_chain = ISC_TRUE;
3600 verbose = strtol(isc_commandline_argument, &endp, 0);
3602 fatal("verbose level must be numeric");
3606 keyset_kskonly = ISC_TRUE;
3610 ignore_kskflag = ISC_TRUE;
3614 /* Reserved for FIPS mode */
3617 if (isc_commandline_option != '?')
3618 fprintf(stderr, "%s: invalid argument -%c\n",
3619 program, isc_commandline_option);
3624 fprintf(stderr, "%s: unhandled option -%c\n",
3625 program, isc_commandline_option);
3631 setup_entropy(mctx, NULL, &ectx);
3632 eflags = ISC_ENTROPY_BLOCKING;
3634 eflags |= ISC_ENTROPY_GOODONLY;
3636 result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
3637 if (result != ISC_R_SUCCESS)
3638 fatal("could not create hash context");
3640 result = dst_lib_init2(mctx, ectx, engine, eflags);
3641 if (result != ISC_R_SUCCESS)
3642 fatal("could not initialize dst: %s",
3643 isc_result_totext(result));
3645 isc_stdtime_get(&now);
3647 if (startstr != NULL) {
3648 starttime = strtotime(startstr, now, now);
3650 starttime = now - 3600; /* Allow for some clock skew. */
3652 if (endstr != NULL) {
3653 endtime = strtotime(endstr, now, starttime);
3655 endtime = starttime + (30 * 24 * 60 * 60);
3658 cycle = (endtime - starttime) / 4;
3661 ntasks = isc_os_ncpus() * 2;
3662 vbprintf(4, "using %d cpus\n", ntasks);
3664 rdclass = strtoclass(classname);
3666 if (directory == NULL)
3669 setup_logging(verbose, mctx, &log);
3671 argc -= isc_commandline_index;
3672 argv += isc_commandline_index;
3685 if (output == NULL) {
3686 free_output = ISC_TRUE;
3687 output = isc_mem_allocate(mctx,
3688 strlen(file) + strlen(".signed") + 1);
3690 fatal("out of memory");
3691 sprintf(output, "%s.signed", file);
3694 if (inputformatstr != NULL) {
3695 if (strcasecmp(inputformatstr, "text") == 0)
3696 inputformat = dns_masterformat_text;
3697 else if (strcasecmp(inputformatstr, "raw") == 0)
3698 inputformat = dns_masterformat_raw;
3700 fatal("unknown file format: %s\n", inputformatstr);
3703 if (outputformatstr != NULL) {
3704 if (strcasecmp(outputformatstr, "text") == 0)
3705 outputformat = dns_masterformat_text;
3706 else if (strcasecmp(outputformatstr, "raw") == 0)
3707 outputformat = dns_masterformat_raw;
3709 fatal("unknown file format: %s\n", outputformatstr);
3712 if (serialformatstr != NULL) {
3713 if (strcasecmp(serialformatstr, "keep") == 0)
3714 serialformat = SOA_SERIAL_KEEP;
3715 else if (strcasecmp(serialformatstr, "increment") == 0 ||
3716 strcasecmp(serialformatstr, "incr") == 0)
3717 serialformat = SOA_SERIAL_INCREMENT;
3718 else if (strcasecmp(serialformatstr, "unixtime") == 0)
3719 serialformat = SOA_SERIAL_UNIXTIME;
3721 fatal("unknown soa serial format: %s\n",
3725 result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL,
3726 0, 24, 0, 0, 0, 8, mctx);
3727 check_result(result, "dns_master_stylecreate");
3730 TIME_NOW(&timer_start);
3731 loadzone(file, origin, rdclass, &gdb);
3732 gorigin = dns_db_origin(gdb);
3733 gclass = dns_db_class(gdb);
3740 * Check for any existing NSEC3 parameters in the zone,
3741 * and use them as defaults if -u was not specified.
3743 if (update_chain && !set_optout && !set_iter && !set_salt)
3744 nsec_datatype = dns_rdatatype_nsec;
3746 set_nsec3params(update_chain, set_salt, set_optout, set_iter);
3749 isc_boolean_t answer;
3750 hash_length = dns_nsec3_hashlength(dns_hash_sha1);
3751 hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2,
3753 result = dns_nsec_nseconly(gdb, gversion, &answer);
3754 check_result(result, "dns_nsec_nseconly");
3756 fatal("NSEC3 generation requested with "
3757 "NSEC only DNSKEY");
3761 * We need to do this early on, as we start messing with the list
3762 * of keys rather early.
3764 ISC_LIST_INIT(keylist);
3765 isc_rwlock_init(&keylist_lock, 0, 0);
3768 * Fill keylist with:
3769 * 1) Keys listed in the DNSKEY set that have
3770 * private keys associated, *if* no keys were
3771 * set on the command line.
3772 * 2) ZSKs set on the command line
3773 * 3) KSKs set on the command line
3774 * 4) Any keys remaining in the DNSKEY set which
3775 * do not have private keys associated and were
3776 * not specified on the command line.
3778 if (argc == 0 || smartsign)
3779 loadzonekeys(!smartsign, ISC_FALSE);
3780 loadexplicitkeys(argv, argc, ISC_FALSE);
3781 loadexplicitkeys(dskeyfile, ndskeys, ISC_TRUE);
3782 loadzonekeys(!smartsign, ISC_TRUE);
3785 * If we're doing smart signing, look in the key repository for
3786 * key files with metadata, and merge them with the keylist
3790 build_final_keylist();
3792 /* Now enumerate the key list */
3793 for (key = ISC_LIST_HEAD(keylist);
3795 key = ISC_LIST_NEXT(key, link)) {
3796 key->index = keycount++;
3799 if (keycount == 0) {
3800 if (disable_zone_check)
3801 fprintf(stderr, "%s: warning: No keys specified "
3802 "or found\n", program);
3804 fatal("No signing keys specified or found.");
3810 result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max);
3811 check_result(result, "dns_nsec3_maxiterations()");
3812 if (nsec3iter > max)
3813 fatal("NSEC3 iterations too big for weakest DNSKEY "
3814 "strength. Maximum iterations allowed %u.", max);
3820 result = dns_db_newversion(gdb, &gversion);
3821 check_result(result, "dns_db_newversion()");
3823 switch (serialformat) {
3824 case SOA_SERIAL_INCREMENT:
3827 case SOA_SERIAL_UNIXTIME:
3830 case SOA_SERIAL_KEEP:
3836 remove_duplicates();
3839 nsec3ify(dns_hash_sha1, nsec3iter, salt, salt_length,
3845 writeset("dsset-", dns_rdatatype_ds);
3847 writeset("keyset-", dns_rdatatype_dnskey);
3849 writeset("dlvset-", dns_rdatatype_dlv);
3853 tempfilelen = strlen(output) + 20;
3854 tempfile = isc_mem_get(mctx, tempfilelen);
3855 if (tempfile == NULL)
3856 fatal("out of memory");
3858 result = isc_file_mktemplate(output, tempfile, tempfilelen);
3859 check_result(result, "isc_file_mktemplate");
3862 result = isc_file_openunique(tempfile, &fp);
3863 if (result != ISC_R_SUCCESS)
3864 fatal("failed to open temporary output file: %s",
3865 isc_result_totext(result));
3866 removefile = ISC_TRUE;
3867 setfatalcallback(&removetempfile);
3872 result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
3873 if (result != ISC_R_SUCCESS)
3874 fatal("failed to create task manager: %s",
3875 isc_result_totext(result));
3878 result = isc_task_create(taskmgr, 0, &master);
3879 if (result != ISC_R_SUCCESS)
3880 fatal("failed to create task: %s", isc_result_totext(result));
3882 tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
3884 fatal("out of memory");
3885 for (i = 0; i < (int)ntasks; i++) {
3887 result = isc_task_create(taskmgr, 0, &tasks[i]);
3888 if (result != ISC_R_SUCCESS)
3889 fatal("failed to create task: %s",
3890 isc_result_totext(result));
3893 RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS);
3895 RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS);
3901 * There is more work to do. Spread it out over multiple
3902 * processors if possible.
3904 for (i = 0; i < (int)ntasks; i++) {
3905 result = isc_app_onrun(mctx, master, startworker,
3907 if (result != ISC_R_SUCCESS)
3908 fatal("failed to start task: %s",
3909 isc_result_totext(result));
3911 (void)isc_app_run();
3913 fatal("process aborted by user");
3915 isc_task_detach(&master);
3916 shuttingdown = ISC_TRUE;
3917 for (i = 0; i < (int)ntasks; i++)
3918 isc_task_detach(&tasks[i]);
3919 isc_taskmgr_destroy(&taskmgr);
3920 isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
3924 if (outputformat != dns_masterformat_text) {
3925 result = dns_master_dumptostream2(mctx, gdb, gversion,
3926 masterstyle, outputformat,
3928 check_result(result, "dns_master_dumptostream2");
3931 result = isc_stdio_close(fp);
3932 check_result(result, "isc_stdio_close");
3933 removefile = ISC_FALSE;
3935 result = isc_file_rename(tempfile, output);
3936 if (result != ISC_R_SUCCESS)
3937 fatal("failed to rename temp file to %s: %s\n",
3938 output, isc_result_totext(result));
3940 DESTROYLOCK(&namelock);
3942 DESTROYLOCK(&statslock);
3944 printf("%s\n", output);
3946 dns_db_closeversion(gdb, &gversion, ISC_FALSE);
3947 dns_db_detach(&gdb);
3949 while (!ISC_LIST_EMPTY(keylist)) {
3950 key = ISC_LIST_HEAD(keylist);
3951 ISC_LIST_UNLINK(keylist, key, link);
3952 dns_dnsseckey_destroy(mctx, &key);
3955 isc_mem_put(mctx, tempfile, tempfilelen);
3958 isc_mem_free(mctx, output);
3960 dns_master_styledestroy(&dsstyle, mctx);
3962 cleanup_logging(&log);
3965 cleanup_entropy(&ectx);
3968 isc_mem_stats(mctx, stdout);
3969 isc_mem_destroy(&mctx);
3971 (void) isc_app_finish();
3974 TIME_NOW(&timer_finish);
3975 print_stats(&timer_start, &timer_finish);