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