4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: validator.c,v 1.182 2009/11/17 23:55:18 marka Exp */
24 #include <isc/base32.h>
26 #include <isc/print.h>
28 #include <isc/string.h>
34 #include <dns/dnssec.h>
35 #include <dns/events.h>
36 #include <dns/keytable.h>
38 #include <dns/message.h>
39 #include <dns/ncache.h>
41 #include <dns/nsec3.h>
42 #include <dns/rdata.h>
43 #include <dns/rdatastruct.h>
44 #include <dns/rdataset.h>
45 #include <dns/rdatatype.h>
46 #include <dns/resolver.h>
47 #include <dns/result.h>
48 #include <dns/validator.h>
53 * Basic processing sequences.
55 * \li When called with rdataset and sigrdataset:
56 * validator_start -> validate -> proveunsecure -> startfinddlvsep ->
57 * dlv_validator_start -> validator_start -> validate -> proveunsecure
59 * validator_start -> validate -> nsecvalidate (secure wildcard answer)
61 * \li When called with rdataset, sigrdataset and with DNS_VALIDATOR_DLV:
62 * validator_start -> startfinddlvsep -> dlv_validator_start ->
63 * validator_start -> validate -> proveunsecure
65 * \li When called with rdataset:
66 * validator_start -> proveunsecure -> startfinddlvsep ->
67 * dlv_validator_start -> validator_start -> proveunsecure
69 * \li When called with rdataset and with DNS_VALIDATOR_DLV:
70 * validator_start -> startfinddlvsep -> dlv_validator_start ->
71 * validator_start -> proveunsecure
73 * \li When called without a rdataset:
74 * validator_start -> nsecvalidate -> proveunsecure -> startfinddlvsep ->
75 * dlv_validator_start -> validator_start -> nsecvalidate -> proveunsecure
77 * Note: there isn't a case for DNS_VALIDATOR_DLV here as we want nsecvalidate()
78 * to always validate the authority section even when it does not contain
81 * validator_start: determines what type of validation to do.
82 * validate: attempts to perform a positive validation.
83 * proveunsecure: attempts to prove the answer comes from a unsecure zone.
84 * nsecvalidate: attempts to prove a negative response.
85 * startfinddlvsep: starts the DLV record lookup.
86 * dlv_validator_start: resets state and restarts the lookup using the
87 * DLV RRset found by startfinddlvsep.
90 #define VALIDATOR_MAGIC ISC_MAGIC('V', 'a', 'l', '?')
91 #define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
93 #define VALATTR_SHUTDOWN 0x0001 /*%< Shutting down. */
94 #define VALATTR_CANCELED 0x0002 /*%< Canceled. */
95 #define VALATTR_TRIEDVERIFY 0x0004 /*%< We have found a key and
96 * have attempted a verify. */
97 #define VALATTR_INSECURITY 0x0010 /*%< Attempting proveunsecure. */
98 #define VALATTR_DLVTRIED 0x0020 /*%< Looked for a DLV record. */
101 * NSEC proofs to be looked for.
103 #define VALATTR_NEEDNOQNAME 0x00000100
104 #define VALATTR_NEEDNOWILDCARD 0x00000200
105 #define VALATTR_NEEDNODATA 0x00000400
108 * NSEC proofs that have been found.
110 #define VALATTR_FOUNDNOQNAME 0x00001000
111 #define VALATTR_FOUNDNOWILDCARD 0x00002000
112 #define VALATTR_FOUNDNODATA 0x00004000
113 #define VALATTR_FOUNDCLOSEST 0x00008000
118 #define VALATTR_FOUNDOPTOUT 0x00010000
119 #define VALATTR_FOUNDUNKNOWN 0x00020000
121 #define NEEDNODATA(val) ((val->attributes & VALATTR_NEEDNODATA) != 0)
122 #define NEEDNOQNAME(val) ((val->attributes & VALATTR_NEEDNOQNAME) != 0)
123 #define NEEDNOWILDCARD(val) ((val->attributes & VALATTR_NEEDNOWILDCARD) != 0)
124 #define DLVTRIED(val) ((val->attributes & VALATTR_DLVTRIED) != 0)
126 #define SHUTDOWN(v) (((v)->attributes & VALATTR_SHUTDOWN) != 0)
127 #define CANCELED(v) (((v)->attributes & VALATTR_CANCELED) != 0)
130 destroy(dns_validator_t
*val
);
133 get_dst_key(dns_validator_t
*val
, dns_rdata_rrsig_t
*siginfo
,
134 dns_rdataset_t
*rdataset
);
137 validate(dns_validator_t
*val
, isc_boolean_t resume
);
140 validatezonekey(dns_validator_t
*val
);
143 nsecvalidate(dns_validator_t
*val
, isc_boolean_t resume
);
146 proveunsecure(dns_validator_t
*val
, isc_boolean_t have_ds
,
147 isc_boolean_t resume
);
150 validator_logv(dns_validator_t
*val
, isc_logcategory_t
*category
,
151 isc_logmodule_t
*module
, int level
, const char *fmt
, va_list ap
)
152 ISC_FORMAT_PRINTF(5, 0);
155 validator_log(dns_validator_t
*val
, int level
, const char *fmt
, ...)
156 ISC_FORMAT_PRINTF(3, 4);
159 validator_logcreate(dns_validator_t
*val
,
160 dns_name_t
*name
, dns_rdatatype_t type
,
161 const char *caller
, const char *operation
);
164 dlv_validatezonekey(dns_validator_t
*val
);
167 dlv_validator_start(dns_validator_t
*val
);
170 finddlvsep(dns_validator_t
*val
, isc_boolean_t resume
);
173 startfinddlvsep(dns_validator_t
*val
, dns_name_t
*unsecure
);
176 * Mark the RRsets as a answer.
179 markanswer(dns_validator_t
*val
) {
180 validator_log(val
, ISC_LOG_DEBUG(3), "marking as answer");
181 if (val
->event
->rdataset
!= NULL
)
182 val
->event
->rdataset
->trust
= dns_trust_answer
;
183 if (val
->event
->sigrdataset
!= NULL
)
184 val
->event
->sigrdataset
->trust
= dns_trust_answer
;
188 validator_done(dns_validator_t
*val
, isc_result_t result
) {
191 if (val
->event
== NULL
)
195 * Caller must be holding the lock.
198 val
->event
->result
= result
;
199 task
= val
->event
->ev_sender
;
200 val
->event
->ev_sender
= val
;
201 val
->event
->ev_type
= DNS_EVENT_VALIDATORDONE
;
202 val
->event
->ev_action
= val
->action
;
203 val
->event
->ev_arg
= val
->arg
;
204 isc_task_sendanddetach(&task
, (isc_event_t
**)&val
->event
);
207 static inline isc_boolean_t
208 exit_check(dns_validator_t
*val
) {
210 * Caller must be holding the lock.
215 INSIST(val
->event
== NULL
);
217 if (val
->fetch
!= NULL
|| val
->subvalidator
!= NULL
)
224 * Check that we have atleast one supported algorithm in the DLV RRset.
226 static inline isc_boolean_t
227 dlv_algorithm_supported(dns_validator_t
*val
) {
228 dns_rdata_t rdata
= DNS_RDATA_INIT
;
232 for (result
= dns_rdataset_first(&val
->dlv
);
233 result
== ISC_R_SUCCESS
;
234 result
= dns_rdataset_next(&val
->dlv
)) {
235 dns_rdata_reset(&rdata
);
236 dns_rdataset_current(&val
->dlv
, &rdata
);
237 result
= dns_rdata_tostruct(&rdata
, &dlv
, NULL
);
238 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
240 if (!dns_resolver_algorithm_supported(val
->view
->resolver
,
245 if (dlv
.digest_type
!= DNS_DSDIGEST_SHA256
&&
246 dlv
.digest_type
!= DNS_DSDIGEST_SHA1
)
255 * Look in the NSEC record returned from a DS query to see if there is
256 * a NS RRset at this name. If it is found we are at a delegation point.
259 isdelegation(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
260 isc_result_t dbresult
)
262 dns_fixedname_t fixed
;
263 dns_label_t hashlabel
;
264 dns_name_t nsec3name
;
265 dns_rdata_nsec3_t nsec3
;
266 dns_rdata_t rdata
= DNS_RDATA_INIT
;
273 unsigned char hash
[NSEC3_MAX_HASH_LENGTH
];
274 unsigned char owner
[NSEC3_MAX_HASH_LENGTH
];
277 REQUIRE(dbresult
== DNS_R_NXRRSET
|| dbresult
== DNS_R_NCACHENXRRSET
);
279 dns_rdataset_init(&set
);
280 if (dbresult
== DNS_R_NXRRSET
)
281 dns_rdataset_clone(rdataset
, &set
);
283 result
= dns_ncache_getrdataset(rdataset
, name
,
284 dns_rdatatype_nsec
, &set
);
285 if (result
== ISC_R_NOTFOUND
)
287 if (result
!= ISC_R_SUCCESS
)
291 INSIST(set
.type
== dns_rdatatype_nsec
);
294 result
= dns_rdataset_first(&set
);
295 if (result
== ISC_R_SUCCESS
) {
296 dns_rdataset_current(&set
, &rdata
);
297 found
= dns_nsec_typepresent(&rdata
, dns_rdatatype_ns
);
298 dns_rdata_reset(&rdata
);
300 dns_rdataset_disassociate(&set
);
305 * Iterate over the ncache entry.
308 dns_name_init(&nsec3name
, NULL
);
309 dns_fixedname_init(&fixed
);
310 dns_name_downcase(name
, dns_fixedname_name(&fixed
), NULL
);
311 name
= dns_fixedname_name(&fixed
);
312 result
= dns_rdataset_first(rdataset
);
313 for (result
= dns_rdataset_first(rdataset
);
314 result
== ISC_R_SUCCESS
;
315 result
= dns_rdataset_next(rdataset
))
317 dns_ncache_current(rdataset
, &nsec3name
, &set
);
318 if (set
.type
!= dns_rdatatype_nsec3
) {
319 dns_rdataset_disassociate(&set
);
322 dns_name_getlabel(&nsec3name
, 0, &hashlabel
);
323 isc_region_consume(&hashlabel
, 1);
324 isc_buffer_init(&buffer
, owner
, sizeof(owner
));
325 result
= isc_base32hex_decoderegion(&hashlabel
, &buffer
);
326 if (result
!= ISC_R_SUCCESS
) {
327 dns_rdataset_disassociate(&set
);
330 for (result
= dns_rdataset_first(&set
);
331 result
== ISC_R_SUCCESS
;
332 result
= dns_rdataset_next(&set
))
334 dns_rdata_reset(&rdata
);
335 dns_rdataset_current(&set
, &rdata
);
336 (void)dns_rdata_tostruct(&rdata
, &nsec3
, NULL
);
339 length
= isc_iterated_hash(hash
, nsec3
.hash
,
340 nsec3
.iterations
, nsec3
.salt
,
342 name
->ndata
, name
->length
);
343 if (length
!= isc_buffer_usedlength(&buffer
))
345 order
= memcmp(hash
, owner
, length
);
347 found
= dns_nsec3_typepresent(&rdata
,
349 dns_rdataset_disassociate(&set
);
352 if ((nsec3
.flags
& DNS_NSEC3FLAG_OPTOUT
) == 0)
355 * Does this optout span cover the name?
357 scope
= memcmp(owner
, nsec3
.next
, nsec3
.next_length
);
358 if ((scope
< 0 && order
> 0 &&
359 memcmp(hash
, nsec3
.next
, length
) < 0) ||
360 (scope
>= 0 && (order
> 0 ||
361 memcmp(hash
, nsec3
.next
, length
) < 0)))
363 dns_rdataset_disassociate(&set
);
367 dns_rdataset_disassociate(&set
);
373 * We have been asked to look for a key.
374 * If found resume the validation process.
375 * If not found fail the validation process.
378 fetch_callback_validator(isc_task_t
*task
, isc_event_t
*event
) {
379 dns_fetchevent_t
*devent
;
380 dns_validator_t
*val
;
381 dns_rdataset_t
*rdataset
;
382 isc_boolean_t want_destroy
;
384 isc_result_t eresult
;
387 INSIST(event
->ev_type
== DNS_EVENT_FETCHDONE
);
388 devent
= (dns_fetchevent_t
*)event
;
389 val
= devent
->ev_arg
;
390 rdataset
= &val
->frdataset
;
391 eresult
= devent
->result
;
393 /* Free resources which are not of interest. */
394 if (devent
->node
!= NULL
)
395 dns_db_detachnode(devent
->db
, &devent
->node
);
396 if (devent
->db
!= NULL
)
397 dns_db_detach(&devent
->db
);
398 if (dns_rdataset_isassociated(&val
->fsigrdataset
))
399 dns_rdataset_disassociate(&val
->fsigrdataset
);
400 isc_event_free(&event
);
401 dns_resolver_destroyfetch(&val
->fetch
);
403 INSIST(val
->event
!= NULL
);
405 validator_log(val
, ISC_LOG_DEBUG(3), "in fetch_callback_validator");
408 validator_done(val
, ISC_R_CANCELED
);
409 } else if (eresult
== ISC_R_SUCCESS
) {
410 validator_log(val
, ISC_LOG_DEBUG(3),
411 "keyset with trust %d", rdataset
->trust
);
413 * Only extract the dst key if the keyset is secure.
415 if (rdataset
->trust
>= dns_trust_secure
) {
416 result
= get_dst_key(val
, val
->siginfo
, rdataset
);
417 if (result
== ISC_R_SUCCESS
)
418 val
->keyset
= &val
->frdataset
;
420 result
= validate(val
, ISC_TRUE
);
421 if (result
!= DNS_R_WAIT
)
422 validator_done(val
, result
);
424 validator_log(val
, ISC_LOG_DEBUG(3),
425 "fetch_callback_validator: got %s",
426 isc_result_totext(eresult
));
427 if (eresult
== ISC_R_CANCELED
)
428 validator_done(val
, eresult
);
430 validator_done(val
, DNS_R_NOVALIDKEY
);
432 want_destroy
= exit_check(val
);
439 * We were asked to look for a DS record as part of following a key chain
440 * upwards. If found resume the validation process. If not found fail the
441 * validation process.
444 dsfetched(isc_task_t
*task
, isc_event_t
*event
) {
445 dns_fetchevent_t
*devent
;
446 dns_validator_t
*val
;
447 dns_rdataset_t
*rdataset
;
448 isc_boolean_t want_destroy
;
450 isc_result_t eresult
;
453 INSIST(event
->ev_type
== DNS_EVENT_FETCHDONE
);
454 devent
= (dns_fetchevent_t
*)event
;
455 val
= devent
->ev_arg
;
456 rdataset
= &val
->frdataset
;
457 eresult
= devent
->result
;
459 /* Free resources which are not of interest. */
460 if (devent
->node
!= NULL
)
461 dns_db_detachnode(devent
->db
, &devent
->node
);
462 if (devent
->db
!= NULL
)
463 dns_db_detach(&devent
->db
);
464 if (dns_rdataset_isassociated(&val
->fsigrdataset
))
465 dns_rdataset_disassociate(&val
->fsigrdataset
);
466 isc_event_free(&event
);
467 dns_resolver_destroyfetch(&val
->fetch
);
469 INSIST(val
->event
!= NULL
);
471 validator_log(val
, ISC_LOG_DEBUG(3), "in dsfetched");
474 validator_done(val
, ISC_R_CANCELED
);
475 } else if (eresult
== ISC_R_SUCCESS
) {
476 validator_log(val
, ISC_LOG_DEBUG(3),
477 "dsset with trust %d", rdataset
->trust
);
478 val
->dsset
= &val
->frdataset
;
479 result
= validatezonekey(val
);
480 if (result
!= DNS_R_WAIT
)
481 validator_done(val
, result
);
482 } else if (eresult
== DNS_R_NXRRSET
||
483 eresult
== DNS_R_NCACHENXRRSET
||
484 eresult
== DNS_R_SERVFAIL
) /* RFC 1034 parent? */
486 validator_log(val
, ISC_LOG_DEBUG(3),
487 "falling back to insecurity proof (%s)",
488 dns_result_totext(eresult
));
489 val
->attributes
|= VALATTR_INSECURITY
;
490 result
= proveunsecure(val
, ISC_FALSE
, ISC_FALSE
);
491 if (result
!= DNS_R_WAIT
)
492 validator_done(val
, result
);
494 validator_log(val
, ISC_LOG_DEBUG(3),
496 isc_result_totext(eresult
));
497 if (eresult
== ISC_R_CANCELED
)
498 validator_done(val
, eresult
);
500 validator_done(val
, DNS_R_NOVALIDDS
);
502 want_destroy
= exit_check(val
);
509 * We were asked to look for the DS record as part of proving that a
512 * If the DS record doesn't exist and the query name corresponds to
513 * a delegation point we are transitioning from a secure zone to a
516 * If the DS record exists it will be secure. We can continue looking
517 * for the break point in the chain of trust.
520 dsfetched2(isc_task_t
*task
, isc_event_t
*event
) {
521 dns_fetchevent_t
*devent
;
522 dns_validator_t
*val
;
524 isc_boolean_t want_destroy
;
526 isc_result_t eresult
;
529 INSIST(event
->ev_type
== DNS_EVENT_FETCHDONE
);
530 devent
= (dns_fetchevent_t
*)event
;
531 val
= devent
->ev_arg
;
532 eresult
= devent
->result
;
534 /* Free resources which are not of interest. */
535 if (devent
->node
!= NULL
)
536 dns_db_detachnode(devent
->db
, &devent
->node
);
537 if (devent
->db
!= NULL
)
538 dns_db_detach(&devent
->db
);
539 if (dns_rdataset_isassociated(&val
->fsigrdataset
))
540 dns_rdataset_disassociate(&val
->fsigrdataset
);
541 dns_resolver_destroyfetch(&val
->fetch
);
543 INSIST(val
->event
!= NULL
);
545 validator_log(val
, ISC_LOG_DEBUG(3), "in dsfetched2: %s",
546 dns_result_totext(eresult
));
549 validator_done(val
, ISC_R_CANCELED
);
550 } else if (eresult
== DNS_R_NXRRSET
|| eresult
== DNS_R_NCACHENXRRSET
) {
552 * There is no DS. If this is a delegation, we're done.
554 tname
= dns_fixedname_name(&devent
->foundname
);
555 if (isdelegation(tname
, &val
->frdataset
, eresult
)) {
556 if (val
->mustbesecure
) {
557 validator_log(val
, ISC_LOG_WARNING
,
558 "must be secure failure, no DS"
559 " and this is a delegation");
560 validator_done(val
, DNS_R_MUSTBESECURE
);
561 } else if (val
->view
->dlv
== NULL
|| DLVTRIED(val
)) {
563 validator_done(val
, ISC_R_SUCCESS
);
565 result
= startfinddlvsep(val
, tname
);
566 if (result
!= DNS_R_WAIT
)
567 validator_done(val
, result
);
570 result
= proveunsecure(val
, ISC_FALSE
, ISC_TRUE
);
571 if (result
!= DNS_R_WAIT
)
572 validator_done(val
, result
);
574 } else if (eresult
== ISC_R_SUCCESS
||
575 eresult
== DNS_R_NXDOMAIN
||
576 eresult
== DNS_R_NCACHENXDOMAIN
)
579 * There is a DS which may or may not be a zone cut.
580 * In either case we are still in a secure zone resume
583 result
= proveunsecure(val
, ISC_TF(eresult
== ISC_R_SUCCESS
),
585 if (result
!= DNS_R_WAIT
)
586 validator_done(val
, result
);
588 if (eresult
== ISC_R_CANCELED
)
589 validator_done(val
, eresult
);
591 validator_done(val
, DNS_R_NOVALIDDS
);
593 isc_event_free(&event
);
594 want_destroy
= exit_check(val
);
601 * Callback from when a DNSKEY RRset has been validated.
603 * Resumes the stalled validation process.
606 keyvalidated(isc_task_t
*task
, isc_event_t
*event
) {
607 dns_validatorevent_t
*devent
;
608 dns_validator_t
*val
;
609 isc_boolean_t want_destroy
;
611 isc_result_t eresult
;
614 INSIST(event
->ev_type
== DNS_EVENT_VALIDATORDONE
);
616 devent
= (dns_validatorevent_t
*)event
;
617 val
= devent
->ev_arg
;
618 eresult
= devent
->result
;
620 isc_event_free(&event
);
621 dns_validator_destroy(&val
->subvalidator
);
623 INSIST(val
->event
!= NULL
);
625 validator_log(val
, ISC_LOG_DEBUG(3), "in keyvalidated");
628 validator_done(val
, ISC_R_CANCELED
);
629 } else if (eresult
== ISC_R_SUCCESS
) {
630 validator_log(val
, ISC_LOG_DEBUG(3),
631 "keyset with trust %d", val
->frdataset
.trust
);
633 * Only extract the dst key if the keyset is secure.
635 if (val
->frdataset
.trust
>= dns_trust_secure
)
636 (void) get_dst_key(val
, val
->siginfo
, &val
->frdataset
);
637 result
= validate(val
, ISC_TRUE
);
638 if (result
!= DNS_R_WAIT
)
639 validator_done(val
, result
);
641 validator_log(val
, ISC_LOG_DEBUG(3),
642 "keyvalidated: got %s",
643 isc_result_totext(eresult
));
644 validator_done(val
, eresult
);
646 want_destroy
= exit_check(val
);
653 * Callback when the DS record has been validated.
655 * Resumes validation of the zone key or the unsecure zone proof.
658 dsvalidated(isc_task_t
*task
, isc_event_t
*event
) {
659 dns_validatorevent_t
*devent
;
660 dns_validator_t
*val
;
661 isc_boolean_t want_destroy
;
663 isc_result_t eresult
;
666 INSIST(event
->ev_type
== DNS_EVENT_VALIDATORDONE
);
668 devent
= (dns_validatorevent_t
*)event
;
669 val
= devent
->ev_arg
;
670 eresult
= devent
->result
;
672 isc_event_free(&event
);
673 dns_validator_destroy(&val
->subvalidator
);
675 INSIST(val
->event
!= NULL
);
677 validator_log(val
, ISC_LOG_DEBUG(3), "in dsvalidated");
680 validator_done(val
, ISC_R_CANCELED
);
681 } else if (eresult
== ISC_R_SUCCESS
) {
682 validator_log(val
, ISC_LOG_DEBUG(3),
683 "dsset with trust %d", val
->frdataset
.trust
);
684 if ((val
->attributes
& VALATTR_INSECURITY
) != 0)
685 result
= proveunsecure(val
, ISC_TRUE
, ISC_TRUE
);
687 result
= validatezonekey(val
);
688 if (result
!= DNS_R_WAIT
)
689 validator_done(val
, result
);
691 validator_log(val
, ISC_LOG_DEBUG(3),
692 "dsvalidated: got %s",
693 isc_result_totext(eresult
));
694 validator_done(val
, eresult
);
696 want_destroy
= exit_check(val
);
703 * Return ISC_R_SUCCESS if we can determine that the name doesn't exist
704 * or we can determine whether there is data or not at the name.
705 * If the name does not exist return the wildcard name.
707 * Return ISC_R_IGNORE when the NSEC is not the appropriate one.
710 nsecnoexistnodata(dns_validator_t
*val
, dns_name_t
* name
, dns_name_t
*nsecname
,
711 dns_rdataset_t
*nsecset
, isc_boolean_t
*exists
,
712 isc_boolean_t
*data
, dns_name_t
*wild
)
715 dns_rdata_t rdata
= DNS_RDATA_INIT
;
717 dns_namereln_t relation
;
718 unsigned int olabels
, nlabels
, labels
;
719 dns_rdata_nsec_t nsec
;
720 isc_boolean_t atparent
;
724 REQUIRE(exists
!= NULL
);
725 REQUIRE(data
!= NULL
);
726 REQUIRE(nsecset
!= NULL
&&
727 nsecset
->type
== dns_rdatatype_nsec
);
729 result
= dns_rdataset_first(nsecset
);
730 if (result
!= ISC_R_SUCCESS
) {
731 validator_log(val
, ISC_LOG_DEBUG(3),
732 "failure processing NSEC set");
735 dns_rdataset_current(nsecset
, &rdata
);
737 validator_log(val
, ISC_LOG_DEBUG(3), "looking for relevant nsec");
738 relation
= dns_name_fullcompare(name
, nsecname
, &order
, &olabels
);
742 * The name is not within the NSEC range.
744 validator_log(val
, ISC_LOG_DEBUG(3),
745 "NSEC does not cover name, before NSEC");
746 return (ISC_R_IGNORE
);
751 * The names are the same.
753 atparent
= dns_rdatatype_atparent(val
->event
->type
);
754 ns
= dns_nsec_typepresent(&rdata
, dns_rdatatype_ns
);
755 soa
= dns_nsec_typepresent(&rdata
, dns_rdatatype_soa
);
759 * This NSEC record is from somewhere higher in
760 * the DNS, and at the parent of a delegation.
761 * It can not be legitimately used here.
763 validator_log(val
, ISC_LOG_DEBUG(3),
764 "ignoring parent nsec");
765 return (ISC_R_IGNORE
);
767 } else if (atparent
&& ns
&& soa
) {
769 * This NSEC record is from the child.
770 * It can not be legitimately used here.
772 validator_log(val
, ISC_LOG_DEBUG(3),
773 "ignoring child nsec");
774 return (ISC_R_IGNORE
);
776 if (val
->event
->type
== dns_rdatatype_cname
||
777 val
->event
->type
== dns_rdatatype_nxt
||
778 val
->event
->type
== dns_rdatatype_nsec
||
779 val
->event
->type
== dns_rdatatype_key
||
780 !dns_nsec_typepresent(&rdata
, dns_rdatatype_cname
)) {
782 *data
= dns_nsec_typepresent(&rdata
, val
->event
->type
);
783 validator_log(val
, ISC_LOG_DEBUG(3),
784 "nsec proves name exists (owner) data=%d",
786 return (ISC_R_SUCCESS
);
788 validator_log(val
, ISC_LOG_DEBUG(3), "NSEC proves CNAME exists");
789 return (ISC_R_IGNORE
);
792 if (relation
== dns_namereln_subdomain
&&
793 dns_nsec_typepresent(&rdata
, dns_rdatatype_ns
) &&
794 !dns_nsec_typepresent(&rdata
, dns_rdatatype_soa
))
797 * This NSEC record is from somewhere higher in
798 * the DNS, and at the parent of a delegation.
799 * It can not be legitimately used here.
801 validator_log(val
, ISC_LOG_DEBUG(3), "ignoring parent nsec");
802 return (ISC_R_IGNORE
);
805 result
= dns_rdata_tostruct(&rdata
, &nsec
, NULL
);
806 if (result
!= ISC_R_SUCCESS
)
808 relation
= dns_name_fullcompare(&nsec
.next
, name
, &order
, &nlabels
);
810 dns_rdata_freestruct(&nsec
);
811 validator_log(val
, ISC_LOG_DEBUG(3),
812 "ignoring nsec matches next name");
813 return (ISC_R_IGNORE
);
816 if (order
< 0 && !dns_name_issubdomain(nsecname
, &nsec
.next
)) {
818 * The name is not within the NSEC range.
820 dns_rdata_freestruct(&nsec
);
821 validator_log(val
, ISC_LOG_DEBUG(3),
822 "ignoring nsec because name is past end of range");
823 return (ISC_R_IGNORE
);
826 if (order
> 0 && relation
== dns_namereln_subdomain
) {
827 validator_log(val
, ISC_LOG_DEBUG(3),
828 "nsec proves name exist (empty)");
829 dns_rdata_freestruct(&nsec
);
832 return (ISC_R_SUCCESS
);
836 dns_name_init(&common
, NULL
);
837 if (olabels
> nlabels
) {
838 labels
= dns_name_countlabels(nsecname
);
839 dns_name_getlabelsequence(nsecname
, labels
- olabels
,
842 labels
= dns_name_countlabels(&nsec
.next
);
843 dns_name_getlabelsequence(&nsec
.next
, labels
- nlabels
,
846 result
= dns_name_concatenate(dns_wildcardname
, &common
,
848 if (result
!= ISC_R_SUCCESS
) {
849 dns_rdata_freestruct(&nsec
);
850 validator_log(val
, ISC_LOG_DEBUG(3),
851 "failure generating wildcard name");
855 dns_rdata_freestruct(&nsec
);
856 validator_log(val
, ISC_LOG_DEBUG(3), "nsec range ok");
858 return (ISC_R_SUCCESS
);
862 nsec3noexistnodata(dns_validator_t
*val
, dns_name_t
* name
,
863 dns_name_t
*nsec3name
, dns_rdataset_t
*nsec3set
,
864 dns_name_t
*zonename
, isc_boolean_t
*exists
,
865 isc_boolean_t
*data
, isc_boolean_t
*optout
,
866 isc_boolean_t
*unknown
, isc_boolean_t
*setclosest
,
867 isc_boolean_t
*setnearest
, dns_name_t
*closest
,
870 char namebuf
[DNS_NAME_FORMATSIZE
];
871 dns_fixedname_t fzone
;
872 dns_fixedname_t qfixed
;
873 dns_label_t hashlabel
;
876 dns_rdata_nsec3_t nsec3
;
877 dns_rdata_t rdata
= DNS_RDATA_INIT
;
880 isc_boolean_t atparent
;
885 isc_result_t answer
= ISC_R_IGNORE
;
887 unsigned char hash
[NSEC3_MAX_HASH_LENGTH
];
888 unsigned char owner
[NSEC3_MAX_HASH_LENGTH
];
890 unsigned int qlabels
;
891 unsigned int zlabels
;
893 REQUIRE((exists
== NULL
&& data
== NULL
) ||
894 (exists
!= NULL
&& data
!= NULL
));
895 REQUIRE(nsec3set
!= NULL
&& nsec3set
->type
== dns_rdatatype_nsec3
);
896 REQUIRE((setclosest
== NULL
&& closest
== NULL
) ||
897 (setclosest
!= NULL
&& closest
!= NULL
));
898 REQUIRE((setnearest
== NULL
&& nearest
== NULL
) ||
899 (setnearest
!= NULL
&& nearest
!= NULL
));
901 result
= dns_rdataset_first(nsec3set
);
902 if (result
!= ISC_R_SUCCESS
) {
903 validator_log(val
, ISC_LOG_DEBUG(3),
904 "failure processing NSEC3 set");
908 dns_rdataset_current(nsec3set
, &rdata
);
910 result
= dns_rdata_tostruct(&rdata
, &nsec3
, NULL
);
911 if (result
!= ISC_R_SUCCESS
)
914 validator_log(val
, ISC_LOG_DEBUG(3), "looking for relevant NSEC3");
916 dns_fixedname_init(&fzone
);
917 zone
= dns_fixedname_name(&fzone
);
918 zlabels
= dns_name_countlabels(nsec3name
);
921 * NSEC3 records must have two or more labels to be valid.
924 return (ISC_R_IGNORE
);
927 * Strip off the NSEC3 hash to get the zone.
930 dns_name_split(nsec3name
, zlabels
, NULL
, zone
);
933 * If not below the zone name we can ignore this record.
935 if (!dns_name_issubdomain(name
, zone
))
936 return (ISC_R_IGNORE
);
939 * Is this zone the same or deeper than the current zone?
941 if (dns_name_countlabels(zonename
) == 0 ||
942 dns_name_issubdomain(zone
, zonename
))
943 dns_name_copy(zone
, zonename
, NULL
);
945 if (!dns_name_equal(zone
, zonename
))
946 return (ISC_R_IGNORE
);
949 * Are we only looking for the most enclosing zone?
951 if (exists
== NULL
|| data
== NULL
)
952 return (ISC_R_SUCCESS
);
955 * Only set unknown once we are sure that this NSEC3 is from
956 * the deepest covering zone.
958 if (!dns_nsec3_supportedhash(nsec3
.hash
)) {
961 return (ISC_R_IGNORE
);
965 * Recover the hash from the first label.
967 dns_name_getlabel(nsec3name
, 0, &hashlabel
);
968 isc_region_consume(&hashlabel
, 1);
969 isc_buffer_init(&buffer
, owner
, sizeof(owner
));
970 result
= isc_base32hex_decoderegion(&hashlabel
, &buffer
);
971 if (result
!= ISC_R_SUCCESS
)
975 * The hash lengths should match. If not ignore the record.
977 if (isc_buffer_usedlength(&buffer
) != nsec3
.next_length
)
978 return (ISC_R_IGNORE
);
981 * Work out what this NSEC3 covers.
982 * Inside (<0) or outside (>=0).
984 scope
= memcmp(owner
, nsec3
.next
, nsec3
.next_length
);
987 * Prepare to compute all the hashes.
989 dns_fixedname_init(&qfixed
);
990 qname
= dns_fixedname_name(&qfixed
);
991 dns_name_downcase(name
, qname
, NULL
);
992 qlabels
= dns_name_countlabels(qname
);
995 while (qlabels
>= zlabels
) {
996 length
= isc_iterated_hash(hash
, nsec3
.hash
, nsec3
.iterations
,
997 nsec3
.salt
, nsec3
.salt_length
,
998 qname
->ndata
, qname
->length
);
1000 * The computed hash length should match.
1002 if (length
!= nsec3
.next_length
) {
1003 validator_log(val
, ISC_LOG_DEBUG(3),
1004 "ignoring NSEC bad length %u vs %u",
1005 length
, nsec3
.next_length
);
1006 return (ISC_R_IGNORE
);
1009 order
= memcmp(hash
, owner
, length
);
1010 if (first
&& order
== 0) {
1012 * The hashes are the same.
1014 atparent
= dns_rdatatype_atparent(val
->event
->type
);
1015 ns
= dns_nsec3_typepresent(&rdata
, dns_rdatatype_ns
);
1016 soa
= dns_nsec3_typepresent(&rdata
, dns_rdatatype_soa
);
1020 * This NSEC3 record is from somewhere
1021 * higher in the DNS, and at the
1022 * parent of a delegation. It can not
1023 * be legitimately used here.
1025 validator_log(val
, ISC_LOG_DEBUG(3),
1026 "ignoring parent NSEC3");
1027 return (ISC_R_IGNORE
);
1029 } else if (atparent
&& ns
&& soa
) {
1031 * This NSEC3 record is from the child.
1032 * It can not be legitimately used here.
1034 validator_log(val
, ISC_LOG_DEBUG(3),
1035 "ignoring child NSEC3");
1036 return (ISC_R_IGNORE
);
1038 if (val
->event
->type
== dns_rdatatype_cname
||
1039 val
->event
->type
== dns_rdatatype_nxt
||
1040 val
->event
->type
== dns_rdatatype_nsec
||
1041 val
->event
->type
== dns_rdatatype_key
||
1042 !dns_nsec3_typepresent(&rdata
, dns_rdatatype_cname
)) {
1044 *data
= dns_nsec3_typepresent(&rdata
,
1046 validator_log(val
, ISC_LOG_DEBUG(3),
1047 "NSEC3 proves name exists (owner) "
1049 return (ISC_R_SUCCESS
);
1051 validator_log(val
, ISC_LOG_DEBUG(3),
1052 "NSEC3 proves CNAME exists");
1053 return (ISC_R_IGNORE
);
1057 dns_nsec3_typepresent(&rdata
, dns_rdatatype_ns
) &&
1058 !dns_nsec3_typepresent(&rdata
, dns_rdatatype_soa
))
1061 * This NSEC3 record is from somewhere higher in
1062 * the DNS, and at the parent of a delegation.
1063 * It can not be legitimately used here.
1065 validator_log(val
, ISC_LOG_DEBUG(3),
1066 "ignoring parent NSEC3");
1067 return (ISC_R_IGNORE
);
1071 * Potential closest encloser.
1074 if (closest
!= NULL
&&
1075 (dns_name_countlabels(closest
) == 0 ||
1076 dns_name_issubdomain(qname
, closest
)) &&
1077 !dns_nsec3_typepresent(&rdata
, dns_rdatatype_ds
) &&
1078 !dns_nsec3_typepresent(&rdata
, dns_rdatatype_dname
) &&
1079 (dns_nsec3_typepresent(&rdata
, dns_rdatatype_soa
) ||
1080 !dns_nsec3_typepresent(&rdata
, dns_rdatatype_ns
)))
1083 dns_name_format(qname
, namebuf
,
1085 validator_log(val
, ISC_LOG_DEBUG(3),
1086 "NSEC3 indicates potential "
1087 "closest encloser: '%s'",
1089 dns_name_copy(qname
, closest
, NULL
);
1090 *setclosest
= ISC_TRUE
;
1092 dns_name_format(qname
, namebuf
, sizeof(namebuf
));
1093 validator_log(val
, ISC_LOG_DEBUG(3),
1094 "NSEC3 at super-domain %s", namebuf
);
1099 * Find if the name does not exist.
1101 * We continue as we need to find the name closest to the
1102 * closest encloser that doesn't exist.
1104 * We also need to continue to ensure that we are not
1105 * proving the non-existence of a record in a sub-zone.
1106 * If that would be the case we will return ISC_R_IGNORE
1109 if ((scope
< 0 && order
> 0 &&
1110 memcmp(hash
, nsec3
.next
, length
) < 0) ||
1111 (scope
>= 0 && (order
> 0 ||
1112 memcmp(hash
, nsec3
.next
, length
) < 0)))
1114 char namebuf
[DNS_NAME_FORMATSIZE
];
1116 dns_name_format(qname
, namebuf
, sizeof(namebuf
));
1117 validator_log(val
, ISC_LOG_DEBUG(3), "NSEC3 proves "
1118 "name does not exist: '%s'", namebuf
);
1119 if (nearest
!= NULL
&&
1120 (dns_name_countlabels(nearest
) == 0 ||
1121 dns_name_issubdomain(nearest
, qname
))) {
1122 dns_name_copy(qname
, nearest
, NULL
);
1123 *setnearest
= ISC_TRUE
;
1127 * The closest encloser may be the zone name.
1129 if (closest
!= NULL
&&
1130 dns_name_countlabels(closest
) == 0 &&
1131 !dns_nsec3_typepresent(&rdata
, dns_rdatatype_ds
) &&
1132 !dns_nsec3_typepresent(&rdata
, dns_rdatatype_dname
) &&
1133 (dns_nsec3_typepresent(&rdata
, dns_rdatatype_soa
) ||
1134 !dns_nsec3_typepresent(&rdata
, dns_rdatatype_ns
)))
1136 char namebuf
[DNS_NAME_FORMATSIZE
];
1138 dns_name_format(zone
, namebuf
,
1140 validator_log(val
, ISC_LOG_DEBUG(3),
1141 "NSEC3 potential closest "
1142 "encloser from zone name: '%s'",
1144 dns_name_copy(zone
, closest
, NULL
);
1145 *setclosest
= ISC_TRUE
;
1148 *exists
= ISC_FALSE
;
1150 if (optout
!= NULL
) {
1151 if ((nsec3
.flags
& DNS_NSEC3FLAG_OPTOUT
) != 0)
1152 validator_log(val
, ISC_LOG_DEBUG(3),
1153 "NSEC3 indicates optout");
1155 ISC_TF(nsec3
.flags
& DNS_NSEC3FLAG_OPTOUT
);
1157 answer
= ISC_R_SUCCESS
;
1162 dns_name_split(qname
, qlabels
, NULL
, qname
);
1169 * Callback for when NSEC records have been validated.
1171 * Looks for NOQNAME, NODATA and OPTOUT proofs.
1173 * Resumes nsecvalidate.
1176 authvalidated(isc_task_t
*task
, isc_event_t
*event
) {
1177 dns_validatorevent_t
*devent
;
1178 dns_validator_t
*val
;
1179 dns_rdataset_t
*rdataset
;
1180 dns_rdataset_t
*sigrdataset
;
1181 isc_boolean_t want_destroy
;
1182 isc_result_t result
;
1183 isc_boolean_t exists
, data
;
1186 INSIST(event
->ev_type
== DNS_EVENT_VALIDATORDONE
);
1188 devent
= (dns_validatorevent_t
*)event
;
1189 rdataset
= devent
->rdataset
;
1190 sigrdataset
= devent
->sigrdataset
;
1191 val
= devent
->ev_arg
;
1192 result
= devent
->result
;
1193 dns_validator_destroy(&val
->subvalidator
);
1195 INSIST(val
->event
!= NULL
);
1197 validator_log(val
, ISC_LOG_DEBUG(3), "in authvalidated");
1199 if (CANCELED(val
)) {
1200 validator_done(val
, ISC_R_CANCELED
);
1201 } else if (result
!= ISC_R_SUCCESS
) {
1202 validator_log(val
, ISC_LOG_DEBUG(3),
1203 "authvalidated: got %s",
1204 isc_result_totext(result
));
1205 if (result
== ISC_R_CANCELED
)
1206 validator_done(val
, result
);
1208 result
= nsecvalidate(val
, ISC_TRUE
);
1209 if (result
!= DNS_R_WAIT
)
1210 validator_done(val
, result
);
1213 dns_name_t
**proofs
= val
->event
->proofs
;
1214 dns_name_t
*wild
= dns_fixedname_name(&val
->wild
);
1216 if (rdataset
->trust
== dns_trust_secure
)
1217 val
->seensig
= ISC_TRUE
;
1219 if (rdataset
->type
== dns_rdatatype_nsec
&&
1220 rdataset
->trust
== dns_trust_secure
&&
1221 ((val
->attributes
& VALATTR_NEEDNODATA
) != 0 ||
1222 (val
->attributes
& VALATTR_NEEDNOQNAME
) != 0) &&
1223 (val
->attributes
& VALATTR_FOUNDNODATA
) == 0 &&
1224 (val
->attributes
& VALATTR_FOUNDNOQNAME
) == 0 &&
1225 nsecnoexistnodata(val
, val
->event
->name
, devent
->name
,
1226 rdataset
, &exists
, &data
, wild
)
1229 if (exists
&& !data
) {
1230 val
->attributes
|= VALATTR_FOUNDNODATA
;
1231 if (NEEDNODATA(val
))
1232 proofs
[DNS_VALIDATOR_NODATAPROOF
] =
1236 val
->attributes
|= VALATTR_FOUNDNOQNAME
;
1237 val
->attributes
|= VALATTR_FOUNDCLOSEST
;
1239 * The NSEC noqname proof also contains
1240 * the closest encloser.
1243 if (NEEDNOQNAME(val
))
1244 proofs
[DNS_VALIDATOR_NOQNAMEPROOF
] =
1249 result
= nsecvalidate(val
, ISC_TRUE
);
1250 if (result
!= DNS_R_WAIT
)
1251 validator_done(val
, result
);
1253 want_destroy
= exit_check(val
);
1259 * Free stuff from the event.
1261 isc_event_free(&event
);
1265 * Looks for the requested name and type in the view (zones and cache).
1267 * When looking for a DLV record also checks to make sure the NSEC record
1268 * returns covers the query name as part of aggressive negative caching.
1272 * \li ISC_R_NOTFOUND
1273 * \li DNS_R_NCACHENXDOMAIN
1274 * \li DNS_R_NCACHENXRRSET
1276 * \li DNS_R_NXDOMAIN
1278 static inline isc_result_t
1279 view_find(dns_validator_t
*val
, dns_name_t
*name
, dns_rdatatype_t type
) {
1280 dns_fixedname_t fixedname
;
1281 dns_name_t
*foundname
;
1282 dns_rdata_nsec_t nsec
;
1283 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1284 isc_result_t result
;
1285 unsigned int options
;
1286 char buf1
[DNS_NAME_FORMATSIZE
];
1287 char buf2
[DNS_NAME_FORMATSIZE
];
1288 char buf3
[DNS_NAME_FORMATSIZE
];
1290 if (dns_rdataset_isassociated(&val
->frdataset
))
1291 dns_rdataset_disassociate(&val
->frdataset
);
1292 if (dns_rdataset_isassociated(&val
->fsigrdataset
))
1293 dns_rdataset_disassociate(&val
->fsigrdataset
);
1295 if (val
->view
->zonetable
== NULL
)
1296 return (ISC_R_CANCELED
);
1298 options
= DNS_DBFIND_PENDINGOK
;
1299 if (type
== dns_rdatatype_dlv
)
1300 options
|= DNS_DBFIND_COVERINGNSEC
;
1301 dns_fixedname_init(&fixedname
);
1302 foundname
= dns_fixedname_name(&fixedname
);
1303 result
= dns_view_find(val
->view
, name
, type
, 0, options
,
1304 ISC_FALSE
, NULL
, NULL
, foundname
,
1305 &val
->frdataset
, &val
->fsigrdataset
);
1306 if (result
== DNS_R_NXDOMAIN
) {
1307 if (dns_rdataset_isassociated(&val
->frdataset
))
1308 dns_rdataset_disassociate(&val
->frdataset
);
1309 if (dns_rdataset_isassociated(&val
->fsigrdataset
))
1310 dns_rdataset_disassociate(&val
->fsigrdataset
);
1311 } else if (result
== DNS_R_COVERINGNSEC
) {
1312 validator_log(val
, ISC_LOG_DEBUG(3), "DNS_R_COVERINGNSEC");
1314 * Check if the returned NSEC covers the name.
1316 INSIST(type
== dns_rdatatype_dlv
);
1317 if (val
->frdataset
.trust
!= dns_trust_secure
) {
1318 validator_log(val
, ISC_LOG_DEBUG(3),
1319 "covering nsec: trust %u",
1320 val
->frdataset
.trust
);
1323 result
= dns_rdataset_first(&val
->frdataset
);
1324 if (result
!= ISC_R_SUCCESS
)
1326 dns_rdataset_current(&val
->frdataset
, &rdata
);
1327 if (dns_nsec_typepresent(&rdata
, dns_rdatatype_ns
) &&
1328 !dns_nsec_typepresent(&rdata
, dns_rdatatype_soa
)) {
1329 /* Parent NSEC record. */
1330 if (dns_name_issubdomain(name
, foundname
)) {
1331 validator_log(val
, ISC_LOG_DEBUG(3),
1332 "covering nsec: for parent");
1336 result
= dns_rdata_tostruct(&rdata
, &nsec
, NULL
);
1337 if (result
!= ISC_R_SUCCESS
)
1339 if (dns_name_compare(foundname
, &nsec
.next
) >= 0) {
1340 /* End of zone chain. */
1341 if (!dns_name_issubdomain(name
, &nsec
.next
)) {
1343 * XXXMPA We could look for a parent NSEC
1344 * at nsec.next and if found retest with
1347 dns_rdata_freestruct(&nsec
);
1348 validator_log(val
, ISC_LOG_DEBUG(3),
1349 "covering nsec: not in zone");
1352 } else if (dns_name_compare(name
, &nsec
.next
) >= 0) {
1354 * XXXMPA We could check if this NSEC is at a zone
1355 * apex and if the qname is not below it and look for
1356 * a parent NSEC with the same name. This requires
1357 * that we can cache both NSEC records which we
1358 * currently don't support.
1360 dns_rdata_freestruct(&nsec
);
1361 validator_log(val
, ISC_LOG_DEBUG(3),
1362 "covering nsec: not in range");
1365 if (isc_log_wouldlog(dns_lctx
,ISC_LOG_DEBUG(3))) {
1366 dns_name_format(name
, buf1
, sizeof buf1
);
1367 dns_name_format(foundname
, buf2
, sizeof buf2
);
1368 dns_name_format(&nsec
.next
, buf3
, sizeof buf3
);
1369 validator_log(val
, ISC_LOG_DEBUG(3),
1370 "covering nsec found: '%s' '%s' '%s'",
1373 if (dns_rdataset_isassociated(&val
->frdataset
))
1374 dns_rdataset_disassociate(&val
->frdataset
);
1375 if (dns_rdataset_isassociated(&val
->fsigrdataset
))
1376 dns_rdataset_disassociate(&val
->fsigrdataset
);
1377 dns_rdata_freestruct(&nsec
);
1378 result
= DNS_R_NCACHENXDOMAIN
;
1379 } else if (result
!= ISC_R_SUCCESS
&&
1380 result
!= DNS_R_NCACHENXDOMAIN
&&
1381 result
!= DNS_R_NCACHENXRRSET
&&
1382 result
!= DNS_R_EMPTYNAME
&&
1383 result
!= DNS_R_NXRRSET
&&
1384 result
!= ISC_R_NOTFOUND
) {
1390 if (dns_rdataset_isassociated(&val
->frdataset
))
1391 dns_rdataset_disassociate(&val
->frdataset
);
1392 if (dns_rdataset_isassociated(&val
->fsigrdataset
))
1393 dns_rdataset_disassociate(&val
->fsigrdataset
);
1394 return (ISC_R_NOTFOUND
);
1398 * Checks to make sure we are not going to loop. As we use a SHARED fetch
1399 * the validation process will stall if looping was to occur.
1401 static inline isc_boolean_t
1402 check_deadlock(dns_validator_t
*val
, dns_name_t
*name
, dns_rdatatype_t type
,
1403 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
)
1405 dns_validator_t
*parent
;
1407 for (parent
= val
; parent
!= NULL
; parent
= parent
->parent
) {
1408 if (parent
->event
!= NULL
&&
1409 parent
->event
->type
== type
&&
1410 dns_name_equal(parent
->event
->name
, name
) &&
1412 * As NSEC3 records are meta data you sometimes
1413 * need to prove a NSEC3 record which says that
1414 * itself doesn't exist.
1416 (parent
->event
->type
!= dns_rdatatype_nsec3
||
1417 rdataset
== NULL
|| sigrdataset
== NULL
||
1418 parent
->event
->message
== NULL
||
1419 parent
->event
->rdataset
!= NULL
||
1420 parent
->event
->sigrdataset
!= NULL
))
1422 validator_log(val
, ISC_LOG_DEBUG(3),
1423 "continuing validation would lead to "
1424 "deadlock: aborting validation");
1432 * Start a fetch for the requested name and type.
1434 static inline isc_result_t
1435 create_fetch(dns_validator_t
*val
, dns_name_t
*name
, dns_rdatatype_t type
,
1436 isc_taskaction_t callback
, const char *caller
)
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
);
1443 if (check_deadlock(val
, name
, type
, NULL
, NULL
)) {
1444 validator_log(val
, ISC_LOG_DEBUG(3),
1445 "deadlock found (create_fetch)");
1446 return (DNS_R_NOVALIDSIG
);
1449 validator_logcreate(val
, name
, type
, caller
, "fetch");
1450 return (dns_resolver_createfetch(val
->view
->resolver
, name
, type
,
1451 NULL
, NULL
, NULL
, 0,
1452 val
->event
->ev_sender
,
1460 * Start a subvalidation process.
1462 static inline isc_result_t
1463 create_validator(dns_validator_t
*val
, dns_name_t
*name
, dns_rdatatype_t type
,
1464 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
,
1465 isc_taskaction_t action
, const char *caller
)
1467 isc_result_t result
;
1469 if (check_deadlock(val
, name
, type
, rdataset
, sigrdataset
)) {
1470 validator_log(val
, ISC_LOG_DEBUG(3),
1471 "deadlock found (create_validator)");
1472 return (DNS_R_NOVALIDSIG
);
1475 validator_logcreate(val
, name
, type
, caller
, "validator");
1476 result
= dns_validator_create(val
->view
, name
, type
,
1477 rdataset
, sigrdataset
, NULL
, 0,
1478 val
->task
, action
, val
,
1479 &val
->subvalidator
);
1480 if (result
== ISC_R_SUCCESS
) {
1481 val
->subvalidator
->parent
= val
;
1482 val
->subvalidator
->depth
= val
->depth
+ 1;
1488 * Try to find a key that could have signed 'siginfo' among those
1489 * in 'rdataset'. If found, build a dst_key_t for it and point
1492 * If val->key is non-NULL, this returns the next matching key.
1495 get_dst_key(dns_validator_t
*val
, dns_rdata_rrsig_t
*siginfo
,
1496 dns_rdataset_t
*rdataset
)
1498 isc_result_t result
;
1500 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1501 dst_key_t
*oldkey
= val
->key
;
1502 isc_boolean_t foundold
;
1505 foundold
= ISC_TRUE
;
1507 foundold
= ISC_FALSE
;
1511 result
= dns_rdataset_first(rdataset
);
1512 if (result
!= ISC_R_SUCCESS
)
1515 dns_rdataset_current(rdataset
, &rdata
);
1517 isc_buffer_init(&b
, rdata
.data
, rdata
.length
);
1518 isc_buffer_add(&b
, rdata
.length
);
1519 INSIST(val
->key
== NULL
);
1520 result
= dst_key_fromdns(&siginfo
->signer
, rdata
.rdclass
, &b
,
1521 val
->view
->mctx
, &val
->key
);
1522 if (result
!= ISC_R_SUCCESS
)
1524 if (siginfo
->algorithm
==
1525 (dns_secalg_t
)dst_key_alg(val
->key
) &&
1527 (dns_keytag_t
)dst_key_id(val
->key
) &&
1528 dst_key_iszonekey(val
->key
))
1532 * This is the key we're looking for.
1534 return (ISC_R_SUCCESS
);
1535 else if (dst_key_compare(oldkey
, val
->key
) == ISC_TRUE
)
1537 foundold
= ISC_TRUE
;
1538 dst_key_free(&oldkey
);
1541 dst_key_free(&val
->key
);
1542 dns_rdata_reset(&rdata
);
1543 result
= dns_rdataset_next(rdataset
);
1544 } while (result
== ISC_R_SUCCESS
);
1545 if (result
== ISC_R_NOMORE
)
1546 result
= ISC_R_NOTFOUND
;
1550 dst_key_free(&oldkey
);
1556 * Get the key that generated this signature.
1559 get_key(dns_validator_t
*val
, dns_rdata_rrsig_t
*siginfo
) {
1560 isc_result_t result
;
1561 unsigned int nlabels
;
1563 dns_namereln_t namereln
;
1566 * Is the signer name appropriate for this signature?
1568 * The signer name must be at the same level as the owner name
1569 * or closer to the DNS root.
1571 namereln
= dns_name_fullcompare(val
->event
->name
, &siginfo
->signer
,
1573 if (namereln
!= dns_namereln_subdomain
&&
1574 namereln
!= dns_namereln_equal
)
1575 return (DNS_R_CONTINUE
);
1577 if (namereln
== dns_namereln_equal
) {
1579 * If this is a self-signed keyset, it must not be a zone key
1580 * (since get_key is not called from validatezonekey).
1582 if (val
->event
->rdataset
->type
== dns_rdatatype_dnskey
)
1583 return (DNS_R_CONTINUE
);
1586 * Records appearing in the parent zone at delegation
1587 * points cannot be self-signed.
1589 if (dns_rdatatype_atparent(val
->event
->rdataset
->type
))
1590 return (DNS_R_CONTINUE
);
1593 * SOA and NS RRsets can only be signed by a key with
1596 if (val
->event
->rdataset
->type
== dns_rdatatype_soa
||
1597 val
->event
->rdataset
->type
== dns_rdatatype_ns
) {
1598 const char *typename
;
1600 if (val
->event
->rdataset
->type
== dns_rdatatype_soa
)
1604 validator_log(val
, ISC_LOG_DEBUG(3),
1605 "%s signer mismatch", typename
);
1606 return (DNS_R_CONTINUE
);
1611 * Do we know about this key?
1613 result
= view_find(val
, &siginfo
->signer
, dns_rdatatype_dnskey
);
1614 if (result
== ISC_R_SUCCESS
) {
1616 * We have an rrset for the given keyname.
1618 val
->keyset
= &val
->frdataset
;
1619 if (DNS_TRUST_PENDING(val
->frdataset
.trust
) &&
1620 dns_rdataset_isassociated(&val
->fsigrdataset
))
1623 * We know the key but haven't validated it yet.
1625 result
= create_validator(val
, &siginfo
->signer
,
1626 dns_rdatatype_dnskey
,
1631 if (result
!= ISC_R_SUCCESS
)
1633 return (DNS_R_WAIT
);
1634 } else if (DNS_TRUST_PENDING(val
->frdataset
.trust
)) {
1636 * Having a pending key with no signature means that
1637 * something is broken.
1639 result
= DNS_R_CONTINUE
;
1640 } else if (val
->frdataset
.trust
< dns_trust_secure
) {
1642 * The key is legitimately insecure. There's no
1643 * point in even attempting verification.
1646 result
= ISC_R_SUCCESS
;
1649 * See if we've got the key used in the signature.
1651 validator_log(val
, ISC_LOG_DEBUG(3),
1652 "keyset with trust %d",
1653 val
->frdataset
.trust
);
1654 result
= get_dst_key(val
, siginfo
, val
->keyset
);
1655 if (result
!= ISC_R_SUCCESS
) {
1657 * Either the key we're looking for is not
1658 * in the rrset, or something bad happened.
1661 result
= DNS_R_CONTINUE
;
1664 } else if (result
== ISC_R_NOTFOUND
) {
1666 * We don't know anything about this key.
1668 result
= create_fetch(val
, &siginfo
->signer
, dns_rdatatype_dnskey
,
1669 fetch_callback_validator
, "get_key");
1670 if (result
!= ISC_R_SUCCESS
)
1672 return (DNS_R_WAIT
);
1673 } else if (result
== DNS_R_NCACHENXDOMAIN
||
1674 result
== DNS_R_NCACHENXRRSET
||
1675 result
== DNS_R_EMPTYNAME
||
1676 result
== DNS_R_NXDOMAIN
||
1677 result
== DNS_R_NXRRSET
)
1680 * This key doesn't exist.
1682 result
= DNS_R_CONTINUE
;
1685 if (dns_rdataset_isassociated(&val
->frdataset
) &&
1686 val
->keyset
!= &val
->frdataset
)
1687 dns_rdataset_disassociate(&val
->frdataset
);
1688 if (dns_rdataset_isassociated(&val
->fsigrdataset
))
1689 dns_rdataset_disassociate(&val
->fsigrdataset
);
1695 compute_keytag(dns_rdata_t
*rdata
, dns_rdata_dnskey_t
*key
) {
1698 dns_rdata_toregion(rdata
, &r
);
1699 return (dst_region_computeid(&r
, key
->algorithm
));
1703 * Is this keyset self-signed?
1705 static isc_boolean_t
1706 isselfsigned(dns_validator_t
*val
) {
1707 dns_rdataset_t
*rdataset
, *sigrdataset
;
1708 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1709 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
1710 dns_rdata_dnskey_t key
;
1711 dns_rdata_rrsig_t sig
;
1712 dns_keytag_t keytag
;
1713 isc_result_t result
;
1715 rdataset
= val
->event
->rdataset
;
1716 sigrdataset
= val
->event
->sigrdataset
;
1718 INSIST(rdataset
->type
== dns_rdatatype_dnskey
);
1720 for (result
= dns_rdataset_first(rdataset
);
1721 result
== ISC_R_SUCCESS
;
1722 result
= dns_rdataset_next(rdataset
))
1724 dns_rdata_reset(&rdata
);
1725 dns_rdataset_current(rdataset
, &rdata
);
1726 result
= dns_rdata_tostruct(&rdata
, &key
, NULL
);
1727 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
1728 keytag
= compute_keytag(&rdata
, &key
);
1729 for (result
= dns_rdataset_first(sigrdataset
);
1730 result
== ISC_R_SUCCESS
;
1731 result
= dns_rdataset_next(sigrdataset
))
1733 dns_rdata_reset(&sigrdata
);
1734 dns_rdataset_current(sigrdataset
, &sigrdata
);
1735 result
= dns_rdata_tostruct(&sigrdata
, &sig
, NULL
);
1736 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
1738 if (sig
.algorithm
== key
.algorithm
&&
1739 sig
.keyid
== keytag
)
1747 * Attempt to verify the rdataset using the given key and rdata (RRSIG).
1748 * The signature was good and from a wildcard record and the QNAME does
1749 * not match the wildcard we need to look for a NOQNAME proof.
1752 * \li ISC_R_SUCCESS if the verification succeeds.
1753 * \li Others if the verification fails.
1756 verify(dns_validator_t
*val
, dst_key_t
*key
, dns_rdata_t
*rdata
,
1759 isc_result_t result
;
1760 dns_fixedname_t fixed
;
1761 isc_boolean_t ignore
= ISC_FALSE
;
1763 val
->attributes
|= VALATTR_TRIEDVERIFY
;
1764 dns_fixedname_init(&fixed
);
1766 result
= dns_dnssec_verify2(val
->event
->name
, val
->event
->rdataset
,
1767 key
, ignore
, val
->view
->mctx
, rdata
,
1768 dns_fixedname_name(&fixed
));
1769 if (result
== DNS_R_SIGEXPIRED
&& val
->view
->acceptexpired
) {
1773 if (ignore
&& (result
== ISC_R_SUCCESS
|| result
== DNS_R_FROMWILDCARD
))
1774 validator_log(val
, ISC_LOG_INFO
,
1775 "accepted expired %sRRSIG (keyid=%u)",
1776 (result
== DNS_R_FROMWILDCARD
) ?
1777 "wildcard " : "", keyid
);
1779 validator_log(val
, ISC_LOG_DEBUG(3),
1780 "verify rdataset (keyid=%u): %s",
1781 keyid
, isc_result_totext(result
));
1782 if (result
== DNS_R_FROMWILDCARD
) {
1783 if (!dns_name_equal(val
->event
->name
,
1784 dns_fixedname_name(&fixed
)))
1785 val
->attributes
|= VALATTR_NEEDNOQNAME
;
1786 result
= ISC_R_SUCCESS
;
1792 * Attempts positive response validation of a normal RRset.
1795 * \li ISC_R_SUCCESS Validation completed successfully
1796 * \li DNS_R_WAIT Validation has started but is waiting
1798 * \li Other return codes are possible and all indicate failure.
1801 validate(dns_validator_t
*val
, isc_boolean_t resume
) {
1802 isc_result_t result
;
1803 dns_validatorevent_t
*event
;
1804 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1807 * Caller must be holding the validator lock.
1814 * We already have a sigrdataset.
1816 result
= ISC_R_SUCCESS
;
1817 validator_log(val
, ISC_LOG_DEBUG(3), "resuming validate");
1819 result
= dns_rdataset_first(event
->sigrdataset
);
1823 result
== ISC_R_SUCCESS
;
1824 result
= dns_rdataset_next(event
->sigrdataset
))
1826 dns_rdata_reset(&rdata
);
1827 dns_rdataset_current(event
->sigrdataset
, &rdata
);
1828 if (val
->siginfo
== NULL
) {
1829 val
->siginfo
= isc_mem_get(val
->view
->mctx
,
1830 sizeof(*val
->siginfo
));
1831 if (val
->siginfo
== NULL
)
1832 return (ISC_R_NOMEMORY
);
1834 result
= dns_rdata_tostruct(&rdata
, val
->siginfo
, NULL
);
1835 if (result
!= ISC_R_SUCCESS
)
1839 * At this point we could check that the signature algorithm
1840 * was known and "sufficiently good".
1842 if (!dns_resolver_algorithm_supported(val
->view
->resolver
,
1844 val
->siginfo
->algorithm
))
1848 result
= get_key(val
, val
->siginfo
);
1849 if (result
== DNS_R_CONTINUE
)
1850 continue; /* Try the next SIG RR. */
1851 if (result
!= ISC_R_SUCCESS
)
1856 * The key is insecure, so mark the data as insecure also.
1858 if (val
->key
== NULL
) {
1859 if (val
->mustbesecure
) {
1860 validator_log(val
, ISC_LOG_WARNING
,
1861 "must be secure failure,"
1862 " key is insecure, so mark the"
1863 " data as insecure also.");
1864 return (DNS_R_MUSTBESECURE
);
1867 return (ISC_R_SUCCESS
);
1871 result
= verify(val
, val
->key
, &rdata
,
1872 val
->siginfo
->keyid
);
1873 if (result
== ISC_R_SUCCESS
)
1875 if (val
->keynode
!= NULL
) {
1876 dns_keynode_t
*nextnode
= NULL
;
1877 result
= dns_keytable_findnextkeynode(
1881 dns_keytable_detachkeynode(val
->keytable
,
1883 val
->keynode
= nextnode
;
1884 if (result
!= ISC_R_SUCCESS
) {
1888 val
->key
= dns_keynode_key(val
->keynode
);
1889 if (val
->key
== NULL
)
1892 if (get_dst_key(val
, val
->siginfo
, val
->keyset
)
1897 if (result
!= ISC_R_SUCCESS
)
1898 validator_log(val
, ISC_LOG_DEBUG(3),
1899 "failed to verify rdataset");
1904 isc_stdtime_get(&now
);
1905 ttl
= ISC_MIN(event
->rdataset
->ttl
,
1906 val
->siginfo
->timeexpire
- now
);
1907 if (val
->keyset
!= NULL
)
1908 ttl
= ISC_MIN(ttl
, val
->keyset
->ttl
);
1909 event
->rdataset
->ttl
= ttl
;
1910 event
->sigrdataset
->ttl
= ttl
;
1913 if (val
->keynode
!= NULL
)
1914 dns_keytable_detachkeynode(val
->keytable
,
1917 if (val
->key
!= NULL
)
1918 dst_key_free(&val
->key
);
1919 if (val
->keyset
!= NULL
) {
1920 dns_rdataset_disassociate(val
->keyset
);
1925 if ((val
->attributes
& VALATTR_NEEDNOQNAME
) != 0) {
1926 if (val
->event
->message
== NULL
) {
1927 validator_log(val
, ISC_LOG_DEBUG(3),
1928 "no message available for noqname proof");
1929 return (DNS_R_NOVALIDSIG
);
1931 validator_log(val
, ISC_LOG_DEBUG(3),
1932 "looking for noqname proof");
1933 return (nsecvalidate(val
, ISC_FALSE
));
1934 } else if (result
== ISC_R_SUCCESS
) {
1935 event
->rdataset
->trust
= dns_trust_secure
;
1936 event
->sigrdataset
->trust
= dns_trust_secure
;
1937 validator_log(val
, ISC_LOG_DEBUG(3),
1938 "marking as secure, "
1939 "noqname proof not needed");
1942 validator_log(val
, ISC_LOG_DEBUG(3),
1943 "verify failure: %s",
1944 isc_result_totext(result
));
1948 if (result
!= ISC_R_NOMORE
) {
1949 validator_log(val
, ISC_LOG_DEBUG(3),
1950 "failed to iterate signatures: %s",
1951 isc_result_totext(result
));
1955 validator_log(val
, ISC_LOG_INFO
, "no valid signature found");
1956 return (DNS_R_NOVALIDSIG
);
1960 * Validate the DNSKEY RRset by looking for a DNSKEY that matches a
1961 * DLV record and that also verifies the DNSKEY RRset.
1964 dlv_validatezonekey(dns_validator_t
*val
) {
1965 dns_keytag_t keytag
;
1966 dns_rdata_dlv_t dlv
;
1967 dns_rdata_dnskey_t key
;
1968 dns_rdata_rrsig_t sig
;
1969 dns_rdata_t dlvrdata
= DNS_RDATA_INIT
;
1970 dns_rdata_t keyrdata
= DNS_RDATA_INIT
;
1971 dns_rdata_t newdsrdata
= DNS_RDATA_INIT
;
1972 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
1973 dns_rdataset_t trdataset
;
1975 isc_boolean_t supported_algorithm
;
1976 isc_result_t result
;
1977 unsigned char dsbuf
[DNS_DS_BUFFERSIZE
];
1978 isc_uint8_t digest_type
;
1980 validator_log(val
, ISC_LOG_DEBUG(3), "dlv_validatezonekey");
1983 * Look through the DLV record and find the keys that can sign the
1984 * key set and the matching signature. For each such key, attempt
1987 supported_algorithm
= ISC_FALSE
;
1990 * If DNS_DSDIGEST_SHA256 is present we are required to prefer
1991 * it over DNS_DSDIGEST_SHA1. This in practice means that we
1992 * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
1995 digest_type
= DNS_DSDIGEST_SHA1
;
1996 for (result
= dns_rdataset_first(&val
->dlv
);
1997 result
== ISC_R_SUCCESS
;
1998 result
= dns_rdataset_next(&val
->dlv
)) {
1999 dns_rdata_reset(&dlvrdata
);
2000 dns_rdataset_current(&val
->dlv
, &dlvrdata
);
2001 result
= dns_rdata_tostruct(&dlvrdata
, &dlv
, NULL
);
2002 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2004 if (!dns_resolver_algorithm_supported(val
->view
->resolver
,
2009 if (dlv
.digest_type
== DNS_DSDIGEST_SHA256
&&
2010 dlv
.length
== ISC_SHA256_DIGESTLENGTH
) {
2011 digest_type
= DNS_DSDIGEST_SHA256
;
2016 for (result
= dns_rdataset_first(&val
->dlv
);
2017 result
== ISC_R_SUCCESS
;
2018 result
= dns_rdataset_next(&val
->dlv
))
2020 dns_rdata_reset(&dlvrdata
);
2021 dns_rdataset_current(&val
->dlv
, &dlvrdata
);
2022 result
= dns_rdata_tostruct(&dlvrdata
, &dlv
, NULL
);
2023 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2025 if (!dns_resolver_digest_supported(val
->view
->resolver
,
2029 if (dlv
.digest_type
!= digest_type
)
2032 if (!dns_resolver_algorithm_supported(val
->view
->resolver
,
2037 supported_algorithm
= ISC_TRUE
;
2039 dns_rdataset_init(&trdataset
);
2040 dns_rdataset_clone(val
->event
->rdataset
, &trdataset
);
2042 for (result
= dns_rdataset_first(&trdataset
);
2043 result
== ISC_R_SUCCESS
;
2044 result
= dns_rdataset_next(&trdataset
))
2046 dns_rdata_reset(&keyrdata
);
2047 dns_rdataset_current(&trdataset
, &keyrdata
);
2048 result
= dns_rdata_tostruct(&keyrdata
, &key
, NULL
);
2049 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2050 keytag
= compute_keytag(&keyrdata
, &key
);
2051 if (dlv
.key_tag
!= keytag
||
2052 dlv
.algorithm
!= key
.algorithm
)
2054 dns_rdata_reset(&newdsrdata
);
2055 result
= dns_ds_buildrdata(val
->event
->name
,
2056 &keyrdata
, dlv
.digest_type
,
2057 dsbuf
, &newdsrdata
);
2058 if (result
!= ISC_R_SUCCESS
) {
2059 validator_log(val
, ISC_LOG_DEBUG(3),
2060 "dns_ds_buildrdata() -> %s",
2061 dns_result_totext(result
));
2065 newdsrdata
.type
= dns_rdatatype_dlv
;
2066 if (dns_rdata_compare(&dlvrdata
, &newdsrdata
) == 0)
2069 if (result
!= ISC_R_SUCCESS
) {
2070 dns_rdataset_disassociate(&trdataset
);
2071 validator_log(val
, ISC_LOG_DEBUG(3),
2072 "no DNSKEY matching DLV");
2075 validator_log(val
, ISC_LOG_DEBUG(3),
2076 "Found matching DLV record: checking for signature");
2078 for (result
= dns_rdataset_first(val
->event
->sigrdataset
);
2079 result
== ISC_R_SUCCESS
;
2080 result
= dns_rdataset_next(val
->event
->sigrdataset
))
2082 dns_rdata_reset(&sigrdata
);
2083 dns_rdataset_current(val
->event
->sigrdataset
,
2085 result
= dns_rdata_tostruct(&sigrdata
, &sig
, NULL
);
2086 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2087 if (dlv
.key_tag
!= sig
.keyid
&&
2088 dlv
.algorithm
!= sig
.algorithm
)
2091 result
= dns_dnssec_keyfromrdata(val
->event
->name
,
2095 if (result
!= ISC_R_SUCCESS
)
2097 * This really shouldn't happen, but...
2101 result
= verify(val
, dstkey
, &sigrdata
, sig
.keyid
);
2102 dst_key_free(&dstkey
);
2103 if (result
== ISC_R_SUCCESS
)
2106 dns_rdataset_disassociate(&trdataset
);
2107 if (result
== ISC_R_SUCCESS
)
2109 validator_log(val
, ISC_LOG_DEBUG(3),
2110 "no RRSIG matching DLV key");
2112 if (result
== ISC_R_SUCCESS
) {
2113 val
->event
->rdataset
->trust
= dns_trust_secure
;
2114 val
->event
->sigrdataset
->trust
= dns_trust_secure
;
2115 validator_log(val
, ISC_LOG_DEBUG(3), "marking as secure (dlv)");
2117 } else if (result
== ISC_R_NOMORE
&& !supported_algorithm
) {
2118 if (val
->mustbesecure
) {
2119 validator_log(val
, ISC_LOG_WARNING
,
2120 "must be secure failure,"
2121 "no supported algorithm/digest (dlv)");
2122 return (DNS_R_MUSTBESECURE
);
2124 validator_log(val
, ISC_LOG_DEBUG(3),
2125 "no supported algorithm/digest (dlv)");
2127 return (ISC_R_SUCCESS
);
2129 return (DNS_R_NOVALIDSIG
);
2133 * Attempts positive response validation of an RRset containing zone keys
2134 * (i.e. a DNSKEY rrset).
2137 * \li ISC_R_SUCCESS Validation completed successfully
2138 * \li DNS_R_WAIT Validation has started but is waiting
2140 * \li Other return codes are possible and all indicate failure.
2143 validatezonekey(dns_validator_t
*val
) {
2144 isc_result_t result
;
2145 dns_validatorevent_t
*event
;
2146 dns_rdataset_t trdataset
;
2147 dns_rdata_t dsrdata
= DNS_RDATA_INIT
;
2148 dns_rdata_t newdsrdata
= DNS_RDATA_INIT
;
2149 dns_rdata_t keyrdata
= DNS_RDATA_INIT
;
2150 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
2151 unsigned char dsbuf
[DNS_DS_BUFFERSIZE
];
2152 char namebuf
[DNS_NAME_FORMATSIZE
];
2153 dns_keytag_t keytag
;
2155 dns_rdata_dnskey_t key
;
2156 dns_rdata_rrsig_t sig
;
2158 isc_boolean_t supported_algorithm
;
2159 isc_boolean_t atsep
= ISC_FALSE
;
2160 isc_uint8_t digest_type
;
2163 * Caller must be holding the validator lock.
2168 if (val
->havedlvsep
&& val
->dlv
.trust
>= dns_trust_secure
&&
2169 dns_name_equal(event
->name
, dns_fixedname_name(&val
->dlvsep
)))
2170 return (dlv_validatezonekey(val
));
2172 if (val
->dsset
== NULL
) {
2174 * First, see if this key was signed by a trusted key.
2176 for (result
= dns_rdataset_first(val
->event
->sigrdataset
);
2177 result
== ISC_R_SUCCESS
;
2178 result
= dns_rdataset_next(val
->event
->sigrdataset
))
2180 dns_keynode_t
*keynode
= NULL
, *nextnode
= NULL
;
2182 dns_rdata_reset(&sigrdata
);
2183 dns_rdataset_current(val
->event
->sigrdataset
,
2185 result
= dns_rdata_tostruct(&sigrdata
, &sig
, NULL
);
2186 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2188 if (!dns_name_equal(val
->event
->name
, &sig
.signer
))
2191 result
= dns_keytable_findkeynode(val
->keytable
,
2196 if (result
== DNS_R_PARTIALMATCH
||
2197 result
== ISC_R_SUCCESS
)
2199 while (result
== ISC_R_SUCCESS
) {
2200 dstkey
= dns_keynode_key(keynode
);
2201 if (dstkey
== NULL
) {
2202 dns_keytable_detachkeynode(
2207 result
= verify(val
, dstkey
, &sigrdata
,
2209 if (result
== ISC_R_SUCCESS
) {
2210 dns_keytable_detachkeynode(
2215 result
= dns_keytable_findnextkeynode(
2219 dns_keytable_detachkeynode(val
->keytable
,
2223 if (result
== ISC_R_SUCCESS
) {
2224 event
->rdataset
->trust
= dns_trust_secure
;
2225 event
->sigrdataset
->trust
= dns_trust_secure
;
2226 validator_log(val
, ISC_LOG_DEBUG(3),
2227 "signed by trusted key; "
2228 "marking as secure");
2234 * If this is the root name and there was no trusted key,
2235 * give up, since there's no DS at the root.
2237 if (dns_name_equal(event
->name
, dns_rootname
)) {
2238 if ((val
->attributes
& VALATTR_TRIEDVERIFY
) != 0) {
2239 validator_log(val
, ISC_LOG_DEBUG(3),
2240 "root key failed to validate");
2241 return (DNS_R_NOVALIDSIG
);
2243 validator_log(val
, ISC_LOG_DEBUG(3),
2244 "no trusted root key");
2245 return (DNS_R_NOVALIDDS
);
2251 * We have not found a key to verify this DNSKEY
2252 * RRset. As this is a SEP we have to assume that
2253 * the RRset is invalid.
2255 dns_name_format(val
->event
->name
, namebuf
,
2257 validator_log(val
, ISC_LOG_DEBUG(2),
2258 "unable to find a DNSKEY which verifies "
2259 "the DNSKEY RRset and also matches a "
2260 "trusted key for '%s'",
2262 return (DNS_R_NOVALIDKEY
);
2266 * Otherwise, try to find the DS record.
2268 result
= view_find(val
, val
->event
->name
, dns_rdatatype_ds
);
2269 if (result
== ISC_R_SUCCESS
) {
2271 * We have DS records.
2273 val
->dsset
= &val
->frdataset
;
2274 if (DNS_TRUST_PENDING(val
->frdataset
.trust
) &&
2275 dns_rdataset_isassociated(&val
->fsigrdataset
))
2277 result
= create_validator(val
,
2284 if (result
!= ISC_R_SUCCESS
)
2286 return (DNS_R_WAIT
);
2287 } else if (DNS_TRUST_PENDING(val
->frdataset
.trust
)) {
2289 * There should never be an unsigned DS.
2291 dns_rdataset_disassociate(&val
->frdataset
);
2292 validator_log(val
, ISC_LOG_DEBUG(2),
2293 "unsigned DS record");
2294 return (DNS_R_NOVALIDSIG
);
2296 result
= ISC_R_SUCCESS
;
2297 } else if (result
== ISC_R_NOTFOUND
) {
2299 * We don't have the DS. Find it.
2301 result
= create_fetch(val
, val
->event
->name
,
2302 dns_rdatatype_ds
, dsfetched
,
2304 if (result
!= ISC_R_SUCCESS
)
2306 return (DNS_R_WAIT
);
2307 } else if (result
== DNS_R_NCACHENXDOMAIN
||
2308 result
== DNS_R_NCACHENXRRSET
||
2309 result
== DNS_R_EMPTYNAME
||
2310 result
== DNS_R_NXDOMAIN
||
2311 result
== DNS_R_NXRRSET
)
2314 * The DS does not exist.
2316 if (dns_rdataset_isassociated(&val
->frdataset
))
2317 dns_rdataset_disassociate(&val
->frdataset
);
2318 if (dns_rdataset_isassociated(&val
->fsigrdataset
))
2319 dns_rdataset_disassociate(&val
->fsigrdataset
);
2320 validator_log(val
, ISC_LOG_DEBUG(2), "no DS record");
2321 return (DNS_R_NOVALIDSIG
);
2328 INSIST(val
->dsset
!= NULL
);
2330 if (val
->dsset
->trust
< dns_trust_secure
) {
2331 if (val
->mustbesecure
) {
2332 validator_log(val
, ISC_LOG_WARNING
,
2333 "must be secure failure,"
2335 return (DNS_R_MUSTBESECURE
);
2338 return (ISC_R_SUCCESS
);
2342 * Look through the DS record and find the keys that can sign the
2343 * key set and the matching signature. For each such key, attempt
2347 supported_algorithm
= ISC_FALSE
;
2350 * If DNS_DSDIGEST_SHA256 is present we are required to prefer
2351 * it over DNS_DSDIGEST_SHA1. This in practice means that we
2352 * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
2355 digest_type
= DNS_DSDIGEST_SHA1
;
2356 for (result
= dns_rdataset_first(val
->dsset
);
2357 result
== ISC_R_SUCCESS
;
2358 result
= dns_rdataset_next(val
->dsset
)) {
2359 dns_rdata_reset(&dsrdata
);
2360 dns_rdataset_current(val
->dsset
, &dsrdata
);
2361 result
= dns_rdata_tostruct(&dsrdata
, &ds
, NULL
);
2362 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2364 if (!dns_resolver_algorithm_supported(val
->view
->resolver
,
2369 if (ds
.digest_type
== DNS_DSDIGEST_SHA256
&&
2370 ds
.length
== ISC_SHA256_DIGESTLENGTH
) {
2371 digest_type
= DNS_DSDIGEST_SHA256
;
2376 for (result
= dns_rdataset_first(val
->dsset
);
2377 result
== ISC_R_SUCCESS
;
2378 result
= dns_rdataset_next(val
->dsset
))
2380 dns_rdata_reset(&dsrdata
);
2381 dns_rdataset_current(val
->dsset
, &dsrdata
);
2382 result
= dns_rdata_tostruct(&dsrdata
, &ds
, NULL
);
2383 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2385 if (!dns_resolver_digest_supported(val
->view
->resolver
,
2389 if (ds
.digest_type
!= digest_type
)
2392 if (!dns_resolver_algorithm_supported(val
->view
->resolver
,
2397 supported_algorithm
= ISC_TRUE
;
2399 dns_rdataset_init(&trdataset
);
2400 dns_rdataset_clone(val
->event
->rdataset
, &trdataset
);
2403 * Look for the KEY that matches the DS record.
2405 for (result
= dns_rdataset_first(&trdataset
);
2406 result
== ISC_R_SUCCESS
;
2407 result
= dns_rdataset_next(&trdataset
))
2409 dns_rdata_reset(&keyrdata
);
2410 dns_rdataset_current(&trdataset
, &keyrdata
);
2411 result
= dns_rdata_tostruct(&keyrdata
, &key
, NULL
);
2412 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2413 keytag
= compute_keytag(&keyrdata
, &key
);
2414 if (ds
.key_tag
!= keytag
||
2415 ds
.algorithm
!= key
.algorithm
)
2417 dns_rdata_reset(&newdsrdata
);
2418 result
= dns_ds_buildrdata(val
->event
->name
,
2419 &keyrdata
, ds
.digest_type
,
2420 dsbuf
, &newdsrdata
);
2421 if (result
!= ISC_R_SUCCESS
)
2423 if (dns_rdata_compare(&dsrdata
, &newdsrdata
) == 0)
2426 if (result
!= ISC_R_SUCCESS
) {
2427 dns_rdataset_disassociate(&trdataset
);
2428 validator_log(val
, ISC_LOG_DEBUG(3),
2429 "no DNSKEY matching DS");
2433 for (result
= dns_rdataset_first(val
->event
->sigrdataset
);
2434 result
== ISC_R_SUCCESS
;
2435 result
= dns_rdataset_next(val
->event
->sigrdataset
))
2437 dns_rdata_reset(&sigrdata
);
2438 dns_rdataset_current(val
->event
->sigrdataset
,
2440 result
= dns_rdata_tostruct(&sigrdata
, &sig
, NULL
);
2441 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2442 if (ds
.key_tag
!= sig
.keyid
||
2443 ds
.algorithm
!= sig
.algorithm
)
2445 if (!dns_name_equal(val
->event
->name
, &sig
.signer
)) {
2446 validator_log(val
, ISC_LOG_DEBUG(3),
2447 "DNSKEY signer mismatch");
2451 result
= dns_dnssec_keyfromrdata(val
->event
->name
,
2455 if (result
!= ISC_R_SUCCESS
)
2457 * This really shouldn't happen, but...
2460 result
= verify(val
, dstkey
, &sigrdata
, sig
.keyid
);
2461 dst_key_free(&dstkey
);
2462 if (result
== ISC_R_SUCCESS
)
2465 dns_rdataset_disassociate(&trdataset
);
2466 if (result
== ISC_R_SUCCESS
)
2468 validator_log(val
, ISC_LOG_DEBUG(3),
2469 "no RRSIG matching DS key");
2471 if (result
== ISC_R_SUCCESS
) {
2472 event
->rdataset
->trust
= dns_trust_secure
;
2473 event
->sigrdataset
->trust
= dns_trust_secure
;
2474 validator_log(val
, ISC_LOG_DEBUG(3), "marking as secure (DS)");
2476 } else if (result
== ISC_R_NOMORE
&& !supported_algorithm
) {
2477 if (val
->mustbesecure
) {
2478 validator_log(val
, ISC_LOG_WARNING
,
2479 "must be secure failure, "
2480 "no supported algorithm/digest (DS)");
2481 return (DNS_R_MUSTBESECURE
);
2483 validator_log(val
, ISC_LOG_DEBUG(3),
2484 "no supported algorithm/digest (DS)");
2486 return (ISC_R_SUCCESS
);
2488 validator_log(val
, ISC_LOG_INFO
,
2489 "no valid signature found (DS)");
2490 return (DNS_R_NOVALIDSIG
);
2495 * Starts a positive response validation.
2498 * \li ISC_R_SUCCESS Validation completed successfully
2499 * \li DNS_R_WAIT Validation has started but is waiting
2501 * \li Other return codes are possible and all indicate failure.
2504 start_positive_validation(dns_validator_t
*val
) {
2506 * If this is not a key, go straight into validate().
2508 if (val
->event
->type
!= dns_rdatatype_dnskey
|| !isselfsigned(val
))
2509 return (validate(val
, ISC_FALSE
));
2511 return (validatezonekey(val
));
2515 * Look for NODATA at the wildcard and NOWILDCARD proofs in the
2516 * previously validated NSEC records. As these proofs are mutually
2517 * exclusive we stop when one is found.
2523 checkwildcard(dns_validator_t
*val
, dns_rdatatype_t type
, dns_name_t
*zonename
)
2525 dns_name_t
*name
, *wild
;
2526 dns_message_t
*message
= val
->event
->message
;
2527 isc_result_t result
;
2528 isc_boolean_t exists
, data
;
2529 char namebuf
[DNS_NAME_FORMATSIZE
];
2531 wild
= dns_fixedname_name(&val
->wild
);
2533 if (dns_name_countlabels(wild
) == 0) {
2534 validator_log(val
, ISC_LOG_DEBUG(3),
2535 "in checkwildcard: no wildcard to check");
2536 return (ISC_R_SUCCESS
);
2539 dns_name_format(wild
, namebuf
, sizeof(namebuf
));
2540 validator_log(val
, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf
);
2542 for (result
= dns_message_firstname(message
, DNS_SECTION_AUTHORITY
);
2543 result
== ISC_R_SUCCESS
;
2544 result
= dns_message_nextname(message
, DNS_SECTION_AUTHORITY
))
2546 dns_rdataset_t
*rdataset
= NULL
, *sigrdataset
= NULL
;
2549 dns_message_currentname(message
, DNS_SECTION_AUTHORITY
, &name
);
2551 for (rdataset
= ISC_LIST_HEAD(name
->list
);
2553 rdataset
= ISC_LIST_NEXT(rdataset
, link
))
2555 if (rdataset
->type
!= type
)
2558 for (sigrdataset
= ISC_LIST_HEAD(name
->list
);
2559 sigrdataset
!= NULL
;
2560 sigrdataset
= ISC_LIST_NEXT(sigrdataset
, link
))
2562 if (sigrdataset
->type
== dns_rdatatype_rrsig
&&
2563 sigrdataset
->covers
== rdataset
->type
)
2566 if (sigrdataset
== NULL
)
2569 if (rdataset
->trust
!= dns_trust_secure
)
2572 if (rdataset
->type
== dns_rdatatype_nsec
&&
2573 ((val
->attributes
& VALATTR_NEEDNODATA
) != 0 ||
2574 (val
->attributes
& VALATTR_NEEDNOWILDCARD
) != 0) &&
2575 (val
->attributes
& VALATTR_FOUNDNODATA
) == 0 &&
2576 (val
->attributes
& VALATTR_FOUNDNOWILDCARD
) == 0 &&
2577 nsecnoexistnodata(val
, wild
, name
, rdataset
,
2578 &exists
, &data
, NULL
)
2581 dns_name_t
**proofs
= val
->event
->proofs
;
2582 if (exists
&& !data
)
2583 val
->attributes
|= VALATTR_FOUNDNODATA
;
2584 if (exists
&& !data
&& NEEDNODATA(val
))
2585 proofs
[DNS_VALIDATOR_NODATAPROOF
] =
2589 VALATTR_FOUNDNOWILDCARD
;
2590 if (!exists
&& NEEDNOQNAME(val
))
2591 proofs
[DNS_VALIDATOR_NOWILDCARDPROOF
] =
2593 return (ISC_R_SUCCESS
);
2596 if (rdataset
->type
== dns_rdatatype_nsec3
&&
2597 ((val
->attributes
& VALATTR_NEEDNODATA
) != 0 ||
2598 (val
->attributes
& VALATTR_NEEDNOWILDCARD
) != 0) &&
2599 (val
->attributes
& VALATTR_FOUNDNODATA
) == 0 &&
2600 (val
->attributes
& VALATTR_FOUNDNOWILDCARD
) == 0 &&
2601 nsec3noexistnodata(val
, wild
, name
, rdataset
,
2602 zonename
, &exists
, &data
,
2603 NULL
, NULL
, NULL
, NULL
, NULL
,
2604 NULL
) == ISC_R_SUCCESS
)
2606 dns_name_t
**proofs
= val
->event
->proofs
;
2607 if (exists
&& !data
)
2608 val
->attributes
|= VALATTR_FOUNDNODATA
;
2609 if (exists
&& !data
&& NEEDNODATA(val
))
2610 proofs
[DNS_VALIDATOR_NODATAPROOF
] =
2614 VALATTR_FOUNDNOWILDCARD
;
2615 if (!exists
&& NEEDNOQNAME(val
))
2616 proofs
[DNS_VALIDATOR_NOWILDCARDPROOF
] =
2618 return (ISC_R_SUCCESS
);
2622 if (result
== ISC_R_NOMORE
)
2623 result
= ISC_R_SUCCESS
;
2629 findnsec3proofs(dns_validator_t
*val
) {
2631 dns_message_t
*message
= val
->event
->message
;
2632 isc_result_t result
;
2633 isc_boolean_t exists
, data
, optout
, unknown
;
2634 isc_boolean_t setclosest
, setnearest
;
2635 dns_fixedname_t fclosest
, fnearest
, fzonename
;
2636 dns_name_t
*closest
, *nearest
, *zonename
;
2637 dns_name_t
**proofs
= val
->event
->proofs
;
2639 dns_fixedname_init(&fclosest
);
2640 dns_fixedname_init(&fnearest
);
2641 dns_fixedname_init(&fzonename
);
2642 closest
= dns_fixedname_name(&fclosest
);
2643 nearest
= dns_fixedname_name(&fnearest
);
2644 zonename
= dns_fixedname_name(&fzonename
);
2646 for (result
= dns_message_firstname(message
, DNS_SECTION_AUTHORITY
);
2647 result
== ISC_R_SUCCESS
;
2648 result
= dns_message_nextname(message
, DNS_SECTION_AUTHORITY
))
2650 dns_rdataset_t
*rdataset
= NULL
, *sigrdataset
= NULL
;
2653 dns_message_currentname(message
, DNS_SECTION_AUTHORITY
, &name
);
2655 for (rdataset
= ISC_LIST_HEAD(name
->list
);
2657 rdataset
= ISC_LIST_NEXT(rdataset
, link
))
2659 if (rdataset
->type
!= dns_rdatatype_nsec3
)
2662 for (sigrdataset
= ISC_LIST_HEAD(name
->list
);
2663 sigrdataset
!= NULL
;
2664 sigrdataset
= ISC_LIST_NEXT(sigrdataset
, link
))
2666 if (sigrdataset
->type
== dns_rdatatype_rrsig
&&
2667 sigrdataset
->covers
== dns_rdatatype_nsec3
)
2670 if (sigrdataset
== NULL
)
2673 if (rdataset
->trust
!= dns_trust_secure
)
2676 result
= nsec3noexistnodata(val
, val
->event
->name
,
2678 zonename
, NULL
, NULL
, NULL
,
2679 NULL
, NULL
, NULL
, NULL
,
2681 if (result
!= ISC_R_IGNORE
&& result
!= ISC_R_SUCCESS
)
2685 if (result
!= ISC_R_NOMORE
)
2686 result
= ISC_R_SUCCESS
;
2688 if (dns_name_countlabels(zonename
) == 0)
2689 return (ISC_R_SUCCESS
);
2691 for (result
= dns_message_firstname(message
, DNS_SECTION_AUTHORITY
);
2692 result
== ISC_R_SUCCESS
;
2693 result
= dns_message_nextname(message
, DNS_SECTION_AUTHORITY
))
2695 dns_rdataset_t
*rdataset
= NULL
, *sigrdataset
= NULL
;
2698 dns_message_currentname(message
, DNS_SECTION_AUTHORITY
, &name
);
2700 for (rdataset
= ISC_LIST_HEAD(name
->list
);
2702 rdataset
= ISC_LIST_NEXT(rdataset
, link
))
2704 if (rdataset
->type
!= dns_rdatatype_nsec3
)
2707 for (sigrdataset
= ISC_LIST_HEAD(name
->list
);
2708 sigrdataset
!= NULL
;
2709 sigrdataset
= ISC_LIST_NEXT(sigrdataset
, link
))
2711 if (sigrdataset
->type
== dns_rdatatype_rrsig
&&
2712 sigrdataset
->covers
== dns_rdatatype_nsec3
)
2715 if (sigrdataset
== NULL
)
2718 if (rdataset
->trust
!= dns_trust_secure
)
2722 * We process all NSEC3 records to find the closest
2723 * encloser and nearest name to the closest encloser.
2725 setclosest
= setnearest
= ISC_FALSE
;
2727 unknown
= ISC_FALSE
;
2728 result
= nsec3noexistnodata(val
, val
->event
->name
,
2731 &data
, &optout
, &unknown
,
2732 &setclosest
, &setnearest
,
2735 proofs
[DNS_VALIDATOR_CLOSESTENCLOSER
] = name
;
2737 val
->attributes
|= VALATTR_FOUNDUNKNOWN
;
2738 if (result
!= ISC_R_SUCCESS
)
2740 if (exists
&& !data
&& NEEDNODATA(val
)) {
2741 val
->attributes
|= VALATTR_FOUNDNODATA
;
2742 proofs
[DNS_VALIDATOR_NODATAPROOF
] = name
;
2744 if (!exists
&& setnearest
) {
2745 val
->attributes
|= VALATTR_FOUNDNOQNAME
;
2746 proofs
[DNS_VALIDATOR_NOQNAMEPROOF
] = name
;
2748 val
->attributes
|= VALATTR_FOUNDOPTOUT
;
2752 if (result
!= ISC_R_NOMORE
)
2753 result
= ISC_R_SUCCESS
;
2756 * To know we have a valid noqname and optout proofs we need to also
2757 * have a valid closest encloser. Otherwise we could still be looking
2758 * at proofs from the parent zone.
2760 if (dns_name_countlabels(closest
) > 0 &&
2761 dns_name_countlabels(nearest
) ==
2762 dns_name_countlabels(closest
) + 1 &&
2763 dns_name_issubdomain(nearest
, closest
))
2765 val
->attributes
|= VALATTR_FOUNDCLOSEST
;
2766 result
= dns_name_concatenate(dns_wildcardname
, closest
,
2767 dns_fixedname_name(&val
->wild
),
2769 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2771 val
->attributes
&= ~VALATTR_FOUNDNOQNAME
;
2772 val
->attributes
&= ~VALATTR_FOUNDOPTOUT
;
2773 proofs
[DNS_VALIDATOR_NOQNAMEPROOF
] = NULL
;
2777 * Do we need to check for the wildcard?
2779 if ((val
->attributes
& VALATTR_FOUNDNOQNAME
) != 0 &&
2780 (val
->attributes
& VALATTR_FOUNDCLOSEST
) != 0 &&
2781 (((val
->attributes
& VALATTR_NEEDNODATA
) != 0 &&
2782 (val
->attributes
& VALATTR_FOUNDNODATA
) == 0) ||
2783 (val
->attributes
& VALATTR_NEEDNOWILDCARD
) != 0)) {
2784 result
= checkwildcard(val
, dns_rdatatype_nsec3
, zonename
);
2785 if (result
!= ISC_R_SUCCESS
)
2792 * Prove a negative answer is good or that there is a NOQNAME when the
2793 * answer is from a wildcard.
2795 * Loop through the authority section looking for NODATA, NOWILDCARD
2796 * and NOQNAME proofs in the NSEC records by calling authvalidated().
2798 * If the required proofs are found we are done.
2800 * If the proofs are not found attempt to prove this is a unsecure
2804 nsecvalidate(dns_validator_t
*val
, isc_boolean_t resume
) {
2806 dns_message_t
*message
= val
->event
->message
;
2807 isc_result_t result
;
2810 result
= dns_message_firstname(message
, DNS_SECTION_AUTHORITY
);
2812 result
= ISC_R_SUCCESS
;
2813 validator_log(val
, ISC_LOG_DEBUG(3), "resuming nsecvalidate");
2817 result
== ISC_R_SUCCESS
;
2818 result
= dns_message_nextname(message
, DNS_SECTION_AUTHORITY
))
2820 dns_rdataset_t
*rdataset
= NULL
, *sigrdataset
= NULL
;
2823 dns_message_currentname(message
, DNS_SECTION_AUTHORITY
, &name
);
2825 rdataset
= ISC_LIST_NEXT(val
->currentset
, link
);
2826 val
->currentset
= NULL
;
2829 rdataset
= ISC_LIST_HEAD(name
->list
);
2833 rdataset
= ISC_LIST_NEXT(rdataset
, link
))
2835 if (rdataset
->type
== dns_rdatatype_rrsig
)
2838 for (sigrdataset
= ISC_LIST_HEAD(name
->list
);
2839 sigrdataset
!= NULL
;
2840 sigrdataset
= ISC_LIST_NEXT(sigrdataset
,
2843 if (sigrdataset
->type
== dns_rdatatype_rrsig
&&
2844 sigrdataset
->covers
== rdataset
->type
)
2848 * If a signed zone is missing the zone key, bad
2849 * things could happen. A query for data in the zone
2850 * would lead to a query for the zone key, which
2851 * would return a negative answer, which would contain
2852 * an SOA and an NSEC signed by the missing key, which
2853 * would trigger another query for the DNSKEY (since
2854 * the first one is still in progress), and go into an
2855 * infinite loop. Avoid that.
2857 if (val
->event
->type
== dns_rdatatype_dnskey
&&
2858 dns_name_equal(name
, val
->event
->name
))
2860 dns_rdata_t nsec
= DNS_RDATA_INIT
;
2862 if (rdataset
->type
!= dns_rdatatype_nsec
)
2865 result
= dns_rdataset_first(rdataset
);
2866 if (result
!= ISC_R_SUCCESS
)
2868 dns_rdataset_current(rdataset
, &nsec
);
2869 if (dns_nsec_typepresent(&nsec
,
2873 val
->currentset
= rdataset
;
2874 result
= create_validator(val
, name
, rdataset
->type
,
2875 rdataset
, sigrdataset
,
2878 if (result
!= ISC_R_SUCCESS
)
2880 return (DNS_R_WAIT
);
2884 if (result
== ISC_R_NOMORE
)
2885 result
= ISC_R_SUCCESS
;
2886 if (result
!= ISC_R_SUCCESS
)
2890 * Do we only need to check for NOQNAME? To get here we must have
2891 * had a secure wildcard answer.
2893 if ((val
->attributes
& VALATTR_NEEDNODATA
) == 0 &&
2894 (val
->attributes
& VALATTR_NEEDNOWILDCARD
) == 0 &&
2895 (val
->attributes
& VALATTR_NEEDNOQNAME
) != 0) {
2896 if ((val
->attributes
& VALATTR_FOUNDNOQNAME
) == 0)
2897 findnsec3proofs(val
);
2898 if ((val
->attributes
& VALATTR_FOUNDNOQNAME
) != 0 &&
2899 (val
->attributes
& VALATTR_FOUNDCLOSEST
) != 0) {
2900 validator_log(val
, ISC_LOG_DEBUG(3),
2901 "marking as secure, noqname proof found");
2902 val
->event
->rdataset
->trust
= dns_trust_secure
;
2903 val
->event
->sigrdataset
->trust
= dns_trust_secure
;
2904 return (ISC_R_SUCCESS
);
2905 } else if ((val
->attributes
& VALATTR_FOUNDOPTOUT
) != 0 &&
2906 dns_name_countlabels(dns_fixedname_name(&val
->wild
))
2908 validator_log(val
, ISC_LOG_DEBUG(3),
2909 "optout proof found");
2910 val
->event
->optout
= ISC_TRUE
;
2912 return (ISC_R_SUCCESS
);
2913 } else if ((val
->attributes
& VALATTR_FOUNDUNKNOWN
) != 0) {
2914 validator_log(val
, ISC_LOG_DEBUG(3),
2915 "unknown NSEC3 hash algorithm found");
2917 return (ISC_R_SUCCESS
);
2919 validator_log(val
, ISC_LOG_DEBUG(3),
2920 "noqname proof not found");
2921 return (DNS_R_NOVALIDNSEC
);
2924 if ((val
->attributes
& VALATTR_FOUNDNOQNAME
) == 0 &&
2925 (val
->attributes
& VALATTR_FOUNDNODATA
) == 0)
2926 findnsec3proofs(val
);
2929 * Do we need to check for the wildcard?
2931 if ((val
->attributes
& VALATTR_FOUNDNOQNAME
) != 0 &&
2932 (val
->attributes
& VALATTR_FOUNDCLOSEST
) != 0 &&
2933 (((val
->attributes
& VALATTR_NEEDNODATA
) != 0 &&
2934 (val
->attributes
& VALATTR_FOUNDNODATA
) == 0) ||
2935 (val
->attributes
& VALATTR_NEEDNOWILDCARD
) != 0)) {
2936 result
= checkwildcard(val
, dns_rdatatype_nsec
, NULL
);
2937 if (result
!= ISC_R_SUCCESS
)
2941 if (((val
->attributes
& VALATTR_NEEDNODATA
) != 0 &&
2942 ((val
->attributes
& VALATTR_FOUNDNODATA
) != 0 ||
2943 (val
->attributes
& VALATTR_FOUNDOPTOUT
) != 0)) ||
2944 ((val
->attributes
& VALATTR_NEEDNOQNAME
) != 0 &&
2945 (val
->attributes
& VALATTR_FOUNDNOQNAME
) != 0 &&
2946 (val
->attributes
& VALATTR_NEEDNOWILDCARD
) != 0 &&
2947 (val
->attributes
& VALATTR_FOUNDNOWILDCARD
) != 0 &&
2948 (val
->attributes
& VALATTR_FOUNDCLOSEST
) != 0)) {
2949 if ((val
->attributes
& VALATTR_FOUNDOPTOUT
) != 0)
2950 val
->event
->optout
= ISC_TRUE
;
2951 validator_log(val
, ISC_LOG_DEBUG(3),
2952 "nonexistence proof(s) found");
2953 return (ISC_R_SUCCESS
);
2956 validator_log(val
, ISC_LOG_DEBUG(3),
2957 "nonexistence proof(s) not found");
2958 val
->attributes
|= VALATTR_INSECURITY
;
2959 return (proveunsecure(val
, ISC_FALSE
, ISC_FALSE
));
2962 static isc_boolean_t
2963 check_ds(dns_validator_t
*val
, dns_name_t
*name
, dns_rdataset_t
*rdataset
) {
2964 dns_rdata_t dsrdata
= DNS_RDATA_INIT
;
2966 isc_result_t result
;
2968 for (result
= dns_rdataset_first(rdataset
);
2969 result
== ISC_R_SUCCESS
;
2970 result
= dns_rdataset_next(rdataset
)) {
2971 dns_rdataset_current(rdataset
, &dsrdata
);
2972 result
= dns_rdata_tostruct(&dsrdata
, &ds
, NULL
);
2973 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2975 if (dns_resolver_digest_supported(val
->view
->resolver
,
2977 dns_resolver_algorithm_supported(val
->view
->resolver
,
2978 name
, ds
.algorithm
)) {
2979 dns_rdata_reset(&dsrdata
);
2982 dns_rdata_reset(&dsrdata
);
2988 * Callback from fetching a DLV record.
2990 * Resumes the DLV lookup process.
2993 dlvfetched(isc_task_t
*task
, isc_event_t
*event
) {
2994 char namebuf
[DNS_NAME_FORMATSIZE
];
2995 dns_fetchevent_t
*devent
;
2996 dns_validator_t
*val
;
2997 isc_boolean_t want_destroy
;
2998 isc_result_t eresult
;
2999 isc_result_t result
;
3002 INSIST(event
->ev_type
== DNS_EVENT_FETCHDONE
);
3003 devent
= (dns_fetchevent_t
*)event
;
3004 val
= devent
->ev_arg
;
3005 eresult
= devent
->result
;
3007 /* Free resources which are not of interest. */
3008 if (devent
->node
!= NULL
)
3009 dns_db_detachnode(devent
->db
, &devent
->node
);
3010 if (devent
->db
!= NULL
)
3011 dns_db_detach(&devent
->db
);
3012 if (dns_rdataset_isassociated(&val
->fsigrdataset
))
3013 dns_rdataset_disassociate(&val
->fsigrdataset
);
3014 isc_event_free(&event
);
3015 dns_resolver_destroyfetch(&val
->fetch
);
3017 INSIST(val
->event
!= NULL
);
3018 validator_log(val
, ISC_LOG_DEBUG(3), "in dlvfetched: %s",
3019 dns_result_totext(eresult
));
3022 if (eresult
== ISC_R_SUCCESS
) {
3023 dns_name_format(dns_fixedname_name(&val
->dlvsep
), namebuf
,
3025 dns_rdataset_clone(&val
->frdataset
, &val
->dlv
);
3026 val
->havedlvsep
= ISC_TRUE
;
3027 if (dlv_algorithm_supported(val
)) {
3028 validator_log(val
, ISC_LOG_DEBUG(3), "DLV %s found",
3030 dlv_validator_start(val
);
3032 validator_log(val
, ISC_LOG_DEBUG(3),
3033 "DLV %s found with no supported algorithms",
3036 validator_done(val
, ISC_R_SUCCESS
);
3038 } else if (eresult
== DNS_R_NXRRSET
||
3039 eresult
== DNS_R_NXDOMAIN
||
3040 eresult
== DNS_R_NCACHENXRRSET
||
3041 eresult
== DNS_R_NCACHENXDOMAIN
) {
3042 result
= finddlvsep(val
, ISC_TRUE
);
3043 if (result
== ISC_R_SUCCESS
) {
3044 if (dlv_algorithm_supported(val
)) {
3045 dns_name_format(dns_fixedname_name(&val
->dlvsep
),
3046 namebuf
, sizeof(namebuf
));
3047 validator_log(val
, ISC_LOG_DEBUG(3),
3048 "DLV %s found", namebuf
);
3049 dlv_validator_start(val
);
3051 validator_log(val
, ISC_LOG_DEBUG(3),
3052 "DLV %s found with no supported "
3053 "algorithms", namebuf
);
3055 validator_done(val
, ISC_R_SUCCESS
);
3057 } else if (result
== ISC_R_NOTFOUND
) {
3058 validator_log(val
, ISC_LOG_DEBUG(3), "DLV not found");
3060 validator_done(val
, ISC_R_SUCCESS
);
3062 validator_log(val
, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3063 dns_result_totext(result
));
3064 if (result
!= DNS_R_WAIT
)
3065 validator_done(val
, result
);
3068 validator_log(val
, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3069 dns_result_totext(eresult
));
3070 validator_done(val
, eresult
);
3072 want_destroy
= exit_check(val
);
3079 * Start the DLV lookup process.
3084 * \li Others on validation failures.
3087 startfinddlvsep(dns_validator_t
*val
, dns_name_t
*unsecure
) {
3088 char namebuf
[DNS_NAME_FORMATSIZE
];
3089 isc_result_t result
;
3091 INSIST(!DLVTRIED(val
));
3093 val
->attributes
|= VALATTR_DLVTRIED
;
3095 dns_name_format(unsecure
, namebuf
, sizeof(namebuf
));
3096 validator_log(val
, ISC_LOG_DEBUG(3),
3097 "plain DNSSEC returns unsecure (%s): looking for DLV",
3100 if (dns_name_issubdomain(val
->event
->name
, val
->view
->dlv
)) {
3101 validator_log(val
, ISC_LOG_WARNING
, "must be secure failure, "
3102 " %s is under DLV (startfinddlvsep)", namebuf
);
3103 return (DNS_R_MUSTBESECURE
);
3106 val
->dlvlabels
= dns_name_countlabels(unsecure
) - 1;
3107 result
= finddlvsep(val
, ISC_FALSE
);
3108 if (result
== ISC_R_NOTFOUND
) {
3109 validator_log(val
, ISC_LOG_DEBUG(3), "DLV not found");
3111 return (ISC_R_SUCCESS
);
3113 if (result
!= ISC_R_SUCCESS
) {
3114 validator_log(val
, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3115 dns_result_totext(result
));
3118 dns_name_format(dns_fixedname_name(&val
->dlvsep
), namebuf
,
3120 if (dlv_algorithm_supported(val
)) {
3121 validator_log(val
, ISC_LOG_DEBUG(3), "DLV %s found", namebuf
);
3122 dlv_validator_start(val
);
3123 return (DNS_R_WAIT
);
3125 validator_log(val
, ISC_LOG_DEBUG(3), "DLV %s found with no supported "
3126 "algorithms", namebuf
);
3128 validator_done(val
, ISC_R_SUCCESS
);
3129 return (ISC_R_SUCCESS
);
3133 * Continue the DLV lookup process.
3137 * \li ISC_R_NOTFOUND
3139 * \li Others on validation failure.
3142 finddlvsep(dns_validator_t
*val
, isc_boolean_t resume
) {
3143 char namebuf
[DNS_NAME_FORMATSIZE
];
3144 dns_fixedname_t dlvfixed
;
3145 dns_name_t
*dlvname
;
3148 isc_result_t result
;
3149 unsigned int labels
;
3151 INSIST(val
->view
->dlv
!= NULL
);
3154 if (dns_name_issubdomain(val
->event
->name
, val
->view
->dlv
)) {
3155 dns_name_format(val
->event
->name
, namebuf
,
3157 validator_log(val
, ISC_LOG_WARNING
,
3158 "must be secure failure, "
3159 "%s is under DLV (finddlvsep)", namebuf
);
3160 return (DNS_R_MUSTBESECURE
);
3163 dns_fixedname_init(&val
->dlvsep
);
3164 dlvsep
= dns_fixedname_name(&val
->dlvsep
);
3165 dns_name_copy(val
->event
->name
, dlvsep
, NULL
);
3167 * If this is a response to a DS query, we need to look in
3168 * the parent zone for the trust anchor.
3170 if (val
->event
->type
== dns_rdatatype_ds
) {
3171 labels
= dns_name_countlabels(dlvsep
);
3173 return (ISC_R_NOTFOUND
);
3174 dns_name_getlabelsequence(dlvsep
, 1, labels
- 1,
3178 dlvsep
= dns_fixedname_name(&val
->dlvsep
);
3179 labels
= dns_name_countlabels(dlvsep
);
3180 dns_name_getlabelsequence(dlvsep
, 1, labels
- 1, dlvsep
);
3182 dns_name_init(&noroot
, NULL
);
3183 dns_fixedname_init(&dlvfixed
);
3184 dlvname
= dns_fixedname_name(&dlvfixed
);
3185 labels
= dns_name_countlabels(dlvsep
);
3187 return (ISC_R_NOTFOUND
);
3188 dns_name_getlabelsequence(dlvsep
, 0, labels
- 1, &noroot
);
3189 result
= dns_name_concatenate(&noroot
, val
->view
->dlv
, dlvname
, NULL
);
3190 while (result
== ISC_R_NOSPACE
) {
3191 labels
= dns_name_countlabels(dlvsep
);
3192 dns_name_getlabelsequence(dlvsep
, 1, labels
- 1, dlvsep
);
3193 dns_name_getlabelsequence(dlvsep
, 0, labels
- 2, &noroot
);
3194 result
= dns_name_concatenate(&noroot
, val
->view
->dlv
,
3197 if (result
!= ISC_R_SUCCESS
) {
3198 validator_log(val
, ISC_LOG_DEBUG(2), "DLV concatenate failed");
3199 return (DNS_R_NOVALIDSIG
);
3202 while (dns_name_countlabels(dlvname
) >=
3203 dns_name_countlabels(val
->view
->dlv
) + val
->dlvlabels
) {
3204 dns_name_format(dlvname
, namebuf
, sizeof(namebuf
));
3205 validator_log(val
, ISC_LOG_DEBUG(3), "looking for DLV %s",
3207 result
= view_find(val
, dlvname
, dns_rdatatype_dlv
);
3208 if (result
== ISC_R_SUCCESS
) {
3209 if (val
->frdataset
.trust
< dns_trust_secure
) {
3210 validator_log(val
, ISC_LOG_DEBUG(3),
3211 "DLV not validated");
3212 return (DNS_R_NOVALIDSIG
);
3214 val
->havedlvsep
= ISC_TRUE
;
3215 dns_rdataset_clone(&val
->frdataset
, &val
->dlv
);
3216 return (ISC_R_SUCCESS
);
3218 if (result
== ISC_R_NOTFOUND
) {
3219 result
= create_fetch(val
, dlvname
, dns_rdatatype_dlv
,
3220 dlvfetched
, "finddlvsep");
3221 if (result
!= ISC_R_SUCCESS
)
3223 return (DNS_R_WAIT
);
3225 if (result
!= DNS_R_NXRRSET
&&
3226 result
!= DNS_R_NXDOMAIN
&&
3227 result
!= DNS_R_EMPTYNAME
&&
3228 result
!= DNS_R_NCACHENXRRSET
&&
3229 result
!= DNS_R_NCACHENXDOMAIN
)
3232 * Strip first labels from both dlvsep and dlvname.
3234 labels
= dns_name_countlabels(dlvsep
);
3237 dns_name_getlabelsequence(dlvsep
, 1, labels
- 1, dlvsep
);
3238 labels
= dns_name_countlabels(dlvname
);
3239 dns_name_getlabelsequence(dlvname
, 1, labels
- 1, dlvname
);
3241 return (ISC_R_NOTFOUND
);
3245 * proveunsecure walks down from the SEP looking for a break in the
3246 * chain of trust. That occurs when we can prove the DS record does
3247 * not exist at a delegation point or the DS exists at a delegation
3248 * but we don't support the algorithm/digest.
3250 * If DLV is active and we look for a DLV record at or below the
3251 * point we go insecure. If found we restart the validation process.
3252 * If not found or DLV isn't active we mark the response as a answer.
3255 * \li ISC_R_SUCCESS val->event->name is in a unsecure zone
3256 * \li DNS_R_WAIT validation is in progress.
3257 * \li DNS_R_MUSTBESECURE val->event->name is supposed to be secure
3258 * (policy) but we proved that it is unsecure.
3259 * \li DNS_R_NOVALIDSIG
3260 * \li DNS_R_NOVALIDNSEC
3261 * \li DNS_R_NOTINSECURE
3264 proveunsecure(dns_validator_t
*val
, isc_boolean_t have_ds
, isc_boolean_t resume
)
3266 isc_result_t result
;
3267 dns_fixedname_t fixedsecroot
;
3268 dns_name_t
*secroot
;
3270 char namebuf
[DNS_NAME_FORMATSIZE
];
3272 dns_fixedname_t fixedfound
;
3274 dns_fixedname_init(&fixedsecroot
);
3275 secroot
= dns_fixedname_name(&fixedsecroot
);
3276 dns_fixedname_init(&fixedfound
);
3277 found
= dns_fixedname_name(&fixedfound
);
3278 if (val
->havedlvsep
)
3279 dns_name_copy(dns_fixedname_name(&val
->dlvsep
), secroot
, NULL
);
3281 dns_name_copy(val
->event
->name
, secroot
, NULL
);
3283 * If this is a response to a DS query, we need to look in
3284 * the parent zone for the trust anchor.
3286 if (val
->event
->type
== dns_rdatatype_ds
&&
3287 dns_name_countlabels(secroot
) > 1U)
3288 dns_name_split(secroot
, 1, NULL
, secroot
);
3289 result
= dns_keytable_finddeepestmatch(val
->keytable
,
3292 if (result
== ISC_R_NOTFOUND
) {
3293 validator_log(val
, ISC_LOG_DEBUG(3),
3294 "not beneath secure root");
3295 if (val
->mustbesecure
) {
3296 validator_log(val
, ISC_LOG_WARNING
,
3297 "must be secure failure, "
3298 "not beneath secure root");
3299 result
= DNS_R_MUSTBESECURE
;
3302 validator_log(val
, ISC_LOG_DEBUG(3),
3303 "not beneath secure root");
3304 if (val
->view
->dlv
== NULL
|| DLVTRIED(val
)) {
3306 return (ISC_R_SUCCESS
);
3308 return (startfinddlvsep(val
, dns_rootname
));
3309 } else if (result
!= ISC_R_SUCCESS
)
3315 * We are looking for breaks below the SEP so add a label.
3317 val
->labels
= dns_name_countlabels(secroot
) + 1;
3319 validator_log(val
, ISC_LOG_DEBUG(3), "resuming proveunsecure");
3321 * If we have a DS rdataset and it is secure then check if
3322 * the DS rdataset has a supported algorithm combination.
3323 * If not this is an insecure delegation as far as this
3324 * resolver is concerned. Fall back to DLV if available.
3326 if (have_ds
&& val
->frdataset
.trust
>= dns_trust_secure
&&
3327 !check_ds(val
, dns_fixedname_name(&val
->fname
),
3329 dns_name_format(dns_fixedname_name(&val
->fname
),
3330 namebuf
, sizeof(namebuf
));
3331 if ((val
->view
->dlv
== NULL
|| DLVTRIED(val
)) &&
3332 val
->mustbesecure
) {
3333 validator_log(val
, ISC_LOG_WARNING
,
3334 "must be secure failure at '%s', "
3335 "can't fall back to DLV",
3337 result
= DNS_R_MUSTBESECURE
;
3340 validator_log(val
, ISC_LOG_DEBUG(3),
3341 "no supported algorithm/digest (%s/DS)",
3343 if (val
->view
->dlv
== NULL
|| DLVTRIED(val
)) {
3345 result
= ISC_R_SUCCESS
;
3348 result
= startfinddlvsep(val
,
3349 dns_fixedname_name(&val
->fname
));
3356 val
->labels
<= dns_name_countlabels(val
->event
->name
);
3360 dns_fixedname_init(&val
->fname
);
3361 tname
= dns_fixedname_name(&val
->fname
);
3362 if (val
->labels
== dns_name_countlabels(val
->event
->name
))
3363 dns_name_copy(val
->event
->name
, tname
, NULL
);
3365 dns_name_split(val
->event
->name
, val
->labels
,
3368 dns_name_format(tname
, namebuf
, sizeof(namebuf
));
3369 validator_log(val
, ISC_LOG_DEBUG(3),
3370 "checking existence of DS at '%s'",
3373 result
= view_find(val
, tname
, dns_rdatatype_ds
);
3375 if (result
== DNS_R_NXRRSET
|| result
== DNS_R_NCACHENXRRSET
) {
3377 * There is no DS. If this is a delegation,
3380 if (DNS_TRUST_PENDING(val
->frdataset
.trust
)) {
3381 result
= create_fetch(val
, tname
,
3385 if (result
!= ISC_R_SUCCESS
)
3387 return (DNS_R_WAIT
);
3390 * Zones using NSEC3 don't return a NSEC RRset so
3391 * we need to use dns_view_findzonecut2 to find
3394 if (result
== DNS_R_NXRRSET
&&
3395 !dns_rdataset_isassociated(&val
->frdataset
) &&
3396 dns_view_findzonecut2(val
->view
, tname
, found
,
3397 0, 0, ISC_FALSE
, ISC_FALSE
,
3398 NULL
, NULL
) == ISC_R_SUCCESS
&&
3399 dns_name_equal(tname
, found
)) {
3400 if (val
->mustbesecure
) {
3401 validator_log(val
, ISC_LOG_WARNING
,
3402 "must be secure failure, "
3403 "no DS at zone cut");
3404 return (DNS_R_MUSTBESECURE
);
3406 if (val
->view
->dlv
== NULL
|| DLVTRIED(val
)) {
3408 return (ISC_R_SUCCESS
);
3410 return (startfinddlvsep(val
, tname
));
3412 if (val
->frdataset
.trust
< dns_trust_secure
) {
3414 * This shouldn't happen, since the negative
3415 * response should have been validated. Since
3416 * there's no way of validating existing
3417 * negative response blobs, give up.
3419 validator_log(val
, ISC_LOG_WARNING
,
3420 "can't validate existing "
3421 "negative responses (no DS)");
3422 result
= DNS_R_NOVALIDSIG
;
3425 if (isdelegation(tname
, &val
->frdataset
, result
)) {
3426 if (val
->mustbesecure
) {
3427 validator_log(val
, ISC_LOG_WARNING
,
3428 "must be secure failure, "
3429 "%s is a delegation",
3431 return (DNS_R_MUSTBESECURE
);
3433 if (val
->view
->dlv
== NULL
|| DLVTRIED(val
)) {
3435 return (ISC_R_SUCCESS
);
3437 return (startfinddlvsep(val
, tname
));
3440 } else if (result
== ISC_R_SUCCESS
) {
3442 * There is a DS here. Verify that it's secure and
3445 if (val
->frdataset
.trust
>= dns_trust_secure
) {
3446 if (!check_ds(val
, tname
, &val
->frdataset
)) {
3447 validator_log(val
, ISC_LOG_DEBUG(3),
3448 "no supported algorithm/"
3449 "digest (%s/DS)", namebuf
);
3450 if (val
->mustbesecure
) {
3453 "must be secure failure, "
3454 "no supported algorithm/"
3457 result
= DNS_R_MUSTBESECURE
;
3460 if (val
->view
->dlv
== NULL
||
3463 result
= ISC_R_SUCCESS
;
3466 result
= startfinddlvsep(val
, tname
);
3471 else if (!dns_rdataset_isassociated(&val
->fsigrdataset
))
3473 validator_log(val
, ISC_LOG_DEBUG(3),
3475 result
= DNS_R_NOVALIDSIG
;
3478 result
= create_validator(val
, tname
, dns_rdatatype_ds
,
3483 if (result
!= ISC_R_SUCCESS
)
3485 return (DNS_R_WAIT
);
3486 } else if (result
== DNS_R_NXDOMAIN
||
3487 result
== DNS_R_NCACHENXDOMAIN
) {
3489 * This is not a zone cut. Assuming things are
3490 * as expected, continue.
3492 if (!dns_rdataset_isassociated(&val
->frdataset
)) {
3494 * There should be an NSEC here, since we
3495 * are still in a secure zone.
3497 result
= DNS_R_NOVALIDNSEC
;
3499 } else if (val
->frdataset
.trust
< dns_trust_secure
) {
3501 * This shouldn't happen, since the negative
3502 * response should have been validated. Since
3503 * there's no way of validating existing
3504 * negative response blobs, give up.
3506 validator_log(val
, ISC_LOG_WARNING
,
3507 "can't validate existing "
3508 "negative responses "
3509 "(not a zone cut)");
3510 result
= DNS_R_NOVALIDSIG
;
3514 } else if (result
== ISC_R_NOTFOUND
) {
3516 * We don't know anything about the DS. Find it.
3518 result
= create_fetch(val
, tname
, dns_rdatatype_ds
,
3519 dsfetched2
, "proveunsecure");
3520 if (result
!= ISC_R_SUCCESS
)
3522 return (DNS_R_WAIT
);
3527 if ((val->attributes & VALATTR_NEEDOPTOUT) == 0 &&
3528 val->event->message != NULL) {
3529 val->attributes |= VALATTR_NEEDOPTOUT;
3530 return (nsecvalidate(val, ISC_FALSE));
3533 /* Couldn't complete insecurity proof */
3534 validator_log(val
, ISC_LOG_DEBUG(3), "insecurity proof failed");
3535 return (DNS_R_NOTINSECURE
);
3538 if (dns_rdataset_isassociated(&val
->frdataset
))
3539 dns_rdataset_disassociate(&val
->frdataset
);
3540 if (dns_rdataset_isassociated(&val
->fsigrdataset
))
3541 dns_rdataset_disassociate(&val
->fsigrdataset
);
3546 * Reset state and revalidate the answer using DLV.
3549 dlv_validator_start(dns_validator_t
*val
) {
3552 validator_log(val
, ISC_LOG_DEBUG(3), "dlv_validator_start");
3555 * Reset state and try again.
3557 val
->attributes
&= VALATTR_DLVTRIED
;
3558 val
->options
&= ~DNS_VALIDATOR_DLV
;
3560 event
= (isc_event_t
*)val
->event
;
3561 isc_task_send(val
->task
, &event
);
3565 * Start the validation process.
3567 * Attempt to validate the answer based on the category it appears to
3569 * \li 1. secure positive answer.
3570 * \li 2. unsecure positive answer.
3571 * \li 3. a negative answer (secure or unsecure).
3573 * Note a answer that appears to be a secure positive answer may actually
3574 * be an unsecure positive answer.
3577 validator_start(isc_task_t
*task
, isc_event_t
*event
) {
3578 dns_validator_t
*val
;
3579 dns_validatorevent_t
*vevent
;
3580 isc_boolean_t want_destroy
= ISC_FALSE
;
3581 isc_result_t result
= ISC_R_FAILURE
;
3584 REQUIRE(event
->ev_type
== DNS_EVENT_VALIDATORSTART
);
3585 vevent
= (dns_validatorevent_t
*)event
;
3586 val
= vevent
->validator
;
3588 /* If the validator has been canceled, val->event == NULL */
3589 if (val
->event
== NULL
)
3593 validator_log(val
, ISC_LOG_DEBUG(3), "restarting using DLV");
3595 validator_log(val
, ISC_LOG_DEBUG(3), "starting");
3599 if ((val
->options
& DNS_VALIDATOR_DLV
) != 0 &&
3600 val
->event
->rdataset
!= NULL
) {
3601 validator_log(val
, ISC_LOG_DEBUG(3), "looking for DLV");
3602 result
= startfinddlvsep(val
, dns_rootname
);
3603 } else if (val
->event
->rdataset
!= NULL
&&
3604 val
->event
->sigrdataset
!= NULL
) {
3605 isc_result_t saved_result
;
3608 * This looks like a simple validation. We say "looks like"
3609 * because it might end up requiring an insecurity proof.
3611 validator_log(val
, ISC_LOG_DEBUG(3),
3612 "attempting positive response validation");
3614 INSIST(dns_rdataset_isassociated(val
->event
->rdataset
));
3615 INSIST(dns_rdataset_isassociated(val
->event
->sigrdataset
));
3616 result
= start_positive_validation(val
);
3617 if (result
== DNS_R_NOVALIDSIG
&&
3618 (val
->attributes
& VALATTR_TRIEDVERIFY
) == 0)
3620 saved_result
= result
;
3621 validator_log(val
, ISC_LOG_DEBUG(3),
3622 "falling back to insecurity proof");
3623 val
->attributes
|= VALATTR_INSECURITY
;
3624 result
= proveunsecure(val
, ISC_FALSE
, ISC_FALSE
);
3625 if (result
== DNS_R_NOTINSECURE
)
3626 result
= saved_result
;
3628 } else if (val
->event
->rdataset
!= NULL
) {
3630 * This is either an unsecure subdomain or a response from
3633 INSIST(dns_rdataset_isassociated(val
->event
->rdataset
));
3634 validator_log(val
, ISC_LOG_DEBUG(3),
3635 "attempting insecurity proof");
3637 val
->attributes
|= VALATTR_INSECURITY
;
3638 result
= proveunsecure(val
, ISC_FALSE
, ISC_FALSE
);
3639 if (result
== DNS_R_NOTINSECURE
)
3640 validator_log(val
, ISC_LOG_INFO
,
3641 "got insecure response; "
3642 "parent indicates it should be secure");
3643 } else if (val
->event
->rdataset
== NULL
&&
3644 val
->event
->sigrdataset
== NULL
)
3647 * This is a nonexistence validation.
3649 validator_log(val
, ISC_LOG_DEBUG(3),
3650 "attempting negative response validation");
3652 if (val
->event
->message
->rcode
== dns_rcode_nxdomain
) {
3653 val
->attributes
|= VALATTR_NEEDNOQNAME
;
3654 val
->attributes
|= VALATTR_NEEDNOWILDCARD
;
3656 val
->attributes
|= VALATTR_NEEDNODATA
;
3657 result
= nsecvalidate(val
, ISC_FALSE
);
3660 * This shouldn't happen.
3665 if (result
!= DNS_R_WAIT
) {
3666 want_destroy
= exit_check(val
);
3667 validator_done(val
, result
);
3676 dns_validator_create(dns_view_t
*view
, dns_name_t
*name
, dns_rdatatype_t type
,
3677 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
,
3678 dns_message_t
*message
, unsigned int options
,
3679 isc_task_t
*task
, isc_taskaction_t action
, void *arg
,
3680 dns_validator_t
**validatorp
)
3682 isc_result_t result
;
3683 dns_validator_t
*val
;
3685 dns_validatorevent_t
*event
;
3687 REQUIRE(name
!= NULL
);
3688 REQUIRE(rdataset
!= NULL
||
3689 (rdataset
== NULL
&& sigrdataset
== NULL
&& message
!= NULL
));
3690 REQUIRE(validatorp
!= NULL
&& *validatorp
== NULL
);
3693 result
= ISC_R_FAILURE
;
3695 val
= isc_mem_get(view
->mctx
, sizeof(*val
));
3697 return (ISC_R_NOMEMORY
);
3699 dns_view_weakattach(view
, &val
->view
);
3701 event
= (dns_validatorevent_t
*)
3702 isc_event_allocate(view
->mctx
, task
,
3703 DNS_EVENT_VALIDATORSTART
,
3704 validator_start
, NULL
,
3705 sizeof(dns_validatorevent_t
));
3706 if (event
== NULL
) {
3707 result
= ISC_R_NOMEMORY
;
3710 isc_task_attach(task
, &tclone
);
3711 event
->validator
= val
;
3712 event
->result
= ISC_R_FAILURE
;
3715 event
->rdataset
= rdataset
;
3716 event
->sigrdataset
= sigrdataset
;
3717 event
->message
= message
;
3718 memset(event
->proofs
, 0, sizeof(event
->proofs
));
3719 event
->optout
= ISC_FALSE
;
3720 result
= isc_mutex_init(&val
->lock
);
3721 if (result
!= ISC_R_SUCCESS
)
3724 val
->options
= options
;
3725 val
->attributes
= 0;
3727 val
->subvalidator
= NULL
;
3730 val
->keytable
= NULL
;
3731 result
= dns_view_getsecroots(val
->view
, &val
->keytable
);
3732 if (result
!= ISC_R_SUCCESS
)
3735 val
->keynode
= NULL
;
3737 val
->siginfo
= NULL
;
3739 val
->action
= action
;
3742 val
->currentset
= NULL
;
3745 dns_rdataset_init(&val
->dlv
);
3746 val
->seensig
= ISC_FALSE
;
3747 val
->havedlvsep
= ISC_FALSE
;
3749 val
->mustbesecure
= dns_resolver_getmustbesecure(view
->resolver
, name
);
3750 dns_rdataset_init(&val
->frdataset
);
3751 dns_rdataset_init(&val
->fsigrdataset
);
3752 dns_fixedname_init(&val
->wild
);
3753 dns_fixedname_init(&val
->nearest
);
3754 dns_fixedname_init(&val
->closest
);
3755 ISC_LINK_INIT(val
, link
);
3756 val
->magic
= VALIDATOR_MAGIC
;
3758 if ((options
& DNS_VALIDATOR_DEFER
) == 0)
3759 isc_task_send(task
, ISC_EVENT_PTR(&event
));
3763 return (ISC_R_SUCCESS
);
3766 isc_task_detach(&tclone
);
3767 isc_event_free(ISC_EVENT_PTR(&event
));
3770 dns_view_weakdetach(&val
->view
);
3771 isc_mem_put(view
->mctx
, val
, sizeof(*val
));
3777 dns_validator_send(dns_validator_t
*validator
) {
3779 REQUIRE(VALID_VALIDATOR(validator
));
3781 LOCK(&validator
->lock
);
3783 INSIST((validator
->options
& DNS_VALIDATOR_DEFER
) != 0);
3784 event
= (isc_event_t
*)validator
->event
;
3785 validator
->options
&= ~DNS_VALIDATOR_DEFER
;
3786 UNLOCK(&validator
->lock
);
3788 isc_task_send(validator
->task
, ISC_EVENT_PTR(&event
));
3792 dns_validator_cancel(dns_validator_t
*validator
) {
3793 REQUIRE(VALID_VALIDATOR(validator
));
3795 LOCK(&validator
->lock
);
3797 validator_log(validator
, ISC_LOG_DEBUG(3), "dns_validator_cancel");
3799 if (validator
->event
!= NULL
) {
3800 if (validator
->fetch
!= NULL
)
3801 dns_resolver_cancelfetch(validator
->fetch
);
3803 if (validator
->subvalidator
!= NULL
)
3804 dns_validator_cancel(validator
->subvalidator
);
3805 if ((validator
->options
& DNS_VALIDATOR_DEFER
) != 0) {
3806 isc_task_t
*task
= validator
->event
->ev_sender
;
3807 validator
->options
&= ~DNS_VALIDATOR_DEFER
;
3808 isc_event_free((isc_event_t
**)&validator
->event
);
3809 isc_task_detach(&task
);
3811 validator
->attributes
|= VALATTR_CANCELED
;
3813 UNLOCK(&validator
->lock
);
3817 destroy(dns_validator_t
*val
) {
3820 REQUIRE(SHUTDOWN(val
));
3821 REQUIRE(val
->event
== NULL
);
3822 REQUIRE(val
->fetch
== NULL
);
3824 if (val
->keynode
!= NULL
)
3825 dns_keytable_detachkeynode(val
->keytable
, &val
->keynode
);
3826 else if (val
->key
!= NULL
)
3827 dst_key_free(&val
->key
);
3828 if (val
->keytable
!= NULL
)
3829 dns_keytable_detach(&val
->keytable
);
3830 if (val
->subvalidator
!= NULL
)
3831 dns_validator_destroy(&val
->subvalidator
);
3832 if (val
->havedlvsep
)
3833 dns_rdataset_disassociate(&val
->dlv
);
3834 if (dns_rdataset_isassociated(&val
->frdataset
))
3835 dns_rdataset_disassociate(&val
->frdataset
);
3836 if (dns_rdataset_isassociated(&val
->fsigrdataset
))
3837 dns_rdataset_disassociate(&val
->fsigrdataset
);
3838 mctx
= val
->view
->mctx
;
3839 if (val
->siginfo
!= NULL
)
3840 isc_mem_put(mctx
, val
->siginfo
, sizeof(*val
->siginfo
));
3841 DESTROYLOCK(&val
->lock
);
3842 dns_view_weakdetach(&val
->view
);
3844 isc_mem_put(mctx
, val
, sizeof(*val
));
3848 dns_validator_destroy(dns_validator_t
**validatorp
) {
3849 dns_validator_t
*val
;
3850 isc_boolean_t want_destroy
= ISC_FALSE
;
3852 REQUIRE(validatorp
!= NULL
);
3854 REQUIRE(VALID_VALIDATOR(val
));
3858 val
->attributes
|= VALATTR_SHUTDOWN
;
3859 validator_log(val
, ISC_LOG_DEBUG(3), "dns_validator_destroy");
3861 want_destroy
= exit_check(val
);
3872 validator_logv(dns_validator_t
*val
, isc_logcategory_t
*category
,
3873 isc_logmodule_t
*module
, int level
, const char *fmt
, va_list ap
)
3876 static const char spaces
[] = " *";
3877 int depth
= val
->depth
* 2;
3879 vsnprintf(msgbuf
, sizeof(msgbuf
), fmt
, ap
);
3881 if ((unsigned int) depth
>= sizeof spaces
)
3882 depth
= sizeof spaces
- 1;
3884 if (val
->event
!= NULL
&& val
->event
->name
!= NULL
) {
3885 char namebuf
[DNS_NAME_FORMATSIZE
];
3886 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
3888 dns_name_format(val
->event
->name
, namebuf
, sizeof(namebuf
));
3889 dns_rdatatype_format(val
->event
->type
, typebuf
,
3891 isc_log_write(dns_lctx
, category
, module
, level
,
3892 "%.*svalidating @%p: %s %s: %s", depth
, spaces
,
3893 val
, namebuf
, typebuf
, msgbuf
);
3895 isc_log_write(dns_lctx
, category
, module
, level
,
3896 "%.*svalidator @%p: %s", depth
, spaces
,
3902 validator_log(dns_validator_t
*val
, int level
, const char *fmt
, ...) {
3905 if (! isc_log_wouldlog(dns_lctx
, level
))
3910 validator_logv(val
, DNS_LOGCATEGORY_DNSSEC
,
3911 DNS_LOGMODULE_VALIDATOR
, level
, fmt
, ap
);
3916 validator_logcreate(dns_validator_t
*val
,
3917 dns_name_t
*name
, dns_rdatatype_t type
,
3918 const char *caller
, const char *operation
)
3920 char namestr
[DNS_NAME_FORMATSIZE
];
3921 char typestr
[DNS_RDATATYPE_FORMATSIZE
];
3923 dns_name_format(name
, namestr
, sizeof(namestr
));
3924 dns_rdatatype_format(type
, typestr
, sizeof(typestr
));
3925 validator_log(val
, ISC_LOG_DEBUG(9), "%s: creating %s for %s %s",
3926 caller
, operation
, namestr
, typestr
);