1/*	$NetBSD: dnssectool.c,v 1.2.6.2 2012/12/15 05:39:24 riz Exp $	*/
2
3/*
4 * Copyright (C) 2004, 2005, 2007, 2009-2012  Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000, 2001, 2003  Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20/* Id: dnssectool.c,v 1.63 2011/10/21 03:55:33 marka Exp  */
21
22/*! \file */
23
24/*%
25 * DNSSEC Support Routines.
26 */
27
28#include <config.h>
29
30#include <stdlib.h>
31
32#include <isc/base32.h>
33#include <isc/buffer.h>
34#include <isc/dir.h>
35#include <isc/entropy.h>
36#include <isc/heap.h>
37#include <isc/list.h>
38#include <isc/mem.h>
39#include <isc/string.h>
40#include <isc/time.h>
41#include <isc/util.h>
42#include <isc/print.h>
43
44#include <dns/db.h>
45#include <dns/dbiterator.h>
46#include <dns/dnssec.h>
47#include <dns/fixedname.h>
48#include <dns/keyvalues.h>
49#include <dns/log.h>
50#include <dns/name.h>
51#include <dns/nsec.h>
52#include <dns/nsec3.h>
53#include <dns/rdatastruct.h>
54#include <dns/rdataclass.h>
55#include <dns/rdataset.h>
56#include <dns/rdatasetiter.h>
57#include <dns/rdatatype.h>
58#include <dns/result.h>
59#include <dns/secalg.h>
60#include <dns/time.h>
61
62#include "dnssectool.h"
63
64static isc_heap_t *expected_chains, *found_chains;
65
66struct nsec3_chain_fixed {
67	isc_uint8_t	hash;
68	isc_uint8_t	salt_length;
69	isc_uint8_t	next_length;
70	isc_uint16_t	iterations;
71	/* unsigned char salt[0]; */
72	/* unsigned char owner[0]; */
73	/* unsigned char next[0]; */
74};
75
76extern int verbose;
77extern const char *program;
78
79typedef struct entropysource entropysource_t;
80
81struct entropysource {
82	isc_entropysource_t *source;
83	isc_mem_t *mctx;
84	ISC_LINK(entropysource_t) link;
85};
86
87static ISC_LIST(entropysource_t) sources;
88static fatalcallback_t *fatalcallback = NULL;
89
90void
91fatal(const char *format, ...) {
92	va_list args;
93
94	fprintf(stderr, "%s: fatal: ", program);
95	va_start(args, format);
96	vfprintf(stderr, format, args);
97	va_end(args);
98	fprintf(stderr, "\n");
99	if (fatalcallback != NULL)
100		(*fatalcallback)();
101	exit(1);
102}
103
104void
105setfatalcallback(fatalcallback_t *callback) {
106	fatalcallback = callback;
107}
108
109void
110check_result(isc_result_t result, const char *message) {
111	if (result != ISC_R_SUCCESS)
112		fatal("%s: %s", message, isc_result_totext(result));
113}
114
115void
116vbprintf(int level, const char *fmt, ...) {
117	va_list ap;
118	if (level > verbose)
119		return;
120	va_start(ap, fmt);
121	fprintf(stderr, "%s: ", program);
122	vfprintf(stderr, fmt, ap);
123	va_end(ap);
124}
125
126void
127type_format(const dns_rdatatype_t type, char *cp, unsigned int size) {
128	isc_buffer_t b;
129	isc_region_t r;
130	isc_result_t result;
131
132	isc_buffer_init(&b, cp, size - 1);
133	result = dns_rdatatype_totext(type, &b);
134	check_result(result, "dns_rdatatype_totext()");
135	isc_buffer_usedregion(&b, &r);
136	r.base[r.length] = 0;
137}
138
139void
140sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size) {
141	char namestr[DNS_NAME_FORMATSIZE];
142	char algstr[DNS_NAME_FORMATSIZE];
143
144	dns_name_format(&sig->signer, namestr, sizeof(namestr));
145	dns_secalg_format(sig->algorithm, algstr, sizeof(algstr));
146	snprintf(cp, size, "%s/%s/%d", namestr, algstr, sig->keyid);
147}
148
149void
150setup_logging(int verbose, isc_mem_t *mctx, isc_log_t **logp) {
151	isc_result_t result;
152	isc_logdestination_t destination;
153	isc_logconfig_t *logconfig = NULL;
154	isc_log_t *log = NULL;
155	int level;
156
157	if (verbose < 0)
158		verbose = 0;
159	switch (verbose) {
160	case 0:
161		/*
162		 * We want to see warnings about things like out-of-zone
163		 * data in the master file even when not verbose.
164		 */
165		level = ISC_LOG_WARNING;
166		break;
167	case 1:
168		level = ISC_LOG_INFO;
169		break;
170	default:
171		level = ISC_LOG_DEBUG(verbose - 2 + 1);
172		break;
173	}
174
175	RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
176	isc_log_setcontext(log);
177	dns_log_init(log);
178	dns_log_setcontext(log);
179
180	RUNTIME_CHECK(isc_log_settag(logconfig, program) == ISC_R_SUCCESS);
181
182	/*
183	 * Set up a channel similar to default_stderr except:
184	 *  - the logging level is passed in
185	 *  - the program name and logging level are printed
186	 *  - no time stamp is printed
187	 */
188	destination.file.stream = stderr;
189	destination.file.name = NULL;
190	destination.file.versions = ISC_LOG_ROLLNEVER;
191	destination.file.maximum_size = 0;
192	result = isc_log_createchannel(logconfig, "stderr",
193				       ISC_LOG_TOFILEDESC,
194				       level,
195				       &destination,
196				       ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL);
197	check_result(result, "isc_log_createchannel()");
198
199	RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr",
200					 NULL, NULL) == ISC_R_SUCCESS);
201
202	*logp = log;
203}
204
205void
206cleanup_logging(isc_log_t **logp) {
207	isc_log_t *log;
208
209	REQUIRE(logp != NULL);
210
211	log = *logp;
212	if (log == NULL)
213		return;
214	isc_log_destroy(&log);
215	isc_log_setcontext(NULL);
216	dns_log_setcontext(NULL);
217	logp = NULL;
218}
219
220void
221setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) {
222	isc_result_t result;
223	isc_entropysource_t *source = NULL;
224	entropysource_t *elt;
225	int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
226
227	REQUIRE(ectx != NULL);
228
229	if (*ectx == NULL) {
230		result = isc_entropy_create(mctx, ectx);
231		if (result != ISC_R_SUCCESS)
232			fatal("could not create entropy object");
233		ISC_LIST_INIT(sources);
234	}
235
236	if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
237		usekeyboard = ISC_ENTROPY_KEYBOARDYES;
238		randomfile = NULL;
239	}
240
241	result = isc_entropy_usebestsource(*ectx, &source, randomfile,
242					   usekeyboard);
243
244	if (result != ISC_R_SUCCESS)
245		fatal("could not initialize entropy source: %s",
246		      isc_result_totext(result));
247
248	if (source != NULL) {
249		elt = isc_mem_get(mctx, sizeof(*elt));
250		if (elt == NULL)
251			fatal("out of memory");
252		elt->source = source;
253		elt->mctx = mctx;
254		ISC_LINK_INIT(elt, link);
255		ISC_LIST_APPEND(sources, elt, link);
256	}
257}
258
259void
260cleanup_entropy(isc_entropy_t **ectx) {
261	entropysource_t *source;
262	while (!ISC_LIST_EMPTY(sources)) {
263		source = ISC_LIST_HEAD(sources);
264		ISC_LIST_UNLINK(sources, source, link);
265		isc_entropy_destroysource(&source->source);
266		isc_mem_put(source->mctx, source, sizeof(*source));
267	}
268	isc_entropy_detach(ectx);
269}
270
271static isc_stdtime_t
272time_units(isc_stdtime_t offset, char *suffix, const char *str) {
273	switch (suffix[0]) {
274	    case 'Y': case 'y':
275		return (offset * (365 * 24 * 3600));
276	    case 'M': case 'm':
277		switch (suffix[1]) {
278		    case 'O': case 'o':
279			return (offset * (30 * 24 * 3600));
280		    case 'I': case 'i':
281			return (offset * 60);
282		    case '\0':
283			fatal("'%s' ambiguous: use 'mi' for minutes "
284			      "or 'mo' for months", str);
285		    default:
286			fatal("time value %s is invalid", str);
287		}
288		/* NOTREACHED */
289		break;
290	    case 'W': case 'w':
291		return (offset * (7 * 24 * 3600));
292	    case 'D': case 'd':
293		return (offset * (24 * 3600));
294	    case 'H': case 'h':
295		return (offset * 3600);
296	    case 'S': case 's': case '\0':
297		return (offset);
298	    default:
299		fatal("time value %s is invalid", str);
300	}
301	/* NOTREACHED */
302	return(0); /* silence compiler warning */
303}
304
305dns_ttl_t
306strtottl(const char *str) {
307	const char *orig = str;
308	dns_ttl_t ttl;
309	char *endp;
310
311	ttl = strtol(str, &endp, 0);
312	if (ttl == 0 && endp == str)
313		fatal("TTL must be numeric");
314	ttl = time_units(ttl, endp, orig);
315	return (ttl);
316}
317
318isc_stdtime_t
319strtotime(const char *str, isc_int64_t now, isc_int64_t base) {
320	isc_int64_t val, offset;
321	isc_result_t result;
322	const char *orig = str;
323	char *endp;
324
325	if ((str[0] == '0' || str[0] == '-') && str[1] == '\0')
326		return ((isc_stdtime_t) 0);
327
328	if (strncmp(str, "now", 3) == 0) {
329		base = now;
330		str += 3;
331	}
332
333	if (str[0] == '\0')
334		return ((isc_stdtime_t) base);
335	else if (str[0] == '+') {
336		offset = strtol(str + 1, &endp, 0);
337		offset = time_units((isc_stdtime_t) offset, endp, orig);
338		val = base + offset;
339	} else if (str[0] == '-') {
340		offset = strtol(str + 1, &endp, 0);
341		offset = time_units((isc_stdtime_t) offset, endp, orig);
342		val = base - offset;
343	} else if (strlen(str) == 8U) {
344		char timestr[15];
345		sprintf(timestr, "%s000000", str);
346		result = dns_time64_fromtext(timestr, &val);
347		if (result != ISC_R_SUCCESS)
348			fatal("time value %s is invalid: %s", orig,
349			      isc_result_totext(result));
350	} else if (strlen(str) > 14U) {
351		fatal("time value %s is invalid", orig);
352	} else {
353		result = dns_time64_fromtext(str, &val);
354		if (result != ISC_R_SUCCESS)
355			fatal("time value %s is invalid: %s", orig,
356			      isc_result_totext(result));
357	}
358
359	return ((isc_stdtime_t) val);
360}
361
362dns_rdataclass_t
363strtoclass(const char *str) {
364	isc_textregion_t r;
365	dns_rdataclass_t rdclass;
366	isc_result_t ret;
367
368	if (str == NULL)
369		return dns_rdataclass_in;
370	DE_CONST(str, r.base);
371	r.length = strlen(str);
372	ret = dns_rdataclass_fromtext(&rdclass, &r);
373	if (ret != ISC_R_SUCCESS)
374		fatal("unknown class %s", str);
375	return (rdclass);
376}
377
378isc_result_t
379try_dir(const char *dirname) {
380	isc_result_t result;
381	isc_dir_t d;
382
383	isc_dir_init(&d);
384	result = isc_dir_open(&d, dirname);
385	if (result == ISC_R_SUCCESS) {
386		isc_dir_close(&d);
387	}
388	return (result);
389}
390
391/*
392 * Check private key version compatibility.
393 */
394void
395check_keyversion(dst_key_t *key, char *keystr) {
396	int major, minor;
397	dst_key_getprivateformat(key, &major, &minor);
398	INSIST(major <= DST_MAJOR_VERSION); /* invalid private key */
399
400	if (major < DST_MAJOR_VERSION || minor < DST_MINOR_VERSION)
401		fatal("Key %s has incompatible format version %d.%d, "
402		      "use -f to force upgrade to new version.",
403		      keystr, major, minor);
404	if (minor > DST_MINOR_VERSION)
405		fatal("Key %s has incompatible format version %d.%d, "
406		      "use -f to force downgrade to current version.",
407		      keystr, major, minor);
408}
409
410void
411set_keyversion(dst_key_t *key) {
412	int major, minor;
413	dst_key_getprivateformat(key, &major, &minor);
414	INSIST(major <= DST_MAJOR_VERSION);
415
416	if (major != DST_MAJOR_VERSION || minor != DST_MINOR_VERSION)
417		dst_key_setprivateformat(key, DST_MAJOR_VERSION,
418					 DST_MINOR_VERSION);
419
420	/*
421	 * If the key is from a version older than 1.3, set
422	 * set the creation date
423	 */
424	if (major < 1 || (major == 1 && minor <= 2)) {
425		isc_stdtime_t now;
426		isc_stdtime_get(&now);
427		dst_key_settime(key, DST_TIME_CREATED, now);
428	}
429}
430
431isc_boolean_t
432key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir,
433	      isc_mem_t *mctx, isc_boolean_t *exact)
434{
435	isc_result_t result;
436	isc_boolean_t conflict = ISC_FALSE;
437	dns_dnsseckeylist_t matchkeys;
438	dns_dnsseckey_t *key = NULL;
439	isc_uint16_t id, oldid;
440	isc_uint32_t rid, roldid;
441	dns_secalg_t alg;
442
443	if (exact != NULL)
444		*exact = ISC_FALSE;
445
446	id = dst_key_id(dstkey);
447	rid = dst_key_rid(dstkey);
448	alg = dst_key_alg(dstkey);
449
450	ISC_LIST_INIT(matchkeys);
451	result = dns_dnssec_findmatchingkeys(name, dir, mctx, &matchkeys);
452	if (result == ISC_R_NOTFOUND)
453		return (ISC_FALSE);
454
455	while (!ISC_LIST_EMPTY(matchkeys) && !conflict) {
456		key = ISC_LIST_HEAD(matchkeys);
457		if (dst_key_alg(key->key) != alg)
458			goto next;
459
460		oldid = dst_key_id(key->key);
461		roldid = dst_key_rid(key->key);
462
463		if (oldid == rid || roldid == id || id == oldid) {
464			conflict = ISC_TRUE;
465			if (id != oldid) {
466				if (verbose > 1)
467					fprintf(stderr, "Key ID %d could "
468						"collide with %d\n",
469						id, oldid);
470			} else {
471				if (exact != NULL)
472					*exact = ISC_TRUE;
473				if (verbose > 1)
474					fprintf(stderr, "Key ID %d exists\n",
475						id);
476			}
477		}
478
479 next:
480		ISC_LIST_UNLINK(matchkeys, key, link);
481		dns_dnsseckey_destroy(mctx, &key);
482	}
483
484	/* Finish freeing the list */
485	while (!ISC_LIST_EMPTY(matchkeys)) {
486		key = ISC_LIST_HEAD(matchkeys);
487		ISC_LIST_UNLINK(matchkeys, key, link);
488		dns_dnsseckey_destroy(mctx, &key);
489	}
490
491	return (conflict);
492}
493
494isc_boolean_t
495is_delegation(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
496	      dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp)
497{
498	dns_rdataset_t nsset;
499	isc_result_t result;
500
501	if (dns_name_equal(name, origin))
502		return (ISC_FALSE);
503
504	dns_rdataset_init(&nsset);
505	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_ns,
506				     0, 0, &nsset, NULL);
507	if (dns_rdataset_isassociated(&nsset)) {
508		if (ttlp != NULL)
509			*ttlp = nsset.ttl;
510		dns_rdataset_disassociate(&nsset);
511	}
512
513	return (ISC_TF(result == ISC_R_SUCCESS));
514}
515
516static isc_boolean_t
517goodsig(dns_name_t *origin, dns_rdata_t *sigrdata, dns_name_t *name,
518	dns_rdataset_t *keyrdataset, dns_rdataset_t *rdataset, isc_mem_t *mctx)
519{
520	dns_rdata_dnskey_t key;
521	dns_rdata_rrsig_t sig;
522	dst_key_t *dstkey = NULL;
523	isc_result_t result;
524
525	dns_rdata_tostruct(sigrdata, &sig, NULL);
526
527	for (result = dns_rdataset_first(keyrdataset);
528	     result == ISC_R_SUCCESS;
529	     result = dns_rdataset_next(keyrdataset)) {
530		dns_rdata_t rdata = DNS_RDATA_INIT;
531		dns_rdataset_current(keyrdataset, &rdata);
532		dns_rdata_tostruct(&rdata, &key, NULL);
533		result = dns_dnssec_keyfromrdata(origin, &rdata, mctx,
534						 &dstkey);
535		if (result != ISC_R_SUCCESS)
536			return (ISC_FALSE);
537		if (sig.algorithm != key.algorithm ||
538		    sig.keyid != dst_key_id(dstkey) ||
539		    !dns_name_equal(&sig.signer, origin)) {
540			dst_key_free(&dstkey);
541			continue;
542		}
543		result = dns_dnssec_verify(name, rdataset, dstkey, ISC_FALSE,
544					   mctx, sigrdata);
545		dst_key_free(&dstkey);
546		if (result == ISC_R_SUCCESS)
547			return(ISC_TRUE);
548	}
549	return (ISC_FALSE);
550}
551
552static isc_result_t
553verifynsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
554	   dns_dbnode_t *node, dns_name_t *nextname)
555{
556	unsigned char buffer[DNS_NSEC_BUFFERSIZE];
557	char namebuf[DNS_NAME_FORMATSIZE];
558	char nextbuf[DNS_NAME_FORMATSIZE];
559	char found[DNS_NAME_FORMATSIZE];
560	dns_rdataset_t rdataset;
561	dns_rdata_t rdata = DNS_RDATA_INIT;
562	dns_rdata_t tmprdata = DNS_RDATA_INIT;
563	dns_rdata_nsec_t nsec;
564	isc_result_t result;
565
566	dns_rdataset_init(&rdataset);
567	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
568				     0, 0, &rdataset, NULL);
569	if (result != ISC_R_SUCCESS) {
570		dns_name_format(name, namebuf, sizeof(namebuf));
571		fprintf(stderr, "Missing NSEC record for %s\n", namebuf);
572		goto failure;
573	}
574
575	result = dns_rdataset_first(&rdataset);
576	check_result(result, "dns_rdataset_first()");
577
578	dns_rdataset_current(&rdataset, &rdata);
579	result = dns_rdata_tostruct(&rdata, &nsec, NULL);
580	check_result(result, "dns_rdata_tostruct()");
581	/* Check bit next name is consistent */
582	if (!dns_name_equal(&nsec.next, nextname)) {
583		dns_name_format(name, namebuf, sizeof(namebuf));
584		dns_name_format(nextname, nextbuf, sizeof(nextbuf));
585		dns_name_format(&nsec.next, found, sizeof(found));
586		fprintf(stderr, "Bad record NSEC record for %s, next name "
587				"mismatch (expected:%s, found:%s)\n", namebuf,
588				nextbuf, found);
589		goto failure;
590	}
591	/* Check bit map is consistent */
592	result = dns_nsec_buildrdata(db, ver, node, nextname, buffer,
593				     &tmprdata);
594	check_result(result, "dns_nsec_buildrdata()");
595	if (dns_rdata_compare(&rdata, &tmprdata) != 0) {
596		dns_name_format(name, namebuf, sizeof(namebuf));
597		fprintf(stderr, "Bad record NSEC record for %s, bit map "
598				"mismatch\n", namebuf);
599		goto failure;
600	}
601	result = dns_rdataset_next(&rdataset);
602	if (result != ISC_R_NOMORE) {
603		dns_name_format(name, namebuf, sizeof(namebuf));
604		fprintf(stderr, "Multipe NSEC records for %s\n", namebuf);
605		goto failure;
606
607	}
608	dns_rdataset_disassociate(&rdataset);
609	return (ISC_R_SUCCESS);
610 failure:
611	if (dns_rdataset_isassociated(&rdataset))
612		dns_rdataset_disassociate(&rdataset);
613	return (ISC_R_FAILURE);
614}
615
616static void
617check_no_rrsig(dns_db_t *db, dns_dbversion_t *ver, dns_rdataset_t *rdataset,
618	       dns_name_t *name, dns_dbnode_t *node)
619{
620	char namebuf[DNS_NAME_FORMATSIZE];
621	char typebuf[80];
622	dns_rdataset_t sigrdataset;
623	dns_rdatasetiter_t *rdsiter = NULL;
624	isc_result_t result;
625
626	dns_rdataset_init(&sigrdataset);
627	result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
628	check_result(result, "dns_db_allrdatasets()");
629	for (result = dns_rdatasetiter_first(rdsiter);
630	     result == ISC_R_SUCCESS;
631	     result = dns_rdatasetiter_next(rdsiter)) {
632		dns_rdatasetiter_current(rdsiter, &sigrdataset);
633		if (sigrdataset.type == dns_rdatatype_rrsig &&
634		    sigrdataset.covers == rdataset->type)
635			break;
636		dns_rdataset_disassociate(&sigrdataset);
637	}
638	if (result == ISC_R_SUCCESS) {
639		dns_name_format(name, namebuf, sizeof(namebuf));
640		type_format(rdataset->type, typebuf, sizeof(typebuf));
641		fprintf(stderr, "Warning: Found unexpected signatures for "
642			"%s/%s\n", namebuf, typebuf);
643	}
644	if (dns_rdataset_isassociated(&sigrdataset))
645		dns_rdataset_disassociate(&sigrdataset);
646	dns_rdatasetiter_destroy(&rdsiter);
647}
648
649static isc_boolean_t
650chain_compare(void *arg1, void *arg2) {
651	struct nsec3_chain_fixed *e1 = arg1, *e2 = arg2;
652	size_t len;
653
654	/*
655	 * Do each element in turn to get a stable sort.
656	 */
657	if (e1->hash < e2->hash)
658		return (ISC_TRUE);
659	if (e1->hash > e2->hash)
660		return (ISC_FALSE);
661	if (e1->iterations < e2->iterations)
662		return (ISC_TRUE);
663	if (e1->iterations > e2->iterations)
664		return (ISC_FALSE);
665	if (e1->salt_length < e2->salt_length)
666		return (ISC_TRUE);
667	if (e1->salt_length > e2->salt_length)
668		return (ISC_FALSE);
669	if (e1->next_length < e2->next_length)
670		return (ISC_TRUE);
671	if (e1->next_length > e2->next_length)
672		return (ISC_FALSE);
673	len = e1->salt_length + 2 * e1->next_length;
674	if (memcmp(e1 + 1, e2 + 1, len) < 0)
675		return (ISC_TRUE);
676	return (ISC_FALSE);
677}
678
679static isc_boolean_t
680chain_equal(struct nsec3_chain_fixed *e1, struct nsec3_chain_fixed *e2) {
681	size_t len;
682
683	if (e1->hash != e2->hash)
684		return (ISC_FALSE);
685	if (e1->iterations != e2->iterations)
686		return (ISC_FALSE);
687	if (e1->salt_length != e2->salt_length)
688		return (ISC_FALSE);
689	if (e1->next_length != e2->next_length)
690		return (ISC_FALSE);
691	len = e1->salt_length + 2 * e1->next_length;
692	if (memcmp(e1 + 1, e2 + 1, len) != 0)
693		return (ISC_FALSE);
694	return (ISC_TRUE);
695}
696
697static isc_result_t
698record_nsec3(const unsigned char *rawhash, const dns_rdata_nsec3_t *nsec3,
699	     isc_mem_t *mctx, isc_heap_t *chains)
700{
701	struct nsec3_chain_fixed *element;
702	size_t len;
703	unsigned char *cp;
704	isc_result_t result;
705
706	len = sizeof(*element) + nsec3->next_length * 2 + nsec3->salt_length;
707
708	element = isc_mem_get(mctx, len);
709	if (element == NULL)
710		return (ISC_R_NOMEMORY);
711	memset(element, 0, len);
712	element->hash = nsec3->hash;
713	element->salt_length = nsec3->salt_length;
714	element->next_length = nsec3->next_length;
715	element->iterations = nsec3->iterations;
716	cp = (unsigned char *)(element + 1);
717	memcpy(cp, nsec3->salt, nsec3->salt_length);
718	cp += nsec3->salt_length;
719	memcpy(cp, rawhash, nsec3->next_length);
720	cp += nsec3->next_length;
721	memcpy(cp, nsec3->next, nsec3->next_length);
722	result = isc_heap_insert(chains, element);
723	if (result != ISC_R_SUCCESS) {
724		fprintf(stderr, "isc_heap_insert failed: %s\n",
725			isc_result_totext(result));
726		isc_mem_put(mctx, element, len);
727	}
728	return (result);
729}
730
731static isc_result_t
732match_nsec3(dns_name_t *name, isc_mem_t *mctx,
733	    dns_rdata_nsec3param_t *nsec3param, dns_rdataset_t *rdataset,
734	    unsigned char types[8192], unsigned int maxtype,
735	    unsigned char *rawhash, size_t rhsize)
736{
737	unsigned char cbm[8244];
738	char namebuf[DNS_NAME_FORMATSIZE];
739	dns_rdata_nsec3_t nsec3;
740	isc_result_t result;
741	unsigned int len;
742
743	/*
744	 * Find matching NSEC3 record.
745	 */
746	for (result = dns_rdataset_first(rdataset);
747	     result == ISC_R_SUCCESS;
748	     result = dns_rdataset_next(rdataset)) {
749		dns_rdata_t rdata = DNS_RDATA_INIT;
750		dns_rdataset_current(rdataset, &rdata);
751		result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
752		check_result(result, "dns_rdata_tostruct()");
753		if (nsec3.hash == nsec3param->hash &&
754		    nsec3.next_length == rhsize &&
755		    nsec3.iterations == nsec3param->iterations &&
756		    nsec3.salt_length == nsec3param->salt_length &&
757		    memcmp(nsec3.salt, nsec3param->salt,
758			   nsec3param->salt_length) == 0)
759			break;
760	}
761	if (result != ISC_R_SUCCESS) {
762		dns_name_format(name, namebuf, sizeof(namebuf));
763		fprintf(stderr, "Missing NSEC3 record for %s\n", namebuf);
764		return (result);
765	}
766
767	/*
768	 * Check the type list.
769	 */
770	len = dns_nsec_compressbitmap(cbm, types, maxtype);
771	if (nsec3.len != len || memcmp(cbm, nsec3.typebits, len) != 0) {
772		dns_name_format(name, namebuf, sizeof(namebuf));
773		fprintf(stderr, "Bad record NSEC3 record for %s, bit map "
774				"mismatch\n", namebuf);
775		return (ISC_R_FAILURE);
776	}
777
778	/*
779	 * Record chain.
780	 */
781	result = record_nsec3(rawhash, &nsec3, mctx, expected_chains);
782	check_result(result, "record_nsec3()");
783
784	/*
785	 * Make sure there is only one NSEC3 record with this set of
786	 * parameters.
787	 */
788	for (result = dns_rdataset_next(rdataset);
789	     result == ISC_R_SUCCESS;
790	     result = dns_rdataset_next(rdataset)) {
791		dns_rdata_t rdata = DNS_RDATA_INIT;
792		dns_rdataset_current(rdataset, &rdata);
793		result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
794		check_result(result, "dns_rdata_tostruct()");
795		if (nsec3.hash == nsec3param->hash &&
796		    nsec3.iterations == nsec3param->iterations &&
797		    nsec3.salt_length == nsec3param->salt_length &&
798		    memcmp(nsec3.salt, nsec3param->salt,
799			   nsec3.salt_length) == 0) {
800			dns_name_format(name, namebuf, sizeof(namebuf));
801			fprintf(stderr, "Multiple NSEC3 records with the "
802				"same parameter set for %s", namebuf);
803			result = DNS_R_DUPLICATE;
804			break;
805		}
806	}
807	if (result != ISC_R_NOMORE)
808		return (result);
809
810	result = ISC_R_SUCCESS;
811	return (result);
812}
813
814static isc_boolean_t
815innsec3params(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *nsec3paramset) {
816	dns_rdata_nsec3param_t nsec3param;
817	isc_result_t result;
818
819	for (result = dns_rdataset_first(nsec3paramset);
820	     result == ISC_R_SUCCESS;
821	     result = dns_rdataset_next(nsec3paramset)) {
822		dns_rdata_t rdata = DNS_RDATA_INIT;
823
824		dns_rdataset_current(nsec3paramset, &rdata);
825		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
826		if (nsec3param.flags == 0 &&
827		    nsec3param.hash == nsec3->hash &&
828		    nsec3param.iterations == nsec3->iterations &&
829		    nsec3param.salt_length == nsec3->salt_length &&
830		    memcmp(nsec3param.salt, nsec3->salt,
831			   nsec3->salt_length) == 0)
832			return (ISC_TRUE);
833	}
834	return (ISC_FALSE);
835}
836
837static isc_result_t
838record_found(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx,
839	     dns_name_t *name, dns_dbnode_t *node,
840	     dns_rdataset_t *nsec3paramset)
841{
842	unsigned char owner[NSEC3_MAX_HASH_LENGTH];
843	dns_rdata_nsec3_t nsec3;
844	dns_rdataset_t rdataset;
845	dns_label_t hashlabel;
846	isc_buffer_t b;
847	isc_result_t result;
848
849	if (nsec3paramset == NULL || !dns_rdataset_isassociated(nsec3paramset))
850		return (ISC_R_SUCCESS);
851
852	dns_rdataset_init(&rdataset);
853	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
854				     0, 0, &rdataset, NULL);
855	if (result != ISC_R_SUCCESS)
856		return (ISC_R_SUCCESS);
857
858	dns_name_getlabel(name, 0, &hashlabel);
859	isc_region_consume(&hashlabel, 1);
860	isc_buffer_init(&b, owner, sizeof(owner));
861	result = isc_base32hex_decoderegion(&hashlabel, &b);
862	if (result != ISC_R_SUCCESS)
863		goto cleanup;
864
865	for (result = dns_rdataset_first(&rdataset);
866	     result == ISC_R_SUCCESS;
867	     result = dns_rdataset_next(&rdataset)) {
868		dns_rdata_t rdata = DNS_RDATA_INIT;
869		dns_rdataset_current(&rdataset, &rdata);
870		result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
871		check_result(result, "dns_rdata_tostruct()");
872		if (nsec3.next_length != isc_buffer_usedlength(&b))
873			continue;
874		/*
875		 * We only care about NSEC3 records that match a NSEC3PARAM
876		 * record.
877		 */
878		if (!innsec3params(&nsec3, nsec3paramset))
879			continue;
880
881		/*
882		 * Record chain.
883		 */
884		result = record_nsec3(owner, &nsec3, mctx, found_chains);
885		check_result(result, "record_nsec3()");
886	}
887
888 cleanup:
889	dns_rdataset_disassociate(&rdataset);
890	return (ISC_R_SUCCESS);
891}
892
893static isc_result_t
894verifynsec3(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
895	    isc_mem_t *mctx, dns_name_t *name, dns_rdata_t *rdata,
896	    isc_boolean_t delegation, unsigned char types[8192],
897	    unsigned int maxtype)
898{
899	char namebuf[DNS_NAME_FORMATSIZE];
900	char hashbuf[DNS_NAME_FORMATSIZE];
901	dns_rdataset_t rdataset;
902	dns_rdata_nsec3param_t nsec3param;
903	dns_fixedname_t fixed;
904	dns_name_t *hashname;
905	isc_result_t result;
906	dns_dbnode_t *node = NULL;
907	unsigned char rawhash[NSEC3_MAX_HASH_LENGTH];
908	size_t rhsize = sizeof(rawhash);
909
910	result = dns_rdata_tostruct(rdata, &nsec3param, NULL);
911	check_result(result, "dns_rdata_tostruct()");
912
913	if (nsec3param.flags != 0)
914		return (ISC_R_SUCCESS);
915
916	if (!dns_nsec3_supportedhash(nsec3param.hash))
917		return (ISC_R_SUCCESS);
918
919	dns_fixedname_init(&fixed);
920	result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, name, origin,
921				    nsec3param.hash, nsec3param.iterations,
922				    nsec3param.salt, nsec3param.salt_length);
923	check_result(result, "dns_nsec3_hashname()");
924
925	/*
926	 * We don't use dns_db_find() here as it works with the choosen
927	 * nsec3 chain and we may also be called with uncommitted data
928	 * from dnssec-signzone so the secure status of the zone may not
929	 * be up to date.
930	 */
931	dns_rdataset_init(&rdataset);
932	hashname = dns_fixedname_name(&fixed);
933	result = dns_db_findnsec3node(db, hashname, ISC_FALSE, &node);
934	if (result == ISC_R_SUCCESS)
935		result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
936					     0, 0, &rdataset, NULL);
937	if (result != ISC_R_SUCCESS &&
938	    (!delegation || dns_nsec_isset(types, dns_rdatatype_ds))) {
939		dns_name_format(name, namebuf, sizeof(namebuf));
940		dns_name_format(hashname, hashbuf, sizeof(hashbuf));
941		fprintf(stderr, "Missing NSEC3 record for %s (%s)\n",
942			namebuf, hashbuf);
943	} else if (result == ISC_R_SUCCESS) {
944		result = match_nsec3(name, mctx, &nsec3param, &rdataset,
945				     types, maxtype, rawhash, rhsize);
946	} else if (result == ISC_R_NOTFOUND && delegation)
947		result = ISC_R_SUCCESS;
948	if (dns_rdataset_isassociated(&rdataset))
949		dns_rdataset_disassociate(&rdataset);
950	if (node != NULL)
951		dns_db_detachnode(db, &node);
952
953	return (result);
954}
955
956static isc_result_t
957verifynsec3s(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
958	     isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *nsec3paramset,
959	     isc_boolean_t delegation, unsigned char types[8192],
960	     unsigned int maxtype)
961{
962	isc_result_t result;
963
964	for (result = dns_rdataset_first(nsec3paramset);
965	     result == ISC_R_SUCCESS;
966	     result = dns_rdataset_next(nsec3paramset)) {
967		dns_rdata_t rdata = DNS_RDATA_INIT;
968
969		dns_rdataset_current(nsec3paramset, &rdata);
970		result = verifynsec3(db, ver, origin, mctx, name, &rdata,
971				     delegation, types, maxtype);
972		if (result != ISC_R_SUCCESS)
973			break;
974	}
975	if (result == ISC_R_NOMORE)
976		result = ISC_R_SUCCESS;
977	return (result);
978}
979
980static void
981verifyset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
982	  isc_mem_t *mctx, dns_rdataset_t *rdataset, dns_name_t *name,
983	  dns_dbnode_t *node, dns_rdataset_t *keyrdataset,
984	  unsigned char *act_algorithms, unsigned char *bad_algorithms)
985{
986	unsigned char set_algorithms[256];
987	char namebuf[DNS_NAME_FORMATSIZE];
988	char algbuf[80];
989	char typebuf[80];
990	dns_rdataset_t sigrdataset;
991	dns_rdatasetiter_t *rdsiter = NULL;
992	isc_result_t result;
993	int i;
994
995	dns_rdataset_init(&sigrdataset);
996	result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
997	check_result(result, "dns_db_allrdatasets()");
998	for (result = dns_rdatasetiter_first(rdsiter);
999	     result == ISC_R_SUCCESS;
1000	     result = dns_rdatasetiter_next(rdsiter)) {
1001		dns_rdatasetiter_current(rdsiter, &sigrdataset);
1002		if (sigrdataset.type == dns_rdatatype_rrsig &&
1003		    sigrdataset.covers == rdataset->type)
1004			break;
1005		dns_rdataset_disassociate(&sigrdataset);
1006	}
1007	if (result != ISC_R_SUCCESS) {
1008		dns_name_format(name, namebuf, sizeof(namebuf));
1009		type_format(rdataset->type, typebuf, sizeof(typebuf));
1010		fprintf(stderr, "No signatures for %s/%s\n", namebuf, typebuf);
1011		for (i = 0; i < 256; i++)
1012			if (act_algorithms[i] != 0)
1013				bad_algorithms[i] = 1;
1014		dns_rdatasetiter_destroy(&rdsiter);
1015		return;
1016	}
1017
1018	memset(set_algorithms, 0, sizeof(set_algorithms));
1019	for (result = dns_rdataset_first(&sigrdataset);
1020	     result == ISC_R_SUCCESS;
1021	     result = dns_rdataset_next(&sigrdataset)) {
1022		dns_rdata_t rdata = DNS_RDATA_INIT;
1023		dns_rdata_rrsig_t sig;
1024
1025		dns_rdataset_current(&sigrdataset, &rdata);
1026		dns_rdata_tostruct(&rdata, &sig, NULL);
1027		if (rdataset->ttl != sig.originalttl) {
1028			dns_name_format(name, namebuf, sizeof(namebuf));
1029			type_format(rdataset->type, typebuf, sizeof(typebuf));
1030			fprintf(stderr, "TTL mismatch for %s %s keytag %u\n",
1031				namebuf, typebuf, sig.keyid);
1032			continue;
1033		}
1034		if ((set_algorithms[sig.algorithm] != 0) ||
1035		    (act_algorithms[sig.algorithm] == 0))
1036			continue;
1037		if (goodsig(origin, &rdata, name, keyrdataset, rdataset, mctx))
1038			set_algorithms[sig.algorithm] = 1;
1039	}
1040	dns_rdatasetiter_destroy(&rdsiter);
1041	if (memcmp(set_algorithms, act_algorithms, sizeof(set_algorithms))) {
1042		dns_name_format(name, namebuf, sizeof(namebuf));
1043		type_format(rdataset->type, typebuf, sizeof(typebuf));
1044		for (i = 0; i < 256; i++)
1045			if ((act_algorithms[i] != 0) &&
1046			    (set_algorithms[i] == 0)) {
1047				dns_secalg_format(i, algbuf, sizeof(algbuf));
1048				fprintf(stderr, "No correct %s signature for "
1049					"%s %s\n", algbuf, namebuf, typebuf);
1050				bad_algorithms[i] = 1;
1051			}
1052	}
1053	dns_rdataset_disassociate(&sigrdataset);
1054}
1055
1056static isc_result_t
1057verifynode(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
1058	   isc_mem_t *mctx, dns_name_t *name, dns_dbnode_t *node,
1059	   isc_boolean_t delegation, dns_rdataset_t *keyrdataset,
1060	   unsigned char *act_algorithms, unsigned char *bad_algorithms,
1061	   dns_rdataset_t *nsecset, dns_rdataset_t *nsec3paramset,
1062	   dns_name_t *nextname)
1063{
1064	unsigned char types[8192];
1065	unsigned int maxtype = 0;
1066	dns_rdataset_t rdataset; dns_rdatasetiter_t *rdsiter = NULL;
1067	isc_result_t result, tresult;
1068
1069	memset(types, 0, sizeof(types));
1070	result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
1071	check_result(result, "dns_db_allrdatasets()");
1072	result = dns_rdatasetiter_first(rdsiter);
1073	dns_rdataset_init(&rdataset);
1074	while (result == ISC_R_SUCCESS) {
1075		dns_rdatasetiter_current(rdsiter, &rdataset);
1076		/*
1077		 * If we are not at a delegation then everything should be
1078		 * signed.  If we are at a delegation then only the DS set
1079		 * is signed.  The NS set is not signed at a delegation but
1080		 * its existance is recorded in the bit map.  Anything else
1081		 * other than NSEC and DS is not signed at a delegation.
1082		 */
1083		if (rdataset.type != dns_rdatatype_rrsig &&
1084		    rdataset.type != dns_rdatatype_dnskey &&
1085		    (!delegation || rdataset.type == dns_rdatatype_ds ||
1086		     rdataset.type == dns_rdatatype_nsec)) {
1087			verifyset(db, ver, origin, mctx, &rdataset,
1088				  name, node, keyrdataset,
1089				  act_algorithms, bad_algorithms);
1090			dns_nsec_setbit(types, rdataset.type, 1);
1091			if (rdataset.type > maxtype)
1092				maxtype = rdataset.type;
1093		} else if (rdataset.type != dns_rdatatype_rrsig &&
1094			   rdataset.type != dns_rdatatype_dnskey) {
1095			if (rdataset.type == dns_rdatatype_ns)
1096				dns_nsec_setbit(types, rdataset.type, 1);
1097			check_no_rrsig(db, ver, &rdataset, name, node);
1098		} else
1099			dns_nsec_setbit(types, rdataset.type, 1);
1100		dns_rdataset_disassociate(&rdataset);
1101		result = dns_rdatasetiter_next(rdsiter);
1102	}
1103	if (result != ISC_R_NOMORE)
1104		fatal("rdataset iteration failed: %s",
1105		      isc_result_totext(result));
1106	dns_rdatasetiter_destroy(&rdsiter);
1107
1108	result = ISC_R_SUCCESS;
1109
1110	if (nsecset != NULL && dns_rdataset_isassociated(nsecset))
1111		result = verifynsec(db, ver, name, node, nextname);
1112
1113	if (nsec3paramset != NULL && dns_rdataset_isassociated(nsec3paramset)) {
1114		tresult = verifynsec3s(db, ver, origin, mctx, name,
1115				       nsec3paramset, delegation, types,
1116				       maxtype);
1117		if (result == ISC_R_SUCCESS && tresult != ISC_R_SUCCESS)
1118			result = tresult;
1119	}
1120	return (result);
1121}
1122
1123static isc_boolean_t
1124is_empty(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node) {
1125	dns_rdatasetiter_t *rdsiter = NULL;
1126	isc_result_t result;
1127
1128	result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
1129	check_result(result, "dns_db_allrdatasets()");
1130	result = dns_rdatasetiter_first(rdsiter);
1131	dns_rdatasetiter_destroy(&rdsiter);
1132	if (result == ISC_R_NOMORE)
1133		return (ISC_TRUE);
1134	return (ISC_FALSE);
1135}
1136
1137static void
1138check_no_nsec(dns_name_t *name, dns_dbnode_t *node, dns_db_t *db,
1139	      dns_dbversion_t *ver)
1140{
1141	dns_rdataset_t rdataset;
1142	isc_result_t result;
1143
1144	dns_rdataset_init(&rdataset);
1145	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
1146				     0, 0, &rdataset, NULL);
1147	if (result != ISC_R_NOTFOUND) {
1148		char namebuf[DNS_NAME_FORMATSIZE];
1149		dns_name_format(name, namebuf, sizeof(namebuf));
1150		fatal("unexpected NSEC RRset at %s\n", namebuf);
1151	}
1152
1153	if (dns_rdataset_isassociated(&rdataset))
1154		dns_rdataset_disassociate(&rdataset);
1155}
1156
1157static isc_boolean_t
1158newchain(const struct nsec3_chain_fixed *first,
1159	 const struct nsec3_chain_fixed *e)
1160{
1161	if (first->hash != e->hash ||
1162	    first->iterations != e->iterations ||
1163	    first->salt_length != e->salt_length ||
1164	    first->next_length != e->next_length ||
1165	    memcmp(first + 1, e + 1, first->salt_length) != 0)
1166		return (ISC_TRUE);
1167	return (ISC_FALSE);
1168}
1169
1170static void
1171free_element(isc_mem_t *mctx, struct nsec3_chain_fixed *e) {
1172	size_t len;
1173
1174	len = sizeof(*e) + e->salt_length + 2 * e->next_length;
1175	isc_mem_put(mctx, e, len);
1176}
1177
1178static isc_boolean_t
1179checknext(const struct nsec3_chain_fixed *first,
1180	  const struct nsec3_chain_fixed *e)
1181{
1182	char buf[512];
1183	const unsigned char *d1 = (const unsigned char *)(first + 1);
1184	const unsigned char *d2 = (const unsigned char *)(e + 1);
1185	isc_buffer_t b;
1186	isc_region_t sr;
1187
1188	d1 += first->salt_length + first->next_length;
1189	d2 += e->salt_length;
1190
1191	if (memcmp(d1, d2, first->next_length) == 0)
1192		return (ISC_TRUE);
1193
1194	DE_CONST(d1 - first->next_length, sr.base);
1195	sr.length = first->next_length;
1196	isc_buffer_init(&b, buf, sizeof(buf));
1197	isc_base32hex_totext(&sr, 1, "", &b);
1198	fprintf(stderr, "Break in NSEC3 chain at: %.*s\n",
1199		(int) isc_buffer_usedlength(&b), buf);
1200
1201	DE_CONST(d1, sr.base);
1202	sr.length = first->next_length;
1203	isc_buffer_init(&b, buf, sizeof(buf));
1204	isc_base32hex_totext(&sr, 1, "", &b);
1205	fprintf(stderr, "Expected: %.*s\n", (int) isc_buffer_usedlength(&b),
1206		buf);
1207
1208	DE_CONST(d2, sr.base);
1209	sr.length = first->next_length;
1210	isc_buffer_init(&b, buf, sizeof(buf));
1211	isc_base32hex_totext(&sr, 1, "", &b);
1212	fprintf(stderr, "Found: %.*s\n", (int) isc_buffer_usedlength(&b), buf);
1213
1214	return (ISC_FALSE);
1215}
1216
1217#define EXPECTEDANDFOUND "Expected and found NSEC3 chains not equal\n"
1218
1219static isc_result_t
1220verify_nsec3_chains(isc_mem_t *mctx) {
1221	isc_result_t result = ISC_R_SUCCESS;
1222	struct nsec3_chain_fixed *e, *f = NULL;
1223	struct nsec3_chain_fixed *first = NULL, *prev = NULL;
1224
1225	while ((e = isc_heap_element(expected_chains, 1)) != NULL) {
1226		isc_heap_delete(expected_chains, 1);
1227		if (f == NULL)
1228			f = isc_heap_element(found_chains, 1);
1229		if (f != NULL) {
1230			isc_heap_delete(found_chains, 1);
1231
1232			/*
1233			 * Check that they match.
1234			 */
1235			if (chain_equal(e, f)) {
1236				free_element(mctx, f);
1237				f = NULL;
1238			} else {
1239				if (result == ISC_R_SUCCESS)
1240					fprintf(stderr, EXPECTEDANDFOUND);
1241				result = ISC_R_FAILURE;
1242				/*
1243				 * Attempt to resync found_chain.
1244				 */
1245				while (f != NULL && !chain_compare(e, f)) {
1246					free_element(mctx, f);
1247					f = isc_heap_element(found_chains, 1);
1248					if (f != NULL)
1249						isc_heap_delete(found_chains, 1);
1250					if (f != NULL && chain_equal(e, f)) {
1251						free_element(mctx, f);
1252						f = NULL;
1253						break;
1254					}
1255				}
1256			}
1257		} else if (result == ISC_R_SUCCESS) {
1258			fprintf(stderr, EXPECTEDANDFOUND);
1259			result = ISC_R_FAILURE;
1260		}
1261		if (first == NULL || newchain(first, e)) {
1262			if (prev != NULL) {
1263				if (!checknext(prev, first))
1264					result = ISC_R_FAILURE;
1265				if (prev != first)
1266					free_element(mctx, prev);
1267			}
1268			if (first != NULL)
1269				free_element(mctx, first);
1270			prev = first = e;
1271			continue;
1272		}
1273		if (!checknext(prev, e))
1274			result = ISC_R_FAILURE;
1275		if (prev != first)
1276			free_element(mctx, prev);
1277		prev = e;
1278	}
1279	if (prev != NULL) {
1280		if (!checknext(prev, first))
1281			result = ISC_R_FAILURE;
1282		if (prev != first)
1283			free_element(mctx, prev);
1284	}
1285	if (first != NULL)
1286		free_element(mctx, first);
1287	do {
1288		if (f != NULL) {
1289			if (result == ISC_R_SUCCESS) {
1290				fprintf(stderr, EXPECTEDANDFOUND);
1291				result = ISC_R_FAILURE;
1292			}
1293			free_element(mctx, f);
1294		}
1295		f = isc_heap_element(found_chains, 1);
1296		if (f != NULL)
1297			isc_heap_delete(found_chains, 1);
1298	} while (f != NULL);
1299
1300	return (result);
1301}
1302
1303static isc_result_t
1304verifyemptynodes(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
1305		 isc_mem_t *mctx, dns_name_t *name, dns_name_t *nextname,
1306		 dns_rdataset_t *nsec3paramset)
1307{
1308	dns_namereln_t reln;
1309	int order;
1310	unsigned int labels, nlabels, i;
1311	dns_name_t suffix;
1312	isc_result_t result = ISC_R_SUCCESS, tresult;
1313
1314	reln = dns_name_fullcompare(name, nextname, &order, &labels);
1315	if (order >= 0)
1316		return (result);
1317
1318	nlabels = dns_name_countlabels(nextname);
1319
1320	if (reln == dns_namereln_commonancestor ||
1321	    reln == dns_namereln_contains) {
1322		dns_name_init(&suffix, NULL);
1323		for (i = labels + 1; i < nlabels; i++) {
1324			dns_name_getlabelsequence(nextname, nlabels - i, i,
1325						  &suffix);
1326			if (nsec3paramset != NULL &&
1327			     dns_rdataset_isassociated(nsec3paramset)) {
1328				tresult = verifynsec3s(db, ver, origin, mctx,
1329						       &suffix, nsec3paramset,
1330						       ISC_FALSE, NULL, 0);
1331				if (result == ISC_R_SUCCESS &&
1332				    tresult != ISC_R_SUCCESS)
1333					result = tresult;
1334			}
1335		}
1336	}
1337	return (result);
1338}
1339
1340/*%
1341 * Verify that certain things are sane:
1342 *
1343 *   The apex has a DNSKEY record with at least one KSK, and at least
1344 *   one ZSK if the -x flag was not used.
1345 *
1346 *   The DNSKEY record was signed with at least one of the KSKs in this
1347 *   set.
1348 *
1349 *   The rest of the zone was signed with at least one of the ZSKs
1350 *   present in the DNSKEY RRSET.
1351 */
1352void
1353verifyzone(dns_db_t *db, dns_dbversion_t *ver,
1354	   dns_name_t *origin, isc_mem_t *mctx,
1355	   isc_boolean_t ignore_kskflag, isc_boolean_t keyset_kskonly)
1356{
1357	char algbuf[80];
1358	dns_dbiterator_t *dbiter = NULL;
1359	dns_dbnode_t *node = NULL, *nextnode = NULL;
1360	dns_fixedname_t fname, fnextname, fzonecut;
1361	dns_name_t *name, *nextname, *zonecut;
1362	dns_rdata_dnskey_t dnskey;
1363	dns_rdata_t rdata = DNS_RDATA_INIT;
1364	dns_rdataset_t keyset, soaset;
1365	dns_rdataset_t keysigs, soasigs;
1366	dns_rdataset_t nsecset, nsecsigs;
1367	dns_rdataset_t nsec3paramset, nsec3paramsigs;
1368	int i;
1369	isc_boolean_t done = ISC_FALSE;
1370	isc_boolean_t first = ISC_TRUE;
1371	isc_boolean_t goodksk = ISC_FALSE;
1372	isc_boolean_t goodzsk = ISC_FALSE;
1373	isc_result_t result, vresult = ISC_R_UNSET;
1374	unsigned char revoked_ksk[256];
1375	unsigned char revoked_zsk[256];
1376	unsigned char standby_ksk[256];
1377	unsigned char standby_zsk[256];
1378	unsigned char ksk_algorithms[256];
1379	unsigned char zsk_algorithms[256];
1380	unsigned char bad_algorithms[256];
1381	unsigned char act_algorithms[256];
1382
1383	result = isc_heap_create(mctx, chain_compare, NULL, 1024,
1384				 &expected_chains);
1385	check_result(result, "isc_heap_create()");
1386	result = isc_heap_create(mctx, chain_compare, NULL, 1024,
1387				 &found_chains);
1388	check_result(result, "isc_heap_create()");
1389
1390	result = dns_db_findnode(db, origin, ISC_FALSE, &node);
1391	if (result != ISC_R_SUCCESS)
1392		fatal("failed to find the zone's origin: %s",
1393		      isc_result_totext(result));
1394
1395	dns_rdataset_init(&keyset);
1396	dns_rdataset_init(&keysigs);
1397	dns_rdataset_init(&soaset);
1398	dns_rdataset_init(&soasigs);
1399	dns_rdataset_init(&nsecset);
1400	dns_rdataset_init(&nsecsigs);
1401	dns_rdataset_init(&nsec3paramset);
1402	dns_rdataset_init(&nsec3paramsigs);
1403	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
1404				     0, 0, &keyset, &keysigs);
1405	if (result != ISC_R_SUCCESS)
1406		fatal("Zone contains no DNSSEC keys\n");
1407
1408	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
1409				     0, 0, &soaset, &soasigs);
1410	if (result != ISC_R_SUCCESS)
1411		fatal("Zone contains no SOA record\n");
1412
1413	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
1414				     0, 0, &nsecset, &nsecsigs);
1415	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
1416		fatal("NSEC lookup failed\n");
1417
1418	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
1419				     0, 0, &nsec3paramset, &nsec3paramsigs);
1420	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
1421		fatal("NSEC3PARAM lookup failed\n");
1422
1423	if (!dns_rdataset_isassociated(&keysigs))
1424		fatal("DNSKEY is not signed (keys offline or inactive?)\n");
1425
1426	if (!dns_rdataset_isassociated(&soasigs))
1427		fatal("SOA is not signed (keys offline or inactive?)\n");
1428
1429	if (dns_rdataset_isassociated(&nsecset) &&
1430	    !dns_rdataset_isassociated(&nsecsigs))
1431		fatal("NSEC is not signed (keys offline or inactive?)\n");
1432
1433	if (dns_rdataset_isassociated(&nsec3paramset) &&
1434	    !dns_rdataset_isassociated(&nsec3paramsigs))
1435		fatal("NSEC3PARAM is not signed (keys offline or inactive?)\n");
1436
1437	if (!dns_rdataset_isassociated(&nsecset) &&
1438	    !dns_rdataset_isassociated(&nsec3paramset))
1439		fatal("No valid NSEC/NSEC3 chain for testing\n");
1440
1441	dns_db_detachnode(db, &node);
1442
1443	memset(revoked_ksk, 0, sizeof(revoked_ksk));
1444	memset(revoked_zsk, 0, sizeof(revoked_zsk));
1445	memset(standby_ksk, 0, sizeof(standby_ksk));
1446	memset(standby_zsk, 0, sizeof(standby_zsk));
1447	memset(ksk_algorithms, 0, sizeof(ksk_algorithms));
1448	memset(zsk_algorithms, 0, sizeof(zsk_algorithms));
1449	memset(bad_algorithms, 0, sizeof(bad_algorithms));
1450	memset(act_algorithms, 0, sizeof(act_algorithms));
1451
1452	/*
1453	 * Check that the DNSKEY RR has at least one self signing KSK
1454	 * and one ZSK per algorithm in it (or, if -x was used, one
1455	 * self-signing KSK).
1456	 */
1457	for (result = dns_rdataset_first(&keyset);
1458	     result == ISC_R_SUCCESS;
1459	     result = dns_rdataset_next(&keyset)) {
1460		dns_rdataset_current(&keyset, &rdata);
1461		result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
1462		check_result(result, "dns_rdata_tostruct");
1463
1464		if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0)
1465			;
1466		else if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) {
1467			if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1468			    !dns_dnssec_selfsigns(&rdata, origin, &keyset,
1469						  &keysigs, ISC_FALSE,
1470						  mctx)) {
1471				char namebuf[DNS_NAME_FORMATSIZE];
1472				char buffer[1024];
1473				isc_buffer_t buf;
1474
1475				dns_name_format(origin, namebuf,
1476						sizeof(namebuf));
1477				isc_buffer_init(&buf, buffer, sizeof(buffer));
1478				result = dns_rdata_totext(&rdata, NULL, &buf);
1479				check_result(result, "dns_rdata_totext");
1480				fatal("revoked KSK is not self signed:\n"
1481				      "%s DNSKEY %.*s", namebuf,
1482				      (int)isc_buffer_usedlength(&buf), buffer);
1483			}
1484			if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1485			     revoked_ksk[dnskey.algorithm] != 255)
1486				revoked_ksk[dnskey.algorithm]++;
1487			else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 &&
1488				 revoked_zsk[dnskey.algorithm] != 255)
1489				revoked_zsk[dnskey.algorithm]++;
1490		} else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) {
1491			if (dns_dnssec_selfsigns(&rdata, origin, &keyset,
1492						 &keysigs, ISC_FALSE, mctx)) {
1493				if (ksk_algorithms[dnskey.algorithm] != 255)
1494					ksk_algorithms[dnskey.algorithm]++;
1495				goodksk = ISC_TRUE;
1496			} else {
1497				if (standby_ksk[dnskey.algorithm] != 255)
1498					standby_ksk[dnskey.algorithm]++;
1499			}
1500		} else if (dns_dnssec_selfsigns(&rdata, origin, &keyset,
1501						&keysigs, ISC_FALSE, mctx)) {
1502			if (zsk_algorithms[dnskey.algorithm] != 255)
1503				zsk_algorithms[dnskey.algorithm]++;
1504			goodzsk = ISC_TRUE;
1505		} else if (dns_dnssec_signs(&rdata, origin, &soaset,
1506					    &soasigs, ISC_FALSE, mctx)) {
1507			if (zsk_algorithms[dnskey.algorithm] != 255)
1508				zsk_algorithms[dnskey.algorithm]++;
1509		} else {
1510			if (standby_zsk[dnskey.algorithm] != 255)
1511				standby_zsk[dnskey.algorithm]++;
1512		}
1513		dns_rdata_freestruct(&dnskey);
1514		dns_rdata_reset(&rdata);
1515	}
1516	dns_rdataset_disassociate(&keysigs);
1517	dns_rdataset_disassociate(&soaset);
1518	dns_rdataset_disassociate(&soasigs);
1519	if (dns_rdataset_isassociated(&nsecsigs))
1520		dns_rdataset_disassociate(&nsecsigs);
1521	if (dns_rdataset_isassociated(&nsec3paramsigs))
1522		dns_rdataset_disassociate(&nsec3paramsigs);
1523
1524	if (ignore_kskflag ) {
1525		if (!goodksk && !goodzsk)
1526			fatal("No self-signed DNSKEY found.");
1527	} else if (!goodksk)
1528		fatal("No self-signed KSK DNSKEY found.  Supply an active\n"
1529		      "key with the KSK flag set, or use '-P'.");
1530
1531	fprintf(stderr, "Verifying the zone using the following algorithms:");
1532	for (i = 0; i < 256; i++) {
1533		if (ignore_kskflag)
1534			act_algorithms[i] = (ksk_algorithms[i] != 0 ||
1535					     zsk_algorithms[i] != 0) ? 1 : 0;
1536		else
1537			act_algorithms[i] = ksk_algorithms[i] != 0 ? 1 : 0;
1538		if (act_algorithms[i] != 0) {
1539			dns_secalg_format(i, algbuf, sizeof(algbuf));
1540			fprintf(stderr, " %s", algbuf);
1541		}
1542	}
1543	fprintf(stderr, ".\n");
1544
1545	if (!ignore_kskflag && !keyset_kskonly) {
1546		for (i = 0; i < 256; i++) {
1547			/*
1548			 * The counts should both be zero or both be non-zero.
1549			 * Mark the algorithm as bad if this is not met.
1550			 */
1551			if ((ksk_algorithms[i] != 0) ==
1552			    (zsk_algorithms[i] != 0))
1553				continue;
1554			dns_secalg_format(i, algbuf, sizeof(algbuf));
1555			fprintf(stderr, "Missing %s for algorithm %s\n",
1556				(ksk_algorithms[i] != 0)
1557				   ? "ZSK"
1558				   : "self-signed KSK",
1559				algbuf);
1560			bad_algorithms[i] = 1;
1561		}
1562	}
1563
1564	/*
1565	 * Check that all the other records were signed by keys that are
1566	 * present in the DNSKEY RRSET.
1567	 */
1568
1569	dns_fixedname_init(&fname);
1570	name = dns_fixedname_name(&fname);
1571	dns_fixedname_init(&fnextname);
1572	nextname = dns_fixedname_name(&fnextname);
1573	dns_fixedname_init(&fzonecut);
1574	zonecut = NULL;
1575
1576	result = dns_db_createiterator(db, DNS_DB_NONSEC3, &dbiter);
1577	check_result(result, "dns_db_createiterator()");
1578
1579	result = dns_dbiterator_first(dbiter);
1580	check_result(result, "dns_dbiterator_first()");
1581
1582	while (!done) {
1583		isc_boolean_t isdelegation = ISC_FALSE;
1584
1585		result = dns_dbiterator_current(dbiter, &node, name);
1586		check_dns_dbiterator_current(result);
1587		if (!dns_name_issubdomain(name, origin)) {
1588			check_no_nsec(name, node, db, ver);
1589			dns_db_detachnode(db, &node);
1590			result = dns_dbiterator_next(dbiter);
1591			if (result == ISC_R_NOMORE)
1592				done = ISC_TRUE;
1593			else
1594				check_result(result, "dns_dbiterator_next()");
1595			continue;
1596		}
1597		if (is_delegation(db, ver, origin, name, node, NULL)) {
1598			zonecut = dns_fixedname_name(&fzonecut);
1599			dns_name_copy(name, zonecut, NULL);
1600			isdelegation = ISC_TRUE;
1601		}
1602		nextnode = NULL;
1603		result = dns_dbiterator_next(dbiter);
1604		while (result == ISC_R_SUCCESS) {
1605			result = dns_dbiterator_current(dbiter, &nextnode,
1606							nextname);
1607			check_dns_dbiterator_current(result);
1608			if (!dns_name_issubdomain(nextname, origin) ||
1609			    (zonecut != NULL &&
1610			     dns_name_issubdomain(nextname, zonecut)))
1611			{
1612				check_no_nsec(nextname, nextnode, db, ver);
1613				dns_db_detachnode(db, &nextnode);
1614				result = dns_dbiterator_next(dbiter);
1615				continue;
1616			}
1617			if (is_empty(db, ver, nextnode)) {
1618				dns_db_detachnode(db, &nextnode);
1619				result = dns_dbiterator_next(dbiter);
1620				continue;
1621			}
1622			dns_db_detachnode(db, &nextnode);
1623			break;
1624		}
1625		if (result == ISC_R_NOMORE) {
1626			done = ISC_TRUE;
1627			nextname = origin;
1628		} else if (result != ISC_R_SUCCESS)
1629			fatal("iterating through the database failed: %s",
1630			      isc_result_totext(result));
1631		result = verifynode(db, ver, origin, mctx, name, node,
1632				    isdelegation, &keyset, act_algorithms,
1633				    bad_algorithms, &nsecset, &nsec3paramset,
1634				    nextname);
1635		if (vresult == ISC_R_UNSET)
1636			vresult = ISC_R_SUCCESS;
1637		if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS)
1638			vresult = result;
1639		result = verifyemptynodes(db, ver, origin, mctx, name,
1640					  nextname, &nsec3paramset);
1641		if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS)
1642			vresult = result;
1643		dns_db_detachnode(db, &node);
1644	}
1645
1646	dns_dbiterator_destroy(&dbiter);
1647
1648	result = dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbiter);
1649	check_result(result, "dns_db_createiterator()");
1650
1651	for (result = dns_dbiterator_first(dbiter);
1652	     result == ISC_R_SUCCESS;
1653	     result = dns_dbiterator_next(dbiter) ) {
1654		result = dns_dbiterator_current(dbiter, &node, name);
1655		check_dns_dbiterator_current(result);
1656		result = verifynode(db, ver, origin, mctx, name, node,
1657				    ISC_FALSE, &keyset, act_algorithms,
1658				    bad_algorithms, NULL, NULL, NULL);
1659		check_result(result, "verifynode");
1660		record_found(db, ver, mctx, name, node, &nsec3paramset);
1661		dns_db_detachnode(db, &node);
1662	}
1663	dns_dbiterator_destroy(&dbiter);
1664
1665	dns_rdataset_disassociate(&keyset);
1666	if (dns_rdataset_isassociated(&nsecset))
1667		dns_rdataset_disassociate(&nsecset);
1668	if (dns_rdataset_isassociated(&nsec3paramset))
1669		dns_rdataset_disassociate(&nsec3paramset);
1670
1671	result = verify_nsec3_chains(mctx);
1672	if (vresult == ISC_R_UNSET)
1673		vresult = ISC_R_SUCCESS;
1674	if (result != ISC_R_SUCCESS && vresult == ISC_R_SUCCESS)
1675		vresult = result;
1676	isc_heap_destroy(&expected_chains);
1677	isc_heap_destroy(&found_chains);
1678
1679	/*
1680	 * If we made it this far, we have what we consider a properly signed
1681	 * zone.  Set the good flag.
1682	 */
1683	for (i = 0; i < 256; i++) {
1684		if (bad_algorithms[i] != 0) {
1685			if (first)
1686				fprintf(stderr, "The zone is not fully signed "
1687					"for the following algorithms:");
1688			dns_secalg_format(i, algbuf, sizeof(algbuf));
1689			fprintf(stderr, " %s", algbuf);
1690			first = ISC_FALSE;
1691		}
1692	}
1693	if (!first) {
1694		fprintf(stderr, ".\n");
1695		fatal("DNSSEC completeness test failed.");
1696	}
1697
1698	if (vresult != ISC_R_SUCCESS)
1699		fatal("DNSSEC completeness test failed (%s).",
1700		      dns_result_totext(vresult));
1701
1702	if (goodksk || ignore_kskflag) {
1703		/*
1704		 * Print the success summary.
1705		 */
1706		fprintf(stderr, "Zone fully signed:\n");
1707		for (i = 0; i < 256; i++) {
1708			if ((ksk_algorithms[i] != 0) ||
1709			    (standby_ksk[i] != 0) ||
1710			    (revoked_zsk[i] != 0) ||
1711			    (zsk_algorithms[i] != 0) ||
1712			    (standby_zsk[i] != 0) ||
1713			    (revoked_zsk[i] != 0)) {
1714				dns_secalg_format(i, algbuf, sizeof(algbuf));
1715				fprintf(stderr, "Algorithm: %s: KSKs: "
1716					"%u active, %u stand-by, %u revoked\n",
1717					algbuf, ksk_algorithms[i],
1718					standby_ksk[i], revoked_ksk[i]);
1719				fprintf(stderr, "%*sZSKs: "
1720					"%u active, %u %s, %u revoked\n",
1721					(int) strlen(algbuf) + 13, "",
1722					zsk_algorithms[i],
1723					standby_zsk[i],
1724					keyset_kskonly ? "present" : "stand-by",
1725					revoked_zsk[i]);
1726			}
1727		}
1728	}
1729}
1730