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