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