2 * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: validator.c,v 1.164.12.23.4.1 2011-05-27 00:19:19 each Exp $ */
22 #include <isc/base32.h>
24 #include <isc/print.h>
26 #include <isc/string.h>
32 #include <dns/dnssec.h>
33 #include <dns/events.h>
34 #include <dns/keytable.h>
36 #include <dns/message.h>
37 #include <dns/ncache.h>
39 #include <dns/nsec3.h>
40 #include <dns/rdata.h>
41 #include <dns/rdatastruct.h>
42 #include <dns/rdataset.h>
43 #include <dns/rdatatype.h>
44 #include <dns/resolver.h>
45 #include <dns/result.h>
46 #include <dns/validator.h>
51 * Basic processing sequences.
53 * \li When called with rdataset and sigrdataset:
54 * validator_start -> validate -> proveunsecure -> startfinddlvsep ->
55 * dlv_validator_start -> validator_start -> validate -> proveunsecure
57 * validator_start -> validate -> nsecvalidate (secure wildcard answer)
59 * \li When called with rdataset, sigrdataset and with DNS_VALIDATOR_DLV:
60 * validator_start -> startfinddlvsep -> dlv_validator_start ->
61 * validator_start -> validate -> proveunsecure
63 * \li When called with rdataset:
64 * validator_start -> proveunsecure -> startfinddlvsep ->
65 * dlv_validator_start -> validator_start -> proveunsecure
67 * \li When called with rdataset and with DNS_VALIDATOR_DLV:
68 * validator_start -> startfinddlvsep -> dlv_validator_start ->
69 * validator_start -> proveunsecure
71 * \li When called without a rdataset:
72 * validator_start -> nsecvalidate -> proveunsecure -> startfinddlvsep ->
73 * dlv_validator_start -> validator_start -> nsecvalidate -> proveunsecure
75 * Note: there isn't a case for DNS_VALIDATOR_DLV here as we want nsecvalidate()
76 * to always validate the authority section even when it does not contain
79 * validator_start: determines what type of validation to do.
80 * validate: attempts to perform a positive validation.
81 * proveunsecure: attempts to prove the answer comes from a unsecure zone.
82 * nsecvalidate: attempts to prove a negative response.
83 * startfinddlvsep: starts the DLV record lookup.
84 * dlv_validator_start: resets state and restarts the lookup using the
85 * DLV RRset found by startfinddlvsep.
88 #define VALIDATOR_MAGIC ISC_MAGIC('V', 'a', 'l', '?')
89 #define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
91 #define VALATTR_SHUTDOWN 0x0001 /*%< Shutting down. */
92 #define VALATTR_CANCELED 0x0002 /*%< Canceled. */
93 #define VALATTR_TRIEDVERIFY 0x0004 /*%< We have found a key and
94 * have attempted a verify. */
95 #define VALATTR_INSECURITY 0x0010 /*%< Attempting proveunsecure. */
96 #define VALATTR_DLVTRIED 0x0020 /*%< Looked for a DLV record. */
99 * NSEC proofs to be looked for.
101 #define VALATTR_NEEDNOQNAME 0x00000100
102 #define VALATTR_NEEDNOWILDCARD 0x00000200
103 #define VALATTR_NEEDNODATA 0x00000400
106 * NSEC proofs that have been found.
108 #define VALATTR_FOUNDNOQNAME 0x00001000
109 #define VALATTR_FOUNDNOWILDCARD 0x00002000
110 #define VALATTR_FOUNDNODATA 0x00004000
111 #define VALATTR_FOUNDCLOSEST 0x00008000
116 #define VALATTR_FOUNDOPTOUT 0x00010000
117 #define VALATTR_FOUNDUNKNOWN 0x00020000
119 #define NEEDNODATA(val) ((val->attributes & VALATTR_NEEDNODATA) != 0)
120 #define NEEDNOQNAME(val) ((val->attributes & VALATTR_NEEDNOQNAME) != 0)
121 #define NEEDNOWILDCARD(val) ((val->attributes & VALATTR_NEEDNOWILDCARD) != 0)
122 #define DLVTRIED(val) ((val->attributes & VALATTR_DLVTRIED) != 0)
123 #define FOUNDNODATA(val) ((val->attributes & VALATTR_FOUNDNODATA) != 0)
124 #define FOUNDNOQNAME(val) ((val->attributes & VALATTR_FOUNDNOQNAME) != 0)
125 #define FOUNDNOWILDCARD(val) ((val->attributes & VALATTR_FOUNDNOWILDCARD) != 0)
126 #define FOUNDCLOSEST(val) ((val->attributes & VALATTR_FOUNDCLOSEST) != 0)
127 #define FOUNDOPTOUT(val) ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
129 #define SHUTDOWN(v) (((v)->attributes & VALATTR_SHUTDOWN) != 0)
130 #define CANCELED(v) (((v)->attributes & VALATTR_CANCELED) != 0)
133 destroy(dns_validator_t *val);
136 get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
137 dns_rdataset_t *rdataset);
140 validate(dns_validator_t *val, isc_boolean_t resume);
143 validatezonekey(dns_validator_t *val);
146 nsecvalidate(dns_validator_t *val, isc_boolean_t resume);
149 proveunsecure(dns_validator_t *val, isc_boolean_t have_ds,
150 isc_boolean_t resume);
153 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
154 isc_logmodule_t *module, int level, const char *fmt, va_list ap)
155 ISC_FORMAT_PRINTF(5, 0);
158 validator_log(dns_validator_t *val, int level, const char *fmt, ...)
159 ISC_FORMAT_PRINTF(3, 4);
162 validator_logcreate(dns_validator_t *val,
163 dns_name_t *name, dns_rdatatype_t type,
164 const char *caller, const char *operation);
167 dlv_validatezonekey(dns_validator_t *val);
170 dlv_validator_start(dns_validator_t *val);
173 finddlvsep(dns_validator_t *val, isc_boolean_t resume);
176 startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure);
179 * Mark the RRsets as a answer.
182 markanswer(dns_validator_t *val, const char *where) {
183 validator_log(val, ISC_LOG_DEBUG(3), "marking as answer (%s)", where);
184 if (val->event->rdataset != NULL)
185 dns_rdataset_settrust(val->event->rdataset, dns_trust_answer);
186 if (val->event->sigrdataset != NULL)
187 dns_rdataset_settrust(val->event->sigrdataset,
192 marksecure(dns_validatorevent_t *event) {
193 dns_rdataset_settrust(event->rdataset, dns_trust_secure);
194 if (event->sigrdataset != NULL)
195 dns_rdataset_settrust(event->sigrdataset, dns_trust_secure);
199 validator_done(dns_validator_t *val, isc_result_t result) {
202 if (val->event == NULL)
206 * Caller must be holding the lock.
209 val->event->result = result;
210 task = val->event->ev_sender;
211 val->event->ev_sender = val;
212 val->event->ev_type = DNS_EVENT_VALIDATORDONE;
213 val->event->ev_action = val->action;
214 val->event->ev_arg = val->arg;
215 isc_task_sendanddetach(&task, (isc_event_t **)&val->event);
218 static inline isc_boolean_t
219 exit_check(dns_validator_t *val) {
221 * Caller must be holding the lock.
226 INSIST(val->event == NULL);
228 if (val->fetch != NULL || val->subvalidator != NULL)
235 * Check that we have atleast one supported algorithm in the DLV RRset.
237 static inline isc_boolean_t
238 dlv_algorithm_supported(dns_validator_t *val) {
239 dns_rdata_t rdata = DNS_RDATA_INIT;
243 for (result = dns_rdataset_first(&val->dlv);
244 result == ISC_R_SUCCESS;
245 result = dns_rdataset_next(&val->dlv)) {
246 dns_rdata_reset(&rdata);
247 dns_rdataset_current(&val->dlv, &rdata);
248 result = dns_rdata_tostruct(&rdata, &dlv, NULL);
249 RUNTIME_CHECK(result == ISC_R_SUCCESS);
251 if (!dns_resolver_algorithm_supported(val->view->resolver,
256 if (dlv.digest_type != DNS_DSDIGEST_SHA256 &&
257 dlv.digest_type != DNS_DSDIGEST_SHA1)
266 * Look in the NSEC record returned from a DS query to see if there is
267 * a NS RRset at this name. If it is found we are at a delegation point.
270 isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
271 isc_result_t dbresult)
273 dns_fixedname_t fixed;
274 dns_label_t hashlabel;
275 dns_name_t nsec3name;
276 dns_rdata_nsec3_t nsec3;
277 dns_rdata_t rdata = DNS_RDATA_INIT;
284 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
285 unsigned char owner[NSEC3_MAX_HASH_LENGTH];
288 REQUIRE(dbresult == DNS_R_NXRRSET || dbresult == DNS_R_NCACHENXRRSET);
290 dns_rdataset_init(&set);
291 if (dbresult == DNS_R_NXRRSET)
292 dns_rdataset_clone(rdataset, &set);
294 result = dns_ncache_getrdataset(rdataset, name,
295 dns_rdatatype_nsec, &set);
296 if (result == ISC_R_NOTFOUND)
298 if (result != ISC_R_SUCCESS)
302 INSIST(set.type == dns_rdatatype_nsec);
305 result = dns_rdataset_first(&set);
306 if (result == ISC_R_SUCCESS) {
307 dns_rdataset_current(&set, &rdata);
308 found = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
309 dns_rdata_reset(&rdata);
311 dns_rdataset_disassociate(&set);
316 * Iterate over the ncache entry.
319 dns_name_init(&nsec3name, NULL);
320 dns_fixedname_init(&fixed);
321 dns_name_downcase(name, dns_fixedname_name(&fixed), NULL);
322 name = dns_fixedname_name(&fixed);
323 result = dns_rdataset_first(rdataset);
324 for (result = dns_rdataset_first(rdataset);
325 result == ISC_R_SUCCESS;
326 result = dns_rdataset_next(rdataset))
328 dns_ncache_current(rdataset, &nsec3name, &set);
329 if (set.type != dns_rdatatype_nsec3) {
330 dns_rdataset_disassociate(&set);
333 dns_name_getlabel(&nsec3name, 0, &hashlabel);
334 isc_region_consume(&hashlabel, 1);
335 isc_buffer_init(&buffer, owner, sizeof(owner));
336 result = isc_base32hex_decoderegion(&hashlabel, &buffer);
337 if (result != ISC_R_SUCCESS) {
338 dns_rdataset_disassociate(&set);
341 for (result = dns_rdataset_first(&set);
342 result == ISC_R_SUCCESS;
343 result = dns_rdataset_next(&set))
345 dns_rdata_reset(&rdata);
346 dns_rdataset_current(&set, &rdata);
347 (void)dns_rdata_tostruct(&rdata, &nsec3, NULL);
350 length = isc_iterated_hash(hash, nsec3.hash,
351 nsec3.iterations, nsec3.salt,
353 name->ndata, name->length);
354 if (length != isc_buffer_usedlength(&buffer))
356 order = memcmp(hash, owner, length);
358 found = dns_nsec3_typepresent(&rdata,
360 dns_rdataset_disassociate(&set);
363 if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) == 0)
366 * Does this optout span cover the name?
368 scope = memcmp(owner, nsec3.next, nsec3.next_length);
369 if ((scope < 0 && order > 0 &&
370 memcmp(hash, nsec3.next, length) < 0) ||
371 (scope >= 0 && (order > 0 ||
372 memcmp(hash, nsec3.next, length) < 0)))
374 dns_rdataset_disassociate(&set);
378 dns_rdataset_disassociate(&set);
384 * We have been asked to to look for a key.
385 * If found resume the validation process.
386 * If not found fail the validation process.
389 fetch_callback_validator(isc_task_t *task, isc_event_t *event) {
390 dns_fetchevent_t *devent;
391 dns_validator_t *val;
392 dns_rdataset_t *rdataset;
393 isc_boolean_t want_destroy;
395 isc_result_t eresult;
396 isc_result_t saved_result;
399 INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
400 devent = (dns_fetchevent_t *)event;
401 val = devent->ev_arg;
402 rdataset = &val->frdataset;
403 eresult = devent->result;
405 /* Free resources which are not of interest. */
406 if (devent->node != NULL)
407 dns_db_detachnode(devent->db, &devent->node);
408 if (devent->db != NULL)
409 dns_db_detach(&devent->db);
410 if (dns_rdataset_isassociated(&val->fsigrdataset))
411 dns_rdataset_disassociate(&val->fsigrdataset);
412 isc_event_free(&event);
413 dns_resolver_destroyfetch(&val->fetch);
415 INSIST(val->event != NULL);
417 validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_validator");
420 validator_done(val, ISC_R_CANCELED);
421 } else if (eresult == ISC_R_SUCCESS) {
422 validator_log(val, ISC_LOG_DEBUG(3),
423 "keyset with trust %s",
424 dns_trust_totext(rdataset->trust));
426 * Only extract the dst key if the keyset is secure.
428 if (rdataset->trust >= dns_trust_secure) {
429 result = get_dst_key(val, val->siginfo, rdataset);
430 if (result == ISC_R_SUCCESS)
431 val->keyset = &val->frdataset;
433 result = validate(val, ISC_TRUE);
434 if (result == DNS_R_NOVALIDSIG &&
435 (val->attributes & VALATTR_TRIEDVERIFY) == 0)
437 saved_result = result;
438 validator_log(val, ISC_LOG_DEBUG(3),
439 "falling back to insecurity proof");
440 val->attributes |= VALATTR_INSECURITY;
441 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
442 if (result == DNS_R_NOTINSECURE)
443 result = saved_result;
445 if (result != DNS_R_WAIT)
446 validator_done(val, result);
448 validator_log(val, ISC_LOG_DEBUG(3),
449 "fetch_callback_validator: got %s",
450 isc_result_totext(eresult));
451 if (eresult == ISC_R_CANCELED)
452 validator_done(val, eresult);
454 validator_done(val, DNS_R_BROKENCHAIN);
456 want_destroy = exit_check(val);
463 * We were asked to look for a DS record as part of following a key chain
464 * upwards. If found resume the validation process. If not found fail the
465 * validation process.
468 dsfetched(isc_task_t *task, isc_event_t *event) {
469 dns_fetchevent_t *devent;
470 dns_validator_t *val;
471 dns_rdataset_t *rdataset;
472 isc_boolean_t want_destroy;
474 isc_result_t eresult;
477 INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
478 devent = (dns_fetchevent_t *)event;
479 val = devent->ev_arg;
480 rdataset = &val->frdataset;
481 eresult = devent->result;
483 /* Free resources which are not of interest. */
484 if (devent->node != NULL)
485 dns_db_detachnode(devent->db, &devent->node);
486 if (devent->db != NULL)
487 dns_db_detach(&devent->db);
488 if (dns_rdataset_isassociated(&val->fsigrdataset))
489 dns_rdataset_disassociate(&val->fsigrdataset);
490 isc_event_free(&event);
491 dns_resolver_destroyfetch(&val->fetch);
493 INSIST(val->event != NULL);
495 validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched");
498 validator_done(val, ISC_R_CANCELED);
499 } else if (eresult == ISC_R_SUCCESS) {
500 validator_log(val, ISC_LOG_DEBUG(3),
501 "dsset with trust %s",
502 dns_trust_totext(rdataset->trust));
503 val->dsset = &val->frdataset;
504 result = validatezonekey(val);
505 if (result != DNS_R_WAIT)
506 validator_done(val, result);
507 } else if (eresult == DNS_R_NXRRSET ||
508 eresult == DNS_R_NCACHENXRRSET ||
509 eresult == DNS_R_SERVFAIL) /* RFC 1034 parent? */
511 validator_log(val, ISC_LOG_DEBUG(3),
512 "falling back to insecurity proof (%s)",
513 dns_result_totext(eresult));
514 val->attributes |= VALATTR_INSECURITY;
515 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
516 if (result != DNS_R_WAIT)
517 validator_done(val, result);
519 validator_log(val, ISC_LOG_DEBUG(3),
521 isc_result_totext(eresult));
522 if (eresult == ISC_R_CANCELED)
523 validator_done(val, eresult);
525 validator_done(val, DNS_R_BROKENCHAIN);
527 want_destroy = exit_check(val);
534 * We were asked to look for the DS record as part of proving that a
537 * If the DS record doesn't exist and the query name corresponds to
538 * a delegation point we are transitioning from a secure zone to a
541 * If the DS record exists it will be secure. We can continue looking
542 * for the break point in the chain of trust.
545 dsfetched2(isc_task_t *task, isc_event_t *event) {
546 dns_fetchevent_t *devent;
547 dns_validator_t *val;
549 isc_boolean_t want_destroy;
551 isc_result_t eresult;
554 INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
555 devent = (dns_fetchevent_t *)event;
556 val = devent->ev_arg;
557 eresult = devent->result;
559 /* Free resources which are not of interest. */
560 if (devent->node != NULL)
561 dns_db_detachnode(devent->db, &devent->node);
562 if (devent->db != NULL)
563 dns_db_detach(&devent->db);
564 if (dns_rdataset_isassociated(&val->fsigrdataset))
565 dns_rdataset_disassociate(&val->fsigrdataset);
566 dns_resolver_destroyfetch(&val->fetch);
568 INSIST(val->event != NULL);
570 validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched2: %s",
571 dns_result_totext(eresult));
574 validator_done(val, ISC_R_CANCELED);
575 } else if (eresult == DNS_R_NXRRSET || eresult == DNS_R_NCACHENXRRSET) {
577 * There is no DS. If this is a delegation, we're done.
579 tname = dns_fixedname_name(&devent->foundname);
580 if (isdelegation(tname, &val->frdataset, eresult)) {
581 if (val->mustbesecure) {
582 validator_log(val, ISC_LOG_WARNING,
583 "must be secure failure");
584 validator_done(val, DNS_R_MUSTBESECURE);
585 } else if (val->view->dlv == NULL || DLVTRIED(val)) {
586 markanswer(val, "dsfetched2");
587 validator_done(val, ISC_R_SUCCESS);
589 result = startfinddlvsep(val, tname);
590 if (result != DNS_R_WAIT)
591 validator_done(val, result);
594 result = proveunsecure(val, ISC_FALSE, ISC_TRUE);
595 if (result != DNS_R_WAIT)
596 validator_done(val, result);
598 } else if (eresult == ISC_R_SUCCESS ||
599 eresult == DNS_R_NXDOMAIN ||
600 eresult == DNS_R_NCACHENXDOMAIN)
603 * There is a DS which may or may not be a zone cut.
604 * In either case we are still in a secure zone resume
607 result = proveunsecure(val, ISC_TF(eresult == ISC_R_SUCCESS),
609 if (result != DNS_R_WAIT)
610 validator_done(val, result);
612 if (eresult == ISC_R_CANCELED)
613 validator_done(val, eresult);
615 validator_done(val, DNS_R_NOVALIDDS);
617 isc_event_free(&event);
618 want_destroy = exit_check(val);
625 * Callback from when a DNSKEY RRset has been validated.
627 * Resumes the stalled validation process.
630 keyvalidated(isc_task_t *task, isc_event_t *event) {
631 dns_validatorevent_t *devent;
632 dns_validator_t *val;
633 isc_boolean_t want_destroy;
635 isc_result_t eresult;
636 isc_result_t saved_result;
639 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
641 devent = (dns_validatorevent_t *)event;
642 val = devent->ev_arg;
643 eresult = devent->result;
645 isc_event_free(&event);
646 dns_validator_destroy(&val->subvalidator);
648 INSIST(val->event != NULL);
650 validator_log(val, ISC_LOG_DEBUG(3), "in keyvalidated");
653 validator_done(val, ISC_R_CANCELED);
654 } else if (eresult == ISC_R_SUCCESS) {
655 validator_log(val, ISC_LOG_DEBUG(3),
656 "keyset with trust %s",
657 dns_trust_totext(val->frdataset.trust));
659 * Only extract the dst key if the keyset is secure.
661 if (val->frdataset.trust >= dns_trust_secure)
662 (void) get_dst_key(val, val->siginfo, &val->frdataset);
663 result = validate(val, ISC_TRUE);
664 if (result == DNS_R_NOVALIDSIG &&
665 (val->attributes & VALATTR_TRIEDVERIFY) == 0)
667 saved_result = result;
668 validator_log(val, ISC_LOG_DEBUG(3),
669 "falling back to insecurity proof");
670 val->attributes |= VALATTR_INSECURITY;
671 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
672 if (result == DNS_R_NOTINSECURE)
673 result = saved_result;
675 if (result != DNS_R_WAIT)
676 validator_done(val, result);
678 if (eresult != DNS_R_BROKENCHAIN) {
679 if (dns_rdataset_isassociated(&val->frdataset))
680 dns_rdataset_expire(&val->frdataset);
681 if (dns_rdataset_isassociated(&val->fsigrdataset))
682 dns_rdataset_expire(&val->fsigrdataset);
684 validator_log(val, ISC_LOG_DEBUG(3),
685 "keyvalidated: got %s",
686 isc_result_totext(eresult));
687 validator_done(val, DNS_R_BROKENCHAIN);
689 want_destroy = exit_check(val);
696 * Callback when the DS record has been validated.
698 * Resumes validation of the zone key or the unsecure zone proof.
701 dsvalidated(isc_task_t *task, isc_event_t *event) {
702 dns_validatorevent_t *devent;
703 dns_validator_t *val;
704 isc_boolean_t want_destroy;
706 isc_result_t eresult;
709 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
711 devent = (dns_validatorevent_t *)event;
712 val = devent->ev_arg;
713 eresult = devent->result;
715 isc_event_free(&event);
716 dns_validator_destroy(&val->subvalidator);
718 INSIST(val->event != NULL);
720 validator_log(val, ISC_LOG_DEBUG(3), "in dsvalidated");
723 validator_done(val, ISC_R_CANCELED);
724 } else if (eresult == ISC_R_SUCCESS) {
725 isc_boolean_t have_dsset;
727 validator_log(val, ISC_LOG_DEBUG(3),
729 val->frdataset.type == dns_rdatatype_ds ?
730 "dsset" : "ds non-existance",
731 dns_trust_totext(val->frdataset.trust));
732 have_dsset = ISC_TF(val->frdataset.type == dns_rdatatype_ds);
733 name = dns_fixedname_name(&val->fname);
734 if ((val->attributes & VALATTR_INSECURITY) != 0 &&
735 val->frdataset.covers == dns_rdatatype_ds &&
736 val->frdataset.type == 0 &&
737 isdelegation(name, &val->frdataset, DNS_R_NCACHENXRRSET)) {
738 if (val->mustbesecure) {
739 validator_log(val, ISC_LOG_WARNING,
740 "must be secure failure, no DS "
741 "and this is a delegation");
742 result = DNS_R_MUSTBESECURE;
743 } else if (val->view->dlv == NULL || DLVTRIED(val)) {
744 markanswer(val, "dsvalidated");
745 result = ISC_R_SUCCESS;;
747 result = startfinddlvsep(val, name);
748 } else if ((val->attributes & VALATTR_INSECURITY) != 0) {
749 result = proveunsecure(val, have_dsset, ISC_TRUE);
751 result = validatezonekey(val);
752 if (result != DNS_R_WAIT)
753 validator_done(val, result);
755 if (eresult != DNS_R_BROKENCHAIN) {
756 if (dns_rdataset_isassociated(&val->frdataset))
757 dns_rdataset_expire(&val->frdataset);
758 if (dns_rdataset_isassociated(&val->fsigrdataset))
759 dns_rdataset_expire(&val->fsigrdataset);
761 validator_log(val, ISC_LOG_DEBUG(3),
762 "dsvalidated: got %s",
763 isc_result_totext(eresult));
764 validator_done(val, DNS_R_BROKENCHAIN);
766 want_destroy = exit_check(val);
773 * Return ISC_R_SUCCESS if we can determine that the name doesn't exist
774 * or we can determine whether there is data or not at the name.
775 * If the name does not exist return the wildcard name.
777 * Return ISC_R_IGNORE when the NSEC is not the appropriate one.
780 nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
781 dns_rdataset_t *nsecset, isc_boolean_t *exists,
782 isc_boolean_t *data, dns_name_t *wild)
785 dns_rdata_t rdata = DNS_RDATA_INIT;
787 dns_namereln_t relation;
788 unsigned int olabels, nlabels, labels;
789 dns_rdata_nsec_t nsec;
790 isc_boolean_t atparent;
794 REQUIRE(exists != NULL);
795 REQUIRE(data != NULL);
796 REQUIRE(nsecset != NULL &&
797 nsecset->type == dns_rdatatype_nsec);
799 result = dns_rdataset_first(nsecset);
800 if (result != ISC_R_SUCCESS) {
801 validator_log(val, ISC_LOG_DEBUG(3),
802 "failure processing NSEC set");
805 dns_rdataset_current(nsecset, &rdata);
807 validator_log(val, ISC_LOG_DEBUG(3), "looking for relevant nsec");
808 relation = dns_name_fullcompare(name, nsecname, &order, &olabels);
812 * The name is not within the NSEC range.
814 validator_log(val, ISC_LOG_DEBUG(3),
815 "NSEC does not cover name, before NSEC");
816 return (ISC_R_IGNORE);
821 * The names are the same.
823 atparent = dns_rdatatype_atparent(val->event->type);
824 ns = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
825 soa = dns_nsec_typepresent(&rdata, dns_rdatatype_soa);
829 * This NSEC record is from somewhere higher in
830 * the DNS, and at the parent of a delegation.
831 * It can not be legitimately used here.
833 validator_log(val, ISC_LOG_DEBUG(3),
834 "ignoring parent nsec");
835 return (ISC_R_IGNORE);
837 } else if (atparent && ns && soa) {
839 * This NSEC record is from the child.
840 * It can not be legitimately used here.
842 validator_log(val, ISC_LOG_DEBUG(3),
843 "ignoring child nsec");
844 return (ISC_R_IGNORE);
846 if (val->event->type == dns_rdatatype_cname ||
847 val->event->type == dns_rdatatype_nxt ||
848 val->event->type == dns_rdatatype_nsec ||
849 val->event->type == dns_rdatatype_key ||
850 !dns_nsec_typepresent(&rdata, dns_rdatatype_cname)) {
852 *data = dns_nsec_typepresent(&rdata, val->event->type);
853 validator_log(val, ISC_LOG_DEBUG(3),
854 "nsec proves name exists (owner) data=%d",
856 return (ISC_R_SUCCESS);
858 validator_log(val, ISC_LOG_DEBUG(3), "NSEC proves CNAME exists");
859 return (ISC_R_IGNORE);
862 if (relation == dns_namereln_subdomain &&
863 dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
864 !dns_nsec_typepresent(&rdata, dns_rdatatype_soa))
867 * This NSEC record is from somewhere higher in
868 * the DNS, and at the parent of a delegation.
869 * It can not be legitimately used here.
871 validator_log(val, ISC_LOG_DEBUG(3), "ignoring parent nsec");
872 return (ISC_R_IGNORE);
875 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
876 if (result != ISC_R_SUCCESS)
878 relation = dns_name_fullcompare(&nsec.next, name, &order, &nlabels);
880 dns_rdata_freestruct(&nsec);
881 validator_log(val, ISC_LOG_DEBUG(3),
882 "ignoring nsec matches next name");
883 return (ISC_R_IGNORE);
886 if (order < 0 && !dns_name_issubdomain(nsecname, &nsec.next)) {
888 * The name is not within the NSEC range.
890 dns_rdata_freestruct(&nsec);
891 validator_log(val, ISC_LOG_DEBUG(3),
892 "ignoring nsec because name is past end of range");
893 return (ISC_R_IGNORE);
896 if (order > 0 && relation == dns_namereln_subdomain) {
897 validator_log(val, ISC_LOG_DEBUG(3),
898 "nsec proves name exist (empty)");
899 dns_rdata_freestruct(&nsec);
902 return (ISC_R_SUCCESS);
906 dns_name_init(&common, NULL);
907 if (olabels > nlabels) {
908 labels = dns_name_countlabels(nsecname);
909 dns_name_getlabelsequence(nsecname, labels - olabels,
912 labels = dns_name_countlabels(&nsec.next);
913 dns_name_getlabelsequence(&nsec.next, labels - nlabels,
916 result = dns_name_concatenate(dns_wildcardname, &common,
918 if (result != ISC_R_SUCCESS) {
919 dns_rdata_freestruct(&nsec);
920 validator_log(val, ISC_LOG_DEBUG(3),
921 "failure generating wildcard name");
925 dns_rdata_freestruct(&nsec);
926 validator_log(val, ISC_LOG_DEBUG(3), "nsec range ok");
928 return (ISC_R_SUCCESS);
932 nsec3noexistnodata(dns_validator_t *val, dns_name_t* name,
933 dns_name_t *nsec3name, dns_rdataset_t *nsec3set,
934 dns_name_t *zonename, isc_boolean_t *exists,
935 isc_boolean_t *data, isc_boolean_t *optout,
936 isc_boolean_t *unknown, isc_boolean_t *setclosest,
937 isc_boolean_t *setnearest, dns_name_t *closest,
940 char namebuf[DNS_NAME_FORMATSIZE];
941 dns_fixedname_t fzone;
942 dns_fixedname_t qfixed;
943 dns_label_t hashlabel;
946 dns_rdata_nsec3_t nsec3;
947 dns_rdata_t rdata = DNS_RDATA_INIT;
950 isc_boolean_t atparent;
955 isc_result_t answer = ISC_R_IGNORE;
957 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
958 unsigned char owner[NSEC3_MAX_HASH_LENGTH];
960 unsigned int qlabels;
961 unsigned int zlabels;
963 REQUIRE((exists == NULL && data == NULL) ||
964 (exists != NULL && data != NULL));
965 REQUIRE(nsec3set != NULL && nsec3set->type == dns_rdatatype_nsec3);
966 REQUIRE((setclosest == NULL && closest == NULL) ||
967 (setclosest != NULL && closest != NULL));
968 REQUIRE((setnearest == NULL && nearest == NULL) ||
969 (setnearest != NULL && nearest != NULL));
971 result = dns_rdataset_first(nsec3set);
972 if (result != ISC_R_SUCCESS) {
973 validator_log(val, ISC_LOG_DEBUG(3),
974 "failure processing NSEC3 set");
978 dns_rdataset_current(nsec3set, &rdata);
980 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
981 if (result != ISC_R_SUCCESS)
984 validator_log(val, ISC_LOG_DEBUG(3), "looking for relevant NSEC3");
986 dns_fixedname_init(&fzone);
987 zone = dns_fixedname_name(&fzone);
988 zlabels = dns_name_countlabels(nsec3name);
991 * NSEC3 records must have two or more labels to be valid.
994 return (ISC_R_IGNORE);
997 * Strip off the NSEC3 hash to get the zone.
1000 dns_name_split(nsec3name, zlabels, NULL, zone);
1003 * If not below the zone name we can ignore this record.
1005 if (!dns_name_issubdomain(name, zone))
1006 return (ISC_R_IGNORE);
1009 * Is this zone the same or deeper than the current zone?
1011 if (dns_name_countlabels(zonename) == 0 ||
1012 dns_name_issubdomain(zone, zonename))
1013 dns_name_copy(zone, zonename, NULL);
1015 if (!dns_name_equal(zone, zonename))
1016 return (ISC_R_IGNORE);
1019 * Are we only looking for the most enclosing zone?
1021 if (exists == NULL || data == NULL)
1022 return (ISC_R_SUCCESS);
1025 * Only set unknown once we are sure that this NSEC3 is from
1026 * the deepest covering zone.
1028 if (!dns_nsec3_supportedhash(nsec3.hash)) {
1029 if (unknown != NULL)
1030 *unknown = ISC_TRUE;
1031 return (ISC_R_IGNORE);
1035 * Recover the hash from the first label.
1037 dns_name_getlabel(nsec3name, 0, &hashlabel);
1038 isc_region_consume(&hashlabel, 1);
1039 isc_buffer_init(&buffer, owner, sizeof(owner));
1040 result = isc_base32hex_decoderegion(&hashlabel, &buffer);
1041 if (result != ISC_R_SUCCESS)
1045 * The hash lengths should match. If not ignore the record.
1047 if (isc_buffer_usedlength(&buffer) != nsec3.next_length)
1048 return (ISC_R_IGNORE);
1051 * Work out what this NSEC3 covers.
1052 * Inside (<0) or outside (>=0).
1054 scope = memcmp(owner, nsec3.next, nsec3.next_length);
1057 * Prepare to compute all the hashes.
1059 dns_fixedname_init(&qfixed);
1060 qname = dns_fixedname_name(&qfixed);
1061 dns_name_downcase(name, qname, NULL);
1062 qlabels = dns_name_countlabels(qname);
1065 while (qlabels >= zlabels) {
1066 length = isc_iterated_hash(hash, nsec3.hash, nsec3.iterations,
1067 nsec3.salt, nsec3.salt_length,
1068 qname->ndata, qname->length);
1070 * The computed hash length should match.
1072 if (length != nsec3.next_length) {
1073 validator_log(val, ISC_LOG_DEBUG(3),
1074 "ignoring NSEC bad length %u vs %u",
1075 length, nsec3.next_length);
1076 return (ISC_R_IGNORE);
1079 order = memcmp(hash, owner, length);
1080 if (first && order == 0) {
1082 * The hashes are the same.
1084 atparent = dns_rdatatype_atparent(val->event->type);
1085 ns = dns_nsec3_typepresent(&rdata, dns_rdatatype_ns);
1086 soa = dns_nsec3_typepresent(&rdata, dns_rdatatype_soa);
1090 * This NSEC record is from somewhere
1091 * higher in the DNS, and at the
1092 * parent of a delegation. It can not
1093 * be legitimately used here.
1095 validator_log(val, ISC_LOG_DEBUG(3),
1096 "ignoring parent NSEC3");
1097 return (ISC_R_IGNORE);
1099 } else if (atparent && ns && soa) {
1101 * This NSEC record is from the child.
1102 * It can not be legitimately used here.
1104 validator_log(val, ISC_LOG_DEBUG(3),
1105 "ignoring child NSEC3");
1106 return (ISC_R_IGNORE);
1108 if (val->event->type == dns_rdatatype_cname ||
1109 val->event->type == dns_rdatatype_nxt ||
1110 val->event->type == dns_rdatatype_nsec ||
1111 val->event->type == dns_rdatatype_key ||
1112 !dns_nsec3_typepresent(&rdata, dns_rdatatype_cname)) {
1114 *data = dns_nsec3_typepresent(&rdata,
1116 validator_log(val, ISC_LOG_DEBUG(3),
1117 "NSEC3 proves name exists (owner) "
1119 return (ISC_R_SUCCESS);
1121 validator_log(val, ISC_LOG_DEBUG(3),
1122 "NSEC3 proves CNAME exists");
1123 return (ISC_R_IGNORE);
1127 dns_nsec3_typepresent(&rdata, dns_rdatatype_ns) &&
1128 !dns_nsec3_typepresent(&rdata, dns_rdatatype_soa))
1131 * This NSEC3 record is from somewhere higher in
1132 * the DNS, and at the parent of a delegation.
1133 * It can not be legitimately used here.
1135 validator_log(val, ISC_LOG_DEBUG(3),
1136 "ignoring parent NSEC3");
1137 return (ISC_R_IGNORE);
1141 * Potential closest encloser.
1144 if (closest != NULL &&
1145 (dns_name_countlabels(closest) == 0 ||
1146 dns_name_issubdomain(qname, closest)) &&
1147 !dns_nsec3_typepresent(&rdata, dns_rdatatype_ds) &&
1148 !dns_nsec3_typepresent(&rdata, dns_rdatatype_dname) &&
1149 (dns_nsec3_typepresent(&rdata, dns_rdatatype_soa) ||
1150 !dns_nsec3_typepresent(&rdata, dns_rdatatype_ns)))
1153 dns_name_format(qname, namebuf,
1155 validator_log(val, ISC_LOG_DEBUG(3),
1156 "NSEC3 indicates potential "
1157 "closest encloser: '%s'",
1159 dns_name_copy(qname, closest, NULL);
1160 *setclosest = ISC_TRUE;
1162 dns_name_format(qname, namebuf, sizeof(namebuf));
1163 validator_log(val, ISC_LOG_DEBUG(3),
1164 "NSEC3 at super-domain %s", namebuf);
1169 * Find if the name does not exist.
1171 * We continue as we need to find the name closest to the
1172 * closest encloser that doesn't exist.
1174 * We also need to continue to ensure that we are not
1175 * proving the non-existence of a record in a sub-zone.
1176 * If that would be the case we will return ISC_R_IGNORE
1179 if ((scope < 0 && order > 0 &&
1180 memcmp(hash, nsec3.next, length) < 0) ||
1181 (scope >= 0 && (order > 0 ||
1182 memcmp(hash, nsec3.next, length) < 0)))
1184 char namebuf[DNS_NAME_FORMATSIZE];
1186 dns_name_format(qname, namebuf, sizeof(namebuf));
1187 validator_log(val, ISC_LOG_DEBUG(3), "NSEC3 proves "
1188 "name does not exist: '%s'", namebuf);
1189 if (nearest != NULL &&
1190 (dns_name_countlabels(nearest) == 0 ||
1191 dns_name_issubdomain(nearest, qname))) {
1192 dns_name_copy(qname, nearest, NULL);
1193 *setnearest = ISC_TRUE;
1196 *exists = ISC_FALSE;
1198 if (optout != NULL) {
1199 if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0)
1200 validator_log(val, ISC_LOG_DEBUG(3),
1201 "NSEC3 indicates optout");
1203 ISC_TF(nsec3.flags & DNS_NSEC3FLAG_OPTOUT);
1205 answer = ISC_R_SUCCESS;
1210 dns_name_split(qname, qlabels, NULL, qname);
1217 * Callback for when NSEC records have been validated.
1219 * Looks for NOQNAME, NODATA and OPTOUT proofs.
1221 * Resumes nsecvalidate.
1224 authvalidated(isc_task_t *task, isc_event_t *event) {
1225 dns_validatorevent_t *devent;
1226 dns_validator_t *val;
1227 dns_rdataset_t *rdataset;
1228 dns_rdataset_t *sigrdataset;
1229 isc_boolean_t want_destroy;
1230 isc_result_t result;
1231 isc_boolean_t exists, data;
1234 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
1236 devent = (dns_validatorevent_t *)event;
1237 rdataset = devent->rdataset;
1238 sigrdataset = devent->sigrdataset;
1239 val = devent->ev_arg;
1240 result = devent->result;
1241 dns_validator_destroy(&val->subvalidator);
1243 INSIST(val->event != NULL);
1245 validator_log(val, ISC_LOG_DEBUG(3), "in authvalidated");
1247 if (CANCELED(val)) {
1248 validator_done(val, ISC_R_CANCELED);
1249 } else if (result != ISC_R_SUCCESS) {
1250 validator_log(val, ISC_LOG_DEBUG(3),
1251 "authvalidated: got %s",
1252 isc_result_totext(result));
1253 if (result == DNS_R_BROKENCHAIN)
1255 if (result == ISC_R_CANCELED)
1256 validator_done(val, result);
1258 result = nsecvalidate(val, ISC_TRUE);
1259 if (result != DNS_R_WAIT)
1260 validator_done(val, result);
1263 dns_name_t **proofs = val->event->proofs;
1264 dns_name_t *wild = dns_fixedname_name(&val->wild);
1266 if (rdataset->trust == dns_trust_secure)
1267 val->seensig = ISC_TRUE;
1269 if (rdataset->type == dns_rdatatype_nsec &&
1270 rdataset->trust == dns_trust_secure &&
1271 (NEEDNODATA(val) || NEEDNOQNAME(val)) &&
1272 !FOUNDNODATA(val) && !FOUNDNOQNAME(val) &&
1273 nsecnoexistnodata(val, val->event->name, devent->name,
1274 rdataset, &exists, &data, wild)
1277 if (exists && !data) {
1278 val->attributes |= VALATTR_FOUNDNODATA;
1279 if (NEEDNODATA(val))
1280 proofs[DNS_VALIDATOR_NODATAPROOF] =
1284 val->attributes |= VALATTR_FOUNDNOQNAME;
1285 val->attributes |= VALATTR_FOUNDCLOSEST;
1287 * The NSEC noqname proof also contains
1288 * the closest encloser.
1291 if (NEEDNOQNAME(val))
1292 proofs[DNS_VALIDATOR_NOQNAMEPROOF] =
1297 result = nsecvalidate(val, ISC_TRUE);
1298 if (result != DNS_R_WAIT)
1299 validator_done(val, result);
1301 want_destroy = exit_check(val);
1307 * Free stuff from the event.
1309 isc_event_free(&event);
1313 * Looks for the requested name and type in the view (zones and cache).
1315 * When looking for a DLV record also checks to make sure the NSEC record
1316 * returns covers the query name as part of aggressive negative caching.
1320 * \li ISC_R_NOTFOUND
1321 * \li DNS_R_NCACHENXDOMAIN
1322 * \li DNS_R_NCACHENXRRSET
1324 * \li DNS_R_NXDOMAIN
1325 * \li DNS_R_BROKENCHAIN
1327 static inline isc_result_t
1328 view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
1329 dns_fixedname_t fixedname;
1330 dns_name_t *foundname;
1331 dns_rdata_nsec_t nsec;
1332 dns_rdata_t rdata = DNS_RDATA_INIT;
1333 isc_result_t result;
1334 unsigned int options;
1336 char buf1[DNS_NAME_FORMATSIZE];
1337 char buf2[DNS_NAME_FORMATSIZE];
1338 char buf3[DNS_NAME_FORMATSIZE];
1339 char namebuf[DNS_NAME_FORMATSIZE];
1340 char typebuf[DNS_RDATATYPE_FORMATSIZE];
1342 if (dns_rdataset_isassociated(&val->frdataset))
1343 dns_rdataset_disassociate(&val->frdataset);
1344 if (dns_rdataset_isassociated(&val->fsigrdataset))
1345 dns_rdataset_disassociate(&val->fsigrdataset);
1347 if (val->view->zonetable == NULL)
1348 return (ISC_R_CANCELED);
1350 if (isc_time_now(&now) == ISC_R_SUCCESS &&
1351 dns_resolver_getbadcache(val->view->resolver, name, type, &now)) {
1353 dns_name_format(name, namebuf, sizeof(namebuf));
1354 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
1355 validator_log(val, ISC_LOG_INFO, "bad cache hit (%s/%s)",
1357 return (DNS_R_BROKENCHAIN);
1360 options = DNS_DBFIND_PENDINGOK;
1361 if (type == dns_rdatatype_dlv)
1362 options |= DNS_DBFIND_COVERINGNSEC;
1363 dns_fixedname_init(&fixedname);
1364 foundname = dns_fixedname_name(&fixedname);
1365 result = dns_view_find(val->view, name, type, 0, options,
1366 ISC_FALSE, NULL, NULL, foundname,
1367 &val->frdataset, &val->fsigrdataset);
1369 if (result == DNS_R_NXDOMAIN) {
1370 if (dns_rdataset_isassociated(&val->frdataset))
1371 dns_rdataset_disassociate(&val->frdataset);
1372 if (dns_rdataset_isassociated(&val->fsigrdataset))
1373 dns_rdataset_disassociate(&val->fsigrdataset);
1374 } else if (result == DNS_R_COVERINGNSEC) {
1375 validator_log(val, ISC_LOG_DEBUG(3), "DNS_R_COVERINGNSEC");
1377 * Check if the returned NSEC covers the name.
1379 INSIST(type == dns_rdatatype_dlv);
1380 if (val->frdataset.trust != dns_trust_secure) {
1381 validator_log(val, ISC_LOG_DEBUG(3),
1382 "covering nsec: trust %s",
1383 dns_trust_totext(val->frdataset.trust));
1386 result = dns_rdataset_first(&val->frdataset);
1387 if (result != ISC_R_SUCCESS)
1389 dns_rdataset_current(&val->frdataset, &rdata);
1390 if (dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
1391 !dns_nsec_typepresent(&rdata, dns_rdatatype_soa)) {
1392 /* Parent NSEC record. */
1393 if (dns_name_issubdomain(name, foundname)) {
1394 validator_log(val, ISC_LOG_DEBUG(3),
1395 "covering nsec: for parent");
1399 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
1400 if (result != ISC_R_SUCCESS)
1402 if (dns_name_compare(foundname, &nsec.next) >= 0) {
1403 /* End of zone chain. */
1404 if (!dns_name_issubdomain(name, &nsec.next)) {
1406 * XXXMPA We could look for a parent NSEC
1407 * at nsec.next and if found retest with
1410 dns_rdata_freestruct(&nsec);
1411 validator_log(val, ISC_LOG_DEBUG(3),
1412 "covering nsec: not in zone");
1415 } else if (dns_name_compare(name, &nsec.next) >= 0) {
1417 * XXXMPA We could check if this NSEC is at a zone
1418 * apex and if the qname is not below it and look for
1419 * a parent NSEC with the same name. This requires
1420 * that we can cache both NSEC records which we
1421 * currently don't support.
1423 dns_rdata_freestruct(&nsec);
1424 validator_log(val, ISC_LOG_DEBUG(3),
1425 "covering nsec: not in range");
1428 if (isc_log_wouldlog(dns_lctx,ISC_LOG_DEBUG(3))) {
1429 dns_name_format(name, buf1, sizeof buf1);
1430 dns_name_format(foundname, buf2, sizeof buf2);
1431 dns_name_format(&nsec.next, buf3, sizeof buf3);
1432 validator_log(val, ISC_LOG_DEBUG(3),
1433 "covering nsec found: '%s' '%s' '%s'",
1436 if (dns_rdataset_isassociated(&val->frdataset))
1437 dns_rdataset_disassociate(&val->frdataset);
1438 if (dns_rdataset_isassociated(&val->fsigrdataset))
1439 dns_rdataset_disassociate(&val->fsigrdataset);
1440 dns_rdata_freestruct(&nsec);
1441 result = DNS_R_NCACHENXDOMAIN;
1442 } else if (result != ISC_R_SUCCESS &&
1443 result != DNS_R_NCACHENXDOMAIN &&
1444 result != DNS_R_NCACHENXRRSET &&
1445 result != DNS_R_EMPTYNAME &&
1446 result != DNS_R_NXRRSET &&
1447 result != ISC_R_NOTFOUND) {
1453 if (dns_rdataset_isassociated(&val->frdataset))
1454 dns_rdataset_disassociate(&val->frdataset);
1455 if (dns_rdataset_isassociated(&val->fsigrdataset))
1456 dns_rdataset_disassociate(&val->fsigrdataset);
1457 return (ISC_R_NOTFOUND);
1461 * Checks to make sure we are not going to loop. As we use a SHARED fetch
1462 * the validation process will stall if looping was to occur.
1464 static inline isc_boolean_t
1465 check_deadlock(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
1466 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
1468 dns_validator_t *parent;
1470 for (parent = val; parent != NULL; parent = parent->parent) {
1471 if (parent->event != NULL &&
1472 parent->event->type == type &&
1473 dns_name_equal(parent->event->name, name) &&
1475 * As NSEC3 records are meta data you sometimes
1476 * need to prove a NSEC3 record which says that
1477 * itself doesn't exist.
1479 (parent->event->type != dns_rdatatype_nsec3 ||
1480 rdataset == NULL || sigrdataset == NULL ||
1481 parent->event->message == NULL ||
1482 parent->event->rdataset != NULL ||
1483 parent->event->sigrdataset != NULL))
1485 validator_log(val, ISC_LOG_DEBUG(3),
1486 "continuing validation would lead to "
1487 "deadlock: aborting validation");
1495 * Start a fetch for the requested name and type.
1497 static inline isc_result_t
1498 create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
1499 isc_taskaction_t callback, const char *caller)
1501 if (dns_rdataset_isassociated(&val->frdataset))
1502 dns_rdataset_disassociate(&val->frdataset);
1503 if (dns_rdataset_isassociated(&val->fsigrdataset))
1504 dns_rdataset_disassociate(&val->fsigrdataset);
1506 if (check_deadlock(val, name, type, NULL, NULL))
1507 return (DNS_R_NOVALIDSIG);
1509 validator_logcreate(val, name, type, caller, "fetch");
1510 return (dns_resolver_createfetch(val->view->resolver, name, type,
1511 NULL, NULL, NULL, 0,
1512 val->event->ev_sender,
1520 * Start a subvalidation process.
1522 static inline isc_result_t
1523 create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
1524 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
1525 isc_taskaction_t action, const char *caller)
1527 isc_result_t result;
1529 if (check_deadlock(val, name, type, rdataset, sigrdataset))
1530 return (DNS_R_NOVALIDSIG);
1532 validator_logcreate(val, name, type, caller, "validator");
1533 result = dns_validator_create(val->view, name, type,
1534 rdataset, sigrdataset, NULL, 0,
1535 val->task, action, val,
1536 &val->subvalidator);
1537 if (result == ISC_R_SUCCESS) {
1538 val->subvalidator->parent = val;
1539 val->subvalidator->depth = val->depth + 1;
1545 * Try to find a key that could have signed 'siginfo' among those
1546 * in 'rdataset'. If found, build a dst_key_t for it and point
1549 * If val->key is non-NULL, this returns the next matching key.
1552 get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
1553 dns_rdataset_t *rdataset)
1555 isc_result_t result;
1557 dns_rdata_t rdata = DNS_RDATA_INIT;
1558 dst_key_t *oldkey = val->key;
1559 isc_boolean_t foundold;
1562 foundold = ISC_TRUE;
1564 foundold = ISC_FALSE;
1568 result = dns_rdataset_first(rdataset);
1569 if (result != ISC_R_SUCCESS)
1572 dns_rdataset_current(rdataset, &rdata);
1574 isc_buffer_init(&b, rdata.data, rdata.length);
1575 isc_buffer_add(&b, rdata.length);
1576 INSIST(val->key == NULL);
1577 result = dst_key_fromdns(&siginfo->signer, rdata.rdclass, &b,
1578 val->view->mctx, &val->key);
1579 if (result != ISC_R_SUCCESS)
1581 if (siginfo->algorithm ==
1582 (dns_secalg_t)dst_key_alg(val->key) &&
1584 (dns_keytag_t)dst_key_id(val->key) &&
1585 dst_key_iszonekey(val->key))
1589 * This is the key we're looking for.
1591 return (ISC_R_SUCCESS);
1592 else if (dst_key_compare(oldkey, val->key) == ISC_TRUE)
1594 foundold = ISC_TRUE;
1595 dst_key_free(&oldkey);
1598 dst_key_free(&val->key);
1599 dns_rdata_reset(&rdata);
1600 result = dns_rdataset_next(rdataset);
1601 } while (result == ISC_R_SUCCESS);
1602 if (result == ISC_R_NOMORE)
1603 result = ISC_R_NOTFOUND;
1607 dst_key_free(&oldkey);
1613 * Get the key that generated this signature.
1616 get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
1617 isc_result_t result;
1618 unsigned int nlabels;
1620 dns_namereln_t namereln;
1623 * Is the signer name appropriate for this signature?
1625 * The signer name must be at the same level as the owner name
1626 * or closer to the DNS root.
1628 namereln = dns_name_fullcompare(val->event->name, &siginfo->signer,
1630 if (namereln != dns_namereln_subdomain &&
1631 namereln != dns_namereln_equal)
1632 return (DNS_R_CONTINUE);
1634 if (namereln == dns_namereln_equal) {
1636 * If this is a self-signed keyset, it must not be a zone key
1637 * (since get_key is not called from validatezonekey).
1639 if (val->event->rdataset->type == dns_rdatatype_dnskey)
1640 return (DNS_R_CONTINUE);
1643 * Records appearing in the parent zone at delegation
1644 * points cannot be self-signed.
1646 if (dns_rdatatype_atparent(val->event->rdataset->type))
1647 return (DNS_R_CONTINUE);
1650 * SOA and NS RRsets can only be signed by a key with
1653 if (val->event->rdataset->type == dns_rdatatype_soa ||
1654 val->event->rdataset->type == dns_rdatatype_ns) {
1655 const char *typename;
1657 if (val->event->rdataset->type == dns_rdatatype_soa)
1661 validator_log(val, ISC_LOG_DEBUG(3),
1662 "%s signer mismatch", typename);
1663 return (DNS_R_CONTINUE);
1668 * Do we know about this key?
1670 result = view_find(val, &siginfo->signer, dns_rdatatype_dnskey);
1671 if (result == ISC_R_SUCCESS) {
1673 * We have an rrset for the given keyname.
1675 val->keyset = &val->frdataset;
1676 if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
1677 DNS_TRUST_ANSWER(val->frdataset.trust)) &&
1678 dns_rdataset_isassociated(&val->fsigrdataset))
1681 * We know the key but haven't validated it yet or
1682 * we have a key of trust answer but a DS/DLV
1683 * record for the zone may have been added.
1685 result = create_validator(val, &siginfo->signer,
1686 dns_rdatatype_dnskey,
1691 if (result != ISC_R_SUCCESS)
1693 return (DNS_R_WAIT);
1694 } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
1696 * Having a pending key with no signature means that
1697 * something is broken.
1699 result = DNS_R_CONTINUE;
1700 } else if (val->frdataset.trust < dns_trust_secure) {
1702 * The key is legitimately insecure. There's no
1703 * point in even attempting verification.
1706 result = ISC_R_SUCCESS;
1709 * See if we've got the key used in the signature.
1711 validator_log(val, ISC_LOG_DEBUG(3),
1712 "keyset with trust %s",
1713 dns_trust_totext(val->frdataset.trust));
1714 result = get_dst_key(val, siginfo, val->keyset);
1715 if (result != ISC_R_SUCCESS) {
1717 * Either the key we're looking for is not
1718 * in the rrset, or something bad happened.
1721 result = DNS_R_CONTINUE;
1724 } else if (result == ISC_R_NOTFOUND) {
1726 * We don't know anything about this key.
1728 result = create_fetch(val, &siginfo->signer,
1729 dns_rdatatype_dnskey,
1730 fetch_callback_validator, "get_key");
1731 if (result != ISC_R_SUCCESS)
1733 return (DNS_R_WAIT);
1734 } else if (result == DNS_R_NCACHENXDOMAIN ||
1735 result == DNS_R_NCACHENXRRSET ||
1736 result == DNS_R_EMPTYNAME ||
1737 result == DNS_R_NXDOMAIN ||
1738 result == DNS_R_NXRRSET)
1741 * This key doesn't exist.
1743 result = DNS_R_CONTINUE;
1744 } else if (result == DNS_R_BROKENCHAIN)
1747 if (dns_rdataset_isassociated(&val->frdataset) &&
1748 val->keyset != &val->frdataset)
1749 dns_rdataset_disassociate(&val->frdataset);
1750 if (dns_rdataset_isassociated(&val->fsigrdataset))
1751 dns_rdataset_disassociate(&val->fsigrdataset);
1757 compute_keytag(dns_rdata_t *rdata, dns_rdata_dnskey_t *key) {
1760 dns_rdata_toregion(rdata, &r);
1761 return (dst_region_computeid(&r, key->algorithm));
1765 * Is this keyset self-signed?
1767 static isc_boolean_t
1768 isselfsigned(dns_validator_t *val) {
1769 dns_rdataset_t *rdataset, *sigrdataset;
1770 dns_rdata_t rdata = DNS_RDATA_INIT;
1771 dns_rdata_t sigrdata = DNS_RDATA_INIT;
1772 dns_rdata_dnskey_t key;
1773 dns_rdata_rrsig_t sig;
1774 dns_keytag_t keytag;
1775 isc_result_t result;
1777 rdataset = val->event->rdataset;
1778 sigrdataset = val->event->sigrdataset;
1780 INSIST(rdataset->type == dns_rdatatype_dnskey);
1782 for (result = dns_rdataset_first(rdataset);
1783 result == ISC_R_SUCCESS;
1784 result = dns_rdataset_next(rdataset))
1786 dns_rdata_reset(&rdata);
1787 dns_rdataset_current(rdataset, &rdata);
1788 result = dns_rdata_tostruct(&rdata, &key, NULL);
1789 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1790 keytag = compute_keytag(&rdata, &key);
1791 for (result = dns_rdataset_first(sigrdataset);
1792 result == ISC_R_SUCCESS;
1793 result = dns_rdataset_next(sigrdataset))
1795 dns_rdata_reset(&sigrdata);
1796 dns_rdataset_current(sigrdataset, &sigrdata);
1797 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
1798 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1800 if (sig.algorithm == key.algorithm &&
1801 sig.keyid == keytag)
1809 * Attempt to verify the rdataset using the given key and rdata (RRSIG).
1810 * The signature was good and from a wildcard record and the QNAME does
1811 * not match the wildcard we need to look for a NOQNAME proof.
1814 * \li ISC_R_SUCCESS if the verification succeeds.
1815 * \li Others if the verification fails.
1818 verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata,
1821 isc_result_t result;
1822 dns_fixedname_t fixed;
1823 isc_boolean_t ignore = ISC_FALSE;
1825 val->attributes |= VALATTR_TRIEDVERIFY;
1826 dns_fixedname_init(&fixed);
1828 result = dns_dnssec_verify2(val->event->name, val->event->rdataset,
1829 key, ignore, val->view->mctx, rdata,
1830 dns_fixedname_name(&fixed));
1831 if (result == DNS_R_SIGEXPIRED && val->view->acceptexpired) {
1835 if (ignore && (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD))
1836 validator_log(val, ISC_LOG_INFO,
1837 "accepted expired %sRRSIG (keyid=%u)",
1838 (result == DNS_R_FROMWILDCARD) ?
1839 "wildcard " : "", keyid);
1841 validator_log(val, ISC_LOG_DEBUG(3),
1842 "verify rdataset (keyid=%u): %s",
1843 keyid, isc_result_totext(result));
1844 if (result == DNS_R_FROMWILDCARD) {
1845 if (!dns_name_equal(val->event->name,
1846 dns_fixedname_name(&fixed)))
1847 val->attributes |= VALATTR_NEEDNOQNAME;
1848 result = ISC_R_SUCCESS;
1854 * Attempts positive response validation of a normal RRset.
1857 * \li ISC_R_SUCCESS Validation completed successfully
1858 * \li DNS_R_WAIT Validation has started but is waiting
1860 * \li Other return codes are possible and all indicate failure.
1863 validate(dns_validator_t *val, isc_boolean_t resume) {
1864 isc_result_t result;
1865 dns_validatorevent_t *event;
1866 dns_rdata_t rdata = DNS_RDATA_INIT;
1869 * Caller must be holding the validator lock.
1876 * We already have a sigrdataset.
1878 result = ISC_R_SUCCESS;
1879 validator_log(val, ISC_LOG_DEBUG(3), "resuming validate");
1881 result = dns_rdataset_first(event->sigrdataset);
1885 result == ISC_R_SUCCESS;
1886 result = dns_rdataset_next(event->sigrdataset))
1888 dns_rdata_reset(&rdata);
1889 dns_rdataset_current(event->sigrdataset, &rdata);
1890 if (val->siginfo == NULL) {
1891 val->siginfo = isc_mem_get(val->view->mctx,
1892 sizeof(*val->siginfo));
1893 if (val->siginfo == NULL)
1894 return (ISC_R_NOMEMORY);
1896 result = dns_rdata_tostruct(&rdata, val->siginfo, NULL);
1897 if (result != ISC_R_SUCCESS)
1901 * At this point we could check that the signature algorithm
1902 * was known and "sufficiently good".
1904 if (!dns_resolver_algorithm_supported(val->view->resolver,
1906 val->siginfo->algorithm)) {
1912 result = get_key(val, val->siginfo);
1913 if (result == DNS_R_CONTINUE)
1914 continue; /* Try the next SIG RR. */
1915 if (result != ISC_R_SUCCESS)
1920 * There isn't a secure DNSKEY for this signature so move
1921 * onto the next RRSIG.
1923 if (val->key == NULL) {
1929 result = verify(val, val->key, &rdata,
1930 val->siginfo->keyid);
1931 if (result == ISC_R_SUCCESS)
1933 if (val->keynode != NULL) {
1934 dns_keynode_t *nextnode = NULL;
1935 result = dns_keytable_findnextkeynode(
1939 dns_keytable_detachkeynode(val->keytable,
1941 val->keynode = nextnode;
1942 if (result != ISC_R_SUCCESS) {
1946 val->key = dns_keynode_key(val->keynode);
1948 if (get_dst_key(val, val->siginfo, val->keyset)
1953 if (result != ISC_R_SUCCESS)
1954 validator_log(val, ISC_LOG_DEBUG(3),
1955 "failed to verify rdataset");
1960 isc_stdtime_get(&now);
1961 ttl = ISC_MIN(event->rdataset->ttl,
1962 val->siginfo->timeexpire - now);
1963 if (val->keyset != NULL)
1964 ttl = ISC_MIN(ttl, val->keyset->ttl);
1965 event->rdataset->ttl = ttl;
1966 event->sigrdataset->ttl = ttl;
1969 if (val->keynode != NULL)
1970 dns_keytable_detachkeynode(val->keytable,
1973 if (val->key != NULL)
1974 dst_key_free(&val->key);
1975 if (val->keyset != NULL) {
1976 dns_rdataset_disassociate(val->keyset);
1981 if (NEEDNOQNAME(val)) {
1982 if (val->event->message == NULL) {
1983 validator_log(val, ISC_LOG_DEBUG(3),
1984 "no message available for noqname proof");
1985 return (DNS_R_NOVALIDSIG);
1987 validator_log(val, ISC_LOG_DEBUG(3),
1988 "looking for noqname proof");
1989 return (nsecvalidate(val, ISC_FALSE));
1990 } else if (result == ISC_R_SUCCESS) {
1992 validator_log(val, ISC_LOG_DEBUG(3),
1993 "marking as secure");
1996 validator_log(val, ISC_LOG_DEBUG(3),
1997 "verify failure: %s",
1998 isc_result_totext(result));
2002 if (result != ISC_R_NOMORE) {
2003 validator_log(val, ISC_LOG_DEBUG(3),
2004 "failed to iterate signatures: %s",
2005 isc_result_totext(result));
2009 validator_log(val, ISC_LOG_INFO, "no valid signature found");
2010 return (DNS_R_NOVALIDSIG);
2014 * Validate the DNSKEY RRset by looking for a DNSKEY that matches a
2015 * DLV record and that also verifies the DNSKEY RRset.
2018 dlv_validatezonekey(dns_validator_t *val) {
2019 dns_keytag_t keytag;
2020 dns_rdata_dlv_t dlv;
2021 dns_rdata_dnskey_t key;
2022 dns_rdata_rrsig_t sig;
2023 dns_rdata_t dlvrdata = DNS_RDATA_INIT;
2024 dns_rdata_t keyrdata = DNS_RDATA_INIT;
2025 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
2026 dns_rdata_t sigrdata = DNS_RDATA_INIT;
2027 dns_rdataset_t trdataset;
2029 isc_boolean_t supported_algorithm;
2030 isc_result_t result;
2031 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
2032 isc_uint8_t digest_type;
2034 validator_log(val, ISC_LOG_DEBUG(3), "dlv_validatezonekey");
2037 * Look through the DLV record and find the keys that can sign the
2038 * key set and the matching signature. For each such key, attempt
2041 supported_algorithm = ISC_FALSE;
2044 * If DNS_DSDIGEST_SHA256 is present we are required to prefer
2045 * it over DNS_DSDIGEST_SHA1. This in practice means that we
2046 * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
2049 digest_type = DNS_DSDIGEST_SHA1;
2050 for (result = dns_rdataset_first(&val->dlv);
2051 result == ISC_R_SUCCESS;
2052 result = dns_rdataset_next(&val->dlv)) {
2053 dns_rdata_reset(&dlvrdata);
2054 dns_rdataset_current(&val->dlv, &dlvrdata);
2055 result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
2056 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2058 if (!dns_resolver_algorithm_supported(val->view->resolver,
2063 if (dlv.digest_type == DNS_DSDIGEST_SHA256 &&
2064 dlv.length == ISC_SHA256_DIGESTLENGTH) {
2065 digest_type = DNS_DSDIGEST_SHA256;
2070 for (result = dns_rdataset_first(&val->dlv);
2071 result == ISC_R_SUCCESS;
2072 result = dns_rdataset_next(&val->dlv))
2074 dns_rdata_reset(&dlvrdata);
2075 dns_rdataset_current(&val->dlv, &dlvrdata);
2076 result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
2077 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2079 if (!dns_resolver_digest_supported(val->view->resolver,
2083 if (dlv.digest_type != digest_type)
2086 if (!dns_resolver_algorithm_supported(val->view->resolver,
2091 supported_algorithm = ISC_TRUE;
2093 dns_rdataset_init(&trdataset);
2094 dns_rdataset_clone(val->event->rdataset, &trdataset);
2096 for (result = dns_rdataset_first(&trdataset);
2097 result == ISC_R_SUCCESS;
2098 result = dns_rdataset_next(&trdataset))
2100 dns_rdata_reset(&keyrdata);
2101 dns_rdataset_current(&trdataset, &keyrdata);
2102 result = dns_rdata_tostruct(&keyrdata, &key, NULL);
2103 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2104 keytag = compute_keytag(&keyrdata, &key);
2105 if (dlv.key_tag != keytag ||
2106 dlv.algorithm != key.algorithm)
2108 dns_rdata_reset(&newdsrdata);
2109 result = dns_ds_buildrdata(val->event->name,
2110 &keyrdata, dlv.digest_type,
2111 dsbuf, &newdsrdata);
2112 if (result != ISC_R_SUCCESS) {
2113 validator_log(val, ISC_LOG_DEBUG(3),
2114 "dns_ds_buildrdata() -> %s",
2115 dns_result_totext(result));
2119 newdsrdata.type = dns_rdatatype_dlv;
2120 if (dns_rdata_compare(&dlvrdata, &newdsrdata) == 0)
2123 if (result != ISC_R_SUCCESS) {
2124 dns_rdataset_disassociate(&trdataset);
2125 validator_log(val, ISC_LOG_DEBUG(3),
2126 "no DNSKEY matching DLV");
2129 validator_log(val, ISC_LOG_DEBUG(3),
2130 "Found matching DLV record: checking for signature");
2132 for (result = dns_rdataset_first(val->event->sigrdataset);
2133 result == ISC_R_SUCCESS;
2134 result = dns_rdataset_next(val->event->sigrdataset))
2136 dns_rdata_reset(&sigrdata);
2137 dns_rdataset_current(val->event->sigrdataset,
2139 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
2140 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2141 if (dlv.key_tag != sig.keyid ||
2142 dlv.algorithm != sig.algorithm)
2145 result = dns_dnssec_keyfromrdata(val->event->name,
2149 if (result != ISC_R_SUCCESS)
2151 * This really shouldn't happen, but...
2155 result = verify(val, dstkey, &sigrdata, sig.keyid);
2156 dst_key_free(&dstkey);
2157 if (result == ISC_R_SUCCESS)
2160 dns_rdataset_disassociate(&trdataset);
2161 if (result == ISC_R_SUCCESS)
2163 validator_log(val, ISC_LOG_DEBUG(3),
2164 "no RRSIG matching DLV key");
2166 if (result == ISC_R_SUCCESS) {
2167 marksecure(val->event);
2168 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure");
2170 } else if (result == ISC_R_NOMORE && !supported_algorithm) {
2171 if (val->mustbesecure) {
2172 validator_log(val, ISC_LOG_WARNING,
2173 "must be secure failure");
2174 return (DNS_R_MUSTBESECURE);
2176 validator_log(val, ISC_LOG_DEBUG(3),
2177 "no supported algorithm/digest (dlv)");
2178 markanswer(val, "dlv_validatezonekey (2)");
2179 return (ISC_R_SUCCESS);
2181 return (DNS_R_NOVALIDSIG);
2185 * Attempts positive response validation of an RRset containing zone keys.
2188 * \li ISC_R_SUCCESS Validation completed successfully
2189 * \li DNS_R_WAIT Validation has started but is waiting
2191 * \li Other return codes are possible and all indicate failure.
2194 validatezonekey(dns_validator_t *val) {
2195 isc_result_t result;
2196 dns_validatorevent_t *event;
2197 dns_rdataset_t trdataset;
2198 dns_rdata_t dsrdata = DNS_RDATA_INIT;
2199 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
2200 dns_rdata_t keyrdata = DNS_RDATA_INIT;
2201 dns_rdata_t sigrdata = DNS_RDATA_INIT;
2202 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
2203 char namebuf[DNS_NAME_FORMATSIZE];
2204 dns_keytag_t keytag;
2206 dns_rdata_dnskey_t key;
2207 dns_rdata_rrsig_t sig;
2209 isc_boolean_t supported_algorithm;
2210 isc_boolean_t atsep = ISC_FALSE;
2211 isc_uint8_t digest_type;
2214 * Caller must be holding the validator lock.
2219 if (val->havedlvsep && val->dlv.trust >= dns_trust_secure &&
2220 dns_name_equal(event->name, dns_fixedname_name(&val->dlvsep)))
2221 return (dlv_validatezonekey(val));
2223 if (val->dsset == NULL) {
2226 * We have a dlv sep. Skip looking up the SEP from
2227 * {trusted,managed}-keys. If the dlv sep is for the
2228 * root then it will have been handled above so we don't
2229 * need to check whether val->event->name is "." prior to
2230 * looking up the DS.
2232 if (val->havedlvsep)
2236 * First, see if this key was signed by a trusted key.
2238 for (result = dns_rdataset_first(val->event->sigrdataset);
2239 result == ISC_R_SUCCESS;
2240 result = dns_rdataset_next(val->event->sigrdataset))
2242 dns_keynode_t *keynode = NULL;
2243 dns_fixedname_t fixed;
2246 dns_fixedname_init(&fixed);
2247 found = dns_fixedname_name(&fixed);
2248 dns_rdata_reset(&sigrdata);
2249 dns_rdataset_current(val->event->sigrdataset,
2251 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
2252 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2254 if (!dns_name_equal(val->event->name, &sig.signer))
2257 result = dns_keytable_findkeynode(val->keytable,
2262 if (result == ISC_R_NOTFOUND &&
2263 dns_keytable_finddeepestmatch(val->keytable,
2264 val->event->name, found) != ISC_R_SUCCESS) {
2265 if (val->mustbesecure) {
2266 validator_log(val, ISC_LOG_WARNING,
2267 "must be secure failure, "
2268 "not beneath secure root");
2269 return (DNS_R_MUSTBESECURE);
2271 validator_log(val, ISC_LOG_DEBUG(3),
2272 "not beneath secure root");
2273 if (val->view->dlv == NULL) {
2274 markanswer(val, "validatezonekey (1)");
2275 return (ISC_R_SUCCESS);
2277 return (startfinddlvsep(val, dns_rootname));
2279 if (result == DNS_R_PARTIALMATCH ||
2280 result == ISC_R_SUCCESS)
2282 while (result == ISC_R_SUCCESS) {
2283 dns_keynode_t *nextnode = NULL;
2284 dstkey = dns_keynode_key(keynode);
2285 result = verify(val, dstkey, &sigrdata,
2287 if (result == ISC_R_SUCCESS) {
2288 dns_keytable_detachkeynode(val->keytable,
2292 result = dns_keytable_findnextkeynode(
2296 dns_keytable_detachkeynode(val->keytable,
2300 if (result == ISC_R_SUCCESS) {
2302 validator_log(val, ISC_LOG_DEBUG(3),
2303 "signed by trusted key; "
2304 "marking as secure");
2311 * We have not found a key to verify this DNSKEY
2312 * RRset. As this is a SEP we have to assume that
2313 * the RRset is invalid.
2315 dns_name_format(val->event->name, namebuf,
2317 validator_log(val, ISC_LOG_NOTICE,
2318 "unable to find a DNSKEY which verifies "
2319 "the DNSKEY RRset and also matches one "
2320 "of specified trusted-keys for '%s'",
2322 validator_log(val, ISC_LOG_NOTICE,
2323 "please check the 'trusted-keys' for "
2324 "'%s' in named.conf.", namebuf);
2325 return (DNS_R_NOVALIDKEY);
2329 * If this is the root name and there was no trusted key,
2330 * give up, since there's no DS at the root.
2332 if (dns_name_equal(event->name, dns_rootname)) {
2333 if ((val->attributes & VALATTR_TRIEDVERIFY) != 0) {
2334 validator_log(val, ISC_LOG_DEBUG(3),
2335 "root key failed to validate");
2336 return (DNS_R_NOVALIDSIG);
2338 validator_log(val, ISC_LOG_DEBUG(3),
2339 "no trusted root key");
2340 return (DNS_R_NOVALIDDS);
2345 * Otherwise, try to find the DS record.
2347 result = view_find(val, val->event->name, dns_rdatatype_ds);
2348 if (result == ISC_R_SUCCESS) {
2350 * We have DS records.
2352 val->dsset = &val->frdataset;
2353 if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
2354 DNS_TRUST_ANSWER(val->frdataset.trust)) &&
2355 dns_rdataset_isassociated(&val->fsigrdataset))
2357 result = create_validator(val,
2364 if (result != ISC_R_SUCCESS)
2366 return (DNS_R_WAIT);
2367 } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
2369 * There should never be an unsigned DS.
2371 dns_rdataset_disassociate(&val->frdataset);
2372 validator_log(val, ISC_LOG_DEBUG(2),
2373 "unsigned DS record");
2374 return (DNS_R_NOVALIDSIG);
2376 result = ISC_R_SUCCESS;
2377 } else if (result == ISC_R_NOTFOUND) {
2379 * We don't have the DS. Find it.
2381 result = create_fetch(val, val->event->name,
2382 dns_rdatatype_ds, dsfetched,
2384 if (result != ISC_R_SUCCESS)
2386 return (DNS_R_WAIT);
2387 } else if (result == DNS_R_NCACHENXDOMAIN ||
2388 result == DNS_R_NCACHENXRRSET ||
2389 result == DNS_R_EMPTYNAME ||
2390 result == DNS_R_NXDOMAIN ||
2391 result == DNS_R_NXRRSET)
2394 * The DS does not exist.
2396 if (dns_rdataset_isassociated(&val->frdataset))
2397 dns_rdataset_disassociate(&val->frdataset);
2398 if (dns_rdataset_isassociated(&val->fsigrdataset))
2399 dns_rdataset_disassociate(&val->fsigrdataset);
2400 validator_log(val, ISC_LOG_DEBUG(2), "no DS record");
2401 return (DNS_R_NOVALIDSIG);
2402 } else if (result == DNS_R_BROKENCHAIN)
2409 INSIST(val->dsset != NULL);
2411 if (val->dsset->trust < dns_trust_secure) {
2412 if (val->mustbesecure) {
2413 validator_log(val, ISC_LOG_WARNING,
2414 "must be secure failure");
2415 return (DNS_R_MUSTBESECURE);
2417 if (val->view->dlv == NULL || DLVTRIED(val)) {
2418 markanswer(val, "validatezonekey (2)");
2419 return (ISC_R_SUCCESS);
2421 return (startfinddlvsep(val, val->event->name));
2425 * Look through the DS record and find the keys that can sign the
2426 * key set and the matching signature. For each such key, attempt
2430 supported_algorithm = ISC_FALSE;
2433 * If DNS_DSDIGEST_SHA256 is present we are required to prefer
2434 * it over DNS_DSDIGEST_SHA1. This in practice means that we
2435 * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
2438 digest_type = DNS_DSDIGEST_SHA1;
2439 for (result = dns_rdataset_first(val->dsset);
2440 result == ISC_R_SUCCESS;
2441 result = dns_rdataset_next(val->dsset)) {
2442 dns_rdata_reset(&dsrdata);
2443 dns_rdataset_current(val->dsset, &dsrdata);
2444 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
2445 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2447 if (!dns_resolver_algorithm_supported(val->view->resolver,
2452 if (ds.digest_type == DNS_DSDIGEST_SHA256 &&
2453 ds.length == ISC_SHA256_DIGESTLENGTH) {
2454 digest_type = DNS_DSDIGEST_SHA256;
2459 for (result = dns_rdataset_first(val->dsset);
2460 result == ISC_R_SUCCESS;
2461 result = dns_rdataset_next(val->dsset))
2463 dns_rdata_reset(&dsrdata);
2464 dns_rdataset_current(val->dsset, &dsrdata);
2465 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
2466 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2468 if (!dns_resolver_digest_supported(val->view->resolver,
2472 if (ds.digest_type != digest_type)
2475 if (!dns_resolver_algorithm_supported(val->view->resolver,
2480 supported_algorithm = ISC_TRUE;
2482 dns_rdataset_init(&trdataset);
2483 dns_rdataset_clone(val->event->rdataset, &trdataset);
2486 * Look for the KEY that matches the DS record.
2488 for (result = dns_rdataset_first(&trdataset);
2489 result == ISC_R_SUCCESS;
2490 result = dns_rdataset_next(&trdataset))
2492 dns_rdata_reset(&keyrdata);
2493 dns_rdataset_current(&trdataset, &keyrdata);
2494 result = dns_rdata_tostruct(&keyrdata, &key, NULL);
2495 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2496 keytag = compute_keytag(&keyrdata, &key);
2497 if (ds.key_tag != keytag ||
2498 ds.algorithm != key.algorithm)
2500 dns_rdata_reset(&newdsrdata);
2501 result = dns_ds_buildrdata(val->event->name,
2502 &keyrdata, ds.digest_type,
2503 dsbuf, &newdsrdata);
2504 if (result != ISC_R_SUCCESS)
2506 if (dns_rdata_compare(&dsrdata, &newdsrdata) == 0)
2509 if (result != ISC_R_SUCCESS) {
2510 dns_rdataset_disassociate(&trdataset);
2511 validator_log(val, ISC_LOG_DEBUG(3),
2512 "no DNSKEY matching DS");
2516 for (result = dns_rdataset_first(val->event->sigrdataset);
2517 result == ISC_R_SUCCESS;
2518 result = dns_rdataset_next(val->event->sigrdataset))
2520 dns_rdata_reset(&sigrdata);
2521 dns_rdataset_current(val->event->sigrdataset,
2523 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
2524 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2525 if (ds.key_tag != sig.keyid ||
2526 ds.algorithm != sig.algorithm)
2528 if (!dns_name_equal(val->event->name, &sig.signer)) {
2529 validator_log(val, ISC_LOG_DEBUG(3),
2530 "DNSKEY signer mismatch");
2534 result = dns_dnssec_keyfromrdata(val->event->name,
2538 if (result != ISC_R_SUCCESS)
2540 * This really shouldn't happen, but...
2543 result = verify(val, dstkey, &sigrdata, sig.keyid);
2544 dst_key_free(&dstkey);
2545 if (result == ISC_R_SUCCESS)
2548 dns_rdataset_disassociate(&trdataset);
2549 if (result == ISC_R_SUCCESS)
2551 validator_log(val, ISC_LOG_DEBUG(3),
2552 "no RRSIG matching DS key");
2554 if (result == ISC_R_SUCCESS) {
2556 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure");
2558 } else if (result == ISC_R_NOMORE && !supported_algorithm) {
2559 if (val->mustbesecure) {
2560 validator_log(val, ISC_LOG_WARNING,
2561 "must be secure failure");
2562 return (DNS_R_MUSTBESECURE);
2564 validator_log(val, ISC_LOG_DEBUG(3),
2565 "no supported algorithm/digest (DS)");
2566 markanswer(val, "validatezonekey (3)");
2567 return (ISC_R_SUCCESS);
2569 return (DNS_R_NOVALIDSIG);
2573 * Starts a positive response validation.
2576 * \li ISC_R_SUCCESS Validation completed successfully
2577 * \li DNS_R_WAIT Validation has started but is waiting
2579 * \li Other return codes are possible and all indicate failure.
2582 start_positive_validation(dns_validator_t *val) {
2584 * If this is not a key, go straight into validate().
2586 if (val->event->type != dns_rdatatype_dnskey || !isselfsigned(val))
2587 return (validate(val, ISC_FALSE));
2589 return (validatezonekey(val));
2593 * val_rdataset_first and val_rdataset_next provide iteration methods
2594 * that hide whether we are iterating across a message or a negative
2598 val_rdataset_first(dns_validator_t *val, dns_name_t **namep,
2599 dns_rdataset_t **rdatasetp)
2601 dns_message_t *message = val->event->message;
2602 isc_result_t result;
2604 REQUIRE(rdatasetp != NULL);
2605 REQUIRE(namep != NULL);
2606 if (message == NULL) {
2607 REQUIRE(*rdatasetp != NULL);
2608 REQUIRE(*namep != NULL);
2610 REQUIRE(*rdatasetp == NULL);
2611 REQUIRE(*namep == NULL);
2614 if (message != NULL) {
2615 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2616 if (result != ISC_R_SUCCESS)
2618 dns_message_currentname(message, DNS_SECTION_AUTHORITY, namep);
2619 *rdatasetp = ISC_LIST_HEAD((*namep)->list);
2620 INSIST(*rdatasetp != NULL);
2622 result = dns_rdataset_first(val->event->rdataset);
2623 if (result == ISC_R_SUCCESS)
2624 dns_ncache_current(val->event->rdataset, *namep,
2631 val_rdataset_next(dns_validator_t *val, dns_name_t **namep,
2632 dns_rdataset_t **rdatasetp)
2634 dns_message_t *message = val->event->message;
2635 isc_result_t result = ISC_R_SUCCESS;
2637 REQUIRE(rdatasetp != NULL && *rdatasetp != NULL);
2638 REQUIRE(namep != NULL && *namep != NULL);
2640 if (message != NULL) {
2641 dns_rdataset_t *rdataset = *rdatasetp;
2642 rdataset = ISC_LIST_NEXT(rdataset, link);
2643 if (rdataset == NULL) {
2645 result = dns_message_nextname(message,
2646 DNS_SECTION_AUTHORITY);
2647 if (result == ISC_R_SUCCESS) {
2648 dns_message_currentname(message,
2649 DNS_SECTION_AUTHORITY,
2651 rdataset = ISC_LIST_HEAD((*namep)->list);
2652 INSIST(rdataset != NULL);
2655 *rdatasetp = rdataset;
2657 dns_rdataset_disassociate(*rdatasetp);
2658 result = dns_rdataset_next(val->event->rdataset);
2659 if (result == ISC_R_SUCCESS)
2660 dns_ncache_current(val->event->rdataset, *namep,
2667 * Look for NODATA at the wildcard and NOWILDCARD proofs in the
2668 * previously validated NSEC records. As these proofs are mutually
2669 * exclusive we stop when one is found.
2675 checkwildcard(dns_validator_t *val, dns_rdatatype_t type, dns_name_t *zonename)
2677 dns_name_t *name, *wild, tname;
2678 isc_result_t result;
2679 isc_boolean_t exists, data;
2680 char namebuf[DNS_NAME_FORMATSIZE];
2681 dns_rdataset_t *rdataset, trdataset;
2683 dns_name_init(&tname, NULL);
2684 dns_rdataset_init(&trdataset);
2685 wild = dns_fixedname_name(&val->wild);
2687 if (dns_name_countlabels(wild) == 0) {
2688 validator_log(val, ISC_LOG_DEBUG(3),
2689 "in checkwildcard: no wildcard to check");
2690 return (ISC_R_SUCCESS);
2693 dns_name_format(wild, namebuf, sizeof(namebuf));
2694 validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf);
2696 if (val->event->message == NULL) {
2698 rdataset = &trdataset;
2704 for (result = val_rdataset_first(val, &name, &rdataset);
2705 result == ISC_R_SUCCESS;
2706 result = val_rdataset_next(val, &name, &rdataset))
2708 if (rdataset->type != type ||
2709 rdataset->trust != dns_trust_secure)
2712 if (rdataset->type == dns_rdatatype_nsec &&
2713 (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
2714 !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
2715 nsecnoexistnodata(val, wild, name, rdataset,
2716 &exists, &data, NULL)
2719 dns_name_t **proofs = val->event->proofs;
2720 if (exists && !data)
2721 val->attributes |= VALATTR_FOUNDNODATA;
2722 if (exists && !data && NEEDNODATA(val))
2723 proofs[DNS_VALIDATOR_NODATAPROOF] =
2727 VALATTR_FOUNDNOWILDCARD;
2728 if (!exists && NEEDNOQNAME(val))
2729 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
2731 if (dns_rdataset_isassociated(&trdataset))
2732 dns_rdataset_disassociate(&trdataset);
2733 return (ISC_R_SUCCESS);
2736 if (rdataset->type == dns_rdatatype_nsec3 &&
2737 (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
2738 !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
2739 nsec3noexistnodata(val, wild, name, rdataset,
2740 zonename, &exists, &data,
2741 NULL, NULL, NULL, NULL, NULL,
2742 NULL) == ISC_R_SUCCESS)
2744 dns_name_t **proofs = val->event->proofs;
2745 if (exists && !data)
2746 val->attributes |= VALATTR_FOUNDNODATA;
2747 if (exists && !data && NEEDNODATA(val))
2748 proofs[DNS_VALIDATOR_NODATAPROOF] =
2752 VALATTR_FOUNDNOWILDCARD;
2753 if (!exists && NEEDNOQNAME(val))
2754 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
2756 if (dns_rdataset_isassociated(&trdataset))
2757 dns_rdataset_disassociate(&trdataset);
2758 return (ISC_R_SUCCESS);
2761 if (result == ISC_R_NOMORE)
2762 result = ISC_R_SUCCESS;
2763 if (dns_rdataset_isassociated(&trdataset))
2764 dns_rdataset_disassociate(&trdataset);
2769 findnsec3proofs(dns_validator_t *val) {
2770 dns_name_t *name, tname;
2771 isc_result_t result;
2772 isc_boolean_t exists, data, optout, unknown;
2773 isc_boolean_t setclosest, setnearest;
2774 dns_fixedname_t fclosest, fnearest, fzonename;
2775 dns_name_t *closest, *nearest, *zonename;
2776 dns_name_t **proofs = val->event->proofs;
2777 dns_rdataset_t *rdataset, trdataset;
2779 dns_name_init(&tname, NULL);
2780 dns_rdataset_init(&trdataset);
2781 dns_fixedname_init(&fclosest);
2782 dns_fixedname_init(&fnearest);
2783 dns_fixedname_init(&fzonename);
2784 closest = dns_fixedname_name(&fclosest);
2785 nearest = dns_fixedname_name(&fnearest);
2786 zonename = dns_fixedname_name(&fzonename);
2788 if (val->event->message == NULL) {
2790 rdataset = &trdataset;
2796 for (result = val_rdataset_first(val, &name, &rdataset);
2797 result == ISC_R_SUCCESS;
2798 result = val_rdataset_next(val, &name, &rdataset))
2800 if (rdataset->type != dns_rdatatype_nsec3 ||
2801 rdataset->trust != dns_trust_secure)
2804 result = nsec3noexistnodata(val, val->event->name,
2806 zonename, NULL, NULL, NULL,
2807 NULL, NULL, NULL, NULL,
2809 if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS) {
2810 if (dns_rdataset_isassociated(&trdataset))
2811 dns_rdataset_disassociate(&trdataset);
2815 if (result != ISC_R_NOMORE)
2816 result = ISC_R_SUCCESS;
2818 if (dns_name_countlabels(zonename) == 0)
2819 return (ISC_R_SUCCESS);
2821 for (result = val_rdataset_first(val, &name, &rdataset);
2822 result == ISC_R_SUCCESS;
2823 result = val_rdataset_next(val, &name, &rdataset))
2825 if (rdataset->type != dns_rdatatype_nsec3 ||
2826 rdataset->trust != dns_trust_secure)
2830 * We process all NSEC3 records to find the closest
2831 * encloser and nearest name to the closest encloser.
2833 setclosest = setnearest = ISC_FALSE;
2835 unknown = ISC_FALSE;
2836 (void)nsec3noexistnodata(val, val->event->name, name, rdataset,
2837 zonename, &exists, &data, &optout,
2838 &unknown, &setclosest, &setnearest,
2841 proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
2843 val->attributes |= VALATTR_FOUNDUNKNOWN;
2844 if (result != ISC_R_SUCCESS)
2846 if (exists && !data && NEEDNODATA(val)) {
2847 val->attributes |= VALATTR_FOUNDNODATA;
2848 proofs[DNS_VALIDATOR_NODATAPROOF] = name;
2850 if (!exists && setnearest) {
2851 val->attributes |= VALATTR_FOUNDNOQNAME;
2852 proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name;
2854 val->attributes |= VALATTR_FOUNDOPTOUT;
2857 if (result == ISC_R_NOMORE)
2858 result = ISC_R_SUCCESS;
2861 * To know we have a valid noqname and optout proofs we need to also
2862 * have a valid closest encloser. Otherwise we could still be looking
2863 * at proofs from the parent zone.
2865 if (dns_name_countlabels(closest) > 0 &&
2866 dns_name_countlabels(nearest) ==
2867 dns_name_countlabels(closest) + 1 &&
2868 dns_name_issubdomain(nearest, closest))
2870 val->attributes |= VALATTR_FOUNDCLOSEST;
2871 result = dns_name_concatenate(dns_wildcardname, closest,
2872 dns_fixedname_name(&val->wild),
2874 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2876 val->attributes &= ~VALATTR_FOUNDNOQNAME;
2877 val->attributes &= ~VALATTR_FOUNDOPTOUT;
2878 proofs[DNS_VALIDATOR_NOQNAMEPROOF] = NULL;
2882 * Do we need to check for the wildcard?
2884 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
2885 ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
2886 result = checkwildcard(val, dns_rdatatype_nsec3, zonename);
2887 if (result != ISC_R_SUCCESS)
2894 * Validate the authority section records.
2897 validate_authority(dns_validator_t *val, isc_boolean_t resume) {
2899 dns_message_t *message = val->event->message;
2900 isc_result_t result;
2903 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2905 result = ISC_R_SUCCESS;
2908 result == ISC_R_SUCCESS;
2909 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
2911 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2914 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
2916 rdataset = ISC_LIST_NEXT(val->currentset, link);
2917 val->currentset = NULL;
2920 rdataset = ISC_LIST_HEAD(name->list);
2924 rdataset = ISC_LIST_NEXT(rdataset, link))
2926 if (rdataset->type == dns_rdatatype_rrsig)
2929 for (sigrdataset = ISC_LIST_HEAD(name->list);
2930 sigrdataset != NULL;
2931 sigrdataset = ISC_LIST_NEXT(sigrdataset,
2934 if (sigrdataset->type == dns_rdatatype_rrsig &&
2935 sigrdataset->covers == rdataset->type)
2939 * If a signed zone is missing the zone key, bad
2940 * things could happen. A query for data in the zone
2941 * would lead to a query for the zone key, which
2942 * would return a negative answer, which would contain
2943 * an SOA and an NSEC signed by the missing key, which
2944 * would trigger another query for the DNSKEY (since
2945 * the first one is still in progress), and go into an
2946 * infinite loop. Avoid that.
2948 if (val->event->type == dns_rdatatype_dnskey &&
2949 dns_name_equal(name, val->event->name))
2951 dns_rdata_t nsec = DNS_RDATA_INIT;
2953 if (rdataset->type != dns_rdatatype_nsec)
2956 result = dns_rdataset_first(rdataset);
2957 if (result != ISC_R_SUCCESS)
2959 dns_rdataset_current(rdataset, &nsec);
2960 if (dns_nsec_typepresent(&nsec,
2964 val->currentset = rdataset;
2965 result = create_validator(val, name, rdataset->type,
2966 rdataset, sigrdataset,
2968 "validate_authority");
2969 if (result != ISC_R_SUCCESS)
2972 return (DNS_R_WAIT);
2975 if (result == ISC_R_NOMORE)
2976 result = ISC_R_SUCCESS;
2981 * Validate the ncache elements.
2984 validate_ncache(dns_validator_t *val, isc_boolean_t resume) {
2986 isc_result_t result;
2989 result = dns_rdataset_first(val->event->rdataset);
2991 result = dns_rdataset_next(val->event->rdataset);
2994 result == ISC_R_SUCCESS;
2995 result = dns_rdataset_next(val->event->rdataset))
2997 dns_rdataset_t *rdataset, *sigrdataset = NULL;
2999 if (dns_rdataset_isassociated(&val->frdataset))
3000 dns_rdataset_disassociate(&val->frdataset);
3001 if (dns_rdataset_isassociated(&val->fsigrdataset))
3002 dns_rdataset_disassociate(&val->fsigrdataset);
3004 dns_fixedname_init(&val->fname);
3005 name = dns_fixedname_name(&val->fname);
3006 rdataset = &val->frdataset;
3007 dns_ncache_current(val->event->rdataset, name, rdataset);
3009 if (val->frdataset.type == dns_rdatatype_rrsig)
3012 result = dns_ncache_getsigrdataset(val->event->rdataset, name,
3014 &val->fsigrdataset);
3015 if (result == ISC_R_SUCCESS)
3016 sigrdataset = &val->fsigrdataset;
3019 * If a signed zone is missing the zone key, bad
3020 * things could happen. A query for data in the zone
3021 * would lead to a query for the zone key, which
3022 * would return a negative answer, which would contain
3023 * an SOA and an NSEC signed by the missing key, which
3024 * would trigger another query for the DNSKEY (since
3025 * the first one is still in progress), and go into an
3026 * infinite loop. Avoid that.
3028 if (val->event->type == dns_rdatatype_dnskey &&
3029 dns_name_equal(name, val->event->name))
3031 dns_rdata_t nsec = DNS_RDATA_INIT;
3033 if (rdataset->type != dns_rdatatype_nsec)
3036 result = dns_rdataset_first(rdataset);
3037 if (result != ISC_R_SUCCESS)
3039 dns_rdataset_current(rdataset, &nsec);
3040 if (dns_nsec_typepresent(&nsec,
3044 val->currentset = rdataset;
3045 result = create_validator(val, name, rdataset->type,
3046 rdataset, sigrdataset,
3049 if (result != ISC_R_SUCCESS)
3052 return (DNS_R_WAIT);
3054 if (result == ISC_R_NOMORE)
3055 result = ISC_R_SUCCESS;
3060 * Prove a negative answer is good or that there is a NOQNAME when the
3061 * answer is from a wildcard.
3063 * Loop through the authority section looking for NODATA, NOWILDCARD
3064 * and NOQNAME proofs in the NSEC records by calling authvalidated().
3066 * If the required proofs are found we are done.
3068 * If the proofs are not found attempt to prove this is a unsecure
3072 nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
3073 isc_result_t result;
3076 validator_log(val, ISC_LOG_DEBUG(3), "resuming nsecvalidate");
3078 if (val->event->message == NULL)
3079 result = validate_ncache(val, resume);
3081 result = validate_authority(val, resume);
3083 if (result != ISC_R_SUCCESS)
3087 * Do we only need to check for NOQNAME? To get here we must have
3088 * had a secure wildcard answer.
3090 if (!NEEDNODATA(val) && !NEEDNOWILDCARD(val) && NEEDNOQNAME(val)) {
3091 if (!FOUNDNOQNAME(val))
3092 findnsec3proofs(val);
3093 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val)) {
3094 validator_log(val, ISC_LOG_DEBUG(3),
3095 "noqname proof found");
3096 validator_log(val, ISC_LOG_DEBUG(3),
3097 "marking as secure");
3098 marksecure(val->event);
3099 return (ISC_R_SUCCESS);
3100 } else if (FOUNDOPTOUT(val) &&
3101 dns_name_countlabels(dns_fixedname_name(&val->wild))
3103 validator_log(val, ISC_LOG_DEBUG(3),
3104 "optout proof found");
3105 val->event->optout = ISC_TRUE;
3106 markanswer(val, "nsecvalidate (1)");
3107 return (ISC_R_SUCCESS);
3108 } else if ((val->attributes & VALATTR_FOUNDUNKNOWN) != 0) {
3109 validator_log(val, ISC_LOG_DEBUG(3),
3110 "unknown NSEC3 hash algorithm found");
3111 markanswer(val, "nsecvalidate (2)");
3112 return (ISC_R_SUCCESS);
3114 validator_log(val, ISC_LOG_DEBUG(3),
3115 "noqname proof not found");
3116 return (DNS_R_NOVALIDNSEC);
3119 if (!FOUNDNOQNAME(val) && !FOUNDNODATA(val))
3120 findnsec3proofs(val);
3123 * Do we need to check for the wildcard?
3125 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
3126 ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
3127 result = checkwildcard(val, dns_rdatatype_nsec, NULL);
3128 if (result != ISC_R_SUCCESS)
3132 if ((NEEDNODATA(val) && (FOUNDNODATA(val) || FOUNDOPTOUT(val))) ||
3133 (NEEDNOQNAME(val) && FOUNDNOQNAME(val) &&
3134 NEEDNOWILDCARD(val) && FOUNDNOWILDCARD(val) &&
3135 FOUNDCLOSEST(val))) {
3136 if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
3137 val->event->optout = ISC_TRUE;
3138 validator_log(val, ISC_LOG_DEBUG(3),
3139 "nonexistence proof(s) found");
3140 if (val->event->message == NULL)
3141 marksecure(val->event);
3142 return (ISC_R_SUCCESS);
3144 findnsec3proofs(val);
3146 if (val->authfail != 0 && val->authcount == val->authfail)
3147 return (DNS_R_BROKENCHAIN);
3148 validator_log(val, ISC_LOG_DEBUG(3),
3149 "nonexistence proof(s) not found");
3150 val->attributes |= VALATTR_INSECURITY;
3151 return (proveunsecure(val, ISC_FALSE, ISC_FALSE));
3154 static isc_boolean_t
3155 check_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) {
3156 dns_rdata_t dsrdata = DNS_RDATA_INIT;
3158 isc_result_t result;
3160 for (result = dns_rdataset_first(rdataset);
3161 result == ISC_R_SUCCESS;
3162 result = dns_rdataset_next(rdataset)) {
3163 dns_rdataset_current(rdataset, &dsrdata);
3164 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
3165 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3167 if (dns_resolver_digest_supported(val->view->resolver,
3169 dns_resolver_algorithm_supported(val->view->resolver,
3170 name, ds.algorithm)) {
3171 dns_rdata_reset(&dsrdata);
3174 dns_rdata_reset(&dsrdata);
3180 dlvvalidated(isc_task_t *task, isc_event_t *event) {
3181 dns_validatorevent_t *devent;
3182 dns_validator_t *val;
3183 isc_result_t eresult;
3184 isc_boolean_t want_destroy;
3187 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
3189 devent = (dns_validatorevent_t *)event;
3190 val = devent->ev_arg;
3191 eresult = devent->result;
3193 isc_event_free(&event);
3194 dns_validator_destroy(&val->subvalidator);
3196 INSIST(val->event != NULL);
3198 validator_log(val, ISC_LOG_DEBUG(3), "in dlvvalidated");
3200 if (CANCELED(val)) {
3201 validator_done(val, ISC_R_CANCELED);
3202 } else if (eresult == ISC_R_SUCCESS) {
3203 validator_log(val, ISC_LOG_DEBUG(3),
3204 "dlvset with trust %s",
3205 dns_trust_totext(val->frdataset.trust));
3206 dns_rdataset_clone(&val->frdataset, &val->dlv);
3207 val->havedlvsep = ISC_TRUE;
3208 if (dlv_algorithm_supported(val))
3209 dlv_validator_start(val);
3211 markanswer(val, "dlvvalidated");
3212 validator_done(val, ISC_R_SUCCESS);
3215 if (eresult != DNS_R_BROKENCHAIN) {
3216 if (dns_rdataset_isassociated(&val->frdataset))
3217 dns_rdataset_expire(&val->frdataset);
3218 if (dns_rdataset_isassociated(&val->fsigrdataset))
3219 dns_rdataset_expire(&val->fsigrdataset);
3221 validator_log(val, ISC_LOG_DEBUG(3),
3222 "dlvvalidated: got %s",
3223 isc_result_totext(eresult));
3224 validator_done(val, DNS_R_BROKENCHAIN);
3226 want_destroy = exit_check(val);
3233 * Callback from fetching a DLV record.
3235 * Resumes the DLV lookup process.
3238 dlvfetched(isc_task_t *task, isc_event_t *event) {
3239 char namebuf[DNS_NAME_FORMATSIZE];
3240 dns_fetchevent_t *devent;
3241 dns_validator_t *val;
3242 isc_boolean_t want_destroy;
3243 isc_result_t eresult;
3244 isc_result_t result;
3247 INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
3248 devent = (dns_fetchevent_t *)event;
3249 val = devent->ev_arg;
3250 eresult = devent->result;
3252 /* Free resources which are not of interest. */
3253 if (devent->node != NULL)
3254 dns_db_detachnode(devent->db, &devent->node);
3255 if (devent->db != NULL)
3256 dns_db_detach(&devent->db);
3257 if (dns_rdataset_isassociated(&val->fsigrdataset))
3258 dns_rdataset_disassociate(&val->fsigrdataset);
3259 isc_event_free(&event);
3260 dns_resolver_destroyfetch(&val->fetch);
3262 INSIST(val->event != NULL);
3263 validator_log(val, ISC_LOG_DEBUG(3), "in dlvfetched: %s",
3264 dns_result_totext(eresult));
3267 if (eresult == ISC_R_SUCCESS) {
3268 dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
3270 dns_rdataset_clone(&val->frdataset, &val->dlv);
3271 val->havedlvsep = ISC_TRUE;
3272 if (dlv_algorithm_supported(val)) {
3273 validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found",
3275 dlv_validator_start(val);
3277 validator_log(val, ISC_LOG_DEBUG(3),
3278 "DLV %s found with no supported algorithms",
3280 markanswer(val, "dlvfetched (1)");
3281 validator_done(val, ISC_R_SUCCESS);
3283 } else if (eresult == DNS_R_NXRRSET ||
3284 eresult == DNS_R_NXDOMAIN ||
3285 eresult == DNS_R_NCACHENXRRSET ||
3286 eresult == DNS_R_NCACHENXDOMAIN) {
3287 result = finddlvsep(val, ISC_TRUE);
3288 if (result == ISC_R_SUCCESS) {
3289 if (dlv_algorithm_supported(val)) {
3290 dns_name_format(dns_fixedname_name(&val->dlvsep),
3291 namebuf, sizeof(namebuf));
3292 validator_log(val, ISC_LOG_DEBUG(3),
3293 "DLV %s found", namebuf);
3294 dlv_validator_start(val);
3296 validator_log(val, ISC_LOG_DEBUG(3),
3297 "DLV %s found with no supported "
3298 "algorithms", namebuf);
3299 markanswer(val, "dlvfetched (2)");
3300 validator_done(val, ISC_R_SUCCESS);
3302 } else if (result == ISC_R_NOTFOUND) {
3303 validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
3304 markanswer(val, "dlvfetched (3)");
3305 validator_done(val, ISC_R_SUCCESS);
3307 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3308 dns_result_totext(result));
3309 if (result != DNS_R_WAIT)
3310 validator_done(val, result);
3313 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3314 dns_result_totext(eresult));
3315 validator_done(val, eresult);
3317 want_destroy = exit_check(val);
3324 * Start the DLV lookup process.
3329 * \li Others on validation failures.
3332 startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) {
3333 char namebuf[DNS_NAME_FORMATSIZE];
3334 isc_result_t result;
3336 INSIST(!DLVTRIED(val));
3338 val->attributes |= VALATTR_DLVTRIED;
3340 dns_name_format(unsecure, namebuf, sizeof(namebuf));
3341 validator_log(val, ISC_LOG_DEBUG(3),
3342 "plain DNSSEC returns unsecure (%s): looking for DLV",
3345 if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
3346 validator_log(val, ISC_LOG_WARNING, "must be secure failure");
3347 return (DNS_R_MUSTBESECURE);
3350 val->dlvlabels = dns_name_countlabels(unsecure) - 1;
3351 result = finddlvsep(val, ISC_FALSE);
3352 if (result == ISC_R_NOTFOUND) {
3353 validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
3354 markanswer(val, "startfinddlvsep (1)");
3355 return (ISC_R_SUCCESS);
3357 if (result != ISC_R_SUCCESS) {
3358 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3359 dns_result_totext(result));
3362 dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
3364 if (dlv_algorithm_supported(val)) {
3365 validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf);
3366 dlv_validator_start(val);
3367 return (DNS_R_WAIT);
3369 validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found with no supported "
3370 "algorithms", namebuf);
3371 markanswer(val, "startfinddlvsep (2)");
3372 validator_done(val, ISC_R_SUCCESS);
3373 return (ISC_R_SUCCESS);
3377 * Continue the DLV lookup process.
3381 * \li ISC_R_NOTFOUND
3383 * \li Others on validation failure.
3386 finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
3387 char namebuf[DNS_NAME_FORMATSIZE];
3388 dns_fixedname_t dlvfixed;
3389 dns_name_t *dlvname;
3392 isc_result_t result;
3393 unsigned int labels;
3395 INSIST(val->view->dlv != NULL);
3399 if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
3400 validator_log(val, ISC_LOG_WARNING,
3401 "must be secure failure");
3402 return (DNS_R_MUSTBESECURE);
3405 dns_fixedname_init(&val->dlvsep);
3406 dlvsep = dns_fixedname_name(&val->dlvsep);
3407 dns_name_copy(val->event->name, dlvsep, NULL);
3409 * If this is a response to a DS query, we need to look in
3410 * the parent zone for the trust anchor.
3412 if (val->event->type == dns_rdatatype_ds) {
3413 labels = dns_name_countlabels(dlvsep);
3415 return (ISC_R_NOTFOUND);
3416 dns_name_getlabelsequence(dlvsep, 1, labels - 1,
3420 dlvsep = dns_fixedname_name(&val->dlvsep);
3421 labels = dns_name_countlabels(dlvsep);
3422 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3424 dns_name_init(&noroot, NULL);
3425 dns_fixedname_init(&dlvfixed);
3426 dlvname = dns_fixedname_name(&dlvfixed);
3427 labels = dns_name_countlabels(dlvsep);
3429 return (ISC_R_NOTFOUND);
3430 dns_name_getlabelsequence(dlvsep, 0, labels - 1, &noroot);
3431 result = dns_name_concatenate(&noroot, val->view->dlv, dlvname, NULL);
3432 while (result == ISC_R_NOSPACE) {
3433 labels = dns_name_countlabels(dlvsep);
3434 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3435 dns_name_getlabelsequence(dlvsep, 0, labels - 2, &noroot);
3436 result = dns_name_concatenate(&noroot, val->view->dlv,
3439 if (result != ISC_R_SUCCESS) {
3440 validator_log(val, ISC_LOG_DEBUG(2), "DLV concatenate failed");
3441 return (DNS_R_NOVALIDSIG);
3444 while (dns_name_countlabels(dlvname) >=
3445 dns_name_countlabels(val->view->dlv) + val->dlvlabels) {
3446 dns_name_format(dlvname, namebuf, sizeof(namebuf));
3447 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV %s",
3449 result = view_find(val, dlvname, dns_rdatatype_dlv);
3450 if (result == ISC_R_SUCCESS) {
3451 if (DNS_TRUST_PENDING(val->frdataset.trust) &&
3452 dns_rdataset_isassociated(&val->fsigrdataset))
3454 dns_fixedname_init(&val->fname);
3455 dns_name_copy(dlvname,
3456 dns_fixedname_name(&val->fname),
3458 result = create_validator(val,
3459 dns_fixedname_name(&val->fname),
3465 if (result != ISC_R_SUCCESS)
3467 return (DNS_R_WAIT);
3469 if (val->frdataset.trust < dns_trust_secure)
3470 return (DNS_R_NOVALIDSIG);
3471 val->havedlvsep = ISC_TRUE;
3472 dns_rdataset_clone(&val->frdataset, &val->dlv);
3473 return (ISC_R_SUCCESS);
3475 if (result == ISC_R_NOTFOUND) {
3476 result = create_fetch(val, dlvname, dns_rdatatype_dlv,
3477 dlvfetched, "finddlvsep");
3478 if (result != ISC_R_SUCCESS)
3480 return (DNS_R_WAIT);
3482 if (result != DNS_R_NXRRSET &&
3483 result != DNS_R_NXDOMAIN &&
3484 result != DNS_R_EMPTYNAME &&
3485 result != DNS_R_NCACHENXRRSET &&
3486 result != DNS_R_NCACHENXDOMAIN)
3489 * Strip first labels from both dlvsep and dlvname.
3491 labels = dns_name_countlabels(dlvsep);
3494 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3495 labels = dns_name_countlabels(dlvname);
3496 dns_name_getlabelsequence(dlvname, 1, labels - 1, dlvname);
3498 return (ISC_R_NOTFOUND);
3502 * proveunsecure walks down from the SEP looking for a break in the
3503 * chain of trust. That occurs when we can prove the DS record does
3504 * not exist at a delegation point or the DS exists at a delegation
3505 * but we don't support the algorithm/digest.
3507 * If DLV is active and we look for a DLV record at or below the
3508 * point we go insecure. If found we restart the validation process.
3509 * If not found or DLV isn't active we mark the response as a answer.
3512 * \li ISC_R_SUCCESS val->event->name is in a unsecure zone
3513 * \li DNS_R_WAIT validation is in progress.
3514 * \li DNS_R_MUSTBESECURE val->event->name is supposed to be secure
3515 * (policy) but we proved that it is unsecure.
3516 * \li DNS_R_NOVALIDSIG
3517 * \li DNS_R_NOVALIDNSEC
3518 * \li DNS_R_NOTINSECURE
3519 * \li DNS_R_BROKENCHAIN
3522 proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
3524 isc_result_t result;
3525 dns_fixedname_t fixedsecroot;
3526 dns_name_t *secroot;
3528 char namebuf[DNS_NAME_FORMATSIZE];
3530 dns_fixedname_t fixedfound;
3532 dns_fixedname_init(&fixedsecroot);
3533 secroot = dns_fixedname_name(&fixedsecroot);
3534 dns_fixedname_init(&fixedfound);
3535 found = dns_fixedname_name(&fixedfound);
3536 if (val->havedlvsep)
3537 dns_name_copy(dns_fixedname_name(&val->dlvsep), secroot, NULL);
3539 unsigned int labels;
3540 dns_name_copy(val->event->name, secroot, NULL);
3542 * If this is a response to a DS query, we need to look in
3543 * the parent zone for the trust anchor.
3546 labels = dns_name_countlabels(secroot);
3547 if (val->event->type == dns_rdatatype_ds && labels > 1U)
3548 dns_name_getlabelsequence(secroot, 1, labels - 1,
3550 result = dns_keytable_finddeepestmatch(val->keytable,
3552 if (result == ISC_R_NOTFOUND) {
3553 if (val->mustbesecure) {
3554 validator_log(val, ISC_LOG_WARNING,
3555 "must be secure failure");
3556 result = DNS_R_MUSTBESECURE;
3559 if (val->view->dlv == NULL || DLVTRIED(val)) {
3560 markanswer(val, "proveunsecure (1)");
3561 return (ISC_R_SUCCESS);
3563 return (startfinddlvsep(val, dns_rootname));
3564 } else if (result != ISC_R_SUCCESS)
3570 * We are looking for breaks below the SEP so add a label.
3572 val->labels = dns_name_countlabels(secroot) + 1;
3574 validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
3576 * If we have a DS rdataset and it is secure then check if
3577 * the DS rdataset has a supported algorithm combination.
3578 * If not this is a insecure delegation as far as this
3579 * resolver is concerned. Fall back to DLV if available.
3581 if (have_ds && val->frdataset.trust >= dns_trust_secure &&
3582 !check_ds(val, dns_fixedname_name(&val->fname),
3584 dns_name_format(dns_fixedname_name(&val->fname),
3585 namebuf, sizeof(namebuf));
3586 if ((val->view->dlv == NULL || DLVTRIED(val)) &&
3587 val->mustbesecure) {
3588 validator_log(val, ISC_LOG_WARNING,
3589 "must be secure failure at '%s'",
3591 result = DNS_R_MUSTBESECURE;
3594 validator_log(val, ISC_LOG_DEBUG(3),
3595 "no supported algorithm/digest (%s/DS)",
3597 if (val->view->dlv == NULL || DLVTRIED(val)) {
3598 markanswer(val, "proveunsecure (2)");
3599 result = ISC_R_SUCCESS;
3602 result = startfinddlvsep(val,
3603 dns_fixedname_name(&val->fname));
3610 val->labels <= dns_name_countlabels(val->event->name);
3614 dns_fixedname_init(&val->fname);
3615 tname = dns_fixedname_name(&val->fname);
3616 if (val->labels == dns_name_countlabels(val->event->name))
3617 dns_name_copy(val->event->name, tname, NULL);
3619 dns_name_split(val->event->name, val->labels,
3622 dns_name_format(tname, namebuf, sizeof(namebuf));
3623 validator_log(val, ISC_LOG_DEBUG(3),
3624 "checking existence of DS at '%s'",
3627 result = view_find(val, tname, dns_rdatatype_ds);
3628 if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
3630 * There is no DS. If this is a delegation,
3634 * If we have "trust == answer" then this namespace
3635 * has switched from insecure to should be secure.
3637 if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3638 DNS_TRUST_ANSWER(val->frdataset.trust)) {
3639 result = create_validator(val, tname,
3644 if (result != ISC_R_SUCCESS)
3646 return (DNS_R_WAIT);
3649 * Zones using NSEC3 don't return a NSEC RRset so
3650 * we need to use dns_view_findzonecut2 to find
3653 if (result == DNS_R_NXRRSET &&
3654 !dns_rdataset_isassociated(&val->frdataset) &&
3655 dns_view_findzonecut2(val->view, tname, found,
3656 0, 0, ISC_FALSE, ISC_FALSE,
3657 NULL, NULL) == ISC_R_SUCCESS &&
3658 dns_name_equal(tname, found)) {
3659 if (val->mustbesecure) {
3660 validator_log(val, ISC_LOG_WARNING,
3661 "must be secure failure");
3662 return (DNS_R_MUSTBESECURE);
3664 if (val->view->dlv == NULL || DLVTRIED(val)) {
3665 markanswer(val, "proveunsecure (3)");
3666 return (ISC_R_SUCCESS);
3668 return (startfinddlvsep(val, tname));
3670 if (val->frdataset.trust < dns_trust_secure) {
3672 * This shouldn't happen, since the negative
3673 * response should have been validated. Since
3674 * there's no way of validating existing
3675 * negative response blobs, give up.
3677 result = DNS_R_NOVALIDSIG;
3680 if (isdelegation(tname, &val->frdataset, result)) {
3681 if (val->mustbesecure) {
3682 validator_log(val, ISC_LOG_WARNING,
3683 "must be secure failure");
3684 return (DNS_R_MUSTBESECURE);
3686 if (val->view->dlv == NULL || DLVTRIED(val)) {
3687 markanswer(val, "proveunsecure (4)");
3688 return (ISC_R_SUCCESS);
3690 return (startfinddlvsep(val, tname));
3693 } else if (result == ISC_R_SUCCESS) {
3695 * There is a DS here. Verify that it's secure and
3698 if (val->frdataset.trust >= dns_trust_secure) {
3699 if (!check_ds(val, tname, &val->frdataset)) {
3700 validator_log(val, ISC_LOG_DEBUG(3),
3701 "no supported algorithm/"
3702 "digest (%s/DS)", namebuf);
3703 if (val->mustbesecure) {
3706 "must be secure failure");
3707 result = DNS_R_MUSTBESECURE;
3710 if (val->view->dlv == NULL ||
3713 "proveunsecure (5)");
3714 result = ISC_R_SUCCESS;
3717 result = startfinddlvsep(val, tname);
3722 else if (!dns_rdataset_isassociated(&val->fsigrdataset))
3724 result = DNS_R_NOVALIDSIG;
3728 * Validate / re-validate answer.
3730 result = create_validator(val, tname, dns_rdatatype_ds,
3735 if (result != ISC_R_SUCCESS)
3737 return (DNS_R_WAIT);
3738 } else if (result == DNS_R_NXDOMAIN ||
3739 result == DNS_R_NCACHENXDOMAIN) {
3741 * This is not a zone cut. Assuming things are
3742 * as expected, continue.
3744 if (!dns_rdataset_isassociated(&val->frdataset)) {
3746 * There should be an NSEC here, since we
3747 * are still in a secure zone.
3749 result = DNS_R_NOVALIDNSEC;
3751 } else if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3752 DNS_TRUST_ANSWER(val->frdataset.trust)) {
3754 * If we have "trust == answer" then this namespace
3755 * has switched from insecure to should be secure.
3757 result = create_validator(val, tname,
3762 if (result != ISC_R_SUCCESS)
3764 return (DNS_R_WAIT);
3765 } else if (val->frdataset.trust < dns_trust_secure) {
3767 * This shouldn't happen, since the negative
3768 * response should have been validated. Since
3769 * there's no way of validating existing
3770 * negative response blobs, give up.
3772 result = DNS_R_NOVALIDSIG;
3776 } else if (result == ISC_R_NOTFOUND) {
3778 * We don't know anything about the DS. Find it.
3780 result = create_fetch(val, tname, dns_rdatatype_ds,
3781 dsfetched2, "proveunsecure");
3782 if (result != ISC_R_SUCCESS)
3784 return (DNS_R_WAIT);
3785 } else if (result == DNS_R_BROKENCHAIN)
3789 /* Couldn't complete insecurity proof */
3790 validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed");
3791 return (DNS_R_NOTINSECURE); /* Couldn't complete insecurity proof */
3794 if (dns_rdataset_isassociated(&val->frdataset))
3795 dns_rdataset_disassociate(&val->frdataset);
3796 if (dns_rdataset_isassociated(&val->fsigrdataset))
3797 dns_rdataset_disassociate(&val->fsigrdataset);
3802 * Reset state and revalidate the answer using DLV.
3805 dlv_validator_start(dns_validator_t *val) {
3808 validator_log(val, ISC_LOG_DEBUG(3), "dlv_validator_start");
3811 * Reset state and try again.
3813 val->attributes &= VALATTR_DLVTRIED;
3814 val->options &= ~DNS_VALIDATOR_DLV;
3816 event = (isc_event_t *)val->event;
3817 isc_task_send(val->task, &event);
3821 * Start the validation process.
3823 * Attempt to validate the answer based on the category it appears to
3825 * \li 1. secure positive answer.
3826 * \li 2. unsecure positive answer.
3827 * \li 3. a negative answer (secure or unsecure).
3829 * Note a answer that appears to be a secure positive answer may actually
3830 * be a unsecure positive answer.
3833 validator_start(isc_task_t *task, isc_event_t *event) {
3834 dns_validator_t *val;
3835 dns_validatorevent_t *vevent;
3836 isc_boolean_t want_destroy = ISC_FALSE;
3837 isc_result_t result = ISC_R_FAILURE;
3840 REQUIRE(event->ev_type == DNS_EVENT_VALIDATORSTART);
3841 vevent = (dns_validatorevent_t *)event;
3842 val = vevent->validator;
3844 /* If the validator has been canceled, val->event == NULL */
3845 if (val->event == NULL)
3849 validator_log(val, ISC_LOG_DEBUG(3), "restarting using DLV");
3851 validator_log(val, ISC_LOG_DEBUG(3), "starting");
3855 if ((val->options & DNS_VALIDATOR_DLV) != 0 &&
3856 val->event->rdataset != NULL) {
3857 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV");
3858 result = startfinddlvsep(val, dns_rootname);
3859 } else if (val->event->rdataset != NULL &&
3860 val->event->sigrdataset != NULL) {
3861 isc_result_t saved_result;
3864 * This looks like a simple validation. We say "looks like"
3865 * because it might end up requiring an insecurity proof.
3867 validator_log(val, ISC_LOG_DEBUG(3),
3868 "attempting positive response validation");
3870 INSIST(dns_rdataset_isassociated(val->event->rdataset));
3871 INSIST(dns_rdataset_isassociated(val->event->sigrdataset));
3872 result = start_positive_validation(val);
3873 if (result == DNS_R_NOVALIDSIG &&
3874 (val->attributes & VALATTR_TRIEDVERIFY) == 0)
3876 saved_result = result;
3877 validator_log(val, ISC_LOG_DEBUG(3),
3878 "falling back to insecurity proof");
3879 val->attributes |= VALATTR_INSECURITY;
3880 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
3881 if (result == DNS_R_NOTINSECURE)
3882 result = saved_result;
3884 } else if (val->event->rdataset != NULL &&
3885 val->event->rdataset->type != 0) {
3887 * This is either an unsecure subdomain or a response from
3890 INSIST(dns_rdataset_isassociated(val->event->rdataset));
3891 validator_log(val, ISC_LOG_DEBUG(3),
3892 "attempting insecurity proof");
3894 val->attributes |= VALATTR_INSECURITY;
3895 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
3896 } else if (val->event->rdataset == NULL &&
3897 val->event->sigrdataset == NULL)
3900 * This is a nonexistence validation.
3902 validator_log(val, ISC_LOG_DEBUG(3),
3903 "attempting negative response validation");
3905 if (val->event->message->rcode == dns_rcode_nxdomain) {
3906 val->attributes |= VALATTR_NEEDNOQNAME;
3907 val->attributes |= VALATTR_NEEDNOWILDCARD;
3909 val->attributes |= VALATTR_NEEDNODATA;
3910 result = nsecvalidate(val, ISC_FALSE);
3911 } else if (val->event->rdataset != NULL &&
3912 val->event->rdataset->type == 0)
3915 * This is a nonexistence validation.
3917 validator_log(val, ISC_LOG_DEBUG(3),
3918 "attempting negative response validation");
3920 if (val->event->rdataset->covers == dns_rdatatype_any) {
3921 val->attributes |= VALATTR_NEEDNOQNAME;
3922 val->attributes |= VALATTR_NEEDNOWILDCARD;
3924 val->attributes |= VALATTR_NEEDNODATA;
3925 result = nsecvalidate(val, ISC_FALSE);
3928 * This shouldn't happen.
3933 if (result != DNS_R_WAIT) {
3934 want_destroy = exit_check(val);
3935 validator_done(val, result);
3944 dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
3945 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
3946 dns_message_t *message, unsigned int options,
3947 isc_task_t *task, isc_taskaction_t action, void *arg,
3948 dns_validator_t **validatorp)
3950 isc_result_t result;
3951 dns_validator_t *val;
3953 dns_validatorevent_t *event;
3955 REQUIRE(name != NULL);
3956 REQUIRE(rdataset != NULL ||
3957 (rdataset == NULL && sigrdataset == NULL && message != NULL));
3958 REQUIRE(validatorp != NULL && *validatorp == NULL);
3961 result = ISC_R_FAILURE;
3963 val = isc_mem_get(view->mctx, sizeof(*val));
3965 return (ISC_R_NOMEMORY);
3967 dns_view_weakattach(view, &val->view);
3968 event = (dns_validatorevent_t *)
3969 isc_event_allocate(view->mctx, task,
3970 DNS_EVENT_VALIDATORSTART,
3971 validator_start, NULL,
3972 sizeof(dns_validatorevent_t));
3973 if (event == NULL) {
3974 result = ISC_R_NOMEMORY;
3977 isc_task_attach(task, &tclone);
3978 event->validator = val;
3979 event->result = ISC_R_FAILURE;
3982 event->rdataset = rdataset;
3983 event->sigrdataset = sigrdataset;
3984 event->message = message;
3985 memset(event->proofs, 0, sizeof(event->proofs));
3986 event->optout = ISC_FALSE;
3987 result = isc_mutex_init(&val->lock);
3988 if (result != ISC_R_SUCCESS)
3991 val->options = options;
3992 val->attributes = 0;
3994 val->subvalidator = NULL;
3996 val->keytable = NULL;
3997 dns_keytable_attach(val->view->secroots, &val->keytable);
3998 val->keynode = NULL;
4000 val->siginfo = NULL;
4002 val->action = action;
4005 val->currentset = NULL;
4008 dns_rdataset_init(&val->dlv);
4009 val->seensig = ISC_FALSE;
4010 val->havedlvsep = ISC_FALSE;
4014 val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
4015 dns_rdataset_init(&val->frdataset);
4016 dns_rdataset_init(&val->fsigrdataset);
4017 dns_fixedname_init(&val->wild);
4018 dns_fixedname_init(&val->nearest);
4019 dns_fixedname_init(&val->closest);
4020 ISC_LINK_INIT(val, link);
4021 val->magic = VALIDATOR_MAGIC;
4023 if ((options & DNS_VALIDATOR_DEFER) == 0)
4024 isc_task_send(task, ISC_EVENT_PTR(&event));
4028 return (ISC_R_SUCCESS);
4031 isc_task_detach(&tclone);
4032 isc_event_free(ISC_EVENT_PTR(&event));
4035 dns_view_weakdetach(&val->view);
4036 isc_mem_put(view->mctx, val, sizeof(*val));
4042 dns_validator_send(dns_validator_t *validator) {
4044 REQUIRE(VALID_VALIDATOR(validator));
4046 LOCK(&validator->lock);
4048 INSIST((validator->options & DNS_VALIDATOR_DEFER) != 0);
4049 event = (isc_event_t *)validator->event;
4050 validator->options &= ~DNS_VALIDATOR_DEFER;
4051 UNLOCK(&validator->lock);
4053 isc_task_send(validator->task, ISC_EVENT_PTR(&event));
4057 dns_validator_cancel(dns_validator_t *validator) {
4058 REQUIRE(VALID_VALIDATOR(validator));
4060 LOCK(&validator->lock);
4062 validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
4064 if ((validator->attributes & VALATTR_CANCELED) == 0) {
4065 validator->attributes |= VALATTR_CANCELED;
4066 if (validator->event != NULL) {
4067 if (validator->fetch != NULL)
4068 dns_resolver_cancelfetch(validator->fetch);
4070 if (validator->subvalidator != NULL)
4071 dns_validator_cancel(validator->subvalidator);
4072 if ((validator->options & DNS_VALIDATOR_DEFER) != 0) {
4073 validator->options &= ~DNS_VALIDATOR_DEFER;
4074 validator_done(validator, ISC_R_CANCELED);
4078 UNLOCK(&validator->lock);
4082 destroy(dns_validator_t *val) {
4085 REQUIRE(SHUTDOWN(val));
4086 REQUIRE(val->event == NULL);
4087 REQUIRE(val->fetch == NULL);
4089 if (val->keynode != NULL)
4090 dns_keytable_detachkeynode(val->keytable, &val->keynode);
4091 else if (val->key != NULL)
4092 dst_key_free(&val->key);
4093 if (val->keytable != NULL)
4094 dns_keytable_detach(&val->keytable);
4095 if (val->subvalidator != NULL)
4096 dns_validator_destroy(&val->subvalidator);
4097 if (val->havedlvsep)
4098 dns_rdataset_disassociate(&val->dlv);
4099 if (dns_rdataset_isassociated(&val->frdataset))
4100 dns_rdataset_disassociate(&val->frdataset);
4101 if (dns_rdataset_isassociated(&val->fsigrdataset))
4102 dns_rdataset_disassociate(&val->fsigrdataset);
4103 mctx = val->view->mctx;
4104 if (val->siginfo != NULL)
4105 isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo));
4106 DESTROYLOCK(&val->lock);
4107 dns_view_weakdetach(&val->view);
4109 isc_mem_put(mctx, val, sizeof(*val));
4113 dns_validator_destroy(dns_validator_t **validatorp) {
4114 dns_validator_t *val;
4115 isc_boolean_t want_destroy = ISC_FALSE;
4117 REQUIRE(validatorp != NULL);
4119 REQUIRE(VALID_VALIDATOR(val));
4123 val->attributes |= VALATTR_SHUTDOWN;
4124 validator_log(val, ISC_LOG_DEBUG(3), "dns_validator_destroy");
4126 want_destroy = exit_check(val);
4137 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
4138 isc_logmodule_t *module, int level, const char *fmt, va_list ap)
4141 static const char spaces[] = " *";
4142 int depth = val->depth * 2;
4144 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
4146 if ((unsigned int) depth >= sizeof spaces)
4147 depth = sizeof spaces - 1;
4149 if (val->event != NULL && val->event->name != NULL) {
4150 char namebuf[DNS_NAME_FORMATSIZE];
4151 char typebuf[DNS_RDATATYPE_FORMATSIZE];
4153 dns_name_format(val->event->name, namebuf, sizeof(namebuf));
4154 dns_rdatatype_format(val->event->type, typebuf,
4156 isc_log_write(dns_lctx, category, module, level,
4157 "%.*svalidating @%p: %s %s: %s", depth, spaces,
4158 val, namebuf, typebuf, msgbuf);
4160 isc_log_write(dns_lctx, category, module, level,
4161 "%.*svalidator @%p: %s", depth, spaces,
4167 validator_log(dns_validator_t *val, int level, const char *fmt, ...) {
4170 if (! isc_log_wouldlog(dns_lctx, level))
4175 validator_logv(val, DNS_LOGCATEGORY_DNSSEC,
4176 DNS_LOGMODULE_VALIDATOR, level, fmt, ap);
4181 validator_logcreate(dns_validator_t *val,
4182 dns_name_t *name, dns_rdatatype_t type,
4183 const char *caller, const char *operation)
4185 char namestr[DNS_NAME_FORMATSIZE];
4186 char typestr[DNS_RDATATYPE_FORMATSIZE];
4188 dns_name_format(name, namestr, sizeof(namestr));
4189 dns_rdatatype_format(type, typestr, sizeof(typestr));
4190 validator_log(val, ISC_LOG_DEBUG(9), "%s: creating %s for %s %s",
4191 caller, operation, namestr, typestr);