2 * Portions Copyright (C) 2004-2009 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.8 2009/06/08 22:23:06 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/serial.h>
55 #include <isc/stdio.h>
56 #include <isc/stdlib.h>
57 #include <isc/string.h>
63 #include <dns/dbiterator.h>
65 #include <dns/dnssec.h>
67 #include <dns/fixedname.h>
68 #include <dns/keyvalues.h>
70 #include <dns/master.h>
71 #include <dns/masterdump.h>
73 #include <dns/nsec3.h>
74 #include <dns/rdata.h>
75 #include <dns/rdatalist.h>
76 #include <dns/rdataset.h>
77 #include <dns/rdataclass.h>
78 #include <dns/rdatasetiter.h>
79 #include <dns/rdatastruct.h>
80 #include <dns/rdatatype.h>
81 #include <dns/result.h>
87 #include "dnssectool.h"
89 const char *program = "dnssec-signzone";
92 typedef struct hashlist hashlist_t;
94 static int nsec_datatype = dns_rdatatype_nsec;
96 #define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3)
97 #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
102 typedef struct signer_key_struct signer_key_t;
104 struct signer_key_struct {
106 isc_boolean_t issigningkey;
109 unsigned int position;
110 ISC_LINK(signer_key_t) link;
113 #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
114 #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
115 #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
117 #define SOA_SERIAL_KEEP 0
118 #define SOA_SERIAL_INCREMENT 1
119 #define SOA_SERIAL_UNIXTIME 2
121 typedef struct signer_event sevent_t;
122 struct signer_event {
123 ISC_EVENT_COMMON(sevent_t);
124 dns_fixedname_t *fname;
128 static ISC_LIST(signer_key_t) keylist;
129 static unsigned int keycount = 0;
130 static isc_stdtime_t starttime = 0, endtime = 0, now;
131 static int cycle = -1;
132 static int jitter = 0;
133 static isc_boolean_t tryverify = ISC_FALSE;
134 static isc_boolean_t printstats = ISC_FALSE;
135 static isc_mem_t *mctx = NULL;
136 static isc_entropy_t *ectx = NULL;
137 static dns_ttl_t zonettl;
139 static char *tempfile = NULL;
140 static const dns_master_style_t *masterstyle;
141 static dns_masterformat_t inputformat = dns_masterformat_text;
142 static dns_masterformat_t outputformat = dns_masterformat_text;
143 static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
144 static unsigned int nverified = 0, nverifyfailed = 0;
145 static const char *directory;
146 static isc_mutex_t namelock, statslock;
147 static isc_taskmgr_t *taskmgr = NULL;
148 static dns_db_t *gdb; /* The database */
149 static dns_dbversion_t *gversion; /* The database version */
150 static dns_dbiterator_t *gdbiter; /* The database iterator */
151 static dns_rdataclass_t gclass; /* The class */
152 static dns_name_t *gorigin; /* The database origin */
153 static int nsec3flags = 0;
154 static isc_task_t *master = NULL;
155 static unsigned int ntasks = 0;
156 static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE;
157 static isc_boolean_t nokeys = ISC_FALSE;
158 static isc_boolean_t removefile = ISC_FALSE;
159 static isc_boolean_t generateds = ISC_FALSE;
160 static isc_boolean_t ignoreksk = ISC_FALSE;
161 static dns_name_t *dlv = NULL;
162 static dns_fixedname_t dlv_fixed;
163 static dns_master_style_t *dsstyle = NULL;
164 static unsigned int serialformat = SOA_SERIAL_KEEP;
165 static unsigned int hash_length = 0;
166 static isc_boolean_t unknownalg = ISC_FALSE;
168 #define INCSTAT(counter) \
172 UNLOCK(&statslock); \
176 sign(isc_task_t *task, isc_event_t *event);
179 nsec3only(dns_dbnode_t *node);
182 dumpnode(dns_name_t *name, dns_dbnode_t *node) {
185 if (outputformat != dns_masterformat_text)
187 result = dns_master_dumpnodetostream(mctx, gdb, gversion, node, name,
189 check_result(result, "dns_master_dumpnodetostream");
192 static signer_key_t *
193 newkeystruct(dst_key_t *dstkey, isc_boolean_t signwithkey) {
196 key = isc_mem_get(mctx, sizeof(signer_key_t));
198 fatal("out of memory");
200 if ((dst_key_flags(dstkey) & DNS_KEYFLAG_KSK) != 0) {
201 key->issigningkey = signwithkey;
202 key->isksk = ISC_TRUE;
203 key->isdsk = ISC_FALSE;
205 key->issigningkey = signwithkey;
206 key->isksk = ISC_FALSE;
207 key->isdsk = ISC_TRUE;
209 key->position = keycount++;
210 ISC_LINK_INIT(key, link);
215 signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdata_t *rdata,
216 dst_key_t *key, isc_buffer_t *b)
219 isc_stdtime_t jendtime;
221 jendtime = (jitter != 0) ? isc_random_jitter(endtime, jitter) : endtime;
222 result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
224 isc_entropy_stopcallbacksources(ectx);
225 if (result != ISC_R_SUCCESS) {
226 char keystr[KEY_FORMATSIZE];
227 key_format(key, keystr, sizeof(keystr));
228 fatal("dnskey '%s' failed to sign data: %s",
229 keystr, isc_result_totext(result));
234 result = dns_dnssec_verify(name, rdataset, key,
235 ISC_TRUE, mctx, rdata);
236 if (result == ISC_R_SUCCESS) {
237 vbprintf(3, "\tsignature verified\n");
240 vbprintf(3, "\tsignature failed to verify\n");
241 INCSTAT(nverifyfailed);
246 static inline isc_boolean_t
247 issigningkey(signer_key_t *key) {
248 return (key->issigningkey);
251 static inline isc_boolean_t
252 iszonekey(signer_key_t *key) {
253 return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) &&
254 dst_key_iszonekey(key->key)));
258 * Finds the key that generated a RRSIG, if possible. First look at the keys
259 * that we've loaded already, and then see if there's a key on disk.
261 static signer_key_t *
262 keythatsigned(dns_rdata_rrsig_t *rrsig) {
264 dst_key_t *pubkey = NULL, *privkey = NULL;
267 key = ISC_LIST_HEAD(keylist);
268 while (key != NULL) {
269 if (rrsig->keyid == dst_key_id(key->key) &&
270 rrsig->algorithm == dst_key_alg(key->key) &&
271 dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
273 key = ISC_LIST_NEXT(key, link);
276 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
277 rrsig->algorithm, DST_TYPE_PUBLIC,
278 NULL, mctx, &pubkey);
279 if (result != ISC_R_SUCCESS)
282 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
284 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
285 NULL, mctx, &privkey);
286 if (result == ISC_R_SUCCESS) {
287 dst_key_free(&pubkey);
288 key = newkeystruct(privkey, ISC_FALSE);
290 key = newkeystruct(pubkey, ISC_FALSE);
291 ISC_LIST_APPEND(keylist, key, link);
296 * Check to see if we expect to find a key at this name. If we see a RRSIG
297 * and can't find the signing key that we expect to find, we drop the rrsig.
298 * I'm not sure if this is completely correct, but it seems to work.
301 expecttofindkey(dns_name_t *name) {
302 unsigned int options = DNS_DBFIND_NOWILD;
303 dns_fixedname_t fname;
305 char namestr[DNS_NAME_FORMATSIZE];
307 dns_fixedname_init(&fname);
308 result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
309 0, NULL, dns_fixedname_name(&fname), NULL, NULL);
315 case DNS_R_DELEGATION:
320 dns_name_format(name, namestr, sizeof(namestr));
321 fatal("failure looking for '%s DNSKEY' in database: %s",
322 namestr, isc_result_totext(result));
323 return (ISC_FALSE); /* removes a warning */
326 static inline isc_boolean_t
327 setverifies(dns_name_t *name, dns_rdataset_t *set, signer_key_t *key,
331 result = dns_dnssec_verify(name, set, key->key, ISC_FALSE, mctx, rrsig);
332 if (result == ISC_R_SUCCESS) {
336 INCSTAT(nverifyfailed);
342 * Signs a set. Goes through contortions to decide if each RRSIG should
343 * be dropped or retained, and then determines if any new SIGs need to
347 signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
350 dns_rdataset_t sigset;
351 dns_rdata_t sigrdata = DNS_RDATA_INIT;
352 dns_rdata_rrsig_t rrsig;
355 isc_boolean_t nosigs = ISC_FALSE;
356 isc_boolean_t *wassignedby, *nowsignedby;
358 dns_difftuple_t *tuple;
361 char namestr[DNS_NAME_FORMATSIZE];
362 char typestr[TYPE_FORMATSIZE];
363 char sigstr[SIG_FORMATSIZE];
365 dns_name_format(name, namestr, sizeof(namestr));
366 type_format(set->type, typestr, sizeof(typestr));
368 ttl = ISC_MIN(set->ttl, endtime - starttime);
370 dns_rdataset_init(&sigset);
371 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
372 set->type, 0, &sigset, NULL);
373 if (result == ISC_R_NOTFOUND) {
374 result = ISC_R_SUCCESS;
377 if (result != ISC_R_SUCCESS)
378 fatal("failed while looking for '%s RRSIG %s': %s",
379 namestr, typestr, isc_result_totext(result));
381 vbprintf(1, "%s/%s:\n", namestr, typestr);
383 arraysize = keycount;
385 arraysize += dns_rdataset_count(&sigset);
386 wassignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
387 nowsignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
388 if (wassignedby == NULL || nowsignedby == NULL)
389 fatal("out of memory");
391 for (i = 0; i < arraysize; i++)
392 wassignedby[i] = nowsignedby[i] = ISC_FALSE;
395 result = ISC_R_NOMORE;
397 result = dns_rdataset_first(&sigset);
399 while (result == ISC_R_SUCCESS) {
400 isc_boolean_t expired, future;
401 isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE;
403 dns_rdataset_current(&sigset, &sigrdata);
405 result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
406 check_result(result, "dns_rdata_tostruct");
408 future = isc_serial_lt(now, rrsig.timesigned);
410 key = keythatsigned(&rrsig);
411 sig_format(&rrsig, sigstr, sizeof(sigstr));
412 if (key != NULL && issigningkey(key))
413 expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
415 expired = isc_serial_gt(now, rrsig.timeexpire);
417 if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
418 /* rrsig is dropped and not replaced */
419 vbprintf(2, "\trrsig by %s dropped - "
420 "invalid validity period\n",
422 } else if (key == NULL && !future &&
423 expecttofindkey(&rrsig.signer))
425 /* rrsig is dropped and not replaced */
426 vbprintf(2, "\trrsig by %s dropped - "
427 "private dnskey not found\n",
429 } else if (key == NULL || future) {
430 vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
431 expired ? "retained" : "dropped", sigstr);
434 } else if (issigningkey(key)) {
435 if (!expired && setverifies(name, set, key, &sigrdata))
437 vbprintf(2, "\trrsig by %s retained\n", sigstr);
439 wassignedby[key->position] = ISC_TRUE;
440 nowsignedby[key->position] = ISC_TRUE;
442 vbprintf(2, "\trrsig by %s dropped - %s\n",
444 expired ? "expired" :
446 wassignedby[key->position] = ISC_TRUE;
449 } else if (iszonekey(key)) {
450 if (!expired && setverifies(name, set, key, &sigrdata))
452 vbprintf(2, "\trrsig by %s retained\n", sigstr);
454 wassignedby[key->position] = ISC_TRUE;
455 nowsignedby[key->position] = ISC_TRUE;
457 vbprintf(2, "\trrsig by %s dropped - %s\n",
459 expired ? "expired" :
461 wassignedby[key->position] = ISC_TRUE;
463 } else if (!expired) {
464 vbprintf(2, "\trrsig by %s retained\n", sigstr);
467 vbprintf(2, "\trrsig by %s expired\n", sigstr);
471 nowsignedby[key->position] = ISC_TRUE;
473 if (sigset.ttl != ttl) {
474 vbprintf(2, "\tfixing ttl %s\n", sigstr);
476 result = dns_difftuple_create(mctx,
481 check_result(result, "dns_difftuple_create");
482 dns_diff_append(del, &tuple);
483 result = dns_difftuple_create(mctx,
488 check_result(result, "dns_difftuple_create");
489 dns_diff_append(add, &tuple);
493 result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL,
496 check_result(result, "dns_difftuple_create");
497 dns_diff_append(del, &tuple);
503 dns_rdata_t trdata = DNS_RDATA_INIT;
504 unsigned char array[BUFSIZE];
505 char keystr[KEY_FORMATSIZE];
509 key_format(key->key, keystr, sizeof(keystr));
510 vbprintf(1, "\tresigning with dnskey %s\n", keystr);
511 isc_buffer_init(&b, array, sizeof(array));
512 signwithkey(name, set, &trdata, key->key, &b);
513 nowsignedby[key->position] = ISC_TRUE;
515 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
518 check_result(result, "dns_difftuple_create");
519 dns_diff_append(add, &tuple);
522 dns_rdata_reset(&sigrdata);
523 dns_rdata_freestruct(&rrsig);
524 result = dns_rdataset_next(&sigset);
526 if (result == ISC_R_NOMORE)
527 result = ISC_R_SUCCESS;
529 check_result(result, "dns_rdataset_first/next");
530 if (dns_rdataset_isassociated(&sigset))
531 dns_rdataset_disassociate(&sigset);
533 for (key = ISC_LIST_HEAD(keylist);
535 key = ISC_LIST_NEXT(key, link))
539 unsigned char array[BUFSIZE];
540 char keystr[KEY_FORMATSIZE];
542 if (nowsignedby[key->position])
545 if (!key->issigningkey)
547 if (!(ignoreksk || key->isdsk ||
549 set->type == dns_rdatatype_dnskey &&
550 dns_name_equal(name, gorigin))))
553 key_format(key->key, keystr, sizeof(keystr));
554 vbprintf(1, "\tsigning with dnskey %s\n", keystr);
555 dns_rdata_init(&trdata);
556 isc_buffer_init(&b, array, sizeof(array));
557 signwithkey(name, set, &trdata, key->key, &b);
559 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
560 ttl, &trdata, &tuple);
561 check_result(result, "dns_difftuple_create");
562 dns_diff_append(add, &tuple);
565 isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t));
566 isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t));
570 unsigned char *hashbuf;
577 hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) {
580 l->length = length + 1;
584 l->hashbuf = malloc(l->size * l->length);
585 if (l->hashbuf == NULL)
594 hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len)
597 REQUIRE(len <= l->length);
599 if (l->entries == l->size) {
600 l->size = l->size * 2 + 100;
601 l->hashbuf = realloc(l->hashbuf, l->size * l->length);
603 memset(l->hashbuf + l->entries * l->length, 0, l->length);
604 memcpy(l->hashbuf + l->entries * l->length, hash, len);
609 hashlist_add_dns_name(hashlist_t *l, /*const*/ dns_name_t *name,
610 unsigned int hashalg, unsigned int iterations,
611 const unsigned char *salt, size_t salt_length,
612 isc_boolean_t speculative)
614 char nametext[DNS_NAME_FORMATSIZE];
615 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
619 len = isc_iterated_hash(hash, hashalg, iterations, salt, salt_length,
620 name->ndata, name->length);
622 dns_name_format(name, nametext, sizeof nametext);
623 for (i = 0 ; i < len; i++)
624 fprintf(stderr, "%02x", hash[i]);
625 fprintf(stderr, " %s\n", nametext);
627 hash[len++] = speculative ? 1 : 0;
628 hashlist_add(l, hash, len);
632 hashlist_comp(const void *a, const void *b) {
633 return (memcmp(a, b, hash_length + 1));
637 hashlist_sort(hashlist_t *l) {
638 qsort(l->hashbuf, l->entries, l->length, hashlist_comp);
642 hashlist_hasdup(hashlist_t *l) {
643 unsigned char *current;
644 unsigned char *next = l->hashbuf;
645 size_t entries = l->entries;
648 * Skip initial speculative wild card hashs.
650 while (entries > 0U && next[l->length-1] != 0U) {
656 while (entries-- > 1U) {
658 if (next[l->length-1] != 0)
660 if (memcmp(current, next, l->length - 1) == 0)
667 static const unsigned char *
668 hashlist_findnext(const hashlist_t *l,
669 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
671 unsigned int entries = l->entries;
672 const unsigned char *next = bsearch(hash, l->hashbuf, l->entries,
673 l->length, hashlist_comp);
674 INSIST(next != NULL);
677 if (next < l->hashbuf + (l->entries - 1) * l->length)
681 if (next[l->length - 1] == 0)
683 } while (entries-- > 1);
684 INSIST(entries != 0);
689 hashlist_exists(const hashlist_t *l,
690 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
692 if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp))
699 addnowildcardhash(hashlist_t *l, /*const*/ dns_name_t *name,
700 unsigned int hashalg, unsigned int iterations,
701 const unsigned char *salt, size_t salt_length)
703 dns_fixedname_t fixed;
705 dns_dbnode_t *node = NULL;
707 char namestr[DNS_NAME_FORMATSIZE];
709 dns_fixedname_init(&fixed);
710 wild = dns_fixedname_name(&fixed);
712 result = dns_name_concatenate(dns_wildcardname, name, wild, NULL);
713 if (result == ISC_R_NOSPACE)
715 check_result(result,"addnowildcardhash: dns_name_concatenate()");
717 result = dns_db_findnode(gdb, wild, ISC_FALSE, &node);
718 if (result == ISC_R_SUCCESS) {
719 dns_db_detachnode(gdb, &node);
724 dns_name_format(wild, namestr, sizeof(namestr));
725 fprintf(stderr, "adding no-wildcardhash for %s\n", namestr);
728 hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_length,
733 opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
740 isc_buffer_init(&b, filename, sizeof(filename));
741 if (directory != NULL) {
742 isc_buffer_putstr(&b, directory);
743 if (directory[strlen(directory) - 1] != '/')
744 isc_buffer_putstr(&b, "/");
746 isc_buffer_putstr(&b, prefix);
747 result = dns_name_tofilenametext(name, ISC_FALSE, &b);
748 check_result(result, "dns_name_tofilenametext()");
749 if (isc_buffer_availablelength(&b) == 0) {
750 char namestr[DNS_NAME_FORMATSIZE];
751 dns_name_format(name, namestr, sizeof(namestr));
752 fatal("name '%s' is too long", namestr);
754 isc_buffer_putuint8(&b, 0);
756 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
757 rdclass, 0, NULL, dbp);
758 check_result(result, "dns_db_create()");
760 result = dns_db_load(*dbp, filename);
761 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
766 * Loads the key set for a child zone, if there is one, and builds DS records.
769 loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
771 dns_dbversion_t *ver = NULL;
772 dns_dbnode_t *node = NULL;
774 dns_rdataset_t keyset;
776 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
778 dns_difftuple_t *tuple = NULL;
780 opendb("keyset-", name, gclass, &db);
782 return (ISC_R_NOTFOUND);
784 result = dns_db_findnode(db, name, ISC_FALSE, &node);
785 if (result != ISC_R_SUCCESS) {
787 return (DNS_R_BADDB);
789 dns_rdataset_init(&keyset);
790 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
792 if (result != ISC_R_SUCCESS) {
793 dns_db_detachnode(db, &node);
798 vbprintf(2, "found DNSKEY records\n");
800 result = dns_db_newversion(db, &ver);
801 check_result(result, "dns_db_newversion");
803 dns_diff_init(mctx, &diff);
805 for (result = dns_rdataset_first(&keyset);
806 result == ISC_R_SUCCESS;
807 result = dns_rdataset_next(&keyset))
809 dns_rdata_init(&key);
811 dns_rdataset_current(&keyset, &key);
812 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
814 check_result(result, "dns_ds_buildrdata");
816 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
818 check_result(result, "dns_difftuple_create");
819 dns_diff_append(&diff, &tuple);
821 dns_rdata_reset(&ds);
822 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
824 check_result(result, "dns_ds_buildrdata");
826 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
828 check_result(result, "dns_difftuple_create");
829 dns_diff_append(&diff, &tuple);
831 result = dns_diff_apply(&diff, db, ver);
832 check_result(result, "dns_diff_apply");
833 dns_diff_clear(&diff);
835 dns_db_closeversion(db, &ver, ISC_TRUE);
837 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
839 check_result(result, "dns_db_findrdataset");
841 dns_rdataset_disassociate(&keyset);
842 dns_db_detachnode(db, &node);
848 delegation(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) {
849 dns_rdataset_t nsset;
852 if (dns_name_equal(name, gorigin))
855 dns_rdataset_init(&nsset);
856 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ns,
858 if (dns_rdataset_isassociated(&nsset)) {
861 dns_rdataset_disassociate(&nsset);
864 return (ISC_TF(result == ISC_R_SUCCESS));
868 secure(dns_name_t *name, dns_dbnode_t *node) {
869 dns_rdataset_t dsset;
872 if (dns_name_equal(name, gorigin))
875 dns_rdataset_init(&dsset);
876 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds,
878 if (dns_rdataset_isassociated(&dsset))
879 dns_rdataset_disassociate(&dsset);
881 return (ISC_TF(result == ISC_R_SUCCESS));
885 * Signs all records at a name.
888 signname(dns_dbnode_t *node, dns_name_t *name) {
890 dns_rdataset_t rdataset;
891 dns_rdatasetiter_t *rdsiter;
892 isc_boolean_t isdelegation = ISC_FALSE;
894 char namestr[DNS_NAME_FORMATSIZE];
896 dns_rdataset_init(&rdataset);
897 dns_name_format(name, namestr, sizeof(namestr));
900 * Determine if this is a delegation point.
902 if (delegation(name, node, NULL))
903 isdelegation = ISC_TRUE;
906 * Now iterate through the rdatasets.
908 dns_diff_init(mctx, &del);
909 dns_diff_init(mctx, &add);
911 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
912 check_result(result, "dns_db_allrdatasets()");
913 result = dns_rdatasetiter_first(rdsiter);
914 while (result == ISC_R_SUCCESS) {
915 dns_rdatasetiter_current(rdsiter, &rdataset);
917 /* If this is a RRSIG set, skip it. */
918 if (rdataset.type == dns_rdatatype_rrsig)
922 * If this name is a delegation point, skip all records
923 * except NSEC and DS sets. Otherwise check that there
927 if (rdataset.type != nsec_datatype &&
928 rdataset.type != dns_rdatatype_ds)
930 } else if (rdataset.type == dns_rdatatype_ds) {
931 char namebuf[DNS_NAME_FORMATSIZE];
932 dns_name_format(name, namebuf, sizeof(namebuf));
933 fatal("'%s': found DS RRset without NS RRset\n",
937 signset(&del, &add, node, name, &rdataset);
940 dns_rdataset_disassociate(&rdataset);
941 result = dns_rdatasetiter_next(rdsiter);
943 if (result != ISC_R_NOMORE)
944 fatal("rdataset iteration for name '%s' failed: %s",
945 namestr, isc_result_totext(result));
947 dns_rdatasetiter_destroy(&rdsiter);
949 result = dns_diff_applysilently(&del, gdb, gversion);
950 if (result != ISC_R_SUCCESS)
951 fatal("failed to delete SIGs at node '%s': %s",
952 namestr, isc_result_totext(result));
954 result = dns_diff_applysilently(&add, gdb, gversion);
955 if (result != ISC_R_SUCCESS)
956 fatal("failed to add SIGs at node '%s': %s",
957 namestr, isc_result_totext(result));
959 dns_diff_clear(&del);
960 dns_diff_clear(&add);
963 static inline isc_boolean_t
964 active_node(dns_dbnode_t *node) {
965 dns_rdatasetiter_t *rdsiter = NULL;
966 dns_rdatasetiter_t *rdsiter2 = NULL;
967 isc_boolean_t active = ISC_FALSE;
969 dns_rdataset_t rdataset;
970 dns_rdatatype_t type;
971 dns_rdatatype_t covers;
974 dns_rdataset_init(&rdataset);
975 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
976 check_result(result, "dns_db_allrdatasets()");
977 result = dns_rdatasetiter_first(rdsiter);
978 while (result == ISC_R_SUCCESS) {
979 dns_rdatasetiter_current(rdsiter, &rdataset);
980 if (rdataset.type != dns_rdatatype_nsec &&
981 rdataset.type != dns_rdatatype_nsec3 &&
982 rdataset.type != dns_rdatatype_rrsig)
984 dns_rdataset_disassociate(&rdataset);
986 result = dns_rdatasetiter_next(rdsiter);
988 result = ISC_R_NOMORE;
990 if (result != ISC_R_NOMORE)
991 fatal("rdataset iteration failed: %s",
992 isc_result_totext(result));
994 if (!active && nsec_datatype == dns_rdatatype_nsec) {
996 * The node is empty of everything but NSEC / RRSIG records.
998 for (result = dns_rdatasetiter_first(rdsiter);
999 result == ISC_R_SUCCESS;
1000 result = dns_rdatasetiter_next(rdsiter)) {
1001 dns_rdatasetiter_current(rdsiter, &rdataset);
1002 result = dns_db_deleterdataset(gdb, node, gversion,
1005 check_result(result, "dns_db_deleterdataset()");
1006 dns_rdataset_disassociate(&rdataset);
1008 if (result != ISC_R_NOMORE)
1009 fatal("rdataset iteration failed: %s",
1010 isc_result_totext(result));
1013 * Delete RRSIGs for types that no longer exist.
1015 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
1016 check_result(result, "dns_db_allrdatasets()");
1017 for (result = dns_rdatasetiter_first(rdsiter);
1018 result == ISC_R_SUCCESS;
1019 result = dns_rdatasetiter_next(rdsiter)) {
1020 dns_rdatasetiter_current(rdsiter, &rdataset);
1021 type = rdataset.type;
1022 covers = rdataset.covers;
1023 dns_rdataset_disassociate(&rdataset);
1024 if (type != dns_rdatatype_rrsig)
1027 for (result = dns_rdatasetiter_first(rdsiter2);
1028 !found && result == ISC_R_SUCCESS;
1029 result = dns_rdatasetiter_next(rdsiter2)) {
1030 dns_rdatasetiter_current(rdsiter2, &rdataset);
1031 if (rdataset.type == covers)
1033 dns_rdataset_disassociate(&rdataset);
1036 if (result != ISC_R_NOMORE)
1037 fatal("rdataset iteration failed: %s",
1038 isc_result_totext(result));
1039 result = dns_db_deleterdataset(gdb, node,
1042 check_result(result,
1043 "dns_db_deleterdataset(rrsig)");
1044 } else if (result != ISC_R_NOMORE &&
1045 result != ISC_R_SUCCESS)
1046 fatal("rdataset iteration failed: %s",
1047 isc_result_totext(result));
1049 if (result != ISC_R_NOMORE)
1050 fatal("rdataset iteration failed: %s",
1051 isc_result_totext(result));
1052 dns_rdatasetiter_destroy(&rdsiter2);
1056 * Delete all NSEC records and RRSIG(NSEC) if we are in
1057 * NSEC3 mode and vica versa.
1059 for (result = dns_rdatasetiter_first(rdsiter2);
1060 result == ISC_R_SUCCESS;
1061 result = dns_rdatasetiter_next(rdsiter2)) {
1062 dns_rdatasetiter_current(rdsiter, &rdataset);
1063 type = rdataset.type;
1064 covers = rdataset.covers;
1065 if (type == dns_rdatatype_rrsig)
1067 dns_rdataset_disassociate(&rdataset);
1068 if (type == nsec_datatype ||
1069 (type != dns_rdatatype_nsec &&
1070 type != dns_rdatatype_nsec3))
1073 type = dns_rdatatype_rrsig;
1074 result = dns_db_deleterdataset(gdb, node, gversion,
1076 check_result(result, "dns_db_deleterdataset()");
1080 dns_rdatasetiter_destroy(&rdsiter);
1086 * Extracts the TTL from the SOA.
1090 dns_rdataset_t soaset;
1091 dns_fixedname_t fname;
1093 isc_result_t result;
1095 dns_rdata_t rdata = DNS_RDATA_INIT;
1096 dns_rdata_soa_t soa;
1098 dns_fixedname_init(&fname);
1099 name = dns_fixedname_name(&fname);
1100 dns_rdataset_init(&soaset);
1101 result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
1102 0, 0, NULL, name, &soaset, NULL);
1103 if (result != ISC_R_SUCCESS)
1104 fatal("failed to find an SOA at the zone apex: %s",
1105 isc_result_totext(result));
1107 result = dns_rdataset_first(&soaset);
1108 check_result(result, "dns_rdataset_first");
1109 dns_rdataset_current(&soaset, &rdata);
1110 result = dns_rdata_tostruct(&rdata, &soa, NULL);
1111 check_result(result, "dns_rdata_tostruct");
1113 dns_rdataset_disassociate(&soaset);
1118 * Increment (or set if nonzero) the SOA serial
1121 setsoaserial(isc_uint32_t serial) {
1122 isc_result_t result;
1123 dns_dbnode_t *node = NULL;
1124 dns_rdataset_t rdataset;
1125 dns_rdata_t rdata = DNS_RDATA_INIT;
1126 isc_uint32_t old_serial, new_serial;
1128 result = dns_db_getoriginnode(gdb, &node);
1129 if (result != ISC_R_SUCCESS)
1132 dns_rdataset_init(&rdataset);
1134 result = dns_db_findrdataset(gdb, node, gversion,
1135 dns_rdatatype_soa, 0,
1136 0, &rdataset, NULL);
1137 if (result != ISC_R_SUCCESS)
1140 result = dns_rdataset_first(&rdataset);
1141 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1143 dns_rdataset_current(&rdataset, &rdata);
1145 old_serial = dns_soa_getserial(&rdata);
1148 /* Set SOA serial to the value provided. */
1149 new_serial = serial;
1151 /* Increment SOA serial using RFC 1982 arithmetics */
1152 new_serial = (old_serial + 1) & 0xFFFFFFFF;
1153 if (new_serial == 0)
1157 /* If the new serial is not likely to cause a zone transfer
1158 * (a/ixfr) from servers having the old serial, warn the user.
1160 * RFC1982 section 7 defines the maximum increment to be
1161 * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
1162 * comparison. (5 - 6 == (2^32)-1, not negative-one)
1164 if (new_serial == old_serial ||
1165 (new_serial - old_serial) > 0x7fffffffU)
1166 fprintf(stderr, "%s: warning: Serial number not advanced, "
1167 "zone may not transfer\n", program);
1169 dns_soa_setserial(new_serial, &rdata);
1171 result = dns_db_deleterdataset(gdb, node, gversion,
1172 dns_rdatatype_soa, 0);
1173 check_result(result, "dns_db_deleterdataset");
1174 if (result != ISC_R_SUCCESS)
1177 result = dns_db_addrdataset(gdb, node, gversion,
1178 0, &rdataset, 0, NULL);
1179 check_result(result, "dns_db_addrdataset");
1180 if (result != ISC_R_SUCCESS)
1184 dns_rdataset_disassociate(&rdataset);
1186 dns_db_detachnode(gdb, &node);
1187 dns_rdata_reset(&rdata);
1193 * Delete any RRSIG records at a node.
1196 cleannode(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
1197 dns_rdatasetiter_t *rdsiter = NULL;
1199 isc_result_t result, dresult;
1201 if (outputformat != dns_masterformat_text)
1204 dns_rdataset_init(&set);
1205 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
1206 check_result(result, "dns_db_allrdatasets");
1207 result = dns_rdatasetiter_first(rdsiter);
1208 while (result == ISC_R_SUCCESS) {
1209 isc_boolean_t destroy = ISC_FALSE;
1210 dns_rdatatype_t covers = 0;
1211 dns_rdatasetiter_current(rdsiter, &set);
1212 if (set.type == dns_rdatatype_rrsig) {
1213 covers = set.covers;
1216 dns_rdataset_disassociate(&set);
1217 result = dns_rdatasetiter_next(rdsiter);
1219 dresult = dns_db_deleterdataset(db, node, version,
1220 dns_rdatatype_rrsig,
1222 check_result(dresult, "dns_db_deleterdataset");
1225 if (result != ISC_R_NOMORE)
1226 fatal("rdataset iteration failed: %s",
1227 isc_result_totext(result));
1228 dns_rdatasetiter_destroy(&rdsiter);
1232 * Set up the iterator and global state before starting the tasks.
1236 isc_result_t result;
1239 result = dns_db_createiterator(gdb, 0, &gdbiter);
1240 check_result(result, "dns_db_createiterator()");
1244 * Clean up the iterator and global state after the tasks complete.
1248 dns_dbiterator_destroy(&gdbiter);
1252 * Sign the apex of the zone.
1253 * Note the origin may not be the first node if there are out of zone
1258 dns_dbnode_t *node = NULL;
1259 dns_fixedname_t fixed;
1261 isc_result_t result;
1263 dns_fixedname_init(&fixed);
1264 name = dns_fixedname_name(&fixed);
1265 result = dns_dbiterator_seek(gdbiter, gorigin);
1266 check_result(result, "dns_dbiterator_seek()");
1267 result = dns_dbiterator_current(gdbiter, &node, name);
1268 check_result(result, "dns_dbiterator_current()");
1269 signname(node, name);
1270 dumpnode(name, node);
1271 cleannode(gdb, gversion, node);
1272 dns_db_detachnode(gdb, &node);
1273 result = dns_dbiterator_first(gdbiter);
1274 if (result == ISC_R_NOMORE)
1275 finished = ISC_TRUE;
1276 else if (result != ISC_R_SUCCESS)
1277 fatal("failure iterating database: %s",
1278 isc_result_totext(result));
1282 * Assigns a node to a worker thread. This is protected by the master task's
1286 assignwork(isc_task_t *task, isc_task_t *worker) {
1287 dns_fixedname_t *fname;
1291 dns_rdataset_t nsec;
1292 isc_boolean_t found;
1293 isc_result_t result;
1294 static dns_name_t *zonecut = NULL; /* Protected by namelock. */
1295 static dns_fixedname_t fzonecut; /* Protected by namelock. */
1296 static unsigned int ended = 0; /* Protected by namelock. */
1304 if (ended == ntasks) {
1305 isc_task_detach(&task);
1311 fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
1313 fatal("out of memory");
1314 dns_fixedname_init(fname);
1315 name = dns_fixedname_name(fname);
1319 result = dns_dbiterator_current(gdbiter, &node, name);
1320 if (result != ISC_R_SUCCESS)
1321 fatal("failure iterating database: %s",
1322 isc_result_totext(result));
1324 * The origin was handled by signapex().
1326 if (dns_name_equal(name, gorigin)) {
1327 dns_db_detachnode(gdb, &node);
1331 * Sort the zone data from the glue and out-of-zone data.
1332 * For NSEC zones nodes with zone data have NSEC records.
1333 * For NSEC3 zones the NSEC3 nodes are zone data but
1334 * outside of the zone name space. For the rest we need
1335 * to track the bottom of zone cuts.
1336 * Nodes which don't need to be signed are dumped here.
1338 dns_rdataset_init(&nsec);
1339 result = dns_db_findrdataset(gdb, node, gversion,
1340 nsec_datatype, 0, 0,
1342 if (dns_rdataset_isassociated(&nsec))
1343 dns_rdataset_disassociate(&nsec);
1344 if (result == ISC_R_SUCCESS) {
1346 } else if (nsec_datatype == dns_rdatatype_nsec3) {
1347 if (dns_name_issubdomain(name, gorigin) &&
1349 !dns_name_issubdomain(name, zonecut))) {
1350 if (delegation(name, node, NULL)) {
1351 dns_fixedname_init(&fzonecut);
1352 zonecut = dns_fixedname_name(&fzonecut);
1353 dns_name_copy(name, zonecut, NULL);
1354 if (!OPTOUT(nsec3flags) ||
1363 dumpnode(name, node);
1364 dns_db_detachnode(gdb, &node);
1368 result = dns_dbiterator_next(gdbiter);
1369 if (result == ISC_R_NOMORE) {
1370 finished = ISC_TRUE;
1372 } else if (result != ISC_R_SUCCESS)
1373 fatal("failure iterating database: %s",
1374 isc_result_totext(result));
1378 if (ended == ntasks) {
1379 isc_task_detach(&task);
1382 isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
1385 sevent = (sevent_t *)
1386 isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
1387 sign, NULL, sizeof(sevent_t));
1389 fatal("failed to allocate event\n");
1391 sevent->node = node;
1392 sevent->fname = fname;
1393 isc_task_send(worker, ISC_EVENT_PTR(&sevent));
1399 * Start a worker task
1402 startworker(isc_task_t *task, isc_event_t *event) {
1405 worker = (isc_task_t *)event->ev_arg;
1406 assignwork(task, worker);
1407 isc_event_free(&event);
1411 * Write a node to the output file, and restart the worker task.
1414 writenode(isc_task_t *task, isc_event_t *event) {
1416 sevent_t *sevent = (sevent_t *)event;
1418 worker = (isc_task_t *)event->ev_sender;
1419 dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
1420 cleannode(gdb, gversion, sevent->node);
1421 dns_db_detachnode(gdb, &sevent->node);
1422 isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
1423 assignwork(task, worker);
1424 isc_event_free(&event);
1428 * Sign a database node.
1431 sign(isc_task_t *task, isc_event_t *event) {
1432 dns_fixedname_t *fname;
1434 sevent_t *sevent, *wevent;
1436 sevent = (sevent_t *)event;
1437 node = sevent->node;
1438 fname = sevent->fname;
1439 isc_event_free(&event);
1441 signname(node, dns_fixedname_name(fname));
1442 wevent = (sevent_t *)
1443 isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
1444 writenode, NULL, sizeof(sevent_t));
1446 fatal("failed to allocate event\n");
1447 wevent->node = node;
1448 wevent->fname = fname;
1449 isc_task_send(master, ISC_EVENT_PTR(&wevent));
1453 * Update / remove the DS RRset. Preserve RRSIG(DS) if possible.
1456 add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) {
1457 dns_rdataset_t dsset;
1458 dns_rdataset_t sigdsset;
1459 isc_result_t result;
1461 dns_rdataset_init(&dsset);
1462 dns_rdataset_init(&sigdsset);
1463 result = dns_db_findrdataset(gdb, node, gversion,
1465 0, 0, &dsset, &sigdsset);
1466 if (result == ISC_R_SUCCESS) {
1467 dns_rdataset_disassociate(&dsset);
1468 result = dns_db_deleterdataset(gdb, node, gversion,
1469 dns_rdatatype_ds, 0);
1470 check_result(result, "dns_db_deleterdataset");
1472 result = loadds(name, nsttl, &dsset);
1473 if (result == ISC_R_SUCCESS) {
1474 result = dns_db_addrdataset(gdb, node, gversion, 0,
1476 check_result(result, "dns_db_addrdataset");
1477 dns_rdataset_disassociate(&dsset);
1478 if (dns_rdataset_isassociated(&sigdsset))
1479 dns_rdataset_disassociate(&sigdsset);
1480 } else if (dns_rdataset_isassociated(&sigdsset)) {
1481 result = dns_db_deleterdataset(gdb, node, gversion,
1482 dns_rdatatype_rrsig,
1484 check_result(result, "dns_db_deleterdataset");
1485 dns_rdataset_disassociate(&sigdsset);
1490 * Generate NSEC records for the zone.
1494 dns_dbiterator_t *dbiter = NULL;
1495 dns_dbnode_t *node = NULL, *nextnode = NULL;
1496 dns_fixedname_t fname, fnextname, fzonecut;
1497 dns_name_t *name, *nextname, *zonecut;
1498 isc_boolean_t done = ISC_FALSE;
1499 isc_result_t result;
1500 isc_uint32_t nsttl = 0;
1502 dns_fixedname_init(&fname);
1503 name = dns_fixedname_name(&fname);
1504 dns_fixedname_init(&fnextname);
1505 nextname = dns_fixedname_name(&fnextname);
1506 dns_fixedname_init(&fzonecut);
1509 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
1510 check_result(result, "dns_db_createiterator()");
1512 result = dns_dbiterator_first(dbiter);
1513 check_result(result, "dns_dbiterator_first()");
1516 dns_dbiterator_current(dbiter, &node, name);
1517 if (delegation(name, node, &nsttl)) {
1518 zonecut = dns_fixedname_name(&fzonecut);
1519 dns_name_copy(name, zonecut, NULL);
1521 add_ds(name, node, nsttl);
1523 result = dns_dbiterator_next(dbiter);
1525 while (result == ISC_R_SUCCESS) {
1526 isc_boolean_t active = ISC_FALSE;
1527 result = dns_dbiterator_current(dbiter, &nextnode,
1529 if (result != ISC_R_SUCCESS)
1531 active = active_node(nextnode);
1533 dns_db_detachnode(gdb, &nextnode);
1534 result = dns_dbiterator_next(dbiter);
1537 if (!dns_name_issubdomain(nextname, gorigin) ||
1539 dns_name_issubdomain(nextname, zonecut)))
1541 dns_db_detachnode(gdb, &nextnode);
1542 result = dns_dbiterator_next(dbiter);
1545 dns_db_detachnode(gdb, &nextnode);
1548 if (result == ISC_R_NOMORE) {
1549 dns_name_clone(gorigin, nextname);
1551 } else if (result != ISC_R_SUCCESS)
1552 fatal("iterating through the database failed: %s",
1553 isc_result_totext(result));
1554 result = dns_nsec_build(gdb, gversion, node, nextname,
1556 check_result(result, "dns_nsec_build()");
1557 dns_db_detachnode(gdb, &node);
1560 dns_dbiterator_destroy(&dbiter);
1564 * Does this node only contain NSEC3 records or RRSIG records or is empty.
1566 static isc_boolean_t
1567 nsec3only(dns_dbnode_t *node) {
1568 dns_rdatasetiter_t *rdsiter = NULL;
1569 isc_result_t result;
1570 dns_rdataset_t rdataset;
1571 isc_boolean_t answer = ISC_TRUE;
1573 dns_rdataset_init(&rdataset);
1574 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1575 check_result(result, "dns_db_allrdatasets()");
1576 result = dns_rdatasetiter_first(rdsiter);
1577 while (result == ISC_R_SUCCESS) {
1578 dns_rdatasetiter_current(rdsiter, &rdataset);
1579 if (rdataset.type != dns_rdatatype_nsec3 &&
1580 rdataset.type != dns_rdatatype_rrsig) {
1582 result = ISC_R_NOMORE;
1584 result = dns_rdatasetiter_next(rdsiter);
1585 dns_rdataset_disassociate(&rdataset);
1587 if (result != ISC_R_NOMORE)
1588 fatal("rdataset iteration failed: %s",
1589 isc_result_totext(result));
1590 dns_rdatasetiter_destroy(&rdsiter);
1595 addnsec3param(const unsigned char *salt, size_t salt_length,
1596 unsigned int iterations)
1598 dns_dbnode_t *node = NULL;
1599 dns_rdata_nsec3param_t nsec3param;
1600 unsigned char nsec3parambuf[5 + 255];
1601 dns_rdatalist_t rdatalist;
1602 dns_rdataset_t rdataset;
1603 dns_rdata_t rdata = DNS_RDATA_INIT;
1605 isc_result_t result;
1607 dns_rdataset_init(&rdataset);
1609 nsec3param.common.rdclass = gclass;
1610 nsec3param.common.rdtype = dns_rdatatype_nsec3param;
1611 ISC_LINK_INIT(&nsec3param.common, link);
1612 nsec3param.mctx = NULL;
1613 nsec3param.flags = 0;
1614 nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1;
1615 nsec3param.iterations = iterations;
1616 nsec3param.salt_length = salt_length;
1617 DE_CONST(salt, nsec3param.salt);
1619 isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf));
1620 result = dns_rdata_fromstruct(&rdata, gclass,
1621 dns_rdatatype_nsec3param,
1623 rdatalist.rdclass = rdata.rdclass;
1624 rdatalist.type = rdata.type;
1625 rdatalist.covers = 0;
1627 ISC_LIST_INIT(rdatalist.rdata);
1628 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
1629 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
1630 check_result(result, "dns_rdatalist_tordataset()");
1632 result = dns_db_findnode(gdb, gorigin, ISC_TRUE, &node);
1633 check_result(result, "dns_db_find(gorigin)");
1634 result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset,
1635 DNS_DBADD_MERGE, NULL);
1636 if (result == DNS_R_UNCHANGED)
1637 result = ISC_R_SUCCESS;
1638 check_result(result, "addnsec3param: dns_db_addrdataset()");
1639 dns_db_detachnode(gdb, &node);
1643 addnsec3(dns_name_t *name, dns_dbnode_t *node,
1644 const unsigned char *salt, size_t salt_length,
1645 unsigned int iterations, hashlist_t *hashlist,
1648 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
1649 const unsigned char *nexthash;
1650 unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE];
1651 dns_fixedname_t hashname;
1652 dns_rdatalist_t rdatalist;
1653 dns_rdataset_t rdataset;
1654 dns_rdata_t rdata = DNS_RDATA_INIT;
1655 isc_result_t result;
1656 dns_dbnode_t *nsec3node = NULL;
1657 char namebuf[DNS_NAME_FORMATSIZE];
1660 dns_name_format(name, namebuf, sizeof(namebuf));
1662 dns_fixedname_init(&hashname);
1663 dns_rdataset_init(&rdataset);
1665 dns_name_downcase(name, name, NULL);
1666 result = dns_nsec3_hashname(&hashname, hash, &hash_length,
1667 name, gorigin, dns_hash_sha1, iterations,
1669 check_result(result, "addnsec3: dns_nsec3_hashname()");
1670 nexthash = hashlist_findnext(hashlist, hash);
1671 result = dns_nsec3_buildrdata(gdb, gversion, node,
1673 DNS_NSEC3_UNKNOWNALG : dns_hash_sha1,
1674 nsec3flags, iterations,
1676 nexthash, ISC_SHA1_DIGESTLENGTH,
1677 nsec3buffer, &rdata);
1678 check_result(result, "addnsec3: dns_nsec3_buildrdata()");
1679 rdatalist.rdclass = rdata.rdclass;
1680 rdatalist.type = rdata.type;
1681 rdatalist.covers = 0;
1682 rdatalist.ttl = ttl;
1683 ISC_LIST_INIT(rdatalist.rdata);
1684 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
1685 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
1686 check_result(result, "dns_rdatalist_tordataset()");
1687 result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname),
1688 ISC_TRUE, &nsec3node);
1689 check_result(result, "addnsec3: dns_db_findnode()");
1690 result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset,
1692 if (result == DNS_R_UNCHANGED)
1693 result = ISC_R_SUCCESS;
1694 check_result(result, "addnsec3: dns_db_addrdataset()");
1695 dns_db_detachnode(gdb, &nsec3node);
1699 * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list.
1701 * Extract the hash from the first label of 'name' then see if it
1702 * is in hashlist. If 'name' is not in the hashlist then delete the
1703 * any NSEC3 records which have the same parameters as the chain we
1706 * XXXMPA Should we also check that it of the form <hash>.<origin>?
1709 nsec3clean(dns_name_t *name, dns_dbnode_t *node,
1710 unsigned int hashalg, unsigned int iterations,
1711 const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
1714 dns_rdata_nsec3_t nsec3;
1715 dns_rdata_t rdata, delrdata;
1716 dns_rdatalist_t rdatalist;
1717 dns_rdataset_t rdataset, delrdataset;
1718 isc_boolean_t delete_rrsigs = ISC_FALSE;
1719 isc_buffer_t target;
1720 isc_result_t result;
1721 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
1724 * Get the first label.
1726 dns_name_getlabel(name, 0, &label);
1729 * We want just the label contents.
1731 isc_region_consume(&label, 1);
1734 * Decode base32hex string.
1736 isc_buffer_init(&target, hash, sizeof(hash) - 1);
1737 result = isc_base32hex_decoderegion(&label, &target);
1738 if (result != ISC_R_SUCCESS)
1741 hash[isc_buffer_usedlength(&target)] = 0;
1743 if (hashlist_exists(hashlist, hash))
1747 * Verify that the NSEC3 parameters match the current ones
1748 * otherwise we are dealing with a different NSEC3 chain.
1750 dns_rdataset_init(&rdataset);
1751 dns_rdataset_init(&delrdataset);
1753 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3,
1754 0, 0, &rdataset, NULL);
1755 if (result != ISC_R_SUCCESS)
1759 * Delete any matching NSEC3 records which have parameters that
1760 * match the NSEC3 chain we are building.
1762 for (result = dns_rdataset_first(&rdataset);
1763 result == ISC_R_SUCCESS;
1764 result = dns_rdataset_next(&rdataset)) {
1765 dns_rdata_init(&rdata);
1766 dns_rdataset_current(&rdataset, &rdata);
1767 dns_rdata_tostruct(&rdata, &nsec3, NULL);
1768 if (nsec3.hash == hashalg &&
1769 nsec3.iterations == iterations &&
1770 nsec3.salt_length == salt_length &&
1771 !memcmp(nsec3.salt, salt, salt_length))
1773 rdatalist.rdclass = rdata.rdclass;
1774 rdatalist.type = rdata.type;
1775 rdatalist.covers = 0;
1776 rdatalist.ttl = rdataset.ttl;
1777 ISC_LIST_INIT(rdatalist.rdata);
1778 dns_rdata_init(&delrdata);
1779 dns_rdata_clone(&rdata, &delrdata);
1780 ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link);
1781 result = dns_rdatalist_tordataset(&rdatalist, &delrdataset);
1782 check_result(result, "dns_rdatalist_tordataset()");
1783 result = dns_db_subtractrdataset(gdb, node, gversion,
1784 &delrdataset, 0, NULL);
1785 dns_rdataset_disassociate(&delrdataset);
1786 if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
1787 check_result(result, "dns_db_subtractrdataset(NSEC3)");
1788 delete_rrsigs = ISC_TRUE;
1790 dns_rdataset_disassociate(&rdataset);
1791 if (result != ISC_R_NOMORE)
1792 check_result(result, "dns_rdataset_first/next");
1797 * Delete the NSEC3 RRSIGs
1799 result = dns_db_deleterdataset(gdb, node, gversion,
1800 dns_rdatatype_rrsig,
1801 dns_rdatatype_nsec3);
1802 if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
1803 check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))");
1807 * Generate NSEC3 records for the zone.
1810 nsec3ify(unsigned int hashalg, unsigned int iterations,
1811 const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
1813 dns_dbiterator_t *dbiter = NULL;
1814 dns_dbnode_t *node = NULL, *nextnode = NULL;
1815 dns_fixedname_t fname, fnextname, fzonecut;
1816 dns_name_t *name, *nextname, *zonecut;
1817 isc_boolean_t done = ISC_FALSE;
1818 isc_result_t result;
1819 isc_boolean_t active;
1820 isc_uint32_t nsttl = 0;
1821 unsigned int count, nlabels;
1824 dns_fixedname_init(&fname);
1825 name = dns_fixedname_name(&fname);
1826 dns_fixedname_init(&fnextname);
1827 nextname = dns_fixedname_name(&fnextname);
1828 dns_fixedname_init(&fzonecut);
1832 * Walk the zone generating the hash names.
1834 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
1835 check_result(result, "dns_db_createiterator()");
1837 result = dns_dbiterator_first(dbiter);
1838 check_result(result, "dns_dbiterator_first()");
1841 dns_dbiterator_current(dbiter, &node, name);
1842 result = dns_dbiterator_next(dbiter);
1844 while (result == ISC_R_SUCCESS) {
1845 result = dns_dbiterator_current(dbiter, &nextnode,
1847 if (result != ISC_R_SUCCESS)
1849 active = active_node(nextnode);
1851 dns_db_detachnode(gdb, &nextnode);
1852 result = dns_dbiterator_next(dbiter);
1855 if (!dns_name_issubdomain(nextname, gorigin) ||
1857 dns_name_issubdomain(nextname, zonecut))) {
1858 dns_db_detachnode(gdb, &nextnode);
1859 result = dns_dbiterator_next(dbiter);
1862 if (delegation(nextname, nextnode, &nsttl)) {
1863 zonecut = dns_fixedname_name(&fzonecut);
1864 dns_name_copy(nextname, zonecut, NULL);
1866 add_ds(nextname, nextnode, nsttl);
1867 if (OPTOUT(nsec3flags) &&
1868 !secure(nextname, nextnode)) {
1869 dns_db_detachnode(gdb, &nextnode);
1870 result = dns_dbiterator_next(dbiter);
1874 dns_db_detachnode(gdb, &nextnode);
1877 if (result == ISC_R_NOMORE) {
1878 dns_name_copy(gorigin, nextname, NULL);
1880 } else if (result != ISC_R_SUCCESS)
1881 fatal("iterating through the database failed: %s",
1882 isc_result_totext(result));
1883 dns_name_downcase(name, name, NULL);
1884 hashlist_add_dns_name(hashlist, name, hashalg, iterations,
1885 salt, salt_length, ISC_FALSE);
1886 dns_db_detachnode(gdb, &node);
1888 * Add hashs for empty nodes. Use closest encloser logic.
1889 * The closest encloser either has data or is a empty
1890 * node for another <name,nextname> span so we don't add
1891 * it here. Empty labels on nextname are within the span.
1893 dns_name_downcase(nextname, nextname, NULL);
1894 dns_name_fullcompare(name, nextname, &order, &nlabels);
1895 addnowildcardhash(hashlist, name, hashalg, iterations,
1897 count = dns_name_countlabels(nextname);
1898 while (count > nlabels + 1) {
1900 dns_name_split(nextname, count, NULL, nextname);
1901 hashlist_add_dns_name(hashlist, nextname, hashalg,
1902 iterations, salt, salt_length,
1904 addnowildcardhash(hashlist, nextname, hashalg,
1905 iterations, salt, salt_length);
1908 dns_dbiterator_destroy(&dbiter);
1911 * We have all the hashes now so we can sort them.
1913 hashlist_sort(hashlist);
1916 * Check for duplicate hashes. If found the salt needs to
1919 if (hashlist_hasdup(hashlist))
1920 fatal("Duplicate hash detected. Pick a different salt.");
1923 * Generate the nsec3 records.
1928 addnsec3param(salt, salt_length, iterations);
1930 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
1931 check_result(result, "dns_db_createiterator()");
1933 result = dns_dbiterator_first(dbiter);
1934 check_result(result, "dns_dbiterator_first()");
1937 dns_dbiterator_current(dbiter, &node, name);
1938 result = dns_dbiterator_next(dbiter);
1940 while (result == ISC_R_SUCCESS) {
1941 result = dns_dbiterator_current(dbiter, &nextnode,
1943 if (result != ISC_R_SUCCESS)
1946 * Cleanout NSEC3 RRsets which don't exist in the
1949 nsec3clean(nextname, nextnode, hashalg, iterations,
1950 salt, salt_length, hashlist);
1952 * Skip NSEC3 only nodes when looking for the next
1953 * node in the zone. Also skips now empty nodes.
1955 if (nsec3only(nextnode)) {
1956 dns_db_detachnode(gdb, &nextnode);
1957 result = dns_dbiterator_next(dbiter);
1960 if (!dns_name_issubdomain(nextname, gorigin) ||
1962 dns_name_issubdomain(nextname, zonecut))) {
1963 dns_db_detachnode(gdb, &nextnode);
1964 result = dns_dbiterator_next(dbiter);
1967 if (delegation(nextname, nextnode, NULL)) {
1968 zonecut = dns_fixedname_name(&fzonecut);
1969 dns_name_copy(nextname, zonecut, NULL);
1970 if (OPTOUT(nsec3flags) &&
1971 !secure(nextname, nextnode)) {
1972 dns_db_detachnode(gdb, &nextnode);
1973 result = dns_dbiterator_next(dbiter);
1977 dns_db_detachnode(gdb, &nextnode);
1980 if (result == ISC_R_NOMORE) {
1981 dns_name_copy(gorigin, nextname, NULL);
1983 } else if (result != ISC_R_SUCCESS)
1984 fatal("iterating through the database failed: %s",
1985 isc_result_totext(result));
1987 * We need to pause here to release the lock on the database.
1989 dns_dbiterator_pause(dbiter);
1990 addnsec3(name, node, salt, salt_length, iterations,
1992 dns_db_detachnode(gdb, &node);
1994 * Add NSEC3's for empty nodes. Use closest encloser logic.
1996 dns_name_fullcompare(name, nextname, &order, &nlabels);
1997 count = dns_name_countlabels(nextname);
1998 while (count > nlabels + 1) {
2000 dns_name_split(nextname, count, NULL, nextname);
2001 addnsec3(nextname, NULL, salt, salt_length,
2002 iterations, hashlist, zonettl);
2005 dns_dbiterator_destroy(&dbiter);
2009 * Load the zone file from disk
2012 loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
2015 dns_fixedname_t fname;
2017 isc_result_t result;
2019 len = strlen(origin);
2020 isc_buffer_init(&b, origin, len);
2021 isc_buffer_add(&b, len);
2023 dns_fixedname_init(&fname);
2024 name = dns_fixedname_name(&fname);
2025 result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
2026 if (result != ISC_R_SUCCESS)
2027 fatal("failed converting name '%s' to dns format: %s",
2028 origin, isc_result_totext(result));
2030 result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
2031 rdclass, 0, NULL, db);
2032 check_result(result, "dns_db_create()");
2034 result = dns_db_load2(*db, file, inputformat);
2035 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
2036 fatal("failed loading zone from '%s': %s",
2037 file, isc_result_totext(result));
2041 * Finds all public zone keys in the zone, and attempts to load the
2042 * private keys from disk.
2045 loadzonekeys(dns_db_t *db) {
2047 dns_dbversion_t *currentversion;
2048 isc_result_t result;
2049 dst_key_t *keys[20];
2050 unsigned int nkeys, i;
2052 currentversion = NULL;
2053 dns_db_currentversion(db, ¤tversion);
2056 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
2057 if (result != ISC_R_SUCCESS)
2058 fatal("failed to find the zone's origin: %s",
2059 isc_result_totext(result));
2061 result = dns_dnssec_findzonekeys(db, currentversion, node, gorigin,
2062 mctx, 20, keys, &nkeys);
2063 if (result == ISC_R_NOTFOUND)
2064 result = ISC_R_SUCCESS;
2065 if (result != ISC_R_SUCCESS)
2066 fatal("failed to find the zone keys: %s",
2067 isc_result_totext(result));
2069 for (i = 0; i < nkeys; i++) {
2072 key = newkeystruct(keys[i], dst_key_isprivate(keys[i]));
2073 ISC_LIST_APPEND(keylist, key, link);
2075 dns_db_detachnode(db, &node);
2076 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
2080 * Finds all public zone keys in the zone.
2083 loadzonepubkeys(dns_db_t *db) {
2084 dns_dbversion_t *currentversion = NULL;
2085 dns_dbnode_t *node = NULL;
2086 dns_rdataset_t rdataset;
2087 dns_rdata_t rdata = DNS_RDATA_INIT;
2090 isc_result_t result;
2092 dns_db_currentversion(db, ¤tversion);
2094 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
2095 if (result != ISC_R_SUCCESS)
2096 fatal("failed to find the zone's origin: %s",
2097 isc_result_totext(result));
2099 dns_rdataset_init(&rdataset);
2100 result = dns_db_findrdataset(db, node, currentversion,
2101 dns_rdatatype_dnskey, 0, 0, &rdataset, NULL);
2102 if (result != ISC_R_SUCCESS)
2103 fatal("failed to find keys at the zone apex: %s",
2104 isc_result_totext(result));
2105 result = dns_rdataset_first(&rdataset);
2106 check_result(result, "dns_rdataset_first");
2107 while (result == ISC_R_SUCCESS) {
2109 dns_rdata_reset(&rdata);
2110 dns_rdataset_current(&rdataset, &rdata);
2111 result = dns_dnssec_keyfromrdata(gorigin, &rdata, mctx,
2113 if (result != ISC_R_SUCCESS)
2115 if (!dst_key_iszonekey(pubkey)) {
2116 dst_key_free(&pubkey);
2120 key = newkeystruct(pubkey, ISC_FALSE);
2121 ISC_LIST_APPEND(keylist, key, link);
2123 result = dns_rdataset_next(&rdataset);
2125 dns_rdataset_disassociate(&rdataset);
2126 dns_db_detachnode(db, &node);
2127 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
2131 warnifallksk(dns_db_t *db) {
2132 dns_dbversion_t *currentversion = NULL;
2133 dns_dbnode_t *node = NULL;
2134 dns_rdataset_t rdataset;
2135 dns_rdata_t rdata = DNS_RDATA_INIT;
2136 isc_result_t result;
2137 dns_rdata_key_t key;
2138 isc_boolean_t have_non_ksk = ISC_FALSE;
2140 dns_db_currentversion(db, ¤tversion);
2142 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
2143 if (result != ISC_R_SUCCESS)
2144 fatal("failed to find the zone's origin: %s",
2145 isc_result_totext(result));
2147 dns_rdataset_init(&rdataset);
2148 result = dns_db_findrdataset(db, node, currentversion,
2149 dns_rdatatype_dnskey, 0, 0, &rdataset, NULL);
2150 if (result != ISC_R_SUCCESS)
2151 fatal("failed to find keys at the zone apex: %s",
2152 isc_result_totext(result));
2153 result = dns_rdataset_first(&rdataset);
2154 check_result(result, "dns_rdataset_first");
2155 while (result == ISC_R_SUCCESS) {
2156 dns_rdata_reset(&rdata);
2157 dns_rdataset_current(&rdataset, &rdata);
2158 result = dns_rdata_tostruct(&rdata, &key, NULL);
2159 check_result(result, "dns_rdata_tostruct");
2160 if ((key.flags & DNS_KEYFLAG_KSK) == 0) {
2161 have_non_ksk = ISC_TRUE;
2162 result = ISC_R_NOMORE;
2164 result = dns_rdataset_next(&rdataset);
2166 dns_rdataset_disassociate(&rdataset);
2167 dns_db_detachnode(db, &node);
2168 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
2169 if (!have_non_ksk && !ignoreksk)
2170 fprintf(stderr, "%s: warning: No non-KSK dnskey found. "
2171 "Supply non-KSK dnskey or use '-z'.\n",
2176 writeset(const char *prefix, dns_rdatatype_t type) {
2178 char namestr[DNS_NAME_FORMATSIZE];
2179 dns_db_t *db = NULL;
2180 dns_dbversion_t *version = NULL;
2182 dns_difftuple_t *tuple = NULL;
2183 dns_fixedname_t fixed;
2185 dns_rdata_t rdata, ds;
2186 isc_boolean_t have_ksk = ISC_FALSE;
2187 isc_boolean_t have_non_ksk = ISC_FALSE;
2189 isc_buffer_t namebuf;
2191 isc_result_t result;
2193 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
2194 unsigned char keybuf[DST_KEY_MAXSIZE];
2195 unsigned int filenamelen;
2196 const dns_master_style_t *style =
2197 (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
2199 isc_buffer_init(&namebuf, namestr, sizeof(namestr));
2200 result = dns_name_tofilenametext(gorigin, ISC_FALSE, &namebuf);
2201 check_result(result, "dns_name_tofilenametext");
2202 isc_buffer_putuint8(&namebuf, 0);
2203 filenamelen = strlen(prefix) + strlen(namestr);
2204 if (directory != NULL)
2205 filenamelen += strlen(directory) + 1;
2206 filename = isc_mem_get(mctx, filenamelen + 1);
2207 if (filename == NULL)
2208 fatal("out of memory");
2209 if (directory != NULL)
2210 sprintf(filename, "%s/", directory);
2213 strcat(filename, prefix);
2214 strcat(filename, namestr);
2216 dns_diff_init(mctx, &diff);
2218 for (key = ISC_LIST_HEAD(keylist);
2220 key = ISC_LIST_NEXT(key, link))
2222 have_non_ksk = ISC_TRUE;
2226 for (key = ISC_LIST_HEAD(keylist);
2228 key = ISC_LIST_NEXT(key, link))
2230 have_ksk = ISC_TRUE;
2234 if (type == dns_rdatatype_dlv) {
2236 unsigned int labels;
2238 dns_name_init(&tname, NULL);
2239 dns_fixedname_init(&fixed);
2240 name = dns_fixedname_name(&fixed);
2241 labels = dns_name_countlabels(gorigin);
2242 dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
2243 result = dns_name_concatenate(&tname, dlv, name, NULL);
2244 check_result(result, "dns_name_concatenate");
2248 for (key = ISC_LIST_HEAD(keylist);
2250 key = ISC_LIST_NEXT(key, link))
2252 if (have_ksk && have_non_ksk && !key->isksk)
2254 dns_rdata_init(&rdata);
2255 dns_rdata_init(&ds);
2256 isc_buffer_init(&b, keybuf, sizeof(keybuf));
2257 result = dst_key_todns(key->key, &b);
2258 check_result(result, "dst_key_todns");
2259 isc_buffer_usedregion(&b, &r);
2260 dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
2261 if (type != dns_rdatatype_dnskey) {
2262 result = dns_ds_buildrdata(gorigin, &rdata,
2265 check_result(result, "dns_ds_buildrdata");
2266 if (type == dns_rdatatype_dlv)
2267 ds.type = dns_rdatatype_dlv;
2268 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
2269 name, 0, &ds, &tuple);
2270 check_result(result, "dns_difftuple_create");
2271 dns_diff_append(&diff, &tuple);
2273 dns_rdata_reset(&ds);
2274 result = dns_ds_buildrdata(gorigin, &rdata,
2275 DNS_DSDIGEST_SHA256,
2277 check_result(result, "dns_ds_buildrdata");
2278 if (type == dns_rdatatype_dlv)
2279 ds.type = dns_rdatatype_dlv;
2280 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
2281 name, 0, &ds, &tuple);
2284 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
2287 check_result(result, "dns_difftuple_create");
2288 dns_diff_append(&diff, &tuple);
2291 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
2292 gclass, 0, NULL, &db);
2293 check_result(result, "dns_db_create");
2295 result = dns_db_newversion(db, &version);
2296 check_result(result, "dns_db_newversion");
2298 result = dns_diff_apply(&diff, db, version);
2299 check_result(result, "dns_diff_apply");
2300 dns_diff_clear(&diff);
2302 result = dns_master_dump(mctx, db, version, style, filename);
2303 check_result(result, "dns_master_dump");
2305 isc_mem_put(mctx, filename, filenamelen + 1);
2307 dns_db_closeversion(db, &version, ISC_FALSE);
2312 print_time(FILE *fp) {
2315 if (outputformat != dns_masterformat_text)
2318 currenttime = time(NULL);
2319 fprintf(fp, "; File written on %s", ctime(¤ttime));
2323 print_version(FILE *fp) {
2324 if (outputformat != dns_masterformat_text)
2327 fprintf(fp, "; dnssec_signzone version " VERSION "\n");
2332 fprintf(stderr, "Usage:\n");
2333 fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
2335 fprintf(stderr, "\n");
2337 fprintf(stderr, "Version: %s\n", VERSION);
2339 fprintf(stderr, "Options: (default value in parenthesis) \n");
2340 fprintf(stderr, "\t-c class (IN)\n");
2341 fprintf(stderr, "\t-d directory\n");
2342 fprintf(stderr, "\t\tdirectory to find keyset files (.)\n");
2343 fprintf(stderr, "\t-g:\t");
2344 fprintf(stderr, "generate DS records from keyset files\n");
2345 fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
2346 fprintf(stderr, "\t\tRRSIG start time - absolute|offset (now - 1 hour)\n");
2347 fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
2348 fprintf(stderr, "\t\tRRSIG end time - absolute|from start|from now "
2349 "(now + 30 days)\n");
2350 fprintf(stderr, "\t-i interval:\n");
2351 fprintf(stderr, "\t\tcycle interval - resign "
2352 "if < interval from end ( (end-start)/4 )\n");
2353 fprintf(stderr, "\t-j jitter:\n");
2354 fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n");
2355 fprintf(stderr, "\t-v debuglevel (0)\n");
2356 fprintf(stderr, "\t-o origin:\n");
2357 fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
2358 fprintf(stderr, "\t-f outfile:\n");
2359 fprintf(stderr, "\t\tfile the signed zone is written in "
2360 "(zonefile + .signed)\n");
2361 fprintf(stderr, "\t-I format:\n");
2362 fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
2363 fprintf(stderr, "\t-O format:\n");
2364 fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
2365 fprintf(stderr, "\t-N format:\n");
2366 fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
2367 fprintf(stderr, "\t-r randomdev:\n");
2368 fprintf(stderr, "\t\ta file containing random data\n");
2369 fprintf(stderr, "\t-a:\t");
2370 fprintf(stderr, "verify generated signatures\n");
2371 fprintf(stderr, "\t-p:\t");
2372 fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
2373 fprintf(stderr, "\t-t:\t");
2374 fprintf(stderr, "print statistics\n");
2375 fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
2376 fprintf(stderr, "\t-k key_signing_key\n");
2377 fprintf(stderr, "\t-l lookasidezone\n");
2378 fprintf(stderr, "\t-3 salt (NSEC3 salt)\n");
2379 fprintf(stderr, "\t-H iterations (NSEC3 iterations)\n");
2380 fprintf(stderr, "\t-A (NSEC3 optout)\n");
2381 fprintf(stderr, "\t-z:\t");
2382 fprintf(stderr, "ignore KSK flag in DNSKEYs");
2384 fprintf(stderr, "\n");
2386 fprintf(stderr, "Signing Keys: ");
2387 fprintf(stderr, "(default: all zone keys that have private keys)\n");
2388 fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
2393 removetempfile(void) {
2395 isc_file_remove(tempfile);
2399 print_stats(isc_time_t *timer_start, isc_time_t *timer_finish) {
2400 isc_uint64_t runtime_us; /* Runtime in microseconds */
2401 isc_uint64_t runtime_ms; /* Runtime in milliseconds */
2402 isc_uint64_t sig_ms; /* Signatures per millisecond */
2404 runtime_us = isc_time_microdiff(timer_finish, timer_start);
2406 printf("Signatures generated: %10d\n", nsigned);
2407 printf("Signatures retained: %10d\n", nretained);
2408 printf("Signatures dropped: %10d\n", ndropped);
2409 printf("Signatures successfully verified: %10d\n", nverified);
2410 printf("Signatures unsuccessfully verified: %10d\n", nverifyfailed);
2411 runtime_ms = runtime_us / 1000;
2412 printf("Runtime in seconds: %7u.%03u\n",
2413 (unsigned int) (runtime_ms / 1000),
2414 (unsigned int) (runtime_ms % 1000));
2415 if (runtime_us > 0) {
2416 sig_ms = ((isc_uint64_t)nsigned * 1000000000) / runtime_us;
2417 printf("Signatures per second: %7u.%03u\n",
2418 (unsigned int) sig_ms / 1000,
2419 (unsigned int) sig_ms % 1000);
2424 main(int argc, char *argv[]) {
2426 char *startstr = NULL, *endstr = NULL, *classname = NULL;
2427 char *origin = NULL, *file = NULL, *output = NULL;
2428 char *inputformatstr = NULL, *outputformatstr = NULL;
2429 char *serialformatstr = NULL;
2430 char *dskeyfile[MAXDSKEYS];
2433 isc_time_t timer_start, timer_finish;
2435 isc_result_t result;
2436 isc_log_t *log = NULL;
2437 isc_boolean_t pseudorandom = ISC_FALSE;
2438 unsigned int eflags;
2439 isc_boolean_t free_output = ISC_FALSE;
2441 dns_rdataclass_t rdclass;
2442 isc_task_t **tasks = NULL;
2445 unsigned int iterations = 100U;
2446 const unsigned char *salt = NULL;
2447 size_t salt_length = 0;
2448 unsigned char saltbuf[255];
2449 hashlist_t hashlist;
2451 #define CMDLINE_FLAGS "3:aAc:d:e:f:ghH:i:I:j:k:l:m:n:N:o:O:pr:s:StUv:z"
2454 * Process memory debugging argument first.
2456 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
2459 if (strcasecmp(isc_commandline_argument, "record") == 0)
2460 isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
2461 if (strcasecmp(isc_commandline_argument, "trace") == 0)
2462 isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
2463 if (strcasecmp(isc_commandline_argument, "usage") == 0)
2464 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
2465 if (strcasecmp(isc_commandline_argument, "size") == 0)
2466 isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
2467 if (strcasecmp(isc_commandline_argument, "mctx") == 0)
2468 isc_mem_debugging |= ISC_MEM_DEBUGCTX;
2474 isc_commandline_reset = ISC_TRUE;
2476 masterstyle = &dns_master_style_explicitttl;
2478 check_result(isc_app_start(), "isc_app_start");
2480 result = isc_mem_create(0, 0, &mctx);
2481 if (result != ISC_R_SUCCESS)
2482 fatal("out of memory");
2484 dns_result_register();
2486 isc_commandline_errprint = ISC_FALSE;
2488 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
2491 if (strcmp(isc_commandline_argument, "-")) {
2492 isc_buffer_t target;
2495 sarg = isc_commandline_argument;
2496 isc_buffer_init(&target, saltbuf,
2498 result = isc_hex_decodestring(sarg, &target);
2499 check_result(result,
2500 "isc_hex_decodestring(salt)");
2502 salt_length = isc_buffer_usedlength(&target);
2507 nsec_datatype = dns_rdatatype_nsec3;
2511 nsec3flags |= DNS_NSEC3FLAG_OPTOUT;
2515 tryverify = ISC_TRUE;
2519 classname = isc_commandline_argument;
2523 directory = isc_commandline_argument;
2527 endstr = isc_commandline_argument;
2531 output = isc_commandline_argument;
2535 generateds = ISC_TRUE;
2539 if (isc_commandline_option != '?')
2540 fprintf(stderr, "%s: invalid argument -%c\n",
2541 program, isc_commandline_option);
2547 fprintf(stderr, "%s: unhandled option -%c\n",
2548 program, isc_commandline_option);
2553 cycle = strtol(isc_commandline_argument, &endp, 0);
2554 if (*endp != '\0' || cycle < 0)
2555 fatal("cycle period must be numeric and "
2560 inputformatstr = isc_commandline_argument;
2565 jitter = strtol(isc_commandline_argument, &endp, 0);
2566 if (*endp != '\0' || jitter < 0)
2567 fatal("jitter must be numeric and positive");
2571 dns_fixedname_init(&dlv_fixed);
2572 len = strlen(isc_commandline_argument);
2573 isc_buffer_init(&b, isc_commandline_argument, len);
2574 isc_buffer_add(&b, len);
2576 dns_fixedname_init(&dlv_fixed);
2577 dlv = dns_fixedname_name(&dlv_fixed);
2578 result = dns_name_fromtext(dlv, &b, dns_rootname,
2580 check_result(result, "dns_name_fromtext(dlv)");
2584 if (ndskeys == MAXDSKEYS)
2585 fatal("too many key-signing keys specified");
2586 dskeyfile[ndskeys++] = isc_commandline_argument;
2594 ntasks = strtol(isc_commandline_argument, &endp, 0);
2595 if (*endp != '\0' || ntasks > ISC_INT32_MAX)
2596 fatal("number of cpus must be numeric");
2600 serialformatstr = isc_commandline_argument;
2604 iterations = strtoul(isc_commandline_argument,
2607 fatal("iterations must be numeric");
2608 if (iterations > 0xffffU)
2609 fatal("iterations too big");
2613 origin = isc_commandline_argument;
2617 outputformatstr = isc_commandline_argument;
2621 pseudorandom = ISC_TRUE;
2625 setup_entropy(mctx, isc_commandline_argument, &ectx);
2629 startstr = isc_commandline_argument;
2633 /* This is intentionally undocumented */
2634 /* -S: simple output style */
2635 masterstyle = &dns_master_style_simple;
2639 printstats = ISC_TRUE;
2642 case 'U': /* Undocumented for testing only. */
2643 unknownalg = ISC_TRUE;
2648 verbose = strtol(isc_commandline_argument, &endp, 0);
2650 fatal("verbose level must be numeric");
2654 ignoreksk = ISC_TRUE;
2660 setup_entropy(mctx, NULL, &ectx);
2661 eflags = ISC_ENTROPY_BLOCKING;
2663 eflags |= ISC_ENTROPY_GOODONLY;
2665 result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
2666 if (result != ISC_R_SUCCESS)
2667 fatal("could not create hash context");
2669 result = dst_lib_init(mctx, ectx, eflags);
2670 if (result != ISC_R_SUCCESS)
2671 fatal("could not initialize dst");
2673 isc_stdtime_get(&now);
2675 if (startstr != NULL)
2676 starttime = strtotime(startstr, now, now);
2678 starttime = now - 3600; /* Allow for some clock skew. */
2681 endtime = strtotime(endstr, now, starttime);
2683 endtime = starttime + (30 * 24 * 60 * 60);
2686 cycle = (endtime - starttime) / 4;
2689 ntasks = isc_os_ncpus() * 2;
2690 vbprintf(4, "using %d cpus\n", ntasks);
2692 rdclass = strtoclass(classname);
2694 setup_logging(verbose, mctx, &log);
2696 argc -= isc_commandline_index;
2697 argv += isc_commandline_index;
2710 if (output == NULL) {
2711 free_output = ISC_TRUE;
2712 output = isc_mem_allocate(mctx,
2713 strlen(file) + strlen(".signed") + 1);
2715 fatal("out of memory");
2716 sprintf(output, "%s.signed", file);
2719 if (inputformatstr != NULL) {
2720 if (strcasecmp(inputformatstr, "text") == 0)
2721 inputformat = dns_masterformat_text;
2722 else if (strcasecmp(inputformatstr, "raw") == 0)
2723 inputformat = dns_masterformat_raw;
2725 fatal("unknown file format: %s\n", inputformatstr);
2728 if (outputformatstr != NULL) {
2729 if (strcasecmp(outputformatstr, "text") == 0)
2730 outputformat = dns_masterformat_text;
2731 else if (strcasecmp(outputformatstr, "raw") == 0)
2732 outputformat = dns_masterformat_raw;
2734 fatal("unknown file format: %s\n", outputformatstr);
2737 if (serialformatstr != NULL) {
2738 if (strcasecmp(serialformatstr, "keep") == 0)
2739 serialformat = SOA_SERIAL_KEEP;
2740 else if (strcasecmp(serialformatstr, "increment") == 0 ||
2741 strcasecmp(serialformatstr, "incr") == 0)
2742 serialformat = SOA_SERIAL_INCREMENT;
2743 else if (strcasecmp(serialformatstr, "unixtime") == 0)
2744 serialformat = SOA_SERIAL_UNIXTIME;
2746 fatal("unknown soa serial format: %s\n", serialformatstr);
2749 result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL,
2750 0, 24, 0, 0, 0, 8, mctx);
2751 check_result(result, "dns_master_stylecreate");
2754 TIME_NOW(&timer_start);
2755 loadzone(file, origin, rdclass, &gdb);
2756 gorigin = dns_db_origin(gdb);
2757 gclass = dns_db_class(gdb);
2761 isc_boolean_t answer;
2762 hash_length = dns_nsec3_hashlength(dns_hash_sha1);
2763 hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2,
2765 result = dns_nsec_nseconly(gdb, gversion, &answer);
2766 check_result(result, "dns_nsec_nseconly");
2768 fatal("NSEC3 generation requested with "
2769 "NSEC only DNSKEY");
2772 ISC_LIST_INIT(keylist);
2777 for (i = 0; i < argc; i++) {
2778 dst_key_t *newkey = NULL;
2780 result = dst_key_fromnamedfile(argv[i],
2784 if (result != ISC_R_SUCCESS)
2785 fatal("cannot load dnskey %s: %s", argv[i],
2786 isc_result_totext(result));
2788 if (!dns_name_equal(gorigin, dst_key_name(newkey)))
2789 fatal("key %s not at origin\n", argv[i]);
2791 key = ISC_LIST_HEAD(keylist);
2792 while (key != NULL) {
2793 dst_key_t *dkey = key->key;
2794 if (dst_key_id(dkey) == dst_key_id(newkey) &&
2795 dst_key_alg(dkey) == dst_key_alg(newkey) &&
2796 dns_name_equal(dst_key_name(dkey),
2797 dst_key_name(newkey)))
2799 if (!dst_key_isprivate(dkey))
2800 fatal("cannot sign zone with "
2801 "non-private dnskey %s",
2805 key = ISC_LIST_NEXT(key, link);
2808 key = newkeystruct(newkey, ISC_TRUE);
2809 ISC_LIST_APPEND(keylist, key, link);
2811 dst_key_free(&newkey);
2814 loadzonepubkeys(gdb);
2817 for (i = 0; i < ndskeys; i++) {
2818 dst_key_t *newkey = NULL;
2820 result = dst_key_fromnamedfile(dskeyfile[i],
2824 if (result != ISC_R_SUCCESS)
2825 fatal("cannot load dnskey %s: %s", dskeyfile[i],
2826 isc_result_totext(result));
2828 if (!dns_name_equal(gorigin, dst_key_name(newkey)))
2829 fatal("key %s not at origin\n", dskeyfile[i]);
2831 key = ISC_LIST_HEAD(keylist);
2832 while (key != NULL) {
2833 dst_key_t *dkey = key->key;
2834 if (dst_key_id(dkey) == dst_key_id(newkey) &&
2835 dst_key_alg(dkey) == dst_key_alg(newkey) &&
2836 dns_name_equal(dst_key_name(dkey),
2837 dst_key_name(newkey)))
2839 /* Override key flags. */
2840 key->issigningkey = ISC_TRUE;
2841 key->isksk = ISC_TRUE;
2842 key->isdsk = ISC_FALSE;
2843 dst_key_free(&dkey);
2847 key = ISC_LIST_NEXT(key, link);
2850 /* Override dnskey flags. */
2851 key = newkeystruct(newkey, ISC_TRUE);
2852 key->isksk = ISC_TRUE;
2853 key->isdsk = ISC_FALSE;
2854 ISC_LIST_APPEND(keylist, key, link);
2858 if (ISC_LIST_EMPTY(keylist)) {
2859 fprintf(stderr, "%s: warning: No keys specified or found\n",
2866 result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max);
2867 check_result(result, "dns_nsec3_maxiterations()");
2868 if (iterations > max)
2869 fatal("NSEC3 iterations too big for weakest DNSKEY "
2870 "strength. Maximum iterations allowed %u.", max);
2876 result = dns_db_newversion(gdb, &gversion);
2877 check_result(result, "dns_db_newversion()");
2879 switch (serialformat) {
2880 case SOA_SERIAL_INCREMENT:
2883 case SOA_SERIAL_UNIXTIME:
2886 case SOA_SERIAL_KEEP:
2893 nsec3ify(dns_hash_sha1, iterations, salt, salt_length,
2899 writeset("keyset-", dns_rdatatype_dnskey);
2900 writeset("dsset-", dns_rdatatype_ds);
2902 writeset("dlvset-", dns_rdatatype_dlv);
2906 tempfilelen = strlen(output) + 20;
2907 tempfile = isc_mem_get(mctx, tempfilelen);
2908 if (tempfile == NULL)
2909 fatal("out of memory");
2911 result = isc_file_mktemplate(output, tempfile, tempfilelen);
2912 check_result(result, "isc_file_mktemplate");
2915 result = isc_file_openunique(tempfile, &fp);
2916 if (result != ISC_R_SUCCESS)
2917 fatal("failed to open temporary output file: %s",
2918 isc_result_totext(result));
2919 removefile = ISC_TRUE;
2920 setfatalcallback(&removetempfile);
2925 result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
2926 if (result != ISC_R_SUCCESS)
2927 fatal("failed to create task manager: %s",
2928 isc_result_totext(result));
2931 result = isc_task_create(taskmgr, 0, &master);
2932 if (result != ISC_R_SUCCESS)
2933 fatal("failed to create task: %s", isc_result_totext(result));
2935 tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
2937 fatal("out of memory");
2938 for (i = 0; i < (int)ntasks; i++) {
2940 result = isc_task_create(taskmgr, 0, &tasks[i]);
2941 if (result != ISC_R_SUCCESS)
2942 fatal("failed to create task: %s",
2943 isc_result_totext(result));
2946 RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS);
2948 RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS);
2954 * There is more work to do. Spread it out over multiple
2955 * processors if possible.
2957 for (i = 0; i < (int)ntasks; i++) {
2958 result = isc_app_onrun(mctx, master, startworker,
2960 if (result != ISC_R_SUCCESS)
2961 fatal("failed to start task: %s",
2962 isc_result_totext(result));
2964 (void)isc_app_run();
2966 fatal("process aborted by user");
2968 isc_task_detach(&master);
2969 shuttingdown = ISC_TRUE;
2970 for (i = 0; i < (int)ntasks; i++)
2971 isc_task_detach(&tasks[i]);
2972 isc_taskmgr_destroy(&taskmgr);
2973 isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
2976 if (outputformat != dns_masterformat_text) {
2977 result = dns_master_dumptostream2(mctx, gdb, gversion,
2978 masterstyle, outputformat,
2980 check_result(result, "dns_master_dumptostream2");
2983 result = isc_stdio_close(fp);
2984 check_result(result, "isc_stdio_close");
2985 removefile = ISC_FALSE;
2987 result = isc_file_rename(tempfile, output);
2988 if (result != ISC_R_SUCCESS)
2989 fatal("failed to rename temp file to %s: %s\n",
2990 output, isc_result_totext(result));
2992 DESTROYLOCK(&namelock);
2994 DESTROYLOCK(&statslock);
2996 printf("%s\n", output);
2998 dns_db_closeversion(gdb, &gversion, ISC_FALSE);
2999 dns_db_detach(&gdb);
3001 while (!ISC_LIST_EMPTY(keylist)) {
3002 key = ISC_LIST_HEAD(keylist);
3003 ISC_LIST_UNLINK(keylist, key, link);
3004 dst_key_free(&key->key);
3005 isc_mem_put(mctx, key, sizeof(signer_key_t));
3008 isc_mem_put(mctx, tempfile, tempfilelen);
3011 isc_mem_free(mctx, output);
3013 dns_master_styledestroy(&dsstyle, mctx);
3015 cleanup_logging(&log);
3018 cleanup_entropy(&ectx);
3021 isc_mem_stats(mctx, stdout);
3022 isc_mem_destroy(&mctx);
3024 (void) isc_app_finish();
3027 TIME_NOW(&timer_finish);
3028 print_stats(&timer_start, &timer_finish);