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