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