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