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