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