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