Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / bind / dist / lib / dns / validator.c
blob960ba5702e63a1242477c85c255aa755c7253073
1 /* $NetBSD$ */
3 /*
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 */
22 #include <config.h>
24 #include <isc/base32.h>
25 #include <isc/mem.h>
26 #include <isc/print.h>
27 #include <isc/sha2.h>
28 #include <isc/string.h>
29 #include <isc/task.h>
30 #include <isc/util.h>
32 #include <dns/db.h>
33 #include <dns/ds.h>
34 #include <dns/dnssec.h>
35 #include <dns/events.h>
36 #include <dns/keytable.h>
37 #include <dns/log.h>
38 #include <dns/message.h>
39 #include <dns/ncache.h>
40 #include <dns/nsec.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>
49 #include <dns/view.h>
51 /*! \file
52 * \brief
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
79 * signatures.
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)
129 static void
130 destroy(dns_validator_t *val);
132 static isc_result_t
133 get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
134 dns_rdataset_t *rdataset);
136 static isc_result_t
137 validate(dns_validator_t *val, isc_boolean_t resume);
139 static isc_result_t
140 validatezonekey(dns_validator_t *val);
142 static isc_result_t
143 nsecvalidate(dns_validator_t *val, isc_boolean_t resume);
145 static isc_result_t
146 proveunsecure(dns_validator_t *val, isc_boolean_t have_ds,
147 isc_boolean_t resume);
149 static void
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);
154 static void
155 validator_log(dns_validator_t *val, int level, const char *fmt, ...)
156 ISC_FORMAT_PRINTF(3, 4);
158 static void
159 validator_logcreate(dns_validator_t *val,
160 dns_name_t *name, dns_rdatatype_t type,
161 const char *caller, const char *operation);
163 static isc_result_t
164 dlv_validatezonekey(dns_validator_t *val);
166 static void
167 dlv_validator_start(dns_validator_t *val);
169 static isc_result_t
170 finddlvsep(dns_validator_t *val, isc_boolean_t resume);
172 static isc_result_t
173 startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure);
176 * Mark the RRsets as a answer.
178 static inline void
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;
187 static void
188 validator_done(dns_validator_t *val, isc_result_t result) {
189 isc_task_t *task;
191 if (val->event == NULL)
192 return;
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.
212 if (!SHUTDOWN(val))
213 return (ISC_FALSE);
215 INSIST(val->event == NULL);
217 if (val->fetch != NULL || val->subvalidator != NULL)
218 return (ISC_FALSE);
220 return (ISC_TRUE);
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;
229 dns_rdata_dlv_t dlv;
230 isc_result_t result;
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,
241 val->event->name,
242 dlv.algorithm))
243 continue;
245 if (dlv.digest_type != DNS_DSDIGEST_SHA256 &&
246 dlv.digest_type != DNS_DSDIGEST_SHA1)
247 continue;
249 return (ISC_TRUE);
251 return (ISC_FALSE);
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.
258 static isc_boolean_t
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;
267 dns_rdataset_t set;
268 int order;
269 int scope;
270 isc_boolean_t found;
271 isc_buffer_t buffer;
272 isc_result_t result;
273 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
274 unsigned char owner[NSEC3_MAX_HASH_LENGTH];
275 unsigned int length;
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);
282 else {
283 result = dns_ncache_getrdataset(rdataset, name,
284 dns_rdatatype_nsec, &set);
285 if (result == ISC_R_NOTFOUND)
286 goto trynsec3;
287 if (result != ISC_R_SUCCESS)
288 return (ISC_FALSE);
291 INSIST(set.type == dns_rdatatype_nsec);
293 found = ISC_FALSE;
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);
301 return (found);
303 trynsec3:
305 * Iterate over the ncache entry.
307 found = ISC_FALSE;
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);
320 continue;
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);
328 continue;
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);
337 if (nsec3.hash != 1)
338 continue;
339 length = isc_iterated_hash(hash, nsec3.hash,
340 nsec3.iterations, nsec3.salt,
341 nsec3.salt_length,
342 name->ndata, name->length);
343 if (length != isc_buffer_usedlength(&buffer))
344 continue;
345 order = memcmp(hash, owner, length);
346 if (order == 0) {
347 found = dns_nsec3_typepresent(&rdata,
348 dns_rdatatype_ns);
349 dns_rdataset_disassociate(&set);
350 return (found);
352 if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) == 0)
353 continue;
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);
364 return (ISC_TRUE);
367 dns_rdataset_disassociate(&set);
369 return (found);
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.
377 static void
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;
383 isc_result_t result;
384 isc_result_t eresult;
386 UNUSED(task);
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");
406 LOCK(&val->lock);
407 if (CANCELED(val)) {
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);
423 } else {
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);
429 else
430 validator_done(val, DNS_R_NOVALIDKEY);
432 want_destroy = exit_check(val);
433 UNLOCK(&val->lock);
434 if (want_destroy)
435 destroy(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.
443 static void
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;
449 isc_result_t result;
450 isc_result_t eresult;
452 UNUSED(task);
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");
472 LOCK(&val->lock);
473 if (CANCELED(val)) {
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);
493 } else {
494 validator_log(val, ISC_LOG_DEBUG(3),
495 "dsfetched: got %s",
496 isc_result_totext(eresult));
497 if (eresult == ISC_R_CANCELED)
498 validator_done(val, eresult);
499 else
500 validator_done(val, DNS_R_NOVALIDDS);
502 want_destroy = exit_check(val);
503 UNLOCK(&val->lock);
504 if (want_destroy)
505 destroy(val);
509 * We were asked to look for the DS record as part of proving that a
510 * name is unsecure.
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
514 * unsecure zone.
516 * If the DS record exists it will be secure. We can continue looking
517 * for the break point in the chain of trust.
519 static void
520 dsfetched2(isc_task_t *task, isc_event_t *event) {
521 dns_fetchevent_t *devent;
522 dns_validator_t *val;
523 dns_name_t *tname;
524 isc_boolean_t want_destroy;
525 isc_result_t result;
526 isc_result_t eresult;
528 UNUSED(task);
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));
547 LOCK(&val->lock);
548 if (CANCELED(val)) {
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)) {
562 markanswer(val);
563 validator_done(val, ISC_R_SUCCESS);
564 } else {
565 result = startfinddlvsep(val, tname);
566 if (result != DNS_R_WAIT)
567 validator_done(val, result);
569 } else {
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
581 * validation.
583 result = proveunsecure(val, ISC_TF(eresult == ISC_R_SUCCESS),
584 ISC_TRUE);
585 if (result != DNS_R_WAIT)
586 validator_done(val, result);
587 } else {
588 if (eresult == ISC_R_CANCELED)
589 validator_done(val, eresult);
590 else
591 validator_done(val, DNS_R_NOVALIDDS);
593 isc_event_free(&event);
594 want_destroy = exit_check(val);
595 UNLOCK(&val->lock);
596 if (want_destroy)
597 destroy(val);
601 * Callback from when a DNSKEY RRset has been validated.
603 * Resumes the stalled validation process.
605 static void
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;
610 isc_result_t result;
611 isc_result_t eresult;
613 UNUSED(task);
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");
626 LOCK(&val->lock);
627 if (CANCELED(val)) {
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);
640 } else {
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);
647 UNLOCK(&val->lock);
648 if (want_destroy)
649 destroy(val);
653 * Callback when the DS record has been validated.
655 * Resumes validation of the zone key or the unsecure zone proof.
657 static void
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;
662 isc_result_t result;
663 isc_result_t eresult;
665 UNUSED(task);
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");
678 LOCK(&val->lock);
679 if (CANCELED(val)) {
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);
686 else
687 result = validatezonekey(val);
688 if (result != DNS_R_WAIT)
689 validator_done(val, result);
690 } else {
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);
697 UNLOCK(&val->lock);
698 if (want_destroy)
699 destroy(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.
709 static isc_result_t
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)
714 int order;
715 dns_rdata_t rdata = DNS_RDATA_INIT;
716 isc_result_t result;
717 dns_namereln_t relation;
718 unsigned int olabels, nlabels, labels;
719 dns_rdata_nsec_t nsec;
720 isc_boolean_t atparent;
721 isc_boolean_t ns;
722 isc_boolean_t soa;
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");
733 return (result);
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);
740 if (order < 0) {
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);
749 if (order == 0) {
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);
756 if (ns && !soa) {
757 if (!atparent) {
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)) {
781 *exists = ISC_TRUE;
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",
785 *data);
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)
807 return (result);
808 relation = dns_name_fullcompare(&nsec.next, name, &order, &nlabels);
809 if (order == 0) {
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);
830 *exists = ISC_TRUE;
831 *data = ISC_FALSE;
832 return (ISC_R_SUCCESS);
834 if (wild != NULL) {
835 dns_name_t common;
836 dns_name_init(&common, NULL);
837 if (olabels > nlabels) {
838 labels = dns_name_countlabels(nsecname);
839 dns_name_getlabelsequence(nsecname, labels - olabels,
840 olabels, &common);
841 } else {
842 labels = dns_name_countlabels(&nsec.next);
843 dns_name_getlabelsequence(&nsec.next, labels - nlabels,
844 nlabels, &common);
846 result = dns_name_concatenate(dns_wildcardname, &common,
847 wild, NULL);
848 if (result != ISC_R_SUCCESS) {
849 dns_rdata_freestruct(&nsec);
850 validator_log(val, ISC_LOG_DEBUG(3),
851 "failure generating wildcard name");
852 return (result);
855 dns_rdata_freestruct(&nsec);
856 validator_log(val, ISC_LOG_DEBUG(3), "nsec range ok");
857 *exists = ISC_FALSE;
858 return (ISC_R_SUCCESS);
861 static isc_result_t
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,
868 dns_name_t *nearest)
870 char namebuf[DNS_NAME_FORMATSIZE];
871 dns_fixedname_t fzone;
872 dns_fixedname_t qfixed;
873 dns_label_t hashlabel;
874 dns_name_t *qname;
875 dns_name_t *zone;
876 dns_rdata_nsec3_t nsec3;
877 dns_rdata_t rdata = DNS_RDATA_INIT;
878 int order;
879 int scope;
880 isc_boolean_t atparent;
881 isc_boolean_t first;
882 isc_boolean_t ns;
883 isc_boolean_t soa;
884 isc_buffer_t buffer;
885 isc_result_t answer = ISC_R_IGNORE;
886 isc_result_t result;
887 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
888 unsigned char owner[NSEC3_MAX_HASH_LENGTH];
889 unsigned int 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");
905 return (result);
908 dns_rdataset_current(nsec3set, &rdata);
910 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
911 if (result != ISC_R_SUCCESS)
912 return (result);
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.
923 if (zlabels < 2)
924 return (ISC_R_IGNORE);
927 * Strip off the NSEC3 hash to get the zone.
929 zlabels--;
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)) {
959 if (unknown != NULL)
960 *unknown = ISC_TRUE;
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)
972 return (result);
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);
993 first = ISC_TRUE;
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);
1017 if (ns && !soa) {
1018 if (!atparent) {
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)) {
1043 *exists = ISC_TRUE;
1044 *data = dns_nsec3_typepresent(&rdata,
1045 val->event->type);
1046 validator_log(val, ISC_LOG_DEBUG(3),
1047 "NSEC3 proves name exists (owner) "
1048 "data=%d", *data);
1049 return (ISC_R_SUCCESS);
1051 validator_log(val, ISC_LOG_DEBUG(3),
1052 "NSEC3 proves CNAME exists");
1053 return (ISC_R_IGNORE);
1056 if (order == 0 &&
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.
1073 if (order == 0) {
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,
1084 sizeof(namebuf));
1085 validator_log(val, ISC_LOG_DEBUG(3),
1086 "NSEC3 indicates potential "
1087 "closest encloser: '%s'",
1088 namebuf);
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);
1095 return (answer);
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
1107 * above.
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;
1125 #if 0
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,
1139 sizeof(namebuf));
1140 validator_log(val, ISC_LOG_DEBUG(3),
1141 "NSEC3 potential closest "
1142 "encloser from zone name: '%s'",
1143 namebuf);
1144 dns_name_copy(zone, closest, NULL);
1145 *setclosest = ISC_TRUE;
1147 #endif
1148 *exists = ISC_FALSE;
1149 *data = 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");
1154 *optout =
1155 ISC_TF(nsec3.flags & DNS_NSEC3FLAG_OPTOUT);
1157 answer = ISC_R_SUCCESS;
1160 qlabels--;
1161 if (qlabels > 0)
1162 dns_name_split(qname, qlabels, NULL, qname);
1163 first = ISC_FALSE;
1165 return (answer);
1169 * Callback for when NSEC records have been validated.
1171 * Looks for NOQNAME, NODATA and OPTOUT proofs.
1173 * Resumes nsecvalidate.
1175 static void
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;
1185 UNUSED(task);
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");
1198 LOCK(&val->lock);
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);
1207 else {
1208 result = nsecvalidate(val, ISC_TRUE);
1209 if (result != DNS_R_WAIT)
1210 validator_done(val, result);
1212 } else {
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)
1227 == ISC_R_SUCCESS)
1229 if (exists && !data) {
1230 val->attributes |= VALATTR_FOUNDNODATA;
1231 if (NEEDNODATA(val))
1232 proofs[DNS_VALIDATOR_NODATAPROOF] =
1233 devent->name;
1235 if (!exists) {
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] =
1245 devent->name;
1249 result = nsecvalidate(val, ISC_TRUE);
1250 if (result != DNS_R_WAIT)
1251 validator_done(val, result);
1253 want_destroy = exit_check(val);
1254 UNLOCK(&val->lock);
1255 if (want_destroy)
1256 destroy(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.
1270 * Returns:
1271 * \li ISC_R_SUCCESS
1272 * \li ISC_R_NOTFOUND
1273 * \li DNS_R_NCACHENXDOMAIN
1274 * \li DNS_R_NCACHENXRRSET
1275 * \li DNS_R_NXRRSET
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);
1321 goto notfound;
1323 result = dns_rdataset_first(&val->frdataset);
1324 if (result != ISC_R_SUCCESS)
1325 goto notfound;
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");
1333 goto notfound;
1336 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
1337 if (result != ISC_R_SUCCESS)
1338 goto notfound;
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
1345 * this NSEC.
1347 dns_rdata_freestruct(&nsec);
1348 validator_log(val, ISC_LOG_DEBUG(3),
1349 "covering nsec: not in zone");
1350 goto notfound;
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");
1363 goto notfound;
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'",
1371 buf1, buf2, buf3);
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) {
1385 goto notfound;
1387 return (result);
1389 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");
1425 return (ISC_TRUE);
1428 return (ISC_FALSE);
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,
1453 callback, val,
1454 &val->frdataset,
1455 &val->fsigrdataset,
1456 &val->fetch));
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;
1484 return (result);
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
1490 * val->key at it.
1492 * If val->key is non-NULL, this returns the next matching key.
1494 static isc_result_t
1495 get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
1496 dns_rdataset_t *rdataset)
1498 isc_result_t result;
1499 isc_buffer_t b;
1500 dns_rdata_t rdata = DNS_RDATA_INIT;
1501 dst_key_t *oldkey = val->key;
1502 isc_boolean_t foundold;
1504 if (oldkey == NULL)
1505 foundold = ISC_TRUE;
1506 else {
1507 foundold = ISC_FALSE;
1508 val->key = NULL;
1511 result = dns_rdataset_first(rdataset);
1512 if (result != ISC_R_SUCCESS)
1513 goto failure;
1514 do {
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)
1523 goto failure;
1524 if (siginfo->algorithm ==
1525 (dns_secalg_t)dst_key_alg(val->key) &&
1526 siginfo->keyid ==
1527 (dns_keytag_t)dst_key_id(val->key) &&
1528 dst_key_iszonekey(val->key))
1530 if (foundold)
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;
1548 failure:
1549 if (oldkey != NULL)
1550 dst_key_free(&oldkey);
1552 return (result);
1556 * Get the key that generated this signature.
1558 static isc_result_t
1559 get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
1560 isc_result_t result;
1561 unsigned int nlabels;
1562 int order;
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,
1572 &order, &nlabels);
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);
1591 } else {
1593 * SOA and NS RRsets can only be signed by a key with
1594 * the same name.
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)
1601 typename = "SOA";
1602 else
1603 typename = "NS";
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,
1627 &val->frdataset,
1628 &val->fsigrdataset,
1629 keyvalidated,
1630 "get_key");
1631 if (result != ISC_R_SUCCESS)
1632 return (result);
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.
1645 val->key = NULL;
1646 result = ISC_R_SUCCESS;
1647 } else {
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.
1659 * Give up.
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)
1671 return (result);
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);
1691 return (result);
1694 static dns_keytag_t
1695 compute_keytag(dns_rdata_t *rdata, dns_rdata_dnskey_t *key) {
1696 isc_region_t r;
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)
1740 return (ISC_TRUE);
1743 return (ISC_FALSE);
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.
1751 * Returns:
1752 * \li ISC_R_SUCCESS if the verification succeeds.
1753 * \li Others if the verification fails.
1755 static isc_result_t
1756 verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata,
1757 isc_uint16_t keyid)
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);
1765 again:
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) {
1770 ignore = ISC_TRUE;
1771 goto again;
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);
1778 else
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;
1788 return (result);
1792 * Attempts positive response validation of a normal RRset.
1794 * Returns:
1795 * \li ISC_R_SUCCESS Validation completed successfully
1796 * \li DNS_R_WAIT Validation has started but is waiting
1797 * for an event.
1798 * \li Other return codes are possible and all indicate failure.
1800 static isc_result_t
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.
1810 event = val->event;
1812 if (resume) {
1814 * We already have a sigrdataset.
1816 result = ISC_R_SUCCESS;
1817 validator_log(val, ISC_LOG_DEBUG(3), "resuming validate");
1818 } else {
1819 result = dns_rdataset_first(event->sigrdataset);
1822 for (;
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)
1836 return (result);
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,
1843 event->name,
1844 val->siginfo->algorithm))
1845 continue;
1847 if (!resume) {
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)
1852 return (result);
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);
1866 markanswer(val);
1867 return (ISC_R_SUCCESS);
1870 do {
1871 result = verify(val, val->key, &rdata,
1872 val->siginfo->keyid);
1873 if (result == ISC_R_SUCCESS)
1874 break;
1875 if (val->keynode != NULL) {
1876 dns_keynode_t *nextnode = NULL;
1877 result = dns_keytable_findnextkeynode(
1878 val->keytable,
1879 val->keynode,
1880 &nextnode);
1881 dns_keytable_detachkeynode(val->keytable,
1882 &val->keynode);
1883 val->keynode = nextnode;
1884 if (result != ISC_R_SUCCESS) {
1885 val->key = NULL;
1886 break;
1888 val->key = dns_keynode_key(val->keynode);
1889 if (val->key == NULL)
1890 break;
1891 } else {
1892 if (get_dst_key(val, val->siginfo, val->keyset)
1893 != ISC_R_SUCCESS)
1894 break;
1896 } while (1);
1897 if (result != ISC_R_SUCCESS)
1898 validator_log(val, ISC_LOG_DEBUG(3),
1899 "failed to verify rdataset");
1900 else {
1901 isc_uint32_t ttl;
1902 isc_stdtime_t now;
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,
1915 &val->keynode);
1916 else {
1917 if (val->key != NULL)
1918 dst_key_free(&val->key);
1919 if (val->keyset != NULL) {
1920 dns_rdataset_disassociate(val->keyset);
1921 val->keyset = NULL;
1924 val->key = NULL;
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");
1940 return (result);
1941 } else {
1942 validator_log(val, ISC_LOG_DEBUG(3),
1943 "verify failure: %s",
1944 isc_result_totext(result));
1945 resume = ISC_FALSE;
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));
1952 return (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.
1963 static isc_result_t
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;
1974 dst_key_t *dstkey;
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
1985 * verification.
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
1993 * is present.
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,
2005 val->event->name,
2006 dlv.algorithm))
2007 continue;
2009 if (dlv.digest_type == DNS_DSDIGEST_SHA256 &&
2010 dlv.length == ISC_SHA256_DIGESTLENGTH) {
2011 digest_type = DNS_DSDIGEST_SHA256;
2012 break;
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,
2026 dlv.digest_type))
2027 continue;
2029 if (dlv.digest_type != digest_type)
2030 continue;
2032 if (!dns_resolver_algorithm_supported(val->view->resolver,
2033 val->event->name,
2034 dlv.algorithm))
2035 continue;
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)
2053 continue;
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));
2062 continue;
2064 /* Covert to DLV */
2065 newdsrdata.type = dns_rdatatype_dlv;
2066 if (dns_rdata_compare(&dlvrdata, &newdsrdata) == 0)
2067 break;
2069 if (result != ISC_R_SUCCESS) {
2070 dns_rdataset_disassociate(&trdataset);
2071 validator_log(val, ISC_LOG_DEBUG(3),
2072 "no DNSKEY matching DLV");
2073 continue;
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,
2084 &sigrdata);
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)
2089 continue;
2090 dstkey = NULL;
2091 result = dns_dnssec_keyfromrdata(val->event->name,
2092 &keyrdata,
2093 val->view->mctx,
2094 &dstkey);
2095 if (result != ISC_R_SUCCESS)
2097 * This really shouldn't happen, but...
2099 continue;
2101 result = verify(val, dstkey, &sigrdata, sig.keyid);
2102 dst_key_free(&dstkey);
2103 if (result == ISC_R_SUCCESS)
2104 break;
2106 dns_rdataset_disassociate(&trdataset);
2107 if (result == ISC_R_SUCCESS)
2108 break;
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)");
2116 return (result);
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)");
2126 markanswer(val);
2127 return (ISC_R_SUCCESS);
2128 } else
2129 return (DNS_R_NOVALIDSIG);
2133 * Attempts positive response validation of an RRset containing zone keys
2134 * (i.e. a DNSKEY rrset).
2136 * Returns:
2137 * \li ISC_R_SUCCESS Validation completed successfully
2138 * \li DNS_R_WAIT Validation has started but is waiting
2139 * for an event.
2140 * \li Other return codes are possible and all indicate failure.
2142 static isc_result_t
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;
2154 dns_rdata_ds_t ds;
2155 dns_rdata_dnskey_t key;
2156 dns_rdata_rrsig_t sig;
2157 dst_key_t *dstkey;
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.
2166 event = val->event;
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,
2184 &sigrdata);
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))
2189 continue;
2191 result = dns_keytable_findkeynode(val->keytable,
2192 val->event->name,
2193 sig.algorithm,
2194 sig.keyid,
2195 &keynode);
2196 if (result == DNS_R_PARTIALMATCH ||
2197 result == ISC_R_SUCCESS)
2198 atsep = ISC_TRUE;
2199 while (result == ISC_R_SUCCESS) {
2200 dstkey = dns_keynode_key(keynode);
2201 if (dstkey == NULL) {
2202 dns_keytable_detachkeynode(
2203 val->keytable,
2204 &keynode);
2205 break;
2207 result = verify(val, dstkey, &sigrdata,
2208 sig.keyid);
2209 if (result == ISC_R_SUCCESS) {
2210 dns_keytable_detachkeynode(
2211 val->keytable,
2212 &keynode);
2213 break;
2215 result = dns_keytable_findnextkeynode(
2216 val->keytable,
2217 keynode,
2218 &nextnode);
2219 dns_keytable_detachkeynode(val->keytable,
2220 &keynode);
2221 keynode = nextnode;
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");
2229 return (result);
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);
2242 } else {
2243 validator_log(val, ISC_LOG_DEBUG(3),
2244 "no trusted root key");
2245 return (DNS_R_NOVALIDDS);
2249 if (atsep) {
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,
2256 sizeof(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'",
2261 namebuf);
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,
2278 val->event->name,
2279 dns_rdatatype_ds,
2280 &val->frdataset,
2281 &val->fsigrdataset,
2282 dsvalidated,
2283 "validatezonekey");
2284 if (result != ISC_R_SUCCESS)
2285 return (result);
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);
2295 } else
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,
2303 "validatezonekey");
2304 if (result != ISC_R_SUCCESS)
2305 return (result);
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);
2326 * We have a DS set.
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,"
2334 " insecure DS");
2335 return (DNS_R_MUSTBESECURE);
2337 markanswer(val);
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
2344 * verification.
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
2353 * is present.
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,
2365 val->event->name,
2366 ds.algorithm))
2367 continue;
2369 if (ds.digest_type == DNS_DSDIGEST_SHA256 &&
2370 ds.length == ISC_SHA256_DIGESTLENGTH) {
2371 digest_type = DNS_DSDIGEST_SHA256;
2372 break;
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,
2386 ds.digest_type))
2387 continue;
2389 if (ds.digest_type != digest_type)
2390 continue;
2392 if (!dns_resolver_algorithm_supported(val->view->resolver,
2393 val->event->name,
2394 ds.algorithm))
2395 continue;
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)
2416 continue;
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)
2422 continue;
2423 if (dns_rdata_compare(&dsrdata, &newdsrdata) == 0)
2424 break;
2426 if (result != ISC_R_SUCCESS) {
2427 dns_rdataset_disassociate(&trdataset);
2428 validator_log(val, ISC_LOG_DEBUG(3),
2429 "no DNSKEY matching DS");
2430 continue;
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,
2439 &sigrdata);
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)
2444 continue;
2445 if (!dns_name_equal(val->event->name, &sig.signer)) {
2446 validator_log(val, ISC_LOG_DEBUG(3),
2447 "DNSKEY signer mismatch");
2448 continue;
2450 dstkey = NULL;
2451 result = dns_dnssec_keyfromrdata(val->event->name,
2452 &keyrdata,
2453 val->view->mctx,
2454 &dstkey);
2455 if (result != ISC_R_SUCCESS)
2457 * This really shouldn't happen, but...
2459 continue;
2460 result = verify(val, dstkey, &sigrdata, sig.keyid);
2461 dst_key_free(&dstkey);
2462 if (result == ISC_R_SUCCESS)
2463 break;
2465 dns_rdataset_disassociate(&trdataset);
2466 if (result == ISC_R_SUCCESS)
2467 break;
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)");
2475 return (result);
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)");
2485 markanswer(val);
2486 return (ISC_R_SUCCESS);
2487 } else {
2488 validator_log(val, ISC_LOG_INFO,
2489 "no valid signature found (DS)");
2490 return (DNS_R_NOVALIDSIG);
2495 * Starts a positive response validation.
2497 * Returns:
2498 * \li ISC_R_SUCCESS Validation completed successfully
2499 * \li DNS_R_WAIT Validation has started but is waiting
2500 * for an event.
2501 * \li Other return codes are possible and all indicate failure.
2503 static isc_result_t
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.
2519 * Returns
2520 * \li ISC_R_SUCCESS
2522 static isc_result_t
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;
2548 name = NULL;
2549 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
2551 for (rdataset = ISC_LIST_HEAD(name->list);
2552 rdataset != NULL;
2553 rdataset = ISC_LIST_NEXT(rdataset, link))
2555 if (rdataset->type != type)
2556 continue;
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)
2564 break;
2566 if (sigrdataset == NULL)
2567 continue;
2569 if (rdataset->trust != dns_trust_secure)
2570 continue;
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)
2579 == ISC_R_SUCCESS)
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] =
2586 name;
2587 if (!exists)
2588 val->attributes |=
2589 VALATTR_FOUNDNOWILDCARD;
2590 if (!exists && NEEDNOQNAME(val))
2591 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
2592 name;
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] =
2611 name;
2612 if (!exists)
2613 val->attributes |=
2614 VALATTR_FOUNDNOWILDCARD;
2615 if (!exists && NEEDNOQNAME(val))
2616 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
2617 name;
2618 return (ISC_R_SUCCESS);
2622 if (result == ISC_R_NOMORE)
2623 result = ISC_R_SUCCESS;
2624 return (result);
2628 static isc_result_t
2629 findnsec3proofs(dns_validator_t *val) {
2630 dns_name_t *name;
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;
2652 name = NULL;
2653 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
2655 for (rdataset = ISC_LIST_HEAD(name->list);
2656 rdataset != NULL;
2657 rdataset = ISC_LIST_NEXT(rdataset, link))
2659 if (rdataset->type != dns_rdatatype_nsec3)
2660 continue;
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)
2668 break;
2670 if (sigrdataset == NULL)
2671 continue;
2673 if (rdataset->trust != dns_trust_secure)
2674 continue;
2676 result = nsec3noexistnodata(val, val->event->name,
2677 name, rdataset,
2678 zonename, NULL, NULL, NULL,
2679 NULL, NULL, NULL, NULL,
2680 NULL);
2681 if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS)
2682 return (result);
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;
2697 name = NULL;
2698 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
2700 for (rdataset = ISC_LIST_HEAD(name->list);
2701 rdataset != NULL;
2702 rdataset = ISC_LIST_NEXT(rdataset, link))
2704 if (rdataset->type != dns_rdatatype_nsec3)
2705 continue;
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)
2713 break;
2715 if (sigrdataset == NULL)
2716 continue;
2718 if (rdataset->trust != dns_trust_secure)
2719 continue;
2722 * We process all NSEC3 records to find the closest
2723 * encloser and nearest name to the closest encloser.
2725 setclosest = setnearest = ISC_FALSE;
2726 optout = ISC_FALSE;
2727 unknown = ISC_FALSE;
2728 result = nsec3noexistnodata(val, val->event->name,
2729 name, rdataset,
2730 zonename, &exists,
2731 &data, &optout, &unknown,
2732 &setclosest, &setnearest,
2733 closest, nearest);
2734 if (setclosest)
2735 proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
2736 if (unknown)
2737 val->attributes |= VALATTR_FOUNDUNKNOWN;
2738 if (result != ISC_R_SUCCESS)
2739 continue;
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;
2747 if (optout)
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),
2768 NULL);
2769 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2770 } else {
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)
2786 return (result);
2788 return (result);
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
2801 * response.
2803 static isc_result_t
2804 nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
2805 dns_name_t *name;
2806 dns_message_t *message = val->event->message;
2807 isc_result_t result;
2809 if (!resume)
2810 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2811 else {
2812 result = ISC_R_SUCCESS;
2813 validator_log(val, ISC_LOG_DEBUG(3), "resuming nsecvalidate");
2816 for (;
2817 result == ISC_R_SUCCESS;
2818 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
2820 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2822 name = NULL;
2823 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
2824 if (resume) {
2825 rdataset = ISC_LIST_NEXT(val->currentset, link);
2826 val->currentset = NULL;
2827 resume = ISC_FALSE;
2828 } else
2829 rdataset = ISC_LIST_HEAD(name->list);
2831 for (;
2832 rdataset != NULL;
2833 rdataset = ISC_LIST_NEXT(rdataset, link))
2835 if (rdataset->type == dns_rdatatype_rrsig)
2836 continue;
2838 for (sigrdataset = ISC_LIST_HEAD(name->list);
2839 sigrdataset != NULL;
2840 sigrdataset = ISC_LIST_NEXT(sigrdataset,
2841 link))
2843 if (sigrdataset->type == dns_rdatatype_rrsig &&
2844 sigrdataset->covers == rdataset->type)
2845 break;
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)
2863 continue;
2865 result = dns_rdataset_first(rdataset);
2866 if (result != ISC_R_SUCCESS)
2867 return (result);
2868 dns_rdataset_current(rdataset, &nsec);
2869 if (dns_nsec_typepresent(&nsec,
2870 dns_rdatatype_soa))
2871 continue;
2873 val->currentset = rdataset;
2874 result = create_validator(val, name, rdataset->type,
2875 rdataset, sigrdataset,
2876 authvalidated,
2877 "nsecvalidate");
2878 if (result != ISC_R_SUCCESS)
2879 return (result);
2880 return (DNS_R_WAIT);
2884 if (result == ISC_R_NOMORE)
2885 result = ISC_R_SUCCESS;
2886 if (result != ISC_R_SUCCESS)
2887 return (result);
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))
2907 != 0) {
2908 validator_log(val, ISC_LOG_DEBUG(3),
2909 "optout proof found");
2910 val->event->optout = ISC_TRUE;
2911 markanswer(val);
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");
2916 markanswer(val);
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)
2938 return (result);
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;
2965 dns_rdata_ds_t ds;
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,
2976 ds.digest_type) &&
2977 dns_resolver_algorithm_supported(val->view->resolver,
2978 name, ds.algorithm)) {
2979 dns_rdata_reset(&dsrdata);
2980 return (ISC_TRUE);
2982 dns_rdata_reset(&dsrdata);
2984 return (ISC_FALSE);
2988 * Callback from fetching a DLV record.
2990 * Resumes the DLV lookup process.
2992 static void
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;
3001 UNUSED(task);
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));
3021 LOCK(&val->lock);
3022 if (eresult == ISC_R_SUCCESS) {
3023 dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
3024 sizeof(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",
3029 namebuf);
3030 dlv_validator_start(val);
3031 } else {
3032 validator_log(val, ISC_LOG_DEBUG(3),
3033 "DLV %s found with no supported algorithms",
3034 namebuf);
3035 markanswer(val);
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);
3050 } else {
3051 validator_log(val, ISC_LOG_DEBUG(3),
3052 "DLV %s found with no supported "
3053 "algorithms", namebuf);
3054 markanswer(val);
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");
3059 markanswer(val);
3060 validator_done(val, ISC_R_SUCCESS);
3061 } else {
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);
3067 } else {
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);
3073 UNLOCK(&val->lock);
3074 if (want_destroy)
3075 destroy(val);
3079 * Start the DLV lookup process.
3081 * Returns
3082 * \li ISC_R_SUCCESS
3083 * \li DNS_R_WAIT
3084 * \li Others on validation failures.
3086 static isc_result_t
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",
3098 namebuf);
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");
3110 markanswer(val);
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));
3116 return (result);
3118 dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
3119 sizeof(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);
3127 markanswer(val);
3128 validator_done(val, ISC_R_SUCCESS);
3129 return (ISC_R_SUCCESS);
3133 * Continue the DLV lookup process.
3135 * Returns
3136 * \li ISC_R_SUCCESS
3137 * \li ISC_R_NOTFOUND
3138 * \li DNS_R_WAIT
3139 * \li Others on validation failure.
3141 static isc_result_t
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;
3146 dns_name_t *dlvsep;
3147 dns_name_t noroot;
3148 isc_result_t result;
3149 unsigned int labels;
3151 INSIST(val->view->dlv != NULL);
3153 if (!resume) {
3154 if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
3155 dns_name_format(val->event->name, namebuf,
3156 sizeof(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);
3172 if (labels == 0)
3173 return (ISC_R_NOTFOUND);
3174 dns_name_getlabelsequence(dlvsep, 1, labels - 1,
3175 dlvsep);
3177 } else {
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);
3186 if (labels == 0)
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,
3195 dlvname, NULL);
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",
3206 namebuf);
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)
3222 return (result);
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)
3230 return (result);
3232 * Strip first labels from both dlvsep and dlvname.
3234 labels = dns_name_countlabels(dlvsep);
3235 if (labels == 0)
3236 break;
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.
3254 * Returns:
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
3263 static isc_result_t
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;
3269 dns_name_t *tname;
3270 char namebuf[DNS_NAME_FORMATSIZE];
3271 dns_name_t *found;
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);
3280 else {
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,
3290 secroot, secroot);
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;
3300 goto out;
3301 } else
3302 validator_log(val, ISC_LOG_DEBUG(3),
3303 "not beneath secure root");
3304 if (val->view->dlv == NULL || DLVTRIED(val)) {
3305 markanswer(val);
3306 return (ISC_R_SUCCESS);
3308 return (startfinddlvsep(val, dns_rootname));
3309 } else if (result != ISC_R_SUCCESS)
3310 return (result);
3313 if (!resume) {
3315 * We are looking for breaks below the SEP so add a label.
3317 val->labels = dns_name_countlabels(secroot) + 1;
3318 } else {
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),
3328 &val->frdataset)) {
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",
3336 namebuf);
3337 result = DNS_R_MUSTBESECURE;
3338 goto out;
3340 validator_log(val, ISC_LOG_DEBUG(3),
3341 "no supported algorithm/digest (%s/DS)",
3342 namebuf);
3343 if (val->view->dlv == NULL || DLVTRIED(val)) {
3344 markanswer(val);
3345 result = ISC_R_SUCCESS;
3346 goto out;
3348 result = startfinddlvsep(val,
3349 dns_fixedname_name(&val->fname));
3350 goto out;
3352 val->labels++;
3355 for (;
3356 val->labels <= dns_name_countlabels(val->event->name);
3357 val->labels++)
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);
3364 else
3365 dns_name_split(val->event->name, val->labels,
3366 NULL, tname);
3368 dns_name_format(tname, namebuf, sizeof(namebuf));
3369 validator_log(val, ISC_LOG_DEBUG(3),
3370 "checking existence of DS at '%s'",
3371 namebuf);
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,
3378 * we may be done.
3380 if (DNS_TRUST_PENDING(val->frdataset.trust)) {
3381 result = create_fetch(val, tname,
3382 dns_rdatatype_ds,
3383 dsfetched2,
3384 "proveunsecure");
3385 if (result != ISC_R_SUCCESS)
3386 goto out;
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
3392 * the zone cut.
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)) {
3407 markanswer(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;
3423 goto out;
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",
3430 namebuf);
3431 return (DNS_R_MUSTBESECURE);
3433 if (val->view->dlv == NULL || DLVTRIED(val)) {
3434 markanswer(val);
3435 return (ISC_R_SUCCESS);
3437 return (startfinddlvsep(val, tname));
3439 continue;
3440 } else if (result == ISC_R_SUCCESS) {
3442 * There is a DS here. Verify that it's secure and
3443 * continue.
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) {
3451 validator_log(val,
3452 ISC_LOG_WARNING,
3453 "must be secure failure, "
3454 "no supported algorithm/"
3455 "digest (%s/DS)",
3456 namebuf);
3457 result = DNS_R_MUSTBESECURE;
3458 goto out;
3460 if (val->view->dlv == NULL ||
3461 DLVTRIED(val)) {
3462 markanswer(val);
3463 result = ISC_R_SUCCESS;
3464 goto out;
3466 result = startfinddlvsep(val, tname);
3467 goto out;
3469 continue;
3471 else if (!dns_rdataset_isassociated(&val->fsigrdataset))
3473 validator_log(val, ISC_LOG_DEBUG(3),
3474 "DS is unsigned");
3475 result = DNS_R_NOVALIDSIG;
3476 goto out;
3478 result = create_validator(val, tname, dns_rdatatype_ds,
3479 &val->frdataset,
3480 &val->fsigrdataset,
3481 dsvalidated,
3482 "proveunsecure");
3483 if (result != ISC_R_SUCCESS)
3484 goto out;
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;
3498 goto out;
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;
3511 goto out;
3513 continue;
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)
3521 goto out;
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);
3537 out:
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);
3542 return (result);
3546 * Reset state and revalidate the answer using DLV.
3548 static void
3549 dlv_validator_start(dns_validator_t *val) {
3550 isc_event_t *event;
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
3568 * fall in.
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.
3576 static void
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;
3583 UNUSED(task);
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)
3590 return;
3592 if (DLVTRIED(val))
3593 validator_log(val, ISC_LOG_DEBUG(3), "restarting using DLV");
3594 else
3595 validator_log(val, ISC_LOG_DEBUG(3), "starting");
3597 LOCK(&val->lock);
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
3631 * a broken server.
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;
3655 } else
3656 val->attributes |= VALATTR_NEEDNODATA;
3657 result = nsecvalidate(val, ISC_FALSE);
3658 } else {
3660 * This shouldn't happen.
3662 INSIST(0);
3665 if (result != DNS_R_WAIT) {
3666 want_destroy = exit_check(val);
3667 validator_done(val, result);
3670 UNLOCK(&val->lock);
3671 if (want_destroy)
3672 destroy(val);
3675 isc_result_t
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;
3684 isc_task_t *tclone;
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);
3692 tclone = NULL;
3693 result = ISC_R_FAILURE;
3695 val = isc_mem_get(view->mctx, sizeof(*val));
3696 if (val == NULL)
3697 return (ISC_R_NOMEMORY);
3698 val->view = NULL;
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;
3708 goto cleanup_val;
3710 isc_task_attach(task, &tclone);
3711 event->validator = val;
3712 event->result = ISC_R_FAILURE;
3713 event->name = name;
3714 event->type = type;
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)
3722 goto cleanup_event;
3723 val->event = event;
3724 val->options = options;
3725 val->attributes = 0;
3726 val->fetch = NULL;
3727 val->subvalidator = NULL;
3728 val->parent = NULL;
3730 val->keytable = NULL;
3731 result = dns_view_getsecroots(val->view, &val->keytable);
3732 if (result != ISC_R_SUCCESS)
3733 return (result);
3735 val->keynode = NULL;
3736 val->key = NULL;
3737 val->siginfo = NULL;
3738 val->task = task;
3739 val->action = action;
3740 val->arg = arg;
3741 val->labels = 0;
3742 val->currentset = NULL;
3743 val->keyset = NULL;
3744 val->dsset = NULL;
3745 dns_rdataset_init(&val->dlv);
3746 val->seensig = ISC_FALSE;
3747 val->havedlvsep = ISC_FALSE;
3748 val->depth = 0;
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));
3761 *validatorp = val;
3763 return (ISC_R_SUCCESS);
3765 cleanup_event:
3766 isc_task_detach(&tclone);
3767 isc_event_free(ISC_EVENT_PTR(&event));
3769 cleanup_val:
3770 dns_view_weakdetach(&val->view);
3771 isc_mem_put(view->mctx, val, sizeof(*val));
3773 return (result);
3776 void
3777 dns_validator_send(dns_validator_t *validator) {
3778 isc_event_t *event;
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));
3791 void
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);
3816 static void
3817 destroy(dns_validator_t *val) {
3818 isc_mem_t *mctx;
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);
3843 val->magic = 0;
3844 isc_mem_put(mctx, val, sizeof(*val));
3847 void
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);
3853 val = *validatorp;
3854 REQUIRE(VALID_VALIDATOR(val));
3856 LOCK(&val->lock);
3858 val->attributes |= VALATTR_SHUTDOWN;
3859 validator_log(val, ISC_LOG_DEBUG(3), "dns_validator_destroy");
3861 want_destroy = exit_check(val);
3863 UNLOCK(&val->lock);
3865 if (want_destroy)
3866 destroy(val);
3868 *validatorp = NULL;
3871 static void
3872 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
3873 isc_logmodule_t *module, int level, const char *fmt, va_list ap)
3875 char msgbuf[2048];
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,
3890 sizeof(typebuf));
3891 isc_log_write(dns_lctx, category, module, level,
3892 "%.*svalidating @%p: %s %s: %s", depth, spaces,
3893 val, namebuf, typebuf, msgbuf);
3894 } else {
3895 isc_log_write(dns_lctx, category, module, level,
3896 "%.*svalidator @%p: %s", depth, spaces,
3897 val, msgbuf);
3901 static void
3902 validator_log(dns_validator_t *val, int level, const char *fmt, ...) {
3903 va_list ap;
3905 if (! isc_log_wouldlog(dns_lctx, level))
3906 return;
3908 va_start(ap, fmt);
3910 validator_logv(val, DNS_LOGCATEGORY_DNSSEC,
3911 DNS_LOGMODULE_VALIDATOR, level, fmt, ap);
3912 va_end(ap);
3915 static void
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);