2 * Copyright (C) 2004-2011 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.3 2011-06-21 20:13:23 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)
132 #define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
135 destroy(dns_validator_t *val);
138 get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
139 dns_rdataset_t *rdataset);
142 validate(dns_validator_t *val, isc_boolean_t resume);
145 validatezonekey(dns_validator_t *val);
148 nsecvalidate(dns_validator_t *val, isc_boolean_t resume);
151 proveunsecure(dns_validator_t *val, isc_boolean_t have_ds,
152 isc_boolean_t resume);
155 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
156 isc_logmodule_t *module, int level, const char *fmt, va_list ap)
157 ISC_FORMAT_PRINTF(5, 0);
160 validator_log(dns_validator_t *val, int level, const char *fmt, ...)
161 ISC_FORMAT_PRINTF(3, 4);
164 validator_logcreate(dns_validator_t *val,
165 dns_name_t *name, dns_rdatatype_t type,
166 const char *caller, const char *operation);
169 dlv_validatezonekey(dns_validator_t *val);
172 dlv_validator_start(dns_validator_t *val);
175 finddlvsep(dns_validator_t *val, isc_boolean_t resume);
178 startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure);
181 * Mark the RRsets as a answer.
184 markanswer(dns_validator_t *val, const char *where) {
185 validator_log(val, ISC_LOG_DEBUG(3), "marking as answer (%s)", where);
186 if (val->event->rdataset != NULL)
187 dns_rdataset_settrust(val->event->rdataset, dns_trust_answer);
188 if (val->event->sigrdataset != NULL)
189 dns_rdataset_settrust(val->event->sigrdataset,
194 marksecure(dns_validatorevent_t *event) {
195 dns_rdataset_settrust(event->rdataset, dns_trust_secure);
196 if (event->sigrdataset != NULL)
197 dns_rdataset_settrust(event->sigrdataset, dns_trust_secure);
201 validator_done(dns_validator_t *val, isc_result_t result) {
204 if (val->event == NULL)
208 * Caller must be holding the lock.
211 val->event->result = result;
212 task = val->event->ev_sender;
213 val->event->ev_sender = val;
214 val->event->ev_type = DNS_EVENT_VALIDATORDONE;
215 val->event->ev_action = val->action;
216 val->event->ev_arg = val->arg;
217 isc_task_sendanddetach(&task, (isc_event_t **)&val->event);
220 static inline isc_boolean_t
221 exit_check(dns_validator_t *val) {
223 * Caller must be holding the lock.
228 INSIST(val->event == NULL);
230 if (val->fetch != NULL || val->subvalidator != NULL)
237 * Check that we have atleast one supported algorithm in the DLV RRset.
239 static inline isc_boolean_t
240 dlv_algorithm_supported(dns_validator_t *val) {
241 dns_rdata_t rdata = DNS_RDATA_INIT;
245 for (result = dns_rdataset_first(&val->dlv);
246 result == ISC_R_SUCCESS;
247 result = dns_rdataset_next(&val->dlv)) {
248 dns_rdata_reset(&rdata);
249 dns_rdataset_current(&val->dlv, &rdata);
250 result = dns_rdata_tostruct(&rdata, &dlv, NULL);
251 RUNTIME_CHECK(result == ISC_R_SUCCESS);
253 if (!dns_resolver_algorithm_supported(val->view->resolver,
258 if (dlv.digest_type != DNS_DSDIGEST_SHA256 &&
259 dlv.digest_type != DNS_DSDIGEST_SHA1)
268 * Look in the NSEC record returned from a DS query to see if there is
269 * a NS RRset at this name. If it is found we are at a delegation point.
272 isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
273 isc_result_t dbresult)
275 dns_fixedname_t fixed;
276 dns_label_t hashlabel;
277 dns_name_t nsec3name;
278 dns_rdata_nsec3_t nsec3;
279 dns_rdata_t rdata = DNS_RDATA_INIT;
286 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
287 unsigned char owner[NSEC3_MAX_HASH_LENGTH];
290 REQUIRE(dbresult == DNS_R_NXRRSET || dbresult == DNS_R_NCACHENXRRSET);
292 dns_rdataset_init(&set);
293 if (dbresult == DNS_R_NXRRSET)
294 dns_rdataset_clone(rdataset, &set);
296 result = dns_ncache_getrdataset(rdataset, name,
297 dns_rdatatype_nsec, &set);
298 if (result == ISC_R_NOTFOUND)
300 if (result != ISC_R_SUCCESS)
304 INSIST(set.type == dns_rdatatype_nsec);
307 result = dns_rdataset_first(&set);
308 if (result == ISC_R_SUCCESS) {
309 dns_rdataset_current(&set, &rdata);
310 found = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
311 dns_rdata_reset(&rdata);
313 dns_rdataset_disassociate(&set);
318 * Iterate over the ncache entry.
321 dns_name_init(&nsec3name, NULL);
322 dns_fixedname_init(&fixed);
323 dns_name_downcase(name, dns_fixedname_name(&fixed), NULL);
324 name = dns_fixedname_name(&fixed);
325 result = dns_rdataset_first(rdataset);
326 for (result = dns_rdataset_first(rdataset);
327 result == ISC_R_SUCCESS;
328 result = dns_rdataset_next(rdataset))
330 dns_ncache_current(rdataset, &nsec3name, &set);
331 if (set.type != dns_rdatatype_nsec3) {
332 dns_rdataset_disassociate(&set);
335 dns_name_getlabel(&nsec3name, 0, &hashlabel);
336 isc_region_consume(&hashlabel, 1);
337 isc_buffer_init(&buffer, owner, sizeof(owner));
338 result = isc_base32hex_decoderegion(&hashlabel, &buffer);
339 if (result != ISC_R_SUCCESS) {
340 dns_rdataset_disassociate(&set);
343 for (result = dns_rdataset_first(&set);
344 result == ISC_R_SUCCESS;
345 result = dns_rdataset_next(&set))
347 dns_rdata_reset(&rdata);
348 dns_rdataset_current(&set, &rdata);
349 (void)dns_rdata_tostruct(&rdata, &nsec3, NULL);
352 length = isc_iterated_hash(hash, nsec3.hash,
353 nsec3.iterations, nsec3.salt,
355 name->ndata, name->length);
356 if (length != isc_buffer_usedlength(&buffer))
358 order = memcmp(hash, owner, length);
360 found = dns_nsec3_typepresent(&rdata,
362 dns_rdataset_disassociate(&set);
365 if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) == 0)
368 * Does this optout span cover the name?
370 scope = memcmp(owner, nsec3.next, nsec3.next_length);
371 if ((scope < 0 && order > 0 &&
372 memcmp(hash, nsec3.next, length) < 0) ||
373 (scope >= 0 && (order > 0 ||
374 memcmp(hash, nsec3.next, length) < 0)))
376 dns_rdataset_disassociate(&set);
380 dns_rdataset_disassociate(&set);
386 * We have been asked to to look for a key.
387 * If found resume the validation process.
388 * If not found fail the validation process.
391 fetch_callback_validator(isc_task_t *task, isc_event_t *event) {
392 dns_fetchevent_t *devent;
393 dns_validator_t *val;
394 dns_rdataset_t *rdataset;
395 isc_boolean_t want_destroy;
397 isc_result_t eresult;
398 isc_result_t saved_result;
401 INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
402 devent = (dns_fetchevent_t *)event;
403 val = devent->ev_arg;
404 rdataset = &val->frdataset;
405 eresult = devent->result;
407 /* Free resources which are not of interest. */
408 if (devent->node != NULL)
409 dns_db_detachnode(devent->db, &devent->node);
410 if (devent->db != NULL)
411 dns_db_detach(&devent->db);
412 if (dns_rdataset_isassociated(&val->fsigrdataset))
413 dns_rdataset_disassociate(&val->fsigrdataset);
414 isc_event_free(&event);
415 dns_resolver_destroyfetch(&val->fetch);
417 INSIST(val->event != NULL);
419 validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_validator");
422 validator_done(val, ISC_R_CANCELED);
423 } else if (eresult == ISC_R_SUCCESS) {
424 validator_log(val, ISC_LOG_DEBUG(3),
425 "keyset with trust %s",
426 dns_trust_totext(rdataset->trust));
428 * Only extract the dst key if the keyset is secure.
430 if (rdataset->trust >= dns_trust_secure) {
431 result = get_dst_key(val, val->siginfo, rdataset);
432 if (result == ISC_R_SUCCESS)
433 val->keyset = &val->frdataset;
435 result = validate(val, ISC_TRUE);
436 if (result == DNS_R_NOVALIDSIG &&
437 (val->attributes & VALATTR_TRIEDVERIFY) == 0)
439 saved_result = result;
440 validator_log(val, ISC_LOG_DEBUG(3),
441 "falling back to insecurity proof");
442 val->attributes |= VALATTR_INSECURITY;
443 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
444 if (result == DNS_R_NOTINSECURE)
445 result = saved_result;
447 if (result != DNS_R_WAIT)
448 validator_done(val, result);
450 validator_log(val, ISC_LOG_DEBUG(3),
451 "fetch_callback_validator: got %s",
452 isc_result_totext(eresult));
453 if (eresult == ISC_R_CANCELED)
454 validator_done(val, eresult);
456 validator_done(val, DNS_R_BROKENCHAIN);
458 want_destroy = exit_check(val);
465 * We were asked to look for a DS record as part of following a key chain
466 * upwards. If found resume the validation process. If not found fail the
467 * validation process.
470 dsfetched(isc_task_t *task, isc_event_t *event) {
471 dns_fetchevent_t *devent;
472 dns_validator_t *val;
473 dns_rdataset_t *rdataset;
474 isc_boolean_t want_destroy;
476 isc_result_t eresult;
479 INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
480 devent = (dns_fetchevent_t *)event;
481 val = devent->ev_arg;
482 rdataset = &val->frdataset;
483 eresult = devent->result;
485 /* Free resources which are not of interest. */
486 if (devent->node != NULL)
487 dns_db_detachnode(devent->db, &devent->node);
488 if (devent->db != NULL)
489 dns_db_detach(&devent->db);
490 if (dns_rdataset_isassociated(&val->fsigrdataset))
491 dns_rdataset_disassociate(&val->fsigrdataset);
492 isc_event_free(&event);
493 dns_resolver_destroyfetch(&val->fetch);
495 INSIST(val->event != NULL);
497 validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched");
500 validator_done(val, ISC_R_CANCELED);
501 } else if (eresult == ISC_R_SUCCESS) {
502 validator_log(val, ISC_LOG_DEBUG(3),
503 "dsset with trust %s",
504 dns_trust_totext(rdataset->trust));
505 val->dsset = &val->frdataset;
506 result = validatezonekey(val);
507 if (result != DNS_R_WAIT)
508 validator_done(val, result);
509 } else if (eresult == DNS_R_NXRRSET ||
510 eresult == DNS_R_NCACHENXRRSET ||
511 eresult == DNS_R_SERVFAIL) /* RFC 1034 parent? */
513 validator_log(val, ISC_LOG_DEBUG(3),
514 "falling back to insecurity proof (%s)",
515 dns_result_totext(eresult));
516 val->attributes |= VALATTR_INSECURITY;
517 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
518 if (result != DNS_R_WAIT)
519 validator_done(val, result);
521 validator_log(val, ISC_LOG_DEBUG(3),
523 isc_result_totext(eresult));
524 if (eresult == ISC_R_CANCELED)
525 validator_done(val, eresult);
527 validator_done(val, DNS_R_BROKENCHAIN);
529 want_destroy = exit_check(val);
536 * We were asked to look for the DS record as part of proving that a
539 * If the DS record doesn't exist and the query name corresponds to
540 * a delegation point we are transitioning from a secure zone to a
543 * If the DS record exists it will be secure. We can continue looking
544 * for the break point in the chain of trust.
547 dsfetched2(isc_task_t *task, isc_event_t *event) {
548 dns_fetchevent_t *devent;
549 dns_validator_t *val;
551 isc_boolean_t want_destroy;
553 isc_result_t eresult;
556 INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
557 devent = (dns_fetchevent_t *)event;
558 val = devent->ev_arg;
559 eresult = devent->result;
561 /* Free resources which are not of interest. */
562 if (devent->node != NULL)
563 dns_db_detachnode(devent->db, &devent->node);
564 if (devent->db != NULL)
565 dns_db_detach(&devent->db);
566 if (dns_rdataset_isassociated(&val->fsigrdataset))
567 dns_rdataset_disassociate(&val->fsigrdataset);
568 dns_resolver_destroyfetch(&val->fetch);
570 INSIST(val->event != NULL);
572 validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched2: %s",
573 dns_result_totext(eresult));
576 validator_done(val, ISC_R_CANCELED);
577 } else if (eresult == DNS_R_NXRRSET || eresult == DNS_R_NCACHENXRRSET) {
579 * There is no DS. If this is a delegation, we're done.
581 tname = dns_fixedname_name(&devent->foundname);
582 if (isdelegation(tname, &val->frdataset, eresult)) {
583 if (val->mustbesecure) {
584 validator_log(val, ISC_LOG_WARNING,
585 "must be secure failure");
586 validator_done(val, DNS_R_MUSTBESECURE);
587 } else if (val->view->dlv == NULL || DLVTRIED(val)) {
588 markanswer(val, "dsfetched2");
589 validator_done(val, ISC_R_SUCCESS);
591 result = startfinddlvsep(val, tname);
592 if (result != DNS_R_WAIT)
593 validator_done(val, result);
596 result = proveunsecure(val, ISC_FALSE, ISC_TRUE);
597 if (result != DNS_R_WAIT)
598 validator_done(val, result);
600 } else if (eresult == ISC_R_SUCCESS ||
601 eresult == DNS_R_NXDOMAIN ||
602 eresult == DNS_R_NCACHENXDOMAIN)
605 * There is a DS which may or may not be a zone cut.
606 * In either case we are still in a secure zone resume
609 result = proveunsecure(val, ISC_TF(eresult == ISC_R_SUCCESS),
611 if (result != DNS_R_WAIT)
612 validator_done(val, result);
614 if (eresult == ISC_R_CANCELED)
615 validator_done(val, eresult);
617 validator_done(val, DNS_R_NOVALIDDS);
619 isc_event_free(&event);
620 want_destroy = exit_check(val);
627 * Callback from when a DNSKEY RRset has been validated.
629 * Resumes the stalled validation process.
632 keyvalidated(isc_task_t *task, isc_event_t *event) {
633 dns_validatorevent_t *devent;
634 dns_validator_t *val;
635 isc_boolean_t want_destroy;
637 isc_result_t eresult;
638 isc_result_t saved_result;
641 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
643 devent = (dns_validatorevent_t *)event;
644 val = devent->ev_arg;
645 eresult = devent->result;
647 isc_event_free(&event);
648 dns_validator_destroy(&val->subvalidator);
650 INSIST(val->event != NULL);
652 validator_log(val, ISC_LOG_DEBUG(3), "in keyvalidated");
655 validator_done(val, ISC_R_CANCELED);
656 } else if (eresult == ISC_R_SUCCESS) {
657 validator_log(val, ISC_LOG_DEBUG(3),
658 "keyset with trust %s",
659 dns_trust_totext(val->frdataset.trust));
661 * Only extract the dst key if the keyset is secure.
663 if (val->frdataset.trust >= dns_trust_secure)
664 (void) get_dst_key(val, val->siginfo, &val->frdataset);
665 result = validate(val, ISC_TRUE);
666 if (result == DNS_R_NOVALIDSIG &&
667 (val->attributes & VALATTR_TRIEDVERIFY) == 0)
669 saved_result = result;
670 validator_log(val, ISC_LOG_DEBUG(3),
671 "falling back to insecurity proof");
672 val->attributes |= VALATTR_INSECURITY;
673 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
674 if (result == DNS_R_NOTINSECURE)
675 result = saved_result;
677 if (result != DNS_R_WAIT)
678 validator_done(val, result);
680 if (eresult != DNS_R_BROKENCHAIN) {
681 if (dns_rdataset_isassociated(&val->frdataset))
682 dns_rdataset_expire(&val->frdataset);
683 if (dns_rdataset_isassociated(&val->fsigrdataset))
684 dns_rdataset_expire(&val->fsigrdataset);
686 validator_log(val, ISC_LOG_DEBUG(3),
687 "keyvalidated: got %s",
688 isc_result_totext(eresult));
689 validator_done(val, DNS_R_BROKENCHAIN);
691 want_destroy = exit_check(val);
698 * Callback when the DS record has been validated.
700 * Resumes validation of the zone key or the unsecure zone proof.
703 dsvalidated(isc_task_t *task, isc_event_t *event) {
704 dns_validatorevent_t *devent;
705 dns_validator_t *val;
706 isc_boolean_t want_destroy;
708 isc_result_t eresult;
711 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
713 devent = (dns_validatorevent_t *)event;
714 val = devent->ev_arg;
715 eresult = devent->result;
717 isc_event_free(&event);
718 dns_validator_destroy(&val->subvalidator);
720 INSIST(val->event != NULL);
722 validator_log(val, ISC_LOG_DEBUG(3), "in dsvalidated");
725 validator_done(val, ISC_R_CANCELED);
726 } else if (eresult == ISC_R_SUCCESS) {
727 isc_boolean_t have_dsset;
729 validator_log(val, ISC_LOG_DEBUG(3),
731 val->frdataset.type == dns_rdatatype_ds ?
732 "dsset" : "ds non-existance",
733 dns_trust_totext(val->frdataset.trust));
734 have_dsset = ISC_TF(val->frdataset.type == dns_rdatatype_ds);
735 name = dns_fixedname_name(&val->fname);
736 if ((val->attributes & VALATTR_INSECURITY) != 0 &&
737 val->frdataset.covers == dns_rdatatype_ds &&
738 NEGATIVE(&val->frdataset) &&
739 isdelegation(name, &val->frdataset, DNS_R_NCACHENXRRSET)) {
740 if (val->mustbesecure) {
741 validator_log(val, ISC_LOG_WARNING,
742 "must be secure failure, no DS "
743 "and this is a delegation");
744 result = DNS_R_MUSTBESECURE;
745 } else if (val->view->dlv == NULL || DLVTRIED(val)) {
746 markanswer(val, "dsvalidated");
747 result = ISC_R_SUCCESS;;
749 result = startfinddlvsep(val, name);
750 } else if ((val->attributes & VALATTR_INSECURITY) != 0) {
751 result = proveunsecure(val, have_dsset, ISC_TRUE);
753 result = validatezonekey(val);
754 if (result != DNS_R_WAIT)
755 validator_done(val, result);
757 if (eresult != DNS_R_BROKENCHAIN) {
758 if (dns_rdataset_isassociated(&val->frdataset))
759 dns_rdataset_expire(&val->frdataset);
760 if (dns_rdataset_isassociated(&val->fsigrdataset))
761 dns_rdataset_expire(&val->fsigrdataset);
763 validator_log(val, ISC_LOG_DEBUG(3),
764 "dsvalidated: got %s",
765 isc_result_totext(eresult));
766 validator_done(val, DNS_R_BROKENCHAIN);
768 want_destroy = exit_check(val);
775 * Return ISC_R_SUCCESS if we can determine that the name doesn't exist
776 * or we can determine whether there is data or not at the name.
777 * If the name does not exist return the wildcard name.
779 * Return ISC_R_IGNORE when the NSEC is not the appropriate one.
782 nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
783 dns_rdataset_t *nsecset, isc_boolean_t *exists,
784 isc_boolean_t *data, dns_name_t *wild)
787 dns_rdata_t rdata = DNS_RDATA_INIT;
789 dns_namereln_t relation;
790 unsigned int olabels, nlabels, labels;
791 dns_rdata_nsec_t nsec;
792 isc_boolean_t atparent;
796 REQUIRE(exists != NULL);
797 REQUIRE(data != NULL);
798 REQUIRE(nsecset != NULL &&
799 nsecset->type == dns_rdatatype_nsec);
801 result = dns_rdataset_first(nsecset);
802 if (result != ISC_R_SUCCESS) {
803 validator_log(val, ISC_LOG_DEBUG(3),
804 "failure processing NSEC set");
807 dns_rdataset_current(nsecset, &rdata);
809 validator_log(val, ISC_LOG_DEBUG(3), "looking for relevant nsec");
810 relation = dns_name_fullcompare(name, nsecname, &order, &olabels);
814 * The name is not within the NSEC range.
816 validator_log(val, ISC_LOG_DEBUG(3),
817 "NSEC does not cover name, before NSEC");
818 return (ISC_R_IGNORE);
823 * The names are the same.
825 atparent = dns_rdatatype_atparent(val->event->type);
826 ns = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
827 soa = dns_nsec_typepresent(&rdata, dns_rdatatype_soa);
831 * This NSEC record is from somewhere higher in
832 * the DNS, and at the parent of a delegation.
833 * It can not be legitimately used here.
835 validator_log(val, ISC_LOG_DEBUG(3),
836 "ignoring parent nsec");
837 return (ISC_R_IGNORE);
839 } else if (atparent && ns && soa) {
841 * This NSEC record is from the child.
842 * It can not be legitimately used here.
844 validator_log(val, ISC_LOG_DEBUG(3),
845 "ignoring child nsec");
846 return (ISC_R_IGNORE);
848 if (val->event->type == dns_rdatatype_cname ||
849 val->event->type == dns_rdatatype_nxt ||
850 val->event->type == dns_rdatatype_nsec ||
851 val->event->type == dns_rdatatype_key ||
852 !dns_nsec_typepresent(&rdata, dns_rdatatype_cname)) {
854 *data = dns_nsec_typepresent(&rdata, val->event->type);
855 validator_log(val, ISC_LOG_DEBUG(3),
856 "nsec proves name exists (owner) data=%d",
858 return (ISC_R_SUCCESS);
860 validator_log(val, ISC_LOG_DEBUG(3), "NSEC proves CNAME exists");
861 return (ISC_R_IGNORE);
864 if (relation == dns_namereln_subdomain &&
865 dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
866 !dns_nsec_typepresent(&rdata, dns_rdatatype_soa))
869 * This NSEC record is from somewhere higher in
870 * the DNS, and at the parent of a delegation.
871 * It can not be legitimately used here.
873 validator_log(val, ISC_LOG_DEBUG(3), "ignoring parent nsec");
874 return (ISC_R_IGNORE);
877 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
878 if (result != ISC_R_SUCCESS)
880 relation = dns_name_fullcompare(&nsec.next, name, &order, &nlabels);
882 dns_rdata_freestruct(&nsec);
883 validator_log(val, ISC_LOG_DEBUG(3),
884 "ignoring nsec matches next name");
885 return (ISC_R_IGNORE);
888 if (order < 0 && !dns_name_issubdomain(nsecname, &nsec.next)) {
890 * The name is not within the NSEC range.
892 dns_rdata_freestruct(&nsec);
893 validator_log(val, ISC_LOG_DEBUG(3),
894 "ignoring nsec because name is past end of range");
895 return (ISC_R_IGNORE);
898 if (order > 0 && relation == dns_namereln_subdomain) {
899 validator_log(val, ISC_LOG_DEBUG(3),
900 "nsec proves name exist (empty)");
901 dns_rdata_freestruct(&nsec);
904 return (ISC_R_SUCCESS);
908 dns_name_init(&common, NULL);
909 if (olabels > nlabels) {
910 labels = dns_name_countlabels(nsecname);
911 dns_name_getlabelsequence(nsecname, labels - olabels,
914 labels = dns_name_countlabels(&nsec.next);
915 dns_name_getlabelsequence(&nsec.next, labels - nlabels,
918 result = dns_name_concatenate(dns_wildcardname, &common,
920 if (result != ISC_R_SUCCESS) {
921 dns_rdata_freestruct(&nsec);
922 validator_log(val, ISC_LOG_DEBUG(3),
923 "failure generating wildcard name");
927 dns_rdata_freestruct(&nsec);
928 validator_log(val, ISC_LOG_DEBUG(3), "nsec range ok");
930 return (ISC_R_SUCCESS);
934 nsec3noexistnodata(dns_validator_t *val, dns_name_t* name,
935 dns_name_t *nsec3name, dns_rdataset_t *nsec3set,
936 dns_name_t *zonename, isc_boolean_t *exists,
937 isc_boolean_t *data, isc_boolean_t *optout,
938 isc_boolean_t *unknown, isc_boolean_t *setclosest,
939 isc_boolean_t *setnearest, dns_name_t *closest,
942 char namebuf[DNS_NAME_FORMATSIZE];
943 dns_fixedname_t fzone;
944 dns_fixedname_t qfixed;
945 dns_label_t hashlabel;
948 dns_rdata_nsec3_t nsec3;
949 dns_rdata_t rdata = DNS_RDATA_INIT;
952 isc_boolean_t atparent;
957 isc_result_t answer = ISC_R_IGNORE;
959 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
960 unsigned char owner[NSEC3_MAX_HASH_LENGTH];
962 unsigned int qlabels;
963 unsigned int zlabels;
965 REQUIRE((exists == NULL && data == NULL) ||
966 (exists != NULL && data != NULL));
967 REQUIRE(nsec3set != NULL && nsec3set->type == dns_rdatatype_nsec3);
968 REQUIRE((setclosest == NULL && closest == NULL) ||
969 (setclosest != NULL && closest != NULL));
970 REQUIRE((setnearest == NULL && nearest == NULL) ||
971 (setnearest != NULL && nearest != NULL));
973 result = dns_rdataset_first(nsec3set);
974 if (result != ISC_R_SUCCESS) {
975 validator_log(val, ISC_LOG_DEBUG(3),
976 "failure processing NSEC3 set");
980 dns_rdataset_current(nsec3set, &rdata);
982 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
983 if (result != ISC_R_SUCCESS)
986 validator_log(val, ISC_LOG_DEBUG(3), "looking for relevant NSEC3");
988 dns_fixedname_init(&fzone);
989 zone = dns_fixedname_name(&fzone);
990 zlabels = dns_name_countlabels(nsec3name);
993 * NSEC3 records must have two or more labels to be valid.
996 return (ISC_R_IGNORE);
999 * Strip off the NSEC3 hash to get the zone.
1002 dns_name_split(nsec3name, zlabels, NULL, zone);
1005 * If not below the zone name we can ignore this record.
1007 if (!dns_name_issubdomain(name, zone))
1008 return (ISC_R_IGNORE);
1011 * Is this zone the same or deeper than the current zone?
1013 if (dns_name_countlabels(zonename) == 0 ||
1014 dns_name_issubdomain(zone, zonename))
1015 dns_name_copy(zone, zonename, NULL);
1017 if (!dns_name_equal(zone, zonename))
1018 return (ISC_R_IGNORE);
1021 * Are we only looking for the most enclosing zone?
1023 if (exists == NULL || data == NULL)
1024 return (ISC_R_SUCCESS);
1027 * Only set unknown once we are sure that this NSEC3 is from
1028 * the deepest covering zone.
1030 if (!dns_nsec3_supportedhash(nsec3.hash)) {
1031 if (unknown != NULL)
1032 *unknown = ISC_TRUE;
1033 return (ISC_R_IGNORE);
1037 * Recover the hash from the first label.
1039 dns_name_getlabel(nsec3name, 0, &hashlabel);
1040 isc_region_consume(&hashlabel, 1);
1041 isc_buffer_init(&buffer, owner, sizeof(owner));
1042 result = isc_base32hex_decoderegion(&hashlabel, &buffer);
1043 if (result != ISC_R_SUCCESS)
1047 * The hash lengths should match. If not ignore the record.
1049 if (isc_buffer_usedlength(&buffer) != nsec3.next_length)
1050 return (ISC_R_IGNORE);
1053 * Work out what this NSEC3 covers.
1054 * Inside (<0) or outside (>=0).
1056 scope = memcmp(owner, nsec3.next, nsec3.next_length);
1059 * Prepare to compute all the hashes.
1061 dns_fixedname_init(&qfixed);
1062 qname = dns_fixedname_name(&qfixed);
1063 dns_name_downcase(name, qname, NULL);
1064 qlabels = dns_name_countlabels(qname);
1067 while (qlabels >= zlabels) {
1068 length = isc_iterated_hash(hash, nsec3.hash, nsec3.iterations,
1069 nsec3.salt, nsec3.salt_length,
1070 qname->ndata, qname->length);
1072 * The computed hash length should match.
1074 if (length != nsec3.next_length) {
1075 validator_log(val, ISC_LOG_DEBUG(3),
1076 "ignoring NSEC bad length %u vs %u",
1077 length, nsec3.next_length);
1078 return (ISC_R_IGNORE);
1081 order = memcmp(hash, owner, length);
1082 if (first && order == 0) {
1084 * The hashes are the same.
1086 atparent = dns_rdatatype_atparent(val->event->type);
1087 ns = dns_nsec3_typepresent(&rdata, dns_rdatatype_ns);
1088 soa = dns_nsec3_typepresent(&rdata, dns_rdatatype_soa);
1092 * This NSEC record is from somewhere
1093 * higher in the DNS, and at the
1094 * parent of a delegation. It can not
1095 * be legitimately used here.
1097 validator_log(val, ISC_LOG_DEBUG(3),
1098 "ignoring parent NSEC3");
1099 return (ISC_R_IGNORE);
1101 } else if (atparent && ns && soa) {
1103 * This NSEC record is from the child.
1104 * It can not be legitimately used here.
1106 validator_log(val, ISC_LOG_DEBUG(3),
1107 "ignoring child NSEC3");
1108 return (ISC_R_IGNORE);
1110 if (val->event->type == dns_rdatatype_cname ||
1111 val->event->type == dns_rdatatype_nxt ||
1112 val->event->type == dns_rdatatype_nsec ||
1113 val->event->type == dns_rdatatype_key ||
1114 !dns_nsec3_typepresent(&rdata, dns_rdatatype_cname)) {
1116 *data = dns_nsec3_typepresent(&rdata,
1118 validator_log(val, ISC_LOG_DEBUG(3),
1119 "NSEC3 proves name exists (owner) "
1121 return (ISC_R_SUCCESS);
1123 validator_log(val, ISC_LOG_DEBUG(3),
1124 "NSEC3 proves CNAME exists");
1125 return (ISC_R_IGNORE);
1129 dns_nsec3_typepresent(&rdata, dns_rdatatype_ns) &&
1130 !dns_nsec3_typepresent(&rdata, dns_rdatatype_soa))
1133 * This NSEC3 record is from somewhere higher in
1134 * the DNS, and at the parent of a delegation.
1135 * It can not be legitimately used here.
1137 validator_log(val, ISC_LOG_DEBUG(3),
1138 "ignoring parent NSEC3");
1139 return (ISC_R_IGNORE);
1143 * Potential closest encloser.
1146 if (closest != NULL &&
1147 (dns_name_countlabels(closest) == 0 ||
1148 dns_name_issubdomain(qname, closest)) &&
1149 !dns_nsec3_typepresent(&rdata, dns_rdatatype_ds) &&
1150 !dns_nsec3_typepresent(&rdata, dns_rdatatype_dname) &&
1151 (dns_nsec3_typepresent(&rdata, dns_rdatatype_soa) ||
1152 !dns_nsec3_typepresent(&rdata, dns_rdatatype_ns)))
1155 dns_name_format(qname, namebuf,
1157 validator_log(val, ISC_LOG_DEBUG(3),
1158 "NSEC3 indicates potential "
1159 "closest encloser: '%s'",
1161 dns_name_copy(qname, closest, NULL);
1162 *setclosest = ISC_TRUE;
1164 dns_name_format(qname, namebuf, sizeof(namebuf));
1165 validator_log(val, ISC_LOG_DEBUG(3),
1166 "NSEC3 at super-domain %s", namebuf);
1171 * Find if the name does not exist.
1173 * We continue as we need to find the name closest to the
1174 * closest encloser that doesn't exist.
1176 * We also need to continue to ensure that we are not
1177 * proving the non-existence of a record in a sub-zone.
1178 * If that would be the case we will return ISC_R_IGNORE
1181 if ((scope < 0 && order > 0 &&
1182 memcmp(hash, nsec3.next, length) < 0) ||
1183 (scope >= 0 && (order > 0 ||
1184 memcmp(hash, nsec3.next, length) < 0)))
1186 char namebuf[DNS_NAME_FORMATSIZE];
1188 dns_name_format(qname, namebuf, sizeof(namebuf));
1189 validator_log(val, ISC_LOG_DEBUG(3), "NSEC3 proves "
1190 "name does not exist: '%s'", namebuf);
1191 if (nearest != NULL &&
1192 (dns_name_countlabels(nearest) == 0 ||
1193 dns_name_issubdomain(nearest, qname))) {
1194 dns_name_copy(qname, nearest, NULL);
1195 *setnearest = ISC_TRUE;
1198 *exists = ISC_FALSE;
1200 if (optout != NULL) {
1201 if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0)
1202 validator_log(val, ISC_LOG_DEBUG(3),
1203 "NSEC3 indicates optout");
1205 ISC_TF(nsec3.flags & DNS_NSEC3FLAG_OPTOUT);
1207 answer = ISC_R_SUCCESS;
1212 dns_name_split(qname, qlabels, NULL, qname);
1219 * Callback for when NSEC records have been validated.
1221 * Looks for NOQNAME, NODATA and OPTOUT proofs.
1223 * Resumes nsecvalidate.
1226 authvalidated(isc_task_t *task, isc_event_t *event) {
1227 dns_validatorevent_t *devent;
1228 dns_validator_t *val;
1229 dns_rdataset_t *rdataset;
1230 dns_rdataset_t *sigrdataset;
1231 isc_boolean_t want_destroy;
1232 isc_result_t result;
1233 isc_boolean_t exists, data;
1236 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
1238 devent = (dns_validatorevent_t *)event;
1239 rdataset = devent->rdataset;
1240 sigrdataset = devent->sigrdataset;
1241 val = devent->ev_arg;
1242 result = devent->result;
1243 dns_validator_destroy(&val->subvalidator);
1245 INSIST(val->event != NULL);
1247 validator_log(val, ISC_LOG_DEBUG(3), "in authvalidated");
1249 if (CANCELED(val)) {
1250 validator_done(val, ISC_R_CANCELED);
1251 } else if (result != ISC_R_SUCCESS) {
1252 validator_log(val, ISC_LOG_DEBUG(3),
1253 "authvalidated: got %s",
1254 isc_result_totext(result));
1255 if (result == DNS_R_BROKENCHAIN)
1257 if (result == ISC_R_CANCELED)
1258 validator_done(val, result);
1260 result = nsecvalidate(val, ISC_TRUE);
1261 if (result != DNS_R_WAIT)
1262 validator_done(val, result);
1265 dns_name_t **proofs = val->event->proofs;
1266 dns_name_t *wild = dns_fixedname_name(&val->wild);
1268 if (rdataset->trust == dns_trust_secure)
1269 val->seensig = ISC_TRUE;
1271 if (rdataset->type == dns_rdatatype_nsec &&
1272 rdataset->trust == dns_trust_secure &&
1273 (NEEDNODATA(val) || NEEDNOQNAME(val)) &&
1274 !FOUNDNODATA(val) && !FOUNDNOQNAME(val) &&
1275 nsecnoexistnodata(val, val->event->name, devent->name,
1276 rdataset, &exists, &data, wild)
1279 if (exists && !data) {
1280 val->attributes |= VALATTR_FOUNDNODATA;
1281 if (NEEDNODATA(val))
1282 proofs[DNS_VALIDATOR_NODATAPROOF] =
1286 val->attributes |= VALATTR_FOUNDNOQNAME;
1287 val->attributes |= VALATTR_FOUNDCLOSEST;
1289 * The NSEC noqname proof also contains
1290 * the closest encloser.
1293 if (NEEDNOQNAME(val))
1294 proofs[DNS_VALIDATOR_NOQNAMEPROOF] =
1299 result = nsecvalidate(val, ISC_TRUE);
1300 if (result != DNS_R_WAIT)
1301 validator_done(val, result);
1303 want_destroy = exit_check(val);
1309 * Free stuff from the event.
1311 isc_event_free(&event);
1315 * Looks for the requested name and type in the view (zones and cache).
1317 * When looking for a DLV record also checks to make sure the NSEC record
1318 * returns covers the query name as part of aggressive negative caching.
1322 * \li ISC_R_NOTFOUND
1323 * \li DNS_R_NCACHENXDOMAIN
1324 * \li DNS_R_NCACHENXRRSET
1326 * \li DNS_R_NXDOMAIN
1327 * \li DNS_R_BROKENCHAIN
1329 static inline isc_result_t
1330 view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
1331 dns_fixedname_t fixedname;
1332 dns_name_t *foundname;
1333 dns_rdata_nsec_t nsec;
1334 dns_rdata_t rdata = DNS_RDATA_INIT;
1335 isc_result_t result;
1336 unsigned int options;
1338 char buf1[DNS_NAME_FORMATSIZE];
1339 char buf2[DNS_NAME_FORMATSIZE];
1340 char buf3[DNS_NAME_FORMATSIZE];
1341 char namebuf[DNS_NAME_FORMATSIZE];
1342 char typebuf[DNS_RDATATYPE_FORMATSIZE];
1344 if (dns_rdataset_isassociated(&val->frdataset))
1345 dns_rdataset_disassociate(&val->frdataset);
1346 if (dns_rdataset_isassociated(&val->fsigrdataset))
1347 dns_rdataset_disassociate(&val->fsigrdataset);
1349 if (val->view->zonetable == NULL)
1350 return (ISC_R_CANCELED);
1352 if (isc_time_now(&now) == ISC_R_SUCCESS &&
1353 dns_resolver_getbadcache(val->view->resolver, name, type, &now)) {
1355 dns_name_format(name, namebuf, sizeof(namebuf));
1356 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
1357 validator_log(val, ISC_LOG_INFO, "bad cache hit (%s/%s)",
1359 return (DNS_R_BROKENCHAIN);
1362 options = DNS_DBFIND_PENDINGOK;
1363 if (type == dns_rdatatype_dlv)
1364 options |= DNS_DBFIND_COVERINGNSEC;
1365 dns_fixedname_init(&fixedname);
1366 foundname = dns_fixedname_name(&fixedname);
1367 result = dns_view_find(val->view, name, type, 0, options,
1368 ISC_FALSE, NULL, NULL, foundname,
1369 &val->frdataset, &val->fsigrdataset);
1371 if (result == DNS_R_NXDOMAIN) {
1372 if (dns_rdataset_isassociated(&val->frdataset))
1373 dns_rdataset_disassociate(&val->frdataset);
1374 if (dns_rdataset_isassociated(&val->fsigrdataset))
1375 dns_rdataset_disassociate(&val->fsigrdataset);
1376 } else if (result == DNS_R_COVERINGNSEC) {
1377 validator_log(val, ISC_LOG_DEBUG(3), "DNS_R_COVERINGNSEC");
1379 * Check if the returned NSEC covers the name.
1381 INSIST(type == dns_rdatatype_dlv);
1382 if (val->frdataset.trust != dns_trust_secure) {
1383 validator_log(val, ISC_LOG_DEBUG(3),
1384 "covering nsec: trust %s",
1385 dns_trust_totext(val->frdataset.trust));
1388 result = dns_rdataset_first(&val->frdataset);
1389 if (result != ISC_R_SUCCESS)
1391 dns_rdataset_current(&val->frdataset, &rdata);
1392 if (dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
1393 !dns_nsec_typepresent(&rdata, dns_rdatatype_soa)) {
1394 /* Parent NSEC record. */
1395 if (dns_name_issubdomain(name, foundname)) {
1396 validator_log(val, ISC_LOG_DEBUG(3),
1397 "covering nsec: for parent");
1401 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
1402 if (result != ISC_R_SUCCESS)
1404 if (dns_name_compare(foundname, &nsec.next) >= 0) {
1405 /* End of zone chain. */
1406 if (!dns_name_issubdomain(name, &nsec.next)) {
1408 * XXXMPA We could look for a parent NSEC
1409 * at nsec.next and if found retest with
1412 dns_rdata_freestruct(&nsec);
1413 validator_log(val, ISC_LOG_DEBUG(3),
1414 "covering nsec: not in zone");
1417 } else if (dns_name_compare(name, &nsec.next) >= 0) {
1419 * XXXMPA We could check if this NSEC is at a zone
1420 * apex and if the qname is not below it and look for
1421 * a parent NSEC with the same name. This requires
1422 * that we can cache both NSEC records which we
1423 * currently don't support.
1425 dns_rdata_freestruct(&nsec);
1426 validator_log(val, ISC_LOG_DEBUG(3),
1427 "covering nsec: not in range");
1430 if (isc_log_wouldlog(dns_lctx,ISC_LOG_DEBUG(3))) {
1431 dns_name_format(name, buf1, sizeof buf1);
1432 dns_name_format(foundname, buf2, sizeof buf2);
1433 dns_name_format(&nsec.next, buf3, sizeof buf3);
1434 validator_log(val, ISC_LOG_DEBUG(3),
1435 "covering nsec found: '%s' '%s' '%s'",
1438 if (dns_rdataset_isassociated(&val->frdataset))
1439 dns_rdataset_disassociate(&val->frdataset);
1440 if (dns_rdataset_isassociated(&val->fsigrdataset))
1441 dns_rdataset_disassociate(&val->fsigrdataset);
1442 dns_rdata_freestruct(&nsec);
1443 result = DNS_R_NCACHENXDOMAIN;
1444 } else if (result != ISC_R_SUCCESS &&
1445 result != DNS_R_NCACHENXDOMAIN &&
1446 result != DNS_R_NCACHENXRRSET &&
1447 result != DNS_R_EMPTYNAME &&
1448 result != DNS_R_NXRRSET &&
1449 result != ISC_R_NOTFOUND) {
1455 if (dns_rdataset_isassociated(&val->frdataset))
1456 dns_rdataset_disassociate(&val->frdataset);
1457 if (dns_rdataset_isassociated(&val->fsigrdataset))
1458 dns_rdataset_disassociate(&val->fsigrdataset);
1459 return (ISC_R_NOTFOUND);
1463 * Checks to make sure we are not going to loop. As we use a SHARED fetch
1464 * the validation process will stall if looping was to occur.
1466 static inline isc_boolean_t
1467 check_deadlock(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
1468 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
1470 dns_validator_t *parent;
1472 for (parent = val; parent != NULL; parent = parent->parent) {
1473 if (parent->event != NULL &&
1474 parent->event->type == type &&
1475 dns_name_equal(parent->event->name, name) &&
1477 * As NSEC3 records are meta data you sometimes
1478 * need to prove a NSEC3 record which says that
1479 * itself doesn't exist.
1481 (parent->event->type != dns_rdatatype_nsec3 ||
1482 rdataset == NULL || sigrdataset == NULL ||
1483 parent->event->message == NULL ||
1484 parent->event->rdataset != NULL ||
1485 parent->event->sigrdataset != NULL))
1487 validator_log(val, ISC_LOG_DEBUG(3),
1488 "continuing validation would lead to "
1489 "deadlock: aborting validation");
1497 * Start a fetch for the requested name and type.
1499 static inline isc_result_t
1500 create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
1501 isc_taskaction_t callback, const char *caller)
1503 if (dns_rdataset_isassociated(&val->frdataset))
1504 dns_rdataset_disassociate(&val->frdataset);
1505 if (dns_rdataset_isassociated(&val->fsigrdataset))
1506 dns_rdataset_disassociate(&val->fsigrdataset);
1508 if (check_deadlock(val, name, type, NULL, NULL))
1509 return (DNS_R_NOVALIDSIG);
1511 validator_logcreate(val, name, type, caller, "fetch");
1512 return (dns_resolver_createfetch(val->view->resolver, name, type,
1513 NULL, NULL, NULL, 0,
1514 val->event->ev_sender,
1522 * Start a subvalidation process.
1524 static inline isc_result_t
1525 create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
1526 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
1527 isc_taskaction_t action, const char *caller)
1529 isc_result_t result;
1531 if (check_deadlock(val, name, type, rdataset, sigrdataset))
1532 return (DNS_R_NOVALIDSIG);
1534 validator_logcreate(val, name, type, caller, "validator");
1535 result = dns_validator_create(val->view, name, type,
1536 rdataset, sigrdataset, NULL, 0,
1537 val->task, action, val,
1538 &val->subvalidator);
1539 if (result == ISC_R_SUCCESS) {
1540 val->subvalidator->parent = val;
1541 val->subvalidator->depth = val->depth + 1;
1547 * Try to find a key that could have signed 'siginfo' among those
1548 * in 'rdataset'. If found, build a dst_key_t for it and point
1551 * If val->key is non-NULL, this returns the next matching key.
1554 get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
1555 dns_rdataset_t *rdataset)
1557 isc_result_t result;
1559 dns_rdata_t rdata = DNS_RDATA_INIT;
1560 dst_key_t *oldkey = val->key;
1561 isc_boolean_t foundold;
1564 foundold = ISC_TRUE;
1566 foundold = ISC_FALSE;
1570 result = dns_rdataset_first(rdataset);
1571 if (result != ISC_R_SUCCESS)
1574 dns_rdataset_current(rdataset, &rdata);
1576 isc_buffer_init(&b, rdata.data, rdata.length);
1577 isc_buffer_add(&b, rdata.length);
1578 INSIST(val->key == NULL);
1579 result = dst_key_fromdns(&siginfo->signer, rdata.rdclass, &b,
1580 val->view->mctx, &val->key);
1581 if (result != ISC_R_SUCCESS)
1583 if (siginfo->algorithm ==
1584 (dns_secalg_t)dst_key_alg(val->key) &&
1586 (dns_keytag_t)dst_key_id(val->key) &&
1587 dst_key_iszonekey(val->key))
1591 * This is the key we're looking for.
1593 return (ISC_R_SUCCESS);
1594 else if (dst_key_compare(oldkey, val->key) == ISC_TRUE)
1596 foundold = ISC_TRUE;
1597 dst_key_free(&oldkey);
1600 dst_key_free(&val->key);
1601 dns_rdata_reset(&rdata);
1602 result = dns_rdataset_next(rdataset);
1603 } while (result == ISC_R_SUCCESS);
1604 if (result == ISC_R_NOMORE)
1605 result = ISC_R_NOTFOUND;
1609 dst_key_free(&oldkey);
1615 * Get the key that generated this signature.
1618 get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
1619 isc_result_t result;
1620 unsigned int nlabels;
1622 dns_namereln_t namereln;
1625 * Is the signer name appropriate for this signature?
1627 * The signer name must be at the same level as the owner name
1628 * or closer to the DNS root.
1630 namereln = dns_name_fullcompare(val->event->name, &siginfo->signer,
1632 if (namereln != dns_namereln_subdomain &&
1633 namereln != dns_namereln_equal)
1634 return (DNS_R_CONTINUE);
1636 if (namereln == dns_namereln_equal) {
1638 * If this is a self-signed keyset, it must not be a zone key
1639 * (since get_key is not called from validatezonekey).
1641 if (val->event->rdataset->type == dns_rdatatype_dnskey)
1642 return (DNS_R_CONTINUE);
1645 * Records appearing in the parent zone at delegation
1646 * points cannot be self-signed.
1648 if (dns_rdatatype_atparent(val->event->rdataset->type))
1649 return (DNS_R_CONTINUE);
1652 * SOA and NS RRsets can only be signed by a key with
1655 if (val->event->rdataset->type == dns_rdatatype_soa ||
1656 val->event->rdataset->type == dns_rdatatype_ns) {
1657 const char *typename;
1659 if (val->event->rdataset->type == dns_rdatatype_soa)
1663 validator_log(val, ISC_LOG_DEBUG(3),
1664 "%s signer mismatch", typename);
1665 return (DNS_R_CONTINUE);
1670 * Do we know about this key?
1672 result = view_find(val, &siginfo->signer, dns_rdatatype_dnskey);
1673 if (result == ISC_R_SUCCESS) {
1675 * We have an rrset for the given keyname.
1677 val->keyset = &val->frdataset;
1678 if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
1679 DNS_TRUST_ANSWER(val->frdataset.trust)) &&
1680 dns_rdataset_isassociated(&val->fsigrdataset))
1683 * We know the key but haven't validated it yet or
1684 * we have a key of trust answer but a DS/DLV
1685 * record for the zone may have been added.
1687 result = create_validator(val, &siginfo->signer,
1688 dns_rdatatype_dnskey,
1693 if (result != ISC_R_SUCCESS)
1695 return (DNS_R_WAIT);
1696 } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
1698 * Having a pending key with no signature means that
1699 * something is broken.
1701 result = DNS_R_CONTINUE;
1702 } else if (val->frdataset.trust < dns_trust_secure) {
1704 * The key is legitimately insecure. There's no
1705 * point in even attempting verification.
1708 result = ISC_R_SUCCESS;
1711 * See if we've got the key used in the signature.
1713 validator_log(val, ISC_LOG_DEBUG(3),
1714 "keyset with trust %s",
1715 dns_trust_totext(val->frdataset.trust));
1716 result = get_dst_key(val, siginfo, val->keyset);
1717 if (result != ISC_R_SUCCESS) {
1719 * Either the key we're looking for is not
1720 * in the rrset, or something bad happened.
1723 result = DNS_R_CONTINUE;
1726 } else if (result == ISC_R_NOTFOUND) {
1728 * We don't know anything about this key.
1730 result = create_fetch(val, &siginfo->signer,
1731 dns_rdatatype_dnskey,
1732 fetch_callback_validator, "get_key");
1733 if (result != ISC_R_SUCCESS)
1735 return (DNS_R_WAIT);
1736 } else if (result == DNS_R_NCACHENXDOMAIN ||
1737 result == DNS_R_NCACHENXRRSET ||
1738 result == DNS_R_EMPTYNAME ||
1739 result == DNS_R_NXDOMAIN ||
1740 result == DNS_R_NXRRSET)
1743 * This key doesn't exist.
1745 result = DNS_R_CONTINUE;
1746 } else if (result == DNS_R_BROKENCHAIN)
1749 if (dns_rdataset_isassociated(&val->frdataset) &&
1750 val->keyset != &val->frdataset)
1751 dns_rdataset_disassociate(&val->frdataset);
1752 if (dns_rdataset_isassociated(&val->fsigrdataset))
1753 dns_rdataset_disassociate(&val->fsigrdataset);
1759 compute_keytag(dns_rdata_t *rdata, dns_rdata_dnskey_t *key) {
1762 dns_rdata_toregion(rdata, &r);
1763 return (dst_region_computeid(&r, key->algorithm));
1767 * Is this keyset self-signed?
1769 static isc_boolean_t
1770 isselfsigned(dns_validator_t *val) {
1771 dns_rdataset_t *rdataset, *sigrdataset;
1772 dns_rdata_t rdata = DNS_RDATA_INIT;
1773 dns_rdata_t sigrdata = DNS_RDATA_INIT;
1774 dns_rdata_dnskey_t key;
1775 dns_rdata_rrsig_t sig;
1776 dns_keytag_t keytag;
1777 isc_result_t result;
1779 rdataset = val->event->rdataset;
1780 sigrdataset = val->event->sigrdataset;
1782 INSIST(rdataset->type == dns_rdatatype_dnskey);
1784 for (result = dns_rdataset_first(rdataset);
1785 result == ISC_R_SUCCESS;
1786 result = dns_rdataset_next(rdataset))
1788 dns_rdata_reset(&rdata);
1789 dns_rdataset_current(rdataset, &rdata);
1790 result = dns_rdata_tostruct(&rdata, &key, NULL);
1791 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1792 keytag = compute_keytag(&rdata, &key);
1793 for (result = dns_rdataset_first(sigrdataset);
1794 result == ISC_R_SUCCESS;
1795 result = dns_rdataset_next(sigrdataset))
1797 dns_rdata_reset(&sigrdata);
1798 dns_rdataset_current(sigrdataset, &sigrdata);
1799 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
1800 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1802 if (sig.algorithm == key.algorithm &&
1803 sig.keyid == keytag)
1811 * Attempt to verify the rdataset using the given key and rdata (RRSIG).
1812 * The signature was good and from a wildcard record and the QNAME does
1813 * not match the wildcard we need to look for a NOQNAME proof.
1816 * \li ISC_R_SUCCESS if the verification succeeds.
1817 * \li Others if the verification fails.
1820 verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata,
1823 isc_result_t result;
1824 dns_fixedname_t fixed;
1825 isc_boolean_t ignore = ISC_FALSE;
1827 val->attributes |= VALATTR_TRIEDVERIFY;
1828 dns_fixedname_init(&fixed);
1830 result = dns_dnssec_verify2(val->event->name, val->event->rdataset,
1831 key, ignore, val->view->mctx, rdata,
1832 dns_fixedname_name(&fixed));
1833 if (result == DNS_R_SIGEXPIRED && val->view->acceptexpired) {
1837 if (ignore && (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD))
1838 validator_log(val, ISC_LOG_INFO,
1839 "accepted expired %sRRSIG (keyid=%u)",
1840 (result == DNS_R_FROMWILDCARD) ?
1841 "wildcard " : "", keyid);
1843 validator_log(val, ISC_LOG_DEBUG(3),
1844 "verify rdataset (keyid=%u): %s",
1845 keyid, isc_result_totext(result));
1846 if (result == DNS_R_FROMWILDCARD) {
1847 if (!dns_name_equal(val->event->name,
1848 dns_fixedname_name(&fixed)))
1849 val->attributes |= VALATTR_NEEDNOQNAME;
1850 result = ISC_R_SUCCESS;
1856 * Attempts positive response validation of a normal RRset.
1859 * \li ISC_R_SUCCESS Validation completed successfully
1860 * \li DNS_R_WAIT Validation has started but is waiting
1862 * \li Other return codes are possible and all indicate failure.
1865 validate(dns_validator_t *val, isc_boolean_t resume) {
1866 isc_result_t result;
1867 dns_validatorevent_t *event;
1868 dns_rdata_t rdata = DNS_RDATA_INIT;
1871 * Caller must be holding the validator lock.
1878 * We already have a sigrdataset.
1880 result = ISC_R_SUCCESS;
1881 validator_log(val, ISC_LOG_DEBUG(3), "resuming validate");
1883 result = dns_rdataset_first(event->sigrdataset);
1887 result == ISC_R_SUCCESS;
1888 result = dns_rdataset_next(event->sigrdataset))
1890 dns_rdata_reset(&rdata);
1891 dns_rdataset_current(event->sigrdataset, &rdata);
1892 if (val->siginfo == NULL) {
1893 val->siginfo = isc_mem_get(val->view->mctx,
1894 sizeof(*val->siginfo));
1895 if (val->siginfo == NULL)
1896 return (ISC_R_NOMEMORY);
1898 result = dns_rdata_tostruct(&rdata, val->siginfo, NULL);
1899 if (result != ISC_R_SUCCESS)
1903 * At this point we could check that the signature algorithm
1904 * was known and "sufficiently good".
1906 if (!dns_resolver_algorithm_supported(val->view->resolver,
1908 val->siginfo->algorithm)) {
1914 result = get_key(val, val->siginfo);
1915 if (result == DNS_R_CONTINUE)
1916 continue; /* Try the next SIG RR. */
1917 if (result != ISC_R_SUCCESS)
1922 * There isn't a secure DNSKEY for this signature so move
1923 * onto the next RRSIG.
1925 if (val->key == NULL) {
1931 result = verify(val, val->key, &rdata,
1932 val->siginfo->keyid);
1933 if (result == ISC_R_SUCCESS)
1935 if (val->keynode != NULL) {
1936 dns_keynode_t *nextnode = NULL;
1937 result = dns_keytable_findnextkeynode(
1941 dns_keytable_detachkeynode(val->keytable,
1943 val->keynode = nextnode;
1944 if (result != ISC_R_SUCCESS) {
1948 val->key = dns_keynode_key(val->keynode);
1950 if (get_dst_key(val, val->siginfo, val->keyset)
1955 if (result != ISC_R_SUCCESS)
1956 validator_log(val, ISC_LOG_DEBUG(3),
1957 "failed to verify rdataset");
1962 isc_stdtime_get(&now);
1963 ttl = ISC_MIN(event->rdataset->ttl,
1964 val->siginfo->timeexpire - now);
1965 if (val->keyset != NULL)
1966 ttl = ISC_MIN(ttl, val->keyset->ttl);
1967 event->rdataset->ttl = ttl;
1968 event->sigrdataset->ttl = ttl;
1971 if (val->keynode != NULL)
1972 dns_keytable_detachkeynode(val->keytable,
1975 if (val->key != NULL)
1976 dst_key_free(&val->key);
1977 if (val->keyset != NULL) {
1978 dns_rdataset_disassociate(val->keyset);
1983 if (NEEDNOQNAME(val)) {
1984 if (val->event->message == NULL) {
1985 validator_log(val, ISC_LOG_DEBUG(3),
1986 "no message available for noqname proof");
1987 return (DNS_R_NOVALIDSIG);
1989 validator_log(val, ISC_LOG_DEBUG(3),
1990 "looking for noqname proof");
1991 return (nsecvalidate(val, ISC_FALSE));
1992 } else if (result == ISC_R_SUCCESS) {
1994 validator_log(val, ISC_LOG_DEBUG(3),
1995 "marking as secure");
1998 validator_log(val, ISC_LOG_DEBUG(3),
1999 "verify failure: %s",
2000 isc_result_totext(result));
2004 if (result != ISC_R_NOMORE) {
2005 validator_log(val, ISC_LOG_DEBUG(3),
2006 "failed to iterate signatures: %s",
2007 isc_result_totext(result));
2011 validator_log(val, ISC_LOG_INFO, "no valid signature found");
2012 return (DNS_R_NOVALIDSIG);
2016 * Validate the DNSKEY RRset by looking for a DNSKEY that matches a
2017 * DLV record and that also verifies the DNSKEY RRset.
2020 dlv_validatezonekey(dns_validator_t *val) {
2021 dns_keytag_t keytag;
2022 dns_rdata_dlv_t dlv;
2023 dns_rdata_dnskey_t key;
2024 dns_rdata_rrsig_t sig;
2025 dns_rdata_t dlvrdata = DNS_RDATA_INIT;
2026 dns_rdata_t keyrdata = DNS_RDATA_INIT;
2027 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
2028 dns_rdata_t sigrdata = DNS_RDATA_INIT;
2029 dns_rdataset_t trdataset;
2031 isc_boolean_t supported_algorithm;
2032 isc_result_t result;
2033 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
2034 isc_uint8_t digest_type;
2036 validator_log(val, ISC_LOG_DEBUG(3), "dlv_validatezonekey");
2039 * Look through the DLV record and find the keys that can sign the
2040 * key set and the matching signature. For each such key, attempt
2043 supported_algorithm = ISC_FALSE;
2046 * If DNS_DSDIGEST_SHA256 is present we are required to prefer
2047 * it over DNS_DSDIGEST_SHA1. This in practice means that we
2048 * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
2051 digest_type = DNS_DSDIGEST_SHA1;
2052 for (result = dns_rdataset_first(&val->dlv);
2053 result == ISC_R_SUCCESS;
2054 result = dns_rdataset_next(&val->dlv)) {
2055 dns_rdata_reset(&dlvrdata);
2056 dns_rdataset_current(&val->dlv, &dlvrdata);
2057 result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
2058 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2060 if (!dns_resolver_algorithm_supported(val->view->resolver,
2065 if (dlv.digest_type == DNS_DSDIGEST_SHA256 &&
2066 dlv.length == ISC_SHA256_DIGESTLENGTH) {
2067 digest_type = DNS_DSDIGEST_SHA256;
2072 for (result = dns_rdataset_first(&val->dlv);
2073 result == ISC_R_SUCCESS;
2074 result = dns_rdataset_next(&val->dlv))
2076 dns_rdata_reset(&dlvrdata);
2077 dns_rdataset_current(&val->dlv, &dlvrdata);
2078 result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
2079 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2081 if (!dns_resolver_digest_supported(val->view->resolver,
2085 if (dlv.digest_type != digest_type)
2088 if (!dns_resolver_algorithm_supported(val->view->resolver,
2093 supported_algorithm = ISC_TRUE;
2095 dns_rdataset_init(&trdataset);
2096 dns_rdataset_clone(val->event->rdataset, &trdataset);
2098 for (result = dns_rdataset_first(&trdataset);
2099 result == ISC_R_SUCCESS;
2100 result = dns_rdataset_next(&trdataset))
2102 dns_rdata_reset(&keyrdata);
2103 dns_rdataset_current(&trdataset, &keyrdata);
2104 result = dns_rdata_tostruct(&keyrdata, &key, NULL);
2105 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2106 keytag = compute_keytag(&keyrdata, &key);
2107 if (dlv.key_tag != keytag ||
2108 dlv.algorithm != key.algorithm)
2110 dns_rdata_reset(&newdsrdata);
2111 result = dns_ds_buildrdata(val->event->name,
2112 &keyrdata, dlv.digest_type,
2113 dsbuf, &newdsrdata);
2114 if (result != ISC_R_SUCCESS) {
2115 validator_log(val, ISC_LOG_DEBUG(3),
2116 "dns_ds_buildrdata() -> %s",
2117 dns_result_totext(result));
2121 newdsrdata.type = dns_rdatatype_dlv;
2122 if (dns_rdata_compare(&dlvrdata, &newdsrdata) == 0)
2125 if (result != ISC_R_SUCCESS) {
2126 dns_rdataset_disassociate(&trdataset);
2127 validator_log(val, ISC_LOG_DEBUG(3),
2128 "no DNSKEY matching DLV");
2131 validator_log(val, ISC_LOG_DEBUG(3),
2132 "Found matching DLV record: checking for signature");
2134 for (result = dns_rdataset_first(val->event->sigrdataset);
2135 result == ISC_R_SUCCESS;
2136 result = dns_rdataset_next(val->event->sigrdataset))
2138 dns_rdata_reset(&sigrdata);
2139 dns_rdataset_current(val->event->sigrdataset,
2141 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
2142 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2143 if (dlv.key_tag != sig.keyid ||
2144 dlv.algorithm != sig.algorithm)
2147 result = dns_dnssec_keyfromrdata(val->event->name,
2151 if (result != ISC_R_SUCCESS)
2153 * This really shouldn't happen, but...
2157 result = verify(val, dstkey, &sigrdata, sig.keyid);
2158 dst_key_free(&dstkey);
2159 if (result == ISC_R_SUCCESS)
2162 dns_rdataset_disassociate(&trdataset);
2163 if (result == ISC_R_SUCCESS)
2165 validator_log(val, ISC_LOG_DEBUG(3),
2166 "no RRSIG matching DLV key");
2168 if (result == ISC_R_SUCCESS) {
2169 marksecure(val->event);
2170 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure");
2172 } else if (result == ISC_R_NOMORE && !supported_algorithm) {
2173 if (val->mustbesecure) {
2174 validator_log(val, ISC_LOG_WARNING,
2175 "must be secure failure");
2176 return (DNS_R_MUSTBESECURE);
2178 validator_log(val, ISC_LOG_DEBUG(3),
2179 "no supported algorithm/digest (dlv)");
2180 markanswer(val, "dlv_validatezonekey (2)");
2181 return (ISC_R_SUCCESS);
2183 return (DNS_R_NOVALIDSIG);
2187 * Attempts positive response validation of an RRset containing zone keys.
2190 * \li ISC_R_SUCCESS Validation completed successfully
2191 * \li DNS_R_WAIT Validation has started but is waiting
2193 * \li Other return codes are possible and all indicate failure.
2196 validatezonekey(dns_validator_t *val) {
2197 isc_result_t result;
2198 dns_validatorevent_t *event;
2199 dns_rdataset_t trdataset;
2200 dns_rdata_t dsrdata = DNS_RDATA_INIT;
2201 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
2202 dns_rdata_t keyrdata = DNS_RDATA_INIT;
2203 dns_rdata_t sigrdata = DNS_RDATA_INIT;
2204 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
2205 char namebuf[DNS_NAME_FORMATSIZE];
2206 dns_keytag_t keytag;
2208 dns_rdata_dnskey_t key;
2209 dns_rdata_rrsig_t sig;
2211 isc_boolean_t supported_algorithm;
2212 isc_boolean_t atsep = ISC_FALSE;
2213 isc_uint8_t digest_type;
2216 * Caller must be holding the validator lock.
2221 if (val->havedlvsep && val->dlv.trust >= dns_trust_secure &&
2222 dns_name_equal(event->name, dns_fixedname_name(&val->dlvsep)))
2223 return (dlv_validatezonekey(val));
2225 if (val->dsset == NULL) {
2228 * We have a dlv sep. Skip looking up the SEP from
2229 * {trusted,managed}-keys. If the dlv sep is for the
2230 * root then it will have been handled above so we don't
2231 * need to check whether val->event->name is "." prior to
2232 * looking up the DS.
2234 if (val->havedlvsep)
2238 * First, see if this key was signed by a trusted key.
2240 for (result = dns_rdataset_first(val->event->sigrdataset);
2241 result == ISC_R_SUCCESS;
2242 result = dns_rdataset_next(val->event->sigrdataset))
2244 dns_keynode_t *keynode = NULL;
2245 dns_fixedname_t fixed;
2248 dns_fixedname_init(&fixed);
2249 found = dns_fixedname_name(&fixed);
2250 dns_rdata_reset(&sigrdata);
2251 dns_rdataset_current(val->event->sigrdataset,
2253 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
2254 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2256 if (!dns_name_equal(val->event->name, &sig.signer))
2259 result = dns_keytable_findkeynode(val->keytable,
2264 if (result == ISC_R_NOTFOUND &&
2265 dns_keytable_finddeepestmatch(val->keytable,
2266 val->event->name, found) != ISC_R_SUCCESS) {
2267 if (val->mustbesecure) {
2268 validator_log(val, ISC_LOG_WARNING,
2269 "must be secure failure, "
2270 "not beneath secure root");
2271 return (DNS_R_MUSTBESECURE);
2273 validator_log(val, ISC_LOG_DEBUG(3),
2274 "not beneath secure root");
2275 if (val->view->dlv == NULL) {
2276 markanswer(val, "validatezonekey (1)");
2277 return (ISC_R_SUCCESS);
2279 return (startfinddlvsep(val, dns_rootname));
2281 if (result == DNS_R_PARTIALMATCH ||
2282 result == ISC_R_SUCCESS)
2284 while (result == ISC_R_SUCCESS) {
2285 dns_keynode_t *nextnode = NULL;
2286 dstkey = dns_keynode_key(keynode);
2287 result = verify(val, dstkey, &sigrdata,
2289 if (result == ISC_R_SUCCESS) {
2290 dns_keytable_detachkeynode(val->keytable,
2294 result = dns_keytable_findnextkeynode(
2298 dns_keytable_detachkeynode(val->keytable,
2302 if (result == ISC_R_SUCCESS) {
2304 validator_log(val, ISC_LOG_DEBUG(3),
2305 "signed by trusted key; "
2306 "marking as secure");
2313 * We have not found a key to verify this DNSKEY
2314 * RRset. As this is a SEP we have to assume that
2315 * the RRset is invalid.
2317 dns_name_format(val->event->name, namebuf,
2319 validator_log(val, ISC_LOG_NOTICE,
2320 "unable to find a DNSKEY which verifies "
2321 "the DNSKEY RRset and also matches one "
2322 "of specified trusted-keys for '%s'",
2324 validator_log(val, ISC_LOG_NOTICE,
2325 "please check the 'trusted-keys' for "
2326 "'%s' in named.conf.", namebuf);
2327 return (DNS_R_NOVALIDKEY);
2331 * If this is the root name and there was no trusted key,
2332 * give up, since there's no DS at the root.
2334 if (dns_name_equal(event->name, dns_rootname)) {
2335 if ((val->attributes & VALATTR_TRIEDVERIFY) != 0) {
2336 validator_log(val, ISC_LOG_DEBUG(3),
2337 "root key failed to validate");
2338 return (DNS_R_NOVALIDSIG);
2340 validator_log(val, ISC_LOG_DEBUG(3),
2341 "no trusted root key");
2342 return (DNS_R_NOVALIDDS);
2347 * Otherwise, try to find the DS record.
2349 result = view_find(val, val->event->name, dns_rdatatype_ds);
2350 if (result == ISC_R_SUCCESS) {
2352 * We have DS records.
2354 val->dsset = &val->frdataset;
2355 if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
2356 DNS_TRUST_ANSWER(val->frdataset.trust)) &&
2357 dns_rdataset_isassociated(&val->fsigrdataset))
2359 result = create_validator(val,
2366 if (result != ISC_R_SUCCESS)
2368 return (DNS_R_WAIT);
2369 } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
2371 * There should never be an unsigned DS.
2373 dns_rdataset_disassociate(&val->frdataset);
2374 validator_log(val, ISC_LOG_DEBUG(2),
2375 "unsigned DS record");
2376 return (DNS_R_NOVALIDSIG);
2378 result = ISC_R_SUCCESS;
2379 } else if (result == ISC_R_NOTFOUND) {
2381 * We don't have the DS. Find it.
2383 result = create_fetch(val, val->event->name,
2384 dns_rdatatype_ds, dsfetched,
2386 if (result != ISC_R_SUCCESS)
2388 return (DNS_R_WAIT);
2389 } else if (result == DNS_R_NCACHENXDOMAIN ||
2390 result == DNS_R_NCACHENXRRSET ||
2391 result == DNS_R_EMPTYNAME ||
2392 result == DNS_R_NXDOMAIN ||
2393 result == DNS_R_NXRRSET)
2396 * The DS does not exist.
2398 if (dns_rdataset_isassociated(&val->frdataset))
2399 dns_rdataset_disassociate(&val->frdataset);
2400 if (dns_rdataset_isassociated(&val->fsigrdataset))
2401 dns_rdataset_disassociate(&val->fsigrdataset);
2402 validator_log(val, ISC_LOG_DEBUG(2), "no DS record");
2403 return (DNS_R_NOVALIDSIG);
2404 } else if (result == DNS_R_BROKENCHAIN)
2411 INSIST(val->dsset != NULL);
2413 if (val->dsset->trust < dns_trust_secure) {
2414 if (val->mustbesecure) {
2415 validator_log(val, ISC_LOG_WARNING,
2416 "must be secure failure");
2417 return (DNS_R_MUSTBESECURE);
2419 if (val->view->dlv == NULL || DLVTRIED(val)) {
2420 markanswer(val, "validatezonekey (2)");
2421 return (ISC_R_SUCCESS);
2423 return (startfinddlvsep(val, val->event->name));
2427 * Look through the DS record and find the keys that can sign the
2428 * key set and the matching signature. For each such key, attempt
2432 supported_algorithm = ISC_FALSE;
2435 * If DNS_DSDIGEST_SHA256 is present we are required to prefer
2436 * it over DNS_DSDIGEST_SHA1. This in practice means that we
2437 * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
2440 digest_type = DNS_DSDIGEST_SHA1;
2441 for (result = dns_rdataset_first(val->dsset);
2442 result == ISC_R_SUCCESS;
2443 result = dns_rdataset_next(val->dsset)) {
2444 dns_rdata_reset(&dsrdata);
2445 dns_rdataset_current(val->dsset, &dsrdata);
2446 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
2447 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2449 if (!dns_resolver_algorithm_supported(val->view->resolver,
2454 if (ds.digest_type == DNS_DSDIGEST_SHA256 &&
2455 ds.length == ISC_SHA256_DIGESTLENGTH) {
2456 digest_type = DNS_DSDIGEST_SHA256;
2461 for (result = dns_rdataset_first(val->dsset);
2462 result == ISC_R_SUCCESS;
2463 result = dns_rdataset_next(val->dsset))
2465 dns_rdata_reset(&dsrdata);
2466 dns_rdataset_current(val->dsset, &dsrdata);
2467 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
2468 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2470 if (!dns_resolver_digest_supported(val->view->resolver,
2474 if (ds.digest_type != digest_type)
2477 if (!dns_resolver_algorithm_supported(val->view->resolver,
2482 supported_algorithm = ISC_TRUE;
2484 dns_rdataset_init(&trdataset);
2485 dns_rdataset_clone(val->event->rdataset, &trdataset);
2488 * Look for the KEY that matches the DS record.
2490 for (result = dns_rdataset_first(&trdataset);
2491 result == ISC_R_SUCCESS;
2492 result = dns_rdataset_next(&trdataset))
2494 dns_rdata_reset(&keyrdata);
2495 dns_rdataset_current(&trdataset, &keyrdata);
2496 result = dns_rdata_tostruct(&keyrdata, &key, NULL);
2497 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2498 keytag = compute_keytag(&keyrdata, &key);
2499 if (ds.key_tag != keytag ||
2500 ds.algorithm != key.algorithm)
2502 dns_rdata_reset(&newdsrdata);
2503 result = dns_ds_buildrdata(val->event->name,
2504 &keyrdata, ds.digest_type,
2505 dsbuf, &newdsrdata);
2506 if (result != ISC_R_SUCCESS)
2508 if (dns_rdata_compare(&dsrdata, &newdsrdata) == 0)
2511 if (result != ISC_R_SUCCESS) {
2512 dns_rdataset_disassociate(&trdataset);
2513 validator_log(val, ISC_LOG_DEBUG(3),
2514 "no DNSKEY matching DS");
2518 for (result = dns_rdataset_first(val->event->sigrdataset);
2519 result == ISC_R_SUCCESS;
2520 result = dns_rdataset_next(val->event->sigrdataset))
2522 dns_rdata_reset(&sigrdata);
2523 dns_rdataset_current(val->event->sigrdataset,
2525 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
2526 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2527 if (ds.key_tag != sig.keyid ||
2528 ds.algorithm != sig.algorithm)
2530 if (!dns_name_equal(val->event->name, &sig.signer)) {
2531 validator_log(val, ISC_LOG_DEBUG(3),
2532 "DNSKEY signer mismatch");
2536 result = dns_dnssec_keyfromrdata(val->event->name,
2540 if (result != ISC_R_SUCCESS)
2542 * This really shouldn't happen, but...
2545 result = verify(val, dstkey, &sigrdata, sig.keyid);
2546 dst_key_free(&dstkey);
2547 if (result == ISC_R_SUCCESS)
2550 dns_rdataset_disassociate(&trdataset);
2551 if (result == ISC_R_SUCCESS)
2553 validator_log(val, ISC_LOG_DEBUG(3),
2554 "no RRSIG matching DS key");
2556 if (result == ISC_R_SUCCESS) {
2558 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure");
2560 } else if (result == ISC_R_NOMORE && !supported_algorithm) {
2561 if (val->mustbesecure) {
2562 validator_log(val, ISC_LOG_WARNING,
2563 "must be secure failure");
2564 return (DNS_R_MUSTBESECURE);
2566 validator_log(val, ISC_LOG_DEBUG(3),
2567 "no supported algorithm/digest (DS)");
2568 markanswer(val, "validatezonekey (3)");
2569 return (ISC_R_SUCCESS);
2571 return (DNS_R_NOVALIDSIG);
2575 * Starts a positive response validation.
2578 * \li ISC_R_SUCCESS Validation completed successfully
2579 * \li DNS_R_WAIT Validation has started but is waiting
2581 * \li Other return codes are possible and all indicate failure.
2584 start_positive_validation(dns_validator_t *val) {
2586 * If this is not a key, go straight into validate().
2588 if (val->event->type != dns_rdatatype_dnskey || !isselfsigned(val))
2589 return (validate(val, ISC_FALSE));
2591 return (validatezonekey(val));
2595 * val_rdataset_first and val_rdataset_next provide iteration methods
2596 * that hide whether we are iterating across a message or a negative
2600 val_rdataset_first(dns_validator_t *val, dns_name_t **namep,
2601 dns_rdataset_t **rdatasetp)
2603 dns_message_t *message = val->event->message;
2604 isc_result_t result;
2606 REQUIRE(rdatasetp != NULL);
2607 REQUIRE(namep != NULL);
2608 if (message == NULL) {
2609 REQUIRE(*rdatasetp != NULL);
2610 REQUIRE(*namep != NULL);
2612 REQUIRE(*rdatasetp == NULL);
2613 REQUIRE(*namep == NULL);
2616 if (message != NULL) {
2617 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2618 if (result != ISC_R_SUCCESS)
2620 dns_message_currentname(message, DNS_SECTION_AUTHORITY, namep);
2621 *rdatasetp = ISC_LIST_HEAD((*namep)->list);
2622 INSIST(*rdatasetp != NULL);
2624 result = dns_rdataset_first(val->event->rdataset);
2625 if (result == ISC_R_SUCCESS)
2626 dns_ncache_current(val->event->rdataset, *namep,
2633 val_rdataset_next(dns_validator_t *val, dns_name_t **namep,
2634 dns_rdataset_t **rdatasetp)
2636 dns_message_t *message = val->event->message;
2637 isc_result_t result = ISC_R_SUCCESS;
2639 REQUIRE(rdatasetp != NULL && *rdatasetp != NULL);
2640 REQUIRE(namep != NULL && *namep != NULL);
2642 if (message != NULL) {
2643 dns_rdataset_t *rdataset = *rdatasetp;
2644 rdataset = ISC_LIST_NEXT(rdataset, link);
2645 if (rdataset == NULL) {
2647 result = dns_message_nextname(message,
2648 DNS_SECTION_AUTHORITY);
2649 if (result == ISC_R_SUCCESS) {
2650 dns_message_currentname(message,
2651 DNS_SECTION_AUTHORITY,
2653 rdataset = ISC_LIST_HEAD((*namep)->list);
2654 INSIST(rdataset != NULL);
2657 *rdatasetp = rdataset;
2659 dns_rdataset_disassociate(*rdatasetp);
2660 result = dns_rdataset_next(val->event->rdataset);
2661 if (result == ISC_R_SUCCESS)
2662 dns_ncache_current(val->event->rdataset, *namep,
2669 * Look for NODATA at the wildcard and NOWILDCARD proofs in the
2670 * previously validated NSEC records. As these proofs are mutually
2671 * exclusive we stop when one is found.
2677 checkwildcard(dns_validator_t *val, dns_rdatatype_t type, dns_name_t *zonename)
2679 dns_name_t *name, *wild, tname;
2680 isc_result_t result;
2681 isc_boolean_t exists, data;
2682 char namebuf[DNS_NAME_FORMATSIZE];
2683 dns_rdataset_t *rdataset, trdataset;
2685 dns_name_init(&tname, NULL);
2686 dns_rdataset_init(&trdataset);
2687 wild = dns_fixedname_name(&val->wild);
2689 if (dns_name_countlabels(wild) == 0) {
2690 validator_log(val, ISC_LOG_DEBUG(3),
2691 "in checkwildcard: no wildcard to check");
2692 return (ISC_R_SUCCESS);
2695 dns_name_format(wild, namebuf, sizeof(namebuf));
2696 validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf);
2698 if (val->event->message == NULL) {
2700 rdataset = &trdataset;
2706 for (result = val_rdataset_first(val, &name, &rdataset);
2707 result == ISC_R_SUCCESS;
2708 result = val_rdataset_next(val, &name, &rdataset))
2710 if (rdataset->type != type ||
2711 rdataset->trust != dns_trust_secure)
2714 if (rdataset->type == dns_rdatatype_nsec &&
2715 (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
2716 !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
2717 nsecnoexistnodata(val, wild, name, rdataset,
2718 &exists, &data, NULL)
2721 dns_name_t **proofs = val->event->proofs;
2722 if (exists && !data)
2723 val->attributes |= VALATTR_FOUNDNODATA;
2724 if (exists && !data && NEEDNODATA(val))
2725 proofs[DNS_VALIDATOR_NODATAPROOF] =
2729 VALATTR_FOUNDNOWILDCARD;
2730 if (!exists && NEEDNOQNAME(val))
2731 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
2733 if (dns_rdataset_isassociated(&trdataset))
2734 dns_rdataset_disassociate(&trdataset);
2735 return (ISC_R_SUCCESS);
2738 if (rdataset->type == dns_rdatatype_nsec3 &&
2739 (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
2740 !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
2741 nsec3noexistnodata(val, wild, name, rdataset,
2742 zonename, &exists, &data,
2743 NULL, NULL, NULL, NULL, NULL,
2744 NULL) == ISC_R_SUCCESS)
2746 dns_name_t **proofs = val->event->proofs;
2747 if (exists && !data)
2748 val->attributes |= VALATTR_FOUNDNODATA;
2749 if (exists && !data && NEEDNODATA(val))
2750 proofs[DNS_VALIDATOR_NODATAPROOF] =
2754 VALATTR_FOUNDNOWILDCARD;
2755 if (!exists && NEEDNOQNAME(val))
2756 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
2758 if (dns_rdataset_isassociated(&trdataset))
2759 dns_rdataset_disassociate(&trdataset);
2760 return (ISC_R_SUCCESS);
2763 if (result == ISC_R_NOMORE)
2764 result = ISC_R_SUCCESS;
2765 if (dns_rdataset_isassociated(&trdataset))
2766 dns_rdataset_disassociate(&trdataset);
2771 findnsec3proofs(dns_validator_t *val) {
2772 dns_name_t *name, tname;
2773 isc_result_t result;
2774 isc_boolean_t exists, data, optout, unknown;
2775 isc_boolean_t setclosest, setnearest;
2776 dns_fixedname_t fclosest, fnearest, fzonename;
2777 dns_name_t *closest, *nearest, *zonename;
2778 dns_name_t **proofs = val->event->proofs;
2779 dns_rdataset_t *rdataset, trdataset;
2781 dns_name_init(&tname, NULL);
2782 dns_rdataset_init(&trdataset);
2783 dns_fixedname_init(&fclosest);
2784 dns_fixedname_init(&fnearest);
2785 dns_fixedname_init(&fzonename);
2786 closest = dns_fixedname_name(&fclosest);
2787 nearest = dns_fixedname_name(&fnearest);
2788 zonename = dns_fixedname_name(&fzonename);
2790 if (val->event->message == NULL) {
2792 rdataset = &trdataset;
2798 for (result = val_rdataset_first(val, &name, &rdataset);
2799 result == ISC_R_SUCCESS;
2800 result = val_rdataset_next(val, &name, &rdataset))
2802 if (rdataset->type != dns_rdatatype_nsec3 ||
2803 rdataset->trust != dns_trust_secure)
2806 result = nsec3noexistnodata(val, val->event->name,
2808 zonename, NULL, NULL, NULL,
2809 NULL, NULL, NULL, NULL,
2811 if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS) {
2812 if (dns_rdataset_isassociated(&trdataset))
2813 dns_rdataset_disassociate(&trdataset);
2817 if (result != ISC_R_NOMORE)
2818 result = ISC_R_SUCCESS;
2820 if (dns_name_countlabels(zonename) == 0)
2821 return (ISC_R_SUCCESS);
2823 for (result = val_rdataset_first(val, &name, &rdataset);
2824 result == ISC_R_SUCCESS;
2825 result = val_rdataset_next(val, &name, &rdataset))
2827 if (rdataset->type != dns_rdatatype_nsec3 ||
2828 rdataset->trust != dns_trust_secure)
2832 * We process all NSEC3 records to find the closest
2833 * encloser and nearest name to the closest encloser.
2835 setclosest = setnearest = ISC_FALSE;
2837 unknown = ISC_FALSE;
2838 (void)nsec3noexistnodata(val, val->event->name, name, rdataset,
2839 zonename, &exists, &data, &optout,
2840 &unknown, &setclosest, &setnearest,
2843 proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
2845 val->attributes |= VALATTR_FOUNDUNKNOWN;
2846 if (result != ISC_R_SUCCESS)
2848 if (exists && !data && NEEDNODATA(val)) {
2849 val->attributes |= VALATTR_FOUNDNODATA;
2850 proofs[DNS_VALIDATOR_NODATAPROOF] = name;
2852 if (!exists && setnearest) {
2853 val->attributes |= VALATTR_FOUNDNOQNAME;
2854 proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name;
2856 val->attributes |= VALATTR_FOUNDOPTOUT;
2859 if (result == ISC_R_NOMORE)
2860 result = ISC_R_SUCCESS;
2863 * To know we have a valid noqname and optout proofs we need to also
2864 * have a valid closest encloser. Otherwise we could still be looking
2865 * at proofs from the parent zone.
2867 if (dns_name_countlabels(closest) > 0 &&
2868 dns_name_countlabels(nearest) ==
2869 dns_name_countlabels(closest) + 1 &&
2870 dns_name_issubdomain(nearest, closest))
2872 val->attributes |= VALATTR_FOUNDCLOSEST;
2873 result = dns_name_concatenate(dns_wildcardname, closest,
2874 dns_fixedname_name(&val->wild),
2876 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2878 val->attributes &= ~VALATTR_FOUNDNOQNAME;
2879 val->attributes &= ~VALATTR_FOUNDOPTOUT;
2880 proofs[DNS_VALIDATOR_NOQNAMEPROOF] = NULL;
2884 * Do we need to check for the wildcard?
2886 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
2887 ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
2888 result = checkwildcard(val, dns_rdatatype_nsec3, zonename);
2889 if (result != ISC_R_SUCCESS)
2896 * Validate the authority section records.
2899 validate_authority(dns_validator_t *val, isc_boolean_t resume) {
2901 dns_message_t *message = val->event->message;
2902 isc_result_t result;
2905 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2907 result = ISC_R_SUCCESS;
2910 result == ISC_R_SUCCESS;
2911 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
2913 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2916 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
2918 rdataset = ISC_LIST_NEXT(val->currentset, link);
2919 val->currentset = NULL;
2922 rdataset = ISC_LIST_HEAD(name->list);
2926 rdataset = ISC_LIST_NEXT(rdataset, link))
2928 if (rdataset->type == dns_rdatatype_rrsig)
2931 for (sigrdataset = ISC_LIST_HEAD(name->list);
2932 sigrdataset != NULL;
2933 sigrdataset = ISC_LIST_NEXT(sigrdataset,
2936 if (sigrdataset->type == dns_rdatatype_rrsig &&
2937 sigrdataset->covers == rdataset->type)
2941 * If a signed zone is missing the zone key, bad
2942 * things could happen. A query for data in the zone
2943 * would lead to a query for the zone key, which
2944 * would return a negative answer, which would contain
2945 * an SOA and an NSEC signed by the missing key, which
2946 * would trigger another query for the DNSKEY (since
2947 * the first one is still in progress), and go into an
2948 * infinite loop. Avoid that.
2950 if (val->event->type == dns_rdatatype_dnskey &&
2951 dns_name_equal(name, val->event->name))
2953 dns_rdata_t nsec = DNS_RDATA_INIT;
2955 if (rdataset->type != dns_rdatatype_nsec)
2958 result = dns_rdataset_first(rdataset);
2959 if (result != ISC_R_SUCCESS)
2961 dns_rdataset_current(rdataset, &nsec);
2962 if (dns_nsec_typepresent(&nsec,
2966 val->currentset = rdataset;
2967 result = create_validator(val, name, rdataset->type,
2968 rdataset, sigrdataset,
2970 "validate_authority");
2971 if (result != ISC_R_SUCCESS)
2974 return (DNS_R_WAIT);
2977 if (result == ISC_R_NOMORE)
2978 result = ISC_R_SUCCESS;
2983 * Validate the ncache elements.
2986 validate_ncache(dns_validator_t *val, isc_boolean_t resume) {
2988 isc_result_t result;
2991 result = dns_rdataset_first(val->event->rdataset);
2993 result = dns_rdataset_next(val->event->rdataset);
2996 result == ISC_R_SUCCESS;
2997 result = dns_rdataset_next(val->event->rdataset))
2999 dns_rdataset_t *rdataset, *sigrdataset = NULL;
3001 if (dns_rdataset_isassociated(&val->frdataset))
3002 dns_rdataset_disassociate(&val->frdataset);
3003 if (dns_rdataset_isassociated(&val->fsigrdataset))
3004 dns_rdataset_disassociate(&val->fsigrdataset);
3006 dns_fixedname_init(&val->fname);
3007 name = dns_fixedname_name(&val->fname);
3008 rdataset = &val->frdataset;
3009 dns_ncache_current(val->event->rdataset, name, rdataset);
3011 if (val->frdataset.type == dns_rdatatype_rrsig)
3014 result = dns_ncache_getsigrdataset(val->event->rdataset, name,
3016 &val->fsigrdataset);
3017 if (result == ISC_R_SUCCESS)
3018 sigrdataset = &val->fsigrdataset;
3021 * If a signed zone is missing the zone key, bad
3022 * things could happen. A query for data in the zone
3023 * would lead to a query for the zone key, which
3024 * would return a negative answer, which would contain
3025 * an SOA and an NSEC signed by the missing key, which
3026 * would trigger another query for the DNSKEY (since
3027 * the first one is still in progress), and go into an
3028 * infinite loop. Avoid that.
3030 if (val->event->type == dns_rdatatype_dnskey &&
3031 dns_name_equal(name, val->event->name))
3033 dns_rdata_t nsec = DNS_RDATA_INIT;
3035 if (rdataset->type != dns_rdatatype_nsec)
3038 result = dns_rdataset_first(rdataset);
3039 if (result != ISC_R_SUCCESS)
3041 dns_rdataset_current(rdataset, &nsec);
3042 if (dns_nsec_typepresent(&nsec,
3046 val->currentset = rdataset;
3047 result = create_validator(val, name, rdataset->type,
3048 rdataset, sigrdataset,
3051 if (result != ISC_R_SUCCESS)
3054 return (DNS_R_WAIT);
3056 if (result == ISC_R_NOMORE)
3057 result = ISC_R_SUCCESS;
3062 * Prove a negative answer is good or that there is a NOQNAME when the
3063 * answer is from a wildcard.
3065 * Loop through the authority section looking for NODATA, NOWILDCARD
3066 * and NOQNAME proofs in the NSEC records by calling authvalidated().
3068 * If the required proofs are found we are done.
3070 * If the proofs are not found attempt to prove this is a unsecure
3074 nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
3075 isc_result_t result;
3078 validator_log(val, ISC_LOG_DEBUG(3), "resuming nsecvalidate");
3080 if (val->event->message == NULL)
3081 result = validate_ncache(val, resume);
3083 result = validate_authority(val, resume);
3085 if (result != ISC_R_SUCCESS)
3089 * Do we only need to check for NOQNAME? To get here we must have
3090 * had a secure wildcard answer.
3092 if (!NEEDNODATA(val) && !NEEDNOWILDCARD(val) && NEEDNOQNAME(val)) {
3093 if (!FOUNDNOQNAME(val))
3094 findnsec3proofs(val);
3095 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val)) {
3096 validator_log(val, ISC_LOG_DEBUG(3),
3097 "noqname proof found");
3098 validator_log(val, ISC_LOG_DEBUG(3),
3099 "marking as secure");
3100 marksecure(val->event);
3101 return (ISC_R_SUCCESS);
3102 } else if (FOUNDOPTOUT(val) &&
3103 dns_name_countlabels(dns_fixedname_name(&val->wild))
3105 validator_log(val, ISC_LOG_DEBUG(3),
3106 "optout proof found");
3107 val->event->optout = ISC_TRUE;
3108 markanswer(val, "nsecvalidate (1)");
3109 return (ISC_R_SUCCESS);
3110 } else if ((val->attributes & VALATTR_FOUNDUNKNOWN) != 0) {
3111 validator_log(val, ISC_LOG_DEBUG(3),
3112 "unknown NSEC3 hash algorithm found");
3113 markanswer(val, "nsecvalidate (2)");
3114 return (ISC_R_SUCCESS);
3116 validator_log(val, ISC_LOG_DEBUG(3),
3117 "noqname proof not found");
3118 return (DNS_R_NOVALIDNSEC);
3121 if (!FOUNDNOQNAME(val) && !FOUNDNODATA(val))
3122 findnsec3proofs(val);
3125 * Do we need to check for the wildcard?
3127 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
3128 ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
3129 result = checkwildcard(val, dns_rdatatype_nsec, NULL);
3130 if (result != ISC_R_SUCCESS)
3134 if ((NEEDNODATA(val) && (FOUNDNODATA(val) || FOUNDOPTOUT(val))) ||
3135 (NEEDNOQNAME(val) && FOUNDNOQNAME(val) &&
3136 NEEDNOWILDCARD(val) && FOUNDNOWILDCARD(val) &&
3137 FOUNDCLOSEST(val))) {
3138 if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
3139 val->event->optout = ISC_TRUE;
3140 validator_log(val, ISC_LOG_DEBUG(3),
3141 "nonexistence proof(s) found");
3142 if (val->event->message == NULL)
3143 marksecure(val->event);
3144 return (ISC_R_SUCCESS);
3146 findnsec3proofs(val);
3148 if (val->authfail != 0 && val->authcount == val->authfail)
3149 return (DNS_R_BROKENCHAIN);
3150 validator_log(val, ISC_LOG_DEBUG(3),
3151 "nonexistence proof(s) not found");
3152 val->attributes |= VALATTR_INSECURITY;
3153 return (proveunsecure(val, ISC_FALSE, ISC_FALSE));
3156 static isc_boolean_t
3157 check_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) {
3158 dns_rdata_t dsrdata = DNS_RDATA_INIT;
3160 isc_result_t result;
3162 for (result = dns_rdataset_first(rdataset);
3163 result == ISC_R_SUCCESS;
3164 result = dns_rdataset_next(rdataset)) {
3165 dns_rdataset_current(rdataset, &dsrdata);
3166 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
3167 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3169 if (dns_resolver_digest_supported(val->view->resolver,
3171 dns_resolver_algorithm_supported(val->view->resolver,
3172 name, ds.algorithm)) {
3173 dns_rdata_reset(&dsrdata);
3176 dns_rdata_reset(&dsrdata);
3182 dlvvalidated(isc_task_t *task, isc_event_t *event) {
3183 dns_validatorevent_t *devent;
3184 dns_validator_t *val;
3185 isc_result_t eresult;
3186 isc_boolean_t want_destroy;
3189 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
3191 devent = (dns_validatorevent_t *)event;
3192 val = devent->ev_arg;
3193 eresult = devent->result;
3195 isc_event_free(&event);
3196 dns_validator_destroy(&val->subvalidator);
3198 INSIST(val->event != NULL);
3200 validator_log(val, ISC_LOG_DEBUG(3), "in dlvvalidated");
3202 if (CANCELED(val)) {
3203 validator_done(val, ISC_R_CANCELED);
3204 } else if (eresult == ISC_R_SUCCESS) {
3205 validator_log(val, ISC_LOG_DEBUG(3),
3206 "dlvset with trust %s",
3207 dns_trust_totext(val->frdataset.trust));
3208 dns_rdataset_clone(&val->frdataset, &val->dlv);
3209 val->havedlvsep = ISC_TRUE;
3210 if (dlv_algorithm_supported(val))
3211 dlv_validator_start(val);
3213 markanswer(val, "dlvvalidated");
3214 validator_done(val, ISC_R_SUCCESS);
3217 if (eresult != DNS_R_BROKENCHAIN) {
3218 if (dns_rdataset_isassociated(&val->frdataset))
3219 dns_rdataset_expire(&val->frdataset);
3220 if (dns_rdataset_isassociated(&val->fsigrdataset))
3221 dns_rdataset_expire(&val->fsigrdataset);
3223 validator_log(val, ISC_LOG_DEBUG(3),
3224 "dlvvalidated: got %s",
3225 isc_result_totext(eresult));
3226 validator_done(val, DNS_R_BROKENCHAIN);
3228 want_destroy = exit_check(val);
3235 * Callback from fetching a DLV record.
3237 * Resumes the DLV lookup process.
3240 dlvfetched(isc_task_t *task, isc_event_t *event) {
3241 char namebuf[DNS_NAME_FORMATSIZE];
3242 dns_fetchevent_t *devent;
3243 dns_validator_t *val;
3244 isc_boolean_t want_destroy;
3245 isc_result_t eresult;
3246 isc_result_t result;
3249 INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
3250 devent = (dns_fetchevent_t *)event;
3251 val = devent->ev_arg;
3252 eresult = devent->result;
3254 /* Free resources which are not of interest. */
3255 if (devent->node != NULL)
3256 dns_db_detachnode(devent->db, &devent->node);
3257 if (devent->db != NULL)
3258 dns_db_detach(&devent->db);
3259 if (dns_rdataset_isassociated(&val->fsigrdataset))
3260 dns_rdataset_disassociate(&val->fsigrdataset);
3261 isc_event_free(&event);
3262 dns_resolver_destroyfetch(&val->fetch);
3264 INSIST(val->event != NULL);
3265 validator_log(val, ISC_LOG_DEBUG(3), "in dlvfetched: %s",
3266 dns_result_totext(eresult));
3269 if (eresult == ISC_R_SUCCESS) {
3270 dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
3272 dns_rdataset_clone(&val->frdataset, &val->dlv);
3273 val->havedlvsep = ISC_TRUE;
3274 if (dlv_algorithm_supported(val)) {
3275 validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found",
3277 dlv_validator_start(val);
3279 validator_log(val, ISC_LOG_DEBUG(3),
3280 "DLV %s found with no supported algorithms",
3282 markanswer(val, "dlvfetched (1)");
3283 validator_done(val, ISC_R_SUCCESS);
3285 } else if (eresult == DNS_R_NXRRSET ||
3286 eresult == DNS_R_NXDOMAIN ||
3287 eresult == DNS_R_NCACHENXRRSET ||
3288 eresult == DNS_R_NCACHENXDOMAIN) {
3289 result = finddlvsep(val, ISC_TRUE);
3290 if (result == ISC_R_SUCCESS) {
3291 if (dlv_algorithm_supported(val)) {
3292 dns_name_format(dns_fixedname_name(&val->dlvsep),
3293 namebuf, sizeof(namebuf));
3294 validator_log(val, ISC_LOG_DEBUG(3),
3295 "DLV %s found", namebuf);
3296 dlv_validator_start(val);
3298 validator_log(val, ISC_LOG_DEBUG(3),
3299 "DLV %s found with no supported "
3300 "algorithms", namebuf);
3301 markanswer(val, "dlvfetched (2)");
3302 validator_done(val, ISC_R_SUCCESS);
3304 } else if (result == ISC_R_NOTFOUND) {
3305 validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
3306 markanswer(val, "dlvfetched (3)");
3307 validator_done(val, ISC_R_SUCCESS);
3309 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3310 dns_result_totext(result));
3311 if (result != DNS_R_WAIT)
3312 validator_done(val, result);
3315 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3316 dns_result_totext(eresult));
3317 validator_done(val, eresult);
3319 want_destroy = exit_check(val);
3326 * Start the DLV lookup process.
3331 * \li Others on validation failures.
3334 startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) {
3335 char namebuf[DNS_NAME_FORMATSIZE];
3336 isc_result_t result;
3338 INSIST(!DLVTRIED(val));
3340 val->attributes |= VALATTR_DLVTRIED;
3342 dns_name_format(unsecure, namebuf, sizeof(namebuf));
3343 validator_log(val, ISC_LOG_DEBUG(3),
3344 "plain DNSSEC returns unsecure (%s): looking for DLV",
3347 if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
3348 validator_log(val, ISC_LOG_WARNING, "must be secure failure");
3349 return (DNS_R_MUSTBESECURE);
3352 val->dlvlabels = dns_name_countlabels(unsecure) - 1;
3353 result = finddlvsep(val, ISC_FALSE);
3354 if (result == ISC_R_NOTFOUND) {
3355 validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
3356 markanswer(val, "startfinddlvsep (1)");
3357 return (ISC_R_SUCCESS);
3359 if (result != ISC_R_SUCCESS) {
3360 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3361 dns_result_totext(result));
3364 dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
3366 if (dlv_algorithm_supported(val)) {
3367 validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf);
3368 dlv_validator_start(val);
3369 return (DNS_R_WAIT);
3371 validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found with no supported "
3372 "algorithms", namebuf);
3373 markanswer(val, "startfinddlvsep (2)");
3374 validator_done(val, ISC_R_SUCCESS);
3375 return (ISC_R_SUCCESS);
3379 * Continue the DLV lookup process.
3383 * \li ISC_R_NOTFOUND
3385 * \li Others on validation failure.
3388 finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
3389 char namebuf[DNS_NAME_FORMATSIZE];
3390 dns_fixedname_t dlvfixed;
3391 dns_name_t *dlvname;
3394 isc_result_t result;
3395 unsigned int labels;
3397 INSIST(val->view->dlv != NULL);
3401 if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
3402 validator_log(val, ISC_LOG_WARNING,
3403 "must be secure failure");
3404 return (DNS_R_MUSTBESECURE);
3407 dns_fixedname_init(&val->dlvsep);
3408 dlvsep = dns_fixedname_name(&val->dlvsep);
3409 dns_name_copy(val->event->name, dlvsep, NULL);
3411 * If this is a response to a DS query, we need to look in
3412 * the parent zone for the trust anchor.
3414 if (val->event->type == dns_rdatatype_ds) {
3415 labels = dns_name_countlabels(dlvsep);
3417 return (ISC_R_NOTFOUND);
3418 dns_name_getlabelsequence(dlvsep, 1, labels - 1,
3422 dlvsep = dns_fixedname_name(&val->dlvsep);
3423 labels = dns_name_countlabels(dlvsep);
3424 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3426 dns_name_init(&noroot, NULL);
3427 dns_fixedname_init(&dlvfixed);
3428 dlvname = dns_fixedname_name(&dlvfixed);
3429 labels = dns_name_countlabels(dlvsep);
3431 return (ISC_R_NOTFOUND);
3432 dns_name_getlabelsequence(dlvsep, 0, labels - 1, &noroot);
3433 result = dns_name_concatenate(&noroot, val->view->dlv, dlvname, NULL);
3434 while (result == ISC_R_NOSPACE) {
3435 labels = dns_name_countlabels(dlvsep);
3436 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3437 dns_name_getlabelsequence(dlvsep, 0, labels - 2, &noroot);
3438 result = dns_name_concatenate(&noroot, val->view->dlv,
3441 if (result != ISC_R_SUCCESS) {
3442 validator_log(val, ISC_LOG_DEBUG(2), "DLV concatenate failed");
3443 return (DNS_R_NOVALIDSIG);
3446 while (dns_name_countlabels(dlvname) >=
3447 dns_name_countlabels(val->view->dlv) + val->dlvlabels) {
3448 dns_name_format(dlvname, namebuf, sizeof(namebuf));
3449 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV %s",
3451 result = view_find(val, dlvname, dns_rdatatype_dlv);
3452 if (result == ISC_R_SUCCESS) {
3453 if (DNS_TRUST_PENDING(val->frdataset.trust) &&
3454 dns_rdataset_isassociated(&val->fsigrdataset))
3456 dns_fixedname_init(&val->fname);
3457 dns_name_copy(dlvname,
3458 dns_fixedname_name(&val->fname),
3460 result = create_validator(val,
3461 dns_fixedname_name(&val->fname),
3467 if (result != ISC_R_SUCCESS)
3469 return (DNS_R_WAIT);
3471 if (val->frdataset.trust < dns_trust_secure)
3472 return (DNS_R_NOVALIDSIG);
3473 val->havedlvsep = ISC_TRUE;
3474 dns_rdataset_clone(&val->frdataset, &val->dlv);
3475 return (ISC_R_SUCCESS);
3477 if (result == ISC_R_NOTFOUND) {
3478 result = create_fetch(val, dlvname, dns_rdatatype_dlv,
3479 dlvfetched, "finddlvsep");
3480 if (result != ISC_R_SUCCESS)
3482 return (DNS_R_WAIT);
3484 if (result != DNS_R_NXRRSET &&
3485 result != DNS_R_NXDOMAIN &&
3486 result != DNS_R_EMPTYNAME &&
3487 result != DNS_R_NCACHENXRRSET &&
3488 result != DNS_R_NCACHENXDOMAIN)
3491 * Strip first labels from both dlvsep and dlvname.
3493 labels = dns_name_countlabels(dlvsep);
3496 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3497 labels = dns_name_countlabels(dlvname);
3498 dns_name_getlabelsequence(dlvname, 1, labels - 1, dlvname);
3500 return (ISC_R_NOTFOUND);
3504 * proveunsecure walks down from the SEP looking for a break in the
3505 * chain of trust. That occurs when we can prove the DS record does
3506 * not exist at a delegation point or the DS exists at a delegation
3507 * but we don't support the algorithm/digest.
3509 * If DLV is active and we look for a DLV record at or below the
3510 * point we go insecure. If found we restart the validation process.
3511 * If not found or DLV isn't active we mark the response as a answer.
3514 * \li ISC_R_SUCCESS val->event->name is in a unsecure zone
3515 * \li DNS_R_WAIT validation is in progress.
3516 * \li DNS_R_MUSTBESECURE val->event->name is supposed to be secure
3517 * (policy) but we proved that it is unsecure.
3518 * \li DNS_R_NOVALIDSIG
3519 * \li DNS_R_NOVALIDNSEC
3520 * \li DNS_R_NOTINSECURE
3521 * \li DNS_R_BROKENCHAIN
3524 proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
3526 isc_result_t result;
3527 dns_fixedname_t fixedsecroot;
3528 dns_name_t *secroot;
3530 char namebuf[DNS_NAME_FORMATSIZE];
3532 dns_fixedname_t fixedfound;
3534 dns_fixedname_init(&fixedsecroot);
3535 secroot = dns_fixedname_name(&fixedsecroot);
3536 dns_fixedname_init(&fixedfound);
3537 found = dns_fixedname_name(&fixedfound);
3538 if (val->havedlvsep)
3539 dns_name_copy(dns_fixedname_name(&val->dlvsep), secroot, NULL);
3541 unsigned int labels;
3542 dns_name_copy(val->event->name, secroot, NULL);
3544 * If this is a response to a DS query, we need to look in
3545 * the parent zone for the trust anchor.
3548 labels = dns_name_countlabels(secroot);
3549 if (val->event->type == dns_rdatatype_ds && labels > 1U)
3550 dns_name_getlabelsequence(secroot, 1, labels - 1,
3552 result = dns_keytable_finddeepestmatch(val->keytable,
3554 if (result == ISC_R_NOTFOUND) {
3555 if (val->mustbesecure) {
3556 validator_log(val, ISC_LOG_WARNING,
3557 "must be secure failure");
3558 result = DNS_R_MUSTBESECURE;
3561 if (val->view->dlv == NULL || DLVTRIED(val)) {
3562 markanswer(val, "proveunsecure (1)");
3563 return (ISC_R_SUCCESS);
3565 return (startfinddlvsep(val, dns_rootname));
3566 } else if (result != ISC_R_SUCCESS)
3572 * We are looking for breaks below the SEP so add a label.
3574 val->labels = dns_name_countlabels(secroot) + 1;
3576 validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
3578 * If we have a DS rdataset and it is secure then check if
3579 * the DS rdataset has a supported algorithm combination.
3580 * If not this is a insecure delegation as far as this
3581 * resolver is concerned. Fall back to DLV if available.
3583 if (have_ds && val->frdataset.trust >= dns_trust_secure &&
3584 !check_ds(val, dns_fixedname_name(&val->fname),
3586 dns_name_format(dns_fixedname_name(&val->fname),
3587 namebuf, sizeof(namebuf));
3588 if ((val->view->dlv == NULL || DLVTRIED(val)) &&
3589 val->mustbesecure) {
3590 validator_log(val, ISC_LOG_WARNING,
3591 "must be secure failure at '%s'",
3593 result = DNS_R_MUSTBESECURE;
3596 validator_log(val, ISC_LOG_DEBUG(3),
3597 "no supported algorithm/digest (%s/DS)",
3599 if (val->view->dlv == NULL || DLVTRIED(val)) {
3600 markanswer(val, "proveunsecure (2)");
3601 result = ISC_R_SUCCESS;
3604 result = startfinddlvsep(val,
3605 dns_fixedname_name(&val->fname));
3612 val->labels <= dns_name_countlabels(val->event->name);
3616 dns_fixedname_init(&val->fname);
3617 tname = dns_fixedname_name(&val->fname);
3618 if (val->labels == dns_name_countlabels(val->event->name))
3619 dns_name_copy(val->event->name, tname, NULL);
3621 dns_name_split(val->event->name, val->labels,
3624 dns_name_format(tname, namebuf, sizeof(namebuf));
3625 validator_log(val, ISC_LOG_DEBUG(3),
3626 "checking existence of DS at '%s'",
3629 result = view_find(val, tname, dns_rdatatype_ds);
3630 if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
3632 * There is no DS. If this is a delegation,
3636 * If we have "trust == answer" then this namespace
3637 * has switched from insecure to should be secure.
3639 if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3640 DNS_TRUST_ANSWER(val->frdataset.trust)) {
3641 result = create_validator(val, tname,
3646 if (result != ISC_R_SUCCESS)
3648 return (DNS_R_WAIT);
3651 * Zones using NSEC3 don't return a NSEC RRset so
3652 * we need to use dns_view_findzonecut2 to find
3655 if (result == DNS_R_NXRRSET &&
3656 !dns_rdataset_isassociated(&val->frdataset) &&
3657 dns_view_findzonecut2(val->view, tname, found,
3658 0, 0, ISC_FALSE, ISC_FALSE,
3659 NULL, NULL) == ISC_R_SUCCESS &&
3660 dns_name_equal(tname, found)) {
3661 if (val->mustbesecure) {
3662 validator_log(val, ISC_LOG_WARNING,
3663 "must be secure failure");
3664 return (DNS_R_MUSTBESECURE);
3666 if (val->view->dlv == NULL || DLVTRIED(val)) {
3667 markanswer(val, "proveunsecure (3)");
3668 return (ISC_R_SUCCESS);
3670 return (startfinddlvsep(val, tname));
3672 if (val->frdataset.trust < dns_trust_secure) {
3674 * This shouldn't happen, since the negative
3675 * response should have been validated. Since
3676 * there's no way of validating existing
3677 * negative response blobs, give up.
3679 result = DNS_R_NOVALIDSIG;
3682 if (isdelegation(tname, &val->frdataset, result)) {
3683 if (val->mustbesecure) {
3684 validator_log(val, ISC_LOG_WARNING,
3685 "must be secure failure");
3686 return (DNS_R_MUSTBESECURE);
3688 if (val->view->dlv == NULL || DLVTRIED(val)) {
3689 markanswer(val, "proveunsecure (4)");
3690 return (ISC_R_SUCCESS);
3692 return (startfinddlvsep(val, tname));
3695 } else if (result == ISC_R_SUCCESS) {
3697 * There is a DS here. Verify that it's secure and
3700 if (val->frdataset.trust >= dns_trust_secure) {
3701 if (!check_ds(val, tname, &val->frdataset)) {
3702 validator_log(val, ISC_LOG_DEBUG(3),
3703 "no supported algorithm/"
3704 "digest (%s/DS)", namebuf);
3705 if (val->mustbesecure) {
3708 "must be secure failure");
3709 result = DNS_R_MUSTBESECURE;
3712 if (val->view->dlv == NULL ||
3715 "proveunsecure (5)");
3716 result = ISC_R_SUCCESS;
3719 result = startfinddlvsep(val, tname);
3724 else if (!dns_rdataset_isassociated(&val->fsigrdataset))
3726 result = DNS_R_NOVALIDSIG;
3730 * Validate / re-validate answer.
3732 result = create_validator(val, tname, dns_rdatatype_ds,
3737 if (result != ISC_R_SUCCESS)
3739 return (DNS_R_WAIT);
3740 } else if (result == DNS_R_NXDOMAIN ||
3741 result == DNS_R_NCACHENXDOMAIN) {
3743 * This is not a zone cut. Assuming things are
3744 * as expected, continue.
3746 if (!dns_rdataset_isassociated(&val->frdataset)) {
3748 * There should be an NSEC here, since we
3749 * are still in a secure zone.
3751 result = DNS_R_NOVALIDNSEC;
3753 } else if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3754 DNS_TRUST_ANSWER(val->frdataset.trust)) {
3756 * If we have "trust == answer" then this namespace
3757 * has switched from insecure to should be secure.
3759 result = create_validator(val, tname,
3764 if (result != ISC_R_SUCCESS)
3766 return (DNS_R_WAIT);
3767 } else if (val->frdataset.trust < dns_trust_secure) {
3769 * This shouldn't happen, since the negative
3770 * response should have been validated. Since
3771 * there's no way of validating existing
3772 * negative response blobs, give up.
3774 result = DNS_R_NOVALIDSIG;
3778 } else if (result == ISC_R_NOTFOUND) {
3780 * We don't know anything about the DS. Find it.
3782 result = create_fetch(val, tname, dns_rdatatype_ds,
3783 dsfetched2, "proveunsecure");
3784 if (result != ISC_R_SUCCESS)
3786 return (DNS_R_WAIT);
3787 } else if (result == DNS_R_BROKENCHAIN)
3791 /* Couldn't complete insecurity proof */
3792 validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed");
3793 return (DNS_R_NOTINSECURE); /* Couldn't complete insecurity proof */
3796 if (dns_rdataset_isassociated(&val->frdataset))
3797 dns_rdataset_disassociate(&val->frdataset);
3798 if (dns_rdataset_isassociated(&val->fsigrdataset))
3799 dns_rdataset_disassociate(&val->fsigrdataset);
3804 * Reset state and revalidate the answer using DLV.
3807 dlv_validator_start(dns_validator_t *val) {
3810 validator_log(val, ISC_LOG_DEBUG(3), "dlv_validator_start");
3813 * Reset state and try again.
3815 val->attributes &= VALATTR_DLVTRIED;
3816 val->options &= ~DNS_VALIDATOR_DLV;
3818 event = (isc_event_t *)val->event;
3819 isc_task_send(val->task, &event);
3823 * Start the validation process.
3825 * Attempt to validate the answer based on the category it appears to
3827 * \li 1. secure positive answer.
3828 * \li 2. unsecure positive answer.
3829 * \li 3. a negative answer (secure or unsecure).
3831 * Note a answer that appears to be a secure positive answer may actually
3832 * be a unsecure positive answer.
3835 validator_start(isc_task_t *task, isc_event_t *event) {
3836 dns_validator_t *val;
3837 dns_validatorevent_t *vevent;
3838 isc_boolean_t want_destroy = ISC_FALSE;
3839 isc_result_t result = ISC_R_FAILURE;
3842 REQUIRE(event->ev_type == DNS_EVENT_VALIDATORSTART);
3843 vevent = (dns_validatorevent_t *)event;
3844 val = vevent->validator;
3846 /* If the validator has been canceled, val->event == NULL */
3847 if (val->event == NULL)
3851 validator_log(val, ISC_LOG_DEBUG(3), "restarting using DLV");
3853 validator_log(val, ISC_LOG_DEBUG(3), "starting");
3857 if ((val->options & DNS_VALIDATOR_DLV) != 0 &&
3858 val->event->rdataset != NULL) {
3859 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV");
3860 result = startfinddlvsep(val, dns_rootname);
3861 } else if (val->event->rdataset != NULL &&
3862 val->event->sigrdataset != NULL) {
3863 isc_result_t saved_result;
3866 * This looks like a simple validation. We say "looks like"
3867 * because it might end up requiring an insecurity proof.
3869 validator_log(val, ISC_LOG_DEBUG(3),
3870 "attempting positive response validation");
3872 INSIST(dns_rdataset_isassociated(val->event->rdataset));
3873 INSIST(dns_rdataset_isassociated(val->event->sigrdataset));
3874 result = start_positive_validation(val);
3875 if (result == DNS_R_NOVALIDSIG &&
3876 (val->attributes & VALATTR_TRIEDVERIFY) == 0)
3878 saved_result = result;
3879 validator_log(val, ISC_LOG_DEBUG(3),
3880 "falling back to insecurity proof");
3881 val->attributes |= VALATTR_INSECURITY;
3882 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
3883 if (result == DNS_R_NOTINSECURE)
3884 result = saved_result;
3886 } else if (val->event->rdataset != NULL &&
3887 val->event->rdataset->type != 0) {
3889 * This is either an unsecure subdomain or a response from
3892 INSIST(dns_rdataset_isassociated(val->event->rdataset));
3893 validator_log(val, ISC_LOG_DEBUG(3),
3894 "attempting insecurity proof");
3896 val->attributes |= VALATTR_INSECURITY;
3897 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
3898 } else if (val->event->rdataset == NULL &&
3899 val->event->sigrdataset == NULL)
3902 * This is a nonexistence validation.
3904 validator_log(val, ISC_LOG_DEBUG(3),
3905 "attempting negative response validation");
3907 if (val->event->message->rcode == dns_rcode_nxdomain) {
3908 val->attributes |= VALATTR_NEEDNOQNAME;
3909 val->attributes |= VALATTR_NEEDNOWILDCARD;
3911 val->attributes |= VALATTR_NEEDNODATA;
3912 result = nsecvalidate(val, ISC_FALSE);
3913 } else if (val->event->rdataset != NULL &&
3914 NEGATIVE(val->event->rdataset))
3917 * This is a nonexistence validation.
3919 validator_log(val, ISC_LOG_DEBUG(3),
3920 "attempting negative response validation");
3922 if (val->event->rdataset->covers == dns_rdatatype_any) {
3923 val->attributes |= VALATTR_NEEDNOQNAME;
3924 val->attributes |= VALATTR_NEEDNOWILDCARD;
3926 val->attributes |= VALATTR_NEEDNODATA;
3927 result = nsecvalidate(val, ISC_FALSE);
3930 * This shouldn't happen.
3935 if (result != DNS_R_WAIT) {
3936 want_destroy = exit_check(val);
3937 validator_done(val, result);
3946 dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
3947 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
3948 dns_message_t *message, unsigned int options,
3949 isc_task_t *task, isc_taskaction_t action, void *arg,
3950 dns_validator_t **validatorp)
3952 isc_result_t result;
3953 dns_validator_t *val;
3955 dns_validatorevent_t *event;
3957 REQUIRE(name != NULL);
3958 REQUIRE(rdataset != NULL ||
3959 (rdataset == NULL && sigrdataset == NULL && message != NULL));
3960 REQUIRE(validatorp != NULL && *validatorp == NULL);
3963 result = ISC_R_FAILURE;
3965 val = isc_mem_get(view->mctx, sizeof(*val));
3967 return (ISC_R_NOMEMORY);
3969 dns_view_weakattach(view, &val->view);
3970 event = (dns_validatorevent_t *)
3971 isc_event_allocate(view->mctx, task,
3972 DNS_EVENT_VALIDATORSTART,
3973 validator_start, NULL,
3974 sizeof(dns_validatorevent_t));
3975 if (event == NULL) {
3976 result = ISC_R_NOMEMORY;
3979 isc_task_attach(task, &tclone);
3980 event->validator = val;
3981 event->result = ISC_R_FAILURE;
3984 event->rdataset = rdataset;
3985 event->sigrdataset = sigrdataset;
3986 event->message = message;
3987 memset(event->proofs, 0, sizeof(event->proofs));
3988 event->optout = ISC_FALSE;
3989 result = isc_mutex_init(&val->lock);
3990 if (result != ISC_R_SUCCESS)
3993 val->options = options;
3994 val->attributes = 0;
3996 val->subvalidator = NULL;
3998 val->keytable = NULL;
3999 dns_keytable_attach(val->view->secroots, &val->keytable);
4000 val->keynode = NULL;
4002 val->siginfo = NULL;
4004 val->action = action;
4007 val->currentset = NULL;
4010 dns_rdataset_init(&val->dlv);
4011 val->seensig = ISC_FALSE;
4012 val->havedlvsep = ISC_FALSE;
4016 val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
4017 dns_rdataset_init(&val->frdataset);
4018 dns_rdataset_init(&val->fsigrdataset);
4019 dns_fixedname_init(&val->wild);
4020 dns_fixedname_init(&val->nearest);
4021 dns_fixedname_init(&val->closest);
4022 ISC_LINK_INIT(val, link);
4023 val->magic = VALIDATOR_MAGIC;
4025 if ((options & DNS_VALIDATOR_DEFER) == 0)
4026 isc_task_send(task, ISC_EVENT_PTR(&event));
4030 return (ISC_R_SUCCESS);
4033 isc_task_detach(&tclone);
4034 isc_event_free(ISC_EVENT_PTR(&event));
4037 dns_view_weakdetach(&val->view);
4038 isc_mem_put(view->mctx, val, sizeof(*val));
4044 dns_validator_send(dns_validator_t *validator) {
4046 REQUIRE(VALID_VALIDATOR(validator));
4048 LOCK(&validator->lock);
4050 INSIST((validator->options & DNS_VALIDATOR_DEFER) != 0);
4051 event = (isc_event_t *)validator->event;
4052 validator->options &= ~DNS_VALIDATOR_DEFER;
4053 UNLOCK(&validator->lock);
4055 isc_task_send(validator->task, ISC_EVENT_PTR(&event));
4059 dns_validator_cancel(dns_validator_t *validator) {
4060 REQUIRE(VALID_VALIDATOR(validator));
4062 LOCK(&validator->lock);
4064 validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
4066 if ((validator->attributes & VALATTR_CANCELED) == 0) {
4067 validator->attributes |= VALATTR_CANCELED;
4068 if (validator->event != NULL) {
4069 if (validator->fetch != NULL)
4070 dns_resolver_cancelfetch(validator->fetch);
4072 if (validator->subvalidator != NULL)
4073 dns_validator_cancel(validator->subvalidator);
4074 if ((validator->options & DNS_VALIDATOR_DEFER) != 0) {
4075 validator->options &= ~DNS_VALIDATOR_DEFER;
4076 validator_done(validator, ISC_R_CANCELED);
4080 UNLOCK(&validator->lock);
4084 destroy(dns_validator_t *val) {
4087 REQUIRE(SHUTDOWN(val));
4088 REQUIRE(val->event == NULL);
4089 REQUIRE(val->fetch == NULL);
4091 if (val->keynode != NULL)
4092 dns_keytable_detachkeynode(val->keytable, &val->keynode);
4093 else if (val->key != NULL)
4094 dst_key_free(&val->key);
4095 if (val->keytable != NULL)
4096 dns_keytable_detach(&val->keytable);
4097 if (val->subvalidator != NULL)
4098 dns_validator_destroy(&val->subvalidator);
4099 if (val->havedlvsep)
4100 dns_rdataset_disassociate(&val->dlv);
4101 if (dns_rdataset_isassociated(&val->frdataset))
4102 dns_rdataset_disassociate(&val->frdataset);
4103 if (dns_rdataset_isassociated(&val->fsigrdataset))
4104 dns_rdataset_disassociate(&val->fsigrdataset);
4105 mctx = val->view->mctx;
4106 if (val->siginfo != NULL)
4107 isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo));
4108 DESTROYLOCK(&val->lock);
4109 dns_view_weakdetach(&val->view);
4111 isc_mem_put(mctx, val, sizeof(*val));
4115 dns_validator_destroy(dns_validator_t **validatorp) {
4116 dns_validator_t *val;
4117 isc_boolean_t want_destroy = ISC_FALSE;
4119 REQUIRE(validatorp != NULL);
4121 REQUIRE(VALID_VALIDATOR(val));
4125 val->attributes |= VALATTR_SHUTDOWN;
4126 validator_log(val, ISC_LOG_DEBUG(3), "dns_validator_destroy");
4128 want_destroy = exit_check(val);
4139 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
4140 isc_logmodule_t *module, int level, const char *fmt, va_list ap)
4143 static const char spaces[] = " *";
4144 int depth = val->depth * 2;
4146 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
4148 if ((unsigned int) depth >= sizeof spaces)
4149 depth = sizeof spaces - 1;
4151 if (val->event != NULL && val->event->name != NULL) {
4152 char namebuf[DNS_NAME_FORMATSIZE];
4153 char typebuf[DNS_RDATATYPE_FORMATSIZE];
4155 dns_name_format(val->event->name, namebuf, sizeof(namebuf));
4156 dns_rdatatype_format(val->event->type, typebuf,
4158 isc_log_write(dns_lctx, category, module, level,
4159 "%.*svalidating @%p: %s %s: %s", depth, spaces,
4160 val, namebuf, typebuf, msgbuf);
4162 isc_log_write(dns_lctx, category, module, level,
4163 "%.*svalidator @%p: %s", depth, spaces,
4169 validator_log(dns_validator_t *val, int level, const char *fmt, ...) {
4172 if (! isc_log_wouldlog(dns_lctx, level))
4177 validator_logv(val, DNS_LOGCATEGORY_DNSSEC,
4178 DNS_LOGMODULE_VALIDATOR, level, fmt, ap);
4183 validator_logcreate(dns_validator_t *val,
4184 dns_name_t *name, dns_rdatatype_t type,
4185 const char *caller, const char *operation)
4187 char namestr[DNS_NAME_FORMATSIZE];
4188 char typestr[DNS_RDATATYPE_FORMATSIZE];
4190 dns_name_format(name, namestr, sizeof(namestr));
4191 dns_rdatatype_format(type, typestr, sizeof(typestr));
4192 validator_log(val, ISC_LOG_DEBUG(9), "%s: creating %s for %s %s",
4193 caller, operation, namestr, typestr);