2 * Portions Copyright (C) 2004-2006 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 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.139.2.2.4.23 2006/01/04 23:50:19 marka Exp $ */
27 #include <isc/commandline.h>
28 #include <isc/entropy.h>
29 #include <isc/event.h>
33 #include <isc/mutex.h>
35 #include <isc/print.h>
36 #include <isc/serial.h>
37 #include <isc/stdio.h>
38 #include <isc/string.h>
44 #include <dns/dbiterator.h>
46 #include <dns/dnssec.h>
48 #include <dns/fixedname.h>
49 #include <dns/keyvalues.h>
51 #include <dns/master.h>
52 #include <dns/masterdump.h>
54 #include <dns/rdata.h>
55 #include <dns/rdataset.h>
56 #include <dns/rdataclass.h>
57 #include <dns/rdatasetiter.h>
58 #include <dns/rdatastruct.h>
59 #include <dns/rdatatype.h>
60 #include <dns/result.h>
65 #include "dnssectool.h"
67 const char *program = "dnssec-signzone";
73 typedef struct signer_key_struct signer_key_t;
75 struct signer_key_struct {
77 isc_boolean_t issigningkey;
80 unsigned int position;
81 ISC_LINK(signer_key_t) link;
84 #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
85 #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
86 #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
88 typedef struct signer_event sevent_t;
90 ISC_EVENT_COMMON(sevent_t);
91 dns_fixedname_t *fname;
95 static ISC_LIST(signer_key_t) keylist;
96 static unsigned int keycount = 0;
97 static isc_stdtime_t starttime = 0, endtime = 0, now;
98 static int cycle = -1;
99 static isc_boolean_t tryverify = ISC_FALSE;
100 static isc_boolean_t printstats = ISC_FALSE;
101 static isc_mem_t *mctx = NULL;
102 static isc_entropy_t *ectx = NULL;
103 static dns_ttl_t zonettl;
105 static char *tempfile = NULL;
106 static const dns_master_style_t *masterstyle;
107 static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
108 static unsigned int nverified = 0, nverifyfailed = 0;
109 static const char *directory;
110 static isc_mutex_t namelock, statslock;
111 static isc_taskmgr_t *taskmgr = NULL;
112 static dns_db_t *gdb; /* The database */
113 static dns_dbversion_t *gversion; /* The database version */
114 static dns_dbiterator_t *gdbiter; /* The database iterator */
115 static dns_rdataclass_t gclass; /* The class */
116 static dns_name_t *gorigin; /* The database origin */
117 static isc_task_t *master = NULL;
118 static unsigned int ntasks = 0;
119 static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE;
120 static unsigned int assigned = 0, completed = 0;
121 static isc_boolean_t nokeys = ISC_FALSE;
122 static isc_boolean_t removefile = ISC_FALSE;
123 static isc_boolean_t generateds = ISC_FALSE;
124 static isc_boolean_t ignoreksk = ISC_FALSE;
125 static dns_name_t *dlv = NULL;
126 static dns_fixedname_t dlv_fixed;
127 static dns_master_style_t *dsstyle = NULL;
129 #define INCSTAT(counter) \
133 UNLOCK(&statslock); \
137 sign(isc_task_t *task, isc_event_t *event);
141 set_bit(unsigned char *array, unsigned int index, unsigned int bit) {
142 unsigned int shift, mask;
144 shift = 7 - (index % 8);
148 array[index / 8] |= mask;
150 array[index / 8] &= (~mask & 0xFF);
154 dumpnode(dns_name_t *name, dns_dbnode_t *node) {
157 result = dns_master_dumpnodetostream(mctx, gdb, gversion, node, name,
159 check_result(result, "dns_master_dumpnodetostream");
163 dumpdb(dns_db_t *db) {
164 dns_dbiterator_t *dbiter = NULL;
166 dns_fixedname_t fname;
171 result = dns_db_createiterator(db, ISC_FALSE, &dbiter);
172 check_result(result, "dns_db_createiterator()");
174 dns_fixedname_init(&fname);
175 name = dns_fixedname_name(&fname);
178 for (result = dns_dbiterator_first(dbiter);
179 result == ISC_R_SUCCESS;
180 result = dns_dbiterator_next(dbiter))
182 result = dns_dbiterator_current(dbiter, &node, name);
183 check_result(result, "dns_dbiterator_current()");
184 dumpnode(name, node);
185 dns_db_detachnode(db, &node);
187 if (result != ISC_R_NOMORE)
188 fatal("iterating database: %s", isc_result_totext(result));
190 dns_dbiterator_destroy(&dbiter);
193 static signer_key_t *
194 newkeystruct(dst_key_t *dstkey, isc_boolean_t signwithkey) {
197 key = isc_mem_get(mctx, sizeof(signer_key_t));
199 fatal("out of memory");
201 if ((dst_key_flags(dstkey) & DNS_KEYFLAG_KSK) != 0) {
202 key->issigningkey = signwithkey;
203 key->isksk = ISC_TRUE;
204 key->isdsk = ISC_FALSE;
206 key->issigningkey = signwithkey;
207 key->isksk = ISC_FALSE;
208 key->isdsk = ISC_TRUE;
210 key->position = keycount++;
211 ISC_LINK_INIT(key, link);
216 signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdata_t *rdata,
217 dst_key_t *key, isc_buffer_t *b)
221 result = dns_dnssec_sign(name, rdataset, key, &starttime, &endtime,
223 isc_entropy_stopcallbacksources(ectx);
224 if (result != ISC_R_SUCCESS) {
225 char keystr[KEY_FORMATSIZE];
226 key_format(key, keystr, sizeof(keystr));
227 fatal("dnskey '%s' failed to sign data: %s",
228 keystr, isc_result_totext(result));
233 result = dns_dnssec_verify(name, rdataset, key,
234 ISC_TRUE, mctx, rdata);
235 if (result == ISC_R_SUCCESS) {
236 vbprintf(3, "\tsignature verified\n");
239 vbprintf(3, "\tsignature failed to verify\n");
240 INCSTAT(nverifyfailed);
245 static inline isc_boolean_t
246 issigningkey(signer_key_t *key) {
247 return (key->issigningkey);
250 static inline isc_boolean_t
251 iszonekey(signer_key_t *key) {
252 return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) &&
253 dst_key_iszonekey(key->key)));
257 * Finds the key that generated a RRSIG, if possible. First look at the keys
258 * that we've loaded already, and then see if there's a key on disk.
260 static signer_key_t *
261 keythatsigned(dns_rdata_rrsig_t *rrsig) {
263 dst_key_t *pubkey = NULL, *privkey = NULL;
266 key = ISC_LIST_HEAD(keylist);
267 while (key != NULL) {
268 if (rrsig->keyid == dst_key_id(key->key) &&
269 rrsig->algorithm == dst_key_alg(key->key) &&
270 dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
272 key = ISC_LIST_NEXT(key, link);
275 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
276 rrsig->algorithm, DST_TYPE_PUBLIC,
277 NULL, mctx, &pubkey);
278 if (result != ISC_R_SUCCESS)
281 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
283 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
284 NULL, mctx, &privkey);
285 if (result == ISC_R_SUCCESS) {
286 dst_key_free(&pubkey);
287 key = newkeystruct(privkey, ISC_FALSE);
289 key = newkeystruct(pubkey, ISC_FALSE);
290 ISC_LIST_APPEND(keylist, key, link);
295 * Check to see if we expect to find a key at this name. If we see a RRSIG
296 * and can't find the signing key that we expect to find, we drop the rrsig.
297 * I'm not sure if this is completely correct, but it seems to work.
300 expecttofindkey(dns_name_t *name) {
301 unsigned int options = DNS_DBFIND_NOWILD;
302 dns_fixedname_t fname;
304 char namestr[DNS_NAME_FORMATSIZE];
306 dns_fixedname_init(&fname);
307 result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
308 0, NULL, dns_fixedname_name(&fname), NULL, NULL);
314 case DNS_R_DELEGATION:
319 dns_name_format(name, namestr, sizeof(namestr));
320 fatal("failure looking for '%s DNSKEY' in database: %s",
321 namestr, isc_result_totext(result));
322 return (ISC_FALSE); /* removes a warning */
325 static inline isc_boolean_t
326 setverifies(dns_name_t *name, dns_rdataset_t *set, signer_key_t *key,
330 result = dns_dnssec_verify(name, set, key->key, ISC_FALSE, mctx, rrsig);
331 if (result == ISC_R_SUCCESS) {
335 INCSTAT(nverifyfailed);
341 * Signs a set. Goes through contortions to decide if each RRSIG should
342 * be dropped or retained, and then determines if any new SIGs need to
346 signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
349 dns_rdataset_t sigset;
350 dns_rdata_t sigrdata = DNS_RDATA_INIT;
351 dns_rdata_rrsig_t rrsig;
354 isc_boolean_t nosigs = ISC_FALSE;
355 isc_boolean_t *wassignedby, *nowsignedby;
357 dns_difftuple_t *tuple;
360 char namestr[DNS_NAME_FORMATSIZE];
361 char typestr[TYPE_FORMATSIZE];
362 char sigstr[SIG_FORMATSIZE];
364 dns_name_format(name, namestr, sizeof(namestr));
365 type_format(set->type, typestr, sizeof(typestr));
367 ttl = ISC_MIN(set->ttl, endtime - starttime);
369 dns_rdataset_init(&sigset);
370 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
371 set->type, 0, &sigset, NULL);
372 if (result == ISC_R_NOTFOUND) {
373 result = ISC_R_SUCCESS;
376 if (result != ISC_R_SUCCESS)
377 fatal("failed while looking for '%s RRSIG %s': %s",
378 namestr, typestr, isc_result_totext(result));
380 vbprintf(1, "%s/%s:\n", namestr, typestr);
382 arraysize = keycount;
384 arraysize += dns_rdataset_count(&sigset);
385 wassignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
386 nowsignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
387 if (wassignedby == NULL || nowsignedby == NULL)
388 fatal("out of memory");
390 for (i = 0; i < arraysize; i++)
391 wassignedby[i] = nowsignedby[i] = ISC_FALSE;
394 result = ISC_R_NOMORE;
396 result = dns_rdataset_first(&sigset);
398 while (result == ISC_R_SUCCESS) {
399 isc_boolean_t expired, future;
400 isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE;
402 dns_rdataset_current(&sigset, &sigrdata);
404 result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
405 check_result(result, "dns_rdata_tostruct");
407 future = isc_serial_lt(now, rrsig.timesigned);
409 key = keythatsigned(&rrsig);
410 sig_format(&rrsig, sigstr, sizeof(sigstr));
411 if (key != NULL && issigningkey(key))
412 expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
414 expired = isc_serial_gt(now, rrsig.timeexpire);
416 if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
417 /* rrsig is dropped and not replaced */
418 vbprintf(2, "\trrsig by %s dropped - "
419 "invalid validity period\n",
421 } else if (key == NULL && !future &&
422 expecttofindkey(&rrsig.signer))
424 /* rrsig is dropped and not replaced */
425 vbprintf(2, "\trrsig by %s dropped - "
426 "private dnskey not found\n",
428 } else if (key == NULL || future) {
429 vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
430 expired ? "retained" : "dropped", sigstr);
433 } else if (issigningkey(key)) {
434 if (!expired && setverifies(name, set, key, &sigrdata))
436 vbprintf(2, "\trrsig by %s retained\n", sigstr);
438 wassignedby[key->position] = ISC_TRUE;
439 nowsignedby[key->position] = ISC_TRUE;
441 vbprintf(2, "\trrsig by %s dropped - %s\n",
443 expired ? "expired" :
445 wassignedby[key->position] = ISC_TRUE;
448 } else if (iszonekey(key)) {
449 if (!expired && setverifies(name, set, key, &sigrdata))
451 vbprintf(2, "\trrsig by %s retained\n", sigstr);
453 wassignedby[key->position] = ISC_TRUE;
454 nowsignedby[key->position] = ISC_TRUE;
456 vbprintf(2, "\trrsig by %s dropped - %s\n",
458 expired ? "expired" :
460 wassignedby[key->position] = ISC_TRUE;
462 } else if (!expired) {
463 vbprintf(2, "\trrsig by %s retained\n", sigstr);
466 vbprintf(2, "\trrsig by %s expired\n", sigstr);
470 nowsignedby[key->position] = ISC_TRUE;
472 if (sigset.ttl != ttl) {
473 vbprintf(2, "\tfixing ttl %s\n", sigstr);
475 result = dns_difftuple_create(mctx,
480 check_result(result, "dns_difftuple_create");
481 dns_diff_append(del, &tuple);
482 result = dns_difftuple_create(mctx,
487 check_result(result, "dns_difftuple_create");
488 dns_diff_append(add, &tuple);
492 result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL,
495 check_result(result, "dns_difftuple_create");
496 dns_diff_append(del, &tuple);
502 dns_rdata_t trdata = DNS_RDATA_INIT;
503 unsigned char array[BUFSIZE];
504 char keystr[KEY_FORMATSIZE];
508 key_format(key->key, keystr, sizeof(keystr));
509 vbprintf(1, "\tresigning with dnskey %s\n", keystr);
510 isc_buffer_init(&b, array, sizeof(array));
511 signwithkey(name, set, &trdata, key->key, &b);
512 nowsignedby[key->position] = ISC_TRUE;
514 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
517 check_result(result, "dns_difftuple_create");
518 dns_diff_append(add, &tuple);
521 dns_rdata_reset(&sigrdata);
522 dns_rdata_freestruct(&rrsig);
523 result = dns_rdataset_next(&sigset);
525 if (result == ISC_R_NOMORE)
526 result = ISC_R_SUCCESS;
528 check_result(result, "dns_rdataset_first/next");
529 if (dns_rdataset_isassociated(&sigset))
530 dns_rdataset_disassociate(&sigset);
532 for (key = ISC_LIST_HEAD(keylist);
534 key = ISC_LIST_NEXT(key, link))
538 unsigned char array[BUFSIZE];
539 char keystr[KEY_FORMATSIZE];
541 if (nowsignedby[key->position])
544 if (!key->issigningkey)
546 if (!(ignoreksk || key->isdsk ||
548 set->type == dns_rdatatype_dnskey &&
549 dns_name_equal(name, gorigin))))
552 key_format(key->key, keystr, sizeof(keystr));
553 vbprintf(1, "\tsigning with dnskey %s\n", keystr);
554 dns_rdata_init(&trdata);
555 isc_buffer_init(&b, array, sizeof(array));
556 signwithkey(name, set, &trdata, key->key, &b);
558 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
559 ttl, &trdata, &tuple);
560 check_result(result, "dns_difftuple_create");
561 dns_diff_append(add, &tuple);
564 isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t));
565 isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t));
569 opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
576 isc_buffer_init(&b, filename, sizeof(filename));
577 if (directory != NULL) {
578 isc_buffer_putstr(&b, directory);
579 if (directory[strlen(directory) - 1] != '/')
580 isc_buffer_putstr(&b, "/");
582 isc_buffer_putstr(&b, prefix);
583 result = dns_name_tofilenametext(name, ISC_FALSE, &b);
584 check_result(result, "dns_name_tofilenametext()");
585 if (isc_buffer_availablelength(&b) == 0) {
586 char namestr[DNS_NAME_FORMATSIZE];
587 dns_name_format(name, namestr, sizeof(namestr));
588 fatal("name '%s' is too long", namestr);
590 isc_buffer_putuint8(&b, 0);
592 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
593 rdclass, 0, NULL, dbp);
594 check_result(result, "dns_db_create()");
596 result = dns_db_load(*dbp, filename);
597 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
602 * Loads the key set for a child zone, if there is one, and builds DS records.
605 loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
607 dns_dbversion_t *ver = NULL;
608 dns_dbnode_t *node = NULL;
610 dns_rdataset_t keyset;
612 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
614 dns_difftuple_t *tuple = NULL;
616 opendb("keyset-", name, gclass, &db);
618 return (ISC_R_NOTFOUND);
620 result = dns_db_findnode(db, name, ISC_FALSE, &node);
621 if (result != ISC_R_SUCCESS) {
623 return (DNS_R_BADDB);
625 dns_rdataset_init(&keyset);
626 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
628 if (result != ISC_R_SUCCESS) {
629 dns_db_detachnode(db, &node);
634 vbprintf(2, "found DNSKEY records\n");
636 result = dns_db_newversion(db, &ver);
637 check_result(result, "dns_db_newversion");
639 dns_diff_init(mctx, &diff);
641 for (result = dns_rdataset_first(&keyset);
642 result == ISC_R_SUCCESS;
643 result = dns_rdataset_next(&keyset))
645 dns_rdata_init(&key);
647 dns_rdataset_current(&keyset, &key);
648 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
650 check_result(result, "dns_ds_buildrdata");
652 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
654 check_result(result, "dns_difftuple_create");
655 dns_diff_append(&diff, &tuple);
657 result = dns_diff_apply(&diff, db, ver);
658 check_result(result, "dns_diff_apply");
659 dns_diff_clear(&diff);
661 dns_db_closeversion(db, &ver, ISC_TRUE);
663 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
665 check_result(result, "dns_db_findrdataset");
667 dns_rdataset_disassociate(&keyset);
668 dns_db_detachnode(db, &node);
674 nsec_setbit(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdatatype_t type,
678 dns_rdata_t rdata = DNS_RDATA_INIT;
679 dns_rdata_nsec_t nsec;
681 unsigned char bitmap[8192 + 512];
682 unsigned char nsecdata[8192 + 512 + DNS_NAME_MAXWIRE];
683 isc_boolean_t answer = ISC_FALSE;
684 unsigned int i, len, window;
687 result = dns_rdataset_first(rdataset);
688 check_result(result, "dns_rdataset_first()");
689 dns_rdataset_current(rdataset, &rdata);
690 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
691 check_result(result, "dns_rdata_tostruct");
693 INSIST(nsec.len <= sizeof(bitmap));
697 memset(bitmap, 0, sizeof(bitmap));
698 for (i = 0; i < nsec.len; i += len) {
699 INSIST(i + 2 <= nsec.len);
700 window = nsec.typebits[i];
701 len = nsec.typebits[i+1];
703 INSIST(len > 0 && len <= 32);
704 INSIST(i + len <= nsec.len);
705 memmove(&bitmap[window * 32 + 512], &nsec.typebits[i], len);
707 set_bit(bitmap + 512, type, val);
708 for (window = 0; window < 256; window++) {
709 for (octet = 31; octet >= 0; octet--)
710 if (bitmap[window * 32 + 512 + octet] != 0)
714 bitmap[newlen] = window;
715 bitmap[newlen + 1] = octet + 1;
720 memmove(&bitmap[newlen], &bitmap[window * 32 + 512], octet + 1);
723 if (newlen != nsec.len ||
724 memcmp(nsec.typebits, bitmap, newlen) != 0) {
725 dns_rdata_t newrdata = DNS_RDATA_INIT;
728 dns_difftuple_t *tuple = NULL;
730 dns_diff_init(mctx, &diff);
731 result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL, name,
732 rdataset->ttl, &rdata, &tuple);
733 check_result(result, "dns_difftuple_create");
734 dns_diff_append(&diff, &tuple);
736 nsec.typebits = bitmap;
738 isc_buffer_init(&b, nsecdata, sizeof(nsecdata));
739 result = dns_rdata_fromstruct(&newrdata, rdata.rdclass,
740 dns_rdatatype_nsec, &nsec,
742 check_result(result, "dns_rdata_fromstruct");
744 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
747 check_result(result, "dns_difftuple_create");
748 dns_diff_append(&diff, &tuple);
749 result = dns_diff_apply(&diff, gdb, gversion);
750 check_result(result, "dns_difftuple_apply");
751 dns_diff_clear(&diff);
754 dns_rdata_freestruct(&nsec);
759 delegation(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) {
760 dns_rdataset_t nsset;
763 if (dns_name_equal(name, gorigin))
766 dns_rdataset_init(&nsset);
767 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ns,
769 if (dns_rdataset_isassociated(&nsset)) {
772 dns_rdataset_disassociate(&nsset);
775 return (ISC_TF(result == ISC_R_SUCCESS));
779 * Signs all records at a name. This mostly just signs each set individually,
780 * but also adds the RRSIG bit to any NSECs generated earlier, deals with
781 * parent/child KEY signatures, and handles other exceptional cases.
784 signname(dns_dbnode_t *node, dns_name_t *name) {
786 dns_rdataset_t rdataset;
787 dns_rdatasetiter_t *rdsiter;
788 isc_boolean_t isdelegation = ISC_FALSE;
789 isc_boolean_t hasds = ISC_FALSE;
790 isc_boolean_t changed = ISC_FALSE;
792 char namestr[DNS_NAME_FORMATSIZE];
793 isc_uint32_t nsttl = 0;
795 dns_name_format(name, namestr, sizeof(namestr));
798 * Determine if this is a delegation point.
800 if (delegation(name, node, &nsttl))
801 isdelegation = ISC_TRUE;
804 * If this is a delegation point, look for a DS set.
807 dns_rdataset_t dsset;
808 dns_rdataset_t sigdsset;
810 dns_rdataset_init(&dsset);
811 dns_rdataset_init(&sigdsset);
812 result = dns_db_findrdataset(gdb, node, gversion,
814 0, 0, &dsset, &sigdsset);
815 if (result == ISC_R_SUCCESS) {
816 dns_rdataset_disassociate(&dsset);
818 result = dns_db_deleterdataset(gdb, node,
822 check_result(result, "dns_db_deleterdataset");
827 result = loadds(name, nsttl, &dsset);
828 if (result == ISC_R_SUCCESS) {
829 result = dns_db_addrdataset(gdb, node,
832 check_result(result, "dns_db_addrdataset");
834 dns_rdataset_disassociate(&dsset);
835 if (dns_rdataset_isassociated(&sigdsset))
836 dns_rdataset_disassociate(&sigdsset);
837 } else if (dns_rdataset_isassociated(&sigdsset)) {
838 result = dns_db_deleterdataset(gdb, node,
842 check_result(result, "dns_db_deleterdataset");
843 dns_rdataset_disassociate(&sigdsset);
845 } else if (dns_rdataset_isassociated(&sigdsset))
846 dns_rdataset_disassociate(&sigdsset);
850 * Make sure that NSEC bits are appropriately set.
852 dns_rdataset_init(&rdataset);
853 RUNTIME_CHECK(dns_db_findrdataset(gdb, node, gversion,
854 dns_rdatatype_nsec, 0, 0, &rdataset,
855 NULL) == ISC_R_SUCCESS);
857 changed = nsec_setbit(name, &rdataset, dns_rdatatype_rrsig, 1);
859 dns_rdataset_disassociate(&rdataset);
860 RUNTIME_CHECK(dns_db_findrdataset(gdb, node, gversion,
861 dns_rdatatype_nsec, 0, 0,
863 NULL) == ISC_R_SUCCESS);
866 (void)nsec_setbit(name, &rdataset, dns_rdatatype_ds, 1);
868 (void)nsec_setbit(name, &rdataset, dns_rdatatype_ds, 0);
869 dns_rdataset_disassociate(&rdataset);
872 * Now iterate through the rdatasets.
874 dns_diff_init(mctx, &del);
875 dns_diff_init(mctx, &add);
877 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
878 check_result(result, "dns_db_allrdatasets()");
879 result = dns_rdatasetiter_first(rdsiter);
880 while (result == ISC_R_SUCCESS) {
881 dns_rdatasetiter_current(rdsiter, &rdataset);
883 /* If this is a RRSIG set, skip it. */
884 if (rdataset.type == dns_rdatatype_rrsig)
888 * If this name is a delegation point, skip all records
889 * except NSEC and DS sets. Otherwise check that there
893 if (rdataset.type != dns_rdatatype_nsec &&
894 rdataset.type != dns_rdatatype_ds)
896 } else if (rdataset.type == dns_rdatatype_ds) {
897 char namebuf[DNS_NAME_FORMATSIZE];
898 dns_name_format(name, namebuf, sizeof(namebuf));
899 fatal("'%s': found DS RRset without NS RRset\n",
903 signset(&del, &add, node, name, &rdataset);
906 dns_rdataset_disassociate(&rdataset);
907 result = dns_rdatasetiter_next(rdsiter);
909 if (result != ISC_R_NOMORE)
910 fatal("rdataset iteration for name '%s' failed: %s",
911 namestr, isc_result_totext(result));
913 dns_rdatasetiter_destroy(&rdsiter);
915 result = dns_diff_applysilently(&del, gdb, gversion);
916 if (result != ISC_R_SUCCESS)
917 fatal("failed to delete SIGs at node '%s': %s",
918 namestr, isc_result_totext(result));
920 result = dns_diff_applysilently(&add, gdb, gversion);
921 if (result != ISC_R_SUCCESS)
922 fatal("failed to add SIGs at node '%s': %s",
923 namestr, isc_result_totext(result));
925 dns_diff_clear(&del);
926 dns_diff_clear(&add);
929 static inline isc_boolean_t
930 active_node(dns_dbnode_t *node) {
931 dns_rdatasetiter_t *rdsiter = NULL;
932 dns_rdatasetiter_t *rdsiter2 = NULL;
933 isc_boolean_t active = ISC_FALSE;
935 dns_rdataset_t rdataset;
936 dns_rdatatype_t type;
937 dns_rdatatype_t covers;
940 dns_rdataset_init(&rdataset);
941 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
942 check_result(result, "dns_db_allrdatasets()");
943 result = dns_rdatasetiter_first(rdsiter);
944 while (result == ISC_R_SUCCESS) {
945 dns_rdatasetiter_current(rdsiter, &rdataset);
946 if (rdataset.type != dns_rdatatype_nsec &&
947 rdataset.type != dns_rdatatype_rrsig)
949 dns_rdataset_disassociate(&rdataset);
951 result = dns_rdatasetiter_next(rdsiter);
953 result = ISC_R_NOMORE;
955 if (result != ISC_R_NOMORE)
956 fatal("rdataset iteration failed: %s",
957 isc_result_totext(result));
961 * The node is empty of everything but NSEC / RRSIG records.
963 for (result = dns_rdatasetiter_first(rdsiter);
964 result == ISC_R_SUCCESS;
965 result = dns_rdatasetiter_next(rdsiter)) {
966 dns_rdatasetiter_current(rdsiter, &rdataset);
967 result = dns_db_deleterdataset(gdb, node, gversion,
970 check_result(result, "dns_db_deleterdataset()");
971 dns_rdataset_disassociate(&rdataset);
973 if (result != ISC_R_NOMORE)
974 fatal("rdataset iteration failed: %s",
975 isc_result_totext(result));
978 * Delete RRSIGs for types that no longer exist.
980 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
981 check_result(result, "dns_db_allrdatasets()");
982 for (result = dns_rdatasetiter_first(rdsiter);
983 result == ISC_R_SUCCESS;
984 result = dns_rdatasetiter_next(rdsiter)) {
985 dns_rdatasetiter_current(rdsiter, &rdataset);
986 type = rdataset.type;
987 covers = rdataset.covers;
988 dns_rdataset_disassociate(&rdataset);
989 if (type != dns_rdatatype_rrsig)
992 for (result = dns_rdatasetiter_first(rdsiter2);
993 !found && result == ISC_R_SUCCESS;
994 result = dns_rdatasetiter_next(rdsiter2)) {
995 dns_rdatasetiter_current(rdsiter2, &rdataset);
996 if (rdataset.type == covers)
998 dns_rdataset_disassociate(&rdataset);
1001 if (result != ISC_R_NOMORE)
1002 fatal("rdataset iteration failed: %s",
1003 isc_result_totext(result));
1004 result = dns_db_deleterdataset(gdb, node,
1007 check_result(result,
1008 "dns_db_deleterdataset(rrsig)");
1009 } else if (result != ISC_R_NOMORE &&
1010 result != ISC_R_SUCCESS)
1011 fatal("rdataset iteration failed: %s",
1012 isc_result_totext(result));
1014 if (result != ISC_R_NOMORE)
1015 fatal("rdataset iteration failed: %s",
1016 isc_result_totext(result));
1017 dns_rdatasetiter_destroy(&rdsiter2);
1019 dns_rdatasetiter_destroy(&rdsiter);
1025 * Extracts the TTL from the SOA.
1029 dns_rdataset_t soaset;
1030 dns_fixedname_t fname;
1032 isc_result_t result;
1034 dns_rdata_t rdata = DNS_RDATA_INIT;
1035 dns_rdata_soa_t soa;
1037 dns_fixedname_init(&fname);
1038 name = dns_fixedname_name(&fname);
1039 dns_rdataset_init(&soaset);
1040 result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
1041 0, 0, NULL, name, &soaset, NULL);
1042 if (result != ISC_R_SUCCESS)
1043 fatal("failed to find an SOA at the zone apex: %s",
1044 isc_result_totext(result));
1046 result = dns_rdataset_first(&soaset);
1047 check_result(result, "dns_rdataset_first");
1048 dns_rdataset_current(&soaset, &rdata);
1049 result = dns_rdata_tostruct(&rdata, &soa, NULL);
1050 check_result(result, "dns_rdata_tostruct");
1052 dns_rdataset_disassociate(&soaset);
1057 * Delete any RRSIG records at a node.
1060 cleannode(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
1061 dns_rdatasetiter_t *rdsiter = NULL;
1063 isc_result_t result, dresult;
1065 dns_rdataset_init(&set);
1066 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
1067 check_result(result, "dns_db_allrdatasets");
1068 result = dns_rdatasetiter_first(rdsiter);
1069 while (result == ISC_R_SUCCESS) {
1070 isc_boolean_t destroy = ISC_FALSE;
1071 dns_rdatatype_t covers = 0;
1072 dns_rdatasetiter_current(rdsiter, &set);
1073 if (set.type == dns_rdatatype_rrsig) {
1074 covers = set.covers;
1077 dns_rdataset_disassociate(&set);
1078 result = dns_rdatasetiter_next(rdsiter);
1080 dresult = dns_db_deleterdataset(db, node, version,
1081 dns_rdatatype_rrsig,
1083 check_result(dresult, "dns_db_deleterdataset");
1086 if (result != ISC_R_NOMORE)
1087 fatal("rdataset iteration failed: %s",
1088 isc_result_totext(result));
1089 dns_rdatasetiter_destroy(&rdsiter);
1093 * Set up the iterator and global state before starting the tasks.
1097 isc_result_t result;
1100 result = dns_db_createiterator(gdb, ISC_FALSE, &gdbiter);
1101 check_result(result, "dns_db_createiterator()");
1103 result = dns_dbiterator_first(gdbiter);
1104 check_result(result, "dns_dbiterator_first()");
1108 * Clean up the iterator and global state after the tasks complete.
1112 dns_dbiterator_destroy(&gdbiter);
1116 * Assigns a node to a worker thread. This is protected by the master task's
1120 assignwork(isc_task_t *task, isc_task_t *worker) {
1121 dns_fixedname_t *fname;
1125 dns_rdataset_t nsec;
1126 isc_boolean_t found;
1127 isc_result_t result;
1133 if (assigned == completed) {
1134 isc_task_detach(&task);
1140 fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
1142 fatal("out of memory");
1143 dns_fixedname_init(fname);
1144 name = dns_fixedname_name(fname);
1149 result = dns_dbiterator_current(gdbiter, &node, name);
1150 if (result != ISC_R_SUCCESS)
1151 fatal("failure iterating database: %s",
1152 isc_result_totext(result));
1153 dns_rdataset_init(&nsec);
1154 result = dns_db_findrdataset(gdb, node, gversion,
1155 dns_rdatatype_nsec, 0, 0,
1157 if (result == ISC_R_SUCCESS)
1160 dumpnode(name, node);
1161 if (dns_rdataset_isassociated(&nsec))
1162 dns_rdataset_disassociate(&nsec);
1164 dns_db_detachnode(gdb, &node);
1166 result = dns_dbiterator_next(gdbiter);
1167 if (result == ISC_R_NOMORE) {
1168 finished = ISC_TRUE;
1170 } else if (result != ISC_R_SUCCESS)
1171 fatal("failure iterating database: %s",
1172 isc_result_totext(result));
1176 if (assigned == completed) {
1177 isc_task_detach(&task);
1180 isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
1183 sevent = (sevent_t *)
1184 isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
1185 sign, NULL, sizeof(sevent_t));
1187 fatal("failed to allocate event\n");
1189 sevent->node = node;
1190 sevent->fname = fname;
1191 isc_task_send(worker, ISC_EVENT_PTR(&sevent));
1196 * Start a worker task
1199 startworker(isc_task_t *task, isc_event_t *event) {
1202 worker = (isc_task_t *)event->ev_arg;
1203 assignwork(task, worker);
1204 isc_event_free(&event);
1208 * Write a node to the output file, and restart the worker task.
1211 writenode(isc_task_t *task, isc_event_t *event) {
1213 sevent_t *sevent = (sevent_t *)event;
1216 worker = (isc_task_t *)event->ev_sender;
1217 dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
1218 cleannode(gdb, gversion, sevent->node);
1219 dns_db_detachnode(gdb, &sevent->node);
1220 isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
1221 assignwork(task, worker);
1222 isc_event_free(&event);
1226 * Sign a database node.
1229 sign(isc_task_t *task, isc_event_t *event) {
1230 dns_fixedname_t *fname;
1232 sevent_t *sevent, *wevent;
1234 sevent = (sevent_t *)event;
1235 node = sevent->node;
1236 fname = sevent->fname;
1237 isc_event_free(&event);
1239 signname(node, dns_fixedname_name(fname));
1240 wevent = (sevent_t *)
1241 isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
1242 writenode, NULL, sizeof(sevent_t));
1244 fatal("failed to allocate event\n");
1245 wevent->node = node;
1246 wevent->fname = fname;
1247 isc_task_send(master, ISC_EVENT_PTR(&wevent));
1251 * Generate NSEC records for the zone.
1255 dns_dbiterator_t *dbiter = NULL;
1256 dns_dbnode_t *node = NULL, *nextnode = NULL;
1257 dns_fixedname_t fname, fnextname, fzonecut;
1258 dns_name_t *name, *nextname, *zonecut;
1259 isc_boolean_t done = ISC_FALSE;
1260 isc_result_t result;
1262 dns_fixedname_init(&fname);
1263 name = dns_fixedname_name(&fname);
1264 dns_fixedname_init(&fnextname);
1265 nextname = dns_fixedname_name(&fnextname);
1266 dns_fixedname_init(&fzonecut);
1269 result = dns_db_createiterator(gdb, ISC_FALSE, &dbiter);
1270 check_result(result, "dns_db_createiterator()");
1272 result = dns_dbiterator_first(dbiter);
1273 check_result(result, "dns_dbiterator_first()");
1276 dns_dbiterator_current(dbiter, &node, name);
1277 if (delegation(name, node, NULL)) {
1278 zonecut = dns_fixedname_name(&fzonecut);
1279 dns_name_copy(name, zonecut, NULL);
1281 result = dns_dbiterator_next(dbiter);
1283 while (result == ISC_R_SUCCESS) {
1284 isc_boolean_t active = ISC_FALSE;
1285 result = dns_dbiterator_current(dbiter, &nextnode,
1287 if (result != ISC_R_SUCCESS)
1289 active = active_node(nextnode);
1291 dns_db_detachnode(gdb, &nextnode);
1292 result = dns_dbiterator_next(dbiter);
1295 if (!dns_name_issubdomain(nextname, gorigin) ||
1297 dns_name_issubdomain(nextname, zonecut)))
1299 dns_db_detachnode(gdb, &nextnode);
1300 result = dns_dbiterator_next(dbiter);
1303 dns_db_detachnode(gdb, &nextnode);
1306 if (result == ISC_R_NOMORE) {
1307 dns_name_clone(gorigin, nextname);
1309 } else if (result != ISC_R_SUCCESS)
1310 fatal("iterating through the database failed: %s",
1311 isc_result_totext(result));
1312 result = dns_nsec_build(gdb, gversion, node, nextname,
1314 check_result(result, "dns_nsec_build()");
1315 dns_db_detachnode(gdb, &node);
1318 dns_dbiterator_destroy(&dbiter);
1322 * Load the zone file from disk
1325 loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
1328 dns_fixedname_t fname;
1330 isc_result_t result;
1332 len = strlen(origin);
1333 isc_buffer_init(&b, origin, len);
1334 isc_buffer_add(&b, len);
1336 dns_fixedname_init(&fname);
1337 name = dns_fixedname_name(&fname);
1338 result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
1339 if (result != ISC_R_SUCCESS)
1340 fatal("failed converting name '%s' to dns format: %s",
1341 origin, isc_result_totext(result));
1343 result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
1344 rdclass, 0, NULL, db);
1345 check_result(result, "dns_db_create()");
1347 result = dns_db_load(*db, file);
1348 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
1349 fatal("failed loading zone from '%s': %s",
1350 file, isc_result_totext(result));
1354 * Finds all public zone keys in the zone, and attempts to load the
1355 * private keys from disk.
1358 loadzonekeys(dns_db_t *db) {
1360 dns_dbversion_t *currentversion;
1361 isc_result_t result;
1362 dst_key_t *keys[20];
1363 unsigned int nkeys, i;
1365 currentversion = NULL;
1366 dns_db_currentversion(db, ¤tversion);
1369 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
1370 if (result != ISC_R_SUCCESS)
1371 fatal("failed to find the zone's origin: %s",
1372 isc_result_totext(result));
1374 result = dns_dnssec_findzonekeys(db, currentversion, node, gorigin,
1375 mctx, 20, keys, &nkeys);
1376 if (result == ISC_R_NOTFOUND)
1377 result = ISC_R_SUCCESS;
1378 if (result != ISC_R_SUCCESS)
1379 fatal("failed to find the zone keys: %s",
1380 isc_result_totext(result));
1382 for (i = 0; i < nkeys; i++) {
1385 key = newkeystruct(keys[i], ISC_TRUE);
1386 ISC_LIST_APPEND(keylist, key, link);
1388 dns_db_detachnode(db, &node);
1389 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
1393 * Finds all public zone keys in the zone.
1396 loadzonepubkeys(dns_db_t *db) {
1397 dns_dbversion_t *currentversion = NULL;
1398 dns_dbnode_t *node = NULL;
1399 dns_rdataset_t rdataset;
1400 dns_rdata_t rdata = DNS_RDATA_INIT;
1403 isc_result_t result;
1405 dns_db_currentversion(db, ¤tversion);
1407 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
1408 if (result != ISC_R_SUCCESS)
1409 fatal("failed to find the zone's origin: %s",
1410 isc_result_totext(result));
1412 dns_rdataset_init(&rdataset);
1413 result = dns_db_findrdataset(db, node, currentversion,
1414 dns_rdatatype_dnskey, 0, 0, &rdataset, NULL);
1415 if (result != ISC_R_SUCCESS)
1416 fatal("failed to find keys at the zone apex: %s",
1417 isc_result_totext(result));
1418 result = dns_rdataset_first(&rdataset);
1419 check_result(result, "dns_rdataset_first");
1420 while (result == ISC_R_SUCCESS) {
1422 dns_rdata_reset(&rdata);
1423 dns_rdataset_current(&rdataset, &rdata);
1424 result = dns_dnssec_keyfromrdata(gorigin, &rdata, mctx,
1426 if (result != ISC_R_SUCCESS)
1428 if (!dst_key_iszonekey(pubkey)) {
1429 dst_key_free(&pubkey);
1433 key = newkeystruct(pubkey, ISC_FALSE);
1434 ISC_LIST_APPEND(keylist, key, link);
1436 result = dns_rdataset_next(&rdataset);
1438 dns_rdataset_disassociate(&rdataset);
1439 dns_db_detachnode(db, &node);
1440 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
1444 warnifallksk(dns_db_t *db) {
1445 dns_dbversion_t *currentversion = NULL;
1446 dns_dbnode_t *node = NULL;
1447 dns_rdataset_t rdataset;
1448 dns_rdata_t rdata = DNS_RDATA_INIT;
1449 isc_result_t result;
1450 dns_rdata_key_t key;
1451 isc_boolean_t have_non_ksk = ISC_FALSE;
1453 dns_db_currentversion(db, ¤tversion);
1455 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
1456 if (result != ISC_R_SUCCESS)
1457 fatal("failed to find the zone's origin: %s",
1458 isc_result_totext(result));
1460 dns_rdataset_init(&rdataset);
1461 result = dns_db_findrdataset(db, node, currentversion,
1462 dns_rdatatype_dnskey, 0, 0, &rdataset, NULL);
1463 if (result != ISC_R_SUCCESS)
1464 fatal("failed to find keys at the zone apex: %s",
1465 isc_result_totext(result));
1466 result = dns_rdataset_first(&rdataset);
1467 check_result(result, "dns_rdataset_first");
1468 while (result == ISC_R_SUCCESS) {
1469 dns_rdata_reset(&rdata);
1470 dns_rdataset_current(&rdataset, &rdata);
1471 result = dns_rdata_tostruct(&rdata, &key, NULL);
1472 check_result(result, "dns_rdata_tostruct");
1473 if ((key.flags & DNS_KEYFLAG_KSK) == 0) {
1474 have_non_ksk = ISC_TRUE;
1475 result = ISC_R_NOMORE;
1477 result = dns_rdataset_next(&rdataset);
1479 dns_rdataset_disassociate(&rdataset);
1480 dns_db_detachnode(db, &node);
1481 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
1482 if (!have_non_ksk && !ignoreksk)
1483 fprintf(stderr, "%s: warning: No non-KSK dnskey found. "
1484 "Supply non-KSK dnskey or use '-z'.\n",
1489 writeset(const char *prefix, dns_rdatatype_t type) {
1491 char namestr[DNS_NAME_FORMATSIZE];
1492 dns_db_t *db = NULL;
1493 dns_dbversion_t *version = NULL;
1495 dns_difftuple_t *tuple = NULL;
1496 dns_fixedname_t fixed;
1498 dns_rdata_t rdata, ds;
1499 isc_boolean_t have_ksk = ISC_FALSE;
1500 isc_boolean_t have_non_ksk = ISC_FALSE;
1502 isc_buffer_t namebuf;
1504 isc_result_t result;
1506 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
1507 unsigned char keybuf[DST_KEY_MAXSIZE];
1508 unsigned int filenamelen;
1509 const dns_master_style_t *style =
1510 (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
1512 isc_buffer_init(&namebuf, namestr, sizeof(namestr));
1513 result = dns_name_tofilenametext(gorigin, ISC_FALSE, &namebuf);
1514 check_result(result, "dns_name_tofilenametext");
1515 isc_buffer_putuint8(&namebuf, 0);
1516 filenamelen = strlen(prefix) + strlen(namestr);
1517 if (directory != NULL)
1518 filenamelen += strlen(directory) + 1;
1519 filename = isc_mem_get(mctx, filenamelen + 1);
1520 if (filename == NULL)
1521 fatal("out of memory");
1522 if (directory != NULL)
1523 sprintf(filename, "%s/", directory);
1526 strcat(filename, prefix);
1527 strcat(filename, namestr);
1529 dns_diff_init(mctx, &diff);
1531 for (key = ISC_LIST_HEAD(keylist);
1533 key = ISC_LIST_NEXT(key, link))
1535 have_non_ksk = ISC_TRUE;
1539 for (key = ISC_LIST_HEAD(keylist);
1541 key = ISC_LIST_NEXT(key, link))
1543 have_ksk = ISC_TRUE;
1547 if (type == dns_rdatatype_dlv) {
1549 unsigned int labels;
1551 dns_name_init(&tname, NULL);
1552 dns_fixedname_init(&fixed);
1553 name = dns_fixedname_name(&fixed);
1554 labels = dns_name_countlabels(gorigin);
1555 dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
1556 result = dns_name_concatenate(&tname, dlv, name, NULL);
1557 check_result(result, "dns_name_concatenate");
1561 for (key = ISC_LIST_HEAD(keylist);
1563 key = ISC_LIST_NEXT(key, link))
1565 if (have_ksk && have_non_ksk && !key->isksk)
1567 dns_rdata_init(&rdata);
1568 dns_rdata_init(&ds);
1569 isc_buffer_init(&b, keybuf, sizeof(keybuf));
1570 result = dst_key_todns(key->key, &b);
1571 check_result(result, "dst_key_todns");
1572 isc_buffer_usedregion(&b, &r);
1573 dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
1574 if (type != dns_rdatatype_dnskey) {
1575 result = dns_ds_buildrdata(gorigin, &rdata,
1578 check_result(result, "dns_ds_buildrdata");
1579 if (type == dns_rdatatype_dlv)
1580 ds.type = dns_rdatatype_dlv;
1581 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
1582 name, 0, &ds, &tuple);
1584 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
1587 check_result(result, "dns_difftuple_create");
1588 dns_diff_append(&diff, &tuple);
1591 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
1592 gclass, 0, NULL, &db);
1593 check_result(result, "dns_db_create");
1595 result = dns_db_newversion(db, &version);
1596 check_result(result, "dns_db_newversion");
1598 result = dns_diff_apply(&diff, db, version);
1599 check_result(result, "dns_diff_apply");
1600 dns_diff_clear(&diff);
1602 result = dns_master_dump(mctx, db, version, style, filename);
1603 check_result(result, "dns_master_dump");
1605 isc_mem_put(mctx, filename, filenamelen + 1);
1607 dns_db_closeversion(db, &version, ISC_FALSE);
1612 print_time(FILE *fp) {
1615 currenttime = time(NULL);
1616 fprintf(fp, "; File written on %s", ctime(¤ttime));
1620 print_version(FILE *fp) {
1621 fprintf(fp, "; dnssec_signzone version " VERSION "\n");
1626 fprintf(stderr, "Usage:\n");
1627 fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
1629 fprintf(stderr, "\n");
1631 fprintf(stderr, "Version: %s\n", VERSION);
1633 fprintf(stderr, "Options: (default value in parenthesis) \n");
1634 fprintf(stderr, "\t-c class (IN)\n");
1635 fprintf(stderr, "\t-d directory\n");
1636 fprintf(stderr, "\t\tdirectory to find keyset files (.)\n");
1637 fprintf(stderr, "\t-g:\t");
1638 fprintf(stderr, "generate DS records from keyset files\n");
1639 fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
1640 fprintf(stderr, "\t\tRRSIG start time - absolute|offset (now - 1 hour)\n");
1641 fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
1642 fprintf(stderr, "\t\tRRSIG end time - absolute|from start|from now "
1643 "(now + 30 days)\n");
1644 fprintf(stderr, "\t-i interval:\n");
1645 fprintf(stderr, "\t\tcycle interval - resign "
1646 "if < interval from end ( (end-start)/4 )\n");
1647 fprintf(stderr, "\t-v debuglevel (0)\n");
1648 fprintf(stderr, "\t-o origin:\n");
1649 fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
1650 fprintf(stderr, "\t-f outfile:\n");
1651 fprintf(stderr, "\t\tfile the signed zone is written in "
1652 "(zonefile + .signed)\n");
1653 fprintf(stderr, "\t-r randomdev:\n");
1654 fprintf(stderr, "\t\ta file containing random data\n");
1655 fprintf(stderr, "\t-a:\t");
1656 fprintf(stderr, "verify generated signatures\n");
1657 fprintf(stderr, "\t-p:\t");
1658 fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
1659 fprintf(stderr, "\t-t:\t");
1660 fprintf(stderr, "print statistics\n");
1661 fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
1662 fprintf(stderr, "\t-k key_signing_key\n");
1663 fprintf(stderr, "\t-l lookasidezone\n");
1664 fprintf(stderr, "\t-z:\t");
1665 fprintf(stderr, "ignore KSK flag in DNSKEYs");
1667 fprintf(stderr, "\n");
1669 fprintf(stderr, "Signing Keys: ");
1670 fprintf(stderr, "(default: all zone keys that have private keys)\n");
1671 fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
1676 removetempfile(void) {
1678 isc_file_remove(tempfile);
1682 print_stats(isc_time_t *timer_start, isc_time_t *timer_finish) {
1683 isc_uint64_t runtime_us; /* Runtime in microseconds */
1684 isc_uint64_t runtime_ms; /* Runtime in milliseconds */
1685 isc_uint64_t sig_ms; /* Signatures per millisecond */
1687 runtime_us = isc_time_microdiff(timer_finish, timer_start);
1689 printf("Signatures generated: %10d\n", nsigned);
1690 printf("Signatures retained: %10d\n", nretained);
1691 printf("Signatures dropped: %10d\n", ndropped);
1692 printf("Signatures successfully verified: %10d\n", nverified);
1693 printf("Signatures unsuccessfully verified: %10d\n", nverifyfailed);
1694 runtime_ms = runtime_us / 1000;
1695 printf("Runtime in seconds: %7u.%03u\n",
1696 (unsigned int) (runtime_ms / 1000),
1697 (unsigned int) (runtime_ms % 1000));
1698 if (runtime_us > 0) {
1699 sig_ms = ((isc_uint64_t)nsigned * 1000000000) / runtime_us;
1700 printf("Signatures per second: %7u.%03u\n",
1701 (unsigned int) sig_ms / 1000,
1702 (unsigned int) sig_ms % 1000);
1707 main(int argc, char *argv[]) {
1709 char *startstr = NULL, *endstr = NULL, *classname = NULL;
1710 char *origin = NULL, *file = NULL, *output = NULL;
1711 char *dskeyfile[MAXDSKEYS];
1714 isc_time_t timer_start, timer_finish;
1716 isc_result_t result;
1717 isc_log_t *log = NULL;
1718 isc_boolean_t pseudorandom = ISC_FALSE;
1719 unsigned int eflags;
1720 isc_boolean_t free_output = ISC_FALSE;
1722 dns_rdataclass_t rdclass;
1723 dns_db_t *udb = NULL;
1724 isc_task_t **tasks = NULL;
1728 masterstyle = &dns_master_style_explicitttl;
1730 check_result(isc_app_start(), "isc_app_start");
1732 result = isc_mem_create(0, 0, &mctx);
1733 if (result != ISC_R_SUCCESS)
1734 fatal("out of memory");
1736 dns_result_register();
1738 while ((ch = isc_commandline_parse(argc, argv,
1739 "ac:d:e:f:ghi:k:l:n:o:pr:s:Stv:z"))
1743 tryverify = ISC_TRUE;
1747 classname = isc_commandline_argument;
1751 directory = isc_commandline_argument;
1755 endstr = isc_commandline_argument;
1759 output = isc_commandline_argument;
1763 generateds = ISC_TRUE;
1773 cycle = strtol(isc_commandline_argument, &endp, 0);
1774 if (*endp != '\0' || cycle < 0)
1775 fatal("cycle period must be numeric and "
1780 dns_fixedname_init(&dlv_fixed);
1781 len = strlen(isc_commandline_argument);
1782 isc_buffer_init(&b, isc_commandline_argument, len);
1783 isc_buffer_add(&b, len);
1785 dns_fixedname_init(&dlv_fixed);
1786 dlv = dns_fixedname_name(&dlv_fixed);
1787 result = dns_name_fromtext(dlv, &b, dns_rootname,
1789 check_result(result, "dns_name_fromtext(dlv)");
1793 if (ndskeys == MAXDSKEYS)
1794 fatal("too many key-signing keys specified");
1795 dskeyfile[ndskeys++] = isc_commandline_argument;
1800 ntasks = strtol(isc_commandline_argument, &endp, 0);
1801 if (*endp != '\0' || ntasks > ISC_INT32_MAX)
1802 fatal("number of cpus must be numeric");
1806 origin = isc_commandline_argument;
1810 pseudorandom = ISC_TRUE;
1814 setup_entropy(mctx, isc_commandline_argument, &ectx);
1818 startstr = isc_commandline_argument;
1822 /* This is intentionally undocumented */
1823 /* -S: simple output style */
1824 masterstyle = &dns_master_style_simple;
1828 printstats = ISC_TRUE;
1833 verbose = strtol(isc_commandline_argument, &endp, 0);
1835 fatal("verbose level must be numeric");
1839 ignoreksk = ISC_TRUE;
1845 setup_entropy(mctx, NULL, &ectx);
1846 eflags = ISC_ENTROPY_BLOCKING;
1848 eflags |= ISC_ENTROPY_GOODONLY;
1850 result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
1851 if (result != ISC_R_SUCCESS)
1852 fatal("could not create hash context");
1854 result = dst_lib_init(mctx, ectx, eflags);
1855 if (result != ISC_R_SUCCESS)
1856 fatal("could not initialize dst");
1858 isc_stdtime_get(&now);
1860 if (startstr != NULL)
1861 starttime = strtotime(startstr, now, now);
1863 starttime = now - 3600; /* Allow for some clock skew. */
1866 endtime = strtotime(endstr, now, starttime);
1868 endtime = starttime + (30 * 24 * 60 * 60);
1871 cycle = (endtime - starttime) / 4;
1874 ntasks = isc_os_ncpus();
1875 vbprintf(4, "using %d cpus\n", ntasks);
1877 rdclass = strtoclass(classname);
1879 setup_logging(verbose, mctx, &log);
1881 argc -= isc_commandline_index;
1882 argv += isc_commandline_index;
1895 if (output == NULL) {
1896 free_output = ISC_TRUE;
1897 output = isc_mem_allocate(mctx,
1898 strlen(file) + strlen(".signed") + 1);
1900 fatal("out of memory");
1901 sprintf(output, "%s.signed", file);
1904 result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL,
1905 0, 24, 0, 0, 0, 8, mctx);
1906 check_result(result, "dns_master_stylecreate");
1910 TIME_NOW(&timer_start);
1911 loadzone(file, origin, rdclass, &gdb);
1912 gorigin = dns_db_origin(gdb);
1913 gclass = dns_db_class(gdb);
1916 ISC_LIST_INIT(keylist);
1921 for (i = 0; i < argc; i++) {
1922 dst_key_t *newkey = NULL;
1924 result = dst_key_fromnamedfile(argv[i],
1928 if (result != ISC_R_SUCCESS)
1929 fatal("cannot load dnskey %s: %s", argv[i],
1930 isc_result_totext(result));
1932 key = ISC_LIST_HEAD(keylist);
1933 while (key != NULL) {
1934 dst_key_t *dkey = key->key;
1935 if (dst_key_id(dkey) == dst_key_id(newkey) &&
1936 dst_key_alg(dkey) == dst_key_alg(newkey) &&
1937 dns_name_equal(dst_key_name(dkey),
1938 dst_key_name(newkey)))
1940 if (!dst_key_isprivate(dkey))
1941 fatal("cannot sign zone with "
1942 "non-private dnskey %s",
1946 key = ISC_LIST_NEXT(key, link);
1949 key = newkeystruct(newkey, ISC_TRUE);
1950 ISC_LIST_APPEND(keylist, key, link);
1952 dst_key_free(&newkey);
1955 loadzonepubkeys(gdb);
1958 for (i = 0; i < ndskeys; i++) {
1959 dst_key_t *newkey = NULL;
1961 result = dst_key_fromnamedfile(dskeyfile[i],
1965 if (result != ISC_R_SUCCESS)
1966 fatal("cannot load dnskey %s: %s", dskeyfile[i],
1967 isc_result_totext(result));
1969 key = ISC_LIST_HEAD(keylist);
1970 while (key != NULL) {
1971 dst_key_t *dkey = key->key;
1972 if (dst_key_id(dkey) == dst_key_id(newkey) &&
1973 dst_key_alg(dkey) == dst_key_alg(newkey) &&
1974 dns_name_equal(dst_key_name(dkey),
1975 dst_key_name(newkey)))
1977 /* Override key flags. */
1978 key->issigningkey = ISC_TRUE;
1979 key->isksk = ISC_TRUE;
1980 key->isdsk = ISC_FALSE;
1981 dst_key_free(&dkey);
1985 key = ISC_LIST_NEXT(key, link);
1988 /* Override dnskey flags. */
1989 key = newkeystruct(newkey, ISC_TRUE);
1990 key->isksk = ISC_TRUE;
1991 key->isdsk = ISC_FALSE;
1992 ISC_LIST_APPEND(keylist, key, link);
1996 if (ISC_LIST_EMPTY(keylist)) {
1997 fprintf(stderr, "%s: warning: No keys specified or found\n",
2005 result = dns_db_newversion(gdb, &gversion);
2006 check_result(result, "dns_db_newversion()");
2011 writeset("keyset-", dns_rdatatype_dnskey);
2012 writeset("dsset-", dns_rdatatype_ds);
2014 writeset("dlvset-", dns_rdatatype_dlv);
2018 tempfilelen = strlen(output) + 20;
2019 tempfile = isc_mem_get(mctx, tempfilelen);
2020 if (tempfile == NULL)
2021 fatal("out of memory");
2023 result = isc_file_mktemplate(output, tempfile, tempfilelen);
2024 check_result(result, "isc_file_mktemplate");
2027 result = isc_file_openunique(tempfile, &fp);
2028 if (result != ISC_R_SUCCESS)
2029 fatal("failed to open temporary output file: %s",
2030 isc_result_totext(result));
2031 removefile = ISC_TRUE;
2032 setfatalcallback(&removetempfile);
2037 result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
2038 if (result != ISC_R_SUCCESS)
2039 fatal("failed to create task manager: %s",
2040 isc_result_totext(result));
2043 result = isc_task_create(taskmgr, 0, &master);
2044 if (result != ISC_R_SUCCESS)
2045 fatal("failed to create task: %s", isc_result_totext(result));
2047 tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
2049 fatal("out of memory");
2050 for (i = 0; i < (int)ntasks; i++) {
2052 result = isc_task_create(taskmgr, 0, &tasks[i]);
2053 if (result != ISC_R_SUCCESS)
2054 fatal("failed to create task: %s",
2055 isc_result_totext(result));
2056 result = isc_app_onrun(mctx, master, startworker, tasks[i]);
2057 if (result != ISC_R_SUCCESS)
2058 fatal("failed to start task: %s",
2059 isc_result_totext(result));
2062 RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS);
2064 RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS);
2067 (void)isc_app_run();
2069 fatal("process aborted by user");
2070 shuttingdown = ISC_TRUE;
2071 for (i = 0; i < (int)ntasks; i++)
2072 isc_task_detach(&tasks[i]);
2073 isc_taskmgr_destroy(&taskmgr);
2074 isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
2079 dns_db_detach(&udb);
2082 result = isc_stdio_close(fp);
2083 check_result(result, "isc_stdio_close");
2084 removefile = ISC_FALSE;
2086 result = isc_file_rename(tempfile, output);
2087 if (result != ISC_R_SUCCESS)
2088 fatal("failed to rename temp file to %s: %s\n",
2089 output, isc_result_totext(result));
2091 DESTROYLOCK(&namelock);
2093 DESTROYLOCK(&statslock);
2095 printf("%s\n", output);
2097 dns_db_closeversion(gdb, &gversion, ISC_FALSE);
2098 dns_db_detach(&gdb);
2100 while (!ISC_LIST_EMPTY(keylist)) {
2101 key = ISC_LIST_HEAD(keylist);
2102 ISC_LIST_UNLINK(keylist, key, link);
2103 dst_key_free(&key->key);
2104 isc_mem_put(mctx, key, sizeof(signer_key_t));
2107 isc_mem_put(mctx, tempfile, tempfilelen);
2110 isc_mem_free(mctx, output);
2112 dns_master_styledestroy(&dsstyle, mctx);
2114 cleanup_logging(&log);
2117 cleanup_entropy(&ectx);
2119 isc_mem_stats(mctx, stdout);
2120 isc_mem_destroy(&mctx);
2122 (void) isc_app_finish();
2125 TIME_NOW(&timer_finish);
2126 print_stats(&timer_start, &timer_finish);