2 * Portions Copyright (C) 2004-2011 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.110.9 2011/07/19 23:47:12 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_FALSE;
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 && rrsig.originalttl == set->ttl &&
490 setverifies(name, set, key->key, &sigrdata)) {
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",
497 sigstr, expired ? "expired" :
498 rrsig.originalttl != set->ttl ?
499 "ttl change" : "failed to verify");
500 wassignedby[key->index] = ISC_TRUE;
503 } else if (iszonekey(key)) {
504 if (!expired && rrsig.originalttl == set->ttl &&
505 setverifies(name, set, key->key, &sigrdata)) {
506 vbprintf(2, "\trrsig by %s retained\n", sigstr);
508 wassignedby[key->index] = ISC_TRUE;
509 nowsignedby[key->index] = ISC_TRUE;
511 vbprintf(2, "\trrsig by %s dropped - %s\n",
512 sigstr, expired ? "expired" :
513 rrsig.originalttl != set->ttl ?
514 "ttl change" : "failed to verify");
515 wassignedby[key->index] = ISC_TRUE;
517 } else if (!expired) {
518 vbprintf(2, "\trrsig by %s retained\n", sigstr);
521 vbprintf(2, "\trrsig by %s expired\n", sigstr);
526 nowsignedby[key->index] = ISC_TRUE;
528 if (sigset.ttl != ttl) {
529 vbprintf(2, "\tfixing ttl %s\n", sigstr);
531 result = dns_difftuple_create(mctx,
536 check_result(result, "dns_difftuple_create");
537 dns_diff_append(del, &tuple);
538 result = dns_difftuple_create(mctx,
543 check_result(result, "dns_difftuple_create");
544 dns_diff_append(add, &tuple);
548 result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL,
551 check_result(result, "dns_difftuple_create");
552 dns_diff_append(del, &tuple);
559 signwithkey(name, set, key->key, ttl, add,
560 "resigning with dnskey");
561 nowsignedby[key->index] = ISC_TRUE;
564 dns_rdata_reset(&sigrdata);
565 dns_rdata_freestruct(&rrsig);
566 result = dns_rdataset_next(&sigset);
568 if (result == ISC_R_NOMORE)
569 result = ISC_R_SUCCESS;
571 check_result(result, "dns_rdataset_first/next");
572 if (dns_rdataset_isassociated(&sigset))
573 dns_rdataset_disassociate(&sigset);
575 for (key = ISC_LIST_HEAD(keylist);
577 key = ISC_LIST_NEXT(key, link))
579 if (nowsignedby[key->index])
582 if (!issigningkey(key))
585 if (set->type == dns_rdatatype_dnskey &&
586 dns_name_equal(name, gorigin)) {
587 isc_boolean_t have_ksk;
588 dns_dnsseckey_t *tmpkey;
590 have_ksk = isksk(key);
591 for (tmpkey = ISC_LIST_HEAD(keylist);
593 tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
594 if (dst_key_alg(key->key) !=
595 dst_key_alg(tmpkey->key))
597 if (REVOKE(tmpkey->key))
602 if (isksk(key) || !have_ksk ||
603 (iszsk(key) && !keyset_kskonly))
604 signwithkey(name, set, key->key, ttl, add,
605 "signing with dnskey");
606 } else if (iszsk(key)) {
607 signwithkey(name, set, key->key, ttl, add,
608 "signing with dnskey");
612 isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t));
613 isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t));
617 unsigned char *hashbuf;
624 hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) {
627 l->length = length + 1;
631 l->hashbuf = malloc(l->size * l->length);
632 if (l->hashbuf == NULL)
641 hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len)
644 REQUIRE(len <= l->length);
646 if (l->entries == l->size) {
647 l->size = l->size * 2 + 100;
648 l->hashbuf = realloc(l->hashbuf, l->size * l->length);
650 memset(l->hashbuf + l->entries * l->length, 0, l->length);
651 memcpy(l->hashbuf + l->entries * l->length, hash, len);
656 hashlist_add_dns_name(hashlist_t *l, /*const*/ dns_name_t *name,
657 unsigned int hashalg, unsigned int iterations,
658 const unsigned char *salt, size_t salt_length,
659 isc_boolean_t speculative)
661 char nametext[DNS_NAME_FORMATSIZE];
662 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
666 len = isc_iterated_hash(hash, hashalg, iterations, salt, salt_length,
667 name->ndata, name->length);
669 dns_name_format(name, nametext, sizeof nametext);
670 for (i = 0 ; i < len; i++)
671 fprintf(stderr, "%02x", hash[i]);
672 fprintf(stderr, " %s\n", nametext);
674 hash[len++] = speculative ? 1 : 0;
675 hashlist_add(l, hash, len);
679 hashlist_comp(const void *a, const void *b) {
680 return (memcmp(a, b, hash_length + 1));
684 hashlist_sort(hashlist_t *l) {
685 qsort(l->hashbuf, l->entries, l->length, hashlist_comp);
689 hashlist_hasdup(hashlist_t *l) {
690 unsigned char *current;
691 unsigned char *next = l->hashbuf;
692 size_t entries = l->entries;
695 * Skip initial speculative wild card hashs.
697 while (entries > 0U && next[l->length-1] != 0U) {
703 while (entries-- > 1U) {
705 if (next[l->length-1] != 0)
707 if (memcmp(current, next, l->length - 1) == 0)
714 static const unsigned char *
715 hashlist_findnext(const hashlist_t *l,
716 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
718 unsigned int entries = l->entries;
719 const unsigned char *next = bsearch(hash, l->hashbuf, l->entries,
720 l->length, hashlist_comp);
721 INSIST(next != NULL);
724 if (next < l->hashbuf + (l->entries - 1) * l->length)
728 if (next[l->length - 1] == 0)
730 } while (entries-- > 1);
731 INSIST(entries != 0);
736 hashlist_exists(const hashlist_t *l,
737 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
739 if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp))
746 addnowildcardhash(hashlist_t *l, /*const*/ dns_name_t *name,
747 unsigned int hashalg, unsigned int iterations,
748 const unsigned char *salt, size_t salt_length)
750 dns_fixedname_t fixed;
752 dns_dbnode_t *node = NULL;
754 char namestr[DNS_NAME_FORMATSIZE];
756 dns_fixedname_init(&fixed);
757 wild = dns_fixedname_name(&fixed);
759 result = dns_name_concatenate(dns_wildcardname, name, wild, NULL);
760 if (result == ISC_R_NOSPACE)
762 check_result(result,"addnowildcardhash: dns_name_concatenate()");
764 result = dns_db_findnode(gdb, wild, ISC_FALSE, &node);
765 if (result == ISC_R_SUCCESS) {
766 dns_db_detachnode(gdb, &node);
771 dns_name_format(wild, namestr, sizeof(namestr));
772 fprintf(stderr, "adding no-wildcardhash for %s\n", namestr);
775 hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_length,
780 opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
783 char filename[PATH_MAX];
787 isc_buffer_init(&b, filename, sizeof(filename));
789 /* allow room for a trailing slash */
790 if (strlen(dsdir) >= isc_buffer_availablelength(&b))
791 fatal("path '%s' is too long", dsdir);
792 isc_buffer_putstr(&b, dsdir);
793 if (dsdir[strlen(dsdir) - 1] != '/')
794 isc_buffer_putstr(&b, "/");
796 if (strlen(prefix) > isc_buffer_availablelength(&b))
797 fatal("path '%s' is too long", dsdir);
798 isc_buffer_putstr(&b, prefix);
799 result = dns_name_tofilenametext(name, ISC_FALSE, &b);
800 check_result(result, "dns_name_tofilenametext()");
801 if (isc_buffer_availablelength(&b) == 0) {
802 char namestr[DNS_NAME_FORMATSIZE];
803 dns_name_format(name, namestr, sizeof(namestr));
804 fatal("name '%s' is too long", namestr);
806 isc_buffer_putuint8(&b, 0);
808 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
809 rdclass, 0, NULL, dbp);
810 check_result(result, "dns_db_create()");
812 result = dns_db_load3(*dbp, filename, inputformat, DNS_MASTER_HINT);
813 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
818 * Load the DS set for a child zone, if a dsset-* file can be found.
819 * If not, try to find a keyset-* file from an earlier version of
820 * dnssec-signzone, and build DS records from that.
823 loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
825 dns_dbversion_t *ver = NULL;
826 dns_dbnode_t *node = NULL;
828 dns_rdataset_t keyset;
830 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
832 dns_difftuple_t *tuple = NULL;
834 opendb("dsset-", name, gclass, &db);
836 result = dns_db_findnode(db, name, ISC_FALSE, &node);
837 if (result == ISC_R_SUCCESS) {
838 dns_rdataset_init(dsset);
839 result = dns_db_findrdataset(db, node, NULL,
840 dns_rdatatype_ds, 0, 0,
842 dns_db_detachnode(db, &node);
843 if (result == ISC_R_SUCCESS) {
844 vbprintf(2, "found DS records\n");
853 /* No DS records found; try again, looking for DNSKEY records */
854 opendb("keyset-", name, gclass, &db);
856 return (ISC_R_NOTFOUND);
859 result = dns_db_findnode(db, name, ISC_FALSE, &node);
860 if (result != ISC_R_SUCCESS) {
865 dns_rdataset_init(&keyset);
866 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
868 if (result != ISC_R_SUCCESS) {
869 dns_db_detachnode(db, &node);
873 vbprintf(2, "found DNSKEY records\n");
875 result = dns_db_newversion(db, &ver);
876 check_result(result, "dns_db_newversion");
877 dns_diff_init(mctx, &diff);
879 for (result = dns_rdataset_first(&keyset);
880 result == ISC_R_SUCCESS;
881 result = dns_rdataset_next(&keyset))
883 dns_rdata_init(&key);
885 dns_rdataset_current(&keyset, &key);
886 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
888 check_result(result, "dns_ds_buildrdata");
890 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
892 check_result(result, "dns_difftuple_create");
893 dns_diff_append(&diff, &tuple);
895 dns_rdata_reset(&ds);
896 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
898 check_result(result, "dns_ds_buildrdata");
900 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
902 check_result(result, "dns_difftuple_create");
903 dns_diff_append(&diff, &tuple);
906 result = dns_diff_apply(&diff, db, ver);
907 check_result(result, "dns_diff_apply");
908 dns_diff_clear(&diff);
910 dns_db_closeversion(db, &ver, ISC_TRUE);
912 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
914 check_result(result, "dns_db_findrdataset");
916 dns_rdataset_disassociate(&keyset);
917 dns_db_detachnode(db, &node);
923 delegation(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) {
924 dns_rdataset_t nsset;
927 if (dns_name_equal(name, gorigin))
930 dns_rdataset_init(&nsset);
931 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ns,
933 if (dns_rdataset_isassociated(&nsset)) {
936 dns_rdataset_disassociate(&nsset);
939 return (ISC_TF(result == ISC_R_SUCCESS));
943 secure(dns_name_t *name, dns_dbnode_t *node) {
944 dns_rdataset_t dsset;
947 if (dns_name_equal(name, gorigin))
950 dns_rdataset_init(&dsset);
951 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds,
953 if (dns_rdataset_isassociated(&dsset))
954 dns_rdataset_disassociate(&dsset);
956 return (ISC_TF(result == ISC_R_SUCCESS));
960 * Signs all records at a name.
963 signname(dns_dbnode_t *node, dns_name_t *name) {
965 dns_rdataset_t rdataset;
966 dns_rdatasetiter_t *rdsiter;
967 isc_boolean_t isdelegation = ISC_FALSE;
969 char namestr[DNS_NAME_FORMATSIZE];
971 dns_rdataset_init(&rdataset);
972 dns_name_format(name, namestr, sizeof(namestr));
975 * Determine if this is a delegation point.
977 if (delegation(name, node, NULL))
978 isdelegation = ISC_TRUE;
981 * Now iterate through the rdatasets.
983 dns_diff_init(mctx, &del);
984 dns_diff_init(mctx, &add);
986 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
987 check_result(result, "dns_db_allrdatasets()");
988 result = dns_rdatasetiter_first(rdsiter);
989 while (result == ISC_R_SUCCESS) {
990 dns_rdatasetiter_current(rdsiter, &rdataset);
992 /* If this is a RRSIG set, skip it. */
993 if (rdataset.type == dns_rdatatype_rrsig)
997 * If this name is a delegation point, skip all records
998 * except NSEC and DS sets. Otherwise check that there
1002 if (rdataset.type != nsec_datatype &&
1003 rdataset.type != dns_rdatatype_ds)
1005 } else if (rdataset.type == dns_rdatatype_ds) {
1006 char namebuf[DNS_NAME_FORMATSIZE];
1007 dns_name_format(name, namebuf, sizeof(namebuf));
1008 fatal("'%s': found DS RRset without NS RRset\n",
1012 signset(&del, &add, node, name, &rdataset);
1015 dns_rdataset_disassociate(&rdataset);
1016 result = dns_rdatasetiter_next(rdsiter);
1018 if (result != ISC_R_NOMORE)
1019 fatal("rdataset iteration for name '%s' failed: %s",
1020 namestr, isc_result_totext(result));
1022 dns_rdatasetiter_destroy(&rdsiter);
1024 result = dns_diff_applysilently(&del, gdb, gversion);
1025 if (result != ISC_R_SUCCESS)
1026 fatal("failed to delete SIGs at node '%s': %s",
1027 namestr, isc_result_totext(result));
1029 result = dns_diff_applysilently(&add, gdb, gversion);
1030 if (result != ISC_R_SUCCESS)
1031 fatal("failed to add SIGs at node '%s': %s",
1032 namestr, isc_result_totext(result));
1034 dns_diff_clear(&del);
1035 dns_diff_clear(&add);
1038 static inline isc_boolean_t
1039 active_node(dns_dbnode_t *node) {
1040 dns_rdatasetiter_t *rdsiter = NULL;
1041 dns_rdatasetiter_t *rdsiter2 = NULL;
1042 isc_boolean_t active = ISC_FALSE;
1043 isc_result_t result;
1044 dns_rdataset_t rdataset;
1045 dns_rdatatype_t type;
1046 dns_rdatatype_t covers;
1047 isc_boolean_t found;
1049 dns_rdataset_init(&rdataset);
1050 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1051 check_result(result, "dns_db_allrdatasets()");
1052 result = dns_rdatasetiter_first(rdsiter);
1053 while (result == ISC_R_SUCCESS) {
1054 dns_rdatasetiter_current(rdsiter, &rdataset);
1055 if (rdataset.type != dns_rdatatype_nsec &&
1056 rdataset.type != dns_rdatatype_nsec3 &&
1057 rdataset.type != dns_rdatatype_rrsig)
1059 dns_rdataset_disassociate(&rdataset);
1061 result = dns_rdatasetiter_next(rdsiter);
1063 result = ISC_R_NOMORE;
1065 if (result != ISC_R_NOMORE)
1066 fatal("rdataset iteration failed: %s",
1067 isc_result_totext(result));
1069 if (!active && nsec_datatype == dns_rdatatype_nsec) {
1071 * The node is empty of everything but NSEC / RRSIG records.
1073 for (result = dns_rdatasetiter_first(rdsiter);
1074 result == ISC_R_SUCCESS;
1075 result = dns_rdatasetiter_next(rdsiter)) {
1076 dns_rdatasetiter_current(rdsiter, &rdataset);
1077 result = dns_db_deleterdataset(gdb, node, gversion,
1080 check_result(result, "dns_db_deleterdataset()");
1081 dns_rdataset_disassociate(&rdataset);
1083 if (result != ISC_R_NOMORE)
1084 fatal("rdataset iteration failed: %s",
1085 isc_result_totext(result));
1088 * Delete RRSIGs for types that no longer exist.
1090 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
1091 check_result(result, "dns_db_allrdatasets()");
1092 for (result = dns_rdatasetiter_first(rdsiter);
1093 result == ISC_R_SUCCESS;
1094 result = dns_rdatasetiter_next(rdsiter)) {
1095 dns_rdatasetiter_current(rdsiter, &rdataset);
1096 type = rdataset.type;
1097 covers = rdataset.covers;
1098 dns_rdataset_disassociate(&rdataset);
1100 * Delete the NSEC chain if we are signing with
1103 if (nsec_datatype == dns_rdatatype_nsec3 &&
1104 (type == dns_rdatatype_nsec ||
1105 covers == dns_rdatatype_nsec)) {
1106 result = dns_db_deleterdataset(gdb, node,
1109 check_result(result,
1110 "dns_db_deleterdataset(nsec/rrsig)");
1113 if (type != dns_rdatatype_rrsig)
1116 for (result = dns_rdatasetiter_first(rdsiter2);
1117 !found && result == ISC_R_SUCCESS;
1118 result = dns_rdatasetiter_next(rdsiter2)) {
1119 dns_rdatasetiter_current(rdsiter2, &rdataset);
1120 if (rdataset.type == covers)
1122 dns_rdataset_disassociate(&rdataset);
1125 if (result != ISC_R_NOMORE)
1126 fatal("rdataset iteration failed: %s",
1127 isc_result_totext(result));
1128 result = dns_db_deleterdataset(gdb, node,
1131 check_result(result,
1132 "dns_db_deleterdataset(rrsig)");
1133 } else if (result != ISC_R_NOMORE &&
1134 result != ISC_R_SUCCESS)
1135 fatal("rdataset iteration failed: %s",
1136 isc_result_totext(result));
1138 if (result != ISC_R_NOMORE)
1139 fatal("rdataset iteration failed: %s",
1140 isc_result_totext(result));
1141 dns_rdatasetiter_destroy(&rdsiter2);
1143 dns_rdatasetiter_destroy(&rdsiter);
1149 * Extracts the minimum TTL from the SOA record, and the SOA record's TTL.
1152 get_soa_ttls(void) {
1153 dns_rdataset_t soaset;
1154 dns_fixedname_t fname;
1156 isc_result_t result;
1157 dns_rdata_t rdata = DNS_RDATA_INIT;
1159 dns_fixedname_init(&fname);
1160 name = dns_fixedname_name(&fname);
1161 dns_rdataset_init(&soaset);
1162 result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
1163 0, 0, NULL, name, &soaset, NULL);
1164 if (result != ISC_R_SUCCESS)
1165 fatal("failed to find an SOA at the zone apex: %s",
1166 isc_result_totext(result));
1168 result = dns_rdataset_first(&soaset);
1169 check_result(result, "dns_rdataset_first");
1170 dns_rdataset_current(&soaset, &rdata);
1171 zone_soa_min_ttl = dns_soa_getminimum(&rdata);
1172 soa_ttl = soaset.ttl;
1173 dns_rdataset_disassociate(&soaset);
1177 * Increment (or set if nonzero) the SOA serial
1180 setsoaserial(isc_uint32_t serial) {
1181 isc_result_t result;
1182 dns_dbnode_t *node = NULL;
1183 dns_rdataset_t rdataset;
1184 dns_rdata_t rdata = DNS_RDATA_INIT;
1185 isc_uint32_t old_serial, new_serial;
1187 result = dns_db_getoriginnode(gdb, &node);
1188 if (result != ISC_R_SUCCESS)
1191 dns_rdataset_init(&rdataset);
1193 result = dns_db_findrdataset(gdb, node, gversion,
1194 dns_rdatatype_soa, 0,
1195 0, &rdataset, NULL);
1196 if (result != ISC_R_SUCCESS)
1199 result = dns_rdataset_first(&rdataset);
1200 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1202 dns_rdataset_current(&rdataset, &rdata);
1204 old_serial = dns_soa_getserial(&rdata);
1207 /* Set SOA serial to the value provided. */
1208 new_serial = serial;
1210 /* Increment SOA serial using RFC 1982 arithmetics */
1211 new_serial = (old_serial + 1) & 0xFFFFFFFF;
1212 if (new_serial == 0)
1216 /* If the new serial is not likely to cause a zone transfer
1217 * (a/ixfr) from servers having the old serial, warn the user.
1219 * RFC1982 section 7 defines the maximum increment to be
1220 * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
1221 * comparison. (5 - 6 == (2^32)-1, not negative-one)
1223 if (new_serial == old_serial ||
1224 (new_serial - old_serial) > 0x7fffffffU)
1225 fprintf(stderr, "%s: warning: Serial number not advanced, "
1226 "zone may not transfer\n", program);
1228 dns_soa_setserial(new_serial, &rdata);
1230 result = dns_db_deleterdataset(gdb, node, gversion,
1231 dns_rdatatype_soa, 0);
1232 check_result(result, "dns_db_deleterdataset");
1233 if (result != ISC_R_SUCCESS)
1236 result = dns_db_addrdataset(gdb, node, gversion,
1237 0, &rdataset, 0, NULL);
1238 check_result(result, "dns_db_addrdataset");
1239 if (result != ISC_R_SUCCESS)
1243 dns_rdataset_disassociate(&rdataset);
1245 dns_db_detachnode(gdb, &node);
1246 dns_rdata_reset(&rdata);
1252 * Delete any RRSIG records at a node.
1255 cleannode(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
1256 dns_rdatasetiter_t *rdsiter = NULL;
1258 isc_result_t result, dresult;
1260 if (outputformat != dns_masterformat_text || !disable_zone_check)
1263 dns_rdataset_init(&set);
1264 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
1265 check_result(result, "dns_db_allrdatasets");
1266 result = dns_rdatasetiter_first(rdsiter);
1267 while (result == ISC_R_SUCCESS) {
1268 isc_boolean_t destroy = ISC_FALSE;
1269 dns_rdatatype_t covers = 0;
1270 dns_rdatasetiter_current(rdsiter, &set);
1271 if (set.type == dns_rdatatype_rrsig) {
1272 covers = set.covers;
1275 dns_rdataset_disassociate(&set);
1276 result = dns_rdatasetiter_next(rdsiter);
1278 dresult = dns_db_deleterdataset(db, node, version,
1279 dns_rdatatype_rrsig,
1281 check_result(dresult, "dns_db_deleterdataset");
1284 if (result != ISC_R_NOMORE)
1285 fatal("rdataset iteration failed: %s",
1286 isc_result_totext(result));
1287 dns_rdatasetiter_destroy(&rdsiter);
1291 * Set up the iterator and global state before starting the tasks.
1295 isc_result_t result;
1298 result = dns_db_createiterator(gdb, 0, &gdbiter);
1299 check_result(result, "dns_db_createiterator()");
1303 * Clean up the iterator and global state after the tasks complete.
1307 dns_dbiterator_destroy(&gdbiter);
1310 static isc_boolean_t
1311 goodsig(dns_rdata_t *sigrdata, dns_name_t *name, dns_rdataset_t *keyrdataset,
1312 dns_rdataset_t *rdataset)
1314 dns_rdata_dnskey_t key;
1315 dns_rdata_rrsig_t sig;
1316 dst_key_t *dstkey = NULL;
1317 isc_result_t result;
1319 dns_rdata_tostruct(sigrdata, &sig, NULL);
1321 for (result = dns_rdataset_first(keyrdataset);
1322 result == ISC_R_SUCCESS;
1323 result = dns_rdataset_next(keyrdataset)) {
1324 dns_rdata_t rdata = DNS_RDATA_INIT;
1325 dns_rdataset_current(keyrdataset, &rdata);
1326 dns_rdata_tostruct(&rdata, &key, NULL);
1327 result = dns_dnssec_keyfromrdata(gorigin, &rdata, mctx,
1329 if (result != ISC_R_SUCCESS)
1331 if (sig.algorithm != key.algorithm ||
1332 sig.keyid != dst_key_id(dstkey) ||
1333 !dns_name_equal(&sig.signer, gorigin)) {
1334 dst_key_free(&dstkey);
1337 result = dns_dnssec_verify(name, rdataset, dstkey, ISC_FALSE,
1339 dst_key_free(&dstkey);
1340 if (result == ISC_R_SUCCESS)
1347 verifyset(dns_rdataset_t *rdataset, dns_name_t *name, dns_dbnode_t *node,
1348 dns_rdataset_t *keyrdataset, unsigned char *ksk_algorithms,
1349 unsigned char *bad_algorithms)
1351 unsigned char set_algorithms[256];
1352 char namebuf[DNS_NAME_FORMATSIZE];
1355 dns_rdataset_t sigrdataset;
1356 dns_rdatasetiter_t *rdsiter = NULL;
1357 isc_result_t result;
1360 dns_rdataset_init(&sigrdataset);
1361 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1362 check_result(result, "dns_db_allrdatasets()");
1363 for (result = dns_rdatasetiter_first(rdsiter);
1364 result == ISC_R_SUCCESS;
1365 result = dns_rdatasetiter_next(rdsiter)) {
1366 dns_rdatasetiter_current(rdsiter, &sigrdataset);
1367 if (sigrdataset.type == dns_rdatatype_rrsig &&
1368 sigrdataset.covers == rdataset->type)
1370 dns_rdataset_disassociate(&sigrdataset);
1372 if (result != ISC_R_SUCCESS) {
1373 dns_name_format(name, namebuf, sizeof(namebuf));
1374 type_format(rdataset->type, typebuf, sizeof(typebuf));
1375 fprintf(stderr, "no signatures for %s/%s\n", namebuf, typebuf);
1376 for (i = 0; i < 256; i++)
1377 if (ksk_algorithms[i] != 0)
1378 bad_algorithms[i] = 1;
1382 memset(set_algorithms, 0, sizeof(set_algorithms));
1383 for (result = dns_rdataset_first(&sigrdataset);
1384 result == ISC_R_SUCCESS;
1385 result = dns_rdataset_next(&sigrdataset)) {
1386 dns_rdata_t rdata = DNS_RDATA_INIT;
1387 dns_rdata_rrsig_t sig;
1389 dns_rdataset_current(&sigrdataset, &rdata);
1390 dns_rdata_tostruct(&rdata, &sig, NULL);
1391 if (rdataset->ttl != sig.originalttl) {
1392 dns_name_format(name, namebuf, sizeof(namebuf));
1393 type_format(rdataset->type, typebuf, sizeof(typebuf));
1394 fprintf(stderr, "TTL mismatch for %s %s keytag %u\n",
1395 namebuf, typebuf, sig.keyid);
1398 if ((set_algorithms[sig.algorithm] != 0) ||
1399 (ksk_algorithms[sig.algorithm] == 0))
1401 if (goodsig(&rdata, name, keyrdataset, rdataset))
1402 set_algorithms[sig.algorithm] = 1;
1404 dns_rdatasetiter_destroy(&rdsiter);
1405 if (memcmp(set_algorithms, ksk_algorithms, sizeof(set_algorithms))) {
1406 dns_name_format(name, namebuf, sizeof(namebuf));
1407 type_format(rdataset->type, typebuf, sizeof(typebuf));
1408 for (i = 0; i < 256; i++)
1409 if ((ksk_algorithms[i] != 0) &&
1410 (set_algorithms[i] == 0)) {
1411 dns_secalg_format(i, algbuf, sizeof(algbuf));
1412 fprintf(stderr, "Missing %s signature for "
1413 "%s %s\n", algbuf, namebuf, typebuf);
1414 bad_algorithms[i] = 1;
1417 dns_rdataset_disassociate(&sigrdataset);
1421 verifynode(dns_name_t *name, dns_dbnode_t *node, isc_boolean_t delegation,
1422 dns_rdataset_t *keyrdataset, unsigned char *ksk_algorithms,
1423 unsigned char *bad_algorithms)
1425 dns_rdataset_t rdataset;
1426 dns_rdatasetiter_t *rdsiter = NULL;
1427 isc_result_t result;
1429 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1430 check_result(result, "dns_db_allrdatasets()");
1431 result = dns_rdatasetiter_first(rdsiter);
1432 dns_rdataset_init(&rdataset);
1433 while (result == ISC_R_SUCCESS) {
1434 dns_rdatasetiter_current(rdsiter, &rdataset);
1435 if (rdataset.type != dns_rdatatype_rrsig &&
1436 rdataset.type != dns_rdatatype_dnskey &&
1437 (!delegation || rdataset.type == dns_rdatatype_ds ||
1438 rdataset.type == dns_rdatatype_nsec)) {
1439 verifyset(&rdataset, name, node, keyrdataset,
1440 ksk_algorithms, bad_algorithms);
1442 dns_rdataset_disassociate(&rdataset);
1443 result = dns_rdatasetiter_next(rdsiter);
1445 if (result != ISC_R_NOMORE)
1446 fatal("rdataset iteration failed: %s",
1447 isc_result_totext(result));
1448 dns_rdatasetiter_destroy(&rdsiter);
1452 * Verify that certain things are sane:
1454 * The apex has a DNSKEY RRset with at least one KSK, and at least
1455 * one ZSK if the -x flag was not used.
1457 * The DNSKEY record was signed with at least one of the KSKs in
1460 * The rest of the zone was signed with at least one of the ZSKs
1461 * present in the DNSKEY RRset.
1466 dns_dbiterator_t *dbiter = NULL;
1467 dns_dbnode_t *node = NULL, *nextnode = NULL;
1468 dns_fixedname_t fname, fnextname, fzonecut;
1469 dns_name_t *name, *nextname, *zonecut;
1470 dns_rdata_dnskey_t dnskey;
1471 dns_rdata_t rdata = DNS_RDATA_INIT;
1472 dns_rdataset_t keyset, soaset;
1473 dns_rdataset_t keysigs, soasigs;
1475 isc_boolean_t done = ISC_FALSE;
1476 isc_boolean_t first = ISC_TRUE;
1477 isc_boolean_t goodksk = ISC_FALSE;
1478 isc_result_t result;
1479 unsigned char revoked_ksk[256];
1480 unsigned char revoked_zsk[256];
1481 unsigned char standby_ksk[256];
1482 unsigned char standby_zsk[256];
1483 unsigned char ksk_algorithms[256];
1484 unsigned char zsk_algorithms[256];
1485 unsigned char bad_algorithms[256];
1486 #ifdef ALLOW_KSKLESS_ZONES
1487 isc_boolean_t allzsksigned = ISC_TRUE;
1488 unsigned char self_algorithms[256];
1491 if (disable_zone_check)
1494 result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node);
1495 if (result != ISC_R_SUCCESS)
1496 fatal("failed to find the zone's origin: %s",
1497 isc_result_totext(result));
1499 dns_rdataset_init(&keyset);
1500 dns_rdataset_init(&keysigs);
1501 dns_rdataset_init(&soaset);
1502 dns_rdataset_init(&soasigs);
1504 result = dns_db_findrdataset(gdb, node, gversion,
1505 dns_rdatatype_dnskey,
1506 0, 0, &keyset, &keysigs);
1507 if (result != ISC_R_SUCCESS)
1508 fatal("cannot find DNSKEY rrset\n");
1510 result = dns_db_findrdataset(gdb, node, gversion,
1512 0, 0, &soaset, &soasigs);
1513 dns_db_detachnode(gdb, &node);
1514 if (result != ISC_R_SUCCESS)
1515 fatal("cannot find SOA rrset\n");
1517 if (!dns_rdataset_isassociated(&keysigs))
1518 fatal("cannot find DNSKEY RRSIGs\n");
1520 if (!dns_rdataset_isassociated(&soasigs))
1521 fatal("cannot find SOA RRSIGs\n");
1523 memset(revoked_ksk, 0, sizeof(revoked_ksk));
1524 memset(revoked_zsk, 0, sizeof(revoked_zsk));
1525 memset(standby_ksk, 0, sizeof(standby_ksk));
1526 memset(standby_zsk, 0, sizeof(standby_zsk));
1527 memset(ksk_algorithms, 0, sizeof(ksk_algorithms));
1528 memset(zsk_algorithms, 0, sizeof(zsk_algorithms));
1529 memset(bad_algorithms, 0, sizeof(bad_algorithms));
1530 #ifdef ALLOW_KSKLESS_ZONES
1531 memset(self_algorithms, 0, sizeof(self_algorithms));
1535 * Check that the DNSKEY RR has at least one self signing KSK
1536 * and one ZSK per algorithm in it (or, if -x was used, one
1537 * self-signing KSK).
1539 for (result = dns_rdataset_first(&keyset);
1540 result == ISC_R_SUCCESS;
1541 result = dns_rdataset_next(&keyset)) {
1542 dns_rdataset_current(&keyset, &rdata);
1543 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
1544 check_result(result, "dns_rdata_tostruct");
1546 if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0)
1548 else if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) {
1549 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1550 !dns_dnssec_selfsigns(&rdata, gorigin, &keyset,
1551 &keysigs, ISC_FALSE,
1553 char namebuf[DNS_NAME_FORMATSIZE];
1557 dns_name_format(gorigin, namebuf,
1559 isc_buffer_init(&buf, buffer, sizeof(buffer));
1560 result = dns_rdata_totext(&rdata, NULL, &buf);
1561 check_result(result, "dns_rdata_totext");
1562 fatal("revoked KSK is not self signed:\n"
1563 "%s DNSKEY %.*s", namebuf,
1564 (int)isc_buffer_usedlength(&buf), buffer);
1566 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1567 revoked_ksk[dnskey.algorithm] != 255)
1568 revoked_ksk[dnskey.algorithm]++;
1569 else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 &&
1570 revoked_zsk[dnskey.algorithm] != 255)
1571 revoked_zsk[dnskey.algorithm]++;
1572 } else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) {
1573 if (dns_dnssec_selfsigns(&rdata, gorigin, &keyset,
1574 &keysigs, ISC_FALSE, mctx)) {
1575 if (ksk_algorithms[dnskey.algorithm] != 255)
1576 ksk_algorithms[dnskey.algorithm]++;
1579 if (standby_ksk[dnskey.algorithm] != 255)
1580 standby_ksk[dnskey.algorithm]++;
1582 } else if (dns_dnssec_selfsigns(&rdata, gorigin, &keyset,
1583 &keysigs, ISC_FALSE,
1585 #ifdef ALLOW_KSKLESS_ZONES
1586 if (self_algorithms[dnskey.algorithm] != 255)
1587 self_algorithms[dnskey.algorithm]++;
1589 if (zsk_algorithms[dnskey.algorithm] != 255)
1590 zsk_algorithms[dnskey.algorithm]++;
1591 } else if (dns_dnssec_signs(&rdata, gorigin, &soaset,
1592 &soasigs, ISC_FALSE, mctx)) {
1593 if (zsk_algorithms[dnskey.algorithm] != 255)
1594 zsk_algorithms[dnskey.algorithm]++;
1596 if (standby_zsk[dnskey.algorithm] != 255)
1597 standby_zsk[dnskey.algorithm]++;
1598 #ifdef ALLOW_KSKLESS_ZONES
1599 allzsksigned = ISC_FALSE;
1602 dns_rdata_freestruct(&dnskey);
1603 dns_rdata_reset(&rdata);
1605 dns_rdataset_disassociate(&keysigs);
1606 dns_rdataset_disassociate(&soaset);
1607 dns_rdataset_disassociate(&soasigs);
1609 #ifdef ALLOW_KSKLESS_ZONES
1611 if (!ignore_kskflag)
1612 fprintf(stderr, "No self signing KSK found. Using "
1613 "self signed ZSK's for active "
1614 "algorithm list.\n");
1615 memcpy(ksk_algorithms, self_algorithms, sizeof(ksk_algorithms));
1617 fprintf(stderr, "warning: not all ZSK's are self "
1622 fatal("No self signed KSK's found");
1626 fprintf(stderr, "Verifying the zone using the following algorithms:");
1627 for (i = 0; i < 256; i++) {
1628 #ifdef ALLOW_KSKLESS_ZONES
1629 if (ksk_algorithms[i] != 0 || zsk_algorithms[i] != 0)
1631 if (ksk_algorithms[i] != 0)
1634 dns_secalg_format(i, algbuf, sizeof(algbuf));
1635 fprintf(stderr, " %s", algbuf);
1638 fprintf(stderr, ".\n");
1640 if (!ignore_kskflag && !keyset_kskonly) {
1641 for (i = 0; i < 256; i++) {
1643 * The counts should both be zero or both be non-zero.
1644 * Mark the algorithm as bad if this is not met.
1646 if ((ksk_algorithms[i] != 0) ==
1647 (zsk_algorithms[i] != 0))
1649 dns_secalg_format(i, algbuf, sizeof(algbuf));
1650 fprintf(stderr, "Missing %s for algorithm %s\n",
1651 (ksk_algorithms[i] != 0)
1653 : "self signing KSK",
1655 bad_algorithms[i] = 1;
1660 * Check that all the other records were signed by keys that are
1661 * present in the DNSKEY RRSET.
1664 dns_fixedname_init(&fname);
1665 name = dns_fixedname_name(&fname);
1666 dns_fixedname_init(&fnextname);
1667 nextname = dns_fixedname_name(&fnextname);
1668 dns_fixedname_init(&fzonecut);
1671 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
1672 check_result(result, "dns_db_createiterator()");
1674 result = dns_dbiterator_first(dbiter);
1675 check_result(result, "dns_dbiterator_first()");
1678 isc_boolean_t isdelegation = ISC_FALSE;
1680 result = dns_dbiterator_current(dbiter, &node, name);
1681 check_dns_dbiterator_current(result);
1682 if (!dns_name_issubdomain(name, gorigin)) {
1683 dns_db_detachnode(gdb, &node);
1684 result = dns_dbiterator_next(dbiter);
1685 if (result == ISC_R_NOMORE)
1688 check_result(result, "dns_dbiterator_next()");
1691 if (delegation(name, node, NULL)) {
1692 zonecut = dns_fixedname_name(&fzonecut);
1693 dns_name_copy(name, zonecut, NULL);
1694 isdelegation = ISC_TRUE;
1696 verifynode(name, node, isdelegation, &keyset,
1697 ksk_algorithms, bad_algorithms);
1698 result = dns_dbiterator_next(dbiter);
1700 while (result == ISC_R_SUCCESS) {
1701 result = dns_dbiterator_current(dbiter, &nextnode,
1703 check_dns_dbiterator_current(result);
1704 if (!dns_name_issubdomain(nextname, gorigin) ||
1706 dns_name_issubdomain(nextname, zonecut)))
1708 dns_db_detachnode(gdb, &nextnode);
1709 result = dns_dbiterator_next(dbiter);
1712 dns_db_detachnode(gdb, &nextnode);
1715 if (result == ISC_R_NOMORE) {
1717 } else if (result != ISC_R_SUCCESS)
1718 fatal("iterating through the database failed: %s",
1719 isc_result_totext(result));
1720 dns_db_detachnode(gdb, &node);
1723 dns_dbiterator_destroy(&dbiter);
1725 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
1726 check_result(result, "dns_db_createiterator()");
1728 for (result = dns_dbiterator_first(dbiter);
1729 result == ISC_R_SUCCESS;
1730 result = dns_dbiterator_next(dbiter) ) {
1731 result = dns_dbiterator_current(dbiter, &node, name);
1732 check_dns_dbiterator_current(result);
1733 verifynode(name, node, ISC_FALSE, &keyset,
1734 ksk_algorithms, bad_algorithms);
1735 dns_db_detachnode(gdb, &node);
1737 dns_dbiterator_destroy(&dbiter);
1739 dns_rdataset_disassociate(&keyset);
1742 * If we made it this far, we have what we consider a properly signed
1743 * zone. Set the good flag.
1745 for (i = 0; i < 256; i++) {
1746 if (bad_algorithms[i] != 0) {
1748 fprintf(stderr, "The zone is not fully signed "
1749 "for the following algorithms:");
1750 dns_secalg_format(i, algbuf, sizeof(algbuf));
1751 fprintf(stderr, " %s", algbuf);
1756 fprintf(stderr, ".\n");
1757 fatal("DNSSEC completeness test failed.");
1760 if (goodksk || ignore_kskflag) {
1762 * Print the success summary.
1764 fprintf(stderr, "Zone signing complete:\n");
1765 for (i = 0; i < 256; i++) {
1766 if ((ksk_algorithms[i] != 0) ||
1767 (standby_ksk[i] != 0) ||
1768 (revoked_zsk[i] != 0) ||
1769 (zsk_algorithms[i] != 0) ||
1770 (standby_zsk[i] != 0) ||
1771 (revoked_zsk[i] != 0)) {
1772 dns_secalg_format(i, algbuf, sizeof(algbuf));
1773 fprintf(stderr, "Algorithm: %s: KSKs: "
1774 "%u active, %u stand-by, %u revoked\n",
1775 algbuf, ksk_algorithms[i],
1776 standby_ksk[i], revoked_ksk[i]);
1777 fprintf(stderr, "%*sZSKs: "
1778 "%u active, %u %s, %u revoked\n",
1779 (int) strlen(algbuf) + 13, "",
1782 keyset_kskonly ? "present" : "stand-by",
1790 * Sign the apex of the zone.
1791 * Note the origin may not be the first node if there are out of zone
1796 dns_dbnode_t *node = NULL;
1797 dns_fixedname_t fixed;
1799 isc_result_t result;
1801 dns_fixedname_init(&fixed);
1802 name = dns_fixedname_name(&fixed);
1803 result = dns_dbiterator_seek(gdbiter, gorigin);
1804 check_result(result, "dns_dbiterator_seek()");
1805 result = dns_dbiterator_current(gdbiter, &node, name);
1806 check_dns_dbiterator_current(result);
1807 signname(node, name);
1808 dumpnode(name, node);
1809 cleannode(gdb, gversion, node);
1810 dns_db_detachnode(gdb, &node);
1811 result = dns_dbiterator_first(gdbiter);
1812 if (result == ISC_R_NOMORE)
1813 finished = ISC_TRUE;
1814 else if (result != ISC_R_SUCCESS)
1815 fatal("failure iterating database: %s",
1816 isc_result_totext(result));
1820 * Assigns a node to a worker thread. This is protected by the master task's
1824 assignwork(isc_task_t *task, isc_task_t *worker) {
1825 dns_fixedname_t *fname;
1829 dns_rdataset_t nsec;
1830 isc_boolean_t found;
1831 isc_result_t result;
1832 static dns_name_t *zonecut = NULL; /* Protected by namelock. */
1833 static dns_fixedname_t fzonecut; /* Protected by namelock. */
1834 static unsigned int ended = 0; /* Protected by namelock. */
1842 if (ended == ntasks) {
1843 isc_task_detach(&task);
1849 fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
1851 fatal("out of memory");
1852 dns_fixedname_init(fname);
1853 name = dns_fixedname_name(fname);
1857 result = dns_dbiterator_current(gdbiter, &node, name);
1858 check_dns_dbiterator_current(result);
1860 * The origin was handled by signapex().
1862 if (dns_name_equal(name, gorigin)) {
1863 dns_db_detachnode(gdb, &node);
1867 * Sort the zone data from the glue and out-of-zone data.
1868 * For NSEC zones nodes with zone data have NSEC records.
1869 * For NSEC3 zones the NSEC3 nodes are zone data but
1870 * outside of the zone name space. For the rest we need
1871 * to track the bottom of zone cuts.
1872 * Nodes which don't need to be signed are dumped here.
1874 dns_rdataset_init(&nsec);
1875 result = dns_db_findrdataset(gdb, node, gversion,
1876 nsec_datatype, 0, 0,
1878 if (dns_rdataset_isassociated(&nsec))
1879 dns_rdataset_disassociate(&nsec);
1880 if (result == ISC_R_SUCCESS) {
1882 } else if (nsec_datatype == dns_rdatatype_nsec3) {
1883 if (dns_name_issubdomain(name, gorigin) &&
1885 !dns_name_issubdomain(name, zonecut))) {
1886 if (delegation(name, node, NULL)) {
1887 dns_fixedname_init(&fzonecut);
1888 zonecut = dns_fixedname_name(&fzonecut);
1889 dns_name_copy(name, zonecut, NULL);
1890 if (!OPTOUT(nsec3flags) ||
1899 dumpnode(name, node);
1900 dns_db_detachnode(gdb, &node);
1904 result = dns_dbiterator_next(gdbiter);
1905 if (result == ISC_R_NOMORE) {
1906 finished = ISC_TRUE;
1908 } else if (result != ISC_R_SUCCESS)
1909 fatal("failure iterating database: %s",
1910 isc_result_totext(result));
1914 if (ended == ntasks) {
1915 isc_task_detach(&task);
1918 isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
1921 sevent = (sevent_t *)
1922 isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
1923 sign, NULL, sizeof(sevent_t));
1925 fatal("failed to allocate event\n");
1927 sevent->node = node;
1928 sevent->fname = fname;
1929 isc_task_send(worker, ISC_EVENT_PTR(&sevent));
1935 * Start a worker task
1938 startworker(isc_task_t *task, isc_event_t *event) {
1941 worker = (isc_task_t *)event->ev_arg;
1942 assignwork(task, worker);
1943 isc_event_free(&event);
1947 * Write a node to the output file, and restart the worker task.
1950 writenode(isc_task_t *task, isc_event_t *event) {
1952 sevent_t *sevent = (sevent_t *)event;
1954 worker = (isc_task_t *)event->ev_sender;
1955 dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
1956 cleannode(gdb, gversion, sevent->node);
1957 dns_db_detachnode(gdb, &sevent->node);
1958 isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
1959 assignwork(task, worker);
1960 isc_event_free(&event);
1964 * Sign a database node.
1967 sign(isc_task_t *task, isc_event_t *event) {
1968 dns_fixedname_t *fname;
1970 sevent_t *sevent, *wevent;
1972 sevent = (sevent_t *)event;
1973 node = sevent->node;
1974 fname = sevent->fname;
1975 isc_event_free(&event);
1977 signname(node, dns_fixedname_name(fname));
1978 wevent = (sevent_t *)
1979 isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
1980 writenode, NULL, sizeof(sevent_t));
1982 fatal("failed to allocate event\n");
1983 wevent->node = node;
1984 wevent->fname = fname;
1985 isc_task_send(master, ISC_EVENT_PTR(&wevent));
1989 * Update / remove the DS RRset. Preserve RRSIG(DS) if possible.
1992 add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) {
1993 dns_rdataset_t dsset;
1994 dns_rdataset_t sigdsset;
1995 isc_result_t result;
1997 dns_rdataset_init(&dsset);
1998 dns_rdataset_init(&sigdsset);
1999 result = dns_db_findrdataset(gdb, node, gversion,
2001 0, 0, &dsset, &sigdsset);
2002 if (result == ISC_R_SUCCESS) {
2003 dns_rdataset_disassociate(&dsset);
2004 result = dns_db_deleterdataset(gdb, node, gversion,
2005 dns_rdatatype_ds, 0);
2006 check_result(result, "dns_db_deleterdataset");
2009 result = loadds(name, nsttl, &dsset);
2010 if (result == ISC_R_SUCCESS) {
2011 result = dns_db_addrdataset(gdb, node, gversion, 0,
2013 check_result(result, "dns_db_addrdataset");
2014 dns_rdataset_disassociate(&dsset);
2015 if (dns_rdataset_isassociated(&sigdsset))
2016 dns_rdataset_disassociate(&sigdsset);
2017 } else if (dns_rdataset_isassociated(&sigdsset)) {
2018 result = dns_db_deleterdataset(gdb, node, gversion,
2019 dns_rdatatype_rrsig,
2021 check_result(result, "dns_db_deleterdataset");
2022 dns_rdataset_disassociate(&sigdsset);
2027 * Remove records of the given type and their signatures.
2030 remove_records(dns_dbnode_t *node, dns_rdatatype_t which) {
2031 isc_result_t result;
2032 dns_rdatatype_t type, covers;
2033 dns_rdatasetiter_t *rdsiter = NULL;
2034 dns_rdataset_t rdataset;
2036 dns_rdataset_init(&rdataset);
2039 * Delete any records of the given type at the apex.
2041 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
2042 check_result(result, "dns_db_allrdatasets()");
2043 for (result = dns_rdatasetiter_first(rdsiter);
2044 result == ISC_R_SUCCESS;
2045 result = dns_rdatasetiter_next(rdsiter)) {
2046 dns_rdatasetiter_current(rdsiter, &rdataset);
2047 type = rdataset.type;
2048 covers = rdataset.covers;
2049 dns_rdataset_disassociate(&rdataset);
2050 if (type == which || covers == which) {
2051 if (which == dns_rdatatype_nsec && !update_chain)
2052 fatal("Zone contains NSEC records. Use -u "
2053 "to update to NSEC3.");
2054 if (which == dns_rdatatype_nsec3param && !update_chain)
2055 fatal("Zone contains NSEC3 chains. Use -u "
2056 "to update to NSEC.");
2057 result = dns_db_deleterdataset(gdb, node, gversion,
2059 check_result(result, "dns_db_deleterdataset()");
2063 dns_rdatasetiter_destroy(&rdsiter);
2067 * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records.
2071 dns_dbiterator_t *dbiter = NULL;
2072 dns_dbnode_t *node = NULL, *nextnode = NULL;
2073 dns_fixedname_t fname, fnextname, fzonecut;
2074 dns_name_t *name, *nextname, *zonecut;
2075 dns_rdataset_t rdataset;
2076 dns_rdatasetiter_t *rdsiter = NULL;
2077 dns_rdatatype_t type, covers;
2078 isc_boolean_t done = ISC_FALSE;
2079 isc_result_t result;
2080 isc_uint32_t nsttl = 0;
2082 dns_rdataset_init(&rdataset);
2083 dns_fixedname_init(&fname);
2084 name = dns_fixedname_name(&fname);
2085 dns_fixedname_init(&fnextname);
2086 nextname = dns_fixedname_name(&fnextname);
2087 dns_fixedname_init(&fzonecut);
2091 * Remove any NSEC3 chains.
2093 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
2094 check_result(result, "dns_db_createiterator()");
2095 for (result = dns_dbiterator_first(dbiter);
2096 result == ISC_R_SUCCESS;
2097 result = dns_dbiterator_next(dbiter)) {
2098 result = dns_dbiterator_current(dbiter, &node, name);
2099 check_dns_dbiterator_current(result);
2100 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
2101 check_result(result, "dns_db_allrdatasets()");
2102 for (result = dns_rdatasetiter_first(rdsiter);
2103 result == ISC_R_SUCCESS;
2104 result = dns_rdatasetiter_next(rdsiter)) {
2105 dns_rdatasetiter_current(rdsiter, &rdataset);
2106 type = rdataset.type;
2107 covers = rdataset.covers;
2108 dns_rdataset_disassociate(&rdataset);
2109 result = dns_db_deleterdataset(gdb, node, gversion,
2111 check_result(result,
2112 "dns_db_deleterdataset(nsec3param/rrsig)");
2114 dns_rdatasetiter_destroy(&rdsiter);
2115 dns_db_detachnode(gdb, &node);
2117 dns_dbiterator_destroy(&dbiter);
2119 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2120 check_result(result, "dns_db_createiterator()");
2122 result = dns_dbiterator_first(dbiter);
2123 check_result(result, "dns_dbiterator_first()");
2126 result = dns_dbiterator_current(dbiter, &node, name);
2127 check_dns_dbiterator_current(result);
2129 * Skip out-of-zone records.
2131 if (!dns_name_issubdomain(name, gorigin)) {
2132 result = dns_dbiterator_next(dbiter);
2133 if (result == ISC_R_NOMORE)
2136 check_result(result, "dns_dbiterator_next()");
2137 dns_db_detachnode(gdb, &node);
2141 if (dns_name_equal(name, gorigin))
2142 remove_records(node, dns_rdatatype_nsec3param);
2144 if (delegation(name, node, &nsttl)) {
2145 zonecut = dns_fixedname_name(&fzonecut);
2146 dns_name_copy(name, zonecut, NULL);
2148 add_ds(name, node, nsttl);
2150 result = dns_dbiterator_next(dbiter);
2152 while (result == ISC_R_SUCCESS) {
2153 isc_boolean_t active = ISC_FALSE;
2154 result = dns_dbiterator_current(dbiter, &nextnode,
2156 check_dns_dbiterator_current(result);
2157 active = active_node(nextnode);
2159 dns_db_detachnode(gdb, &nextnode);
2160 result = dns_dbiterator_next(dbiter);
2163 if (!dns_name_issubdomain(nextname, gorigin) ||
2165 dns_name_issubdomain(nextname, zonecut)))
2167 dns_db_detachnode(gdb, &nextnode);
2168 result = dns_dbiterator_next(dbiter);
2171 dns_db_detachnode(gdb, &nextnode);
2174 if (result == ISC_R_NOMORE) {
2175 dns_name_clone(gorigin, nextname);
2177 } else if (result != ISC_R_SUCCESS)
2178 fatal("iterating through the database failed: %s",
2179 isc_result_totext(result));
2180 dns_dbiterator_pause(dbiter);
2181 result = dns_nsec_build(gdb, gversion, node, nextname,
2183 check_result(result, "dns_nsec_build()");
2184 dns_db_detachnode(gdb, &node);
2187 dns_dbiterator_destroy(&dbiter);
2191 addnsec3param(const unsigned char *salt, size_t salt_length,
2192 unsigned int iterations)
2194 dns_dbnode_t *node = NULL;
2195 dns_rdata_nsec3param_t nsec3param;
2196 unsigned char nsec3parambuf[5 + 255];
2197 dns_rdatalist_t rdatalist;
2198 dns_rdataset_t rdataset;
2199 dns_rdata_t rdata = DNS_RDATA_INIT;
2201 isc_result_t result;
2203 dns_rdataset_init(&rdataset);
2205 nsec3param.common.rdclass = gclass;
2206 nsec3param.common.rdtype = dns_rdatatype_nsec3param;
2207 ISC_LINK_INIT(&nsec3param.common, link);
2208 nsec3param.mctx = NULL;
2209 nsec3param.flags = 0;
2210 nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1;
2211 nsec3param.iterations = iterations;
2212 nsec3param.salt_length = salt_length;
2213 DE_CONST(salt, nsec3param.salt);
2215 isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf));
2216 result = dns_rdata_fromstruct(&rdata, gclass,
2217 dns_rdatatype_nsec3param,
2219 check_result(result, "dns_rdata_fromstruct()");
2220 rdatalist.rdclass = rdata.rdclass;
2221 rdatalist.type = rdata.type;
2222 rdatalist.covers = 0;
2224 ISC_LIST_INIT(rdatalist.rdata);
2225 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
2226 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
2227 check_result(result, "dns_rdatalist_tordataset()");
2229 result = dns_db_findnode(gdb, gorigin, ISC_TRUE, &node);
2230 check_result(result, "dns_db_find(gorigin)");
2233 * Delete any current NSEC3PARAM records.
2235 result = dns_db_deleterdataset(gdb, node, gversion,
2236 dns_rdatatype_nsec3param, 0);
2237 if (result == DNS_R_UNCHANGED)
2238 result = ISC_R_SUCCESS;
2239 check_result(result, "dddnsec3param: dns_db_deleterdataset()");
2241 result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset,
2242 DNS_DBADD_MERGE, NULL);
2243 if (result == DNS_R_UNCHANGED)
2244 result = ISC_R_SUCCESS;
2245 check_result(result, "addnsec3param: dns_db_addrdataset()");
2246 dns_db_detachnode(gdb, &node);
2250 addnsec3(dns_name_t *name, dns_dbnode_t *node,
2251 const unsigned char *salt, size_t salt_length,
2252 unsigned int iterations, hashlist_t *hashlist,
2255 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
2256 const unsigned char *nexthash;
2257 unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE];
2258 dns_fixedname_t hashname;
2259 dns_rdatalist_t rdatalist;
2260 dns_rdataset_t rdataset;
2261 dns_rdata_t rdata = DNS_RDATA_INIT;
2262 isc_result_t result;
2263 dns_dbnode_t *nsec3node = NULL;
2264 char namebuf[DNS_NAME_FORMATSIZE];
2267 dns_name_format(name, namebuf, sizeof(namebuf));
2269 dns_fixedname_init(&hashname);
2270 dns_rdataset_init(&rdataset);
2272 dns_name_downcase(name, name, NULL);
2273 result = dns_nsec3_hashname(&hashname, hash, &hash_length,
2274 name, gorigin, dns_hash_sha1, iterations,
2276 check_result(result, "addnsec3: dns_nsec3_hashname()");
2277 nexthash = hashlist_findnext(hashlist, hash);
2278 result = dns_nsec3_buildrdata(gdb, gversion, node,
2280 DNS_NSEC3_UNKNOWNALG : dns_hash_sha1,
2281 nsec3flags, iterations,
2283 nexthash, ISC_SHA1_DIGESTLENGTH,
2284 nsec3buffer, &rdata);
2285 check_result(result, "addnsec3: dns_nsec3_buildrdata()");
2286 rdatalist.rdclass = rdata.rdclass;
2287 rdatalist.type = rdata.type;
2288 rdatalist.covers = 0;
2289 rdatalist.ttl = ttl;
2290 ISC_LIST_INIT(rdatalist.rdata);
2291 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
2292 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
2293 check_result(result, "dns_rdatalist_tordataset()");
2294 result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname),
2295 ISC_TRUE, &nsec3node);
2296 check_result(result, "addnsec3: dns_db_findnode()");
2297 result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset,
2299 if (result == DNS_R_UNCHANGED)
2300 result = ISC_R_SUCCESS;
2301 check_result(result, "addnsec3: dns_db_addrdataset()");
2302 dns_db_detachnode(gdb, &nsec3node);
2306 * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list.
2308 * Extract the hash from the first label of 'name' then see if it
2309 * is in hashlist. If 'name' is not in the hashlist then delete the
2310 * any NSEC3 records which have the same parameters as the chain we
2313 * XXXMPA Should we also check that it of the form <hash>.<origin>?
2316 nsec3clean(dns_name_t *name, dns_dbnode_t *node,
2317 unsigned int hashalg, unsigned int iterations,
2318 const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
2321 dns_rdata_nsec3_t nsec3;
2322 dns_rdata_t rdata, delrdata;
2323 dns_rdatalist_t rdatalist;
2324 dns_rdataset_t rdataset, delrdataset;
2325 isc_boolean_t delete_rrsigs = ISC_FALSE;
2326 isc_buffer_t target;
2327 isc_result_t result;
2328 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
2329 isc_boolean_t exists;
2332 * Get the first label.
2334 dns_name_getlabel(name, 0, &label);
2337 * We want just the label contents.
2339 isc_region_consume(&label, 1);
2342 * Decode base32hex string.
2344 isc_buffer_init(&target, hash, sizeof(hash) - 1);
2345 result = isc_base32hex_decoderegion(&label, &target);
2346 if (result != ISC_R_SUCCESS)
2349 hash[isc_buffer_usedlength(&target)] = 0;
2351 exists = hashlist_exists(hashlist, hash);
2354 * Verify that the NSEC3 parameters match the current ones
2355 * otherwise we are dealing with a different NSEC3 chain.
2357 dns_rdataset_init(&rdataset);
2358 dns_rdataset_init(&delrdataset);
2360 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3,
2361 0, 0, &rdataset, NULL);
2362 if (result != ISC_R_SUCCESS)
2366 * Delete any NSEC3 records which are not part of the current
2369 for (result = dns_rdataset_first(&rdataset);
2370 result == ISC_R_SUCCESS;
2371 result = dns_rdataset_next(&rdataset)) {
2372 dns_rdata_init(&rdata);
2373 dns_rdataset_current(&rdataset, &rdata);
2374 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
2375 check_result(result, "dns_rdata_tostruct");
2376 if (exists && nsec3.hash == hashalg &&
2377 nsec3.iterations == iterations &&
2378 nsec3.salt_length == salt_length &&
2379 !memcmp(nsec3.salt, salt, salt_length))
2381 rdatalist.rdclass = rdata.rdclass;
2382 rdatalist.type = rdata.type;
2383 rdatalist.covers = 0;
2384 rdatalist.ttl = rdataset.ttl;
2385 ISC_LIST_INIT(rdatalist.rdata);
2386 dns_rdata_init(&delrdata);
2387 dns_rdata_clone(&rdata, &delrdata);
2388 ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link);
2389 result = dns_rdatalist_tordataset(&rdatalist, &delrdataset);
2390 check_result(result, "dns_rdatalist_tordataset()");
2391 result = dns_db_subtractrdataset(gdb, node, gversion,
2392 &delrdataset, 0, NULL);
2393 dns_rdataset_disassociate(&delrdataset);
2394 if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET)
2395 check_result(result, "dns_db_subtractrdataset(NSEC3)");
2396 delete_rrsigs = ISC_TRUE;
2398 dns_rdataset_disassociate(&rdataset);
2399 if (result != ISC_R_NOMORE)
2400 check_result(result, "dns_rdataset_first/next");
2405 * Delete the NSEC3 RRSIGs
2407 result = dns_db_deleterdataset(gdb, node, gversion,
2408 dns_rdatatype_rrsig,
2409 dns_rdatatype_nsec3);
2410 if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
2411 check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))");
2415 rrset_remove_duplicates(dns_name_t *name, dns_rdataset_t *rdataset,
2418 dns_difftuple_t *tuple = NULL;
2419 isc_result_t result;
2420 unsigned int count1 = 0;
2421 dns_rdataset_t tmprdataset;
2423 dns_rdataset_init(&tmprdataset);
2424 for (result = dns_rdataset_first(rdataset);
2425 result == ISC_R_SUCCESS;
2426 result = dns_rdataset_next(rdataset)) {
2427 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2428 unsigned int count2 = 0;
2431 dns_rdataset_current(rdataset, &rdata1);
2432 dns_rdataset_clone(rdataset, &tmprdataset);
2433 for (result = dns_rdataset_first(&tmprdataset);
2434 result == ISC_R_SUCCESS;
2435 result = dns_rdataset_next(&tmprdataset)) {
2436 dns_rdata_t rdata2 = DNS_RDATA_INIT;
2438 if (count1 >= count2)
2440 dns_rdataset_current(&tmprdataset, &rdata2);
2441 if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2442 result = dns_difftuple_create(mctx,
2447 check_result(result, "dns_difftuple_create");
2448 dns_diff_append(diff, &tuple);
2451 dns_rdataset_disassociate(&tmprdataset);
2456 remove_duplicates(void) {
2457 isc_result_t result;
2458 dns_dbiterator_t *dbiter = NULL;
2459 dns_rdatasetiter_t *rdsiter = NULL;
2461 dns_dbnode_t *node = NULL;
2462 dns_rdataset_t rdataset;
2463 dns_fixedname_t fname;
2466 dns_diff_init(mctx, &diff);
2467 dns_fixedname_init(&fname);
2468 name = dns_fixedname_name(&fname);
2469 dns_rdataset_init(&rdataset);
2471 result = dns_db_createiterator(gdb, 0, &dbiter);
2472 check_result(result, "dns_db_createiterator()");
2474 for (result = dns_dbiterator_first(dbiter);
2475 result == ISC_R_SUCCESS;
2476 result = dns_dbiterator_next(dbiter)) {
2478 result = dns_dbiterator_current(dbiter, &node, name);
2479 check_dns_dbiterator_current(result);
2480 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
2481 check_result(result, "dns_db_allrdatasets()");
2482 for (result = dns_rdatasetiter_first(rdsiter);
2483 result == ISC_R_SUCCESS;
2484 result = dns_rdatasetiter_next(rdsiter)) {
2485 dns_rdatasetiter_current(rdsiter, &rdataset);
2486 rrset_remove_duplicates(name, &rdataset, &diff);
2487 dns_rdataset_disassociate(&rdataset);
2489 if (result != ISC_R_NOMORE)
2490 fatal("rdatasets iteration failed.");
2491 dns_rdatasetiter_destroy(&rdsiter);
2492 dns_db_detachnode(gdb, &node);
2494 if (result != ISC_R_NOMORE)
2495 fatal("zone iteration failed.");
2497 if (!ISC_LIST_EMPTY(diff.tuples)) {
2498 result = dns_diff_applysilently(&diff, gdb, gversion);
2499 check_result(result, "dns_diff_applysilently");
2501 dns_diff_clear(&diff);
2502 dns_dbiterator_destroy(&dbiter);
2506 * Generate NSEC3 records for the zone.
2509 nsec3ify(unsigned int hashalg, unsigned int iterations,
2510 const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
2512 dns_dbiterator_t *dbiter = NULL;
2513 dns_dbnode_t *node = NULL, *nextnode = NULL;
2514 dns_fixedname_t fname, fnextname, fzonecut;
2515 dns_name_t *name, *nextname, *zonecut;
2516 dns_rdataset_t rdataset;
2518 isc_boolean_t active;
2519 isc_boolean_t done = ISC_FALSE;
2520 isc_result_t result;
2521 isc_uint32_t nsttl = 0;
2522 unsigned int count, nlabels;
2524 dns_rdataset_init(&rdataset);
2525 dns_fixedname_init(&fname);
2526 name = dns_fixedname_name(&fname);
2527 dns_fixedname_init(&fnextname);
2528 nextname = dns_fixedname_name(&fnextname);
2529 dns_fixedname_init(&fzonecut);
2533 * Walk the zone generating the hash names.
2535 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2536 check_result(result, "dns_db_createiterator()");
2538 result = dns_dbiterator_first(dbiter);
2539 check_result(result, "dns_dbiterator_first()");
2542 result = dns_dbiterator_current(dbiter, &node, name);
2543 check_dns_dbiterator_current(result);
2545 * Skip out-of-zone records.
2547 if (!dns_name_issubdomain(name, gorigin)) {
2548 result = dns_dbiterator_next(dbiter);
2549 if (result == ISC_R_NOMORE)
2552 check_result(result, "dns_dbiterator_next()");
2553 dns_db_detachnode(gdb, &node);
2557 if (dns_name_equal(name, gorigin))
2558 remove_records(node, dns_rdatatype_nsec);
2560 result = dns_dbiterator_next(dbiter);
2562 while (result == ISC_R_SUCCESS) {
2563 result = dns_dbiterator_current(dbiter, &nextnode,
2565 check_dns_dbiterator_current(result);
2566 active = active_node(nextnode);
2568 dns_db_detachnode(gdb, &nextnode);
2569 result = dns_dbiterator_next(dbiter);
2572 if (!dns_name_issubdomain(nextname, gorigin) ||
2574 dns_name_issubdomain(nextname, zonecut))) {
2575 dns_db_detachnode(gdb, &nextnode);
2576 result = dns_dbiterator_next(dbiter);
2579 if (delegation(nextname, nextnode, &nsttl)) {
2580 zonecut = dns_fixedname_name(&fzonecut);
2581 dns_name_copy(nextname, zonecut, NULL);
2583 add_ds(nextname, nextnode, nsttl);
2584 if (OPTOUT(nsec3flags) &&
2585 !secure(nextname, nextnode)) {
2586 dns_db_detachnode(gdb, &nextnode);
2587 result = dns_dbiterator_next(dbiter);
2591 dns_db_detachnode(gdb, &nextnode);
2594 if (result == ISC_R_NOMORE) {
2595 dns_name_copy(gorigin, nextname, NULL);
2597 } else if (result != ISC_R_SUCCESS)
2598 fatal("iterating through the database failed: %s",
2599 isc_result_totext(result));
2600 dns_name_downcase(name, name, NULL);
2601 hashlist_add_dns_name(hashlist, name, hashalg, iterations,
2602 salt, salt_length, ISC_FALSE);
2603 dns_db_detachnode(gdb, &node);
2605 * Add hashs for empty nodes. Use closest encloser logic.
2606 * The closest encloser either has data or is a empty
2607 * node for another <name,nextname> span so we don't add
2608 * it here. Empty labels on nextname are within the span.
2610 dns_name_downcase(nextname, nextname, NULL);
2611 dns_name_fullcompare(name, nextname, &order, &nlabels);
2612 addnowildcardhash(hashlist, name, hashalg, iterations,
2614 count = dns_name_countlabels(nextname);
2615 while (count > nlabels + 1) {
2617 dns_name_split(nextname, count, NULL, nextname);
2618 hashlist_add_dns_name(hashlist, nextname, hashalg,
2619 iterations, salt, salt_length,
2621 addnowildcardhash(hashlist, nextname, hashalg,
2622 iterations, salt, salt_length);
2625 dns_dbiterator_destroy(&dbiter);
2628 * We have all the hashes now so we can sort them.
2630 hashlist_sort(hashlist);
2633 * Check for duplicate hashes. If found the salt needs to
2636 if (hashlist_hasdup(hashlist))
2637 fatal("Duplicate hash detected. Pick a different salt.");
2640 * Generate the nsec3 records.
2645 addnsec3param(salt, salt_length, iterations);
2648 * Clean out NSEC3 records which don't match this chain.
2650 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
2651 check_result(result, "dns_db_createiterator()");
2653 for (result = dns_dbiterator_first(dbiter);
2654 result == ISC_R_SUCCESS;
2655 result = dns_dbiterator_next(dbiter)) {
2656 result = dns_dbiterator_current(dbiter, &node, name);
2657 check_dns_dbiterator_current(result);
2658 nsec3clean(name, node, hashalg, iterations, salt, salt_length,
2660 dns_db_detachnode(gdb, &node);
2662 dns_dbiterator_destroy(&dbiter);
2665 * Generate / complete the new chain.
2667 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2668 check_result(result, "dns_db_createiterator()");
2670 result = dns_dbiterator_first(dbiter);
2671 check_result(result, "dns_dbiterator_first()");
2674 result = dns_dbiterator_current(dbiter, &node, name);
2675 check_dns_dbiterator_current(result);
2677 * Skip out-of-zone records.
2679 if (!dns_name_issubdomain(name, gorigin)) {
2680 result = dns_dbiterator_next(dbiter);
2681 if (result == ISC_R_NOMORE)
2684 check_result(result, "dns_dbiterator_next()");
2685 dns_db_detachnode(gdb, &node);
2688 result = dns_dbiterator_next(dbiter);
2690 while (result == ISC_R_SUCCESS) {
2691 result = dns_dbiterator_current(dbiter, &nextnode,
2693 check_dns_dbiterator_current(result);
2694 active = active_node(nextnode);
2696 dns_db_detachnode(gdb, &nextnode);
2697 result = dns_dbiterator_next(dbiter);
2700 if (!dns_name_issubdomain(nextname, gorigin) ||
2702 dns_name_issubdomain(nextname, zonecut))) {
2703 dns_db_detachnode(gdb, &nextnode);
2704 result = dns_dbiterator_next(dbiter);
2707 if (delegation(nextname, nextnode, NULL)) {
2708 zonecut = dns_fixedname_name(&fzonecut);
2709 dns_name_copy(nextname, zonecut, NULL);
2710 if (OPTOUT(nsec3flags) &&
2711 !secure(nextname, nextnode)) {
2712 dns_db_detachnode(gdb, &nextnode);
2713 result = dns_dbiterator_next(dbiter);
2717 dns_db_detachnode(gdb, &nextnode);
2720 if (result == ISC_R_NOMORE) {
2721 dns_name_copy(gorigin, nextname, NULL);
2723 } else if (result != ISC_R_SUCCESS)
2724 fatal("iterating through the database failed: %s",
2725 isc_result_totext(result));
2727 * We need to pause here to release the lock on the database.
2729 dns_dbiterator_pause(dbiter);
2730 addnsec3(name, node, salt, salt_length, iterations,
2731 hashlist, zone_soa_min_ttl);
2732 dns_db_detachnode(gdb, &node);
2734 * Add NSEC3's for empty nodes. Use closest encloser logic.
2736 dns_name_fullcompare(name, nextname, &order, &nlabels);
2737 count = dns_name_countlabels(nextname);
2738 while (count > nlabels + 1) {
2740 dns_name_split(nextname, count, NULL, nextname);
2741 addnsec3(nextname, NULL, salt, salt_length,
2742 iterations, hashlist, zone_soa_min_ttl);
2745 dns_dbiterator_destroy(&dbiter);
2749 * Load the zone file from disk
2752 loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
2755 dns_fixedname_t fname;
2757 isc_result_t result;
2759 len = strlen(origin);
2760 isc_buffer_init(&b, origin, len);
2761 isc_buffer_add(&b, len);
2763 dns_fixedname_init(&fname);
2764 name = dns_fixedname_name(&fname);
2765 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
2766 if (result != ISC_R_SUCCESS)
2767 fatal("failed converting name '%s' to dns format: %s",
2768 origin, isc_result_totext(result));
2770 result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
2771 rdclass, 0, NULL, db);
2772 check_result(result, "dns_db_create()");
2774 result = dns_db_load2(*db, file, inputformat);
2775 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
2776 fatal("failed loading zone from '%s': %s",
2777 file, isc_result_totext(result));
2781 * Finds all public zone keys in the zone, and attempts to load the
2782 * private keys from disk.
2785 loadzonekeys(isc_boolean_t preserve_keys, isc_boolean_t load_public) {
2787 dns_dbversion_t *currentversion = NULL;
2788 isc_result_t result;
2789 dns_rdataset_t rdataset, keysigs, soasigs;
2792 result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node);
2793 if (result != ISC_R_SUCCESS)
2794 fatal("failed to find the zone's origin: %s",
2795 isc_result_totext(result));
2797 dns_db_currentversion(gdb, ¤tversion);
2799 dns_rdataset_init(&rdataset);
2800 dns_rdataset_init(&soasigs);
2801 dns_rdataset_init(&keysigs);
2803 /* Make note of the keys which signed the SOA, if any */
2804 result = dns_db_findrdataset(gdb, node, currentversion,
2805 dns_rdatatype_soa, 0, 0,
2806 &rdataset, &soasigs);
2807 if (result != ISC_R_SUCCESS)
2810 /* Preserve the TTL of the DNSKEY RRset, if any */
2811 dns_rdataset_disassociate(&rdataset);
2812 result = dns_db_findrdataset(gdb, node, currentversion,
2813 dns_rdatatype_dnskey, 0, 0,
2814 &rdataset, &keysigs);
2816 if (result != ISC_R_SUCCESS)
2819 if (set_keyttl && keyttl != rdataset.ttl) {
2820 fprintf(stderr, "User-specified TTL (%d) conflicts "
2821 "with existing DNSKEY RRset TTL.\n",
2823 fprintf(stderr, "Imported keys will use the RRSet "
2824 "TTL (%d) instead.\n",
2827 keyttl = rdataset.ttl;
2829 /* Load keys corresponding to the existing DNSKEY RRset. */
2830 result = dns_dnssec_keylistfromrdataset(gorigin, directory, mctx,
2831 &rdataset, &keysigs, &soasigs,
2832 preserve_keys, load_public,
2834 if (result != ISC_R_SUCCESS)
2835 fatal("failed to load the zone keys: %s",
2836 isc_result_totext(result));
2839 if (dns_rdataset_isassociated(&rdataset))
2840 dns_rdataset_disassociate(&rdataset);
2841 if (dns_rdataset_isassociated(&keysigs))
2842 dns_rdataset_disassociate(&keysigs);
2843 if (dns_rdataset_isassociated(&soasigs))
2844 dns_rdataset_disassociate(&soasigs);
2845 dns_db_detachnode(gdb, &node);
2846 dns_db_closeversion(gdb, ¤tversion, ISC_FALSE);
2850 loadexplicitkeys(char *keyfiles[], int n, isc_boolean_t setksk) {
2851 isc_result_t result;
2854 for (i = 0; i < n; i++) {
2855 dns_dnsseckey_t *key = NULL;
2856 dst_key_t *newkey = NULL;
2858 result = dst_key_fromnamedfile(keyfiles[i], directory,
2862 if (result != ISC_R_SUCCESS)
2863 fatal("cannot load dnskey %s: %s", keyfiles[i],
2864 isc_result_totext(result));
2866 if (!dns_name_equal(gorigin, dst_key_name(newkey)))
2867 fatal("key %s not at origin\n", keyfiles[i]);
2869 if (!dst_key_isprivate(newkey))
2870 fatal("cannot sign zone with non-private dnskey %s",
2873 /* Skip any duplicates */
2874 for (key = ISC_LIST_HEAD(keylist);
2876 key = ISC_LIST_NEXT(key, link)) {
2877 if (dst_key_id(key->key) == dst_key_id(newkey) &&
2878 dst_key_alg(key->key) == dst_key_alg(newkey))
2883 /* We haven't seen this key before */
2884 dns_dnsseckey_create(mctx, &newkey, &key);
2885 ISC_LIST_APPEND(keylist, key, link);
2886 key->source = dns_keysource_user;
2888 dst_key_free(&key->key);
2892 key->force_publish = ISC_TRUE;
2893 key->force_sign = ISC_TRUE;
2896 key->ksk = ISC_TRUE;
2901 report(const char *format, ...) {
2903 va_start(args, format);
2904 vfprintf(stderr, format, args);
2910 build_final_keylist() {
2911 isc_result_t result;
2912 dns_dbversion_t *ver = NULL;
2914 dns_dnsseckeylist_t matchkeys;
2915 char name[DNS_NAME_FORMATSIZE];
2918 * Find keys that match this zone in the key repository.
2920 ISC_LIST_INIT(matchkeys);
2921 result = dns_dnssec_findmatchingkeys(gorigin, directory,
2923 if (result == ISC_R_NOTFOUND)
2924 result = ISC_R_SUCCESS;
2925 check_result(result, "dns_dnssec_findmatchingkeys");
2927 result = dns_db_newversion(gdb, &ver);
2928 check_result(result, "dns_db_newversion");
2930 dns_diff_init(mctx, &diff);
2933 * Update keylist with information from from the key repository.
2935 dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl,
2936 &diff, ignore_kskflag, mctx, report);
2938 dns_name_format(gorigin, name, sizeof(name));
2940 result = dns_diff_applysilently(&diff, gdb, ver);
2941 if (result != ISC_R_SUCCESS)
2942 fatal("failed to update DNSKEY RRset at node '%s': %s",
2943 name, isc_result_totext(result));
2945 dns_db_closeversion(gdb, &ver, ISC_TRUE);
2947 dns_diff_clear(&diff);
2951 warnifallksk(dns_db_t *db) {
2952 dns_dbversion_t *currentversion = NULL;
2953 dns_dbnode_t *node = NULL;
2954 dns_rdataset_t rdataset;
2955 dns_rdata_t rdata = DNS_RDATA_INIT;
2956 isc_result_t result;
2957 dns_rdata_dnskey_t dnskey;
2958 isc_boolean_t have_non_ksk = ISC_FALSE;
2960 dns_db_currentversion(db, ¤tversion);
2962 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
2963 if (result != ISC_R_SUCCESS)
2964 fatal("failed to find the zone's origin: %s",
2965 isc_result_totext(result));
2967 dns_rdataset_init(&rdataset);
2968 result = dns_db_findrdataset(db, node, currentversion,
2969 dns_rdatatype_dnskey, 0, 0, &rdataset,
2971 if (result != ISC_R_SUCCESS)
2972 fatal("failed to find keys at the zone apex: %s",
2973 isc_result_totext(result));
2974 result = dns_rdataset_first(&rdataset);
2975 check_result(result, "dns_rdataset_first");
2976 while (result == ISC_R_SUCCESS) {
2977 dns_rdata_reset(&rdata);
2978 dns_rdataset_current(&rdataset, &rdata);
2979 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2980 check_result(result, "dns_rdata_tostruct");
2981 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
2982 have_non_ksk = ISC_TRUE;
2983 result = ISC_R_NOMORE;
2985 result = dns_rdataset_next(&rdataset);
2986 dns_rdata_freestruct(&dnskey);
2988 dns_rdataset_disassociate(&rdataset);
2989 dns_db_detachnode(db, &node);
2990 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
2991 if (!have_non_ksk && !ignore_kskflag) {
2992 if (disable_zone_check)
2993 fprintf(stderr, "%s: warning: No non-KSK DNSKEY found; "
2994 "supply a ZSK or use '-z'.\n",
2997 fatal("No non-KSK DNSKEY found; "
2998 "supply a ZSK or use '-z'.");
3003 set_nsec3params(isc_boolean_t update_chain, isc_boolean_t set_salt,
3004 isc_boolean_t set_optout, isc_boolean_t set_iter)
3006 isc_result_t result;
3007 dns_dbversion_t *ver = NULL;
3008 dns_dbnode_t *node = NULL;
3009 dns_rdataset_t rdataset;
3010 dns_rdata_t rdata = DNS_RDATA_INIT;
3011 dns_rdata_nsec3_t nsec3;
3012 dns_fixedname_t fname;
3013 dns_name_t *hashname;
3014 unsigned char orig_salt[256];
3015 size_t orig_saltlen;
3016 dns_hash_t orig_hash;
3017 isc_uint16_t orig_iter;
3019 dns_db_currentversion(gdb, &ver);
3020 dns_rdataset_init(&rdataset);
3022 orig_saltlen = sizeof(orig_salt);
3023 result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL,
3024 &orig_iter, orig_salt,
3026 if (result != ISC_R_SUCCESS)
3029 nsec_datatype = dns_rdatatype_nsec3;
3031 if (!update_chain && set_salt) {
3032 if (salt_length != orig_saltlen ||
3033 memcmp(saltbuf, orig_salt, salt_length) != 0)
3034 fatal("An NSEC3 chain exists with a different salt. "
3035 "Use -u to update it.");
3036 } else if (!set_salt) {
3037 salt_length = orig_saltlen;
3038 memcpy(saltbuf, orig_salt, orig_saltlen);
3042 if (!update_chain && set_iter) {
3043 if (nsec3iter != orig_iter)
3044 fatal("An NSEC3 chain exists with different "
3045 "iterations. Use -u to update it.");
3046 } else if (!set_iter)
3047 nsec3iter = orig_iter;
3050 * Find an NSEC3 record to get the current OPTOUT value.
3051 * (This assumes all NSEC3 records agree.)
3054 dns_fixedname_init(&fname);
3055 hashname = dns_fixedname_name(&fname);
3056 result = dns_nsec3_hashname(&fname, NULL, NULL,
3057 gorigin, gorigin, dns_hash_sha1,
3058 orig_iter, orig_salt, orig_saltlen);
3059 check_result(result, "dns_nsec3_hashname");
3061 result = dns_db_findnsec3node(gdb, hashname, ISC_FALSE, &node);
3062 if (result != ISC_R_SUCCESS)
3065 result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3,
3066 0, 0, &rdataset, NULL);
3067 if (result != ISC_R_SUCCESS)
3070 result = dns_rdataset_first(&rdataset);
3071 check_result(result, "dns_rdataset_first");
3072 dns_rdataset_current(&rdataset, &rdata);
3073 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
3074 check_result(result, "dns_rdata_tostruct");
3076 if (!update_chain && set_optout) {
3077 if (nsec3flags != nsec3.flags)
3078 fatal("An NSEC3 chain exists with%s OPTOUT. "
3079 "Use -u -%s to %s it.",
3080 OPTOUT(nsec3.flags) ? "" : "out",
3081 OPTOUT(nsec3.flags) ? "AA" : "A",
3082 OPTOUT(nsec3.flags) ? "clear" : "set");
3083 } else if (!set_optout)
3084 nsec3flags = nsec3.flags;
3086 dns_rdata_freestruct(&nsec3);
3089 if (dns_rdataset_isassociated(&rdataset))
3090 dns_rdataset_disassociate(&rdataset);
3092 dns_db_detachnode(gdb, &node);
3093 dns_db_closeversion(gdb, &ver, ISC_FALSE);
3097 writeset(const char *prefix, dns_rdatatype_t type) {
3099 char namestr[DNS_NAME_FORMATSIZE];
3100 dns_db_t *db = NULL;
3101 dns_dbversion_t *version = NULL;
3103 dns_difftuple_t *tuple = NULL;
3104 dns_fixedname_t fixed;
3106 dns_rdata_t rdata, ds;
3107 isc_boolean_t have_ksk = ISC_FALSE;
3108 isc_boolean_t have_non_ksk = ISC_FALSE;
3110 isc_buffer_t namebuf;
3112 isc_result_t result;
3113 dns_dnsseckey_t *key, *tmpkey;
3114 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
3115 unsigned char keybuf[DST_KEY_MAXSIZE];
3116 unsigned int filenamelen;
3117 const dns_master_style_t *style =
3118 (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
3120 isc_buffer_init(&namebuf, namestr, sizeof(namestr));
3121 result = dns_name_tofilenametext(gorigin, ISC_FALSE, &namebuf);
3122 check_result(result, "dns_name_tofilenametext");
3123 isc_buffer_putuint8(&namebuf, 0);
3124 filenamelen = strlen(prefix) + strlen(namestr);
3126 filenamelen += strlen(dsdir) + 1;
3127 filename = isc_mem_get(mctx, filenamelen + 1);
3128 if (filename == NULL)
3129 fatal("out of memory");
3131 sprintf(filename, "%s/", dsdir);
3134 strcat(filename, prefix);
3135 strcat(filename, namestr);
3137 dns_diff_init(mctx, &diff);
3139 if (type == dns_rdatatype_dlv) {
3141 unsigned int labels;
3143 dns_name_init(&tname, NULL);
3144 dns_fixedname_init(&fixed);
3145 name = dns_fixedname_name(&fixed);
3146 labels = dns_name_countlabels(gorigin);
3147 dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
3148 result = dns_name_concatenate(&tname, dlv, name, NULL);
3149 check_result(result, "dns_name_concatenate");
3153 for (key = ISC_LIST_HEAD(keylist);
3155 key = ISC_LIST_NEXT(key, link))
3157 if (REVOKE(key->key))
3160 have_ksk = ISC_TRUE;
3161 have_non_ksk = ISC_FALSE;
3163 have_ksk = ISC_FALSE;
3164 have_non_ksk = ISC_TRUE;
3166 for (tmpkey = ISC_LIST_HEAD(keylist);
3168 tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
3169 if (dst_key_alg(key->key) != dst_key_alg(tmpkey->key))
3171 if (REVOKE(tmpkey->key))
3174 have_ksk = ISC_TRUE;
3176 have_non_ksk = ISC_TRUE;
3178 if (have_ksk && have_non_ksk && !isksk(key))
3180 dns_rdata_init(&rdata);
3181 dns_rdata_init(&ds);
3182 isc_buffer_init(&b, keybuf, sizeof(keybuf));
3183 result = dst_key_todns(key->key, &b);
3184 check_result(result, "dst_key_todns");
3185 isc_buffer_usedregion(&b, &r);
3186 dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
3187 if (type != dns_rdatatype_dnskey) {
3188 result = dns_ds_buildrdata(gorigin, &rdata,
3191 check_result(result, "dns_ds_buildrdata");
3192 if (type == dns_rdatatype_dlv)
3193 ds.type = dns_rdatatype_dlv;
3194 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
3195 name, 0, &ds, &tuple);
3196 check_result(result, "dns_difftuple_create");
3197 dns_diff_append(&diff, &tuple);
3199 dns_rdata_reset(&ds);
3200 result = dns_ds_buildrdata(gorigin, &rdata,
3201 DNS_DSDIGEST_SHA256,
3203 check_result(result, "dns_ds_buildrdata");
3204 if (type == dns_rdatatype_dlv)
3205 ds.type = dns_rdatatype_dlv;
3206 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
3207 name, 0, &ds, &tuple);
3210 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
3211 gorigin, zone_soa_min_ttl,
3213 check_result(result, "dns_difftuple_create");
3214 dns_diff_append(&diff, &tuple);
3217 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
3218 gclass, 0, NULL, &db);
3219 check_result(result, "dns_db_create");
3221 result = dns_db_newversion(db, &version);
3222 check_result(result, "dns_db_newversion");
3224 result = dns_diff_apply(&diff, db, version);
3225 check_result(result, "dns_diff_apply");
3226 dns_diff_clear(&diff);
3228 result = dns_master_dump(mctx, db, version, style, filename);
3229 check_result(result, "dns_master_dump");
3231 isc_mem_put(mctx, filename, filenamelen + 1);
3233 dns_db_closeversion(db, &version, ISC_FALSE);
3238 print_time(FILE *fp) {
3241 if (outputformat != dns_masterformat_text)
3244 currenttime = time(NULL);
3245 fprintf(fp, "; File written on %s", ctime(¤ttime));
3249 print_version(FILE *fp) {
3250 if (outputformat != dns_masterformat_text)
3253 fprintf(fp, "; dnssec_signzone version " VERSION "\n");
3256 ISC_PLATFORM_NORETURN_PRE static void
3257 usage(void) ISC_PLATFORM_NORETURN_POST;
3261 fprintf(stderr, "Usage:\n");
3262 fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
3264 fprintf(stderr, "\n");
3266 fprintf(stderr, "Version: %s\n", VERSION);
3268 fprintf(stderr, "Options: (default value in parenthesis) \n");
3269 fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n"
3270 "\t\tfor the zone and determines how they are to "
3272 fprintf(stderr, "\t-K directory:\n");
3273 fprintf(stderr, "\t\tdirectory to find key files (.)\n");
3274 fprintf(stderr, "\t-d directory:\n");
3275 fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n");
3276 fprintf(stderr, "\t-g:\t");
3277 fprintf(stderr, "update DS records based on child zones' "
3279 fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
3280 fprintf(stderr, "\t\tRRSIG start time - absolute|offset (now - 1 hour)\n");
3281 fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
3282 fprintf(stderr, "\t\tRRSIG end time - absolute|from start|from now "
3283 "(now + 30 days)\n");
3284 fprintf(stderr, "\t-i interval:\n");
3285 fprintf(stderr, "\t\tcycle interval - resign "
3286 "if < interval from end ( (end-start)/4 )\n");
3287 fprintf(stderr, "\t-j jitter:\n");
3288 fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n");
3289 fprintf(stderr, "\t-v debuglevel (0)\n");
3290 fprintf(stderr, "\t-o origin:\n");
3291 fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
3292 fprintf(stderr, "\t-f outfile:\n");
3293 fprintf(stderr, "\t\tfile the signed zone is written in "
3294 "(zonefile + .signed)\n");
3295 fprintf(stderr, "\t-I format:\n");
3296 fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
3297 fprintf(stderr, "\t-O format:\n");
3298 fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
3299 fprintf(stderr, "\t-N format:\n");
3300 fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
3301 fprintf(stderr, "\t-r randomdev:\n");
3302 fprintf(stderr, "\t\ta file containing random data\n");
3303 fprintf(stderr, "\t-a:\t");
3304 fprintf(stderr, "verify generated signatures\n");
3305 fprintf(stderr, "\t-c class (IN)\n");
3306 fprintf(stderr, "\t-E engine:\n");
3308 fprintf(stderr, "\t\tname of an OpenSSL engine to use "
3309 "(default is \"pkcs11\")\n");
3311 fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
3313 fprintf(stderr, "\t-p:\t");
3314 fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
3315 fprintf(stderr, "\t-P:\t");
3316 fprintf(stderr, "disable post-sign verification\n");
3317 fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n");
3318 fprintf(stderr, "\t-t:\t");
3319 fprintf(stderr, "print statistics\n");
3320 fprintf(stderr, "\t-u:\t");
3321 fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n");
3322 fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n");
3323 fprintf(stderr, "\t-z:\tsign all records with KSKs\n");
3324 fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n"
3325 "\t\twith older versions of dnssec-signzone -g\n");
3326 fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
3327 fprintf(stderr, "\t-k key_signing_key\n");
3328 fprintf(stderr, "\t-l lookasidezone\n");
3329 fprintf(stderr, "\t-3 NSEC3 salt\n");
3330 fprintf(stderr, "\t-H NSEC3 iterations (10)\n");
3331 fprintf(stderr, "\t-A NSEC3 optout\n");
3333 fprintf(stderr, "\n");
3335 fprintf(stderr, "Signing Keys: ");
3336 fprintf(stderr, "(default: all zone keys that have private keys)\n");
3337 fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
3342 removetempfile(void) {
3344 isc_file_remove(tempfile);
3348 print_stats(isc_time_t *timer_start, isc_time_t *timer_finish,
3349 isc_time_t *sign_start, isc_time_t *sign_finish)
3351 isc_uint64_t time_us; /* Time in microseconds */
3352 isc_uint64_t time_ms; /* Time in milliseconds */
3353 isc_uint64_t sig_ms; /* Signatures per millisecond */
3355 printf("Signatures generated: %10d\n", nsigned);
3356 printf("Signatures retained: %10d\n", nretained);
3357 printf("Signatures dropped: %10d\n", ndropped);
3358 printf("Signatures successfully verified: %10d\n", nverified);
3359 printf("Signatures unsuccessfully verified: %10d\n", nverifyfailed);
3361 time_us = isc_time_microdiff(sign_finish, sign_start);
3362 time_ms = time_us / 1000;
3363 printf("Signing time in seconds: %7u.%03u\n",
3364 (unsigned int) (time_ms / 1000),
3365 (unsigned int) (time_ms % 1000));
3367 sig_ms = ((isc_uint64_t)nsigned * 1000000000) / time_us;
3368 printf("Signatures per second: %7u.%03u\n",
3369 (unsigned int) sig_ms / 1000,
3370 (unsigned int) sig_ms % 1000);
3373 time_us = isc_time_microdiff(timer_finish, timer_start);
3374 time_ms = time_us / 1000;
3375 printf("Runtime in seconds: %7u.%03u\n",
3376 (unsigned int) (time_ms / 1000),
3377 (unsigned int) (time_ms % 1000));
3381 main(int argc, char *argv[]) {
3383 char *startstr = NULL, *endstr = NULL, *classname = NULL;
3384 char *origin = NULL, *file = NULL, *output = NULL;
3385 char *inputformatstr = NULL, *outputformatstr = NULL;
3386 char *serialformatstr = NULL;
3387 char *dskeyfile[MAXDSKEYS];
3390 isc_time_t timer_start, timer_finish;
3391 isc_time_t sign_start, sign_finish;
3392 dns_dnsseckey_t *key;
3393 isc_result_t result;
3394 isc_log_t *log = NULL;
3395 isc_boolean_t pseudorandom = ISC_FALSE;
3397 const char *engine = "pkcs11";
3399 const char *engine = NULL;
3401 unsigned int eflags;
3402 isc_boolean_t free_output = ISC_FALSE;
3404 dns_rdataclass_t rdclass;
3405 isc_task_t **tasks = NULL;
3408 hashlist_t hashlist;
3409 isc_boolean_t smartsign = ISC_FALSE;
3410 isc_boolean_t make_keyset = ISC_FALSE;
3411 isc_boolean_t set_salt = ISC_FALSE;
3412 isc_boolean_t set_optout = ISC_FALSE;
3413 isc_boolean_t set_iter = ISC_FALSE;
3415 #define CMDLINE_FLAGS \
3416 "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:l:m:n:N:o:O:pPr:s:ST:tuUv:xz"
3419 * Process memory debugging argument first.
3421 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3424 if (strcasecmp(isc_commandline_argument, "record") == 0)
3425 isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
3426 if (strcasecmp(isc_commandline_argument, "trace") == 0)
3427 isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
3428 if (strcasecmp(isc_commandline_argument, "usage") == 0)
3429 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
3430 if (strcasecmp(isc_commandline_argument, "size") == 0)
3431 isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
3432 if (strcasecmp(isc_commandline_argument, "mctx") == 0)
3433 isc_mem_debugging |= ISC_MEM_DEBUGCTX;
3439 isc_commandline_reset = ISC_TRUE;
3441 masterstyle = &dns_master_style_explicitttl;
3443 check_result(isc_app_start(), "isc_app_start");
3445 result = isc_mem_create(0, 0, &mctx);
3446 if (result != ISC_R_SUCCESS)
3447 fatal("out of memory");
3449 dns_result_register();
3451 isc_commandline_errprint = ISC_FALSE;
3453 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3456 set_salt = ISC_TRUE;
3457 nsec_datatype = dns_rdatatype_nsec3;
3458 if (strcmp(isc_commandline_argument, "-") != 0) {
3459 isc_buffer_t target;
3462 sarg = isc_commandline_argument;
3463 isc_buffer_init(&target, saltbuf,
3465 result = isc_hex_decodestring(sarg, &target);
3466 check_result(result,
3467 "isc_hex_decodestring(salt)");
3468 salt_length = isc_buffer_usedlength(&target);
3473 set_optout = ISC_TRUE;
3474 if (OPTOUT(nsec3flags))
3475 nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT;
3477 nsec3flags |= DNS_NSEC3FLAG_OPTOUT;
3481 tryverify = ISC_TRUE;
3485 make_keyset = ISC_TRUE;
3489 classname = isc_commandline_argument;
3493 dsdir = isc_commandline_argument;
3494 if (strlen(dsdir) == 0U)
3495 fatal("DS directory must be non-empty string");
3496 result = try_dir(dsdir);
3497 if (result != ISC_R_SUCCESS)
3498 fatal("cannot open directory %s: %s",
3499 dsdir, isc_result_totext(result));
3503 engine = isc_commandline_argument;
3507 endstr = isc_commandline_argument;
3511 output = isc_commandline_argument;
3515 generateds = ISC_TRUE;
3519 set_iter = ISC_TRUE;
3520 nsec3iter = strtoul(isc_commandline_argument, &endp, 0);
3522 fatal("iterations must be numeric");
3523 if (nsec3iter > 0xffffU)
3524 fatal("iterations too big");
3532 inputformatstr = isc_commandline_argument;
3537 cycle = strtol(isc_commandline_argument, &endp, 0);
3538 if (*endp != '\0' || cycle < 0)
3539 fatal("cycle period must be numeric and "
3545 jitter = strtol(isc_commandline_argument, &endp, 0);
3546 if (*endp != '\0' || jitter < 0)
3547 fatal("jitter must be numeric and positive");
3551 directory = isc_commandline_argument;
3555 if (ndskeys == MAXDSKEYS)
3556 fatal("too many key-signing keys specified");
3557 dskeyfile[ndskeys++] = isc_commandline_argument;
3561 len = strlen(isc_commandline_argument);
3562 isc_buffer_init(&b, isc_commandline_argument, len);
3563 isc_buffer_add(&b, len);
3565 dns_fixedname_init(&dlv_fixed);
3566 dlv = dns_fixedname_name(&dlv_fixed);
3567 result = dns_name_fromtext(dlv, &b, dns_rootname, 0,
3569 check_result(result, "dns_name_fromtext(dlv)");
3576 serialformatstr = isc_commandline_argument;
3581 ntasks = strtol(isc_commandline_argument, &endp, 0);
3582 if (*endp != '\0' || ntasks > ISC_INT32_MAX)
3583 fatal("number of cpus must be numeric");
3587 outputformatstr = isc_commandline_argument;
3591 origin = isc_commandline_argument;
3595 disable_zone_check = ISC_TRUE;
3599 pseudorandom = ISC_TRUE;
3603 setup_entropy(mctx, isc_commandline_argument, &ectx);
3607 smartsign = ISC_TRUE;
3611 startstr = isc_commandline_argument;
3616 set_keyttl = ISC_TRUE;
3617 keyttl = strtottl(isc_commandline_argument);
3621 printstats = ISC_TRUE;
3624 case 'U': /* Undocumented for testing only. */
3625 unknownalg = ISC_TRUE;
3629 update_chain = ISC_TRUE;
3634 verbose = strtol(isc_commandline_argument, &endp, 0);
3636 fatal("verbose level must be numeric");
3640 keyset_kskonly = ISC_TRUE;
3644 ignore_kskflag = ISC_TRUE;
3648 /* Reserved for FIPS mode */
3651 if (isc_commandline_option != '?')
3652 fprintf(stderr, "%s: invalid argument -%c\n",
3653 program, isc_commandline_option);
3658 fprintf(stderr, "%s: unhandled option -%c\n",
3659 program, isc_commandline_option);
3665 setup_entropy(mctx, NULL, &ectx);
3666 eflags = ISC_ENTROPY_BLOCKING;
3668 eflags |= ISC_ENTROPY_GOODONLY;
3670 result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
3671 if (result != ISC_R_SUCCESS)
3672 fatal("could not create hash context");
3674 result = dst_lib_init2(mctx, ectx, engine, eflags);
3675 if (result != ISC_R_SUCCESS)
3676 fatal("could not initialize dst: %s",
3677 isc_result_totext(result));
3679 isc_stdtime_get(&now);
3681 if (startstr != NULL) {
3682 starttime = strtotime(startstr, now, now);
3684 starttime = now - 3600; /* Allow for some clock skew. */
3686 if (endstr != NULL) {
3687 endtime = strtotime(endstr, now, starttime);
3689 endtime = starttime + (30 * 24 * 60 * 60);
3692 cycle = (endtime - starttime) / 4;
3695 ntasks = isc_os_ncpus() * 2;
3696 vbprintf(4, "using %d cpus\n", ntasks);
3698 rdclass = strtoclass(classname);
3700 if (directory == NULL)
3703 setup_logging(verbose, mctx, &log);
3705 argc -= isc_commandline_index;
3706 argv += isc_commandline_index;
3719 if (output == NULL) {
3720 free_output = ISC_TRUE;
3721 output = isc_mem_allocate(mctx,
3722 strlen(file) + strlen(".signed") + 1);
3724 fatal("out of memory");
3725 sprintf(output, "%s.signed", file);
3728 if (inputformatstr != NULL) {
3729 if (strcasecmp(inputformatstr, "text") == 0)
3730 inputformat = dns_masterformat_text;
3731 else if (strcasecmp(inputformatstr, "raw") == 0)
3732 inputformat = dns_masterformat_raw;
3734 fatal("unknown file format: %s\n", inputformatstr);
3737 if (outputformatstr != NULL) {
3738 if (strcasecmp(outputformatstr, "text") == 0)
3739 outputformat = dns_masterformat_text;
3740 else if (strcasecmp(outputformatstr, "raw") == 0)
3741 outputformat = dns_masterformat_raw;
3743 fatal("unknown file format: %s\n", outputformatstr);
3746 if (serialformatstr != NULL) {
3747 if (strcasecmp(serialformatstr, "keep") == 0)
3748 serialformat = SOA_SERIAL_KEEP;
3749 else if (strcasecmp(serialformatstr, "increment") == 0 ||
3750 strcasecmp(serialformatstr, "incr") == 0)
3751 serialformat = SOA_SERIAL_INCREMENT;
3752 else if (strcasecmp(serialformatstr, "unixtime") == 0)
3753 serialformat = SOA_SERIAL_UNIXTIME;
3755 fatal("unknown soa serial format: %s\n",
3759 result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL,
3760 0, 24, 0, 0, 0, 8, mctx);
3761 check_result(result, "dns_master_stylecreate");
3764 TIME_NOW(&timer_start);
3765 loadzone(file, origin, rdclass, &gdb);
3766 gorigin = dns_db_origin(gdb);
3767 gclass = dns_db_class(gdb);
3774 * Check for any existing NSEC3 parameters in the zone,
3775 * and use them as defaults if -u was not specified.
3777 if (update_chain && !set_optout && !set_iter && !set_salt)
3778 nsec_datatype = dns_rdatatype_nsec;
3780 set_nsec3params(update_chain, set_salt, set_optout, set_iter);
3783 isc_boolean_t answer;
3784 hash_length = dns_nsec3_hashlength(dns_hash_sha1);
3785 hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2,
3787 result = dns_nsec_nseconly(gdb, gversion, &answer);
3788 check_result(result, "dns_nsec_nseconly");
3790 fatal("NSEC3 generation requested with "
3791 "NSEC only DNSKEY");
3795 * We need to do this early on, as we start messing with the list
3796 * of keys rather early.
3798 ISC_LIST_INIT(keylist);
3799 isc_rwlock_init(&keylist_lock, 0, 0);
3802 * Fill keylist with:
3803 * 1) Keys listed in the DNSKEY set that have
3804 * private keys associated, *if* no keys were
3805 * set on the command line.
3806 * 2) ZSKs set on the command line
3807 * 3) KSKs set on the command line
3808 * 4) Any keys remaining in the DNSKEY set which
3809 * do not have private keys associated and were
3810 * not specified on the command line.
3812 if (argc == 0 || smartsign)
3813 loadzonekeys(!smartsign, ISC_FALSE);
3814 loadexplicitkeys(argv, argc, ISC_FALSE);
3815 loadexplicitkeys(dskeyfile, ndskeys, ISC_TRUE);
3816 loadzonekeys(!smartsign, ISC_TRUE);
3819 * If we're doing smart signing, look in the key repository for
3820 * key files with metadata, and merge them with the keylist
3824 build_final_keylist();
3826 /* Now enumerate the key list */
3827 for (key = ISC_LIST_HEAD(keylist);
3829 key = ISC_LIST_NEXT(key, link)) {
3830 key->index = keycount++;
3833 if (keycount == 0) {
3834 if (disable_zone_check)
3835 fprintf(stderr, "%s: warning: No keys specified "
3836 "or found\n", program);
3838 fatal("No signing keys specified or found.");
3846 result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max);
3847 check_result(result, "dns_nsec3_maxiterations()");
3848 if (nsec3iter > max)
3849 fatal("NSEC3 iterations too big for weakest DNSKEY "
3850 "strength. Maximum iterations allowed %u.", max);
3854 result = dns_db_newversion(gdb, &gversion);
3855 check_result(result, "dns_db_newversion()");
3857 switch (serialformat) {
3858 case SOA_SERIAL_INCREMENT:
3861 case SOA_SERIAL_UNIXTIME:
3864 case SOA_SERIAL_KEEP:
3870 remove_duplicates();
3873 nsec3ify(dns_hash_sha1, nsec3iter, salt, salt_length,
3879 writeset("dsset-", dns_rdatatype_ds);
3881 writeset("keyset-", dns_rdatatype_dnskey);
3883 writeset("dlvset-", dns_rdatatype_dlv);
3887 tempfilelen = strlen(output) + 20;
3888 tempfile = isc_mem_get(mctx, tempfilelen);
3889 if (tempfile == NULL)
3890 fatal("out of memory");
3892 result = isc_file_mktemplate(output, tempfile, tempfilelen);
3893 check_result(result, "isc_file_mktemplate");
3896 result = isc_file_openunique(tempfile, &fp);
3897 if (result != ISC_R_SUCCESS)
3898 fatal("failed to open temporary output file: %s",
3899 isc_result_totext(result));
3900 removefile = ISC_TRUE;
3901 setfatalcallback(&removetempfile);
3906 result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
3907 if (result != ISC_R_SUCCESS)
3908 fatal("failed to create task manager: %s",
3909 isc_result_totext(result));
3912 result = isc_task_create(taskmgr, 0, &master);
3913 if (result != ISC_R_SUCCESS)
3914 fatal("failed to create task: %s", isc_result_totext(result));
3916 tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
3918 fatal("out of memory");
3919 for (i = 0; i < (int)ntasks; i++) {
3921 result = isc_task_create(taskmgr, 0, &tasks[i]);
3922 if (result != ISC_R_SUCCESS)
3923 fatal("failed to create task: %s",
3924 isc_result_totext(result));
3927 RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS);
3929 RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS);
3932 TIME_NOW(&sign_start);
3936 * There is more work to do. Spread it out over multiple
3937 * processors if possible.
3939 for (i = 0; i < (int)ntasks; i++) {
3940 result = isc_app_onrun(mctx, master, startworker,
3942 if (result != ISC_R_SUCCESS)
3943 fatal("failed to start task: %s",
3944 isc_result_totext(result));
3946 (void)isc_app_run();
3948 fatal("process aborted by user");
3950 isc_task_detach(&master);
3951 shuttingdown = ISC_TRUE;
3952 for (i = 0; i < (int)ntasks; i++)
3953 isc_task_detach(&tasks[i]);
3954 isc_taskmgr_destroy(&taskmgr);
3955 isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
3957 TIME_NOW(&sign_finish);
3960 if (outputformat != dns_masterformat_text) {
3961 result = dns_master_dumptostream2(mctx, gdb, gversion,
3962 masterstyle, outputformat,
3964 check_result(result, "dns_master_dumptostream2");
3967 result = isc_stdio_close(fp);
3968 check_result(result, "isc_stdio_close");
3969 removefile = ISC_FALSE;
3971 result = isc_file_rename(tempfile, output);
3972 if (result != ISC_R_SUCCESS)
3973 fatal("failed to rename temp file to %s: %s\n",
3974 output, isc_result_totext(result));
3976 DESTROYLOCK(&namelock);
3978 DESTROYLOCK(&statslock);
3980 printf("%s\n", output);
3982 dns_db_closeversion(gdb, &gversion, ISC_FALSE);
3983 dns_db_detach(&gdb);
3985 while (!ISC_LIST_EMPTY(keylist)) {
3986 key = ISC_LIST_HEAD(keylist);
3987 ISC_LIST_UNLINK(keylist, key, link);
3988 dns_dnsseckey_destroy(mctx, &key);
3991 isc_mem_put(mctx, tempfile, tempfilelen);
3994 isc_mem_free(mctx, output);
3996 dns_master_styledestroy(&dsstyle, mctx);
3998 cleanup_logging(&log);
4001 cleanup_entropy(&ectx);
4004 isc_mem_stats(mctx, stdout);
4005 isc_mem_destroy(&mctx);
4007 (void) isc_app_finish();
4010 TIME_NOW(&timer_finish);
4011 print_stats(&timer_start, &timer_finish,
4012 &sign_start, &sign_finish);