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