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