Home | History | Annotate | Line # | Download | only in dns
      1 /*	$NetBSD: validator.c,v 1.22 2026/06/19 20:10:00 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 #include <inttypes.h>
     17 #include <stdbool.h>
     18 
     19 #include <isc/async.h>
     20 #include <isc/atomic.h>
     21 #include <isc/base32.h>
     22 #include <isc/counter.h>
     23 #include <isc/helper.h>
     24 #include <isc/job.h>
     25 #include <isc/md.h>
     26 #include <isc/mem.h>
     27 #include <isc/refcount.h>
     28 #include <isc/result.h>
     29 #include <isc/string.h>
     30 #include <isc/tid.h>
     31 #include <isc/util.h>
     32 #include <isc/work.h>
     33 
     34 #include <dns/client.h>
     35 #include <dns/db.h>
     36 #include <dns/dnssec.h>
     37 #include <dns/ds.h>
     38 #include <dns/ede.h>
     39 #include <dns/keytable.h>
     40 #include <dns/keyvalues.h>
     41 #include <dns/log.h>
     42 #include <dns/message.h>
     43 #include <dns/ncache.h>
     44 #include <dns/nsec.h>
     45 #include <dns/nsec3.h>
     46 #include <dns/rdata.h>
     47 #include <dns/rdataset.h>
     48 #include <dns/rdatatype.h>
     49 #include <dns/resolver.h>
     50 #include <dns/validator.h>
     51 #include <dns/view.h>
     52 
     53 /*! \file
     54  * \brief
     55  * Basic processing sequences:
     56  *
     57  * \li When called with rdataset and sigrdataset:
     58  *     validator_start -> validate_answer -> proveunsecure
     59  *     validator_start -> validate_answer -> validate_nx (if secure wildcard)
     60  *
     61  * \li When called with rdataset but no sigrdataset:
     62  *     validator_start -> proveunsecure
     63  *
     64  * \li When called with no rdataset or sigrdataset:
     65  *     validator_start -> validate_nx -> proveunsecure
     66  *
     67  * validator_start:   determine what type of validation to do.
     68  * validate_answer:   attempt to perform a positive validation.
     69  * proveunsecure:     attempt to prove the answer comes from an unsecure zone.
     70  * validate_nx:       attempt to prove a negative response.
     71  */
     72 
     73 #define VALIDATOR_MAGIC	   ISC_MAGIC('V', 'a', 'l', '?')
     74 #define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
     75 
     76 enum valattr {
     77 	VALATTR_CANCELED = 1 << 1,	     /*%< Canceled. */
     78 	VALATTR_TRIEDVERIFY = 1 << 2,	     /*%< We have found a key and have
     79 						attempted a verify. */
     80 	VALATTR_COMPLETE = 1 << 3,	     /*%< Completion event sent. */
     81 	VALATTR_INSECURITY = 1 << 4,	     /*%< Attempting proveunsecure. */
     82 	VALATTR_MAXVALIDATIONS = 1 << 5,     /*%< Max validations quota */
     83 	VALATTR_MAXVALIDATIONFAILS = 1 << 6, /*%< Max validation fails quota */
     84 	VALATTR_OFFLOADED = 1 << 7, /*%< The ownership has been passed to
     85 				       offloaded thread */
     86 
     87 	/*!
     88 	 * NSEC proofs to be looked for.
     89 	 */
     90 	VALATTR_NEEDNOQNAME = 1 << 8,
     91 	VALATTR_NEEDNOWILDCARD = 1 << 9,
     92 	VALATTR_NEEDNODATA = 1 << 10,
     93 
     94 	/*!
     95 	 * NSEC proofs that have been found.
     96 	 */
     97 	VALATTR_FOUNDNOQNAME = 1 << 12,
     98 	VALATTR_FOUNDNOWILDCARD = 1 << 13,
     99 	VALATTR_FOUNDNODATA = 1 << 14,
    100 	VALATTR_FOUNDCLOSEST = 1 << 15,
    101 	VALATTR_FOUNDOPTOUT = 1 << 16,
    102 	VALATTR_FOUNDUNKNOWN = 1 << 17,
    103 };
    104 
    105 #define NEEDNODATA(val)	     ((val->attributes & VALATTR_NEEDNODATA) != 0)
    106 #define NEEDNOQNAME(val)     ((val->attributes & VALATTR_NEEDNOQNAME) != 0)
    107 #define NEEDNOWILDCARD(val)  ((val->attributes & VALATTR_NEEDNOWILDCARD) != 0)
    108 #define FOUNDNODATA(val)     ((val->attributes & VALATTR_FOUNDNODATA) != 0)
    109 #define FOUNDNOQNAME(val)    ((val->attributes & VALATTR_FOUNDNOQNAME) != 0)
    110 #define FOUNDNOWILDCARD(val) ((val->attributes & VALATTR_FOUNDNOWILDCARD) != 0)
    111 #define FOUNDCLOSEST(val)    ((val->attributes & VALATTR_FOUNDCLOSEST) != 0)
    112 #define FOUNDOPTOUT(val)     ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
    113 
    114 #define CANCELING(v) atomic_load(&(v)->canceling)
    115 #define CANCELED(v)  (((v)->attributes & VALATTR_CANCELED) != 0)
    116 #define OFFLOADED(v) (((v)->attributes & VALATTR_OFFLOADED) != 0)
    117 #define COMPLETE(v)  (((v)->attributes & VALATTR_COMPLETE) != 0)
    118 
    119 #define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
    120 #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
    121 
    122 #define MAXVALIDATIONS(r) (((r)->attributes & VALATTR_MAXVALIDATIONS) != 0)
    123 #define MAXVALIDATIONFAILS(r) \
    124 	(((r)->attributes & VALATTR_MAXVALIDATIONFAILS) != 0)
    125 
    126 static void
    127 destroy_validator(dns_validator_t *val);
    128 
    129 static isc_result_t
    130 select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset);
    131 
    132 static void
    133 resume_answer(void *arg);
    134 static void
    135 validate_async_done(dns_validator_t *val, isc_result_t result);
    136 static isc_result_t
    137 validate_async_run(dns_validator_t *val, isc_job_cb cb);
    138 static isc_result_t
    139 validate_helper_run(dns_validator_t *val, isc_job_cb cb);
    140 
    141 static void
    142 validate_dnskey(void *arg);
    143 static void
    144 validate_dnskey_dsset_done(dns_validator_t *val, isc_result_t result);
    145 
    146 static isc_result_t
    147 validate_nx(dns_validator_t *val, bool resume);
    148 
    149 static isc_result_t
    150 proveunsecure(dns_validator_t *val, bool have_ds, bool resume);
    151 
    152 static void
    153 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
    154 	       isc_logmodule_t *module, int level, const char *fmt, va_list ap)
    155 	ISC_FORMAT_PRINTF(5, 0);
    156 
    157 static void
    158 validator_log(void *val, int level, const char *fmt, ...)
    159 	ISC_FORMAT_PRINTF(3, 4);
    160 
    161 static void
    162 validator_logcreate(dns_validator_t *val, dns_name_t *name,
    163 		    dns_rdatatype_t type, const char *caller,
    164 		    const char *operation);
    165 
    166 static isc_result_t
    167 create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
    168 	     isc_job_cb callback, const char *caller);
    169 
    170 /*%
    171  * Ensure the validator's rdatasets are marked as expired.
    172  */
    173 static void
    174 expire_rdatasets(dns_validator_t *val) {
    175 	if (dns_rdataset_isassociated(&val->frdataset)) {
    176 		dns_rdataset_expire(&val->frdataset);
    177 	}
    178 	if (dns_rdataset_isassociated(&val->fsigrdataset)) {
    179 		dns_rdataset_expire(&val->fsigrdataset);
    180 	}
    181 }
    182 
    183 static void
    184 validate_extendederror(dns_validator_t *val);
    185 
    186 static void
    187 validator_addede(dns_validator_t *val, uint16_t code, const char *extra);
    188 
    189 /*%
    190  * Ensure the validator's rdatasets are disassociated.
    191  */
    192 static void
    193 disassociate_rdatasets(dns_validator_t *val) {
    194 	if (dns_rdataset_isassociated(&val->fdsset)) {
    195 		dns_rdataset_disassociate(&val->fdsset);
    196 	}
    197 	if (dns_rdataset_isassociated(&val->frdataset)) {
    198 		dns_rdataset_disassociate(&val->frdataset);
    199 	}
    200 	if (dns_rdataset_isassociated(&val->fsigrdataset)) {
    201 		dns_rdataset_disassociate(&val->fsigrdataset);
    202 	}
    203 }
    204 
    205 /*%
    206  * Mark the rdatasets in val->vstat with trust level "answer",
    207  * indicating that they did not validate, but could be cached as insecure.
    208  *
    209  * If we are validating a name that is marked as "must be secure", log a
    210  * warning and return DNS_R_MUSTBESECURE instead.
    211  */
    212 static isc_result_t
    213 markanswer(dns_validator_t *val, const char *where, const char *mbstext) {
    214 	if (val->mustbesecure && mbstext != NULL) {
    215 		validator_log(val, ISC_LOG_WARNING,
    216 			      "must be secure failure, %s", mbstext);
    217 		return DNS_R_MUSTBESECURE;
    218 	}
    219 
    220 	validator_log(val, ISC_LOG_DEBUG(3), "marking as answer (%s)", where);
    221 	if (val->rdataset != NULL) {
    222 		dns_rdataset_settrust(val->rdataset, dns_trust_answer);
    223 	}
    224 	if (val->sigrdataset != NULL) {
    225 		dns_rdataset_settrust(val->sigrdataset, dns_trust_answer);
    226 	}
    227 
    228 	return ISC_R_SUCCESS;
    229 }
    230 
    231 /*%
    232  * Mark the RRsets in val->vstat with trust level secure.
    233  */
    234 static void
    235 marksecure(dns_validator_t *val, const char *where) {
    236 	validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (%s)", where);
    237 	dns_rdataset_settrust(val->rdataset, dns_trust_secure);
    238 	if (val->sigrdataset != NULL) {
    239 		dns_rdataset_settrust(val->sigrdataset, dns_trust_secure);
    240 	}
    241 	val->secure = true;
    242 }
    243 
    244 /*
    245  * Validator 'val' is finished; send the completion event to the loop
    246  * that called dns_validator_create(), with result `result`.
    247  */
    248 static void
    249 validator_done(dns_validator_t *val, isc_result_t result) {
    250 	if (COMPLETE(val)) {
    251 		return;
    252 	}
    253 
    254 	val->attributes |= VALATTR_COMPLETE;
    255 	val->result = result;
    256 
    257 	dns_ede_copy(val->cb_edectx, &val->edectx);
    258 
    259 	isc_async_run(val->loop, val->cb, val);
    260 }
    261 
    262 /*%
    263  * The is_insecure_referral() function is called as part of seeking the DS
    264  * record. Look in the NSEC or NSEC3 record returned from a DS query to see if
    265  * the record has the NS bitmap set. If so, we are at a delegation point.
    266  *
    267  * If the response contains NSEC3 records with too high iterations, we cannot
    268  * (or rather we are not going to) validate the insecurity proof. Instead we
    269  * are going to treat the message as insecure and just assume the DS was at
    270  * the delegation.
    271  *
    272  * Returns:
    273  *\li	#true  the NS bitmap was set in the NSEC or NSEC3 record, or
    274  *	       the NSEC3 covers the name (in case of opt-out), or
    275  *	       we cannot validate the insecurity proof and are going
    276  *	       to treat the message as insecure.
    277  *\li	#false the NS bitmap was not set.
    278  */
    279 static bool
    280 is_insecure_referral(dns_validator_t *val, dns_name_t *name,
    281 		     dns_rdataset_t *rdataset, isc_result_t dbresult,
    282 		     const char *caller) {
    283 	dns_fixedname_t fixed;
    284 	dns_label_t hashlabel;
    285 	dns_name_t nsec3name;
    286 	dns_rdata_nsec3_t nsec3;
    287 	dns_rdata_t rdata = DNS_RDATA_INIT;
    288 	dns_rdataset_t set;
    289 	int order;
    290 	int scope;
    291 	bool found;
    292 	isc_buffer_t buffer;
    293 	isc_result_t result;
    294 	unsigned char hash[NSEC3_MAX_HASH_LENGTH];
    295 	unsigned char owner[NSEC3_MAX_HASH_LENGTH];
    296 	unsigned int length;
    297 
    298 	REQUIRE(dbresult == DNS_R_NXRRSET || dbresult == DNS_R_NCACHENXRRSET);
    299 
    300 	dns_rdataset_init(&set);
    301 	if (dbresult == DNS_R_NXRRSET) {
    302 		dns_rdataset_clone(rdataset, &set);
    303 	} else {
    304 		result = dns_ncache_getrdataset(rdataset, name,
    305 						dns_rdatatype_nsec, &set);
    306 		if (result == ISC_R_NOTFOUND) {
    307 			goto trynsec3;
    308 		}
    309 		if (result != ISC_R_SUCCESS) {
    310 			return false;
    311 		}
    312 	}
    313 
    314 	INSIST(set.type == dns_rdatatype_nsec);
    315 
    316 	found = false;
    317 	result = dns_rdataset_first(&set);
    318 	if (result == ISC_R_SUCCESS) {
    319 		dns_rdataset_current(&set, &rdata);
    320 		found = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
    321 		dns_rdata_reset(&rdata);
    322 	}
    323 	dns_rdataset_disassociate(&set);
    324 	return found;
    325 
    326 trynsec3:
    327 	/*
    328 	 * Iterate over the ncache entry.
    329 	 */
    330 	found = false;
    331 	dns_name_init(&nsec3name, NULL);
    332 	dns_fixedname_init(&fixed);
    333 	dns_name_downcase(name, dns_fixedname_name(&fixed), NULL);
    334 	name = dns_fixedname_name(&fixed);
    335 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
    336 	     result = dns_rdataset_next(rdataset))
    337 	{
    338 		dns_ncache_current(rdataset, &nsec3name, &set);
    339 		if (set.type != dns_rdatatype_nsec3) {
    340 			dns_rdataset_disassociate(&set);
    341 			continue;
    342 		}
    343 		dns_name_getlabel(&nsec3name, 0, &hashlabel);
    344 		isc_region_consume(&hashlabel, 1);
    345 		isc_buffer_init(&buffer, owner, sizeof(owner));
    346 		result = isc_base32hexnp_decoderegion(&hashlabel, &buffer);
    347 		if (result != ISC_R_SUCCESS) {
    348 			dns_rdataset_disassociate(&set);
    349 			continue;
    350 		}
    351 		for (result = dns_rdataset_first(&set); result == ISC_R_SUCCESS;
    352 		     result = dns_rdataset_next(&set))
    353 		{
    354 			dns_rdata_reset(&rdata);
    355 			dns_rdataset_current(&set, &rdata);
    356 			(void)dns_rdata_tostruct(&rdata, &nsec3, NULL);
    357 			if (nsec3.hash != 1) {
    358 				continue;
    359 			}
    360 			if (nsec3.next_length > NSEC3_MAX_HASH_LENGTH) {
    361 				continue;
    362 			}
    363 			/*
    364 			 * If there are too many iterations assume bad things
    365 			 * are happening and bail out early. Treat as if the
    366 			 * DS was at the delegation.
    367 			 */
    368 			if (nsec3.iterations > DNS_NSEC3_MAXITERATIONS) {
    369 				validator_log(val, ISC_LOG_DEBUG(3),
    370 					      "%s: too many iterations",
    371 					      caller);
    372 				dns_rdataset_disassociate(&set);
    373 				return true;
    374 			}
    375 			length = isc_iterated_hash(
    376 				hash, nsec3.hash, nsec3.iterations, nsec3.salt,
    377 				nsec3.salt_length, name->ndata, name->length);
    378 			if (length != isc_buffer_usedlength(&buffer)) {
    379 				continue;
    380 			}
    381 			order = memcmp(hash, owner, length);
    382 			if (order == 0) {
    383 				found = dns_nsec3_typepresent(&rdata,
    384 							      dns_rdatatype_ns);
    385 				dns_rdataset_disassociate(&set);
    386 				return found;
    387 			}
    388 			if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) == 0) {
    389 				continue;
    390 			}
    391 			/*
    392 			 * Does this optout span cover the name?
    393 			 */
    394 			scope = memcmp(owner, nsec3.next, nsec3.next_length);
    395 			if ((scope < 0 && order > 0 &&
    396 			     memcmp(hash, nsec3.next, length) < 0) ||
    397 			    (scope >= 0 &&
    398 			     (order > 0 ||
    399 			      memcmp(hash, nsec3.next, length) < 0)))
    400 			{
    401 				dns_rdataset_disassociate(&set);
    402 				return true;
    403 			}
    404 		}
    405 		dns_rdataset_disassociate(&set);
    406 	}
    407 	return found;
    408 }
    409 
    410 static void
    411 resume_answer_with_key_done(void *arg);
    412 
    413 static bool
    414 over_max_fails(dns_validator_t *val);
    415 
    416 static void
    417 consume_validation_fail(dns_validator_t *val);
    418 
    419 static void
    420 resume_answer_with_key(void *arg) {
    421 	dns_validator_t *val = arg;
    422 	dns_rdataset_t *rdataset = &val->frdataset;
    423 
    424 	isc_result_t result = select_signing_key(val, rdataset);
    425 	if (result == ISC_R_SUCCESS) {
    426 		val->keyset = &val->frdataset;
    427 	} else if (result != ISC_R_NOTFOUND) {
    428 		val->result = result;
    429 		if (over_max_fails(val)) {
    430 			INSIST(val->key == NULL);
    431 			val->result = ISC_R_QUOTA;
    432 		}
    433 		consume_validation_fail(val);
    434 	}
    435 
    436 	(void)validate_async_run(val, resume_answer_with_key_done);
    437 }
    438 
    439 static void
    440 resume_answer_with_key_done(void *arg) {
    441 	dns_validator_t *val = arg;
    442 
    443 	switch (val->result) {
    444 	case ISC_R_CANCELED:	 /* Validation was canceled */
    445 	case ISC_R_SHUTTINGDOWN: /* Server shutting down */
    446 	case ISC_R_QUOTA:	 /* Validation fails quota reached */
    447 		dns_validator_cancel(val);
    448 		break;
    449 	default:
    450 		break;
    451 	}
    452 
    453 	resume_answer(val);
    454 }
    455 
    456 /*%
    457  * We have been asked to look for a key.
    458  * If found, resume the validation process.
    459  * If not found, fail the validation process.
    460  */
    461 static void
    462 fetch_callback_dnskey(void *arg) {
    463 	dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg;
    464 	dns_validator_t *val = resp->arg;
    465 	dns_rdataset_t *rdataset = &val->frdataset;
    466 	isc_result_t eresult = resp->result;
    467 	isc_result_t result;
    468 
    469 	/* Free resources which are not of interest. */
    470 	if (resp->node != NULL) {
    471 		dns_db_detachnode(resp->db, &resp->node);
    472 	}
    473 	if (resp->db != NULL) {
    474 		dns_db_detach(&resp->db);
    475 	}
    476 	if (dns_rdataset_isassociated(&val->fsigrdataset)) {
    477 		dns_rdataset_disassociate(&val->fsigrdataset);
    478 	}
    479 
    480 	validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_dnskey");
    481 
    482 	dns_resolver_destroyfetch(&val->fetch);
    483 
    484 	if (CANCELED(val) || CANCELING(val)) {
    485 		result = ISC_R_CANCELED;
    486 		goto cleanup;
    487 	}
    488 
    489 	switch (eresult) {
    490 	case ISC_R_SUCCESS:
    491 	case DNS_R_NCACHENXRRSET:
    492 		/*
    493 		 * We have an answer to our DNSKEY query.  Either the DNSKEY
    494 		 * RRset or a NODATA response.
    495 		 */
    496 		validator_log(val, ISC_LOG_DEBUG(3), "%s with trust %s",
    497 			      eresult == ISC_R_SUCCESS ? "keyset"
    498 						       : "NCACHENXRRSET",
    499 			      dns_trust_totext(rdataset->trust));
    500 		/*
    501 		 * Only extract the dst key if the keyset exists and is secure.
    502 		 */
    503 		if (eresult == ISC_R_SUCCESS &&
    504 		    rdataset->trust >= dns_trust_secure)
    505 		{
    506 			result = validate_helper_run(val,
    507 						     resume_answer_with_key);
    508 		} else {
    509 			result = validate_async_run(val, resume_answer);
    510 		}
    511 		break;
    512 	default:
    513 		validator_log(val, ISC_LOG_DEBUG(3),
    514 			      "fetch_callback_dnskey: got %s",
    515 			      isc_result_totext(eresult));
    516 		result = DNS_R_BROKENCHAIN;
    517 	}
    518 
    519 cleanup:
    520 	dns_resolver_freefresp(&resp);
    521 	validate_async_done(val, result);
    522 	dns_validator_detach(&val);
    523 }
    524 
    525 /*%
    526  * We have been asked to look for a DS. This may be part of
    527  * walking a trust chain, or an insecurity proof.
    528  */
    529 static void
    530 fetch_callback_ds(void *arg) {
    531 	dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg;
    532 	dns_validator_t *val = resp->arg;
    533 	dns_rdataset_t *rdataset = &val->frdataset;
    534 	isc_result_t eresult = resp->result;
    535 	isc_result_t result;
    536 	bool trustchain;
    537 
    538 	/*
    539 	 * Set 'trustchain' to true if we're walking a chain of
    540 	 * trust; false if we're attempting to prove insecurity.
    541 	 */
    542 	trustchain = ((val->attributes & VALATTR_INSECURITY) == 0);
    543 
    544 	/* Free resources which are not of interest. */
    545 	if (resp->node != NULL) {
    546 		dns_db_detachnode(resp->db, &resp->node);
    547 	}
    548 	if (resp->db != NULL) {
    549 		dns_db_detach(&resp->db);
    550 	}
    551 	if (dns_rdataset_isassociated(&val->fsigrdataset)) {
    552 		dns_rdataset_disassociate(&val->fsigrdataset);
    553 	}
    554 
    555 	validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_ds");
    556 
    557 	dns_resolver_destroyfetch(&val->fetch);
    558 
    559 	if (CANCELED(val) || CANCELING(val)) {
    560 		result = ISC_R_CANCELED;
    561 		goto cleanup;
    562 	}
    563 
    564 	if (trustchain) {
    565 		switch (eresult) {
    566 		case ISC_R_SUCCESS:
    567 			/*
    568 			 * We looked for a DS record as part of
    569 			 * following a key chain upwards; resume following
    570 			 * the chain.
    571 			 */
    572 			validator_log(val, ISC_LOG_DEBUG(3),
    573 				      "dsset with trust %s",
    574 				      dns_trust_totext(rdataset->trust));
    575 			val->dsset = &val->frdataset;
    576 			result = validate_async_run(val, validate_dnskey);
    577 			break;
    578 		case DNS_R_CNAME:
    579 		case DNS_R_NXRRSET:
    580 		case DNS_R_NCACHENXRRSET:
    581 		case DNS_R_SERVFAIL: /* RFC 1034 parent? */
    582 			/*
    583 			 * Failed to find a DS while following the
    584 			 * chain of trust; now we need to prove insecurity.
    585 			 */
    586 			validator_log(val, ISC_LOG_DEBUG(3),
    587 				      "falling back to insecurity proof (%s)",
    588 				      isc_result_totext(eresult));
    589 			result = proveunsecure(val, false, false);
    590 			break;
    591 		default:
    592 			validator_log(val, ISC_LOG_DEBUG(3),
    593 				      "fetch_callback_ds: got %s",
    594 				      isc_result_totext(eresult));
    595 			result = DNS_R_BROKENCHAIN;
    596 			break;
    597 		}
    598 	} else {
    599 		switch (eresult) {
    600 		case DNS_R_NXDOMAIN:
    601 		case DNS_R_NCACHENXDOMAIN:
    602 			/*
    603 			 * These results only make sense if we're attempting
    604 			 * an insecurity proof, not when walking a chain of
    605 			 * trust.
    606 			 */
    607 
    608 			result = proveunsecure(val, false, true);
    609 			break;
    610 		case ISC_R_SUCCESS:
    611 			/*
    612 			 * There is a DS which may or may not be a zone cut.
    613 			 * In either case we are still in a secure zone,
    614 			 * so keep looking for the break in the chain
    615 			 * of trust.
    616 			 */
    617 			result = proveunsecure(val, true, true);
    618 			break;
    619 		case DNS_R_NXRRSET:
    620 		case DNS_R_NCACHENXRRSET:
    621 			if (is_insecure_referral(val, resp->foundname,
    622 						 &val->frdataset, eresult,
    623 						 "fetch_callback_ds"))
    624 			{
    625 				/*
    626 				 * Failed to find a DS while trying to prove
    627 				 * insecurity. If this is a zone cut, that
    628 				 * means we're insecure.
    629 				 */
    630 				result = markanswer(
    631 					val, "fetch_callback_ds",
    632 					"no DS and this is a delegation");
    633 				break;
    634 			}
    635 			FALLTHROUGH;
    636 		case DNS_R_CNAME:
    637 			/*
    638 			 * Not a zone cut, so we have to keep looking for
    639 			 * the break point in the chain of trust.
    640 			 */
    641 			result = proveunsecure(val, false, true);
    642 			break;
    643 		default:
    644 			validator_log(val, ISC_LOG_DEBUG(3),
    645 				      "fetch_callback_ds: got %s",
    646 				      isc_result_totext(eresult));
    647 			result = DNS_R_BROKENCHAIN;
    648 		}
    649 	}
    650 
    651 cleanup:
    652 	dns_resolver_freefresp(&resp);
    653 	validate_async_done(val, result);
    654 	dns_validator_detach(&val);
    655 }
    656 
    657 /*%
    658  * Callback from when a DNSKEY RRset has been validated.
    659  *
    660  * Resumes the stalled validation process.
    661  */
    662 static void
    663 validator_callback_dnskey(void *arg) {
    664 	dns_validator_t *subvalidator = (dns_validator_t *)arg;
    665 	dns_validator_t *val = subvalidator->parent;
    666 	isc_result_t result = subvalidator->result;
    667 
    668 	val->subvalidator = NULL;
    669 
    670 	if (CANCELED(val) || CANCELING(val)) {
    671 		result = ISC_R_CANCELED;
    672 		goto cleanup;
    673 	}
    674 
    675 	validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_dnskey");
    676 	if (result == ISC_R_SUCCESS) {
    677 		validator_log(val, ISC_LOG_DEBUG(3), "keyset with trust %s",
    678 			      dns_trust_totext(val->frdataset.trust));
    679 		/*
    680 		 * Only extract the dst key if the keyset is secure.
    681 		 */
    682 		if (val->frdataset.trust >= dns_trust_secure) {
    683 			result = validate_helper_run(val,
    684 						     resume_answer_with_key);
    685 		} else {
    686 			result = validate_async_run(val, resume_answer);
    687 		}
    688 	} else {
    689 		validator_log(val, ISC_LOG_DEBUG(3),
    690 			      "validator_callback_dnskey: got %s",
    691 			      isc_result_totext(result));
    692 		if (result != DNS_R_BROKENCHAIN) {
    693 			expire_rdatasets(val);
    694 			result = create_fetch(val, &val->siginfo->signer,
    695 					      dns_rdatatype_dnskey,
    696 					      fetch_callback_dnskey,
    697 					      "validator_callback_dnskey");
    698 			if (result == ISC_R_SUCCESS) {
    699 				result = DNS_R_WAIT;
    700 			}
    701 		}
    702 	}
    703 
    704 cleanup:
    705 	dns_validator_detach(&subvalidator->parent);
    706 	dns_validator_shutdown(subvalidator);
    707 	dns_validator_detach(&subvalidator);
    708 	validate_async_done(val, result);
    709 }
    710 
    711 /*%
    712  * Callback when the DS record has been validated.
    713  *
    714  * Resumes validation of the zone key or the unsecure zone proof.
    715  */
    716 static void
    717 validator_callback_ds(void *arg) {
    718 	dns_validator_t *subvalidator = (dns_validator_t *)arg;
    719 	dns_validator_t *val = subvalidator->parent;
    720 	isc_result_t result = subvalidator->result;
    721 
    722 	val->subvalidator = NULL;
    723 
    724 	if (CANCELED(val) || CANCELING(val)) {
    725 		result = ISC_R_CANCELED;
    726 		goto cleanup;
    727 	}
    728 
    729 	validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_ds");
    730 	if (result == ISC_R_SUCCESS) {
    731 		bool have_dsset;
    732 		dns_name_t *name;
    733 		validator_log(val, ISC_LOG_DEBUG(3), "%s with trust %s",
    734 			      val->frdataset.type == dns_rdatatype_ds
    735 				      ? "dsset"
    736 				      : "ds non-existence",
    737 			      dns_trust_totext(val->frdataset.trust));
    738 		have_dsset = (val->frdataset.type == dns_rdatatype_ds);
    739 		name = dns_fixedname_name(&val->fname);
    740 
    741 		if ((val->attributes & VALATTR_INSECURITY) != 0 &&
    742 		    val->frdataset.covers == dns_rdatatype_ds &&
    743 		    NEGATIVE(&val->frdataset) &&
    744 		    is_insecure_referral(val, name, &val->frdataset,
    745 					 DNS_R_NCACHENXRRSET,
    746 					 "validator_callback_ds"))
    747 		{
    748 			result = markanswer(val, "validator_callback_ds",
    749 					    "no DS and this is a delegation");
    750 		} else if ((val->attributes & VALATTR_INSECURITY) != 0) {
    751 			result = proveunsecure(val, have_dsset, true);
    752 		} else {
    753 			result = validate_async_run(val, validate_dnskey);
    754 		}
    755 	} else {
    756 		validator_log(val, ISC_LOG_DEBUG(3),
    757 			      "validator_callback_ds: got %s",
    758 			      isc_result_totext(result));
    759 		if (result != DNS_R_BROKENCHAIN) {
    760 			expire_rdatasets(val);
    761 			result = create_fetch(val, val->name, dns_rdatatype_ds,
    762 					      fetch_callback_ds,
    763 					      "validator_callback_ds");
    764 			if (result == ISC_R_SUCCESS) {
    765 				result = DNS_R_WAIT;
    766 			}
    767 		}
    768 	}
    769 
    770 cleanup:
    771 	dns_validator_detach(&subvalidator->parent);
    772 	dns_validator_shutdown(subvalidator);
    773 	dns_validator_detach(&subvalidator);
    774 	validate_async_done(val, result);
    775 }
    776 
    777 /*%
    778  * Callback when the CNAME record has been validated.
    779  *
    780  * Resumes validation of the unsecure zone proof.
    781  */
    782 static void
    783 validator_callback_cname(void *arg) {
    784 	dns_validator_t *subvalidator = (dns_validator_t *)arg;
    785 	dns_validator_t *val = subvalidator->parent;
    786 	isc_result_t result;
    787 	isc_result_t eresult = subvalidator->result;
    788 
    789 	INSIST((val->attributes & VALATTR_INSECURITY) != 0);
    790 
    791 	val->subvalidator = NULL;
    792 
    793 	if (CANCELED(val) || CANCELING(val)) {
    794 		result = ISC_R_CANCELED;
    795 		goto cleanup;
    796 	}
    797 
    798 	validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_cname");
    799 	if (eresult == ISC_R_SUCCESS) {
    800 		validator_log(val, ISC_LOG_DEBUG(3), "cname with trust %s",
    801 			      dns_trust_totext(val->frdataset.trust));
    802 		result = proveunsecure(val, false, true);
    803 	} else {
    804 		if (eresult != DNS_R_BROKENCHAIN) {
    805 			expire_rdatasets(val);
    806 		}
    807 		validator_log(val, ISC_LOG_DEBUG(3),
    808 			      "validator_callback_cname: got %s",
    809 			      isc_result_totext(eresult));
    810 		result = DNS_R_BROKENCHAIN;
    811 	}
    812 
    813 cleanup:
    814 	dns_validator_detach(&subvalidator->parent);
    815 	dns_validator_shutdown(subvalidator);
    816 	dns_validator_detach(&subvalidator);
    817 	validate_async_done(val, result);
    818 }
    819 
    820 /*%
    821  * Callback for when NSEC records have been validated.
    822  *
    823  * Looks for NOQNAME, NODATA and OPTOUT proofs.
    824  *
    825  * Resumes the negative response validation by calling validate_nx().
    826  */
    827 static void
    828 validator_callback_nsec(void *arg) {
    829 	dns_validator_t *subvalidator = (dns_validator_t *)arg;
    830 	dns_validator_t *val = subvalidator->parent;
    831 	dns_rdataset_t *rdataset = subvalidator->rdataset;
    832 	isc_result_t result;
    833 	isc_result_t eresult = subvalidator->result;
    834 	bool exists, data;
    835 
    836 	val->subvalidator = NULL;
    837 
    838 	if (CANCELED(val) || CANCELING(val)) {
    839 		result = ISC_R_CANCELED;
    840 		goto cleanup;
    841 	}
    842 
    843 	validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_nsec");
    844 	if (eresult == ISC_R_SUCCESS) {
    845 		dns_name_t **proofs = val->proofs;
    846 		dns_name_t *wild = dns_fixedname_name(&val->wild);
    847 
    848 		if (rdataset->type == dns_rdatatype_nsec &&
    849 		    rdataset->trust == dns_trust_secure &&
    850 		    (NEEDNODATA(val) || NEEDNOQNAME(val)) &&
    851 		    !FOUNDNODATA(val) && !FOUNDNOQNAME(val) &&
    852 		    dns_nsec_noexistnodata(val->type, val->name,
    853 					   subvalidator->name, rdataset,
    854 					   &exists, &data, wild, validator_log,
    855 					   val) == ISC_R_SUCCESS)
    856 		{
    857 			if (exists && !data) {
    858 				val->attributes |= VALATTR_FOUNDNODATA;
    859 				if (NEEDNODATA(val)) {
    860 					proofs[DNS_VALIDATOR_NODATAPROOF] =
    861 						subvalidator->name;
    862 				}
    863 			}
    864 			if (!exists) {
    865 				dns_name_t *closest = NULL;
    866 				unsigned int clabels;
    867 
    868 				val->attributes |= VALATTR_FOUNDNOQNAME;
    869 
    870 				closest = dns_fixedname_name(&val->closest);
    871 				clabels = dns_name_countlabels(closest);
    872 				/*
    873 				 * If we are validating a wildcard response
    874 				 * clabels will not be zero.  We then need
    875 				 * to check if the generated wildcard from
    876 				 * dns_nsec_noexistnodata is consistent with
    877 				 * the wildcard used to generate the response.
    878 				 */
    879 				if (clabels == 0 ||
    880 				    dns_name_countlabels(wild) == clabels + 1)
    881 				{
    882 					val->attributes |= VALATTR_FOUNDCLOSEST;
    883 				}
    884 				/*
    885 				 * The NSEC noqname proof also contains
    886 				 * the closest encloser.
    887 				 */
    888 				if (NEEDNOQNAME(val)) {
    889 					proofs[DNS_VALIDATOR_NOQNAMEPROOF] =
    890 						subvalidator->name;
    891 				}
    892 			}
    893 		}
    894 
    895 		result = validate_nx(val, true);
    896 	} else {
    897 		validator_log(val, ISC_LOG_DEBUG(3),
    898 			      "validator_callback_nsec: got %s",
    899 			      isc_result_totext(eresult));
    900 		switch (eresult) {
    901 		case ISC_R_CANCELED:
    902 		case ISC_R_SHUTTINGDOWN:
    903 			result = eresult;
    904 			break;
    905 		case DNS_R_BROKENCHAIN:
    906 			val->authfail++;
    907 			FALLTHROUGH;
    908 		default:
    909 			result = validate_nx(val, true);
    910 		}
    911 	}
    912 
    913 cleanup:
    914 	dns_validator_detach(&subvalidator->parent);
    915 	dns_validator_shutdown(subvalidator);
    916 	dns_validator_detach(&subvalidator);
    917 	validate_async_done(val, result);
    918 }
    919 
    920 /*%
    921  * Looks for the requested name and type in the view (zones and cache).
    922  *
    923  * Returns:
    924  * \li	ISC_R_SUCCESS
    925  * \li	ISC_R_NOTFOUND
    926  * \li	DNS_R_NCACHENXDOMAIN
    927  * \li	DNS_R_NCACHENXRRSET
    928  * \li	DNS_R_NXRRSET
    929  * \li	DNS_R_NXDOMAIN
    930  * \li	DNS_R_BROKENCHAIN
    931  */
    932 static isc_result_t
    933 view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
    934 	dns_fixedname_t fixedname;
    935 	dns_name_t *foundname;
    936 	isc_result_t result;
    937 	unsigned int options;
    938 
    939 	disassociate_rdatasets(val);
    940 
    941 	options = DNS_DBFIND_PENDINGOK;
    942 	foundname = dns_fixedname_initname(&fixedname);
    943 	result = dns_view_find(val->view, name, type, 0, options, false, false,
    944 			       NULL, NULL, foundname, &val->frdataset,
    945 			       &val->fsigrdataset);
    946 
    947 	if (result == DNS_R_NXDOMAIN) {
    948 		goto notfound;
    949 	} else if (result != ISC_R_SUCCESS && result != DNS_R_NCACHENXDOMAIN &&
    950 		   result != DNS_R_NCACHENXRRSET && result != DNS_R_EMPTYNAME &&
    951 		   result != DNS_R_NXRRSET && result != ISC_R_NOTFOUND)
    952 	{
    953 		result = ISC_R_NOTFOUND;
    954 		goto notfound;
    955 	}
    956 
    957 	return result;
    958 
    959 notfound:
    960 	disassociate_rdatasets(val);
    961 
    962 	return result;
    963 }
    964 
    965 #define CHAINING(r) (((r)->attributes & DNS_RDATASETATTR_CHAINING) != 0)
    966 
    967 /*%
    968  * Returns true if proceeding would stall the SHARED fetch: either the
    969  * fetch cannot advance an alias chain, or an ancestor is already
    970  * resolving the same (name, type).
    971  */
    972 static bool
    973 check_deadlock(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
    974 	       dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
    975 	for (dns_validator_t *cur = val; cur != NULL; cur = cur->parent) {
    976 		if (!dns_name_equal(cur->name, name)) {
    977 			continue;
    978 		}
    979 
    980 		/*
    981 		 * Validating a CNAME/DNAME ("chaining" rdataset): a fetch at
    982 		 * the alias's own name cannot advance the chain (the type we
    983 		 * need, e.g. DS/DNSKEY for an insecurity proof, cannot live at
    984 		 * an alias) and would only self-join the in-flight fetch.
    985 		 */
    986 		if (cur->rdataset != NULL && CHAINING(cur->rdataset)) {
    987 			validator_log(
    988 				val, ISC_LOG_DEBUG(3),
    989 				"fetch would not advance the alias chain: "
    990 				"aborting validation");
    991 			return true;
    992 		}
    993 
    994 		/*
    995 		 * Not a loop: NSEC3 is meta data, so proving a name's
    996 		 * nonexistence can need the NSEC3 RRset that proves it
    997 		 * validated at its own owner name.  Allow that when we hold a
    998 		 * concrete RRset and the ancestor runs a message-driven
    999 		 * nonexistence proof.
   1000 		 */
   1001 		if (cur->type == dns_rdatatype_nsec3 && rdataset != NULL &&
   1002 		    sigrdataset != NULL && cur->message != NULL &&
   1003 		    cur->rdataset == NULL && cur->sigrdataset == NULL)
   1004 		{
   1005 			continue;
   1006 		}
   1007 
   1008 		/*
   1009 		 * An ancestor at this name is already validating this type; a
   1010 		 * shared fetch would block on itself.
   1011 		 */
   1012 		if (cur->type == type) {
   1013 			validator_log(val, ISC_LOG_DEBUG(3),
   1014 				      "continuing validation would lead to "
   1015 				      "deadlock: aborting validation");
   1016 			return true;
   1017 		}
   1018 	}
   1019 	return false;
   1020 }
   1021 
   1022 #undef CHAINING
   1023 
   1024 /*%
   1025  * Start a fetch for the requested name and type.
   1026  */
   1027 static isc_result_t
   1028 create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
   1029 	     isc_job_cb callback, const char *caller) {
   1030 	unsigned int fopts = 0;
   1031 	isc_result_t result;
   1032 
   1033 	disassociate_rdatasets(val);
   1034 
   1035 	if (check_deadlock(val, name, type, NULL, NULL)) {
   1036 		return ISC_R_DEADLOCK;
   1037 	}
   1038 
   1039 	if ((val->options & DNS_VALIDATOR_NOCDFLAG) != 0) {
   1040 		fopts |= DNS_FETCHOPT_NOCDFLAG;
   1041 	}
   1042 
   1043 	if ((val->options & DNS_VALIDATOR_NONTA) != 0) {
   1044 		fopts |= DNS_FETCHOPT_NONTA;
   1045 	}
   1046 
   1047 	validator_logcreate(val, name, type, caller, "fetch");
   1048 
   1049 	dns_validator_ref(val);
   1050 	result = dns_resolver_createfetch(
   1051 		val->view->resolver, name, type, NULL, NULL, NULL, NULL, 0,
   1052 		fopts, 0, val->qc, val->gqc, val->parent_fetch, val->loop,
   1053 		callback, val, &val->edectx, &val->frdataset,
   1054 		&val->fsigrdataset, &val->fetch);
   1055 	if (result != ISC_R_SUCCESS) {
   1056 		dns_validator_detach(&val);
   1057 	}
   1058 
   1059 	return result;
   1060 }
   1061 
   1062 /*%
   1063  * Start a subvalidation process.
   1064  */
   1065 static isc_result_t
   1066 create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
   1067 		 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
   1068 		 isc_job_cb cb, const char *caller) {
   1069 	isc_result_t result;
   1070 	unsigned int vopts = 0;
   1071 	dns_rdataset_t *sig = NULL;
   1072 
   1073 	if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
   1074 		sig = sigrdataset;
   1075 	}
   1076 
   1077 	if (check_deadlock(val, name, type, rdataset, sig)) {
   1078 		validator_log(val, ISC_LOG_DEBUG(3),
   1079 			      "deadlock found (create_validator)");
   1080 		return ISC_R_DEADLOCK;
   1081 	}
   1082 
   1083 	/* OK to clear other options, but preserve NOCDFLAG and NONTA. */
   1084 	vopts |= (val->options &
   1085 		  (DNS_VALIDATOR_NOCDFLAG | DNS_VALIDATOR_NONTA));
   1086 
   1087 	validator_logcreate(val, name, type, caller, "validator");
   1088 	result = dns_validator_create(
   1089 		val->view, name, type, rdataset, sig, NULL, vopts, val->loop,
   1090 		cb, val, val->nvalidations, val->nfails, val->qc, val->gqc,
   1091 		val->parent_fetch, &val->edectx, &val->subvalidator);
   1092 	if (result == ISC_R_SUCCESS) {
   1093 		dns_validator_attach(val, &val->subvalidator->parent);
   1094 		val->subvalidator->depth = val->depth + 1;
   1095 	}
   1096 	return result;
   1097 }
   1098 
   1099 /*%
   1100  * Try to find a key that could have signed val->siginfo among those in
   1101  * 'rdataset'.  If found, build a dst_key_t for it and point val->key at
   1102  * it.
   1103  *
   1104  * If val->key is already non-NULL, locate it in the rdataset and then
   1105  * search past it for the *next* key that could have signed 'siginfo', then
   1106  * set val->key to that.
   1107  *
   1108  * Returns ISC_R_SUCCESS if a possible matching key has been found,
   1109  * ISC_R_NOTFOUND if not. Any other value indicates error.
   1110  */
   1111 static isc_result_t
   1112 select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) {
   1113 	isc_result_t result;
   1114 	dns_rdata_rrsig_t *siginfo = val->siginfo;
   1115 	isc_buffer_t b;
   1116 	dns_rdata_t rdata = DNS_RDATA_INIT;
   1117 	dst_key_t *oldkey = val->key;
   1118 	bool no_rdata = false;
   1119 
   1120 	if (oldkey == NULL) {
   1121 		result = dns_rdataset_first(rdataset);
   1122 	} else {
   1123 		dst_key_free(&oldkey);
   1124 		val->key = NULL;
   1125 		result = dns_rdataset_next(rdataset);
   1126 	}
   1127 	if (result != ISC_R_SUCCESS) {
   1128 		goto done;
   1129 	}
   1130 
   1131 	do {
   1132 		dns_rdataset_current(rdataset, &rdata);
   1133 
   1134 		isc_buffer_init(&b, rdata.data, rdata.length);
   1135 		isc_buffer_add(&b, rdata.length);
   1136 		INSIST(val->key == NULL);
   1137 		result = dst_key_fromdns_ex(&siginfo->signer, rdata.rdclass, &b,
   1138 					    val->view->mctx, no_rdata,
   1139 					    &val->key);
   1140 		if (result == ISC_R_SUCCESS) {
   1141 			if (siginfo->algorithm ==
   1142 				    (dns_secalg_t)dst_key_alg(val->key) &&
   1143 			    siginfo->keyid ==
   1144 				    (dns_keytag_t)dst_key_id(val->key) &&
   1145 			    (dst_key_flags(val->key) & DNS_KEYFLAG_REVOKE) ==
   1146 				    0 &&
   1147 			    dst_key_iszonekey(val->key))
   1148 			{
   1149 				if (no_rdata) {
   1150 					/* Retry with full key */
   1151 					dns_rdata_reset(&rdata);
   1152 					dst_key_free(&val->key);
   1153 					no_rdata = false;
   1154 					continue;
   1155 				}
   1156 				/* This is the key we're looking for. */
   1157 				goto done;
   1158 			}
   1159 			dst_key_free(&val->key);
   1160 		} else if (result != DST_R_UNSUPPORTEDALG) {
   1161 			/*
   1162 			 * We can encounter unsupported algorithm when the zone
   1163 			 * is signed with both supported and unsupported
   1164 			 * algorithm at the same time.  Stop looking in all
   1165 			 * other failure cases.
   1166 			 */
   1167 			break;
   1168 		}
   1169 		dns_rdata_reset(&rdata);
   1170 		result = dns_rdataset_next(rdataset);
   1171 		no_rdata = true;
   1172 	} while (result == ISC_R_SUCCESS);
   1173 
   1174 done:
   1175 	if (result == ISC_R_NOMORE) {
   1176 		result = ISC_R_NOTFOUND;
   1177 	}
   1178 
   1179 	return result;
   1180 }
   1181 
   1182 /*%
   1183  * Get the key that generated the signature in val->siginfo.
   1184  */
   1185 static isc_result_t
   1186 seek_dnskey(dns_validator_t *val) {
   1187 	isc_result_t result;
   1188 	dns_rdata_rrsig_t *siginfo = val->siginfo;
   1189 	unsigned int nlabels;
   1190 	int order;
   1191 	dns_namereln_t namereln;
   1192 
   1193 	/*
   1194 	 * Is the signer name appropriate for this signature?
   1195 	 *
   1196 	 * The signer name must be at the same level as the owner name
   1197 	 * or closer to the DNS root.
   1198 	 */
   1199 	namereln = dns_name_fullcompare(val->name, &siginfo->signer, &order,
   1200 					&nlabels);
   1201 	if (namereln != dns_namereln_subdomain &&
   1202 	    namereln != dns_namereln_equal)
   1203 	{
   1204 		return DNS_R_CONTINUE;
   1205 	}
   1206 
   1207 	if (namereln == dns_namereln_equal) {
   1208 		/*
   1209 		 * If this is a self-signed keyset, it must not be a zone key
   1210 		 * (since seek_dnskey is not called from validate_dnskey).
   1211 		 */
   1212 		if (val->rdataset->type == dns_rdatatype_dnskey) {
   1213 			return DNS_R_CONTINUE;
   1214 		}
   1215 
   1216 		/*
   1217 		 * Records appearing in the parent zone at delegation
   1218 		 * points cannot be self-signed.
   1219 		 */
   1220 		if (dns_rdatatype_atparent(val->rdataset->type)) {
   1221 			return DNS_R_CONTINUE;
   1222 		}
   1223 	} else {
   1224 		/*
   1225 		 * SOA and NS RRsets can only be signed by a key with
   1226 		 * the same name.
   1227 		 */
   1228 		if (val->rdataset->type == dns_rdatatype_soa ||
   1229 		    val->rdataset->type == dns_rdatatype_ns)
   1230 		{
   1231 			const char *type;
   1232 
   1233 			if (val->rdataset->type == dns_rdatatype_soa) {
   1234 				type = "SOA";
   1235 			} else {
   1236 				type = "NS";
   1237 			}
   1238 			validator_log(val, ISC_LOG_DEBUG(3),
   1239 				      "%s signer mismatch", type);
   1240 			return DNS_R_CONTINUE;
   1241 		}
   1242 	}
   1243 
   1244 	/*
   1245 	 * Do we know about this key?
   1246 	 */
   1247 	result = view_find(val, &siginfo->signer, dns_rdatatype_dnskey);
   1248 	switch (result) {
   1249 	case ISC_R_SUCCESS:
   1250 		/*
   1251 		 * We have an rrset for the given keyname.
   1252 		 */
   1253 		val->keyset = &val->frdataset;
   1254 		if (DNS_TRUST_PENDING(val->frdataset.trust) ||
   1255 		    DNS_TRUST_ANSWER(val->frdataset.trust))
   1256 		{
   1257 			/*
   1258 			 * We know the key but haven't validated it yet, or
   1259 			 * we had a key with trust level "answer" and
   1260 			 * a DS record for the zone has now been added.
   1261 			 */
   1262 			result = create_validator(
   1263 				val, &siginfo->signer, dns_rdatatype_dnskey,
   1264 				&val->frdataset, &val->fsigrdataset,
   1265 				validator_callback_dnskey, "seek_dnskey");
   1266 			if (result != ISC_R_SUCCESS) {
   1267 				return result;
   1268 			}
   1269 			return DNS_R_WAIT;
   1270 		} else if (val->frdataset.trust < dns_trust_secure) {
   1271 			/*
   1272 			 * The key is legitimately insecure.  There's no
   1273 			 * point in even attempting verification.
   1274 			 */
   1275 			val->key = NULL;
   1276 			result = ISC_R_SUCCESS;
   1277 		} else {
   1278 			/*
   1279 			 * See if we've got the key used in the signature.
   1280 			 */
   1281 			validator_log(val, ISC_LOG_DEBUG(3),
   1282 				      "keyset with trust %s",
   1283 				      dns_trust_totext(val->frdataset.trust));
   1284 
   1285 			/*
   1286 			 * Cleanup before passing control to the offload thread
   1287 			 */
   1288 			if (dns_rdataset_isassociated(&val->frdataset) &&
   1289 			    val->keyset != &val->frdataset)
   1290 			{
   1291 				dns_rdataset_disassociate(&val->frdataset);
   1292 			}
   1293 			if (dns_rdataset_isassociated(&val->fsigrdataset)) {
   1294 				dns_rdataset_disassociate(&val->fsigrdataset);
   1295 			}
   1296 
   1297 			return validate_helper_run(val, resume_answer_with_key);
   1298 		}
   1299 		break;
   1300 
   1301 	case ISC_R_NOTFOUND:
   1302 		/*
   1303 		 * We don't know anything about this key.
   1304 		 */
   1305 		result = create_fetch(val, &siginfo->signer,
   1306 				      dns_rdatatype_dnskey,
   1307 				      fetch_callback_dnskey, "seek_dnskey");
   1308 		if (result != ISC_R_SUCCESS) {
   1309 			return result;
   1310 		}
   1311 		return DNS_R_WAIT;
   1312 
   1313 	case DNS_R_NCACHENXDOMAIN:
   1314 	case DNS_R_NCACHENXRRSET:
   1315 	case DNS_R_EMPTYNAME:
   1316 	case DNS_R_NXDOMAIN:
   1317 	case DNS_R_NXRRSET:
   1318 		/*
   1319 		 * This key doesn't exist.
   1320 		 */
   1321 		result = DNS_R_CONTINUE;
   1322 		break;
   1323 
   1324 	case DNS_R_BROKENCHAIN:
   1325 		return result;
   1326 
   1327 	default:
   1328 		break;
   1329 	}
   1330 
   1331 	if (dns_rdataset_isassociated(&val->frdataset) &&
   1332 	    val->keyset != &val->frdataset)
   1333 	{
   1334 		dns_rdataset_disassociate(&val->frdataset);
   1335 	}
   1336 	if (dns_rdataset_isassociated(&val->fsigrdataset)) {
   1337 		dns_rdataset_disassociate(&val->fsigrdataset);
   1338 	}
   1339 
   1340 	return result;
   1341 }
   1342 
   1343 /*
   1344  * Compute the tag for a key represented in a DNSKEY rdata.
   1345  */
   1346 static dns_keytag_t
   1347 compute_keytag(dns_rdata_t *rdata) {
   1348 	isc_region_t r;
   1349 
   1350 	dns_rdata_toregion(rdata, &r);
   1351 	return dst_region_computeid(&r);
   1352 }
   1353 
   1354 static bool
   1355 over_max_validations(dns_validator_t *val) {
   1356 	if (val->nvalidations == NULL ||
   1357 	    isc_counter_used(val->nvalidations) <
   1358 		    isc_counter_getlimit(val->nvalidations))
   1359 	{
   1360 		return false;
   1361 	}
   1362 
   1363 	/* The attribute is set only on failure */
   1364 	val->attributes |= VALATTR_MAXVALIDATIONS;
   1365 	return true;
   1366 }
   1367 
   1368 static void
   1369 consume_validation(dns_validator_t *val) {
   1370 	if (val->nvalidations == NULL) {
   1371 		return;
   1372 	}
   1373 	(void)isc_counter_increment(val->nvalidations);
   1374 }
   1375 
   1376 static bool
   1377 over_max_fails(dns_validator_t *val) {
   1378 	if (val->nfails == NULL ||
   1379 	    isc_counter_used(val->nfails) < isc_counter_getlimit(val->nfails))
   1380 	{
   1381 		return false;
   1382 	}
   1383 
   1384 	/* The attribute is set only on failure */
   1385 	val->attributes |= VALATTR_MAXVALIDATIONFAILS;
   1386 	return true;
   1387 }
   1388 
   1389 static void
   1390 consume_validation_fail(dns_validator_t *val) {
   1391 	if (val->nfails == NULL) {
   1392 		return;
   1393 	}
   1394 	(void)isc_counter_increment(val->nfails);
   1395 }
   1396 
   1397 /*%
   1398  * Is the DNSKEY rrset in val->rdataset self-signed?
   1399  */
   1400 static isc_result_t
   1401 selfsigned_dnskey(dns_validator_t *val) {
   1402 	dns_rdataset_t *rdataset = val->rdataset;
   1403 	dns_rdataset_t *sigrdataset = val->sigrdataset;
   1404 	dns_name_t *name = val->name;
   1405 	isc_result_t result;
   1406 	isc_mem_t *mctx = val->view->mctx;
   1407 	bool match = false;
   1408 
   1409 	if (rdataset->type != dns_rdatatype_dnskey) {
   1410 		return DNS_R_NOKEYMATCH;
   1411 	}
   1412 
   1413 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
   1414 	     result = dns_rdataset_next(rdataset))
   1415 	{
   1416 		dns_rdata_t keyrdata = DNS_RDATA_INIT;
   1417 		dns_rdata_t sigrdata = DNS_RDATA_INIT;
   1418 		dns_rdata_dnskey_t key;
   1419 		dns_rdata_rrsig_t sig;
   1420 		dns_keytag_t keytag;
   1421 
   1422 		dns_rdata_reset(&keyrdata);
   1423 		dns_rdataset_current(rdataset, &keyrdata);
   1424 		result = dns_rdata_tostruct(&keyrdata, &key, NULL);
   1425 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   1426 		keytag = compute_keytag(&keyrdata);
   1427 
   1428 		for (result = dns_rdataset_first(sigrdataset);
   1429 		     result == ISC_R_SUCCESS;
   1430 		     result = dns_rdataset_next(sigrdataset))
   1431 		{
   1432 			dst_key_t *dstkey = NULL;
   1433 
   1434 			dns_rdata_reset(&sigrdata);
   1435 			dns_rdataset_current(sigrdataset, &sigrdata);
   1436 			result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
   1437 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   1438 
   1439 			if (sig.algorithm != key.algorithm ||
   1440 			    sig.keyid != keytag ||
   1441 			    !dns_name_equal(name, &sig.signer))
   1442 			{
   1443 				continue;
   1444 			}
   1445 
   1446 			/*
   1447 			 * If the REVOKE bit is not set we have a
   1448 			 * theoretically self-signed DNSKEY RRset;
   1449 			 * this will be verified later.
   1450 			 *
   1451 			 * We don't return the answer yet, though,
   1452 			 * because we need to check the remaining keys
   1453 			 * and possbly remove them if they're revoked.
   1454 			 */
   1455 			if ((key.flags & DNS_KEYFLAG_REVOKE) == 0) {
   1456 				match = true;
   1457 				break;
   1458 			}
   1459 
   1460 			/*
   1461 			 * If this RRset is pending and it is trusted,
   1462 			 * see if it was self signed by this DNSKEY.
   1463 			 */
   1464 			if (DNS_TRUST_PENDING(rdataset->trust) &&
   1465 			    dns_view_istrusted(val->view, name, &key))
   1466 			{
   1467 				result = dns_dnssec_keyfromrdata(
   1468 					name, &keyrdata, mctx, &dstkey);
   1469 				if (result == DST_R_UNSUPPORTEDALG) {
   1470 					/* don't count towards max fails */
   1471 					break; /* continue with next key */
   1472 				} else if (result != ISC_R_SUCCESS) {
   1473 					consume_validation(val);
   1474 					if (over_max_fails(val)) {
   1475 						return ISC_R_QUOTA;
   1476 					}
   1477 					consume_validation_fail(val);
   1478 					break; /* continue with next key */
   1479 				}
   1480 
   1481 				if (over_max_validations(val)) {
   1482 					dst_key_free(&dstkey);
   1483 					return ISC_R_QUOTA;
   1484 				}
   1485 				consume_validation(val);
   1486 
   1487 				result = dns_dnssec_verify(
   1488 					name, rdataset, dstkey, true,
   1489 					val->view->maxbits, mctx, &sigrdata,
   1490 					NULL);
   1491 				switch (result) {
   1492 				case DNS_R_SIGFUTURE:
   1493 				case DNS_R_SIGEXPIRED:
   1494 					/*
   1495 					 * Temporal errors don't count towards
   1496 					 * max fails.
   1497 					 */
   1498 					break;
   1499 				case ISC_R_SUCCESS:
   1500 					/*
   1501 					 * The key with the REVOKE flag has
   1502 					 * self signed the RRset so it is no
   1503 					 * good.
   1504 					 */
   1505 					dns_view_untrust(val->view, name, &key);
   1506 					break;
   1507 				default:
   1508 					if (over_max_fails(val)) {
   1509 						dst_key_free(&dstkey);
   1510 						return ISC_R_QUOTA;
   1511 					}
   1512 					consume_validation_fail(val);
   1513 				}
   1514 
   1515 				dst_key_free(&dstkey);
   1516 			} else if (rdataset->trust >= dns_trust_secure) {
   1517 				/*
   1518 				 * We trust this RRset so if the key is
   1519 				 * marked revoked remove it.
   1520 				 */
   1521 				dns_view_untrust(val->view, name, &key);
   1522 			}
   1523 		}
   1524 	}
   1525 
   1526 	if (!match) {
   1527 		return DNS_R_NOKEYMATCH;
   1528 	}
   1529 
   1530 	return ISC_R_SUCCESS;
   1531 }
   1532 
   1533 /*%
   1534  * Attempt to verify the rdataset using the given key and rdata (RRSIG).
   1535  * The signature was good and from a wildcard record and the QNAME does
   1536  * not match the wildcard we need to look for a NOQNAME proof.
   1537  *
   1538  * Returns:
   1539  * \li	ISC_R_SUCCESS if the verification succeeds.
   1540  * \li	Others if the verification fails.
   1541  */
   1542 static isc_result_t
   1543 verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata,
   1544        uint16_t keyid) {
   1545 	isc_result_t result;
   1546 	dns_fixedname_t fixed;
   1547 	bool ignore = false;
   1548 	dns_name_t *wild = dns_fixedname_initname(&fixed);
   1549 
   1550 	if (DNS_TRUST_SECURE(val->rdataset->trust)) {
   1551 		/*
   1552 		 * This RRset was already verified before.
   1553 		 */
   1554 		return ISC_R_SUCCESS;
   1555 	}
   1556 
   1557 	val->attributes |= VALATTR_TRIEDVERIFY;
   1558 	if (over_max_validations(val)) {
   1559 		return ISC_R_QUOTA;
   1560 	}
   1561 	consume_validation(val);
   1562 
   1563 again:
   1564 	result = dns_dnssec_verify(val->name, val->rdataset, key, ignore,
   1565 				   val->view->maxbits, val->view->mctx, rdata,
   1566 				   wild);
   1567 	if ((result == DNS_R_SIGEXPIRED || result == DNS_R_SIGFUTURE) &&
   1568 	    val->view->acceptexpired)
   1569 	{
   1570 		ignore = true;
   1571 		goto again;
   1572 	}
   1573 
   1574 	if (ignore && (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD))
   1575 	{
   1576 		validator_log(val, ISC_LOG_INFO,
   1577 			      "accepted expired %sRRSIG (keyid=%u)",
   1578 			      (result == DNS_R_FROMWILDCARD) ? "wildcard " : "",
   1579 			      keyid);
   1580 	} else if (result == DNS_R_SIGEXPIRED || result == DNS_R_SIGFUTURE) {
   1581 		validator_log(val, ISC_LOG_INFO,
   1582 			      "verify failed due to bad signature (keyid=%u): "
   1583 			      "%s",
   1584 			      keyid, isc_result_totext(result));
   1585 	} else {
   1586 		validator_log(val, ISC_LOG_DEBUG(3),
   1587 			      "verify rdataset (keyid=%u): %s", keyid,
   1588 			      isc_result_totext(result));
   1589 	}
   1590 	if (result == DNS_R_FROMWILDCARD) {
   1591 		if (!dns_name_equal(val->name, wild)) {
   1592 			dns_name_t *closest;
   1593 			unsigned int labels;
   1594 
   1595 			/*
   1596 			 * Compute the closest encloser in case we need it
   1597 			 * for the NSEC3 NOQNAME proof.
   1598 			 */
   1599 			closest = dns_fixedname_name(&val->closest);
   1600 			dns_name_copy(wild, closest);
   1601 			labels = dns_name_countlabels(closest) - 1;
   1602 			dns_name_getlabelsequence(closest, 1, labels, closest);
   1603 			val->attributes |= VALATTR_NEEDNOQNAME;
   1604 		}
   1605 		result = ISC_R_SUCCESS;
   1606 	}
   1607 
   1608 	switch (result) {
   1609 	case DNS_R_SIGFUTURE:
   1610 	case DNS_R_SIGEXPIRED:
   1611 		/*
   1612 		 * Temporal errors don't count towards max fails.
   1613 		 */
   1614 		validator_addede(val,
   1615 				 result == DNS_R_SIGEXPIRED
   1616 					 ? DNS_EDE_SIGNATUREEXPIRED
   1617 					 : DNS_EDE_SIGNATURENOTYETVALID,
   1618 				 NULL);
   1619 		break;
   1620 	case ISC_R_SUCCESS:
   1621 		break;
   1622 	default:
   1623 		if (over_max_fails(val)) {
   1624 			result = ISC_R_QUOTA;
   1625 			break;
   1626 		}
   1627 		consume_validation_fail(val);
   1628 	}
   1629 	return result;
   1630 }
   1631 
   1632 /*%
   1633  * Attempts positive response validation of a normal RRset.
   1634  *
   1635  * Returns:
   1636  * \li	ISC_R_SUCCESS	Validation completed successfully
   1637  * \li	DNS_R_WAIT	Validation has started but is waiting
   1638  *			for an event.
   1639  * \li	Other return codes are possible and all indicate failure.
   1640  */
   1641 
   1642 static void
   1643 validate_answer_iter_next(void *arg);
   1644 static void
   1645 validate_answer_process(void *arg);
   1646 static void
   1647 validate_answer_iter_done(dns_validator_t *val, isc_result_t result);
   1648 
   1649 static void
   1650 validator_cancel_finish(dns_validator_t *validator);
   1651 
   1652 static void
   1653 validate_answer_iter_start(dns_validator_t *val) {
   1654 	isc_result_t result = ISC_R_SUCCESS;
   1655 
   1656 	/*
   1657 	 * Caller must be holding the validator lock.
   1658 	 */
   1659 
   1660 	val->attributes &= ~VALATTR_OFFLOADED;
   1661 	if (CANCELING(val)) {
   1662 		validator_cancel_finish(val);
   1663 		result = ISC_R_CANCELED;
   1664 		goto cleanup;
   1665 	}
   1666 
   1667 	if (val->resume) {
   1668 		/* We already have a sigrdataset. */
   1669 		result = ISC_R_SUCCESS;
   1670 		validator_log(val, ISC_LOG_DEBUG(3), "resuming validate");
   1671 	} else {
   1672 		result = dns_rdataset_first(val->sigrdataset);
   1673 	}
   1674 
   1675 cleanup:
   1676 	if (result != ISC_R_SUCCESS) {
   1677 		validate_answer_iter_done(val, result);
   1678 		return;
   1679 	}
   1680 
   1681 	val->unsupported_algorithm = 0;
   1682 	val->unsupported_digest = 0;
   1683 	result = validate_async_run(val, validate_answer_process);
   1684 	INSIST(result == DNS_R_WAIT);
   1685 }
   1686 
   1687 static void
   1688 validate_answer_iter_next(void *arg) {
   1689 	dns_validator_t *val = arg;
   1690 	isc_result_t result;
   1691 
   1692 	val->attributes &= ~VALATTR_OFFLOADED;
   1693 	if (CANCELING(val)) {
   1694 		validator_cancel_finish(val);
   1695 		result = ISC_R_CANCELED;
   1696 		goto cleanup;
   1697 	}
   1698 
   1699 	val->resume = false;
   1700 	result = dns_rdataset_next(val->sigrdataset);
   1701 
   1702 cleanup:
   1703 	if (result != ISC_R_SUCCESS) {
   1704 		validate_answer_iter_done(val, result);
   1705 		return;
   1706 	}
   1707 
   1708 	(void)validate_async_run(val, validate_answer_process);
   1709 }
   1710 
   1711 static void
   1712 validate_answer_finish(void *arg);
   1713 
   1714 static void
   1715 validate_answer_signing_key_done(void *arg);
   1716 
   1717 static void
   1718 validate_answer_signing_key(void *arg) {
   1719 	dns_validator_t *val = arg;
   1720 	isc_result_t result;
   1721 
   1722 	if (CANCELED(val) || CANCELING(val)) {
   1723 		val->result = ISC_R_CANCELED;
   1724 	} else {
   1725 		val->result = verify(val, val->key, &val->rdata,
   1726 				     val->siginfo->keyid);
   1727 	}
   1728 
   1729 	switch (val->result) {
   1730 	case ISC_R_CANCELED:	 /* Validation was canceled */
   1731 	case ISC_R_SHUTTINGDOWN: /* Server shutting down */
   1732 	case ISC_R_QUOTA:	 /* Validation fails quota reached */
   1733 	case ISC_R_SUCCESS: /* We found our valid signature, we are done! */
   1734 		if (val->key != NULL) {
   1735 			dst_key_free(&val->key);
   1736 			val->key = NULL;
   1737 		}
   1738 
   1739 		break;
   1740 	default:
   1741 		/* Select next signing key */
   1742 		result = select_signing_key(val, val->keyset);
   1743 		if (result == ISC_R_SUCCESS) {
   1744 			INSIST(val->key != NULL);
   1745 		} else if (result == ISC_R_NOTFOUND) {
   1746 			INSIST(val->key == NULL);
   1747 		} else {
   1748 			val->result = result;
   1749 			if (over_max_fails(val)) {
   1750 				INSIST(val->key == NULL);
   1751 				val->result = ISC_R_QUOTA;
   1752 			}
   1753 			consume_validation_fail(val);
   1754 		}
   1755 		break;
   1756 	}
   1757 
   1758 	(void)validate_async_run(val, validate_answer_signing_key_done);
   1759 }
   1760 
   1761 static void
   1762 validate_answer_signing_key_done(void *arg) {
   1763 	dns_validator_t *val = arg;
   1764 
   1765 	val->attributes &= ~VALATTR_OFFLOADED;
   1766 	if (CANCELING(val)) {
   1767 		validator_cancel_finish(val);
   1768 		val->result = ISC_R_CANCELED;
   1769 	} else if (val->key != NULL) {
   1770 		/* Process with next key if we selected one */
   1771 		(void)validate_helper_run(val, validate_answer_signing_key);
   1772 		return;
   1773 	}
   1774 
   1775 	validate_answer_finish(val);
   1776 }
   1777 
   1778 static void
   1779 validate_answer_process(void *arg) {
   1780 	dns_validator_t *val = arg;
   1781 	isc_result_t result;
   1782 
   1783 	val->attributes &= ~VALATTR_OFFLOADED;
   1784 	if (CANCELING(val)) {
   1785 		validator_cancel_finish(val);
   1786 		result = ISC_R_CANCELED;
   1787 		goto cleanup;
   1788 	}
   1789 
   1790 	dns_rdata_reset(&val->rdata);
   1791 
   1792 	dns_rdataset_current(val->sigrdataset, &val->rdata);
   1793 	if (val->siginfo == NULL) {
   1794 		val->siginfo = isc_mem_get(val->view->mctx,
   1795 					   sizeof(*val->siginfo));
   1796 	}
   1797 	result = dns_rdata_tostruct(&val->rdata, val->siginfo, NULL);
   1798 	if (result != ISC_R_SUCCESS) {
   1799 		goto cleanup;
   1800 	}
   1801 
   1802 	/*
   1803 	 * At this point we could check that the signature algorithm
   1804 	 * was known and "sufficiently good".
   1805 	 */
   1806 	if (!dns_resolver_algorithm_supported(val->view->resolver,
   1807 					      &val->siginfo->signer,
   1808 					      val->siginfo->algorithm))
   1809 	{
   1810 		if (val->unsupported_algorithm == 0) {
   1811 			val->unsupported_algorithm = val->siginfo->algorithm;
   1812 		}
   1813 		goto next_key;
   1814 	}
   1815 
   1816 	if (!val->resume) {
   1817 		result = seek_dnskey(val);
   1818 		switch (result) {
   1819 		case ISC_R_SUCCESS:
   1820 			break;
   1821 		case DNS_R_CONTINUE:
   1822 			goto next_key;
   1823 		case DNS_R_WAIT:
   1824 			goto cleanup;
   1825 		default:
   1826 			goto cleanup;
   1827 		}
   1828 	}
   1829 
   1830 	/*
   1831 	 * There isn't a secure DNSKEY for this signature so move
   1832 	 * onto the next RRSIG.
   1833 	 */
   1834 	if (val->key == NULL) {
   1835 		val->resume = false;
   1836 		goto next_key;
   1837 	}
   1838 
   1839 	(void)validate_helper_run(val, validate_answer_signing_key);
   1840 	return;
   1841 
   1842 next_key:
   1843 	result = validate_async_run(val, validate_answer_iter_next);
   1844 	goto cleanup;
   1845 
   1846 cleanup:
   1847 	validate_async_done(val, result);
   1848 }
   1849 
   1850 static void
   1851 validate_answer_finish(void *arg) {
   1852 	dns_validator_t *val = arg;
   1853 	isc_result_t result = ISC_R_UNSET;
   1854 
   1855 	if (val->result == ISC_R_SUCCESS) {
   1856 		dns_rdataset_trimttl(val->rdataset, val->sigrdataset,
   1857 				     val->siginfo, val->start,
   1858 				     val->view->acceptexpired);
   1859 	}
   1860 
   1861 	if (val->key != NULL) {
   1862 		dst_key_free(&val->key);
   1863 		val->key = NULL;
   1864 	}
   1865 	if (val->keyset != NULL) {
   1866 		dns_rdataset_disassociate(val->keyset);
   1867 		val->keyset = NULL;
   1868 	}
   1869 
   1870 	switch (val->result) {
   1871 	case ISC_R_CANCELED:
   1872 		validator_log(val, ISC_LOG_DEBUG(3), "validation was canceled");
   1873 		validate_async_done(val, val->result);
   1874 		return;
   1875 	case ISC_R_SHUTTINGDOWN:
   1876 		validator_log(val, ISC_LOG_DEBUG(3), "server is shutting down");
   1877 		validate_async_done(val, val->result);
   1878 		return;
   1879 	case ISC_R_QUOTA:
   1880 		if (MAXVALIDATIONS(val)) {
   1881 			validator_log(val, ISC_LOG_DEBUG(3),
   1882 				      "maximum number of validations exceeded");
   1883 		} else if (MAXVALIDATIONFAILS(val)) {
   1884 			validator_log(val, ISC_LOG_DEBUG(3),
   1885 				      "maximum number of validation failures "
   1886 				      "exceeded");
   1887 		} else {
   1888 			validator_log(
   1889 				val, ISC_LOG_DEBUG(3),
   1890 				"unknown error: validation quota exceeded");
   1891 		}
   1892 		validate_async_done(val, val->result);
   1893 		return;
   1894 	default:
   1895 		break;
   1896 	}
   1897 
   1898 	if (NEEDNOQNAME(val)) {
   1899 		if (val->message == NULL) {
   1900 			validator_log(val, ISC_LOG_DEBUG(3),
   1901 				      "no message available for noqname proof");
   1902 			validate_async_done(val, DNS_R_NOVALIDSIG);
   1903 			return;
   1904 		}
   1905 
   1906 		validator_log(val, ISC_LOG_DEBUG(3),
   1907 			      "looking for noqname proof");
   1908 		result = validate_nx(val, false);
   1909 		validate_async_done(val, result);
   1910 		return;
   1911 	}
   1912 
   1913 	if (val->result == ISC_R_SUCCESS) {
   1914 		marksecure(val, "noqname proof not needed");
   1915 		validate_async_done(val, val->result);
   1916 		return;
   1917 	}
   1918 
   1919 	validator_log(val, ISC_LOG_DEBUG(3), "verify failure: %s",
   1920 		      isc_result_totext(val->result));
   1921 	(void)validate_async_run(val, validate_answer_iter_next);
   1922 }
   1923 
   1924 static void
   1925 validate_answer_iter_done(dns_validator_t *val, isc_result_t result) {
   1926 	if (result != ISC_R_NOMORE) {
   1927 		validator_log(val, ISC_LOG_DEBUG(3),
   1928 			      "failed to iterate signatures: %s",
   1929 			      isc_result_totext(result));
   1930 		validate_async_done(val, result);
   1931 		return;
   1932 	}
   1933 
   1934 	if (result != ISC_R_SUCCESS && result != DNS_R_WAIT) {
   1935 		validate_extendederror(val);
   1936 	}
   1937 
   1938 	validator_log(val, ISC_LOG_INFO, "no valid signature found");
   1939 	validate_async_done(val, val->result);
   1940 }
   1941 
   1942 static void
   1943 resume_answer(void *arg) {
   1944 	dns_validator_t *val = arg;
   1945 
   1946 	val->resume = true;
   1947 	validate_answer_iter_start(val);
   1948 }
   1949 
   1950 static void
   1951 validate_answer(void *arg) {
   1952 	dns_validator_t *val = arg;
   1953 	val->resume = false;
   1954 	validate_answer_iter_start(val);
   1955 }
   1956 
   1957 static isc_result_t
   1958 validate_async_run(dns_validator_t *val, isc_job_cb cb) {
   1959 	isc_async_run(val->loop, cb, val);
   1960 	return DNS_R_WAIT;
   1961 }
   1962 
   1963 static isc_result_t
   1964 validate_helper_run(dns_validator_t *val, isc_job_cb cb) {
   1965 	val->attributes |= VALATTR_OFFLOADED;
   1966 	isc_helper_run(val->loop, cb, val);
   1967 	return DNS_R_WAIT;
   1968 }
   1969 
   1970 static void
   1971 validate_async_done(dns_validator_t *val, isc_result_t result) {
   1972 	if (result == DNS_R_NOVALIDSIG &&
   1973 	    (val->attributes & VALATTR_TRIEDVERIFY) == 0)
   1974 	{
   1975 		isc_result_t saved_result = result;
   1976 		validator_log(val, ISC_LOG_DEBUG(3),
   1977 			      "falling back to insecurity proof");
   1978 		result = proveunsecure(val, false, false);
   1979 		if (result == DNS_R_NOTINSECURE) {
   1980 			result = saved_result;
   1981 		}
   1982 	}
   1983 
   1984 	if (result != DNS_R_WAIT) {
   1985 		/* We are still continuing */
   1986 		validator_done(val, result);
   1987 		dns_validator_detach(&val);
   1988 	}
   1989 }
   1990 
   1991 /*%
   1992  * Check whether this DNSKEY (keyrdata) signed the DNSKEY RRset
   1993  * (val->rdataset).
   1994  */
   1995 static isc_result_t
   1996 check_signer(dns_validator_t *val, dns_rdata_t *keyrdata, uint16_t keyid,
   1997 	     dns_secalg_t algorithm) {
   1998 	dns_rdata_rrsig_t sig;
   1999 	dst_key_t *dstkey = NULL;
   2000 	isc_result_t result;
   2001 	dns_rdataset_t rdataset = DNS_RDATASET_INIT;
   2002 
   2003 	result = dns_dnssec_keyfromrdata(val->name, keyrdata, val->view->mctx,
   2004 					 &dstkey);
   2005 	if (result != ISC_R_SUCCESS) {
   2006 		return result;
   2007 	}
   2008 
   2009 	dns_rdataset_clone(val->sigrdataset, &rdataset);
   2010 
   2011 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   2012 	     result = dns_rdataset_next(&rdataset))
   2013 	{
   2014 		dns_rdata_t rdata = DNS_RDATA_INIT;
   2015 
   2016 		dns_rdataset_current(&rdataset, &rdata);
   2017 		result = dns_rdata_tostruct(&rdata, &sig, NULL);
   2018 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   2019 		if (keyid != sig.keyid || algorithm != sig.algorithm) {
   2020 			continue;
   2021 		}
   2022 
   2023 		result = verify(val, dstkey, &rdata, sig.keyid);
   2024 		if (result == ISC_R_SUCCESS || result == ISC_R_QUOTA) {
   2025 			break;
   2026 		}
   2027 	}
   2028 
   2029 	dst_key_free(&dstkey);
   2030 	dns_rdataset_disassociate(&rdataset);
   2031 
   2032 	return result;
   2033 }
   2034 
   2035 /*
   2036  * get_dsset() is called to look up a DS RRset corresponding to the name
   2037  * of a DNSKEY record, either in the cache or, if necessary, by starting a
   2038  * fetch. This is done in the context of validating a zone key to build a
   2039  * trust chain.
   2040  *
   2041  * Returns:
   2042  * \li	ISC_R_COMPLETE		a DS has not been found; the caller should
   2043  *				stop trying to validate the zone key and
   2044  *				return the result code in '*resp'.
   2045  * \li	DNS_R_CONTINUE		a DS has been found and the caller may
   2046  * 				continue the zone key validation.
   2047  */
   2048 static isc_result_t
   2049 get_dsset(dns_validator_t *val, dns_name_t *tname, isc_result_t *resp) {
   2050 	isc_result_t result;
   2051 
   2052 	result = view_find(val, tname, dns_rdatatype_ds);
   2053 	switch (result) {
   2054 	case ISC_R_SUCCESS:
   2055 		/*
   2056 		 * We have a DS RRset.
   2057 		 */
   2058 		val->dsset = &val->frdataset;
   2059 		if (DNS_TRUST_PENDING(val->frdataset.trust) ||
   2060 		    DNS_TRUST_ANSWER(val->frdataset.trust))
   2061 		{
   2062 			/*
   2063 			 * ... which is signed but not yet validated.
   2064 			 */
   2065 			result = create_validator(
   2066 				val, tname, dns_rdatatype_ds, &val->frdataset,
   2067 				&val->fsigrdataset, validator_callback_ds,
   2068 				"get_dsset");
   2069 			*resp = DNS_R_WAIT;
   2070 			if (result != ISC_R_SUCCESS) {
   2071 				*resp = result;
   2072 			}
   2073 			return ISC_R_COMPLETE;
   2074 		}
   2075 		break;
   2076 
   2077 	case ISC_R_NOTFOUND:
   2078 		/*
   2079 		 * We don't have the DS.  Find it.
   2080 		 */
   2081 		result = create_fetch(val, tname, dns_rdatatype_ds,
   2082 				      fetch_callback_ds, "validate_dnskey");
   2083 		*resp = DNS_R_WAIT;
   2084 		if (result != ISC_R_SUCCESS) {
   2085 			*resp = result;
   2086 		}
   2087 		return ISC_R_COMPLETE;
   2088 
   2089 	case DNS_R_NCACHENXDOMAIN:
   2090 	case DNS_R_NCACHENXRRSET:
   2091 	case DNS_R_EMPTYNAME:
   2092 	case DNS_R_NXDOMAIN:
   2093 	case DNS_R_NXRRSET:
   2094 	case DNS_R_CNAME:
   2095 		/*
   2096 		 * The DS does not exist.
   2097 		 */
   2098 		disassociate_rdatasets(val);
   2099 		validator_log(val, ISC_LOG_DEBUG(2), "no DS record");
   2100 		*resp = DNS_R_NOVALIDSIG;
   2101 		return ISC_R_COMPLETE;
   2102 
   2103 	case DNS_R_BROKENCHAIN:
   2104 		*resp = result;
   2105 		return ISC_R_COMPLETE;
   2106 
   2107 	default:
   2108 		break;
   2109 	}
   2110 
   2111 	return DNS_R_CONTINUE;
   2112 }
   2113 
   2114 static void
   2115 validate_dnskey_dsset_done(dns_validator_t *val, isc_result_t result) {
   2116 	switch (result) {
   2117 	case ISC_R_CANCELED:
   2118 	case ISC_R_SHUTTINGDOWN:
   2119 		/* Abort, abort, abort! */
   2120 		break;
   2121 	case ISC_R_SUCCESS:
   2122 		marksecure(val, "validate_dnskey (DS)");
   2123 		break;
   2124 	case ISC_R_NOMORE:
   2125 		if (val->unsupported_algorithm != 0 ||
   2126 		    val->unsupported_digest != 0)
   2127 		{
   2128 			validator_log(val, ISC_LOG_DEBUG(3),
   2129 				      "no supported algorithm/digest (DS)");
   2130 			result = markanswer(
   2131 				val, "validate_dnskey (3)",
   2132 				"no supported algorithm/digest (DS)");
   2133 			validate_extendederror(val);
   2134 			break;
   2135 		}
   2136 		FALLTHROUGH;
   2137 	default:
   2138 		validator_log(val, ISC_LOG_INFO,
   2139 			      "no valid signature found (DS)");
   2140 		result = DNS_R_NOVALIDSIG;
   2141 	}
   2142 
   2143 	if (val->dsset == &val->fdsset) {
   2144 		val->dsset = NULL;
   2145 		dns_rdataset_disassociate(&val->fdsset);
   2146 	}
   2147 
   2148 	validate_async_done(val, result);
   2149 }
   2150 
   2151 static isc_result_t
   2152 validate_dnskey_dsset(dns_validator_t *val) {
   2153 	dns_rdata_t dsrdata = DNS_RDATA_INIT;
   2154 	dns_rdata_t keyrdata = DNS_RDATA_INIT;
   2155 	isc_result_t result;
   2156 	dns_rdata_ds_t ds;
   2157 
   2158 	dns_rdata_reset(&dsrdata);
   2159 	dns_rdataset_current(val->dsset, &dsrdata);
   2160 	result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
   2161 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   2162 
   2163 	if (ds.digest_type == DNS_DSDIGEST_SHA1 && val->digest_sha1 == false) {
   2164 		return DNS_R_BADALG;
   2165 	}
   2166 
   2167 	if (!dns_resolver_ds_digest_supported(val->view->resolver, val->name,
   2168 					      ds.digest_type))
   2169 	{
   2170 		if (val->unsupported_digest == 0) {
   2171 			val->unsupported_digest = ds.digest_type;
   2172 		}
   2173 		return DNS_R_BADALG;
   2174 	}
   2175 
   2176 	if (!dns_resolver_algorithm_supported(val->view->resolver, val->name,
   2177 					      ds.algorithm))
   2178 	{
   2179 		if (val->unsupported_algorithm == 0) {
   2180 			val->unsupported_algorithm = ds.algorithm;
   2181 		}
   2182 		return DNS_R_BADALG;
   2183 	}
   2184 
   2185 	val->validation_attempts++;
   2186 
   2187 	/*
   2188 	 * Find the DNSKEY matching the DS...
   2189 	 */
   2190 	result = dns_dnssec_matchdskey(val->name, &dsrdata, val->rdataset,
   2191 				       &keyrdata);
   2192 	if (result != ISC_R_SUCCESS) {
   2193 		validator_log(val, ISC_LOG_DEBUG(3), "no DNSKEY matching DS");
   2194 		return DNS_R_NOKEYMATCH;
   2195 	}
   2196 
   2197 	/*
   2198 	 * ... and check that it signed the DNSKEY RRset.
   2199 	 */
   2200 	result = check_signer(val, &keyrdata, ds.key_tag, ds.algorithm);
   2201 	if (result != ISC_R_SUCCESS) {
   2202 		validator_log(val, ISC_LOG_DEBUG(3),
   2203 			      "no RRSIG matching DS key");
   2204 
   2205 		return DNS_R_NOVALIDSIG;
   2206 	}
   2207 
   2208 	return ISC_R_SUCCESS;
   2209 }
   2210 
   2211 static void
   2212 validate_dnskey_dsset_next_done(void *arg);
   2213 
   2214 static void
   2215 validate_dnskey_dsset_next(void *arg) {
   2216 	dns_validator_t *val = arg;
   2217 
   2218 	if (CANCELED(val) || CANCELING(val)) {
   2219 		val->result = ISC_R_CANCELED;
   2220 	} else {
   2221 		val->result = dns_rdataset_next(val->dsset);
   2222 	}
   2223 
   2224 	if (val->result == ISC_R_SUCCESS) {
   2225 		/* continue async run */
   2226 		val->result = validate_dnskey_dsset(val);
   2227 	}
   2228 
   2229 	validate_async_run(val, validate_dnskey_dsset_next_done);
   2230 }
   2231 
   2232 static void
   2233 validate_dnskey_dsset_next_done(void *arg) {
   2234 	dns_validator_t *val = arg;
   2235 	isc_result_t result = val->result;
   2236 
   2237 	val->attributes &= ~VALATTR_OFFLOADED;
   2238 	if (CANCELING(val)) {
   2239 		validator_cancel_finish(val);
   2240 		result = ISC_R_CANCELED;
   2241 	}
   2242 
   2243 	switch (result) {
   2244 	case ISC_R_CANCELED:
   2245 	case ISC_R_SHUTTINGDOWN:
   2246 		/* Abort, abort, abort! */
   2247 		break;
   2248 	case ISC_R_SUCCESS:
   2249 	case ISC_R_NOMORE:
   2250 		/* We are done */
   2251 		break;
   2252 	default:
   2253 		/* Continue validation until we have success or no more data */
   2254 		(void)validate_helper_run(val, validate_dnskey_dsset_next);
   2255 		return;
   2256 	}
   2257 
   2258 	if (val->validation_attempts != 0) {
   2259 		val->unsupported_algorithm = 0;
   2260 		val->unsupported_digest = 0;
   2261 	}
   2262 
   2263 	validate_dnskey_dsset_done(val, result);
   2264 	return;
   2265 }
   2266 
   2267 static void
   2268 validate_dnskey_dsset_first(dns_validator_t *val) {
   2269 	isc_result_t result;
   2270 
   2271 	if (CANCELED(val) || CANCELING(val)) {
   2272 		result = ISC_R_CANCELED;
   2273 	} else {
   2274 		result = dns_rdataset_first(val->dsset);
   2275 	}
   2276 
   2277 	if (result == ISC_R_SUCCESS) {
   2278 		/* continue async run */
   2279 		result = validate_dnskey_dsset(val);
   2280 		if (result != ISC_R_SUCCESS) {
   2281 			(void)validate_helper_run(val,
   2282 						  validate_dnskey_dsset_next);
   2283 			return;
   2284 		}
   2285 	}
   2286 
   2287 	validate_dnskey_dsset_done(val, result);
   2288 }
   2289 
   2290 static void
   2291 validate_dnskey(void *arg) {
   2292 	dns_validator_t *val = arg;
   2293 	isc_result_t result = ISC_R_SUCCESS;
   2294 	dns_keynode_t *keynode = NULL;
   2295 	dns_rdata_ds_t ds;
   2296 
   2297 	if (CANCELED(val) || CANCELING(val)) {
   2298 		result = ISC_R_CANCELED;
   2299 		goto cleanup;
   2300 	}
   2301 
   2302 	/*
   2303 	 * If we don't already have a DS RRset, check to see if there's
   2304 	 * a DS style trust anchor configured for this key.
   2305 	 */
   2306 	if (val->dsset == NULL) {
   2307 		result = dns_keytable_find(val->keytable, val->name, &keynode);
   2308 		if (result == ISC_R_SUCCESS) {
   2309 			if (dns_keynode_dsset(keynode, &val->fdsset)) {
   2310 				val->dsset = &val->fdsset;
   2311 			}
   2312 			dns_keynode_detach(&keynode);
   2313 		}
   2314 	}
   2315 
   2316 	/*
   2317 	 * No trust anchor for this name, so we look up the DS at the parent.
   2318 	 */
   2319 	if (val->dsset == NULL) {
   2320 		isc_result_t tresult = ISC_R_SUCCESS;
   2321 
   2322 		/*
   2323 		 * If this is the root name and there was no trust anchor,
   2324 		 * we can give up now, since there's no DS at the root.
   2325 		 */
   2326 		if (dns_name_equal(val->name, dns_rootname)) {
   2327 			if ((val->attributes & VALATTR_TRIEDVERIFY) != 0) {
   2328 				validator_log(val, ISC_LOG_DEBUG(3),
   2329 					      "root key failed to validate");
   2330 			} else {
   2331 				validator_log(val, ISC_LOG_DEBUG(3),
   2332 					      "no trusted root key");
   2333 			}
   2334 			result = DNS_R_NOVALIDSIG;
   2335 			goto cleanup;
   2336 		}
   2337 
   2338 		/*
   2339 		 * Look up the DS RRset for this name.
   2340 		 */
   2341 		result = get_dsset(val, val->name, &tresult);
   2342 		if (result == ISC_R_COMPLETE) {
   2343 			result = tresult;
   2344 			goto cleanup;
   2345 		}
   2346 	}
   2347 
   2348 	/*
   2349 	 * We have a DS set.
   2350 	 */
   2351 	INSIST(val->dsset != NULL);
   2352 
   2353 	if (val->dsset->trust < dns_trust_secure) {
   2354 		result = markanswer(val, "validate_dnskey (2)", "insecure DS");
   2355 		goto cleanup;
   2356 	}
   2357 
   2358 	/*
   2359 	 * Look through the DS record and find the keys that can sign the
   2360 	 * key set and the matching signature.  For each such key, attempt
   2361 	 * verification.
   2362 	 */
   2363 	val->unsupported_algorithm = 0;
   2364 	val->unsupported_digest = 0;
   2365 
   2366 	/*
   2367 	 * If DNS_DSDIGEST_SHA256 or DNS_DSDIGEST_SHA384 is present we
   2368 	 * are required to prefer it over DNS_DSDIGEST_SHA1.  This in
   2369 	 * practice means that we need to ignore DNS_DSDIGEST_SHA1 if a
   2370 	 * DNS_DSDIGEST_SHA256 or DNS_DSDIGEST_SHA384 is present.
   2371 	 */
   2372 	val->digest_sha1 = true;
   2373 	dns_rdata_t dsrdata = DNS_RDATA_INIT;
   2374 	for (result = dns_rdataset_first(val->dsset); result == ISC_R_SUCCESS;
   2375 	     result = dns_rdataset_next(val->dsset))
   2376 	{
   2377 		dns_rdata_reset(&dsrdata);
   2378 		dns_rdataset_current(val->dsset, &dsrdata);
   2379 		result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
   2380 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   2381 
   2382 		if (!dns_resolver_ds_digest_supported(
   2383 			    val->view->resolver, val->name, ds.digest_type))
   2384 		{
   2385 			continue;
   2386 		}
   2387 
   2388 		if (!dns_resolver_algorithm_supported(val->view->resolver,
   2389 						      val->name, ds.algorithm))
   2390 		{
   2391 			continue;
   2392 		}
   2393 
   2394 		if ((ds.digest_type == DNS_DSDIGEST_SHA256 &&
   2395 		     ds.length == ISC_SHA256_DIGESTLENGTH) ||
   2396 		    (ds.digest_type == DNS_DSDIGEST_SHA384 &&
   2397 		     ds.length == ISC_SHA384_DIGESTLENGTH))
   2398 		{
   2399 			val->digest_sha1 = false;
   2400 			break;
   2401 		}
   2402 	}
   2403 
   2404 	validate_dnskey_dsset_first(val);
   2405 	return;
   2406 
   2407 cleanup:
   2408 	if (val->dsset == &val->fdsset) {
   2409 		val->dsset = NULL;
   2410 		dns_rdataset_disassociate(&val->fdsset);
   2411 	}
   2412 	validate_async_done(val, result);
   2413 }
   2414 
   2415 /*%
   2416  * val_rdataset_first and val_rdataset_next provide iteration methods
   2417  * that hide whether we are iterating across the AUTHORITY section of
   2418  * a message, or a negative cache rdataset.
   2419  */
   2420 static isc_result_t
   2421 val_rdataset_first(dns_validator_t *val, dns_name_t **namep,
   2422 		   dns_rdataset_t **rdatasetp) {
   2423 	dns_message_t *message = val->message;
   2424 	isc_result_t result;
   2425 
   2426 	REQUIRE(rdatasetp != NULL);
   2427 	REQUIRE(namep != NULL);
   2428 	if (message == NULL) {
   2429 		REQUIRE(*rdatasetp != NULL);
   2430 		REQUIRE(*namep != NULL);
   2431 	} else {
   2432 		REQUIRE(*rdatasetp == NULL);
   2433 		REQUIRE(*namep == NULL);
   2434 	}
   2435 
   2436 	if (message != NULL) {
   2437 		result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
   2438 		if (result != ISC_R_SUCCESS) {
   2439 			return result;
   2440 		}
   2441 		dns_message_currentname(message, DNS_SECTION_AUTHORITY, namep);
   2442 		*rdatasetp = ISC_LIST_HEAD((*namep)->list);
   2443 		INSIST(*rdatasetp != NULL);
   2444 	} else {
   2445 		result = dns_rdataset_first(val->rdataset);
   2446 		if (result == ISC_R_SUCCESS) {
   2447 			dns_ncache_current(val->rdataset, *namep, *rdatasetp);
   2448 		}
   2449 	}
   2450 	return result;
   2451 }
   2452 
   2453 static isc_result_t
   2454 val_rdataset_next(dns_validator_t *val, dns_name_t **namep,
   2455 		  dns_rdataset_t **rdatasetp) {
   2456 	dns_message_t *message = val->message;
   2457 	isc_result_t result = ISC_R_SUCCESS;
   2458 
   2459 	REQUIRE(rdatasetp != NULL && *rdatasetp != NULL);
   2460 	REQUIRE(namep != NULL && *namep != NULL);
   2461 
   2462 	if (message != NULL) {
   2463 		dns_rdataset_t *rdataset = *rdatasetp;
   2464 		rdataset = ISC_LIST_NEXT(rdataset, link);
   2465 		if (rdataset == NULL) {
   2466 			*namep = NULL;
   2467 			result = dns_message_nextname(message,
   2468 						      DNS_SECTION_AUTHORITY);
   2469 			if (result == ISC_R_SUCCESS) {
   2470 				dns_message_currentname(
   2471 					message, DNS_SECTION_AUTHORITY, namep);
   2472 				rdataset = ISC_LIST_HEAD((*namep)->list);
   2473 				INSIST(rdataset != NULL);
   2474 			}
   2475 		}
   2476 		*rdatasetp = rdataset;
   2477 	} else {
   2478 		dns_rdataset_disassociate(*rdatasetp);
   2479 		result = dns_rdataset_next(val->rdataset);
   2480 		if (result == ISC_R_SUCCESS) {
   2481 			dns_ncache_current(val->rdataset, *namep, *rdatasetp);
   2482 		}
   2483 	}
   2484 	return result;
   2485 }
   2486 
   2487 /*%
   2488  * Look for NODATA at the wildcard and NOWILDCARD proofs in the
   2489  * previously validated NSEC records.  As these proofs are mutually
   2490  * exclusive we stop when one is found.
   2491  *
   2492  * Returns
   2493  * \li	ISC_R_SUCCESS
   2494  */
   2495 static isc_result_t
   2496 checkwildcard(dns_validator_t *val, dns_rdatatype_t type,
   2497 	      dns_name_t *zonename) {
   2498 	dns_name_t *name, *wild, tname;
   2499 	isc_result_t result;
   2500 	bool exists, data;
   2501 	char namebuf[DNS_NAME_FORMATSIZE];
   2502 	dns_rdataset_t *rdataset, trdataset;
   2503 
   2504 	dns_name_init(&tname, NULL);
   2505 	dns_rdataset_init(&trdataset);
   2506 	wild = dns_fixedname_name(&val->wild);
   2507 
   2508 	if (dns_name_countlabels(wild) == 0) {
   2509 		validator_log(val, ISC_LOG_DEBUG(3),
   2510 			      "in checkwildcard: no wildcard to check");
   2511 		return ISC_R_SUCCESS;
   2512 	}
   2513 
   2514 	dns_name_format(wild, namebuf, sizeof(namebuf));
   2515 	validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf);
   2516 
   2517 	if (val->message == NULL) {
   2518 		name = &tname;
   2519 		rdataset = &trdataset;
   2520 	} else {
   2521 		name = NULL;
   2522 		rdataset = NULL;
   2523 	}
   2524 
   2525 	for (result = val_rdataset_first(val, &name, &rdataset);
   2526 	     result == ISC_R_SUCCESS;
   2527 	     result = val_rdataset_next(val, &name, &rdataset))
   2528 	{
   2529 		if (rdataset->type != type ||
   2530 		    rdataset->trust != dns_trust_secure)
   2531 		{
   2532 			continue;
   2533 		}
   2534 
   2535 		if (rdataset->type == dns_rdatatype_nsec &&
   2536 		    (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
   2537 		    !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
   2538 		    dns_nsec_noexistnodata(val->type, wild, name, rdataset,
   2539 					   &exists, &data, NULL, validator_log,
   2540 					   val) == ISC_R_SUCCESS)
   2541 		{
   2542 			dns_name_t **proofs = val->proofs;
   2543 			if (exists && !data) {
   2544 				val->attributes |= VALATTR_FOUNDNODATA;
   2545 			}
   2546 			if (exists && !data && NEEDNODATA(val)) {
   2547 				proofs[DNS_VALIDATOR_NODATAPROOF] = name;
   2548 			}
   2549 			if (!exists) {
   2550 				val->attributes |= VALATTR_FOUNDNOWILDCARD;
   2551 			}
   2552 			if (!exists && NEEDNOQNAME(val)) {
   2553 				proofs[DNS_VALIDATOR_NOWILDCARDPROOF] = name;
   2554 			}
   2555 			if (dns_rdataset_isassociated(&trdataset)) {
   2556 				dns_rdataset_disassociate(&trdataset);
   2557 			}
   2558 			return ISC_R_SUCCESS;
   2559 		}
   2560 
   2561 		if (rdataset->type == dns_rdatatype_nsec3 &&
   2562 		    (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
   2563 		    !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
   2564 		    dns_nsec3_noexistnodata(
   2565 			    val->type, wild, name, rdataset, zonename, &exists,
   2566 			    &data, NULL, NULL, NULL, NULL, NULL, NULL,
   2567 			    validator_log, val) == ISC_R_SUCCESS)
   2568 		{
   2569 			dns_name_t **proofs = val->proofs;
   2570 			if (exists && !data) {
   2571 				val->attributes |= VALATTR_FOUNDNODATA;
   2572 			}
   2573 			if (exists && !data && NEEDNODATA(val)) {
   2574 				proofs[DNS_VALIDATOR_NODATAPROOF] = name;
   2575 			}
   2576 			if (!exists) {
   2577 				val->attributes |= VALATTR_FOUNDNOWILDCARD;
   2578 			}
   2579 			if (!exists && NEEDNOQNAME(val)) {
   2580 				proofs[DNS_VALIDATOR_NOWILDCARDPROOF] = name;
   2581 			}
   2582 			if (dns_rdataset_isassociated(&trdataset)) {
   2583 				dns_rdataset_disassociate(&trdataset);
   2584 			}
   2585 			return ISC_R_SUCCESS;
   2586 		}
   2587 	}
   2588 	if (result == ISC_R_NOMORE) {
   2589 		result = ISC_R_SUCCESS;
   2590 	}
   2591 	if (dns_rdataset_isassociated(&trdataset)) {
   2592 		dns_rdataset_disassociate(&trdataset);
   2593 	}
   2594 	return result;
   2595 }
   2596 
   2597 /*
   2598  * Look for the needed proofs for a negative or wildcard response
   2599  * from a zone using NSEC3, and set flags in the validator as they
   2600  * are found.
   2601  */
   2602 static isc_result_t
   2603 findnsec3proofs(dns_validator_t *val) {
   2604 	dns_name_t *name, tname;
   2605 	isc_result_t result;
   2606 	bool exists, data, optout, unknown;
   2607 	bool setclosest, setnearest, *setclosestp;
   2608 	dns_fixedname_t fclosest, fnearest, fzonename;
   2609 	dns_name_t *closest, *nearest, *zonename, *closestp;
   2610 	dns_name_t **proofs = val->proofs;
   2611 	dns_rdataset_t *rdataset, trdataset;
   2612 
   2613 	dns_name_init(&tname, NULL);
   2614 	dns_rdataset_init(&trdataset);
   2615 	closest = dns_fixedname_initname(&fclosest);
   2616 	nearest = dns_fixedname_initname(&fnearest);
   2617 	zonename = dns_fixedname_initname(&fzonename);
   2618 
   2619 	if (val->message == NULL) {
   2620 		name = &tname;
   2621 		rdataset = &trdataset;
   2622 	} else {
   2623 		name = NULL;
   2624 		rdataset = NULL;
   2625 	}
   2626 
   2627 	for (result = val_rdataset_first(val, &name, &rdataset);
   2628 	     result == ISC_R_SUCCESS;
   2629 	     result = val_rdataset_next(val, &name, &rdataset))
   2630 	{
   2631 		if (rdataset->type != dns_rdatatype_nsec3 ||
   2632 		    rdataset->trust != dns_trust_secure)
   2633 		{
   2634 			continue;
   2635 		}
   2636 
   2637 		result = dns_nsec3_noexistnodata(val->type, val->name, name,
   2638 						 rdataset, zonename, NULL, NULL,
   2639 						 NULL, NULL, NULL, NULL, NULL,
   2640 						 NULL, validator_log, val);
   2641 		if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS) {
   2642 			if (dns_rdataset_isassociated(&trdataset)) {
   2643 				dns_rdataset_disassociate(&trdataset);
   2644 			}
   2645 			return result;
   2646 		}
   2647 	}
   2648 	if (result != ISC_R_NOMORE) {
   2649 		result = ISC_R_SUCCESS;
   2650 	}
   2651 	POST(result);
   2652 
   2653 	if (dns_name_countlabels(zonename) == 0) {
   2654 		if (dns_rdataset_isassociated(&trdataset)) {
   2655 			dns_rdataset_disassociate(&trdataset);
   2656 		}
   2657 		return ISC_R_SUCCESS;
   2658 	}
   2659 
   2660 	/*
   2661 	 * If the val->closest is set then we want to use it otherwise
   2662 	 * we need to discover it.
   2663 	 */
   2664 	if (dns_name_countlabels(dns_fixedname_name(&val->closest)) != 0) {
   2665 		char namebuf[DNS_NAME_FORMATSIZE];
   2666 
   2667 		dns_name_format(dns_fixedname_name(&val->closest), namebuf,
   2668 				sizeof(namebuf));
   2669 		validator_log(val, ISC_LOG_DEBUG(3),
   2670 			      "closest encloser from wildcard signature '%s'",
   2671 			      namebuf);
   2672 		dns_name_copy(dns_fixedname_name(&val->closest), closest);
   2673 		closestp = NULL;
   2674 		setclosestp = NULL;
   2675 	} else {
   2676 		closestp = closest;
   2677 		setclosestp = &setclosest;
   2678 	}
   2679 
   2680 	for (result = val_rdataset_first(val, &name, &rdataset);
   2681 	     result == ISC_R_SUCCESS;
   2682 	     result = val_rdataset_next(val, &name, &rdataset))
   2683 	{
   2684 		if (rdataset->type != dns_rdatatype_nsec3 ||
   2685 		    rdataset->trust != dns_trust_secure)
   2686 		{
   2687 			continue;
   2688 		}
   2689 
   2690 		/*
   2691 		 * We process all NSEC3 records to find the closest
   2692 		 * encloser and nearest name to the closest encloser.
   2693 		 */
   2694 		setclosest = setnearest = false;
   2695 		optout = false;
   2696 		unknown = false;
   2697 		result = dns_nsec3_noexistnodata(
   2698 			val->type, val->name, name, rdataset, zonename, &exists,
   2699 			&data, &optout, &unknown, setclosestp, &setnearest,
   2700 			closestp, nearest, validator_log, val);
   2701 		if (unknown) {
   2702 			val->attributes |= VALATTR_FOUNDUNKNOWN;
   2703 		}
   2704 		if (result == DNS_R_NSEC3ITERRANGE) {
   2705 			/*
   2706 			 * We don't really know which NSEC3 record provides
   2707 			 * which proof.  Just populate them.
   2708 			 */
   2709 			if (NEEDNOQNAME(val) &&
   2710 			    proofs[DNS_VALIDATOR_NOQNAMEPROOF] == NULL)
   2711 			{
   2712 				proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name;
   2713 			} else if (setclosest) {
   2714 				proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
   2715 			} else if (NEEDNODATA(val) &&
   2716 				   proofs[DNS_VALIDATOR_NODATAPROOF] == NULL)
   2717 			{
   2718 				proofs[DNS_VALIDATOR_NODATAPROOF] = name;
   2719 			} else if (NEEDNOWILDCARD(val) &&
   2720 				   proofs[DNS_VALIDATOR_NOWILDCARDPROOF] ==
   2721 					   NULL)
   2722 			{
   2723 				proofs[DNS_VALIDATOR_NOWILDCARDPROOF] = name;
   2724 			}
   2725 			if (dns_rdataset_isassociated(&trdataset)) {
   2726 				dns_rdataset_disassociate(&trdataset);
   2727 			}
   2728 			return result;
   2729 		}
   2730 		if (result != ISC_R_SUCCESS) {
   2731 			continue;
   2732 		}
   2733 		if (setclosest) {
   2734 			proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
   2735 		}
   2736 		if (exists && !data && NEEDNODATA(val)) {
   2737 			val->attributes |= VALATTR_FOUNDNODATA;
   2738 			proofs[DNS_VALIDATOR_NODATAPROOF] = name;
   2739 		}
   2740 		if (!exists && setnearest) {
   2741 			val->attributes |= VALATTR_FOUNDNOQNAME;
   2742 			proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name;
   2743 			if (optout) {
   2744 				val->attributes |= VALATTR_FOUNDOPTOUT;
   2745 			}
   2746 		}
   2747 	}
   2748 	if (result == ISC_R_NOMORE) {
   2749 		result = ISC_R_SUCCESS;
   2750 	}
   2751 
   2752 	/*
   2753 	 * To know we have a valid noqname and optout proofs we need to also
   2754 	 * have a valid closest encloser.  Otherwise we could still be looking
   2755 	 * at proofs from the parent zone.
   2756 	 */
   2757 	if (dns_name_countlabels(closest) > 0 &&
   2758 	    dns_name_countlabels(nearest) ==
   2759 		    dns_name_countlabels(closest) + 1 &&
   2760 	    dns_name_issubdomain(nearest, closest))
   2761 	{
   2762 		val->attributes |= VALATTR_FOUNDCLOSEST;
   2763 		result = dns_name_concatenate(dns_wildcardname, closest,
   2764 					      dns_fixedname_name(&val->wild),
   2765 					      NULL);
   2766 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   2767 	} else {
   2768 		val->attributes &= ~VALATTR_FOUNDNOQNAME;
   2769 		val->attributes &= ~VALATTR_FOUNDOPTOUT;
   2770 		proofs[DNS_VALIDATOR_NOQNAMEPROOF] = NULL;
   2771 	}
   2772 
   2773 	/*
   2774 	 * Do we need to check for the wildcard?
   2775 	 */
   2776 	if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
   2777 	    ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val)))
   2778 	{
   2779 		result = checkwildcard(val, dns_rdatatype_nsec3, zonename);
   2780 		if (result != ISC_R_SUCCESS) {
   2781 			if (dns_rdataset_isassociated(&trdataset)) {
   2782 				dns_rdataset_disassociate(&trdataset);
   2783 			}
   2784 			return result;
   2785 		}
   2786 	}
   2787 	if (dns_rdataset_isassociated(&trdataset)) {
   2788 		dns_rdataset_disassociate(&trdataset);
   2789 	}
   2790 	return result;
   2791 }
   2792 
   2793 /*
   2794  * Start a validator for negative response data.
   2795  *
   2796  * Returns:
   2797  * \li	DNS_R_CONTINUE	Validation skipped, continue
   2798  * \li	DNS_R_WAIT	Validation is in progress
   2799  *
   2800  * \li	Other return codes indicate failure.
   2801  */
   2802 static isc_result_t
   2803 validate_neg_rrset(dns_validator_t *val, dns_name_t *name,
   2804 		   dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
   2805 	isc_result_t result;
   2806 
   2807 	/*
   2808 	 * If a signed zone is missing the zone key, bad
   2809 	 * things could happen.  A query for data in the zone
   2810 	 * would lead to a query for the zone key, which
   2811 	 * would return a negative answer, which would contain
   2812 	 * an SOA and an NSEC signed by the missing key, which
   2813 	 * would trigger another query for the DNSKEY (since
   2814 	 * the first one is still in progress), and go into an
   2815 	 * infinite loop.  Avoid that.
   2816 	 */
   2817 	if (val->type == dns_rdatatype_dnskey &&
   2818 	    rdataset->type == dns_rdatatype_nsec &&
   2819 	    dns_name_equal(name, val->name))
   2820 	{
   2821 		dns_rdata_t nsec = DNS_RDATA_INIT;
   2822 
   2823 		result = dns_rdataset_first(rdataset);
   2824 		if (result != ISC_R_SUCCESS) {
   2825 			return result;
   2826 		}
   2827 		dns_rdataset_current(rdataset, &nsec);
   2828 		if (dns_nsec_typepresent(&nsec, dns_rdatatype_soa)) {
   2829 			return DNS_R_CONTINUE;
   2830 		}
   2831 	}
   2832 
   2833 	if (rdataset->type != dns_rdatatype_nsec &&
   2834 	    DNS_TRUST_SECURE(rdataset->trust))
   2835 	{
   2836 		/*
   2837 		 * The negative response data is already verified.
   2838 		 * We skip NSEC records, because they require special
   2839 		 * processing in validator_callback_nsec().
   2840 		 */
   2841 		return DNS_R_CONTINUE;
   2842 	}
   2843 
   2844 	val->nxset = rdataset;
   2845 
   2846 	result = create_validator(val, name, rdataset->type, rdataset,
   2847 				  sigrdataset, validator_callback_nsec,
   2848 				  "validate_neg_rrset");
   2849 	if (result != ISC_R_SUCCESS) {
   2850 		return result;
   2851 	}
   2852 
   2853 	val->authcount++;
   2854 	return DNS_R_WAIT;
   2855 }
   2856 
   2857 /*%
   2858  * Validate the authority section records.
   2859  */
   2860 static isc_result_t
   2861 validate_authority(dns_validator_t *val, bool resume) {
   2862 	dns_name_t *name;
   2863 	dns_message_t *message = val->message;
   2864 	isc_result_t result;
   2865 
   2866 	if (!resume) {
   2867 		result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
   2868 	} else {
   2869 		result = ISC_R_SUCCESS;
   2870 	}
   2871 
   2872 	for (; result == ISC_R_SUCCESS;
   2873 	     result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
   2874 	{
   2875 		dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
   2876 
   2877 		name = NULL;
   2878 		dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
   2879 		if (resume) {
   2880 			rdataset = ISC_LIST_NEXT(val->nxset, link);
   2881 			val->nxset = NULL;
   2882 			resume = false;
   2883 		} else {
   2884 			rdataset = ISC_LIST_HEAD(name->list);
   2885 		}
   2886 
   2887 		for (; rdataset != NULL;
   2888 		     rdataset = ISC_LIST_NEXT(rdataset, link))
   2889 		{
   2890 			if (rdataset->type == dns_rdatatype_rrsig) {
   2891 				continue;
   2892 			}
   2893 
   2894 			for (sigrdataset = ISC_LIST_HEAD(name->list);
   2895 			     sigrdataset != NULL;
   2896 			     sigrdataset = ISC_LIST_NEXT(sigrdataset, link))
   2897 			{
   2898 				if (sigrdataset->type == dns_rdatatype_rrsig &&
   2899 				    sigrdataset->covers == rdataset->type)
   2900 				{
   2901 					break;
   2902 				}
   2903 			}
   2904 
   2905 			result = validate_neg_rrset(val, name, rdataset,
   2906 						    sigrdataset);
   2907 			if (result != DNS_R_CONTINUE) {
   2908 				return result;
   2909 			}
   2910 		}
   2911 	}
   2912 	if (result == ISC_R_NOMORE) {
   2913 		result = ISC_R_SUCCESS;
   2914 	}
   2915 	return result;
   2916 }
   2917 
   2918 /*%
   2919  * Validate negative cache elements.
   2920  */
   2921 static isc_result_t
   2922 validate_ncache(dns_validator_t *val, bool resume) {
   2923 	dns_name_t *name;
   2924 	isc_result_t result;
   2925 
   2926 	if (!resume) {
   2927 		result = dns_rdataset_first(val->rdataset);
   2928 	} else {
   2929 		result = dns_rdataset_next(val->rdataset);
   2930 	}
   2931 
   2932 	for (; result == ISC_R_SUCCESS;
   2933 	     result = dns_rdataset_next(val->rdataset))
   2934 	{
   2935 		dns_rdataset_t *rdataset, *sigrdataset = NULL;
   2936 
   2937 		disassociate_rdatasets(val);
   2938 
   2939 		name = dns_fixedname_initname(&val->fname);
   2940 		rdataset = &val->frdataset;
   2941 		dns_ncache_current(val->rdataset, name, rdataset);
   2942 
   2943 		if (val->frdataset.type == dns_rdatatype_rrsig) {
   2944 			continue;
   2945 		}
   2946 
   2947 		result = dns_ncache_getsigrdataset(val->rdataset, name,
   2948 						   rdataset->type,
   2949 						   &val->fsigrdataset);
   2950 		if (result == ISC_R_SUCCESS) {
   2951 			sigrdataset = &val->fsigrdataset;
   2952 		}
   2953 
   2954 		result = validate_neg_rrset(val, name, rdataset, sigrdataset);
   2955 		if (result != DNS_R_CONTINUE) {
   2956 			return result;
   2957 		}
   2958 	}
   2959 	if (result == ISC_R_NOMORE) {
   2960 		result = ISC_R_SUCCESS;
   2961 	}
   2962 
   2963 	return result;
   2964 }
   2965 
   2966 /*%
   2967  * Prove a negative answer is good or that there is a NOQNAME when the
   2968  * answer is from a wildcard.
   2969  *
   2970  * Loop through the authority section looking for NODATA, NOWILDCARD
   2971  * and NOQNAME proofs in the NSEC records by calling
   2972  * validator_callback_nsec().
   2973  *
   2974  * If the required proofs are found we are done.
   2975  *
   2976  * If the proofs are not found attempt to prove this is an unsecure
   2977  * response.
   2978  */
   2979 static isc_result_t
   2980 validate_nx(dns_validator_t *val, bool resume) {
   2981 	isc_result_t result;
   2982 
   2983 	if (resume) {
   2984 		validator_log(val, ISC_LOG_DEBUG(3), "resuming validate_nx");
   2985 	}
   2986 
   2987 	if (val->message == NULL) {
   2988 		result = validate_ncache(val, resume);
   2989 	} else {
   2990 		result = validate_authority(val, resume);
   2991 	}
   2992 
   2993 	if (result != ISC_R_SUCCESS) {
   2994 		return result;
   2995 	}
   2996 
   2997 	/*
   2998 	 * Do we only need to check for NOQNAME?  To get here we must have
   2999 	 * had a secure wildcard answer.
   3000 	 */
   3001 	if (!NEEDNODATA(val) && !NEEDNOWILDCARD(val) && NEEDNOQNAME(val)) {
   3002 		if (!FOUNDNOQNAME(val)) {
   3003 			result = findnsec3proofs(val);
   3004 			if (result == DNS_R_NSEC3ITERRANGE) {
   3005 				validator_log(val, ISC_LOG_DEBUG(3),
   3006 					      "%s: too many iterations",
   3007 					      __func__);
   3008 				markanswer(val, "validate_nx (3)", NULL);
   3009 				return ISC_R_SUCCESS;
   3010 			}
   3011 		}
   3012 
   3013 		if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) && !FOUNDOPTOUT(val))
   3014 		{
   3015 			marksecure(val, "validate_nx (noqname proof found)");
   3016 			return ISC_R_SUCCESS;
   3017 		} else if (FOUNDOPTOUT(val) &&
   3018 			   dns_name_countlabels(
   3019 				   dns_fixedname_name(&val->wild)) != 0)
   3020 		{
   3021 			validator_log(val, ISC_LOG_DEBUG(3),
   3022 				      "optout proof found");
   3023 			val->optout = true;
   3024 			markanswer(val, "validate_nx (1)", NULL);
   3025 			return ISC_R_SUCCESS;
   3026 		} else if ((val->attributes & VALATTR_FOUNDUNKNOWN) != 0) {
   3027 			validator_log(val, ISC_LOG_DEBUG(3),
   3028 				      "unknown NSEC3 hash algorithm found");
   3029 			markanswer(val, "validate_nx (2)", NULL);
   3030 			return ISC_R_SUCCESS;
   3031 		}
   3032 
   3033 		validator_log(val, ISC_LOG_DEBUG(3), "noqname proof not found");
   3034 		return DNS_R_NOVALIDNSEC;
   3035 	}
   3036 
   3037 	if (!FOUNDNOQNAME(val) && !FOUNDNODATA(val)) {
   3038 		result = findnsec3proofs(val);
   3039 		if (result == DNS_R_NSEC3ITERRANGE) {
   3040 			validator_log(val, ISC_LOG_DEBUG(3),
   3041 				      "%s: too many iterations", __func__);
   3042 			markanswer(val, "validate_nx (4)", NULL);
   3043 			return ISC_R_SUCCESS;
   3044 		}
   3045 	}
   3046 
   3047 	/*
   3048 	 * Do we need to check for the wildcard?
   3049 	 */
   3050 	if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
   3051 	    ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val)))
   3052 	{
   3053 		result = checkwildcard(val, dns_rdatatype_nsec, NULL);
   3054 		if (result != ISC_R_SUCCESS) {
   3055 			return result;
   3056 		}
   3057 	}
   3058 
   3059 	if ((NEEDNODATA(val) && (FOUNDNODATA(val) || FOUNDOPTOUT(val))) ||
   3060 	    (NEEDNOQNAME(val) && FOUNDNOQNAME(val) && NEEDNOWILDCARD(val) &&
   3061 	     FOUNDNOWILDCARD(val) && FOUNDCLOSEST(val)))
   3062 	{
   3063 		if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0) {
   3064 			val->optout = true;
   3065 		}
   3066 		validator_log(val, ISC_LOG_DEBUG(3),
   3067 			      "nonexistence proof(s) found");
   3068 		if (val->message == NULL) {
   3069 			marksecure(val,
   3070 				   "validate_nx (nonexistence proofs found)");
   3071 		} else {
   3072 			val->secure = true;
   3073 		}
   3074 		return ISC_R_SUCCESS;
   3075 	}
   3076 
   3077 	if (val->authfail != 0 && val->authcount == val->authfail) {
   3078 		return DNS_R_BROKENCHAIN;
   3079 	}
   3080 
   3081 	return proveunsecure(val, false, false);
   3082 }
   3083 
   3084 /*%
   3085  * Check that DS rdataset has at least one record with
   3086  * a supported algorithm and digest.
   3087  */
   3088 static bool
   3089 check_ds_algs(dns_validator_t *val, dns_name_t *name,
   3090 	      dns_rdataset_t *rdataset) {
   3091 	dns_rdata_t dsrdata = DNS_RDATA_INIT;
   3092 	dns_rdata_ds_t ds;
   3093 	isc_result_t result;
   3094 
   3095 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
   3096 	     result = dns_rdataset_next(rdataset))
   3097 	{
   3098 		dns_rdataset_current(rdataset, &dsrdata);
   3099 		result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
   3100 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3101 
   3102 		if (dns_resolver_ds_digest_supported(val->view->resolver, name,
   3103 						     ds.digest_type) &&
   3104 		    dns_resolver_algorithm_supported(val->view->resolver, name,
   3105 						     ds.algorithm))
   3106 		{
   3107 			dns_rdata_reset(&dsrdata);
   3108 			return true;
   3109 		}
   3110 		dns_rdata_reset(&dsrdata);
   3111 	}
   3112 
   3113 	/*
   3114 	 * No unsupported alg/digest EDE error is raised here because the prove
   3115 	 * unsecure flow always runs after a validate/validatenx flow. So if an
   3116 	 * unsupported alg/digest was found while building the chain of trust,
   3117 	 * it would be raised already.
   3118 	 */
   3119 	return false;
   3120 }
   3121 
   3122 /*%
   3123  * seek_ds is called to look up DS rrsets at the label of val->name
   3124  * indicated by val->labels. This is done while building an insecurity
   3125  * proof, and so it will attempt validation of NXDOMAIN, NXRRSET or CNAME
   3126  * responses.
   3127  *
   3128  * Returns:
   3129  * \li	ISC_R_COMPLETE		a result has been determined and copied
   3130  * 				into `*resp`; ISC_R_SUCCESS indicates that
   3131  * 				the name has been proven insecure and any
   3132  * 				other result indicates failure.
   3133  * \li	DNS_R_CONTINUE		result is indeterminate; caller should
   3134  * 				continue walking down labels.
   3135  */
   3136 static isc_result_t
   3137 seek_ds(dns_validator_t *val, isc_result_t *resp) {
   3138 	isc_result_t result;
   3139 	char namebuf[DNS_NAME_FORMATSIZE];
   3140 	dns_fixedname_t fixedfound;
   3141 	dns_name_t *found = dns_fixedname_initname(&fixedfound);
   3142 	dns_name_t *tname = dns_fixedname_initname(&val->fname);
   3143 
   3144 	if (val->labels == dns_name_countlabels(val->name)) {
   3145 		dns_name_copy(val->name, tname);
   3146 	} else {
   3147 		dns_name_split(val->name, val->labels, NULL, tname);
   3148 	}
   3149 
   3150 	dns_name_format(tname, namebuf, sizeof(namebuf));
   3151 	validator_log(val, ISC_LOG_DEBUG(3), "checking existence of DS at '%s'",
   3152 		      namebuf);
   3153 
   3154 	result = view_find(val, tname, dns_rdatatype_ds);
   3155 	switch (result) {
   3156 	case ISC_R_SUCCESS:
   3157 		/*
   3158 		 * There is a DS here.  If it's already been
   3159 		 * validated, continue walking down labels.
   3160 		 */
   3161 		if (val->frdataset.trust >= dns_trust_secure) {
   3162 			if (!check_ds_algs(val, tname, &val->frdataset)) {
   3163 				validator_log(
   3164 					val, ISC_LOG_DEBUG(3),
   3165 					"no supported algorithm/digest (%s/DS)",
   3166 					namebuf);
   3167 				*resp = markanswer(val, "seek_ds (1)",
   3168 						   "no supported "
   3169 						   "algorithm/digest (DS)");
   3170 				return ISC_R_COMPLETE;
   3171 			}
   3172 
   3173 			break;
   3174 		}
   3175 
   3176 		/*
   3177 		 * Otherwise, try to validate it now.
   3178 		 */
   3179 		result = create_validator(val, tname, dns_rdatatype_ds,
   3180 					  &val->frdataset, &val->fsigrdataset,
   3181 					  validator_callback_ds, "seek_ds");
   3182 		*resp = DNS_R_WAIT;
   3183 		if (result != ISC_R_SUCCESS) {
   3184 			*resp = result;
   3185 		}
   3186 
   3187 		return ISC_R_COMPLETE;
   3188 
   3189 	case ISC_R_NOTFOUND:
   3190 		/*
   3191 		 * We don't know anything about the DS.  Find it.
   3192 		 */
   3193 		*resp = DNS_R_WAIT;
   3194 		result = create_fetch(val, tname, dns_rdatatype_ds,
   3195 				      fetch_callback_ds, "seek_ds");
   3196 		if (result != ISC_R_SUCCESS) {
   3197 			*resp = result;
   3198 		}
   3199 		return ISC_R_COMPLETE;
   3200 
   3201 	case DNS_R_NXRRSET:
   3202 	case DNS_R_NCACHENXRRSET:
   3203 		/*
   3204 		 * There is no DS.  If this is a delegation,
   3205 		 * we may be done.
   3206 		 *
   3207 		 * If we have "trust == answer" then this namespace
   3208 		 * has switched from insecure to should be secure.
   3209 		 */
   3210 		if (DNS_TRUST_PENDING(val->frdataset.trust) ||
   3211 		    DNS_TRUST_ANSWER(val->frdataset.trust))
   3212 		{
   3213 			result = create_validator(
   3214 				val, tname, dns_rdatatype_ds, &val->frdataset,
   3215 				&val->fsigrdataset, validator_callback_ds,
   3216 				"seek_ds");
   3217 			*resp = DNS_R_WAIT;
   3218 			if (result != ISC_R_SUCCESS) {
   3219 				*resp = result;
   3220 			}
   3221 			return ISC_R_COMPLETE;
   3222 		}
   3223 
   3224 		/*
   3225 		 * Zones using NSEC3 don't return a NSEC RRset so
   3226 		 * we need to use dns_view_findzonecut2 to find
   3227 		 * the zone cut.
   3228 		 */
   3229 		if (result == DNS_R_NXRRSET &&
   3230 		    !dns_rdataset_isassociated(&val->frdataset) &&
   3231 		    dns_view_findzonecut(val->view, tname, found, NULL, 0, 0,
   3232 					 false, false, NULL,
   3233 					 NULL) == ISC_R_SUCCESS &&
   3234 		    dns_name_equal(tname, found))
   3235 		{
   3236 			*resp = markanswer(val, "seek_ds (2)",
   3237 					   "no DS at zone cut");
   3238 			return ISC_R_COMPLETE;
   3239 		}
   3240 
   3241 		if (val->frdataset.trust < dns_trust_secure) {
   3242 			/*
   3243 			 * This shouldn't happen, since the negative
   3244 			 * response should have been validated.  Since
   3245 			 * there's no way of validating existing
   3246 			 * negative response blobs, give up.
   3247 			 */
   3248 			validator_log(val, ISC_LOG_WARNING,
   3249 				      "can't validate existing "
   3250 				      "negative responses (no DS)");
   3251 			*resp = DNS_R_MUSTBESECURE;
   3252 			return ISC_R_COMPLETE;
   3253 		}
   3254 
   3255 		if (is_insecure_referral(val, tname, &val->frdataset, result,
   3256 					 "seek_ds"))
   3257 		{
   3258 			*resp = markanswer(val, "seek_ds (3)",
   3259 					   "this is a delegation");
   3260 			return ISC_R_COMPLETE;
   3261 		}
   3262 
   3263 		break;
   3264 
   3265 	case DNS_R_NXDOMAIN:
   3266 	case DNS_R_NCACHENXDOMAIN:
   3267 		/*
   3268 		 * This is not a zone cut. Assuming things are
   3269 		 * as expected, continue.
   3270 		 */
   3271 		if (!dns_rdataset_isassociated(&val->frdataset)) {
   3272 			/*
   3273 			 * There should be an NSEC here, since we
   3274 			 * are still in a secure zone.
   3275 			 */
   3276 			*resp = DNS_R_NOVALIDNSEC;
   3277 			return ISC_R_COMPLETE;
   3278 		} else if (DNS_TRUST_PENDING(val->frdataset.trust) ||
   3279 			   DNS_TRUST_ANSWER(val->frdataset.trust))
   3280 		{
   3281 			/*
   3282 			 * If we have "trust == answer" then this
   3283 			 * namespace has switched from insecure to
   3284 			 * should be secure.
   3285 			 */
   3286 			*resp = DNS_R_WAIT;
   3287 			result = create_validator(
   3288 				val, tname, dns_rdatatype_ds, &val->frdataset,
   3289 				&val->fsigrdataset, validator_callback_ds,
   3290 				"seek_ds");
   3291 			if (result != ISC_R_SUCCESS) {
   3292 				*resp = result;
   3293 			}
   3294 			return ISC_R_COMPLETE;
   3295 		} else if (val->frdataset.trust < dns_trust_secure) {
   3296 			/*
   3297 			 * This shouldn't happen, since the negative
   3298 			 * response should have been validated.  Since
   3299 			 * there's no way of validating existing
   3300 			 * negative response blobs, give up.
   3301 			 */
   3302 			validator_log(val, ISC_LOG_WARNING,
   3303 				      "can't validate existing "
   3304 				      "negative responses "
   3305 				      "(not a zone cut)");
   3306 			*resp = DNS_R_NOVALIDSIG;
   3307 			return ISC_R_COMPLETE;
   3308 		}
   3309 
   3310 		break;
   3311 
   3312 	case DNS_R_CNAME:
   3313 		if (DNS_TRUST_PENDING(val->frdataset.trust) ||
   3314 		    DNS_TRUST_ANSWER(val->frdataset.trust))
   3315 		{
   3316 			result = create_validator(
   3317 				val, tname, dns_rdatatype_cname,
   3318 				&val->frdataset, &val->fsigrdataset,
   3319 				validator_callback_cname, "seek_ds (cname)");
   3320 			*resp = DNS_R_WAIT;
   3321 			if (result != ISC_R_SUCCESS) {
   3322 				*resp = result;
   3323 			}
   3324 			return ISC_R_COMPLETE;
   3325 		}
   3326 
   3327 		break;
   3328 
   3329 	default:
   3330 		*resp = result;
   3331 		return ISC_R_COMPLETE;
   3332 	}
   3333 
   3334 	/*
   3335 	 * No definite answer yet; continue walking down labels.
   3336 	 */
   3337 	return DNS_R_CONTINUE;
   3338 }
   3339 
   3340 /*%
   3341  * proveunsecure walks down, label by label, from the closest enclosing
   3342  * trust anchor to the name that is being validated, looking for an
   3343  * endpoint in the chain of trust.  That occurs when we can prove that
   3344  * a DS record does not exist at a delegation point, or that a DS exists
   3345  * at a delegation point but we don't support its algorithm/digest.  If
   3346  * no such endpoint is found, then the response should have been secure.
   3347  *
   3348  * Returns:
   3349  * \li	ISC_R_SUCCESS		val->name is in an unsecure zone
   3350  * \li	DNS_R_WAIT		validation is in progress.
   3351  * \li	DNS_R_MUSTBESECURE	val->name is supposed to be secure
   3352  *				(policy) but we proved that it is unsecure.
   3353  * \li	DNS_R_NOVALIDSIG
   3354  * \li	DNS_R_NOVALIDNSEC
   3355  * \li	DNS_R_NOTINSECURE
   3356  * \li	DNS_R_BROKENCHAIN
   3357  */
   3358 static isc_result_t
   3359 proveunsecure(dns_validator_t *val, bool have_ds, bool resume) {
   3360 	isc_result_t result;
   3361 	char namebuf[DNS_NAME_FORMATSIZE];
   3362 	dns_fixedname_t fixedsecroot;
   3363 	dns_name_t *secroot = dns_fixedname_initname(&fixedsecroot);
   3364 	unsigned int labels;
   3365 
   3366 	/*
   3367 	 * We're attempting to prove insecurity.
   3368 	 */
   3369 	val->attributes |= VALATTR_INSECURITY;
   3370 
   3371 	dns_name_copy(val->name, secroot);
   3372 
   3373 	/*
   3374 	 * If this is a response to a DS query, we need to look in
   3375 	 * the parent zone for the trust anchor.
   3376 	 */
   3377 	labels = dns_name_countlabels(secroot);
   3378 	if (val->type == dns_rdatatype_ds && labels > 1U) {
   3379 		dns_name_getlabelsequence(secroot, 1, labels - 1, secroot);
   3380 	}
   3381 
   3382 	result = dns_keytable_finddeepestmatch(val->keytable, secroot, secroot);
   3383 	if (result == ISC_R_NOTFOUND) {
   3384 		validator_log(val, ISC_LOG_DEBUG(3), "not beneath secure root");
   3385 		return markanswer(val, "proveunsecure (1)",
   3386 				  "not beneath secure root");
   3387 	} else if (result != ISC_R_SUCCESS) {
   3388 		return result;
   3389 	}
   3390 
   3391 	if (!resume) {
   3392 		/*
   3393 		 * We are looking for interruptions in the chain of trust.
   3394 		 * That can only happen *below* the trust anchor, so we
   3395 		 * start looking at the next label down.
   3396 		 */
   3397 		val->labels = dns_name_countlabels(secroot) + 1;
   3398 	} else {
   3399 		validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
   3400 
   3401 		/*
   3402 		 * If we have a DS rdataset and it is secure, check whether
   3403 		 * it has a supported algorithm combination.  If not, this is
   3404 		 * an insecure delegation as far as this resolver is concerned.
   3405 		 */
   3406 		if (have_ds && val->frdataset.trust >= dns_trust_secure &&
   3407 		    !check_ds_algs(val, dns_fixedname_name(&val->fname),
   3408 				   &val->frdataset))
   3409 		{
   3410 			dns_name_format(dns_fixedname_name(&val->fname),
   3411 					namebuf, sizeof(namebuf));
   3412 			validator_log(val, ISC_LOG_DEBUG(3),
   3413 				      "no supported algorithm/digest (%s/DS)",
   3414 				      namebuf);
   3415 			result = markanswer(val, "proveunsecure (2)", namebuf);
   3416 			goto out;
   3417 		}
   3418 		val->labels++;
   3419 	}
   3420 
   3421 	/*
   3422 	 * Walk down through each of the remaining labels in the name,
   3423 	 * looking for DS records.
   3424 	 */
   3425 	while (val->labels <= dns_name_countlabels(val->name)) {
   3426 		isc_result_t tresult;
   3427 
   3428 		result = seek_ds(val, &tresult);
   3429 		if (result == ISC_R_COMPLETE) {
   3430 			result = tresult;
   3431 			goto out;
   3432 		}
   3433 
   3434 		INSIST(result == DNS_R_CONTINUE);
   3435 		val->labels++;
   3436 	}
   3437 
   3438 	/* Couldn't complete insecurity proof. */
   3439 	validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed: %s",
   3440 		      isc_result_totext(result));
   3441 	return DNS_R_NOTINSECURE;
   3442 
   3443 out:
   3444 	if (result != DNS_R_WAIT) {
   3445 		disassociate_rdatasets(val);
   3446 	}
   3447 	return result;
   3448 }
   3449 
   3450 /*%
   3451  * Start the validation process.
   3452  *
   3453  * Attempt to validate the answer based on the category it appears to
   3454  * fall in.
   3455  * \li	1. secure positive answer.
   3456  * \li	2. unsecure positive answer.
   3457  * \li	3. a negative answer (secure or unsecure).
   3458  *
   3459  * Note an answer that appears to be a secure positive answer may actually
   3460  * be an unsecure positive answer.
   3461  */
   3462 static void
   3463 validator_start(void *arg) {
   3464 	dns_validator_t *val = (dns_validator_t *)arg;
   3465 	isc_result_t result = ISC_R_FAILURE;
   3466 
   3467 	if (CANCELED(val) || CANCELING(val)) {
   3468 		result = ISC_R_CANCELED;
   3469 		goto cleanup;
   3470 	}
   3471 
   3472 	validator_log(val, ISC_LOG_DEBUG(3), "starting");
   3473 
   3474 	if (val->rdataset != NULL && val->sigrdataset != NULL) {
   3475 		/*
   3476 		 * This looks like a simple validation.  We say "looks like"
   3477 		 * because it might end up requiring an insecurity proof.
   3478 		 */
   3479 		validator_log(val, ISC_LOG_DEBUG(3),
   3480 			      "attempting positive response validation");
   3481 
   3482 		INSIST(dns_rdataset_isassociated(val->rdataset));
   3483 		INSIST(dns_rdataset_isassociated(val->sigrdataset));
   3484 
   3485 		result = selfsigned_dnskey(val);
   3486 		switch (result) {
   3487 		case ISC_R_QUOTA:
   3488 			goto cleanup;
   3489 		case ISC_R_SUCCESS:
   3490 			result = validate_async_run(val, validate_dnskey);
   3491 			break;
   3492 		case DNS_R_NOKEYMATCH:
   3493 			result = validate_async_run(val, validate_answer);
   3494 			break;
   3495 		default:
   3496 			UNREACHABLE();
   3497 		}
   3498 	} else if (val->rdataset != NULL && val->rdataset->type != 0) {
   3499 		/*
   3500 		 * This is either an unsecure subdomain or a response
   3501 		 * from a broken server.
   3502 		 */
   3503 		INSIST(dns_rdataset_isassociated(val->rdataset));
   3504 		validator_log(val, ISC_LOG_DEBUG(3),
   3505 			      "attempting insecurity proof");
   3506 
   3507 		result = proveunsecure(val, false, false);
   3508 		if (result == DNS_R_NOTINSECURE) {
   3509 			validator_log(val, ISC_LOG_INFO,
   3510 				      "got insecure response; "
   3511 				      "parent indicates it should be secure");
   3512 		}
   3513 	} else if (val->rdataset == NULL && val->sigrdataset == NULL) {
   3514 		/*
   3515 		 * This is a validation of a negative response.
   3516 		 */
   3517 		validator_log(val, ISC_LOG_DEBUG(3),
   3518 			      "attempting negative response validation "
   3519 			      "from message");
   3520 
   3521 		if (val->message->rcode == dns_rcode_nxdomain) {
   3522 			val->attributes |= VALATTR_NEEDNOQNAME;
   3523 			val->attributes |= VALATTR_NEEDNOWILDCARD;
   3524 		} else {
   3525 			val->attributes |= VALATTR_NEEDNODATA;
   3526 		}
   3527 
   3528 		result = validate_nx(val, false);
   3529 	} else if (val->rdataset != NULL && NEGATIVE(val->rdataset)) {
   3530 		/*
   3531 		 * This is a delayed validation of a negative cache entry.
   3532 		 */
   3533 		validator_log(val, ISC_LOG_DEBUG(3),
   3534 			      "attempting negative response validation "
   3535 			      "from cache");
   3536 
   3537 		if (NXDOMAIN(val->rdataset)) {
   3538 			val->attributes |= VALATTR_NEEDNOQNAME;
   3539 			val->attributes |= VALATTR_NEEDNOWILDCARD;
   3540 		} else {
   3541 			val->attributes |= VALATTR_NEEDNODATA;
   3542 		}
   3543 
   3544 		result = validate_nx(val, false);
   3545 	} else {
   3546 		UNREACHABLE();
   3547 	}
   3548 
   3549 cleanup:
   3550 	validate_async_done(val, result);
   3551 }
   3552 
   3553 isc_result_t
   3554 dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
   3555 		     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
   3556 		     dns_message_t *message, unsigned int options,
   3557 		     isc_loop_t *loop, isc_job_cb cb, void *arg,
   3558 		     isc_counter_t *nvalidations, isc_counter_t *nfails,
   3559 		     isc_counter_t *qc, isc_counter_t *gqc, fetchctx_t *parent,
   3560 		     dns_edectx_t *edectx, dns_validator_t **validatorp) {
   3561 	isc_result_t result = ISC_R_FAILURE;
   3562 	dns_validator_t *val = NULL;
   3563 	dns_keytable_t *kt = NULL;
   3564 
   3565 	REQUIRE(name != NULL);
   3566 	REQUIRE(rdataset != NULL ||
   3567 		(rdataset == NULL && sigrdataset == NULL && message != NULL));
   3568 	REQUIRE(validatorp != NULL && *validatorp == NULL);
   3569 	REQUIRE(edectx != NULL);
   3570 
   3571 	result = dns_view_getsecroots(view, &kt);
   3572 	if (result != ISC_R_SUCCESS) {
   3573 		return result;
   3574 	}
   3575 
   3576 	val = isc_mem_get(view->mctx, sizeof(*val));
   3577 	*val = (dns_validator_t){
   3578 		.tid = isc_tid(),
   3579 		.result = DNS_R_NOVALIDSIG,
   3580 		.rdataset = rdataset,
   3581 		.sigrdataset = sigrdataset,
   3582 		.name = name,
   3583 		.type = type,
   3584 		.options = options,
   3585 		.keytable = kt,
   3586 		.link = ISC_LINK_INITIALIZER,
   3587 		.loop = isc_loop_ref(loop),
   3588 		.cb = cb,
   3589 		.arg = arg,
   3590 		.rdata = DNS_RDATA_INIT,
   3591 		.cb_edectx = edectx,
   3592 		.parent_fetch = parent,
   3593 	};
   3594 
   3595 	dns_ede_init(view->mctx, &val->edectx);
   3596 
   3597 	isc_refcount_init(&val->references, 1);
   3598 	dns_view_attach(view, &val->view);
   3599 	if (message != NULL) {
   3600 		dns_message_attach(message, &val->message);
   3601 	}
   3602 
   3603 	if (nfails != NULL) {
   3604 		isc_counter_attach(nfails, &val->nfails);
   3605 	}
   3606 
   3607 	if (nvalidations != NULL) {
   3608 		isc_counter_attach(nvalidations, &val->nvalidations);
   3609 	}
   3610 
   3611 	if (qc != NULL) {
   3612 		isc_counter_attach(qc, &val->qc);
   3613 	}
   3614 	if (gqc != NULL) {
   3615 		isc_counter_attach(gqc, &val->gqc);
   3616 	}
   3617 
   3618 	val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
   3619 	dns_rdataset_init(&val->fdsset);
   3620 	dns_rdataset_init(&val->frdataset);
   3621 	dns_rdataset_init(&val->fsigrdataset);
   3622 	dns_fixedname_init(&val->wild);
   3623 	dns_fixedname_init(&val->closest);
   3624 	val->start = isc_stdtime_now();
   3625 	val->magic = VALIDATOR_MAGIC;
   3626 
   3627 	if ((options & DNS_VALIDATOR_DEFER) == 0) {
   3628 		dns_validator_ref(val);
   3629 		(void)validate_async_run(val, validator_start);
   3630 	}
   3631 
   3632 	*validatorp = val;
   3633 
   3634 	return ISC_R_SUCCESS;
   3635 }
   3636 
   3637 void
   3638 dns_validator_send(dns_validator_t *val) {
   3639 	REQUIRE(VALID_VALIDATOR(val));
   3640 	REQUIRE(val->tid == isc_tid());
   3641 
   3642 	INSIST((val->options & DNS_VALIDATOR_DEFER) != 0);
   3643 	val->options &= ~DNS_VALIDATOR_DEFER;
   3644 
   3645 	dns_validator_ref(val);
   3646 	(void)validate_async_run(val, validator_start);
   3647 }
   3648 
   3649 static void
   3650 validator_cancel_finish(dns_validator_t *validator) {
   3651 	validator_log(validator, ISC_LOG_DEBUG(3), "validator_cancel_finish");
   3652 
   3653 	if (CANCELING(validator) && !CANCELED(validator)) {
   3654 		if (validator->fetch != NULL) {
   3655 			dns_resolver_cancelfetch(validator->fetch);
   3656 		}
   3657 		if (validator->subvalidator != NULL) {
   3658 			dns_validator_cancel(validator->subvalidator);
   3659 		}
   3660 		if (!COMPLETE(validator)) {
   3661 			validator->options &= ~DNS_VALIDATOR_DEFER;
   3662 			validator_done(validator, ISC_R_CANCELED);
   3663 		}
   3664 		validator->attributes |= VALATTR_CANCELED;
   3665 	}
   3666 }
   3667 
   3668 void
   3669 dns_validator_cancel(dns_validator_t *validator) {
   3670 	REQUIRE(VALID_VALIDATOR(validator));
   3671 	REQUIRE(validator->tid == isc_tid());
   3672 
   3673 	validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
   3674 
   3675 	atomic_store(&validator->canceling, true);
   3676 
   3677 	if (!OFFLOADED(validator)) {
   3678 		validator_cancel_finish(validator);
   3679 	}
   3680 }
   3681 
   3682 static void
   3683 destroy_validator(dns_validator_t *val) {
   3684 	isc_mem_t *mctx = NULL;
   3685 
   3686 	REQUIRE(val->fetch == NULL);
   3687 	REQUIRE(val->subvalidator == NULL);
   3688 
   3689 	val->magic = 0;
   3690 	if (val->key != NULL) {
   3691 		dst_key_free(&val->key);
   3692 	}
   3693 	if (val->keytable != NULL) {
   3694 		dns_keytable_detach(&val->keytable);
   3695 	}
   3696 	disassociate_rdatasets(val);
   3697 	mctx = val->view->mctx;
   3698 	if (val->siginfo != NULL) {
   3699 		isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo));
   3700 	}
   3701 	if (val->message != NULL) {
   3702 		dns_message_detach(&val->message);
   3703 	}
   3704 	if (val->nfails != NULL) {
   3705 		isc_counter_detach(&val->nfails);
   3706 	}
   3707 	if (val->nvalidations != NULL) {
   3708 		isc_counter_detach(&val->nvalidations);
   3709 	}
   3710 	if (val->qc != NULL) {
   3711 		isc_counter_detach(&val->qc);
   3712 	}
   3713 	if (val->gqc != NULL) {
   3714 		isc_counter_detach(&val->gqc);
   3715 	}
   3716 
   3717 	dns_ede_invalidate(&val->edectx);
   3718 
   3719 	dns_view_detach(&val->view);
   3720 	isc_loop_detach(&val->loop);
   3721 
   3722 	isc_mem_put(mctx, val, sizeof(*val));
   3723 }
   3724 
   3725 void
   3726 dns_validator_shutdown(dns_validator_t *val) {
   3727 	REQUIRE(VALID_VALIDATOR(val));
   3728 	REQUIRE(COMPLETE(val));
   3729 	REQUIRE(val->tid == isc_tid());
   3730 
   3731 	validator_log(val, ISC_LOG_DEBUG(4), "dns_validator_shutdown");
   3732 
   3733 	/*
   3734 	 * The validation is now complete and the owner is no longer interested
   3735 	 * in any further results. If there are still callback events queued up
   3736 	 * which hold a validator reference, they should not be allowed to use
   3737 	 * val->name during logging, because the owner may destroy it after this
   3738 	 * function is called.
   3739 	 */
   3740 	val->name = NULL;
   3741 }
   3742 
   3743 static void
   3744 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
   3745 	       isc_logmodule_t *module, int level, const char *fmt,
   3746 	       va_list ap) {
   3747 	char msgbuf[2048];
   3748 	static const char spaces[] = "        *";
   3749 	int depth = val->depth * 2;
   3750 	const char *viewname, *sep1, *sep2;
   3751 
   3752 	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
   3753 
   3754 	if ((unsigned int)depth >= sizeof spaces) {
   3755 		depth = sizeof spaces - 1;
   3756 	}
   3757 
   3758 	/*
   3759 	 * Log the view name unless it's:
   3760 	 * * "_default/IN" (which means there's only one view
   3761 	 *   configured in the server), or
   3762 	 * * "_dnsclient/IN" (which means this is being called
   3763 	 *   from an application using dns/client.c).
   3764 	 */
   3765 	if (val->view->rdclass == dns_rdataclass_in &&
   3766 	    (strcmp(val->view->name, "_default") == 0 ||
   3767 	     strcmp(val->view->name, DNS_CLIENTVIEW_NAME) == 0))
   3768 	{
   3769 		sep1 = viewname = sep2 = "";
   3770 	} else {
   3771 		sep1 = "view ";
   3772 		viewname = val->view->name;
   3773 		sep2 = ": ";
   3774 	}
   3775 
   3776 	if (val->name != NULL) {
   3777 		char namebuf[DNS_NAME_FORMATSIZE];
   3778 		char typebuf[DNS_RDATATYPE_FORMATSIZE];
   3779 
   3780 		dns_name_format(val->name, namebuf, sizeof(namebuf));
   3781 		dns_rdatatype_format(val->type, typebuf, sizeof(typebuf));
   3782 		isc_log_write(dns_lctx, category, module, level,
   3783 			      "%s%s%s%.*svalidating %s/%s: %s", sep1, viewname,
   3784 			      sep2, depth, spaces, namebuf, typebuf, msgbuf);
   3785 	} else {
   3786 		isc_log_write(dns_lctx, category, module, level,
   3787 			      "%s%s%s%.*svalidator @%p: %s", sep1, viewname,
   3788 			      sep2, depth, spaces, val, msgbuf);
   3789 	}
   3790 }
   3791 
   3792 static void
   3793 validator_log(void *val, int level, const char *fmt, ...) {
   3794 	va_list ap;
   3795 
   3796 	if (!isc_log_wouldlog(dns_lctx, level)) {
   3797 		return;
   3798 	}
   3799 
   3800 	va_start(ap, fmt);
   3801 
   3802 	validator_logv(val, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_VALIDATOR,
   3803 		       level, fmt, ap);
   3804 	va_end(ap);
   3805 }
   3806 
   3807 static void
   3808 validator_logcreate(dns_validator_t *val, dns_name_t *name,
   3809 		    dns_rdatatype_t type, const char *caller,
   3810 		    const char *operation) {
   3811 	char namestr[DNS_NAME_FORMATSIZE];
   3812 	char typestr[DNS_RDATATYPE_FORMATSIZE];
   3813 
   3814 	dns_name_format(name, namestr, sizeof(namestr));
   3815 	dns_rdatatype_format(type, typestr, sizeof(typestr));
   3816 	validator_log(val, ISC_LOG_DEBUG(9), "%s: creating %s for %s %s",
   3817 		      caller, operation, namestr, typestr);
   3818 }
   3819 
   3820 static void
   3821 validator_addede(dns_validator_t *val, uint16_t code, const char *extra) {
   3822 	REQUIRE(VALID_VALIDATOR(val));
   3823 
   3824 	char bdata[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE +
   3825 		   DNS_EDE_EXTRATEXT_LEN];
   3826 	isc_buffer_t b;
   3827 
   3828 	isc_buffer_init(&b, bdata, sizeof(bdata));
   3829 
   3830 	if (extra != NULL) {
   3831 		isc_buffer_putstr(&b, extra);
   3832 	}
   3833 
   3834 	if (val->name != NULL) {
   3835 		if (extra != NULL) {
   3836 			isc_buffer_putuint8(&b, ' ');
   3837 		}
   3838 		dns_name_totext(val->name, DNS_NAME_OMITFINALDOT, &b);
   3839 		isc_buffer_putuint8(&b, '/');
   3840 		dns_rdatatype_totext(val->type, &b);
   3841 	}
   3842 	isc_buffer_putuint8(&b, '\0');
   3843 
   3844 	dns_ede_add(&val->edectx, code, bdata);
   3845 }
   3846 
   3847 static void
   3848 validate_extendederror(dns_validator_t *val) {
   3849 	dns_validator_t *edeval = val;
   3850 	char bdata[DNS_EDE_EXTRATEXT_LEN];
   3851 	isc_buffer_t b;
   3852 
   3853 	REQUIRE(VALID_VALIDATOR(edeval));
   3854 
   3855 	isc_buffer_init(&b, bdata, sizeof(bdata));
   3856 
   3857 	while (edeval->parent != NULL) {
   3858 		edeval = edeval->parent;
   3859 	}
   3860 
   3861 	if (val->unsupported_algorithm != 0) {
   3862 		isc_buffer_clear(&b);
   3863 		dns_secalg_totext(val->unsupported_algorithm, &b);
   3864 		isc_buffer_putuint8(&b, '\0');
   3865 		validator_addede(val, DNS_EDE_DNSKEYALG, bdata);
   3866 	}
   3867 
   3868 	if (val->unsupported_digest != 0) {
   3869 		isc_buffer_clear(&b);
   3870 		dns_dsdigest_totext(val->unsupported_digest, &b);
   3871 		isc_buffer_putuint8(&b, '\0');
   3872 		validator_addede(val, DNS_EDE_DSDIGESTTYPE, bdata);
   3873 	}
   3874 }
   3875 
   3876 #if DNS_VALIDATOR_TRACE
   3877 ISC_REFCOUNT_TRACE_IMPL(dns_validator, destroy_validator);
   3878 #else
   3879 ISC_REFCOUNT_IMPL(dns_validator, destroy_validator);
   3880 #endif
   3881