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