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