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.209.12.24 2011-05-07 00:23:50 each 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"
90 const char *program = "dnssec-signzone";
93 typedef struct hashlist hashlist_t;
95 static int nsec_datatype = dns_rdatatype_nsec;
97 #define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3)
98 #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
103 typedef struct signer_key_struct signer_key_t;
105 struct signer_key_struct {
107 isc_boolean_t issigningkey;
110 isc_boolean_t wasused;
111 isc_boolean_t commandline;
112 unsigned int position;
113 ISC_LINK(signer_key_t) link;
116 #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
117 #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
118 #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
120 #define SOA_SERIAL_KEEP 0
121 #define SOA_SERIAL_INCREMENT 1
122 #define SOA_SERIAL_UNIXTIME 2
124 typedef struct signer_event sevent_t;
125 struct signer_event {
126 ISC_EVENT_COMMON(sevent_t);
127 dns_fixedname_t *fname;
131 static ISC_LIST(signer_key_t) keylist;
132 static unsigned int keycount = 0;
133 isc_rwlock_t keylist_lock;
134 static isc_stdtime_t starttime = 0, endtime = 0, now;
135 static int cycle = -1;
136 static int jitter = 0;
137 static isc_boolean_t tryverify = ISC_FALSE;
138 static isc_boolean_t printstats = ISC_FALSE;
139 static isc_mem_t *mctx = NULL;
140 static isc_entropy_t *ectx = NULL;
141 static dns_ttl_t zonettl;
143 static char *tempfile = NULL;
144 static const dns_master_style_t *masterstyle;
145 static dns_masterformat_t inputformat = dns_masterformat_text;
146 static dns_masterformat_t outputformat = dns_masterformat_text;
147 static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
148 static unsigned int nverified = 0, nverifyfailed = 0;
149 static const char *directory;
150 static isc_mutex_t namelock, statslock;
151 static isc_taskmgr_t *taskmgr = NULL;
152 static dns_db_t *gdb; /* The database */
153 static dns_dbversion_t *gversion; /* The database version */
154 static dns_dbiterator_t *gdbiter; /* The database iterator */
155 static dns_rdataclass_t gclass; /* The class */
156 static dns_name_t *gorigin; /* The database origin */
157 static int nsec3flags = 0;
158 static isc_task_t *master = NULL;
159 static unsigned int ntasks = 0;
160 static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE;
161 static isc_boolean_t nokeys = ISC_FALSE;
162 static isc_boolean_t removefile = ISC_FALSE;
163 static isc_boolean_t generateds = ISC_FALSE;
164 static isc_boolean_t ignoreksk = ISC_FALSE;
165 static dns_name_t *dlv = NULL;
166 static dns_fixedname_t dlv_fixed;
167 static dns_master_style_t *dsstyle = NULL;
168 static unsigned int serialformat = SOA_SERIAL_KEEP;
169 static unsigned int hash_length = 0;
170 static isc_boolean_t unknownalg = ISC_FALSE;
171 static isc_boolean_t disable_zone_check = ISC_FALSE;
173 #define INCSTAT(counter) \
177 UNLOCK(&statslock); \
181 sign(isc_task_t *task, isc_event_t *event);
183 #define check_dns_dbiterator_current(result) \
184 check_result((result == DNS_R_NEWORIGIN) ? ISC_R_SUCCESS : result, \
185 "dns_dbiterator_current()")
188 dumpnode(dns_name_t *name, dns_dbnode_t *node) {
191 if (outputformat != dns_masterformat_text)
193 result = dns_master_dumpnodetostream(mctx, gdb, gversion, node, name,
195 check_result(result, "dns_master_dumpnodetostream");
198 static signer_key_t *
199 newkeystruct(dst_key_t *dstkey, isc_boolean_t signwithkey) {
202 key = isc_mem_get(mctx, sizeof(signer_key_t));
204 fatal("out of memory");
206 if ((dst_key_flags(dstkey) & DNS_KEYFLAG_KSK) != 0) {
207 key->issigningkey = signwithkey;
208 key->isksk = ISC_TRUE;
209 key->isdsk = ISC_FALSE;
211 key->issigningkey = signwithkey;
212 key->isksk = ISC_FALSE;
213 key->isdsk = ISC_TRUE;
215 key->wasused = ISC_FALSE;
216 key->commandline = ISC_FALSE;
217 key->position = keycount++;
218 ISC_LINK_INIT(key, link);
223 * Sign the given RRset with given key, and add the signature record to the
228 signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key,
229 dns_ttl_t ttl, dns_diff_t *add, const char *logmsg)
232 isc_stdtime_t jendtime;
233 char keystr[KEY_FORMATSIZE];
234 dns_rdata_t trdata = DNS_RDATA_INIT;
235 unsigned char array[BUFSIZE];
237 dns_difftuple_t *tuple;
239 key_format(key, keystr, sizeof(keystr));
240 vbprintf(1, "\t%s %s\n", logmsg, keystr);
242 jendtime = (jitter != 0) ? isc_random_jitter(endtime, jitter) : endtime;
243 isc_buffer_init(&b, array, sizeof(array));
244 result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
246 isc_entropy_stopcallbacksources(ectx);
247 if (result != ISC_R_SUCCESS) {
248 char keystr[KEY_FORMATSIZE];
249 key_format(key, keystr, sizeof(keystr));
250 fatal("dnskey '%s' failed to sign data: %s",
251 keystr, isc_result_totext(result));
256 result = dns_dnssec_verify(name, rdataset, key,
257 ISC_TRUE, mctx, &trdata);
258 if (result == ISC_R_SUCCESS) {
259 vbprintf(3, "\tsignature verified\n");
262 vbprintf(3, "\tsignature failed to verify\n");
263 INCSTAT(nverifyfailed);
268 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name, ttl, &trdata,
270 check_result(result, "dns_difftuple_create");
271 dns_diff_append(add, &tuple);
274 static inline isc_boolean_t
275 issigningkey(signer_key_t *key) {
276 return (key->issigningkey);
279 static inline isc_boolean_t
280 iszonekey(signer_key_t *key) {
281 return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) &&
282 dst_key_iszonekey(key->key)));
286 * Find the key if it is in our list. If it is, return it, otherwise null.
287 * No locking is performed here, this must be done by the caller.
289 static signer_key_t *
290 keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
293 key = ISC_LIST_HEAD(keylist);
294 while (key != NULL) {
295 if (rrsig->keyid == dst_key_id(key->key) &&
296 rrsig->algorithm == dst_key_alg(key->key) &&
297 dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
299 key = ISC_LIST_NEXT(key, link);
305 * Finds the key that generated a RRSIG, if possible. First look at the keys
306 * that we've loaded already, and then see if there's a key on disk.
308 static signer_key_t *
309 keythatsigned(dns_rdata_rrsig_t *rrsig) {
311 dst_key_t *pubkey = NULL, *privkey = NULL;
314 isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read);
315 key = keythatsigned_unlocked(rrsig);
316 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_read);
321 * We did not find the key in our list. Get a write lock now, since
322 * we may be modifying the bits. We could do the tryupgrade() dance,
323 * but instead just get a write lock and check once again to see if
324 * it is on our list. It's possible someone else may have added it
327 isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write);
329 key = keythatsigned_unlocked(rrsig);
331 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
335 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
336 rrsig->algorithm, DST_TYPE_PUBLIC,
337 NULL, mctx, &pubkey);
338 if (result != ISC_R_SUCCESS) {
339 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
343 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
345 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
346 NULL, mctx, &privkey);
347 if (result == ISC_R_SUCCESS) {
348 dst_key_free(&pubkey);
349 key = newkeystruct(privkey, ISC_FALSE);
351 key = newkeystruct(pubkey, ISC_FALSE);
352 ISC_LIST_APPEND(keylist, key, link);
354 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
359 * Check to see if we expect to find a key at this name. If we see a RRSIG
360 * and can't find the signing key that we expect to find, we drop the rrsig.
361 * I'm not sure if this is completely correct, but it seems to work.
364 expecttofindkey(dns_name_t *name) {
365 unsigned int options = DNS_DBFIND_NOWILD;
366 dns_fixedname_t fname;
368 char namestr[DNS_NAME_FORMATSIZE];
370 dns_fixedname_init(&fname);
371 result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
372 0, NULL, dns_fixedname_name(&fname), NULL, NULL);
378 case DNS_R_DELEGATION:
383 dns_name_format(name, namestr, sizeof(namestr));
384 fatal("failure looking for '%s DNSKEY' in database: %s",
385 namestr, isc_result_totext(result));
386 return (ISC_FALSE); /* removes a warning */
389 static inline isc_boolean_t
390 setverifies(dns_name_t *name, dns_rdataset_t *set, signer_key_t *key,
394 result = dns_dnssec_verify(name, set, key->key, ISC_FALSE, mctx, rrsig);
395 if (result == ISC_R_SUCCESS) {
399 INCSTAT(nverifyfailed);
405 * Signs a set. Goes through contortions to decide if each RRSIG should
406 * be dropped or retained, and then determines if any new SIGs need to
410 signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
413 dns_rdataset_t sigset;
414 dns_rdata_t sigrdata = DNS_RDATA_INIT;
415 dns_rdata_rrsig_t rrsig;
418 isc_boolean_t nosigs = ISC_FALSE;
419 isc_boolean_t *wassignedby, *nowsignedby;
421 dns_difftuple_t *tuple;
424 char namestr[DNS_NAME_FORMATSIZE];
425 char typestr[TYPE_FORMATSIZE];
426 char sigstr[SIG_FORMATSIZE];
428 dns_name_format(name, namestr, sizeof(namestr));
429 type_format(set->type, typestr, sizeof(typestr));
431 ttl = ISC_MIN(set->ttl, endtime - starttime);
433 dns_rdataset_init(&sigset);
434 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
435 set->type, 0, &sigset, NULL);
436 if (result == ISC_R_NOTFOUND) {
437 result = ISC_R_SUCCESS;
440 if (result != ISC_R_SUCCESS)
441 fatal("failed while looking for '%s RRSIG %s': %s",
442 namestr, typestr, isc_result_totext(result));
444 vbprintf(1, "%s/%s:\n", namestr, typestr);
446 arraysize = keycount;
448 arraysize += dns_rdataset_count(&sigset);
449 wassignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
450 nowsignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
451 if (wassignedby == NULL || nowsignedby == NULL)
452 fatal("out of memory");
454 for (i = 0; i < arraysize; i++)
455 wassignedby[i] = nowsignedby[i] = ISC_FALSE;
458 result = ISC_R_NOMORE;
460 result = dns_rdataset_first(&sigset);
462 while (result == ISC_R_SUCCESS) {
463 isc_boolean_t expired, future;
464 isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE;
466 dns_rdataset_current(&sigset, &sigrdata);
468 result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
469 check_result(result, "dns_rdata_tostruct");
471 future = isc_serial_lt(now, rrsig.timesigned);
473 key = keythatsigned(&rrsig);
474 sig_format(&rrsig, sigstr, sizeof(sigstr));
475 if (key != NULL && issigningkey(key))
476 expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
478 expired = isc_serial_gt(now, rrsig.timeexpire);
480 if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
481 /* rrsig is dropped and not replaced */
482 vbprintf(2, "\trrsig by %s dropped - "
483 "invalid validity period\n",
485 } else if (key == NULL && !future &&
486 expecttofindkey(&rrsig.signer))
488 /* rrsig is dropped and not replaced */
489 vbprintf(2, "\trrsig by %s dropped - "
490 "private dnskey not found\n",
492 } else if (key == NULL || future) {
493 vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
494 expired ? "retained" : "dropped", sigstr);
497 } else if (issigningkey(key)) {
498 if (!expired && rrsig.originalttl == set->ttl &&
499 setverifies(name, set, key, &sigrdata)) {
500 vbprintf(2, "\trrsig by %s retained\n", sigstr);
502 wassignedby[key->position] = ISC_TRUE;
503 nowsignedby[key->position] = ISC_TRUE;
504 key->wasused = ISC_TRUE;
506 vbprintf(2, "\trrsig by %s dropped - %s\n",
507 sigstr, expired ? "expired" :
508 rrsig.originalttl != set->ttl ?
509 "ttl change" : "failed to verify");
510 wassignedby[key->position] = ISC_TRUE;
513 } else if (iszonekey(key)) {
514 if (!expired && rrsig.originalttl == set->ttl &&
515 setverifies(name, set, key, &sigrdata)) {
516 vbprintf(2, "\trrsig by %s retained\n", sigstr);
518 wassignedby[key->position] = ISC_TRUE;
519 nowsignedby[key->position] = ISC_TRUE;
520 key->wasused = ISC_TRUE;
522 vbprintf(2, "\trrsig by %s dropped - %s\n",
523 sigstr, expired ? "expired" :
524 rrsig.originalttl != set->ttl ?
525 "ttl change" : "failed to verify");
526 wassignedby[key->position] = ISC_TRUE;
528 } else if (!expired) {
529 vbprintf(2, "\trrsig by %s retained\n", sigstr);
532 vbprintf(2, "\trrsig by %s expired\n", sigstr);
536 nowsignedby[key->position] = ISC_TRUE;
538 if (sigset.ttl != ttl) {
539 vbprintf(2, "\tfixing ttl %s\n", sigstr);
541 result = dns_difftuple_create(mctx,
546 check_result(result, "dns_difftuple_create");
547 dns_diff_append(del, &tuple);
548 result = dns_difftuple_create(mctx,
553 check_result(result, "dns_difftuple_create");
554 dns_diff_append(add, &tuple);
558 result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL,
561 check_result(result, "dns_difftuple_create");
562 dns_diff_append(del, &tuple);
569 signwithkey(name, set, key->key, ttl, add,
570 "resigning with dnskey");
571 nowsignedby[key->position] = ISC_TRUE;
572 key->wasused = ISC_TRUE;
575 dns_rdata_reset(&sigrdata);
576 dns_rdata_freestruct(&rrsig);
577 result = dns_rdataset_next(&sigset);
579 if (result == ISC_R_NOMORE)
580 result = ISC_R_SUCCESS;
582 check_result(result, "dns_rdataset_first/next");
583 if (dns_rdataset_isassociated(&sigset))
584 dns_rdataset_disassociate(&sigset);
586 for (key = ISC_LIST_HEAD(keylist);
588 key = ISC_LIST_NEXT(key, link))
590 if (nowsignedby[key->position])
593 if (!key->issigningkey)
595 if (!(ignoreksk || key->isdsk ||
597 set->type == dns_rdatatype_dnskey &&
598 dns_name_equal(name, gorigin))))
601 signwithkey(name, set, key->key, ttl, add,
602 "signing with dnskey");
603 key->wasused = ISC_TRUE;
606 isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t));
607 isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t));
611 unsigned char *hashbuf;
618 hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) {
621 l->length = length + 1;
625 l->hashbuf = malloc(l->size * l->length);
626 if (l->hashbuf == NULL)
635 hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len)
638 REQUIRE(len <= l->length);
640 if (l->entries == l->size) {
641 l->size = l->size * 2 + 100;
642 l->hashbuf = realloc(l->hashbuf, l->size * l->length);
644 memset(l->hashbuf + l->entries * l->length, 0, l->length);
645 memcpy(l->hashbuf + l->entries * l->length, hash, len);
650 hashlist_add_dns_name(hashlist_t *l, /*const*/ dns_name_t *name,
651 unsigned int hashalg, unsigned int iterations,
652 const unsigned char *salt, size_t salt_length,
653 isc_boolean_t speculative)
655 char nametext[DNS_NAME_FORMATSIZE];
656 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
660 len = isc_iterated_hash(hash, hashalg, iterations, salt, salt_length,
661 name->ndata, name->length);
663 dns_name_format(name, nametext, sizeof nametext);
664 for (i = 0 ; i < len; i++)
665 fprintf(stderr, "%02x", hash[i]);
666 fprintf(stderr, " %s\n", nametext);
668 hash[len++] = speculative ? 1 : 0;
669 hashlist_add(l, hash, len);
673 hashlist_comp(const void *a, const void *b) {
674 return (memcmp(a, b, hash_length + 1));
678 hashlist_sort(hashlist_t *l) {
679 qsort(l->hashbuf, l->entries, l->length, hashlist_comp);
683 hashlist_hasdup(hashlist_t *l) {
684 unsigned char *current;
685 unsigned char *next = l->hashbuf;
686 size_t entries = l->entries;
689 * Skip initial speculative wild card hashs.
691 while (entries > 0U && next[l->length-1] != 0U) {
697 while (entries-- > 1U) {
699 if (next[l->length-1] != 0)
701 if (memcmp(current, next, l->length - 1) == 0)
708 static const unsigned char *
709 hashlist_findnext(const hashlist_t *l,
710 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
712 unsigned int entries = l->entries;
713 const unsigned char *next = bsearch(hash, l->hashbuf, l->entries,
714 l->length, hashlist_comp);
715 INSIST(next != NULL);
718 if (next < l->hashbuf + (l->entries - 1) * l->length)
722 if (next[l->length - 1] == 0)
724 } while (entries-- > 1);
725 INSIST(entries != 0);
730 hashlist_exists(const hashlist_t *l,
731 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
733 if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp))
740 addnowildcardhash(hashlist_t *l, /*const*/ dns_name_t *name,
741 unsigned int hashalg, unsigned int iterations,
742 const unsigned char *salt, size_t salt_length)
744 dns_fixedname_t fixed;
746 dns_dbnode_t *node = NULL;
748 char namestr[DNS_NAME_FORMATSIZE];
750 dns_fixedname_init(&fixed);
751 wild = dns_fixedname_name(&fixed);
753 result = dns_name_concatenate(dns_wildcardname, name, wild, NULL);
754 if (result == ISC_R_NOSPACE)
756 check_result(result,"addnowildcardhash: dns_name_concatenate()");
758 result = dns_db_findnode(gdb, wild, ISC_FALSE, &node);
759 if (result == ISC_R_SUCCESS) {
760 dns_db_detachnode(gdb, &node);
765 dns_name_format(wild, namestr, sizeof(namestr));
766 fprintf(stderr, "adding no-wildcardhash for %s\n", namestr);
769 hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_length,
774 opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
781 isc_buffer_init(&b, filename, sizeof(filename));
782 if (directory != NULL) {
783 isc_buffer_putstr(&b, directory);
784 if (directory[strlen(directory) - 1] != '/')
785 isc_buffer_putstr(&b, "/");
787 isc_buffer_putstr(&b, prefix);
788 result = dns_name_tofilenametext(name, ISC_FALSE, &b);
789 check_result(result, "dns_name_tofilenametext()");
790 if (isc_buffer_availablelength(&b) == 0) {
791 char namestr[DNS_NAME_FORMATSIZE];
792 dns_name_format(name, namestr, sizeof(namestr));
793 fatal("name '%s' is too long", namestr);
795 isc_buffer_putuint8(&b, 0);
797 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
798 rdclass, 0, NULL, dbp);
799 check_result(result, "dns_db_create()");
801 result = dns_db_load(*dbp, filename);
802 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
807 * Loads the key set for a child zone, if there is one, and builds DS records.
810 loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
812 dns_dbversion_t *ver = NULL;
813 dns_dbnode_t *node = NULL;
815 dns_rdataset_t keyset;
817 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
819 dns_difftuple_t *tuple = NULL;
821 opendb("keyset-", name, gclass, &db);
823 return (ISC_R_NOTFOUND);
825 result = dns_db_findnode(db, name, ISC_FALSE, &node);
826 if (result != ISC_R_SUCCESS) {
828 return (DNS_R_BADDB);
830 dns_rdataset_init(&keyset);
831 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0,
833 if (result != ISC_R_SUCCESS) {
834 dns_db_detachnode(db, &node);
839 vbprintf(2, "found DNSKEY records\n");
841 result = dns_db_newversion(db, &ver);
842 check_result(result, "dns_db_newversion");
844 dns_diff_init(mctx, &diff);
846 for (result = dns_rdataset_first(&keyset);
847 result == ISC_R_SUCCESS;
848 result = dns_rdataset_next(&keyset))
850 dns_rdata_init(&key);
852 dns_rdataset_current(&keyset, &key);
853 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
855 check_result(result, "dns_ds_buildrdata");
857 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
859 check_result(result, "dns_difftuple_create");
860 dns_diff_append(&diff, &tuple);
862 dns_rdata_reset(&ds);
863 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
865 check_result(result, "dns_ds_buildrdata");
867 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
869 check_result(result, "dns_difftuple_create");
870 dns_diff_append(&diff, &tuple);
872 result = dns_diff_apply(&diff, db, ver);
873 check_result(result, "dns_diff_apply");
874 dns_diff_clear(&diff);
876 dns_db_closeversion(db, &ver, ISC_TRUE);
878 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
880 check_result(result, "dns_db_findrdataset");
882 dns_rdataset_disassociate(&keyset);
883 dns_db_detachnode(db, &node);
889 delegation(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) {
890 dns_rdataset_t nsset;
893 if (dns_name_equal(name, gorigin))
896 dns_rdataset_init(&nsset);
897 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ns,
899 if (dns_rdataset_isassociated(&nsset)) {
902 dns_rdataset_disassociate(&nsset);
905 return (ISC_TF(result == ISC_R_SUCCESS));
909 secure(dns_name_t *name, dns_dbnode_t *node) {
910 dns_rdataset_t dsset;
913 if (dns_name_equal(name, gorigin))
916 dns_rdataset_init(&dsset);
917 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds,
919 if (dns_rdataset_isassociated(&dsset))
920 dns_rdataset_disassociate(&dsset);
922 return (ISC_TF(result == ISC_R_SUCCESS));
926 * Signs all records at a name.
929 signname(dns_dbnode_t *node, dns_name_t *name) {
931 dns_rdataset_t rdataset;
932 dns_rdatasetiter_t *rdsiter;
933 isc_boolean_t isdelegation = ISC_FALSE;
935 char namestr[DNS_NAME_FORMATSIZE];
937 dns_rdataset_init(&rdataset);
938 dns_name_format(name, namestr, sizeof(namestr));
941 * Determine if this is a delegation point.
943 if (delegation(name, node, NULL))
944 isdelegation = ISC_TRUE;
947 * Now iterate through the rdatasets.
949 dns_diff_init(mctx, &del);
950 dns_diff_init(mctx, &add);
952 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
953 check_result(result, "dns_db_allrdatasets()");
954 result = dns_rdatasetiter_first(rdsiter);
955 while (result == ISC_R_SUCCESS) {
956 dns_rdatasetiter_current(rdsiter, &rdataset);
958 /* If this is a RRSIG set, skip it. */
959 if (rdataset.type == dns_rdatatype_rrsig)
963 * If this name is a delegation point, skip all records
964 * except NSEC and DS sets. Otherwise check that there
968 if (rdataset.type != nsec_datatype &&
969 rdataset.type != dns_rdatatype_ds)
971 } else if (rdataset.type == dns_rdatatype_ds) {
972 char namebuf[DNS_NAME_FORMATSIZE];
973 dns_name_format(name, namebuf, sizeof(namebuf));
974 fatal("'%s': found DS RRset without NS RRset\n",
978 signset(&del, &add, node, name, &rdataset);
981 dns_rdataset_disassociate(&rdataset);
982 result = dns_rdatasetiter_next(rdsiter);
984 if (result != ISC_R_NOMORE)
985 fatal("rdataset iteration for name '%s' failed: %s",
986 namestr, isc_result_totext(result));
988 dns_rdatasetiter_destroy(&rdsiter);
990 result = dns_diff_applysilently(&del, gdb, gversion);
991 if (result != ISC_R_SUCCESS)
992 fatal("failed to delete SIGs at node '%s': %s",
993 namestr, isc_result_totext(result));
995 result = dns_diff_applysilently(&add, gdb, gversion);
996 if (result != ISC_R_SUCCESS)
997 fatal("failed to add SIGs at node '%s': %s",
998 namestr, isc_result_totext(result));
1000 dns_diff_clear(&del);
1001 dns_diff_clear(&add);
1004 static inline isc_boolean_t
1005 active_node(dns_dbnode_t *node) {
1006 dns_rdatasetiter_t *rdsiter = NULL;
1007 dns_rdatasetiter_t *rdsiter2 = NULL;
1008 isc_boolean_t active = ISC_FALSE;
1009 isc_result_t result;
1010 dns_rdataset_t rdataset;
1011 dns_rdatatype_t type;
1012 dns_rdatatype_t covers;
1013 isc_boolean_t found;
1015 dns_rdataset_init(&rdataset);
1016 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1017 check_result(result, "dns_db_allrdatasets()");
1018 result = dns_rdatasetiter_first(rdsiter);
1019 while (result == ISC_R_SUCCESS) {
1020 dns_rdatasetiter_current(rdsiter, &rdataset);
1021 if (rdataset.type != dns_rdatatype_nsec &&
1022 rdataset.type != dns_rdatatype_nsec3 &&
1023 rdataset.type != dns_rdatatype_rrsig)
1025 dns_rdataset_disassociate(&rdataset);
1027 result = dns_rdatasetiter_next(rdsiter);
1029 result = ISC_R_NOMORE;
1031 if (result != ISC_R_NOMORE)
1032 fatal("rdataset iteration failed: %s",
1033 isc_result_totext(result));
1035 if (!active && nsec_datatype == dns_rdatatype_nsec) {
1037 * The node is empty of everything but NSEC / RRSIG records.
1039 for (result = dns_rdatasetiter_first(rdsiter);
1040 result == ISC_R_SUCCESS;
1041 result = dns_rdatasetiter_next(rdsiter)) {
1042 dns_rdatasetiter_current(rdsiter, &rdataset);
1043 result = dns_db_deleterdataset(gdb, node, gversion,
1046 check_result(result, "dns_db_deleterdataset()");
1047 dns_rdataset_disassociate(&rdataset);
1049 if (result != ISC_R_NOMORE)
1050 fatal("rdataset iteration failed: %s",
1051 isc_result_totext(result));
1054 * Delete RRSIGs for types that no longer exist.
1056 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
1057 check_result(result, "dns_db_allrdatasets()");
1058 for (result = dns_rdatasetiter_first(rdsiter);
1059 result == ISC_R_SUCCESS;
1060 result = dns_rdatasetiter_next(rdsiter)) {
1061 dns_rdatasetiter_current(rdsiter, &rdataset);
1062 type = rdataset.type;
1063 covers = rdataset.covers;
1064 dns_rdataset_disassociate(&rdataset);
1066 * Delete the NSEC chain if we are signing with
1069 if (nsec_datatype == dns_rdatatype_nsec3 &&
1070 (type == dns_rdatatype_nsec ||
1071 covers == dns_rdatatype_nsec)) {
1072 result = dns_db_deleterdataset(gdb, node,
1075 check_result(result,
1076 "dns_db_deleterdataset(nsec/rrsig)");
1079 if (type != dns_rdatatype_rrsig)
1082 for (result = dns_rdatasetiter_first(rdsiter2);
1083 !found && result == ISC_R_SUCCESS;
1084 result = dns_rdatasetiter_next(rdsiter2)) {
1085 dns_rdatasetiter_current(rdsiter2, &rdataset);
1086 if (rdataset.type == covers)
1088 dns_rdataset_disassociate(&rdataset);
1091 if (result != ISC_R_NOMORE)
1092 fatal("rdataset iteration failed: %s",
1093 isc_result_totext(result));
1094 result = dns_db_deleterdataset(gdb, node,
1097 check_result(result,
1098 "dns_db_deleterdataset(rrsig)");
1099 } else if (result != ISC_R_NOMORE &&
1100 result != ISC_R_SUCCESS)
1101 fatal("rdataset iteration failed: %s",
1102 isc_result_totext(result));
1104 if (result != ISC_R_NOMORE)
1105 fatal("rdataset iteration failed: %s",
1106 isc_result_totext(result));
1107 dns_rdatasetiter_destroy(&rdsiter2);
1109 dns_rdatasetiter_destroy(&rdsiter);
1115 * Extracts the TTL from the SOA.
1119 dns_rdataset_t soaset;
1120 dns_fixedname_t fname;
1122 isc_result_t result;
1124 dns_rdata_t rdata = DNS_RDATA_INIT;
1125 dns_rdata_soa_t soa;
1127 dns_fixedname_init(&fname);
1128 name = dns_fixedname_name(&fname);
1129 dns_rdataset_init(&soaset);
1130 result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
1131 0, 0, NULL, name, &soaset, NULL);
1132 if (result != ISC_R_SUCCESS)
1133 fatal("failed to find an SOA at the zone apex: %s",
1134 isc_result_totext(result));
1136 result = dns_rdataset_first(&soaset);
1137 check_result(result, "dns_rdataset_first");
1138 dns_rdataset_current(&soaset, &rdata);
1139 result = dns_rdata_tostruct(&rdata, &soa, NULL);
1140 check_result(result, "dns_rdata_tostruct");
1142 dns_rdataset_disassociate(&soaset);
1147 * Increment (or set if nonzero) the SOA serial
1150 setsoaserial(isc_uint32_t serial) {
1151 isc_result_t result;
1152 dns_dbnode_t *node = NULL;
1153 dns_rdataset_t rdataset;
1154 dns_rdata_t rdata = DNS_RDATA_INIT;
1155 isc_uint32_t old_serial, new_serial;
1157 result = dns_db_getoriginnode(gdb, &node);
1158 if (result != ISC_R_SUCCESS)
1161 dns_rdataset_init(&rdataset);
1163 result = dns_db_findrdataset(gdb, node, gversion,
1164 dns_rdatatype_soa, 0,
1165 0, &rdataset, NULL);
1166 if (result != ISC_R_SUCCESS)
1169 result = dns_rdataset_first(&rdataset);
1170 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1172 dns_rdataset_current(&rdataset, &rdata);
1174 old_serial = dns_soa_getserial(&rdata);
1177 /* Set SOA serial to the value provided. */
1178 new_serial = serial;
1180 /* Increment SOA serial using RFC 1982 arithmetics */
1181 new_serial = (old_serial + 1) & 0xFFFFFFFF;
1182 if (new_serial == 0)
1186 /* If the new serial is not likely to cause a zone transfer
1187 * (a/ixfr) from servers having the old serial, warn the user.
1189 * RFC1982 section 7 defines the maximum increment to be
1190 * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
1191 * comparison. (5 - 6 == (2^32)-1, not negative-one)
1193 if (new_serial == old_serial ||
1194 (new_serial - old_serial) > 0x7fffffffU)
1195 fprintf(stderr, "%s: warning: Serial number not advanced, "
1196 "zone may not transfer\n", program);
1198 dns_soa_setserial(new_serial, &rdata);
1200 result = dns_db_deleterdataset(gdb, node, gversion,
1201 dns_rdatatype_soa, 0);
1202 check_result(result, "dns_db_deleterdataset");
1203 if (result != ISC_R_SUCCESS)
1206 result = dns_db_addrdataset(gdb, node, gversion,
1207 0, &rdataset, 0, NULL);
1208 check_result(result, "dns_db_addrdataset");
1209 if (result != ISC_R_SUCCESS)
1213 dns_rdataset_disassociate(&rdataset);
1215 dns_db_detachnode(gdb, &node);
1216 dns_rdata_reset(&rdata);
1222 * Delete any RRSIG records at a node.
1225 cleannode(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
1226 dns_rdatasetiter_t *rdsiter = NULL;
1228 isc_result_t result, dresult;
1230 if (outputformat != dns_masterformat_text || !disable_zone_check)
1233 dns_rdataset_init(&set);
1234 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
1235 check_result(result, "dns_db_allrdatasets");
1236 result = dns_rdatasetiter_first(rdsiter);
1237 while (result == ISC_R_SUCCESS) {
1238 isc_boolean_t destroy = ISC_FALSE;
1239 dns_rdatatype_t covers = 0;
1240 dns_rdatasetiter_current(rdsiter, &set);
1241 if (set.type == dns_rdatatype_rrsig) {
1242 covers = set.covers;
1245 dns_rdataset_disassociate(&set);
1246 result = dns_rdatasetiter_next(rdsiter);
1248 dresult = dns_db_deleterdataset(db, node, version,
1249 dns_rdatatype_rrsig,
1251 check_result(dresult, "dns_db_deleterdataset");
1254 if (result != ISC_R_NOMORE)
1255 fatal("rdataset iteration failed: %s",
1256 isc_result_totext(result));
1257 dns_rdatasetiter_destroy(&rdsiter);
1261 * Set up the iterator and global state before starting the tasks.
1265 isc_result_t result;
1268 result = dns_db_createiterator(gdb, 0, &gdbiter);
1269 check_result(result, "dns_db_createiterator()");
1273 * Clean up the iterator and global state after the tasks complete.
1277 dns_dbiterator_destroy(&gdbiter);
1280 static isc_boolean_t
1281 goodsig(dns_rdata_t *sigrdata, dns_name_t *name, dns_rdataset_t *keyrdataset,
1282 dns_rdataset_t *rdataset)
1284 dns_rdata_dnskey_t key;
1285 dns_rdata_rrsig_t sig;
1286 dst_key_t *dstkey = NULL;
1287 isc_result_t result;
1289 dns_rdata_tostruct(sigrdata, &sig, NULL);
1291 for (result = dns_rdataset_first(keyrdataset);
1292 result == ISC_R_SUCCESS;
1293 result = dns_rdataset_next(keyrdataset)) {
1294 dns_rdata_t rdata = DNS_RDATA_INIT;
1295 dns_rdataset_current(keyrdataset, &rdata);
1296 dns_rdata_tostruct(&rdata, &key, NULL);
1297 result = dns_dnssec_keyfromrdata(gorigin, &rdata, mctx,
1299 if (result != ISC_R_SUCCESS)
1301 if (sig.algorithm != key.algorithm ||
1302 sig.keyid != dst_key_id(dstkey) ||
1303 !dns_name_equal(&sig.signer, gorigin)) {
1304 dst_key_free(&dstkey);
1307 result = dns_dnssec_verify(name, rdataset, dstkey, ISC_FALSE,
1309 dst_key_free(&dstkey);
1310 if (result == ISC_R_SUCCESS)
1317 verifyset(dns_rdataset_t *rdataset, dns_name_t *name, dns_dbnode_t *node,
1318 dns_rdataset_t *keyrdataset, unsigned char *ksk_algorithms,
1319 unsigned char *bad_algorithms)
1321 unsigned char set_algorithms[256];
1322 char namebuf[DNS_NAME_FORMATSIZE];
1325 dns_rdataset_t sigrdataset;
1326 dns_rdatasetiter_t *rdsiter = NULL;
1327 isc_result_t result;
1330 dns_rdataset_init(&sigrdataset);
1331 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1332 check_result(result, "dns_db_allrdatasets()");
1333 for (result = dns_rdatasetiter_first(rdsiter);
1334 result == ISC_R_SUCCESS;
1335 result = dns_rdatasetiter_next(rdsiter)) {
1336 dns_rdatasetiter_current(rdsiter, &sigrdataset);
1337 if (sigrdataset.type == dns_rdatatype_rrsig &&
1338 sigrdataset.covers == rdataset->type)
1340 dns_rdataset_disassociate(&sigrdataset);
1342 if (result != ISC_R_SUCCESS) {
1343 dns_name_format(name, namebuf, sizeof(namebuf));
1344 type_format(rdataset->type, typebuf, sizeof(typebuf));
1345 fprintf(stderr, "no signatures for %s/%s\n", namebuf, typebuf);
1346 for (i = 0; i < 256; i++)
1347 if (ksk_algorithms[i] != 0)
1348 bad_algorithms[i] = 1;
1352 memset(set_algorithms, 0, sizeof(set_algorithms));
1353 for (result = dns_rdataset_first(&sigrdataset);
1354 result == ISC_R_SUCCESS;
1355 result = dns_rdataset_next(&sigrdataset)) {
1356 dns_rdata_t rdata = DNS_RDATA_INIT;
1357 dns_rdata_rrsig_t sig;
1359 dns_rdataset_current(&sigrdataset, &rdata);
1360 dns_rdata_tostruct(&rdata, &sig, NULL);
1361 if (rdataset->ttl != sig.originalttl) {
1362 dns_name_format(name, namebuf, sizeof(namebuf));
1363 type_format(rdataset->type, typebuf, sizeof(typebuf));
1364 fprintf(stderr, "TTL mismatch for %s %s keytag %u\n",
1365 namebuf, typebuf, sig.keyid);
1368 if ((set_algorithms[sig.algorithm] != 0) ||
1369 (ksk_algorithms[sig.algorithm] == 0))
1371 if (goodsig(&rdata, name, keyrdataset, rdataset))
1372 set_algorithms[sig.algorithm] = 1;
1374 dns_rdatasetiter_destroy(&rdsiter);
1375 if (memcmp(set_algorithms, ksk_algorithms, sizeof(set_algorithms))) {
1376 dns_name_format(name, namebuf, sizeof(namebuf));
1377 type_format(rdataset->type, typebuf, sizeof(typebuf));
1378 for (i = 0; i < 256; i++)
1379 if ((ksk_algorithms[i] != 0) &&
1380 (set_algorithms[i] == 0)) {
1381 alg_format(i, algbuf, sizeof(algbuf));
1382 fprintf(stderr, "Missing %s signature for "
1383 "%s %s\n", algbuf, namebuf, typebuf);
1384 bad_algorithms[i] = 1;
1387 dns_rdataset_disassociate(&sigrdataset);
1391 verifynode(dns_name_t *name, dns_dbnode_t *node, isc_boolean_t delegation,
1392 dns_rdataset_t *keyrdataset, unsigned char *ksk_algorithms,
1393 unsigned char *bad_algorithms)
1395 dns_rdataset_t rdataset;
1396 dns_rdatasetiter_t *rdsiter = NULL;
1397 isc_result_t result;
1399 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1400 check_result(result, "dns_db_allrdatasets()");
1401 result = dns_rdatasetiter_first(rdsiter);
1402 dns_rdataset_init(&rdataset);
1403 while (result == ISC_R_SUCCESS) {
1404 dns_rdatasetiter_current(rdsiter, &rdataset);
1405 if (rdataset.type != dns_rdatatype_rrsig &&
1406 rdataset.type != dns_rdatatype_dnskey &&
1407 (!delegation || rdataset.type == dns_rdatatype_ds ||
1408 rdataset.type == dns_rdatatype_nsec)) {
1409 verifyset(&rdataset, name, node, keyrdataset,
1410 ksk_algorithms, bad_algorithms);
1412 dns_rdataset_disassociate(&rdataset);
1413 result = dns_rdatasetiter_next(rdsiter);
1415 if (result != ISC_R_NOMORE)
1416 fatal("rdataset iteration failed: %s",
1417 isc_result_totext(result));
1418 dns_rdatasetiter_destroy(&rdsiter);
1422 * Verify that certain things are sane:
1424 * The apex has a DNSKEY record with at least one KSK and at least
1427 * The DNSKEY record was signed with at least one of the KSKs in this
1430 * The rest of the zone was signed with at least one of the ZSKs
1431 * present in the DNSKEY RRSET.
1436 dns_dbiterator_t *dbiter = NULL;
1437 dns_dbnode_t *node = NULL, *nextnode = NULL;
1438 dns_fixedname_t fname, fnextname, fzonecut;
1439 dns_name_t *name, *nextname, *zonecut;
1440 dns_rdata_dnskey_t dnskey;
1441 dns_rdata_t rdata = DNS_RDATA_INIT;
1442 dns_rdataset_t rdataset;
1443 dns_rdataset_t sigrdataset;
1445 isc_boolean_t done = ISC_FALSE;
1446 isc_boolean_t first = ISC_TRUE;
1447 isc_boolean_t goodksk = ISC_FALSE;
1448 isc_result_t result;
1449 unsigned char revoked[256];
1450 unsigned char standby[256];
1451 unsigned char ksk_algorithms[256];
1452 unsigned char zsk_algorithms[256];
1453 unsigned char bad_algorithms[256];
1454 #ifdef ALLOW_KSKLESS_ZONES
1455 isc_boolean_t allzsksigned = ISC_TRUE;
1456 unsigned char self_algorithms[256];
1459 if (disable_zone_check)
1462 result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node);
1463 if (result != ISC_R_SUCCESS)
1464 fatal("failed to find the zone's origin: %s",
1465 isc_result_totext(result));
1467 dns_rdataset_init(&rdataset);
1468 dns_rdataset_init(&sigrdataset);
1469 result = dns_db_findrdataset(gdb, node, gversion,
1470 dns_rdatatype_dnskey,
1471 0, 0, &rdataset, &sigrdataset);
1472 dns_db_detachnode(gdb, &node);
1473 if (result != ISC_R_SUCCESS)
1474 fatal("cannot find DNSKEY rrset\n");
1476 if (!dns_rdataset_isassociated(&sigrdataset))
1477 fatal("cannot find DNSKEY RRSIGs\n");
1479 memset(revoked, 0, sizeof(revoked));
1480 memset(standby, 0, sizeof(revoked));
1481 memset(ksk_algorithms, 0, sizeof(ksk_algorithms));
1482 memset(zsk_algorithms, 0, sizeof(zsk_algorithms));
1483 memset(bad_algorithms, 0, sizeof(bad_algorithms));
1484 #ifdef ALLOW_KSKLESS_ZONES
1485 memset(self_algorithms, 0, sizeof(self_algorithms));
1489 * Check that the DNSKEY RR has at least one self signing KSK and
1490 * one ZSK per algorithm in it.
1492 for (result = dns_rdataset_first(&rdataset);
1493 result == ISC_R_SUCCESS;
1494 result = dns_rdataset_next(&rdataset)) {
1495 dns_rdataset_current(&rdataset, &rdata);
1496 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
1497 check_result(result, "dns_rdata_tostruct");
1499 if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0)
1501 else if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) {
1502 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1503 !dns_dnssec_selfsigns(&rdata, gorigin, &rdataset,
1504 &sigrdataset, ISC_FALSE,
1506 char namebuf[DNS_NAME_FORMATSIZE];
1510 dns_name_format(gorigin, namebuf,
1512 isc_buffer_init(&buf, buffer, sizeof(buffer));
1513 result = dns_rdata_totext(&rdata, NULL, &buf);
1514 check_result(result, "dns_rdata_totext");
1515 fatal("revoked KSK is not self signed:\n"
1516 "%s DNSKEY %.*s", namebuf,
1517 (int)isc_buffer_usedlength(&buf), buffer);
1519 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1520 revoked[dnskey.algorithm] != 255)
1521 revoked[dnskey.algorithm]++;
1522 } else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) {
1523 if (dns_dnssec_selfsigns(&rdata, gorigin, &rdataset,
1524 &sigrdataset, ISC_FALSE, mctx)) {
1525 if (ksk_algorithms[dnskey.algorithm] != 255)
1526 ksk_algorithms[dnskey.algorithm]++;
1529 if (standby[dnskey.algorithm] != 255)
1530 standby[dnskey.algorithm]++;
1532 } else if (dns_dnssec_selfsigns(&rdata, gorigin, &rdataset,
1533 &sigrdataset, ISC_FALSE,
1535 #ifdef ALLOW_KSKLESS_ZONES
1536 if (self_algorithms[dnskey.algorithm] != 255)
1537 self_algorithms[dnskey.algorithm]++;
1539 if (zsk_algorithms[dnskey.algorithm] != 255)
1540 zsk_algorithms[dnskey.algorithm]++;
1542 if (zsk_algorithms[dnskey.algorithm] != 255)
1543 zsk_algorithms[dnskey.algorithm]++;
1544 #ifdef ALLOW_KSKLESS_ZONES
1545 allzsksigned = ISC_FALSE;
1548 dns_rdata_freestruct(&dnskey);
1549 dns_rdata_reset(&rdata);
1551 dns_rdataset_disassociate(&sigrdataset);
1554 #ifdef ALLOW_KSKLESS_ZONES
1556 fatal("no self signing keys found");
1557 fprintf(stderr, "No self signing KSK found. Using self signed "
1558 "ZSK's for active algorithm list.\n");
1559 memcpy(ksk_algorithms, self_algorithms, sizeof(ksk_algorithms));
1561 fprintf(stderr, "warning: not all ZSK's are self "
1564 fatal("no self signed KSK's found");
1568 fprintf(stderr, "Verifying the zone using the following algorithms:");
1569 for (i = 0; i < 256; i++) {
1570 if (ksk_algorithms[i] != 0) {
1571 alg_format(i, algbuf, sizeof(algbuf));
1572 fprintf(stderr, " %s", algbuf);
1575 fprintf(stderr, ".\n");
1577 for (i = 0; i < 256; i++) {
1579 * The counts should both be zero or both be non-zero.
1580 * Mark the algorithm as bad if this is not met.
1582 if ((ksk_algorithms[i] != 0) == (zsk_algorithms[i] != 0))
1584 alg_format(i, algbuf, sizeof(algbuf));
1585 fprintf(stderr, "Missing %s for algorithm %s\n",
1586 (ksk_algorithms[i] != 0) ? "ZSK" : "self signing KSK",
1588 bad_algorithms[i] = 1;
1592 * Check that all the other records were signed by keys that are
1593 * present in the DNSKEY RRSET.
1596 dns_fixedname_init(&fname);
1597 name = dns_fixedname_name(&fname);
1598 dns_fixedname_init(&fnextname);
1599 nextname = dns_fixedname_name(&fnextname);
1600 dns_fixedname_init(&fzonecut);
1603 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
1604 check_result(result, "dns_db_createiterator()");
1606 result = dns_dbiterator_first(dbiter);
1607 check_result(result, "dns_dbiterator_first()");
1610 isc_boolean_t isdelegation = ISC_FALSE;
1612 result = dns_dbiterator_current(dbiter, &node, name);
1613 check_dns_dbiterator_current(result);
1614 if (!dns_name_issubdomain(name, gorigin)) {
1615 dns_db_detachnode(gdb, &node);
1616 result = dns_dbiterator_next(dbiter);
1617 if (result == ISC_R_NOMORE)
1620 check_result(result, "dns_dbiterator_next()");
1623 if (delegation(name, node, NULL)) {
1624 zonecut = dns_fixedname_name(&fzonecut);
1625 dns_name_copy(name, zonecut, NULL);
1626 isdelegation = ISC_TRUE;
1628 verifynode(name, node, isdelegation, &rdataset,
1629 ksk_algorithms, bad_algorithms);
1630 result = dns_dbiterator_next(dbiter);
1632 while (result == ISC_R_SUCCESS) {
1633 result = dns_dbiterator_current(dbiter, &nextnode,
1635 check_dns_dbiterator_current(result);
1636 if (!dns_name_issubdomain(nextname, gorigin) ||
1638 dns_name_issubdomain(nextname, zonecut)))
1640 dns_db_detachnode(gdb, &nextnode);
1641 result = dns_dbiterator_next(dbiter);
1644 dns_db_detachnode(gdb, &nextnode);
1647 if (result == ISC_R_NOMORE) {
1649 } else if (result != ISC_R_SUCCESS)
1650 fatal("iterating through the database failed: %s",
1651 isc_result_totext(result));
1652 dns_db_detachnode(gdb, &node);
1655 dns_dbiterator_destroy(&dbiter);
1657 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
1658 check_result(result, "dns_db_createiterator()");
1660 for (result = dns_dbiterator_first(dbiter);
1661 result == ISC_R_SUCCESS;
1662 result = dns_dbiterator_next(dbiter) ) {
1663 result = dns_dbiterator_current(dbiter, &node, name);
1664 check_dns_dbiterator_current(result);
1665 verifynode(name, node, ISC_FALSE, &rdataset,
1666 ksk_algorithms, bad_algorithms);
1667 dns_db_detachnode(gdb, &node);
1669 dns_dbiterator_destroy(&dbiter);
1671 dns_rdataset_disassociate(&rdataset);
1674 * If we made it this far, we have what we consider a properly signed
1675 * zone. Set the good flag.
1677 for (i = 0; i < 256; i++) {
1678 if (bad_algorithms[i] != 0) {
1680 fprintf(stderr, "The zone is not fully signed "
1681 "for the following algorithms:");
1682 alg_format(i, algbuf, sizeof(algbuf));
1683 fprintf(stderr, " %s", algbuf);
1688 fprintf(stderr, ".\n");
1689 fatal("DNSSEC completeness test failed.");
1694 * Print the success summary.
1696 fprintf(stderr, "Zone signing complete:\n");
1697 for (i = 0; i < 256; i++) {
1698 if ((zsk_algorithms[i] != 0) ||
1699 (ksk_algorithms[i] != 0) ||
1700 (revoked[i] != 0) || (standby[i] != 0)) {
1701 alg_format(i, algbuf, sizeof(algbuf));
1702 fprintf(stderr, "Algorithm: %s: ZSKs: %u, "
1703 "KSKs: %u active, %u revoked, %u "
1704 "stand-by\n", algbuf,
1705 zsk_algorithms[i], ksk_algorithms[i],
1706 revoked[i], standby[i]);
1713 * Sign the apex of the zone.
1714 * Note the origin may not be the first node if there are out of zone
1719 dns_dbnode_t *node = NULL;
1720 dns_fixedname_t fixed;
1722 isc_result_t result;
1724 dns_fixedname_init(&fixed);
1725 name = dns_fixedname_name(&fixed);
1726 result = dns_dbiterator_seek(gdbiter, gorigin);
1727 check_result(result, "dns_dbiterator_seek()");
1728 result = dns_dbiterator_current(gdbiter, &node, name);
1729 check_dns_dbiterator_current(result);
1730 signname(node, name);
1731 dumpnode(name, node);
1732 cleannode(gdb, gversion, node);
1733 dns_db_detachnode(gdb, &node);
1734 result = dns_dbiterator_first(gdbiter);
1735 if (result == ISC_R_NOMORE)
1736 finished = ISC_TRUE;
1737 else if (result != ISC_R_SUCCESS)
1738 fatal("failure iterating database: %s",
1739 isc_result_totext(result));
1743 * Assigns a node to a worker thread. This is protected by the master task's
1747 assignwork(isc_task_t *task, isc_task_t *worker) {
1748 dns_fixedname_t *fname;
1752 dns_rdataset_t nsec;
1753 isc_boolean_t found;
1754 isc_result_t result;
1755 static dns_name_t *zonecut = NULL; /* Protected by namelock. */
1756 static dns_fixedname_t fzonecut; /* Protected by namelock. */
1757 static unsigned int ended = 0; /* Protected by namelock. */
1765 if (ended == ntasks) {
1766 isc_task_detach(&task);
1772 fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
1774 fatal("out of memory");
1775 dns_fixedname_init(fname);
1776 name = dns_fixedname_name(fname);
1780 result = dns_dbiterator_current(gdbiter, &node, name);
1781 check_dns_dbiterator_current(result);
1783 * The origin was handled by signapex().
1785 if (dns_name_equal(name, gorigin)) {
1786 dns_db_detachnode(gdb, &node);
1790 * Sort the zone data from the glue and out-of-zone data.
1791 * For NSEC zones nodes with zone data have NSEC records.
1792 * For NSEC3 zones the NSEC3 nodes are zone data but
1793 * outside of the zone name space. For the rest we need
1794 * to track the bottom of zone cuts.
1795 * Nodes which don't need to be signed are dumped here.
1797 dns_rdataset_init(&nsec);
1798 result = dns_db_findrdataset(gdb, node, gversion,
1799 nsec_datatype, 0, 0,
1801 if (dns_rdataset_isassociated(&nsec))
1802 dns_rdataset_disassociate(&nsec);
1803 if (result == ISC_R_SUCCESS) {
1805 } else if (nsec_datatype == dns_rdatatype_nsec3) {
1806 if (dns_name_issubdomain(name, gorigin) &&
1808 !dns_name_issubdomain(name, zonecut))) {
1809 if (delegation(name, node, NULL)) {
1810 dns_fixedname_init(&fzonecut);
1811 zonecut = dns_fixedname_name(&fzonecut);
1812 dns_name_copy(name, zonecut, NULL);
1813 if (!OPTOUT(nsec3flags) ||
1822 dumpnode(name, node);
1823 dns_db_detachnode(gdb, &node);
1827 result = dns_dbiterator_next(gdbiter);
1828 if (result == ISC_R_NOMORE) {
1829 finished = ISC_TRUE;
1831 } else if (result != ISC_R_SUCCESS)
1832 fatal("failure iterating database: %s",
1833 isc_result_totext(result));
1837 if (ended == ntasks) {
1838 isc_task_detach(&task);
1841 isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
1844 sevent = (sevent_t *)
1845 isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
1846 sign, NULL, sizeof(sevent_t));
1848 fatal("failed to allocate event\n");
1850 sevent->node = node;
1851 sevent->fname = fname;
1852 isc_task_send(worker, ISC_EVENT_PTR(&sevent));
1858 * Start a worker task
1861 startworker(isc_task_t *task, isc_event_t *event) {
1864 worker = (isc_task_t *)event->ev_arg;
1865 assignwork(task, worker);
1866 isc_event_free(&event);
1870 * Write a node to the output file, and restart the worker task.
1873 writenode(isc_task_t *task, isc_event_t *event) {
1875 sevent_t *sevent = (sevent_t *)event;
1877 worker = (isc_task_t *)event->ev_sender;
1878 dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
1879 cleannode(gdb, gversion, sevent->node);
1880 dns_db_detachnode(gdb, &sevent->node);
1881 isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
1882 assignwork(task, worker);
1883 isc_event_free(&event);
1887 * Sign a database node.
1890 sign(isc_task_t *task, isc_event_t *event) {
1891 dns_fixedname_t *fname;
1893 sevent_t *sevent, *wevent;
1895 sevent = (sevent_t *)event;
1896 node = sevent->node;
1897 fname = sevent->fname;
1898 isc_event_free(&event);
1900 signname(node, dns_fixedname_name(fname));
1901 wevent = (sevent_t *)
1902 isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
1903 writenode, NULL, sizeof(sevent_t));
1905 fatal("failed to allocate event\n");
1906 wevent->node = node;
1907 wevent->fname = fname;
1908 isc_task_send(master, ISC_EVENT_PTR(&wevent));
1912 * Update / remove the DS RRset. Preserve RRSIG(DS) if possible.
1915 add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) {
1916 dns_rdataset_t dsset;
1917 dns_rdataset_t sigdsset;
1918 isc_result_t result;
1920 dns_rdataset_init(&dsset);
1921 dns_rdataset_init(&sigdsset);
1922 result = dns_db_findrdataset(gdb, node, gversion,
1924 0, 0, &dsset, &sigdsset);
1925 if (result == ISC_R_SUCCESS) {
1926 dns_rdataset_disassociate(&dsset);
1927 result = dns_db_deleterdataset(gdb, node, gversion,
1928 dns_rdatatype_ds, 0);
1929 check_result(result, "dns_db_deleterdataset");
1931 result = loadds(name, nsttl, &dsset);
1932 if (result == ISC_R_SUCCESS) {
1933 result = dns_db_addrdataset(gdb, node, gversion, 0,
1935 check_result(result, "dns_db_addrdataset");
1936 dns_rdataset_disassociate(&dsset);
1937 if (dns_rdataset_isassociated(&sigdsset))
1938 dns_rdataset_disassociate(&sigdsset);
1939 } else if (dns_rdataset_isassociated(&sigdsset)) {
1940 result = dns_db_deleterdataset(gdb, node, gversion,
1941 dns_rdatatype_rrsig,
1943 check_result(result, "dns_db_deleterdataset");
1944 dns_rdataset_disassociate(&sigdsset);
1949 * Remove records of the given type and their signatures.
1952 remove_records(dns_dbnode_t *node, dns_rdatatype_t which) {
1953 isc_result_t result;
1954 dns_rdatatype_t type, covers;
1955 dns_rdatasetiter_t *rdsiter = NULL;
1956 dns_rdataset_t rdataset;
1958 dns_rdataset_init(&rdataset);
1961 * Delete any NSEC records at the apex.
1963 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1964 check_result(result, "dns_db_allrdatasets()");
1965 for (result = dns_rdatasetiter_first(rdsiter);
1966 result == ISC_R_SUCCESS;
1967 result = dns_rdatasetiter_next(rdsiter)) {
1968 dns_rdatasetiter_current(rdsiter, &rdataset);
1969 type = rdataset.type;
1970 covers = rdataset.covers;
1971 dns_rdataset_disassociate(&rdataset);
1972 if (type == which || covers == which) {
1973 result = dns_db_deleterdataset(gdb, node, gversion,
1975 check_result(result, "dns_db_deleterdataset()");
1979 dns_rdatasetiter_destroy(&rdsiter);
1983 * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records.
1987 dns_dbiterator_t *dbiter = NULL;
1988 dns_dbnode_t *node = NULL, *nextnode = NULL;
1989 dns_fixedname_t fname, fnextname, fzonecut;
1990 dns_name_t *name, *nextname, *zonecut;
1991 dns_rdataset_t rdataset;
1992 dns_rdatasetiter_t *rdsiter = NULL;
1993 dns_rdatatype_t type, covers;
1994 isc_boolean_t done = ISC_FALSE;
1995 isc_result_t result;
1996 isc_uint32_t nsttl = 0;
1998 dns_rdataset_init(&rdataset);
1999 dns_fixedname_init(&fname);
2000 name = dns_fixedname_name(&fname);
2001 dns_fixedname_init(&fnextname);
2002 nextname = dns_fixedname_name(&fnextname);
2003 dns_fixedname_init(&fzonecut);
2007 * Remove any NSEC3 chains.
2009 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
2010 check_result(result, "dns_db_createiterator()");
2011 for (result = dns_dbiterator_first(dbiter);
2012 result == ISC_R_SUCCESS;
2013 result = dns_dbiterator_next(dbiter)) {
2014 result = dns_dbiterator_current(dbiter, &node, name);
2015 check_dns_dbiterator_current(result);
2016 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
2017 check_result(result, "dns_db_allrdatasets()");
2018 for (result = dns_rdatasetiter_first(rdsiter);
2019 result == ISC_R_SUCCESS;
2020 result = dns_rdatasetiter_next(rdsiter)) {
2021 dns_rdatasetiter_current(rdsiter, &rdataset);
2022 type = rdataset.type;
2023 covers = rdataset.covers;
2024 dns_rdataset_disassociate(&rdataset);
2025 result = dns_db_deleterdataset(gdb, node, gversion,
2027 check_result(result,
2028 "dns_db_deleterdataset(nsec3param/rrsig)");
2030 dns_rdatasetiter_destroy(&rdsiter);
2031 dns_db_detachnode(gdb, &node);
2033 dns_dbiterator_destroy(&dbiter);
2035 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2036 check_result(result, "dns_db_createiterator()");
2038 result = dns_dbiterator_first(dbiter);
2039 check_result(result, "dns_dbiterator_first()");
2042 result = dns_dbiterator_current(dbiter, &node, name);
2043 check_dns_dbiterator_current(result);
2045 * Skip out-of-zone records.
2047 if (!dns_name_issubdomain(name, gorigin)) {
2048 result = dns_dbiterator_next(dbiter);
2049 if (result == ISC_R_NOMORE)
2052 check_result(result, "dns_dbiterator_next()");
2053 dns_db_detachnode(gdb, &node);
2057 if (dns_name_equal(name, gorigin))
2058 remove_records(node, dns_rdatatype_nsec3param);
2060 if (delegation(name, node, &nsttl)) {
2061 zonecut = dns_fixedname_name(&fzonecut);
2062 dns_name_copy(name, zonecut, NULL);
2064 add_ds(name, node, nsttl);
2066 result = dns_dbiterator_next(dbiter);
2068 while (result == ISC_R_SUCCESS) {
2069 isc_boolean_t active = ISC_FALSE;
2070 result = dns_dbiterator_current(dbiter, &nextnode,
2072 check_dns_dbiterator_current(result);
2073 active = active_node(nextnode);
2075 dns_db_detachnode(gdb, &nextnode);
2076 result = dns_dbiterator_next(dbiter);
2079 if (!dns_name_issubdomain(nextname, gorigin) ||
2081 dns_name_issubdomain(nextname, zonecut)))
2083 dns_db_detachnode(gdb, &nextnode);
2084 result = dns_dbiterator_next(dbiter);
2087 dns_db_detachnode(gdb, &nextnode);
2090 if (result == ISC_R_NOMORE) {
2091 dns_name_clone(gorigin, nextname);
2093 } else if (result != ISC_R_SUCCESS)
2094 fatal("iterating through the database failed: %s",
2095 isc_result_totext(result));
2096 result = dns_nsec_build(gdb, gversion, node, nextname,
2098 check_result(result, "dns_nsec_build()");
2099 dns_db_detachnode(gdb, &node);
2102 dns_dbiterator_destroy(&dbiter);
2106 addnsec3param(const unsigned char *salt, size_t salt_length,
2107 unsigned int iterations)
2109 dns_dbnode_t *node = NULL;
2110 dns_rdata_nsec3param_t nsec3param;
2111 unsigned char nsec3parambuf[5 + 255];
2112 dns_rdatalist_t rdatalist;
2113 dns_rdataset_t rdataset;
2114 dns_rdata_t rdata = DNS_RDATA_INIT;
2116 isc_result_t result;
2118 dns_rdataset_init(&rdataset);
2120 nsec3param.common.rdclass = gclass;
2121 nsec3param.common.rdtype = dns_rdatatype_nsec3param;
2122 ISC_LINK_INIT(&nsec3param.common, link);
2123 nsec3param.mctx = NULL;
2124 nsec3param.flags = 0;
2125 nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1;
2126 nsec3param.iterations = iterations;
2127 nsec3param.salt_length = salt_length;
2128 DE_CONST(salt, nsec3param.salt);
2130 isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf));
2131 result = dns_rdata_fromstruct(&rdata, gclass,
2132 dns_rdatatype_nsec3param,
2134 check_result(result, "dns_rdata_fromstruct()");
2135 rdatalist.rdclass = rdata.rdclass;
2136 rdatalist.type = rdata.type;
2137 rdatalist.covers = 0;
2139 ISC_LIST_INIT(rdatalist.rdata);
2140 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
2141 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
2142 check_result(result, "dns_rdatalist_tordataset()");
2144 result = dns_db_findnode(gdb, gorigin, ISC_TRUE, &node);
2145 check_result(result, "dns_db_find(gorigin)");
2148 * Delete any current NSEC3PARAM records.
2150 result = dns_db_deleterdataset(gdb, node, gversion,
2151 dns_rdatatype_nsec3param, 0);
2152 if (result == DNS_R_UNCHANGED)
2153 result = ISC_R_SUCCESS;
2154 check_result(result, "dddnsec3param: dns_db_deleterdataset()");
2156 result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset,
2157 DNS_DBADD_MERGE, NULL);
2158 if (result == DNS_R_UNCHANGED)
2159 result = ISC_R_SUCCESS;
2160 check_result(result, "addnsec3param: dns_db_addrdataset()");
2161 dns_db_detachnode(gdb, &node);
2165 addnsec3(dns_name_t *name, dns_dbnode_t *node,
2166 const unsigned char *salt, size_t salt_length,
2167 unsigned int iterations, hashlist_t *hashlist,
2170 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
2171 const unsigned char *nexthash;
2172 unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE];
2173 dns_fixedname_t hashname;
2174 dns_rdatalist_t rdatalist;
2175 dns_rdataset_t rdataset;
2176 dns_rdata_t rdata = DNS_RDATA_INIT;
2177 isc_result_t result;
2178 dns_dbnode_t *nsec3node = NULL;
2179 char namebuf[DNS_NAME_FORMATSIZE];
2182 dns_name_format(name, namebuf, sizeof(namebuf));
2184 dns_fixedname_init(&hashname);
2185 dns_rdataset_init(&rdataset);
2187 dns_name_downcase(name, name, NULL);
2188 result = dns_nsec3_hashname(&hashname, hash, &hash_length,
2189 name, gorigin, dns_hash_sha1, iterations,
2191 check_result(result, "addnsec3: dns_nsec3_hashname()");
2192 nexthash = hashlist_findnext(hashlist, hash);
2193 result = dns_nsec3_buildrdata(gdb, gversion, node,
2195 DNS_NSEC3_UNKNOWNALG : dns_hash_sha1,
2196 nsec3flags, iterations,
2198 nexthash, ISC_SHA1_DIGESTLENGTH,
2199 nsec3buffer, &rdata);
2200 check_result(result, "addnsec3: dns_nsec3_buildrdata()");
2201 rdatalist.rdclass = rdata.rdclass;
2202 rdatalist.type = rdata.type;
2203 rdatalist.covers = 0;
2204 rdatalist.ttl = ttl;
2205 ISC_LIST_INIT(rdatalist.rdata);
2206 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
2207 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
2208 check_result(result, "dns_rdatalist_tordataset()");
2209 result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname),
2210 ISC_TRUE, &nsec3node);
2211 check_result(result, "addnsec3: dns_db_findnode()");
2212 result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset,
2214 if (result == DNS_R_UNCHANGED)
2215 result = ISC_R_SUCCESS;
2216 check_result(result, "addnsec3: dns_db_addrdataset()");
2217 dns_db_detachnode(gdb, &nsec3node);
2221 * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list.
2223 * Extract the hash from the first label of 'name' then see if it
2224 * is in hashlist. If 'name' is not in the hashlist then delete the
2225 * any NSEC3 records which have the same parameters as the chain we
2228 * XXXMPA Should we also check that it of the form <hash>.<origin>?
2231 nsec3clean(dns_name_t *name, dns_dbnode_t *node,
2232 unsigned int hashalg, unsigned int iterations,
2233 const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
2236 dns_rdata_nsec3_t nsec3;
2237 dns_rdata_t rdata, delrdata;
2238 dns_rdatalist_t rdatalist;
2239 dns_rdataset_t rdataset, delrdataset;
2240 isc_boolean_t delete_rrsigs = ISC_FALSE;
2241 isc_buffer_t target;
2242 isc_result_t result;
2243 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
2244 isc_boolean_t exists;
2247 * Get the first label.
2249 dns_name_getlabel(name, 0, &label);
2252 * We want just the label contents.
2254 isc_region_consume(&label, 1);
2257 * Decode base32hex string.
2259 isc_buffer_init(&target, hash, sizeof(hash) - 1);
2260 result = isc_base32hex_decoderegion(&label, &target);
2261 if (result != ISC_R_SUCCESS)
2264 hash[isc_buffer_usedlength(&target)] = 0;
2266 exists = hashlist_exists(hashlist, hash);
2269 * Verify that the NSEC3 parameters match the current ones
2270 * otherwise we are dealing with a different NSEC3 chain.
2272 dns_rdataset_init(&rdataset);
2273 dns_rdataset_init(&delrdataset);
2275 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3,
2276 0, 0, &rdataset, NULL);
2277 if (result != ISC_R_SUCCESS)
2281 * Delete any NSEC3 records which are not part of the current
2284 for (result = dns_rdataset_first(&rdataset);
2285 result == ISC_R_SUCCESS;
2286 result = dns_rdataset_next(&rdataset)) {
2287 dns_rdata_init(&rdata);
2288 dns_rdataset_current(&rdataset, &rdata);
2289 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
2290 check_result(result, "dns_rdata_tostruct");
2291 if (exists && nsec3.hash == hashalg &&
2292 nsec3.iterations == iterations &&
2293 nsec3.salt_length == salt_length &&
2294 !memcmp(nsec3.salt, salt, salt_length))
2296 rdatalist.rdclass = rdata.rdclass;
2297 rdatalist.type = rdata.type;
2298 rdatalist.covers = 0;
2299 rdatalist.ttl = rdataset.ttl;
2300 ISC_LIST_INIT(rdatalist.rdata);
2301 dns_rdata_init(&delrdata);
2302 dns_rdata_clone(&rdata, &delrdata);
2303 ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link);
2304 result = dns_rdatalist_tordataset(&rdatalist, &delrdataset);
2305 check_result(result, "dns_rdatalist_tordataset()");
2306 result = dns_db_subtractrdataset(gdb, node, gversion,
2307 &delrdataset, 0, NULL);
2308 dns_rdataset_disassociate(&delrdataset);
2309 if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET)
2310 check_result(result, "dns_db_subtractrdataset(NSEC3)");
2311 delete_rrsigs = ISC_TRUE;
2313 dns_rdataset_disassociate(&rdataset);
2314 if (result != ISC_R_NOMORE)
2315 check_result(result, "dns_rdataset_first/next");
2320 * Delete the NSEC3 RRSIGs
2322 result = dns_db_deleterdataset(gdb, node, gversion,
2323 dns_rdatatype_rrsig,
2324 dns_rdatatype_nsec3);
2325 if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
2326 check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))");
2330 * Generate NSEC3 records for the zone.
2333 nsec3ify(unsigned int hashalg, unsigned int iterations,
2334 const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
2336 dns_dbiterator_t *dbiter = NULL;
2337 dns_dbnode_t *node = NULL, *nextnode = NULL;
2338 dns_fixedname_t fname, fnextname, fzonecut;
2339 dns_name_t *name, *nextname, *zonecut;
2340 dns_rdataset_t rdataset;
2342 isc_boolean_t active;
2343 isc_boolean_t done = ISC_FALSE;
2344 isc_result_t result;
2345 isc_uint32_t nsttl = 0;
2346 unsigned int count, nlabels;
2348 dns_rdataset_init(&rdataset);
2349 dns_fixedname_init(&fname);
2350 name = dns_fixedname_name(&fname);
2351 dns_fixedname_init(&fnextname);
2352 nextname = dns_fixedname_name(&fnextname);
2353 dns_fixedname_init(&fzonecut);
2357 * Walk the zone generating the hash names.
2359 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2360 check_result(result, "dns_db_createiterator()");
2362 result = dns_dbiterator_first(dbiter);
2363 check_result(result, "dns_dbiterator_first()");
2366 result = dns_dbiterator_current(dbiter, &node, name);
2367 check_dns_dbiterator_current(result);
2369 * Skip out-of-zone records.
2371 if (!dns_name_issubdomain(name, gorigin)) {
2372 result = dns_dbiterator_next(dbiter);
2373 if (result == ISC_R_NOMORE)
2376 check_result(result, "dns_dbiterator_next()");
2377 dns_db_detachnode(gdb, &node);
2381 if (dns_name_equal(name, gorigin))
2382 remove_records(node, dns_rdatatype_nsec);
2384 result = dns_dbiterator_next(dbiter);
2386 while (result == ISC_R_SUCCESS) {
2387 result = dns_dbiterator_current(dbiter, &nextnode,
2389 check_dns_dbiterator_current(result);
2390 active = active_node(nextnode);
2392 dns_db_detachnode(gdb, &nextnode);
2393 result = dns_dbiterator_next(dbiter);
2396 if (!dns_name_issubdomain(nextname, gorigin) ||
2398 dns_name_issubdomain(nextname, zonecut))) {
2399 dns_db_detachnode(gdb, &nextnode);
2400 result = dns_dbiterator_next(dbiter);
2403 if (delegation(nextname, nextnode, &nsttl)) {
2404 zonecut = dns_fixedname_name(&fzonecut);
2405 dns_name_copy(nextname, zonecut, NULL);
2407 add_ds(nextname, nextnode, nsttl);
2408 if (OPTOUT(nsec3flags) &&
2409 !secure(nextname, nextnode)) {
2410 dns_db_detachnode(gdb, &nextnode);
2411 result = dns_dbiterator_next(dbiter);
2415 dns_db_detachnode(gdb, &nextnode);
2418 if (result == ISC_R_NOMORE) {
2419 dns_name_copy(gorigin, nextname, NULL);
2421 } else if (result != ISC_R_SUCCESS)
2422 fatal("iterating through the database failed: %s",
2423 isc_result_totext(result));
2424 dns_name_downcase(name, name, NULL);
2425 hashlist_add_dns_name(hashlist, name, hashalg, iterations,
2426 salt, salt_length, ISC_FALSE);
2427 dns_db_detachnode(gdb, &node);
2429 * Add hashs for empty nodes. Use closest encloser logic.
2430 * The closest encloser either has data or is a empty
2431 * node for another <name,nextname> span so we don't add
2432 * it here. Empty labels on nextname are within the span.
2434 dns_name_downcase(nextname, nextname, NULL);
2435 dns_name_fullcompare(name, nextname, &order, &nlabels);
2436 addnowildcardhash(hashlist, name, hashalg, iterations,
2438 count = dns_name_countlabels(nextname);
2439 while (count > nlabels + 1) {
2441 dns_name_split(nextname, count, NULL, nextname);
2442 hashlist_add_dns_name(hashlist, nextname, hashalg,
2443 iterations, salt, salt_length,
2445 addnowildcardhash(hashlist, nextname, hashalg,
2446 iterations, salt, salt_length);
2449 dns_dbiterator_destroy(&dbiter);
2452 * We have all the hashes now so we can sort them.
2454 hashlist_sort(hashlist);
2457 * Check for duplicate hashes. If found the salt needs to
2460 if (hashlist_hasdup(hashlist))
2461 fatal("Duplicate hash detected. Pick a different salt.");
2464 * Generate the nsec3 records.
2469 addnsec3param(salt, salt_length, iterations);
2472 * Clean out NSEC3 records which don't match this chain.
2474 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
2475 check_result(result, "dns_db_createiterator()");
2477 for (result = dns_dbiterator_first(dbiter);
2478 result == ISC_R_SUCCESS;
2479 result = dns_dbiterator_next(dbiter)) {
2480 result = dns_dbiterator_current(dbiter, &node, name);
2481 check_dns_dbiterator_current(result);
2482 nsec3clean(name, node, hashalg, iterations, salt, salt_length,
2484 dns_db_detachnode(gdb, &node);
2486 dns_dbiterator_destroy(&dbiter);
2489 * Generate / complete the new chain.
2491 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2492 check_result(result, "dns_db_createiterator()");
2494 result = dns_dbiterator_first(dbiter);
2495 check_result(result, "dns_dbiterator_first()");
2498 result = dns_dbiterator_current(dbiter, &node, name);
2499 check_dns_dbiterator_current(result);
2501 * Skip out-of-zone records.
2503 if (!dns_name_issubdomain(name, gorigin)) {
2504 result = dns_dbiterator_next(dbiter);
2505 if (result == ISC_R_NOMORE)
2508 check_result(result, "dns_dbiterator_next()");
2509 dns_db_detachnode(gdb, &node);
2512 result = dns_dbiterator_next(dbiter);
2514 while (result == ISC_R_SUCCESS) {
2515 result = dns_dbiterator_current(dbiter, &nextnode,
2517 check_dns_dbiterator_current(result);
2518 active = active_node(nextnode);
2520 dns_db_detachnode(gdb, &nextnode);
2521 result = dns_dbiterator_next(dbiter);
2524 if (!dns_name_issubdomain(nextname, gorigin) ||
2526 dns_name_issubdomain(nextname, zonecut))) {
2527 dns_db_detachnode(gdb, &nextnode);
2528 result = dns_dbiterator_next(dbiter);
2531 if (delegation(nextname, nextnode, NULL)) {
2532 zonecut = dns_fixedname_name(&fzonecut);
2533 dns_name_copy(nextname, zonecut, NULL);
2534 if (OPTOUT(nsec3flags) &&
2535 !secure(nextname, nextnode)) {
2536 dns_db_detachnode(gdb, &nextnode);
2537 result = dns_dbiterator_next(dbiter);
2541 dns_db_detachnode(gdb, &nextnode);
2544 if (result == ISC_R_NOMORE) {
2545 dns_name_copy(gorigin, nextname, NULL);
2547 } else if (result != ISC_R_SUCCESS)
2548 fatal("iterating through the database failed: %s",
2549 isc_result_totext(result));
2551 * We need to pause here to release the lock on the database.
2553 dns_dbiterator_pause(dbiter);
2554 addnsec3(name, node, salt, salt_length, iterations,
2556 dns_db_detachnode(gdb, &node);
2558 * Add NSEC3's for empty nodes. Use closest encloser logic.
2560 dns_name_fullcompare(name, nextname, &order, &nlabels);
2561 count = dns_name_countlabels(nextname);
2562 while (count > nlabels + 1) {
2564 dns_name_split(nextname, count, NULL, nextname);
2565 addnsec3(nextname, NULL, salt, salt_length,
2566 iterations, hashlist, zonettl);
2569 dns_dbiterator_destroy(&dbiter);
2573 * Load the zone file from disk
2576 loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
2579 dns_fixedname_t fname;
2581 isc_result_t result;
2583 len = strlen(origin);
2584 isc_buffer_init(&b, origin, len);
2585 isc_buffer_add(&b, len);
2587 dns_fixedname_init(&fname);
2588 name = dns_fixedname_name(&fname);
2589 result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
2590 if (result != ISC_R_SUCCESS)
2591 fatal("failed converting name '%s' to dns format: %s",
2592 origin, isc_result_totext(result));
2594 result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
2595 rdclass, 0, NULL, db);
2596 check_result(result, "dns_db_create()");
2598 result = dns_db_load2(*db, file, inputformat);
2599 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
2600 fatal("failed loading zone from '%s': %s",
2601 file, isc_result_totext(result));
2605 * Finds all public zone keys in the zone, and attempts to load the
2606 * private keys from disk.
2609 loadzonekeys(dns_db_t *db) {
2611 dns_dbversion_t *currentversion;
2612 isc_result_t result;
2613 dst_key_t *keys[20];
2614 unsigned int nkeys, i;
2616 currentversion = NULL;
2617 dns_db_currentversion(db, ¤tversion);
2620 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
2621 if (result != ISC_R_SUCCESS)
2622 fatal("failed to find the zone's origin: %s",
2623 isc_result_totext(result));
2625 result = dns_dnssec_findzonekeys(db, currentversion, node, gorigin,
2626 mctx, 20, keys, &nkeys);
2627 if (result == ISC_R_NOTFOUND)
2628 result = ISC_R_SUCCESS;
2629 if (result != ISC_R_SUCCESS)
2630 fatal("failed to find the zone keys: %s",
2631 isc_result_totext(result));
2633 for (i = 0; i < nkeys; i++) {
2636 key = newkeystruct(keys[i], dst_key_isprivate(keys[i]));
2637 ISC_LIST_APPEND(keylist, key, link);
2639 dns_db_detachnode(db, &node);
2640 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
2644 * Finds all public zone keys in the zone.
2647 loadzonepubkeys(dns_db_t *db) {
2648 dns_dbversion_t *currentversion = NULL;
2649 dns_dbnode_t *node = NULL;
2650 dns_rdataset_t rdataset;
2651 dns_rdata_t rdata = DNS_RDATA_INIT;
2654 isc_result_t result;
2656 dns_db_currentversion(db, ¤tversion);
2658 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
2659 if (result != ISC_R_SUCCESS)
2660 fatal("failed to find the zone's origin: %s",
2661 isc_result_totext(result));
2663 dns_rdataset_init(&rdataset);
2664 result = dns_db_findrdataset(db, node, currentversion,
2665 dns_rdatatype_dnskey, 0, 0, &rdataset,
2667 if (result != ISC_R_SUCCESS)
2668 fatal("failed to find keys at the zone apex: %s",
2669 isc_result_totext(result));
2670 result = dns_rdataset_first(&rdataset);
2671 check_result(result, "dns_rdataset_first");
2672 while (result == ISC_R_SUCCESS) {
2674 dns_rdata_reset(&rdata);
2675 dns_rdataset_current(&rdataset, &rdata);
2676 result = dns_dnssec_keyfromrdata(gorigin, &rdata, mctx,
2678 if (result != ISC_R_SUCCESS)
2680 if (!dst_key_iszonekey(pubkey)) {
2681 dst_key_free(&pubkey);
2685 key = newkeystruct(pubkey, ISC_FALSE);
2686 ISC_LIST_APPEND(keylist, key, link);
2688 result = dns_rdataset_next(&rdataset);
2690 dns_rdataset_disassociate(&rdataset);
2691 dns_db_detachnode(db, &node);
2692 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
2696 warnifallksk(dns_db_t *db) {
2697 dns_dbversion_t *currentversion = NULL;
2698 dns_dbnode_t *node = NULL;
2699 dns_rdataset_t rdataset;
2700 dns_rdata_t rdata = DNS_RDATA_INIT;
2701 isc_result_t result;
2702 dns_rdata_dnskey_t dnskey;
2703 isc_boolean_t have_non_ksk = ISC_FALSE;
2705 dns_db_currentversion(db, ¤tversion);
2707 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
2708 if (result != ISC_R_SUCCESS)
2709 fatal("failed to find the zone's origin: %s",
2710 isc_result_totext(result));
2712 dns_rdataset_init(&rdataset);
2713 result = dns_db_findrdataset(db, node, currentversion,
2714 dns_rdatatype_dnskey, 0, 0, &rdataset,
2716 if (result != ISC_R_SUCCESS)
2717 fatal("failed to find keys at the zone apex: %s",
2718 isc_result_totext(result));
2719 result = dns_rdataset_first(&rdataset);
2720 check_result(result, "dns_rdataset_first");
2721 while (result == ISC_R_SUCCESS) {
2722 dns_rdata_reset(&rdata);
2723 dns_rdataset_current(&rdataset, &rdata);
2724 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2725 check_result(result, "dns_rdata_tostruct");
2726 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
2727 have_non_ksk = ISC_TRUE;
2728 result = ISC_R_NOMORE;
2730 result = dns_rdataset_next(&rdataset);
2731 dns_rdata_freestruct(&dnskey);
2733 dns_rdataset_disassociate(&rdataset);
2734 dns_db_detachnode(db, &node);
2735 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
2736 if (!have_non_ksk && !ignoreksk) {
2737 if (disable_zone_check)
2738 fprintf(stderr, "%s: warning: No non-KSK dnskey found. "
2739 "Supply non-KSK dnskey or use '-z'.\n",
2742 fatal("No non-KSK dnskey found. "
2743 "Supply non-KSK dnskey or use '-z'.");
2748 writeset(const char *prefix, dns_rdatatype_t type) {
2750 char namestr[DNS_NAME_FORMATSIZE];
2751 dns_db_t *db = NULL;
2752 dns_dbversion_t *version = NULL;
2754 dns_difftuple_t *tuple = NULL;
2755 dns_fixedname_t fixed;
2757 dns_rdata_t rdata, ds;
2758 isc_boolean_t have_ksk = ISC_FALSE;
2759 isc_boolean_t have_non_ksk = ISC_FALSE;
2761 isc_buffer_t namebuf;
2763 isc_result_t result;
2765 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
2766 unsigned char keybuf[DST_KEY_MAXSIZE];
2767 unsigned int filenamelen;
2768 const dns_master_style_t *style =
2769 (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
2771 isc_buffer_init(&namebuf, namestr, sizeof(namestr));
2772 result = dns_name_tofilenametext(gorigin, ISC_FALSE, &namebuf);
2773 check_result(result, "dns_name_tofilenametext");
2774 isc_buffer_putuint8(&namebuf, 0);
2775 filenamelen = strlen(prefix) + strlen(namestr);
2776 if (directory != NULL)
2777 filenamelen += strlen(directory) + 1;
2778 filename = isc_mem_get(mctx, filenamelen + 1);
2779 if (filename == NULL)
2780 fatal("out of memory");
2781 if (directory != NULL)
2782 sprintf(filename, "%s/", directory);
2785 strcat(filename, prefix);
2786 strcat(filename, namestr);
2788 dns_diff_init(mctx, &diff);
2790 for (key = ISC_LIST_HEAD(keylist);
2792 key = ISC_LIST_NEXT(key, link))
2794 have_non_ksk = ISC_TRUE;
2798 for (key = ISC_LIST_HEAD(keylist);
2800 key = ISC_LIST_NEXT(key, link))
2802 have_ksk = ISC_TRUE;
2806 if (type == dns_rdatatype_dlv) {
2808 unsigned int labels;
2810 dns_name_init(&tname, NULL);
2811 dns_fixedname_init(&fixed);
2812 name = dns_fixedname_name(&fixed);
2813 labels = dns_name_countlabels(gorigin);
2814 dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
2815 result = dns_name_concatenate(&tname, dlv, name, NULL);
2816 check_result(result, "dns_name_concatenate");
2820 for (key = ISC_LIST_HEAD(keylist);
2822 key = ISC_LIST_NEXT(key, link))
2824 if (have_ksk && have_non_ksk && !key->isksk)
2826 dns_rdata_init(&rdata);
2827 dns_rdata_init(&ds);
2828 isc_buffer_init(&b, keybuf, sizeof(keybuf));
2829 result = dst_key_todns(key->key, &b);
2830 check_result(result, "dst_key_todns");
2831 isc_buffer_usedregion(&b, &r);
2832 dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
2833 if (type != dns_rdatatype_dnskey) {
2834 result = dns_ds_buildrdata(gorigin, &rdata,
2837 check_result(result, "dns_ds_buildrdata");
2838 if (type == dns_rdatatype_dlv)
2839 ds.type = dns_rdatatype_dlv;
2840 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
2841 name, 0, &ds, &tuple);
2842 check_result(result, "dns_difftuple_create");
2843 dns_diff_append(&diff, &tuple);
2845 dns_rdata_reset(&ds);
2846 result = dns_ds_buildrdata(gorigin, &rdata,
2847 DNS_DSDIGEST_SHA256,
2849 check_result(result, "dns_ds_buildrdata");
2850 if (type == dns_rdatatype_dlv)
2851 ds.type = dns_rdatatype_dlv;
2852 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
2853 name, 0, &ds, &tuple);
2856 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
2859 check_result(result, "dns_difftuple_create");
2860 dns_diff_append(&diff, &tuple);
2863 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
2864 gclass, 0, NULL, &db);
2865 check_result(result, "dns_db_create");
2867 result = dns_db_newversion(db, &version);
2868 check_result(result, "dns_db_newversion");
2870 result = dns_diff_apply(&diff, db, version);
2871 check_result(result, "dns_diff_apply");
2872 dns_diff_clear(&diff);
2874 result = dns_master_dump(mctx, db, version, style, filename);
2875 check_result(result, "dns_master_dump");
2877 isc_mem_put(mctx, filename, filenamelen + 1);
2879 dns_db_closeversion(db, &version, ISC_FALSE);
2884 print_time(FILE *fp) {
2887 if (outputformat != dns_masterformat_text)
2890 currenttime = time(NULL);
2891 fprintf(fp, "; File written on %s", ctime(¤ttime));
2895 print_version(FILE *fp) {
2896 if (outputformat != dns_masterformat_text)
2899 fprintf(fp, "; dnssec_signzone version " VERSION "\n");
2904 fprintf(stderr, "Usage:\n");
2905 fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
2907 fprintf(stderr, "\n");
2909 fprintf(stderr, "Version: %s\n", VERSION);
2911 fprintf(stderr, "Options: (default value in parenthesis) \n");
2912 fprintf(stderr, "\t-c class (IN)\n");
2913 fprintf(stderr, "\t-d directory\n");
2914 fprintf(stderr, "\t\tdirectory to find keyset files (.)\n");
2915 fprintf(stderr, "\t-g:\t");
2916 fprintf(stderr, "generate DS records from keyset files\n");
2917 fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
2918 fprintf(stderr, "\t\tRRSIG start time - absolute|offset "
2919 "(now - 1 hour)\n");
2920 fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
2921 fprintf(stderr, "\t\tRRSIG end time - absolute|from start|from now "
2922 "(now + 30 days)\n");
2923 fprintf(stderr, "\t-i interval:\n");
2924 fprintf(stderr, "\t\tcycle interval - resign "
2925 "if < interval from end ( (end-start)/4 )\n");
2926 fprintf(stderr, "\t-j jitter:\n");
2927 fprintf(stderr, "\t\trandomize signature end time up to jitter "
2929 fprintf(stderr, "\t-v debuglevel (0)\n");
2930 fprintf(stderr, "\t-o origin:\n");
2931 fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
2932 fprintf(stderr, "\t-f outfile:\n");
2933 fprintf(stderr, "\t\tfile the signed zone is written in "
2934 "(zonefile + .signed)\n");
2935 fprintf(stderr, "\t-I format:\n");
2936 fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
2937 fprintf(stderr, "\t-O format:\n");
2938 fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
2939 fprintf(stderr, "\t-N format:\n");
2940 fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
2941 fprintf(stderr, "\t-r randomdev:\n");
2942 fprintf(stderr, "\t\ta file containing random data\n");
2943 fprintf(stderr, "\t-a:\t");
2944 fprintf(stderr, "verify generated signatures\n");
2945 fprintf(stderr, "\t-p:\t");
2946 fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
2947 fprintf(stderr, "\t-P:\t");
2948 fprintf(stderr, "disable post-sign verification\n");
2949 fprintf(stderr, "\t-t:\t");
2950 fprintf(stderr, "print statistics\n");
2951 fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
2952 fprintf(stderr, "\t-k key_signing_key\n");
2953 fprintf(stderr, "\t-l lookasidezone\n");
2954 fprintf(stderr, "\t-3 salt (NSEC3 salt)\n");
2955 fprintf(stderr, "\t-H iterations (NSEC3 iterations)\n");
2956 fprintf(stderr, "\t-A (NSEC3 optout)\n");
2957 fprintf(stderr, "\t-z:\t");
2958 fprintf(stderr, "ignore KSK flag in DNSKEYs");
2960 fprintf(stderr, "\n");
2962 fprintf(stderr, "Signing Keys: ");
2963 fprintf(stderr, "(default: all zone keys that have private keys)\n");
2964 fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
2969 removetempfile(void) {
2971 isc_file_remove(tempfile);
2975 print_stats(isc_time_t *timer_start, isc_time_t *timer_finish) {
2976 isc_uint64_t runtime_us; /* Runtime in microseconds */
2977 isc_uint64_t runtime_ms; /* Runtime in milliseconds */
2978 isc_uint64_t sig_ms; /* Signatures per millisecond */
2980 runtime_us = isc_time_microdiff(timer_finish, timer_start);
2982 printf("Signatures generated: %10d\n", nsigned);
2983 printf("Signatures retained: %10d\n", nretained);
2984 printf("Signatures dropped: %10d\n", ndropped);
2985 printf("Signatures successfully verified: %10d\n", nverified);
2986 printf("Signatures unsuccessfully verified: %10d\n", nverifyfailed);
2987 runtime_ms = runtime_us / 1000;
2988 printf("Runtime in seconds: %7u.%03u\n",
2989 (unsigned int) (runtime_ms / 1000),
2990 (unsigned int) (runtime_ms % 1000));
2991 if (runtime_us > 0) {
2992 sig_ms = ((isc_uint64_t)nsigned * 1000000000) / runtime_us;
2993 printf("Signatures per second: %7u.%03u\n",
2994 (unsigned int) sig_ms / 1000,
2995 (unsigned int) sig_ms % 1000);
3000 main(int argc, char *argv[]) {
3002 char *startstr = NULL, *endstr = NULL, *classname = NULL;
3003 char *origin = NULL, *file = NULL, *output = NULL;
3004 char *inputformatstr = NULL, *outputformatstr = NULL;
3005 char *serialformatstr = NULL;
3006 char *dskeyfile[MAXDSKEYS];
3009 isc_time_t timer_start, timer_finish;
3011 isc_result_t result;
3012 isc_log_t *log = NULL;
3013 isc_boolean_t pseudorandom = ISC_FALSE;
3014 unsigned int eflags;
3015 isc_boolean_t free_output = ISC_FALSE;
3017 dns_rdataclass_t rdclass;
3018 isc_task_t **tasks = NULL;
3021 unsigned int iterations = 100U;
3022 const unsigned char *salt = NULL;
3023 size_t salt_length = 0;
3024 unsigned char saltbuf[255];
3025 hashlist_t hashlist;
3027 #define CMDLINE_FLAGS "3:aAc:d:e:f:FghH:i:I:j:k:l:m:n:N:o:O:pPr:s:StUv:z"
3030 * Process memory debugging argument first.
3032 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3035 if (strcasecmp(isc_commandline_argument, "record") == 0)
3036 isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
3037 if (strcasecmp(isc_commandline_argument, "trace") == 0)
3038 isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
3039 if (strcasecmp(isc_commandline_argument, "usage") == 0)
3040 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
3041 if (strcasecmp(isc_commandline_argument, "size") == 0)
3042 isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
3043 if (strcasecmp(isc_commandline_argument, "mctx") == 0)
3044 isc_mem_debugging |= ISC_MEM_DEBUGCTX;
3050 isc_commandline_reset = ISC_TRUE;
3052 masterstyle = &dns_master_style_explicitttl;
3054 check_result(isc_app_start(), "isc_app_start");
3056 result = isc_mem_create(0, 0, &mctx);
3057 if (result != ISC_R_SUCCESS)
3058 fatal("out of memory");
3060 dns_result_register();
3062 isc_commandline_errprint = ISC_FALSE;
3064 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3067 if (strcmp(isc_commandline_argument, "-")) {
3068 isc_buffer_t target;
3071 sarg = isc_commandline_argument;
3072 isc_buffer_init(&target, saltbuf,
3074 result = isc_hex_decodestring(sarg, &target);
3075 check_result(result,
3076 "isc_hex_decodestring(salt)");
3078 salt_length = isc_buffer_usedlength(&target);
3083 nsec_datatype = dns_rdatatype_nsec3;
3087 nsec3flags |= DNS_NSEC3FLAG_OPTOUT;
3091 tryverify = ISC_TRUE;
3095 classname = isc_commandline_argument;
3099 directory = isc_commandline_argument;
3103 endstr = isc_commandline_argument;
3107 output = isc_commandline_argument;
3111 generateds = ISC_TRUE;
3115 iterations = strtoul(isc_commandline_argument,
3118 fatal("iterations must be numeric");
3119 if (iterations > 0xffffU)
3120 fatal("iterations too big");
3129 cycle = strtol(isc_commandline_argument, &endp, 0);
3130 if (*endp != '\0' || cycle < 0)
3131 fatal("cycle period must be numeric and "
3136 inputformatstr = isc_commandline_argument;
3141 jitter = strtol(isc_commandline_argument, &endp, 0);
3142 if (*endp != '\0' || jitter < 0)
3143 fatal("jitter must be numeric and positive");
3147 if (ndskeys == MAXDSKEYS)
3148 fatal("too many key-signing keys specified");
3149 dskeyfile[ndskeys++] = isc_commandline_argument;
3153 len = strlen(isc_commandline_argument);
3154 isc_buffer_init(&b, isc_commandline_argument, len);
3155 isc_buffer_add(&b, len);
3157 dns_fixedname_init(&dlv_fixed);
3158 dlv = dns_fixedname_name(&dlv_fixed);
3159 result = dns_name_fromtext(dlv, &b, dns_rootname,
3161 check_result(result, "dns_name_fromtext(dlv)");
3169 ntasks = strtol(isc_commandline_argument, &endp, 0);
3170 if (*endp != '\0' || ntasks > ISC_INT32_MAX)
3171 fatal("number of cpus must be numeric");
3175 serialformatstr = isc_commandline_argument;
3179 origin = isc_commandline_argument;
3183 outputformatstr = isc_commandline_argument;
3187 pseudorandom = ISC_TRUE;
3191 disable_zone_check = ISC_TRUE;
3195 setup_entropy(mctx, isc_commandline_argument, &ectx);
3199 startstr = isc_commandline_argument;
3203 /* This is intentionally undocumented */
3204 /* -S: simple output style */
3205 masterstyle = &dns_master_style_simple;
3209 printstats = ISC_TRUE;
3212 case 'U': /* Undocumented for testing only. */
3213 unknownalg = ISC_TRUE;
3218 verbose = strtol(isc_commandline_argument, &endp, 0);
3220 fatal("verbose level must be numeric");
3224 ignoreksk = ISC_TRUE;
3228 /* Reserved for FIPS mode */
3231 if (isc_commandline_option != '?')
3232 fprintf(stderr, "%s: invalid argument -%c\n",
3233 program, isc_commandline_option);
3238 fprintf(stderr, "%s: unhandled option -%c\n",
3239 program, isc_commandline_option);
3245 setup_entropy(mctx, NULL, &ectx);
3246 eflags = ISC_ENTROPY_BLOCKING;
3248 eflags |= ISC_ENTROPY_GOODONLY;
3250 result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
3251 if (result != ISC_R_SUCCESS)
3252 fatal("could not create hash context");
3254 result = dst_lib_init(mctx, ectx, eflags);
3255 if (result != ISC_R_SUCCESS)
3256 fatal("could not initialize dst");
3258 isc_stdtime_get(&now);
3260 if (startstr != NULL)
3261 starttime = strtotime(startstr, now, now);
3263 starttime = now - 3600; /* Allow for some clock skew. */
3266 endtime = strtotime(endstr, now, starttime);
3268 endtime = starttime + (30 * 24 * 60 * 60);
3271 cycle = (endtime - starttime) / 4;
3274 ntasks = isc_os_ncpus() * 2;
3275 vbprintf(4, "using %d cpus\n", ntasks);
3277 rdclass = strtoclass(classname);
3279 setup_logging(verbose, mctx, &log);
3281 argc -= isc_commandline_index;
3282 argv += isc_commandline_index;
3295 if (output == NULL) {
3296 free_output = ISC_TRUE;
3297 output = isc_mem_allocate(mctx,
3298 strlen(file) + strlen(".signed") + 1);
3300 fatal("out of memory");
3301 sprintf(output, "%s.signed", file);
3304 if (inputformatstr != NULL) {
3305 if (strcasecmp(inputformatstr, "text") == 0)
3306 inputformat = dns_masterformat_text;
3307 else if (strcasecmp(inputformatstr, "raw") == 0)
3308 inputformat = dns_masterformat_raw;
3310 fatal("unknown file format: %s\n", inputformatstr);
3313 if (outputformatstr != NULL) {
3314 if (strcasecmp(outputformatstr, "text") == 0)
3315 outputformat = dns_masterformat_text;
3316 else if (strcasecmp(outputformatstr, "raw") == 0)
3317 outputformat = dns_masterformat_raw;
3319 fatal("unknown file format: %s\n", outputformatstr);
3322 if (serialformatstr != NULL) {
3323 if (strcasecmp(serialformatstr, "keep") == 0)
3324 serialformat = SOA_SERIAL_KEEP;
3325 else if (strcasecmp(serialformatstr, "increment") == 0 ||
3326 strcasecmp(serialformatstr, "incr") == 0)
3327 serialformat = SOA_SERIAL_INCREMENT;
3328 else if (strcasecmp(serialformatstr, "unixtime") == 0)
3329 serialformat = SOA_SERIAL_UNIXTIME;
3331 fatal("unknown soa serial format: %s\n",
3335 result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL,
3336 0, 24, 0, 0, 0, 8, mctx);
3337 check_result(result, "dns_master_stylecreate");
3340 TIME_NOW(&timer_start);
3341 loadzone(file, origin, rdclass, &gdb);
3342 gorigin = dns_db_origin(gdb);
3343 gclass = dns_db_class(gdb);
3347 isc_boolean_t answer;
3348 hash_length = dns_nsec3_hashlength(dns_hash_sha1);
3349 hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2,
3351 result = dns_nsec_nseconly(gdb, gversion, &answer);
3352 check_result(result, "dns_nsec_nseconly");
3354 fatal("NSEC3 generation requested with "
3355 "NSEC only DNSKEY");
3359 * We need to do this early on, as we start messing with the list
3360 * of keys rather early.
3362 ISC_LIST_INIT(keylist);
3363 isc_rwlock_init(&keylist_lock, 0, 0);
3368 for (i = 0; i < argc; i++) {
3369 dst_key_t *newkey = NULL;
3371 result = dst_key_fromnamedfile(argv[i],
3375 if (result != ISC_R_SUCCESS)
3376 fatal("cannot load dnskey %s: %s", argv[i],
3377 isc_result_totext(result));
3379 if (!dns_name_equal(gorigin, dst_key_name(newkey)))
3380 fatal("key %s not at origin\n", argv[i]);
3382 key = ISC_LIST_HEAD(keylist);
3383 while (key != NULL) {
3384 dst_key_t *dkey = key->key;
3385 if (dst_key_id(dkey) == dst_key_id(newkey) &&
3386 dst_key_alg(dkey) == dst_key_alg(newkey) &&
3387 dns_name_equal(dst_key_name(dkey),
3388 dst_key_name(newkey)))
3390 if (!dst_key_isprivate(dkey))
3391 fatal("cannot sign zone with "
3392 "non-private dnskey %s",
3396 key = ISC_LIST_NEXT(key, link);
3399 key = newkeystruct(newkey, ISC_TRUE);
3400 key->commandline = ISC_TRUE;
3401 ISC_LIST_APPEND(keylist, key, link);
3403 dst_key_free(&newkey);
3406 loadzonepubkeys(gdb);
3409 for (i = 0; i < ndskeys; i++) {
3410 dst_key_t *newkey = NULL;
3412 result = dst_key_fromnamedfile(dskeyfile[i],
3416 if (result != ISC_R_SUCCESS)
3417 fatal("cannot load dnskey %s: %s", dskeyfile[i],
3418 isc_result_totext(result));
3420 if (!dns_name_equal(gorigin, dst_key_name(newkey)))
3421 fatal("key %s not at origin\n", dskeyfile[i]);
3423 key = ISC_LIST_HEAD(keylist);
3424 while (key != NULL) {
3425 dst_key_t *dkey = key->key;
3426 if (dst_key_id(dkey) == dst_key_id(newkey) &&
3427 dst_key_alg(dkey) == dst_key_alg(newkey) &&
3428 dns_name_equal(dst_key_name(dkey),
3429 dst_key_name(newkey)))
3431 /* Override key flags. */
3432 key->issigningkey = ISC_TRUE;
3433 key->isksk = ISC_TRUE;
3434 key->isdsk = ISC_FALSE;
3435 dst_key_free(&dkey);
3439 key = ISC_LIST_NEXT(key, link);
3442 /* Override dnskey flags. */
3443 key = newkeystruct(newkey, ISC_TRUE);
3444 key->isksk = ISC_TRUE;
3445 key->isdsk = ISC_FALSE;
3446 ISC_LIST_APPEND(keylist, key, link);
3450 if (ISC_LIST_EMPTY(keylist)) {
3451 if (disable_zone_check)
3452 fprintf(stderr, "%s: warning: No keys specified "
3453 "or found\n", program);
3455 fatal("No signing keys specified or found.");
3463 result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max);
3464 check_result(result, "dns_nsec3_maxiterations()");
3465 if (iterations > max)
3466 fatal("NSEC3 iterations too big for weakest DNSKEY "
3467 "strength. Maximum iterations allowed %u.", max);
3471 result = dns_db_newversion(gdb, &gversion);
3472 check_result(result, "dns_db_newversion()");
3474 switch (serialformat) {
3475 case SOA_SERIAL_INCREMENT:
3478 case SOA_SERIAL_UNIXTIME:
3481 case SOA_SERIAL_KEEP:
3488 nsec3ify(dns_hash_sha1, iterations, salt, salt_length,
3494 writeset("keyset-", dns_rdatatype_dnskey);
3495 writeset("dsset-", dns_rdatatype_ds);
3497 writeset("dlvset-", dns_rdatatype_dlv);
3501 tempfilelen = strlen(output) + 20;
3502 tempfile = isc_mem_get(mctx, tempfilelen);
3503 if (tempfile == NULL)
3504 fatal("out of memory");
3506 result = isc_file_mktemplate(output, tempfile, tempfilelen);
3507 check_result(result, "isc_file_mktemplate");
3510 result = isc_file_openunique(tempfile, &fp);
3511 if (result != ISC_R_SUCCESS)
3512 fatal("failed to open temporary output file: %s",
3513 isc_result_totext(result));
3514 removefile = ISC_TRUE;
3515 setfatalcallback(&removetempfile);
3520 result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
3521 if (result != ISC_R_SUCCESS)
3522 fatal("failed to create task manager: %s",
3523 isc_result_totext(result));
3526 result = isc_task_create(taskmgr, 0, &master);
3527 if (result != ISC_R_SUCCESS)
3528 fatal("failed to create task: %s", isc_result_totext(result));
3530 tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
3532 fatal("out of memory");
3533 for (i = 0; i < (int)ntasks; i++) {
3535 result = isc_task_create(taskmgr, 0, &tasks[i]);
3536 if (result != ISC_R_SUCCESS)
3537 fatal("failed to create task: %s",
3538 isc_result_totext(result));
3541 RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS);
3543 RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS);
3549 * There is more work to do. Spread it out over multiple
3550 * processors if possible.
3552 for (i = 0; i < (int)ntasks; i++) {
3553 result = isc_app_onrun(mctx, master, startworker,
3555 if (result != ISC_R_SUCCESS)
3556 fatal("failed to start task: %s",
3557 isc_result_totext(result));
3559 (void)isc_app_run();
3561 fatal("process aborted by user");
3563 isc_task_detach(&master);
3564 shuttingdown = ISC_TRUE;
3565 for (i = 0; i < (int)ntasks; i++)
3566 isc_task_detach(&tasks[i]);
3567 isc_taskmgr_destroy(&taskmgr);
3568 isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
3572 if (outputformat != dns_masterformat_text) {
3573 result = dns_master_dumptostream2(mctx, gdb, gversion,
3574 masterstyle, outputformat,
3576 check_result(result, "dns_master_dumptostream2");
3579 result = isc_stdio_close(fp);
3580 check_result(result, "isc_stdio_close");
3581 removefile = ISC_FALSE;
3583 result = isc_file_rename(tempfile, output);
3584 if (result != ISC_R_SUCCESS)
3585 fatal("failed to rename temp file to %s: %s\n",
3586 output, isc_result_totext(result));
3588 DESTROYLOCK(&namelock);
3590 DESTROYLOCK(&statslock);
3592 printf("%s\n", output);
3594 dns_db_closeversion(gdb, &gversion, ISC_FALSE);
3595 dns_db_detach(&gdb);
3597 while (!ISC_LIST_EMPTY(keylist)) {
3598 key = ISC_LIST_HEAD(keylist);
3599 ISC_LIST_UNLINK(keylist, key, link);
3600 dst_key_free(&key->key);
3601 isc_mem_put(mctx, key, sizeof(signer_key_t));
3604 isc_mem_put(mctx, tempfile, tempfilelen);
3607 isc_mem_free(mctx, output);
3609 dns_master_styledestroy(&dsstyle, mctx);
3611 cleanup_logging(&log);
3614 cleanup_entropy(&ectx);
3617 isc_mem_stats(mctx, stdout);
3618 isc_mem_destroy(&mctx);
3620 (void) isc_app_finish();
3623 TIME_NOW(&timer_finish);
3624 print_stats(&timer_start, &timer_finish);