BIND: update vendor tree to 9.5.2-P2
[dragonfly.git] / contrib / bind / lib / dns / validator.c
blob937da6688f4c8c6b4c5705d766d036ff8516b02d
1 /*
2 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: validator.c,v 1.155.52.14.2.2 2009/12/31 21:02:44 each Exp $ */
20 #include <config.h>
22 #include <isc/mem.h>
23 #include <isc/print.h>
24 #include <isc/string.h>
25 #include <isc/task.h>
26 #include <isc/util.h>
27 #include <isc/sha2.h>
29 #include <dns/db.h>
30 #include <dns/ds.h>
31 #include <dns/dnssec.h>
32 #include <dns/events.h>
33 #include <dns/keytable.h>
34 #include <dns/log.h>
35 #include <dns/message.h>
36 #include <dns/ncache.h>
37 #include <dns/nsec.h>
38 #include <dns/rdata.h>
39 #include <dns/rdatastruct.h>
40 #include <dns/rdataset.h>
41 #include <dns/rdatatype.h>
42 #include <dns/resolver.h>
43 #include <dns/result.h>
44 #include <dns/validator.h>
45 #include <dns/view.h>
47 /*! \file
48 * \brief
49 * Basic processing sequences.
51 * \li When called with rdataset and sigrdataset:
52 * validator_start -> validate -> proveunsecure -> startfinddlvsep ->
53 * dlv_validator_start -> validator_start -> validate -> proveunsecure
55 * validator_start -> validate -> nsecvalidate (secure wildcard answer)
57 * \li When called with rdataset, sigrdataset and with DNS_VALIDATOR_DLV:
58 * validator_start -> startfinddlvsep -> dlv_validator_start ->
59 * validator_start -> validate -> proveunsecure
61 * \li When called with rdataset:
62 * validator_start -> proveunsecure -> startfinddlvsep ->
63 * dlv_validator_start -> validator_start -> proveunsecure
65 * \li When called with rdataset and with DNS_VALIDATOR_DLV:
66 * validator_start -> startfinddlvsep -> dlv_validator_start ->
67 * validator_start -> proveunsecure
69 * \li When called without a rdataset:
70 * validator_start -> nsecvalidate -> proveunsecure -> startfinddlvsep ->
71 * dlv_validator_start -> validator_start -> nsecvalidate -> proveunsecure
73 * Note: there isn't a case for DNS_VALIDATOR_DLV here as we want nsecvalidate()
74 * to always validate the authority section even when it does not contain
75 * signatures.
77 * validator_start: determines what type of validation to do.
78 * validate: attempts to perform a positive validation.
79 * proveunsecure: attempts to prove the answer comes from a unsecure zone.
80 * nsecvalidate: attempts to prove a negative response.
81 * startfinddlvsep: starts the DLV record lookup.
82 * dlv_validator_start: resets state and restarts the lookup using the
83 * DLV RRset found by startfinddlvsep.
86 #define VALIDATOR_MAGIC ISC_MAGIC('V', 'a', 'l', '?')
87 #define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
89 #define VALATTR_SHUTDOWN 0x0001 /*%< Shutting down. */
90 #define VALATTR_CANCELED 0x0002 /*%< Canceled. */
91 #define VALATTR_TRIEDVERIFY 0x0004 /*%< We have found a key and
92 * have attempted a verify. */
93 #define VALATTR_INSECURITY 0x0010 /*%< Attempting proveunsecure. */
94 #define VALATTR_DLVTRIED 0x0020 /*%< Looked for a DLV record. */
96 /*!
97 * NSEC proofs to be looked for.
99 #define VALATTR_NEEDNOQNAME 0x0100
100 #define VALATTR_NEEDNOWILDCARD 0x0200
101 #define VALATTR_NEEDNODATA 0x0400
104 * NSEC proofs that have been found.
106 #define VALATTR_FOUNDNOQNAME 0x1000
107 #define VALATTR_FOUNDNOWILDCARD 0x2000
108 #define VALATTR_FOUNDNODATA 0x4000
110 #define NEEDNODATA(val) ((val->attributes & VALATTR_NEEDNODATA) != 0)
111 #define NEEDNOQNAME(val) ((val->attributes & VALATTR_NEEDNOQNAME) != 0)
112 #define NEEDNOWILDCARD(val) ((val->attributes & VALATTR_NEEDNOWILDCARD) != 0)
113 #define DLVTRIED(val) ((val->attributes & VALATTR_DLVTRIED) != 0)
115 #define SHUTDOWN(v) (((v)->attributes & VALATTR_SHUTDOWN) != 0)
116 #define CANCELED(v) (((v)->attributes & VALATTR_CANCELED) != 0)
118 static void
119 destroy(dns_validator_t *val);
121 static isc_result_t
122 get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
123 dns_rdataset_t *rdataset);
125 static isc_result_t
126 validate(dns_validator_t *val, isc_boolean_t resume);
128 static isc_result_t
129 validatezonekey(dns_validator_t *val);
131 static isc_result_t
132 nsecvalidate(dns_validator_t *val, isc_boolean_t resume);
134 static isc_result_t
135 proveunsecure(dns_validator_t *val, isc_boolean_t have_ds,
136 isc_boolean_t resume);
138 static void
139 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
140 isc_logmodule_t *module, int level, const char *fmt, va_list ap)
141 ISC_FORMAT_PRINTF(5, 0);
143 static void
144 validator_log(dns_validator_t *val, int level, const char *fmt, ...)
145 ISC_FORMAT_PRINTF(3, 4);
147 static void
148 validator_logcreate(dns_validator_t *val,
149 dns_name_t *name, dns_rdatatype_t type,
150 const char *caller, const char *operation);
152 static isc_result_t
153 dlv_validatezonekey(dns_validator_t *val);
155 static void
156 dlv_validator_start(dns_validator_t *val);
158 static isc_result_t
159 finddlvsep(dns_validator_t *val, isc_boolean_t resume);
161 static isc_result_t
162 startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure);
165 * Mark the RRsets as a answer.
167 static inline void
168 markanswer(dns_validator_t *val) {
169 validator_log(val, ISC_LOG_DEBUG(3), "marking as answer");
170 if (val->event->rdataset != NULL)
171 val->event->rdataset->trust = dns_trust_answer;
172 if (val->event->sigrdataset != NULL)
173 val->event->sigrdataset->trust = dns_trust_answer;
176 static void
177 validator_done(dns_validator_t *val, isc_result_t result) {
178 isc_task_t *task;
180 if (val->event == NULL)
181 return;
184 * Caller must be holding the lock.
187 val->event->result = result;
188 task = val->event->ev_sender;
189 val->event->ev_sender = val;
190 val->event->ev_type = DNS_EVENT_VALIDATORDONE;
191 val->event->ev_action = val->action;
192 val->event->ev_arg = val->arg;
193 isc_task_sendanddetach(&task, (isc_event_t **)&val->event);
196 static inline isc_boolean_t
197 exit_check(dns_validator_t *val) {
199 * Caller must be holding the lock.
201 if (!SHUTDOWN(val))
202 return (ISC_FALSE);
204 INSIST(val->event == NULL);
206 if (val->fetch != NULL || val->subvalidator != NULL)
207 return (ISC_FALSE);
209 return (ISC_TRUE);
213 * Check that we have atleast one supported algorithm in the DLV RRset.
215 static inline isc_boolean_t
216 dlv_algorithm_supported(dns_validator_t *val) {
217 dns_rdata_t rdata = DNS_RDATA_INIT;
218 dns_rdata_dlv_t dlv;
219 isc_result_t result;
221 for (result = dns_rdataset_first(&val->dlv);
222 result == ISC_R_SUCCESS;
223 result = dns_rdataset_next(&val->dlv)) {
224 dns_rdata_reset(&rdata);
225 dns_rdataset_current(&val->dlv, &rdata);
226 result = dns_rdata_tostruct(&rdata, &dlv, NULL);
227 RUNTIME_CHECK(result == ISC_R_SUCCESS);
229 if (!dns_resolver_algorithm_supported(val->view->resolver,
230 val->event->name,
231 dlv.algorithm))
232 continue;
234 if (dlv.digest_type != DNS_DSDIGEST_SHA256 &&
235 dlv.digest_type != DNS_DSDIGEST_SHA1)
236 continue;
238 return (ISC_TRUE);
240 return (ISC_FALSE);
244 * Look in the NSEC record returned from a DS query to see if there is
245 * a NS RRset at this name. If it is found we are at a delegation point.
247 static isc_boolean_t
248 isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
249 isc_result_t dbresult)
251 dns_rdataset_t set;
252 dns_rdata_t rdata = DNS_RDATA_INIT;
253 isc_boolean_t found;
254 isc_result_t result;
256 REQUIRE(dbresult == DNS_R_NXRRSET || dbresult == DNS_R_NCACHENXRRSET);
258 dns_rdataset_init(&set);
259 if (dbresult == DNS_R_NXRRSET)
260 dns_rdataset_clone(rdataset, &set);
261 else {
262 result = dns_ncache_getrdataset(rdataset, name,
263 dns_rdatatype_nsec, &set);
264 if (result != ISC_R_SUCCESS)
265 return (ISC_FALSE);
268 INSIST(set.type == dns_rdatatype_nsec);
270 found = ISC_FALSE;
271 result = dns_rdataset_first(&set);
272 if (result == ISC_R_SUCCESS) {
273 dns_rdataset_current(&set, &rdata);
274 found = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
276 dns_rdataset_disassociate(&set);
277 return (found);
281 * We have been asked to to look for a key.
282 * If found resume the validation process.
283 * If not found fail the validation process.
285 static void
286 fetch_callback_validator(isc_task_t *task, isc_event_t *event) {
287 dns_fetchevent_t *devent;
288 dns_validator_t *val;
289 dns_rdataset_t *rdataset;
290 isc_boolean_t want_destroy;
291 isc_result_t result;
292 isc_result_t eresult;
294 UNUSED(task);
295 INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
296 devent = (dns_fetchevent_t *)event;
297 val = devent->ev_arg;
298 rdataset = &val->frdataset;
299 eresult = devent->result;
301 /* Free resources which are not of interest. */
302 if (devent->node != NULL)
303 dns_db_detachnode(devent->db, &devent->node);
304 if (devent->db != NULL)
305 dns_db_detach(&devent->db);
306 if (dns_rdataset_isassociated(&val->fsigrdataset))
307 dns_rdataset_disassociate(&val->fsigrdataset);
308 isc_event_free(&event);
309 dns_resolver_destroyfetch(&val->fetch);
311 INSIST(val->event != NULL);
313 validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_validator");
314 LOCK(&val->lock);
315 if (CANCELED(val)) {
316 validator_done(val, ISC_R_CANCELED);
317 } else if (eresult == ISC_R_SUCCESS) {
318 validator_log(val, ISC_LOG_DEBUG(3),
319 "keyset with trust %d", rdataset->trust);
321 * Only extract the dst key if the keyset is secure.
323 if (rdataset->trust >= dns_trust_secure) {
324 result = get_dst_key(val, val->siginfo, rdataset);
325 if (result == ISC_R_SUCCESS)
326 val->keyset = &val->frdataset;
328 result = validate(val, ISC_TRUE);
329 if (result != DNS_R_WAIT)
330 validator_done(val, result);
331 } else {
332 validator_log(val, ISC_LOG_DEBUG(3),
333 "fetch_callback_validator: got %s",
334 isc_result_totext(eresult));
335 if (eresult == ISC_R_CANCELED)
336 validator_done(val, eresult);
337 else
338 validator_done(val, DNS_R_NOVALIDKEY);
340 want_destroy = exit_check(val);
341 UNLOCK(&val->lock);
342 if (want_destroy)
343 destroy(val);
347 * We were asked to look for a DS record as part of following a key chain
348 * upwards. If found resume the validation process. If not found fail the
349 * validation process.
351 static void
352 dsfetched(isc_task_t *task, isc_event_t *event) {
353 dns_fetchevent_t *devent;
354 dns_validator_t *val;
355 dns_rdataset_t *rdataset;
356 isc_boolean_t want_destroy;
357 isc_result_t result;
358 isc_result_t eresult;
360 UNUSED(task);
361 INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
362 devent = (dns_fetchevent_t *)event;
363 val = devent->ev_arg;
364 rdataset = &val->frdataset;
365 eresult = devent->result;
367 /* Free resources which are not of interest. */
368 if (devent->node != NULL)
369 dns_db_detachnode(devent->db, &devent->node);
370 if (devent->db != NULL)
371 dns_db_detach(&devent->db);
372 if (dns_rdataset_isassociated(&val->fsigrdataset))
373 dns_rdataset_disassociate(&val->fsigrdataset);
374 isc_event_free(&event);
375 dns_resolver_destroyfetch(&val->fetch);
377 INSIST(val->event != NULL);
379 validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched");
380 LOCK(&val->lock);
381 if (CANCELED(val)) {
382 validator_done(val, ISC_R_CANCELED);
383 } else if (eresult == ISC_R_SUCCESS) {
384 validator_log(val, ISC_LOG_DEBUG(3),
385 "dsset with trust %d", rdataset->trust);
386 val->dsset = &val->frdataset;
387 result = validatezonekey(val);
388 if (result != DNS_R_WAIT)
389 validator_done(val, result);
390 } else if (eresult == DNS_R_NXRRSET ||
391 eresult == DNS_R_NCACHENXRRSET ||
392 eresult == DNS_R_SERVFAIL) /* RFC 1034 parent? */
394 validator_log(val, ISC_LOG_DEBUG(3),
395 "falling back to insecurity proof (%s)",
396 dns_result_totext(eresult));
397 val->attributes |= VALATTR_INSECURITY;
398 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
399 if (result != DNS_R_WAIT)
400 validator_done(val, result);
401 } else {
402 validator_log(val, ISC_LOG_DEBUG(3),
403 "dsfetched: got %s",
404 isc_result_totext(eresult));
405 if (eresult == ISC_R_CANCELED)
406 validator_done(val, eresult);
407 else
408 validator_done(val, DNS_R_NOVALIDDS);
410 want_destroy = exit_check(val);
411 UNLOCK(&val->lock);
412 if (want_destroy)
413 destroy(val);
417 * We were asked to look for the DS record as part of proving that a
418 * name is unsecure.
420 * If the DS record doesn't exist and the query name corresponds to
421 * a delegation point we are transitioning from a secure zone to a
422 * unsecure zone.
424 * If the DS record exists it will be secure. We can continue looking
425 * for the break point in the chain of trust.
427 static void
428 dsfetched2(isc_task_t *task, isc_event_t *event) {
429 dns_fetchevent_t *devent;
430 dns_validator_t *val;
431 dns_name_t *tname;
432 isc_boolean_t want_destroy;
433 isc_result_t result;
434 isc_result_t eresult;
436 UNUSED(task);
437 INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
438 devent = (dns_fetchevent_t *)event;
439 val = devent->ev_arg;
440 eresult = devent->result;
442 /* Free resources which are not of interest. */
443 if (devent->node != NULL)
444 dns_db_detachnode(devent->db, &devent->node);
445 if (devent->db != NULL)
446 dns_db_detach(&devent->db);
447 if (dns_rdataset_isassociated(&val->fsigrdataset))
448 dns_rdataset_disassociate(&val->fsigrdataset);
449 dns_resolver_destroyfetch(&val->fetch);
451 INSIST(val->event != NULL);
453 validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched2: %s",
454 dns_result_totext(eresult));
455 LOCK(&val->lock);
456 if (CANCELED(val)) {
457 validator_done(val, ISC_R_CANCELED);
458 } else if (eresult == DNS_R_NXRRSET || eresult == DNS_R_NCACHENXRRSET) {
460 * There is no DS. If this is a delegation, we're done.
462 tname = dns_fixedname_name(&devent->foundname);
463 if (isdelegation(tname, &val->frdataset, eresult)) {
464 if (val->mustbesecure) {
465 validator_log(val, ISC_LOG_WARNING,
466 "must be secure failure");
467 validator_done(val, DNS_R_MUSTBESECURE);
468 } else if (val->view->dlv == NULL || DLVTRIED(val)) {
469 markanswer(val);
470 validator_done(val, ISC_R_SUCCESS);
471 } else {
472 result = startfinddlvsep(val, tname);
473 if (result != DNS_R_WAIT)
474 validator_done(val, result);
476 } else {
477 result = proveunsecure(val, ISC_FALSE, ISC_TRUE);
478 if (result != DNS_R_WAIT)
479 validator_done(val, result);
481 } else if (eresult == ISC_R_SUCCESS ||
482 eresult == DNS_R_NXDOMAIN ||
483 eresult == DNS_R_NCACHENXDOMAIN)
486 * There is a DS which may or may not be a zone cut.
487 * In either case we are still in a secure zone resume
488 * validation.
490 result = proveunsecure(val, ISC_TF(eresult == ISC_R_SUCCESS),
491 ISC_TRUE);
492 if (result != DNS_R_WAIT)
493 validator_done(val, result);
494 } else {
495 if (eresult == ISC_R_CANCELED)
496 validator_done(val, eresult);
497 else
498 validator_done(val, DNS_R_NOVALIDDS);
500 isc_event_free(&event);
501 want_destroy = exit_check(val);
502 UNLOCK(&val->lock);
503 if (want_destroy)
504 destroy(val);
508 * Callback from when a DNSKEY RRset has been validated.
510 * Resumes the stalled validation process.
512 static void
513 keyvalidated(isc_task_t *task, isc_event_t *event) {
514 dns_validatorevent_t *devent;
515 dns_validator_t *val;
516 isc_boolean_t want_destroy;
517 isc_result_t result;
518 isc_result_t eresult;
520 UNUSED(task);
521 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
523 devent = (dns_validatorevent_t *)event;
524 val = devent->ev_arg;
525 eresult = devent->result;
527 isc_event_free(&event);
528 dns_validator_destroy(&val->subvalidator);
530 INSIST(val->event != NULL);
532 validator_log(val, ISC_LOG_DEBUG(3), "in keyvalidated");
533 LOCK(&val->lock);
534 if (CANCELED(val)) {
535 validator_done(val, ISC_R_CANCELED);
536 } else if (eresult == ISC_R_SUCCESS) {
537 validator_log(val, ISC_LOG_DEBUG(3),
538 "keyset with trust %d", val->frdataset.trust);
540 * Only extract the dst key if the keyset is secure.
542 if (val->frdataset.trust >= dns_trust_secure)
543 (void) get_dst_key(val, val->siginfo, &val->frdataset);
544 result = validate(val, ISC_TRUE);
545 if (result != DNS_R_WAIT)
546 validator_done(val, result);
547 } else {
548 validator_log(val, ISC_LOG_DEBUG(3),
549 "keyvalidated: got %s",
550 isc_result_totext(eresult));
551 validator_done(val, eresult);
553 want_destroy = exit_check(val);
554 UNLOCK(&val->lock);
555 if (want_destroy)
556 destroy(val);
560 * Callback when the DS record has been validated.
562 * Resumes validation of the zone key or the unsecure zone proof.
564 static void
565 dsvalidated(isc_task_t *task, isc_event_t *event) {
566 dns_validatorevent_t *devent;
567 dns_validator_t *val;
568 isc_boolean_t want_destroy;
569 isc_result_t result;
570 isc_result_t eresult;
572 UNUSED(task);
573 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
575 devent = (dns_validatorevent_t *)event;
576 val = devent->ev_arg;
577 eresult = devent->result;
579 isc_event_free(&event);
580 dns_validator_destroy(&val->subvalidator);
582 INSIST(val->event != NULL);
584 validator_log(val, ISC_LOG_DEBUG(3), "in dsvalidated");
585 LOCK(&val->lock);
586 if (CANCELED(val)) {
587 validator_done(val, ISC_R_CANCELED);
588 } else if (eresult == ISC_R_SUCCESS) {
589 validator_log(val, ISC_LOG_DEBUG(3),
590 "dsset with trust %d", val->frdataset.trust);
591 if ((val->attributes & VALATTR_INSECURITY) != 0)
592 result = proveunsecure(val, ISC_TRUE, ISC_TRUE);
593 else
594 result = validatezonekey(val);
595 if (result != DNS_R_WAIT)
596 validator_done(val, result);
597 } else {
598 validator_log(val, ISC_LOG_DEBUG(3),
599 "dsvalidated: got %s",
600 isc_result_totext(eresult));
601 validator_done(val, eresult);
603 want_destroy = exit_check(val);
604 UNLOCK(&val->lock);
605 if (want_destroy)
606 destroy(val);
610 * Return ISC_R_SUCCESS if we can determine that the name doesn't exist
611 * or we can determine whether there is data or not at the name.
612 * If the name does not exist return the wildcard name.
614 * Return ISC_R_IGNORE when the NSEC is not the appropriate one.
616 static isc_result_t
617 nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
618 dns_rdataset_t *nsecset, isc_boolean_t *exists,
619 isc_boolean_t *data, dns_name_t *wild)
621 int order;
622 dns_rdata_t rdata = DNS_RDATA_INIT;
623 isc_result_t result;
624 dns_namereln_t relation;
625 unsigned int olabels, nlabels, labels;
626 dns_rdata_nsec_t nsec;
627 isc_boolean_t atparent;
628 isc_boolean_t ns;
629 isc_boolean_t soa;
631 REQUIRE(exists != NULL);
632 REQUIRE(data != NULL);
633 REQUIRE(nsecset != NULL &&
634 nsecset->type == dns_rdatatype_nsec);
636 result = dns_rdataset_first(nsecset);
637 if (result != ISC_R_SUCCESS) {
638 validator_log(val, ISC_LOG_DEBUG(3),
639 "failure processing NSEC set");
640 return (result);
642 dns_rdataset_current(nsecset, &rdata);
644 validator_log(val, ISC_LOG_DEBUG(3), "looking for relevant nsec");
645 relation = dns_name_fullcompare(name, nsecname, &order, &olabels);
647 if (order < 0) {
649 * The name is not within the NSEC range.
651 validator_log(val, ISC_LOG_DEBUG(3),
652 "NSEC does not cover name, before NSEC");
653 return (ISC_R_IGNORE);
656 if (order == 0) {
658 * The names are the same.
660 atparent = dns_rdatatype_atparent(val->event->type);
661 ns = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
662 soa = dns_nsec_typepresent(&rdata, dns_rdatatype_soa);
663 if (ns && !soa) {
664 if (!atparent) {
666 * This NSEC record is from somewhere higher in
667 * the DNS, and at the parent of a delegation.
668 * It can not be legitimately used here.
670 validator_log(val, ISC_LOG_DEBUG(3),
671 "ignoring parent nsec");
672 return (ISC_R_IGNORE);
674 } else if (atparent && ns && soa) {
676 * This NSEC record is from the child.
677 * It can not be legitimately used here.
679 validator_log(val, ISC_LOG_DEBUG(3),
680 "ignoring child nsec");
681 return (ISC_R_IGNORE);
683 if (val->event->type == dns_rdatatype_cname ||
684 val->event->type == dns_rdatatype_nxt ||
685 val->event->type == dns_rdatatype_nsec ||
686 val->event->type == dns_rdatatype_key ||
687 !dns_nsec_typepresent(&rdata, dns_rdatatype_cname)) {
688 *exists = ISC_TRUE;
689 *data = dns_nsec_typepresent(&rdata, val->event->type);
690 validator_log(val, ISC_LOG_DEBUG(3),
691 "nsec proves name exists (owner) data=%d",
692 *data);
693 return (ISC_R_SUCCESS);
695 validator_log(val, ISC_LOG_DEBUG(3), "NSEC proves CNAME exists");
696 return (ISC_R_IGNORE);
699 if (relation == dns_namereln_subdomain &&
700 dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
701 !dns_nsec_typepresent(&rdata, dns_rdatatype_soa))
704 * This NSEC record is from somewhere higher in
705 * the DNS, and at the parent of a delegation.
706 * It can not be legitimately used here.
708 validator_log(val, ISC_LOG_DEBUG(3), "ignoring parent nsec");
709 return (ISC_R_IGNORE);
712 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
713 if (result != ISC_R_SUCCESS)
714 return (result);
715 relation = dns_name_fullcompare(&nsec.next, name, &order, &nlabels);
716 if (order == 0) {
717 dns_rdata_freestruct(&nsec);
718 validator_log(val, ISC_LOG_DEBUG(3),
719 "ignoring nsec matches next name");
720 return (ISC_R_IGNORE);
723 if (order < 0 && !dns_name_issubdomain(nsecname, &nsec.next)) {
725 * The name is not within the NSEC range.
727 dns_rdata_freestruct(&nsec);
728 validator_log(val, ISC_LOG_DEBUG(3),
729 "ignoring nsec because name is past end of range");
730 return (ISC_R_IGNORE);
733 if (order > 0 && relation == dns_namereln_subdomain) {
734 validator_log(val, ISC_LOG_DEBUG(3),
735 "nsec proves name exist (empty)");
736 dns_rdata_freestruct(&nsec);
737 *exists = ISC_TRUE;
738 *data = ISC_FALSE;
739 return (ISC_R_SUCCESS);
741 if (wild != NULL) {
742 dns_name_t common;
743 dns_name_init(&common, NULL);
744 if (olabels > nlabels) {
745 labels = dns_name_countlabels(nsecname);
746 dns_name_getlabelsequence(nsecname, labels - olabels,
747 olabels, &common);
748 } else {
749 labels = dns_name_countlabels(&nsec.next);
750 dns_name_getlabelsequence(&nsec.next, labels - nlabels,
751 nlabels, &common);
753 result = dns_name_concatenate(dns_wildcardname, &common,
754 wild, NULL);
755 if (result != ISC_R_SUCCESS) {
756 dns_rdata_freestruct(&nsec);
757 validator_log(val, ISC_LOG_DEBUG(3),
758 "failure generating wildcard name");
759 return (result);
762 dns_rdata_freestruct(&nsec);
763 validator_log(val, ISC_LOG_DEBUG(3), "nsec range ok");
764 *exists = ISC_FALSE;
765 return (ISC_R_SUCCESS);
769 * Callback for when NSEC records have been validated.
771 * Looks for NOQNAME and NODATA proofs.
773 * Resumes nsecvalidate.
775 static void
776 authvalidated(isc_task_t *task, isc_event_t *event) {
777 dns_validatorevent_t *devent;
778 dns_validator_t *val;
779 dns_rdataset_t *rdataset;
780 isc_boolean_t want_destroy;
781 isc_result_t result;
782 isc_boolean_t exists, data;
784 UNUSED(task);
785 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
787 devent = (dns_validatorevent_t *)event;
788 rdataset = devent->rdataset;
789 val = devent->ev_arg;
790 result = devent->result;
791 dns_validator_destroy(&val->subvalidator);
793 INSIST(val->event != NULL);
795 validator_log(val, ISC_LOG_DEBUG(3), "in authvalidated");
796 LOCK(&val->lock);
797 if (CANCELED(val)) {
798 validator_done(val, ISC_R_CANCELED);
799 } else if (result != ISC_R_SUCCESS) {
800 validator_log(val, ISC_LOG_DEBUG(3),
801 "authvalidated: got %s",
802 isc_result_totext(result));
803 if (result == ISC_R_CANCELED)
804 validator_done(val, result);
805 else {
806 result = nsecvalidate(val, ISC_TRUE);
807 if (result != DNS_R_WAIT)
808 validator_done(val, result);
810 } else {
811 dns_name_t **proofs = val->event->proofs;
812 dns_name_t *wild = dns_fixedname_name(&val->wild);
814 if (rdataset->trust == dns_trust_secure)
815 val->seensig = ISC_TRUE;
817 if (rdataset->type == dns_rdatatype_nsec &&
818 rdataset->trust == dns_trust_secure &&
819 ((val->attributes & VALATTR_NEEDNODATA) != 0 ||
820 (val->attributes & VALATTR_NEEDNOQNAME) != 0) &&
821 (val->attributes & VALATTR_FOUNDNODATA) == 0 &&
822 (val->attributes & VALATTR_FOUNDNOQNAME) == 0 &&
823 nsecnoexistnodata(val, val->event->name, devent->name,
824 rdataset, &exists, &data, wild)
825 == ISC_R_SUCCESS)
827 if (exists && !data) {
828 val->attributes |= VALATTR_FOUNDNODATA;
829 if (NEEDNODATA(val))
830 proofs[DNS_VALIDATOR_NODATAPROOF] =
831 devent->name;
833 if (!exists) {
834 val->attributes |= VALATTR_FOUNDNOQNAME;
835 if (NEEDNOQNAME(val))
836 proofs[DNS_VALIDATOR_NOQNAMEPROOF] =
837 devent->name;
840 result = nsecvalidate(val, ISC_TRUE);
841 if (result != DNS_R_WAIT)
842 validator_done(val, result);
844 want_destroy = exit_check(val);
845 UNLOCK(&val->lock);
846 if (want_destroy)
847 destroy(val);
850 * Free stuff from the event.
852 isc_event_free(&event);
856 * Looks for the requested name and type in the view (zones and cache).
858 * When looking for a DLV record also checks to make sure the NSEC record
859 * returns covers the query name as part of aggressive negative caching.
861 * Returns:
862 * \li ISC_R_SUCCESS
863 * \li ISC_R_NOTFOUND
864 * \li DNS_R_NCACHENXDOMAIN
865 * \li DNS_R_NCACHENXRRSET
866 * \li DNS_R_NXRRSET
867 * \li DNS_R_NXDOMAIN
869 static inline isc_result_t
870 view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
871 dns_fixedname_t fixedname;
872 dns_name_t *foundname;
873 dns_rdata_nsec_t nsec;
874 dns_rdata_t rdata = DNS_RDATA_INIT;
875 isc_result_t result;
876 unsigned int options;
877 char buf1[DNS_NAME_FORMATSIZE];
878 char buf2[DNS_NAME_FORMATSIZE];
879 char buf3[DNS_NAME_FORMATSIZE];
881 if (dns_rdataset_isassociated(&val->frdataset))
882 dns_rdataset_disassociate(&val->frdataset);
883 if (dns_rdataset_isassociated(&val->fsigrdataset))
884 dns_rdataset_disassociate(&val->fsigrdataset);
886 if (val->view->zonetable == NULL)
887 return (ISC_R_CANCELED);
889 options = DNS_DBFIND_PENDINGOK;
890 if (type == dns_rdatatype_dlv)
891 options |= DNS_DBFIND_COVERINGNSEC;
892 dns_fixedname_init(&fixedname);
893 foundname = dns_fixedname_name(&fixedname);
894 result = dns_view_find(val->view, name, type, 0, options,
895 ISC_FALSE, NULL, NULL, foundname,
896 &val->frdataset, &val->fsigrdataset);
897 if (result == DNS_R_NXDOMAIN) {
898 if (dns_rdataset_isassociated(&val->frdataset))
899 dns_rdataset_disassociate(&val->frdataset);
900 if (dns_rdataset_isassociated(&val->fsigrdataset))
901 dns_rdataset_disassociate(&val->fsigrdataset);
902 } else if (result == DNS_R_COVERINGNSEC) {
903 validator_log(val, ISC_LOG_DEBUG(3), "DNS_R_COVERINGNSEC");
905 * Check if the returned NSEC covers the name.
907 INSIST(type == dns_rdatatype_dlv);
908 if (val->frdataset.trust != dns_trust_secure) {
909 validator_log(val, ISC_LOG_DEBUG(3),
910 "covering nsec: trust %u",
911 val->frdataset.trust);
912 goto notfound;
914 result = dns_rdataset_first(&val->frdataset);
915 if (result != ISC_R_SUCCESS)
916 goto notfound;
917 dns_rdataset_current(&val->frdataset, &rdata);
918 if (dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
919 !dns_nsec_typepresent(&rdata, dns_rdatatype_soa)) {
920 /* Parent NSEC record. */
921 if (dns_name_issubdomain(name, foundname)) {
922 validator_log(val, ISC_LOG_DEBUG(3),
923 "covering nsec: for parent");
924 goto notfound;
927 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
928 if (result != ISC_R_SUCCESS)
929 goto notfound;
930 if (dns_name_compare(foundname, &nsec.next) >= 0) {
931 /* End of zone chain. */
932 if (!dns_name_issubdomain(name, &nsec.next)) {
934 * XXXMPA We could look for a parent NSEC
935 * at nsec.next and if found retest with
936 * this NSEC.
938 dns_rdata_freestruct(&nsec);
939 validator_log(val, ISC_LOG_DEBUG(3),
940 "covering nsec: not in zone");
941 goto notfound;
943 } else if (dns_name_compare(name, &nsec.next) >= 0) {
945 * XXXMPA We could check if this NSEC is at a zone
946 * apex and if the qname is not below it and look for
947 * a parent NSEC with the same name. This requires
948 * that we can cache both NSEC records which we
949 * currently don't support.
951 dns_rdata_freestruct(&nsec);
952 validator_log(val, ISC_LOG_DEBUG(3),
953 "covering nsec: not in range");
954 goto notfound;
956 if (isc_log_wouldlog(dns_lctx,ISC_LOG_DEBUG(3))) {
957 dns_name_format(name, buf1, sizeof buf1);
958 dns_name_format(foundname, buf2, sizeof buf2);
959 dns_name_format(&nsec.next, buf3, sizeof buf3);
960 validator_log(val, ISC_LOG_DEBUG(3),
961 "covering nsec found: '%s' '%s' '%s'",
962 buf1, buf2, buf3);
964 if (dns_rdataset_isassociated(&val->frdataset))
965 dns_rdataset_disassociate(&val->frdataset);
966 if (dns_rdataset_isassociated(&val->fsigrdataset))
967 dns_rdataset_disassociate(&val->fsigrdataset);
968 dns_rdata_freestruct(&nsec);
969 result = DNS_R_NCACHENXDOMAIN;
970 } else if (result != ISC_R_SUCCESS &&
971 result != DNS_R_NCACHENXDOMAIN &&
972 result != DNS_R_NCACHENXRRSET &&
973 result != DNS_R_EMPTYNAME &&
974 result != DNS_R_NXRRSET &&
975 result != ISC_R_NOTFOUND) {
976 goto notfound;
978 return (result);
980 notfound:
981 if (dns_rdataset_isassociated(&val->frdataset))
982 dns_rdataset_disassociate(&val->frdataset);
983 if (dns_rdataset_isassociated(&val->fsigrdataset))
984 dns_rdataset_disassociate(&val->fsigrdataset);
985 return (ISC_R_NOTFOUND);
989 * Checks to make sure we are not going to loop. As we use a SHARED fetch
990 * the validation process will stall if looping was to occur.
992 static inline isc_boolean_t
993 check_deadlock(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
994 dns_validator_t *parent;
996 for (parent = val; parent != NULL; parent = parent->parent) {
997 if (parent->event != NULL &&
998 parent->event->type == type &&
999 dns_name_equal(parent->event->name, name))
1001 validator_log(val, ISC_LOG_DEBUG(3),
1002 "continuing validation would lead to "
1003 "deadlock: aborting validation");
1004 return (ISC_TRUE);
1007 return (ISC_FALSE);
1011 * Start a fetch for the requested name and type.
1013 static inline isc_result_t
1014 create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
1015 isc_taskaction_t callback, const char *caller)
1017 if (dns_rdataset_isassociated(&val->frdataset))
1018 dns_rdataset_disassociate(&val->frdataset);
1019 if (dns_rdataset_isassociated(&val->fsigrdataset))
1020 dns_rdataset_disassociate(&val->fsigrdataset);
1022 if (check_deadlock(val, name, type))
1023 return (DNS_R_NOVALIDSIG);
1025 validator_logcreate(val, name, type, caller, "fetch");
1026 return (dns_resolver_createfetch(val->view->resolver, name, type,
1027 NULL, NULL, NULL, 0,
1028 val->event->ev_sender,
1029 callback, val,
1030 &val->frdataset,
1031 &val->fsigrdataset,
1032 &val->fetch));
1036 * Start a subvalidation process.
1038 static inline isc_result_t
1039 create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
1040 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
1041 isc_taskaction_t action, const char *caller)
1043 isc_result_t result;
1045 if (check_deadlock(val, name, type))
1046 return (DNS_R_NOVALIDSIG);
1048 validator_logcreate(val, name, type, caller, "validator");
1049 result = dns_validator_create(val->view, name, type,
1050 rdataset, sigrdataset, NULL, 0,
1051 val->task, action, val,
1052 &val->subvalidator);
1053 if (result == ISC_R_SUCCESS) {
1054 val->subvalidator->parent = val;
1055 val->subvalidator->depth = val->depth + 1;
1057 return (result);
1061 * Try to find a key that could have signed 'siginfo' among those
1062 * in 'rdataset'. If found, build a dst_key_t for it and point
1063 * val->key at it.
1065 * If val->key is non-NULL, this returns the next matching key.
1067 static isc_result_t
1068 get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
1069 dns_rdataset_t *rdataset)
1071 isc_result_t result;
1072 isc_buffer_t b;
1073 dns_rdata_t rdata = DNS_RDATA_INIT;
1074 dst_key_t *oldkey = val->key;
1075 isc_boolean_t foundold;
1077 if (oldkey == NULL)
1078 foundold = ISC_TRUE;
1079 else {
1080 foundold = ISC_FALSE;
1081 val->key = NULL;
1084 result = dns_rdataset_first(rdataset);
1085 if (result != ISC_R_SUCCESS)
1086 goto failure;
1087 do {
1088 dns_rdataset_current(rdataset, &rdata);
1090 isc_buffer_init(&b, rdata.data, rdata.length);
1091 isc_buffer_add(&b, rdata.length);
1092 INSIST(val->key == NULL);
1093 result = dst_key_fromdns(&siginfo->signer, rdata.rdclass, &b,
1094 val->view->mctx, &val->key);
1095 if (result != ISC_R_SUCCESS)
1096 goto failure;
1097 if (siginfo->algorithm ==
1098 (dns_secalg_t)dst_key_alg(val->key) &&
1099 siginfo->keyid ==
1100 (dns_keytag_t)dst_key_id(val->key) &&
1101 dst_key_iszonekey(val->key))
1103 if (foundold)
1105 * This is the key we're looking for.
1107 return (ISC_R_SUCCESS);
1108 else if (dst_key_compare(oldkey, val->key) == ISC_TRUE)
1110 foundold = ISC_TRUE;
1111 dst_key_free(&oldkey);
1114 dst_key_free(&val->key);
1115 dns_rdata_reset(&rdata);
1116 result = dns_rdataset_next(rdataset);
1117 } while (result == ISC_R_SUCCESS);
1118 if (result == ISC_R_NOMORE)
1119 result = ISC_R_NOTFOUND;
1121 failure:
1122 if (oldkey != NULL)
1123 dst_key_free(&oldkey);
1125 return (result);
1129 * Get the key that generated this signature.
1131 static isc_result_t
1132 get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
1133 isc_result_t result;
1134 unsigned int nlabels;
1135 int order;
1136 dns_namereln_t namereln;
1139 * Is the signer name appropriate for this signature?
1141 * The signer name must be at the same level as the owner name
1142 * or closer to the DNS root.
1144 namereln = dns_name_fullcompare(val->event->name, &siginfo->signer,
1145 &order, &nlabels);
1146 if (namereln != dns_namereln_subdomain &&
1147 namereln != dns_namereln_equal)
1148 return (DNS_R_CONTINUE);
1150 if (namereln == dns_namereln_equal) {
1152 * If this is a self-signed keyset, it must not be a zone key
1153 * (since get_key is not called from validatezonekey).
1155 if (val->event->rdataset->type == dns_rdatatype_dnskey)
1156 return (DNS_R_CONTINUE);
1159 * Records appearing in the parent zone at delegation
1160 * points cannot be self-signed.
1162 if (dns_rdatatype_atparent(val->event->rdataset->type))
1163 return (DNS_R_CONTINUE);
1164 } else {
1166 * SOA and NS RRsets can only be signed by a key with
1167 * the same name.
1169 if (val->event->rdataset->type == dns_rdatatype_soa ||
1170 val->event->rdataset->type == dns_rdatatype_ns) {
1171 const char *typename;
1173 if (val->event->rdataset->type == dns_rdatatype_soa)
1174 typename = "SOA";
1175 else
1176 typename = "NS";
1177 validator_log(val, ISC_LOG_DEBUG(3),
1178 "%s signer mismatch", typename);
1179 return (DNS_R_CONTINUE);
1184 * Do we know about this key?
1186 result = view_find(val, &siginfo->signer, dns_rdatatype_dnskey);
1187 if (result == ISC_R_SUCCESS) {
1189 * We have an rrset for the given keyname.
1191 val->keyset = &val->frdataset;
1192 if (DNS_TRUST_PENDING(val->frdataset.trust) &&
1193 dns_rdataset_isassociated(&val->fsigrdataset))
1196 * We know the key but haven't validated it yet.
1198 result = create_validator(val, &siginfo->signer,
1199 dns_rdatatype_dnskey,
1200 &val->frdataset,
1201 &val->fsigrdataset,
1202 keyvalidated,
1203 "get_key");
1204 if (result != ISC_R_SUCCESS)
1205 return (result);
1206 return (DNS_R_WAIT);
1207 } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
1209 * Having a pending key with no signature means that
1210 * something is broken.
1212 result = DNS_R_CONTINUE;
1213 } else if (val->frdataset.trust < dns_trust_secure) {
1215 * The key is legitimately insecure. There's no
1216 * point in even attempting verification.
1218 val->key = NULL;
1219 result = ISC_R_SUCCESS;
1220 } else {
1222 * See if we've got the key used in the signature.
1224 validator_log(val, ISC_LOG_DEBUG(3),
1225 "keyset with trust %d",
1226 val->frdataset.trust);
1227 result = get_dst_key(val, siginfo, val->keyset);
1228 if (result != ISC_R_SUCCESS) {
1230 * Either the key we're looking for is not
1231 * in the rrset, or something bad happened.
1232 * Give up.
1234 result = DNS_R_CONTINUE;
1237 } else if (result == ISC_R_NOTFOUND) {
1239 * We don't know anything about this key.
1241 result = create_fetch(val, &siginfo->signer, dns_rdatatype_dnskey,
1242 fetch_callback_validator, "get_key");
1243 if (result != ISC_R_SUCCESS)
1244 return (result);
1245 return (DNS_R_WAIT);
1246 } else if (result == DNS_R_NCACHENXDOMAIN ||
1247 result == DNS_R_NCACHENXRRSET ||
1248 result == DNS_R_EMPTYNAME ||
1249 result == DNS_R_NXDOMAIN ||
1250 result == DNS_R_NXRRSET)
1253 * This key doesn't exist.
1255 result = DNS_R_CONTINUE;
1258 if (dns_rdataset_isassociated(&val->frdataset) &&
1259 val->keyset != &val->frdataset)
1260 dns_rdataset_disassociate(&val->frdataset);
1261 if (dns_rdataset_isassociated(&val->fsigrdataset))
1262 dns_rdataset_disassociate(&val->fsigrdataset);
1264 return (result);
1267 static dns_keytag_t
1268 compute_keytag(dns_rdata_t *rdata, dns_rdata_dnskey_t *key) {
1269 isc_region_t r;
1271 dns_rdata_toregion(rdata, &r);
1272 return (dst_region_computeid(&r, key->algorithm));
1276 * Is this keyset self-signed?
1278 static isc_boolean_t
1279 isselfsigned(dns_validator_t *val) {
1280 dns_rdataset_t *rdataset, *sigrdataset;
1281 dns_rdata_t rdata = DNS_RDATA_INIT;
1282 dns_rdata_t sigrdata = DNS_RDATA_INIT;
1283 dns_rdata_dnskey_t key;
1284 dns_rdata_rrsig_t sig;
1285 dns_keytag_t keytag;
1286 isc_result_t result;
1288 rdataset = val->event->rdataset;
1289 sigrdataset = val->event->sigrdataset;
1291 INSIST(rdataset->type == dns_rdatatype_dnskey);
1293 for (result = dns_rdataset_first(rdataset);
1294 result == ISC_R_SUCCESS;
1295 result = dns_rdataset_next(rdataset))
1297 dns_rdata_reset(&rdata);
1298 dns_rdataset_current(rdataset, &rdata);
1299 result = dns_rdata_tostruct(&rdata, &key, NULL);
1300 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1301 keytag = compute_keytag(&rdata, &key);
1302 for (result = dns_rdataset_first(sigrdataset);
1303 result == ISC_R_SUCCESS;
1304 result = dns_rdataset_next(sigrdataset))
1306 dns_rdata_reset(&sigrdata);
1307 dns_rdataset_current(sigrdataset, &sigrdata);
1308 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
1309 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1311 if (sig.algorithm == key.algorithm &&
1312 sig.keyid == keytag)
1313 return (ISC_TRUE);
1316 return (ISC_FALSE);
1320 * Attempt to verify the rdataset using the given key and rdata (RRSIG).
1321 * The signature was good and from a wildcard record and the QNAME does
1322 * not match the wildcard we need to look for a NOQNAME proof.
1324 * Returns:
1325 * \li ISC_R_SUCCESS if the verification succeeds.
1326 * \li Others if the verification fails.
1328 static isc_result_t
1329 verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata,
1330 isc_uint16_t keyid)
1332 isc_result_t result;
1333 dns_fixedname_t fixed;
1334 isc_boolean_t ignore = ISC_FALSE;
1336 val->attributes |= VALATTR_TRIEDVERIFY;
1337 dns_fixedname_init(&fixed);
1338 again:
1339 result = dns_dnssec_verify2(val->event->name, val->event->rdataset,
1340 key, ignore, val->view->mctx, rdata,
1341 dns_fixedname_name(&fixed));
1342 if (result == DNS_R_SIGEXPIRED && val->view->acceptexpired) {
1343 ignore = ISC_TRUE;
1344 goto again;
1346 if (ignore && (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD))
1347 validator_log(val, ISC_LOG_INFO,
1348 "accepted expired %sRRSIG (keyid=%u)",
1349 (result == DNS_R_FROMWILDCARD) ?
1350 "wildcard " : "", keyid);
1351 else
1352 validator_log(val, ISC_LOG_DEBUG(3),
1353 "verify rdataset (keyid=%u): %s",
1354 keyid, isc_result_totext(result));
1355 if (result == DNS_R_FROMWILDCARD) {
1356 if (!dns_name_equal(val->event->name,
1357 dns_fixedname_name(&fixed)))
1358 val->attributes |= VALATTR_NEEDNOQNAME;
1359 result = ISC_R_SUCCESS;
1361 return (result);
1365 * Attempts positive response validation of a normal RRset.
1367 * Returns:
1368 * \li ISC_R_SUCCESS Validation completed successfully
1369 * \li DNS_R_WAIT Validation has started but is waiting
1370 * for an event.
1371 * \li Other return codes are possible and all indicate failure.
1373 static isc_result_t
1374 validate(dns_validator_t *val, isc_boolean_t resume) {
1375 isc_result_t result;
1376 dns_validatorevent_t *event;
1377 dns_rdata_t rdata = DNS_RDATA_INIT;
1380 * Caller must be holding the validator lock.
1383 event = val->event;
1385 if (resume) {
1387 * We already have a sigrdataset.
1389 result = ISC_R_SUCCESS;
1390 validator_log(val, ISC_LOG_DEBUG(3), "resuming validate");
1391 } else {
1392 result = dns_rdataset_first(event->sigrdataset);
1395 for (;
1396 result == ISC_R_SUCCESS;
1397 result = dns_rdataset_next(event->sigrdataset))
1399 dns_rdata_reset(&rdata);
1400 dns_rdataset_current(event->sigrdataset, &rdata);
1401 if (val->siginfo == NULL) {
1402 val->siginfo = isc_mem_get(val->view->mctx,
1403 sizeof(*val->siginfo));
1404 if (val->siginfo == NULL)
1405 return (ISC_R_NOMEMORY);
1407 result = dns_rdata_tostruct(&rdata, val->siginfo, NULL);
1408 if (result != ISC_R_SUCCESS)
1409 return (result);
1412 * At this point we could check that the signature algorithm
1413 * was known and "sufficiently good".
1415 if (!dns_resolver_algorithm_supported(val->view->resolver,
1416 event->name,
1417 val->siginfo->algorithm))
1418 continue;
1420 if (!resume) {
1421 result = get_key(val, val->siginfo);
1422 if (result == DNS_R_CONTINUE)
1423 continue; /* Try the next SIG RR. */
1424 if (result != ISC_R_SUCCESS)
1425 return (result);
1429 * The key is insecure, so mark the data as insecure also.
1431 if (val->key == NULL) {
1432 if (val->mustbesecure) {
1433 validator_log(val, ISC_LOG_WARNING,
1434 "must be secure failure");
1435 return (DNS_R_MUSTBESECURE);
1437 markanswer(val);
1438 return (ISC_R_SUCCESS);
1441 do {
1442 result = verify(val, val->key, &rdata,
1443 val->siginfo->keyid);
1444 if (result == ISC_R_SUCCESS)
1445 break;
1446 if (val->keynode != NULL) {
1447 dns_keynode_t *nextnode = NULL;
1448 result = dns_keytable_findnextkeynode(
1449 val->keytable,
1450 val->keynode,
1451 &nextnode);
1452 dns_keytable_detachkeynode(val->keytable,
1453 &val->keynode);
1454 val->keynode = nextnode;
1455 if (result != ISC_R_SUCCESS) {
1456 val->key = NULL;
1457 break;
1459 val->key = dns_keynode_key(val->keynode);
1460 } else {
1461 if (get_dst_key(val, val->siginfo, val->keyset)
1462 != ISC_R_SUCCESS)
1463 break;
1465 } while (1);
1466 if (result != ISC_R_SUCCESS)
1467 validator_log(val, ISC_LOG_DEBUG(3),
1468 "failed to verify rdataset");
1469 else {
1470 isc_uint32_t ttl;
1471 isc_stdtime_t now;
1473 isc_stdtime_get(&now);
1474 ttl = ISC_MIN(event->rdataset->ttl,
1475 val->siginfo->timeexpire - now);
1476 if (val->keyset != NULL)
1477 ttl = ISC_MIN(ttl, val->keyset->ttl);
1478 event->rdataset->ttl = ttl;
1479 event->sigrdataset->ttl = ttl;
1482 if (val->keynode != NULL)
1483 dns_keytable_detachkeynode(val->keytable,
1484 &val->keynode);
1485 else {
1486 if (val->key != NULL)
1487 dst_key_free(&val->key);
1488 if (val->keyset != NULL) {
1489 dns_rdataset_disassociate(val->keyset);
1490 val->keyset = NULL;
1493 val->key = NULL;
1494 if ((val->attributes & VALATTR_NEEDNOQNAME) != 0) {
1495 if (val->event->message == NULL) {
1496 validator_log(val, ISC_LOG_DEBUG(3),
1497 "no message available for noqname proof");
1498 return (DNS_R_NOVALIDSIG);
1500 validator_log(val, ISC_LOG_DEBUG(3),
1501 "looking for noqname proof");
1502 return (nsecvalidate(val, ISC_FALSE));
1503 } else if (result == ISC_R_SUCCESS) {
1504 event->rdataset->trust = dns_trust_secure;
1505 event->sigrdataset->trust = dns_trust_secure;
1506 validator_log(val, ISC_LOG_DEBUG(3),
1507 "marking as secure");
1508 return (result);
1509 } else {
1510 validator_log(val, ISC_LOG_DEBUG(3),
1511 "verify failure: %s",
1512 isc_result_totext(result));
1513 resume = ISC_FALSE;
1516 if (result != ISC_R_NOMORE) {
1517 validator_log(val, ISC_LOG_DEBUG(3),
1518 "failed to iterate signatures: %s",
1519 isc_result_totext(result));
1520 return (result);
1523 validator_log(val, ISC_LOG_INFO, "no valid signature found");
1524 return (DNS_R_NOVALIDSIG);
1528 * Validate the DNSKEY RRset by looking for a DNSKEY that matches a
1529 * DLV record and that also verifies the DNSKEY RRset.
1531 static isc_result_t
1532 dlv_validatezonekey(dns_validator_t *val) {
1533 dns_keytag_t keytag;
1534 dns_rdata_dlv_t dlv;
1535 dns_rdata_dnskey_t key;
1536 dns_rdata_rrsig_t sig;
1537 dns_rdata_t dlvrdata = DNS_RDATA_INIT;
1538 dns_rdata_t keyrdata = DNS_RDATA_INIT;
1539 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
1540 dns_rdata_t sigrdata = DNS_RDATA_INIT;
1541 dns_rdataset_t trdataset;
1542 dst_key_t *dstkey;
1543 isc_boolean_t supported_algorithm;
1544 isc_result_t result;
1545 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
1546 isc_uint8_t digest_type;
1548 validator_log(val, ISC_LOG_DEBUG(3), "dlv_validatezonekey");
1551 * Look through the DLV record and find the keys that can sign the
1552 * key set and the matching signature. For each such key, attempt
1553 * verification.
1555 supported_algorithm = ISC_FALSE;
1558 * If DNS_DSDIGEST_SHA256 is present we are required to prefer
1559 * it over DNS_DSDIGEST_SHA1. This in practice means that we
1560 * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
1561 * is present.
1563 digest_type = DNS_DSDIGEST_SHA1;
1564 for (result = dns_rdataset_first(&val->dlv);
1565 result == ISC_R_SUCCESS;
1566 result = dns_rdataset_next(&val->dlv)) {
1567 dns_rdata_reset(&dlvrdata);
1568 dns_rdataset_current(&val->dlv, &dlvrdata);
1569 result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
1570 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1572 if (!dns_resolver_algorithm_supported(val->view->resolver,
1573 val->event->name,
1574 dlv.algorithm))
1575 continue;
1577 if (dlv.digest_type == DNS_DSDIGEST_SHA256 &&
1578 dlv.length == ISC_SHA256_DIGESTLENGTH) {
1579 digest_type = DNS_DSDIGEST_SHA256;
1580 break;
1584 for (result = dns_rdataset_first(&val->dlv);
1585 result == ISC_R_SUCCESS;
1586 result = dns_rdataset_next(&val->dlv))
1588 dns_rdata_reset(&dlvrdata);
1589 dns_rdataset_current(&val->dlv, &dlvrdata);
1590 result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
1591 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1593 if (!dns_resolver_digest_supported(val->view->resolver,
1594 dlv.digest_type))
1595 continue;
1597 if (dlv.digest_type != digest_type)
1598 continue;
1600 if (!dns_resolver_algorithm_supported(val->view->resolver,
1601 val->event->name,
1602 dlv.algorithm))
1603 continue;
1605 supported_algorithm = ISC_TRUE;
1607 dns_rdataset_init(&trdataset);
1608 dns_rdataset_clone(val->event->rdataset, &trdataset);
1610 for (result = dns_rdataset_first(&trdataset);
1611 result == ISC_R_SUCCESS;
1612 result = dns_rdataset_next(&trdataset))
1614 dns_rdata_reset(&keyrdata);
1615 dns_rdataset_current(&trdataset, &keyrdata);
1616 result = dns_rdata_tostruct(&keyrdata, &key, NULL);
1617 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1618 keytag = compute_keytag(&keyrdata, &key);
1619 if (dlv.key_tag != keytag ||
1620 dlv.algorithm != key.algorithm)
1621 continue;
1622 dns_rdata_reset(&newdsrdata);
1623 result = dns_ds_buildrdata(val->event->name,
1624 &keyrdata, dlv.digest_type,
1625 dsbuf, &newdsrdata);
1626 if (result != ISC_R_SUCCESS) {
1627 validator_log(val, ISC_LOG_DEBUG(3),
1628 "dns_ds_buildrdata() -> %s",
1629 dns_result_totext(result));
1630 continue;
1632 /* Covert to DLV */
1633 newdsrdata.type = dns_rdatatype_dlv;
1634 if (dns_rdata_compare(&dlvrdata, &newdsrdata) == 0)
1635 break;
1637 if (result != ISC_R_SUCCESS) {
1638 dns_rdataset_disassociate(&trdataset);
1639 validator_log(val, ISC_LOG_DEBUG(3),
1640 "no DNSKEY matching DLV");
1641 continue;
1643 validator_log(val, ISC_LOG_DEBUG(3),
1644 "Found matching DLV record: checking for signature");
1646 for (result = dns_rdataset_first(val->event->sigrdataset);
1647 result == ISC_R_SUCCESS;
1648 result = dns_rdataset_next(val->event->sigrdataset))
1650 dns_rdata_reset(&sigrdata);
1651 dns_rdataset_current(val->event->sigrdataset,
1652 &sigrdata);
1653 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
1654 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1655 if (dlv.key_tag != sig.keyid &&
1656 dlv.algorithm != sig.algorithm)
1657 continue;
1658 dstkey = NULL;
1659 result = dns_dnssec_keyfromrdata(val->event->name,
1660 &keyrdata,
1661 val->view->mctx,
1662 &dstkey);
1663 if (result != ISC_R_SUCCESS)
1665 * This really shouldn't happen, but...
1667 continue;
1669 result = verify(val, dstkey, &sigrdata, sig.keyid);
1670 dst_key_free(&dstkey);
1671 if (result == ISC_R_SUCCESS)
1672 break;
1674 dns_rdataset_disassociate(&trdataset);
1675 if (result == ISC_R_SUCCESS)
1676 break;
1677 validator_log(val, ISC_LOG_DEBUG(3),
1678 "no RRSIG matching DLV key");
1680 if (result == ISC_R_SUCCESS) {
1681 val->event->rdataset->trust = dns_trust_secure;
1682 val->event->sigrdataset->trust = dns_trust_secure;
1683 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure");
1684 return (result);
1685 } else if (result == ISC_R_NOMORE && !supported_algorithm) {
1686 if (val->mustbesecure) {
1687 validator_log(val, ISC_LOG_WARNING,
1688 "must be secure failure");
1689 return (DNS_R_MUSTBESECURE);
1691 validator_log(val, ISC_LOG_DEBUG(3),
1692 "no supported algorithm/digest (dlv)");
1693 markanswer(val);
1694 return (ISC_R_SUCCESS);
1695 } else
1696 return (DNS_R_NOVALIDSIG);
1700 * Attempts positive response validation of an RRset containing zone keys.
1702 * Returns:
1703 * \li ISC_R_SUCCESS Validation completed successfully
1704 * \li DNS_R_WAIT Validation has started but is waiting
1705 * for an event.
1706 * \li Other return codes are possible and all indicate failure.
1708 static isc_result_t
1709 validatezonekey(dns_validator_t *val) {
1710 isc_result_t result;
1711 dns_validatorevent_t *event;
1712 dns_rdataset_t trdataset;
1713 dns_rdata_t dsrdata = DNS_RDATA_INIT;
1714 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
1715 dns_rdata_t keyrdata = DNS_RDATA_INIT;
1716 dns_rdata_t sigrdata = DNS_RDATA_INIT;
1717 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
1718 char namebuf[DNS_NAME_FORMATSIZE];
1719 dns_keytag_t keytag;
1720 dns_rdata_ds_t ds;
1721 dns_rdata_dnskey_t key;
1722 dns_rdata_rrsig_t sig;
1723 dst_key_t *dstkey;
1724 isc_boolean_t supported_algorithm;
1725 isc_boolean_t atsep = ISC_FALSE;
1726 isc_uint8_t digest_type;
1729 * Caller must be holding the validator lock.
1732 event = val->event;
1734 if (val->havedlvsep && val->dlv.trust >= dns_trust_secure &&
1735 dns_name_equal(event->name, dns_fixedname_name(&val->dlvsep)))
1736 return (dlv_validatezonekey(val));
1738 if (val->dsset == NULL) {
1740 * First, see if this key was signed by a trusted key.
1742 for (result = dns_rdataset_first(val->event->sigrdataset);
1743 result == ISC_R_SUCCESS;
1744 result = dns_rdataset_next(val->event->sigrdataset))
1746 dns_keynode_t *keynode = NULL, *nextnode = NULL;
1748 dns_rdata_reset(&sigrdata);
1749 dns_rdataset_current(val->event->sigrdataset,
1750 &sigrdata);
1751 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
1752 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1754 if (!dns_name_equal(val->event->name, &sig.signer))
1755 continue;
1757 result = dns_keytable_findkeynode(val->keytable,
1758 val->event->name,
1759 sig.algorithm,
1760 sig.keyid,
1761 &keynode);
1762 if (result == DNS_R_PARTIALMATCH ||
1763 result == ISC_R_SUCCESS)
1764 atsep = ISC_TRUE;
1765 while (result == ISC_R_SUCCESS) {
1766 dstkey = dns_keynode_key(keynode);
1767 result = verify(val, dstkey, &sigrdata,
1768 sig.keyid);
1769 if (result == ISC_R_SUCCESS) {
1770 dns_keytable_detachkeynode(val->keytable,
1771 &keynode);
1772 break;
1774 result = dns_keytable_findnextkeynode(
1775 val->keytable,
1776 keynode,
1777 &nextnode);
1778 dns_keytable_detachkeynode(val->keytable,
1779 &keynode);
1780 keynode = nextnode;
1782 if (result == ISC_R_SUCCESS) {
1783 event->rdataset->trust = dns_trust_secure;
1784 event->sigrdataset->trust = dns_trust_secure;
1785 validator_log(val, ISC_LOG_DEBUG(3),
1786 "signed by trusted key; "
1787 "marking as secure");
1788 return (result);
1793 * If this is the root name and there was no trusted key,
1794 * give up, since there's no DS at the root.
1796 if (dns_name_equal(event->name, dns_rootname)) {
1797 if ((val->attributes & VALATTR_TRIEDVERIFY) != 0)
1798 return (DNS_R_NOVALIDSIG);
1799 else
1800 return (DNS_R_NOVALIDDS);
1803 if (atsep) {
1805 * We have not found a key to verify this DNSKEY
1806 * RRset. As this is a SEP we have to assume that
1807 * the RRset is invalid.
1809 dns_name_format(val->event->name, namebuf,
1810 sizeof(namebuf));
1811 validator_log(val, ISC_LOG_DEBUG(2),
1812 "unable to find a DNSKEY which verifies "
1813 "the DNSKEY RRset and also matches one "
1814 "of specified trusted-keys for '%s'",
1815 namebuf);
1816 return (DNS_R_NOVALIDKEY);
1820 * Otherwise, try to find the DS record.
1822 result = view_find(val, val->event->name, dns_rdatatype_ds);
1823 if (result == ISC_R_SUCCESS) {
1825 * We have DS records.
1827 val->dsset = &val->frdataset;
1828 if (DNS_TRUST_PENDING(val->frdataset.trust) &&
1829 dns_rdataset_isassociated(&val->fsigrdataset))
1831 result = create_validator(val,
1832 val->event->name,
1833 dns_rdatatype_ds,
1834 &val->frdataset,
1835 &val->fsigrdataset,
1836 dsvalidated,
1837 "validatezonekey");
1838 if (result != ISC_R_SUCCESS)
1839 return (result);
1840 return (DNS_R_WAIT);
1841 } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
1843 * There should never be an unsigned DS.
1845 dns_rdataset_disassociate(&val->frdataset);
1846 validator_log(val, ISC_LOG_DEBUG(2),
1847 "unsigned DS record");
1848 return (DNS_R_NOVALIDSIG);
1849 } else
1850 result = ISC_R_SUCCESS;
1851 } else if (result == ISC_R_NOTFOUND) {
1853 * We don't have the DS. Find it.
1855 result = create_fetch(val, val->event->name,
1856 dns_rdatatype_ds, dsfetched,
1857 "validatezonekey");
1858 if (result != ISC_R_SUCCESS)
1859 return (result);
1860 return (DNS_R_WAIT);
1861 } else if (result == DNS_R_NCACHENXDOMAIN ||
1862 result == DNS_R_NCACHENXRRSET ||
1863 result == DNS_R_EMPTYNAME ||
1864 result == DNS_R_NXDOMAIN ||
1865 result == DNS_R_NXRRSET)
1868 * The DS does not exist.
1870 if (dns_rdataset_isassociated(&val->frdataset))
1871 dns_rdataset_disassociate(&val->frdataset);
1872 if (dns_rdataset_isassociated(&val->fsigrdataset))
1873 dns_rdataset_disassociate(&val->fsigrdataset);
1874 validator_log(val, ISC_LOG_DEBUG(2), "no DS record");
1875 return (DNS_R_NOVALIDSIG);
1880 * We have a DS set.
1882 INSIST(val->dsset != NULL);
1884 if (val->dsset->trust < dns_trust_secure) {
1885 if (val->mustbesecure) {
1886 validator_log(val, ISC_LOG_WARNING,
1887 "must be secure failure");
1888 return (DNS_R_MUSTBESECURE);
1890 markanswer(val);
1891 return (ISC_R_SUCCESS);
1895 * Look through the DS record and find the keys that can sign the
1896 * key set and the matching signature. For each such key, attempt
1897 * verification.
1900 supported_algorithm = ISC_FALSE;
1903 * If DNS_DSDIGEST_SHA256 is present we are required to prefer
1904 * it over DNS_DSDIGEST_SHA1. This in practice means that we
1905 * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
1906 * is present.
1908 digest_type = DNS_DSDIGEST_SHA1;
1909 for (result = dns_rdataset_first(val->dsset);
1910 result == ISC_R_SUCCESS;
1911 result = dns_rdataset_next(val->dsset)) {
1912 dns_rdata_reset(&dsrdata);
1913 dns_rdataset_current(val->dsset, &dsrdata);
1914 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
1915 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1917 if (!dns_resolver_algorithm_supported(val->view->resolver,
1918 val->event->name,
1919 ds.algorithm))
1920 continue;
1922 if (ds.digest_type == DNS_DSDIGEST_SHA256 &&
1923 ds.length == ISC_SHA256_DIGESTLENGTH) {
1924 digest_type = DNS_DSDIGEST_SHA256;
1925 break;
1929 for (result = dns_rdataset_first(val->dsset);
1930 result == ISC_R_SUCCESS;
1931 result = dns_rdataset_next(val->dsset))
1933 dns_rdata_reset(&dsrdata);
1934 dns_rdataset_current(val->dsset, &dsrdata);
1935 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
1936 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1938 if (!dns_resolver_digest_supported(val->view->resolver,
1939 ds.digest_type))
1940 continue;
1942 if (ds.digest_type != digest_type)
1943 continue;
1945 if (!dns_resolver_algorithm_supported(val->view->resolver,
1946 val->event->name,
1947 ds.algorithm))
1948 continue;
1950 supported_algorithm = ISC_TRUE;
1952 dns_rdataset_init(&trdataset);
1953 dns_rdataset_clone(val->event->rdataset, &trdataset);
1956 * Look for the KEY that matches the DS record.
1958 for (result = dns_rdataset_first(&trdataset);
1959 result == ISC_R_SUCCESS;
1960 result = dns_rdataset_next(&trdataset))
1962 dns_rdata_reset(&keyrdata);
1963 dns_rdataset_current(&trdataset, &keyrdata);
1964 result = dns_rdata_tostruct(&keyrdata, &key, NULL);
1965 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1966 keytag = compute_keytag(&keyrdata, &key);
1967 if (ds.key_tag != keytag ||
1968 ds.algorithm != key.algorithm)
1969 continue;
1970 dns_rdata_reset(&newdsrdata);
1971 result = dns_ds_buildrdata(val->event->name,
1972 &keyrdata, ds.digest_type,
1973 dsbuf, &newdsrdata);
1974 if (result != ISC_R_SUCCESS)
1975 continue;
1976 if (dns_rdata_compare(&dsrdata, &newdsrdata) == 0)
1977 break;
1979 if (result != ISC_R_SUCCESS) {
1980 dns_rdataset_disassociate(&trdataset);
1981 validator_log(val, ISC_LOG_DEBUG(3),
1982 "no DNSKEY matching DS");
1983 continue;
1986 for (result = dns_rdataset_first(val->event->sigrdataset);
1987 result == ISC_R_SUCCESS;
1988 result = dns_rdataset_next(val->event->sigrdataset))
1990 dns_rdata_reset(&sigrdata);
1991 dns_rdataset_current(val->event->sigrdataset,
1992 &sigrdata);
1993 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
1994 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1995 if (ds.key_tag != sig.keyid ||
1996 ds.algorithm != sig.algorithm)
1997 continue;
1998 if (!dns_name_equal(val->event->name, &sig.signer)) {
1999 validator_log(val, ISC_LOG_DEBUG(3),
2000 "DNSKEY signer mismatch");
2001 continue;
2003 dstkey = NULL;
2004 result = dns_dnssec_keyfromrdata(val->event->name,
2005 &keyrdata,
2006 val->view->mctx,
2007 &dstkey);
2008 if (result != ISC_R_SUCCESS)
2010 * This really shouldn't happen, but...
2012 continue;
2013 result = verify(val, dstkey, &sigrdata, sig.keyid);
2014 dst_key_free(&dstkey);
2015 if (result == ISC_R_SUCCESS)
2016 break;
2018 dns_rdataset_disassociate(&trdataset);
2019 if (result == ISC_R_SUCCESS)
2020 break;
2021 validator_log(val, ISC_LOG_DEBUG(3),
2022 "no RRSIG matching DS key");
2024 if (result == ISC_R_SUCCESS) {
2025 event->rdataset->trust = dns_trust_secure;
2026 event->sigrdataset->trust = dns_trust_secure;
2027 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure");
2028 return (result);
2029 } else if (result == ISC_R_NOMORE && !supported_algorithm) {
2030 if (val->mustbesecure) {
2031 validator_log(val, ISC_LOG_WARNING,
2032 "must be secure failure");
2033 return (DNS_R_MUSTBESECURE);
2035 validator_log(val, ISC_LOG_DEBUG(3),
2036 "no supported algorithm/digest (DS)");
2037 markanswer(val);
2038 return (ISC_R_SUCCESS);
2039 } else
2040 return (DNS_R_NOVALIDSIG);
2044 * Starts a positive response validation.
2046 * Returns:
2047 * \li ISC_R_SUCCESS Validation completed successfully
2048 * \li DNS_R_WAIT Validation has started but is waiting
2049 * for an event.
2050 * \li Other return codes are possible and all indicate failure.
2052 static isc_result_t
2053 start_positive_validation(dns_validator_t *val) {
2055 * If this is not a key, go straight into validate().
2057 if (val->event->type != dns_rdatatype_dnskey || !isselfsigned(val))
2058 return (validate(val, ISC_FALSE));
2060 return (validatezonekey(val));
2064 * Look for NODATA at the wildcard and NOWILDCARD proofs in the
2065 * previously validated NSEC records. As these proofs are mutually
2066 * exclusive we stop when one is found.
2068 * Returns
2069 * \li ISC_R_SUCCESS
2071 static isc_result_t
2072 checkwildcard(dns_validator_t *val) {
2073 dns_name_t *name, *wild;
2074 dns_message_t *message = val->event->message;
2075 isc_result_t result;
2076 isc_boolean_t exists, data;
2077 char namebuf[DNS_NAME_FORMATSIZE];
2079 wild = dns_fixedname_name(&val->wild);
2080 dns_name_format(wild, namebuf, sizeof(namebuf));
2081 validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf);
2083 for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2084 result == ISC_R_SUCCESS;
2085 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
2087 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2089 name = NULL;
2090 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
2092 for (rdataset = ISC_LIST_HEAD(name->list);
2093 rdataset != NULL;
2094 rdataset = ISC_LIST_NEXT(rdataset, link))
2096 if (rdataset->type != dns_rdatatype_nsec)
2097 continue;
2098 val->nsecset = rdataset;
2100 for (sigrdataset = ISC_LIST_HEAD(name->list);
2101 sigrdataset != NULL;
2102 sigrdataset = ISC_LIST_NEXT(sigrdataset, link))
2104 if (sigrdataset->type == dns_rdatatype_rrsig &&
2105 sigrdataset->covers == rdataset->type)
2106 break;
2108 if (sigrdataset == NULL)
2109 continue;
2111 if (rdataset->trust != dns_trust_secure)
2112 continue;
2114 if (((val->attributes & VALATTR_NEEDNODATA) != 0 ||
2115 (val->attributes & VALATTR_NEEDNOWILDCARD) != 0) &&
2116 (val->attributes & VALATTR_FOUNDNODATA) == 0 &&
2117 (val->attributes & VALATTR_FOUNDNOWILDCARD) == 0 &&
2118 nsecnoexistnodata(val, wild, name, rdataset,
2119 &exists, &data, NULL)
2120 == ISC_R_SUCCESS)
2122 dns_name_t **proofs = val->event->proofs;
2123 if (exists && !data)
2124 val->attributes |= VALATTR_FOUNDNODATA;
2125 if (exists && !data && NEEDNODATA(val))
2126 proofs[DNS_VALIDATOR_NODATAPROOF] =
2127 name;
2128 if (!exists)
2129 val->attributes |=
2130 VALATTR_FOUNDNOWILDCARD;
2131 if (!exists && NEEDNOQNAME(val))
2132 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
2133 name;
2134 return (ISC_R_SUCCESS);
2138 if (result == ISC_R_NOMORE)
2139 result = ISC_R_SUCCESS;
2140 return (result);
2144 * Prove a negative answer is good or that there is a NOQNAME when the
2145 * answer is from a wildcard.
2147 * Loop through the authority section looking for NODATA, NOWILDCARD
2148 * and NOQNAME proofs in the NSEC records by calling authvalidated().
2150 * If the required proofs are found we are done.
2152 * If the proofs are not found attempt to prove this is a unsecure
2153 * response.
2155 static isc_result_t
2156 nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
2157 dns_name_t *name;
2158 dns_message_t *message = val->event->message;
2159 isc_result_t result;
2161 if (!resume)
2162 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2163 else {
2164 result = ISC_R_SUCCESS;
2165 validator_log(val, ISC_LOG_DEBUG(3), "resuming nsecvalidate");
2168 for (;
2169 result == ISC_R_SUCCESS;
2170 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
2172 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2174 name = NULL;
2175 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
2176 if (resume) {
2177 rdataset = ISC_LIST_NEXT(val->currentset, link);
2178 val->currentset = NULL;
2179 resume = ISC_FALSE;
2180 } else
2181 rdataset = ISC_LIST_HEAD(name->list);
2183 for (;
2184 rdataset != NULL;
2185 rdataset = ISC_LIST_NEXT(rdataset, link))
2187 if (rdataset->type == dns_rdatatype_rrsig)
2188 continue;
2190 for (sigrdataset = ISC_LIST_HEAD(name->list);
2191 sigrdataset != NULL;
2192 sigrdataset = ISC_LIST_NEXT(sigrdataset,
2193 link))
2195 if (sigrdataset->type == dns_rdatatype_rrsig &&
2196 sigrdataset->covers == rdataset->type)
2197 break;
2200 * If a signed zone is missing the zone key, bad
2201 * things could happen. A query for data in the zone
2202 * would lead to a query for the zone key, which
2203 * would return a negative answer, which would contain
2204 * an SOA and an NSEC signed by the missing key, which
2205 * would trigger another query for the DNSKEY (since
2206 * the first one is still in progress), and go into an
2207 * infinite loop. Avoid that.
2209 if (val->event->type == dns_rdatatype_dnskey &&
2210 dns_name_equal(name, val->event->name))
2212 dns_rdata_t nsec = DNS_RDATA_INIT;
2214 if (rdataset->type != dns_rdatatype_nsec)
2215 continue;
2217 result = dns_rdataset_first(rdataset);
2218 if (result != ISC_R_SUCCESS)
2219 return (result);
2220 dns_rdataset_current(rdataset, &nsec);
2221 if (dns_nsec_typepresent(&nsec,
2222 dns_rdatatype_soa))
2223 continue;
2225 val->currentset = rdataset;
2226 result = create_validator(val, name, rdataset->type,
2227 rdataset, sigrdataset,
2228 authvalidated,
2229 "nsecvalidate");
2230 if (result != ISC_R_SUCCESS)
2231 return (result);
2232 return (DNS_R_WAIT);
2236 if (result == ISC_R_NOMORE)
2237 result = ISC_R_SUCCESS;
2238 if (result != ISC_R_SUCCESS)
2239 return (result);
2242 * Do we only need to check for NOQNAME? To get here we must have
2243 * had a secure wildcard answer.
2245 if ((val->attributes & VALATTR_NEEDNODATA) == 0 &&
2246 (val->attributes & VALATTR_NEEDNOWILDCARD) == 0 &&
2247 (val->attributes & VALATTR_NEEDNOQNAME) != 0) {
2248 if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0) {
2249 validator_log(val, ISC_LOG_DEBUG(3),
2250 "noqname proof found");
2251 validator_log(val, ISC_LOG_DEBUG(3),
2252 "marking as secure");
2253 val->event->rdataset->trust = dns_trust_secure;
2254 val->event->sigrdataset->trust = dns_trust_secure;
2255 return (ISC_R_SUCCESS);
2257 validator_log(val, ISC_LOG_DEBUG(3),
2258 "noqname proof not found");
2259 return (DNS_R_NOVALIDNSEC);
2263 * Do we need to check for the wildcard?
2265 if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
2266 (((val->attributes & VALATTR_NEEDNODATA) != 0 &&
2267 (val->attributes & VALATTR_FOUNDNODATA) == 0) ||
2268 (val->attributes & VALATTR_NEEDNOWILDCARD) != 0)) {
2269 result = checkwildcard(val);
2270 if (result != ISC_R_SUCCESS)
2271 return (result);
2274 if (((val->attributes & VALATTR_NEEDNODATA) != 0 &&
2275 (val->attributes & VALATTR_FOUNDNODATA) != 0) ||
2276 ((val->attributes & VALATTR_NEEDNOQNAME) != 0 &&
2277 (val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
2278 (val->attributes & VALATTR_NEEDNOWILDCARD) != 0 &&
2279 (val->attributes & VALATTR_FOUNDNOWILDCARD) != 0)) {
2280 validator_log(val, ISC_LOG_DEBUG(3),
2281 "nonexistence proof(s) found");
2282 return (ISC_R_SUCCESS);
2285 validator_log(val, ISC_LOG_DEBUG(3),
2286 "nonexistence proof(s) not found");
2287 val->attributes |= VALATTR_INSECURITY;
2288 return (proveunsecure(val, ISC_FALSE, ISC_FALSE));
2291 static isc_boolean_t
2292 check_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) {
2293 dns_rdata_t dsrdata = DNS_RDATA_INIT;
2294 dns_rdata_ds_t ds;
2295 isc_result_t result;
2297 for (result = dns_rdataset_first(rdataset);
2298 result == ISC_R_SUCCESS;
2299 result = dns_rdataset_next(rdataset)) {
2300 dns_rdataset_current(rdataset, &dsrdata);
2301 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
2302 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2304 if (dns_resolver_digest_supported(val->view->resolver,
2305 ds.digest_type) &&
2306 dns_resolver_algorithm_supported(val->view->resolver,
2307 name, ds.algorithm)) {
2308 dns_rdata_reset(&dsrdata);
2309 return (ISC_TRUE);
2311 dns_rdata_reset(&dsrdata);
2313 return (ISC_FALSE);
2317 * Callback from fetching a DLV record.
2319 * Resumes the DLV lookup process.
2321 static void
2322 dlvfetched(isc_task_t *task, isc_event_t *event) {
2323 char namebuf[DNS_NAME_FORMATSIZE];
2324 dns_fetchevent_t *devent;
2325 dns_validator_t *val;
2326 isc_boolean_t want_destroy;
2327 isc_result_t eresult;
2328 isc_result_t result;
2330 UNUSED(task);
2331 INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
2332 devent = (dns_fetchevent_t *)event;
2333 val = devent->ev_arg;
2334 eresult = devent->result;
2336 /* Free resources which are not of interest. */
2337 if (devent->node != NULL)
2338 dns_db_detachnode(devent->db, &devent->node);
2339 if (devent->db != NULL)
2340 dns_db_detach(&devent->db);
2341 if (dns_rdataset_isassociated(&val->fsigrdataset))
2342 dns_rdataset_disassociate(&val->fsigrdataset);
2343 isc_event_free(&event);
2344 dns_resolver_destroyfetch(&val->fetch);
2346 INSIST(val->event != NULL);
2347 validator_log(val, ISC_LOG_DEBUG(3), "in dlvfetched: %s",
2348 dns_result_totext(eresult));
2350 LOCK(&val->lock);
2351 if (eresult == ISC_R_SUCCESS) {
2352 dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
2353 sizeof(namebuf));
2354 dns_rdataset_clone(&val->frdataset, &val->dlv);
2355 val->havedlvsep = ISC_TRUE;
2356 if (dlv_algorithm_supported(val)) {
2357 validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found",
2358 namebuf);
2359 dlv_validator_start(val);
2360 } else {
2361 validator_log(val, ISC_LOG_DEBUG(3),
2362 "DLV %s found with no supported algorithms",
2363 namebuf);
2364 markanswer(val);
2365 validator_done(val, ISC_R_SUCCESS);
2367 } else if (eresult == DNS_R_NXRRSET ||
2368 eresult == DNS_R_NXDOMAIN ||
2369 eresult == DNS_R_NCACHENXRRSET ||
2370 eresult == DNS_R_NCACHENXDOMAIN) {
2371 result = finddlvsep(val, ISC_TRUE);
2372 if (result == ISC_R_SUCCESS) {
2373 if (dlv_algorithm_supported(val)) {
2374 dns_name_format(dns_fixedname_name(&val->dlvsep),
2375 namebuf, sizeof(namebuf));
2376 validator_log(val, ISC_LOG_DEBUG(3),
2377 "DLV %s found", namebuf);
2378 dlv_validator_start(val);
2379 } else {
2380 validator_log(val, ISC_LOG_DEBUG(3),
2381 "DLV %s found with no supported "
2382 "algorithms", namebuf);
2383 markanswer(val);
2384 validator_done(val, ISC_R_SUCCESS);
2386 } else if (result == ISC_R_NOTFOUND) {
2387 validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
2388 markanswer(val);
2389 validator_done(val, ISC_R_SUCCESS);
2390 } else {
2391 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
2392 dns_result_totext(result));
2393 if (result != DNS_R_WAIT)
2394 validator_done(val, result);
2396 } else {
2397 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
2398 dns_result_totext(eresult));
2399 validator_done(val, eresult);
2401 want_destroy = exit_check(val);
2402 UNLOCK(&val->lock);
2403 if (want_destroy)
2404 destroy(val);
2408 * Start the DLV lookup process.
2410 * Returns
2411 * \li ISC_R_SUCCESS
2412 * \li DNS_R_WAIT
2413 * \li Others on validation failures.
2415 static isc_result_t
2416 startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) {
2417 char namebuf[DNS_NAME_FORMATSIZE];
2418 isc_result_t result;
2420 INSIST(!DLVTRIED(val));
2422 val->attributes |= VALATTR_DLVTRIED;
2424 dns_name_format(unsecure, namebuf, sizeof(namebuf));
2425 validator_log(val, ISC_LOG_DEBUG(3),
2426 "plain DNSSEC returns unsecure (%s): looking for DLV",
2427 namebuf);
2429 if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
2430 validator_log(val, ISC_LOG_WARNING, "must be secure failure");
2431 return (DNS_R_MUSTBESECURE);
2434 val->dlvlabels = dns_name_countlabels(unsecure) - 1;
2435 result = finddlvsep(val, ISC_FALSE);
2436 if (result == ISC_R_NOTFOUND) {
2437 validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
2438 markanswer(val);
2439 return (ISC_R_SUCCESS);
2441 if (result != ISC_R_SUCCESS) {
2442 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
2443 dns_result_totext(result));
2444 return (result);
2446 dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
2447 sizeof(namebuf));
2448 if (dlv_algorithm_supported(val)) {
2449 validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf);
2450 dlv_validator_start(val);
2451 return (DNS_R_WAIT);
2453 validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found with no supported "
2454 "algorithms", namebuf);
2455 markanswer(val);
2456 validator_done(val, ISC_R_SUCCESS);
2457 return (ISC_R_SUCCESS);
2461 * Continue the DLV lookup process.
2463 * Returns
2464 * \li ISC_R_SUCCESS
2465 * \li ISC_R_NOTFOUND
2466 * \li DNS_R_WAIT
2467 * \li Others on validation failure.
2469 static isc_result_t
2470 finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
2471 char namebuf[DNS_NAME_FORMATSIZE];
2472 dns_fixedname_t dlvfixed;
2473 dns_name_t *dlvname;
2474 dns_name_t *dlvsep;
2475 dns_name_t noroot;
2476 isc_result_t result;
2477 unsigned int labels;
2479 INSIST(val->view->dlv != NULL);
2481 if (!resume) {
2483 if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
2484 validator_log(val, ISC_LOG_WARNING,
2485 "must be secure failure");
2486 return (DNS_R_MUSTBESECURE);
2489 dns_fixedname_init(&val->dlvsep);
2490 dlvsep = dns_fixedname_name(&val->dlvsep);
2491 dns_name_copy(val->event->name, dlvsep, NULL);
2493 * If this is a response to a DS query, we need to look in
2494 * the parent zone for the trust anchor.
2496 if (val->event->type == dns_rdatatype_ds) {
2497 labels = dns_name_countlabels(dlvsep);
2498 if (labels == 0)
2499 return (ISC_R_NOTFOUND);
2500 dns_name_getlabelsequence(dlvsep, 1, labels - 1,
2501 dlvsep);
2503 } else {
2504 dlvsep = dns_fixedname_name(&val->dlvsep);
2505 labels = dns_name_countlabels(dlvsep);
2506 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
2508 dns_name_init(&noroot, NULL);
2509 dns_fixedname_init(&dlvfixed);
2510 dlvname = dns_fixedname_name(&dlvfixed);
2511 labels = dns_name_countlabels(dlvsep);
2512 if (labels == 0)
2513 return (ISC_R_NOTFOUND);
2514 dns_name_getlabelsequence(dlvsep, 0, labels - 1, &noroot);
2515 result = dns_name_concatenate(&noroot, val->view->dlv, dlvname, NULL);
2516 while (result == ISC_R_NOSPACE) {
2517 labels = dns_name_countlabels(dlvsep);
2518 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
2519 dns_name_getlabelsequence(dlvsep, 0, labels - 2, &noroot);
2520 result = dns_name_concatenate(&noroot, val->view->dlv,
2521 dlvname, NULL);
2523 if (result != ISC_R_SUCCESS) {
2524 validator_log(val, ISC_LOG_DEBUG(2), "DLV concatenate failed");
2525 return (DNS_R_NOVALIDSIG);
2528 while (dns_name_countlabels(dlvname) >=
2529 dns_name_countlabels(val->view->dlv) + val->dlvlabels) {
2530 dns_name_format(dlvname, namebuf, sizeof(namebuf));
2531 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV %s",
2532 namebuf);
2533 result = view_find(val, dlvname, dns_rdatatype_dlv);
2534 if (result == ISC_R_SUCCESS) {
2535 if (val->frdataset.trust < dns_trust_secure)
2536 return (DNS_R_NOVALIDSIG);
2537 val->havedlvsep = ISC_TRUE;
2538 dns_rdataset_clone(&val->frdataset, &val->dlv);
2539 return (ISC_R_SUCCESS);
2541 if (result == ISC_R_NOTFOUND) {
2542 result = create_fetch(val, dlvname, dns_rdatatype_dlv,
2543 dlvfetched, "finddlvsep");
2544 if (result != ISC_R_SUCCESS)
2545 return (result);
2546 return (DNS_R_WAIT);
2548 if (result != DNS_R_NXRRSET &&
2549 result != DNS_R_NXDOMAIN &&
2550 result != DNS_R_EMPTYNAME &&
2551 result != DNS_R_NCACHENXRRSET &&
2552 result != DNS_R_NCACHENXDOMAIN)
2553 return (result);
2555 * Strip first labels from both dlvsep and dlvname.
2557 labels = dns_name_countlabels(dlvsep);
2558 if (labels == 0)
2559 break;
2560 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
2561 labels = dns_name_countlabels(dlvname);
2562 dns_name_getlabelsequence(dlvname, 1, labels - 1, dlvname);
2564 return (ISC_R_NOTFOUND);
2568 * proveunsecure walks down from the SEP looking for a break in the
2569 * chain of trust. That occurs when we can prove the DS record does
2570 * not exist at a delegation point or the DS exists at a delegation
2571 * but we don't support the algorithm/digest.
2573 * If DLV is active and we look for a DLV record at or below the
2574 * point we go insecure. If found we restart the validation process.
2575 * If not found or DLV isn't active we mark the response as a answer.
2577 * Returns:
2578 * \li ISC_R_SUCCESS val->event->name is in a unsecure zone
2579 * \li DNS_R_WAIT validation is in progress.
2580 * \li DNS_R_MUSTBESECURE val->event->name is supposed to be secure
2581 * (policy) but we proved that it is unsecure.
2582 * \li DNS_R_NOVALIDSIG
2583 * \li DNS_R_NOVALIDNSEC
2584 * \li DNS_R_NOTINSECURE
2586 static isc_result_t
2587 proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
2589 isc_result_t result;
2590 dns_fixedname_t fixedsecroot;
2591 dns_name_t *secroot;
2592 dns_name_t *tname;
2593 char namebuf[DNS_NAME_FORMATSIZE];
2595 dns_fixedname_init(&fixedsecroot);
2596 secroot = dns_fixedname_name(&fixedsecroot);
2597 if (val->havedlvsep)
2598 dns_name_copy(dns_fixedname_name(&val->dlvsep), secroot, NULL);
2599 else {
2600 unsigned int labels;
2601 dns_name_copy(val->event->name, secroot, NULL);
2603 * If this is a response to a DS query, we need to look in
2604 * the parent zone for the trust anchor.
2607 labels = dns_name_countlabels(secroot);
2608 if (val->event->type == dns_rdatatype_ds && labels > 1U)
2609 dns_name_getlabelsequence(secroot, 1, labels - 1,
2610 secroot);
2611 result = dns_keytable_finddeepestmatch(val->keytable,
2612 secroot, secroot);
2613 if (result == ISC_R_NOTFOUND) {
2614 if (val->mustbesecure) {
2615 validator_log(val, ISC_LOG_WARNING,
2616 "must be secure failure");
2617 result = DNS_R_MUSTBESECURE;
2618 goto out;
2620 if (val->view->dlv == NULL || DLVTRIED(val)) {
2621 markanswer(val);
2622 return (ISC_R_SUCCESS);
2624 return (startfinddlvsep(val, dns_rootname));
2625 } else if (result != ISC_R_SUCCESS)
2626 return (result);
2629 if (!resume) {
2631 * We are looking for breaks below the SEP so add a label.
2633 val->labels = dns_name_countlabels(secroot) + 1;
2634 } else {
2635 validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
2637 * If we have a DS rdataset and it is secure then check if
2638 * the DS rdataset has a supported algorithm combination.
2639 * If not this is a insecure delegation as far as this
2640 * resolver is concerned. Fall back to DLV if available.
2642 if (have_ds && val->frdataset.trust >= dns_trust_secure &&
2643 !check_ds(val, dns_fixedname_name(&val->fname),
2644 &val->frdataset)) {
2645 dns_name_format(dns_fixedname_name(&val->fname),
2646 namebuf, sizeof(namebuf));
2647 if ((val->view->dlv == NULL || DLVTRIED(val)) &&
2648 val->mustbesecure) {
2649 validator_log(val, ISC_LOG_WARNING,
2650 "must be secure failure at '%s'",
2651 namebuf);
2652 result = DNS_R_MUSTBESECURE;
2653 goto out;
2655 validator_log(val, ISC_LOG_DEBUG(3),
2656 "no supported algorithm/digest (%s/DS)",
2657 namebuf);
2658 if (val->view->dlv == NULL || DLVTRIED(val)) {
2659 markanswer(val);
2660 result = ISC_R_SUCCESS;
2661 goto out;
2663 result = startfinddlvsep(val,
2664 dns_fixedname_name(&val->fname));
2665 goto out;
2667 val->labels++;
2670 for (;
2671 val->labels <= dns_name_countlabels(val->event->name);
2672 val->labels++)
2675 dns_fixedname_init(&val->fname);
2676 tname = dns_fixedname_name(&val->fname);
2677 if (val->labels == dns_name_countlabels(val->event->name))
2678 dns_name_copy(val->event->name, tname, NULL);
2679 else
2680 dns_name_split(val->event->name, val->labels,
2681 NULL, tname);
2683 dns_name_format(tname, namebuf, sizeof(namebuf));
2684 validator_log(val, ISC_LOG_DEBUG(3),
2685 "checking existence of DS at '%s'",
2686 namebuf);
2688 result = view_find(val, tname, dns_rdatatype_ds);
2690 if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
2692 * There is no DS. If this is a delegation,
2693 * we maybe done.
2695 if (DNS_TRUST_PENDING(val->frdataset.trust)) {
2696 result = create_fetch(val, tname,
2697 dns_rdatatype_ds,
2698 dsfetched2,
2699 "proveunsecure");
2700 if (result != ISC_R_SUCCESS)
2701 goto out;
2702 return (DNS_R_WAIT);
2704 if (val->frdataset.trust < dns_trust_secure) {
2706 * This shouldn't happen, since the negative
2707 * response should have been validated. Since
2708 * there's no way of validating existing
2709 * negative response blobs, give up.
2711 result = DNS_R_NOVALIDSIG;
2712 goto out;
2714 if (isdelegation(tname, &val->frdataset, result)) {
2715 if (val->mustbesecure) {
2716 validator_log(val, ISC_LOG_WARNING,
2717 "must be secure failure");
2718 return (DNS_R_MUSTBESECURE);
2720 if (val->view->dlv == NULL || DLVTRIED(val)) {
2721 markanswer(val);
2722 return (ISC_R_SUCCESS);
2724 return (startfinddlvsep(val, tname));
2726 continue;
2727 } else if (result == ISC_R_SUCCESS) {
2729 * There is a DS here. Verify that it's secure and
2730 * continue.
2732 if (val->frdataset.trust >= dns_trust_secure) {
2733 if (!check_ds(val, tname, &val->frdataset)) {
2734 validator_log(val, ISC_LOG_DEBUG(3),
2735 "no supported algorithm/"
2736 "digest (%s/DS)", namebuf);
2737 if (val->mustbesecure) {
2738 validator_log(val,
2739 ISC_LOG_WARNING,
2740 "must be secure failure");
2741 result = DNS_R_MUSTBESECURE;
2742 goto out;
2744 if (val->view->dlv == NULL ||
2745 DLVTRIED(val)) {
2746 markanswer(val);
2747 result = ISC_R_SUCCESS;
2748 goto out;
2750 result = startfinddlvsep(val, tname);
2751 goto out;
2753 continue;
2755 else if (!dns_rdataset_isassociated(&val->fsigrdataset))
2757 result = DNS_R_NOVALIDSIG;
2758 goto out;
2760 result = create_validator(val, tname, dns_rdatatype_ds,
2761 &val->frdataset,
2762 &val->fsigrdataset,
2763 dsvalidated,
2764 "proveunsecure");
2765 if (result != ISC_R_SUCCESS)
2766 goto out;
2767 return (DNS_R_WAIT);
2768 } else if (result == DNS_R_NXDOMAIN ||
2769 result == DNS_R_NCACHENXDOMAIN) {
2771 * This is not a zone cut. Assuming things are
2772 * as expected, continue.
2774 if (!dns_rdataset_isassociated(&val->frdataset)) {
2776 * There should be an NSEC here, since we
2777 * are still in a secure zone.
2779 result = DNS_R_NOVALIDNSEC;
2780 goto out;
2781 } else if (val->frdataset.trust < dns_trust_secure) {
2783 * This shouldn't happen, since the negative
2784 * response should have been validated. Since
2785 * there's no way of validating existing
2786 * negative response blobs, give up.
2788 result = DNS_R_NOVALIDSIG;
2789 goto out;
2791 continue;
2792 } else if (result == ISC_R_NOTFOUND) {
2794 * We don't know anything about the DS. Find it.
2796 result = create_fetch(val, tname, dns_rdatatype_ds,
2797 dsfetched2, "proveunsecure");
2798 if (result != ISC_R_SUCCESS)
2799 goto out;
2800 return (DNS_R_WAIT);
2803 validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed");
2804 return (DNS_R_NOTINSECURE); /* Couldn't complete insecurity proof */
2806 out:
2807 if (dns_rdataset_isassociated(&val->frdataset))
2808 dns_rdataset_disassociate(&val->frdataset);
2809 if (dns_rdataset_isassociated(&val->fsigrdataset))
2810 dns_rdataset_disassociate(&val->fsigrdataset);
2811 return (result);
2815 * Reset state and revalidate the answer using DLV.
2817 static void
2818 dlv_validator_start(dns_validator_t *val) {
2819 isc_event_t *event;
2821 validator_log(val, ISC_LOG_DEBUG(3), "dlv_validator_start");
2824 * Reset state and try again.
2826 val->attributes &= VALATTR_DLVTRIED;
2827 val->options &= ~DNS_VALIDATOR_DLV;
2829 event = (isc_event_t *)val->event;
2830 isc_task_send(val->task, &event);
2834 * Start the validation process.
2836 * Attempt to validate the answer based on the category it appears to
2837 * fall in.
2838 * \li 1. secure positive answer.
2839 * \li 2. unsecure positive answer.
2840 * \li 3. a negative answer (secure or unsecure).
2842 * Note a answer that appears to be a secure positive answer may actually
2843 * be a unsecure positive answer.
2845 static void
2846 validator_start(isc_task_t *task, isc_event_t *event) {
2847 dns_validator_t *val;
2848 dns_validatorevent_t *vevent;
2849 isc_boolean_t want_destroy = ISC_FALSE;
2850 isc_result_t result = ISC_R_FAILURE;
2852 UNUSED(task);
2853 REQUIRE(event->ev_type == DNS_EVENT_VALIDATORSTART);
2854 vevent = (dns_validatorevent_t *)event;
2855 val = vevent->validator;
2857 /* If the validator has been canceled, val->event == NULL */
2858 if (val->event == NULL)
2859 return;
2861 if (DLVTRIED(val))
2862 validator_log(val, ISC_LOG_DEBUG(3), "restarting using DLV");
2863 else
2864 validator_log(val, ISC_LOG_DEBUG(3), "starting");
2866 LOCK(&val->lock);
2868 if ((val->options & DNS_VALIDATOR_DLV) != 0 &&
2869 val->event->rdataset != NULL) {
2870 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV");
2871 result = startfinddlvsep(val, dns_rootname);
2872 } else if (val->event->rdataset != NULL &&
2873 val->event->sigrdataset != NULL) {
2874 isc_result_t saved_result;
2877 * This looks like a simple validation. We say "looks like"
2878 * because it might end up requiring an insecurity proof.
2880 validator_log(val, ISC_LOG_DEBUG(3),
2881 "attempting positive response validation");
2883 INSIST(dns_rdataset_isassociated(val->event->rdataset));
2884 INSIST(dns_rdataset_isassociated(val->event->sigrdataset));
2885 result = start_positive_validation(val);
2886 if (result == DNS_R_NOVALIDSIG &&
2887 (val->attributes & VALATTR_TRIEDVERIFY) == 0)
2889 saved_result = result;
2890 validator_log(val, ISC_LOG_DEBUG(3),
2891 "falling back to insecurity proof");
2892 val->attributes |= VALATTR_INSECURITY;
2893 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
2894 if (result == DNS_R_NOTINSECURE)
2895 result = saved_result;
2897 } else if (val->event->rdataset != NULL) {
2899 * This is either an unsecure subdomain or a response from
2900 * a broken server.
2902 INSIST(dns_rdataset_isassociated(val->event->rdataset));
2903 validator_log(val, ISC_LOG_DEBUG(3),
2904 "attempting insecurity proof");
2906 val->attributes |= VALATTR_INSECURITY;
2907 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
2908 } else if (val->event->rdataset == NULL &&
2909 val->event->sigrdataset == NULL)
2912 * This is a nonexistence validation.
2914 validator_log(val, ISC_LOG_DEBUG(3),
2915 "attempting negative response validation");
2917 if (val->event->message->rcode == dns_rcode_nxdomain) {
2918 val->attributes |= VALATTR_NEEDNOQNAME;
2919 val->attributes |= VALATTR_NEEDNOWILDCARD;
2920 } else
2921 val->attributes |= VALATTR_NEEDNODATA;
2922 result = nsecvalidate(val, ISC_FALSE);
2923 } else {
2925 * This shouldn't happen.
2927 INSIST(0);
2930 if (result != DNS_R_WAIT) {
2931 want_destroy = exit_check(val);
2932 validator_done(val, result);
2935 UNLOCK(&val->lock);
2936 if (want_destroy)
2937 destroy(val);
2940 isc_result_t
2941 dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
2942 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
2943 dns_message_t *message, unsigned int options,
2944 isc_task_t *task, isc_taskaction_t action, void *arg,
2945 dns_validator_t **validatorp)
2947 isc_result_t result;
2948 dns_validator_t *val;
2949 isc_task_t *tclone;
2950 dns_validatorevent_t *event;
2952 REQUIRE(name != NULL);
2953 REQUIRE(rdataset != NULL ||
2954 (rdataset == NULL && sigrdataset == NULL && message != NULL));
2955 REQUIRE(validatorp != NULL && *validatorp == NULL);
2957 tclone = NULL;
2958 result = ISC_R_FAILURE;
2960 val = isc_mem_get(view->mctx, sizeof(*val));
2961 if (val == NULL)
2962 return (ISC_R_NOMEMORY);
2963 val->view = NULL;
2964 dns_view_weakattach(view, &val->view);
2965 event = (dns_validatorevent_t *)
2966 isc_event_allocate(view->mctx, task,
2967 DNS_EVENT_VALIDATORSTART,
2968 validator_start, NULL,
2969 sizeof(dns_validatorevent_t));
2970 if (event == NULL) {
2971 result = ISC_R_NOMEMORY;
2972 goto cleanup_val;
2974 isc_task_attach(task, &tclone);
2975 event->validator = val;
2976 event->result = ISC_R_FAILURE;
2977 event->name = name;
2978 event->type = type;
2979 event->rdataset = rdataset;
2980 event->sigrdataset = sigrdataset;
2981 event->message = message;
2982 memset(event->proofs, 0, sizeof(event->proofs));
2983 result = isc_mutex_init(&val->lock);
2984 if (result != ISC_R_SUCCESS)
2985 goto cleanup_event;
2986 val->event = event;
2987 val->options = options;
2988 val->attributes = 0;
2989 val->fetch = NULL;
2990 val->subvalidator = NULL;
2991 val->parent = NULL;
2992 val->keytable = NULL;
2993 dns_keytable_attach(val->view->secroots, &val->keytable);
2994 val->keynode = NULL;
2995 val->key = NULL;
2996 val->siginfo = NULL;
2997 val->task = task;
2998 val->action = action;
2999 val->arg = arg;
3000 val->labels = 0;
3001 val->currentset = NULL;
3002 val->keyset = NULL;
3003 val->dsset = NULL;
3004 dns_rdataset_init(&val->dlv);
3005 val->seensig = ISC_FALSE;
3006 val->havedlvsep = ISC_FALSE;
3007 val->depth = 0;
3008 val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
3009 dns_rdataset_init(&val->frdataset);
3010 dns_rdataset_init(&val->fsigrdataset);
3011 dns_fixedname_init(&val->wild);
3012 ISC_LINK_INIT(val, link);
3013 val->magic = VALIDATOR_MAGIC;
3015 if ((options & DNS_VALIDATOR_DEFER) == 0)
3016 isc_task_send(task, ISC_EVENT_PTR(&event));
3018 *validatorp = val;
3020 return (ISC_R_SUCCESS);
3022 cleanup_event:
3023 isc_task_detach(&tclone);
3024 isc_event_free(ISC_EVENT_PTR(&event));
3026 cleanup_val:
3027 dns_view_weakdetach(&val->view);
3028 isc_mem_put(view->mctx, val, sizeof(*val));
3030 return (result);
3033 void
3034 dns_validator_send(dns_validator_t *validator) {
3035 isc_event_t *event;
3036 REQUIRE(VALID_VALIDATOR(validator));
3038 LOCK(&validator->lock);
3040 INSIST((validator->options & DNS_VALIDATOR_DEFER) != 0);
3041 event = (isc_event_t *)validator->event;
3042 validator->options &= ~DNS_VALIDATOR_DEFER;
3043 UNLOCK(&validator->lock);
3045 isc_task_send(validator->task, ISC_EVENT_PTR(&event));
3048 void
3049 dns_validator_cancel(dns_validator_t *validator) {
3050 REQUIRE(VALID_VALIDATOR(validator));
3052 LOCK(&validator->lock);
3054 validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
3056 if (validator->event != NULL) {
3057 if (validator->fetch != NULL)
3058 dns_resolver_cancelfetch(validator->fetch);
3060 if (validator->subvalidator != NULL)
3061 dns_validator_cancel(validator->subvalidator);
3062 if ((validator->options & DNS_VALIDATOR_DEFER) != 0) {
3063 isc_task_t *task = validator->event->ev_sender;
3064 validator->options &= ~DNS_VALIDATOR_DEFER;
3065 isc_event_free((isc_event_t **)&validator->event);
3066 isc_task_detach(&task);
3068 validator->attributes |= VALATTR_CANCELED;
3070 UNLOCK(&validator->lock);
3073 static void
3074 destroy(dns_validator_t *val) {
3075 isc_mem_t *mctx;
3077 REQUIRE(SHUTDOWN(val));
3078 REQUIRE(val->event == NULL);
3079 REQUIRE(val->fetch == NULL);
3081 if (val->keynode != NULL)
3082 dns_keytable_detachkeynode(val->keytable, &val->keynode);
3083 else if (val->key != NULL)
3084 dst_key_free(&val->key);
3085 if (val->keytable != NULL)
3086 dns_keytable_detach(&val->keytable);
3087 if (val->subvalidator != NULL)
3088 dns_validator_destroy(&val->subvalidator);
3089 if (val->havedlvsep)
3090 dns_rdataset_disassociate(&val->dlv);
3091 if (dns_rdataset_isassociated(&val->frdataset))
3092 dns_rdataset_disassociate(&val->frdataset);
3093 if (dns_rdataset_isassociated(&val->fsigrdataset))
3094 dns_rdataset_disassociate(&val->fsigrdataset);
3095 mctx = val->view->mctx;
3096 if (val->siginfo != NULL)
3097 isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo));
3098 DESTROYLOCK(&val->lock);
3099 dns_view_weakdetach(&val->view);
3100 val->magic = 0;
3101 isc_mem_put(mctx, val, sizeof(*val));
3104 void
3105 dns_validator_destroy(dns_validator_t **validatorp) {
3106 dns_validator_t *val;
3107 isc_boolean_t want_destroy = ISC_FALSE;
3109 REQUIRE(validatorp != NULL);
3110 val = *validatorp;
3111 REQUIRE(VALID_VALIDATOR(val));
3113 LOCK(&val->lock);
3115 val->attributes |= VALATTR_SHUTDOWN;
3116 validator_log(val, ISC_LOG_DEBUG(3), "dns_validator_destroy");
3118 want_destroy = exit_check(val);
3120 UNLOCK(&val->lock);
3122 if (want_destroy)
3123 destroy(val);
3125 *validatorp = NULL;
3128 static void
3129 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
3130 isc_logmodule_t *module, int level, const char *fmt, va_list ap)
3132 char msgbuf[2048];
3133 static const char spaces[] = " *";
3134 int depth = val->depth * 2;
3136 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
3138 if ((unsigned int) depth >= sizeof spaces)
3139 depth = sizeof spaces - 1;
3141 if (val->event != NULL && val->event->name != NULL) {
3142 char namebuf[DNS_NAME_FORMATSIZE];
3143 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3145 dns_name_format(val->event->name, namebuf, sizeof(namebuf));
3146 dns_rdatatype_format(val->event->type, typebuf,
3147 sizeof(typebuf));
3148 isc_log_write(dns_lctx, category, module, level,
3149 "%.*svalidating @%p: %s %s: %s", depth, spaces,
3150 val, namebuf, typebuf, msgbuf);
3151 } else {
3152 isc_log_write(dns_lctx, category, module, level,
3153 "%.*svalidator @%p: %s", depth, spaces,
3154 val, msgbuf);
3158 static void
3159 validator_log(dns_validator_t *val, int level, const char *fmt, ...) {
3160 va_list ap;
3162 if (! isc_log_wouldlog(dns_lctx, level))
3163 return;
3165 va_start(ap, fmt);
3167 validator_logv(val, DNS_LOGCATEGORY_DNSSEC,
3168 DNS_LOGMODULE_VALIDATOR, level, fmt, ap);
3169 va_end(ap);
3172 static void
3173 validator_logcreate(dns_validator_t *val,
3174 dns_name_t *name, dns_rdatatype_t type,
3175 const char *caller, const char *operation)
3177 char namestr[DNS_NAME_FORMATSIZE];
3178 char typestr[DNS_RDATATYPE_FORMATSIZE];
3180 dns_name_format(name, namestr, sizeof(namestr));
3181 dns_rdatatype_format(type, typestr, sizeof(typestr));
3182 validator_log(val, ISC_LOG_DEBUG(9), "%s: creating %s for %s %s",
3183 caller, operation, namestr, typestr);