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