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