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