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 &lt;hash&gt;.&lt;origin&gt;?
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, &currentversion);
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, &currentversion, 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, &currentversion);
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, &currentversion, 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(&currenttime, &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