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