1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
7  *
8  * See the COPYRIGHT file distributed with this work for additional
9  * information regarding copyright ownership.
10  */
11 
12 /*! \file */
13 
14 #include <inttypes.h>
15 #include <stdarg.h>
16 #include <stdbool.h>
17 #include <stdio.h>
18 #include <string.h>
19 
20 #include <isc/base32.h>
21 #include <isc/buffer.h>
22 #include <isc/heap.h>
23 #include <isc/iterated_hash.h>
24 #include <isc/log.h>
25 #include <isc/mem.h>
26 #include <isc/region.h>
27 #include <isc/result.h>
28 #include <isc/types.h>
29 #include <isc/util.h>
30 
31 #include <dns/db.h>
32 #include <dns/dbiterator.h>
33 #include <dns/dnssec.h>
34 #include <dns/fixedname.h>
35 #include <dns/keytable.h>
36 #include <dns/keyvalues.h>
37 #include <dns/log.h>
38 #include <dns/name.h>
39 #include <dns/nsec.h>
40 #include <dns/nsec3.h>
41 #include <dns/rdata.h>
42 #include <dns/rdataset.h>
43 #include <dns/rdatasetiter.h>
44 #include <dns/rdatastruct.h>
45 #include <dns/rdatatype.h>
46 #include <dns/secalg.h>
47 #include <dns/types.h>
48 #include <dns/zone.h>
49 #include <dns/zoneverify.h>
50 
51 #include <dst/dst.h>
52 
53 typedef struct vctx {
54 	isc_mem_t *mctx;
55 	dns_zone_t *zone;
56 	dns_db_t *db;
57 	dns_dbversion_t *ver;
58 	dns_name_t *origin;
59 	dns_keytable_t *secroots;
60 	bool goodksk;
61 	bool goodzsk;
62 	dns_rdataset_t keyset;
63 	dns_rdataset_t keysigs;
64 	dns_rdataset_t soaset;
65 	dns_rdataset_t soasigs;
66 	dns_rdataset_t nsecset;
67 	dns_rdataset_t nsecsigs;
68 	dns_rdataset_t nsec3paramset;
69 	dns_rdataset_t nsec3paramsigs;
70 	unsigned char revoked_ksk[256];
71 	unsigned char revoked_zsk[256];
72 	unsigned char standby_ksk[256];
73 	unsigned char standby_zsk[256];
74 	unsigned char ksk_algorithms[256];
75 	unsigned char zsk_algorithms[256];
76 	unsigned char bad_algorithms[256];
77 	unsigned char act_algorithms[256];
78 	isc_heap_t *expected_chains;
79 	isc_heap_t *found_chains;
80 } vctx_t;
81 
82 struct nsec3_chain_fixed {
83 	uint8_t hash;
84 	uint8_t salt_length;
85 	uint8_t next_length;
86 	uint16_t iterations;
87 	/*
88 	 * The following non-fixed-length data is stored in memory after the
89 	 * fields declared above for each NSEC3 chain element:
90 	 *
91 	 * unsigned char	salt[salt_length];
92 	 * unsigned char	owner[next_length];
93 	 * unsigned char	next[next_length];
94 	 */
95 };
96 
97 /*
98  * Helper function used to calculate length of variable-length
99  * data section in object pointed to by 'chain'.
100  */
101 static inline size_t
chain_length(struct nsec3_chain_fixed * chain)102 chain_length(struct nsec3_chain_fixed *chain) {
103 	return (chain->salt_length + 2 * chain->next_length);
104 }
105 
106 /*%
107  * Log a zone verification error described by 'fmt' and the variable arguments
108  * following it.  Either use dns_zone_logv() or print to stderr, depending on
109  * whether the function was invoked from within named or by a standalone tool,
110  * respectively.
111  */
112 static void
zoneverify_log_error(const vctx_t * vctx,const char * fmt,...)113 zoneverify_log_error(const vctx_t *vctx, const char *fmt, ...) {
114 	va_list ap;
115 
116 	va_start(ap, fmt);
117 	if (vctx->zone != NULL) {
118 		dns_zone_logv(vctx->zone, DNS_LOGCATEGORY_GENERAL,
119 			      ISC_LOG_ERROR, NULL, fmt, ap);
120 	} else {
121 		vfprintf(stderr, fmt, ap);
122 		fprintf(stderr, "\n");
123 	}
124 	va_end(ap);
125 }
126 
127 static bool
is_delegation(const vctx_t * vctx,const dns_name_t * name,dns_dbnode_t * node,uint32_t * ttlp)128 is_delegation(const vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node,
129 	      uint32_t *ttlp) {
130 	dns_rdataset_t nsset;
131 	isc_result_t result;
132 
133 	if (dns_name_equal(name, vctx->origin)) {
134 		return (false);
135 	}
136 
137 	dns_rdataset_init(&nsset);
138 	result = dns_db_findrdataset(vctx->db, node, vctx->ver,
139 				     dns_rdatatype_ns, 0, 0, &nsset, NULL);
140 	if (dns_rdataset_isassociated(&nsset)) {
141 		if (ttlp != NULL) {
142 			*ttlp = nsset.ttl;
143 		}
144 		dns_rdataset_disassociate(&nsset);
145 	}
146 
147 	return ((result == ISC_R_SUCCESS));
148 }
149 
150 /*%
151  * Return true if version 'ver' of database 'db' contains a DNAME RRset at
152  * 'node'; return false otherwise.
153  */
154 static bool
has_dname(const vctx_t * vctx,dns_dbnode_t * node)155 has_dname(const vctx_t *vctx, dns_dbnode_t *node) {
156 	dns_rdataset_t dnameset;
157 	isc_result_t result;
158 
159 	dns_rdataset_init(&dnameset);
160 	result = dns_db_findrdataset(vctx->db, node, vctx->ver,
161 				     dns_rdatatype_dname, 0, 0, &dnameset,
162 				     NULL);
163 	if (dns_rdataset_isassociated(&dnameset)) {
164 		dns_rdataset_disassociate(&dnameset);
165 	}
166 
167 	return ((result == ISC_R_SUCCESS));
168 }
169 
170 static bool
goodsig(const vctx_t * vctx,dns_rdata_t * sigrdata,const dns_name_t * name,dst_key_t ** dstkeys,size_t nkeys,dns_rdataset_t * rdataset)171 goodsig(const vctx_t *vctx, dns_rdata_t *sigrdata, const dns_name_t *name,
172 	dst_key_t **dstkeys, size_t nkeys, dns_rdataset_t *rdataset) {
173 	dns_rdata_rrsig_t sig;
174 	isc_result_t result;
175 
176 	result = dns_rdata_tostruct(sigrdata, &sig, NULL);
177 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
178 
179 	for (size_t key = 0; key < nkeys; key++) {
180 		if (sig.algorithm != dst_key_alg(dstkeys[key]) ||
181 		    sig.keyid != dst_key_id(dstkeys[key]) ||
182 		    !dns_name_equal(&sig.signer, vctx->origin))
183 		{
184 			continue;
185 		}
186 		result = dns_dnssec_verify(name, rdataset, dstkeys[key], false,
187 					   0, vctx->mctx, sigrdata, NULL);
188 		if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) {
189 			return (true);
190 		}
191 	}
192 	return (false);
193 }
194 
195 static bool
nsec_bitmap_equal(dns_rdata_nsec_t * nsec,dns_rdata_t * rdata)196 nsec_bitmap_equal(dns_rdata_nsec_t *nsec, dns_rdata_t *rdata) {
197 	isc_result_t result;
198 	dns_rdata_nsec_t tmpnsec;
199 
200 	result = dns_rdata_tostruct(rdata, &tmpnsec, NULL);
201 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
202 
203 	if (nsec->len != tmpnsec.len ||
204 	    memcmp(nsec->typebits, tmpnsec.typebits, nsec->len) != 0)
205 	{
206 		return (false);
207 	}
208 	return (true);
209 }
210 
211 static isc_result_t
verifynsec(const vctx_t * vctx,const dns_name_t * name,dns_dbnode_t * node,const dns_name_t * nextname,isc_result_t * vresult)212 verifynsec(const vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node,
213 	   const dns_name_t *nextname, isc_result_t *vresult) {
214 	unsigned char buffer[DNS_NSEC_BUFFERSIZE];
215 	char namebuf[DNS_NAME_FORMATSIZE];
216 	char nextbuf[DNS_NAME_FORMATSIZE];
217 	char found[DNS_NAME_FORMATSIZE];
218 	dns_rdataset_t rdataset;
219 	dns_rdata_t rdata = DNS_RDATA_INIT;
220 	dns_rdata_t tmprdata = DNS_RDATA_INIT;
221 	dns_rdata_nsec_t nsec;
222 	isc_result_t result;
223 
224 	dns_rdataset_init(&rdataset);
225 	result = dns_db_findrdataset(vctx->db, node, vctx->ver,
226 				     dns_rdatatype_nsec, 0, 0, &rdataset, NULL);
227 	if (result != ISC_R_SUCCESS) {
228 		dns_name_format(name, namebuf, sizeof(namebuf));
229 		zoneverify_log_error(vctx, "Missing NSEC record for %s",
230 				     namebuf);
231 		*vresult = ISC_R_FAILURE;
232 		result = ISC_R_SUCCESS;
233 		goto done;
234 	}
235 
236 	result = dns_rdataset_first(&rdataset);
237 	if (result != ISC_R_SUCCESS) {
238 		zoneverify_log_error(vctx, "dns_rdataset_first(): %s",
239 				     isc_result_totext(result));
240 		goto done;
241 	}
242 
243 	dns_rdataset_current(&rdataset, &rdata);
244 	result = dns_rdata_tostruct(&rdata, &nsec, NULL);
245 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
246 
247 	/* Check next name is consistent */
248 	if (!dns_name_equal(&nsec.next, nextname)) {
249 		dns_name_format(name, namebuf, sizeof(namebuf));
250 		dns_name_format(nextname, nextbuf, sizeof(nextbuf));
251 		dns_name_format(&nsec.next, found, sizeof(found));
252 		zoneverify_log_error(vctx,
253 				     "Bad NSEC record for %s, next name "
254 				     "mismatch (expected:%s, found:%s)",
255 				     namebuf, nextbuf, found);
256 		*vresult = ISC_R_FAILURE;
257 		goto done;
258 	}
259 
260 	/* Check bit map is consistent */
261 	result = dns_nsec_buildrdata(vctx->db, vctx->ver, node, nextname,
262 				     buffer, &tmprdata);
263 	if (result != ISC_R_SUCCESS) {
264 		zoneverify_log_error(vctx, "dns_nsec_buildrdata(): %s",
265 				     isc_result_totext(result));
266 		goto done;
267 	}
268 	if (!nsec_bitmap_equal(&nsec, &tmprdata)) {
269 		dns_name_format(name, namebuf, sizeof(namebuf));
270 		zoneverify_log_error(vctx,
271 				     "Bad NSEC record for %s, bit map "
272 				     "mismatch",
273 				     namebuf);
274 		*vresult = ISC_R_FAILURE;
275 		goto done;
276 	}
277 
278 	result = dns_rdataset_next(&rdataset);
279 	if (result != ISC_R_NOMORE) {
280 		dns_name_format(name, namebuf, sizeof(namebuf));
281 		zoneverify_log_error(vctx, "Multiple NSEC records for %s",
282 				     namebuf);
283 		*vresult = ISC_R_FAILURE;
284 		goto done;
285 	}
286 
287 	*vresult = ISC_R_SUCCESS;
288 	result = ISC_R_SUCCESS;
289 
290 done:
291 	if (dns_rdataset_isassociated(&rdataset)) {
292 		dns_rdataset_disassociate(&rdataset);
293 	}
294 
295 	return (result);
296 }
297 
298 static isc_result_t
check_no_rrsig(const vctx_t * vctx,const dns_rdataset_t * rdataset,const dns_name_t * name,dns_dbnode_t * node)299 check_no_rrsig(const vctx_t *vctx, const dns_rdataset_t *rdataset,
300 	       const dns_name_t *name, dns_dbnode_t *node) {
301 	char namebuf[DNS_NAME_FORMATSIZE];
302 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
303 	dns_rdataset_t sigrdataset;
304 	dns_rdatasetiter_t *rdsiter = NULL;
305 	isc_result_t result;
306 
307 	dns_rdataset_init(&sigrdataset);
308 	result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, &rdsiter);
309 	if (result != ISC_R_SUCCESS) {
310 		zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s",
311 				     isc_result_totext(result));
312 		return (result);
313 	}
314 	for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS;
315 	     result = dns_rdatasetiter_next(rdsiter))
316 	{
317 		dns_rdatasetiter_current(rdsiter, &sigrdataset);
318 		if (sigrdataset.type == dns_rdatatype_rrsig &&
319 		    sigrdataset.covers == rdataset->type)
320 		{
321 			dns_name_format(name, namebuf, sizeof(namebuf));
322 			dns_rdatatype_format(rdataset->type, typebuf,
323 					     sizeof(typebuf));
324 			zoneverify_log_error(
325 				vctx,
326 				"Warning: Found unexpected signatures "
327 				"for %s/%s",
328 				namebuf, typebuf);
329 			break;
330 		}
331 		dns_rdataset_disassociate(&sigrdataset);
332 	}
333 	if (dns_rdataset_isassociated(&sigrdataset)) {
334 		dns_rdataset_disassociate(&sigrdataset);
335 	}
336 	dns_rdatasetiter_destroy(&rdsiter);
337 
338 	return (ISC_R_SUCCESS);
339 }
340 
341 static bool
chain_compare(void * arg1,void * arg2)342 chain_compare(void *arg1, void *arg2) {
343 	struct nsec3_chain_fixed *e1 = arg1, *e2 = arg2;
344 	/*
345 	 * Do each element in turn to get a stable sort.
346 	 */
347 	if (e1->hash < e2->hash) {
348 		return (true);
349 	}
350 	if (e1->hash > e2->hash) {
351 		return (false);
352 	}
353 	if (e1->iterations < e2->iterations) {
354 		return (true);
355 	}
356 	if (e1->iterations > e2->iterations) {
357 		return (false);
358 	}
359 	if (e1->salt_length < e2->salt_length) {
360 		return (true);
361 	}
362 	if (e1->salt_length > e2->salt_length) {
363 		return (false);
364 	}
365 	if (e1->next_length < e2->next_length) {
366 		return (true);
367 	}
368 	if (e1->next_length > e2->next_length) {
369 		return (false);
370 	}
371 	if (memcmp(e1 + 1, e2 + 1, chain_length(e1)) < 0) {
372 		return (true);
373 	}
374 	return (false);
375 }
376 
377 static bool
chain_equal(const struct nsec3_chain_fixed * e1,const struct nsec3_chain_fixed * e2,size_t data_length)378 chain_equal(const struct nsec3_chain_fixed *e1,
379 	    const struct nsec3_chain_fixed *e2, size_t data_length) {
380 	if (e1->hash != e2->hash) {
381 		return (false);
382 	}
383 	if (e1->iterations != e2->iterations) {
384 		return (false);
385 	}
386 	if (e1->salt_length != e2->salt_length) {
387 		return (false);
388 	}
389 	if (e1->next_length != e2->next_length) {
390 		return (false);
391 	}
392 
393 	return (memcmp(e1 + 1, e2 + 1, data_length) == 0);
394 }
395 
396 static isc_result_t
record_nsec3(const vctx_t * vctx,const unsigned char * rawhash,const dns_rdata_nsec3_t * nsec3,isc_heap_t * chains)397 record_nsec3(const vctx_t *vctx, const unsigned char *rawhash,
398 	     const dns_rdata_nsec3_t *nsec3, isc_heap_t *chains) {
399 	struct nsec3_chain_fixed *element;
400 	size_t len;
401 	unsigned char *cp;
402 	isc_result_t result;
403 
404 	len = sizeof(*element) + nsec3->next_length * 2 + nsec3->salt_length;
405 
406 	element = isc_mem_get(vctx->mctx, len);
407 	memset(element, 0, len);
408 	element->hash = nsec3->hash;
409 	element->salt_length = nsec3->salt_length;
410 	element->next_length = nsec3->next_length;
411 	element->iterations = nsec3->iterations;
412 	cp = (unsigned char *)(element + 1);
413 	memmove(cp, nsec3->salt, nsec3->salt_length);
414 	cp += nsec3->salt_length;
415 	memmove(cp, rawhash, nsec3->next_length);
416 	cp += nsec3->next_length;
417 	memmove(cp, nsec3->next, nsec3->next_length);
418 	result = isc_heap_insert(chains, element);
419 	if (result != ISC_R_SUCCESS) {
420 		zoneverify_log_error(vctx, "isc_heap_insert failed: %s",
421 				     isc_result_totext(result));
422 		isc_mem_put(vctx->mctx, element, len);
423 	}
424 	return (result);
425 }
426 
427 /*
428  * Check whether any NSEC3 within 'rdataset' matches the parameters in
429  * 'nsec3param'.
430  */
431 static isc_result_t
find_nsec3_match(const dns_rdata_nsec3param_t * nsec3param,dns_rdataset_t * rdataset,size_t rhsize,dns_rdata_nsec3_t * nsec3_match)432 find_nsec3_match(const dns_rdata_nsec3param_t *nsec3param,
433 		 dns_rdataset_t *rdataset, size_t rhsize,
434 		 dns_rdata_nsec3_t *nsec3_match) {
435 	isc_result_t result;
436 
437 	/*
438 	 * Find matching NSEC3 record.
439 	 */
440 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
441 	     result = dns_rdataset_next(rdataset))
442 	{
443 		dns_rdata_t rdata = DNS_RDATA_INIT;
444 		dns_rdataset_current(rdataset, &rdata);
445 		result = dns_rdata_tostruct(&rdata, nsec3_match, NULL);
446 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
447 		if (nsec3_match->hash == nsec3param->hash &&
448 		    nsec3_match->next_length == rhsize &&
449 		    nsec3_match->iterations == nsec3param->iterations &&
450 		    nsec3_match->salt_length == nsec3param->salt_length &&
451 		    memcmp(nsec3_match->salt, nsec3param->salt,
452 			   nsec3param->salt_length) == 0)
453 		{
454 			return (ISC_R_SUCCESS);
455 		}
456 	}
457 
458 	return (result);
459 }
460 
461 static isc_result_t
match_nsec3(const vctx_t * vctx,const dns_name_t * name,const dns_rdata_nsec3param_t * nsec3param,dns_rdataset_t * rdataset,const unsigned char types[8192],unsigned int maxtype,const unsigned char * rawhash,size_t rhsize,isc_result_t * vresult)462 match_nsec3(const vctx_t *vctx, const dns_name_t *name,
463 	    const dns_rdata_nsec3param_t *nsec3param, dns_rdataset_t *rdataset,
464 	    const unsigned char types[8192], unsigned int maxtype,
465 	    const unsigned char *rawhash, size_t rhsize,
466 	    isc_result_t *vresult) {
467 	unsigned char cbm[8244];
468 	char namebuf[DNS_NAME_FORMATSIZE];
469 	dns_rdata_nsec3_t nsec3;
470 	isc_result_t result;
471 	unsigned int len;
472 
473 	result = find_nsec3_match(nsec3param, rdataset, rhsize, &nsec3);
474 	if (result != ISC_R_SUCCESS) {
475 		dns_name_format(name, namebuf, sizeof(namebuf));
476 		zoneverify_log_error(vctx, "Missing NSEC3 record for %s",
477 				     namebuf);
478 		*vresult = result;
479 		return (ISC_R_SUCCESS);
480 	}
481 
482 	/*
483 	 * Check the type list.
484 	 */
485 	len = dns_nsec_compressbitmap(cbm, types, maxtype);
486 	if (nsec3.len != len || memcmp(cbm, nsec3.typebits, len) != 0) {
487 		dns_name_format(name, namebuf, sizeof(namebuf));
488 		zoneverify_log_error(vctx,
489 				     "Bad NSEC3 record for %s, bit map "
490 				     "mismatch",
491 				     namebuf);
492 		*vresult = ISC_R_FAILURE;
493 		return (ISC_R_SUCCESS);
494 	}
495 
496 	/*
497 	 * Record chain.
498 	 */
499 	result = record_nsec3(vctx, rawhash, &nsec3, vctx->expected_chains);
500 	if (result != ISC_R_SUCCESS) {
501 		zoneverify_log_error(vctx, "record_nsec3(): %s",
502 				     isc_result_totext(result));
503 		return (result);
504 	}
505 
506 	/*
507 	 * Make sure there is only one NSEC3 record with this set of
508 	 * parameters.
509 	 */
510 	for (result = dns_rdataset_next(rdataset); result == ISC_R_SUCCESS;
511 	     result = dns_rdataset_next(rdataset))
512 	{
513 		dns_rdata_t rdata = DNS_RDATA_INIT;
514 		dns_rdataset_current(rdataset, &rdata);
515 		result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
516 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
517 		if (nsec3.hash == nsec3param->hash &&
518 		    nsec3.iterations == nsec3param->iterations &&
519 		    nsec3.salt_length == nsec3param->salt_length &&
520 		    memcmp(nsec3.salt, nsec3param->salt, nsec3.salt_length) ==
521 			    0)
522 		{
523 			dns_name_format(name, namebuf, sizeof(namebuf));
524 			zoneverify_log_error(vctx,
525 					     "Multiple NSEC3 records with the "
526 					     "same parameter set for %s",
527 					     namebuf);
528 			*vresult = DNS_R_DUPLICATE;
529 			return (ISC_R_SUCCESS);
530 		}
531 	}
532 	if (result != ISC_R_NOMORE) {
533 		return (result);
534 	}
535 
536 	*vresult = ISC_R_SUCCESS;
537 
538 	return (ISC_R_SUCCESS);
539 }
540 
541 static bool
innsec3params(const dns_rdata_nsec3_t * nsec3,dns_rdataset_t * nsec3paramset)542 innsec3params(const dns_rdata_nsec3_t *nsec3, dns_rdataset_t *nsec3paramset) {
543 	dns_rdata_nsec3param_t nsec3param;
544 	isc_result_t result;
545 
546 	for (result = dns_rdataset_first(nsec3paramset);
547 	     result == ISC_R_SUCCESS; result = dns_rdataset_next(nsec3paramset))
548 	{
549 		dns_rdata_t rdata = DNS_RDATA_INIT;
550 
551 		dns_rdataset_current(nsec3paramset, &rdata);
552 		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
553 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
554 		if (nsec3param.flags == 0 && nsec3param.hash == nsec3->hash &&
555 		    nsec3param.iterations == nsec3->iterations &&
556 		    nsec3param.salt_length == nsec3->salt_length &&
557 		    memcmp(nsec3param.salt, nsec3->salt, nsec3->salt_length) ==
558 			    0)
559 		{
560 			return (true);
561 		}
562 	}
563 	return (false);
564 }
565 
566 static isc_result_t
record_found(const vctx_t * vctx,const dns_name_t * name,dns_dbnode_t * node,dns_rdataset_t * nsec3paramset)567 record_found(const vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node,
568 	     dns_rdataset_t *nsec3paramset) {
569 	unsigned char owner[NSEC3_MAX_HASH_LENGTH];
570 	dns_rdata_nsec3_t nsec3;
571 	dns_rdataset_t rdataset;
572 	dns_label_t hashlabel;
573 	isc_buffer_t b;
574 	isc_result_t result;
575 
576 	if (nsec3paramset == NULL || !dns_rdataset_isassociated(nsec3paramset))
577 	{
578 		return (ISC_R_SUCCESS);
579 	}
580 
581 	dns_rdataset_init(&rdataset);
582 	result = dns_db_findrdataset(vctx->db, node, vctx->ver,
583 				     dns_rdatatype_nsec3, 0, 0, &rdataset,
584 				     NULL);
585 	if (result != ISC_R_SUCCESS) {
586 		return (ISC_R_SUCCESS);
587 	}
588 
589 	dns_name_getlabel(name, 0, &hashlabel);
590 	isc_region_consume(&hashlabel, 1);
591 	isc_buffer_init(&b, owner, sizeof(owner));
592 	result = isc_base32hex_decoderegion(&hashlabel, &b);
593 	if (result != ISC_R_SUCCESS) {
594 		result = ISC_R_SUCCESS;
595 		goto cleanup;
596 	}
597 
598 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
599 	     result = dns_rdataset_next(&rdataset))
600 	{
601 		dns_rdata_t rdata = DNS_RDATA_INIT;
602 		dns_rdataset_current(&rdataset, &rdata);
603 		result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
604 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
605 		if (nsec3.next_length != isc_buffer_usedlength(&b)) {
606 			continue;
607 		}
608 		/*
609 		 * We only care about NSEC3 records that match a NSEC3PARAM
610 		 * record.
611 		 */
612 		if (!innsec3params(&nsec3, nsec3paramset)) {
613 			continue;
614 		}
615 
616 		/*
617 		 * Record chain.
618 		 */
619 		result = record_nsec3(vctx, owner, &nsec3, vctx->found_chains);
620 		if (result != ISC_R_SUCCESS) {
621 			zoneverify_log_error(vctx, "record_nsec3(): %s",
622 					     isc_result_totext(result));
623 			goto cleanup;
624 		}
625 	}
626 	result = ISC_R_SUCCESS;
627 
628 cleanup:
629 	dns_rdataset_disassociate(&rdataset);
630 	return (result);
631 }
632 
633 static isc_result_t
isoptout(const vctx_t * vctx,const dns_rdata_nsec3param_t * nsec3param,bool * optout)634 isoptout(const vctx_t *vctx, const dns_rdata_nsec3param_t *nsec3param,
635 	 bool *optout) {
636 	dns_rdataset_t rdataset;
637 	dns_rdata_t rdata = DNS_RDATA_INIT;
638 	dns_rdata_nsec3_t nsec3;
639 	dns_fixedname_t fixed;
640 	dns_name_t *hashname;
641 	isc_result_t result;
642 	dns_dbnode_t *node = NULL;
643 	unsigned char rawhash[NSEC3_MAX_HASH_LENGTH];
644 	size_t rhsize = sizeof(rawhash);
645 
646 	dns_fixedname_init(&fixed);
647 	result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, vctx->origin,
648 				    vctx->origin, nsec3param->hash,
649 				    nsec3param->iterations, nsec3param->salt,
650 				    nsec3param->salt_length);
651 	if (result != ISC_R_SUCCESS) {
652 		zoneverify_log_error(vctx, "dns_nsec3_hashname(): %s",
653 				     isc_result_totext(result));
654 		return (result);
655 	}
656 
657 	dns_rdataset_init(&rdataset);
658 	hashname = dns_fixedname_name(&fixed);
659 	result = dns_db_findnsec3node(vctx->db, hashname, false, &node);
660 	if (result == ISC_R_SUCCESS) {
661 		result = dns_db_findrdataset(vctx->db, node, vctx->ver,
662 					     dns_rdatatype_nsec3, 0, 0,
663 					     &rdataset, NULL);
664 	}
665 	if (result != ISC_R_SUCCESS) {
666 		*optout = false;
667 		result = ISC_R_SUCCESS;
668 		goto done;
669 	}
670 
671 	result = dns_rdataset_first(&rdataset);
672 	if (result != ISC_R_SUCCESS) {
673 		zoneverify_log_error(vctx, "dns_rdataset_first(): %s",
674 				     isc_result_totext(result));
675 		goto done;
676 	}
677 
678 	dns_rdataset_current(&rdataset, &rdata);
679 
680 	result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
681 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
682 	*optout = ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0);
683 
684 done:
685 	if (dns_rdataset_isassociated(&rdataset)) {
686 		dns_rdataset_disassociate(&rdataset);
687 	}
688 	if (node != NULL) {
689 		dns_db_detachnode(vctx->db, &node);
690 	}
691 
692 	return (result);
693 }
694 
695 static isc_result_t
verifynsec3(const vctx_t * vctx,const dns_name_t * name,const dns_rdata_t * rdata,bool delegation,bool empty,const unsigned char types[8192],unsigned int maxtype,isc_result_t * vresult)696 verifynsec3(const vctx_t *vctx, const dns_name_t *name,
697 	    const dns_rdata_t *rdata, bool delegation, bool empty,
698 	    const unsigned char types[8192], unsigned int maxtype,
699 	    isc_result_t *vresult) {
700 	char namebuf[DNS_NAME_FORMATSIZE];
701 	char hashbuf[DNS_NAME_FORMATSIZE];
702 	dns_rdataset_t rdataset;
703 	dns_rdata_nsec3param_t nsec3param;
704 	dns_fixedname_t fixed;
705 	dns_name_t *hashname;
706 	isc_result_t result, tvresult = ISC_R_UNSET;
707 	dns_dbnode_t *node = NULL;
708 	unsigned char rawhash[NSEC3_MAX_HASH_LENGTH];
709 	size_t rhsize = sizeof(rawhash);
710 	bool optout = false;
711 
712 	result = dns_rdata_tostruct(rdata, &nsec3param, NULL);
713 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
714 
715 	if (nsec3param.flags != 0) {
716 		return (ISC_R_SUCCESS);
717 	}
718 
719 	if (!dns_nsec3_supportedhash(nsec3param.hash)) {
720 		return (ISC_R_SUCCESS);
721 	}
722 
723 	if (nsec3param.iterations > DNS_NSEC3_MAXITERATIONS) {
724 		result = DNS_R_NSEC3ITERRANGE;
725 		zoneverify_log_error(vctx, "verifynsec3: %s",
726 				     isc_result_totext(result));
727 		return (result);
728 	}
729 
730 	result = isoptout(vctx, &nsec3param, &optout);
731 	if (result != ISC_R_SUCCESS) {
732 		return (result);
733 	}
734 
735 	dns_fixedname_init(&fixed);
736 	result = dns_nsec3_hashname(
737 		&fixed, rawhash, &rhsize, name, vctx->origin, nsec3param.hash,
738 		nsec3param.iterations, nsec3param.salt, nsec3param.salt_length);
739 	if (result != ISC_R_SUCCESS) {
740 		zoneverify_log_error(vctx, "dns_nsec3_hashname(): %s",
741 				     isc_result_totext(result));
742 		return (result);
743 	}
744 
745 	/*
746 	 * We don't use dns_db_find() here as it works with the chosen
747 	 * nsec3 chain and we may also be called with uncommitted data
748 	 * from dnssec-signzone so the secure status of the zone may not
749 	 * be up to date.
750 	 */
751 	dns_rdataset_init(&rdataset);
752 	hashname = dns_fixedname_name(&fixed);
753 	result = dns_db_findnsec3node(vctx->db, hashname, false, &node);
754 	if (result == ISC_R_SUCCESS) {
755 		result = dns_db_findrdataset(vctx->db, node, vctx->ver,
756 					     dns_rdatatype_nsec3, 0, 0,
757 					     &rdataset, NULL);
758 	}
759 	if (result != ISC_R_SUCCESS &&
760 	    (!delegation || (empty && !optout) ||
761 	     (!empty && dns_nsec_isset(types, dns_rdatatype_ds))))
762 	{
763 		dns_name_format(name, namebuf, sizeof(namebuf));
764 		dns_name_format(hashname, hashbuf, sizeof(hashbuf));
765 		zoneverify_log_error(vctx, "Missing NSEC3 record for %s (%s)",
766 				     namebuf, hashbuf);
767 	} else if (result == ISC_R_NOTFOUND && delegation && (!empty || optout))
768 	{
769 		result = ISC_R_SUCCESS;
770 	} else if (result == ISC_R_SUCCESS) {
771 		result = match_nsec3(vctx, name, &nsec3param, &rdataset, types,
772 				     maxtype, rawhash, rhsize, &tvresult);
773 		if (result != ISC_R_SUCCESS) {
774 			goto done;
775 		}
776 		result = tvresult;
777 	}
778 
779 	*vresult = result;
780 	result = ISC_R_SUCCESS;
781 
782 done:
783 	if (dns_rdataset_isassociated(&rdataset)) {
784 		dns_rdataset_disassociate(&rdataset);
785 	}
786 	if (node != NULL) {
787 		dns_db_detachnode(vctx->db, &node);
788 	}
789 
790 	return (result);
791 }
792 
793 static isc_result_t
verifynsec3s(const vctx_t * vctx,const dns_name_t * name,dns_rdataset_t * nsec3paramset,bool delegation,bool empty,const unsigned char types[8192],unsigned int maxtype,isc_result_t * vresult)794 verifynsec3s(const vctx_t *vctx, const dns_name_t *name,
795 	     dns_rdataset_t *nsec3paramset, bool delegation, bool empty,
796 	     const unsigned char types[8192], unsigned int maxtype,
797 	     isc_result_t *vresult) {
798 	isc_result_t result;
799 
800 	for (result = dns_rdataset_first(nsec3paramset);
801 	     result == ISC_R_SUCCESS; result = dns_rdataset_next(nsec3paramset))
802 	{
803 		dns_rdata_t rdata = DNS_RDATA_INIT;
804 
805 		dns_rdataset_current(nsec3paramset, &rdata);
806 		result = verifynsec3(vctx, name, &rdata, delegation, empty,
807 				     types, maxtype, vresult);
808 		if (result != ISC_R_SUCCESS) {
809 			return (result);
810 		}
811 		if (*vresult != ISC_R_SUCCESS) {
812 			break;
813 		}
814 	}
815 	if (result == ISC_R_NOMORE) {
816 		result = ISC_R_SUCCESS;
817 	}
818 	return (result);
819 }
820 
821 static isc_result_t
verifyset(vctx_t * vctx,dns_rdataset_t * rdataset,const dns_name_t * name,dns_dbnode_t * node,dst_key_t ** dstkeys,size_t nkeys)822 verifyset(vctx_t *vctx, dns_rdataset_t *rdataset, const dns_name_t *name,
823 	  dns_dbnode_t *node, dst_key_t **dstkeys, size_t nkeys) {
824 	unsigned char set_algorithms[256] = { 0 };
825 	char namebuf[DNS_NAME_FORMATSIZE];
826 	char algbuf[DNS_SECALG_FORMATSIZE];
827 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
828 	dns_rdataset_t sigrdataset;
829 	dns_rdatasetiter_t *rdsiter = NULL;
830 	isc_result_t result;
831 
832 	dns_rdataset_init(&sigrdataset);
833 	result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, &rdsiter);
834 	if (result != ISC_R_SUCCESS) {
835 		zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s",
836 				     isc_result_totext(result));
837 		return (result);
838 	}
839 	for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS;
840 	     result = dns_rdatasetiter_next(rdsiter))
841 	{
842 		dns_rdatasetiter_current(rdsiter, &sigrdataset);
843 		if (sigrdataset.type == dns_rdatatype_rrsig &&
844 		    sigrdataset.covers == rdataset->type)
845 		{
846 			break;
847 		}
848 		dns_rdataset_disassociate(&sigrdataset);
849 	}
850 	if (result != ISC_R_SUCCESS) {
851 		dns_name_format(name, namebuf, sizeof(namebuf));
852 		dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf));
853 		zoneverify_log_error(vctx, "No signatures for %s/%s", namebuf,
854 				     typebuf);
855 		for (size_t i = 0; i < ARRAY_SIZE(set_algorithms); i++) {
856 			if (vctx->act_algorithms[i] != 0) {
857 				vctx->bad_algorithms[i] = 1;
858 			}
859 		}
860 		result = ISC_R_SUCCESS;
861 		goto done;
862 	}
863 
864 	for (result = dns_rdataset_first(&sigrdataset); result == ISC_R_SUCCESS;
865 	     result = dns_rdataset_next(&sigrdataset))
866 	{
867 		dns_rdata_t rdata = DNS_RDATA_INIT;
868 		dns_rdata_rrsig_t sig;
869 
870 		dns_rdataset_current(&sigrdataset, &rdata);
871 		result = dns_rdata_tostruct(&rdata, &sig, NULL);
872 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
873 		if (rdataset->ttl != sig.originalttl) {
874 			dns_name_format(name, namebuf, sizeof(namebuf));
875 			dns_rdatatype_format(rdataset->type, typebuf,
876 					     sizeof(typebuf));
877 			zoneverify_log_error(vctx,
878 					     "TTL mismatch for "
879 					     "%s %s keytag %u",
880 					     namebuf, typebuf, sig.keyid);
881 			continue;
882 		}
883 		if ((set_algorithms[sig.algorithm] != 0) ||
884 		    (vctx->act_algorithms[sig.algorithm] == 0))
885 		{
886 			continue;
887 		}
888 		if (goodsig(vctx, &rdata, name, dstkeys, nkeys, rdataset)) {
889 			dns_rdataset_settrust(rdataset, dns_trust_secure);
890 			dns_rdataset_settrust(&sigrdataset, dns_trust_secure);
891 			set_algorithms[sig.algorithm] = 1;
892 		}
893 	}
894 	result = ISC_R_SUCCESS;
895 
896 	if (memcmp(set_algorithms, vctx->act_algorithms,
897 		   sizeof(set_algorithms)) != 0) {
898 		dns_name_format(name, namebuf, sizeof(namebuf));
899 		dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf));
900 		for (size_t i = 0; i < ARRAY_SIZE(set_algorithms); i++) {
901 			if ((vctx->act_algorithms[i] != 0) &&
902 			    (set_algorithms[i] == 0)) {
903 				dns_secalg_format(i, algbuf, sizeof(algbuf));
904 				zoneverify_log_error(vctx,
905 						     "No correct %s signature "
906 						     "for %s %s",
907 						     algbuf, namebuf, typebuf);
908 				vctx->bad_algorithms[i] = 1;
909 			}
910 		}
911 	}
912 
913 done:
914 	if (dns_rdataset_isassociated(&sigrdataset)) {
915 		dns_rdataset_disassociate(&sigrdataset);
916 	}
917 	dns_rdatasetiter_destroy(&rdsiter);
918 
919 	return (result);
920 }
921 
922 static isc_result_t
verifynode(vctx_t * vctx,const dns_name_t * name,dns_dbnode_t * node,bool delegation,dst_key_t ** dstkeys,size_t nkeys,dns_rdataset_t * nsecset,dns_rdataset_t * nsec3paramset,const dns_name_t * nextname,isc_result_t * vresult)923 verifynode(vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node,
924 	   bool delegation, dst_key_t **dstkeys, size_t nkeys,
925 	   dns_rdataset_t *nsecset, dns_rdataset_t *nsec3paramset,
926 	   const dns_name_t *nextname, isc_result_t *vresult) {
927 	unsigned char types[8192] = { 0 };
928 	unsigned int maxtype = 0;
929 	dns_rdataset_t rdataset;
930 	dns_rdatasetiter_t *rdsiter = NULL;
931 	isc_result_t result, tvresult = ISC_R_UNSET;
932 
933 	REQUIRE(vresult != NULL || (nsecset == NULL && nsec3paramset == NULL));
934 
935 	result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, &rdsiter);
936 	if (result != ISC_R_SUCCESS) {
937 		zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s",
938 				     isc_result_totext(result));
939 		return (result);
940 	}
941 
942 	result = dns_rdatasetiter_first(rdsiter);
943 	dns_rdataset_init(&rdataset);
944 	while (result == ISC_R_SUCCESS) {
945 		dns_rdatasetiter_current(rdsiter, &rdataset);
946 		/*
947 		 * If we are not at a delegation then everything should be
948 		 * signed.  If we are at a delegation then only the DS set
949 		 * is signed.  The NS set is not signed at a delegation but
950 		 * its existence is recorded in the bit map.  Anything else
951 		 * other than NSEC and DS is not signed at a delegation.
952 		 */
953 		if (rdataset.type != dns_rdatatype_rrsig &&
954 		    rdataset.type != dns_rdatatype_dnskey &&
955 		    (!delegation || rdataset.type == dns_rdatatype_ds ||
956 		     rdataset.type == dns_rdatatype_nsec))
957 		{
958 			result = verifyset(vctx, &rdataset, name, node, dstkeys,
959 					   nkeys);
960 			if (result != ISC_R_SUCCESS) {
961 				dns_rdataset_disassociate(&rdataset);
962 				dns_rdatasetiter_destroy(&rdsiter);
963 				return (result);
964 			}
965 			dns_nsec_setbit(types, rdataset.type, 1);
966 			if (rdataset.type > maxtype) {
967 				maxtype = rdataset.type;
968 			}
969 		} else if (rdataset.type != dns_rdatatype_rrsig &&
970 			   rdataset.type != dns_rdatatype_dnskey)
971 		{
972 			if (rdataset.type == dns_rdatatype_ns) {
973 				dns_nsec_setbit(types, rdataset.type, 1);
974 			}
975 			result = check_no_rrsig(vctx, &rdataset, name, node);
976 			if (result != ISC_R_SUCCESS) {
977 				dns_rdataset_disassociate(&rdataset);
978 				dns_rdatasetiter_destroy(&rdsiter);
979 				return (result);
980 			}
981 		} else {
982 			dns_nsec_setbit(types, rdataset.type, 1);
983 		}
984 		dns_rdataset_disassociate(&rdataset);
985 		result = dns_rdatasetiter_next(rdsiter);
986 	}
987 	dns_rdatasetiter_destroy(&rdsiter);
988 	if (result != ISC_R_NOMORE) {
989 		zoneverify_log_error(vctx, "rdataset iteration failed: %s",
990 				     isc_result_totext(result));
991 		return (result);
992 	}
993 
994 	if (vresult == NULL) {
995 		return (ISC_R_SUCCESS);
996 	}
997 
998 	*vresult = ISC_R_SUCCESS;
999 
1000 	if (nsecset != NULL && dns_rdataset_isassociated(nsecset)) {
1001 		result = verifynsec(vctx, name, node, nextname, &tvresult);
1002 		if (result != ISC_R_SUCCESS) {
1003 			return (result);
1004 		}
1005 		*vresult = tvresult;
1006 	}
1007 
1008 	if (nsec3paramset != NULL && dns_rdataset_isassociated(nsec3paramset)) {
1009 		result = verifynsec3s(vctx, name, nsec3paramset, delegation,
1010 				      false, types, maxtype, &tvresult);
1011 		if (result != ISC_R_SUCCESS) {
1012 			return (result);
1013 		}
1014 		if (*vresult == ISC_R_SUCCESS) {
1015 			*vresult = tvresult;
1016 		}
1017 	}
1018 
1019 	return (ISC_R_SUCCESS);
1020 }
1021 
1022 static isc_result_t
is_empty(const vctx_t * vctx,dns_dbnode_t * node,bool * empty)1023 is_empty(const vctx_t *vctx, dns_dbnode_t *node, bool *empty) {
1024 	dns_rdatasetiter_t *rdsiter = NULL;
1025 	isc_result_t result;
1026 
1027 	result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, &rdsiter);
1028 	if (result != ISC_R_SUCCESS) {
1029 		zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s",
1030 				     isc_result_totext(result));
1031 		return (result);
1032 	}
1033 	result = dns_rdatasetiter_first(rdsiter);
1034 	dns_rdatasetiter_destroy(&rdsiter);
1035 
1036 	*empty = (result == ISC_R_NOMORE);
1037 
1038 	return (ISC_R_SUCCESS);
1039 }
1040 
1041 static isc_result_t
check_no_nsec(const vctx_t * vctx,const dns_name_t * name,dns_dbnode_t * node)1042 check_no_nsec(const vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node) {
1043 	bool nsec_exists = false;
1044 	dns_rdataset_t rdataset;
1045 	isc_result_t result;
1046 
1047 	dns_rdataset_init(&rdataset);
1048 	result = dns_db_findrdataset(vctx->db, node, vctx->ver,
1049 				     dns_rdatatype_nsec, 0, 0, &rdataset, NULL);
1050 	if (result != ISC_R_NOTFOUND) {
1051 		char namebuf[DNS_NAME_FORMATSIZE];
1052 		dns_name_format(name, namebuf, sizeof(namebuf));
1053 		zoneverify_log_error(vctx, "unexpected NSEC RRset at %s",
1054 				     namebuf);
1055 		nsec_exists = true;
1056 	}
1057 
1058 	if (dns_rdataset_isassociated(&rdataset)) {
1059 		dns_rdataset_disassociate(&rdataset);
1060 	}
1061 
1062 	return (nsec_exists ? ISC_R_FAILURE : ISC_R_SUCCESS);
1063 }
1064 
1065 static void
free_element(isc_mem_t * mctx,struct nsec3_chain_fixed * e)1066 free_element(isc_mem_t *mctx, struct nsec3_chain_fixed *e) {
1067 	size_t len;
1068 
1069 	len = sizeof(*e) + e->salt_length + 2 * e->next_length;
1070 	isc_mem_put(mctx, e, len);
1071 }
1072 
1073 static void
free_element_heap(void * element,void * uap)1074 free_element_heap(void *element, void *uap) {
1075 	struct nsec3_chain_fixed *e = (struct nsec3_chain_fixed *)element;
1076 	isc_mem_t *mctx = (isc_mem_t *)uap;
1077 
1078 	free_element(mctx, e);
1079 }
1080 
1081 static bool
_checknext(const vctx_t * vctx,const struct nsec3_chain_fixed * first,const struct nsec3_chain_fixed * e)1082 _checknext(const vctx_t *vctx, const struct nsec3_chain_fixed *first,
1083 	   const struct nsec3_chain_fixed *e) {
1084 	char buf[512];
1085 	const unsigned char *d1 = (const unsigned char *)(first + 1);
1086 	const unsigned char *d2 = (const unsigned char *)(e + 1);
1087 	isc_buffer_t b;
1088 	isc_region_t sr;
1089 
1090 	d1 += first->salt_length + first->next_length;
1091 	d2 += e->salt_length;
1092 
1093 	if (memcmp(d1, d2, first->next_length) == 0) {
1094 		return (true);
1095 	}
1096 
1097 	DE_CONST(d1 - first->next_length, sr.base);
1098 	sr.length = first->next_length;
1099 	isc_buffer_init(&b, buf, sizeof(buf));
1100 	isc_base32hex_totext(&sr, 1, "", &b);
1101 	zoneverify_log_error(vctx, "Break in NSEC3 chain at: %.*s",
1102 			     (int)isc_buffer_usedlength(&b), buf);
1103 
1104 	DE_CONST(d1, sr.base);
1105 	sr.length = first->next_length;
1106 	isc_buffer_init(&b, buf, sizeof(buf));
1107 	isc_base32hex_totext(&sr, 1, "", &b);
1108 	zoneverify_log_error(vctx, "Expected: %.*s",
1109 			     (int)isc_buffer_usedlength(&b), buf);
1110 
1111 	DE_CONST(d2, sr.base);
1112 	sr.length = first->next_length;
1113 	isc_buffer_init(&b, buf, sizeof(buf));
1114 	isc_base32hex_totext(&sr, 1, "", &b);
1115 	zoneverify_log_error(vctx, "Found: %.*s",
1116 			     (int)isc_buffer_usedlength(&b), buf);
1117 
1118 	return (false);
1119 }
1120 
1121 static inline bool
checknext(isc_mem_t * mctx,const vctx_t * vctx,const struct nsec3_chain_fixed * first,struct nsec3_chain_fixed * prev,const struct nsec3_chain_fixed * cur)1122 checknext(isc_mem_t *mctx, const vctx_t *vctx,
1123 	  const struct nsec3_chain_fixed *first, struct nsec3_chain_fixed *prev,
1124 	  const struct nsec3_chain_fixed *cur) {
1125 	bool result = _checknext(vctx, prev, cur);
1126 
1127 	if (prev != first) {
1128 		free_element(mctx, prev);
1129 	}
1130 
1131 	return (result);
1132 }
1133 
1134 static inline bool
checklast(isc_mem_t * mctx,const vctx_t * vctx,struct nsec3_chain_fixed * first,struct nsec3_chain_fixed * prev)1135 checklast(isc_mem_t *mctx, const vctx_t *vctx, struct nsec3_chain_fixed *first,
1136 	  struct nsec3_chain_fixed *prev) {
1137 	bool result = _checknext(vctx, prev, first);
1138 	if (prev != first) {
1139 		free_element(mctx, prev);
1140 	}
1141 	free_element(mctx, first);
1142 
1143 	return (result);
1144 }
1145 
1146 static isc_result_t
verify_nsec3_chains(const vctx_t * vctx,isc_mem_t * mctx)1147 verify_nsec3_chains(const vctx_t *vctx, isc_mem_t *mctx) {
1148 	isc_result_t result = ISC_R_SUCCESS;
1149 	struct nsec3_chain_fixed *e, *f = NULL;
1150 	struct nsec3_chain_fixed *first = NULL, *prev = NULL;
1151 
1152 	while ((e = isc_heap_element(vctx->expected_chains, 1)) != NULL) {
1153 		isc_heap_delete(vctx->expected_chains, 1);
1154 		if (f == NULL) {
1155 			f = isc_heap_element(vctx->found_chains, 1);
1156 		}
1157 		if (f != NULL) {
1158 			isc_heap_delete(vctx->found_chains, 1);
1159 
1160 			/*
1161 			 * Check that they match.
1162 			 */
1163 			if (chain_equal(e, f, chain_length(e))) {
1164 				free_element(mctx, f);
1165 				f = NULL;
1166 			} else {
1167 				if (result == ISC_R_SUCCESS) {
1168 					zoneverify_log_error(vctx, "Expected "
1169 								   "and found "
1170 								   "NSEC3 "
1171 								   "chains not "
1172 								   "equal");
1173 				}
1174 				result = ISC_R_FAILURE;
1175 				/*
1176 				 * Attempt to resync found_chain.
1177 				 */
1178 				while (f != NULL && !chain_compare(e, f)) {
1179 					free_element(mctx, f);
1180 					f = isc_heap_element(vctx->found_chains,
1181 							     1);
1182 					if (f != NULL) {
1183 						isc_heap_delete(
1184 							vctx->found_chains, 1);
1185 					}
1186 					if (f != NULL &&
1187 					    chain_equal(e, f, chain_length(e)))
1188 					{
1189 						free_element(mctx, f);
1190 						f = NULL;
1191 						break;
1192 					}
1193 				}
1194 			}
1195 		} else if (result == ISC_R_SUCCESS) {
1196 			zoneverify_log_error(vctx, "Expected and found NSEC3 "
1197 						   "chains "
1198 						   "not equal");
1199 			result = ISC_R_FAILURE;
1200 		}
1201 
1202 		if (first == NULL) {
1203 			prev = first = e;
1204 		} else if (!chain_equal(first, e, first->salt_length)) {
1205 			if (!checklast(mctx, vctx, first, prev)) {
1206 				result = ISC_R_FAILURE;
1207 			}
1208 
1209 			prev = first = e;
1210 		} else {
1211 			if (!checknext(mctx, vctx, first, prev, e)) {
1212 				result = ISC_R_FAILURE;
1213 			}
1214 
1215 			prev = e;
1216 		}
1217 	}
1218 	if (prev != NULL) {
1219 		if (!checklast(mctx, vctx, first, prev)) {
1220 			result = ISC_R_FAILURE;
1221 		}
1222 	}
1223 	do {
1224 		if (f != NULL) {
1225 			if (result == ISC_R_SUCCESS) {
1226 				zoneverify_log_error(vctx, "Expected and found "
1227 							   "NSEC3 chains not "
1228 							   "equal");
1229 				result = ISC_R_FAILURE;
1230 			}
1231 			free_element(mctx, f);
1232 		}
1233 		f = isc_heap_element(vctx->found_chains, 1);
1234 		if (f != NULL) {
1235 			isc_heap_delete(vctx->found_chains, 1);
1236 		}
1237 	} while (f != NULL);
1238 
1239 	return (result);
1240 }
1241 
1242 static isc_result_t
verifyemptynodes(const vctx_t * vctx,const dns_name_t * name,const dns_name_t * prevname,bool isdelegation,dns_rdataset_t * nsec3paramset,isc_result_t * vresult)1243 verifyemptynodes(const vctx_t *vctx, const dns_name_t *name,
1244 		 const dns_name_t *prevname, bool isdelegation,
1245 		 dns_rdataset_t *nsec3paramset, isc_result_t *vresult) {
1246 	dns_namereln_t reln;
1247 	int order;
1248 	unsigned int labels, nlabels, i;
1249 	dns_name_t suffix;
1250 	isc_result_t result, tvresult = ISC_R_UNSET;
1251 
1252 	*vresult = ISC_R_SUCCESS;
1253 
1254 	reln = dns_name_fullcompare(prevname, name, &order, &labels);
1255 	if (order >= 0) {
1256 		return (ISC_R_SUCCESS);
1257 	}
1258 
1259 	nlabels = dns_name_countlabels(name);
1260 
1261 	if (reln == dns_namereln_commonancestor ||
1262 	    reln == dns_namereln_contains) {
1263 		dns_name_init(&suffix, NULL);
1264 		for (i = labels + 1; i < nlabels; i++) {
1265 			dns_name_getlabelsequence(name, nlabels - i, i,
1266 						  &suffix);
1267 			if (nsec3paramset != NULL &&
1268 			    dns_rdataset_isassociated(nsec3paramset)) {
1269 				result = verifynsec3s(
1270 					vctx, &suffix, nsec3paramset,
1271 					isdelegation, true, NULL, 0, &tvresult);
1272 				if (result != ISC_R_SUCCESS) {
1273 					return (result);
1274 				}
1275 				if (*vresult == ISC_R_SUCCESS) {
1276 					*vresult = tvresult;
1277 				}
1278 			}
1279 		}
1280 	}
1281 
1282 	return (ISC_R_SUCCESS);
1283 }
1284 
1285 static isc_result_t
vctx_init(vctx_t * vctx,isc_mem_t * mctx,dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_name_t * origin,dns_keytable_t * secroots)1286 vctx_init(vctx_t *vctx, isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db,
1287 	  dns_dbversion_t *ver, dns_name_t *origin, dns_keytable_t *secroots) {
1288 	isc_result_t result;
1289 
1290 	memset(vctx, 0, sizeof(*vctx));
1291 
1292 	vctx->mctx = mctx;
1293 	vctx->zone = zone;
1294 	vctx->db = db;
1295 	vctx->ver = ver;
1296 	vctx->origin = origin;
1297 	vctx->secroots = secroots;
1298 	vctx->goodksk = false;
1299 	vctx->goodzsk = false;
1300 
1301 	dns_rdataset_init(&vctx->keyset);
1302 	dns_rdataset_init(&vctx->keysigs);
1303 	dns_rdataset_init(&vctx->soaset);
1304 	dns_rdataset_init(&vctx->soasigs);
1305 	dns_rdataset_init(&vctx->nsecset);
1306 	dns_rdataset_init(&vctx->nsecsigs);
1307 	dns_rdataset_init(&vctx->nsec3paramset);
1308 	dns_rdataset_init(&vctx->nsec3paramsigs);
1309 
1310 	vctx->expected_chains = NULL;
1311 	result = isc_heap_create(mctx, chain_compare, NULL, 1024,
1312 				 &vctx->expected_chains);
1313 	if (result != ISC_R_SUCCESS) {
1314 		return (result);
1315 	}
1316 
1317 	vctx->found_chains = NULL;
1318 	result = isc_heap_create(mctx, chain_compare, NULL, 1024,
1319 				 &vctx->found_chains);
1320 	if (result != ISC_R_SUCCESS) {
1321 		isc_heap_destroy(&vctx->expected_chains);
1322 		return (result);
1323 	}
1324 
1325 	return (result);
1326 }
1327 
1328 static void
vctx_destroy(vctx_t * vctx)1329 vctx_destroy(vctx_t *vctx) {
1330 	if (dns_rdataset_isassociated(&vctx->keyset)) {
1331 		dns_rdataset_disassociate(&vctx->keyset);
1332 	}
1333 	if (dns_rdataset_isassociated(&vctx->keysigs)) {
1334 		dns_rdataset_disassociate(&vctx->keysigs);
1335 	}
1336 	if (dns_rdataset_isassociated(&vctx->soaset)) {
1337 		dns_rdataset_disassociate(&vctx->soaset);
1338 	}
1339 	if (dns_rdataset_isassociated(&vctx->soasigs)) {
1340 		dns_rdataset_disassociate(&vctx->soasigs);
1341 	}
1342 	if (dns_rdataset_isassociated(&vctx->nsecset)) {
1343 		dns_rdataset_disassociate(&vctx->nsecset);
1344 	}
1345 	if (dns_rdataset_isassociated(&vctx->nsecsigs)) {
1346 		dns_rdataset_disassociate(&vctx->nsecsigs);
1347 	}
1348 	if (dns_rdataset_isassociated(&vctx->nsec3paramset)) {
1349 		dns_rdataset_disassociate(&vctx->nsec3paramset);
1350 	}
1351 	if (dns_rdataset_isassociated(&vctx->nsec3paramsigs)) {
1352 		dns_rdataset_disassociate(&vctx->nsec3paramsigs);
1353 	}
1354 	isc_heap_foreach(vctx->expected_chains, free_element_heap, vctx->mctx);
1355 	isc_heap_destroy(&vctx->expected_chains);
1356 	isc_heap_foreach(vctx->found_chains, free_element_heap, vctx->mctx);
1357 	isc_heap_destroy(&vctx->found_chains);
1358 }
1359 
1360 static isc_result_t
check_apex_rrsets(vctx_t * vctx)1361 check_apex_rrsets(vctx_t *vctx) {
1362 	dns_dbnode_t *node = NULL;
1363 	isc_result_t result;
1364 
1365 	result = dns_db_findnode(vctx->db, vctx->origin, false, &node);
1366 	if (result != ISC_R_SUCCESS) {
1367 		zoneverify_log_error(vctx,
1368 				     "failed to find the zone's origin: %s",
1369 				     isc_result_totext(result));
1370 		return (result);
1371 	}
1372 
1373 	result = dns_db_findrdataset(vctx->db, node, vctx->ver,
1374 				     dns_rdatatype_dnskey, 0, 0, &vctx->keyset,
1375 				     &vctx->keysigs);
1376 	if (result != ISC_R_SUCCESS) {
1377 		zoneverify_log_error(vctx, "Zone contains no DNSSEC keys");
1378 		goto done;
1379 	}
1380 
1381 	result = dns_db_findrdataset(vctx->db, node, vctx->ver,
1382 				     dns_rdatatype_soa, 0, 0, &vctx->soaset,
1383 				     &vctx->soasigs);
1384 	if (result != ISC_R_SUCCESS) {
1385 		zoneverify_log_error(vctx, "Zone contains no SOA record");
1386 		goto done;
1387 	}
1388 
1389 	result = dns_db_findrdataset(vctx->db, node, vctx->ver,
1390 				     dns_rdatatype_nsec, 0, 0, &vctx->nsecset,
1391 				     &vctx->nsecsigs);
1392 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
1393 		zoneverify_log_error(vctx, "NSEC lookup failed");
1394 		goto done;
1395 	}
1396 
1397 	result = dns_db_findrdataset(
1398 		vctx->db, node, vctx->ver, dns_rdatatype_nsec3param, 0, 0,
1399 		&vctx->nsec3paramset, &vctx->nsec3paramsigs);
1400 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
1401 		zoneverify_log_error(vctx, "NSEC3PARAM lookup failed");
1402 		goto done;
1403 	}
1404 
1405 	if (!dns_rdataset_isassociated(&vctx->keysigs)) {
1406 		zoneverify_log_error(vctx, "DNSKEY is not signed "
1407 					   "(keys offline or inactive?)");
1408 		result = ISC_R_FAILURE;
1409 		goto done;
1410 	}
1411 
1412 	if (!dns_rdataset_isassociated(&vctx->soasigs)) {
1413 		zoneverify_log_error(vctx, "SOA is not signed "
1414 					   "(keys offline or inactive?)");
1415 		result = ISC_R_FAILURE;
1416 		goto done;
1417 	}
1418 
1419 	if (dns_rdataset_isassociated(&vctx->nsecset) &&
1420 	    !dns_rdataset_isassociated(&vctx->nsecsigs))
1421 	{
1422 		zoneverify_log_error(vctx, "NSEC is not signed "
1423 					   "(keys offline or inactive?)");
1424 		result = ISC_R_FAILURE;
1425 		goto done;
1426 	}
1427 
1428 	if (dns_rdataset_isassociated(&vctx->nsec3paramset) &&
1429 	    !dns_rdataset_isassociated(&vctx->nsec3paramsigs))
1430 	{
1431 		zoneverify_log_error(vctx, "NSEC3PARAM is not signed "
1432 					   "(keys offline or inactive?)");
1433 		result = ISC_R_FAILURE;
1434 		goto done;
1435 	}
1436 
1437 	if (!dns_rdataset_isassociated(&vctx->nsecset) &&
1438 	    !dns_rdataset_isassociated(&vctx->nsec3paramset))
1439 	{
1440 		zoneverify_log_error(vctx, "No valid NSEC/NSEC3 chain for "
1441 					   "testing");
1442 		result = ISC_R_FAILURE;
1443 		goto done;
1444 	}
1445 
1446 	result = ISC_R_SUCCESS;
1447 
1448 done:
1449 	dns_db_detachnode(vctx->db, &node);
1450 
1451 	return (result);
1452 }
1453 
1454 /*%
1455  * Update 'vctx' tables tracking active and standby key algorithms used in the
1456  * verified zone based on the signatures made using 'dnskey' (prepared from
1457  * 'rdata') found at zone apex.  Set 'vctx->goodksk' or 'vctx->goodzsk' to true
1458  * if 'dnskey' correctly signs the DNSKEY RRset at zone apex and either
1459  * 'vctx->secroots' is NULL or 'dnskey' is present in 'vctx->secroots'.
1460  *
1461  * The variables to update are chosen based on 'is_ksk', which is true when
1462  * 'dnskey' is a KSK and false otherwise.
1463  */
1464 static void
check_dnskey_sigs(vctx_t * vctx,const dns_rdata_dnskey_t * dnskey,dns_rdata_t * keyrdata,bool is_ksk)1465 check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey,
1466 		  dns_rdata_t *keyrdata, bool is_ksk) {
1467 	unsigned char *active_keys = NULL, *standby_keys = NULL;
1468 	dns_keynode_t *keynode = NULL;
1469 	bool *goodkey = NULL;
1470 	dst_key_t *key = NULL;
1471 	isc_result_t result;
1472 	dns_rdataset_t dsset;
1473 
1474 	active_keys = (is_ksk ? vctx->ksk_algorithms : vctx->zsk_algorithms);
1475 	standby_keys = (is_ksk ? vctx->standby_ksk : vctx->standby_zsk);
1476 	goodkey = (is_ksk ? &vctx->goodksk : &vctx->goodzsk);
1477 
1478 	/*
1479 	 * First, does this key sign the DNSKEY rrset?
1480 	 */
1481 	if (!dns_dnssec_selfsigns(keyrdata, vctx->origin, &vctx->keyset,
1482 				  &vctx->keysigs, false, vctx->mctx))
1483 	{
1484 		if (!is_ksk &&
1485 		    dns_dnssec_signs(keyrdata, vctx->origin, &vctx->soaset,
1486 				     &vctx->soasigs, false, vctx->mctx))
1487 		{
1488 			if (active_keys[dnskey->algorithm] != DNS_KEYALG_MAX) {
1489 				active_keys[dnskey->algorithm]++;
1490 			}
1491 		} else {
1492 			if (standby_keys[dnskey->algorithm] != DNS_KEYALG_MAX) {
1493 				standby_keys[dnskey->algorithm]++;
1494 			}
1495 		}
1496 		return;
1497 	}
1498 
1499 	if (active_keys[dnskey->algorithm] != DNS_KEYALG_MAX) {
1500 		active_keys[dnskey->algorithm]++;
1501 	}
1502 
1503 	/*
1504 	 * If a trust anchor table was not supplied, a correctly self-signed
1505 	 * DNSKEY RRset is good enough.
1506 	 */
1507 	if (vctx->secroots == NULL) {
1508 		*goodkey = true;
1509 		return;
1510 	}
1511 
1512 	/*
1513 	 * Convert the supplied key rdata to dst_key_t. (If this
1514 	 * fails we can't go further.)
1515 	 */
1516 	result = dns_dnssec_keyfromrdata(vctx->origin, keyrdata, vctx->mctx,
1517 					 &key);
1518 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
1519 
1520 	/*
1521 	 * Look up the supplied key in the trust anchor table.
1522 	 * If we don't find an exact match, or if the keynode data
1523 	 * is NULL, then we have neither a DNSKEY nor a DS format
1524 	 * trust anchor, and can give up.
1525 	 */
1526 	result = dns_keytable_find(vctx->secroots, vctx->origin, &keynode);
1527 	if (result != ISC_R_SUCCESS) {
1528 		/* No such trust anchor */
1529 		goto cleanup;
1530 	}
1531 
1532 	/*
1533 	 * If the keynode has any DS format trust anchors, that means
1534 	 * it doesn't have any DNSKEY ones. So, we can check for a DS
1535 	 * match and then stop.
1536 	 */
1537 	dns_rdataset_init(&dsset);
1538 	if (dns_keynode_dsset(keynode, &dsset)) {
1539 		for (result = dns_rdataset_first(&dsset);
1540 		     result == ISC_R_SUCCESS;
1541 		     result = dns_rdataset_next(&dsset))
1542 		{
1543 			dns_rdata_t dsrdata = DNS_RDATA_INIT;
1544 			dns_rdata_t newdsrdata = DNS_RDATA_INIT;
1545 			unsigned char buf[DNS_DS_BUFFERSIZE];
1546 			dns_rdata_ds_t ds;
1547 
1548 			dns_rdata_reset(&dsrdata);
1549 			dns_rdataset_current(&dsset, &dsrdata);
1550 			result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
1551 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
1552 
1553 			if (ds.key_tag != dst_key_id(key) ||
1554 			    ds.algorithm != dst_key_alg(key)) {
1555 				continue;
1556 			}
1557 
1558 			result = dns_ds_buildrdata(vctx->origin, keyrdata,
1559 						   ds.digest_type, buf,
1560 						   &newdsrdata);
1561 			if (result != ISC_R_SUCCESS) {
1562 				continue;
1563 			}
1564 
1565 			if (dns_rdata_compare(&dsrdata, &newdsrdata) == 0) {
1566 				dns_rdataset_settrust(&vctx->keyset,
1567 						      dns_trust_secure);
1568 				dns_rdataset_settrust(&vctx->keysigs,
1569 						      dns_trust_secure);
1570 				*goodkey = true;
1571 				break;
1572 			}
1573 		}
1574 		dns_rdataset_disassociate(&dsset);
1575 
1576 		goto cleanup;
1577 	}
1578 
1579 cleanup:
1580 	if (keynode != NULL) {
1581 		dns_keytable_detachkeynode(vctx->secroots, &keynode);
1582 	}
1583 	if (key != NULL) {
1584 		dst_key_free(&key);
1585 	}
1586 }
1587 
1588 /*%
1589  * Check that the DNSKEY RR has at least one self signing KSK and one ZSK per
1590  * algorithm in it (or, if -x was used, one self-signing KSK).
1591  */
1592 static isc_result_t
check_dnskey(vctx_t * vctx)1593 check_dnskey(vctx_t *vctx) {
1594 	dns_rdata_t rdata = DNS_RDATA_INIT;
1595 	dns_rdata_dnskey_t dnskey;
1596 	isc_result_t result;
1597 	bool is_ksk;
1598 
1599 	for (result = dns_rdataset_first(&vctx->keyset);
1600 	     result == ISC_R_SUCCESS; result = dns_rdataset_next(&vctx->keyset))
1601 	{
1602 		dns_rdataset_current(&vctx->keyset, &rdata);
1603 		result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
1604 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
1605 		is_ksk = ((dnskey.flags & DNS_KEYFLAG_KSK) != 0);
1606 
1607 		if ((dnskey.flags & DNS_KEYOWNER_ZONE) != 0 &&
1608 		    (dnskey.flags & DNS_KEYFLAG_REVOKE) != 0)
1609 		{
1610 			if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1611 			    !dns_dnssec_selfsigns(&rdata, vctx->origin,
1612 						  &vctx->keyset, &vctx->keysigs,
1613 						  false, vctx->mctx))
1614 			{
1615 				char namebuf[DNS_NAME_FORMATSIZE];
1616 				char buffer[1024];
1617 				isc_buffer_t buf;
1618 
1619 				dns_name_format(vctx->origin, namebuf,
1620 						sizeof(namebuf));
1621 				isc_buffer_init(&buf, buffer, sizeof(buffer));
1622 				result = dns_rdata_totext(&rdata, NULL, &buf);
1623 				if (result != ISC_R_SUCCESS) {
1624 					zoneverify_log_error(
1625 						vctx, "dns_rdata_totext: %s",
1626 						isc_result_totext(result));
1627 					return (ISC_R_FAILURE);
1628 				}
1629 				zoneverify_log_error(
1630 					vctx,
1631 					"revoked KSK is not self signed:\n"
1632 					"%s DNSKEY %.*s",
1633 					namebuf,
1634 					(int)isc_buffer_usedlength(&buf),
1635 					buffer);
1636 				return (ISC_R_FAILURE);
1637 			}
1638 			if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1639 			    vctx->revoked_ksk[dnskey.algorithm] !=
1640 				    DNS_KEYALG_MAX)
1641 			{
1642 				vctx->revoked_ksk[dnskey.algorithm]++;
1643 			} else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 &&
1644 				   vctx->revoked_zsk[dnskey.algorithm] !=
1645 					   DNS_KEYALG_MAX)
1646 			{
1647 				vctx->revoked_zsk[dnskey.algorithm]++;
1648 			}
1649 		} else {
1650 			check_dnskey_sigs(vctx, &dnskey, &rdata, is_ksk);
1651 		}
1652 		dns_rdata_freestruct(&dnskey);
1653 		dns_rdata_reset(&rdata);
1654 	}
1655 
1656 	return (ISC_R_SUCCESS);
1657 }
1658 
1659 static void
determine_active_algorithms(vctx_t * vctx,bool ignore_kskflag,bool keyset_kskonly,void (* report)(const char *,...))1660 determine_active_algorithms(vctx_t *vctx, bool ignore_kskflag,
1661 			    bool keyset_kskonly,
1662 			    void (*report)(const char *, ...)) {
1663 	char algbuf[DNS_SECALG_FORMATSIZE];
1664 
1665 	report("Verifying the zone using the following algorithms:");
1666 
1667 	for (size_t i = 0; i < ARRAY_SIZE(vctx->act_algorithms); i++) {
1668 		if (ignore_kskflag) {
1669 			vctx->act_algorithms[i] = (vctx->ksk_algorithms[i] !=
1670 							   0 ||
1671 						   vctx->zsk_algorithms[i] != 0)
1672 							  ? 1
1673 							  : 0;
1674 		} else {
1675 			vctx->act_algorithms[i] = vctx->ksk_algorithms[i] != 0
1676 							  ? 1
1677 							  : 0;
1678 		}
1679 		if (vctx->act_algorithms[i] != 0) {
1680 			dns_secalg_format(i, algbuf, sizeof(algbuf));
1681 			report("- %s", algbuf);
1682 		}
1683 	}
1684 
1685 	if (ignore_kskflag || keyset_kskonly) {
1686 		return;
1687 	}
1688 
1689 	for (size_t i = 0; i < ARRAY_SIZE(vctx->ksk_algorithms); i++) {
1690 		/*
1691 		 * The counts should both be zero or both be non-zero.  Mark
1692 		 * the algorithm as bad if this is not met.
1693 		 */
1694 		if ((vctx->ksk_algorithms[i] != 0) ==
1695 		    (vctx->zsk_algorithms[i] != 0)) {
1696 			continue;
1697 		}
1698 		dns_secalg_format(i, algbuf, sizeof(algbuf));
1699 		zoneverify_log_error(vctx, "Missing %s for algorithm %s",
1700 				     (vctx->ksk_algorithms[i] != 0) ? "ZSK"
1701 								    : "self-"
1702 								      "signed "
1703 								      "KSK",
1704 				     algbuf);
1705 		vctx->bad_algorithms[i] = 1;
1706 	}
1707 }
1708 
1709 /*%
1710  * Check that all the records not yet verified were signed by keys that are
1711  * present in the DNSKEY RRset.
1712  */
1713 static isc_result_t
verify_nodes(vctx_t * vctx,isc_result_t * vresult)1714 verify_nodes(vctx_t *vctx, isc_result_t *vresult) {
1715 	dns_fixedname_t fname, fnextname, fprevname, fzonecut;
1716 	dns_name_t *name, *nextname, *prevname, *zonecut;
1717 	dns_dbnode_t *node = NULL, *nextnode;
1718 	dns_dbiterator_t *dbiter = NULL;
1719 	dst_key_t **dstkeys;
1720 	size_t count, nkeys = 0;
1721 	bool done = false;
1722 	isc_result_t tvresult = ISC_R_UNSET;
1723 	isc_result_t result;
1724 
1725 	name = dns_fixedname_initname(&fname);
1726 	nextname = dns_fixedname_initname(&fnextname);
1727 	dns_fixedname_init(&fprevname);
1728 	prevname = NULL;
1729 	dns_fixedname_init(&fzonecut);
1730 	zonecut = NULL;
1731 
1732 	count = dns_rdataset_count(&vctx->keyset);
1733 	dstkeys = isc_mem_get(vctx->mctx, sizeof(*dstkeys) * count);
1734 
1735 	for (result = dns_rdataset_first(&vctx->keyset);
1736 	     result == ISC_R_SUCCESS; result = dns_rdataset_next(&vctx->keyset))
1737 	{
1738 		dns_rdata_t rdata = DNS_RDATA_INIT;
1739 		dns_rdataset_current(&vctx->keyset, &rdata);
1740 		dstkeys[nkeys] = NULL;
1741 		result = dns_dnssec_keyfromrdata(vctx->origin, &rdata,
1742 						 vctx->mctx, &dstkeys[nkeys]);
1743 		if (result == ISC_R_SUCCESS) {
1744 			nkeys++;
1745 		}
1746 	}
1747 
1748 	result = dns_db_createiterator(vctx->db, DNS_DB_NONSEC3, &dbiter);
1749 	if (result != ISC_R_SUCCESS) {
1750 		zoneverify_log_error(vctx, "dns_db_createiterator(): %s",
1751 				     isc_result_totext(result));
1752 		goto done;
1753 	}
1754 
1755 	result = dns_dbiterator_first(dbiter);
1756 	if (result != ISC_R_SUCCESS) {
1757 		zoneverify_log_error(vctx, "dns_dbiterator_first(): %s",
1758 				     isc_result_totext(result));
1759 		goto done;
1760 	}
1761 
1762 	while (!done) {
1763 		bool isdelegation = false;
1764 
1765 		result = dns_dbiterator_current(dbiter, &node, name);
1766 		if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
1767 			zoneverify_log_error(vctx,
1768 					     "dns_dbiterator_current(): %s",
1769 					     isc_result_totext(result));
1770 			goto done;
1771 		}
1772 		if (!dns_name_issubdomain(name, vctx->origin)) {
1773 			result = check_no_nsec(vctx, name, node);
1774 			if (result != ISC_R_SUCCESS) {
1775 				dns_db_detachnode(vctx->db, &node);
1776 				goto done;
1777 			}
1778 			dns_db_detachnode(vctx->db, &node);
1779 			result = dns_dbiterator_next(dbiter);
1780 			if (result == ISC_R_NOMORE) {
1781 				done = true;
1782 			} else if (result != ISC_R_SUCCESS) {
1783 				zoneverify_log_error(vctx,
1784 						     "dns_dbiterator_next(): "
1785 						     "%s",
1786 						     isc_result_totext(result));
1787 				goto done;
1788 			}
1789 			continue;
1790 		}
1791 		if (is_delegation(vctx, name, node, NULL)) {
1792 			zonecut = dns_fixedname_name(&fzonecut);
1793 			dns_name_copy(name, zonecut);
1794 			isdelegation = true;
1795 		} else if (has_dname(vctx, node)) {
1796 			zonecut = dns_fixedname_name(&fzonecut);
1797 			dns_name_copy(name, zonecut);
1798 		}
1799 		nextnode = NULL;
1800 		result = dns_dbiterator_next(dbiter);
1801 		while (result == ISC_R_SUCCESS) {
1802 			bool empty;
1803 			result = dns_dbiterator_current(dbiter, &nextnode,
1804 							nextname);
1805 			if (result != ISC_R_SUCCESS &&
1806 			    result != DNS_R_NEWORIGIN) {
1807 				zoneverify_log_error(vctx,
1808 						     "dns_dbiterator_current():"
1809 						     " %s",
1810 						     isc_result_totext(result));
1811 				dns_db_detachnode(vctx->db, &node);
1812 				goto done;
1813 			}
1814 			if (!dns_name_issubdomain(nextname, vctx->origin) ||
1815 			    (zonecut != NULL &&
1816 			     dns_name_issubdomain(nextname, zonecut)))
1817 			{
1818 				result = check_no_nsec(vctx, nextname,
1819 						       nextnode);
1820 				if (result != ISC_R_SUCCESS) {
1821 					dns_db_detachnode(vctx->db, &node);
1822 					dns_db_detachnode(vctx->db, &nextnode);
1823 					goto done;
1824 				}
1825 				dns_db_detachnode(vctx->db, &nextnode);
1826 				result = dns_dbiterator_next(dbiter);
1827 				continue;
1828 			}
1829 			result = is_empty(vctx, nextnode, &empty);
1830 			dns_db_detachnode(vctx->db, &nextnode);
1831 			if (result != ISC_R_SUCCESS) {
1832 				dns_db_detachnode(vctx->db, &node);
1833 				goto done;
1834 			}
1835 			if (empty) {
1836 				result = dns_dbiterator_next(dbiter);
1837 				continue;
1838 			}
1839 			break;
1840 		}
1841 		if (result == ISC_R_NOMORE) {
1842 			done = true;
1843 			nextname = vctx->origin;
1844 		} else if (result != ISC_R_SUCCESS) {
1845 			zoneverify_log_error(vctx,
1846 					     "iterating through the database "
1847 					     "failed: %s",
1848 					     isc_result_totext(result));
1849 			dns_db_detachnode(vctx->db, &node);
1850 			goto done;
1851 		}
1852 		result = verifynode(vctx, name, node, isdelegation, dstkeys,
1853 				    nkeys, &vctx->nsecset, &vctx->nsec3paramset,
1854 				    nextname, &tvresult);
1855 		if (result != ISC_R_SUCCESS) {
1856 			dns_db_detachnode(vctx->db, &node);
1857 			goto done;
1858 		}
1859 		if (*vresult == ISC_R_UNSET) {
1860 			*vresult = ISC_R_SUCCESS;
1861 		}
1862 		if (*vresult == ISC_R_SUCCESS) {
1863 			*vresult = tvresult;
1864 		}
1865 		if (prevname != NULL) {
1866 			result = verifyemptynodes(
1867 				vctx, name, prevname, isdelegation,
1868 				&vctx->nsec3paramset, &tvresult);
1869 			if (result != ISC_R_SUCCESS) {
1870 				dns_db_detachnode(vctx->db, &node);
1871 				goto done;
1872 			}
1873 		} else {
1874 			prevname = dns_fixedname_name(&fprevname);
1875 		}
1876 		dns_name_copy(name, prevname);
1877 		if (*vresult == ISC_R_SUCCESS) {
1878 			*vresult = tvresult;
1879 		}
1880 		dns_db_detachnode(vctx->db, &node);
1881 	}
1882 
1883 	dns_dbiterator_destroy(&dbiter);
1884 
1885 	result = dns_db_createiterator(vctx->db, DNS_DB_NSEC3ONLY, &dbiter);
1886 	if (result != ISC_R_SUCCESS) {
1887 		zoneverify_log_error(vctx, "dns_db_createiterator(): %s",
1888 				     isc_result_totext(result));
1889 		return (result);
1890 	}
1891 
1892 	for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS;
1893 	     result = dns_dbiterator_next(dbiter))
1894 	{
1895 		result = dns_dbiterator_current(dbiter, &node, name);
1896 		if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
1897 			zoneverify_log_error(vctx,
1898 					     "dns_dbiterator_current(): %s",
1899 					     isc_result_totext(result));
1900 			goto done;
1901 		}
1902 		result = verifynode(vctx, name, node, false, dstkeys, nkeys,
1903 				    NULL, NULL, NULL, NULL);
1904 		if (result != ISC_R_SUCCESS) {
1905 			zoneverify_log_error(vctx, "verifynode: %s",
1906 					     isc_result_totext(result));
1907 			dns_db_detachnode(vctx->db, &node);
1908 			goto done;
1909 		}
1910 		result = record_found(vctx, name, node, &vctx->nsec3paramset);
1911 		dns_db_detachnode(vctx->db, &node);
1912 		if (result != ISC_R_SUCCESS) {
1913 			goto done;
1914 		}
1915 	}
1916 
1917 	result = ISC_R_SUCCESS;
1918 
1919 done:
1920 	while (nkeys-- > 0U) {
1921 		dst_key_free(&dstkeys[nkeys]);
1922 	}
1923 	isc_mem_put(vctx->mctx, dstkeys, sizeof(*dstkeys) * count);
1924 	if (dbiter != NULL) {
1925 		dns_dbiterator_destroy(&dbiter);
1926 	}
1927 
1928 	return (result);
1929 }
1930 
1931 static isc_result_t
check_bad_algorithms(const vctx_t * vctx,void (* report)(const char *,...))1932 check_bad_algorithms(const vctx_t *vctx, void (*report)(const char *, ...)) {
1933 	char algbuf[DNS_SECALG_FORMATSIZE];
1934 	bool first = true;
1935 
1936 	for (size_t i = 0; i < ARRAY_SIZE(vctx->bad_algorithms); i++) {
1937 		if (vctx->bad_algorithms[i] == 0) {
1938 			continue;
1939 		}
1940 		if (first) {
1941 			report("The zone is not fully signed "
1942 			       "for the following algorithms:");
1943 		}
1944 		dns_secalg_format(i, algbuf, sizeof(algbuf));
1945 		report(" %s", algbuf);
1946 		first = false;
1947 	}
1948 
1949 	if (!first) {
1950 		report(".");
1951 	}
1952 
1953 	return (first ? ISC_R_SUCCESS : ISC_R_FAILURE);
1954 }
1955 
1956 static void
print_summary(const vctx_t * vctx,bool keyset_kskonly,void (* report)(const char *,...))1957 print_summary(const vctx_t *vctx, bool keyset_kskonly,
1958 	      void (*report)(const char *, ...)) {
1959 	char algbuf[DNS_SECALG_FORMATSIZE];
1960 
1961 	report("Zone fully signed:");
1962 	for (size_t i = 0; i < ARRAY_SIZE(vctx->ksk_algorithms); i++) {
1963 		if ((vctx->ksk_algorithms[i] == 0) &&
1964 		    (vctx->standby_ksk[i] == 0) &&
1965 		    (vctx->revoked_ksk[i] == 0) &&
1966 		    (vctx->zsk_algorithms[i] == 0) &&
1967 		    (vctx->standby_zsk[i] == 0) && (vctx->revoked_zsk[i] == 0))
1968 		{
1969 			continue;
1970 		}
1971 		dns_secalg_format(i, algbuf, sizeof(algbuf));
1972 		report("Algorithm: %s: KSKs: "
1973 		       "%u active, %u stand-by, %u revoked",
1974 		       algbuf, vctx->ksk_algorithms[i], vctx->standby_ksk[i],
1975 		       vctx->revoked_ksk[i]);
1976 		report("%*sZSKs: "
1977 		       "%u active, %u %s, %u revoked",
1978 		       (int)strlen(algbuf) + 13, "", vctx->zsk_algorithms[i],
1979 		       vctx->standby_zsk[i],
1980 		       keyset_kskonly ? "present" : "stand-by",
1981 		       vctx->revoked_zsk[i]);
1982 	}
1983 }
1984 
1985 isc_result_t
dns_zoneverify_dnssec(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_name_t * origin,dns_keytable_t * secroots,isc_mem_t * mctx,bool ignore_kskflag,bool keyset_kskonly,void (* report)(const char *,...))1986 dns_zoneverify_dnssec(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
1987 		      dns_name_t *origin, dns_keytable_t *secroots,
1988 		      isc_mem_t *mctx, bool ignore_kskflag, bool keyset_kskonly,
1989 		      void (*report)(const char *, ...)) {
1990 	const char *keydesc = (secroots == NULL ? "self-signed" : "trusted");
1991 	isc_result_t result, vresult = ISC_R_UNSET;
1992 	vctx_t vctx;
1993 
1994 	result = vctx_init(&vctx, mctx, zone, db, ver, origin, secroots);
1995 	if (result != ISC_R_SUCCESS) {
1996 		return (result);
1997 	}
1998 
1999 	result = check_apex_rrsets(&vctx);
2000 	if (result != ISC_R_SUCCESS) {
2001 		goto done;
2002 	}
2003 
2004 	result = check_dnskey(&vctx);
2005 	if (result != ISC_R_SUCCESS) {
2006 		goto done;
2007 	}
2008 
2009 	if (ignore_kskflag) {
2010 		if (!vctx.goodksk && !vctx.goodzsk) {
2011 			zoneverify_log_error(&vctx, "No %s DNSKEY found",
2012 					     keydesc);
2013 			result = ISC_R_FAILURE;
2014 			goto done;
2015 		}
2016 	} else if (!vctx.goodksk) {
2017 		zoneverify_log_error(&vctx, "No %s KSK DNSKEY found", keydesc);
2018 		result = ISC_R_FAILURE;
2019 		goto done;
2020 	}
2021 
2022 	determine_active_algorithms(&vctx, ignore_kskflag, keyset_kskonly,
2023 				    report);
2024 
2025 	result = verify_nodes(&vctx, &vresult);
2026 	if (result != ISC_R_SUCCESS) {
2027 		goto done;
2028 	}
2029 
2030 	result = verify_nsec3_chains(&vctx, mctx);
2031 	if (vresult == ISC_R_UNSET) {
2032 		vresult = ISC_R_SUCCESS;
2033 	}
2034 	if (result != ISC_R_SUCCESS && vresult == ISC_R_SUCCESS) {
2035 		vresult = result;
2036 	}
2037 
2038 	result = check_bad_algorithms(&vctx, report);
2039 	if (result != ISC_R_SUCCESS) {
2040 		report("DNSSEC completeness test failed.");
2041 		goto done;
2042 	}
2043 
2044 	result = vresult;
2045 	if (result != ISC_R_SUCCESS) {
2046 		report("DNSSEC completeness test failed (%s).",
2047 		       isc_result_totext(result));
2048 		goto done;
2049 	}
2050 
2051 	if (vctx.goodksk || ignore_kskflag) {
2052 		print_summary(&vctx, keyset_kskonly, report);
2053 	}
2054 
2055 done:
2056 	vctx_destroy(&vctx);
2057 
2058 	return (result);
2059 }
2060