Update repub branch u/fanf2/patch to rebasing branch u/fanf2/rebasing revision v9_15_...
[ipreg/bind9.git] / bin / dnssec / dnssec-signzone.c
1 /*
2 * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 *
8 * See the COPYRIGHT file distributed with this work for additional
9 * information regarding copyright ownership.
10 *
11 * Portions Copyright (C) Network Associates, Inc.
12 *
13 * Permission to use, copy, modify, and/or distribute this software for any
14 * purpose with or without fee is hereby granted, provided that the above
15 * copyright notice and this permission notice appear in all copies.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
18 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
20 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
22 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
23 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 */
25
26 /*! \file */
27
28 #include <inttypes.h>
29 #include <stdbool.h>
30 #include <stdlib.h>
31 #include <time.h>
32 #include <unistd.h>
33
34 #include <isc/app.h>
35 #include <isc/base32.h>
36 #include <isc/commandline.h>
37 #include <isc/event.h>
38 #include <isc/file.h>
39 #include <isc/hash.h>
40 #include <isc/hex.h>
41 #include <isc/md.h>
42 #include <isc/mem.h>
43 #include <isc/mutex.h>
44 #include <isc/os.h>
45 #include <isc/print.h>
46 #include <isc/random.h>
47 #include <isc/rwlock.h>
48 #include <isc/serial.h>
49 #include <isc/safe.h>
50 #include <isc/stdio.h>
51 #include <isc/string.h>
52 #include <isc/task.h>
53 #include <isc/time.h>
54 #include <isc/util.h>
55
56 #include <dns/db.h>
57 #include <dns/dbiterator.h>
58 #include <dns/diff.h>
59 #include <dns/dnssec.h>
60 #include <dns/ds.h>
61 #include <dns/fixedname.h>
62 #include <dns/keyvalues.h>
63 #include <dns/log.h>
64 #include <dns/master.h>
65 #include <dns/masterdump.h>
66 #include <dns/nsec.h>
67 #include <dns/nsec3.h>
68 #include <dns/rdata.h>
69 #include <dns/rdatalist.h>
70 #include <dns/rdataset.h>
71 #include <dns/rdataclass.h>
72 #include <dns/rdatasetiter.h>
73 #include <dns/rdatastruct.h>
74 #include <dns/rdatatype.h>
75 #include <dns/result.h>
76 #include <dns/soa.h>
77 #include <dns/time.h>
78 #include <dns/update.h>
79 #include <dns/zoneverify.h>
80
81 #include <dst/dst.h>
82
83 #if USE_PKCS11
84 #include <pk11/result.h>
85 #endif
86
87 #include "dnssectool.h"
88
89 const char *program = "dnssec-signzone";
90
91 typedef struct hashlist hashlist_t;
92
93 static int nsec_datatype = dns_rdatatype_nsec;
94
95 #define check_dns_dbiterator_current(result) \
96 check_result((result == DNS_R_NEWORIGIN) ? ISC_R_SUCCESS : result, \
97 "dns_dbiterator_current()")
98
99 #define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3)
100 #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
101
102 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
103
104 #define BUFSIZE 2048
105 #define MAXDSKEYS 8
106
107 #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
108 #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
109 #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
110
111 #define SOA_SERIAL_KEEP 0
112 #define SOA_SERIAL_INCREMENT 1
113 #define SOA_SERIAL_UNIXTIME 2
114 #define SOA_SERIAL_DATE 3
115
116 typedef struct signer_event sevent_t;
117 struct signer_event {
118 ISC_EVENT_COMMON(sevent_t);
119 dns_fixedname_t *fname;
120 dns_dbnode_t *node;
121 };
122
123 static dns_dnsseckeylist_t keylist;
124 static unsigned int keycount = 0;
125 isc_rwlock_t keylist_lock;
126 static isc_stdtime_t starttime = 0, endtime = 0, dnskey_endtime = 0, now;
127 static int cycle = -1;
128 static int jitter = 0;
129 static int jump = 0;
130 static bool tryverify = false;
131 static bool printstats = false;
132 static isc_mem_t *mctx = NULL;
133 static dns_ttl_t zone_soa_min_ttl;
134 static dns_ttl_t soa_ttl;
135 static FILE *outfp = NULL;
136 static char *tempfile = NULL;
137 static const dns_master_style_t *masterstyle;
138 static dns_masterformat_t inputformat = dns_masterformat_text;
139 static dns_masterformat_t outputformat = dns_masterformat_text;
140 static uint32_t rawversion = 1, serialnum = 0;
141 static bool snset = false;
142 static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
143 static unsigned int nverified = 0, nverifyfailed = 0;
144 static const char *directory = NULL, *dsdir = NULL;
145 static isc_mutex_t namelock, statslock;
146 static isc_taskmgr_t *taskmgr = NULL;
147 static dns_db_t *gdb; /* The database */
148 static dns_dbversion_t *gversion; /* The database version */
149 static dns_dbiterator_t *gdbiter; /* The database iterator */
150 static dns_rdataclass_t gclass; /* The class */
151 static dns_name_t *gorigin; /* The database origin */
152 static int nsec3flags = 0;
153 static dns_iterations_t nsec3iter = 10U;
154 static unsigned char saltbuf[255];
155 static unsigned char *gsalt = saltbuf;
156 static size_t salt_length = 0;
157 static isc_task_t *master = NULL;
158 static unsigned int ntasks = 0;
159 static bool shuttingdown = false, finished = false;
160 static bool nokeys = false;
161 static bool removefile = false;
162 static bool generateds = false;
163 static bool ignore_kskflag = false;
164 static bool keyset_kskonly = false;
165 static dns_name_t *dlv = NULL;
166 static dns_fixedname_t dlv_fixed;
167 static dns_master_style_t *dsstyle = NULL;
168 static unsigned int serialformat = SOA_SERIAL_KEEP;
169 static unsigned int hash_length = 0;
170 static bool unknownalg = false;
171 static bool disable_zone_check = false;
172 static bool update_chain = false;
173 static bool set_keyttl = false;
174 static dns_ttl_t keyttl;
175 static bool smartsign = false;
176 static bool remove_orphansigs = false;
177 static bool remove_inactkeysigs = false;
178 static bool output_dnssec_only = false;
179 static bool output_stdout = false;
180 bool set_maxttl = false;
181 static dns_ttl_t maxttl = 0;
182
183 #define INCSTAT(counter) \
184 if (printstats) { \
185 LOCK(&statslock); \
186 counter++; \
187 UNLOCK(&statslock); \
188 }
189
190 static void
191 sign(isc_task_t *task, isc_event_t *event);
192
193 /*%
194 * Store a copy of 'name' in 'fzonecut' and return a pointer to that copy.
195 */
196 static dns_name_t *
197 savezonecut(dns_fixedname_t *fzonecut, dns_name_t *name) {
198 dns_name_t *result;
199
200 result = dns_fixedname_initname(fzonecut);
201 dns_name_copy(name, result, NULL);
202
203 return (result);
204 }
205
206 static void
207 dumpnode(dns_name_t *name, dns_dbnode_t *node) {
208 dns_rdataset_t rds;
209 dns_rdatasetiter_t *iter = NULL;
210 isc_buffer_t *buffer = NULL;
211 isc_region_t r;
212 isc_result_t result;
213 unsigned bufsize = 4096;
214
215 if (outputformat != dns_masterformat_text)
216 return;
217
218 if (!output_dnssec_only) {
219 result = dns_master_dumpnodetostream(mctx, gdb, gversion, node,
220 name, masterstyle, outfp);
221 check_result(result, "dns_master_dumpnodetostream");
222 return;
223 }
224
225 result = dns_db_allrdatasets(gdb, node, gversion, 0, &iter);
226 check_result(result, "dns_db_allrdatasets");
227
228 dns_rdataset_init(&rds);
229
230 result = isc_buffer_allocate(mctx, &buffer, bufsize);
231 check_result(result, "isc_buffer_allocate");
232
233 for (result = dns_rdatasetiter_first(iter);
234 result == ISC_R_SUCCESS;
235 result = dns_rdatasetiter_next(iter)) {
236
237 dns_rdatasetiter_current(iter, &rds);
238
239 if (rds.type != dns_rdatatype_rrsig &&
240 rds.type != dns_rdatatype_nsec &&
241 rds.type != dns_rdatatype_nsec3 &&
242 rds.type != dns_rdatatype_nsec3param &&
243 (!smartsign || rds.type != dns_rdatatype_dnskey)) {
244 dns_rdataset_disassociate(&rds);
245 continue;
246 }
247
248 for (;;) {
249 result = dns_master_rdatasettotext(name, &rds,
250 masterstyle, buffer);
251 if (result != ISC_R_NOSPACE)
252 break;
253
254 bufsize <<= 1;
255 isc_buffer_free(&buffer);
256 result = isc_buffer_allocate(mctx, &buffer, bufsize);
257 check_result(result, "isc_buffer_allocate");
258 }
259 check_result(result, "dns_master_rdatasettotext");
260
261 isc_buffer_usedregion(buffer, &r);
262 result = isc_stdio_write(r.base, 1, r.length, outfp, NULL);
263 check_result(result, "isc_stdio_write");
264 isc_buffer_clear(buffer);
265
266 dns_rdataset_disassociate(&rds);
267 }
268
269 isc_buffer_free(&buffer);
270 dns_rdatasetiter_destroy(&iter);
271 }
272
273 /*%
274 * Sign the given RRset with given key, and add the signature record to the
275 * given tuple.
276 */
277 static void
278 signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key,
279 dns_ttl_t ttl, dns_diff_t *add, const char *logmsg)
280 {
281 isc_result_t result;
282 isc_stdtime_t jendtime, expiry;
283 char keystr[DST_KEY_FORMATSIZE];
284 dns_rdata_t trdata = DNS_RDATA_INIT;
285 unsigned char array[BUFSIZE];
286 isc_buffer_t b;
287 dns_difftuple_t *tuple;
288
289 dst_key_format(key, keystr, sizeof(keystr));
290 vbprintf(1, "\t%s %s\n", logmsg, keystr);
291
292 if (rdataset->type == dns_rdatatype_dnskey)
293 expiry = dnskey_endtime;
294 else
295 expiry = endtime;
296
297 jendtime = (jitter != 0) ? expiry - isc_random_uniform(jitter) : expiry;
298 jendtime -= (jump != 0) ? jendtime % jump : 0;
299 isc_buffer_init(&b, array, sizeof(array));
300 result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
301 mctx, &b, &trdata);
302 if (result != ISC_R_SUCCESS) {
303 fatal("dnskey '%s' failed to sign data: %s",
304 keystr, isc_result_totext(result));
305 }
306 INCSTAT(nsigned);
307
308 if (tryverify) {
309 result = dns_dnssec_verify(name, rdataset, key,
310 true, 0, mctx, &trdata, NULL);
311 if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) {
312 vbprintf(3, "\tsignature verified\n");
313 INCSTAT(nverified);
314 } else {
315 vbprintf(3, "\tsignature failed to verify\n");
316 INCSTAT(nverifyfailed);
317 }
318 }
319
320 tuple = NULL;
321 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN,
322 name, ttl, &trdata, &tuple);
323 check_result(result, "dns_difftuple_create");
324 dns_diff_append(add, &tuple);
325 }
326
327 static inline bool
328 issigningkey(dns_dnsseckey_t *key) {
329 return (key->force_sign || key->hint_sign);
330 }
331
332 static inline bool
333 ispublishedkey(dns_dnsseckey_t *key) {
334 return ((key->force_publish || key->hint_publish) &&
335 !key->hint_remove);
336 }
337
338 static inline bool
339 iszonekey(dns_dnsseckey_t *key) {
340 return (dns_name_equal(dst_key_name(key->key), gorigin) &&
341 dst_key_iszonekey(key->key));
342 }
343
344 static inline bool
345 isksk(dns_dnsseckey_t *key) {
346 return (key->ksk);
347 }
348
349 static inline bool
350 iszsk(dns_dnsseckey_t *key) {
351 return (ignore_kskflag || !key->ksk);
352 }
353
354 /*%
355 * Find the key that generated an RRSIG, if it is in the key list. If
356 * so, return a pointer to it, otherwise return NULL.
357 *
358 * No locking is performed here, this must be done by the caller.
359 */
360 static dns_dnsseckey_t *
361 keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
362 dns_dnsseckey_t *key;
363
364 for (key = ISC_LIST_HEAD(keylist);
365 key != NULL;
366 key = ISC_LIST_NEXT(key, link)) {
367 if (rrsig->keyid == dst_key_id(key->key) &&
368 rrsig->algorithm == dst_key_alg(key->key) &&
369 dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
370 return (key);
371 }
372 return (NULL);
373 }
374
375 /*%
376 * Finds the key that generated a RRSIG, if possible. First look at the keys
377 * that we've loaded already, and then see if there's a key on disk.
378 */
379 static dns_dnsseckey_t *
380 keythatsigned(dns_rdata_rrsig_t *rrsig) {
381 isc_result_t result;
382 dst_key_t *pubkey = NULL, *privkey = NULL;
383 dns_dnsseckey_t *key = NULL;
384
385 isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read);
386 key = keythatsigned_unlocked(rrsig);
387 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_read);
388 if (key != NULL)
389 return (key);
390
391 /*
392 * We did not find the key in our list. Get a write lock now, since
393 * we may be modifying the bits. We could do the tryupgrade() dance,
394 * but instead just get a write lock and check once again to see if
395 * it is on our list. It's possible someone else may have added it
396 * after all.
397 */
398 isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write);
399 key = keythatsigned_unlocked(rrsig);
400 if (key != NULL) {
401 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
402 return (key);
403 }
404
405 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
406 rrsig->algorithm, DST_TYPE_PUBLIC,
407 directory, mctx, &pubkey);
408 if (result != ISC_R_SUCCESS) {
409 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
410 return (NULL);
411 }
412
413 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
414 rrsig->algorithm,
415 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
416 directory, mctx, &privkey);
417 if (result == ISC_R_SUCCESS) {
418 dst_key_free(&pubkey);
419 result = dns_dnsseckey_create(mctx, &privkey, &key);
420 } else
421 result = dns_dnsseckey_create(mctx, &pubkey, &key);
422
423 if (result == ISC_R_SUCCESS) {
424 key->force_publish = false;
425 key->force_sign = false;
426 key->index = keycount++;
427 ISC_LIST_APPEND(keylist, key, link);
428 }
429
430 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
431 return (key);
432 }
433
434 /*%
435 * Check to see if we expect to find a key at this name. If we see a RRSIG
436 * and can't find the signing key that we expect to find, we drop the rrsig.
437 * I'm not sure if this is completely correct, but it seems to work.
438 */
439 static bool
440 expecttofindkey(dns_name_t *name) {
441 unsigned int options = DNS_DBFIND_NOWILD;
442 dns_fixedname_t fname;
443 isc_result_t result;
444 char namestr[DNS_NAME_FORMATSIZE];
445
446 dns_fixedname_init(&fname);
447 result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
448 0, NULL, dns_fixedname_name(&fname), NULL, NULL);
449 switch (result) {
450 case ISC_R_SUCCESS:
451 case DNS_R_NXDOMAIN:
452 case DNS_R_NXRRSET:
453 return (true);
454 case DNS_R_DELEGATION:
455 case DNS_R_CNAME:
456 case DNS_R_DNAME:
457 return (false);
458 }
459 dns_name_format(name, namestr, sizeof(namestr));
460 fatal("failure looking for '%s DNSKEY' in database: %s",
461 namestr, isc_result_totext(result));
462 /* NOTREACHED */
463 return (false); /* removes a warning */
464 }
465
466 static inline bool
467 setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
468 dns_rdata_t *rrsig)
469 {
470 isc_result_t result;
471 result = dns_dnssec_verify(name, set, key, false, 0, mctx, rrsig,
472 NULL);
473 if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) {
474 INCSTAT(nverified);
475 return (true);
476 } else {
477 INCSTAT(nverifyfailed);
478 return (false);
479 }
480 }
481
482 /*%
483 * Signs a set. Goes through contortions to decide if each RRSIG should
484 * be dropped or retained, and then determines if any new SIGs need to
485 * be generated.
486 */
487 static void
488 signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
489 dns_rdataset_t *set)
490 {
491 dns_rdataset_t sigset;
492 dns_rdata_t sigrdata = DNS_RDATA_INIT;
493 dns_rdata_rrsig_t rrsig;
494 dns_dnsseckey_t *key;
495 isc_result_t result;
496 bool nosigs = false;
497 bool *wassignedby, *nowsignedby;
498 int arraysize;
499 dns_difftuple_t *tuple;
500 dns_ttl_t ttl;
501 int i;
502 char namestr[DNS_NAME_FORMATSIZE];
503 char typestr[DNS_RDATATYPE_FORMATSIZE];
504 char sigstr[SIG_FORMATSIZE];
505
506 dns_name_format(name, namestr, sizeof(namestr));
507 dns_rdatatype_format(set->type, typestr, sizeof(typestr));
508
509 ttl = ISC_MIN(set->ttl, endtime - starttime);
510
511 dns_rdataset_init(&sigset);
512 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
513 set->type, 0, &sigset, NULL);
514 if (result == ISC_R_NOTFOUND) {
515 vbprintf(2, "no existing signatures for %s/%s\n",
516 namestr, typestr);
517 result = ISC_R_SUCCESS;
518 nosigs = true;
519 }
520 if (result != ISC_R_SUCCESS)
521 fatal("failed while looking for '%s RRSIG %s': %s",
522 namestr, typestr, isc_result_totext(result));
523
524 vbprintf(1, "%s/%s:\n", namestr, typestr);
525
526 arraysize = keycount;
527 if (!nosigs)
528 arraysize += dns_rdataset_count(&sigset);
529 wassignedby = isc_mem_get(mctx, arraysize * sizeof(bool));
530 nowsignedby = isc_mem_get(mctx, arraysize * sizeof(bool));
531
532 for (i = 0; i < arraysize; i++)
533 wassignedby[i] = nowsignedby[i] = false;
534
535 if (nosigs)
536 result = ISC_R_NOMORE;
537 else
538 result = dns_rdataset_first(&sigset);
539
540 while (result == ISC_R_SUCCESS) {
541 bool expired, future;
542 bool keep = false, resign = false;
543
544 dns_rdataset_current(&sigset, &sigrdata);
545
546 result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
547 check_result(result, "dns_rdata_tostruct");
548
549 future = isc_serial_lt(now, rrsig.timesigned);
550
551 key = keythatsigned(&rrsig);
552 sig_format(&rrsig, sigstr, sizeof(sigstr));
553 if (key != NULL && issigningkey(key))
554 expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
555 else
556 expired = isc_serial_gt(now, rrsig.timeexpire);
557
558 if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
559 /* rrsig is dropped and not replaced */
560 vbprintf(2, "\trrsig by %s dropped - "
561 "invalid validity period\n",
562 sigstr);
563 } else if (key == NULL && !future &&
564 expecttofindkey(&rrsig.signer)) {
565 /* rrsig is dropped and not replaced */
566 vbprintf(2, "\trrsig by %s dropped - "
567 "private dnskey not found\n",
568 sigstr);
569 } else if (key == NULL || future) {
570 keep = (!expired && !remove_orphansigs);
571 vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
572 keep ? "retained" : "dropped", sigstr);
573 } else if (!dns_dnssec_keyactive(key->key, now) &&
574 remove_inactkeysigs) {
575 keep = false;
576 vbprintf(2, "\trrsig by %s dropped - key inactive\n",
577 sigstr);
578 } else if (issigningkey(key)) {
579 wassignedby[key->index] = true;
580
581 if (!expired && rrsig.originalttl == set->ttl &&
582 setverifies(name, set, key->key, &sigrdata)) {
583 vbprintf(2, "\trrsig by %s retained\n", sigstr);
584 keep = true;
585 } else {
586 vbprintf(2, "\trrsig by %s dropped - %s\n",
587 sigstr, expired ? "expired" :
588 rrsig.originalttl != set->ttl ?
589 "ttl change" : "failed to verify");
590 resign = true;
591 }
592 } else if (!ispublishedkey(key) && remove_orphansigs) {
593 vbprintf(2, "\trrsig by %s dropped - dnskey removed\n",
594 sigstr);
595 } else if (iszonekey(key)) {
596 wassignedby[key->index] = true;
597
598 if (!expired && rrsig.originalttl == set->ttl &&
599 setverifies(name, set, key->key, &sigrdata)) {
600 vbprintf(2, "\trrsig by %s retained\n", sigstr);
601 keep = true;
602 } else {
603 vbprintf(2, "\trrsig by %s dropped - %s\n",
604 sigstr, expired ? "expired" :
605 rrsig.originalttl != set->ttl ?
606 "ttl change" : "failed to verify");
607 }
608 } else if (!expired) {
609 vbprintf(2, "\trrsig by %s retained\n", sigstr);
610 keep = true;
611 } else {
612 vbprintf(2, "\trrsig by %s expired\n", sigstr);
613 }
614
615 if (keep) {
616 if (key != NULL)
617 nowsignedby[key->index] = true;
618 INCSTAT(nretained);
619 if (sigset.ttl != ttl) {
620 vbprintf(2, "\tfixing ttl %s\n", sigstr);
621 tuple = NULL;
622 result = dns_difftuple_create(mctx,
623 DNS_DIFFOP_DELRESIGN,
624 name, sigset.ttl,
625 &sigrdata, &tuple);
626 check_result(result, "dns_difftuple_create");
627 dns_diff_append(del, &tuple);
628 result = dns_difftuple_create(mctx,
629 DNS_DIFFOP_ADDRESIGN,
630 name, ttl,
631 &sigrdata, &tuple);
632 check_result(result, "dns_difftuple_create");
633 dns_diff_append(add, &tuple);
634 }
635 } else {
636 tuple = NULL;
637 vbprintf(2, "removing signature by %s\n", sigstr);
638 result = dns_difftuple_create(mctx,
639 DNS_DIFFOP_DELRESIGN,
640 name, sigset.ttl,
641 &sigrdata, &tuple);
642 check_result(result, "dns_difftuple_create");
643 dns_diff_append(del, &tuple);
644 INCSTAT(ndropped);
645 }
646
647 if (resign) {
648 INSIST(!keep);
649
650 signwithkey(name, set, key->key, ttl, add,
651 "resigning with dnskey");
652 nowsignedby[key->index] = true;
653 }
654
655 dns_rdata_reset(&sigrdata);
656 dns_rdata_freestruct(&rrsig);
657 result = dns_rdataset_next(&sigset);
658 }
659 if (result == ISC_R_NOMORE)
660 result = ISC_R_SUCCESS;
661
662 check_result(result, "dns_rdataset_first/next");
663 if (dns_rdataset_isassociated(&sigset))
664 dns_rdataset_disassociate(&sigset);
665
666 for (key = ISC_LIST_HEAD(keylist);
667 key != NULL;
668 key = ISC_LIST_NEXT(key, link))
669 {
670 if (nowsignedby[key->index])
671 continue;
672
673 if (!issigningkey(key))
674 continue;
675
676 if ((set->type == dns_rdatatype_cds ||
677 set->type == dns_rdatatype_cdnskey ||
678 set->type == dns_rdatatype_dnskey) &&
679 dns_name_equal(name, gorigin)) {
680 bool have_ksk;
681 dns_dnsseckey_t *tmpkey;
682
683 have_ksk = isksk(key);
684 for (tmpkey = ISC_LIST_HEAD(keylist);
685 tmpkey != NULL;
686 tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
687 if (dst_key_alg(key->key) !=
688 dst_key_alg(tmpkey->key))
689 continue;
690 if (REVOKE(tmpkey->key))
691 continue;
692 if (isksk(tmpkey))
693 have_ksk = true;
694 }
695 if (isksk(key) || !have_ksk ||
696 (iszsk(key) && !keyset_kskonly))
697 signwithkey(name, set, key->key, ttl, add,
698 "signing with dnskey");
699 } else if (iszsk(key)) {
700 signwithkey(name, set, key->key, ttl, add,
701 "signing with dnskey");
702 }
703 }
704
705 isc_mem_put(mctx, wassignedby, arraysize * sizeof(bool));
706 isc_mem_put(mctx, nowsignedby, arraysize * sizeof(bool));
707 }
708
709 struct hashlist {
710 unsigned char *hashbuf;
711 size_t entries;
712 size_t size;
713 size_t length;
714 };
715
716 static void
717 hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) {
718
719 l->entries = 0;
720 l->length = length + 1;
721
722 if (nodes != 0) {
723 l->size = nodes;
724 l->hashbuf = malloc(l->size * l->length);
725 if (l->hashbuf == NULL)
726 l->size = 0;
727 } else {
728 l->size = 0;
729 l->hashbuf = NULL;
730 }
731 }
732
733 static void
734 hashlist_free(hashlist_t *l) {
735 if (l->hashbuf) {
736 free(l->hashbuf);
737 l->hashbuf = NULL;
738 l->entries = 0;
739 l->length = 0;
740 l->size = 0;
741 }
742 }
743
744 static void
745 hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len)
746 {
747
748 REQUIRE(len <= l->length);
749
750 if (l->entries == l->size) {
751 l->size = l->size * 2 + 100;
752 l->hashbuf = realloc(l->hashbuf, l->size * l->length);
753 if (l->hashbuf == NULL)
754 fatal("unable to grow hashlist: out of memory");
755 }
756 memset(l->hashbuf + l->entries * l->length, 0, l->length);
757 memmove(l->hashbuf + l->entries * l->length, hash, len);
758 l->entries++;
759 }
760
761 static void
762 hashlist_add_dns_name(hashlist_t *l, /*const*/ dns_name_t *name,
763 unsigned int hashalg, unsigned int iterations,
764 const unsigned char *salt, size_t salt_len,
765 bool speculative)
766 {
767 char nametext[DNS_NAME_FORMATSIZE];
768 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
769 unsigned int len;
770 size_t i;
771
772 len = isc_iterated_hash(hash, hashalg, iterations,
773 salt, (int)salt_len,
774 name->ndata, name->length);
775 if (verbose) {
776 dns_name_format(name, nametext, sizeof nametext);
777 for (i = 0 ; i < len; i++)
778 fprintf(stderr, "%02x", hash[i]);
779 fprintf(stderr, " %s\n", nametext);
780 }
781 hash[len++] = speculative ? 1 : 0;
782 hashlist_add(l, hash, len);
783 }
784
785 static int
786 hashlist_comp(const void *a, const void *b) {
787 return (memcmp(a, b, hash_length + 1));
788 }
789
790 static void
791 hashlist_sort(hashlist_t *l) {
792 qsort(l->hashbuf, l->entries, l->length, hashlist_comp);
793 }
794
795 static bool
796 hashlist_hasdup(hashlist_t *l) {
797 unsigned char *current;
798 unsigned char *next = l->hashbuf;
799 size_t entries = l->entries;
800
801 /*
802 * Skip initial speculative wild card hashs.
803 */
804 while (entries > 0U && next[l->length-1] != 0U) {
805 next += l->length;
806 entries--;
807 }
808
809 current = next;
810 while (entries-- > 1U) {
811 next += l->length;
812 if (next[l->length-1] != 0)
813 continue;
814 if (isc_safe_memequal(current, next, l->length - 1))
815 return (true);
816 current = next;
817 }
818 return (false);
819 }
820
821 static const unsigned char *
822 hashlist_findnext(const hashlist_t *l,
823 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
824 {
825 size_t entries = l->entries;
826 const unsigned char *next = bsearch(hash, l->hashbuf, l->entries,
827 l->length, hashlist_comp);
828 INSIST(next != NULL);
829
830 do {
831 if (next < l->hashbuf + (l->entries - 1) * l->length)
832 next += l->length;
833 else
834 next = l->hashbuf;
835 if (next[l->length - 1] == 0)
836 break;
837 } while (entries-- > 1U);
838 INSIST(entries != 0U);
839 return (next);
840 }
841
842 static bool
843 hashlist_exists(const hashlist_t *l,
844 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
845 {
846 if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp))
847 return (true);
848 else
849 return (false);
850 }
851
852 static void
853 addnowildcardhash(hashlist_t *l, /*const*/ dns_name_t *name,
854 unsigned int hashalg, unsigned int iterations,
855 const unsigned char *salt, size_t salt_len)
856 {
857 dns_fixedname_t fixed;
858 dns_name_t *wild;
859 dns_dbnode_t *node = NULL;
860 isc_result_t result;
861 char namestr[DNS_NAME_FORMATSIZE];
862
863 wild = dns_fixedname_initname(&fixed);
864
865 result = dns_name_concatenate(dns_wildcardname, name, wild, NULL);
866 if (result == ISC_R_NOSPACE)
867 return;
868 check_result(result,"addnowildcardhash: dns_name_concatenate()");
869
870 result = dns_db_findnode(gdb, wild, false, &node);
871 if (result == ISC_R_SUCCESS) {
872 dns_db_detachnode(gdb, &node);
873 return;
874 }
875
876 if (verbose) {
877 dns_name_format(wild, namestr, sizeof(namestr));
878 fprintf(stderr, "adding no-wildcardhash for %s\n", namestr);
879 }
880
881 hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_len,
882 true);
883 }
884
885 static void
886 opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
887 dns_db_t **dbp)
888 {
889 char filename[PATH_MAX];
890 isc_buffer_t b;
891 isc_result_t result;
892
893 isc_buffer_init(&b, filename, sizeof(filename));
894 if (dsdir != NULL) {
895 /* allow room for a trailing slash */
896 if (strlen(dsdir) >= isc_buffer_availablelength(&b))
897 fatal("path '%s' is too long", dsdir);
898 isc_buffer_putstr(&b, dsdir);
899 if (dsdir[strlen(dsdir) - 1] != '/')
900 isc_buffer_putstr(&b, "/");
901 }
902 if (strlen(prefix) > isc_buffer_availablelength(&b))
903 fatal("path '%s' is too long", dsdir);
904 isc_buffer_putstr(&b, prefix);
905 result = dns_name_tofilenametext(name, false, &b);
906 check_result(result, "dns_name_tofilenametext()");
907 if (isc_buffer_availablelength(&b) == 0) {
908 char namestr[DNS_NAME_FORMATSIZE];
909 dns_name_format(name, namestr, sizeof(namestr));
910 fatal("name '%s' is too long", namestr);
911 }
912 isc_buffer_putuint8(&b, 0);
913
914 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
915 rdclass, 0, NULL, dbp);
916 check_result(result, "dns_db_create()");
917
918 result = dns_db_load(*dbp, filename, inputformat, DNS_MASTER_HINT);
919 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
920 dns_db_detach(dbp);
921 }
922
923 /*%
924 * Load the DS set for a child zone, if a dsset-* file can be found.
925 * If not, try to find a keyset-* file from an earlier version of
926 * dnssec-signzone, and build DS records from that.
927 */
928 static isc_result_t
929 loadds(dns_name_t *name, uint32_t ttl, dns_rdataset_t *dsset) {
930 dns_db_t *db = NULL;
931 dns_dbversion_t *ver = NULL;
932 dns_dbnode_t *node = NULL;
933 isc_result_t result;
934 dns_rdataset_t keyset;
935 dns_rdata_t key, ds;
936 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
937 dns_diff_t diff;
938 dns_difftuple_t *tuple = NULL;
939
940 opendb("dsset-", name, gclass, &db);
941 if (db != NULL) {
942 result = dns_db_findnode(db, name, false, &node);
943 if (result == ISC_R_SUCCESS) {
944 dns_rdataset_init(dsset);
945 result = dns_db_findrdataset(db, node, NULL,
946 dns_rdatatype_ds, 0, 0,
947 dsset, NULL);
948 dns_db_detachnode(db, &node);
949 if (result == ISC_R_SUCCESS) {
950 vbprintf(2, "found DS records\n");
951 dsset->ttl = ttl;
952 dns_db_detach(&db);
953 return (result);
954 }
955 }
956 dns_db_detach(&db);
957 }
958
959 /* No DS records found; try again, looking for DNSKEY records */
960 opendb("keyset-", name, gclass, &db);
961 if (db == NULL) {
962 return (ISC_R_NOTFOUND);
963 }
964
965 result = dns_db_findnode(db, name, false, &node);
966 if (result != ISC_R_SUCCESS) {
967 dns_db_detach(&db);
968 return (result);
969 }
970
971 dns_rdataset_init(&keyset);
972 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
973 &keyset, NULL);
974 if (result != ISC_R_SUCCESS) {
975 dns_db_detachnode(db, &node);
976 dns_db_detach(&db);
977 return (result);
978 }
979 vbprintf(2, "found DNSKEY records\n");
980
981 result = dns_db_newversion(db, &ver);
982 check_result(result, "dns_db_newversion");
983 dns_diff_init(mctx, &diff);
984
985 for (result = dns_rdataset_first(&keyset);
986 result == ISC_R_SUCCESS;
987 result = dns_rdataset_next(&keyset))
988 {
989 dns_rdata_init(&key);
990 dns_rdata_init(&ds);
991 dns_rdataset_current(&keyset, &key);
992 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
993 dsbuf, &ds);
994 check_result(result, "dns_ds_buildrdata");
995
996 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name,
997 ttl, &ds, &tuple);
998 check_result(result, "dns_difftuple_create");
999 dns_diff_append(&diff, &tuple);
1000 }
1001
1002 result = dns_diff_apply(&diff, db, ver);
1003 check_result(result, "dns_diff_apply");
1004 dns_diff_clear(&diff);
1005
1006 dns_db_closeversion(db, &ver, true);
1007
1008 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
1009 dsset, NULL);
1010 check_result(result, "dns_db_findrdataset");
1011
1012 dns_rdataset_disassociate(&keyset);
1013 dns_db_detachnode(db, &node);
1014 dns_db_detach(&db);
1015 return (result);
1016 }
1017
1018 static bool
1019 secure(dns_name_t *name, dns_dbnode_t *node) {
1020 dns_rdataset_t dsset;
1021 isc_result_t result;
1022
1023 if (dns_name_equal(name, gorigin))
1024 return (false);
1025
1026 dns_rdataset_init(&dsset);
1027 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds,
1028 0, 0, &dsset, NULL);
1029 if (dns_rdataset_isassociated(&dsset))
1030 dns_rdataset_disassociate(&dsset);
1031
1032 return (result == ISC_R_SUCCESS);
1033 }
1034
1035 static bool
1036 is_delegation(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
1037 dns_name_t *name, dns_dbnode_t *node, uint32_t *ttlp)
1038 {
1039 dns_rdataset_t nsset;
1040 isc_result_t result;
1041
1042 if (dns_name_equal(name, origin))
1043 return (false);
1044
1045 dns_rdataset_init(&nsset);
1046 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_ns,
1047 0, 0, &nsset, NULL);
1048 if (dns_rdataset_isassociated(&nsset)) {
1049 if (ttlp != NULL)
1050 *ttlp = nsset.ttl;
1051 dns_rdataset_disassociate(&nsset);
1052 }
1053
1054 return ((result == ISC_R_SUCCESS));
1055 }
1056
1057 /*%
1058 * Return true if version 'ver' of database 'db' contains a DNAME RRset at
1059 * 'node'; return false otherwise.
1060 */
1061 static bool
1062 has_dname(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node) {
1063 dns_rdataset_t dnameset;
1064 isc_result_t result;
1065
1066 dns_rdataset_init(&dnameset);
1067 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dname, 0, 0,
1068 &dnameset, NULL);
1069 if (dns_rdataset_isassociated(&dnameset)) {
1070 dns_rdataset_disassociate(&dnameset);
1071 }
1072
1073 return ((result == ISC_R_SUCCESS));
1074 }
1075
1076 /*%
1077 * Signs all records at a name.
1078 */
1079 static void
1080 signname(dns_dbnode_t *node, dns_name_t *name) {
1081 isc_result_t result;
1082 dns_rdataset_t rdataset;
1083 dns_rdatasetiter_t *rdsiter;
1084 bool isdelegation = false;
1085 dns_diff_t del, add;
1086 char namestr[DNS_NAME_FORMATSIZE];
1087
1088 dns_rdataset_init(&rdataset);
1089 dns_name_format(name, namestr, sizeof(namestr));
1090
1091 /*
1092 * Determine if this is a delegation point.
1093 */
1094 if (is_delegation(gdb, gversion, gorigin, name, node, NULL))
1095 isdelegation = true;
1096
1097 /*
1098 * Now iterate through the rdatasets.
1099 */
1100 dns_diff_init(mctx, &del);
1101 dns_diff_init(mctx, &add);
1102 rdsiter = NULL;
1103 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1104 check_result(result, "dns_db_allrdatasets()");
1105 result = dns_rdatasetiter_first(rdsiter);
1106 while (result == ISC_R_SUCCESS) {
1107 dns_rdatasetiter_current(rdsiter, &rdataset);
1108
1109 /* If this is a RRSIG set, skip it. */
1110 if (rdataset.type == dns_rdatatype_rrsig)
1111 goto skip;
1112
1113 /*
1114 * If this name is a delegation point, skip all records
1115 * except NSEC and DS sets. Otherwise check that there
1116 * isn't a DS record.
1117 */
1118 if (isdelegation) {
1119 if (rdataset.type != nsec_datatype &&
1120 rdataset.type != dns_rdatatype_ds)
1121 goto skip;
1122 } else if (rdataset.type == dns_rdatatype_ds) {
1123 char namebuf[DNS_NAME_FORMATSIZE];
1124 dns_name_format(name, namebuf, sizeof(namebuf));
1125 fatal("'%s': found DS RRset without NS RRset\n",
1126 namebuf);
1127 }
1128
1129 signset(&del, &add, node, name, &rdataset);
1130
1131 skip:
1132 dns_rdataset_disassociate(&rdataset);
1133 result = dns_rdatasetiter_next(rdsiter);
1134 }
1135 if (result != ISC_R_NOMORE)
1136 fatal("rdataset iteration for name '%s' failed: %s",
1137 namestr, isc_result_totext(result));
1138
1139 dns_rdatasetiter_destroy(&rdsiter);
1140
1141 result = dns_diff_applysilently(&del, gdb, gversion);
1142 if (result != ISC_R_SUCCESS)
1143 fatal("failed to delete SIGs at node '%s': %s",
1144 namestr, isc_result_totext(result));
1145
1146 result = dns_diff_applysilently(&add, gdb, gversion);
1147 if (result != ISC_R_SUCCESS)
1148 fatal("failed to add SIGs at node '%s': %s",
1149 namestr, isc_result_totext(result));
1150
1151 dns_diff_clear(&del);
1152 dns_diff_clear(&add);
1153 }
1154
1155 /*
1156 * See if the node contains any non RRSIG/NSEC records and report to
1157 * caller. Clean out extranous RRSIG records for node.
1158 */
1159 static inline bool
1160 active_node(dns_dbnode_t *node) {
1161 dns_rdatasetiter_t *rdsiter = NULL;
1162 dns_rdatasetiter_t *rdsiter2 = NULL;
1163 bool active = false;
1164 isc_result_t result;
1165 dns_rdataset_t rdataset;
1166 dns_rdatatype_t type;
1167 dns_rdatatype_t covers;
1168 bool found;
1169
1170 dns_rdataset_init(&rdataset);
1171 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1172 check_result(result, "dns_db_allrdatasets()");
1173 result = dns_rdatasetiter_first(rdsiter);
1174 while (result == ISC_R_SUCCESS) {
1175 dns_rdatasetiter_current(rdsiter, &rdataset);
1176 if (rdataset.type != dns_rdatatype_nsec &&
1177 rdataset.type != dns_rdatatype_nsec3 &&
1178 rdataset.type != dns_rdatatype_rrsig)
1179 active = true;
1180 dns_rdataset_disassociate(&rdataset);
1181 if (!active)
1182 result = dns_rdatasetiter_next(rdsiter);
1183 else
1184 result = ISC_R_NOMORE;
1185 }
1186 if (result != ISC_R_NOMORE)
1187 fatal("rdataset iteration failed: %s",
1188 isc_result_totext(result));
1189
1190 if (!active && nsec_datatype == dns_rdatatype_nsec) {
1191 /*%
1192 * The node is empty of everything but NSEC / RRSIG records.
1193 */
1194 for (result = dns_rdatasetiter_first(rdsiter);
1195 result == ISC_R_SUCCESS;
1196 result = dns_rdatasetiter_next(rdsiter)) {
1197 dns_rdatasetiter_current(rdsiter, &rdataset);
1198 result = dns_db_deleterdataset(gdb, node, gversion,
1199 rdataset.type,
1200 rdataset.covers);
1201 check_result(result, "dns_db_deleterdataset()");
1202 dns_rdataset_disassociate(&rdataset);
1203 }
1204 if (result != ISC_R_NOMORE)
1205 fatal("rdataset iteration failed: %s",
1206 isc_result_totext(result));
1207 } else {
1208 /*
1209 * Delete RRSIGs for types that no longer exist.
1210 */
1211 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
1212 check_result(result, "dns_db_allrdatasets()");
1213 for (result = dns_rdatasetiter_first(rdsiter);
1214 result == ISC_R_SUCCESS;
1215 result = dns_rdatasetiter_next(rdsiter)) {
1216 dns_rdatasetiter_current(rdsiter, &rdataset);
1217 type = rdataset.type;
1218 covers = rdataset.covers;
1219 dns_rdataset_disassociate(&rdataset);
1220 /*
1221 * Delete the NSEC chain if we are signing with
1222 * NSEC3.
1223 */
1224 if (nsec_datatype == dns_rdatatype_nsec3 &&
1225 (type == dns_rdatatype_nsec ||
1226 covers == dns_rdatatype_nsec)) {
1227 result = dns_db_deleterdataset(gdb, node,
1228 gversion, type,
1229 covers);
1230 check_result(result,
1231 "dns_db_deleterdataset(nsec/rrsig)");
1232 continue;
1233 }
1234 if (type != dns_rdatatype_rrsig)
1235 continue;
1236 found = false;
1237 for (result = dns_rdatasetiter_first(rdsiter2);
1238 !found && result == ISC_R_SUCCESS;
1239 result = dns_rdatasetiter_next(rdsiter2)) {
1240 dns_rdatasetiter_current(rdsiter2, &rdataset);
1241 if (rdataset.type == covers)
1242 found = true;
1243 dns_rdataset_disassociate(&rdataset);
1244 }
1245 if (!found) {
1246 if (result != ISC_R_NOMORE)
1247 fatal("rdataset iteration failed: %s",
1248 isc_result_totext(result));
1249 result = dns_db_deleterdataset(gdb, node,
1250 gversion, type,
1251 covers);
1252 check_result(result,
1253 "dns_db_deleterdataset(rrsig)");
1254 } else if (result != ISC_R_NOMORE &&
1255 result != ISC_R_SUCCESS)
1256 fatal("rdataset iteration failed: %s",
1257 isc_result_totext(result));
1258 }
1259 if (result != ISC_R_NOMORE)
1260 fatal("rdataset iteration failed: %s",
1261 isc_result_totext(result));
1262 dns_rdatasetiter_destroy(&rdsiter2);
1263 }
1264 dns_rdatasetiter_destroy(&rdsiter);
1265
1266 return (active);
1267 }
1268
1269 /*%
1270 * Extracts the minimum TTL from the SOA record, and the SOA record's TTL.
1271 */
1272 static void
1273 get_soa_ttls(void) {
1274 dns_rdataset_t soaset;
1275 dns_fixedname_t fname;
1276 dns_name_t *name;
1277 isc_result_t result;
1278 dns_rdata_t rdata = DNS_RDATA_INIT;
1279
1280 name = dns_fixedname_initname(&fname);
1281 dns_rdataset_init(&soaset);
1282 result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
1283 0, 0, NULL, name, &soaset, NULL);
1284 if (result != ISC_R_SUCCESS)
1285 fatal("failed to find an SOA at the zone apex: %s",
1286 isc_result_totext(result));
1287
1288 result = dns_rdataset_first(&soaset);
1289 check_result(result, "dns_rdataset_first");
1290 dns_rdataset_current(&soaset, &rdata);
1291 zone_soa_min_ttl = dns_soa_getminimum(&rdata);
1292 soa_ttl = soaset.ttl;
1293 if (set_maxttl) {
1294 zone_soa_min_ttl = ISC_MIN(zone_soa_min_ttl, maxttl);
1295 soa_ttl = ISC_MIN(soa_ttl, maxttl);
1296 }
1297 dns_rdataset_disassociate(&soaset);
1298 }
1299
1300 /*%
1301 * Increment (or set if nonzero) the SOA serial
1302 */
1303 static isc_result_t
1304 setsoaserial(uint32_t serial, dns_updatemethod_t method) {
1305 isc_result_t result;
1306 dns_dbnode_t *node = NULL;
1307 dns_rdataset_t rdataset;
1308 dns_rdata_t rdata = DNS_RDATA_INIT;
1309 uint32_t old_serial, new_serial;
1310
1311 result = dns_db_getoriginnode(gdb, &node);
1312 if (result != ISC_R_SUCCESS)
1313 return result;
1314
1315 dns_rdataset_init(&rdataset);
1316
1317 result = dns_db_findrdataset(gdb, node, gversion,
1318 dns_rdatatype_soa, 0,
1319 0, &rdataset, NULL);
1320 if (result != ISC_R_SUCCESS)
1321 goto cleanup;
1322
1323 result = dns_rdataset_first(&rdataset);
1324 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1325
1326 dns_rdataset_current(&rdataset, &rdata);
1327
1328 old_serial = dns_soa_getserial(&rdata);
1329
1330 if (method == dns_updatemethod_date ||
1331 method == dns_updatemethod_unixtime) {
1332 new_serial = dns_update_soaserial(old_serial, method);
1333 } else if (serial != 0 || method == dns_updatemethod_none) {
1334 /* Set SOA serial to the value provided. */
1335 new_serial = serial;
1336 } else {
1337 /* Increment SOA serial using RFC 1982 arithmetics */
1338 new_serial = (old_serial + 1) & 0xFFFFFFFF;
1339 if (new_serial == 0)
1340 new_serial = 1;
1341 }
1342
1343 /* If the new serial is not likely to cause a zone transfer
1344 * (a/ixfr) from servers having the old serial, warn the user.
1345 *
1346 * RFC1982 section 7 defines the maximum increment to be
1347 * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
1348 * comparison. (5 - 6 == (2^32)-1, not negative-one)
1349 */
1350 if (new_serial == old_serial ||
1351 (new_serial - old_serial) > 0x7fffffffU)
1352 fprintf(stderr, "%s: warning: Serial number not advanced, "
1353 "zone may not transfer\n", program);
1354
1355 dns_soa_setserial(new_serial, &rdata);
1356
1357 result = dns_db_deleterdataset(gdb, node, gversion,
1358 dns_rdatatype_soa, 0);
1359 check_result(result, "dns_db_deleterdataset");
1360 if (result != ISC_R_SUCCESS)
1361 goto cleanup;
1362
1363 result = dns_db_addrdataset(gdb, node, gversion,
1364 0, &rdataset, 0, NULL);
1365 check_result(result, "dns_db_addrdataset");
1366 if (result != ISC_R_SUCCESS)
1367 goto cleanup;
1368
1369 cleanup:
1370 dns_rdataset_disassociate(&rdataset);
1371 if (node != NULL)
1372 dns_db_detachnode(gdb, &node);
1373 dns_rdata_reset(&rdata);
1374
1375 return (result);
1376 }
1377
1378 /*%
1379 * Delete any RRSIG records at a node.
1380 */
1381 static void
1382 cleannode(dns_db_t *db, dns_dbversion_t *dbversion, dns_dbnode_t *node) {
1383 dns_rdatasetiter_t *rdsiter = NULL;
1384 dns_rdataset_t set;
1385 isc_result_t result, dresult;
1386
1387 if (outputformat != dns_masterformat_text || !disable_zone_check)
1388 return;
1389
1390 dns_rdataset_init(&set);
1391 result = dns_db_allrdatasets(db, node, dbversion, 0, &rdsiter);
1392 check_result(result, "dns_db_allrdatasets");
1393 result = dns_rdatasetiter_first(rdsiter);
1394 while (result == ISC_R_SUCCESS) {
1395 bool destroy = false;
1396 dns_rdatatype_t covers = 0;
1397 dns_rdatasetiter_current(rdsiter, &set);
1398 if (set.type == dns_rdatatype_rrsig) {
1399 covers = set.covers;
1400 destroy = true;
1401 }
1402 dns_rdataset_disassociate(&set);
1403 result = dns_rdatasetiter_next(rdsiter);
1404 if (destroy) {
1405 dresult = dns_db_deleterdataset(db, node, dbversion,
1406 dns_rdatatype_rrsig,
1407 covers);
1408 check_result(dresult, "dns_db_deleterdataset");
1409 }
1410 }
1411 if (result != ISC_R_NOMORE)
1412 fatal("rdataset iteration failed: %s",
1413 isc_result_totext(result));
1414 dns_rdatasetiter_destroy(&rdsiter);
1415 }
1416
1417 /*%
1418 * Set up the iterator and global state before starting the tasks.
1419 */
1420 static void
1421 presign(void) {
1422 isc_result_t result;
1423
1424 gdbiter = NULL;
1425 result = dns_db_createiterator(gdb, 0, &gdbiter);
1426 check_result(result, "dns_db_createiterator()");
1427 }
1428
1429 /*%
1430 * Clean up the iterator and global state after the tasks complete.
1431 */
1432 static void
1433 postsign(void) {
1434 dns_dbiterator_destroy(&gdbiter);
1435 }
1436
1437 /*%
1438 * Sign the apex of the zone.
1439 * Note the origin may not be the first node if there are out of zone
1440 * records.
1441 */
1442 static void
1443 signapex(void) {
1444 dns_dbnode_t *node = NULL;
1445 dns_fixedname_t fixed;
1446 dns_name_t *name;
1447 isc_result_t result;
1448
1449 name = dns_fixedname_initname(&fixed);
1450 result = dns_dbiterator_seek(gdbiter, gorigin);
1451 check_result(result, "dns_dbiterator_seek()");
1452 result = dns_dbiterator_current(gdbiter, &node, name);
1453 check_dns_dbiterator_current(result);
1454 signname(node, name);
1455 dumpnode(name, node);
1456 cleannode(gdb, gversion, node);
1457 dns_db_detachnode(gdb, &node);
1458 result = dns_dbiterator_first(gdbiter);
1459 if (result == ISC_R_NOMORE)
1460 finished = true;
1461 else if (result != ISC_R_SUCCESS)
1462 fatal("failure iterating database: %s",
1463 isc_result_totext(result));
1464 }
1465
1466 /*%
1467 * Assigns a node to a worker thread. This is protected by the master task's
1468 * lock.
1469 */
1470 static void
1471 assignwork(isc_task_t *task, isc_task_t *worker) {
1472 dns_fixedname_t *fname;
1473 dns_name_t *name;
1474 dns_dbnode_t *node;
1475 sevent_t *sevent;
1476 dns_rdataset_t nsec;
1477 bool found;
1478 isc_result_t result;
1479 static dns_name_t *zonecut = NULL; /* Protected by namelock. */
1480 static dns_fixedname_t fzonecut; /* Protected by namelock. */
1481 static unsigned int ended = 0; /* Protected by namelock. */
1482
1483 if (shuttingdown)
1484 return;
1485
1486 LOCK(&namelock);
1487 if (finished) {
1488 ended++;
1489 if (ended == ntasks) {
1490 isc_task_detach(&task);
1491 isc_app_shutdown();
1492 }
1493 goto unlock;
1494 }
1495
1496 fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
1497 if (fname == NULL)
1498 fatal("out of memory");
1499 name = dns_fixedname_initname(fname);
1500 node = NULL;
1501 found = false;
1502 while (!found) {
1503 result = dns_dbiterator_current(gdbiter, &node, name);
1504 check_dns_dbiterator_current(result);
1505 /*
1506 * The origin was handled by signapex().
1507 */
1508 if (dns_name_equal(name, gorigin)) {
1509 dns_db_detachnode(gdb, &node);
1510 goto next;
1511 }
1512 /*
1513 * Sort the zone data from the glue and out-of-zone data.
1514 * For NSEC zones nodes with zone data have NSEC records.
1515 * For NSEC3 zones the NSEC3 nodes are zone data but
1516 * outside of the zone name space. For the rest we need
1517 * to track the bottom of zone cuts.
1518 * Nodes which don't need to be signed are dumped here.
1519 */
1520 dns_rdataset_init(&nsec);
1521 result = dns_db_findrdataset(gdb, node, gversion,
1522 nsec_datatype, 0, 0,
1523 &nsec, NULL);
1524 if (dns_rdataset_isassociated(&nsec))
1525 dns_rdataset_disassociate(&nsec);
1526 if (result == ISC_R_SUCCESS) {
1527 found = true;
1528 } else if (nsec_datatype == dns_rdatatype_nsec3) {
1529 if (dns_name_issubdomain(name, gorigin) &&
1530 (zonecut == NULL ||
1531 !dns_name_issubdomain(name, zonecut))) {
1532 if (is_delegation(gdb, gversion, gorigin,
1533 name, node, NULL))
1534 {
1535 zonecut = savezonecut(&fzonecut, name);
1536 if (!OPTOUT(nsec3flags) ||
1537 secure(name, node)) {
1538 found = true;
1539 }
1540 } else if (has_dname(gdb, gversion, node)) {
1541 zonecut = savezonecut(&fzonecut, name);
1542 found = true;
1543 } else {
1544 found = true;
1545 }
1546 }
1547 }
1548
1549 if (!found) {
1550 dumpnode(name, node);
1551 dns_db_detachnode(gdb, &node);
1552 }
1553
1554 next:
1555 result = dns_dbiterator_next(gdbiter);
1556 if (result == ISC_R_NOMORE) {
1557 finished = true;
1558 break;
1559 } else if (result != ISC_R_SUCCESS)
1560 fatal("failure iterating database: %s",
1561 isc_result_totext(result));
1562 }
1563 if (!found) {
1564 ended++;
1565 if (ended == ntasks) {
1566 isc_task_detach(&task);
1567 isc_app_shutdown();
1568 }
1569 isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
1570 goto unlock;
1571 }
1572 sevent = (sevent_t *)
1573 isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
1574 sign, NULL, sizeof(sevent_t));
1575 if (sevent == NULL)
1576 fatal("failed to allocate event\n");
1577
1578 sevent->node = node;
1579 sevent->fname = fname;
1580 isc_task_send(worker, ISC_EVENT_PTR(&sevent));
1581 unlock:
1582 UNLOCK(&namelock);
1583 }
1584
1585 /*%
1586 * Start a worker task
1587 */
1588 static void
1589 startworker(isc_task_t *task, isc_event_t *event) {
1590 isc_task_t *worker;
1591
1592 worker = (isc_task_t *)event->ev_arg;
1593 assignwork(task, worker);
1594 isc_event_free(&event);
1595 }
1596
1597 /*%
1598 * Write a node to the output file, and restart the worker task.
1599 */
1600 static void
1601 writenode(isc_task_t *task, isc_event_t *event) {
1602 isc_task_t *worker;
1603 sevent_t *sevent = (sevent_t *)event;
1604
1605 worker = (isc_task_t *)event->ev_sender;
1606 dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
1607 cleannode(gdb, gversion, sevent->node);
1608 dns_db_detachnode(gdb, &sevent->node);
1609 isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
1610 assignwork(task, worker);
1611 isc_event_free(&event);
1612 }
1613
1614 /*%
1615 * Sign a database node.
1616 */
1617 static void
1618 sign(isc_task_t *task, isc_event_t *event) {
1619 dns_fixedname_t *fname;
1620 dns_dbnode_t *node;
1621 sevent_t *sevent, *wevent;
1622
1623 sevent = (sevent_t *)event;
1624 node = sevent->node;
1625 fname = sevent->fname;
1626 isc_event_free(&event);
1627
1628 signname(node, dns_fixedname_name(fname));
1629 wevent = (sevent_t *)
1630 isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
1631 writenode, NULL, sizeof(sevent_t));
1632 if (wevent == NULL)
1633 fatal("failed to allocate event\n");
1634 wevent->node = node;
1635 wevent->fname = fname;
1636 isc_task_send(master, ISC_EVENT_PTR(&wevent));
1637 }
1638
1639 /*%
1640 * Update / remove the DS RRset. Preserve RRSIG(DS) if possible.
1641 */
1642 static void
1643 add_ds(dns_name_t *name, dns_dbnode_t *node, uint32_t nsttl) {
1644 dns_rdataset_t dsset;
1645 dns_rdataset_t sigdsset;
1646 isc_result_t result;
1647
1648 dns_rdataset_init(&dsset);
1649 dns_rdataset_init(&sigdsset);
1650 result = dns_db_findrdataset(gdb, node, gversion,
1651 dns_rdatatype_ds,
1652 0, 0, &dsset, &sigdsset);
1653 if (result == ISC_R_SUCCESS) {
1654 dns_rdataset_disassociate(&dsset);
1655 result = dns_db_deleterdataset(gdb, node, gversion,
1656 dns_rdatatype_ds, 0);
1657 check_result(result, "dns_db_deleterdataset");
1658 }
1659
1660 result = loadds(name, nsttl, &dsset);
1661 if (result == ISC_R_SUCCESS) {
1662 result = dns_db_addrdataset(gdb, node, gversion, 0,
1663 &dsset, 0, NULL);
1664 check_result(result, "dns_db_addrdataset");
1665 dns_rdataset_disassociate(&dsset);
1666 if (dns_rdataset_isassociated(&sigdsset))
1667 dns_rdataset_disassociate(&sigdsset);
1668 } else if (dns_rdataset_isassociated(&sigdsset)) {
1669 result = dns_db_deleterdataset(gdb, node, gversion,
1670 dns_rdatatype_rrsig,
1671 dns_rdatatype_ds);
1672 check_result(result, "dns_db_deleterdataset");
1673 dns_rdataset_disassociate(&sigdsset);
1674 }
1675 }
1676
1677 /*
1678 * Remove records of the given type and their signatures.
1679 */
1680 static void
1681 remove_records(dns_dbnode_t *node, dns_rdatatype_t which,
1682 bool checknsec)
1683 {
1684 isc_result_t result;
1685 dns_rdatatype_t type, covers;
1686 dns_rdatasetiter_t *rdsiter = NULL;
1687 dns_rdataset_t rdataset;
1688
1689 dns_rdataset_init(&rdataset);
1690
1691 /*
1692 * Delete any records of the given type at the apex.
1693 */
1694 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1695 check_result(result, "dns_db_allrdatasets()");
1696 for (result = dns_rdatasetiter_first(rdsiter);
1697 result == ISC_R_SUCCESS;
1698 result = dns_rdatasetiter_next(rdsiter)) {
1699 dns_rdatasetiter_current(rdsiter, &rdataset);
1700 type = rdataset.type;
1701 covers = rdataset.covers;
1702 dns_rdataset_disassociate(&rdataset);
1703 if (type == which || covers == which) {
1704 if (which == dns_rdatatype_nsec &&
1705 checknsec && !update_chain)
1706 fatal("Zone contains NSEC records. Use -u "
1707 "to update to NSEC3.");
1708 if (which == dns_rdatatype_nsec3param &&
1709 checknsec && !update_chain)
1710 fatal("Zone contains NSEC3 chains. Use -u "
1711 "to update to NSEC.");
1712 result = dns_db_deleterdataset(gdb, node, gversion,
1713 type, covers);
1714 check_result(result, "dns_db_deleterdataset()");
1715 continue;
1716 }
1717 }
1718 dns_rdatasetiter_destroy(&rdsiter);
1719 }
1720
1721 /*
1722 * Remove signatures covering the given type. If type == 0,
1723 * then remove all signatures, unless this is a delegation, in
1724 * which case remove all signatures except for DS or nsec_datatype
1725 */
1726 static void
1727 remove_sigs(dns_dbnode_t *node, bool delegation,
1728 dns_rdatatype_t which)
1729 {
1730 isc_result_t result;
1731 dns_rdatatype_t type, covers;
1732 dns_rdatasetiter_t *rdsiter = NULL;
1733 dns_rdataset_t rdataset;
1734
1735 dns_rdataset_init(&rdataset);
1736 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1737 check_result(result, "dns_db_allrdatasets()");
1738 for (result = dns_rdatasetiter_first(rdsiter);
1739 result == ISC_R_SUCCESS;
1740 result = dns_rdatasetiter_next(rdsiter)) {
1741 dns_rdatasetiter_current(rdsiter, &rdataset);
1742 type = rdataset.type;
1743 covers = rdataset.covers;
1744 dns_rdataset_disassociate(&rdataset);
1745
1746 if (type != dns_rdatatype_rrsig)
1747 continue;
1748
1749 if (which == 0 && delegation &&
1750 (dns_rdatatype_atparent(covers) ||
1751 (nsec_datatype == dns_rdatatype_nsec &&
1752 covers == nsec_datatype)))
1753 continue;
1754
1755 if (which != 0 && covers != which)
1756 continue;
1757
1758 result = dns_db_deleterdataset(gdb, node, gversion,
1759 type, covers);
1760 check_result(result, "dns_db_deleterdataset()");
1761 }
1762 dns_rdatasetiter_destroy(&rdsiter);
1763 }
1764
1765 /*%
1766 * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records.
1767 */
1768 static void
1769 nsecify(void) {
1770 dns_dbiterator_t *dbiter = NULL;
1771 dns_dbnode_t *node = NULL, *nextnode = NULL;
1772 dns_fixedname_t fname, fnextname, fzonecut;
1773 dns_name_t *name, *nextname, *zonecut;
1774 dns_rdataset_t rdataset;
1775 dns_rdatasetiter_t *rdsiter = NULL;
1776 dns_rdatatype_t type, covers;
1777 bool done = false;
1778 isc_result_t result;
1779 uint32_t nsttl = 0;
1780
1781 dns_rdataset_init(&rdataset);
1782 name = dns_fixedname_initname(&fname);
1783 nextname = dns_fixedname_initname(&fnextname);
1784 zonecut = NULL;
1785
1786 /*
1787 * Remove any NSEC3 chains.
1788 */
1789 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
1790 check_result(result, "dns_db_createiterator()");
1791 for (result = dns_dbiterator_first(dbiter);
1792 result == ISC_R_SUCCESS;
1793 result = dns_dbiterator_next(dbiter)) {
1794 result = dns_dbiterator_current(dbiter, &node, name);
1795 check_dns_dbiterator_current(result);
1796 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1797 check_result(result, "dns_db_allrdatasets()");
1798 for (result = dns_rdatasetiter_first(rdsiter);
1799 result == ISC_R_SUCCESS;
1800 result = dns_rdatasetiter_next(rdsiter)) {
1801 dns_rdatasetiter_current(rdsiter, &rdataset);
1802 type = rdataset.type;
1803 covers = rdataset.covers;
1804 dns_rdataset_disassociate(&rdataset);
1805 result = dns_db_deleterdataset(gdb, node, gversion,
1806 type, covers);
1807 check_result(result,
1808 "dns_db_deleterdataset(nsec3param/rrsig)");
1809 }
1810 dns_rdatasetiter_destroy(&rdsiter);
1811 dns_db_detachnode(gdb, &node);
1812 }
1813 dns_dbiterator_destroy(&dbiter);
1814
1815 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
1816 check_result(result, "dns_db_createiterator()");
1817
1818 result = dns_dbiterator_first(dbiter);
1819 check_result(result, "dns_dbiterator_first()");
1820
1821 while (!done) {
1822 result = dns_dbiterator_current(dbiter, &node, name);
1823 check_dns_dbiterator_current(result);
1824 /*
1825 * Skip out-of-zone records.
1826 */
1827 if (!dns_name_issubdomain(name, gorigin)) {
1828 result = dns_dbiterator_next(dbiter);
1829 if (result == ISC_R_NOMORE)
1830 done = true;
1831 else
1832 check_result(result, "dns_dbiterator_next()");
1833 dns_db_detachnode(gdb, &node);
1834 continue;
1835 }
1836
1837 if (dns_name_equal(name, gorigin)) {
1838 remove_records(node, dns_rdatatype_nsec3param,
1839 true);
1840 /* Clean old rrsigs at apex. */
1841 (void)active_node(node);
1842 }
1843
1844 if (is_delegation(gdb, gversion, gorigin, name, node, &nsttl)) {
1845 zonecut = savezonecut(&fzonecut, name);
1846 remove_sigs(node, true, 0);
1847 if (generateds)
1848 add_ds(name, node, nsttl);
1849 } else if (has_dname(gdb, gversion, node)) {
1850 zonecut = savezonecut(&fzonecut, name);
1851 }
1852
1853 result = dns_dbiterator_next(dbiter);
1854 nextnode = NULL;
1855 while (result == ISC_R_SUCCESS) {
1856 bool active = false;
1857 result = dns_dbiterator_current(dbiter, &nextnode,
1858 nextname);
1859 check_dns_dbiterator_current(result);
1860 active = active_node(nextnode);
1861 if (!active) {
1862 dns_db_detachnode(gdb, &nextnode);
1863 result = dns_dbiterator_next(dbiter);
1864 continue;
1865 }
1866 if (!dns_name_issubdomain(nextname, gorigin) ||
1867 (zonecut != NULL &&
1868 dns_name_issubdomain(nextname, zonecut)))
1869 {
1870 remove_sigs(nextnode, false, 0);
1871 remove_records(nextnode, dns_rdatatype_nsec,
1872 false);
1873 dns_db_detachnode(gdb, &nextnode);
1874 result = dns_dbiterator_next(dbiter);
1875 continue;
1876 }
1877 dns_db_detachnode(gdb, &nextnode);
1878 break;
1879 }
1880 if (result == ISC_R_NOMORE) {
1881 dns_name_clone(gorigin, nextname);
1882 done = true;
1883 } else if (result != ISC_R_SUCCESS)
1884 fatal("iterating through the database failed: %s",
1885 isc_result_totext(result));
1886 dns_dbiterator_pause(dbiter);
1887 result = dns_nsec_build(gdb, gversion, node, nextname,
1888 zone_soa_min_ttl);
1889 check_result(result, "dns_nsec_build()");
1890 dns_db_detachnode(gdb, &node);
1891 }
1892
1893 dns_dbiterator_destroy(&dbiter);
1894 }
1895
1896 static void
1897 addnsec3param(const unsigned char *salt, size_t salt_len,
1898 dns_iterations_t iterations)
1899 {
1900 dns_dbnode_t *node = NULL;
1901 dns_rdata_nsec3param_t nsec3param;
1902 unsigned char nsec3parambuf[5 + 255];
1903 dns_rdatalist_t rdatalist;
1904 dns_rdataset_t rdataset;
1905 dns_rdata_t rdata = DNS_RDATA_INIT;
1906 isc_buffer_t b;
1907 isc_result_t result;
1908
1909 dns_rdataset_init(&rdataset);
1910
1911 nsec3param.common.rdclass = gclass;
1912 nsec3param.common.rdtype = dns_rdatatype_nsec3param;
1913 ISC_LINK_INIT(&nsec3param.common, link);
1914 nsec3param.mctx = NULL;
1915 nsec3param.flags = 0;
1916 nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1;
1917 nsec3param.iterations = iterations;
1918 nsec3param.salt_length = (unsigned char)salt_len;
1919 DE_CONST(salt, nsec3param.salt);
1920
1921 isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf));
1922 result = dns_rdata_fromstruct(&rdata, gclass,
1923 dns_rdatatype_nsec3param,
1924 &nsec3param, &b);
1925 check_result(result, "dns_rdata_fromstruct()");
1926 dns_rdatalist_init(&rdatalist);
1927 rdatalist.rdclass = rdata.rdclass;
1928 rdatalist.type = rdata.type;
1929 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
1930 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
1931 check_result(result, "dns_rdatalist_tordataset()");
1932
1933 result = dns_db_findnode(gdb, gorigin, true, &node);
1934 check_result(result, "dns_db_find(gorigin)");
1935
1936 /*
1937 * Delete any current NSEC3PARAM records.
1938 */
1939 result = dns_db_deleterdataset(gdb, node, gversion,
1940 dns_rdatatype_nsec3param, 0);
1941 if (result == DNS_R_UNCHANGED)
1942 result = ISC_R_SUCCESS;
1943 check_result(result, "dddnsec3param: dns_db_deleterdataset()");
1944
1945 result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset,
1946 DNS_DBADD_MERGE, NULL);
1947 if (result == DNS_R_UNCHANGED)
1948 result = ISC_R_SUCCESS;
1949 check_result(result, "addnsec3param: dns_db_addrdataset()");
1950 dns_db_detachnode(gdb, &node);
1951 }
1952
1953 static void
1954 addnsec3(dns_name_t *name, dns_dbnode_t *node,
1955 const unsigned char *salt, size_t salt_len,
1956 unsigned int iterations, hashlist_t *hashlist,
1957 dns_ttl_t ttl)
1958 {
1959 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
1960 const unsigned char *nexthash;
1961 unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE];
1962 dns_fixedname_t hashname;
1963 dns_rdatalist_t rdatalist;
1964 dns_rdataset_t rdataset;
1965 dns_rdata_t rdata = DNS_RDATA_INIT;
1966 isc_result_t result;
1967 dns_dbnode_t *nsec3node = NULL;
1968 char namebuf[DNS_NAME_FORMATSIZE];
1969 size_t hash_len;
1970
1971 dns_name_format(name, namebuf, sizeof(namebuf));
1972
1973 dns_fixedname_init(&hashname);
1974 dns_rdataset_init(&rdataset);
1975
1976 dns_name_downcase(name, name, NULL);
1977 result = dns_nsec3_hashname(&hashname, hash, &hash_len,
1978 name, gorigin, dns_hash_sha1, iterations,
1979 salt, salt_len);
1980 check_result(result, "addnsec3: dns_nsec3_hashname()");
1981 nexthash = hashlist_findnext(hashlist, hash);
1982 result = dns_nsec3_buildrdata(gdb, gversion, node,
1983 unknownalg ?
1984 DNS_NSEC3_UNKNOWNALG : dns_hash_sha1,
1985 nsec3flags, iterations,
1986 salt, salt_len,
1987 nexthash, ISC_SHA1_DIGESTLENGTH,
1988 nsec3buffer, &rdata);
1989 check_result(result, "addnsec3: dns_nsec3_buildrdata()");
1990 dns_rdatalist_init(&rdatalist);
1991 rdatalist.rdclass = rdata.rdclass;
1992 rdatalist.type = rdata.type;
1993 rdatalist.ttl = ttl;
1994 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
1995 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
1996 check_result(result, "dns_rdatalist_tordataset()");
1997 result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname),
1998 true, &nsec3node);
1999 check_result(result, "addnsec3: dns_db_findnode()");
2000 result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset,
2001 0, NULL);
2002 if (result == DNS_R_UNCHANGED)
2003 result = ISC_R_SUCCESS;
2004 check_result(result, "addnsec3: dns_db_addrdataset()");
2005 dns_db_detachnode(gdb, &nsec3node);
2006 }
2007
2008 /*%
2009 * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list.
2010 *
2011 * Extract the hash from the first label of 'name' then see if it
2012 * is in hashlist. If 'name' is not in the hashlist then delete the
2013 * any NSEC3 records which have the same parameters as the chain we
2014 * are building.
2015 *
2016 * XXXMPA Should we also check that it of the form &lt;hash&gt;.&lt;origin&gt;?
2017 */
2018 static void
2019 nsec3clean(dns_name_t *name, dns_dbnode_t *node,
2020 unsigned int hashalg, unsigned int iterations,
2021 const unsigned char *salt, size_t salt_len, hashlist_t *hashlist)
2022 {
2023 dns_label_t label;
2024 dns_rdata_nsec3_t nsec3;
2025 dns_rdata_t rdata, delrdata;
2026 dns_rdatalist_t rdatalist;
2027 dns_rdataset_t rdataset, delrdataset;
2028 bool delete_rrsigs = false;
2029 isc_buffer_t target;
2030 isc_result_t result;
2031 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
2032 bool exists;
2033
2034 /*
2035 * Get the first label.
2036 */
2037 dns_name_getlabel(name, 0, &label);
2038
2039 /*
2040 * We want just the label contents.
2041 */
2042 isc_region_consume(&label, 1);
2043
2044 /*
2045 * Decode base32hex string.
2046 */
2047 isc_buffer_init(&target, hash, sizeof(hash) - 1);
2048 result = isc_base32hex_decoderegion(&label, &target);
2049 if (result != ISC_R_SUCCESS)
2050 return;
2051
2052 hash[isc_buffer_usedlength(&target)] = 0;
2053
2054 exists = hashlist_exists(hashlist, hash);
2055
2056 /*
2057 * Verify that the NSEC3 parameters match the current ones
2058 * otherwise we are dealing with a different NSEC3 chain.
2059 */
2060 dns_rdataset_init(&rdataset);
2061 dns_rdataset_init(&delrdataset);
2062
2063 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3,
2064 0, 0, &rdataset, NULL);
2065 if (result != ISC_R_SUCCESS)
2066 return;
2067
2068 /*
2069 * Delete any NSEC3 records which are not part of the current
2070 * NSEC3 chain.
2071 */
2072 for (result = dns_rdataset_first(&rdataset);
2073 result == ISC_R_SUCCESS;
2074 result = dns_rdataset_next(&rdataset)) {
2075 dns_rdata_init(&rdata);
2076 dns_rdataset_current(&rdataset, &rdata);
2077 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
2078 check_result(result, "dns_rdata_tostruct");
2079 if (exists && nsec3.hash == hashalg &&
2080 nsec3.iterations == iterations &&
2081 nsec3.salt_length == salt_len &&
2082 isc_safe_memequal(nsec3.salt, salt, salt_len))
2083 continue;
2084 dns_rdatalist_init(&rdatalist);
2085 rdatalist.rdclass = rdata.rdclass;
2086 rdatalist.type = rdata.type;
2087 if (set_maxttl)
2088 rdatalist.ttl = ISC_MIN(rdataset.ttl, maxttl);
2089 dns_rdata_init(&delrdata);
2090 dns_rdata_clone(&rdata, &delrdata);
2091 ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link);
2092 result = dns_rdatalist_tordataset(&rdatalist, &delrdataset);
2093 check_result(result, "dns_rdatalist_tordataset()");
2094 result = dns_db_subtractrdataset(gdb, node, gversion,
2095 &delrdataset, 0, NULL);
2096 dns_rdataset_disassociate(&delrdataset);
2097 if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET)
2098 check_result(result, "dns_db_subtractrdataset(NSEC3)");
2099 delete_rrsigs = true;
2100 }
2101 dns_rdataset_disassociate(&rdataset);
2102 if (result != ISC_R_NOMORE)
2103 check_result(result, "dns_rdataset_first/next");
2104
2105 if (!delete_rrsigs)
2106 return;
2107 /*
2108 * Delete the NSEC3 RRSIGs
2109 */
2110 result = dns_db_deleterdataset(gdb, node, gversion,
2111 dns_rdatatype_rrsig,
2112 dns_rdatatype_nsec3);
2113 if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
2114 check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))");
2115 }
2116
2117 static void
2118 rrset_cleanup(dns_name_t *name, dns_rdataset_t *rdataset,
2119 dns_diff_t *add, dns_diff_t *del)
2120 {
2121 isc_result_t result;
2122 unsigned int count1 = 0;
2123 dns_rdataset_t tmprdataset;
2124 char namestr[DNS_NAME_FORMATSIZE];
2125 char typestr[DNS_RDATATYPE_FORMATSIZE];
2126
2127 dns_name_format(name, namestr, sizeof(namestr));
2128 dns_rdatatype_format(rdataset->type, typestr, sizeof(typestr));
2129
2130 dns_rdataset_init(&tmprdataset);
2131 for (result = dns_rdataset_first(rdataset);
2132 result == ISC_R_SUCCESS;
2133 result = dns_rdataset_next(rdataset)) {
2134 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2135 unsigned int count2 = 0;
2136
2137 count1++;
2138 dns_rdataset_current(rdataset, &rdata1);
2139 dns_rdataset_clone(rdataset, &tmprdataset);
2140 for (result = dns_rdataset_first(&tmprdataset);
2141 result == ISC_R_SUCCESS;
2142 result = dns_rdataset_next(&tmprdataset)) {
2143 dns_rdata_t rdata2 = DNS_RDATA_INIT;
2144 dns_difftuple_t *tuple = NULL;
2145 count2++;
2146 dns_rdataset_current(&tmprdataset, &rdata2);
2147 if (count1 < count2 &&
2148 dns_rdata_casecompare(&rdata1, &rdata2) == 0)
2149 {
2150 vbprintf(2, "removing duplicate at %s/%s\n",
2151 namestr, typestr);
2152 result = dns_difftuple_create(mctx,
2153 DNS_DIFFOP_DELRESIGN,
2154 name, rdataset->ttl,
2155 &rdata2, &tuple);
2156 check_result(result, "dns_difftuple_create");
2157 dns_diff_append(del, &tuple);
2158 } else if (set_maxttl && rdataset->ttl > maxttl) {
2159 vbprintf(2, "reducing ttl of %s/%s "
2160 "from %d to %d\n",
2161 namestr, typestr,
2162 rdataset->ttl, maxttl);
2163 result = dns_difftuple_create(mctx,
2164 DNS_DIFFOP_DELRESIGN,
2165 name, rdataset->ttl,
2166 &rdata2, &tuple);
2167 check_result(result, "dns_difftuple_create");
2168 dns_diff_append(del, &tuple);
2169 tuple = NULL;
2170 result = dns_difftuple_create(mctx,
2171 DNS_DIFFOP_ADDRESIGN,
2172 name, maxttl,
2173 &rdata2, &tuple);
2174 check_result(result, "dns_difftuple_create");
2175 dns_diff_append(add, &tuple);
2176 }
2177 }
2178 dns_rdataset_disassociate(&tmprdataset);
2179 }
2180 }
2181
2182 static void
2183 cleanup_zone(void) {
2184 isc_result_t result;
2185 dns_dbiterator_t *dbiter = NULL;
2186 dns_rdatasetiter_t *rdsiter = NULL;
2187 dns_diff_t add, del;
2188 dns_dbnode_t *node = NULL;
2189 dns_rdataset_t rdataset;
2190 dns_fixedname_t fname;
2191 dns_name_t *name;
2192
2193 dns_diff_init(mctx, &add);
2194 dns_diff_init(mctx, &del);
2195 name = dns_fixedname_initname(&fname);
2196 dns_rdataset_init(&rdataset);
2197
2198 result = dns_db_createiterator(gdb, 0, &dbiter);
2199 check_result(result, "dns_db_createiterator()");
2200
2201 for (result = dns_dbiterator_first(dbiter);
2202 result == ISC_R_SUCCESS;
2203 result = dns_dbiterator_next(dbiter)) {
2204
2205 result = dns_dbiterator_current(dbiter, &node, name);
2206 check_dns_dbiterator_current(result);
2207 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
2208 check_result(result, "dns_db_allrdatasets()");
2209 for (result = dns_rdatasetiter_first(rdsiter);
2210 result == ISC_R_SUCCESS;
2211 result = dns_rdatasetiter_next(rdsiter)) {
2212 dns_rdatasetiter_current(rdsiter, &rdataset);
2213 rrset_cleanup(name, &rdataset, &add, &del);
2214 dns_rdataset_disassociate(&rdataset);
2215 }
2216 if (result != ISC_R_NOMORE)
2217 fatal("rdatasets iteration failed.");
2218 dns_rdatasetiter_destroy(&rdsiter);
2219 dns_db_detachnode(gdb, &node);
2220 }
2221 if (result != ISC_R_NOMORE)
2222 fatal("zone iteration failed.");
2223
2224 result = dns_diff_applysilently(&del, gdb, gversion);
2225 check_result(result, "dns_diff_applysilently");
2226
2227 result = dns_diff_applysilently(&add, gdb, gversion);
2228 check_result(result, "dns_diff_applysilently");
2229
2230 dns_diff_clear(&del);
2231 dns_diff_clear(&add);
2232 dns_dbiterator_destroy(&dbiter);
2233 }
2234
2235 /*
2236 * Generate NSEC3 records for the zone.
2237 */
2238 static void
2239 nsec3ify(unsigned int hashalg, dns_iterations_t iterations,
2240 const unsigned char *salt, size_t salt_len, hashlist_t *hashlist)
2241 {
2242 dns_dbiterator_t *dbiter = NULL;
2243 dns_dbnode_t *node = NULL, *nextnode = NULL;
2244 dns_fixedname_t fname, fnextname, fzonecut;
2245 dns_name_t *name, *nextname, *zonecut;
2246 dns_rdataset_t rdataset;
2247 int order;
2248 bool active;
2249 bool done = false;
2250 isc_result_t result;
2251 uint32_t nsttl = 0;
2252 unsigned int count, nlabels;
2253
2254 dns_rdataset_init(&rdataset);
2255 name = dns_fixedname_initname(&fname);
2256 nextname = dns_fixedname_initname(&fnextname);
2257 zonecut = NULL;
2258
2259 /*
2260 * Walk the zone generating the hash names.
2261 */
2262 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2263 check_result(result, "dns_db_createiterator()");
2264
2265 result = dns_dbiterator_first(dbiter);
2266 check_result(result, "dns_dbiterator_first()");
2267
2268 while (!done) {
2269 result = dns_dbiterator_current(dbiter, &node, name);
2270 check_dns_dbiterator_current(result);
2271 /*
2272 * Skip out-of-zone records.
2273 */
2274 if (!dns_name_issubdomain(name, gorigin)) {
2275 result = dns_dbiterator_next(dbiter);
2276 if (result == ISC_R_NOMORE)
2277 done = true;
2278 else
2279 check_result(result, "dns_dbiterator_next()");
2280 dns_db_detachnode(gdb, &node);
2281 continue;
2282 }
2283
2284 if (dns_name_equal(name, gorigin)) {
2285 remove_records(node, dns_rdatatype_nsec, true);
2286 /* Clean old rrsigs at apex. */
2287 (void)active_node(node);
2288 }
2289
2290 if (has_dname(gdb, gversion, node)) {
2291 zonecut = savezonecut(&fzonecut, name);
2292 }
2293
2294 result = dns_dbiterator_next(dbiter);
2295 nextnode = NULL;
2296 while (result == ISC_R_SUCCESS) {
2297 result = dns_dbiterator_current(dbiter, &nextnode,
2298 nextname);
2299 check_dns_dbiterator_current(result);
2300 active = active_node(nextnode);
2301 if (!active) {
2302 dns_db_detachnode(gdb, &nextnode);
2303 result = dns_dbiterator_next(dbiter);
2304 continue;
2305 }
2306 if (!dns_name_issubdomain(nextname, gorigin) ||
2307 (zonecut != NULL &&
2308 dns_name_issubdomain(nextname, zonecut))) {
2309 remove_sigs(nextnode, false, 0);
2310 dns_db_detachnode(gdb, &nextnode);
2311 result = dns_dbiterator_next(dbiter);
2312 continue;
2313 }
2314 if (is_delegation(gdb, gversion, gorigin,
2315 nextname, nextnode, &nsttl))
2316 {
2317 zonecut = savezonecut(&fzonecut, nextname);
2318 remove_sigs(nextnode, true, 0);
2319 if (generateds)
2320 add_ds(nextname, nextnode, nsttl);
2321 if (OPTOUT(nsec3flags) &&
2322 !secure(nextname, nextnode)) {
2323 dns_db_detachnode(gdb, &nextnode);
2324 result = dns_dbiterator_next(dbiter);
2325 continue;
2326 }
2327 } else if (has_dname(gdb, gversion, nextnode)) {
2328 zonecut = savezonecut(&fzonecut, nextname);
2329 }
2330 dns_db_detachnode(gdb, &nextnode);
2331 break;
2332 }
2333 if (result == ISC_R_NOMORE) {
2334 dns_name_copy(gorigin, nextname, NULL);
2335 done = true;
2336 } else if (result != ISC_R_SUCCESS)
2337 fatal("iterating through the database failed: %s",
2338 isc_result_totext(result));
2339 dns_name_downcase(name, name, NULL);
2340 hashlist_add_dns_name(hashlist, name, hashalg, iterations,
2341 salt, salt_len, false);
2342 dns_db_detachnode(gdb, &node);
2343 /*
2344 * Add hashs for empty nodes. Use closest encloser logic.
2345 * The closest encloser either has data or is a empty
2346 * node for another <name,nextname> span so we don't add
2347 * it here. Empty labels on nextname are within the span.
2348 */
2349 dns_name_downcase(nextname, nextname, NULL);
2350 dns_name_fullcompare(name, nextname, &order, &nlabels);
2351 addnowildcardhash(hashlist, name, hashalg, iterations,
2352 salt, salt_len);
2353 count = dns_name_countlabels(nextname);
2354 while (count > nlabels + 1) {
2355 count--;
2356 dns_name_split(nextname, count, NULL, nextname);
2357 hashlist_add_dns_name(hashlist, nextname, hashalg,
2358 iterations, salt, salt_len,
2359 false);
2360 addnowildcardhash(hashlist, nextname, hashalg,
2361 iterations, salt, salt_len);
2362 }
2363 }
2364 dns_dbiterator_destroy(&dbiter);
2365
2366 /*
2367 * We have all the hashes now so we can sort them.
2368 */
2369 hashlist_sort(hashlist);
2370
2371 /*
2372 * Check for duplicate hashes. If found the salt needs to
2373 * be changed.
2374 */
2375 if (hashlist_hasdup(hashlist))
2376 fatal("Duplicate hash detected. Pick a different salt.");
2377
2378 /*
2379 * Generate the nsec3 records.
2380 */
2381 zonecut = NULL;
2382 done = false;
2383
2384 addnsec3param(salt, salt_len, iterations);
2385
2386 /*
2387 * Clean out NSEC3 records which don't match this chain.
2388 */
2389 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
2390 check_result(result, "dns_db_createiterator()");
2391
2392 for (result = dns_dbiterator_first(dbiter);
2393 result == ISC_R_SUCCESS;
2394 result = dns_dbiterator_next(dbiter)) {
2395 result = dns_dbiterator_current(dbiter, &node, name);
2396 check_dns_dbiterator_current(result);
2397 nsec3clean(name, node, hashalg, iterations, salt, salt_len,
2398 hashlist);
2399 dns_db_detachnode(gdb, &node);
2400 }
2401 dns_dbiterator_destroy(&dbiter);
2402
2403 /*
2404 * Generate / complete the new chain.
2405 */
2406 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2407 check_result(result, "dns_db_createiterator()");
2408
2409 result = dns_dbiterator_first(dbiter);
2410 check_result(result, "dns_dbiterator_first()");
2411
2412 while (!done) {
2413 result = dns_dbiterator_current(dbiter, &node, name);
2414 check_dns_dbiterator_current(result);
2415 /*
2416 * Skip out-of-zone records.
2417 */
2418 if (!dns_name_issubdomain(name, gorigin)) {
2419 result = dns_dbiterator_next(dbiter);
2420 if (result == ISC_R_NOMORE)
2421 done = true;
2422 else
2423 check_result(result, "dns_dbiterator_next()");
2424 dns_db_detachnode(gdb, &node);
2425 continue;
2426 }
2427
2428 if (has_dname(gdb, gversion, node)) {
2429 zonecut = savezonecut(&fzonecut, name);
2430 }
2431
2432 result = dns_dbiterator_next(dbiter);
2433 nextnode = NULL;
2434 while (result == ISC_R_SUCCESS) {
2435 result = dns_dbiterator_current(dbiter, &nextnode,
2436 nextname);
2437 check_dns_dbiterator_current(result);
2438 active = active_node(nextnode);
2439 if (!active) {
2440 dns_db_detachnode(gdb, &nextnode);
2441 result = dns_dbiterator_next(dbiter);
2442 continue;
2443 }
2444 if (!dns_name_issubdomain(nextname, gorigin) ||
2445 (zonecut != NULL &&
2446 dns_name_issubdomain(nextname, zonecut))) {
2447 dns_db_detachnode(gdb, &nextnode);
2448 result = dns_dbiterator_next(dbiter);
2449 continue;
2450 }
2451 if (is_delegation(gdb, gversion, gorigin,
2452 nextname, nextnode, NULL))
2453 {
2454 zonecut = savezonecut(&fzonecut, nextname);
2455 if (OPTOUT(nsec3flags) &&
2456 !secure(nextname, nextnode)) {
2457 dns_db_detachnode(gdb, &nextnode);
2458 result = dns_dbiterator_next(dbiter);
2459 continue;
2460 }
2461 } else if (has_dname(gdb, gversion, nextnode)) {
2462 zonecut = savezonecut(&fzonecut, nextname);
2463 }
2464 dns_db_detachnode(gdb, &nextnode);
2465 break;
2466 }
2467 if (result == ISC_R_NOMORE) {
2468 dns_name_copy(gorigin, nextname, NULL);
2469 done = true;
2470 } else if (result != ISC_R_SUCCESS)
2471 fatal("iterating through the database failed: %s",
2472 isc_result_totext(result));
2473 /*
2474 * We need to pause here to release the lock on the database.
2475 */
2476 dns_dbiterator_pause(dbiter);
2477 addnsec3(name, node, salt, salt_len, iterations,
2478 hashlist, zone_soa_min_ttl);
2479 dns_db_detachnode(gdb, &node);
2480 /*
2481 * Add NSEC3's for empty nodes. Use closest encloser logic.
2482 */
2483 dns_name_fullcompare(name, nextname, &order, &nlabels);
2484 count = dns_name_countlabels(nextname);
2485 while (count > nlabels + 1) {
2486 count--;
2487 dns_name_split(nextname, count, NULL, nextname);
2488 addnsec3(nextname, NULL, salt, salt_len,
2489 iterations, hashlist, zone_soa_min_ttl);
2490 }
2491 }
2492 dns_dbiterator_destroy(&dbiter);
2493 }
2494
2495 /*%
2496 * Load the zone file from disk
2497 */
2498 static void
2499 loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
2500 isc_buffer_t b;
2501 int len;
2502 dns_fixedname_t fname;
2503 dns_name_t *name;
2504 isc_result_t result;
2505
2506 len = strlen(origin);
2507 isc_buffer_init(&b, origin, len);
2508 isc_buffer_add(&b, len);
2509
2510 name = dns_fixedname_initname(&fname);
2511 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
2512 if (result != ISC_R_SUCCESS)
2513 fatal("failed converting name '%s' to dns format: %s",
2514 origin, isc_result_totext(result));
2515
2516 result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
2517 rdclass, 0, NULL, db);
2518 check_result(result, "dns_db_create()");
2519
2520 result = dns_db_load(*db, file, inputformat, 0);
2521 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
2522 fatal("failed loading zone from '%s': %s",
2523 file, isc_result_totext(result));
2524 }
2525
2526 /*%
2527 * Finds all public zone keys in the zone, and attempts to load the
2528 * private keys from disk.
2529 */
2530 static void
2531 loadzonekeys(bool preserve_keys, bool load_public) {
2532 dns_dbnode_t *node;
2533 dns_dbversion_t *currentversion = NULL;
2534 isc_result_t result;
2535 dns_rdataset_t rdataset, keysigs, soasigs;
2536
2537 node = NULL;
2538 result = dns_db_findnode(gdb, gorigin, false, &node);
2539 if (result != ISC_R_SUCCESS)
2540 fatal("failed to find the zone's origin: %s",
2541 isc_result_totext(result));
2542
2543 dns_db_currentversion(gdb, &currentversion);
2544
2545 dns_rdataset_init(&rdataset);
2546 dns_rdataset_init(&soasigs);
2547 dns_rdataset_init(&keysigs);
2548
2549 /* Make note of the keys which signed the SOA, if any */
2550 result = dns_db_findrdataset(gdb, node, currentversion,
2551 dns_rdatatype_soa, 0, 0,
2552 &rdataset, &soasigs);
2553 if (result != ISC_R_SUCCESS)
2554 goto cleanup;
2555
2556 /* Preserve the TTL of the DNSKEY RRset, if any */
2557 dns_rdataset_disassociate(&rdataset);
2558 result = dns_db_findrdataset(gdb, node, currentversion,
2559 dns_rdatatype_dnskey, 0, 0,
2560 &rdataset, &keysigs);
2561
2562 if (result != ISC_R_SUCCESS)
2563 goto cleanup;
2564
2565 if (set_keyttl && keyttl != rdataset.ttl) {
2566 fprintf(stderr, "User-specified TTL %u conflicts "
2567 "with existing DNSKEY RRset TTL.\n",
2568 keyttl);
2569 fprintf(stderr, "Imported keys will use the RRSet "
2570 "TTL %u instead.\n",
2571 rdataset.ttl);
2572 }
2573 keyttl = rdataset.ttl;
2574
2575 /* Load keys corresponding to the existing DNSKEY RRset. */
2576 result = dns_dnssec_keylistfromrdataset(gorigin, directory, mctx,
2577 &rdataset, &keysigs, &soasigs,
2578 preserve_keys, load_public,
2579 &keylist);
2580 if (result != ISC_R_SUCCESS)
2581 fatal("failed to load the zone keys: %s",
2582 isc_result_totext(result));
2583
2584 cleanup:
2585 if (dns_rdataset_isassociated(&rdataset))
2586 dns_rdataset_disassociate(&rdataset);
2587 if (dns_rdataset_isassociated(&keysigs))
2588 dns_rdataset_disassociate(&keysigs);
2589 if (dns_rdataset_isassociated(&soasigs))
2590 dns_rdataset_disassociate(&soasigs);
2591 dns_db_detachnode(gdb, &node);
2592 dns_db_closeversion(gdb, &currentversion, false);
2593 }
2594
2595 static void
2596 loadexplicitkeys(char *keyfiles[], int n, bool setksk) {
2597 isc_result_t result;
2598 int i;
2599
2600 for (i = 0; i < n; i++) {
2601 dns_dnsseckey_t *key = NULL;
2602 dst_key_t *newkey = NULL;
2603
2604 result = dst_key_fromnamedfile(keyfiles[i], directory,
2605 DST_TYPE_PUBLIC |
2606 DST_TYPE_PRIVATE,
2607 mctx, &newkey);
2608 if (result != ISC_R_SUCCESS)
2609 fatal("cannot load dnskey %s: %s", keyfiles[i],
2610 isc_result_totext(result));
2611
2612 if (!dns_name_equal(gorigin, dst_key_name(newkey)))
2613 fatal("key %s not at origin\n", keyfiles[i]);
2614
2615 if (!dst_key_isprivate(newkey))
2616 fatal("cannot sign zone with non-private dnskey %s",
2617 keyfiles[i]);
2618
2619 /* Skip any duplicates */
2620 for (key = ISC_LIST_HEAD(keylist);
2621 key != NULL;
2622 key = ISC_LIST_NEXT(key, link)) {
2623 if (dst_key_id(key->key) == dst_key_id(newkey) &&
2624 dst_key_alg(key->key) == dst_key_alg(newkey))
2625 break;
2626 }
2627
2628 if (key == NULL) {
2629 /* We haven't seen this key before */
2630 dns_dnsseckey_create(mctx, &newkey, &key);
2631 ISC_LIST_APPEND(keylist, key, link);
2632 key->source = dns_keysource_user;
2633 } else {
2634 dst_key_free(&key->key);
2635 key->key = newkey;
2636 }
2637
2638 key->force_publish = true;
2639 key->force_sign = true;
2640
2641 if (setksk)
2642 key->ksk = true;
2643 }
2644 }
2645
2646 static void
2647 report(const char *format, ...) {
2648 va_list args;
2649 va_start(args, format);
2650 vfprintf(stderr, format, args);
2651 va_end(args);
2652 putc('\n', stderr);
2653 }
2654
2655 static void
2656 clear_keylist(dns_dnsseckeylist_t *list) {
2657 dns_dnsseckey_t *key;
2658 while (!ISC_LIST_EMPTY(*list)) {
2659 key = ISC_LIST_HEAD(*list);
2660 ISC_LIST_UNLINK(*list, key, link);
2661 dns_dnsseckey_destroy(mctx, &key);
2662 }
2663 }
2664
2665 static void
2666 build_final_keylist(void) {
2667 isc_result_t result;
2668 dns_dbnode_t *node = NULL;
2669 dns_dbversion_t *ver = NULL;
2670 dns_diff_t diff;
2671 dns_dnsseckeylist_t rmkeys, matchkeys;
2672 char name[DNS_NAME_FORMATSIZE];
2673 dns_rdataset_t cdsset, cdnskeyset, soaset;
2674
2675 ISC_LIST_INIT(rmkeys);
2676 ISC_LIST_INIT(matchkeys);
2677
2678 dns_rdataset_init(&soaset);
2679 dns_rdataset_init(&cdsset);
2680 dns_rdataset_init(&cdnskeyset);
2681
2682 /*
2683 * Find keys that match this zone in the key repository.
2684 */
2685 result = dns_dnssec_findmatchingkeys(gorigin, directory,
2686 now, mctx, &matchkeys);
2687 if (result == ISC_R_NOTFOUND) {
2688 result = ISC_R_SUCCESS;
2689 }
2690 check_result(result, "dns_dnssec_findmatchingkeys");
2691
2692 result = dns_db_newversion(gdb, &ver);
2693 check_result(result, "dns_db_newversion");
2694
2695 result = dns_db_getoriginnode(gdb, &node);
2696 check_result(result, "dns_db_getoriginnode");
2697
2698 /* Get the CDS rdataset */
2699 result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_cds,
2700 dns_rdatatype_none, 0, &cdsset, NULL);
2701 if (result != ISC_R_SUCCESS &&
2702 dns_rdataset_isassociated(&cdsset))
2703 {
2704 dns_rdataset_disassociate(&cdsset);
2705 }
2706
2707 /* Get the CDNSKEY rdataset */
2708 result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_cdnskey,
2709 dns_rdatatype_none, 0, &cdnskeyset, NULL);
2710 if (result != ISC_R_SUCCESS &&
2711 dns_rdataset_isassociated(&cdnskeyset))
2712 {
2713 dns_rdataset_disassociate(&cdnskeyset);
2714 }
2715
2716 dns_diff_init(mctx, &diff);
2717
2718 /*
2719 * Update keylist with information from from the key repository.
2720 */
2721 dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl,
2722 &diff, ignore_kskflag, mctx, report);
2723
2724 /*
2725 * Update keylist with sync records.
2726 */
2727 dns_dnssec_syncupdate(&keylist, &rmkeys, &cdsset, &cdnskeyset,
2728 now, keyttl, &diff, mctx);
2729
2730 dns_name_format(gorigin, name, sizeof(name));
2731
2732 result = dns_diff_applysilently(&diff, gdb, ver);
2733 if (result != ISC_R_SUCCESS) {
2734 fatal("failed to update DNSKEY RRset at node '%s': %s",
2735 name, isc_result_totext(result));
2736 }
2737
2738 dns_db_detachnode(gdb, &node);
2739 dns_db_closeversion(gdb, &ver, true);
2740
2741 dns_diff_clear(&diff);
2742
2743 if (dns_rdataset_isassociated(&cdsset)) {
2744 dns_rdataset_disassociate(&cdsset);
2745 }
2746 if (dns_rdataset_isassociated(&cdnskeyset)) {
2747 dns_rdataset_disassociate(&cdnskeyset);
2748 }
2749
2750 clear_keylist(&rmkeys);
2751 clear_keylist(&matchkeys);
2752 }
2753
2754 static void
2755 warnifallksk(dns_db_t *db) {
2756 dns_dbversion_t *currentversion = NULL;
2757 dns_dbnode_t *node = NULL;
2758 dns_rdataset_t rdataset;
2759 dns_rdata_t rdata = DNS_RDATA_INIT;
2760 isc_result_t result;
2761 dns_rdata_dnskey_t dnskey;
2762 bool have_non_ksk = false;
2763
2764 dns_db_currentversion(db, &currentversion);
2765
2766 result = dns_db_findnode(db, gorigin, false, &node);
2767 if (result != ISC_R_SUCCESS)
2768 fatal("failed to find the zone's origin: %s",
2769 isc_result_totext(result));
2770
2771 dns_rdataset_init(&rdataset);
2772 result = dns_db_findrdataset(db, node, currentversion,
2773 dns_rdatatype_dnskey, 0, 0, &rdataset,
2774 NULL);
2775 if (result != ISC_R_SUCCESS)
2776 fatal("failed to find keys at the zone apex: %s",
2777 isc_result_totext(result));
2778 result = dns_rdataset_first(&rdataset);
2779 check_result(result, "dns_rdataset_first");
2780 while (result == ISC_R_SUCCESS) {
2781 dns_rdata_reset(&rdata);
2782 dns_rdataset_current(&rdataset, &rdata);
2783 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2784 check_result(result, "dns_rdata_tostruct");
2785 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
2786 have_non_ksk = true;
2787 result = ISC_R_NOMORE;
2788 } else
2789 result = dns_rdataset_next(&rdataset);
2790 dns_rdata_freestruct(&dnskey);
2791 }
2792 dns_rdataset_disassociate(&rdataset);
2793 dns_db_detachnode(db, &node);
2794 dns_db_closeversion(db, &currentversion, false);
2795 if (!have_non_ksk && !ignore_kskflag) {
2796 if (disable_zone_check)
2797 fprintf(stderr, "%s: warning: No non-KSK DNSKEY found; "
2798 "supply a ZSK or use '-z'.\n",
2799 program);
2800 else
2801 fatal("No non-KSK DNSKEY found; "
2802 "supply a ZSK or use '-z'.");
2803 }
2804 }
2805
2806 static void
2807 set_nsec3params(bool update, bool set_salt,
2808 bool set_optout, bool set_iter)
2809 {
2810 isc_result_t result;
2811 dns_dbversion_t *ver = NULL;
2812 dns_dbnode_t *node = NULL;
2813 dns_rdataset_t rdataset;
2814 dns_rdata_t rdata = DNS_RDATA_INIT;
2815 dns_rdata_nsec3_t nsec3;
2816 dns_fixedname_t fname;
2817 dns_name_t *hashname;
2818 unsigned char orig_salt[255];
2819 size_t orig_saltlen;
2820 dns_hash_t orig_hash;
2821 uint16_t orig_iter;
2822
2823 dns_db_currentversion(gdb, &ver);
2824 dns_rdataset_init(&rdataset);
2825
2826 orig_saltlen = sizeof(orig_salt);
2827 result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL,
2828 &orig_iter, orig_salt,
2829 &orig_saltlen);
2830 if (result != ISC_R_SUCCESS)
2831 goto cleanup;
2832
2833 nsec_datatype = dns_rdatatype_nsec3;
2834
2835 if (!update && set_salt) {
2836 if (salt_length != orig_saltlen ||
2837 !isc_safe_memequal(saltbuf, orig_salt, salt_length))
2838 fatal("An NSEC3 chain exists with a different salt. "
2839 "Use -u to update it.");
2840 } else if (!set_salt) {
2841 salt_length = orig_saltlen;
2842 memmove(saltbuf, orig_salt, orig_saltlen);
2843 gsalt = saltbuf;
2844 }
2845
2846 if (!update && set_iter) {
2847 if (nsec3iter != orig_iter)
2848 fatal("An NSEC3 chain exists with different "
2849 "iterations. Use -u to update it.");
2850 } else if (!set_iter)
2851 nsec3iter = orig_iter;
2852
2853 /*
2854 * Find an NSEC3 record to get the current OPTOUT value.
2855 * (This assumes all NSEC3 records agree.)
2856 */
2857
2858 hashname = dns_fixedname_initname(&fname);
2859 result = dns_nsec3_hashname(&fname, NULL, NULL,
2860 gorigin, gorigin, dns_hash_sha1,
2861 orig_iter, orig_salt, orig_saltlen);
2862 check_result(result, "dns_nsec3_hashname");
2863
2864 result = dns_db_findnsec3node(gdb, hashname, false, &node);
2865 if (result != ISC_R_SUCCESS)
2866 goto cleanup;
2867
2868 result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3,
2869 0, 0, &rdataset, NULL);
2870 if (result != ISC_R_SUCCESS)
2871 goto cleanup;
2872
2873 result = dns_rdataset_first(&rdataset);
2874 check_result(result, "dns_rdataset_first");
2875 dns_rdataset_current(&rdataset, &rdata);
2876 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
2877 check_result(result, "dns_rdata_tostruct");
2878
2879 if (!update && set_optout) {
2880 if (nsec3flags != nsec3.flags)
2881 fatal("An NSEC3 chain exists with%s OPTOUT. "
2882 "Use -u -%s to %s it.",
2883 OPTOUT(nsec3.flags) ? "" : "out",
2884 OPTOUT(nsec3.flags) ? "AA" : "A",
2885 OPTOUT(nsec3.flags) ? "clear" : "set");
2886 } else if (!set_optout)
2887 nsec3flags = nsec3.flags;
2888
2889 dns_rdata_freestruct(&nsec3);
2890
2891 cleanup:
2892 if (dns_rdataset_isassociated(&rdataset))
2893 dns_rdataset_disassociate(&rdataset);
2894 if (node != NULL)
2895 dns_db_detachnode(gdb, &node);
2896 dns_db_closeversion(gdb, &ver, false);
2897 }
2898
2899 static void
2900 writeset(const char *prefix, dns_rdatatype_t type) {
2901 char *filename;
2902 char namestr[DNS_NAME_FORMATSIZE];
2903 dns_db_t *db = NULL;
2904 dns_dbversion_t *dbversion = NULL;
2905 dns_diff_t diff;
2906 dns_difftuple_t *tuple = NULL;
2907 dns_fixedname_t fixed;
2908 dns_name_t *name;
2909 dns_rdata_t rdata, ds;
2910 bool have_ksk = false;
2911 bool have_non_ksk = false;
2912 isc_buffer_t b;
2913 isc_buffer_t namebuf;
2914 isc_region_t r;
2915 isc_result_t result;
2916 dns_dnsseckey_t *key, *tmpkey;
2917 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
2918 unsigned char keybuf[DST_KEY_MAXSIZE];
2919 unsigned int filenamelen;
2920 const dns_master_style_t *style =
2921 (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
2922
2923 isc_buffer_init(&namebuf, namestr, sizeof(namestr));
2924 result = dns_name_tofilenametext(gorigin, false, &namebuf);
2925 check_result(result, "dns_name_tofilenametext");
2926 isc_buffer_putuint8(&namebuf, 0);
2927 filenamelen = strlen(prefix) + strlen(namestr) + 1;
2928 if (dsdir != NULL)
2929 filenamelen += strlen(dsdir) + 1;
2930 filename = isc_mem_get(mctx, filenamelen);
2931 if (filename == NULL)
2932 fatal("out of memory");
2933 if (dsdir != NULL)
2934 snprintf(filename, filenamelen, "%s/", dsdir);
2935 else
2936 filename[0] = 0;
2937 strlcat(filename, prefix, filenamelen);
2938 strlcat(filename, namestr, filenamelen);
2939
2940 dns_diff_init(mctx, &diff);
2941
2942 if (type == dns_rdatatype_dlv) {
2943 dns_name_t tname;
2944 unsigned int labels;
2945
2946 dns_name_init(&tname, NULL);
2947 name = dns_fixedname_initname(&fixed);
2948 labels = dns_name_countlabels(gorigin);
2949 dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
2950 result = dns_name_concatenate(&tname, dlv, name, NULL);
2951 check_result(result, "dns_name_concatenate");
2952 } else
2953 name = gorigin;
2954
2955 for (key = ISC_LIST_HEAD(keylist);
2956 key != NULL;
2957 key = ISC_LIST_NEXT(key, link))
2958 {
2959 if (REVOKE(key->key))
2960 continue;
2961 if (isksk(key)) {
2962 have_ksk = true;
2963 have_non_ksk = false;
2964 } else {
2965 have_ksk = false;
2966 have_non_ksk = true;
2967 }
2968 for (tmpkey = ISC_LIST_HEAD(keylist);
2969 tmpkey != NULL;
2970 tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
2971 if (dst_key_alg(key->key) != dst_key_alg(tmpkey->key))
2972 continue;
2973 if (REVOKE(tmpkey->key))
2974 continue;
2975 if (isksk(tmpkey))
2976 have_ksk = true;
2977 else
2978 have_non_ksk = true;
2979 }
2980 if (have_ksk && have_non_ksk && !isksk(key))
2981 continue;
2982 dns_rdata_init(&rdata);
2983 dns_rdata_init(&ds);
2984 isc_buffer_init(&b, keybuf, sizeof(keybuf));
2985 result = dst_key_todns(key->key, &b);
2986 check_result(result, "dst_key_todns");
2987 isc_buffer_usedregion(&b, &r);
2988 dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
2989 if (type != dns_rdatatype_dnskey) {
2990 result = dns_ds_buildrdata(gorigin, &rdata,
2991 DNS_DSDIGEST_SHA256,
2992 dsbuf, &ds);
2993 check_result(result, "dns_ds_buildrdata");
2994 if (type == dns_rdatatype_dlv)
2995 ds.type = dns_rdatatype_dlv;
2996 result = dns_difftuple_create(mctx,
2997 DNS_DIFFOP_ADDRESIGN,
2998 name, 0, &ds, &tuple);
2999
3000 } else {
3001 result = dns_difftuple_create(mctx,
3002 DNS_DIFFOP_ADDRESIGN,
3003 gorigin, zone_soa_min_ttl,
3004 &rdata, &tuple);
3005 }
3006 check_result(result, "dns_difftuple_create");
3007 dns_diff_append(&diff, &tuple);
3008 }
3009
3010 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
3011 gclass, 0, NULL, &db);
3012 check_result(result, "dns_db_create");
3013
3014 result = dns_db_newversion(db, &dbversion);
3015 check_result(result, "dns_db_newversion");
3016
3017 result = dns_diff_apply(&diff, db, dbversion);
3018 check_result(result, "dns_diff_apply");
3019 dns_diff_clear(&diff);
3020
3021 result = dns_master_dump(mctx, db, dbversion, style, filename,
3022 dns_masterformat_text, NULL);
3023 check_result(result, "dns_master_dump");
3024
3025 isc_mem_put(mctx, filename, filenamelen);
3026
3027 dns_db_closeversion(db, &dbversion, false);
3028 dns_db_detach(&db);
3029 }
3030
3031 static void
3032 print_time(FILE *fp) {
3033 time_t currenttime;
3034
3035 if (outputformat != dns_masterformat_text)
3036 return;
3037
3038 currenttime = time(NULL);
3039 fprintf(fp, "; File written on %s", ctime(&currenttime));
3040 }
3041
3042 static void
3043 print_version(FILE *fp) {
3044 if (outputformat != dns_masterformat_text)
3045 return;
3046
3047 fprintf(fp, "; dnssec_signzone version " VERSION "\n");
3048 }
3049
3050 ISC_PLATFORM_NORETURN_PRE static void
3051 usage(void) ISC_PLATFORM_NORETURN_POST;
3052
3053 static void
3054 usage(void) {
3055 fprintf(stderr, "Usage:\n");
3056 fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
3057
3058 fprintf(stderr, "\n");
3059
3060 fprintf(stderr, "Version: %s\n", VERSION);
3061
3062 fprintf(stderr, "Options: (default value in parenthesis) \n");
3063 fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n"
3064 "\t\tfor the zone and determines how they are to "
3065 "be used\n");
3066 fprintf(stderr, "\t-K directory:\n");
3067 fprintf(stderr, "\t\tdirectory to find key files (.)\n");
3068 fprintf(stderr, "\t-d directory:\n");
3069 fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n");
3070 fprintf(stderr, "\t-g:\t");
3071 fprintf(stderr, "update DS records based on child zones' "
3072 "dsset-* files\n");
3073 fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
3074 fprintf(stderr, "\t\tRRSIG start time "
3075 "- absolute|offset (now - 1 hour)\n");
3076 fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
3077 fprintf(stderr, "\t\tRRSIG end time "
3078 "- absolute|from start|from now "
3079 "(now + 30 days)\n");
3080 fprintf(stderr, "\t-X [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
3081 fprintf(stderr, "\t\tDNSKEY RRSIG end "
3082 "- absolute|from start|from now "
3083 "(matches -e)\n");
3084 fprintf(stderr, "\t-i interval:\n");
3085 fprintf(stderr, "\t\tcycle interval - resign "
3086 "if < interval from end ( (end-start)/4 )\n");
3087 fprintf(stderr, "\t-j jitter:\n");
3088 fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n");
3089 fprintf(stderr, "\t-J jump:\n");
3090 fprintf(stderr, "\t\tleave jump seconds between jittered signatures\n");
3091 fprintf(stderr, "\t-v debuglevel (0)\n");
3092 fprintf(stderr, "\t-V:\tprint version information\n");
3093 fprintf(stderr, "\t-o origin:\n");
3094 fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
3095 fprintf(stderr, "\t-f outfile:\n");
3096 fprintf(stderr, "\t\tfile the signed zone is written in "
3097 "(zonefile + .signed)\n");
3098 fprintf(stderr, "\t-I format:\n");
3099 fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
3100 fprintf(stderr, "\t-O format:\n");
3101 fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
3102 fprintf(stderr, "\t-N format:\n");
3103 fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
3104 fprintf(stderr, "\t-D:\n");
3105 fprintf(stderr, "\t\toutput only DNSSEC-related records\n");
3106 fprintf(stderr, "\t-a:\t");
3107 fprintf(stderr, "verify generated signatures\n");
3108 fprintf(stderr, "\t-c class (IN)\n");
3109 fprintf(stderr, "\t-E engine:\n");
3110 #if USE_PKCS11
3111 fprintf(stderr, "\t\tpath to PKCS#11 provider library "
3112 "(default is %s)\n", PK11_LIB_LOCATION);
3113 #else
3114 fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
3115 #endif
3116 fprintf(stderr, "\t-P:\t");
3117 fprintf(stderr, "disable post-sign verification\n");
3118 fprintf(stderr, "\t-Q:\t");
3119 fprintf(stderr, "remove signatures from keys that are no "
3120 "longer active\n");
3121 fprintf(stderr, "\t-R:\t");
3122 fprintf(stderr, "remove signatures from keys that no longer exist\n");
3123 fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n");
3124 fprintf(stderr, "\t-t:\t");
3125 fprintf(stderr, "print statistics\n");
3126 fprintf(stderr, "\t-u:\t");
3127 fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n");
3128 fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n");
3129 fprintf(stderr, "\t-z:\tsign all records with KSKs\n");
3130 fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n"
3131 "\t\twith older versions of dnssec-signzone -g\n");
3132 fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
3133 fprintf(stderr, "\t-k key_signing_key\n");
3134 fprintf(stderr, "\t-l lookasidezone\n");
3135 fprintf(stderr, "\t-3 NSEC3 salt\n");
3136 fprintf(stderr, "\t-H NSEC3 iterations (10)\n");
3137 fprintf(stderr, "\t-A NSEC3 optout\n");
3138
3139 fprintf(stderr, "\n");
3140
3141 fprintf(stderr, "Signing Keys: ");
3142 fprintf(stderr, "(default: all zone keys that have private keys)\n");
3143 fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
3144
3145 exit(0);
3146 }
3147
3148 static void
3149 removetempfile(void) {
3150 if (removefile)
3151 isc_file_remove(tempfile);
3152 }
3153
3154 static void
3155 print_stats(isc_time_t *timer_start, isc_time_t *timer_finish,
3156 isc_time_t *sign_start, isc_time_t *sign_finish)
3157 {
3158 uint64_t time_us; /* Time in microseconds */
3159 uint64_t time_ms; /* Time in milliseconds */
3160 uint64_t sig_ms; /* Signatures per millisecond */
3161 FILE *out = output_stdout ? stderr : stdout;
3162
3163 fprintf(out, "Signatures generated: %10u\n", nsigned);
3164 fprintf(out, "Signatures retained: %10u\n", nretained);
3165 fprintf(out, "Signatures dropped: %10u\n", ndropped);
3166 fprintf(out, "Signatures successfully verified: %10u\n", nverified);
3167 fprintf(out, "Signatures unsuccessfully "
3168 "verified: %10u\n", nverifyfailed);
3169
3170 time_us = isc_time_microdiff(sign_finish, sign_start);
3171 time_ms = time_us / 1000;
3172 fprintf(out, "Signing time in seconds: %7u.%03u\n",
3173 (unsigned int) (time_ms / 1000),
3174 (unsigned int) (time_ms % 1000));
3175 if (time_us > 0) {
3176 sig_ms = ((uint64_t)nsigned * 1000000000) / time_us;
3177 fprintf(out, "Signatures per second: %7u.%03u\n",
3178 (unsigned int) sig_ms / 1000,
3179 (unsigned int) sig_ms % 1000);
3180 }
3181
3182 time_us = isc_time_microdiff(timer_finish, timer_start);
3183 time_ms = time_us / 1000;
3184 fprintf(out, "Runtime in seconds: %7u.%03u\n",
3185 (unsigned int) (time_ms / 1000),
3186 (unsigned int) (time_ms % 1000));
3187 }
3188
3189 int
3190 main(int argc, char *argv[]) {
3191 int i, ch;
3192 char *startstr = NULL, *endstr = NULL, *classname = NULL;
3193 char *dnskey_endstr = NULL;
3194 char *origin = NULL, *file = NULL, *output = NULL;
3195 char *inputformatstr = NULL, *outputformatstr = NULL;
3196 char *serialformatstr = NULL;
3197 char *dskeyfile[MAXDSKEYS];
3198 int ndskeys = 0;
3199 char *endp;
3200 isc_time_t timer_start, timer_finish;
3201 isc_time_t sign_start, sign_finish;
3202 dns_dnsseckey_t *key;
3203 isc_result_t result, vresult;
3204 isc_log_t *log = NULL;
3205 const char *engine = NULL;
3206 bool free_output = false;
3207 int tempfilelen = 0;
3208 dns_rdataclass_t rdclass;
3209 isc_task_t **tasks = NULL;
3210 isc_buffer_t b;
3211 int len;
3212 hashlist_t hashlist;
3213 bool make_keyset = false;
3214 bool set_salt = false;
3215 bool set_optout = false;
3216 bool set_iter = false;
3217 bool nonsecify = false;
3218
3219 /* Unused letters: Bb G J q Yy (and F is reserved). */
3220 #define CMDLINE_FLAGS \
3221 "3:AaCc:Dd:E:e:f:FghH:i:I:J:j:K:k:L:l:m:M:n:N:o:O:PpQRr:s:ST:tuUv:VX:xzZ:"
3222
3223 /*
3224 * Process memory debugging argument first.
3225 */
3226 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3227 switch (ch) {
3228 case 'm':
3229 if (strcasecmp(isc_commandline_argument, "record") == 0)
3230 isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
3231 if (strcasecmp(isc_commandline_argument, "trace") == 0)
3232 isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
3233 if (strcasecmp(isc_commandline_argument, "usage") == 0)
3234 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
3235 if (strcasecmp(isc_commandline_argument, "size") == 0)
3236 isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
3237 if (strcasecmp(isc_commandline_argument, "mctx") == 0)
3238 isc_mem_debugging |= ISC_MEM_DEBUGCTX;
3239 break;
3240 default:
3241 break;
3242 }
3243 }
3244 isc_commandline_reset = true;
3245
3246 #ifdef _WIN32
3247 InitSockets();
3248 #endif
3249
3250 masterstyle = &dns_master_style_explicitttl;
3251
3252 check_result(isc_app_start(), "isc_app_start");
3253
3254 result = isc_mem_create(0, 0, &mctx);
3255 if (result != ISC_R_SUCCESS)
3256 fatal("out of memory");
3257
3258 #if USE_PKCS11
3259 pk11_result_register();
3260 #endif
3261 dns_result_register();
3262
3263 isc_commandline_errprint = false;
3264
3265 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3266 switch (ch) {
3267 case '3':
3268 set_salt = true;
3269 nsec_datatype = dns_rdatatype_nsec3;
3270 if (strcmp(isc_commandline_argument, "-") != 0) {
3271 isc_buffer_t target;
3272 char *sarg;
3273
3274 sarg = isc_commandline_argument;
3275 isc_buffer_init(&target, saltbuf,
3276 sizeof(saltbuf));
3277 result = isc_hex_decodestring(sarg, &target);
3278 check_result(result,
3279 "isc_hex_decodestring(salt)");
3280 salt_length = isc_buffer_usedlength(&target);
3281 }
3282 break;
3283
3284 case 'A':
3285 set_optout = true;
3286 if (OPTOUT(nsec3flags))
3287 nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT;
3288 else
3289 nsec3flags |= DNS_NSEC3FLAG_OPTOUT;
3290 break;
3291
3292 case 'a':
3293 tryverify = true;
3294 break;
3295
3296 case 'C':
3297 make_keyset = true;
3298 break;
3299
3300 case 'c':
3301 classname = isc_commandline_argument;
3302 break;
3303
3304 case 'd':
3305 dsdir = isc_commandline_argument;
3306 if (strlen(dsdir) == 0U)
3307 fatal("DS directory must be non-empty string");
3308 result = try_dir(dsdir);
3309 if (result != ISC_R_SUCCESS)
3310 fatal("cannot open directory %s: %s",
3311 dsdir, isc_result_totext(result));
3312 break;
3313
3314 case 'D':
3315 output_dnssec_only = true;
3316 break;
3317
3318 case 'E':
3319 engine = isc_commandline_argument;
3320 break;
3321
3322 case 'e':
3323 endstr = isc_commandline_argument;
3324 break;
3325
3326 case 'f':
3327 output = isc_commandline_argument;
3328 if (strcmp(output, "-") == 0)
3329 output_stdout = true;
3330 break;
3331
3332 case 'g':
3333 generateds = true;
3334 break;
3335
3336 case 'H':
3337 set_iter = true;
3338 nsec3iter = strtoul(isc_commandline_argument, &endp, 0);
3339 if (*endp != '\0')
3340 fatal("iterations must be numeric");
3341 if (nsec3iter > 0xffffU)
3342 fatal("iterations too big");
3343 break;
3344
3345 case 'I':
3346 inputformatstr = isc_commandline_argument;
3347 break;
3348
3349 case 'i':
3350 endp = NULL;
3351 cycle = strtol(isc_commandline_argument, &endp, 0);
3352 if (*endp != '\0' || cycle < 0)
3353 fatal("cycle period must be numeric and "
3354 "positive");
3355 break;
3356
3357 case 'J':
3358 endp = NULL;
3359 jump = strtol(isc_commandline_argument, &endp, 0);
3360 if (*endp != '\0' || jump < 0)
3361 fatal("jump must be numeric and positive");
3362 break;
3363
3364 case 'j':
3365 endp = NULL;
3366 jitter = strtol(isc_commandline_argument, &endp, 0);
3367 if (*endp != '\0' || jitter < 0)
3368 fatal("jitter must be numeric and positive");
3369 break;
3370
3371 case 'K':
3372 directory = isc_commandline_argument;
3373 break;
3374
3375 case 'k':
3376 if (ndskeys == MAXDSKEYS)
3377 fatal("too many key-signing keys specified");
3378 dskeyfile[ndskeys++] = isc_commandline_argument;
3379 break;
3380
3381 case 'L':
3382 snset = true;
3383 endp = NULL;
3384 serialnum = strtol(isc_commandline_argument, &endp, 0);
3385 if (*endp != '\0') {
3386 fprintf(stderr, "source serial number "
3387 "must be numeric");
3388 exit(1);
3389 }
3390 break;
3391
3392 case 'l':
3393 len = strlen(isc_commandline_argument);
3394 isc_buffer_init(&b, isc_commandline_argument, len);
3395 isc_buffer_add(&b, len);
3396
3397 dlv = dns_fixedname_initname(&dlv_fixed);
3398 result = dns_name_fromtext(dlv, &b, dns_rootname, 0,
3399 NULL);
3400 check_result(result, "dns_name_fromtext(dlv)");
3401 break;
3402
3403 case 'M':
3404 endp = NULL;
3405 set_maxttl = true;
3406 maxttl = strtol(isc_commandline_argument, &endp, 0);
3407 if (*endp != '\0') {
3408 fprintf(stderr, "maximum TTL "
3409 "must be numeric");
3410 exit(1);
3411 }
3412 break;
3413
3414 case 'm':
3415 break;
3416
3417 case 'N':
3418 serialformatstr = isc_commandline_argument;
3419 break;
3420
3421 case 'n':
3422 endp = NULL;
3423 ntasks = strtol(isc_commandline_argument, &endp, 0);
3424 if (*endp != '\0' || ntasks > INT32_MAX)
3425 fatal("number of cpus must be numeric");
3426 break;
3427
3428 case 'O':
3429 outputformatstr = isc_commandline_argument;
3430 break;
3431
3432 case 'o':
3433 origin = isc_commandline_argument;
3434 break;
3435
3436 case 'P':
3437 disable_zone_check = true;
3438 break;
3439
3440 case 'p':
3441 fatal("The -p option has been deprecated.\n");
3442 break;
3443
3444 case 'Q':
3445 remove_inactkeysigs = true;
3446 break;
3447
3448 case 'R':
3449 remove_orphansigs = true;
3450 break;
3451
3452 case 'r':
3453 fatal("The -r options has been deprecated.\n");
3454 break;
3455
3456 case 'S':
3457 smartsign = true;
3458 break;
3459
3460 case 's':
3461 startstr = isc_commandline_argument;
3462 break;
3463
3464 case 'T':
3465 endp = NULL;
3466 set_keyttl = true;
3467 keyttl = strtottl(isc_commandline_argument);
3468 break;
3469
3470 case 't':
3471 printstats = true;
3472 break;
3473
3474 case 'U': /* Undocumented for testing only. */
3475 unknownalg = true;
3476 break;
3477
3478 case 'u':
3479 update_chain = true;
3480 break;
3481
3482 case 'v':
3483 endp = NULL;
3484 verbose = strtol(isc_commandline_argument, &endp, 0);
3485 if (*endp != '\0')
3486 fatal("verbose level must be numeric");
3487 break;
3488
3489 case 'X':
3490 dnskey_endstr = isc_commandline_argument;
3491 break;
3492
3493 case 'x':
3494 keyset_kskonly = true;
3495 break;
3496
3497 case 'z':
3498 ignore_kskflag = true;
3499 break;
3500
3501 case 'F':
3502 /* Reserved for FIPS mode */
3503 /* FALLTHROUGH */
3504 case '?':
3505 if (isc_commandline_option != '?')
3506 fprintf(stderr, "%s: invalid argument -%c\n",
3507 program, isc_commandline_option);
3508 /* FALLTHROUGH */
3509 case 'h':
3510 /* Does not return. */
3511 usage();
3512
3513 case 'V':
3514 /* Does not return. */
3515 version(program);
3516
3517 case 'Z': /* Undocumented test options */
3518 if (!strcmp(isc_commandline_argument, "nonsecify"))
3519 nonsecify = true;
3520 break;
3521
3522 default:
3523 fprintf(stderr, "%s: unhandled option -%c\n",
3524 program, isc_commandline_option);
3525 exit(1);
3526 }
3527 }
3528
3529 result = dst_lib_init(mctx, engine);
3530 if (result != ISC_R_SUCCESS)
3531 fatal("could not initialize dst: %s",
3532 isc_result_totext(result));
3533
3534 isc_stdtime_get(&now);
3535
3536 if (startstr != NULL) {
3537 starttime = strtotime(startstr, now, now, NULL);
3538 } else
3539 starttime = now - 3600; /* Allow for some clock skew. */
3540
3541 if (endstr != NULL)
3542 endtime = strtotime(endstr, now, starttime, NULL);
3543 else
3544 endtime = starttime + (30 * 24 * 60 * 60);
3545
3546 if (dnskey_endstr != NULL) {
3547 dnskey_endtime = strtotime(dnskey_endstr, now, starttime,
3548 NULL);
3549 if (endstr != NULL && dnskey_endtime == endtime)
3550 fprintf(stderr, "WARNING: -e and -X were both set, "
3551 "but have identical values.\n");
3552 } else
3553 dnskey_endtime = endtime;
3554
3555 if (cycle == -1)
3556 cycle = (endtime - starttime) / 4;
3557
3558 if (ntasks == 0)
3559 ntasks = isc_os_ncpus() * 2;
3560 vbprintf(4, "using %d cpus\n", ntasks);
3561
3562 rdclass = strtoclass(classname);
3563
3564 if (directory == NULL)
3565 directory = ".";
3566
3567 setup_logging(mctx, &log);
3568
3569 argc -= isc_commandline_index;
3570 argv += isc_commandline_index;
3571
3572 if (argc < 1)
3573 usage();
3574
3575 file = argv[0];
3576
3577 argc -= 1;
3578 argv += 1;
3579
3580 if (origin == NULL)
3581 origin = file;
3582
3583 if (output == NULL) {
3584 size_t size;
3585 free_output = true;
3586 size = strlen(file) + strlen(".signed") + 1;
3587 output = isc_mem_allocate(mctx, size);
3588 if (output == NULL)
3589 fatal("out of memory");
3590 snprintf(output, size, "%s.signed", file);
3591 }
3592
3593 if (inputformatstr != NULL) {
3594 if (strcasecmp(inputformatstr, "text") == 0)
3595 inputformat = dns_masterformat_text;
3596 else if (strcasecmp(inputformatstr, "map") == 0)
3597 inputformat = dns_masterformat_map;
3598 else if (strcasecmp(inputformatstr, "raw") == 0)
3599 inputformat = dns_masterformat_raw;
3600 else if (strncasecmp(inputformatstr, "raw=", 4) == 0) {
3601 inputformat = dns_masterformat_raw;
3602 fprintf(stderr,
3603 "WARNING: input format version ignored\n");
3604 } else
3605 fatal("unknown file format: %s", inputformatstr);
3606
3607 }
3608
3609 if (outputformatstr != NULL) {
3610 if (strcasecmp(outputformatstr, "text") == 0) {
3611 outputformat = dns_masterformat_text;
3612 } else if (strcasecmp(outputformatstr, "full") == 0) {
3613 outputformat = dns_masterformat_text;
3614 masterstyle = &dns_master_style_full;
3615 } else if (strcasecmp(outputformatstr, "map") == 0) {
3616 outputformat = dns_masterformat_map;
3617 } else if (strcasecmp(outputformatstr, "raw") == 0) {
3618 outputformat = dns_masterformat_raw;
3619 } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
3620 char *end;
3621 outputformat = dns_masterformat_raw;
3622
3623 outputformat = dns_masterformat_raw;
3624 rawversion = strtol(outputformatstr + 4, &end, 10);
3625 if (end == outputformatstr + 4 || *end != '\0' ||
3626 rawversion > 1U) {
3627 fprintf(stderr,
3628 "unknown raw format version\n");
3629 exit(1);
3630 }
3631 } else
3632 fatal("unknown file format: %s", outputformatstr);
3633 }
3634
3635 if (serialformatstr != NULL) {
3636 if (strcasecmp(serialformatstr, "keep") == 0)
3637 serialformat = SOA_SERIAL_KEEP;
3638 else if (strcasecmp(serialformatstr, "increment") == 0 ||
3639 strcasecmp(serialformatstr, "incr") == 0)
3640 serialformat = SOA_SERIAL_INCREMENT;
3641 else if (strcasecmp(serialformatstr, "unixtime") == 0)
3642 serialformat = SOA_SERIAL_UNIXTIME;
3643 else if (strcasecmp(serialformatstr, "date") == 0)
3644 serialformat = SOA_SERIAL_DATE;
3645 else
3646 fatal("unknown soa serial format: %s",
3647 serialformatstr);
3648 }
3649
3650 if (output_dnssec_only && outputformat != dns_masterformat_text)
3651 fatal("option -D can only be used with \"-O text\"");
3652
3653 if (output_dnssec_only && serialformat != SOA_SERIAL_KEEP)
3654 fatal("option -D can only be used with \"-N keep\"");
3655
3656 if (output_dnssec_only && set_maxttl)
3657 fatal("option -D cannot be used with -M");
3658
3659 result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL,
3660 0, 24, 0, 0, 0, 8, 0xffffffff, mctx);
3661 check_result(result, "dns_master_stylecreate");
3662
3663 gdb = NULL;
3664 TIME_NOW(&timer_start);
3665 loadzone(file, origin, rdclass, &gdb);
3666 gorigin = dns_db_origin(gdb);
3667 gclass = dns_db_class(gdb);
3668 get_soa_ttls();
3669
3670 if (set_maxttl && set_keyttl && keyttl > maxttl) {
3671 fprintf(stderr, "%s: warning: Specified key TTL %u "
3672 "exceeds maximum zone TTL; reducing to %u\n",
3673 program, keyttl, maxttl);
3674 keyttl = maxttl;
3675 }
3676
3677 if (!set_keyttl)
3678 keyttl = soa_ttl;
3679
3680 /*
3681 * Check for any existing NSEC3 parameters in the zone,
3682 * and use them as defaults if -u was not specified.
3683 */
3684 if (update_chain && !set_optout && !set_iter && !set_salt)
3685 nsec_datatype = dns_rdatatype_nsec;
3686 else
3687 set_nsec3params(update_chain, set_salt, set_optout, set_iter);
3688
3689 /*
3690 * We need to do this early on, as we start messing with the list
3691 * of keys rather early.
3692 */
3693 ISC_LIST_INIT(keylist);
3694 result = isc_rwlock_init(&keylist_lock, 0, 0);
3695 if (result != ISC_R_SUCCESS)
3696 fatal("could not initialize keylist_lock: %s",
3697 isc_result_totext(result));
3698
3699 /*
3700 * Fill keylist with:
3701 * 1) Keys listed in the DNSKEY set that have
3702 * private keys associated, *if* no keys were
3703 * set on the command line.
3704 * 2) ZSKs set on the command line
3705 * 3) KSKs set on the command line
3706 * 4) Any keys remaining in the DNSKEY set which
3707 * do not have private keys associated and were
3708 * not specified on the command line.
3709 */
3710 if (argc == 0 || smartsign) {
3711 loadzonekeys(!smartsign, false);
3712 }
3713 loadexplicitkeys(argv, argc, false);
3714 loadexplicitkeys(dskeyfile, ndskeys, true);
3715 loadzonekeys(!smartsign, true);
3716
3717 /*
3718 * If we're doing smart signing, look in the key repository for
3719 * key files with metadata, and merge them with the keylist
3720 * we have now.
3721 */
3722 if (smartsign) {
3723 build_final_keylist();
3724 }
3725
3726 /* Now enumerate the key list */
3727 for (key = ISC_LIST_HEAD(keylist);
3728 key != NULL;
3729 key = ISC_LIST_NEXT(key, link)) {
3730 key->index = keycount++;
3731 }
3732
3733 if (keycount == 0) {
3734 if (disable_zone_check)
3735 fprintf(stderr, "%s: warning: No keys specified "
3736 "or found\n", program);
3737 else
3738 fatal("No signing keys specified or found.");
3739 nokeys = true;
3740 }
3741
3742 warnifallksk(gdb);
3743
3744 if (IS_NSEC3) {
3745 unsigned int max;
3746 bool answer;
3747
3748 hash_length = dns_nsec3_hashlength(dns_hash_sha1);
3749 hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2,
3750 hash_length);
3751 result = dns_nsec_nseconly(gdb, gversion, &answer);
3752 if (result == ISC_R_NOTFOUND)
3753 fprintf(stderr, "%s: warning: NSEC3 generation "
3754 "requested with no DNSKEY; ignoring\n",
3755 program);
3756 else if (result != ISC_R_SUCCESS)
3757 check_result(result, "dns_nsec_nseconly");
3758 else if (answer)
3759 fatal("NSEC3 generation requested with "
3760 "NSEC-only DNSKEY");
3761
3762 result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max);
3763 check_result(result, "dns_nsec3_maxiterations()");
3764 if (nsec3iter > max)
3765 fatal("NSEC3 iterations too big for weakest DNSKEY "
3766 "strength. Maximum iterations allowed %u.", max);
3767 } else {
3768 hashlist_init(&hashlist, 0, 0); /* silence clang */
3769 }
3770
3771 gversion = NULL;
3772 result = dns_db_newversion(gdb, &gversion);
3773 check_result(result, "dns_db_newversion()");
3774
3775 switch (serialformat) {
3776 case SOA_SERIAL_INCREMENT:
3777 setsoaserial(0, dns_updatemethod_increment);
3778 break;
3779 case SOA_SERIAL_UNIXTIME:
3780 setsoaserial(now, dns_updatemethod_unixtime);
3781 break;
3782 case SOA_SERIAL_DATE:
3783 setsoaserial(now, dns_updatemethod_date);
3784 break;
3785 case SOA_SERIAL_KEEP:
3786 default:
3787 /* do nothing */
3788 break;
3789 }
3790
3791 /* Remove duplicates and cap TTLs at maxttl */
3792 cleanup_zone();
3793
3794 if (!nonsecify) {
3795 if (IS_NSEC3)
3796 nsec3ify(dns_hash_sha1, nsec3iter, gsalt, salt_length,
3797 &hashlist);
3798 else
3799 nsecify();
3800 }
3801
3802 if (!nokeys) {
3803 writeset("dsset-", dns_rdatatype_ds);
3804 if (make_keyset)
3805 writeset("keyset-", dns_rdatatype_dnskey);
3806 if (dlv != NULL) {
3807 writeset("dlvset-", dns_rdatatype_dlv);
3808 }
3809 }
3810
3811 if (output_stdout) {
3812 outfp = stdout;
3813 if (outputformatstr == NULL)
3814 masterstyle = &dns_master_style_full;
3815 } else {
3816 tempfilelen = strlen(output) + 20;
3817 tempfile = isc_mem_get(mctx, tempfilelen);
3818 if (tempfile == NULL)
3819 fatal("out of memory");
3820
3821 result = isc_file_mktemplate(output, tempfile, tempfilelen);
3822 check_result(result, "isc_file_mktemplate");
3823
3824 if (outputformat == dns_masterformat_text)
3825 result = isc_file_openunique(tempfile, &outfp);
3826 else
3827 result = isc_file_bopenunique(tempfile, &outfp);
3828 if (result != ISC_R_SUCCESS)
3829 fatal("failed to open temporary output file: %s",
3830 isc_result_totext(result));
3831 removefile = true;
3832 setfatalcallback(&removetempfile);
3833 }
3834
3835 print_time(outfp);
3836 print_version(outfp);
3837
3838 result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
3839 if (result != ISC_R_SUCCESS)
3840 fatal("failed to create task manager: %s",
3841 isc_result_totext(result));
3842
3843 master = NULL;
3844 result = isc_task_create(taskmgr, 0, &master);
3845 if (result != ISC_R_SUCCESS)
3846 fatal("failed to create task: %s", isc_result_totext(result));
3847
3848 tasks = isc_mem_get(mctx