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