bind - Upgraded vendor branch to 9.5.2-P1
[dragonfly.git] / contrib / bind-9.5.2 / lib / dns / validator.c
CommitLineData
bbbf71a3
JL
1/*
2 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2003 Internet Software Consortium.
4 *
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.
8 *
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.
16 */
17
c4067435 18/* $Id: validator.c,v 1.155.52.14.2.1 2009/11/18 23:41:18 marka Exp $ */
bbbf71a3
JL
19
20#include <config.h>
21
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>
28
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>
46
47/*! \file
48 * \brief
49 * Basic processing sequences.
50 *
51 * \li When called with rdataset and sigrdataset:
52 * validator_start -> validate -> proveunsecure -> startfinddlvsep ->
53 * dlv_validator_start -> validator_start -> validate -> proveunsecure
54 *
55 * validator_start -> validate -> nsecvalidate (secure wildcard answer)
56 *
57 * \li When called with rdataset, sigrdataset and with DNS_VALIDATOR_DLV:
58 * validator_start -> startfinddlvsep -> dlv_validator_start ->
59 * validator_start -> validate -> proveunsecure
60 *
61 * \li When called with rdataset:
62 * validator_start -> proveunsecure -> startfinddlvsep ->
63 * dlv_validator_start -> validator_start -> proveunsecure
64 *
65 * \li When called with rdataset and with DNS_VALIDATOR_DLV:
66 * validator_start -> startfinddlvsep -> dlv_validator_start ->
67 * validator_start -> proveunsecure
68 *
69 * \li When called without a rdataset:
70 * validator_start -> nsecvalidate -> proveunsecure -> startfinddlvsep ->
71 * dlv_validator_start -> validator_start -> nsecvalidate -> proveunsecure
72 *
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.
76 *
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.
84 */
85
86#define VALIDATOR_MAGIC ISC_MAGIC('V', 'a', 'l', '?')
87#define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
88
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. */
95
96/*!
97 * NSEC proofs to be looked for.
98 */
99#define VALATTR_NEEDNOQNAME 0x0100
100#define VALATTR_NEEDNOWILDCARD 0x0200
101#define VALATTR_NEEDNODATA 0x0400
102
103/*!
104 * NSEC proofs that have been found.
105 */
106#define VALATTR_FOUNDNOQNAME 0x1000
107#define VALATTR_FOUNDNOWILDCARD 0x2000
108#define VALATTR_FOUNDNODATA 0x4000
109
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)
114
115#define SHUTDOWN(v) (((v)->attributes & VALATTR_SHUTDOWN) != 0)
116#define CANCELED(v) (((v)->attributes & VALATTR_CANCELED) != 0)
117
118static void
119destroy(dns_validator_t *val);
120
121static isc_result_t
122get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
123 dns_rdataset_t *rdataset);
124
125static isc_result_t
126validate(dns_validator_t *val, isc_boolean_t resume);
127
128static isc_result_t
129validatezonekey(dns_validator_t *val);
130
131static isc_result_t
132nsecvalidate(dns_validator_t *val, isc_boolean_t resume);
133
134static isc_result_t
135proveunsecure(dns_validator_t *val, isc_boolean_t have_ds,
136 isc_boolean_t resume);
137
138static void
139validator_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);
142
143static void
144validator_log(dns_validator_t *val, int level, const char *fmt, ...)
145 ISC_FORMAT_PRINTF(3, 4);
146
147static void
148validator_logcreate(dns_validator_t *val,
149 dns_name_t *name, dns_rdatatype_t type,
150 const char *caller, const char *operation);
151
152static isc_result_t
153dlv_validatezonekey(dns_validator_t *val);
154
155static void
156dlv_validator_start(dns_validator_t *val);
157
158static isc_result_t
159finddlvsep(dns_validator_t *val, isc_boolean_t resume);
160
161static isc_result_t
162startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure);
163
164/*%
165 * Mark the RRsets as a answer.
166 */
167static inline void
168markanswer(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;
174}
175
176static void
177validator_done(dns_validator_t *val, isc_result_t result) {
178 isc_task_t *task;
179
180 if (val->event == NULL)
181 return;
182
183 /*
184 * Caller must be holding the lock.
185 */
186
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);
194}
195
196static inline isc_boolean_t
197exit_check(dns_validator_t *val) {
198 /*
199 * Caller must be holding the lock.
200 */
201 if (!SHUTDOWN(val))
202 return (ISC_FALSE);
203
204 INSIST(val->event == NULL);
205
206 if (val->fetch != NULL || val->subvalidator != NULL)
207 return (ISC_FALSE);
208
209 return (ISC_TRUE);
210}
211
212/*
213 * Check that we have atleast one supported algorithm in the DLV RRset.
214 */
215static inline isc_boolean_t
216dlv_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;
220
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);
228
229 if (!dns_resolver_algorithm_supported(val->view->resolver,
230 val->event->name,
231 dlv.algorithm))
232 continue;
233
234 if (dlv.digest_type != DNS_DSDIGEST_SHA256 &&
235 dlv.digest_type != DNS_DSDIGEST_SHA1)
236 continue;
237
238 return (ISC_TRUE);
239 }
240 return (ISC_FALSE);
241}
242
243/*%
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.
246 */
247static isc_boolean_t
248isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
249 isc_result_t dbresult)
250{
251 dns_rdataset_t set;
252 dns_rdata_t rdata = DNS_RDATA_INIT;
253 isc_boolean_t found;
254 isc_result_t result;
255
256 REQUIRE(dbresult == DNS_R_NXRRSET || dbresult == DNS_R_NCACHENXRRSET);
257
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);
266 }
267
268 INSIST(set.type == dns_rdatatype_nsec);
269
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);
275 }
276 dns_rdataset_disassociate(&set);
277 return (found);
278}
279
280/*%
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.
284 */
285static void
286fetch_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;
293
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;
300
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);
310
311 INSIST(val->event != NULL);
312
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);
320 /*
321 * Only extract the dst key if the keyset is secure.
322 */
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;
327 }
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);
339 }
340 want_destroy = exit_check(val);
341 UNLOCK(&val->lock);
342 if (want_destroy)
343 destroy(val);
344}
345
346/*%
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.
350 */
351static void
352dsfetched(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;
359
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;
366
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);
376
377 INSIST(val->event != NULL);
378
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? */
393 {
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);
409 }
410 want_destroy = exit_check(val);
411 UNLOCK(&val->lock);
412 if (want_destroy)
413 destroy(val);
414}
415
416/*%
417 * We were asked to look for the DS record as part of proving that a
418 * name is unsecure.
419 *
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.
423 *
424 * If the DS record exists it will be secure. We can continue looking
425 * for the break point in the chain of trust.
426 */
427static void
428dsfetched2(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;
435
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;
441
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);
450
451 INSIST(val->event != NULL);
452
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) {
459 /*
460 * There is no DS. If this is a delegation, we're done.
461 */
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);
475 }
476 } else {
477 result = proveunsecure(val, ISC_FALSE, ISC_TRUE);
478 if (result != DNS_R_WAIT)
479 validator_done(val, result);
480 }
481 } else if (eresult == ISC_R_SUCCESS ||
482 eresult == DNS_R_NXDOMAIN ||
483 eresult == DNS_R_NCACHENXDOMAIN)
484 {
485 /*
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.
489 */
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);
499 }
500 isc_event_free(&event);
501 want_destroy = exit_check(val);
502 UNLOCK(&val->lock);
503 if (want_destroy)
504 destroy(val);
505}
506
507/*%
508 * Callback from when a DNSKEY RRset has been validated.
509 *
510 * Resumes the stalled validation process.
511 */
512static void
513keyvalidated(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;
519
520 UNUSED(task);
521 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
522
523 devent = (dns_validatorevent_t *)event;
524 val = devent->ev_arg;
525 eresult = devent->result;
526
527 isc_event_free(&event);
528 dns_validator_destroy(&val->subvalidator);
529
530 INSIST(val->event != NULL);
531
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);
539 /*
540 * Only extract the dst key if the keyset is secure.
541 */
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);
552 }
553 want_destroy = exit_check(val);
554 UNLOCK(&val->lock);
555 if (want_destroy)
556 destroy(val);
557}
558
559/*%
560 * Callback when the DS record has been validated.
561 *
562 * Resumes validation of the zone key or the unsecure zone proof.
563 */
564static void
565dsvalidated(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;
571
572 UNUSED(task);
573 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
574
575 devent = (dns_validatorevent_t *)event;
576 val = devent->ev_arg;
577 eresult = devent->result;
578
579 isc_event_free(&event);
580 dns_validator_destroy(&val->subvalidator);
581
582 INSIST(val->event != NULL);
583
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);
602 }
603 want_destroy = exit_check(val);
604 UNLOCK(&val->lock);
605 if (want_destroy)
606 destroy(val);
607}
608
609/*%
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.
613 *
614 * Return ISC_R_IGNORE when the NSEC is not the appropriate one.
615 */
616static isc_result_t
617nsecnoexistnodata(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)
620{
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;
630
631 REQUIRE(exists != NULL);
632 REQUIRE(data != NULL);
633 REQUIRE(nsecset != NULL &&
634 nsecset->type == dns_rdatatype_nsec);
635
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);
641 }
642 dns_rdataset_current(nsecset, &rdata);
643
644 validator_log(val, ISC_LOG_DEBUG(3), "looking for relevant nsec");
645 relation = dns_name_fullcompare(name, nsecname, &order, &olabels);
646
647 if (order < 0) {
648 /*
649 * The name is not within the NSEC range.
650 */
651 validator_log(val, ISC_LOG_DEBUG(3),
652 "NSEC does not cover name, before NSEC");
653 return (ISC_R_IGNORE);
654 }
655
656 if (order == 0) {
657 /*
658 * The names are the same.
659 */
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) {
665 /*
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.
669 */
670 validator_log(val, ISC_LOG_DEBUG(3),
671 "ignoring parent nsec");
672 return (ISC_R_IGNORE);
673 }
674 } else if (atparent && ns && soa) {
675 /*
676 * This NSEC record is from the child.
677 * It can not be legitimately used here.
678 */
679 validator_log(val, ISC_LOG_DEBUG(3),
680 "ignoring child nsec");
681 return (ISC_R_IGNORE);
682 }
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);
694 }
695 validator_log(val, ISC_LOG_DEBUG(3), "NSEC proves CNAME exists");
696 return (ISC_R_IGNORE);
697 }
698
699 if (relation == dns_namereln_subdomain &&
700 dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
701 !dns_nsec_typepresent(&rdata, dns_rdatatype_soa))
702 {
703 /*
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.
707 */
708 validator_log(val, ISC_LOG_DEBUG(3), "ignoring parent nsec");
709 return (ISC_R_IGNORE);
710 }
711
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);
721 }
722
723 if (order < 0 && !dns_name_issubdomain(nsecname, &nsec.next)) {
724 /*
725 * The name is not within the NSEC range.
726 */
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);
731 }
732
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);
740 }
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);
752 }
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);
760 }
761 }
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);
766}
767
768/*%
769 * Callback for when NSEC records have been validated.
770 *
771 * Looks for NOQNAME and NODATA proofs.
772 *
773 * Resumes nsecvalidate.
774 */
775static void
776authvalidated(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;
783
784 UNUSED(task);
785 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
786
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);
792
793 INSIST(val->event != NULL);
794
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);
809 }
810 } else {
811 dns_name_t **proofs = val->event->proofs;
812 dns_name_t *wild = dns_fixedname_name(&val->wild);
813
814 if (rdataset->trust == dns_trust_secure)
815 val->seensig = ISC_TRUE;
816
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)
826 {
827 if (exists && !data) {
828 val->attributes |= VALATTR_FOUNDNODATA;
829 if (NEEDNODATA(val))
830 proofs[DNS_VALIDATOR_NODATAPROOF] =
831 devent->name;
832 }
833 if (!exists) {
834 val->attributes |= VALATTR_FOUNDNOQNAME;
835 if (NEEDNOQNAME(val))
836 proofs[DNS_VALIDATOR_NOQNAMEPROOF] =
837 devent->name;
838 }
839 }
840 result = nsecvalidate(val, ISC_TRUE);
841 if (result != DNS_R_WAIT)
842 validator_done(val, result);
843 }
844 want_destroy = exit_check(val);
845 UNLOCK(&val->lock);
846 if (want_destroy)
847 destroy(val);
848
849 /*
850 * Free stuff from the event.
851 */
852 isc_event_free(&event);
853}
854
855/*%
856 * Looks for the requested name and type in the view (zones and cache).
857 *
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.
860 *
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
868 */
869static inline isc_result_t
870view_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];
880
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);
885
886 if (val->view->zonetable == NULL)
887 return (ISC_R_CANCELED);
888
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");
904 /*
905 * Check if the returned NSEC covers the name.
906 */
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;
913 }
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;
925 }
926 }
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)) {
933 /*
934 * XXXMPA We could look for a parent NSEC
935 * at nsec.next and if found retest with
936 * this NSEC.
937 */
938 dns_rdata_freestruct(&nsec);
939 validator_log(val, ISC_LOG_DEBUG(3),
940 "covering nsec: not in zone");
941 goto notfound;
942 }
943 } else if (dns_name_compare(name, &nsec.next) >= 0) {
944 /*
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.
950 */
951 dns_rdata_freestruct(&nsec);
952 validator_log(val, ISC_LOG_DEBUG(3),
953 "covering nsec: not in range");
954 goto notfound;
955 }
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);
963 }
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;
977 }
978 return (result);
979
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);
986}
987
988/*%
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.
991 */
992static inline isc_boolean_t
993check_deadlock(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
994 dns_validator_t *parent;
995
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))
1000 {
1001 validator_log(val, ISC_LOG_DEBUG(3),
1002 "continuing validation would lead to "
1003 "deadlock: aborting validation");
1004 return (ISC_TRUE);
1005 }
1006 }
1007 return (ISC_FALSE);
1008}
1009
1010/*%
1011 * Start a fetch for the requested name and type.
1012 */
1013static inline isc_result_t
1014create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
1015 isc_taskaction_t callback, const char *caller)
1016{
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);
1021
1022 if (check_deadlock(val, name, type))
1023 return (DNS_R_NOVALIDSIG);
1024
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));
1033}
1034
1035/*%
1036 * Start a subvalidation process.
1037 */
1038static inline isc_result_t
1039create_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)
1042{
1043 isc_result_t result;
1044
1045 if (check_deadlock(val, name, type))
1046 return (DNS_R_NOVALIDSIG);
1047
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;
1056 }
1057 return (result);
1058}
1059
1060/*%
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.
1064 *
1065 * If val->key is non-NULL, this returns the next matching key.
1066 */
1067static isc_result_t
1068get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
1069 dns_rdataset_t *rdataset)
1070{
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;
1076
1077 if (oldkey == NULL)
1078 foundold = ISC_TRUE;
1079 else {
1080 foundold = ISC_FALSE;
1081 val->key = NULL;
1082 }
1083
1084 result = dns_rdataset_first(rdataset);
1085 if (result != ISC_R_SUCCESS)
1086 goto failure;
1087 do {
1088 dns_rdataset_current(rdataset, &rdata);
1089
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))
1102 {
1103 if (foundold)
1104 /*
1105 * This is the key we're looking for.
1106 */
1107 return (ISC_R_SUCCESS);
1108 else if (dst_key_compare(oldkey, val->key) == ISC_TRUE)
1109 {
1110 foundold = ISC_TRUE;
1111 dst_key_free(&oldkey);
1112 }
1113 }
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;
1120
1121 failure:
1122 if (oldkey != NULL)
1123 dst_key_free(&oldkey);
1124
1125 return (result);
1126}
1127
1128/*%
1129 * Get the key that generated this signature.
1130 */
1131static isc_result_t
1132get_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;
1137
1138 /*
1139 * Is the signer name appropriate for this signature?
1140 *
1141 * The signer name must be at the same level as the owner name
1142 * or closer to the DNS root.
1143 */
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);
1149
1150 if (namereln == dns_namereln_equal) {
1151 /*
1152 * If this is a self-signed keyset, it must not be a zone key
1153 * (since get_key is not called from validatezonekey).
1154 */
1155 if (val->event->rdataset->type == dns_rdatatype_dnskey)
1156 return (DNS_R_CONTINUE);
1157
1158 /*
1159 * Records appearing in the parent zone at delegation
1160 * points cannot be self-signed.
1161 */
1162 if (dns_rdatatype_atparent(val->event->rdataset->type))
1163 return (DNS_R_CONTINUE);
1164 } else {
1165 /*
1166 * SOA and NS RRsets can only be signed by a key with
1167 * the same name.
1168 */
1169 if (val->event->rdataset->type == dns_rdatatype_soa ||
1170 val->event->rdataset->type == dns_rdatatype_ns) {
1171 const char *typename;
1172
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);
1180 }
1181 }
1182
1183 /*
1184 * Do we know about this key?
1185 */
1186 result = view_find(val, &siginfo->signer, dns_rdatatype_dnskey);
1187 if (result == ISC_R_SUCCESS) {
1188 /*
1189 * We have an rrset for the given keyname.
1190 */
1191 val->keyset = &val->frdataset;
c4067435 1192 if (DNS_TRUST_PENDING(val->frdataset.trust) &&
bbbf71a3
JL
1193 dns_rdataset_isassociated(&val->fsigrdataset))
1194 {
1195 /*
1196 * We know the key but haven't validated it yet.
1197 */
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);
c4067435 1207 } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
bbbf71a3
JL
1208 /*
1209 * Having a pending key with no signature means that
1210 * something is broken.
1211 */
1212 result = DNS_R_CONTINUE;
1213 } else if (val->frdataset.trust < dns_trust_secure) {
1214 /*
1215 * The key is legitimately insecure. There's no
1216 * point in even attempting verification.
1217 */
1218 val->key = NULL;
1219 result = ISC_R_SUCCESS;
1220 } else {
1221 /*
1222 * See if we've got the key used in the signature.
1223 */
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) {
1229 /*
1230 * Either the key we're looking for is not
1231 * in the rrset, or something bad happened.
1232 * Give up.
1233 */
1234 result = DNS_R_CONTINUE;
1235 }
1236 }
1237 } else if (result == ISC_R_NOTFOUND) {
1238 /*
1239 * We don't know anything about this key.
1240 */
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)
1251 {
1252 /*
1253 * This key doesn't exist.
1254 */
1255 result = DNS_R_CONTINUE;
1256 }
1257
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);
1263
1264 return (result);
1265}
1266
1267static dns_keytag_t
1268compute_keytag(dns_rdata_t *rdata, dns_rdata_dnskey_t *key) {
1269 isc_region_t r;
1270
1271 dns_rdata_toregion(rdata, &r);
1272 return (dst_region_computeid(&r, key->algorithm));
1273}
1274
1275/*%
1276 * Is this keyset self-signed?
1277 */
1278static isc_boolean_t
1279isselfsigned(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;
1287
1288 rdataset = val->event->rdataset;
1289 sigrdataset = val->event->sigrdataset;
1290
1291 INSIST(rdataset->type == dns_rdatatype_dnskey);
1292
1293 for (result = dns_rdataset_first(rdataset);
1294 result == ISC_R_SUCCESS;
1295 result = dns_rdataset_next(rdataset))
1296 {
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))
1305 {
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);
1310
1311 if (sig.algorithm == key.algorithm &&
1312 sig.keyid == keytag)
1313 return (ISC_TRUE);
1314 }
1315 }
1316 return (ISC_FALSE);
1317}
1318
1319/*%
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.
1323 *
1324 * Returns:
1325 * \li ISC_R_SUCCESS if the verification succeeds.
1326 * \li Others if the verification fails.
1327 */
1328static isc_result_t
1329verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata,
1330 isc_uint16_t keyid)
1331{
1332 isc_result_t result;
1333 dns_fixedname_t fixed;
1334 isc_boolean_t ignore = ISC_FALSE;
1335
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;
1345 }
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;
1360 }
1361 return (result);
1362}
1363
1364/*%
1365 * Attempts positive response validation of a normal RRset.
1366 *
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.
1372 */
1373static isc_result_t
1374validate(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;
1378
1379 /*
1380 * Caller must be holding the validator lock.
1381 */
1382
1383 event = val->event;
1384
1385 if (resume) {
1386 /*
1387 * We already have a sigrdataset.
1388 */
1389 result = ISC_R_SUCCESS;
1390 validator_log(val, ISC_LOG_DEBUG(3), "resuming validate");
1391 } else {
1392 result = dns_rdataset_first(event->sigrdataset);
1393 }
1394
1395 for (;
1396 result == ISC_R_SUCCESS;
1397 result = dns_rdataset_next(event->sigrdataset))
1398 {
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);
1406 }
1407 result = dns_rdata_tostruct(&rdata, val->siginfo, NULL);
1408 if (result != ISC_R_SUCCESS)
1409 return (result);
1410
1411 /*
1412 * At this point we could check that the signature algorithm
1413 * was known and "sufficiently good".
1414 */
1415 if (!dns_resolver_algorithm_supported(val->view->resolver,
1416 event->name,
1417 val->siginfo->algorithm))
1418 continue;
1419
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);
1426 }
1427
1428 /*
1429 * The key is insecure, so mark the data as insecure also.
1430 */
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);
1436 }
1437 markanswer(val);
1438 return (ISC_R_SUCCESS);
1439 }
1440
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;
1458 }
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;
1464 }
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;
1472
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;
1480 }
1481
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;
1491 }
1492 }
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);
1499 }
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;
1514 }
1515 }
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);
1521 }
1522
1523 validator_log(val, ISC_LOG_INFO, "no valid signature found");
1524 return (DNS_R_NOVALIDSIG);
1525}
1526
1527/*%
1528 * Validate the DNSKEY RRset by looking for a DNSKEY that matches a
1529 * DLV record and that also verifies the DNSKEY RRset.
1530 */
1531static isc_result_t
1532dlv_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;
1547
1548 validator_log(val, ISC_LOG_DEBUG(3), "dlv_validatezonekey");
1549
1550 /*
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.
1554 */
1555 supported_algorithm = ISC_FALSE;
1556
1557 /*
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.
1562 */
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);
1571
1572 if (!dns_resolver_algorithm_supported(val->view->resolver,
1573 val->event->name,
1574 dlv.algorithm))
1575 continue;
1576
1577 if (dlv.digest_type == DNS_DSDIGEST_SHA256 &&
1578 dlv.length == ISC_SHA256_DIGESTLENGTH) {
1579 digest_type = DNS_DSDIGEST_SHA256;
1580 break;
1581 }
1582 }
1583
1584 for (result = dns_rdataset_first(&val->dlv);
1585 result == ISC_R_SUCCESS;
1586 result = dns_rdataset_next(&val->dlv))
1587 {
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);
1592
1593 if (!dns_resolver_digest_supported(val->view->resolver,
1594 dlv.digest_type))
1595 continue;
1596
1597 if (dlv.digest_type != digest_type)
1598 continue;
1599
1600 if (!dns_resolver_algorithm_supported(val->view->resolver,
1601 val->event->name,
1602 dlv.algorithm))
1603 continue;
1604
1605 supported_algorithm = ISC_TRUE;
1606
1607 dns_rdataset_init(&trdataset);
1608 dns_rdataset_clone(val->event->rdataset, &trdataset);
1609
1610 for (result = dns_rdataset_first(&trdataset);
1611 result == ISC_R_SUCCESS;
1612 result = dns_rdataset_next(&trdataset))
1613 {
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;
1631 }
1632 /* Covert to DLV */
1633 newdsrdata.type = dns_rdatatype_dlv;
1634 if (dns_rdata_compare(&dlvrdata, &newdsrdata) == 0)
1635 break;
1636 }
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;
1642 }
1643 validator_log(val, ISC_LOG_DEBUG(3),
1644 "Found matching DLV record: checking for signature");
1645
1646 for (result = dns_rdataset_first(val->event->sigrdataset);
1647 result == ISC_R_SUCCESS;
1648 result = dns_rdataset_next(val->event->sigrdataset))
1649 {
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)
1664 /*
1665 * This really shouldn't happen, but...
1666 */
1667 continue;
1668
1669 result = verify(val, dstkey, &sigrdata, sig.keyid);
1670 dst_key_free(&dstkey);
1671 if (result == ISC_R_SUCCESS)
1672 break;
1673 }
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");
1679 }
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);
1690 }
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);
1697}
1698
1699/*%
1700 * Attempts positive response validation of an RRset containing zone keys.
1701 *
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.
1707 */
1708static isc_result_t
1709validatezonekey(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;
1727
1728 /*
1729 * Caller must be holding the validator lock.
1730 */
1731
1732 event = val->event;
1733
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));
1737
1738 if (val->dsset == NULL) {
1739 /*
1740 * First, see if this key was signed by a trusted key.
1741 */
1742 for (result = dns_rdataset_first(val->event->sigrdataset);
1743 result == ISC_R_SUCCESS;
1744 result = dns_rdataset_next(val->event->sigrdataset))
1745 {
1746 dns_keynode_t *keynode = NULL, *nextnode = NULL;
1747
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);
1753
1754 if (!dns_name_equal(val->event->name, &sig.signer))
1755 continue;
1756
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;
1773 }
1774 result = dns_keytable_findnextkeynode(
1775 val->keytable,
1776 keynode,
1777 &nextnode);
1778 dns_keytable_detachkeynode(val->keytable,
1779 &keynode);
1780 keynode = nextnode;
1781 }
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);
1789 }
1790 }
1791
1792 /*
1793 * If this is the root name and there was no trusted key,
1794 * give up, since there's no DS at the root.
1795 */
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);
1801 }
1802
1803 if (atsep) {
1804 /*
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.
1808 */
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);
1817 }
1818
1819 /*
1820 * Otherwise, try to find the DS record.
1821 */
1822 result = view_find(val, val->event->name, dns_rdatatype_ds);
1823 if (result == ISC_R_SUCCESS) {
1824 /*
1825 * We have DS records.
1826 */
1827 val->dsset = &val->frdataset;
c4067435 1828 if (DNS_TRUST_PENDING(val->frdataset.trust) &&
bbbf71a3
JL
1829 dns_rdataset_isassociated(&val->fsigrdataset))
1830 {
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);
c4067435 1841 } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
bbbf71a3
JL
1842 /*
1843 * There should never be an unsigned DS.
1844 */
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) {
1852 /*
1853 * We don't have the DS. Find it.
1854 */
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)
1866 {
1867 /*
1868 * The DS does not exist.
1869 */
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);
1876 }
1877 }
1878
1879 /*
1880 * We have a DS set.
1881 */
1882 INSIST(val->dsset != NULL);
1883
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);
1889 }
1890 markanswer(val);
1891 return (ISC_R_SUCCESS);
1892 }
1893
1894 /*
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.
1898 */
1899
1900 supported_algorithm = ISC_FALSE;
1901
1902 /*
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.
1907 */
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);
1916
1917 if (!dns_resolver_algorithm_supported(val->view->resolver,
1918 val->event->name,
1919 ds.algorithm))
1920 continue;
1921
1922 if (ds.digest_type == DNS_DSDIGEST_SHA256 &&
1923 ds.length == ISC_SHA256_DIGESTLENGTH) {
1924 digest_type = DNS_DSDIGEST_SHA256;
1925 break;
1926 }
1927 }
1928
1929 for (result = dns_rdataset_first(val->dsset);
1930 result == ISC_R_SUCCESS;
1931 result = dns_rdataset_next(val->dsset))
1932 {
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);
1937
1938 if (!dns_resolver_digest_supported(val->view->resolver,
1939 ds.digest_type))
1940 continue;
1941
1942 if (ds.digest_type != digest_type)
1943 continue;
1944
1945 if (!dns_resolver_algorithm_supported(val->view->resolver,
1946 val->event->name,
1947 ds.algorithm))
1948 continue;
1949
1950 supported_algorithm = ISC_TRUE;
1951
1952 dns_rdataset_init(&trdataset);
1953 dns_rdataset_clone(val->event->rdataset, &trdataset);
1954
1955 /*
1956 * Look for the KEY that matches the DS record.
1957 */
1958 for (result = dns_rdataset_first(&trdataset);
1959 result == ISC_R_SUCCESS;
1960 result = dns_rdataset_next(&trdataset))
1961 {
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;
1978 }
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;
1984 }
1985
1986 for (result = dns_rdataset_first(val->event->sigrdataset);
1987 result == ISC_R_SUCCESS;
1988 result = dns_rdataset_next(val->event->sigrdataset))
1989 {
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;
2002 }
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)
2009 /*
2010 * This really shouldn't happen, but...
2011 */
2012 continue;
2013 result = verify(val, dstkey, &sigrdata, sig.keyid);
2014 dst_key_free(&dstkey);
2015 if (result == ISC_R_SUCCESS)
2016 break;
2017 }
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");
2023 }
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);
2034 }
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);
2041}
2042
2043/*%
2044 * Starts a positive response validation.
2045 *
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.
2051 */
2052static isc_result_t
2053start_positive_validation(dns_validator_t *val) {
2054 /*
2055 * If this is not a key, go straight into validate().
2056 */
2057 if (val->event->type != dns_rdatatype_dnskey || !isselfsigned(val))
2058 return (validate(val, ISC_FALSE));
2059
2060 return (validatezonekey(val));
2061}
2062
2063/*%
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.
2067 *
2068 * Returns
2069 * \li ISC_R_SUCCESS
2070 */
2071static isc_result_t
2072checkwildcard(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];
2078
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);
2082
2083 for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2084 result == ISC_R_SUCCESS;
2085 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
2086 {
2087 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2088
2089 name = NULL;
2090 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
2091
2092 for (rdataset = ISC_LIST_HEAD(name->list);
2093 rdataset != NULL;
2094 rdataset = ISC_LIST_NEXT(rdataset, link))
2095 {
2096 if (rdataset->type != dns_rdatatype_nsec)
2097 continue;
2098 val->nsecset = rdataset;
2099
2100 for (sigrdataset = ISC_LIST_HEAD(name->list);
2101 sigrdataset != NULL;
2102 sigrdataset = ISC_LIST_NEXT(sigrdataset, link))
2103 {
2104 if (sigrdataset->type == dns_rdatatype_rrsig &&
2105 sigrdataset->covers == rdataset->type)
2106 break;
2107 }
2108 if (sigrdataset == NULL)
2109 continue;
2110
2111 if (rdataset->trust != dns_trust_secure)
2112 continue;
2113
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)
2121 {
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);
2135 }
2136 }
2137 }
2138 if (result == ISC_R_NOMORE)
2139 result = ISC_R_SUCCESS;
2140 return (result);
2141}
2142
2143/*%
2144 * Prove a negative answer is good or that there is a NOQNAME when the
2145 * answer is from a wildcard.
2146 *
2147 * Loop through the authority section looking for NODATA, NOWILDCARD
2148 * and NOQNAME proofs in the NSEC records by calling authvalidated().
2149 *
2150 * If the required proofs are found we are done.
2151 *
2152 * If the proofs are not found attempt to prove this is a unsecure
2153 * response.
2154 */
2155static isc_result_t
2156nsecvalidate(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;
2160
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");
2166 }
2167
2168 for (;
2169 result == ISC_R_SUCCESS;
2170 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
2171 {
2172 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2173
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);
2182
2183 for (;
2184 rdataset != NULL;
2185 rdataset = ISC_LIST_NEXT(rdataset, link))
2186 {
2187 if (rdataset->type == dns_rdatatype_rrsig)
2188 continue;
2189
2190 for (sigrdataset = ISC_LIST_HEAD(name->list);
2191 sigrdataset != NULL;
2192 sigrdataset = ISC_LIST_NEXT(sigrdataset,
2193 link))
2194 {
2195 if (sigrdataset->type == dns_rdatatype_rrsig &&
2196 sigrdataset->covers == rdataset->type)
2197 break;
2198 }
2199 /*
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.
2208 */
2209 if (val->event->type == dns_rdatatype_dnskey &&
2210 dns_name_equal(name, val->event->name))
2211 {
2212 dns_rdata_t nsec = DNS_RDATA_INIT;
2213
2214 if (rdataset->type != dns_rdatatype_nsec)
2215 continue;
2216
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;
2224 }
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);
2233
2234 }
2235 }
2236 if (result == ISC_R_NOMORE)
2237 result = ISC_R_SUCCESS;
2238 if (result != ISC_R_SUCCESS)
2239 return (result);
2240
2241 /*
2242 * Do we only need to check for NOQNAME? To get here we must have
2243 * had a secure wildcard answer.
2244 */
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);
2256 }
2257 validator_log(val, ISC_LOG_DEBUG(3),
2258 "noqname proof not found");
2259 return (DNS_R_NOVALIDNSEC);
2260 }
2261
2262 /*
2263 * Do we need to check for the wildcard?
2264 */
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);
2272 }
2273
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);
2283 }
2284
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));
2289}
2290
2291static isc_boolean_t
2292check_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;
2296
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);
2303
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);
2310 }
2311 dns_rdata_reset(&dsrdata);
2312 }
2313 return (ISC_FALSE);
2314}
2315
2316/*%
2317 * Callback from fetching a DLV record.
2318 *
2319 * Resumes the DLV lookup process.
2320 */
2321static void
2322dlvfetched(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;
2329
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;
2335
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);
2345
2346 INSIST(val->event != NULL);
2347 validator_log(val, ISC_LOG_DEBUG(3), "in dlvfetched: %s",
2348 dns_result_totext(eresult));
2349
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);
2366 }
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);
2385 }
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);
2395 }
2396 } else {
2397 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
2398 dns_result_totext(eresult));
2399 validator_done(val, eresult);
2400 }
2401 want_destroy = exit_check(val);
2402 UNLOCK(&val->lock);
2403 if (want_destroy)
2404 destroy(val);
2405}
2406
2407/*%
2408 * Start the DLV lookup process.
2409 *
2410 * Returns
2411 * \li ISC_R_SUCCESS
2412 * \li DNS_R_WAIT
2413 * \li Others on validation failures.
2414 */
2415static isc_result_t
2416startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) {
2417 char namebuf[DNS_NAME_FORMATSIZE];
2418 isc_result_t result;
2419
2420 INSIST(!DLVTRIED(val));
2421
2422 val->attributes |= VALATTR_DLVTRIED;
2423
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);
2428
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);
2432 }
2433
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);
2440 }
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);
2445 }
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);
2452 }
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);
2458}
2459
2460/*%
2461 * Continue the DLV lookup process.
2462 *
2463 * Returns
2464 * \li ISC_R_SUCCESS
2465 * \li ISC_R_NOTFOUND
2466 * \li DNS_R_WAIT
2467 * \li Others on validation failure.
2468 */
2469static isc_result_t
2470finddlvsep(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;
2478
2479 INSIST(val->view->dlv != NULL);
2480
2481 if (!resume) {
2482
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);
2487 }
2488
2489 dns_fixedname_init(&val->dlvsep);
2490 dlvsep = dns_fixedname_name(&val->dlvsep);
2491 dns_name_copy(val->event->name, dlvsep, NULL);
2492 /*
2493 * If this is a response to a DS query, we need to look in
2494 * the parent zone for the trust anchor.
2495 */
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);
2502 }
2503 } else {
2504 dlvsep = dns_fixedname_name(&val->dlvsep);
2505 labels = dns_name_countlabels(dlvsep);
2506 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
2507 }
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);
2522 }
2523 if (result != ISC_R_SUCCESS) {
2524 validator_log(val, ISC_LOG_DEBUG(2), "DLV concatenate failed");
2525 return (DNS_R_NOVALIDSIG);
2526 }
2527
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);
2540 }
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);
2547 }
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);
2554 /*
2555 * Strip first labels from both dlvsep and dlvname.
2556 */
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);
2563 }
2564 return (ISC_R_NOTFOUND);
2565}
2566
2567/*%
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.
2572 *
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.
2576 *
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
2585 */
2586static isc_result_t
2587proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
2588{
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];
2594
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 dns_name_copy(val->event->name, secroot, NULL);
2601 /*
2602 * If this is a response to a DS query, we need to look in
2603 * the parent zone for the trust anchor.
2604 */
2605 if (val->event->type == dns_rdatatype_ds &&
2606 dns_name_countlabels(secroot) > 1U)
2607 dns_name_split(secroot, 1, NULL, secroot);
2608 result = dns_keytable_finddeepestmatch(val->keytable,
2609 secroot, secroot);
2610
2611 if (result == ISC_R_NOTFOUND) {
2612 validator_log(val, ISC_LOG_DEBUG(3),
2613 "not beneath secure root");
2614 if (val->mustbesecure) {
2615 validator_log(val, ISC_LOG_WARNING,
2616 "must be secure failure");
2617 result = DNS_R_MUSTBESECURE;
2618 goto out;
2619 }
2620 if (val->view->dlv == NULL || DLVTRIED(val)) {
2621 markanswer(val);
2622 return (ISC_R_SUCCESS);
2623 }
2624 return (startfinddlvsep(val, dns_rootname));
2625 } else if (result != ISC_R_SUCCESS)
2626 return (result);
2627 }
2628
2629 if (!resume) {
2630 /*
2631 * We are looking for breaks below the SEP so add a label.
2632 */
2633 val->labels = dns_name_countlabels(secroot) + 1;
2634 } else {
2635 validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
2636 /*
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.
2641 */
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;
2654 }
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;
2662 }
2663 result = startfinddlvsep(val,
2664 dns_fixedname_name(&val->fname));
2665 goto out;
2666 }
2667 val->labels++;
2668 }
2669
2670 for (;
2671 val->labels <= dns_name_countlabels(val->event->name);
2672 val->labels++)
2673 {
2674
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);
2682
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);
2687
2688 result = view_find(val, tname, dns_rdatatype_ds);
2689
2690 if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
2691 /*
2692 * There is no DS. If this is a delegation,
2693 * we maybe done.
2694 */
c4067435 2695 if (DNS_TRUST_PENDING(val->frdataset.trust)) {
bbbf71a3
JL
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);
2703 }
2704 if (val->frdataset.trust < dns_trust_secure) {
2705 /*
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.
2710 */
2711 result = DNS_R_NOVALIDSIG;
2712 goto out;
2713 }
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);
2719 }
2720 if (val->view->dlv == NULL || DLVTRIED(val)) {
2721 markanswer(val);
2722 return (ISC_R_SUCCESS);
2723 }
2724 return (startfinddlvsep(val, tname));
2725 }
2726 continue;
2727 } else if (result == ISC_R_SUCCESS) {
2728 /*
2729 * There is a DS here. Verify that it's secure and
2730 * continue.
2731 */
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;
2743 }
2744 if (val->view->dlv == NULL ||
2745 DLVTRIED(val)) {
2746 markanswer(val);
2747 result = ISC_R_SUCCESS;
2748 goto out;
2749 }
2750 result = startfinddlvsep(val, tname);
2751 goto out;
2752 }
2753 continue;
2754 }
2755 else if (!dns_rdataset_isassociated(&val->fsigrdataset))
2756 {
2757 result = DNS_R_NOVALIDSIG;
2758 goto out;
2759 }
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) {
2770 /*
2771 * This is not a zone cut. Assuming things are
2772 * as expected, continue.
2773 */
2774 if (!dns_rdataset_isassociated(&val->frdataset)) {
2775 /*
2776 * There should be an NSEC here, since we
2777 * are still in a secure zone.
2778 */
2779 result = DNS_R_NOVALIDNSEC;
2780 goto out;
2781 } else if (val->frdataset.trust < dns_trust_secure) {
2782 /*
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.
2787 */
2788 result = DNS_R_NOVALIDSIG;
2789 goto out;
2790 }
2791 continue;
2792 } else if (result == ISC_R_NOTFOUND) {
2793 /*
2794 * We don't know anything about the DS. Find it.
2795 */
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);
2801 }
2802 }
2803 validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed");
2804 return (DNS_R_NOTINSECURE); /* Couldn't complete insecurity proof */
2805
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);
2812}
2813
2814/*%
2815 * Reset state and revalidate the answer using DLV.
2816 */
2817static void
2818dlv_validator_start(dns_validator_t *val) {
2819 isc_event_t *event;
2820
2821 validator_log(val, ISC_LOG_DEBUG(3), "dlv_validator_start");
2822
2823 /*
2824 * Reset state and try again.
2825 */
2826 val->attributes &= VALATTR_DLVTRIED;
2827 val->options &= ~DNS_VALIDATOR_DLV;
2828
2829 event = (isc_event_t *)val->event;
2830 isc_task_send(val->task, &event);
2831}
2832
2833/*%
2834 * Start the validation process.
2835 *
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).
2841 *
2842 * Note a answer that appears to be a secure positive answer may actually
2843 * be a unsecure positive answer.
2844 */
2845static void
2846validator_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;
2851
2852 UNUSED(task);
2853 REQUIRE(event->ev_type == DNS_EVENT_VALIDATORSTART);
2854 vevent = (dns_validatorevent_t *)event;
2855 val = vevent->validator;
2856
2857 /* If the validator has been canceled, val->event == NULL */
2858 if (val->event == NULL)
2859 return;
2860
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");
2865
2866 LOCK(&val->lock);
2867
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;
2875
2876 /*
2877 * This looks like a simple validation. We say "looks like"
2878 * because it might end up requiring an insecurity proof.
2879 */
2880 validator_log(val, ISC_LOG_DEBUG(3),
2881 "attempting positive response validation");
2882
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)
2888 {
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;
2896 }
2897 } else if (val->event->rdataset != NULL) {
2898 /*
2899 * This is either an unsecure subdomain or a response from
2900 * a broken server.
2901 */
2902 INSIST(dns_rdataset_isassociated(val->event->rdataset));
2903 validator_log(val, ISC_LOG_DEBUG(3),
2904 "attempting insecurity proof");
2905
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)
2910 {
2911 /*
2912 * This is a nonexistence validation.
2913 */
2914 validator_log(val, ISC_LOG_DEBUG(3),
2915 "attempting negative response validation");
2916
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 {
2924 /*
2925 * This shouldn't happen.
2926 */
2927 INSIST(0);
2928 }
2929
2930 if (result != DNS_R_WAIT) {
2931 want_destroy = exit_check(val);
2932 validator_done(val, result);
2933 }
2934
2935 UNLOCK(&val->lock);
2936 if (want_destroy)
2937 destroy(val);
2938}
2939
2940isc_result_t
2941dns_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)
2946{
2947 isc_result_t result;
2948 dns_validator_t *val;
2949 isc_task_t *tclone;
2950 dns_validatorevent_t *event;
2951
2952 REQUIRE(name != NULL);
2953 REQUIRE(rdataset != NULL ||
2954 (rdataset == NULL && sigrdataset == NULL && message != NULL));
2955 REQUIRE(validatorp != NULL && *validatorp == NULL);
2956
2957 tclone = NULL;
2958 result = ISC_R_FAILURE;
2959
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;
2973 }
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;
3014
3015 if ((options & DNS_VALIDATOR_DEFER) == 0)
3016 isc_task_send(task, ISC_EVENT_PTR(&event));
3017
3018 *validatorp = val;
3019
3020 return (ISC_R_SUCCESS);
3021
3022 cleanup_event:
3023 isc_task_detach(&tclone);
3024 isc_event_free(ISC_EVENT_PTR(&event));
3025
3026 cleanup_val:
3027 dns_view_weakdetach(&val->view);
3028 isc_mem_put(view->mctx, val, sizeof(*val));
3029
3030 return (result);
3031}
3032
3033void
3034dns_validator_send(dns_validator_t *validator) {
3035 isc_event_t *event;
3036 REQUIRE(VALID_VALIDATOR(validator));
3037
3038 LOCK(&validator->lock);
3039
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);
3044
3045 isc_task_send(validator->task, ISC_EVENT_PTR(&event));
3046}
3047
3048void
3049dns_validator_cancel(dns_validator_t *validator) {
3050 REQUIRE(VALID_VALIDATOR(validator));
3051
3052 LOCK(&validator->lock);
3053
3054 validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
3055
3056 if (validator->event != NULL) {
3057 if (validator->fetch != NULL)
3058 dns_resolver_cancelfetch(validator->fetch);
3059
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);
3067 }
3068 validator->attributes |= VALATTR_CANCELED;
3069 }
3070 UNLOCK(&validator->lock);
3071}
3072
3073static void
3074destroy(dns_validator_t *val) {
3075 isc_mem_t *mctx;
3076
3077 REQUIRE(SHUTDOWN(val));
3078 REQUIRE(val->event == NULL);
3079 REQUIRE(val->fetch == NULL);
3080
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));
3102}
3103
3104void
3105dns_validator_destroy(dns_validator_t **validatorp) {
3106 dns_validator_t *val;
3107 isc_boolean_t want_destroy = ISC_FALSE;
3108
3109 REQUIRE(validatorp != NULL);
3110 val = *validatorp;
3111 REQUIRE(VALID_VALIDATOR(val));
3112
3113 LOCK(&val->lock);
3114
3115 val->attributes |= VALATTR_SHUTDOWN;
3116 validator_log(val, ISC_LOG_DEBUG(3), "dns_validator_destroy");
3117
3118 want_destroy = exit_check(val);
3119
3120 UNLOCK(&val->lock);
3121
3122 if (want_destroy)
3123 destroy(val);
3124
3125 *validatorp = NULL;
3126}
3127
3128static void
3129validator_logv(dns_validator_t *val, isc_logcategory_t *category,
3130 isc_logmodule_t *module, int level, const char *fmt, va_list ap)
3131{
3132 char msgbuf[2048];
3133 static const char spaces[] = " *";
3134 int depth = val->depth * 2;
3135
3136 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
3137
3138 if ((unsigned int) depth >= sizeof spaces)
3139 depth = sizeof spaces - 1;
3140
3141 if (val->event != NULL && val->event->name != NULL) {
3142 char namebuf[DNS_NAME_FORMATSIZE];
3143 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3144
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);
3155 }
3156}
3157
3158static void
3159validator_log(dns_validator_t *val, int level, const char *fmt, ...) {
3160 va_list ap;
3161
3162 if (! isc_log_wouldlog(dns_lctx, level))
3163 return;
3164
3165 va_start(ap, fmt);
3166
3167 validator_logv(val, DNS_LOGCATEGORY_DNSSEC,
3168 DNS_LOGMODULE_VALIDATOR, level, fmt, ap);
3169 va_end(ap);
3170}
3171
3172static void
3173validator_logcreate(dns_validator_t *val,
3174 dns_name_t *name, dns_rdatatype_t type,
3175 const char *caller, const char *operation)
3176{
3177 char namestr[DNS_NAME_FORMATSIZE];
3178 char typestr[DNS_RDATATYPE_FORMATSIZE];
3179
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);
3184}