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