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