Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / bind / dist / bin / dnssec / dnssec-signzone.c
blob818d8a4a260b1a2986068102dfc1e8a5a2281b0d
1 /* $NetBSD: dnssec-signzone.c,v 1.1.1.4 2009/12/26 22:19:04 christos Exp $ */
3 /*
4 * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Portions Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
12 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
14 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
17 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
21 * Permission to use, copy, modify, and/or distribute this software for any
22 * purpose with or without fee is hereby granted, provided that the above
23 * copyright notice and this permission notice appear in all copies.
25 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
26 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
27 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
28 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
29 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
30 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
31 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
34 /* Id: dnssec-signzone.c,v 1.258 2009/12/04 22:06:37 tbox Exp */
36 /*! \file */
38 #include <config.h>
40 #include <stdlib.h>
41 #include <time.h>
43 #include <isc/app.h>
44 #include <isc/base32.h>
45 #include <isc/commandline.h>
46 #include <isc/entropy.h>
47 #include <isc/event.h>
48 #include <isc/file.h>
49 #include <isc/hash.h>
50 #include <isc/hex.h>
51 #include <isc/mem.h>
52 #include <isc/mutex.h>
53 #include <isc/os.h>
54 #include <isc/print.h>
55 #include <isc/random.h>
56 #include <isc/rwlock.h>
57 #include <isc/serial.h>
58 #include <isc/stdio.h>
59 #include <isc/stdlib.h>
60 #include <isc/string.h>
61 #include <isc/task.h>
62 #include <isc/time.h>
63 #include <isc/util.h>
65 #include <dns/db.h>
66 #include <dns/dbiterator.h>
67 #include <dns/diff.h>
68 #include <dns/dnssec.h>
69 #include <dns/ds.h>
70 #include <dns/fixedname.h>
71 #include <dns/keyvalues.h>
72 #include <dns/log.h>
73 #include <dns/master.h>
74 #include <dns/masterdump.h>
75 #include <dns/nsec.h>
76 #include <dns/nsec3.h>
77 #include <dns/rdata.h>
78 #include <dns/rdatalist.h>
79 #include <dns/rdataset.h>
80 #include <dns/rdataclass.h>
81 #include <dns/rdatasetiter.h>
82 #include <dns/rdatastruct.h>
83 #include <dns/rdatatype.h>
84 #include <dns/result.h>
85 #include <dns/soa.h>
86 #include <dns/time.h>
88 #include <dst/dst.h>
90 #include "dnssectool.h"
92 #ifndef PATH_MAX
93 #define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */
94 #endif
96 const char *program = "dnssec-signzone";
97 int verbose;
99 typedef struct hashlist hashlist_t;
101 static int nsec_datatype = dns_rdatatype_nsec;
103 #define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3)
104 #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
106 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
108 #define BUFSIZE 2048
109 #define MAXDSKEYS 8
111 #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
112 #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
113 #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
115 #define SOA_SERIAL_KEEP 0
116 #define SOA_SERIAL_INCREMENT 1
117 #define SOA_SERIAL_UNIXTIME 2
119 typedef struct signer_event sevent_t;
120 struct signer_event {
121 ISC_EVENT_COMMON(sevent_t);
122 dns_fixedname_t *fname;
123 dns_dbnode_t *node;
126 static dns_dnsseckeylist_t keylist;
127 static unsigned int keycount = 0;
128 isc_rwlock_t keylist_lock;
129 static isc_stdtime_t starttime = 0, endtime = 0, now;
130 static int cycle = -1;
131 static int jitter = 0;
132 static isc_boolean_t tryverify = ISC_FALSE;
133 static isc_boolean_t printstats = ISC_FALSE;
134 static isc_mem_t *mctx = NULL;
135 static isc_entropy_t *ectx = NULL;
136 static dns_ttl_t zone_soa_min_ttl;
137 static dns_ttl_t soa_ttl;
138 static FILE *fp;
139 static char *tempfile = NULL;
140 static const dns_master_style_t *masterstyle;
141 static dns_masterformat_t inputformat = dns_masterformat_text;
142 static dns_masterformat_t outputformat = dns_masterformat_text;
143 static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
144 static unsigned int nverified = 0, nverifyfailed = 0;
145 static const char *directory = NULL, *dsdir = NULL;
146 static isc_mutex_t namelock, statslock;
147 static isc_taskmgr_t *taskmgr = NULL;
148 static dns_db_t *gdb; /* The database */
149 static dns_dbversion_t *gversion; /* The database version */
150 static dns_dbiterator_t *gdbiter; /* The database iterator */
151 static dns_rdataclass_t gclass; /* The class */
152 static dns_name_t *gorigin; /* The database origin */
153 static int nsec3flags = 0;
154 static dns_iterations_t nsec3iter = 10U;
155 static unsigned char saltbuf[255];
156 static unsigned char *salt = saltbuf;
157 static size_t salt_length = 0;
158 static isc_task_t *master = NULL;
159 static unsigned int ntasks = 0;
160 static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE;
161 static isc_boolean_t nokeys = ISC_FALSE;
162 static isc_boolean_t removefile = ISC_FALSE;
163 static isc_boolean_t generateds = ISC_FALSE;
164 static isc_boolean_t ignore_kskflag = ISC_FALSE;
165 static isc_boolean_t keyset_kskonly = ISC_FALSE;
166 static dns_name_t *dlv = NULL;
167 static dns_fixedname_t dlv_fixed;
168 static dns_master_style_t *dsstyle = NULL;
169 static unsigned int serialformat = SOA_SERIAL_KEEP;
170 static unsigned int hash_length = 0;
171 static isc_boolean_t unknownalg = ISC_FALSE;
172 static isc_boolean_t disable_zone_check = ISC_FALSE;
173 static isc_boolean_t update_chain = ISC_FALSE;
174 static isc_boolean_t set_keyttl = ISC_FALSE;
175 static dns_ttl_t keyttl;
177 #define INCSTAT(counter) \
178 if (printstats) { \
179 LOCK(&statslock); \
180 counter++; \
181 UNLOCK(&statslock); \
184 static void
185 sign(isc_task_t *task, isc_event_t *event);
187 #define check_dns_dbiterator_current(result) \
188 check_result((result == DNS_R_NEWORIGIN) ? ISC_R_SUCCESS : result, \
189 "dns_dbiterator_current()")
191 static void
192 dumpnode(dns_name_t *name, dns_dbnode_t *node) {
193 isc_result_t result;
195 if (outputformat != dns_masterformat_text)
196 return;
197 result = dns_master_dumpnodetostream(mctx, gdb, gversion, node, name,
198 masterstyle, fp);
199 check_result(result, "dns_master_dumpnodetostream");
203 * Sign the given RRset with given key, and add the signature record to the
204 * given tuple.
206 static void
207 signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key,
208 dns_ttl_t ttl, dns_diff_t *add, const char *logmsg)
210 isc_result_t result;
211 isc_stdtime_t jendtime;
212 char keystr[DST_KEY_FORMATSIZE];
213 dns_rdata_t trdata = DNS_RDATA_INIT;
214 unsigned char array[BUFSIZE];
215 isc_buffer_t b;
216 dns_difftuple_t *tuple;
218 dst_key_format(key, keystr, sizeof(keystr));
219 vbprintf(1, "\t%s %s\n", logmsg, keystr);
221 jendtime = (jitter != 0) ? isc_random_jitter(endtime, jitter) : endtime;
222 isc_buffer_init(&b, array, sizeof(array));
223 result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
224 mctx, &b, &trdata);
225 isc_entropy_stopcallbacksources(ectx);
226 if (result != ISC_R_SUCCESS) {
227 char keystr[DST_KEY_FORMATSIZE];
228 dst_key_format(key, keystr, sizeof(keystr));
229 fatal("dnskey '%s' failed to sign data: %s",
230 keystr, isc_result_totext(result));
232 INCSTAT(nsigned);
234 if (tryverify) {
235 result = dns_dnssec_verify(name, rdataset, key,
236 ISC_TRUE, mctx, &trdata);
237 if (result == ISC_R_SUCCESS) {
238 vbprintf(3, "\tsignature verified\n");
239 INCSTAT(nverified);
240 } else {
241 vbprintf(3, "\tsignature failed to verify\n");
242 INCSTAT(nverifyfailed);
246 tuple = NULL;
247 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name, ttl, &trdata,
248 &tuple);
249 check_result(result, "dns_difftuple_create");
250 dns_diff_append(add, &tuple);
253 static inline isc_boolean_t
254 issigningkey(dns_dnsseckey_t *key) {
255 return (key->force_sign || key->hint_sign);
258 static inline isc_boolean_t
259 iszonekey(dns_dnsseckey_t *key) {
260 return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) &&
261 dst_key_iszonekey(key->key)));
264 static inline isc_boolean_t
265 isksk(dns_dnsseckey_t *key) {
266 return (key->ksk);
269 static inline isc_boolean_t
270 iszsk(dns_dnsseckey_t *key) {
271 return (ignore_kskflag || !key->ksk);
275 * Find the key that generated an RRSIG, if it is in the key list. If
276 * so, return a pointer to it, otherwise return NULL.
278 * No locking is performed here, this must be done by the caller.
280 static dns_dnsseckey_t *
281 keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
282 dns_dnsseckey_t *key;
284 for (key = ISC_LIST_HEAD(keylist);
285 key != NULL;
286 key = ISC_LIST_NEXT(key, link)) {
287 if (rrsig->keyid == dst_key_id(key->key) &&
288 rrsig->algorithm == dst_key_alg(key->key) &&
289 dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
290 return (key);
292 return (NULL);
296 * Finds the key that generated a RRSIG, if possible. First look at the keys
297 * that we've loaded already, and then see if there's a key on disk.
299 static dns_dnsseckey_t *
300 keythatsigned(dns_rdata_rrsig_t *rrsig) {
301 isc_result_t result;
302 dst_key_t *pubkey = NULL, *privkey = NULL;
303 dns_dnsseckey_t *key = NULL;
305 isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read);
306 key = keythatsigned_unlocked(rrsig);
307 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_read);
308 if (key != NULL)
309 return (key);
312 * We did not find the key in our list. Get a write lock now, since
313 * we may be modifying the bits. We could do the tryupgrade() dance,
314 * but instead just get a write lock and check once again to see if
315 * it is on our list. It's possible someone else may have added it
316 * after all.
318 isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write);
319 key = keythatsigned_unlocked(rrsig);
320 if (key != NULL) {
321 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
322 return (key);
325 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
326 rrsig->algorithm, DST_TYPE_PUBLIC,
327 directory, mctx, &pubkey);
328 if (result != ISC_R_SUCCESS) {
329 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
330 return (NULL);
333 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
334 rrsig->algorithm,
335 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
336 directory, mctx, &privkey);
337 if (result == ISC_R_SUCCESS) {
338 dst_key_free(&pubkey);
339 dns_dnsseckey_create(mctx, &privkey, &key);
340 } else {
341 dns_dnsseckey_create(mctx, &pubkey, &key);
343 key->force_publish = ISC_TRUE;
344 key->force_sign = ISC_FALSE;
345 ISC_LIST_APPEND(keylist, key, link);
347 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
348 return (key);
352 * Check to see if we expect to find a key at this name. If we see a RRSIG
353 * and can't find the signing key that we expect to find, we drop the rrsig.
354 * I'm not sure if this is completely correct, but it seems to work.
356 static isc_boolean_t
357 expecttofindkey(dns_name_t *name) {
358 unsigned int options = DNS_DBFIND_NOWILD;
359 dns_fixedname_t fname;
360 isc_result_t result;
361 char namestr[DNS_NAME_FORMATSIZE];
363 dns_fixedname_init(&fname);
364 result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
365 0, NULL, dns_fixedname_name(&fname), NULL, NULL);
366 switch (result) {
367 case ISC_R_SUCCESS:
368 case DNS_R_NXDOMAIN:
369 case DNS_R_NXRRSET:
370 return (ISC_TRUE);
371 case DNS_R_DELEGATION:
372 case DNS_R_CNAME:
373 case DNS_R_DNAME:
374 return (ISC_FALSE);
376 dns_name_format(name, namestr, sizeof(namestr));
377 fatal("failure looking for '%s DNSKEY' in database: %s",
378 namestr, isc_result_totext(result));
379 /* NOTREACHED */
380 return (ISC_FALSE); /* removes a warning */
383 static inline isc_boolean_t
384 setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
385 dns_rdata_t *rrsig)
387 isc_result_t result;
388 result = dns_dnssec_verify(name, set, key, ISC_FALSE, mctx, rrsig);
389 if (result == ISC_R_SUCCESS) {
390 INCSTAT(nverified);
391 return (ISC_TRUE);
392 } else {
393 INCSTAT(nverifyfailed);
394 return (ISC_FALSE);
399 * Signs a set. Goes through contortions to decide if each RRSIG should
400 * be dropped or retained, and then determines if any new SIGs need to
401 * be generated.
403 static void
404 signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
405 dns_rdataset_t *set)
407 dns_rdataset_t sigset;
408 dns_rdata_t sigrdata = DNS_RDATA_INIT;
409 dns_rdata_rrsig_t rrsig;
410 dns_dnsseckey_t *key;
411 isc_result_t result;
412 isc_boolean_t nosigs = ISC_FALSE;
413 isc_boolean_t *wassignedby, *nowsignedby;
414 int arraysize;
415 dns_difftuple_t *tuple;
416 dns_ttl_t ttl;
417 int i;
418 char namestr[DNS_NAME_FORMATSIZE];
419 char typestr[TYPE_FORMATSIZE];
420 char sigstr[SIG_FORMATSIZE];
422 dns_name_format(name, namestr, sizeof(namestr));
423 type_format(set->type, typestr, sizeof(typestr));
425 ttl = ISC_MIN(set->ttl, endtime - starttime);
427 dns_rdataset_init(&sigset);
428 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
429 set->type, 0, &sigset, NULL);
430 if (result == ISC_R_NOTFOUND) {
431 result = ISC_R_SUCCESS;
432 nosigs = ISC_TRUE;
434 if (result != ISC_R_SUCCESS)
435 fatal("failed while looking for '%s RRSIG %s': %s",
436 namestr, typestr, isc_result_totext(result));
438 vbprintf(1, "%s/%s:\n", namestr, typestr);
440 arraysize = keycount;
441 if (!nosigs)
442 arraysize += dns_rdataset_count(&sigset);
443 wassignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
444 nowsignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
445 if (wassignedby == NULL || nowsignedby == NULL)
446 fatal("out of memory");
448 for (i = 0; i < arraysize; i++)
449 wassignedby[i] = nowsignedby[i] = ISC_FALSE;
451 if (nosigs)
452 result = ISC_R_NOMORE;
453 else
454 result = dns_rdataset_first(&sigset);
456 while (result == ISC_R_SUCCESS) {
457 isc_boolean_t expired, future;
458 isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE;
460 dns_rdataset_current(&sigset, &sigrdata);
462 result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
463 check_result(result, "dns_rdata_tostruct");
465 future = isc_serial_lt(now, rrsig.timesigned);
467 key = keythatsigned(&rrsig);
468 sig_format(&rrsig, sigstr, sizeof(sigstr));
469 if (key != NULL && issigningkey(key))
470 expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
471 else
472 expired = isc_serial_gt(now, rrsig.timeexpire);
474 if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
475 /* rrsig is dropped and not replaced */
476 vbprintf(2, "\trrsig by %s dropped - "
477 "invalid validity period\n",
478 sigstr);
479 } else if (key == NULL && !future &&
480 expecttofindkey(&rrsig.signer)) {
481 /* rrsig is dropped and not replaced */
482 vbprintf(2, "\trrsig by %s dropped - "
483 "private dnskey not found\n",
484 sigstr);
485 } else if (key == NULL || future) {
486 vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
487 expired ? "retained" : "dropped", sigstr);
488 if (!expired)
489 keep = ISC_TRUE;
490 } else if (issigningkey(key)) {
491 if (!expired && setverifies(name, set, key->key,
492 &sigrdata)) {
493 vbprintf(2, "\trrsig by %s retained\n", sigstr);
494 keep = ISC_TRUE;
495 wassignedby[key->index] = ISC_TRUE;
496 nowsignedby[key->index] = ISC_TRUE;
497 } else {
498 vbprintf(2, "\trrsig by %s dropped - %s\n",
499 sigstr,
500 expired ? "expired" :
501 "failed to verify");
502 wassignedby[key->index] = ISC_TRUE;
503 resign = ISC_TRUE;
505 } else if (iszonekey(key)) {
506 if (!expired && setverifies(name, set, key->key,
507 &sigrdata)) {
508 vbprintf(2, "\trrsig by %s retained\n", sigstr);
509 keep = ISC_TRUE;
510 wassignedby[key->index] = ISC_TRUE;
511 nowsignedby[key->index] = ISC_TRUE;
512 } else {
513 vbprintf(2, "\trrsig by %s dropped - %s\n",
514 sigstr,
515 expired ? "expired" :
516 "failed to verify");
517 wassignedby[key->index] = ISC_TRUE;
519 } else if (!expired) {
520 vbprintf(2, "\trrsig by %s retained\n", sigstr);
521 keep = ISC_TRUE;
522 } else {
523 vbprintf(2, "\trrsig by %s expired\n", sigstr);
526 if (keep) {
527 nowsignedby[key->index] = ISC_TRUE;
528 INCSTAT(nretained);
529 if (sigset.ttl != ttl) {
530 vbprintf(2, "\tfixing ttl %s\n", sigstr);
531 tuple = NULL;
532 result = dns_difftuple_create(mctx,
533 DNS_DIFFOP_DEL,
534 name, sigset.ttl,
535 &sigrdata,
536 &tuple);
537 check_result(result, "dns_difftuple_create");
538 dns_diff_append(del, &tuple);
539 result = dns_difftuple_create(mctx,
540 DNS_DIFFOP_ADD,
541 name, ttl,
542 &sigrdata,
543 &tuple);
544 check_result(result, "dns_difftuple_create");
545 dns_diff_append(add, &tuple);
547 } else {
548 tuple = NULL;
549 result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL,
550 name, sigset.ttl,
551 &sigrdata, &tuple);
552 check_result(result, "dns_difftuple_create");
553 dns_diff_append(del, &tuple);
554 INCSTAT(ndropped);
557 if (resign) {
558 INSIST(!keep);
560 signwithkey(name, set, key->key, ttl, add,
561 "resigning with dnskey");
562 nowsignedby[key->index] = ISC_TRUE;
565 dns_rdata_reset(&sigrdata);
566 dns_rdata_freestruct(&rrsig);
567 result = dns_rdataset_next(&sigset);
569 if (result == ISC_R_NOMORE)
570 result = ISC_R_SUCCESS;
572 check_result(result, "dns_rdataset_first/next");
573 if (dns_rdataset_isassociated(&sigset))
574 dns_rdataset_disassociate(&sigset);
576 for (key = ISC_LIST_HEAD(keylist);
577 key != NULL;
578 key = ISC_LIST_NEXT(key, link))
580 if (nowsignedby[key->index])
581 continue;
583 if (!issigningkey(key))
584 continue;
586 if (set->type == dns_rdatatype_dnskey &&
587 dns_name_equal(name, gorigin)) {
588 isc_boolean_t have_ksk;
589 dns_dnsseckey_t *tmpkey;
591 have_ksk = isksk(key);
592 for (tmpkey = ISC_LIST_HEAD(keylist);
593 tmpkey != NULL;
594 tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
595 if (dst_key_alg(key->key) !=
596 dst_key_alg(tmpkey->key))
597 continue;
598 if (REVOKE(tmpkey->key))
599 continue;
600 if (isksk(tmpkey))
601 have_ksk = ISC_TRUE;
603 if (isksk(key) || !have_ksk ||
604 (iszsk(key) && !keyset_kskonly))
605 signwithkey(name, set, key->key, ttl, add,
606 "signing with dnskey");
607 } else if (iszsk(key)) {
608 signwithkey(name, set, key->key, ttl, add,
609 "signing with dnskey");
613 isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t));
614 isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t));
617 struct hashlist {
618 unsigned char *hashbuf;
619 size_t entries;
620 size_t size;
621 size_t length;
624 static void
625 hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) {
627 l->entries = 0;
628 l->length = length + 1;
630 if (nodes != 0) {
631 l->size = nodes;
632 l->hashbuf = malloc(l->size * l->length);
633 if (l->hashbuf == NULL)
634 l->size = 0;
635 } else {
636 l->size = 0;
637 l->hashbuf = NULL;
641 static void
642 hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len)
645 REQUIRE(len <= l->length);
647 if (l->entries == l->size) {
648 l->size = l->size * 2 + 100;
649 l->hashbuf = realloc(l->hashbuf, l->size * l->length);
651 memset(l->hashbuf + l->entries * l->length, 0, l->length);
652 memcpy(l->hashbuf + l->entries * l->length, hash, len);
653 l->entries++;
656 static void
657 hashlist_add_dns_name(hashlist_t *l, /*const*/ dns_name_t *name,
658 unsigned int hashalg, unsigned int iterations,
659 const unsigned char *salt, size_t salt_length,
660 isc_boolean_t speculative)
662 char nametext[DNS_NAME_FORMATSIZE];
663 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
664 unsigned int len;
665 size_t i;
667 len = isc_iterated_hash(hash, hashalg, iterations, salt, salt_length,
668 name->ndata, name->length);
669 if (verbose) {
670 dns_name_format(name, nametext, sizeof nametext);
671 for (i = 0 ; i < len; i++)
672 fprintf(stderr, "%02x", hash[i]);
673 fprintf(stderr, " %s\n", nametext);
675 hash[len++] = speculative ? 1 : 0;
676 hashlist_add(l, hash, len);
679 static int
680 hashlist_comp(const void *a, const void *b) {
681 return (memcmp(a, b, hash_length + 1));
684 static void
685 hashlist_sort(hashlist_t *l) {
686 qsort(l->hashbuf, l->entries, l->length, hashlist_comp);
689 static isc_boolean_t
690 hashlist_hasdup(hashlist_t *l) {
691 unsigned char *current;
692 unsigned char *next = l->hashbuf;
693 size_t entries = l->entries;
696 * Skip initial speculative wild card hashs.
698 while (entries > 0U && next[l->length-1] != 0U) {
699 next += l->length;
700 entries--;
703 current = next;
704 while (entries-- > 1U) {
705 next += l->length;
706 if (next[l->length-1] != 0)
707 continue;
708 if (memcmp(current, next, l->length - 1) == 0)
709 return (ISC_TRUE);
710 current = next;
712 return (ISC_FALSE);
715 static const unsigned char *
716 hashlist_findnext(const hashlist_t *l,
717 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
719 unsigned int entries = l->entries;
720 const unsigned char *next = bsearch(hash, l->hashbuf, l->entries,
721 l->length, hashlist_comp);
722 INSIST(next != NULL);
724 do {
725 if (next < l->hashbuf + (l->entries - 1) * l->length)
726 next += l->length;
727 else
728 next = l->hashbuf;
729 if (next[l->length - 1] == 0)
730 break;
731 } while (entries-- > 1);
732 INSIST(entries != 0);
733 return (next);
736 static isc_boolean_t
737 hashlist_exists(const hashlist_t *l,
738 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
740 if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp))
741 return (ISC_TRUE);
742 else
743 return (ISC_FALSE);
746 static void
747 addnowildcardhash(hashlist_t *l, /*const*/ dns_name_t *name,
748 unsigned int hashalg, unsigned int iterations,
749 const unsigned char *salt, size_t salt_length)
751 dns_fixedname_t fixed;
752 dns_name_t *wild;
753 dns_dbnode_t *node = NULL;
754 isc_result_t result;
755 char namestr[DNS_NAME_FORMATSIZE];
757 dns_fixedname_init(&fixed);
758 wild = dns_fixedname_name(&fixed);
760 result = dns_name_concatenate(dns_wildcardname, name, wild, NULL);
761 if (result == ISC_R_NOSPACE)
762 return;
763 check_result(result,"addnowildcardhash: dns_name_concatenate()");
765 result = dns_db_findnode(gdb, wild, ISC_FALSE, &node);
766 if (result == ISC_R_SUCCESS) {
767 dns_db_detachnode(gdb, &node);
768 return;
771 if (verbose) {
772 dns_name_format(wild, namestr, sizeof(namestr));
773 fprintf(stderr, "adding no-wildcardhash for %s\n", namestr);
776 hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_length,
777 ISC_TRUE);
780 static void
781 opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
782 dns_db_t **dbp)
784 char filename[PATH_MAX];
785 isc_buffer_t b;
786 isc_result_t result;
788 isc_buffer_init(&b, filename, sizeof(filename));
789 if (dsdir != NULL) {
790 /* allow room for a trailing slash */
791 if (strlen(dsdir) >= isc_buffer_availablelength(&b))
792 fatal("path '%s' is too long", dsdir);
793 isc_buffer_putstr(&b, dsdir);
794 if (dsdir[strlen(dsdir) - 1] != '/')
795 isc_buffer_putstr(&b, "/");
797 if (strlen(prefix) > isc_buffer_availablelength(&b))
798 fatal("path '%s' is too long", dsdir);
799 isc_buffer_putstr(&b, prefix);
800 result = dns_name_tofilenametext(name, ISC_FALSE, &b);
801 check_result(result, "dns_name_tofilenametext()");
802 if (isc_buffer_availablelength(&b) == 0) {
803 char namestr[DNS_NAME_FORMATSIZE];
804 dns_name_format(name, namestr, sizeof(namestr));
805 fatal("name '%s' is too long", namestr);
807 isc_buffer_putuint8(&b, 0);
809 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
810 rdclass, 0, NULL, dbp);
811 check_result(result, "dns_db_create()");
813 result = dns_db_load3(*dbp, filename, inputformat, DNS_MASTER_HINT);
814 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
815 dns_db_detach(dbp);
819 * Load the DS set for a child zone, if a dsset-* file can be found.
820 * If not, try to find a keyset-* file from an earlier version of
821 * dnssec-signzone, and build DS records from that.
823 static isc_result_t
824 loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
825 dns_db_t *db = NULL;
826 dns_dbversion_t *ver = NULL;
827 dns_dbnode_t *node = NULL;
828 isc_result_t result;
829 dns_rdataset_t keyset;
830 dns_rdata_t key, ds;
831 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
832 dns_diff_t diff;
833 dns_difftuple_t *tuple = NULL;
835 opendb("dsset-", name, gclass, &db);
836 if (db != NULL) {
837 result = dns_db_findnode(db, name, ISC_FALSE, &node);
838 if (result == ISC_R_SUCCESS) {
839 dns_rdataset_init(dsset);
840 result = dns_db_findrdataset(db, node, NULL,
841 dns_rdatatype_ds, 0, 0,
842 dsset, NULL);
843 dns_db_detachnode(db, &node);
844 if (result == ISC_R_SUCCESS) {
845 vbprintf(2, "found DS records\n");
846 dsset->ttl = ttl;
847 dns_db_detach(&db);
848 return (result);
851 dns_db_detach(&db);
854 /* No DS records found; try again, looking for DNSKEY records */
855 opendb("keyset-", name, gclass, &db);
856 if (db == NULL) {
857 return (ISC_R_NOTFOUND);
860 result = dns_db_findnode(db, name, ISC_FALSE, &node);
861 if (result != ISC_R_SUCCESS) {
862 dns_db_detach(&db);
863 return (result);
866 dns_rdataset_init(&keyset);
867 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
868 &keyset, NULL);
869 if (result != ISC_R_SUCCESS) {
870 dns_db_detachnode(db, &node);
871 dns_db_detach(&db);
872 return (result);
874 vbprintf(2, "found DNSKEY records\n");
876 result = dns_db_newversion(db, &ver);
877 check_result(result, "dns_db_newversion");
878 dns_diff_init(mctx, &diff);
880 for (result = dns_rdataset_first(&keyset);
881 result == ISC_R_SUCCESS;
882 result = dns_rdataset_next(&keyset))
884 dns_rdata_init(&key);
885 dns_rdata_init(&ds);
886 dns_rdataset_current(&keyset, &key);
887 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
888 dsbuf, &ds);
889 check_result(result, "dns_ds_buildrdata");
891 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
892 ttl, &ds, &tuple);
893 check_result(result, "dns_difftuple_create");
894 dns_diff_append(&diff, &tuple);
896 dns_rdata_reset(&ds);
897 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
898 dsbuf, &ds);
899 check_result(result, "dns_ds_buildrdata");
901 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
902 ttl, &ds, &tuple);
903 check_result(result, "dns_difftuple_create");
904 dns_diff_append(&diff, &tuple);
907 result = dns_diff_apply(&diff, db, ver);
908 check_result(result, "dns_diff_apply");
909 dns_diff_clear(&diff);
911 dns_db_closeversion(db, &ver, ISC_TRUE);
913 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
914 dsset, NULL);
915 check_result(result, "dns_db_findrdataset");
917 dns_rdataset_disassociate(&keyset);
918 dns_db_detachnode(db, &node);
919 dns_db_detach(&db);
920 return (result);
923 static isc_boolean_t
924 delegation(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) {
925 dns_rdataset_t nsset;
926 isc_result_t result;
928 if (dns_name_equal(name, gorigin))
929 return (ISC_FALSE);
931 dns_rdataset_init(&nsset);
932 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ns,
933 0, 0, &nsset, NULL);
934 if (dns_rdataset_isassociated(&nsset)) {
935 if (ttlp != NULL)
936 *ttlp = nsset.ttl;
937 dns_rdataset_disassociate(&nsset);
940 return (ISC_TF(result == ISC_R_SUCCESS));
943 static isc_boolean_t
944 secure(dns_name_t *name, dns_dbnode_t *node) {
945 dns_rdataset_t dsset;
946 isc_result_t result;
948 if (dns_name_equal(name, gorigin))
949 return (ISC_FALSE);
951 dns_rdataset_init(&dsset);
952 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds,
953 0, 0, &dsset, NULL);
954 if (dns_rdataset_isassociated(&dsset))
955 dns_rdataset_disassociate(&dsset);
957 return (ISC_TF(result == ISC_R_SUCCESS));
961 * Signs all records at a name.
963 static void
964 signname(dns_dbnode_t *node, dns_name_t *name) {
965 isc_result_t result;
966 dns_rdataset_t rdataset;
967 dns_rdatasetiter_t *rdsiter;
968 isc_boolean_t isdelegation = ISC_FALSE;
969 dns_diff_t del, add;
970 char namestr[DNS_NAME_FORMATSIZE];
972 dns_rdataset_init(&rdataset);
973 dns_name_format(name, namestr, sizeof(namestr));
976 * Determine if this is a delegation point.
978 if (delegation(name, node, NULL))
979 isdelegation = ISC_TRUE;
982 * Now iterate through the rdatasets.
984 dns_diff_init(mctx, &del);
985 dns_diff_init(mctx, &add);
986 rdsiter = NULL;
987 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
988 check_result(result, "dns_db_allrdatasets()");
989 result = dns_rdatasetiter_first(rdsiter);
990 while (result == ISC_R_SUCCESS) {
991 dns_rdatasetiter_current(rdsiter, &rdataset);
993 /* If this is a RRSIG set, skip it. */
994 if (rdataset.type == dns_rdatatype_rrsig)
995 goto skip;
998 * If this name is a delegation point, skip all records
999 * except NSEC and DS sets. Otherwise check that there
1000 * isn't a DS record.
1002 if (isdelegation) {
1003 if (rdataset.type != nsec_datatype &&
1004 rdataset.type != dns_rdatatype_ds)
1005 goto skip;
1006 } else if (rdataset.type == dns_rdatatype_ds) {
1007 char namebuf[DNS_NAME_FORMATSIZE];
1008 dns_name_format(name, namebuf, sizeof(namebuf));
1009 fatal("'%s': found DS RRset without NS RRset\n",
1010 namebuf);
1013 signset(&del, &add, node, name, &rdataset);
1015 skip:
1016 dns_rdataset_disassociate(&rdataset);
1017 result = dns_rdatasetiter_next(rdsiter);
1019 if (result != ISC_R_NOMORE)
1020 fatal("rdataset iteration for name '%s' failed: %s",
1021 namestr, isc_result_totext(result));
1023 dns_rdatasetiter_destroy(&rdsiter);
1025 result = dns_diff_applysilently(&del, gdb, gversion);
1026 if (result != ISC_R_SUCCESS)
1027 fatal("failed to delete SIGs at node '%s': %s",
1028 namestr, isc_result_totext(result));
1030 result = dns_diff_applysilently(&add, gdb, gversion);
1031 if (result != ISC_R_SUCCESS)
1032 fatal("failed to add SIGs at node '%s': %s",
1033 namestr, isc_result_totext(result));
1035 dns_diff_clear(&del);
1036 dns_diff_clear(&add);
1039 static inline isc_boolean_t
1040 active_node(dns_dbnode_t *node) {
1041 dns_rdatasetiter_t *rdsiter = NULL;
1042 dns_rdatasetiter_t *rdsiter2 = NULL;
1043 isc_boolean_t active = ISC_FALSE;
1044 isc_result_t result;
1045 dns_rdataset_t rdataset;
1046 dns_rdatatype_t type;
1047 dns_rdatatype_t covers;
1048 isc_boolean_t found;
1050 dns_rdataset_init(&rdataset);
1051 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1052 check_result(result, "dns_db_allrdatasets()");
1053 result = dns_rdatasetiter_first(rdsiter);
1054 while (result == ISC_R_SUCCESS) {
1055 dns_rdatasetiter_current(rdsiter, &rdataset);
1056 if (rdataset.type != dns_rdatatype_nsec &&
1057 rdataset.type != dns_rdatatype_nsec3 &&
1058 rdataset.type != dns_rdatatype_rrsig)
1059 active = ISC_TRUE;
1060 dns_rdataset_disassociate(&rdataset);
1061 if (!active)
1062 result = dns_rdatasetiter_next(rdsiter);
1063 else
1064 result = ISC_R_NOMORE;
1066 if (result != ISC_R_NOMORE)
1067 fatal("rdataset iteration failed: %s",
1068 isc_result_totext(result));
1070 if (!active && nsec_datatype == dns_rdatatype_nsec) {
1072 * The node is empty of everything but NSEC / RRSIG records.
1074 for (result = dns_rdatasetiter_first(rdsiter);
1075 result == ISC_R_SUCCESS;
1076 result = dns_rdatasetiter_next(rdsiter)) {
1077 dns_rdatasetiter_current(rdsiter, &rdataset);
1078 result = dns_db_deleterdataset(gdb, node, gversion,
1079 rdataset.type,
1080 rdataset.covers);
1081 check_result(result, "dns_db_deleterdataset()");
1082 dns_rdataset_disassociate(&rdataset);
1084 if (result != ISC_R_NOMORE)
1085 fatal("rdataset iteration failed: %s",
1086 isc_result_totext(result));
1087 } else {
1089 * Delete RRSIGs for types that no longer exist.
1091 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
1092 check_result(result, "dns_db_allrdatasets()");
1093 for (result = dns_rdatasetiter_first(rdsiter);
1094 result == ISC_R_SUCCESS;
1095 result = dns_rdatasetiter_next(rdsiter)) {
1096 dns_rdatasetiter_current(rdsiter, &rdataset);
1097 type = rdataset.type;
1098 covers = rdataset.covers;
1099 dns_rdataset_disassociate(&rdataset);
1101 * Delete the NSEC chain if we are signing with
1102 * NSEC3.
1104 if (nsec_datatype == dns_rdatatype_nsec3 &&
1105 (type == dns_rdatatype_nsec ||
1106 covers == dns_rdatatype_nsec)) {
1107 result = dns_db_deleterdataset(gdb, node,
1108 gversion, type,
1109 covers);
1110 check_result(result,
1111 "dns_db_deleterdataset(nsec/rrsig)");
1112 continue;
1114 if (type != dns_rdatatype_rrsig)
1115 continue;
1116 found = ISC_FALSE;
1117 for (result = dns_rdatasetiter_first(rdsiter2);
1118 !found && result == ISC_R_SUCCESS;
1119 result = dns_rdatasetiter_next(rdsiter2)) {
1120 dns_rdatasetiter_current(rdsiter2, &rdataset);
1121 if (rdataset.type == covers)
1122 found = ISC_TRUE;
1123 dns_rdataset_disassociate(&rdataset);
1125 if (!found) {
1126 if (result != ISC_R_NOMORE)
1127 fatal("rdataset iteration failed: %s",
1128 isc_result_totext(result));
1129 result = dns_db_deleterdataset(gdb, node,
1130 gversion, type,
1131 covers);
1132 check_result(result,
1133 "dns_db_deleterdataset(rrsig)");
1134 } else if (result != ISC_R_NOMORE &&
1135 result != ISC_R_SUCCESS)
1136 fatal("rdataset iteration failed: %s",
1137 isc_result_totext(result));
1139 if (result != ISC_R_NOMORE)
1140 fatal("rdataset iteration failed: %s",
1141 isc_result_totext(result));
1142 dns_rdatasetiter_destroy(&rdsiter2);
1144 dns_rdatasetiter_destroy(&rdsiter);
1146 return (active);
1150 * Extracts the minimum TTL from the SOA record, and the SOA record's TTL.
1152 static void
1153 get_soa_ttls(void) {
1154 dns_rdataset_t soaset;
1155 dns_fixedname_t fname;
1156 dns_name_t *name;
1157 isc_result_t result;
1158 dns_rdata_t rdata = DNS_RDATA_INIT;
1160 dns_fixedname_init(&fname);
1161 name = dns_fixedname_name(&fname);
1162 dns_rdataset_init(&soaset);
1163 result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
1164 0, 0, NULL, name, &soaset, NULL);
1165 if (result != ISC_R_SUCCESS)
1166 fatal("failed to find an SOA at the zone apex: %s",
1167 isc_result_totext(result));
1169 result = dns_rdataset_first(&soaset);
1170 check_result(result, "dns_rdataset_first");
1171 dns_rdataset_current(&soaset, &rdata);
1172 zone_soa_min_ttl = dns_soa_getminimum(&rdata);
1173 soa_ttl = soaset.ttl;
1174 dns_rdataset_disassociate(&soaset);
1178 * Increment (or set if nonzero) the SOA serial
1180 static isc_result_t
1181 setsoaserial(isc_uint32_t serial) {
1182 isc_result_t result;
1183 dns_dbnode_t *node = NULL;
1184 dns_rdataset_t rdataset;
1185 dns_rdata_t rdata = DNS_RDATA_INIT;
1186 isc_uint32_t old_serial, new_serial;
1188 result = dns_db_getoriginnode(gdb, &node);
1189 if (result != ISC_R_SUCCESS)
1190 return result;
1192 dns_rdataset_init(&rdataset);
1194 result = dns_db_findrdataset(gdb, node, gversion,
1195 dns_rdatatype_soa, 0,
1196 0, &rdataset, NULL);
1197 if (result != ISC_R_SUCCESS)
1198 goto cleanup;
1200 result = dns_rdataset_first(&rdataset);
1201 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1203 dns_rdataset_current(&rdataset, &rdata);
1205 old_serial = dns_soa_getserial(&rdata);
1207 if (serial) {
1208 /* Set SOA serial to the value provided. */
1209 new_serial = serial;
1210 } else {
1211 /* Increment SOA serial using RFC 1982 arithmetics */
1212 new_serial = (old_serial + 1) & 0xFFFFFFFF;
1213 if (new_serial == 0)
1214 new_serial = 1;
1217 /* If the new serial is not likely to cause a zone transfer
1218 * (a/ixfr) from servers having the old serial, warn the user.
1220 * RFC1982 section 7 defines the maximum increment to be
1221 * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
1222 * comparison. (5 - 6 == (2^32)-1, not negative-one)
1224 if (new_serial == old_serial ||
1225 (new_serial - old_serial) > 0x7fffffffU)
1226 fprintf(stderr, "%s: warning: Serial number not advanced, "
1227 "zone may not transfer\n", program);
1229 dns_soa_setserial(new_serial, &rdata);
1231 result = dns_db_deleterdataset(gdb, node, gversion,
1232 dns_rdatatype_soa, 0);
1233 check_result(result, "dns_db_deleterdataset");
1234 if (result != ISC_R_SUCCESS)
1235 goto cleanup;
1237 result = dns_db_addrdataset(gdb, node, gversion,
1238 0, &rdataset, 0, NULL);
1239 check_result(result, "dns_db_addrdataset");
1240 if (result != ISC_R_SUCCESS)
1241 goto cleanup;
1243 cleanup:
1244 dns_rdataset_disassociate(&rdataset);
1245 if (node != NULL)
1246 dns_db_detachnode(gdb, &node);
1247 dns_rdata_reset(&rdata);
1249 return (result);
1253 * Delete any RRSIG records at a node.
1255 static void
1256 cleannode(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
1257 dns_rdatasetiter_t *rdsiter = NULL;
1258 dns_rdataset_t set;
1259 isc_result_t result, dresult;
1261 if (outputformat != dns_masterformat_text || !disable_zone_check)
1262 return;
1264 dns_rdataset_init(&set);
1265 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
1266 check_result(result, "dns_db_allrdatasets");
1267 result = dns_rdatasetiter_first(rdsiter);
1268 while (result == ISC_R_SUCCESS) {
1269 isc_boolean_t destroy = ISC_FALSE;
1270 dns_rdatatype_t covers = 0;
1271 dns_rdatasetiter_current(rdsiter, &set);
1272 if (set.type == dns_rdatatype_rrsig) {
1273 covers = set.covers;
1274 destroy = ISC_TRUE;
1276 dns_rdataset_disassociate(&set);
1277 result = dns_rdatasetiter_next(rdsiter);
1278 if (destroy) {
1279 dresult = dns_db_deleterdataset(db, node, version,
1280 dns_rdatatype_rrsig,
1281 covers);
1282 check_result(dresult, "dns_db_deleterdataset");
1285 if (result != ISC_R_NOMORE)
1286 fatal("rdataset iteration failed: %s",
1287 isc_result_totext(result));
1288 dns_rdatasetiter_destroy(&rdsiter);
1292 * Set up the iterator and global state before starting the tasks.
1294 static void
1295 presign(void) {
1296 isc_result_t result;
1298 gdbiter = NULL;
1299 result = dns_db_createiterator(gdb, 0, &gdbiter);
1300 check_result(result, "dns_db_createiterator()");
1304 * Clean up the iterator and global state after the tasks complete.
1306 static void
1307 postsign(void) {
1308 dns_dbiterator_destroy(&gdbiter);
1311 static isc_boolean_t
1312 goodsig(dns_rdata_t *sigrdata, dns_name_t *name, dns_rdataset_t *keyrdataset,
1313 dns_rdataset_t *rdataset)
1315 dns_rdata_dnskey_t key;
1316 dns_rdata_rrsig_t sig;
1317 dst_key_t *dstkey = NULL;
1318 isc_result_t result;
1320 dns_rdata_tostruct(sigrdata, &sig, NULL);
1322 for (result = dns_rdataset_first(keyrdataset);
1323 result == ISC_R_SUCCESS;
1324 result = dns_rdataset_next(keyrdataset)) {
1325 dns_rdata_t rdata = DNS_RDATA_INIT;
1326 dns_rdataset_current(keyrdataset, &rdata);
1327 dns_rdata_tostruct(&rdata, &key, NULL);
1328 result = dns_dnssec_keyfromrdata(gorigin, &rdata, mctx,
1329 &dstkey);
1330 if (result != ISC_R_SUCCESS)
1331 return (ISC_FALSE);
1332 if (sig.algorithm != key.algorithm ||
1333 sig.keyid != dst_key_id(dstkey) ||
1334 !dns_name_equal(&sig.signer, gorigin)) {
1335 dst_key_free(&dstkey);
1336 continue;
1338 result = dns_dnssec_verify(name, rdataset, dstkey, ISC_FALSE,
1339 mctx, sigrdata);
1340 dst_key_free(&dstkey);
1341 if (result == ISC_R_SUCCESS)
1342 return(ISC_TRUE);
1344 return (ISC_FALSE);
1347 static void
1348 verifyset(dns_rdataset_t *rdataset, dns_name_t *name, dns_dbnode_t *node,
1349 dns_rdataset_t *keyrdataset, unsigned char *ksk_algorithms,
1350 unsigned char *bad_algorithms)
1352 unsigned char set_algorithms[256];
1353 char namebuf[DNS_NAME_FORMATSIZE];
1354 char algbuf[80];
1355 char typebuf[80];
1356 dns_rdataset_t sigrdataset;
1357 dns_rdatasetiter_t *rdsiter = NULL;
1358 isc_result_t result;
1359 int i;
1361 dns_rdataset_init(&sigrdataset);
1362 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1363 check_result(result, "dns_db_allrdatasets()");
1364 for (result = dns_rdatasetiter_first(rdsiter);
1365 result == ISC_R_SUCCESS;
1366 result = dns_rdatasetiter_next(rdsiter)) {
1367 dns_rdatasetiter_current(rdsiter, &sigrdataset);
1368 if (sigrdataset.type == dns_rdatatype_rrsig &&
1369 sigrdataset.covers == rdataset->type)
1370 break;
1371 dns_rdataset_disassociate(&sigrdataset);
1373 if (result != ISC_R_SUCCESS) {
1374 dns_name_format(name, namebuf, sizeof(namebuf));
1375 type_format(rdataset->type, typebuf, sizeof(typebuf));
1376 fprintf(stderr, "no signatures for %s/%s\n", namebuf, typebuf);
1377 for (i = 0; i < 256; i++)
1378 if (ksk_algorithms[i] != 0)
1379 bad_algorithms[i] = 1;
1380 return;
1383 memset(set_algorithms, 0, sizeof(set_algorithms));
1384 for (result = dns_rdataset_first(&sigrdataset);
1385 result == ISC_R_SUCCESS;
1386 result = dns_rdataset_next(&sigrdataset)) {
1387 dns_rdata_t rdata = DNS_RDATA_INIT;
1388 dns_rdata_rrsig_t sig;
1390 dns_rdataset_current(&sigrdataset, &rdata);
1391 dns_rdata_tostruct(&rdata, &sig, NULL);
1392 if ((set_algorithms[sig.algorithm] != 0) ||
1393 (ksk_algorithms[sig.algorithm] == 0))
1394 continue;
1395 if (goodsig(&rdata, name, keyrdataset, rdataset))
1396 set_algorithms[sig.algorithm] = 1;
1398 dns_rdatasetiter_destroy(&rdsiter);
1399 if (memcmp(set_algorithms, ksk_algorithms, sizeof(set_algorithms))) {
1400 dns_name_format(name, namebuf, sizeof(namebuf));
1401 type_format(rdataset->type, typebuf, sizeof(typebuf));
1402 for (i = 0; i < 256; i++)
1403 if ((ksk_algorithms[i] != 0) &&
1404 (set_algorithms[i] == 0)) {
1405 dns_secalg_format(i, algbuf, sizeof(algbuf));
1406 fprintf(stderr, "Missing %s signature for "
1407 "%s %s\n", algbuf, namebuf, typebuf);
1408 bad_algorithms[i] = 1;
1411 dns_rdataset_disassociate(&sigrdataset);
1414 static void
1415 verifynode(dns_name_t *name, dns_dbnode_t *node, isc_boolean_t delegation,
1416 dns_rdataset_t *keyrdataset, unsigned char *ksk_algorithms,
1417 unsigned char *bad_algorithms)
1419 dns_rdataset_t rdataset;
1420 dns_rdatasetiter_t *rdsiter = NULL;
1421 isc_result_t result;
1423 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1424 check_result(result, "dns_db_allrdatasets()");
1425 result = dns_rdatasetiter_first(rdsiter);
1426 dns_rdataset_init(&rdataset);
1427 while (result == ISC_R_SUCCESS) {
1428 dns_rdatasetiter_current(rdsiter, &rdataset);
1429 if (rdataset.type != dns_rdatatype_rrsig &&
1430 rdataset.type != dns_rdatatype_dnskey &&
1431 (!delegation || rdataset.type == dns_rdatatype_ds ||
1432 rdataset.type == dns_rdatatype_nsec)) {
1433 verifyset(&rdataset, name, node, keyrdataset,
1434 ksk_algorithms, bad_algorithms);
1436 dns_rdataset_disassociate(&rdataset);
1437 result = dns_rdatasetiter_next(rdsiter);
1439 if (result != ISC_R_NOMORE)
1440 fatal("rdataset iteration failed: %s",
1441 isc_result_totext(result));
1442 dns_rdatasetiter_destroy(&rdsiter);
1446 * Verify that certain things are sane:
1448 * The apex has a DNSKEY record with at least one KSK, and at least
1449 * one ZSK if the -x flag was not used.
1451 * The DNSKEY record was signed with at least one of the KSKs in this
1452 * set.
1454 * The rest of the zone was signed with at least one of the ZSKs
1455 * present in the DNSKEY RRSET.
1457 static void
1458 verifyzone(void) {
1459 char algbuf[80];
1460 dns_dbiterator_t *dbiter = NULL;
1461 dns_dbnode_t *node = NULL, *nextnode = NULL;
1462 dns_fixedname_t fname, fnextname, fzonecut;
1463 dns_name_t *name, *nextname, *zonecut;
1464 dns_rdata_dnskey_t dnskey;
1465 dns_rdata_t rdata = DNS_RDATA_INIT;
1466 dns_rdataset_t rdataset;
1467 dns_rdataset_t sigrdataset;
1468 int i;
1469 isc_boolean_t done = ISC_FALSE;
1470 isc_boolean_t first = ISC_TRUE;
1471 isc_boolean_t goodksk = ISC_FALSE;
1472 isc_boolean_t goodzsk = ISC_FALSE;
1473 isc_result_t result;
1474 unsigned char revoked_ksk[256];
1475 unsigned char revoked_zsk[256];
1476 unsigned char standby_ksk[256];
1477 unsigned char standby_zsk[256];
1478 unsigned char ksk_algorithms[256];
1479 unsigned char zsk_algorithms[256];
1480 unsigned char bad_algorithms[256];
1481 #ifdef ALLOW_KSKLESS_ZONES
1482 isc_boolean_t allzsksigned = ISC_TRUE;
1483 unsigned char self_algorithms[256];
1484 #endif
1486 if (disable_zone_check)
1487 return;
1489 result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node);
1490 if (result != ISC_R_SUCCESS)
1491 fatal("failed to find the zone's origin: %s",
1492 isc_result_totext(result));
1494 dns_rdataset_init(&rdataset);
1495 dns_rdataset_init(&sigrdataset);
1496 result = dns_db_findrdataset(gdb, node, gversion,
1497 dns_rdatatype_dnskey,
1498 0, 0, &rdataset, &sigrdataset);
1499 dns_db_detachnode(gdb, &node);
1500 if (result != ISC_R_SUCCESS)
1501 fatal("cannot find DNSKEY rrset\n");
1503 if (!dns_rdataset_isassociated(&sigrdataset))
1504 fatal("cannot find DNSKEY RRSIGs\n");
1506 memset(revoked_ksk, 0, sizeof(revoked_ksk));
1507 memset(revoked_zsk, 0, sizeof(revoked_zsk));
1508 memset(standby_ksk, 0, sizeof(standby_ksk));
1509 memset(standby_zsk, 0, sizeof(standby_zsk));
1510 memset(ksk_algorithms, 0, sizeof(ksk_algorithms));
1511 memset(zsk_algorithms, 0, sizeof(zsk_algorithms));
1512 memset(bad_algorithms, 0, sizeof(bad_algorithms));
1513 #ifdef ALLOW_KSKLESS_ZONES
1514 memset(self_algorithms, 0, sizeof(self_algorithms));
1515 #endif
1518 * Check that the DNSKEY RR has at least one self signing KSK
1519 * and one ZSK per algorithm in it (or, if -x was used, one
1520 * self-signing KSK).
1522 for (result = dns_rdataset_first(&rdataset);
1523 result == ISC_R_SUCCESS;
1524 result = dns_rdataset_next(&rdataset)) {
1525 dns_rdataset_current(&rdataset, &rdata);
1526 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
1527 check_result(result, "dns_rdata_tostruct");
1529 if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0)
1531 else if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) {
1532 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1533 !dns_dnssec_selfsigns(&rdata, gorigin, &rdataset,
1534 &sigrdataset, ISC_FALSE,
1535 mctx)) {
1536 char namebuf[DNS_NAME_FORMATSIZE];
1537 char buffer[1024];
1538 isc_buffer_t buf;
1540 dns_name_format(gorigin, namebuf,
1541 sizeof(namebuf));
1542 isc_buffer_init(&buf, buffer, sizeof(buffer));
1543 result = dns_rdata_totext(&rdata, NULL, &buf);
1544 check_result(result, "dns_rdata_totext");
1545 fatal("revoked KSK is not self signed:\n"
1546 "%s DNSKEY %.*s", namebuf,
1547 (int)isc_buffer_usedlength(&buf), buffer);
1549 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1550 revoked_ksk[dnskey.algorithm] != 255)
1551 revoked_ksk[dnskey.algorithm]++;
1552 else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 &&
1553 revoked_zsk[dnskey.algorithm] != 255)
1554 revoked_zsk[dnskey.algorithm]++;
1555 } else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) {
1556 if (dns_dnssec_selfsigns(&rdata, gorigin, &rdataset,
1557 &sigrdataset, ISC_FALSE, mctx)) {
1558 if (ksk_algorithms[dnskey.algorithm] != 255)
1559 ksk_algorithms[dnskey.algorithm]++;
1560 goodksk = ISC_TRUE;
1561 } else {
1562 if (standby_ksk[dnskey.algorithm] != 255)
1563 standby_ksk[dnskey.algorithm]++;
1565 } else if (dns_dnssec_selfsigns(&rdata, gorigin, &rdataset,
1566 &sigrdataset, ISC_FALSE,
1567 mctx)) {
1568 #ifdef ALLOW_KSKLESS_ZONES
1569 if (self_algorithms[dnskey.algorithm] != 255)
1570 self_algorithms[dnskey.algorithm]++;
1571 #endif
1572 if (zsk_algorithms[dnskey.algorithm] != 255)
1573 zsk_algorithms[dnskey.algorithm]++;
1574 goodzsk = ISC_TRUE;
1575 } else {
1576 if (standby_zsk[dnskey.algorithm] != 255)
1577 standby_zsk[dnskey.algorithm]++;
1578 #ifdef ALLOW_KSKLESS_ZONES
1579 allzsksigned = ISC_FALSE;
1580 #endif
1582 dns_rdata_freestruct(&dnskey);
1583 dns_rdata_reset(&rdata);
1585 dns_rdataset_disassociate(&sigrdataset);
1587 #ifdef ALLOW_KSKLESS_ZONES
1588 if (!goodksk) {
1589 if (!ignore_kskflag)
1590 fprintf(stderr, "No self signing KSK found. Using "
1591 "self signed ZSK's for active "
1592 "algorithm list.\n");
1593 memcpy(ksk_algorithms, self_algorithms, sizeof(ksk_algorithms));
1594 if (!allzsksigned)
1595 fprintf(stderr, "warning: not all ZSK's are self "
1596 "signed.\n");
1598 #else
1599 if (!goodksk) {
1600 fatal("no self signed KSK's found");
1602 #endif
1604 fprintf(stderr, "Verifying the zone using the following algorithms:");
1605 for (i = 0; i < 256; i++) {
1606 #ifdef ALLOW_KSKLESS_ZONES
1607 if (ksk_algorithms[i] != 0 || zsk_algorithms[i] != 0)
1608 #else
1609 if (ksk_algorithms[i] != 0)
1610 #endif
1612 dns_secalg_format(i, algbuf, sizeof(algbuf));
1613 fprintf(stderr, " %s", algbuf);
1616 fprintf(stderr, ".\n");
1618 if (!ignore_kskflag && !keyset_kskonly) {
1619 for (i = 0; i < 256; i++) {
1621 * The counts should both be zero or both be non-zero.
1622 * Mark the algorithm as bad if this is not met.
1624 if ((ksk_algorithms[i] != 0) ==
1625 (zsk_algorithms[i] != 0))
1626 continue;
1627 dns_secalg_format(i, algbuf, sizeof(algbuf));
1628 fprintf(stderr, "Missing %s for algorithm %s\n",
1629 (ksk_algorithms[i] != 0)
1630 ? "ZSK"
1631 : "self signing KSK",
1632 algbuf);
1633 bad_algorithms[i] = 1;
1638 * Check that all the other records were signed by keys that are
1639 * present in the DNSKEY RRSET.
1642 dns_fixedname_init(&fname);
1643 name = dns_fixedname_name(&fname);
1644 dns_fixedname_init(&fnextname);
1645 nextname = dns_fixedname_name(&fnextname);
1646 dns_fixedname_init(&fzonecut);
1647 zonecut = NULL;
1649 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
1650 check_result(result, "dns_db_createiterator()");
1652 result = dns_dbiterator_first(dbiter);
1653 check_result(result, "dns_dbiterator_first()");
1655 while (!done) {
1656 isc_boolean_t isdelegation = ISC_FALSE;
1658 result = dns_dbiterator_current(dbiter, &node, name);
1659 check_dns_dbiterator_current(result);
1660 if (delegation(name, node, NULL)) {
1661 zonecut = dns_fixedname_name(&fzonecut);
1662 dns_name_copy(name, zonecut, NULL);
1663 isdelegation = ISC_TRUE;
1665 verifynode(name, node, isdelegation, &rdataset,
1666 ksk_algorithms, bad_algorithms);
1667 result = dns_dbiterator_next(dbiter);
1668 nextnode = NULL;
1669 while (result == ISC_R_SUCCESS) {
1670 result = dns_dbiterator_current(dbiter, &nextnode,
1671 nextname);
1672 check_dns_dbiterator_current(result);
1673 if (!dns_name_issubdomain(nextname, gorigin) ||
1674 (zonecut != NULL &&
1675 dns_name_issubdomain(nextname, zonecut)))
1677 dns_db_detachnode(gdb, &nextnode);
1678 result = dns_dbiterator_next(dbiter);
1679 continue;
1681 dns_db_detachnode(gdb, &nextnode);
1682 break;
1684 if (result == ISC_R_NOMORE) {
1685 done = ISC_TRUE;
1686 } else if (result != ISC_R_SUCCESS)
1687 fatal("iterating through the database failed: %s",
1688 isc_result_totext(result));
1689 dns_db_detachnode(gdb, &node);
1692 dns_dbiterator_destroy(&dbiter);
1694 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
1695 check_result(result, "dns_db_createiterator()");
1697 for (result = dns_dbiterator_first(dbiter);
1698 result == ISC_R_SUCCESS;
1699 result = dns_dbiterator_next(dbiter) ) {
1700 result = dns_dbiterator_current(dbiter, &node, name);
1701 check_dns_dbiterator_current(result);
1702 verifynode(name, node, ISC_FALSE, &rdataset,
1703 ksk_algorithms, bad_algorithms);
1704 dns_db_detachnode(gdb, &node);
1706 dns_dbiterator_destroy(&dbiter);
1708 dns_rdataset_disassociate(&rdataset);
1711 * If we made it this far, we have what we consider a properly signed
1712 * zone. Set the good flag.
1714 for (i = 0; i < 256; i++) {
1715 if (bad_algorithms[i] != 0) {
1716 if (first)
1717 fprintf(stderr, "The zone is not fully signed "
1718 "for the following algorithms:");
1719 dns_secalg_format(i, algbuf, sizeof(algbuf));
1720 fprintf(stderr, " %s", algbuf);
1721 first = ISC_FALSE;
1724 if (!first) {
1725 fprintf(stderr, ".\n");
1726 fatal("DNSSEC completeness test failed.");
1729 if (goodksk || ignore_kskflag) {
1731 * Print the success summary.
1733 fprintf(stderr, "Zone signing complete:\n");
1734 for (i = 0; i < 256; i++) {
1735 if ((ksk_algorithms[i] != 0) ||
1736 (standby_ksk[i] != 0) ||
1737 (revoked_zsk[i] != 0) ||
1738 (zsk_algorithms[i] != 0) ||
1739 (standby_zsk[i] != 0) ||
1740 (revoked_zsk[i] != 0)) {
1741 dns_secalg_format(i, algbuf, sizeof(algbuf));
1742 fprintf(stderr, "Algorithm: %s: KSKs: "
1743 "%u active, %u stand-by, %u revoked\n",
1744 algbuf, ksk_algorithms[i],
1745 standby_ksk[i], revoked_ksk[i]);
1746 fprintf(stderr, "%*sZSKs: "
1747 "%u active, %u %s, %u revoked\n",
1748 (int) strlen(algbuf) + 13, "",
1749 zsk_algorithms[i],
1750 standby_zsk[i],
1751 keyset_kskonly ? "present" : "stand-by",
1752 revoked_zsk[i]);
1759 * Sign the apex of the zone.
1760 * Note the origin may not be the first node if there are out of zone
1761 * records.
1763 static void
1764 signapex(void) {
1765 dns_dbnode_t *node = NULL;
1766 dns_fixedname_t fixed;
1767 dns_name_t *name;
1768 isc_result_t result;
1770 dns_fixedname_init(&fixed);
1771 name = dns_fixedname_name(&fixed);
1772 result = dns_dbiterator_seek(gdbiter, gorigin);
1773 check_result(result, "dns_dbiterator_seek()");
1774 result = dns_dbiterator_current(gdbiter, &node, name);
1775 check_dns_dbiterator_current(result);
1776 signname(node, name);
1777 dumpnode(name, node);
1778 cleannode(gdb, gversion, node);
1779 dns_db_detachnode(gdb, &node);
1780 result = dns_dbiterator_first(gdbiter);
1781 if (result == ISC_R_NOMORE)
1782 finished = ISC_TRUE;
1783 else if (result != ISC_R_SUCCESS)
1784 fatal("failure iterating database: %s",
1785 isc_result_totext(result));
1789 * Assigns a node to a worker thread. This is protected by the master task's
1790 * lock.
1792 static void
1793 assignwork(isc_task_t *task, isc_task_t *worker) {
1794 dns_fixedname_t *fname;
1795 dns_name_t *name;
1796 dns_dbnode_t *node;
1797 sevent_t *sevent;
1798 dns_rdataset_t nsec;
1799 isc_boolean_t found;
1800 isc_result_t result;
1801 static dns_name_t *zonecut = NULL; /* Protected by namelock. */
1802 static dns_fixedname_t fzonecut; /* Protected by namelock. */
1803 static unsigned int ended = 0; /* Protected by namelock. */
1805 if (shuttingdown)
1806 return;
1808 LOCK(&namelock);
1809 if (finished) {
1810 ended++;
1811 if (ended == ntasks) {
1812 isc_task_detach(&task);
1813 isc_app_shutdown();
1815 goto unlock;
1818 fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
1819 if (fname == NULL)
1820 fatal("out of memory");
1821 dns_fixedname_init(fname);
1822 name = dns_fixedname_name(fname);
1823 node = NULL;
1824 found = ISC_FALSE;
1825 while (!found) {
1826 result = dns_dbiterator_current(gdbiter, &node, name);
1827 check_dns_dbiterator_current(result);
1829 * The origin was handled by signapex().
1831 if (dns_name_equal(name, gorigin)) {
1832 dns_db_detachnode(gdb, &node);
1833 goto next;
1836 * Sort the zone data from the glue and out-of-zone data.
1837 * For NSEC zones nodes with zone data have NSEC records.
1838 * For NSEC3 zones the NSEC3 nodes are zone data but
1839 * outside of the zone name space. For the rest we need
1840 * to track the bottom of zone cuts.
1841 * Nodes which don't need to be signed are dumped here.
1843 dns_rdataset_init(&nsec);
1844 result = dns_db_findrdataset(gdb, node, gversion,
1845 nsec_datatype, 0, 0,
1846 &nsec, NULL);
1847 if (dns_rdataset_isassociated(&nsec))
1848 dns_rdataset_disassociate(&nsec);
1849 if (result == ISC_R_SUCCESS) {
1850 found = ISC_TRUE;
1851 } else if (nsec_datatype == dns_rdatatype_nsec3) {
1852 if (dns_name_issubdomain(name, gorigin) &&
1853 (zonecut == NULL ||
1854 !dns_name_issubdomain(name, zonecut))) {
1855 if (delegation(name, node, NULL)) {
1856 dns_fixedname_init(&fzonecut);
1857 zonecut = dns_fixedname_name(&fzonecut);
1858 dns_name_copy(name, zonecut, NULL);
1859 if (!OPTOUT(nsec3flags) ||
1860 secure(name, node))
1861 found = ISC_TRUE;
1862 } else
1863 found = ISC_TRUE;
1867 if (!found) {
1868 dumpnode(name, node);
1869 dns_db_detachnode(gdb, &node);
1872 next:
1873 result = dns_dbiterator_next(gdbiter);
1874 if (result == ISC_R_NOMORE) {
1875 finished = ISC_TRUE;
1876 break;
1877 } else if (result != ISC_R_SUCCESS)
1878 fatal("failure iterating database: %s",
1879 isc_result_totext(result));
1881 if (!found) {
1882 ended++;
1883 if (ended == ntasks) {
1884 isc_task_detach(&task);
1885 isc_app_shutdown();
1887 isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
1888 goto unlock;
1890 sevent = (sevent_t *)
1891 isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
1892 sign, NULL, sizeof(sevent_t));
1893 if (sevent == NULL)
1894 fatal("failed to allocate event\n");
1896 sevent->node = node;
1897 sevent->fname = fname;
1898 isc_task_send(worker, ISC_EVENT_PTR(&sevent));
1899 unlock:
1900 UNLOCK(&namelock);
1904 * Start a worker task
1906 static void
1907 startworker(isc_task_t *task, isc_event_t *event) {
1908 isc_task_t *worker;
1910 worker = (isc_task_t *)event->ev_arg;
1911 assignwork(task, worker);
1912 isc_event_free(&event);
1916 * Write a node to the output file, and restart the worker task.
1918 static void
1919 writenode(isc_task_t *task, isc_event_t *event) {
1920 isc_task_t *worker;
1921 sevent_t *sevent = (sevent_t *)event;
1923 worker = (isc_task_t *)event->ev_sender;
1924 dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
1925 cleannode(gdb, gversion, sevent->node);
1926 dns_db_detachnode(gdb, &sevent->node);
1927 isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
1928 assignwork(task, worker);
1929 isc_event_free(&event);
1933 * Sign a database node.
1935 static void
1936 sign(isc_task_t *task, isc_event_t *event) {
1937 dns_fixedname_t *fname;
1938 dns_dbnode_t *node;
1939 sevent_t *sevent, *wevent;
1941 sevent = (sevent_t *)event;
1942 node = sevent->node;
1943 fname = sevent->fname;
1944 isc_event_free(&event);
1946 signname(node, dns_fixedname_name(fname));
1947 wevent = (sevent_t *)
1948 isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
1949 writenode, NULL, sizeof(sevent_t));
1950 if (wevent == NULL)
1951 fatal("failed to allocate event\n");
1952 wevent->node = node;
1953 wevent->fname = fname;
1954 isc_task_send(master, ISC_EVENT_PTR(&wevent));
1958 * Update / remove the DS RRset. Preserve RRSIG(DS) if possible.
1960 static void
1961 add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) {
1962 dns_rdataset_t dsset;
1963 dns_rdataset_t sigdsset;
1964 isc_result_t result;
1966 dns_rdataset_init(&dsset);
1967 dns_rdataset_init(&sigdsset);
1968 result = dns_db_findrdataset(gdb, node, gversion,
1969 dns_rdatatype_ds,
1970 0, 0, &dsset, &sigdsset);
1971 if (result == ISC_R_SUCCESS) {
1972 dns_rdataset_disassociate(&dsset);
1973 result = dns_db_deleterdataset(gdb, node, gversion,
1974 dns_rdatatype_ds, 0);
1975 check_result(result, "dns_db_deleterdataset");
1978 result = loadds(name, nsttl, &dsset);
1979 if (result == ISC_R_SUCCESS) {
1980 result = dns_db_addrdataset(gdb, node, gversion, 0,
1981 &dsset, 0, NULL);
1982 check_result(result, "dns_db_addrdataset");
1983 dns_rdataset_disassociate(&dsset);
1984 if (dns_rdataset_isassociated(&sigdsset))
1985 dns_rdataset_disassociate(&sigdsset);
1986 } else if (dns_rdataset_isassociated(&sigdsset)) {
1987 result = dns_db_deleterdataset(gdb, node, gversion,
1988 dns_rdatatype_rrsig,
1989 dns_rdatatype_ds);
1990 check_result(result, "dns_db_deleterdataset");
1991 dns_rdataset_disassociate(&sigdsset);
1996 * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records.
1998 static void
1999 nsecify(void) {
2000 dns_dbiterator_t *dbiter = NULL;
2001 dns_dbnode_t *node = NULL, *nextnode = NULL;
2002 dns_fixedname_t fname, fnextname, fzonecut;
2003 dns_name_t *name, *nextname, *zonecut;
2004 dns_rdataset_t rdataset;
2005 dns_rdatasetiter_t *rdsiter = NULL;
2006 dns_rdatatype_t type, covers;
2007 isc_boolean_t done = ISC_FALSE;
2008 isc_result_t result;
2009 isc_uint32_t nsttl = 0;
2011 dns_rdataset_init(&rdataset);
2012 dns_fixedname_init(&fname);
2013 name = dns_fixedname_name(&fname);
2014 dns_fixedname_init(&fnextname);
2015 nextname = dns_fixedname_name(&fnextname);
2016 dns_fixedname_init(&fzonecut);
2017 zonecut = NULL;
2020 * Remove any NSEC3 chains.
2022 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
2023 check_result(result, "dns_db_createiterator()");
2024 for (result = dns_dbiterator_first(dbiter);
2025 result == ISC_R_SUCCESS;
2026 result = dns_dbiterator_next(dbiter)) {
2027 result = dns_dbiterator_current(dbiter, &node, name);
2028 check_dns_dbiterator_current(result);
2029 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
2030 check_result(result, "dns_db_allrdatasets()");
2031 for (result = dns_rdatasetiter_first(rdsiter);
2032 result == ISC_R_SUCCESS;
2033 result = dns_rdatasetiter_next(rdsiter)) {
2034 dns_rdatasetiter_current(rdsiter, &rdataset);
2035 type = rdataset.type;
2036 covers = rdataset.covers;
2037 dns_rdataset_disassociate(&rdataset);
2038 result = dns_db_deleterdataset(gdb, node, gversion,
2039 type, covers);
2040 check_result(result,
2041 "dns_db_deleterdataset(nsec3param/rrsig)");
2043 dns_rdatasetiter_destroy(&rdsiter);
2044 dns_db_detachnode(gdb, &node);
2046 dns_dbiterator_destroy(&dbiter);
2048 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2049 check_result(result, "dns_db_createiterator()");
2051 result = dns_dbiterator_first(dbiter);
2052 check_result(result, "dns_dbiterator_first()");
2054 result = dns_dbiterator_current(dbiter, &node, name);
2055 check_dns_dbiterator_current(result);
2058 * Delete any NSEC3PARAM records at the apex.
2060 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
2061 check_result(result, "dns_db_allrdatasets()");
2062 for (result = dns_rdatasetiter_first(rdsiter);
2063 result == ISC_R_SUCCESS;
2064 result = dns_rdatasetiter_next(rdsiter)) {
2065 dns_rdatasetiter_current(rdsiter, &rdataset);
2066 type = rdataset.type;
2067 covers = rdataset.covers;
2068 dns_rdataset_disassociate(&rdataset);
2069 if (type == dns_rdatatype_nsec3param ||
2070 covers == dns_rdatatype_nsec3param) {
2071 result = dns_db_deleterdataset(gdb, node, gversion,
2072 type, covers);
2073 check_result(result,
2074 "dns_db_deleterdataset(nsec3param/rrsig)");
2075 continue;
2078 dns_rdatasetiter_destroy(&rdsiter);
2079 dns_db_detachnode(gdb, &node);
2081 while (!done) {
2082 result = dns_dbiterator_current(dbiter, &node, name);
2083 check_dns_dbiterator_current(result);
2084 if (delegation(name, node, &nsttl)) {
2085 zonecut = dns_fixedname_name(&fzonecut);
2086 dns_name_copy(name, zonecut, NULL);
2087 if (generateds)
2088 add_ds(name, node, nsttl);
2090 result = dns_dbiterator_next(dbiter);
2091 nextnode = NULL;
2092 while (result == ISC_R_SUCCESS) {
2093 isc_boolean_t active = ISC_FALSE;
2094 result = dns_dbiterator_current(dbiter, &nextnode,
2095 nextname);
2096 check_dns_dbiterator_current(result);
2097 active = active_node(nextnode);
2098 if (!active) {
2099 dns_db_detachnode(gdb, &nextnode);
2100 result = dns_dbiterator_next(dbiter);
2101 continue;
2103 if (!dns_name_issubdomain(nextname, gorigin) ||
2104 (zonecut != NULL &&
2105 dns_name_issubdomain(nextname, zonecut)))
2107 dns_db_detachnode(gdb, &nextnode);
2108 result = dns_dbiterator_next(dbiter);
2109 continue;
2111 dns_db_detachnode(gdb, &nextnode);
2112 break;
2114 if (result == ISC_R_NOMORE) {
2115 dns_name_clone(gorigin, nextname);
2116 done = ISC_TRUE;
2117 } else if (result != ISC_R_SUCCESS)
2118 fatal("iterating through the database failed: %s",
2119 isc_result_totext(result));
2120 dns_dbiterator_pause(dbiter);
2121 result = dns_nsec_build(gdb, gversion, node, nextname,
2122 zone_soa_min_ttl);
2123 check_result(result, "dns_nsec_build()");
2124 dns_db_detachnode(gdb, &node);
2127 dns_dbiterator_destroy(&dbiter);
2130 static void
2131 addnsec3param(const unsigned char *salt, size_t salt_length,
2132 unsigned int iterations)
2134 dns_dbnode_t *node = NULL;
2135 dns_rdata_nsec3param_t nsec3param;
2136 unsigned char nsec3parambuf[5 + 255];
2137 dns_rdatalist_t rdatalist;
2138 dns_rdataset_t rdataset;
2139 dns_rdata_t rdata = DNS_RDATA_INIT;
2140 isc_buffer_t b;
2141 isc_result_t result;
2143 dns_rdataset_init(&rdataset);
2145 nsec3param.common.rdclass = gclass;
2146 nsec3param.common.rdtype = dns_rdatatype_nsec3param;
2147 ISC_LINK_INIT(&nsec3param.common, link);
2148 nsec3param.mctx = NULL;
2149 nsec3param.flags = 0;
2150 nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1;
2151 nsec3param.iterations = iterations;
2152 nsec3param.salt_length = salt_length;
2153 DE_CONST(salt, nsec3param.salt);
2155 isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf));
2156 result = dns_rdata_fromstruct(&rdata, gclass,
2157 dns_rdatatype_nsec3param,
2158 &nsec3param, &b);
2159 rdatalist.rdclass = rdata.rdclass;
2160 rdatalist.type = rdata.type;
2161 rdatalist.covers = 0;
2162 rdatalist.ttl = 0;
2163 ISC_LIST_INIT(rdatalist.rdata);
2164 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
2165 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
2166 check_result(result, "dns_rdatalist_tordataset()");
2168 result = dns_db_findnode(gdb, gorigin, ISC_TRUE, &node);
2169 check_result(result, "dns_db_find(gorigin)");
2172 * Delete any current NSEC3PARAM records.
2174 result = dns_db_deleterdataset(gdb, node, gversion,
2175 dns_rdatatype_nsec3param, 0);
2176 if (result == DNS_R_UNCHANGED)
2177 result = ISC_R_SUCCESS;
2178 check_result(result, "dddnsec3param: dns_db_deleterdataset()");
2180 result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset,
2181 DNS_DBADD_MERGE, NULL);
2182 if (result == DNS_R_UNCHANGED)
2183 result = ISC_R_SUCCESS;
2184 check_result(result, "addnsec3param: dns_db_addrdataset()");
2185 dns_db_detachnode(gdb, &node);
2188 static void
2189 addnsec3(dns_name_t *name, dns_dbnode_t *node,
2190 const unsigned char *salt, size_t salt_length,
2191 unsigned int iterations, hashlist_t *hashlist,
2192 dns_ttl_t ttl)
2194 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
2195 const unsigned char *nexthash;
2196 unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE];
2197 dns_fixedname_t hashname;
2198 dns_rdatalist_t rdatalist;
2199 dns_rdataset_t rdataset;
2200 dns_rdata_t rdata = DNS_RDATA_INIT;
2201 isc_result_t result;
2202 dns_dbnode_t *nsec3node = NULL;
2203 char namebuf[DNS_NAME_FORMATSIZE];
2204 size_t hash_length;
2206 dns_name_format(name, namebuf, sizeof(namebuf));
2208 dns_fixedname_init(&hashname);
2209 dns_rdataset_init(&rdataset);
2211 dns_name_downcase(name, name, NULL);
2212 result = dns_nsec3_hashname(&hashname, hash, &hash_length,
2213 name, gorigin, dns_hash_sha1, iterations,
2214 salt, salt_length);
2215 check_result(result, "addnsec3: dns_nsec3_hashname()");
2216 nexthash = hashlist_findnext(hashlist, hash);
2217 result = dns_nsec3_buildrdata(gdb, gversion, node,
2218 unknownalg ?
2219 DNS_NSEC3_UNKNOWNALG : dns_hash_sha1,
2220 nsec3flags, iterations,
2221 salt, salt_length,
2222 nexthash, ISC_SHA1_DIGESTLENGTH,
2223 nsec3buffer, &rdata);
2224 check_result(result, "addnsec3: dns_nsec3_buildrdata()");
2225 rdatalist.rdclass = rdata.rdclass;
2226 rdatalist.type = rdata.type;
2227 rdatalist.covers = 0;
2228 rdatalist.ttl = ttl;
2229 ISC_LIST_INIT(rdatalist.rdata);
2230 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
2231 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
2232 check_result(result, "dns_rdatalist_tordataset()");
2233 result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname),
2234 ISC_TRUE, &nsec3node);
2235 check_result(result, "addnsec3: dns_db_findnode()");
2236 result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset,
2237 0, NULL);
2238 if (result == DNS_R_UNCHANGED)
2239 result = ISC_R_SUCCESS;
2240 check_result(result, "addnsec3: dns_db_addrdataset()");
2241 dns_db_detachnode(gdb, &nsec3node);
2245 * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list.
2247 * Extract the hash from the first label of 'name' then see if it
2248 * is in hashlist. If 'name' is not in the hashlist then delete the
2249 * any NSEC3 records which have the same parameters as the chain we
2250 * are building.
2252 * XXXMPA Should we also check that it of the form <hash>.<origin>?
2254 static void
2255 nsec3clean(dns_name_t *name, dns_dbnode_t *node,
2256 unsigned int hashalg, unsigned int iterations,
2257 const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
2259 dns_label_t label;
2260 dns_rdata_nsec3_t nsec3;
2261 dns_rdata_t rdata, delrdata;
2262 dns_rdatalist_t rdatalist;
2263 dns_rdataset_t rdataset, delrdataset;
2264 isc_boolean_t delete_rrsigs = ISC_FALSE;
2265 isc_buffer_t target;
2266 isc_result_t result;
2267 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
2268 isc_boolean_t exists;
2271 * Get the first label.
2273 dns_name_getlabel(name, 0, &label);
2276 * We want just the label contents.
2278 isc_region_consume(&label, 1);
2281 * Decode base32hex string.
2283 isc_buffer_init(&target, hash, sizeof(hash) - 1);
2284 result = isc_base32hex_decoderegion(&label, &target);
2285 if (result != ISC_R_SUCCESS)
2286 return;
2288 hash[isc_buffer_usedlength(&target)] = 0;
2290 exists = hashlist_exists(hashlist, hash);
2293 * Verify that the NSEC3 parameters match the current ones
2294 * otherwise we are dealing with a different NSEC3 chain.
2296 dns_rdataset_init(&rdataset);
2297 dns_rdataset_init(&delrdataset);
2299 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3,
2300 0, 0, &rdataset, NULL);
2301 if (result != ISC_R_SUCCESS)
2302 return;
2305 * Delete any NSEC3 records which are not part of the current
2306 * NSEC3 chain.
2308 for (result = dns_rdataset_first(&rdataset);
2309 result == ISC_R_SUCCESS;
2310 result = dns_rdataset_next(&rdataset)) {
2311 dns_rdata_init(&rdata);
2312 dns_rdataset_current(&rdataset, &rdata);
2313 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
2314 check_result(result, "dns_rdata_tostruct");
2315 if (exists && nsec3.hash == hashalg &&
2316 nsec3.iterations == iterations &&
2317 nsec3.salt_length == salt_length &&
2318 !memcmp(nsec3.salt, salt, salt_length))
2319 continue;
2320 rdatalist.rdclass = rdata.rdclass;
2321 rdatalist.type = rdata.type;
2322 rdatalist.covers = 0;
2323 rdatalist.ttl = rdataset.ttl;
2324 ISC_LIST_INIT(rdatalist.rdata);
2325 dns_rdata_init(&delrdata);
2326 dns_rdata_clone(&rdata, &delrdata);
2327 ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link);
2328 result = dns_rdatalist_tordataset(&rdatalist, &delrdataset);
2329 check_result(result, "dns_rdatalist_tordataset()");
2330 result = dns_db_subtractrdataset(gdb, node, gversion,
2331 &delrdataset, 0, NULL);
2332 dns_rdataset_disassociate(&delrdataset);
2333 if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET)
2334 check_result(result, "dns_db_subtractrdataset(NSEC3)");
2335 delete_rrsigs = ISC_TRUE;
2337 dns_rdataset_disassociate(&rdataset);
2338 if (result != ISC_R_NOMORE)
2339 check_result(result, "dns_rdataset_first/next");
2341 if (!delete_rrsigs)
2342 return;
2344 * Delete the NSEC3 RRSIGs
2346 result = dns_db_deleterdataset(gdb, node, gversion,
2347 dns_rdatatype_rrsig,
2348 dns_rdatatype_nsec3);
2349 if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
2350 check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))");
2353 static void
2354 rrset_remove_duplicates(dns_name_t *name, dns_rdataset_t *rdataset,
2355 dns_diff_t *diff)
2357 dns_difftuple_t *tuple = NULL;
2358 isc_result_t result;
2359 unsigned int count1 = 0;
2360 dns_rdataset_t tmprdataset;
2362 dns_rdataset_init(&tmprdataset);
2363 for (result = dns_rdataset_first(rdataset);
2364 result == ISC_R_SUCCESS;
2365 result = dns_rdataset_next(rdataset)) {
2366 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2367 unsigned int count2 = 0;
2369 count1++;
2370 dns_rdataset_current(rdataset, &rdata1);
2371 dns_rdataset_clone(rdataset, &tmprdataset);
2372 for (result = dns_rdataset_first(&tmprdataset);
2373 result == ISC_R_SUCCESS;
2374 result = dns_rdataset_next(&tmprdataset)) {
2375 dns_rdata_t rdata2 = DNS_RDATA_INIT;
2376 count2++;
2377 if (count1 >= count2)
2378 continue;
2379 dns_rdataset_current(&tmprdataset, &rdata2);
2380 if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2381 result = dns_difftuple_create(mctx,
2382 DNS_DIFFOP_DEL,
2383 name,
2384 rdataset->ttl,
2385 &rdata2, &tuple);
2386 check_result(result, "dns_difftuple_create");
2387 dns_diff_append(diff, &tuple);
2390 dns_rdataset_disassociate(&tmprdataset);
2394 static void
2395 remove_duplicates(void) {
2396 isc_result_t result;
2397 dns_dbiterator_t *dbiter = NULL;
2398 dns_rdatasetiter_t *rdsiter = NULL;
2399 dns_diff_t diff;
2400 dns_dbnode_t *node = NULL;
2401 dns_rdataset_t rdataset;
2402 dns_fixedname_t fname;
2403 dns_name_t *name;
2405 dns_diff_init(mctx, &diff);
2406 dns_fixedname_init(&fname);
2407 name = dns_fixedname_name(&fname);
2408 dns_rdataset_init(&rdataset);
2410 result = dns_db_createiterator(gdb, 0, &dbiter);
2411 check_result(result, "dns_db_createiterator()");
2413 for (result = dns_dbiterator_first(dbiter);
2414 result == ISC_R_SUCCESS;
2415 result = dns_dbiterator_next(dbiter)) {
2417 result = dns_dbiterator_current(dbiter, &node, name);
2418 check_dns_dbiterator_current(result);
2419 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
2420 check_result(result, "dns_db_allrdatasets()");
2421 for (result = dns_rdatasetiter_first(rdsiter);
2422 result == ISC_R_SUCCESS;
2423 result = dns_rdatasetiter_next(rdsiter)) {
2424 dns_rdatasetiter_current(rdsiter, &rdataset);
2425 rrset_remove_duplicates(name, &rdataset, &diff);
2426 dns_rdataset_disassociate(&rdataset);
2428 if (result != ISC_R_NOMORE)
2429 fatal("rdatasets iteration failed.");
2430 dns_rdatasetiter_destroy(&rdsiter);
2431 dns_db_detachnode(gdb, &node);
2433 if (result != ISC_R_NOMORE)
2434 fatal("zone iteration failed.");
2436 if (!ISC_LIST_EMPTY(diff.tuples)) {
2437 result = dns_diff_applysilently(&diff, gdb, gversion);
2438 check_result(result, "dns_diff_applysilently");
2440 dns_diff_clear(&diff);
2441 dns_dbiterator_destroy(&dbiter);
2445 * Generate NSEC3 records for the zone.
2447 static void
2448 nsec3ify(unsigned int hashalg, unsigned int iterations,
2449 const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
2451 dns_dbiterator_t *dbiter = NULL;
2452 dns_dbnode_t *node = NULL, *nextnode = NULL;
2453 dns_fixedname_t fname, fnextname, fzonecut;
2454 dns_name_t *name, *nextname, *zonecut;
2455 dns_rdataset_t rdataset;
2456 dns_rdatasetiter_t *rdsiter = NULL;
2457 dns_rdatatype_t type, covers;
2458 int order;
2459 isc_boolean_t active;
2460 isc_boolean_t done = ISC_FALSE;
2461 isc_result_t result;
2462 isc_uint32_t nsttl = 0;
2463 unsigned int count, nlabels;
2465 dns_rdataset_init(&rdataset);
2466 dns_fixedname_init(&fname);
2467 name = dns_fixedname_name(&fname);
2468 dns_fixedname_init(&fnextname);
2469 nextname = dns_fixedname_name(&fnextname);
2470 dns_fixedname_init(&fzonecut);
2471 zonecut = NULL;
2474 * Walk the zone generating the hash names.
2476 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2477 check_result(result, "dns_db_createiterator()");
2479 result = dns_dbiterator_first(dbiter);
2480 check_result(result, "dns_dbiterator_first()");
2482 result = dns_dbiterator_current(dbiter, &node, name);
2483 check_dns_dbiterator_current(result);
2486 * Delete any NSEC records at the apex.
2488 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
2489 check_result(result, "dns_db_allrdatasets()");
2490 for (result = dns_rdatasetiter_first(rdsiter);
2491 result == ISC_R_SUCCESS;
2492 result = dns_rdatasetiter_next(rdsiter)) {
2493 dns_rdatasetiter_current(rdsiter, &rdataset);
2494 type = rdataset.type;
2495 covers = rdataset.covers;
2496 dns_rdataset_disassociate(&rdataset);
2497 if (type == dns_rdatatype_nsec ||
2498 covers == dns_rdatatype_nsec) {
2499 if (!update_chain)
2500 fatal("Zone contains NSEC records. Use -u "
2501 "to update to NSEC3.");
2503 result = dns_db_deleterdataset(gdb, node, gversion,
2504 type, covers);
2505 check_result(result,
2506 "dns_db_deleterdataset(nsec3param/rrsig)");
2507 continue;
2510 dns_rdatasetiter_destroy(&rdsiter);
2511 dns_db_detachnode(gdb, &node);
2513 while (!done) {
2514 result = dns_dbiterator_current(dbiter, &node, name);
2515 check_dns_dbiterator_current(result);
2516 result = dns_dbiterator_next(dbiter);
2517 nextnode = NULL;
2518 while (result == ISC_R_SUCCESS) {
2519 result = dns_dbiterator_current(dbiter, &nextnode,
2520 nextname);
2521 check_dns_dbiterator_current(result);
2522 active = active_node(nextnode);
2523 if (!active) {
2524 dns_db_detachnode(gdb, &nextnode);
2525 result = dns_dbiterator_next(dbiter);
2526 continue;
2528 if (!dns_name_issubdomain(nextname, gorigin) ||
2529 (zonecut != NULL &&
2530 dns_name_issubdomain(nextname, zonecut))) {
2531 dns_db_detachnode(gdb, &nextnode);
2532 result = dns_dbiterator_next(dbiter);
2533 continue;
2535 if (delegation(nextname, nextnode, &nsttl)) {
2536 zonecut = dns_fixedname_name(&fzonecut);
2537 dns_name_copy(nextname, zonecut, NULL);
2538 if (generateds)
2539 add_ds(nextname, nextnode, nsttl);
2540 if (OPTOUT(nsec3flags) &&
2541 !secure(nextname, nextnode)) {
2542 dns_db_detachnode(gdb, &nextnode);
2543 result = dns_dbiterator_next(dbiter);
2544 continue;
2547 dns_db_detachnode(gdb, &nextnode);
2548 break;
2550 if (result == ISC_R_NOMORE) {
2551 dns_name_copy(gorigin, nextname, NULL);
2552 done = ISC_TRUE;
2553 } else if (result != ISC_R_SUCCESS)
2554 fatal("iterating through the database failed: %s",
2555 isc_result_totext(result));
2556 dns_name_downcase(name, name, NULL);
2557 hashlist_add_dns_name(hashlist, name, hashalg, iterations,
2558 salt, salt_length, ISC_FALSE);
2559 dns_db_detachnode(gdb, &node);
2561 * Add hashs for empty nodes. Use closest encloser logic.
2562 * The closest encloser either has data or is a empty
2563 * node for another <name,nextname> span so we don't add
2564 * it here. Empty labels on nextname are within the span.
2566 dns_name_downcase(nextname, nextname, NULL);
2567 dns_name_fullcompare(name, nextname, &order, &nlabels);
2568 addnowildcardhash(hashlist, name, hashalg, iterations,
2569 salt, salt_length);
2570 count = dns_name_countlabels(nextname);
2571 while (count > nlabels + 1) {
2572 count--;
2573 dns_name_split(nextname, count, NULL, nextname);
2574 hashlist_add_dns_name(hashlist, nextname, hashalg,
2575 iterations, salt, salt_length,
2576 ISC_FALSE);
2577 addnowildcardhash(hashlist, nextname, hashalg,
2578 iterations, salt, salt_length);
2581 dns_dbiterator_destroy(&dbiter);
2584 * We have all the hashes now so we can sort them.
2586 hashlist_sort(hashlist);
2589 * Check for duplicate hashes. If found the salt needs to
2590 * be changed.
2592 if (hashlist_hasdup(hashlist))
2593 fatal("Duplicate hash detected. Pick a different salt.");
2596 * Generate the nsec3 records.
2598 zonecut = NULL;
2599 done = ISC_FALSE;
2601 addnsec3param(salt, salt_length, iterations);
2604 * Clean out NSEC3 records which don't match this chain.
2606 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
2607 check_result(result, "dns_db_createiterator()");
2609 for (result = dns_dbiterator_first(dbiter);
2610 result == ISC_R_SUCCESS;
2611 result = dns_dbiterator_next(dbiter)) {
2612 result = dns_dbiterator_current(dbiter, &node, name);
2613 check_dns_dbiterator_current(result);
2614 nsec3clean(name, node, hashalg, iterations, salt, salt_length,
2615 hashlist);
2616 dns_db_detachnode(gdb, &node);
2618 dns_dbiterator_destroy(&dbiter);
2621 * Generate / complete the new chain.
2623 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2624 check_result(result, "dns_db_createiterator()");
2626 result = dns_dbiterator_first(dbiter);
2627 check_result(result, "dns_dbiterator_first()");
2629 while (!done) {
2630 result = dns_dbiterator_current(dbiter, &node, name);
2631 check_dns_dbiterator_current(result);
2632 result = dns_dbiterator_next(dbiter);
2633 nextnode = NULL;
2634 while (result == ISC_R_SUCCESS) {
2635 result = dns_dbiterator_current(dbiter, &nextnode,
2636 nextname);
2637 check_dns_dbiterator_current(result);
2638 active = active_node(nextnode);
2639 if (!active) {
2640 dns_db_detachnode(gdb, &nextnode);
2641 result = dns_dbiterator_next(dbiter);
2642 continue;
2644 if (!dns_name_issubdomain(nextname, gorigin) ||
2645 (zonecut != NULL &&
2646 dns_name_issubdomain(nextname, zonecut))) {
2647 dns_db_detachnode(gdb, &nextnode);
2648 result = dns_dbiterator_next(dbiter);
2649 continue;
2651 if (delegation(nextname, nextnode, NULL)) {
2652 zonecut = dns_fixedname_name(&fzonecut);
2653 dns_name_copy(nextname, zonecut, NULL);
2654 if (OPTOUT(nsec3flags) &&
2655 !secure(nextname, nextnode)) {
2656 dns_db_detachnode(gdb, &nextnode);
2657 result = dns_dbiterator_next(dbiter);
2658 continue;
2661 dns_db_detachnode(gdb, &nextnode);
2662 break;
2664 if (result == ISC_R_NOMORE) {
2665 dns_name_copy(gorigin, nextname, NULL);
2666 done = ISC_TRUE;
2667 } else if (result != ISC_R_SUCCESS)
2668 fatal("iterating through the database failed: %s",
2669 isc_result_totext(result));
2671 * We need to pause here to release the lock on the database.
2673 dns_dbiterator_pause(dbiter);
2674 addnsec3(name, node, salt, salt_length, iterations,
2675 hashlist, zone_soa_min_ttl);
2676 dns_db_detachnode(gdb, &node);
2678 * Add NSEC3's for empty nodes. Use closest encloser logic.
2680 dns_name_fullcompare(name, nextname, &order, &nlabels);
2681 count = dns_name_countlabels(nextname);
2682 while (count > nlabels + 1) {
2683 count--;
2684 dns_name_split(nextname, count, NULL, nextname);
2685 addnsec3(nextname, NULL, salt, salt_length,
2686 iterations, hashlist, zone_soa_min_ttl);
2689 dns_dbiterator_destroy(&dbiter);
2693 * Load the zone file from disk
2695 static void
2696 loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
2697 isc_buffer_t b;
2698 int len;
2699 dns_fixedname_t fname;
2700 dns_name_t *name;
2701 isc_result_t result;
2703 len = strlen(origin);
2704 isc_buffer_init(&b, origin, len);
2705 isc_buffer_add(&b, len);
2707 dns_fixedname_init(&fname);
2708 name = dns_fixedname_name(&fname);
2709 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
2710 if (result != ISC_R_SUCCESS)
2711 fatal("failed converting name '%s' to dns format: %s",
2712 origin, isc_result_totext(result));
2714 result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
2715 rdclass, 0, NULL, db);
2716 check_result(result, "dns_db_create()");
2718 result = dns_db_load2(*db, file, inputformat);
2719 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
2720 fatal("failed loading zone from '%s': %s",
2721 file, isc_result_totext(result));
2725 * Finds all public zone keys in the zone, and attempts to load the
2726 * private keys from disk.
2728 static void
2729 loadzonekeys(isc_boolean_t preserve_keys, isc_boolean_t load_public) {
2730 dns_dbnode_t *node;
2731 dns_dbversion_t *currentversion = NULL;
2732 isc_result_t result;
2733 dns_rdataset_t rdataset, keysigs, soasigs;
2735 node = NULL;
2736 result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node);
2737 if (result != ISC_R_SUCCESS)
2738 fatal("failed to find the zone's origin: %s",
2739 isc_result_totext(result));
2741 dns_db_currentversion(gdb, &currentversion);
2743 dns_rdataset_init(&rdataset);
2744 dns_rdataset_init(&soasigs);
2745 dns_rdataset_init(&keysigs);
2747 /* Make note of the keys which signed the SOA, if any */
2748 result = dns_db_findrdataset(gdb, node, currentversion,
2749 dns_rdatatype_soa, 0, 0,
2750 &rdataset, &soasigs);
2751 if (result != ISC_R_SUCCESS)
2752 goto cleanup;
2754 /* Preserve the TTL of the DNSKEY RRset, if any */
2755 dns_rdataset_disassociate(&rdataset);
2756 result = dns_db_findrdataset(gdb, node, currentversion,
2757 dns_rdatatype_dnskey, 0, 0,
2758 &rdataset, &keysigs);
2760 if (result != ISC_R_SUCCESS)
2761 goto cleanup;
2763 if (set_keyttl && keyttl != rdataset.ttl) {
2764 fprintf(stderr, "User-specified TTL (%d) conflicts "
2765 "with existing DNSKEY RRset TTL.\n",
2766 keyttl);
2767 fprintf(stderr, "Imported keys will use the RRSet "
2768 "TTL (%d) instead.\n",
2769 rdataset.ttl);
2771 keyttl = rdataset.ttl;
2773 /* Load keys corresponding to the existing DNSKEY RRset */
2774 result = dns_dnssec_keylistfromrdataset(gorigin, directory, mctx,
2775 &rdataset, &keysigs, &soasigs,
2776 preserve_keys, load_public,
2777 &keylist);
2778 if (result != ISC_R_SUCCESS)
2779 fatal("failed to load the zone keys: %s",
2780 isc_result_totext(result));
2782 cleanup:
2783 if (dns_rdataset_isassociated(&rdataset))
2784 dns_rdataset_disassociate(&rdataset);
2785 if (dns_rdataset_isassociated(&keysigs))
2786 dns_rdataset_disassociate(&keysigs);
2787 if (dns_rdataset_isassociated(&soasigs))
2788 dns_rdataset_disassociate(&soasigs);
2789 dns_db_detachnode(gdb, &node);
2790 dns_db_closeversion(gdb, &currentversion, ISC_FALSE);
2793 static void
2794 loadexplicitkeys(char *keyfiles[], int n, isc_boolean_t setksk) {
2795 isc_result_t result;
2796 int i;
2798 for (i = 0; i < n; i++) {
2799 dns_dnsseckey_t *key = NULL;
2800 dst_key_t *newkey = NULL;
2802 result = dst_key_fromnamedfile(keyfiles[i], directory,
2803 DST_TYPE_PUBLIC |
2804 DST_TYPE_PRIVATE,
2805 mctx, &newkey);
2806 if (result != ISC_R_SUCCESS)
2807 fatal("cannot load dnskey %s: %s", keyfiles[i],
2808 isc_result_totext(result));
2810 if (!dns_name_equal(gorigin, dst_key_name(newkey)))
2811 fatal("key %s not at origin\n", keyfiles[i]);
2813 if (!dst_key_isprivate(newkey))
2814 fatal("cannot sign zone with non-private dnskey %s",
2815 keyfiles[i]);
2817 /* Skip any duplicates */
2818 for (key = ISC_LIST_HEAD(keylist);
2819 key != NULL;
2820 key = ISC_LIST_NEXT(key, link)) {
2821 if (dst_key_id(key->key) == dst_key_id(newkey) &&
2822 dst_key_alg(key->key) == dst_key_alg(newkey))
2823 break;
2826 if (key == NULL) {
2827 /* We haven't seen this key before */
2828 dns_dnsseckey_create(mctx, &newkey, &key);
2829 ISC_LIST_APPEND(keylist, key, link);
2830 key->source = dns_keysource_user;
2831 } else {
2832 dst_key_free(&key->key);
2833 key->key = newkey;
2836 key->force_publish = ISC_TRUE;
2837 key->force_sign = ISC_TRUE;
2839 if (setksk)
2840 key->ksk = ISC_TRUE;
2844 static void
2845 report(const char *format, ...) {
2846 va_list args;
2847 va_start(args, format);
2848 vfprintf(stderr, format, args);
2849 va_end(args);
2850 putc('\n', stderr);
2853 static void
2854 build_final_keylist(void) {
2855 isc_result_t result;
2856 dns_dbversion_t *ver = NULL;
2857 dns_diff_t diff;
2858 dns_dnsseckeylist_t matchkeys;
2859 char name[DNS_NAME_FORMATSIZE];
2862 * Find keys that match this zone in the key repository.
2864 ISC_LIST_INIT(matchkeys);
2865 result = dns_dnssec_findmatchingkeys(gorigin, directory,
2866 mctx, &matchkeys);
2867 if (result == ISC_R_NOTFOUND)
2868 result = ISC_R_SUCCESS;
2869 check_result(result, "dns_dnssec_findmatchingkeys");
2871 result = dns_db_newversion(gdb, &ver);
2872 check_result(result, "dns_db_newversion");
2874 dns_diff_init(mctx, &diff);
2877 * Update keylist with information from from the key repository.
2879 dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl,
2880 &diff, ignore_kskflag, mctx, report);
2882 dns_name_format(gorigin, name, sizeof(name));
2884 result = dns_diff_applysilently(&diff, gdb, ver);
2885 if (result != ISC_R_SUCCESS)
2886 fatal("failed to update DNSKEY RRset at node '%s': %s",
2887 name, isc_result_totext(result));
2889 dns_db_closeversion(gdb, &ver, ISC_TRUE);
2891 dns_diff_clear(&diff);
2894 static void
2895 warnifallksk(dns_db_t *db) {
2896 dns_dbversion_t *currentversion = NULL;
2897 dns_dbnode_t *node = NULL;
2898 dns_rdataset_t rdataset;
2899 dns_rdata_t rdata = DNS_RDATA_INIT;
2900 isc_result_t result;
2901 dns_rdata_dnskey_t dnskey;
2902 isc_boolean_t have_non_ksk = ISC_FALSE;
2904 dns_db_currentversion(db, &currentversion);
2906 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
2907 if (result != ISC_R_SUCCESS)
2908 fatal("failed to find the zone's origin: %s",
2909 isc_result_totext(result));
2911 dns_rdataset_init(&rdataset);
2912 result = dns_db_findrdataset(db, node, currentversion,
2913 dns_rdatatype_dnskey, 0, 0, &rdataset,
2914 NULL);
2915 if (result != ISC_R_SUCCESS)
2916 fatal("failed to find keys at the zone apex: %s",
2917 isc_result_totext(result));
2918 result = dns_rdataset_first(&rdataset);
2919 check_result(result, "dns_rdataset_first");
2920 while (result == ISC_R_SUCCESS) {
2921 dns_rdata_reset(&rdata);
2922 dns_rdataset_current(&rdataset, &rdata);
2923 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2924 check_result(result, "dns_rdata_tostruct");
2925 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
2926 have_non_ksk = ISC_TRUE;
2927 result = ISC_R_NOMORE;
2928 } else
2929 result = dns_rdataset_next(&rdataset);
2930 dns_rdata_freestruct(&dnskey);
2932 dns_rdataset_disassociate(&rdataset);
2933 dns_db_detachnode(db, &node);
2934 dns_db_closeversion(db, &currentversion, ISC_FALSE);
2935 if (!have_non_ksk && !ignore_kskflag) {
2936 if (disable_zone_check)
2937 fprintf(stderr, "%s: warning: No non-KSK DNSKEY found; "
2938 "supply a ZSK or use '-z'.\n",
2939 program);
2940 else
2941 fatal("No non-KSK DNSKEY found; "
2942 "supply a ZSK or use '-z'.");
2946 static void
2947 set_nsec3params(isc_boolean_t update_chain, isc_boolean_t set_salt,
2948 isc_boolean_t set_optout, isc_boolean_t set_iter)
2950 isc_result_t result;
2951 dns_dbversion_t *ver = NULL;
2952 dns_dbnode_t *node = NULL;
2953 dns_rdataset_t rdataset;
2954 dns_rdata_t rdata = DNS_RDATA_INIT;
2955 dns_rdata_nsec3_t nsec3;
2956 dns_fixedname_t fname;
2957 dns_name_t *hashname;
2958 unsigned char orig_salt[256];
2959 size_t orig_saltlen;
2960 dns_hash_t orig_hash;
2961 isc_uint16_t orig_iter;
2963 dns_db_currentversion(gdb, &ver);
2964 dns_rdataset_init(&rdataset);
2966 orig_saltlen = sizeof(orig_salt);
2967 result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL,
2968 &orig_iter, orig_salt,
2969 &orig_saltlen);
2970 if (result != ISC_R_SUCCESS)
2971 goto cleanup;
2973 nsec_datatype = dns_rdatatype_nsec3;
2975 if (!update_chain && set_salt) {
2976 if (salt_length != orig_saltlen ||
2977 memcmp(saltbuf, orig_salt, salt_length) != 0)
2978 fatal("An NSEC3 chain exists with a different salt. "
2979 "Use -u to update it.");
2980 } else if (!set_salt) {
2981 salt_length = orig_saltlen;
2982 memcpy(saltbuf, orig_salt, orig_saltlen);
2983 salt = saltbuf;
2986 if (!update_chain && set_iter) {
2987 if (nsec3iter != orig_iter)
2988 fatal("An NSEC3 chain exists with different "
2989 "iterations. Use -u to update it.");
2990 } else if (!set_iter)
2991 nsec3iter = orig_iter;
2994 * Find an NSEC3 record to get the current OPTOUT value.
2995 * (This assumes all NSEC3 records agree.)
2998 dns_fixedname_init(&fname);
2999 hashname = dns_fixedname_name(&fname);
3000 result = dns_nsec3_hashname(&fname, NULL, NULL,
3001 gorigin, gorigin, dns_hash_sha1,
3002 orig_iter, orig_salt, orig_saltlen);
3003 check_result(result, "dns_nsec3_hashname");
3005 result = dns_db_findnsec3node(gdb, hashname, ISC_FALSE, &node);
3006 if (result != ISC_R_SUCCESS)
3007 goto cleanup;
3009 result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3,
3010 0, 0, &rdataset, NULL);
3011 if (result != ISC_R_SUCCESS)
3012 goto cleanup;
3014 result = dns_rdataset_first(&rdataset);
3015 check_result(result, "dns_rdataset_first");
3016 dns_rdataset_current(&rdataset, &rdata);
3017 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
3018 check_result(result, "dns_rdata_tostruct");
3020 if (!update_chain && set_optout) {
3021 if (nsec3flags != nsec3.flags)
3022 fatal("An NSEC3 chain exists with%s OPTOUT. "
3023 "Use -u -%s to %s it.",
3024 OPTOUT(nsec3.flags) ? "" : "out",
3025 OPTOUT(nsec3.flags) ? "AA" : "A",
3026 OPTOUT(nsec3.flags) ? "clear" : "set");
3027 } else if (!set_optout)
3028 nsec3flags = nsec3.flags;
3030 dns_rdata_freestruct(&nsec3);
3032 cleanup:
3033 if (dns_rdataset_isassociated(&rdataset))
3034 dns_rdataset_disassociate(&rdataset);
3035 if (node != NULL)
3036 dns_db_detachnode(gdb, &node);
3037 dns_db_closeversion(gdb, &ver, ISC_FALSE);
3040 static void
3041 writeset(const char *prefix, dns_rdatatype_t type) {
3042 char *filename;
3043 char namestr[DNS_NAME_FORMATSIZE];
3044 dns_db_t *db = NULL;
3045 dns_dbversion_t *version = NULL;
3046 dns_diff_t diff;
3047 dns_difftuple_t *tuple = NULL;
3048 dns_fixedname_t fixed;
3049 dns_name_t *name;
3050 dns_rdata_t rdata, ds;
3051 isc_boolean_t have_ksk = ISC_FALSE;
3052 isc_boolean_t have_non_ksk = ISC_FALSE;
3053 isc_buffer_t b;
3054 isc_buffer_t namebuf;
3055 isc_region_t r;
3056 isc_result_t result;
3057 dns_dnsseckey_t *key, *tmpkey;
3058 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
3059 unsigned char keybuf[DST_KEY_MAXSIZE];
3060 unsigned int filenamelen;
3061 const dns_master_style_t *style =
3062 (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
3064 isc_buffer_init(&namebuf, namestr, sizeof(namestr));
3065 result = dns_name_tofilenametext(gorigin, ISC_FALSE, &namebuf);
3066 check_result(result, "dns_name_tofilenametext");
3067 isc_buffer_putuint8(&namebuf, 0);
3068 filenamelen = strlen(prefix) + strlen(namestr);
3069 if (dsdir != NULL)
3070 filenamelen += strlen(dsdir) + 1;
3071 filename = isc_mem_get(mctx, filenamelen + 1);
3072 if (filename == NULL)
3073 fatal("out of memory");
3074 if (dsdir != NULL)
3075 sprintf(filename, "%s/", dsdir);
3076 else
3077 filename[0] = 0;
3078 strcat(filename, prefix);
3079 strcat(filename, namestr);
3081 dns_diff_init(mctx, &diff);
3083 if (type == dns_rdatatype_dlv) {
3084 dns_name_t tname;
3085 unsigned int labels;
3087 dns_name_init(&tname, NULL);
3088 dns_fixedname_init(&fixed);
3089 name = dns_fixedname_name(&fixed);
3090 labels = dns_name_countlabels(gorigin);
3091 dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
3092 result = dns_name_concatenate(&tname, dlv, name, NULL);
3093 check_result(result, "dns_name_concatenate");
3094 } else
3095 name = gorigin;
3097 for (key = ISC_LIST_HEAD(keylist);
3098 key != NULL;
3099 key = ISC_LIST_NEXT(key, link))
3101 if (REVOKE(key->key))
3102 continue;
3103 if (isksk(key)) {
3104 have_ksk = ISC_TRUE;
3105 have_non_ksk = ISC_FALSE;
3106 } else {
3107 have_ksk = ISC_FALSE;
3108 have_non_ksk = ISC_TRUE;
3110 for (tmpkey = ISC_LIST_HEAD(keylist);
3111 tmpkey != NULL;
3112 tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
3113 if (dst_key_alg(key->key) != dst_key_alg(tmpkey->key))
3114 continue;
3115 if (REVOKE(tmpkey->key))
3116 continue;
3117 if (isksk(tmpkey))
3118 have_ksk = ISC_TRUE;
3119 else
3120 have_non_ksk = ISC_TRUE;
3122 if (have_ksk && have_non_ksk && !isksk(key))
3123 continue;
3124 dns_rdata_init(&rdata);
3125 dns_rdata_init(&ds);
3126 isc_buffer_init(&b, keybuf, sizeof(keybuf));
3127 result = dst_key_todns(key->key, &b);
3128 check_result(result, "dst_key_todns");
3129 isc_buffer_usedregion(&b, &r);
3130 dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
3131 if (type != dns_rdatatype_dnskey) {
3132 result = dns_ds_buildrdata(gorigin, &rdata,
3133 DNS_DSDIGEST_SHA1,
3134 dsbuf, &ds);
3135 check_result(result, "dns_ds_buildrdata");
3136 if (type == dns_rdatatype_dlv)
3137 ds.type = dns_rdatatype_dlv;
3138 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
3139 name, 0, &ds, &tuple);
3140 check_result(result, "dns_difftuple_create");
3141 dns_diff_append(&diff, &tuple);
3143 dns_rdata_reset(&ds);
3144 result = dns_ds_buildrdata(gorigin, &rdata,
3145 DNS_DSDIGEST_SHA256,
3146 dsbuf, &ds);
3147 check_result(result, "dns_ds_buildrdata");
3148 if (type == dns_rdatatype_dlv)
3149 ds.type = dns_rdatatype_dlv;
3150 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
3151 name, 0, &ds, &tuple);
3153 } else
3154 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
3155 gorigin, zone_soa_min_ttl,
3156 &rdata, &tuple);
3157 check_result(result, "dns_difftuple_create");
3158 dns_diff_append(&diff, &tuple);
3161 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
3162 gclass, 0, NULL, &db);
3163 check_result(result, "dns_db_create");
3165 result = dns_db_newversion(db, &version);
3166 check_result(result, "dns_db_newversion");
3168 result = dns_diff_apply(&diff, db, version);
3169 check_result(result, "dns_diff_apply");
3170 dns_diff_clear(&diff);
3172 result = dns_master_dump(mctx, db, version, style, filename);
3173 check_result(result, "dns_master_dump");
3175 isc_mem_put(mctx, filename, filenamelen + 1);
3177 dns_db_closeversion(db, &version, ISC_FALSE);
3178 dns_db_detach(&db);
3181 static void
3182 print_time(FILE *fp) {
3183 time_t currenttime;
3185 if (outputformat != dns_masterformat_text)
3186 return;
3188 currenttime = time(NULL);
3189 fprintf(fp, "; File written on %s", ctime(&currenttime));
3192 static void
3193 print_version(FILE *fp) {
3194 if (outputformat != dns_masterformat_text)
3195 return;
3197 fprintf(fp, "; dnssec_signzone version " VERSION "\n");
3200 ISC_PLATFORM_NORETURN_PRE static void
3201 usage(void) ISC_PLATFORM_NORETURN_POST;
3203 static void
3204 usage(void) {
3205 fprintf(stderr, "Usage:\n");
3206 fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
3208 fprintf(stderr, "\n");
3210 fprintf(stderr, "Version: %s\n", VERSION);
3212 fprintf(stderr, "Options: (default value in parenthesis) \n");
3213 fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n"
3214 "\t\tfor the zone and determines how they are to "
3215 "be used\n");
3216 fprintf(stderr, "\t-K directory:\n");
3217 fprintf(stderr, "\t\tdirectory to find key files (.)\n");
3218 fprintf(stderr, "\t-d directory:\n");
3219 fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n");
3220 fprintf(stderr, "\t-g:\t");
3221 fprintf(stderr, "update DS records based on child zones' "
3222 "dsset-* files\n");
3223 fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
3224 fprintf(stderr, "\t\tRRSIG start time - absolute|offset (now - 1 hour)\n");
3225 fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
3226 fprintf(stderr, "\t\tRRSIG end time - absolute|from start|from now "
3227 "(now + 30 days)\n");
3228 fprintf(stderr, "\t-i interval:\n");
3229 fprintf(stderr, "\t\tcycle interval - resign "
3230 "if < interval from end ( (end-start)/4 )\n");
3231 fprintf(stderr, "\t-j jitter:\n");
3232 fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n");
3233 fprintf(stderr, "\t-v debuglevel (0)\n");
3234 fprintf(stderr, "\t-o origin:\n");
3235 fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
3236 fprintf(stderr, "\t-f outfile:\n");
3237 fprintf(stderr, "\t\tfile the signed zone is written in "
3238 "(zonefile + .signed)\n");
3239 fprintf(stderr, "\t-I format:\n");
3240 fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
3241 fprintf(stderr, "\t-O format:\n");
3242 fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
3243 fprintf(stderr, "\t-N format:\n");
3244 fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
3245 fprintf(stderr, "\t-r randomdev:\n");
3246 fprintf(stderr, "\t\ta file containing random data\n");
3247 fprintf(stderr, "\t-a:\t");
3248 fprintf(stderr, "verify generated signatures\n");
3249 fprintf(stderr, "\t-c class (IN)\n");
3250 fprintf(stderr, "\t-E engine:\n");
3251 #ifdef USE_PKCS11
3252 fprintf(stderr, "\t\tname of an OpenSSL engine to use "
3253 "(default is \"pkcs11\")\n");
3254 #else
3255 fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
3256 #endif
3257 fprintf(stderr, "\t-p:\t");
3258 fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
3259 fprintf(stderr, "\t-P:\t");
3260 fprintf(stderr, "disable post-sign verification\n");
3261 fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs");
3262 fprintf(stderr, "\t-t:\t");
3263 fprintf(stderr, "print statistics\n");
3264 fprintf(stderr, "\t-u:\t");
3265 fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n");
3266 fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n");
3267 fprintf(stderr, "\t-z:\tsign all records with KSKs\n");
3268 fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n"
3269 "\t\twith older versions of dnssec-signzone -g\n");
3270 fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
3271 fprintf(stderr, "\t-k key_signing_key\n");
3272 fprintf(stderr, "\t-l lookasidezone\n");
3273 fprintf(stderr, "\t-3 NSEC3 salt\n");
3274 fprintf(stderr, "\t-H NSEC3 iterations (10)\n");
3275 fprintf(stderr, "\t-A NSEC3 optout\n");
3277 fprintf(stderr, "\n");
3279 fprintf(stderr, "Signing Keys: ");
3280 fprintf(stderr, "(default: all zone keys that have private keys)\n");
3281 fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
3282 exit(0);
3285 static void
3286 removetempfile(void) {
3287 if (removefile)
3288 isc_file_remove(tempfile);
3291 static void
3292 print_stats(isc_time_t *timer_start, isc_time_t *timer_finish) {
3293 isc_uint64_t runtime_us; /* Runtime in microseconds */
3294 isc_uint64_t runtime_ms; /* Runtime in milliseconds */
3295 isc_uint64_t sig_ms; /* Signatures per millisecond */
3297 runtime_us = isc_time_microdiff(timer_finish, timer_start);
3299 printf("Signatures generated: %10d\n", nsigned);
3300 printf("Signatures retained: %10d\n", nretained);
3301 printf("Signatures dropped: %10d\n", ndropped);
3302 printf("Signatures successfully verified: %10d\n", nverified);
3303 printf("Signatures unsuccessfully verified: %10d\n", nverifyfailed);
3304 runtime_ms = runtime_us / 1000;
3305 printf("Runtime in seconds: %7u.%03u\n",
3306 (unsigned int) (runtime_ms / 1000),
3307 (unsigned int) (runtime_ms % 1000));
3308 if (runtime_us > 0) {
3309 sig_ms = ((isc_uint64_t)nsigned * 1000000000) / runtime_us;
3310 printf("Signatures per second: %7u.%03u\n",
3311 (unsigned int) sig_ms / 1000,
3312 (unsigned int) sig_ms % 1000);
3317 main(int argc, char *argv[]) {
3318 int i, ch;
3319 char *startstr = NULL, *endstr = NULL, *classname = NULL;
3320 char *origin = NULL, *file = NULL, *output = NULL;
3321 char *inputformatstr = NULL, *outputformatstr = NULL;
3322 char *serialformatstr = NULL;
3323 char *dskeyfile[MAXDSKEYS];
3324 int ndskeys = 0;
3325 char *endp;
3326 isc_time_t timer_start, timer_finish;
3327 dns_dnsseckey_t *key;
3328 isc_result_t result;
3329 isc_log_t *log = NULL;
3330 isc_boolean_t pseudorandom = ISC_FALSE;
3331 #ifdef USE_PKCS11
3332 const char *engine = "pkcs11";
3333 #else
3334 const char *engine = NULL;
3335 #endif
3336 unsigned int eflags;
3337 isc_boolean_t free_output = ISC_FALSE;
3338 int tempfilelen;
3339 dns_rdataclass_t rdclass;
3340 isc_task_t **tasks = NULL;
3341 isc_buffer_t b;
3342 int len;
3343 hashlist_t hashlist;
3344 isc_boolean_t smartsign = ISC_FALSE;
3345 isc_boolean_t make_keyset = ISC_FALSE;
3346 isc_boolean_t set_salt = ISC_FALSE;
3347 isc_boolean_t set_optout = ISC_FALSE;
3348 isc_boolean_t set_iter = ISC_FALSE;
3350 #define CMDLINE_FLAGS \
3351 "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:l:m:n:N:o:O:pPr:s:ST:tuUv:xz"
3354 * Process memory debugging argument first.
3356 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3357 switch (ch) {
3358 case 'm':
3359 if (strcasecmp(isc_commandline_argument, "record") == 0)
3360 isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
3361 if (strcasecmp(isc_commandline_argument, "trace") == 0)
3362 isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
3363 if (strcasecmp(isc_commandline_argument, "usage") == 0)
3364 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
3365 if (strcasecmp(isc_commandline_argument, "size") == 0)
3366 isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
3367 if (strcasecmp(isc_commandline_argument, "mctx") == 0)
3368 isc_mem_debugging |= ISC_MEM_DEBUGCTX;
3369 break;
3370 default:
3371 break;
3374 isc_commandline_reset = ISC_TRUE;
3376 masterstyle = &dns_master_style_explicitttl;
3378 check_result(isc_app_start(), "isc_app_start");
3380 result = isc_mem_create(0, 0, &mctx);
3381 if (result != ISC_R_SUCCESS)
3382 fatal("out of memory");
3384 dns_result_register();
3386 isc_commandline_errprint = ISC_FALSE;
3388 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3389 switch (ch) {
3390 case '3':
3391 set_salt = ISC_TRUE;
3392 nsec_datatype = dns_rdatatype_nsec3;
3393 if (strcmp(isc_commandline_argument, "-") != 0) {
3394 isc_buffer_t target;
3395 char *sarg;
3397 sarg = isc_commandline_argument;
3398 isc_buffer_init(&target, saltbuf,
3399 sizeof(saltbuf));
3400 result = isc_hex_decodestring(sarg, &target);
3401 check_result(result,
3402 "isc_hex_decodestring(salt)");
3403 salt_length = isc_buffer_usedlength(&target);
3405 break;
3407 case 'A':
3408 set_optout = ISC_TRUE;
3409 if (OPTOUT(nsec3flags))
3410 nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT;
3411 else
3412 nsec3flags |= DNS_NSEC3FLAG_OPTOUT;
3413 break;
3415 case 'a':
3416 tryverify = ISC_TRUE;
3417 break;
3419 case 'C':
3420 make_keyset = ISC_TRUE;
3421 break;
3423 case 'c':
3424 classname = isc_commandline_argument;
3425 break;
3427 case 'd':
3428 dsdir = isc_commandline_argument;
3429 if (strlen(dsdir) == 0U)
3430 fatal("DS directory must be non-empty string");
3431 result = try_dir(dsdir);
3432 if (result != ISC_R_SUCCESS)
3433 fatal("cannot open directory %s: %s",
3434 dsdir, isc_result_totext(result));
3435 break;
3437 case 'E':
3438 engine = isc_commandline_argument;
3439 break;
3441 case 'e':
3442 endstr = isc_commandline_argument;
3443 break;
3445 case 'f':
3446 output = isc_commandline_argument;
3447 break;
3449 case 'g':
3450 generateds = ISC_TRUE;
3451 break;
3453 case 'H':
3454 set_iter = ISC_TRUE;
3455 nsec3iter = strtoul(isc_commandline_argument, &endp, 0);
3456 if (*endp != '\0')
3457 fatal("iterations must be numeric");
3458 if (nsec3iter > 0xffffU)
3459 fatal("iterations too big");
3460 break;
3462 case 'h':
3463 usage();
3464 break;
3466 case 'I':
3467 inputformatstr = isc_commandline_argument;
3468 break;
3470 case 'i':
3471 endp = NULL;
3472 cycle = strtol(isc_commandline_argument, &endp, 0);
3473 if (*endp != '\0' || cycle < 0)
3474 fatal("cycle period must be numeric and "
3475 "positive");
3476 break;
3478 case 'j':
3479 endp = NULL;
3480 jitter = strtol(isc_commandline_argument, &endp, 0);
3481 if (*endp != '\0' || jitter < 0)
3482 fatal("jitter must be numeric and positive");
3483 break;
3485 case 'K':
3486 directory = isc_commandline_argument;
3487 break;
3489 case 'k':
3490 if (ndskeys == MAXDSKEYS)
3491 fatal("too many key-signing keys specified");
3492 dskeyfile[ndskeys++] = isc_commandline_argument;
3493 break;
3495 case 'l':
3496 len = strlen(isc_commandline_argument);
3497 isc_buffer_init(&b, isc_commandline_argument, len);
3498 isc_buffer_add(&b, len);
3500 dns_fixedname_init(&dlv_fixed);
3501 dlv = dns_fixedname_name(&dlv_fixed);
3502 result = dns_name_fromtext(dlv, &b, dns_rootname, 0,
3503 NULL);
3504 check_result(result, "dns_name_fromtext(dlv)");
3505 break;
3507 case 'm':
3508 break;
3510 case 'N':
3511 serialformatstr = isc_commandline_argument;
3512 break;
3514 case 'n':
3515 endp = NULL;
3516 ntasks = strtol(isc_commandline_argument, &endp, 0);
3517 if (*endp != '\0' || ntasks > ISC_INT32_MAX)
3518 fatal("number of cpus must be numeric");
3519 break;
3521 case 'O':
3522 outputformatstr = isc_commandline_argument;
3523 break;
3525 case 'o':
3526 origin = isc_commandline_argument;
3527 break;
3529 case 'P':
3530 disable_zone_check = ISC_TRUE;
3531 break;
3533 case 'p':
3534 pseudorandom = ISC_TRUE;
3535 break;
3537 case 'r':
3538 setup_entropy(mctx, isc_commandline_argument, &ectx);
3539 break;
3541 case 'S':
3542 smartsign = ISC_TRUE;
3543 break;
3545 case 's':
3546 startstr = isc_commandline_argument;
3547 break;
3549 case 'T':
3550 endp = NULL;
3551 set_keyttl = ISC_TRUE;
3552 keyttl = strtottl(isc_commandline_argument);
3553 break;
3555 case 't':
3556 printstats = ISC_TRUE;
3557 break;
3559 case 'U': /* Undocumented for testing only. */
3560 unknownalg = ISC_TRUE;
3561 break;
3563 case 'u':
3564 update_chain = ISC_TRUE;
3565 break;
3567 case 'v':
3568 endp = NULL;
3569 verbose = strtol(isc_commandline_argument, &endp, 0);
3570 if (*endp != '\0')
3571 fatal("verbose level must be numeric");
3572 break;
3574 case 'x':
3575 keyset_kskonly = ISC_TRUE;
3576 break;
3578 case 'z':
3579 ignore_kskflag = ISC_TRUE;
3580 break;
3582 case 'F':
3583 /* Reserved for FIPS mode */
3584 /* FALLTHROUGH */
3585 case '?':
3586 if (isc_commandline_option != '?')
3587 fprintf(stderr, "%s: invalid argument -%c\n",
3588 program, isc_commandline_option);
3589 usage();
3590 break;
3592 default:
3593 fprintf(stderr, "%s: unhandled option -%c\n",
3594 program, isc_commandline_option);
3595 exit(1);
3599 if (ectx == NULL)
3600 setup_entropy(mctx, NULL, &ectx);
3601 eflags = ISC_ENTROPY_BLOCKING;
3602 if (!pseudorandom)
3603 eflags |= ISC_ENTROPY_GOODONLY;
3605 result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
3606 if (result != ISC_R_SUCCESS)
3607 fatal("could not create hash context");
3609 result = dst_lib_init2(mctx, ectx, engine, eflags);
3610 if (result != ISC_R_SUCCESS)
3611 fatal("could not initialize dst: %s",
3612 isc_result_totext(result));
3614 isc_stdtime_get(&now);
3616 if (startstr != NULL) {
3617 starttime = strtotime(startstr, now, now);
3618 } else
3619 starttime = now - 3600; /* Allow for some clock skew. */
3621 if (endstr != NULL) {
3622 endtime = strtotime(endstr, now, starttime);
3623 } else
3624 endtime = starttime + (30 * 24 * 60 * 60);
3626 if (cycle == -1)
3627 cycle = (endtime - starttime) / 4;
3629 if (ntasks == 0)
3630 ntasks = isc_os_ncpus() * 2;
3631 vbprintf(4, "using %d cpus\n", ntasks);
3633 rdclass = strtoclass(classname);
3635 if (directory == NULL)
3636 directory = ".";
3638 setup_logging(verbose, mctx, &log);
3640 argc -= isc_commandline_index;
3641 argv += isc_commandline_index;
3643 if (argc < 1)
3644 usage();
3646 file = argv[0];
3648 argc -= 1;
3649 argv += 1;
3651 if (origin == NULL)
3652 origin = file;
3654 if (output == NULL) {
3655 free_output = ISC_TRUE;
3656 output = isc_mem_allocate(mctx,
3657 strlen(file) + strlen(".signed") + 1);
3658 if (output == NULL)
3659 fatal("out of memory");
3660 sprintf(output, "%s.signed", file);
3663 if (inputformatstr != NULL) {
3664 if (strcasecmp(inputformatstr, "text") == 0)
3665 inputformat = dns_masterformat_text;
3666 else if (strcasecmp(inputformatstr, "raw") == 0)
3667 inputformat = dns_masterformat_raw;
3668 else
3669 fatal("unknown file format: %s\n", inputformatstr);
3672 if (outputformatstr != NULL) {
3673 if (strcasecmp(outputformatstr, "text") == 0)
3674 outputformat = dns_masterformat_text;
3675 else if (strcasecmp(outputformatstr, "raw") == 0)
3676 outputformat = dns_masterformat_raw;
3677 else
3678 fatal("unknown file format: %s\n", outputformatstr);
3681 if (serialformatstr != NULL) {
3682 if (strcasecmp(serialformatstr, "keep") == 0)
3683 serialformat = SOA_SERIAL_KEEP;
3684 else if (strcasecmp(serialformatstr, "increment") == 0 ||
3685 strcasecmp(serialformatstr, "incr") == 0)
3686 serialformat = SOA_SERIAL_INCREMENT;
3687 else if (strcasecmp(serialformatstr, "unixtime") == 0)
3688 serialformat = SOA_SERIAL_UNIXTIME;
3689 else
3690 fatal("unknown soa serial format: %s\n",
3691 serialformatstr);
3694 result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL,
3695 0, 24, 0, 0, 0, 8, mctx);
3696 check_result(result, "dns_master_stylecreate");
3698 gdb = NULL;
3699 TIME_NOW(&timer_start);
3700 loadzone(file, origin, rdclass, &gdb);
3701 gorigin = dns_db_origin(gdb);
3702 gclass = dns_db_class(gdb);
3703 get_soa_ttls();
3705 if (!set_keyttl)
3706 keyttl = soa_ttl;
3709 * Check for any existing NSEC3 parameters in the zone,
3710 * and use them as defaults if -u was not specified.
3712 if (update_chain && !set_optout && !set_iter && !set_salt)
3713 nsec_datatype = dns_rdatatype_nsec;
3714 else
3715 set_nsec3params(update_chain, set_salt, set_optout, set_iter);
3717 if (IS_NSEC3) {
3718 isc_boolean_t answer;
3719 hash_length = dns_nsec3_hashlength(dns_hash_sha1);
3720 hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2,
3721 hash_length);
3722 result = dns_nsec_nseconly(gdb, gversion, &answer);
3723 check_result(result, "dns_nsec_nseconly");
3724 if (answer)
3725 fatal("NSEC3 generation requested with "
3726 "NSEC only DNSKEY");
3730 * We need to do this early on, as we start messing with the list
3731 * of keys rather early.
3733 ISC_LIST_INIT(keylist);
3734 isc_rwlock_init(&keylist_lock, 0, 0);
3737 * Fill keylist with:
3738 * 1) Keys listed in the DNSKEY set that have
3739 * private keys associated, *if* no keys were
3740 * set on the command line.
3741 * 2) ZSKs set on the command line
3742 * 3) KSKs set on the command line
3743 * 4) Any keys remaining in the DNSKEY set which
3744 * do not have private keys associated and were
3745 * not specified on the command line.
3747 if (argc == 0 || smartsign)
3748 loadzonekeys(!smartsign, ISC_FALSE);
3749 loadexplicitkeys(argv, argc, ISC_FALSE);
3750 loadexplicitkeys(dskeyfile, ndskeys, ISC_TRUE);
3751 loadzonekeys(!smartsign, ISC_TRUE);
3754 * If we're doing smart signing, look in the key repository for
3755 * key files with metadata, and merge them with the keylist
3756 * we have now.
3758 if (smartsign)
3759 build_final_keylist();
3761 /* Now enumerate the key list */
3762 for (key = ISC_LIST_HEAD(keylist);
3763 key != NULL;
3764 key = ISC_LIST_NEXT(key, link)) {
3765 key->index = keycount++;
3768 if (keycount == 0) {
3769 if (disable_zone_check)
3770 fprintf(stderr, "%s: warning: No keys specified "
3771 "or found\n", program);
3772 else
3773 fatal("No signing keys specified or found.");
3774 nokeys = ISC_TRUE;
3777 if (IS_NSEC3) {
3778 unsigned int max;
3779 result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max);
3780 check_result(result, "dns_nsec3_maxiterations()");
3781 if (nsec3iter > max)
3782 fatal("NSEC3 iterations too big for weakest DNSKEY "
3783 "strength. Maximum iterations allowed %u.", max);
3786 warnifallksk(gdb);
3788 gversion = NULL;
3789 result = dns_db_newversion(gdb, &gversion);
3790 check_result(result, "dns_db_newversion()");
3792 switch (serialformat) {
3793 case SOA_SERIAL_INCREMENT:
3794 setsoaserial(0);
3795 break;
3796 case SOA_SERIAL_UNIXTIME:
3797 setsoaserial(now);
3798 break;
3799 case SOA_SERIAL_KEEP:
3800 default:
3801 /* do nothing */
3802 break;
3805 remove_duplicates();
3807 if (IS_NSEC3)
3808 nsec3ify(dns_hash_sha1, nsec3iter, salt, salt_length,
3809 &hashlist);
3810 else
3811 nsecify();
3813 if (!nokeys) {
3814 writeset("dsset-", dns_rdatatype_ds);
3815 if (make_keyset)
3816 writeset("keyset-", dns_rdatatype_dnskey);
3817 if (dlv != NULL) {
3818 writeset("dlvset-", dns_rdatatype_dlv);
3822 tempfilelen = strlen(output) + 20;
3823 tempfile = isc_mem_get(mctx, tempfilelen);
3824 if (tempfile == NULL)
3825 fatal("out of memory");
3827 result = isc_file_mktemplate(output, tempfile, tempfilelen);
3828 check_result(result, "isc_file_mktemplate");
3830 fp = NULL;
3831 result = isc_file_openunique(tempfile, &fp);
3832 if (result != ISC_R_SUCCESS)
3833 fatal("failed to open temporary output file: %s",
3834 isc_result_totext(result));
3835 removefile = ISC_TRUE;
3836 setfatalcallback(&removetempfile);
3838 print_time(fp);
3839 print_version(fp);
3841 result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
3842 if (result != ISC_R_SUCCESS)
3843 fatal("failed to create task manager: %s",
3844 isc_result_totext(result));
3846 master = NULL;
3847 result = isc_task_create(taskmgr, 0, &master);
3848 if (result != ISC_R_SUCCESS)
3849 fatal("failed to create task: %s", isc_result_totext(result));
3851 tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
3852 if (tasks == NULL)
3853 fatal("out of memory");
3854 for (i = 0; i < (int)ntasks; i++) {
3855 tasks[i] = NULL;
3856 result = isc_task_create(taskmgr, 0, &tasks[i]);
3857 if (result != ISC_R_SUCCESS)
3858 fatal("failed to create task: %s",
3859 isc_result_totext(result));
3862 RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS);
3863 if (printstats)
3864 RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS);
3866 presign();
3867 signapex();
3868 if (!finished) {
3870 * There is more work to do. Spread it out over multiple
3871 * processors if possible.
3873 for (i = 0; i < (int)ntasks; i++) {
3874 result = isc_app_onrun(mctx, master, startworker,
3875 tasks[i]);
3876 if (result != ISC_R_SUCCESS)
3877 fatal("failed to start task: %s",
3878 isc_result_totext(result));
3880 (void)isc_app_run();
3881 if (!finished)
3882 fatal("process aborted by user");
3883 } else
3884 isc_task_detach(&master);
3885 shuttingdown = ISC_TRUE;
3886 for (i = 0; i < (int)ntasks; i++)
3887 isc_task_detach(&tasks[i]);
3888 isc_taskmgr_destroy(&taskmgr);
3889 isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
3890 postsign();
3891 verifyzone();
3893 if (outputformat != dns_masterformat_text) {
3894 result = dns_master_dumptostream2(mctx, gdb, gversion,
3895 masterstyle, outputformat,
3896 fp);
3897 check_result(result, "dns_master_dumptostream2");
3900 result = isc_stdio_close(fp);
3901 check_result(result, "isc_stdio_close");
3902 removefile = ISC_FALSE;
3904 result = isc_file_rename(tempfile, output);
3905 if (result != ISC_R_SUCCESS)
3906 fatal("failed to rename temp file to %s: %s\n",
3907 output, isc_result_totext(result));
3909 DESTROYLOCK(&namelock);
3910 if (printstats)
3911 DESTROYLOCK(&statslock);
3913 printf("%s\n", output);
3915 dns_db_closeversion(gdb, &gversion, ISC_FALSE);
3916 dns_db_detach(&gdb);
3918 while (!ISC_LIST_EMPTY(keylist)) {
3919 key = ISC_LIST_HEAD(keylist);
3920 ISC_LIST_UNLINK(keylist, key, link);
3921 dns_dnsseckey_destroy(mctx, &key);
3924 isc_mem_put(mctx, tempfile, tempfilelen);
3926 if (free_output)
3927 isc_mem_free(mctx, output);
3929 dns_master_styledestroy(&dsstyle, mctx);
3931 cleanup_logging(&log);
3932 dst_lib_destroy();
3933 isc_hash_destroy();
3934 cleanup_entropy(&ectx);
3935 dns_name_destroy();
3936 if (verbose > 10)
3937 isc_mem_stats(mctx, stdout);
3938 isc_mem_destroy(&mctx);
3940 (void) isc_app_finish();
3942 if (printstats) {
3943 TIME_NOW(&timer_finish);
3944 print_stats(&timer_start, &timer_finish);
3947 return (0);