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