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