2 * Portions Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (C) 1999-2003 Internet Software Consortium.
4 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
13 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
16 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 /* $Id: dnssec-signzone.c,v 1.177.18.26 2008/06/02 23:46:01 tbox Exp $ */
29 #include <isc/commandline.h>
30 #include <isc/entropy.h>
31 #include <isc/event.h>
35 #include <isc/mutex.h>
37 #include <isc/print.h>
38 #include <isc/random.h>
39 #include <isc/serial.h>
40 #include <isc/stdio.h>
41 #include <isc/string.h>
47 #include <dns/dbiterator.h>
49 #include <dns/dnssec.h>
51 #include <dns/fixedname.h>
52 #include <dns/keyvalues.h>
54 #include <dns/master.h>
55 #include <dns/masterdump.h>
57 #include <dns/rdata.h>
58 #include <dns/rdataset.h>
59 #include <dns/rdataclass.h>
60 #include <dns/rdatasetiter.h>
61 #include <dns/rdatastruct.h>
62 #include <dns/rdatatype.h>
63 #include <dns/result.h>
69 #include "dnssectool.h"
71 const char *program = "dnssec-signzone";
77 typedef struct signer_key_struct signer_key_t;
79 struct signer_key_struct {
81 isc_boolean_t issigningkey;
84 unsigned int position;
85 ISC_LINK(signer_key_t) link;
88 #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
89 #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
90 #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
92 #define SOA_SERIAL_KEEP 0
93 #define SOA_SERIAL_INCREMENT 1
94 #define SOA_SERIAL_UNIXTIME 2
96 typedef struct signer_event sevent_t;
98 ISC_EVENT_COMMON(sevent_t);
99 dns_fixedname_t *fname;
103 static ISC_LIST(signer_key_t) keylist;
104 static unsigned int keycount = 0;
105 static isc_stdtime_t starttime = 0, endtime = 0, now;
106 static int cycle = -1;
107 static int jitter = 0;
108 static isc_boolean_t tryverify = ISC_FALSE;
109 static isc_boolean_t printstats = ISC_FALSE;
110 static isc_mem_t *mctx = NULL;
111 static isc_entropy_t *ectx = NULL;
112 static dns_ttl_t zonettl;
114 static char *tempfile = NULL;
115 static const dns_master_style_t *masterstyle;
116 static dns_masterformat_t inputformat = dns_masterformat_text;
117 static dns_masterformat_t outputformat = dns_masterformat_text;
118 static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
119 static unsigned int nverified = 0, nverifyfailed = 0;
120 static const char *directory;
121 static isc_mutex_t namelock, statslock;
122 static isc_taskmgr_t *taskmgr = NULL;
123 static dns_db_t *gdb; /* The database */
124 static dns_dbversion_t *gversion; /* The database version */
125 static dns_dbiterator_t *gdbiter; /* The database iterator */
126 static dns_rdataclass_t gclass; /* The class */
127 static dns_name_t *gorigin; /* The database origin */
128 static isc_task_t *master = NULL;
129 static unsigned int ntasks = 0;
130 static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE;
131 static isc_boolean_t nokeys = ISC_FALSE;
132 static isc_boolean_t removefile = ISC_FALSE;
133 static isc_boolean_t generateds = ISC_FALSE;
134 static isc_boolean_t ignoreksk = ISC_FALSE;
135 static dns_name_t *dlv = NULL;
136 static dns_fixedname_t dlv_fixed;
137 static dns_master_style_t *dsstyle = NULL;
138 static unsigned int serialformat = SOA_SERIAL_KEEP;
140 #define INCSTAT(counter) \
144 UNLOCK(&statslock); \
148 sign(isc_task_t *task, isc_event_t *event);
152 set_bit(unsigned char *array, unsigned int index, unsigned int bit) {
153 unsigned int shift, mask;
155 shift = 7 - (index % 8);
159 array[index / 8] |= mask;
161 array[index / 8] &= (~mask & 0xFF);
165 dumpnode(dns_name_t *name, dns_dbnode_t *node) {
168 if (outputformat != dns_masterformat_text)
170 result = dns_master_dumpnodetostream(mctx, gdb, gversion, node, name,
172 check_result(result, "dns_master_dumpnodetostream");
175 static signer_key_t *
176 newkeystruct(dst_key_t *dstkey, isc_boolean_t signwithkey) {
179 key = isc_mem_get(mctx, sizeof(signer_key_t));
181 fatal("out of memory");
183 if ((dst_key_flags(dstkey) & DNS_KEYFLAG_KSK) != 0) {
184 key->issigningkey = signwithkey;
185 key->isksk = ISC_TRUE;
186 key->isdsk = ISC_FALSE;
188 key->issigningkey = signwithkey;
189 key->isksk = ISC_FALSE;
190 key->isdsk = ISC_TRUE;
192 key->position = keycount++;
193 ISC_LINK_INIT(key, link);
198 signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdata_t *rdata,
199 dst_key_t *key, isc_buffer_t *b)
202 isc_stdtime_t jendtime;
204 jendtime = (jitter != 0) ? isc_random_jitter(endtime, jitter) : endtime;
205 result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
207 isc_entropy_stopcallbacksources(ectx);
208 if (result != ISC_R_SUCCESS) {
209 char keystr[KEY_FORMATSIZE];
210 key_format(key, keystr, sizeof(keystr));
211 fatal("dnskey '%s' failed to sign data: %s",
212 keystr, isc_result_totext(result));
217 result = dns_dnssec_verify(name, rdataset, key,
218 ISC_TRUE, mctx, rdata);
219 if (result == ISC_R_SUCCESS) {
220 vbprintf(3, "\tsignature verified\n");
223 vbprintf(3, "\tsignature failed to verify\n");
224 INCSTAT(nverifyfailed);
229 static inline isc_boolean_t
230 issigningkey(signer_key_t *key) {
231 return (key->issigningkey);
234 static inline isc_boolean_t
235 iszonekey(signer_key_t *key) {
236 return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) &&
237 dst_key_iszonekey(key->key)));
241 * Finds the key that generated a RRSIG, if possible. First look at the keys
242 * that we've loaded already, and then see if there's a key on disk.
244 static signer_key_t *
245 keythatsigned(dns_rdata_rrsig_t *rrsig) {
247 dst_key_t *pubkey = NULL, *privkey = NULL;
250 key = ISC_LIST_HEAD(keylist);
251 while (key != NULL) {
252 if (rrsig->keyid == dst_key_id(key->key) &&
253 rrsig->algorithm == dst_key_alg(key->key) &&
254 dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
256 key = ISC_LIST_NEXT(key, link);
259 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
260 rrsig->algorithm, DST_TYPE_PUBLIC,
261 NULL, mctx, &pubkey);
262 if (result != ISC_R_SUCCESS)
265 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
267 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
268 NULL, mctx, &privkey);
269 if (result == ISC_R_SUCCESS) {
270 dst_key_free(&pubkey);
271 key = newkeystruct(privkey, ISC_FALSE);
273 key = newkeystruct(pubkey, ISC_FALSE);
274 ISC_LIST_APPEND(keylist, key, link);
279 * Check to see if we expect to find a key at this name. If we see a RRSIG
280 * and can't find the signing key that we expect to find, we drop the rrsig.
281 * I'm not sure if this is completely correct, but it seems to work.
284 expecttofindkey(dns_name_t *name) {
285 unsigned int options = DNS_DBFIND_NOWILD;
286 dns_fixedname_t fname;
288 char namestr[DNS_NAME_FORMATSIZE];
290 dns_fixedname_init(&fname);
291 result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
292 0, NULL, dns_fixedname_name(&fname), NULL, NULL);
298 case DNS_R_DELEGATION:
303 dns_name_format(name, namestr, sizeof(namestr));
304 fatal("failure looking for '%s DNSKEY' in database: %s",
305 namestr, isc_result_totext(result));
306 return (ISC_FALSE); /* removes a warning */
309 static inline isc_boolean_t
310 setverifies(dns_name_t *name, dns_rdataset_t *set, signer_key_t *key,
314 result = dns_dnssec_verify(name, set, key->key, ISC_FALSE, mctx, rrsig);
315 if (result == ISC_R_SUCCESS) {
319 INCSTAT(nverifyfailed);
325 * Signs a set. Goes through contortions to decide if each RRSIG should
326 * be dropped or retained, and then determines if any new SIGs need to
330 signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
333 dns_rdataset_t sigset;
334 dns_rdata_t sigrdata = DNS_RDATA_INIT;
335 dns_rdata_rrsig_t rrsig;
338 isc_boolean_t nosigs = ISC_FALSE;
339 isc_boolean_t *wassignedby, *nowsignedby;
341 dns_difftuple_t *tuple;
344 char namestr[DNS_NAME_FORMATSIZE];
345 char typestr[TYPE_FORMATSIZE];
346 char sigstr[SIG_FORMATSIZE];
348 dns_name_format(name, namestr, sizeof(namestr));
349 type_format(set->type, typestr, sizeof(typestr));
351 ttl = ISC_MIN(set->ttl, endtime - starttime);
353 dns_rdataset_init(&sigset);
354 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
355 set->type, 0, &sigset, NULL);
356 if (result == ISC_R_NOTFOUND) {
357 result = ISC_R_SUCCESS;
360 if (result != ISC_R_SUCCESS)
361 fatal("failed while looking for '%s RRSIG %s': %s",
362 namestr, typestr, isc_result_totext(result));
364 vbprintf(1, "%s/%s:\n", namestr, typestr);
366 arraysize = keycount;
368 arraysize += dns_rdataset_count(&sigset);
369 wassignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
370 nowsignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
371 if (wassignedby == NULL || nowsignedby == NULL)
372 fatal("out of memory");
374 for (i = 0; i < arraysize; i++)
375 wassignedby[i] = nowsignedby[i] = ISC_FALSE;
378 result = ISC_R_NOMORE;
380 result = dns_rdataset_first(&sigset);
382 while (result == ISC_R_SUCCESS) {
383 isc_boolean_t expired, future;
384 isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE;
386 dns_rdataset_current(&sigset, &sigrdata);
388 result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
389 check_result(result, "dns_rdata_tostruct");
391 future = isc_serial_lt(now, rrsig.timesigned);
393 key = keythatsigned(&rrsig);
394 sig_format(&rrsig, sigstr, sizeof(sigstr));
395 if (key != NULL && issigningkey(key))
396 expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
398 expired = isc_serial_gt(now, rrsig.timeexpire);
400 if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
401 /* rrsig is dropped and not replaced */
402 vbprintf(2, "\trrsig by %s dropped - "
403 "invalid validity period\n",
405 } else if (key == NULL && !future &&
406 expecttofindkey(&rrsig.signer))
408 /* rrsig is dropped and not replaced */
409 vbprintf(2, "\trrsig by %s dropped - "
410 "private dnskey not found\n",
412 } else if (key == NULL || future) {
413 vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
414 expired ? "retained" : "dropped", sigstr);
417 } else if (issigningkey(key)) {
418 if (!expired && setverifies(name, set, key, &sigrdata))
420 vbprintf(2, "\trrsig by %s retained\n", sigstr);
422 wassignedby[key->position] = ISC_TRUE;
423 nowsignedby[key->position] = ISC_TRUE;
425 vbprintf(2, "\trrsig by %s dropped - %s\n",
427 expired ? "expired" :
429 wassignedby[key->position] = ISC_TRUE;
432 } else if (iszonekey(key)) {
433 if (!expired && setverifies(name, set, key, &sigrdata))
435 vbprintf(2, "\trrsig by %s retained\n", sigstr);
437 wassignedby[key->position] = ISC_TRUE;
438 nowsignedby[key->position] = ISC_TRUE;
440 vbprintf(2, "\trrsig by %s dropped - %s\n",
442 expired ? "expired" :
444 wassignedby[key->position] = ISC_TRUE;
446 } else if (!expired) {
447 vbprintf(2, "\trrsig by %s retained\n", sigstr);
450 vbprintf(2, "\trrsig by %s expired\n", sigstr);
454 nowsignedby[key->position] = ISC_TRUE;
456 if (sigset.ttl != ttl) {
457 vbprintf(2, "\tfixing ttl %s\n", sigstr);
459 result = dns_difftuple_create(mctx,
464 check_result(result, "dns_difftuple_create");
465 dns_diff_append(del, &tuple);
466 result = dns_difftuple_create(mctx,
471 check_result(result, "dns_difftuple_create");
472 dns_diff_append(add, &tuple);
476 result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL,
479 check_result(result, "dns_difftuple_create");
480 dns_diff_append(del, &tuple);
486 dns_rdata_t trdata = DNS_RDATA_INIT;
487 unsigned char array[BUFSIZE];
488 char keystr[KEY_FORMATSIZE];
492 key_format(key->key, keystr, sizeof(keystr));
493 vbprintf(1, "\tresigning with dnskey %s\n", keystr);
494 isc_buffer_init(&b, array, sizeof(array));
495 signwithkey(name, set, &trdata, key->key, &b);
496 nowsignedby[key->position] = ISC_TRUE;
498 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
501 check_result(result, "dns_difftuple_create");
502 dns_diff_append(add, &tuple);
505 dns_rdata_reset(&sigrdata);
506 dns_rdata_freestruct(&rrsig);
507 result = dns_rdataset_next(&sigset);
509 if (result == ISC_R_NOMORE)
510 result = ISC_R_SUCCESS;
512 check_result(result, "dns_rdataset_first/next");
513 if (dns_rdataset_isassociated(&sigset))
514 dns_rdataset_disassociate(&sigset);
516 for (key = ISC_LIST_HEAD(keylist);
518 key = ISC_LIST_NEXT(key, link))
522 unsigned char array[BUFSIZE];
523 char keystr[KEY_FORMATSIZE];
525 if (nowsignedby[key->position])
528 if (!key->issigningkey)
530 if (!(ignoreksk || key->isdsk ||
532 set->type == dns_rdatatype_dnskey &&
533 dns_name_equal(name, gorigin))))
536 key_format(key->key, keystr, sizeof(keystr));
537 vbprintf(1, "\tsigning with dnskey %s\n", keystr);
538 dns_rdata_init(&trdata);
539 isc_buffer_init(&b, array, sizeof(array));
540 signwithkey(name, set, &trdata, key->key, &b);
542 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
543 ttl, &trdata, &tuple);
544 check_result(result, "dns_difftuple_create");
545 dns_diff_append(add, &tuple);
548 isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t));
549 isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t));
553 opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
560 isc_buffer_init(&b, filename, sizeof(filename));
561 if (directory != NULL) {
562 isc_buffer_putstr(&b, directory);
563 if (directory[strlen(directory) - 1] != '/')
564 isc_buffer_putstr(&b, "/");
566 isc_buffer_putstr(&b, prefix);
567 result = dns_name_tofilenametext(name, ISC_FALSE, &b);
568 check_result(result, "dns_name_tofilenametext()");
569 if (isc_buffer_availablelength(&b) == 0) {
570 char namestr[DNS_NAME_FORMATSIZE];
571 dns_name_format(name, namestr, sizeof(namestr));
572 fatal("name '%s' is too long", namestr);
574 isc_buffer_putuint8(&b, 0);
576 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
577 rdclass, 0, NULL, dbp);
578 check_result(result, "dns_db_create()");
580 result = dns_db_load(*dbp, filename);
581 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
586 * Loads the key set for a child zone, if there is one, and builds DS records.
589 loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
591 dns_dbversion_t *ver = NULL;
592 dns_dbnode_t *node = NULL;
594 dns_rdataset_t keyset;
596 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
598 dns_difftuple_t *tuple = NULL;
600 opendb("keyset-", name, gclass, &db);
602 return (ISC_R_NOTFOUND);
604 result = dns_db_findnode(db, name, ISC_FALSE, &node);
605 if (result != ISC_R_SUCCESS) {
607 return (DNS_R_BADDB);
609 dns_rdataset_init(&keyset);
610 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
612 if (result != ISC_R_SUCCESS) {
613 dns_db_detachnode(db, &node);
618 vbprintf(2, "found DNSKEY records\n");
620 result = dns_db_newversion(db, &ver);
621 check_result(result, "dns_db_newversion");
623 dns_diff_init(mctx, &diff);
625 for (result = dns_rdataset_first(&keyset);
626 result == ISC_R_SUCCESS;
627 result = dns_rdataset_next(&keyset))
629 dns_rdata_init(&key);
631 dns_rdataset_current(&keyset, &key);
632 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
634 check_result(result, "dns_ds_buildrdata");
636 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
638 check_result(result, "dns_difftuple_create");
639 dns_diff_append(&diff, &tuple);
641 dns_rdata_reset(&ds);
642 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
644 check_result(result, "dns_ds_buildrdata");
646 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
648 check_result(result, "dns_difftuple_create");
649 dns_diff_append(&diff, &tuple);
651 result = dns_diff_apply(&diff, db, ver);
652 check_result(result, "dns_diff_apply");
653 dns_diff_clear(&diff);
655 dns_db_closeversion(db, &ver, ISC_TRUE);
657 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
659 check_result(result, "dns_db_findrdataset");
661 dns_rdataset_disassociate(&keyset);
662 dns_db_detachnode(db, &node);
668 nsec_setbit(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdatatype_t type,
672 dns_rdata_t rdata = DNS_RDATA_INIT;
673 dns_rdata_nsec_t nsec;
675 unsigned char bitmap[8192 + 512];
676 unsigned char nsecdata[8192 + 512 + DNS_NAME_MAXWIRE];
677 isc_boolean_t answer = ISC_FALSE;
678 unsigned int i, len, window;
681 result = dns_rdataset_first(rdataset);
682 check_result(result, "dns_rdataset_first()");
683 dns_rdataset_current(rdataset, &rdata);
684 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
685 check_result(result, "dns_rdata_tostruct");
687 INSIST(nsec.len <= sizeof(bitmap));
691 memset(bitmap, 0, sizeof(bitmap));
692 for (i = 0; i < nsec.len; i += len) {
693 INSIST(i + 2 <= nsec.len);
694 window = nsec.typebits[i];
695 len = nsec.typebits[i+1];
697 INSIST(len > 0 && len <= 32);
698 INSIST(i + len <= nsec.len);
699 memmove(&bitmap[window * 32 + 512], &nsec.typebits[i], len);
701 set_bit(bitmap + 512, type, val);
702 for (window = 0; window < 256; window++) {
703 for (octet = 31; octet >= 0; octet--)
704 if (bitmap[window * 32 + 512 + octet] != 0)
708 bitmap[newlen] = window;
709 bitmap[newlen + 1] = octet + 1;
714 memmove(&bitmap[newlen], &bitmap[window * 32 + 512], octet + 1);
717 if (newlen != nsec.len ||
718 memcmp(nsec.typebits, bitmap, newlen) != 0) {
719 dns_rdata_t newrdata = DNS_RDATA_INIT;
722 dns_difftuple_t *tuple = NULL;
724 dns_diff_init(mctx, &diff);
725 result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL, name,
726 rdataset->ttl, &rdata, &tuple);
727 check_result(result, "dns_difftuple_create");
728 dns_diff_append(&diff, &tuple);
730 nsec.typebits = bitmap;
732 isc_buffer_init(&b, nsecdata, sizeof(nsecdata));
733 result = dns_rdata_fromstruct(&newrdata, rdata.rdclass,
734 dns_rdatatype_nsec, &nsec,
736 check_result(result, "dns_rdata_fromstruct");
738 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
741 check_result(result, "dns_difftuple_create");
742 dns_diff_append(&diff, &tuple);
743 result = dns_diff_apply(&diff, gdb, gversion);
744 check_result(result, "dns_difftuple_apply");
745 dns_diff_clear(&diff);
748 dns_rdata_freestruct(&nsec);
753 delegation(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) {
754 dns_rdataset_t nsset;
757 if (dns_name_equal(name, gorigin))
760 dns_rdataset_init(&nsset);
761 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ns,
763 if (dns_rdataset_isassociated(&nsset)) {
766 dns_rdataset_disassociate(&nsset);
769 return (ISC_TF(result == ISC_R_SUCCESS));
773 * Signs all records at a name. This mostly just signs each set individually,
774 * but also adds the RRSIG bit to any NSECs generated earlier, deals with
775 * parent/child KEY signatures, and handles other exceptional cases.
778 signname(dns_dbnode_t *node, dns_name_t *name) {
780 dns_rdataset_t rdataset;
781 dns_rdatasetiter_t *rdsiter;
782 isc_boolean_t isdelegation = ISC_FALSE;
783 isc_boolean_t hasds = ISC_FALSE;
784 isc_boolean_t changed = ISC_FALSE;
786 char namestr[DNS_NAME_FORMATSIZE];
787 isc_uint32_t nsttl = 0;
789 dns_name_format(name, namestr, sizeof(namestr));
792 * Determine if this is a delegation point.
794 if (delegation(name, node, &nsttl))
795 isdelegation = ISC_TRUE;
798 * If this is a delegation point, look for a DS set.
801 dns_rdataset_t dsset;
802 dns_rdataset_t sigdsset;
804 dns_rdataset_init(&dsset);
805 dns_rdataset_init(&sigdsset);
806 result = dns_db_findrdataset(gdb, node, gversion,
808 0, 0, &dsset, &sigdsset);
809 if (result == ISC_R_SUCCESS) {
810 dns_rdataset_disassociate(&dsset);
812 result = dns_db_deleterdataset(gdb, node,
816 check_result(result, "dns_db_deleterdataset");
821 result = loadds(name, nsttl, &dsset);
822 if (result == ISC_R_SUCCESS) {
823 result = dns_db_addrdataset(gdb, node,
826 check_result(result, "dns_db_addrdataset");
828 dns_rdataset_disassociate(&dsset);
829 if (dns_rdataset_isassociated(&sigdsset))
830 dns_rdataset_disassociate(&sigdsset);
831 } else if (dns_rdataset_isassociated(&sigdsset)) {
832 result = dns_db_deleterdataset(gdb, node,
836 check_result(result, "dns_db_deleterdataset");
837 dns_rdataset_disassociate(&sigdsset);
839 } else if (dns_rdataset_isassociated(&sigdsset))
840 dns_rdataset_disassociate(&sigdsset);
844 * Make sure that NSEC bits are appropriately set.
846 dns_rdataset_init(&rdataset);
847 RUNTIME_CHECK(dns_db_findrdataset(gdb, node, gversion,
848 dns_rdatatype_nsec, 0, 0, &rdataset,
849 NULL) == ISC_R_SUCCESS);
851 changed = nsec_setbit(name, &rdataset, dns_rdatatype_rrsig, 1);
853 dns_rdataset_disassociate(&rdataset);
854 RUNTIME_CHECK(dns_db_findrdataset(gdb, node, gversion,
855 dns_rdatatype_nsec, 0, 0,
857 NULL) == ISC_R_SUCCESS);
860 (void)nsec_setbit(name, &rdataset, dns_rdatatype_ds, 1);
862 (void)nsec_setbit(name, &rdataset, dns_rdatatype_ds, 0);
863 dns_rdataset_disassociate(&rdataset);
866 * Now iterate through the rdatasets.
868 dns_diff_init(mctx, &del);
869 dns_diff_init(mctx, &add);
871 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
872 check_result(result, "dns_db_allrdatasets()");
873 result = dns_rdatasetiter_first(rdsiter);
874 while (result == ISC_R_SUCCESS) {
875 dns_rdatasetiter_current(rdsiter, &rdataset);
877 /* If this is a RRSIG set, skip it. */
878 if (rdataset.type == dns_rdatatype_rrsig)
882 * If this name is a delegation point, skip all records
883 * except NSEC and DS sets. Otherwise check that there
887 if (rdataset.type != dns_rdatatype_nsec &&
888 rdataset.type != dns_rdatatype_ds)
890 } else if (rdataset.type == dns_rdatatype_ds) {
891 char namebuf[DNS_NAME_FORMATSIZE];
892 dns_name_format(name, namebuf, sizeof(namebuf));
893 fatal("'%s': found DS RRset without NS RRset\n",
897 signset(&del, &add, node, name, &rdataset);
900 dns_rdataset_disassociate(&rdataset);
901 result = dns_rdatasetiter_next(rdsiter);
903 if (result != ISC_R_NOMORE)
904 fatal("rdataset iteration for name '%s' failed: %s",
905 namestr, isc_result_totext(result));
907 dns_rdatasetiter_destroy(&rdsiter);
909 result = dns_diff_applysilently(&del, gdb, gversion);
910 if (result != ISC_R_SUCCESS)
911 fatal("failed to delete SIGs at node '%s': %s",
912 namestr, isc_result_totext(result));
914 result = dns_diff_applysilently(&add, gdb, gversion);
915 if (result != ISC_R_SUCCESS)
916 fatal("failed to add SIGs at node '%s': %s",
917 namestr, isc_result_totext(result));
919 dns_diff_clear(&del);
920 dns_diff_clear(&add);
923 static inline isc_boolean_t
924 active_node(dns_dbnode_t *node) {
925 dns_rdatasetiter_t *rdsiter = NULL;
926 dns_rdatasetiter_t *rdsiter2 = NULL;
927 isc_boolean_t active = ISC_FALSE;
929 dns_rdataset_t rdataset;
930 dns_rdatatype_t type;
931 dns_rdatatype_t covers;
934 dns_rdataset_init(&rdataset);
935 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
936 check_result(result, "dns_db_allrdatasets()");
937 result = dns_rdatasetiter_first(rdsiter);
938 while (result == ISC_R_SUCCESS) {
939 dns_rdatasetiter_current(rdsiter, &rdataset);
940 if (rdataset.type != dns_rdatatype_nsec &&
941 rdataset.type != dns_rdatatype_rrsig)
943 dns_rdataset_disassociate(&rdataset);
945 result = dns_rdatasetiter_next(rdsiter);
947 result = ISC_R_NOMORE;
949 if (result != ISC_R_NOMORE)
950 fatal("rdataset iteration failed: %s",
951 isc_result_totext(result));
955 * The node is empty of everything but NSEC / RRSIG records.
957 for (result = dns_rdatasetiter_first(rdsiter);
958 result == ISC_R_SUCCESS;
959 result = dns_rdatasetiter_next(rdsiter)) {
960 dns_rdatasetiter_current(rdsiter, &rdataset);
961 result = dns_db_deleterdataset(gdb, node, gversion,
964 check_result(result, "dns_db_deleterdataset()");
965 dns_rdataset_disassociate(&rdataset);
967 if (result != ISC_R_NOMORE)
968 fatal("rdataset iteration failed: %s",
969 isc_result_totext(result));
972 * Delete RRSIGs for types that no longer exist.
974 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
975 check_result(result, "dns_db_allrdatasets()");
976 for (result = dns_rdatasetiter_first(rdsiter);
977 result == ISC_R_SUCCESS;
978 result = dns_rdatasetiter_next(rdsiter)) {
979 dns_rdatasetiter_current(rdsiter, &rdataset);
980 type = rdataset.type;
981 covers = rdataset.covers;
982 dns_rdataset_disassociate(&rdataset);
983 if (type != dns_rdatatype_rrsig)
986 for (result = dns_rdatasetiter_first(rdsiter2);
987 !found && result == ISC_R_SUCCESS;
988 result = dns_rdatasetiter_next(rdsiter2)) {
989 dns_rdatasetiter_current(rdsiter2, &rdataset);
990 if (rdataset.type == covers)
992 dns_rdataset_disassociate(&rdataset);
995 if (result != ISC_R_NOMORE)
996 fatal("rdataset iteration failed: %s",
997 isc_result_totext(result));
998 result = dns_db_deleterdataset(gdb, node,
1001 check_result(result,
1002 "dns_db_deleterdataset(rrsig)");
1003 } else if (result != ISC_R_NOMORE &&
1004 result != ISC_R_SUCCESS)
1005 fatal("rdataset iteration failed: %s",
1006 isc_result_totext(result));
1008 if (result != ISC_R_NOMORE)
1009 fatal("rdataset iteration failed: %s",
1010 isc_result_totext(result));
1011 dns_rdatasetiter_destroy(&rdsiter2);
1013 dns_rdatasetiter_destroy(&rdsiter);
1019 * Extracts the TTL from the SOA.
1023 dns_rdataset_t soaset;
1024 dns_fixedname_t fname;
1026 isc_result_t result;
1028 dns_rdata_t rdata = DNS_RDATA_INIT;
1029 dns_rdata_soa_t soa;
1031 dns_fixedname_init(&fname);
1032 name = dns_fixedname_name(&fname);
1033 dns_rdataset_init(&soaset);
1034 result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
1035 0, 0, NULL, name, &soaset, NULL);
1036 if (result != ISC_R_SUCCESS)
1037 fatal("failed to find an SOA at the zone apex: %s",
1038 isc_result_totext(result));
1040 result = dns_rdataset_first(&soaset);
1041 check_result(result, "dns_rdataset_first");
1042 dns_rdataset_current(&soaset, &rdata);
1043 result = dns_rdata_tostruct(&rdata, &soa, NULL);
1044 check_result(result, "dns_rdata_tostruct");
1046 dns_rdataset_disassociate(&soaset);
1051 * Increment (or set if nonzero) the SOA serial
1054 setsoaserial(isc_uint32_t serial) {
1055 isc_result_t result;
1056 dns_dbnode_t *node = NULL;
1057 dns_rdataset_t rdataset;
1058 dns_rdata_t rdata = DNS_RDATA_INIT;
1059 isc_uint32_t old_serial, new_serial;
1061 result = dns_db_getoriginnode(gdb, &node);
1062 if (result != ISC_R_SUCCESS)
1065 dns_rdataset_init(&rdataset);
1067 result = dns_db_findrdataset(gdb, node, gversion,
1068 dns_rdatatype_soa, 0,
1069 0, &rdataset, NULL);
1070 if (result != ISC_R_SUCCESS)
1073 result = dns_rdataset_first(&rdataset);
1074 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1076 dns_rdataset_current(&rdataset, &rdata);
1078 old_serial = dns_soa_getserial(&rdata);
1081 /* Set SOA serial to the value provided. */
1082 new_serial = serial;
1084 /* Increment SOA serial using RFC 1982 arithmetics */
1085 new_serial = (old_serial + 1) & 0xFFFFFFFF;
1086 if (new_serial == 0)
1090 /* If the new serial is not likely to cause a zone transfer
1091 * (a/ixfr) from servers having the old serial, warn the user.
1093 * RFC1982 section 7 defines the maximum increment to be
1094 * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
1095 * comparison. (5 - 6 == (2^32)-1, not negative-one)
1097 if (new_serial == old_serial ||
1098 (new_serial - old_serial) > 0x7fffffffU)
1099 fprintf(stderr, "%s: warning: Serial number not advanced, "
1100 "zone may not transfer\n", program);
1102 dns_soa_setserial(new_serial, &rdata);
1104 result = dns_db_deleterdataset(gdb, node, gversion,
1105 dns_rdatatype_soa, 0);
1106 check_result(result, "dns_db_deleterdataset");
1107 if (result != ISC_R_SUCCESS)
1110 result = dns_db_addrdataset(gdb, node, gversion,
1111 0, &rdataset, 0, NULL);
1112 check_result(result, "dns_db_addrdataset");
1113 if (result != ISC_R_SUCCESS)
1117 dns_rdataset_disassociate(&rdataset);
1119 dns_db_detachnode(gdb, &node);
1120 dns_rdata_reset(&rdata);
1126 * Delete any RRSIG records at a node.
1129 cleannode(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
1130 dns_rdatasetiter_t *rdsiter = NULL;
1132 isc_result_t result, dresult;
1134 if (outputformat != dns_masterformat_text)
1137 dns_rdataset_init(&set);
1138 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
1139 check_result(result, "dns_db_allrdatasets");
1140 result = dns_rdatasetiter_first(rdsiter);
1141 while (result == ISC_R_SUCCESS) {
1142 isc_boolean_t destroy = ISC_FALSE;
1143 dns_rdatatype_t covers = 0;
1144 dns_rdatasetiter_current(rdsiter, &set);
1145 if (set.type == dns_rdatatype_rrsig) {
1146 covers = set.covers;
1149 dns_rdataset_disassociate(&set);
1150 result = dns_rdatasetiter_next(rdsiter);
1152 dresult = dns_db_deleterdataset(db, node, version,
1153 dns_rdatatype_rrsig,
1155 check_result(dresult, "dns_db_deleterdataset");
1158 if (result != ISC_R_NOMORE)
1159 fatal("rdataset iteration failed: %s",
1160 isc_result_totext(result));
1161 dns_rdatasetiter_destroy(&rdsiter);
1165 * Set up the iterator and global state before starting the tasks.
1169 isc_result_t result;
1172 result = dns_db_createiterator(gdb, ISC_FALSE, &gdbiter);
1173 check_result(result, "dns_db_createiterator()");
1175 result = dns_dbiterator_first(gdbiter);
1176 check_result(result, "dns_dbiterator_first()");
1180 * Clean up the iterator and global state after the tasks complete.
1184 dns_dbiterator_destroy(&gdbiter);
1188 * Sign the apex of the zone.
1192 dns_dbnode_t *node = NULL;
1193 dns_fixedname_t fixed;
1195 isc_result_t result;
1197 dns_fixedname_init(&fixed);
1198 name = dns_fixedname_name(&fixed);
1199 result = dns_dbiterator_current(gdbiter, &node, name);
1200 check_result(result, "dns_dbiterator_current()");
1201 signname(node, name);
1202 dumpnode(name, node);
1203 cleannode(gdb, gversion, node);
1204 dns_db_detachnode(gdb, &node);
1205 result = dns_dbiterator_next(gdbiter);
1206 if (result == ISC_R_NOMORE)
1207 finished = ISC_TRUE;
1208 else if (result != ISC_R_SUCCESS)
1209 fatal("failure iterating database: %s",
1210 isc_result_totext(result));
1214 * Assigns a node to a worker thread. This is protected by the master task's
1218 assignwork(isc_task_t *task, isc_task_t *worker) {
1219 dns_fixedname_t *fname;
1223 dns_rdataset_t nsec;
1224 isc_boolean_t found;
1225 isc_result_t result;
1226 static unsigned int ended = 0; /* Protected by namelock. */
1234 if (ended == ntasks) {
1235 isc_task_detach(&task);
1241 fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
1243 fatal("out of memory");
1244 dns_fixedname_init(fname);
1245 name = dns_fixedname_name(fname);
1249 result = dns_dbiterator_current(gdbiter, &node, name);
1250 if (result != ISC_R_SUCCESS)
1251 fatal("failure iterating database: %s",
1252 isc_result_totext(result));
1253 dns_rdataset_init(&nsec);
1254 result = dns_db_findrdataset(gdb, node, gversion,
1255 dns_rdatatype_nsec, 0, 0,
1257 if (result == ISC_R_SUCCESS)
1260 dumpnode(name, node);
1261 if (dns_rdataset_isassociated(&nsec))
1262 dns_rdataset_disassociate(&nsec);
1264 dns_db_detachnode(gdb, &node);
1266 result = dns_dbiterator_next(gdbiter);
1267 if (result == ISC_R_NOMORE) {
1268 finished = ISC_TRUE;
1270 } else if (result != ISC_R_SUCCESS)
1271 fatal("failure iterating database: %s",
1272 isc_result_totext(result));
1276 if (ended == ntasks) {
1277 isc_task_detach(&task);
1280 isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
1283 sevent = (sevent_t *)
1284 isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
1285 sign, NULL, sizeof(sevent_t));
1287 fatal("failed to allocate event\n");
1289 sevent->node = node;
1290 sevent->fname = fname;
1291 isc_task_send(worker, ISC_EVENT_PTR(&sevent));
1297 * Start a worker task
1300 startworker(isc_task_t *task, isc_event_t *event) {
1303 worker = (isc_task_t *)event->ev_arg;
1304 assignwork(task, worker);
1305 isc_event_free(&event);
1309 * Write a node to the output file, and restart the worker task.
1312 writenode(isc_task_t *task, isc_event_t *event) {
1314 sevent_t *sevent = (sevent_t *)event;
1316 worker = (isc_task_t *)event->ev_sender;
1317 dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
1318 cleannode(gdb, gversion, sevent->node);
1319 dns_db_detachnode(gdb, &sevent->node);
1320 isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
1321 assignwork(task, worker);
1322 isc_event_free(&event);
1326 * Sign a database node.
1329 sign(isc_task_t *task, isc_event_t *event) {
1330 dns_fixedname_t *fname;
1332 sevent_t *sevent, *wevent;
1334 sevent = (sevent_t *)event;
1335 node = sevent->node;
1336 fname = sevent->fname;
1337 isc_event_free(&event);
1339 signname(node, dns_fixedname_name(fname));
1340 wevent = (sevent_t *)
1341 isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
1342 writenode, NULL, sizeof(sevent_t));
1344 fatal("failed to allocate event\n");
1345 wevent->node = node;
1346 wevent->fname = fname;
1347 isc_task_send(master, ISC_EVENT_PTR(&wevent));
1351 * Generate NSEC records for the zone.
1355 dns_dbiterator_t *dbiter = NULL;
1356 dns_dbnode_t *node = NULL, *nextnode = NULL;
1357 dns_fixedname_t fname, fnextname, fzonecut;
1358 dns_name_t *name, *nextname, *zonecut;
1359 isc_boolean_t done = ISC_FALSE;
1360 isc_result_t result;
1362 dns_fixedname_init(&fname);
1363 name = dns_fixedname_name(&fname);
1364 dns_fixedname_init(&fnextname);
1365 nextname = dns_fixedname_name(&fnextname);
1366 dns_fixedname_init(&fzonecut);
1369 result = dns_db_createiterator(gdb, ISC_FALSE, &dbiter);
1370 check_result(result, "dns_db_createiterator()");
1372 result = dns_dbiterator_first(dbiter);
1373 check_result(result, "dns_dbiterator_first()");
1376 dns_dbiterator_current(dbiter, &node, name);
1377 if (delegation(name, node, NULL)) {
1378 zonecut = dns_fixedname_name(&fzonecut);
1379 dns_name_copy(name, zonecut, NULL);
1381 result = dns_dbiterator_next(dbiter);
1383 while (result == ISC_R_SUCCESS) {
1384 isc_boolean_t active = ISC_FALSE;
1385 result = dns_dbiterator_current(dbiter, &nextnode,
1387 if (result != ISC_R_SUCCESS)
1389 active = active_node(nextnode);
1391 dns_db_detachnode(gdb, &nextnode);
1392 result = dns_dbiterator_next(dbiter);
1395 if (!dns_name_issubdomain(nextname, gorigin) ||
1397 dns_name_issubdomain(nextname, zonecut)))
1399 dns_db_detachnode(gdb, &nextnode);
1400 result = dns_dbiterator_next(dbiter);
1403 dns_db_detachnode(gdb, &nextnode);
1406 if (result == ISC_R_NOMORE) {
1407 dns_name_clone(gorigin, nextname);
1409 } else if (result != ISC_R_SUCCESS)
1410 fatal("iterating through the database failed: %s",
1411 isc_result_totext(result));
1412 result = dns_nsec_build(gdb, gversion, node, nextname,
1414 check_result(result, "dns_nsec_build()");
1415 dns_db_detachnode(gdb, &node);
1418 dns_dbiterator_destroy(&dbiter);
1422 * Load the zone file from disk
1425 loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
1428 dns_fixedname_t fname;
1430 isc_result_t result;
1432 len = strlen(origin);
1433 isc_buffer_init(&b, origin, len);
1434 isc_buffer_add(&b, len);
1436 dns_fixedname_init(&fname);
1437 name = dns_fixedname_name(&fname);
1438 result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
1439 if (result != ISC_R_SUCCESS)
1440 fatal("failed converting name '%s' to dns format: %s",
1441 origin, isc_result_totext(result));
1443 result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
1444 rdclass, 0, NULL, db);
1445 check_result(result, "dns_db_create()");
1447 result = dns_db_load2(*db, file, inputformat);
1448 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
1449 fatal("failed loading zone from '%s': %s",
1450 file, isc_result_totext(result));
1454 * Finds all public zone keys in the zone, and attempts to load the
1455 * private keys from disk.
1458 loadzonekeys(dns_db_t *db) {
1460 dns_dbversion_t *currentversion;
1461 isc_result_t result;
1462 dst_key_t *keys[20];
1463 unsigned int nkeys, i;
1465 currentversion = NULL;
1466 dns_db_currentversion(db, ¤tversion);
1469 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
1470 if (result != ISC_R_SUCCESS)
1471 fatal("failed to find the zone's origin: %s",
1472 isc_result_totext(result));
1474 result = dns_dnssec_findzonekeys(db, currentversion, node, gorigin,
1475 mctx, 20, keys, &nkeys);
1476 if (result == ISC_R_NOTFOUND)
1477 result = ISC_R_SUCCESS;
1478 if (result != ISC_R_SUCCESS)
1479 fatal("failed to find the zone keys: %s",
1480 isc_result_totext(result));
1482 for (i = 0; i < nkeys; i++) {
1485 key = newkeystruct(keys[i], dst_key_isprivate(keys[i]));
1486 ISC_LIST_APPEND(keylist, key, link);
1488 dns_db_detachnode(db, &node);
1489 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
1493 * Finds all public zone keys in the zone.
1496 loadzonepubkeys(dns_db_t *db) {
1497 dns_dbversion_t *currentversion = NULL;
1498 dns_dbnode_t *node = NULL;
1499 dns_rdataset_t rdataset;
1500 dns_rdata_t rdata = DNS_RDATA_INIT;
1503 isc_result_t result;
1505 dns_db_currentversion(db, ¤tversion);
1507 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
1508 if (result != ISC_R_SUCCESS)
1509 fatal("failed to find the zone's origin: %s",
1510 isc_result_totext(result));
1512 dns_rdataset_init(&rdataset);
1513 result = dns_db_findrdataset(db, node, currentversion,
1514 dns_rdatatype_dnskey, 0, 0, &rdataset, NULL);
1515 if (result != ISC_R_SUCCESS)
1516 fatal("failed to find keys at the zone apex: %s",
1517 isc_result_totext(result));
1518 result = dns_rdataset_first(&rdataset);
1519 check_result(result, "dns_rdataset_first");
1520 while (result == ISC_R_SUCCESS) {
1522 dns_rdata_reset(&rdata);
1523 dns_rdataset_current(&rdataset, &rdata);
1524 result = dns_dnssec_keyfromrdata(gorigin, &rdata, mctx,
1526 if (result != ISC_R_SUCCESS)
1528 if (!dst_key_iszonekey(pubkey)) {
1529 dst_key_free(&pubkey);
1533 key = newkeystruct(pubkey, ISC_FALSE);
1534 ISC_LIST_APPEND(keylist, key, link);
1536 result = dns_rdataset_next(&rdataset);
1538 dns_rdataset_disassociate(&rdataset);
1539 dns_db_detachnode(db, &node);
1540 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
1544 warnifallksk(dns_db_t *db) {
1545 dns_dbversion_t *currentversion = NULL;
1546 dns_dbnode_t *node = NULL;
1547 dns_rdataset_t rdataset;
1548 dns_rdata_t rdata = DNS_RDATA_INIT;
1549 isc_result_t result;
1550 dns_rdata_key_t key;
1551 isc_boolean_t have_non_ksk = ISC_FALSE;
1553 dns_db_currentversion(db, ¤tversion);
1555 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
1556 if (result != ISC_R_SUCCESS)
1557 fatal("failed to find the zone's origin: %s",
1558 isc_result_totext(result));
1560 dns_rdataset_init(&rdataset);
1561 result = dns_db_findrdataset(db, node, currentversion,
1562 dns_rdatatype_dnskey, 0, 0, &rdataset, NULL);
1563 if (result != ISC_R_SUCCESS)
1564 fatal("failed to find keys at the zone apex: %s",
1565 isc_result_totext(result));
1566 result = dns_rdataset_first(&rdataset);
1567 check_result(result, "dns_rdataset_first");
1568 while (result == ISC_R_SUCCESS) {
1569 dns_rdata_reset(&rdata);
1570 dns_rdataset_current(&rdataset, &rdata);
1571 result = dns_rdata_tostruct(&rdata, &key, NULL);
1572 check_result(result, "dns_rdata_tostruct");
1573 if ((key.flags & DNS_KEYFLAG_KSK) == 0) {
1574 have_non_ksk = ISC_TRUE;
1575 result = ISC_R_NOMORE;
1577 result = dns_rdataset_next(&rdataset);
1579 dns_rdataset_disassociate(&rdataset);
1580 dns_db_detachnode(db, &node);
1581 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
1582 if (!have_non_ksk && !ignoreksk)
1583 fprintf(stderr, "%s: warning: No non-KSK dnskey found. "
1584 "Supply non-KSK dnskey or use '-z'.\n",
1589 writeset(const char *prefix, dns_rdatatype_t type) {
1591 char namestr[DNS_NAME_FORMATSIZE];
1592 dns_db_t *db = NULL;
1593 dns_dbversion_t *version = NULL;
1595 dns_difftuple_t *tuple = NULL;
1596 dns_fixedname_t fixed;
1598 dns_rdata_t rdata, ds;
1599 isc_boolean_t have_ksk = ISC_FALSE;
1600 isc_boolean_t have_non_ksk = ISC_FALSE;
1602 isc_buffer_t namebuf;
1604 isc_result_t result;
1606 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
1607 unsigned char keybuf[DST_KEY_MAXSIZE];
1608 unsigned int filenamelen;
1609 const dns_master_style_t *style =
1610 (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
1612 isc_buffer_init(&namebuf, namestr, sizeof(namestr));
1613 result = dns_name_tofilenametext(gorigin, ISC_FALSE, &namebuf);
1614 check_result(result, "dns_name_tofilenametext");
1615 isc_buffer_putuint8(&namebuf, 0);
1616 filenamelen = strlen(prefix) + strlen(namestr);
1617 if (directory != NULL)
1618 filenamelen += strlen(directory) + 1;
1619 filename = isc_mem_get(mctx, filenamelen + 1);
1620 if (filename == NULL)
1621 fatal("out of memory");
1622 if (directory != NULL)
1623 sprintf(filename, "%s/", directory);
1626 strcat(filename, prefix);
1627 strcat(filename, namestr);
1629 dns_diff_init(mctx, &diff);
1631 for (key = ISC_LIST_HEAD(keylist);
1633 key = ISC_LIST_NEXT(key, link))
1635 have_non_ksk = ISC_TRUE;
1639 for (key = ISC_LIST_HEAD(keylist);
1641 key = ISC_LIST_NEXT(key, link))
1643 have_ksk = ISC_TRUE;
1647 if (type == dns_rdatatype_dlv) {
1649 unsigned int labels;
1651 dns_name_init(&tname, NULL);
1652 dns_fixedname_init(&fixed);
1653 name = dns_fixedname_name(&fixed);
1654 labels = dns_name_countlabels(gorigin);
1655 dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
1656 result = dns_name_concatenate(&tname, dlv, name, NULL);
1657 check_result(result, "dns_name_concatenate");
1661 for (key = ISC_LIST_HEAD(keylist);
1663 key = ISC_LIST_NEXT(key, link))
1665 if (have_ksk && have_non_ksk && !key->isksk)
1667 dns_rdata_init(&rdata);
1668 dns_rdata_init(&ds);
1669 isc_buffer_init(&b, keybuf, sizeof(keybuf));
1670 result = dst_key_todns(key->key, &b);
1671 check_result(result, "dst_key_todns");
1672 isc_buffer_usedregion(&b, &r);
1673 dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
1674 if (type != dns_rdatatype_dnskey) {
1675 result = dns_ds_buildrdata(gorigin, &rdata,
1678 check_result(result, "dns_ds_buildrdata");
1679 if (type == dns_rdatatype_dlv)
1680 ds.type = dns_rdatatype_dlv;
1681 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
1682 name, 0, &ds, &tuple);
1683 check_result(result, "dns_difftuple_create");
1684 dns_diff_append(&diff, &tuple);
1686 dns_rdata_reset(&ds);
1687 result = dns_ds_buildrdata(gorigin, &rdata,
1688 DNS_DSDIGEST_SHA256,
1690 check_result(result, "dns_ds_buildrdata");
1691 if (type == dns_rdatatype_dlv)
1692 ds.type = dns_rdatatype_dlv;
1693 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
1694 name, 0, &ds, &tuple);
1697 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
1700 check_result(result, "dns_difftuple_create");
1701 dns_diff_append(&diff, &tuple);
1704 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
1705 gclass, 0, NULL, &db);
1706 check_result(result, "dns_db_create");
1708 result = dns_db_newversion(db, &version);
1709 check_result(result, "dns_db_newversion");
1711 result = dns_diff_apply(&diff, db, version);
1712 check_result(result, "dns_diff_apply");
1713 dns_diff_clear(&diff);
1715 result = dns_master_dump(mctx, db, version, style, filename);
1716 check_result(result, "dns_master_dump");
1718 isc_mem_put(mctx, filename, filenamelen + 1);
1720 dns_db_closeversion(db, &version, ISC_FALSE);
1725 print_time(FILE *fp) {
1728 if (outputformat != dns_masterformat_text)
1731 currenttime = time(NULL);
1732 fprintf(fp, "; File written on %s", ctime(¤ttime));
1736 print_version(FILE *fp) {
1737 if (outputformat != dns_masterformat_text)
1740 fprintf(fp, "; dnssec_signzone version " VERSION "\n");
1745 fprintf(stderr, "Usage:\n");
1746 fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
1748 fprintf(stderr, "\n");
1750 fprintf(stderr, "Version: %s\n", VERSION);
1752 fprintf(stderr, "Options: (default value in parenthesis) \n");
1753 fprintf(stderr, "\t-c class (IN)\n");
1754 fprintf(stderr, "\t-d directory\n");
1755 fprintf(stderr, "\t\tdirectory to find keyset files (.)\n");
1756 fprintf(stderr, "\t-g:\t");
1757 fprintf(stderr, "generate DS records from keyset files\n");
1758 fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
1759 fprintf(stderr, "\t\tRRSIG start time - absolute|offset (now - 1 hour)\n");
1760 fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
1761 fprintf(stderr, "\t\tRRSIG end time - absolute|from start|from now "
1762 "(now + 30 days)\n");
1763 fprintf(stderr, "\t-i interval:\n");
1764 fprintf(stderr, "\t\tcycle interval - resign "
1765 "if < interval from end ( (end-start)/4 )\n");
1766 fprintf(stderr, "\t-j jitter:\n");
1767 fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n");
1768 fprintf(stderr, "\t-v debuglevel (0)\n");
1769 fprintf(stderr, "\t-o origin:\n");
1770 fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
1771 fprintf(stderr, "\t-f outfile:\n");
1772 fprintf(stderr, "\t\tfile the signed zone is written in "
1773 "(zonefile + .signed)\n");
1774 fprintf(stderr, "\t-I format:\n");
1775 fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
1776 fprintf(stderr, "\t-O format:\n");
1777 fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
1778 fprintf(stderr, "\t-N format:\n");
1779 fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
1780 fprintf(stderr, "\t-r randomdev:\n");
1781 fprintf(stderr, "\t\ta file containing random data\n");
1782 fprintf(stderr, "\t-a:\t");
1783 fprintf(stderr, "verify generated signatures\n");
1784 fprintf(stderr, "\t-p:\t");
1785 fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
1786 fprintf(stderr, "\t-t:\t");
1787 fprintf(stderr, "print statistics\n");
1788 fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
1789 fprintf(stderr, "\t-k key_signing_key\n");
1790 fprintf(stderr, "\t-l lookasidezone\n");
1791 fprintf(stderr, "\t-z:\t");
1792 fprintf(stderr, "ignore KSK flag in DNSKEYs");
1794 fprintf(stderr, "\n");
1796 fprintf(stderr, "Signing Keys: ");
1797 fprintf(stderr, "(default: all zone keys that have private keys)\n");
1798 fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
1803 removetempfile(void) {
1805 isc_file_remove(tempfile);
1809 print_stats(isc_time_t *timer_start, isc_time_t *timer_finish) {
1810 isc_uint64_t runtime_us; /* Runtime in microseconds */
1811 isc_uint64_t runtime_ms; /* Runtime in milliseconds */
1812 isc_uint64_t sig_ms; /* Signatures per millisecond */
1814 runtime_us = isc_time_microdiff(timer_finish, timer_start);
1816 printf("Signatures generated: %10d\n", nsigned);
1817 printf("Signatures retained: %10d\n", nretained);
1818 printf("Signatures dropped: %10d\n", ndropped);
1819 printf("Signatures successfully verified: %10d\n", nverified);
1820 printf("Signatures unsuccessfully verified: %10d\n", nverifyfailed);
1821 runtime_ms = runtime_us / 1000;
1822 printf("Runtime in seconds: %7u.%03u\n",
1823 (unsigned int) (runtime_ms / 1000),
1824 (unsigned int) (runtime_ms % 1000));
1825 if (runtime_us > 0) {
1826 sig_ms = ((isc_uint64_t)nsigned * 1000000000) / runtime_us;
1827 printf("Signatures per second: %7u.%03u\n",
1828 (unsigned int) sig_ms / 1000,
1829 (unsigned int) sig_ms % 1000);
1834 main(int argc, char *argv[]) {
1836 char *startstr = NULL, *endstr = NULL, *classname = NULL;
1837 char *origin = NULL, *file = NULL, *output = NULL;
1838 char *inputformatstr = NULL, *outputformatstr = NULL;
1839 char *serialformatstr = NULL;
1840 char *dskeyfile[MAXDSKEYS];
1843 isc_time_t timer_start, timer_finish;
1845 isc_result_t result;
1846 isc_log_t *log = NULL;
1847 isc_boolean_t pseudorandom = ISC_FALSE;
1848 unsigned int eflags;
1849 isc_boolean_t free_output = ISC_FALSE;
1851 dns_rdataclass_t rdclass;
1852 isc_task_t **tasks = NULL;
1856 masterstyle = &dns_master_style_explicitttl;
1858 check_result(isc_app_start(), "isc_app_start");
1860 result = isc_mem_create(0, 0, &mctx);
1861 if (result != ISC_R_SUCCESS)
1862 fatal("out of memory");
1864 dns_result_register();
1866 while ((ch = isc_commandline_parse(argc, argv,
1867 "ac:d:e:f:ghi:I:j:k:l:n:N:o:O:pr:s:Stv:z"))
1871 tryverify = ISC_TRUE;
1875 classname = isc_commandline_argument;
1879 directory = isc_commandline_argument;
1883 endstr = isc_commandline_argument;
1887 output = isc_commandline_argument;
1891 generateds = ISC_TRUE;
1901 cycle = strtol(isc_commandline_argument, &endp, 0);
1902 if (*endp != '\0' || cycle < 0)
1903 fatal("cycle period must be numeric and "
1908 inputformatstr = isc_commandline_argument;
1913 jitter = strtol(isc_commandline_argument, &endp, 0);
1914 if (*endp != '\0' || jitter < 0)
1915 fatal("jitter must be numeric and positive");
1919 dns_fixedname_init(&dlv_fixed);
1920 len = strlen(isc_commandline_argument);
1921 isc_buffer_init(&b, isc_commandline_argument, len);
1922 isc_buffer_add(&b, len);
1924 dns_fixedname_init(&dlv_fixed);
1925 dlv = dns_fixedname_name(&dlv_fixed);
1926 result = dns_name_fromtext(dlv, &b, dns_rootname,
1928 check_result(result, "dns_name_fromtext(dlv)");
1932 if (ndskeys == MAXDSKEYS)
1933 fatal("too many key-signing keys specified");
1934 dskeyfile[ndskeys++] = isc_commandline_argument;
1939 ntasks = strtol(isc_commandline_argument, &endp, 0);
1940 if (*endp != '\0' || ntasks > ISC_INT32_MAX)
1941 fatal("number of cpus must be numeric");
1945 serialformatstr = isc_commandline_argument;
1949 origin = isc_commandline_argument;
1953 outputformatstr = isc_commandline_argument;
1957 pseudorandom = ISC_TRUE;
1961 setup_entropy(mctx, isc_commandline_argument, &ectx);
1965 startstr = isc_commandline_argument;
1969 /* This is intentionally undocumented */
1970 /* -S: simple output style */
1971 masterstyle = &dns_master_style_simple;
1975 printstats = ISC_TRUE;
1980 verbose = strtol(isc_commandline_argument, &endp, 0);
1982 fatal("verbose level must be numeric");
1986 ignoreksk = ISC_TRUE;
1992 setup_entropy(mctx, NULL, &ectx);
1993 eflags = ISC_ENTROPY_BLOCKING;
1995 eflags |= ISC_ENTROPY_GOODONLY;
1997 result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
1998 if (result != ISC_R_SUCCESS)
1999 fatal("could not create hash context");
2001 result = dst_lib_init(mctx, ectx, eflags);
2002 if (result != ISC_R_SUCCESS)
2003 fatal("could not initialize dst");
2005 isc_stdtime_get(&now);
2007 if (startstr != NULL)
2008 starttime = strtotime(startstr, now, now);
2010 starttime = now - 3600; /* Allow for some clock skew. */
2013 endtime = strtotime(endstr, now, starttime);
2015 endtime = starttime + (30 * 24 * 60 * 60);
2018 cycle = (endtime - starttime) / 4;
2021 ntasks = isc_os_ncpus();
2022 vbprintf(4, "using %d cpus\n", ntasks);
2024 rdclass = strtoclass(classname);
2026 setup_logging(verbose, mctx, &log);
2028 argc -= isc_commandline_index;
2029 argv += isc_commandline_index;
2042 if (output == NULL) {
2043 free_output = ISC_TRUE;
2044 output = isc_mem_allocate(mctx,
2045 strlen(file) + strlen(".signed") + 1);
2047 fatal("out of memory");
2048 sprintf(output, "%s.signed", file);
2051 if (inputformatstr != NULL) {
2052 if (strcasecmp(inputformatstr, "text") == 0)
2053 inputformat = dns_masterformat_text;
2054 else if (strcasecmp(inputformatstr, "raw") == 0)
2055 inputformat = dns_masterformat_raw;
2057 fatal("unknown file format: %s\n", inputformatstr);
2060 if (outputformatstr != NULL) {
2061 if (strcasecmp(outputformatstr, "text") == 0)
2062 outputformat = dns_masterformat_text;
2063 else if (strcasecmp(outputformatstr, "raw") == 0)
2064 outputformat = dns_masterformat_raw;
2066 fatal("unknown file format: %s\n", outputformatstr);
2069 if (serialformatstr != NULL) {
2070 if (strcasecmp(serialformatstr, "keep") == 0)
2071 serialformat = SOA_SERIAL_KEEP;
2072 else if (strcasecmp(serialformatstr, "increment") == 0 ||
2073 strcasecmp(serialformatstr, "incr") == 0)
2074 serialformat = SOA_SERIAL_INCREMENT;
2075 else if (strcasecmp(serialformatstr, "unixtime") == 0)
2076 serialformat = SOA_SERIAL_UNIXTIME;
2078 fatal("unknown soa serial format: %s\n", serialformatstr);
2081 result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL,
2082 0, 24, 0, 0, 0, 8, mctx);
2083 check_result(result, "dns_master_stylecreate");
2087 TIME_NOW(&timer_start);
2088 loadzone(file, origin, rdclass, &gdb);
2089 gorigin = dns_db_origin(gdb);
2090 gclass = dns_db_class(gdb);
2093 ISC_LIST_INIT(keylist);
2098 for (i = 0; i < argc; i++) {
2099 dst_key_t *newkey = NULL;
2101 result = dst_key_fromnamedfile(argv[i],
2105 if (result != ISC_R_SUCCESS)
2106 fatal("cannot load dnskey %s: %s", argv[i],
2107 isc_result_totext(result));
2109 key = ISC_LIST_HEAD(keylist);
2110 while (key != NULL) {
2111 dst_key_t *dkey = key->key;
2112 if (dst_key_id(dkey) == dst_key_id(newkey) &&
2113 dst_key_alg(dkey) == dst_key_alg(newkey) &&
2114 dns_name_equal(dst_key_name(dkey),
2115 dst_key_name(newkey)))
2117 if (!dst_key_isprivate(dkey))
2118 fatal("cannot sign zone with "
2119 "non-private dnskey %s",
2123 key = ISC_LIST_NEXT(key, link);
2126 key = newkeystruct(newkey, ISC_TRUE);
2127 ISC_LIST_APPEND(keylist, key, link);
2129 dst_key_free(&newkey);
2132 loadzonepubkeys(gdb);
2135 for (i = 0; i < ndskeys; i++) {
2136 dst_key_t *newkey = NULL;
2138 result = dst_key_fromnamedfile(dskeyfile[i],
2142 if (result != ISC_R_SUCCESS)
2143 fatal("cannot load dnskey %s: %s", dskeyfile[i],
2144 isc_result_totext(result));
2146 key = ISC_LIST_HEAD(keylist);
2147 while (key != NULL) {
2148 dst_key_t *dkey = key->key;
2149 if (dst_key_id(dkey) == dst_key_id(newkey) &&
2150 dst_key_alg(dkey) == dst_key_alg(newkey) &&
2151 dns_name_equal(dst_key_name(dkey),
2152 dst_key_name(newkey)))
2154 /* Override key flags. */
2155 key->issigningkey = ISC_TRUE;
2156 key->isksk = ISC_TRUE;
2157 key->isdsk = ISC_FALSE;
2158 dst_key_free(&dkey);
2162 key = ISC_LIST_NEXT(key, link);
2165 /* Override dnskey flags. */
2166 key = newkeystruct(newkey, ISC_TRUE);
2167 key->isksk = ISC_TRUE;
2168 key->isdsk = ISC_FALSE;
2169 ISC_LIST_APPEND(keylist, key, link);
2173 if (ISC_LIST_EMPTY(keylist)) {
2174 fprintf(stderr, "%s: warning: No keys specified or found\n",
2182 result = dns_db_newversion(gdb, &gversion);
2183 check_result(result, "dns_db_newversion()");
2185 switch (serialformat) {
2186 case SOA_SERIAL_INCREMENT:
2189 case SOA_SERIAL_UNIXTIME:
2192 case SOA_SERIAL_KEEP:
2201 writeset("keyset-", dns_rdatatype_dnskey);
2202 writeset("dsset-", dns_rdatatype_ds);
2204 writeset("dlvset-", dns_rdatatype_dlv);
2208 tempfilelen = strlen(output) + 20;
2209 tempfile = isc_mem_get(mctx, tempfilelen);
2210 if (tempfile == NULL)
2211 fatal("out of memory");
2213 result = isc_file_mktemplate(output, tempfile, tempfilelen);
2214 check_result(result, "isc_file_mktemplate");
2217 result = isc_file_openunique(tempfile, &fp);
2218 if (result != ISC_R_SUCCESS)
2219 fatal("failed to open temporary output file: %s",
2220 isc_result_totext(result));
2221 removefile = ISC_TRUE;
2222 setfatalcallback(&removetempfile);
2227 result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
2228 if (result != ISC_R_SUCCESS)
2229 fatal("failed to create task manager: %s",
2230 isc_result_totext(result));
2233 result = isc_task_create(taskmgr, 0, &master);
2234 if (result != ISC_R_SUCCESS)
2235 fatal("failed to create task: %s", isc_result_totext(result));
2237 tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
2239 fatal("out of memory");
2240 for (i = 0; i < (int)ntasks; i++) {
2242 result = isc_task_create(taskmgr, 0, &tasks[i]);
2243 if (result != ISC_R_SUCCESS)
2244 fatal("failed to create task: %s",
2245 isc_result_totext(result));
2248 RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS);
2250 RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS);
2256 * There is more work to do. Spread it out over multiple
2257 * processors if possible.
2259 for (i = 0; i < (int)ntasks; i++) {
2260 result = isc_app_onrun(mctx, master, startworker,
2262 if (result != ISC_R_SUCCESS)
2263 fatal("failed to start task: %s",
2264 isc_result_totext(result));
2266 (void)isc_app_run();
2268 fatal("process aborted by user");
2270 isc_task_detach(&master);
2271 shuttingdown = ISC_TRUE;
2272 for (i = 0; i < (int)ntasks; i++)
2273 isc_task_detach(&tasks[i]);
2274 isc_taskmgr_destroy(&taskmgr);
2275 isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
2278 if (outputformat != dns_masterformat_text) {
2279 result = dns_master_dumptostream2(mctx, gdb, gversion,
2280 masterstyle, outputformat,
2282 check_result(result, "dns_master_dumptostream2");
2285 result = isc_stdio_close(fp);
2286 check_result(result, "isc_stdio_close");
2287 removefile = ISC_FALSE;
2289 result = isc_file_rename(tempfile, output);
2290 if (result != ISC_R_SUCCESS)
2291 fatal("failed to rename temp file to %s: %s\n",
2292 output, isc_result_totext(result));
2294 DESTROYLOCK(&namelock);
2296 DESTROYLOCK(&statslock);
2298 printf("%s\n", output);
2300 dns_db_closeversion(gdb, &gversion, ISC_FALSE);
2301 dns_db_detach(&gdb);
2303 while (!ISC_LIST_EMPTY(keylist)) {
2304 key = ISC_LIST_HEAD(keylist);
2305 ISC_LIST_UNLINK(keylist, key, link);
2306 dst_key_free(&key->key);
2307 isc_mem_put(mctx, key, sizeof(signer_key_t));
2310 isc_mem_put(mctx, tempfile, tempfilelen);
2313 isc_mem_free(mctx, output);
2315 dns_master_styledestroy(&dsstyle, mctx);
2317 cleanup_logging(&log);
2320 cleanup_entropy(&ectx);
2323 isc_mem_stats(mctx, stdout);
2324 isc_mem_destroy(&mctx);
2326 (void) isc_app_finish();
2329 TIME_NOW(&timer_finish);
2330 print_stats(&timer_start, &timer_finish);