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