validator.c revision 1.1 1 /* $NetBSD: validator.c,v 1.1 2018/08/12 12:08:15 christos Exp $ */
2
3 /*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 */
13
14 #include <config.h>
15
16 #include <isc/base32.h>
17 #include <isc/mem.h>
18 #include <isc/print.h>
19 #include <isc/sha2.h>
20 #include <isc/string.h>
21 #include <isc/task.h>
22 #include <isc/util.h>
23
24 #include <dns/client.h>
25 #include <dns/db.h>
26 #include <dns/dnssec.h>
27 #include <dns/ds.h>
28 #include <dns/events.h>
29 #include <dns/keytable.h>
30 #include <dns/keyvalues.h>
31 #include <dns/log.h>
32 #include <dns/message.h>
33 #include <dns/ncache.h>
34 #include <dns/nsec.h>
35 #include <dns/nsec3.h>
36 #include <dns/rdata.h>
37 #include <dns/rdataset.h>
38 #include <dns/rdatatype.h>
39 #include <dns/resolver.h>
40 #include <dns/result.h>
41 #include <dns/validator.h>
42 #include <dns/view.h>
43
44 /*! \file
45 * \brief
46 * Basic processing sequences.
47 *
48 * \li When called with rdataset and sigrdataset:
49 * validator_start -> validate -> proveunsecure -> startfinddlvsep ->
50 * dlv_validator_start -> validator_start -> validate -> proveunsecure
51 *
52 * validator_start -> validate -> nsecvalidate (secure wildcard answer)
53 *
54 * \li When called with rdataset, sigrdataset and with DNS_VALIDATOR_DLV:
55 * validator_start -> startfinddlvsep -> dlv_validator_start ->
56 * validator_start -> validate -> proveunsecure
57 *
58 * \li When called with rdataset:
59 * validator_start -> proveunsecure -> startfinddlvsep ->
60 * dlv_validator_start -> validator_start -> proveunsecure
61 *
62 * \li When called with rdataset and with DNS_VALIDATOR_DLV:
63 * validator_start -> startfinddlvsep -> dlv_validator_start ->
64 * validator_start -> proveunsecure
65 *
66 * \li When called without a rdataset:
67 * validator_start -> nsecvalidate -> proveunsecure -> startfinddlvsep ->
68 * dlv_validator_start -> validator_start -> nsecvalidate -> proveunsecure
69 *
70 * Note: there isn't a case for DNS_VALIDATOR_DLV here as we want nsecvalidate()
71 * to always validate the authority section even when it does not contain
72 * signatures.
73 *
74 * validator_start: determines what type of validation to do.
75 * validate: attempts to perform a positive validation.
76 * proveunsecure: attempts to prove the answer comes from a unsecure zone.
77 * nsecvalidate: attempts to prove a negative response.
78 * startfinddlvsep: starts the DLV record lookup.
79 * dlv_validator_start: resets state and restarts the lookup using the
80 * DLV RRset found by startfinddlvsep.
81 */
82
83 #define VALIDATOR_MAGIC ISC_MAGIC('V', 'a', 'l', '?')
84 #define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
85
86 #define VALATTR_SHUTDOWN 0x0001 /*%< Shutting down. */
87 #define VALATTR_CANCELED 0x0002 /*%< Canceled. */
88 #define VALATTR_TRIEDVERIFY 0x0004 /*%< We have found a key and
89 * have attempted a verify. */
90 #define VALATTR_INSECURITY 0x0010 /*%< Attempting proveunsecure. */
91 #define VALATTR_DLVTRIED 0x0020 /*%< Looked for a DLV record. */
92
93 /*!
94 * NSEC proofs to be looked for.
95 */
96 #define VALATTR_NEEDNOQNAME 0x00000100
97 #define VALATTR_NEEDNOWILDCARD 0x00000200
98 #define VALATTR_NEEDNODATA 0x00000400
99
100 /*!
101 * NSEC proofs that have been found.
102 */
103 #define VALATTR_FOUNDNOQNAME 0x00001000
104 #define VALATTR_FOUNDNOWILDCARD 0x00002000
105 #define VALATTR_FOUNDNODATA 0x00004000
106 #define VALATTR_FOUNDCLOSEST 0x00008000
107
108 /*
109 *
110 */
111 #define VALATTR_FOUNDOPTOUT 0x00010000
112 #define VALATTR_FOUNDUNKNOWN 0x00020000
113
114 #define NEEDNODATA(val) ((val->attributes & VALATTR_NEEDNODATA) != 0)
115 #define NEEDNOQNAME(val) ((val->attributes & VALATTR_NEEDNOQNAME) != 0)
116 #define NEEDNOWILDCARD(val) ((val->attributes & VALATTR_NEEDNOWILDCARD) != 0)
117 #define DLVTRIED(val) ((val->attributes & VALATTR_DLVTRIED) != 0)
118 #define FOUNDNODATA(val) ((val->attributes & VALATTR_FOUNDNODATA) != 0)
119 #define FOUNDNOQNAME(val) ((val->attributes & VALATTR_FOUNDNOQNAME) != 0)
120 #define FOUNDNOWILDCARD(val) ((val->attributes & VALATTR_FOUNDNOWILDCARD) != 0)
121 #define FOUNDCLOSEST(val) ((val->attributes & VALATTR_FOUNDCLOSEST) != 0)
122 #define FOUNDOPTOUT(val) ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
123
124 #define SHUTDOWN(v) (((v)->attributes & VALATTR_SHUTDOWN) != 0)
125 #define CANCELED(v) (((v)->attributes & VALATTR_CANCELED) != 0)
126
127 #define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
128
129 static void
130 destroy(dns_validator_t *val);
131
132 static isc_result_t
133 get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
134 dns_rdataset_t *rdataset);
135
136 static isc_result_t
137 validate(dns_validator_t *val, isc_boolean_t resume);
138
139 static isc_result_t
140 validatezonekey(dns_validator_t *val);
141
142 static isc_result_t
143 nsecvalidate(dns_validator_t *val, isc_boolean_t resume);
144
145 static isc_result_t
146 proveunsecure(dns_validator_t *val, isc_boolean_t have_ds,
147 isc_boolean_t resume);
148
149 static void
150 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
151 isc_logmodule_t *module, int level, const char *fmt, va_list ap)
152 ISC_FORMAT_PRINTF(5, 0);
153
154 static void
155 validator_log(void *val, int level, const char *fmt, ...)
156 ISC_FORMAT_PRINTF(3, 4);
157
158 static void
159 validator_logcreate(dns_validator_t *val,
160 dns_name_t *name, dns_rdatatype_t type,
161 const char *caller, const char *operation);
162
163 static isc_result_t
164 dlv_validatezonekey(dns_validator_t *val);
165
166 static void
167 dlv_validator_start(dns_validator_t *val);
168
169 static isc_result_t
170 finddlvsep(dns_validator_t *val, isc_boolean_t resume);
171
172 static isc_result_t
173 startfinddlvsep(dns_validator_t *val, const dns_name_t *unsecure);
174
175 /*%
176 * Mark the RRsets as a answer.
177 */
178 static inline void
179 markanswer(dns_validator_t *val, const char *where) {
180 validator_log(val, ISC_LOG_DEBUG(3), "marking as answer (%s)", where);
181 if (val->event->rdataset != NULL)
182 dns_rdataset_settrust(val->event->rdataset, dns_trust_answer);
183 if (val->event->sigrdataset != NULL)
184 dns_rdataset_settrust(val->event->sigrdataset,
185 dns_trust_answer);
186 }
187
188 static inline void
189 marksecure(dns_validatorevent_t *event) {
190 dns_rdataset_settrust(event->rdataset, dns_trust_secure);
191 if (event->sigrdataset != NULL)
192 dns_rdataset_settrust(event->sigrdataset, dns_trust_secure);
193 event->secure = ISC_TRUE;
194 }
195
196 static void
197 validator_done(dns_validator_t *val, isc_result_t result) {
198 isc_task_t *task;
199
200 if (val->event == NULL)
201 return;
202
203 /*
204 * Caller must be holding the lock.
205 */
206
207 val->event->result = result;
208 task = val->event->ev_sender;
209 val->event->ev_sender = val;
210 val->event->ev_type = DNS_EVENT_VALIDATORDONE;
211 val->event->ev_action = val->action;
212 val->event->ev_arg = val->arg;
213 isc_task_sendanddetach(&task, (isc_event_t **)&val->event);
214 }
215
216 static inline isc_boolean_t
217 exit_check(dns_validator_t *val) {
218 /*
219 * Caller must be holding the lock.
220 */
221 if (!SHUTDOWN(val))
222 return (ISC_FALSE);
223
224 INSIST(val->event == NULL);
225
226 if (val->fetch != NULL || val->subvalidator != NULL)
227 return (ISC_FALSE);
228
229 return (ISC_TRUE);
230 }
231
232 /*
233 * Check that we have atleast one supported algorithm in the DLV RRset.
234 */
235 static inline isc_boolean_t
236 dlv_algorithm_supported(dns_validator_t *val) {
237 dns_rdata_t rdata = DNS_RDATA_INIT;
238 dns_rdata_dlv_t dlv;
239 isc_result_t result;
240
241 for (result = dns_rdataset_first(&val->dlv);
242 result == ISC_R_SUCCESS;
243 result = dns_rdataset_next(&val->dlv)) {
244 dns_rdata_reset(&rdata);
245 dns_rdataset_current(&val->dlv, &rdata);
246 result = dns_rdata_tostruct(&rdata, &dlv, NULL);
247 RUNTIME_CHECK(result == ISC_R_SUCCESS);
248
249 if (!dns_resolver_algorithm_supported(val->view->resolver,
250 val->event->name,
251 dlv.algorithm))
252 continue;
253
254 if (!dns_resolver_ds_digest_supported(val->view->resolver,
255 val->event->name,
256 dlv.digest_type))
257 continue;
258
259 return (ISC_TRUE);
260 }
261 return (ISC_FALSE);
262 }
263
264 /*%
265 * Look in the NSEC record returned from a DS query to see if there is
266 * a NS RRset at this name. If it is found we are at a delegation point.
267 */
268 static isc_boolean_t
269 isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
270 isc_result_t dbresult)
271 {
272 dns_fixedname_t fixed;
273 dns_label_t hashlabel;
274 dns_name_t nsec3name;
275 dns_rdata_nsec3_t nsec3;
276 dns_rdata_t rdata = DNS_RDATA_INIT;
277 dns_rdataset_t set;
278 int order;
279 int scope;
280 isc_boolean_t found;
281 isc_buffer_t buffer;
282 isc_result_t result;
283 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
284 unsigned char owner[NSEC3_MAX_HASH_LENGTH];
285 unsigned int length;
286
287 REQUIRE(dbresult == DNS_R_NXRRSET || dbresult == DNS_R_NCACHENXRRSET);
288
289 dns_rdataset_init(&set);
290 if (dbresult == DNS_R_NXRRSET)
291 dns_rdataset_clone(rdataset, &set);
292 else {
293 result = dns_ncache_getrdataset(rdataset, name,
294 dns_rdatatype_nsec, &set);
295 if (result == ISC_R_NOTFOUND)
296 goto trynsec3;
297 if (result != ISC_R_SUCCESS)
298 return (ISC_FALSE);
299 }
300
301 INSIST(set.type == dns_rdatatype_nsec);
302
303 found = ISC_FALSE;
304 result = dns_rdataset_first(&set);
305 if (result == ISC_R_SUCCESS) {
306 dns_rdataset_current(&set, &rdata);
307 found = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
308 dns_rdata_reset(&rdata);
309 }
310 dns_rdataset_disassociate(&set);
311 return (found);
312
313 trynsec3:
314 /*
315 * Iterate over the ncache entry.
316 */
317 found = ISC_FALSE;
318 dns_name_init(&nsec3name, NULL);
319 dns_fixedname_init(&fixed);
320 dns_name_downcase(name, dns_fixedname_name(&fixed), NULL);
321 name = dns_fixedname_name(&fixed);
322 for (result = dns_rdataset_first(rdataset);
323 result == ISC_R_SUCCESS;
324 result = dns_rdataset_next(rdataset))
325 {
326 dns_ncache_current(rdataset, &nsec3name, &set);
327 if (set.type != dns_rdatatype_nsec3) {
328 dns_rdataset_disassociate(&set);
329 continue;
330 }
331 dns_name_getlabel(&nsec3name, 0, &hashlabel);
332 isc_region_consume(&hashlabel, 1);
333 isc_buffer_init(&buffer, owner, sizeof(owner));
334 result = isc_base32hexnp_decoderegion(&hashlabel, &buffer);
335 if (result != ISC_R_SUCCESS) {
336 dns_rdataset_disassociate(&set);
337 continue;
338 }
339 for (result = dns_rdataset_first(&set);
340 result == ISC_R_SUCCESS;
341 result = dns_rdataset_next(&set))
342 {
343 dns_rdata_reset(&rdata);
344 dns_rdataset_current(&set, &rdata);
345 (void)dns_rdata_tostruct(&rdata, &nsec3, NULL);
346 if (nsec3.hash != 1)
347 continue;
348 length = isc_iterated_hash(hash, nsec3.hash,
349 nsec3.iterations, nsec3.salt,
350 nsec3.salt_length,
351 name->ndata, name->length);
352 if (length != isc_buffer_usedlength(&buffer))
353 continue;
354 order = memcmp(hash, owner, length);
355 if (order == 0) {
356 found = dns_nsec3_typepresent(&rdata,
357 dns_rdatatype_ns);
358 dns_rdataset_disassociate(&set);
359 return (found);
360 }
361 if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) == 0)
362 continue;
363 /*
364 * Does this optout span cover the name?
365 */
366 scope = memcmp(owner, nsec3.next, nsec3.next_length);
367 if ((scope < 0 && order > 0 &&
368 memcmp(hash, nsec3.next, length) < 0) ||
369 (scope >= 0 && (order > 0 ||
370 memcmp(hash, nsec3.next, length) < 0)))
371 {
372 dns_rdataset_disassociate(&set);
373 return (ISC_TRUE);
374 }
375 }
376 dns_rdataset_disassociate(&set);
377 }
378 return (found);
379 }
380
381 /*%
382 * We have been asked to look for a key.
383 * If found resume the validation process.
384 * If not found fail the validation process.
385 */
386 static void
387 fetch_callback_validator(isc_task_t *task, isc_event_t *event) {
388 dns_fetchevent_t *devent;
389 dns_validator_t *val;
390 dns_rdataset_t *rdataset;
391 isc_boolean_t want_destroy;
392 isc_result_t result;
393 isc_result_t eresult;
394 isc_result_t saved_result;
395 dns_fetch_t *fetch;
396
397 UNUSED(task);
398 INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
399 devent = (dns_fetchevent_t *)event;
400 val = devent->ev_arg;
401 rdataset = &val->frdataset;
402 eresult = devent->result;
403
404 /* Free resources which are not of interest. */
405 if (devent->node != NULL)
406 dns_db_detachnode(devent->db, &devent->node);
407 if (devent->db != NULL)
408 dns_db_detach(&devent->db);
409 if (dns_rdataset_isassociated(&val->fsigrdataset))
410 dns_rdataset_disassociate(&val->fsigrdataset);
411 isc_event_free(&event);
412
413 INSIST(val->event != NULL);
414
415 validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_validator");
416 LOCK(&val->lock);
417 fetch = val->fetch;
418 val->fetch = NULL;
419 if (CANCELED(val)) {
420 validator_done(val, ISC_R_CANCELED);
421 } else if (eresult == ISC_R_SUCCESS) {
422 validator_log(val, ISC_LOG_DEBUG(3),
423 "keyset with trust %s",
424 dns_trust_totext(rdataset->trust));
425 /*
426 * Only extract the dst key if the keyset is secure.
427 */
428 if (rdataset->trust >= dns_trust_secure) {
429 result = get_dst_key(val, val->siginfo, rdataset);
430 if (result == ISC_R_SUCCESS)
431 val->keyset = &val->frdataset;
432 }
433 result = validate(val, ISC_TRUE);
434 if (result == DNS_R_NOVALIDSIG &&
435 (val->attributes & VALATTR_TRIEDVERIFY) == 0)
436 {
437 saved_result = result;
438 validator_log(val, ISC_LOG_DEBUG(3),
439 "falling back to insecurity proof");
440 val->attributes |= VALATTR_INSECURITY;
441 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
442 if (result == DNS_R_NOTINSECURE)
443 result = saved_result;
444 }
445 if (result != DNS_R_WAIT)
446 validator_done(val, result);
447 } else {
448 validator_log(val, ISC_LOG_DEBUG(3),
449 "fetch_callback_validator: got %s",
450 isc_result_totext(eresult));
451 if (eresult == ISC_R_CANCELED)
452 validator_done(val, eresult);
453 else
454 validator_done(val, DNS_R_BROKENCHAIN);
455 }
456 want_destroy = exit_check(val);
457 UNLOCK(&val->lock);
458 if (fetch != NULL)
459 dns_resolver_destroyfetch(&fetch);
460 if (want_destroy)
461 destroy(val);
462 }
463
464 /*%
465 * We were asked to look for a DS record as part of following a key chain
466 * upwards. If found resume the validation process. If not found fail the
467 * validation process.
468 */
469 static void
470 dsfetched(isc_task_t *task, isc_event_t *event) {
471 dns_fetchevent_t *devent;
472 dns_validator_t *val;
473 dns_rdataset_t *rdataset;
474 isc_boolean_t want_destroy;
475 isc_result_t result;
476 isc_result_t eresult;
477 dns_fetch_t *fetch;
478
479 UNUSED(task);
480 INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
481 devent = (dns_fetchevent_t *)event;
482 val = devent->ev_arg;
483 rdataset = &val->frdataset;
484 eresult = devent->result;
485
486 /* Free resources which are not of interest. */
487 if (devent->node != NULL)
488 dns_db_detachnode(devent->db, &devent->node);
489 if (devent->db != NULL)
490 dns_db_detach(&devent->db);
491 if (dns_rdataset_isassociated(&val->fsigrdataset))
492 dns_rdataset_disassociate(&val->fsigrdataset);
493 isc_event_free(&event);
494
495 INSIST(val->event != NULL);
496
497 validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched");
498 LOCK(&val->lock);
499 fetch = val->fetch;
500 val->fetch = NULL;
501 if (CANCELED(val)) {
502 validator_done(val, ISC_R_CANCELED);
503 } else if (eresult == ISC_R_SUCCESS) {
504 validator_log(val, ISC_LOG_DEBUG(3),
505 "dsset with trust %s",
506 dns_trust_totext(rdataset->trust));
507 val->dsset = &val->frdataset;
508 result = validatezonekey(val);
509 if (result != DNS_R_WAIT)
510 validator_done(val, result);
511 } else if (eresult == DNS_R_CNAME ||
512 eresult == DNS_R_NXRRSET ||
513 eresult == DNS_R_NCACHENXRRSET ||
514 eresult == DNS_R_SERVFAIL) /* RFC 1034 parent? */
515 {
516 validator_log(val, ISC_LOG_DEBUG(3),
517 "falling back to insecurity proof (%s)",
518 dns_result_totext(eresult));
519 val->attributes |= VALATTR_INSECURITY;
520 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
521 if (result != DNS_R_WAIT)
522 validator_done(val, result);
523 } else {
524 validator_log(val, ISC_LOG_DEBUG(3),
525 "dsfetched: got %s",
526 isc_result_totext(eresult));
527 if (eresult == ISC_R_CANCELED)
528 validator_done(val, eresult);
529 else
530 validator_done(val, DNS_R_BROKENCHAIN);
531 }
532 want_destroy = exit_check(val);
533 UNLOCK(&val->lock);
534 if (fetch != NULL)
535 dns_resolver_destroyfetch(&fetch);
536 if (want_destroy)
537 destroy(val);
538 }
539
540 /*%
541 * We were asked to look for the DS record as part of proving that a
542 * name is unsecure.
543 *
544 * If the DS record doesn't exist and the query name corresponds to
545 * a delegation point we are transitioning from a secure zone to a
546 * unsecure zone.
547 *
548 * If the DS record exists it will be secure. We can continue looking
549 * for the break point in the chain of trust.
550 */
551 static void
552 dsfetched2(isc_task_t *task, isc_event_t *event) {
553 dns_fetchevent_t *devent;
554 dns_validator_t *val;
555 dns_name_t *tname;
556 isc_boolean_t want_destroy;
557 isc_result_t result;
558 isc_result_t eresult;
559 dns_fetch_t *fetch;
560
561 UNUSED(task);
562 INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
563 devent = (dns_fetchevent_t *)event;
564 val = devent->ev_arg;
565 eresult = devent->result;
566
567 /* Free resources which are not of interest. */
568 if (devent->node != NULL)
569 dns_db_detachnode(devent->db, &devent->node);
570 if (devent->db != NULL)
571 dns_db_detach(&devent->db);
572 if (dns_rdataset_isassociated(&val->fsigrdataset))
573 dns_rdataset_disassociate(&val->fsigrdataset);
574
575 INSIST(val->event != NULL);
576
577 validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched2: %s",
578 dns_result_totext(eresult));
579 LOCK(&val->lock);
580 fetch = val->fetch;
581 val->fetch = NULL;
582 if (CANCELED(val)) {
583 validator_done(val, ISC_R_CANCELED);
584 } else if (eresult == DNS_R_CNAME ||
585 eresult == DNS_R_NXRRSET ||
586 eresult == DNS_R_NCACHENXRRSET)
587 {
588 /*
589 * There is no DS. If this is a delegation, we're done.
590 */
591 tname = dns_fixedname_name(&devent->foundname);
592 if (eresult != DNS_R_CNAME &&
593 isdelegation(tname, &val->frdataset, eresult)) {
594 if (val->mustbesecure) {
595 validator_log(val, ISC_LOG_WARNING,
596 "must be secure failure, no DS"
597 " and this is a delegation");
598 validator_done(val, DNS_R_MUSTBESECURE);
599 } else if (val->view->dlv == NULL || DLVTRIED(val)) {
600 markanswer(val, "dsfetched2");
601 validator_done(val, ISC_R_SUCCESS);
602 } else {
603 result = startfinddlvsep(val, tname);
604 if (result != DNS_R_WAIT)
605 validator_done(val, result);
606 }
607 } else {
608 result = proveunsecure(val, ISC_FALSE, ISC_TRUE);
609 if (result != DNS_R_WAIT)
610 validator_done(val, result);
611 }
612 } else if (eresult == ISC_R_SUCCESS ||
613 eresult == DNS_R_NXDOMAIN ||
614 eresult == DNS_R_NCACHENXDOMAIN)
615 {
616 /*
617 * There is a DS which may or may not be a zone cut.
618 * In either case we are still in a secure zone resume
619 * validation.
620 */
621 result = proveunsecure(val, ISC_TF(eresult == ISC_R_SUCCESS),
622 ISC_TRUE);
623 if (result != DNS_R_WAIT)
624 validator_done(val, result);
625 } else {
626 if (eresult == ISC_R_CANCELED)
627 validator_done(val, eresult);
628 else
629 validator_done(val, DNS_R_NOVALIDDS);
630 }
631 isc_event_free(&event);
632 want_destroy = exit_check(val);
633 UNLOCK(&val->lock);
634 if (fetch != NULL)
635 dns_resolver_destroyfetch(&fetch);
636 if (want_destroy)
637 destroy(val);
638 }
639
640 /*%
641 * Callback from when a DNSKEY RRset has been validated.
642 *
643 * Resumes the stalled validation process.
644 */
645 static void
646 keyvalidated(isc_task_t *task, isc_event_t *event) {
647 dns_validatorevent_t *devent;
648 dns_validator_t *val;
649 isc_boolean_t want_destroy;
650 isc_result_t result;
651 isc_result_t eresult;
652 isc_result_t saved_result;
653
654 UNUSED(task);
655 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
656
657 devent = (dns_validatorevent_t *)event;
658 val = devent->ev_arg;
659 eresult = devent->result;
660
661 isc_event_free(&event);
662 dns_validator_destroy(&val->subvalidator);
663
664 INSIST(val->event != NULL);
665
666 validator_log(val, ISC_LOG_DEBUG(3), "in keyvalidated");
667 LOCK(&val->lock);
668 if (CANCELED(val)) {
669 validator_done(val, ISC_R_CANCELED);
670 } else if (eresult == ISC_R_SUCCESS) {
671 validator_log(val, ISC_LOG_DEBUG(3),
672 "keyset with trust %s",
673 dns_trust_totext(val->frdataset.trust));
674 /*
675 * Only extract the dst key if the keyset is secure.
676 */
677 if (val->frdataset.trust >= dns_trust_secure)
678 (void) get_dst_key(val, val->siginfo, &val->frdataset);
679 result = validate(val, ISC_TRUE);
680 if (result == DNS_R_NOVALIDSIG &&
681 (val->attributes & VALATTR_TRIEDVERIFY) == 0)
682 {
683 saved_result = result;
684 validator_log(val, ISC_LOG_DEBUG(3),
685 "falling back to insecurity proof");
686 val->attributes |= VALATTR_INSECURITY;
687 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
688 if (result == DNS_R_NOTINSECURE)
689 result = saved_result;
690 }
691 if (result != DNS_R_WAIT)
692 validator_done(val, result);
693 } else {
694 if (eresult != DNS_R_BROKENCHAIN) {
695 if (dns_rdataset_isassociated(&val->frdataset))
696 dns_rdataset_expire(&val->frdataset);
697 if (dns_rdataset_isassociated(&val->fsigrdataset))
698 dns_rdataset_expire(&val->fsigrdataset);
699 }
700 validator_log(val, ISC_LOG_DEBUG(3),
701 "keyvalidated: got %s",
702 isc_result_totext(eresult));
703 validator_done(val, DNS_R_BROKENCHAIN);
704 }
705 want_destroy = exit_check(val);
706 UNLOCK(&val->lock);
707 if (want_destroy)
708 destroy(val);
709 }
710
711 /*%
712 * Callback when the DS record has been validated.
713 *
714 * Resumes validation of the zone key or the unsecure zone proof.
715 */
716 static void
717 dsvalidated(isc_task_t *task, isc_event_t *event) {
718 dns_validatorevent_t *devent;
719 dns_validator_t *val;
720 isc_boolean_t want_destroy;
721 isc_result_t result;
722 isc_result_t eresult;
723
724 UNUSED(task);
725 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
726
727 devent = (dns_validatorevent_t *)event;
728 val = devent->ev_arg;
729 eresult = devent->result;
730
731 isc_event_free(&event);
732 dns_validator_destroy(&val->subvalidator);
733
734 INSIST(val->event != NULL);
735
736 validator_log(val, ISC_LOG_DEBUG(3), "in dsvalidated");
737 LOCK(&val->lock);
738 if (CANCELED(val)) {
739 validator_done(val, ISC_R_CANCELED);
740 } else if (eresult == ISC_R_SUCCESS) {
741 isc_boolean_t have_dsset;
742 dns_name_t *name;
743 validator_log(val, ISC_LOG_DEBUG(3),
744 "%s with trust %s",
745 val->frdataset.type == dns_rdatatype_ds ?
746 "dsset" : "ds non-existance",
747 dns_trust_totext(val->frdataset.trust));
748 have_dsset = ISC_TF(val->frdataset.type == dns_rdatatype_ds);
749 name = dns_fixedname_name(&val->fname);
750 if ((val->attributes & VALATTR_INSECURITY) != 0 &&
751 val->frdataset.covers == dns_rdatatype_ds &&
752 NEGATIVE(&val->frdataset) &&
753 isdelegation(name, &val->frdataset, DNS_R_NCACHENXRRSET)) {
754 if (val->mustbesecure) {
755 validator_log(val, ISC_LOG_WARNING,
756 "must be secure failure, no DS "
757 "and this is a delegation");
758 result = DNS_R_MUSTBESECURE;
759 } else if (val->view->dlv == NULL || DLVTRIED(val)) {
760 markanswer(val, "dsvalidated");
761 result = ISC_R_SUCCESS;;
762 } else
763 result = startfinddlvsep(val, name);
764 } else if ((val->attributes & VALATTR_INSECURITY) != 0) {
765 result = proveunsecure(val, have_dsset, ISC_TRUE);
766 } else
767 result = validatezonekey(val);
768 if (result != DNS_R_WAIT)
769 validator_done(val, result);
770 } else {
771 if (eresult != DNS_R_BROKENCHAIN) {
772 if (dns_rdataset_isassociated(&val->frdataset))
773 dns_rdataset_expire(&val->frdataset);
774 if (dns_rdataset_isassociated(&val->fsigrdataset))
775 dns_rdataset_expire(&val->fsigrdataset);
776 }
777 validator_log(val, ISC_LOG_DEBUG(3),
778 "dsvalidated: got %s",
779 isc_result_totext(eresult));
780 validator_done(val, DNS_R_BROKENCHAIN);
781 }
782 want_destroy = exit_check(val);
783 UNLOCK(&val->lock);
784 if (want_destroy)
785 destroy(val);
786 }
787
788 /*%
789 * Callback when the CNAME record has been validated.
790 *
791 * Resumes validation of the unsecure zone proof.
792 */
793 static void
794 cnamevalidated(isc_task_t *task, isc_event_t *event) {
795 dns_validatorevent_t *devent;
796 dns_validator_t *val;
797 isc_boolean_t want_destroy;
798 isc_result_t result;
799 isc_result_t eresult;
800
801 UNUSED(task);
802 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
803
804 devent = (dns_validatorevent_t *)event;
805 val = devent->ev_arg;
806 eresult = devent->result;
807
808 isc_event_free(&event);
809 dns_validator_destroy(&val->subvalidator);
810
811 INSIST(val->event != NULL);
812 INSIST((val->attributes & VALATTR_INSECURITY) != 0);
813
814 validator_log(val, ISC_LOG_DEBUG(3), "in cnamevalidated");
815 LOCK(&val->lock);
816 if (CANCELED(val)) {
817 validator_done(val, ISC_R_CANCELED);
818 } else if (eresult == ISC_R_SUCCESS) {
819 validator_log(val, ISC_LOG_DEBUG(3), "cname with trust %s",
820 dns_trust_totext(val->frdataset.trust));
821 result = proveunsecure(val, ISC_FALSE, ISC_TRUE);
822 if (result != DNS_R_WAIT)
823 validator_done(val, result);
824 } else {
825 if (eresult != DNS_R_BROKENCHAIN) {
826 if (dns_rdataset_isassociated(&val->frdataset))
827 dns_rdataset_expire(&val->frdataset);
828 if (dns_rdataset_isassociated(&val->fsigrdataset))
829 dns_rdataset_expire(&val->fsigrdataset);
830 }
831 validator_log(val, ISC_LOG_DEBUG(3),
832 "cnamevalidated: got %s",
833 isc_result_totext(eresult));
834 validator_done(val, DNS_R_BROKENCHAIN);
835 }
836 want_destroy = exit_check(val);
837 UNLOCK(&val->lock);
838 if (want_destroy)
839 destroy(val);
840 }
841
842 /*%
843 * Callback for when NSEC records have been validated.
844 *
845 * Looks for NOQNAME, NODATA and OPTOUT proofs.
846 *
847 * Resumes nsecvalidate.
848 */
849 static void
850 authvalidated(isc_task_t *task, isc_event_t *event) {
851 dns_validatorevent_t *devent;
852 dns_validator_t *val;
853 dns_rdataset_t *rdataset;
854 isc_boolean_t want_destroy;
855 isc_result_t result;
856 isc_boolean_t exists, data;
857
858 UNUSED(task);
859 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
860
861 devent = (dns_validatorevent_t *)event;
862 rdataset = devent->rdataset;
863 val = devent->ev_arg;
864 result = devent->result;
865 dns_validator_destroy(&val->subvalidator);
866
867 INSIST(val->event != NULL);
868
869 validator_log(val, ISC_LOG_DEBUG(3), "in authvalidated");
870 LOCK(&val->lock);
871 if (CANCELED(val)) {
872 validator_done(val, ISC_R_CANCELED);
873 } else if (result != ISC_R_SUCCESS) {
874 validator_log(val, ISC_LOG_DEBUG(3),
875 "authvalidated: got %s",
876 isc_result_totext(result));
877 if (result == DNS_R_BROKENCHAIN)
878 val->authfail++;
879 if (result == ISC_R_CANCELED)
880 validator_done(val, result);
881 else {
882 result = nsecvalidate(val, ISC_TRUE);
883 if (result != DNS_R_WAIT)
884 validator_done(val, result);
885 }
886 } else {
887 dns_name_t **proofs = val->event->proofs;
888 dns_name_t *wild = dns_fixedname_name(&val->wild);
889
890 if (rdataset->trust == dns_trust_secure)
891 val->seensig = ISC_TRUE;
892
893 if (rdataset->type == dns_rdatatype_nsec &&
894 rdataset->trust == dns_trust_secure &&
895 (NEEDNODATA(val) || NEEDNOQNAME(val)) &&
896 !FOUNDNODATA(val) && !FOUNDNOQNAME(val) &&
897 dns_nsec_noexistnodata(val->event->type, val->event->name,
898 devent->name, rdataset, &exists,
899 &data, wild, validator_log, val)
900 == ISC_R_SUCCESS)
901 {
902 if (exists && !data) {
903 val->attributes |= VALATTR_FOUNDNODATA;
904 if (NEEDNODATA(val))
905 proofs[DNS_VALIDATOR_NODATAPROOF] =
906 devent->name;
907 }
908 if (!exists) {
909 dns_name_t *closest;
910 unsigned int clabels;
911
912 val->attributes |= VALATTR_FOUNDNOQNAME;
913
914 closest = dns_fixedname_name(&val->closest);
915 clabels = dns_name_countlabels(closest);
916 /*
917 * If we are validating a wildcard response
918 * clabels will not be zero. We then need
919 * to check if the generated wilcard from
920 * dns_nsec_noexistnodata is consistent with
921 * the wildcard used to generate the response.
922 */
923 if (clabels == 0 ||
924 dns_name_countlabels(wild) == clabels + 1)
925 val->attributes |= VALATTR_FOUNDCLOSEST;
926 /*
927 * The NSEC noqname proof also contains
928 * the closest encloser.
929 */
930 if (NEEDNOQNAME(val))
931 proofs[DNS_VALIDATOR_NOQNAMEPROOF] =
932 devent->name;
933 }
934 }
935
936 result = nsecvalidate(val, ISC_TRUE);
937 if (result != DNS_R_WAIT)
938 validator_done(val, result);
939 }
940 want_destroy = exit_check(val);
941 UNLOCK(&val->lock);
942 if (want_destroy)
943 destroy(val);
944
945 /*
946 * Free stuff from the event.
947 */
948 isc_event_free(&event);
949 }
950
951 /*%
952 * Looks for the requested name and type in the view (zones and cache).
953 *
954 * When looking for a DLV record also checks to make sure the NSEC record
955 * returns covers the query name as part of aggressive negative caching.
956 *
957 * Returns:
958 * \li ISC_R_SUCCESS
959 * \li ISC_R_NOTFOUND
960 * \li DNS_R_NCACHENXDOMAIN
961 * \li DNS_R_NCACHENXRRSET
962 * \li DNS_R_NXRRSET
963 * \li DNS_R_NXDOMAIN
964 * \li DNS_R_BROKENCHAIN
965 */
966 static inline isc_result_t
967 view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
968 dns_fixedname_t fixedname;
969 dns_name_t *foundname;
970 dns_rdata_nsec_t nsec;
971 dns_rdata_t rdata = DNS_RDATA_INIT;
972 isc_result_t result;
973 unsigned int options;
974 isc_time_t now;
975 char buf1[DNS_NAME_FORMATSIZE];
976 char buf2[DNS_NAME_FORMATSIZE];
977 char buf3[DNS_NAME_FORMATSIZE];
978 char namebuf[DNS_NAME_FORMATSIZE];
979 char typebuf[DNS_RDATATYPE_FORMATSIZE];
980
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
986 if (isc_time_now(&now) == ISC_R_SUCCESS &&
987 dns_resolver_getbadcache(val->view->resolver, name, type, &now)) {
988
989 dns_name_format(name, namebuf, sizeof(namebuf));
990 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
991 validator_log(val, ISC_LOG_INFO, "bad cache hit (%s/%s)",
992 namebuf, typebuf);
993 return (DNS_R_BROKENCHAIN);
994 }
995
996 options = DNS_DBFIND_PENDINGOK;
997 if (type == dns_rdatatype_dlv)
998 options |= DNS_DBFIND_COVERINGNSEC;
999 foundname = dns_fixedname_initname(&fixedname);
1000 result = dns_view_find(val->view, name, type, 0, options,
1001 ISC_FALSE, NULL, NULL, foundname,
1002 &val->frdataset, &val->fsigrdataset);
1003
1004 if (result == DNS_R_NXDOMAIN) {
1005 if (dns_rdataset_isassociated(&val->frdataset))
1006 dns_rdataset_disassociate(&val->frdataset);
1007 if (dns_rdataset_isassociated(&val->fsigrdataset))
1008 dns_rdataset_disassociate(&val->fsigrdataset);
1009 } else if (result == DNS_R_COVERINGNSEC) {
1010 validator_log(val, ISC_LOG_DEBUG(3), "DNS_R_COVERINGNSEC");
1011 /*
1012 * Check if the returned NSEC covers the name.
1013 */
1014 INSIST(type == dns_rdatatype_dlv);
1015 if (val->frdataset.trust != dns_trust_secure) {
1016 validator_log(val, ISC_LOG_DEBUG(3),
1017 "covering nsec: trust %s",
1018 dns_trust_totext(val->frdataset.trust));
1019 goto notfound;
1020 }
1021 result = dns_rdataset_first(&val->frdataset);
1022 if (result != ISC_R_SUCCESS)
1023 goto notfound;
1024 dns_rdataset_current(&val->frdataset, &rdata);
1025 if (dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
1026 !dns_nsec_typepresent(&rdata, dns_rdatatype_soa)) {
1027 /* Parent NSEC record. */
1028 if (dns_name_issubdomain(name, foundname)) {
1029 validator_log(val, ISC_LOG_DEBUG(3),
1030 "covering nsec: for parent");
1031 goto notfound;
1032 }
1033 }
1034 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
1035 if (result != ISC_R_SUCCESS)
1036 goto notfound;
1037 if (dns_name_compare(foundname, &nsec.next) >= 0) {
1038 /* End of zone chain. */
1039 if (!dns_name_issubdomain(name, &nsec.next)) {
1040 /*
1041 * XXXMPA We could look for a parent NSEC
1042 * at nsec.next and if found retest with
1043 * this NSEC.
1044 */
1045 dns_rdata_freestruct(&nsec);
1046 validator_log(val, ISC_LOG_DEBUG(3),
1047 "covering nsec: not in zone");
1048 goto notfound;
1049 }
1050 } else if (dns_name_compare(name, &nsec.next) >= 0) {
1051 /*
1052 * XXXMPA We could check if this NSEC is at a zone
1053 * apex and if the qname is not below it and look for
1054 * a parent NSEC with the same name. This requires
1055 * that we can cache both NSEC records which we
1056 * currently don't support.
1057 */
1058 dns_rdata_freestruct(&nsec);
1059 validator_log(val, ISC_LOG_DEBUG(3),
1060 "covering nsec: not in range");
1061 goto notfound;
1062 }
1063 if (isc_log_wouldlog(dns_lctx,ISC_LOG_DEBUG(3))) {
1064 dns_name_format(name, buf1, sizeof buf1);
1065 dns_name_format(foundname, buf2, sizeof buf2);
1066 dns_name_format(&nsec.next, buf3, sizeof buf3);
1067 validator_log(val, ISC_LOG_DEBUG(3),
1068 "covering nsec found: '%s' '%s' '%s'",
1069 buf1, buf2, buf3);
1070 }
1071 if (dns_rdataset_isassociated(&val->frdataset))
1072 dns_rdataset_disassociate(&val->frdataset);
1073 if (dns_rdataset_isassociated(&val->fsigrdataset))
1074 dns_rdataset_disassociate(&val->fsigrdataset);
1075 dns_rdata_freestruct(&nsec);
1076 result = DNS_R_NCACHENXDOMAIN;
1077 } else if (result != ISC_R_SUCCESS &&
1078 result != DNS_R_NCACHENXDOMAIN &&
1079 result != DNS_R_NCACHENXRRSET &&
1080 result != DNS_R_EMPTYNAME &&
1081 result != DNS_R_NXRRSET &&
1082 result != ISC_R_NOTFOUND) {
1083 goto notfound;
1084 }
1085 return (result);
1086
1087 notfound:
1088 if (dns_rdataset_isassociated(&val->frdataset))
1089 dns_rdataset_disassociate(&val->frdataset);
1090 if (dns_rdataset_isassociated(&val->fsigrdataset))
1091 dns_rdataset_disassociate(&val->fsigrdataset);
1092 return (ISC_R_NOTFOUND);
1093 }
1094
1095 /*%
1096 * Checks to make sure we are not going to loop. As we use a SHARED fetch
1097 * the validation process will stall if looping was to occur.
1098 */
1099 static inline isc_boolean_t
1100 check_deadlock(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
1101 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
1102 {
1103 dns_validator_t *parent;
1104
1105 for (parent = val; parent != NULL; parent = parent->parent) {
1106 if (parent->event != NULL &&
1107 parent->event->type == type &&
1108 dns_name_equal(parent->event->name, name) &&
1109 /*
1110 * As NSEC3 records are meta data you sometimes
1111 * need to prove a NSEC3 record which says that
1112 * itself doesn't exist.
1113 */
1114 (parent->event->type != dns_rdatatype_nsec3 ||
1115 rdataset == NULL || sigrdataset == NULL ||
1116 parent->event->message == NULL ||
1117 parent->event->rdataset != NULL ||
1118 parent->event->sigrdataset != NULL))
1119 {
1120 validator_log(val, ISC_LOG_DEBUG(3),
1121 "continuing validation would lead to "
1122 "deadlock: aborting validation");
1123 return (ISC_TRUE);
1124 }
1125 }
1126 return (ISC_FALSE);
1127 }
1128
1129 /*%
1130 * Start a fetch for the requested name and type.
1131 */
1132 static inline isc_result_t
1133 create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
1134 isc_taskaction_t callback, const char *caller)
1135 {
1136 unsigned int fopts = 0;
1137
1138 if (dns_rdataset_isassociated(&val->frdataset))
1139 dns_rdataset_disassociate(&val->frdataset);
1140 if (dns_rdataset_isassociated(&val->fsigrdataset))
1141 dns_rdataset_disassociate(&val->fsigrdataset);
1142
1143 if (check_deadlock(val, name, type, NULL, NULL)) {
1144 validator_log(val, ISC_LOG_DEBUG(3),
1145 "deadlock found (create_fetch)");
1146 return (DNS_R_NOVALIDSIG);
1147 }
1148
1149 if ((val->options & DNS_VALIDATOR_NOCDFLAG) != 0)
1150 fopts |= DNS_FETCHOPT_NOCDFLAG;
1151
1152 if ((val->options & DNS_VALIDATOR_NONTA) != 0)
1153 fopts |= DNS_FETCHOPT_NONTA;
1154
1155 validator_logcreate(val, name, type, caller, "fetch");
1156 return (dns_resolver_createfetch(val->view->resolver, name, type,
1157 NULL, NULL, NULL, fopts,
1158 val->event->ev_sender,
1159 callback, val,
1160 &val->frdataset,
1161 &val->fsigrdataset,
1162 &val->fetch));
1163 }
1164
1165 /*%
1166 * Start a subvalidation process.
1167 */
1168 static inline isc_result_t
1169 create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
1170 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
1171 isc_taskaction_t action, const char *caller)
1172 {
1173 isc_result_t result;
1174 unsigned int vopts = 0;
1175
1176 if (check_deadlock(val, name, type, rdataset, sigrdataset)) {
1177 validator_log(val, ISC_LOG_DEBUG(3),
1178 "deadlock found (create_validator)");
1179 return (DNS_R_NOVALIDSIG);
1180 }
1181
1182 /* OK to clear other options, but preserve NOCDFLAG and NONTA. */
1183 vopts |= (val->options & (DNS_VALIDATOR_NOCDFLAG|DNS_VALIDATOR_NONTA));
1184
1185 validator_logcreate(val, name, type, caller, "validator");
1186 result = dns_validator_create(val->view, name, type,
1187 rdataset, sigrdataset, NULL, vopts,
1188 val->task, action, val,
1189 &val->subvalidator);
1190 if (result == ISC_R_SUCCESS) {
1191 val->subvalidator->parent = val;
1192 val->subvalidator->depth = val->depth + 1;
1193 }
1194 return (result);
1195 }
1196
1197 /*%
1198 * Try to find a key that could have signed 'siginfo' among those
1199 * in 'rdataset'. If found, build a dst_key_t for it and point
1200 * val->key at it.
1201 *
1202 * If val->key is non-NULL, this returns the next matching key.
1203 */
1204 static isc_result_t
1205 get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
1206 dns_rdataset_t *rdataset)
1207 {
1208 isc_result_t result;
1209 isc_buffer_t b;
1210 dns_rdata_t rdata = DNS_RDATA_INIT;
1211 dst_key_t *oldkey = val->key;
1212 isc_boolean_t foundold;
1213
1214 if (oldkey == NULL)
1215 foundold = ISC_TRUE;
1216 else {
1217 foundold = ISC_FALSE;
1218 val->key = NULL;
1219 }
1220
1221 result = dns_rdataset_first(rdataset);
1222 if (result != ISC_R_SUCCESS)
1223 goto failure;
1224 do {
1225 dns_rdataset_current(rdataset, &rdata);
1226
1227 isc_buffer_init(&b, rdata.data, rdata.length);
1228 isc_buffer_add(&b, rdata.length);
1229 INSIST(val->key == NULL);
1230 result = dst_key_fromdns(&siginfo->signer, rdata.rdclass, &b,
1231 val->view->mctx, &val->key);
1232 if (result != ISC_R_SUCCESS)
1233 goto failure;
1234 if (siginfo->algorithm ==
1235 (dns_secalg_t)dst_key_alg(val->key) &&
1236 siginfo->keyid ==
1237 (dns_keytag_t)dst_key_id(val->key) &&
1238 dst_key_iszonekey(val->key))
1239 {
1240 if (foundold)
1241 /*
1242 * This is the key we're looking for.
1243 */
1244 return (ISC_R_SUCCESS);
1245 else if (dst_key_compare(oldkey, val->key) == ISC_TRUE)
1246 {
1247 foundold = ISC_TRUE;
1248 dst_key_free(&oldkey);
1249 }
1250 }
1251 dst_key_free(&val->key);
1252 dns_rdata_reset(&rdata);
1253 result = dns_rdataset_next(rdataset);
1254 } while (result == ISC_R_SUCCESS);
1255 if (result == ISC_R_NOMORE)
1256 result = ISC_R_NOTFOUND;
1257
1258 failure:
1259 if (oldkey != NULL)
1260 dst_key_free(&oldkey);
1261
1262 return (result);
1263 }
1264
1265 /*%
1266 * Get the key that generated this signature.
1267 */
1268 static isc_result_t
1269 get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
1270 isc_result_t result;
1271 unsigned int nlabels;
1272 int order;
1273 dns_namereln_t namereln;
1274
1275 /*
1276 * Is the signer name appropriate for this signature?
1277 *
1278 * The signer name must be at the same level as the owner name
1279 * or closer to the DNS root.
1280 */
1281 namereln = dns_name_fullcompare(val->event->name, &siginfo->signer,
1282 &order, &nlabels);
1283 if (namereln != dns_namereln_subdomain &&
1284 namereln != dns_namereln_equal)
1285 return (DNS_R_CONTINUE);
1286
1287 if (namereln == dns_namereln_equal) {
1288 /*
1289 * If this is a self-signed keyset, it must not be a zone key
1290 * (since get_key is not called from validatezonekey).
1291 */
1292 if (val->event->rdataset->type == dns_rdatatype_dnskey)
1293 return (DNS_R_CONTINUE);
1294
1295 /*
1296 * Records appearing in the parent zone at delegation
1297 * points cannot be self-signed.
1298 */
1299 if (dns_rdatatype_atparent(val->event->rdataset->type))
1300 return (DNS_R_CONTINUE);
1301 } else {
1302 /*
1303 * SOA and NS RRsets can only be signed by a key with
1304 * the same name.
1305 */
1306 if (val->event->rdataset->type == dns_rdatatype_soa ||
1307 val->event->rdataset->type == dns_rdatatype_ns) {
1308 const char *typename;
1309
1310 if (val->event->rdataset->type == dns_rdatatype_soa)
1311 typename = "SOA";
1312 else
1313 typename = "NS";
1314 validator_log(val, ISC_LOG_DEBUG(3),
1315 "%s signer mismatch", typename);
1316 return (DNS_R_CONTINUE);
1317 }
1318 }
1319
1320 /*
1321 * Do we know about this key?
1322 */
1323 result = view_find(val, &siginfo->signer, dns_rdatatype_dnskey);
1324 if (result == ISC_R_SUCCESS) {
1325 /*
1326 * We have an rrset for the given keyname.
1327 */
1328 val->keyset = &val->frdataset;
1329 if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
1330 DNS_TRUST_ANSWER(val->frdataset.trust)) &&
1331 dns_rdataset_isassociated(&val->fsigrdataset))
1332 {
1333 /*
1334 * We know the key but haven't validated it yet or
1335 * we have a key of trust answer but a DS/DLV
1336 * record for the zone may have been added.
1337 */
1338 result = create_validator(val, &siginfo->signer,
1339 dns_rdatatype_dnskey,
1340 &val->frdataset,
1341 &val->fsigrdataset,
1342 keyvalidated,
1343 "get_key");
1344 if (result != ISC_R_SUCCESS)
1345 return (result);
1346 return (DNS_R_WAIT);
1347 } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
1348 /*
1349 * Having a pending key with no signature means that
1350 * something is broken.
1351 */
1352 result = DNS_R_CONTINUE;
1353 } else if (val->frdataset.trust < dns_trust_secure) {
1354 /*
1355 * The key is legitimately insecure. There's no
1356 * point in even attempting verification.
1357 */
1358 val->key = NULL;
1359 result = ISC_R_SUCCESS;
1360 } else {
1361 /*
1362 * See if we've got the key used in the signature.
1363 */
1364 validator_log(val, ISC_LOG_DEBUG(3),
1365 "keyset with trust %s",
1366 dns_trust_totext(val->frdataset.trust));
1367 result = get_dst_key(val, siginfo, val->keyset);
1368 if (result != ISC_R_SUCCESS) {
1369 /*
1370 * Either the key we're looking for is not
1371 * in the rrset, or something bad happened.
1372 * Give up.
1373 */
1374 result = DNS_R_CONTINUE;
1375 }
1376 }
1377 } else if (result == ISC_R_NOTFOUND) {
1378 /*
1379 * We don't know anything about this key.
1380 */
1381 result = create_fetch(val, &siginfo->signer,
1382 dns_rdatatype_dnskey,
1383 fetch_callback_validator, "get_key");
1384 if (result != ISC_R_SUCCESS)
1385 return (result);
1386 return (DNS_R_WAIT);
1387 } else if (result == DNS_R_NCACHENXDOMAIN ||
1388 result == DNS_R_NCACHENXRRSET ||
1389 result == DNS_R_EMPTYNAME ||
1390 result == DNS_R_NXDOMAIN ||
1391 result == DNS_R_NXRRSET)
1392 {
1393 /*
1394 * This key doesn't exist.
1395 */
1396 result = DNS_R_CONTINUE;
1397 } else if (result == DNS_R_BROKENCHAIN)
1398 return (result);
1399
1400 if (dns_rdataset_isassociated(&val->frdataset) &&
1401 val->keyset != &val->frdataset)
1402 dns_rdataset_disassociate(&val->frdataset);
1403 if (dns_rdataset_isassociated(&val->fsigrdataset))
1404 dns_rdataset_disassociate(&val->fsigrdataset);
1405
1406 return (result);
1407 }
1408
1409 static dns_keytag_t
1410 compute_keytag(dns_rdata_t *rdata, dns_rdata_dnskey_t *key) {
1411 isc_region_t r;
1412
1413 dns_rdata_toregion(rdata, &r);
1414 return (dst_region_computeid(&r, key->algorithm));
1415 }
1416
1417 /*%
1418 * Is this keyset self-signed?
1419 */
1420 static isc_boolean_t
1421 isselfsigned(dns_validator_t *val) {
1422 dns_rdataset_t *rdataset, *sigrdataset;
1423 dns_rdata_t rdata = DNS_RDATA_INIT;
1424 dns_rdata_t sigrdata = DNS_RDATA_INIT;
1425 dns_rdata_dnskey_t key;
1426 dns_rdata_rrsig_t sig;
1427 dns_keytag_t keytag;
1428 dns_name_t *name;
1429 isc_result_t result;
1430 dst_key_t *dstkey;
1431 isc_mem_t *mctx;
1432 isc_boolean_t answer = ISC_FALSE;
1433
1434 rdataset = val->event->rdataset;
1435 sigrdataset = val->event->sigrdataset;
1436 name = val->event->name;
1437 mctx = val->view->mctx;
1438
1439 if (rdataset->type == dns_rdatatype_cname ||
1440 rdataset->type == dns_rdatatype_dname)
1441 return (answer);
1442
1443 INSIST(rdataset->type == dns_rdatatype_dnskey);
1444
1445 for (result = dns_rdataset_first(rdataset);
1446 result == ISC_R_SUCCESS;
1447 result = dns_rdataset_next(rdataset))
1448 {
1449 dns_rdata_reset(&rdata);
1450 dns_rdataset_current(rdataset, &rdata);
1451 result = dns_rdata_tostruct(&rdata, &key, NULL);
1452 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1453 keytag = compute_keytag(&rdata, &key);
1454 for (result = dns_rdataset_first(sigrdataset);
1455 result == ISC_R_SUCCESS;
1456 result = dns_rdataset_next(sigrdataset))
1457 {
1458 dns_rdata_reset(&sigrdata);
1459 dns_rdataset_current(sigrdataset, &sigrdata);
1460 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
1461 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1462
1463 if (sig.algorithm != key.algorithm ||
1464 sig.keyid != keytag ||
1465 !dns_name_equal(name, &sig.signer))
1466 continue;
1467
1468 dstkey = NULL;
1469 result = dns_dnssec_keyfromrdata(name, &rdata, mctx,
1470 &dstkey);
1471 if (result != ISC_R_SUCCESS)
1472 continue;
1473
1474 result = dns_dnssec_verify3(name, rdataset, dstkey,
1475 ISC_TRUE,
1476 val->view->maxbits,
1477 mctx, &sigrdata, NULL);
1478 dst_key_free(&dstkey);
1479 if (result != ISC_R_SUCCESS)
1480 continue;
1481 if ((key.flags & DNS_KEYFLAG_REVOKE) == 0) {
1482 answer = ISC_TRUE;
1483 continue;
1484 }
1485 dns_view_untrust(val->view, name, &key, mctx);
1486 }
1487 }
1488 return (answer);
1489 }
1490
1491 /*%
1492 * Attempt to verify the rdataset using the given key and rdata (RRSIG).
1493 * The signature was good and from a wildcard record and the QNAME does
1494 * not match the wildcard we need to look for a NOQNAME proof.
1495 *
1496 * Returns:
1497 * \li ISC_R_SUCCESS if the verification succeeds.
1498 * \li Others if the verification fails.
1499 */
1500 static isc_result_t
1501 verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata,
1502 isc_uint16_t keyid)
1503 {
1504 isc_result_t result;
1505 dns_fixedname_t fixed;
1506 isc_boolean_t ignore = ISC_FALSE;
1507 dns_name_t *wild;
1508
1509 val->attributes |= VALATTR_TRIEDVERIFY;
1510 wild = dns_fixedname_initname(&fixed);
1511 again:
1512 result = dns_dnssec_verify3(val->event->name, val->event->rdataset,
1513 key, ignore, val->view->maxbits,
1514 val->view->mctx, rdata, wild);
1515 if ((result == DNS_R_SIGEXPIRED || result == DNS_R_SIGFUTURE) &&
1516 val->view->acceptexpired)
1517 {
1518 ignore = ISC_TRUE;
1519 goto again;
1520 }
1521 if (ignore && (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD))
1522 validator_log(val, ISC_LOG_INFO,
1523 "accepted expired %sRRSIG (keyid=%u)",
1524 (result == DNS_R_FROMWILDCARD) ?
1525 "wildcard " : "", keyid);
1526 else if (result == DNS_R_SIGEXPIRED || result == DNS_R_SIGFUTURE)
1527 validator_log(val, ISC_LOG_INFO,
1528 "verify failed due to bad signature (keyid=%u): "
1529 "%s", keyid, isc_result_totext(result));
1530 else
1531 validator_log(val, ISC_LOG_DEBUG(3),
1532 "verify rdataset (keyid=%u): %s",
1533 keyid, isc_result_totext(result));
1534 if (result == DNS_R_FROMWILDCARD) {
1535 if (!dns_name_equal(val->event->name, wild)) {
1536 dns_name_t *closest;
1537 unsigned int labels;
1538
1539 /*
1540 * Compute the closest encloser in case we need it
1541 * for the NSEC3 NOQNAME proof.
1542 */
1543 closest = dns_fixedname_name(&val->closest);
1544 dns_name_copy(wild, closest, NULL);
1545 labels = dns_name_countlabels(closest) - 1;
1546 dns_name_getlabelsequence(closest, 1, labels, closest);
1547 val->attributes |= VALATTR_NEEDNOQNAME;
1548 }
1549 result = ISC_R_SUCCESS;
1550 }
1551 return (result);
1552 }
1553
1554 /*%
1555 * Attempts positive response validation of a normal RRset.
1556 *
1557 * Returns:
1558 * \li ISC_R_SUCCESS Validation completed successfully
1559 * \li DNS_R_WAIT Validation has started but is waiting
1560 * for an event.
1561 * \li Other return codes are possible and all indicate failure.
1562 */
1563 static isc_result_t
1564 validate(dns_validator_t *val, isc_boolean_t resume) {
1565 isc_result_t result, vresult = DNS_R_NOVALIDSIG;
1566 dns_validatorevent_t *event;
1567 dns_rdata_t rdata = DNS_RDATA_INIT;
1568
1569 /*
1570 * Caller must be holding the validator lock.
1571 */
1572
1573 event = val->event;
1574
1575 if (resume) {
1576 /*
1577 * We already have a sigrdataset.
1578 */
1579 result = ISC_R_SUCCESS;
1580 validator_log(val, ISC_LOG_DEBUG(3), "resuming validate");
1581 } else {
1582 result = dns_rdataset_first(event->sigrdataset);
1583 }
1584
1585 for (;
1586 result == ISC_R_SUCCESS;
1587 result = dns_rdataset_next(event->sigrdataset))
1588 {
1589 dns_rdata_reset(&rdata);
1590 dns_rdataset_current(event->sigrdataset, &rdata);
1591 if (val->siginfo == NULL) {
1592 val->siginfo = isc_mem_get(val->view->mctx,
1593 sizeof(*val->siginfo));
1594 if (val->siginfo == NULL)
1595 return (ISC_R_NOMEMORY);
1596 }
1597 result = dns_rdata_tostruct(&rdata, val->siginfo, NULL);
1598 if (result != ISC_R_SUCCESS)
1599 return (result);
1600
1601 /*
1602 * At this point we could check that the signature algorithm
1603 * was known and "sufficiently good".
1604 */
1605 if (!dns_resolver_algorithm_supported(val->view->resolver,
1606 event->name,
1607 val->siginfo->algorithm)) {
1608 resume = ISC_FALSE;
1609 continue;
1610 }
1611
1612 if (!resume) {
1613 result = get_key(val, val->siginfo);
1614 if (result == DNS_R_CONTINUE)
1615 continue; /* Try the next SIG RR. */
1616 if (result != ISC_R_SUCCESS)
1617 return (result);
1618 }
1619
1620 /*
1621 * There isn't a secure DNSKEY for this signature so move
1622 * onto the next RRSIG.
1623 */
1624 if (val->key == NULL) {
1625 resume = ISC_FALSE;
1626 continue;
1627 }
1628
1629 do {
1630 vresult = verify(val, val->key, &rdata,
1631 val->siginfo->keyid);
1632 if (vresult == ISC_R_SUCCESS)
1633 break;
1634 if (val->keynode != NULL) {
1635 dns_keynode_t *nextnode = NULL;
1636 result = dns_keytable_findnextkeynode(
1637 val->keytable,
1638 val->keynode,
1639 &nextnode);
1640 dns_keytable_detachkeynode(val->keytable,
1641 &val->keynode);
1642 val->keynode = nextnode;
1643 if (result != ISC_R_SUCCESS) {
1644 val->key = NULL;
1645 break;
1646 }
1647 val->key = dns_keynode_key(val->keynode);
1648 if (val->key == NULL)
1649 break;
1650 } else {
1651 if (get_dst_key(val, val->siginfo, val->keyset)
1652 != ISC_R_SUCCESS)
1653 break;
1654 }
1655 } while (1);
1656 if (vresult != ISC_R_SUCCESS)
1657 validator_log(val, ISC_LOG_DEBUG(3),
1658 "failed to verify rdataset");
1659 else {
1660 dns_rdataset_trimttl(event->rdataset,
1661 event->sigrdataset,
1662 val->siginfo, val->start,
1663 val->view->acceptexpired);
1664 }
1665
1666 if (val->keynode != NULL)
1667 dns_keytable_detachkeynode(val->keytable,
1668 &val->keynode);
1669 else {
1670 if (val->key != NULL)
1671 dst_key_free(&val->key);
1672 if (val->keyset != NULL) {
1673 dns_rdataset_disassociate(val->keyset);
1674 val->keyset = NULL;
1675 }
1676 }
1677 val->key = NULL;
1678 if (NEEDNOQNAME(val)) {
1679 if (val->event->message == NULL) {
1680 validator_log(val, ISC_LOG_DEBUG(3),
1681 "no message available for noqname proof");
1682 return (DNS_R_NOVALIDSIG);
1683 }
1684 validator_log(val, ISC_LOG_DEBUG(3),
1685 "looking for noqname proof");
1686 return (nsecvalidate(val, ISC_FALSE));
1687 } else if (vresult == ISC_R_SUCCESS) {
1688 marksecure(event);
1689 validator_log(val, ISC_LOG_DEBUG(3),
1690 "marking as secure, "
1691 "noqname proof not needed");
1692 return (ISC_R_SUCCESS);
1693 } else {
1694 validator_log(val, ISC_LOG_DEBUG(3),
1695 "verify failure: %s",
1696 isc_result_totext(result));
1697 resume = ISC_FALSE;
1698 }
1699 }
1700 if (result != ISC_R_NOMORE) {
1701 validator_log(val, ISC_LOG_DEBUG(3),
1702 "failed to iterate signatures: %s",
1703 isc_result_totext(result));
1704 return (result);
1705 }
1706
1707 validator_log(val, ISC_LOG_INFO, "no valid signature found");
1708 return (vresult);
1709 }
1710
1711 /*%
1712 * Check whether this DNSKEY (keyrdata) signed the DNSKEY RRset
1713 * (val->event->rdataset).
1714 */
1715 static isc_result_t
1716 checkkey(dns_validator_t *val, dns_rdata_t *keyrdata, isc_uint16_t keyid,
1717 dns_secalg_t algorithm)
1718 {
1719 dns_rdata_rrsig_t sig;
1720 dst_key_t *dstkey = NULL;
1721 isc_result_t result;
1722
1723 for (result = dns_rdataset_first(val->event->sigrdataset);
1724 result == ISC_R_SUCCESS;
1725 result = dns_rdataset_next(val->event->sigrdataset))
1726 {
1727 dns_rdata_t rdata = DNS_RDATA_INIT;
1728
1729 dns_rdataset_current(val->event->sigrdataset, &rdata);
1730 result = dns_rdata_tostruct(&rdata, &sig, NULL);
1731 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1732 if (keyid != sig.keyid || algorithm != sig.algorithm)
1733 continue;
1734 if (dstkey == NULL) {
1735 result = dns_dnssec_keyfromrdata(val->event->name,
1736 keyrdata,
1737 val->view->mctx,
1738 &dstkey);
1739 if (result != ISC_R_SUCCESS)
1740 /*
1741 * This really shouldn't happen, but...
1742 */
1743 continue;
1744 }
1745 result = verify(val, dstkey, &rdata, sig.keyid);
1746 if (result == ISC_R_SUCCESS)
1747 break;
1748 }
1749 if (dstkey != NULL)
1750 dst_key_free(&dstkey);
1751 return (result);
1752 }
1753
1754 /*%
1755 * Find the DNSKEY that corresponds to the DS.
1756 */
1757 static isc_result_t
1758 keyfromds(dns_validator_t *val, dns_rdataset_t *rdataset, dns_rdata_t *dsrdata,
1759 isc_uint8_t digest, isc_uint16_t keyid, dns_secalg_t algorithm,
1760 dns_rdata_t *keyrdata)
1761 {
1762 dns_keytag_t keytag;
1763 dns_rdata_dnskey_t key;
1764 isc_result_t result;
1765 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
1766
1767 for (result = dns_rdataset_first(rdataset);
1768 result == ISC_R_SUCCESS;
1769 result = dns_rdataset_next(rdataset))
1770 {
1771 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
1772
1773 dns_rdata_reset(keyrdata);
1774 dns_rdataset_current(rdataset, keyrdata);
1775 result = dns_rdata_tostruct(keyrdata, &key, NULL);
1776 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1777 keytag = compute_keytag(keyrdata, &key);
1778 if (keyid != keytag || algorithm != key.algorithm)
1779 continue;
1780 dns_rdata_reset(&newdsrdata);
1781 result = dns_ds_buildrdata(val->event->name, keyrdata, digest,
1782 dsbuf, &newdsrdata);
1783 if (result != ISC_R_SUCCESS) {
1784 validator_log(val, ISC_LOG_DEBUG(3),
1785 "dns_ds_buildrdata() -> %s",
1786 dns_result_totext(result));
1787 continue;
1788 }
1789 if (dns_rdata_compare(dsrdata, &newdsrdata) == 0)
1790 break;
1791 }
1792 return (result);
1793 }
1794
1795 /*%
1796 * Validate the DNSKEY RRset by looking for a DNSKEY that matches a
1797 * DLV record and that also verifies the DNSKEY RRset.
1798 */
1799 static isc_result_t
1800 dlv_validatezonekey(dns_validator_t *val) {
1801 dns_rdata_dlv_t dlv;
1802 dns_rdata_t dlvrdata = DNS_RDATA_INIT;
1803 dns_rdata_t keyrdata = DNS_RDATA_INIT;
1804 dns_rdataset_t trdataset;
1805 isc_boolean_t supported_algorithm;
1806 isc_result_t result;
1807 char digest_types[256];
1808
1809 validator_log(val, ISC_LOG_DEBUG(3), "dlv_validatezonekey");
1810
1811 /*
1812 * Look through the DLV record and find the keys that can sign the
1813 * key set and the matching signature. For each such key, attempt
1814 * verification.
1815 */
1816 supported_algorithm = ISC_FALSE;
1817
1818 /*
1819 * If DNS_DSDIGEST_SHA256 or DNS_DSDIGEST_SHA384 is present we
1820 * are required to prefer it over DNS_DSDIGEST_SHA1. This in
1821 * practice means that we need to ignore DNS_DSDIGEST_SHA1 if a
1822 * DNS_DSDIGEST_SHA256 or DNS_DSDIGEST_SHA384 is present.
1823 */
1824 memset(digest_types, 1, sizeof(digest_types));
1825 for (result = dns_rdataset_first(&val->dlv);
1826 result == ISC_R_SUCCESS;
1827 result = dns_rdataset_next(&val->dlv)) {
1828 dns_rdata_reset(&dlvrdata);
1829 dns_rdataset_current(&val->dlv, &dlvrdata);
1830 result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
1831 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1832
1833 if (!dns_resolver_ds_digest_supported(val->view->resolver,
1834 val->event->name,
1835 dlv.digest_type))
1836 continue;
1837
1838 if (!dns_resolver_algorithm_supported(val->view->resolver,
1839 val->event->name,
1840 dlv.algorithm))
1841 continue;
1842
1843 if ((dlv.digest_type == DNS_DSDIGEST_SHA256 &&
1844 dlv.length == ISC_SHA256_DIGESTLENGTH) ||
1845 (dlv.digest_type == DNS_DSDIGEST_SHA384 &&
1846 dlv.length == ISC_SHA384_DIGESTLENGTH))
1847 {
1848 digest_types[DNS_DSDIGEST_SHA1] = 0;
1849 break;
1850 }
1851 }
1852
1853 for (result = dns_rdataset_first(&val->dlv);
1854 result == ISC_R_SUCCESS;
1855 result = dns_rdataset_next(&val->dlv))
1856 {
1857 dns_rdata_reset(&dlvrdata);
1858 dns_rdataset_current(&val->dlv, &dlvrdata);
1859 result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
1860 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1861
1862 if (digest_types[dlv.digest_type] == 0)
1863 continue;
1864
1865 if (!dns_resolver_ds_digest_supported(val->view->resolver,
1866 val->event->name,
1867 dlv.digest_type))
1868 continue;
1869
1870 if (!dns_resolver_algorithm_supported(val->view->resolver,
1871 val->event->name,
1872 dlv.algorithm))
1873 continue;
1874
1875 supported_algorithm = ISC_TRUE;
1876
1877 dns_rdataset_init(&trdataset);
1878 dns_rdataset_clone(val->event->rdataset, &trdataset);
1879
1880 /*
1881 * Convert to DLV to DS and find matching DNSKEY.
1882 */
1883 dlvrdata.type = dns_rdatatype_ds;
1884 result = keyfromds(val, &trdataset, &dlvrdata,
1885 dlv.digest_type, dlv.key_tag,
1886 dlv.algorithm, &keyrdata);
1887 if (result != ISC_R_SUCCESS) {
1888 dns_rdataset_disassociate(&trdataset);
1889 validator_log(val, ISC_LOG_DEBUG(3),
1890 "no DNSKEY matching DLV");
1891 continue;
1892 }
1893
1894 validator_log(val, ISC_LOG_DEBUG(3),
1895 "Found matching DLV record: checking for signature");
1896 /*
1897 * Check that this DNSKEY signed the DNSKEY rrset.
1898 */
1899 result = checkkey(val, &keyrdata, dlv.key_tag, dlv.algorithm);
1900
1901 dns_rdataset_disassociate(&trdataset);
1902 if (result == ISC_R_SUCCESS)
1903 break;
1904 validator_log(val, ISC_LOG_DEBUG(3),
1905 "no RRSIG matching DLV key");
1906 }
1907 if (result == ISC_R_SUCCESS) {
1908 marksecure(val->event);
1909 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (dlv)");
1910 return (result);
1911 } else if (result == ISC_R_NOMORE && !supported_algorithm) {
1912 if (val->mustbesecure) {
1913 validator_log(val, ISC_LOG_WARNING,
1914 "must be secure failure,"
1915 "no supported algorithm/digest (dlv)");
1916 return (DNS_R_MUSTBESECURE);
1917 }
1918 validator_log(val, ISC_LOG_DEBUG(3),
1919 "no supported algorithm/digest (dlv)");
1920 markanswer(val, "dlv_validatezonekey (2)");
1921 return (ISC_R_SUCCESS);
1922 } else
1923 return (DNS_R_NOVALIDSIG);
1924 }
1925
1926 /*%
1927 * Attempts positive response validation of an RRset containing zone keys
1928 * (i.e. a DNSKEY rrset).
1929 *
1930 * Returns:
1931 * \li ISC_R_SUCCESS Validation completed successfully
1932 * \li DNS_R_WAIT Validation has started but is waiting
1933 * for an event.
1934 * \li Other return codes are possible and all indicate failure.
1935 */
1936 static isc_result_t
1937 validatezonekey(dns_validator_t *val) {
1938 isc_result_t result;
1939 dns_validatorevent_t *event;
1940 dns_rdataset_t trdataset;
1941 dns_rdata_t dsrdata = DNS_RDATA_INIT;
1942 dns_rdata_t keyrdata = DNS_RDATA_INIT;
1943 dns_rdata_t sigrdata = DNS_RDATA_INIT;
1944 char namebuf[DNS_NAME_FORMATSIZE];
1945 dns_rdata_ds_t ds;
1946 dns_rdata_rrsig_t sig;
1947 dst_key_t *dstkey;
1948 isc_boolean_t supported_algorithm;
1949 isc_boolean_t atsep = ISC_FALSE;
1950 char digest_types[256];
1951
1952 /*
1953 * Caller must be holding the validator lock.
1954 */
1955
1956 event = val->event;
1957
1958 if (val->havedlvsep && val->dlv.trust >= dns_trust_secure &&
1959 dns_name_equal(event->name, dns_fixedname_name(&val->dlvsep)))
1960 return (dlv_validatezonekey(val));
1961
1962 if (val->dsset == NULL) {
1963
1964 /*
1965 * We have a dlv sep. Skip looking up the SEP from
1966 * {trusted,managed}-keys. If the dlv sep is for the
1967 * root then it will have been handled above so we don't
1968 * need to check whether val->event->name is "." prior to
1969 * looking up the DS.
1970 */
1971 if (val->havedlvsep)
1972 goto find_ds;
1973
1974 /*
1975 * First, see if this key was signed by a trusted key.
1976 */
1977 for (result = dns_rdataset_first(val->event->sigrdataset);
1978 result == ISC_R_SUCCESS;
1979 result = dns_rdataset_next(val->event->sigrdataset))
1980 {
1981 dns_keynode_t *keynode = NULL;
1982 dns_fixedname_t fixed;
1983 dns_name_t *found;
1984
1985 found = dns_fixedname_initname(&fixed);
1986 dns_rdata_reset(&sigrdata);
1987 dns_rdataset_current(val->event->sigrdataset,
1988 &sigrdata);
1989 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
1990 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1991
1992 if (!dns_name_equal(val->event->name, &sig.signer))
1993 continue;
1994
1995 result = dns_keytable_findkeynode(val->keytable,
1996 val->event->name,
1997 sig.algorithm,
1998 sig.keyid, &keynode);
1999 if (result == ISC_R_NOTFOUND &&
2000 dns_keytable_finddeepestmatch(val->keytable,
2001 val->event->name, found) != ISC_R_SUCCESS) {
2002 if (val->mustbesecure) {
2003 validator_log(val, ISC_LOG_WARNING,
2004 "must be secure failure, "
2005 "not beneath secure root");
2006 return (DNS_R_MUSTBESECURE);
2007 } else
2008 validator_log(val, ISC_LOG_DEBUG(3),
2009 "not beneath secure root");
2010 if (val->view->dlv == NULL) {
2011 markanswer(val, "validatezonekey (1)");
2012 return (ISC_R_SUCCESS);
2013 }
2014 return (startfinddlvsep(val, dns_rootname));
2015 }
2016 if (result == DNS_R_PARTIALMATCH ||
2017 result == ISC_R_SUCCESS)
2018 atsep = ISC_TRUE;
2019 while (result == ISC_R_SUCCESS) {
2020 dns_keynode_t *nextnode = NULL;
2021 dstkey = dns_keynode_key(keynode);
2022 if (dstkey == NULL) {
2023 dns_keytable_detachkeynode(
2024 val->keytable,
2025 &keynode);
2026 break;
2027 }
2028 result = verify(val, dstkey, &sigrdata,
2029 sig.keyid);
2030 if (result == ISC_R_SUCCESS) {
2031 dns_keytable_detachkeynode(
2032 val->keytable,
2033 &keynode);
2034 break;
2035 }
2036 result = dns_keytable_findnextkeynode(
2037 val->keytable,
2038 keynode,
2039 &nextnode);
2040 dns_keytable_detachkeynode(val->keytable,
2041 &keynode);
2042 keynode = nextnode;
2043 }
2044 if (result == ISC_R_SUCCESS) {
2045 marksecure(event);
2046 validator_log(val, ISC_LOG_DEBUG(3),
2047 "signed by trusted key; "
2048 "marking as secure");
2049 return (result);
2050 }
2051 }
2052
2053 if (atsep) {
2054 /*
2055 * We have not found a key to verify this DNSKEY
2056 * RRset. As this is a SEP we have to assume that
2057 * the RRset is invalid.
2058 */
2059 dns_name_format(val->event->name, namebuf,
2060 sizeof(namebuf));
2061 validator_log(val, ISC_LOG_NOTICE,
2062 "unable to find a DNSKEY which verifies "
2063 "the DNSKEY RRset and also matches a "
2064 "trusted key for '%s'",
2065 namebuf);
2066 return (DNS_R_NOVALIDKEY);
2067 }
2068
2069 /*
2070 * If this is the root name and there was no trusted key,
2071 * give up, since there's no DS at the root.
2072 */
2073 if (dns_name_equal(event->name, dns_rootname)) {
2074 if ((val->attributes & VALATTR_TRIEDVERIFY) != 0) {
2075 validator_log(val, ISC_LOG_DEBUG(3),
2076 "root key failed to validate");
2077 return (DNS_R_NOVALIDSIG);
2078 } else {
2079 validator_log(val, ISC_LOG_DEBUG(3),
2080 "no trusted root key");
2081 return (DNS_R_NOVALIDDS);
2082 }
2083 }
2084 find_ds:
2085 /*
2086 * Otherwise, try to find the DS record.
2087 */
2088 result = view_find(val, val->event->name, dns_rdatatype_ds);
2089 if (result == ISC_R_SUCCESS) {
2090 /*
2091 * We have DS records.
2092 */
2093 val->dsset = &val->frdataset;
2094 if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
2095 DNS_TRUST_ANSWER(val->frdataset.trust)) &&
2096 dns_rdataset_isassociated(&val->fsigrdataset))
2097 {
2098 result = create_validator(val,
2099 val->event->name,
2100 dns_rdatatype_ds,
2101 &val->frdataset,
2102 &val->fsigrdataset,
2103 dsvalidated,
2104 "validatezonekey");
2105 if (result != ISC_R_SUCCESS)
2106 return (result);
2107 return (DNS_R_WAIT);
2108 } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
2109 /*
2110 * There should never be an unsigned DS.
2111 */
2112 dns_rdataset_disassociate(&val->frdataset);
2113 validator_log(val, ISC_LOG_DEBUG(2),
2114 "unsigned DS record");
2115 return (DNS_R_NOVALIDSIG);
2116 } else {
2117 result = ISC_R_SUCCESS;
2118 POST(result);
2119 }
2120 } else if (result == ISC_R_NOTFOUND) {
2121 /*
2122 * We don't have the DS. Find it.
2123 */
2124 result = create_fetch(val, val->event->name,
2125 dns_rdatatype_ds, dsfetched,
2126 "validatezonekey");
2127 if (result != ISC_R_SUCCESS)
2128 return (result);
2129 return (DNS_R_WAIT);
2130 } else if (result == DNS_R_NCACHENXDOMAIN ||
2131 result == DNS_R_NCACHENXRRSET ||
2132 result == DNS_R_EMPTYNAME ||
2133 result == DNS_R_NXDOMAIN ||
2134 result == DNS_R_NXRRSET ||
2135 result == DNS_R_CNAME)
2136 {
2137 /*
2138 * The DS does not exist.
2139 */
2140 if (dns_rdataset_isassociated(&val->frdataset))
2141 dns_rdataset_disassociate(&val->frdataset);
2142 if (dns_rdataset_isassociated(&val->fsigrdataset))
2143 dns_rdataset_disassociate(&val->fsigrdataset);
2144 validator_log(val, ISC_LOG_DEBUG(2), "no DS record");
2145 return (DNS_R_NOVALIDSIG);
2146 } else if (result == DNS_R_BROKENCHAIN)
2147 return (result);
2148 }
2149
2150 /*
2151 * We have a DS set.
2152 */
2153 INSIST(val->dsset != NULL);
2154
2155 if (val->dsset->trust < dns_trust_secure) {
2156 if (val->mustbesecure) {
2157 validator_log(val, ISC_LOG_WARNING,
2158 "must be secure failure,"
2159 " insecure DS");
2160 return (DNS_R_MUSTBESECURE);
2161 }
2162 if (val->view->dlv == NULL || DLVTRIED(val)) {
2163 markanswer(val, "validatezonekey (2)");
2164 return (ISC_R_SUCCESS);
2165 }
2166 return (startfinddlvsep(val, val->event->name));
2167 }
2168
2169 /*
2170 * Look through the DS record and find the keys that can sign the
2171 * key set and the matching signature. For each such key, attempt
2172 * verification.
2173 */
2174
2175 supported_algorithm = ISC_FALSE;
2176
2177 /*
2178 * If DNS_DSDIGEST_SHA256 or DNS_DSDIGEST_SHA384 is present we
2179 * are required to prefer it over DNS_DSDIGEST_SHA1. This in
2180 * practice means that we need to ignore DNS_DSDIGEST_SHA1 if a
2181 * DNS_DSDIGEST_SHA256 or DNS_DSDIGEST_SHA384 is present.
2182 */
2183 memset(digest_types, 1, sizeof(digest_types));
2184 for (result = dns_rdataset_first(val->dsset);
2185 result == ISC_R_SUCCESS;
2186 result = dns_rdataset_next(val->dsset)) {
2187 dns_rdata_reset(&dsrdata);
2188 dns_rdataset_current(val->dsset, &dsrdata);
2189 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
2190 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2191
2192 if (!dns_resolver_ds_digest_supported(val->view->resolver,
2193 val->event->name,
2194 ds.digest_type))
2195 continue;
2196
2197 if (!dns_resolver_algorithm_supported(val->view->resolver,
2198 val->event->name,
2199 ds.algorithm))
2200 continue;
2201
2202 if ((ds.digest_type == DNS_DSDIGEST_SHA256 &&
2203 ds.length == ISC_SHA256_DIGESTLENGTH) ||
2204 (ds.digest_type == DNS_DSDIGEST_SHA384 &&
2205 ds.length == ISC_SHA384_DIGESTLENGTH))
2206 {
2207 digest_types[DNS_DSDIGEST_SHA1] = 0;
2208 break;
2209 }
2210 }
2211
2212 for (result = dns_rdataset_first(val->dsset);
2213 result == ISC_R_SUCCESS;
2214 result = dns_rdataset_next(val->dsset))
2215 {
2216 dns_rdata_reset(&dsrdata);
2217 dns_rdataset_current(val->dsset, &dsrdata);
2218 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
2219 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2220
2221 if (digest_types[ds.digest_type] == 0)
2222 continue;
2223
2224 if (!dns_resolver_ds_digest_supported(val->view->resolver,
2225 val->event->name,
2226 ds.digest_type))
2227 continue;
2228
2229 if (!dns_resolver_algorithm_supported(val->view->resolver,
2230 val->event->name,
2231 ds.algorithm))
2232 continue;
2233
2234 supported_algorithm = ISC_TRUE;
2235
2236 dns_rdataset_init(&trdataset);
2237 dns_rdataset_clone(val->event->rdataset, &trdataset);
2238
2239 /*
2240 * Find matching DNSKEY from DS.
2241 */
2242 result = keyfromds(val, &trdataset, &dsrdata, ds.digest_type,
2243 ds.key_tag, ds.algorithm, &keyrdata);
2244 if (result != ISC_R_SUCCESS) {
2245 dns_rdataset_disassociate(&trdataset);
2246 validator_log(val, ISC_LOG_DEBUG(3),
2247 "no DNSKEY matching DS");
2248 continue;
2249 }
2250
2251 /*
2252 * Check that this DNSKEY signed the DNSKEY rrset.
2253 */
2254 result = checkkey(val, &keyrdata, ds.key_tag, ds.algorithm);
2255
2256 dns_rdataset_disassociate(&trdataset);
2257 if (result == ISC_R_SUCCESS)
2258 break;
2259 validator_log(val, ISC_LOG_DEBUG(3),
2260 "no RRSIG matching DS key");
2261 }
2262 if (result == ISC_R_SUCCESS) {
2263 marksecure(event);
2264 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (DS)");
2265 return (result);
2266 } else if (result == ISC_R_NOMORE && !supported_algorithm) {
2267 if (val->mustbesecure) {
2268 validator_log(val, ISC_LOG_WARNING,
2269 "must be secure failure, "
2270 "no supported algorithm/digest (DS)");
2271 return (DNS_R_MUSTBESECURE);
2272 }
2273 validator_log(val, ISC_LOG_DEBUG(3),
2274 "no supported algorithm/digest (DS)");
2275 markanswer(val, "validatezonekey (3)");
2276 return (ISC_R_SUCCESS);
2277 } else {
2278 validator_log(val, ISC_LOG_INFO,
2279 "no valid signature found (DS)");
2280 return (DNS_R_NOVALIDSIG);
2281 }
2282 }
2283
2284 /*%
2285 * Starts a positive response validation.
2286 *
2287 * Returns:
2288 * \li ISC_R_SUCCESS Validation completed successfully
2289 * \li DNS_R_WAIT Validation has started but is waiting
2290 * for an event.
2291 * \li Other return codes are possible and all indicate failure.
2292 */
2293 static isc_result_t
2294 start_positive_validation(dns_validator_t *val) {
2295 /*
2296 * If this is not a key, go straight into validate().
2297 */
2298 if (val->event->type != dns_rdatatype_dnskey || !isselfsigned(val))
2299 return (validate(val, ISC_FALSE));
2300
2301 return (validatezonekey(val));
2302 }
2303
2304 /*%
2305 * val_rdataset_first and val_rdataset_next provide iteration methods
2306 * that hide whether we are iterating across a message or a negative
2307 * cache rdataset.
2308 */
2309 static isc_result_t
2310 val_rdataset_first(dns_validator_t *val, dns_name_t **namep,
2311 dns_rdataset_t **rdatasetp)
2312 {
2313 dns_message_t *message = val->event->message;
2314 isc_result_t result;
2315
2316 REQUIRE(rdatasetp != NULL);
2317 REQUIRE(namep != NULL);
2318 if (message == NULL) {
2319 REQUIRE(*rdatasetp != NULL);
2320 REQUIRE(*namep != NULL);
2321 } else {
2322 REQUIRE(*rdatasetp == NULL);
2323 REQUIRE(*namep == NULL);
2324 }
2325
2326 if (message != NULL) {
2327 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2328 if (result != ISC_R_SUCCESS)
2329 return (result);
2330 dns_message_currentname(message, DNS_SECTION_AUTHORITY, namep);
2331 *rdatasetp = ISC_LIST_HEAD((*namep)->list);
2332 INSIST(*rdatasetp != NULL);
2333 } else {
2334 result = dns_rdataset_first(val->event->rdataset);
2335 if (result == ISC_R_SUCCESS)
2336 dns_ncache_current(val->event->rdataset, *namep,
2337 *rdatasetp);
2338 }
2339 return (result);
2340 }
2341
2342 static isc_result_t
2343 val_rdataset_next(dns_validator_t *val, dns_name_t **namep,
2344 dns_rdataset_t **rdatasetp)
2345 {
2346 dns_message_t *message = val->event->message;
2347 isc_result_t result = ISC_R_SUCCESS;
2348
2349 REQUIRE(rdatasetp != NULL && *rdatasetp != NULL);
2350 REQUIRE(namep != NULL && *namep != NULL);
2351
2352 if (message != NULL) {
2353 dns_rdataset_t *rdataset = *rdatasetp;
2354 rdataset = ISC_LIST_NEXT(rdataset, link);
2355 if (rdataset == NULL) {
2356 *namep = NULL;
2357 result = dns_message_nextname(message,
2358 DNS_SECTION_AUTHORITY);
2359 if (result == ISC_R_SUCCESS) {
2360 dns_message_currentname(message,
2361 DNS_SECTION_AUTHORITY,
2362 namep);
2363 rdataset = ISC_LIST_HEAD((*namep)->list);
2364 INSIST(rdataset != NULL);
2365 }
2366 }
2367 *rdatasetp = rdataset;
2368 } else {
2369 dns_rdataset_disassociate(*rdatasetp);
2370 result = dns_rdataset_next(val->event->rdataset);
2371 if (result == ISC_R_SUCCESS)
2372 dns_ncache_current(val->event->rdataset, *namep,
2373 *rdatasetp);
2374 }
2375 return (result);
2376 }
2377
2378 /*%
2379 * Look for NODATA at the wildcard and NOWILDCARD proofs in the
2380 * previously validated NSEC records. As these proofs are mutually
2381 * exclusive we stop when one is found.
2382 *
2383 * Returns
2384 * \li ISC_R_SUCCESS
2385 */
2386 static isc_result_t
2387 checkwildcard(dns_validator_t *val, dns_rdatatype_t type, dns_name_t *zonename)
2388 {
2389 dns_name_t *name, *wild, tname;
2390 isc_result_t result;
2391 isc_boolean_t exists, data;
2392 char namebuf[DNS_NAME_FORMATSIZE];
2393 dns_rdataset_t *rdataset, trdataset;
2394
2395 dns_name_init(&tname, NULL);
2396 dns_rdataset_init(&trdataset);
2397 wild = dns_fixedname_name(&val->wild);
2398
2399 if (dns_name_countlabels(wild) == 0) {
2400 validator_log(val, ISC_LOG_DEBUG(3),
2401 "in checkwildcard: no wildcard to check");
2402 return (ISC_R_SUCCESS);
2403 }
2404
2405 dns_name_format(wild, namebuf, sizeof(namebuf));
2406 validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf);
2407
2408 if (val->event->message == NULL) {
2409 name = &tname;
2410 rdataset = &trdataset;
2411 } else {
2412 name = NULL;
2413 rdataset = NULL;
2414 }
2415
2416 for (result = val_rdataset_first(val, &name, &rdataset);
2417 result == ISC_R_SUCCESS;
2418 result = val_rdataset_next(val, &name, &rdataset))
2419 {
2420 if (rdataset->type != type ||
2421 rdataset->trust != dns_trust_secure)
2422 continue;
2423
2424 if (rdataset->type == dns_rdatatype_nsec &&
2425 (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
2426 !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
2427 dns_nsec_noexistnodata(val->event->type, wild, name,
2428 rdataset, &exists, &data, NULL,
2429 validator_log, val)
2430 == ISC_R_SUCCESS)
2431 {
2432 dns_name_t **proofs = val->event->proofs;
2433 if (exists && !data)
2434 val->attributes |= VALATTR_FOUNDNODATA;
2435 if (exists && !data && NEEDNODATA(val))
2436 proofs[DNS_VALIDATOR_NODATAPROOF] =
2437 name;
2438 if (!exists)
2439 val->attributes |=
2440 VALATTR_FOUNDNOWILDCARD;
2441 if (!exists && NEEDNOQNAME(val))
2442 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
2443 name;
2444 if (dns_rdataset_isassociated(&trdataset))
2445 dns_rdataset_disassociate(&trdataset);
2446 return (ISC_R_SUCCESS);
2447 }
2448
2449 if (rdataset->type == dns_rdatatype_nsec3 &&
2450 (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
2451 !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
2452 dns_nsec3_noexistnodata(val->event->type, wild, name,
2453 rdataset, zonename, &exists, &data,
2454 NULL, NULL, NULL, NULL, NULL, NULL,
2455 validator_log, val)
2456 == ISC_R_SUCCESS)
2457 {
2458 dns_name_t **proofs = val->event->proofs;
2459 if (exists && !data)
2460 val->attributes |= VALATTR_FOUNDNODATA;
2461 if (exists && !data && NEEDNODATA(val))
2462 proofs[DNS_VALIDATOR_NODATAPROOF] =
2463 name;
2464 if (!exists)
2465 val->attributes |=
2466 VALATTR_FOUNDNOWILDCARD;
2467 if (!exists && NEEDNOQNAME(val))
2468 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
2469 name;
2470 if (dns_rdataset_isassociated(&trdataset))
2471 dns_rdataset_disassociate(&trdataset);
2472 return (ISC_R_SUCCESS);
2473 }
2474 }
2475 if (result == ISC_R_NOMORE)
2476 result = ISC_R_SUCCESS;
2477 if (dns_rdataset_isassociated(&trdataset))
2478 dns_rdataset_disassociate(&trdataset);
2479 return (result);
2480 }
2481
2482 static isc_result_t
2483 findnsec3proofs(dns_validator_t *val) {
2484 dns_name_t *name, tname;
2485 isc_result_t result;
2486 isc_boolean_t exists, data, optout, unknown;
2487 isc_boolean_t setclosest, setnearest, *setclosestp;
2488 dns_fixedname_t fclosest, fnearest, fzonename;
2489 dns_name_t *closest, *nearest, *zonename, *closestp;
2490 dns_name_t **proofs = val->event->proofs;
2491 dns_rdataset_t *rdataset, trdataset;
2492
2493 dns_name_init(&tname, NULL);
2494 dns_rdataset_init(&trdataset);
2495 closest = dns_fixedname_initname(&fclosest);
2496 nearest = dns_fixedname_initname(&fnearest);
2497 zonename = dns_fixedname_initname(&fzonename);
2498
2499 if (val->event->message == NULL) {
2500 name = &tname;
2501 rdataset = &trdataset;
2502 } else {
2503 name = NULL;
2504 rdataset = NULL;
2505 }
2506
2507 for (result = val_rdataset_first(val, &name, &rdataset);
2508 result == ISC_R_SUCCESS;
2509 result = val_rdataset_next(val, &name, &rdataset))
2510 {
2511 if (rdataset->type != dns_rdatatype_nsec3 ||
2512 rdataset->trust != dns_trust_secure)
2513 continue;
2514
2515 result = dns_nsec3_noexistnodata(val->event->type,
2516 val->event->name, name,
2517 rdataset, zonename, NULL,
2518 NULL, NULL, NULL, NULL, NULL,
2519 NULL, NULL, validator_log,
2520 val);
2521 if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS) {
2522 if (dns_rdataset_isassociated(&trdataset))
2523 dns_rdataset_disassociate(&trdataset);
2524 return (result);
2525 }
2526 }
2527 if (result != ISC_R_NOMORE)
2528 result = ISC_R_SUCCESS;
2529 POST(result);
2530
2531 if (dns_name_countlabels(zonename) == 0)
2532 return (ISC_R_SUCCESS);
2533
2534 /*
2535 * If the val->closest is set then we want to use it otherwise
2536 * we need to discover it.
2537 */
2538 if (dns_name_countlabels(dns_fixedname_name(&val->closest)) != 0) {
2539 char namebuf[DNS_NAME_FORMATSIZE];
2540
2541 dns_name_format(dns_fixedname_name(&val->closest),
2542 namebuf, sizeof(namebuf));
2543 validator_log(val, ISC_LOG_DEBUG(3), "closest encloser from "
2544 "wildcard signature '%s'", namebuf);
2545 dns_name_copy(dns_fixedname_name(&val->closest), closest, NULL);
2546 closestp = NULL;
2547 setclosestp = NULL;
2548 } else {
2549 closestp = closest;
2550 setclosestp = &setclosest;
2551 }
2552
2553 for (result = val_rdataset_first(val, &name, &rdataset);
2554 result == ISC_R_SUCCESS;
2555 result = val_rdataset_next(val, &name, &rdataset))
2556 {
2557 if (rdataset->type != dns_rdatatype_nsec3 ||
2558 rdataset->trust != dns_trust_secure)
2559 continue;
2560
2561 /*
2562 * We process all NSEC3 records to find the closest
2563 * encloser and nearest name to the closest encloser.
2564 */
2565 setclosest = setnearest = ISC_FALSE;
2566 optout = ISC_FALSE;
2567 unknown = ISC_FALSE;
2568 result = dns_nsec3_noexistnodata(val->event->type,
2569 val->event->name,
2570 name, rdataset, zonename,
2571 &exists, &data, &optout,
2572 &unknown, setclosestp,
2573 &setnearest, closestp,
2574 nearest, validator_log, val);
2575 if (unknown)
2576 val->attributes |= VALATTR_FOUNDUNKNOWN;
2577 if (result != ISC_R_SUCCESS)
2578 continue;
2579 if (setclosest)
2580 proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
2581 if (exists && !data && NEEDNODATA(val)) {
2582 val->attributes |= VALATTR_FOUNDNODATA;
2583 proofs[DNS_VALIDATOR_NODATAPROOF] = name;
2584 }
2585 if (!exists && setnearest) {
2586 val->attributes |= VALATTR_FOUNDNOQNAME;
2587 proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name;
2588 if (optout)
2589 val->attributes |= VALATTR_FOUNDOPTOUT;
2590 }
2591 }
2592 if (result == ISC_R_NOMORE)
2593 result = ISC_R_SUCCESS;
2594
2595 /*
2596 * To know we have a valid noqname and optout proofs we need to also
2597 * have a valid closest encloser. Otherwise we could still be looking
2598 * at proofs from the parent zone.
2599 */
2600 if (dns_name_countlabels(closest) > 0 &&
2601 dns_name_countlabels(nearest) ==
2602 dns_name_countlabels(closest) + 1 &&
2603 dns_name_issubdomain(nearest, closest))
2604 {
2605 val->attributes |= VALATTR_FOUNDCLOSEST;
2606 result = dns_name_concatenate(dns_wildcardname, closest,
2607 dns_fixedname_name(&val->wild),
2608 NULL);
2609 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2610 } else {
2611 val->attributes &= ~VALATTR_FOUNDNOQNAME;
2612 val->attributes &= ~VALATTR_FOUNDOPTOUT;
2613 proofs[DNS_VALIDATOR_NOQNAMEPROOF] = NULL;
2614 }
2615
2616 /*
2617 * Do we need to check for the wildcard?
2618 */
2619 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
2620 ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
2621 result = checkwildcard(val, dns_rdatatype_nsec3, zonename);
2622 if (result != ISC_R_SUCCESS)
2623 return (result);
2624 }
2625 return (result);
2626 }
2627
2628 /*%
2629 * Validate the authority section records.
2630 */
2631 static isc_result_t
2632 validate_authority(dns_validator_t *val, isc_boolean_t resume) {
2633 dns_name_t *name;
2634 dns_message_t *message = val->event->message;
2635 isc_result_t result;
2636
2637 if (!resume)
2638 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2639 else
2640 result = ISC_R_SUCCESS;
2641
2642 for (;
2643 result == ISC_R_SUCCESS;
2644 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
2645 {
2646 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2647
2648 name = NULL;
2649 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
2650 if (resume) {
2651 rdataset = ISC_LIST_NEXT(val->currentset, link);
2652 val->currentset = NULL;
2653 resume = ISC_FALSE;
2654 } else
2655 rdataset = ISC_LIST_HEAD(name->list);
2656
2657 for (;
2658 rdataset != NULL;
2659 rdataset = ISC_LIST_NEXT(rdataset, link))
2660 {
2661 if (rdataset->type == dns_rdatatype_rrsig)
2662 continue;
2663
2664 for (sigrdataset = ISC_LIST_HEAD(name->list);
2665 sigrdataset != NULL;
2666 sigrdataset = ISC_LIST_NEXT(sigrdataset,
2667 link))
2668 {
2669 if (sigrdataset->type == dns_rdatatype_rrsig &&
2670 sigrdataset->covers == rdataset->type)
2671 break;
2672 }
2673 /*
2674 * If a signed zone is missing the zone key, bad
2675 * things could happen. A query for data in the zone
2676 * would lead to a query for the zone key, which
2677 * would return a negative answer, which would contain
2678 * an SOA and an NSEC signed by the missing key, which
2679 * would trigger another query for the DNSKEY (since
2680 * the first one is still in progress), and go into an
2681 * infinite loop. Avoid that.
2682 */
2683 if (val->event->type == dns_rdatatype_dnskey &&
2684 rdataset->type == dns_rdatatype_nsec &&
2685 dns_name_equal(name, val->event->name))
2686 {
2687 dns_rdata_t nsec = DNS_RDATA_INIT;
2688
2689 result = dns_rdataset_first(rdataset);
2690 if (result != ISC_R_SUCCESS)
2691 return (result);
2692 dns_rdataset_current(rdataset, &nsec);
2693 if (dns_nsec_typepresent(&nsec,
2694 dns_rdatatype_soa))
2695 continue;
2696 }
2697 val->currentset = rdataset;
2698 result = create_validator(val, name, rdataset->type,
2699 rdataset, sigrdataset,
2700 authvalidated,
2701 "validate_authority");
2702 if (result != ISC_R_SUCCESS)
2703 return (result);
2704 val->authcount++;
2705 return (DNS_R_WAIT);
2706 }
2707 }
2708 if (result == ISC_R_NOMORE)
2709 result = ISC_R_SUCCESS;
2710 return (result);
2711 }
2712
2713 /*%
2714 * Validate the ncache elements.
2715 */
2716 static isc_result_t
2717 validate_ncache(dns_validator_t *val, isc_boolean_t resume) {
2718 dns_name_t *name;
2719 isc_result_t result;
2720
2721 if (!resume)
2722 result = dns_rdataset_first(val->event->rdataset);
2723 else
2724 result = dns_rdataset_next(val->event->rdataset);
2725
2726 for (;
2727 result == ISC_R_SUCCESS;
2728 result = dns_rdataset_next(val->event->rdataset))
2729 {
2730 dns_rdataset_t *rdataset, *sigrdataset = NULL;
2731
2732 if (dns_rdataset_isassociated(&val->frdataset))
2733 dns_rdataset_disassociate(&val->frdataset);
2734 if (dns_rdataset_isassociated(&val->fsigrdataset))
2735 dns_rdataset_disassociate(&val->fsigrdataset);
2736
2737 name = dns_fixedname_initname(&val->fname);
2738 rdataset = &val->frdataset;
2739 dns_ncache_current(val->event->rdataset, name, rdataset);
2740
2741 if (val->frdataset.type == dns_rdatatype_rrsig)
2742 continue;
2743
2744 result = dns_ncache_getsigrdataset(val->event->rdataset, name,
2745 rdataset->type,
2746 &val->fsigrdataset);
2747 if (result == ISC_R_SUCCESS)
2748 sigrdataset = &val->fsigrdataset;
2749
2750 /*
2751 * If a signed zone is missing the zone key, bad
2752 * things could happen. A query for data in the zone
2753 * would lead to a query for the zone key, which
2754 * would return a negative answer, which would contain
2755 * an SOA and an NSEC signed by the missing key, which
2756 * would trigger another query for the DNSKEY (since
2757 * the first one is still in progress), and go into an
2758 * infinite loop. Avoid that.
2759 */
2760 if (val->event->type == dns_rdatatype_dnskey &&
2761 rdataset->type == dns_rdatatype_nsec &&
2762 dns_name_equal(name, val->event->name))
2763 {
2764 dns_rdata_t nsec = DNS_RDATA_INIT;
2765
2766 result = dns_rdataset_first(rdataset);
2767 if (result != ISC_R_SUCCESS)
2768 return (result);
2769 dns_rdataset_current(rdataset, &nsec);
2770 if (dns_nsec_typepresent(&nsec,
2771 dns_rdatatype_soa))
2772 continue;
2773 }
2774 val->currentset = rdataset;
2775 result = create_validator(val, name, rdataset->type,
2776 rdataset, sigrdataset,
2777 authvalidated,
2778 "validate_ncache");
2779 if (result != ISC_R_SUCCESS)
2780 return (result);
2781 val->authcount++;
2782 return (DNS_R_WAIT);
2783 }
2784 if (result == ISC_R_NOMORE)
2785 result = ISC_R_SUCCESS;
2786 return (result);
2787 }
2788
2789 /*%
2790 * Prove a negative answer is good or that there is a NOQNAME when the
2791 * answer is from a wildcard.
2792 *
2793 * Loop through the authority section looking for NODATA, NOWILDCARD
2794 * and NOQNAME proofs in the NSEC records by calling authvalidated().
2795 *
2796 * If the required proofs are found we are done.
2797 *
2798 * If the proofs are not found attempt to prove this is a unsecure
2799 * response.
2800 */
2801 static isc_result_t
2802 nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
2803 isc_result_t result;
2804
2805 if (resume)
2806 validator_log(val, ISC_LOG_DEBUG(3), "resuming nsecvalidate");
2807
2808 if (val->event->message == NULL)
2809 result = validate_ncache(val, resume);
2810 else
2811 result = validate_authority(val, resume);
2812
2813 if (result != ISC_R_SUCCESS)
2814 return (result);
2815
2816 /*
2817 * Do we only need to check for NOQNAME? To get here we must have
2818 * had a secure wildcard answer.
2819 */
2820 if (!NEEDNODATA(val) && !NEEDNOWILDCARD(val) && NEEDNOQNAME(val)) {
2821 if (!FOUNDNOQNAME(val))
2822 findnsec3proofs(val);
2823 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
2824 !FOUNDOPTOUT(val)) {
2825 validator_log(val, ISC_LOG_DEBUG(3),
2826 "marking as secure, noqname proof found");
2827 marksecure(val->event);
2828 return (ISC_R_SUCCESS);
2829 } else if (FOUNDOPTOUT(val) &&
2830 dns_name_countlabels(dns_fixedname_name(&val->wild))
2831 != 0) {
2832 validator_log(val, ISC_LOG_DEBUG(3),
2833 "optout proof found");
2834 val->event->optout = ISC_TRUE;
2835 markanswer(val, "nsecvalidate (1)");
2836 return (ISC_R_SUCCESS);
2837 } else if ((val->attributes & VALATTR_FOUNDUNKNOWN) != 0) {
2838 validator_log(val, ISC_LOG_DEBUG(3),
2839 "unknown NSEC3 hash algorithm found");
2840 markanswer(val, "nsecvalidate (2)");
2841 return (ISC_R_SUCCESS);
2842 }
2843 validator_log(val, ISC_LOG_DEBUG(3),
2844 "noqname proof not found");
2845 return (DNS_R_NOVALIDNSEC);
2846 }
2847
2848 if (!FOUNDNOQNAME(val) && !FOUNDNODATA(val))
2849 findnsec3proofs(val);
2850
2851 /*
2852 * Do we need to check for the wildcard?
2853 */
2854 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
2855 ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
2856 result = checkwildcard(val, dns_rdatatype_nsec, NULL);
2857 if (result != ISC_R_SUCCESS)
2858 return (result);
2859 }
2860
2861 if ((NEEDNODATA(val) && (FOUNDNODATA(val) || FOUNDOPTOUT(val))) ||
2862 (NEEDNOQNAME(val) && FOUNDNOQNAME(val) &&
2863 NEEDNOWILDCARD(val) && FOUNDNOWILDCARD(val) &&
2864 FOUNDCLOSEST(val))) {
2865 if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
2866 val->event->optout = ISC_TRUE;
2867 validator_log(val, ISC_LOG_DEBUG(3),
2868 "nonexistence proof(s) found");
2869 if (val->event->message == NULL)
2870 marksecure(val->event);
2871 else
2872 val->event->secure = ISC_TRUE;
2873 return (ISC_R_SUCCESS);
2874 }
2875
2876 if (val->authfail != 0 && val->authcount == val->authfail)
2877 return (DNS_R_BROKENCHAIN);
2878 validator_log(val, ISC_LOG_DEBUG(3),
2879 "nonexistence proof(s) not found");
2880 val->attributes |= VALATTR_INSECURITY;
2881 return (proveunsecure(val, ISC_FALSE, ISC_FALSE));
2882 }
2883
2884 static isc_boolean_t
2885 check_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) {
2886 dns_rdata_t dsrdata = DNS_RDATA_INIT;
2887 dns_rdata_ds_t ds;
2888 isc_result_t result;
2889
2890 for (result = dns_rdataset_first(rdataset);
2891 result == ISC_R_SUCCESS;
2892 result = dns_rdataset_next(rdataset)) {
2893 dns_rdataset_current(rdataset, &dsrdata);
2894 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
2895 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2896
2897 if (dns_resolver_ds_digest_supported(val->view->resolver,
2898 name, ds.digest_type) &&
2899 dns_resolver_algorithm_supported(val->view->resolver,
2900 name, ds.algorithm)) {
2901 dns_rdata_reset(&dsrdata);
2902 return (ISC_TRUE);
2903 }
2904 dns_rdata_reset(&dsrdata);
2905 }
2906 return (ISC_FALSE);
2907 }
2908
2909 static void
2910 dlvvalidated(isc_task_t *task, isc_event_t *event) {
2911 dns_validatorevent_t *devent;
2912 dns_validator_t *val;
2913 isc_result_t eresult;
2914 isc_boolean_t want_destroy;
2915
2916 UNUSED(task);
2917 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
2918
2919 devent = (dns_validatorevent_t *)event;
2920 val = devent->ev_arg;
2921 eresult = devent->result;
2922
2923 isc_event_free(&event);
2924 dns_validator_destroy(&val->subvalidator);
2925
2926 INSIST(val->event != NULL);
2927
2928 validator_log(val, ISC_LOG_DEBUG(3), "in dlvvalidated");
2929 LOCK(&val->lock);
2930 if (CANCELED(val)) {
2931 validator_done(val, ISC_R_CANCELED);
2932 } else if (eresult == ISC_R_SUCCESS) {
2933 validator_log(val, ISC_LOG_DEBUG(3),
2934 "dlvset with trust %s",
2935 dns_trust_totext(val->frdataset.trust));
2936 dns_rdataset_clone(&val->frdataset, &val->dlv);
2937 val->havedlvsep = ISC_TRUE;
2938 if (dlv_algorithm_supported(val))
2939 dlv_validator_start(val);
2940 else {
2941 markanswer(val, "dlvvalidated");
2942 validator_done(val, ISC_R_SUCCESS);
2943 }
2944 } else {
2945 if (eresult != DNS_R_BROKENCHAIN) {
2946 if (dns_rdataset_isassociated(&val->frdataset))
2947 dns_rdataset_expire(&val->frdataset);
2948 if (dns_rdataset_isassociated(&val->fsigrdataset))
2949 dns_rdataset_expire(&val->fsigrdataset);
2950 }
2951 validator_log(val, ISC_LOG_DEBUG(3),
2952 "dlvvalidated: got %s",
2953 isc_result_totext(eresult));
2954 validator_done(val, DNS_R_BROKENCHAIN);
2955 }
2956 want_destroy = exit_check(val);
2957 UNLOCK(&val->lock);
2958 if (want_destroy)
2959 destroy(val);
2960 }
2961
2962 /*%
2963 * Callback from fetching a DLV record.
2964 *
2965 * Resumes the DLV lookup process.
2966 */
2967 static void
2968 dlvfetched(isc_task_t *task, isc_event_t *event) {
2969 char namebuf[DNS_NAME_FORMATSIZE];
2970 dns_fetchevent_t *devent;
2971 dns_validator_t *val;
2972 isc_boolean_t want_destroy;
2973 isc_result_t eresult;
2974 isc_result_t result;
2975 dns_fetch_t *fetch;
2976
2977 UNUSED(task);
2978 INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
2979 devent = (dns_fetchevent_t *)event;
2980 val = devent->ev_arg;
2981 eresult = devent->result;
2982
2983 /* Free resources which are not of interest. */
2984 if (devent->node != NULL)
2985 dns_db_detachnode(devent->db, &devent->node);
2986 if (devent->db != NULL)
2987 dns_db_detach(&devent->db);
2988 if (dns_rdataset_isassociated(&val->fsigrdataset))
2989 dns_rdataset_disassociate(&val->fsigrdataset);
2990 isc_event_free(&event);
2991
2992 INSIST(val->event != NULL);
2993 validator_log(val, ISC_LOG_DEBUG(3), "in dlvfetched: %s",
2994 dns_result_totext(eresult));
2995
2996 LOCK(&val->lock);
2997 fetch = val->fetch;
2998 val->fetch = NULL;
2999 if (eresult == ISC_R_SUCCESS) {
3000 dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
3001 sizeof(namebuf));
3002 dns_rdataset_clone(&val->frdataset, &val->dlv);
3003 val->havedlvsep = ISC_TRUE;
3004 if (dlv_algorithm_supported(val)) {
3005 validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found",
3006 namebuf);
3007 dlv_validator_start(val);
3008 } else {
3009 validator_log(val, ISC_LOG_DEBUG(3),
3010 "DLV %s found with no supported algorithms",
3011 namebuf);
3012 markanswer(val, "dlvfetched (1)");
3013 validator_done(val, ISC_R_SUCCESS);
3014 }
3015 } else if (eresult == DNS_R_NXRRSET ||
3016 eresult == DNS_R_NXDOMAIN ||
3017 eresult == DNS_R_NCACHENXRRSET ||
3018 eresult == DNS_R_NCACHENXDOMAIN) {
3019 result = finddlvsep(val, ISC_TRUE);
3020 if (result == ISC_R_SUCCESS) {
3021 if (dlv_algorithm_supported(val)) {
3022 dns_name_format(dns_fixedname_name(&val->dlvsep),
3023 namebuf, sizeof(namebuf));
3024 validator_log(val, ISC_LOG_DEBUG(3),
3025 "DLV %s found", namebuf);
3026 dlv_validator_start(val);
3027 } else {
3028 validator_log(val, ISC_LOG_DEBUG(3),
3029 "DLV %s found with no supported "
3030 "algorithms", namebuf);
3031 markanswer(val, "dlvfetched (2)");
3032 validator_done(val, ISC_R_SUCCESS);
3033 }
3034 } else if (result == ISC_R_NOTFOUND) {
3035 validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
3036 markanswer(val, "dlvfetched (3)");
3037 validator_done(val, ISC_R_SUCCESS);
3038 } else {
3039 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3040 dns_result_totext(result));
3041 if (result != DNS_R_WAIT)
3042 validator_done(val, result);
3043 }
3044 } else {
3045 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3046 dns_result_totext(eresult));
3047 validator_done(val, eresult);
3048 }
3049 want_destroy = exit_check(val);
3050 UNLOCK(&val->lock);
3051 if (fetch != NULL)
3052 dns_resolver_destroyfetch(&fetch);
3053 if (want_destroy)
3054 destroy(val);
3055 }
3056
3057 /*%
3058 * Start the DLV lookup process.
3059 *
3060 * Returns
3061 * \li ISC_R_SUCCESS
3062 * \li DNS_R_WAIT
3063 * \li Others on validation failures.
3064 */
3065 static isc_result_t
3066 startfinddlvsep(dns_validator_t *val, const dns_name_t *unsecure) {
3067 char namebuf[DNS_NAME_FORMATSIZE];
3068 isc_result_t result;
3069
3070 INSIST(!DLVTRIED(val));
3071
3072 val->attributes |= VALATTR_DLVTRIED;
3073
3074 dns_name_format(unsecure, namebuf, sizeof(namebuf));
3075 validator_log(val, ISC_LOG_DEBUG(3),
3076 "plain DNSSEC returns unsecure (%s): looking for DLV",
3077 namebuf);
3078
3079 if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
3080 validator_log(val, ISC_LOG_WARNING, "must be secure failure, "
3081 " %s is under DLV (startfinddlvsep)", namebuf);
3082 return (DNS_R_MUSTBESECURE);
3083 }
3084
3085 val->dlvlabels = dns_name_countlabels(unsecure) - 1;
3086 result = finddlvsep(val, ISC_FALSE);
3087 if (result == ISC_R_NOTFOUND) {
3088 validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
3089 markanswer(val, "startfinddlvsep (1)");
3090 return (ISC_R_SUCCESS);
3091 }
3092 if (result == DNS_R_NTACOVERED) {
3093 validator_log(val, ISC_LOG_DEBUG(3), "DLV covered by NTA");
3094 validator_done(val, ISC_R_SUCCESS);
3095 return (ISC_R_SUCCESS);
3096 }
3097 if (result != ISC_R_SUCCESS) {
3098 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3099 dns_result_totext(result));
3100 return (result);
3101 }
3102 dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
3103 sizeof(namebuf));
3104 if (dlv_algorithm_supported(val)) {
3105 validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf);
3106 dlv_validator_start(val);
3107 return (DNS_R_WAIT);
3108 }
3109 validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found with no supported "
3110 "algorithms", namebuf);
3111 markanswer(val, "startfinddlvsep (2)");
3112 validator_done(val, ISC_R_SUCCESS);
3113 return (ISC_R_SUCCESS);
3114 }
3115
3116 /*%
3117 * Continue the DLV lookup process.
3118 *
3119 * Returns
3120 * \li ISC_R_SUCCESS
3121 * \li ISC_R_NOTFOUND
3122 * \li DNS_R_WAIT
3123 * \li Others on validation failure.
3124 */
3125 static isc_result_t
3126 finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
3127 char namebuf[DNS_NAME_FORMATSIZE];
3128 dns_fixedname_t dlvfixed;
3129 dns_name_t *dlvname;
3130 dns_name_t *dlvsep;
3131 dns_name_t noroot;
3132 isc_result_t result;
3133 unsigned int labels;
3134
3135 INSIST(val->view->dlv != NULL);
3136
3137 if (!resume) {
3138 if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
3139 dns_name_format(val->event->name, namebuf,
3140 sizeof(namebuf));
3141 validator_log(val, ISC_LOG_WARNING,
3142 "must be secure failure, "
3143 "%s is under DLV (finddlvsep)", namebuf);
3144 return (DNS_R_MUSTBESECURE);
3145 }
3146
3147 dlvsep = dns_fixedname_initname(&val->dlvsep);
3148 dns_name_copy(val->event->name, dlvsep, NULL);
3149 /*
3150 * If this is a response to a DS query, we need to look in
3151 * the parent zone for the trust anchor.
3152 */
3153 if (val->event->type == dns_rdatatype_ds) {
3154 labels = dns_name_countlabels(dlvsep);
3155 if (labels == 0)
3156 return (ISC_R_NOTFOUND);
3157 dns_name_getlabelsequence(dlvsep, 1, labels - 1,
3158 dlvsep);
3159 }
3160 } else {
3161 dlvsep = dns_fixedname_name(&val->dlvsep);
3162 labels = dns_name_countlabels(dlvsep);
3163 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3164 }
3165 dns_name_init(&noroot, NULL);
3166 dlvname = dns_fixedname_initname(&dlvfixed);
3167 labels = dns_name_countlabels(dlvsep);
3168 if (labels == 0)
3169 return (ISC_R_NOTFOUND);
3170 dns_name_getlabelsequence(dlvsep, 0, labels - 1, &noroot);
3171 result = dns_name_concatenate(&noroot, val->view->dlv, dlvname, NULL);
3172 while (result == ISC_R_NOSPACE) {
3173 labels = dns_name_countlabels(dlvsep);
3174 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3175 dns_name_getlabelsequence(dlvsep, 0, labels - 2, &noroot);
3176 result = dns_name_concatenate(&noroot, val->view->dlv,
3177 dlvname, NULL);
3178 }
3179 if (result != ISC_R_SUCCESS) {
3180 validator_log(val, ISC_LOG_DEBUG(2), "DLV concatenate failed");
3181 return (DNS_R_NOVALIDSIG);
3182 }
3183
3184 if (((val->options & DNS_VALIDATOR_NONTA) == 0) &&
3185 dns_view_ntacovers(val->view, val->start, dlvname, val->view->dlv))
3186 return (DNS_R_NTACOVERED);
3187
3188 while (dns_name_countlabels(dlvname) >=
3189 dns_name_countlabels(val->view->dlv) + val->dlvlabels) {
3190 dns_name_format(dlvname, namebuf, sizeof(namebuf));
3191 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV %s",
3192 namebuf);
3193 result = view_find(val, dlvname, dns_rdatatype_dlv);
3194 if (result == ISC_R_SUCCESS) {
3195 if (DNS_TRUST_PENDING(val->frdataset.trust) &&
3196 dns_rdataset_isassociated(&val->fsigrdataset))
3197 {
3198 dns_fixedname_init(&val->fname);
3199 dns_name_copy(dlvname,
3200 dns_fixedname_name(&val->fname),
3201 NULL);
3202 result = create_validator(val,
3203 dns_fixedname_name(&val->fname),
3204 dns_rdatatype_dlv,
3205 &val->frdataset,
3206 &val->fsigrdataset,
3207 dlvvalidated,
3208 "finddlvsep");
3209 if (result != ISC_R_SUCCESS)
3210 return (result);
3211 return (DNS_R_WAIT);
3212 }
3213 if (val->frdataset.trust < dns_trust_secure) {
3214 validator_log(val, ISC_LOG_DEBUG(3),
3215 "DLV not validated");
3216 return (DNS_R_NOVALIDSIG);
3217 }
3218 val->havedlvsep = ISC_TRUE;
3219 dns_rdataset_clone(&val->frdataset, &val->dlv);
3220 return (ISC_R_SUCCESS);
3221 }
3222 if (result == ISC_R_NOTFOUND) {
3223 result = create_fetch(val, dlvname, dns_rdatatype_dlv,
3224 dlvfetched, "finddlvsep");
3225 if (result != ISC_R_SUCCESS)
3226 return (result);
3227 return (DNS_R_WAIT);
3228 }
3229 if (result != DNS_R_NXRRSET &&
3230 result != DNS_R_NXDOMAIN &&
3231 result != DNS_R_EMPTYNAME &&
3232 result != DNS_R_NCACHENXRRSET &&
3233 result != DNS_R_NCACHENXDOMAIN)
3234 return (result);
3235 /*
3236 * Strip first labels from both dlvsep and dlvname.
3237 */
3238 labels = dns_name_countlabels(dlvsep);
3239 if (labels == 0)
3240 break;
3241 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3242 labels = dns_name_countlabels(dlvname);
3243 dns_name_getlabelsequence(dlvname, 1, labels - 1, dlvname);
3244 }
3245 return (ISC_R_NOTFOUND);
3246 }
3247
3248 /*%
3249 * proveunsecure walks down from the SEP looking for a break in the
3250 * chain of trust. That occurs when we can prove the DS record does
3251 * not exist at a delegation point or the DS exists at a delegation
3252 * but we don't support the algorithm/digest.
3253 *
3254 * If DLV is active and we look for a DLV record at or below the
3255 * point we go insecure. If found we restart the validation process.
3256 * If not found or DLV isn't active we mark the response as a answer.
3257 *
3258 * Returns:
3259 * \li ISC_R_SUCCESS val->event->name is in a unsecure zone
3260 * \li DNS_R_WAIT validation is in progress.
3261 * \li DNS_R_MUSTBESECURE val->event->name is supposed to be secure
3262 * (policy) but we proved that it is unsecure.
3263 * \li DNS_R_NOVALIDSIG
3264 * \li DNS_R_NOVALIDNSEC
3265 * \li DNS_R_NOTINSECURE
3266 * \li DNS_R_BROKENCHAIN
3267 */
3268 static isc_result_t
3269 proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
3270 {
3271 isc_result_t result;
3272 dns_fixedname_t fixedsecroot;
3273 dns_name_t *secroot;
3274 dns_name_t *tname;
3275 char namebuf[DNS_NAME_FORMATSIZE];
3276 dns_name_t *found;
3277 dns_fixedname_t fixedfound;
3278
3279 secroot = dns_fixedname_initname(&fixedsecroot);
3280 found = dns_fixedname_initname(&fixedfound);
3281 if (val->havedlvsep)
3282 dns_name_copy(dns_fixedname_name(&val->dlvsep), secroot, NULL);
3283 else {
3284 unsigned int labels;
3285 dns_name_copy(val->event->name, secroot, NULL);
3286 /*
3287 * If this is a response to a DS query, we need to look in
3288 * the parent zone for the trust anchor.
3289 */
3290
3291 labels = dns_name_countlabels(secroot);
3292 if (val->event->type == dns_rdatatype_ds && labels > 1U)
3293 dns_name_getlabelsequence(secroot, 1, labels - 1,
3294 secroot);
3295 result = dns_keytable_finddeepestmatch(val->keytable,
3296 secroot, secroot);
3297 if (result == ISC_R_NOTFOUND) {
3298 if (val->mustbesecure) {
3299 validator_log(val, ISC_LOG_WARNING,
3300 "must be secure failure, "
3301 "not beneath secure root");
3302 result = DNS_R_MUSTBESECURE;
3303 goto out;
3304 } else
3305 validator_log(val, ISC_LOG_DEBUG(3),
3306 "not beneath secure root");
3307 if (val->view->dlv == NULL || DLVTRIED(val)) {
3308 markanswer(val, "proveunsecure (1)");
3309 return (ISC_R_SUCCESS);
3310 }
3311 return (startfinddlvsep(val, dns_rootname));
3312 } else if (result != ISC_R_SUCCESS)
3313 return (result);
3314 }
3315
3316 if (!resume) {
3317 /*
3318 * We are looking for breaks below the SEP so add a label.
3319 */
3320 val->labels = dns_name_countlabels(secroot) + 1;
3321 } else {
3322 validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
3323 /*
3324 * If we have a DS rdataset and it is secure then check if
3325 * the DS rdataset has a supported algorithm combination.
3326 * If not this is an insecure delegation as far as this
3327 * resolver is concerned. Fall back to DLV if available.
3328 */
3329 if (have_ds && val->frdataset.trust >= dns_trust_secure &&
3330 !check_ds(val, dns_fixedname_name(&val->fname),
3331 &val->frdataset)) {
3332 dns_name_format(dns_fixedname_name(&val->fname),
3333 namebuf, sizeof(namebuf));
3334 if ((val->view->dlv == NULL || DLVTRIED(val)) &&
3335 val->mustbesecure) {
3336 validator_log(val, ISC_LOG_WARNING,
3337 "must be secure failure at '%s', "
3338 "can't fall back to DLV",
3339 namebuf);
3340 result = DNS_R_MUSTBESECURE;
3341 goto out;
3342 }
3343 validator_log(val, ISC_LOG_DEBUG(3),
3344 "no supported algorithm/digest (%s/DS)",
3345 namebuf);
3346 if (val->view->dlv == NULL || DLVTRIED(val)) {
3347 markanswer(val, "proveunsecure (2)");
3348 result = ISC_R_SUCCESS;
3349 goto out;
3350 }
3351 return(startfinddlvsep(val,
3352 dns_fixedname_name(&val->fname)));
3353 }
3354 val->labels++;
3355 }
3356
3357 for (;
3358 val->labels <= dns_name_countlabels(val->event->name);
3359 val->labels++)
3360 {
3361
3362 tname = dns_fixedname_initname(&val->fname);
3363 if (val->labels == dns_name_countlabels(val->event->name))
3364 dns_name_copy(val->event->name, tname, NULL);
3365 else
3366 dns_name_split(val->event->name, val->labels,
3367 NULL, tname);
3368
3369 dns_name_format(tname, namebuf, sizeof(namebuf));
3370 validator_log(val, ISC_LOG_DEBUG(3),
3371 "checking existence of DS at '%s'",
3372 namebuf);
3373
3374 result = view_find(val, tname, dns_rdatatype_ds);
3375 if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
3376 /*
3377 * There is no DS. If this is a delegation,
3378 * we may be done.
3379 */
3380 /*
3381 * If we have "trust == answer" then this namespace
3382 * has switched from insecure to should be secure.
3383 */
3384 if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3385 DNS_TRUST_ANSWER(val->frdataset.trust)) {
3386 result = create_validator(val, tname,
3387 dns_rdatatype_ds,
3388 &val->frdataset,
3389 NULL, dsvalidated,
3390 "proveunsecure");
3391 if (result != ISC_R_SUCCESS)
3392 goto out;
3393 return (DNS_R_WAIT);
3394 }
3395 /*
3396 * Zones using NSEC3 don't return a NSEC RRset so
3397 * we need to use dns_view_findzonecut2 to find
3398 * the zone cut.
3399 */
3400 if (result == DNS_R_NXRRSET &&
3401 !dns_rdataset_isassociated(&val->frdataset) &&
3402 dns_view_findzonecut2(val->view, tname, found,
3403 0, 0, ISC_FALSE, ISC_FALSE,
3404 NULL, NULL) == ISC_R_SUCCESS &&
3405 dns_name_equal(tname, found)) {
3406 if (val->mustbesecure) {
3407 validator_log(val, ISC_LOG_WARNING,
3408 "must be secure failure, "
3409 "no DS at zone cut");
3410 return (DNS_R_MUSTBESECURE);
3411 }
3412 if (val->view->dlv == NULL || DLVTRIED(val)) {
3413 markanswer(val, "proveunsecure (3)");
3414 return (ISC_R_SUCCESS);
3415 }
3416 return (startfinddlvsep(val, tname));
3417 }
3418 if (val->frdataset.trust < dns_trust_secure) {
3419 /*
3420 * This shouldn't happen, since the negative
3421 * response should have been validated. Since
3422 * there's no way of validating existing
3423 * negative response blobs, give up.
3424 */
3425 validator_log(val, ISC_LOG_WARNING,
3426 "can't validate existing "
3427 "negative responses (no DS)");
3428 result = DNS_R_NOVALIDSIG;
3429 goto out;
3430 }
3431 if (isdelegation(tname, &val->frdataset, result)) {
3432 if (val->mustbesecure) {
3433 validator_log(val, ISC_LOG_WARNING,
3434 "must be secure failure, "
3435 "%s is a delegation",
3436 namebuf);
3437 return (DNS_R_MUSTBESECURE);
3438 }
3439 if (val->view->dlv == NULL || DLVTRIED(val)) {
3440 markanswer(val, "proveunsecure (4)");
3441 return (ISC_R_SUCCESS);
3442 }
3443 return (startfinddlvsep(val, tname));
3444 }
3445 continue;
3446 } else if (result == DNS_R_CNAME) {
3447 if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3448 DNS_TRUST_ANSWER(val->frdataset.trust)) {
3449 result = create_validator(val, tname,
3450 dns_rdatatype_cname,
3451 &val->frdataset,
3452 NULL, cnamevalidated,
3453 "proveunsecure "
3454 "(cname)");
3455 if (result != ISC_R_SUCCESS)
3456 goto out;
3457 return (DNS_R_WAIT);
3458 }
3459 continue;
3460 } else if (result == ISC_R_SUCCESS) {
3461 /*
3462 * There is a DS here. Verify that it's secure and
3463 * continue.
3464 */
3465 if (val->frdataset.trust >= dns_trust_secure) {
3466 if (!check_ds(val, tname, &val->frdataset)) {
3467 validator_log(val, ISC_LOG_DEBUG(3),
3468 "no supported algorithm/"
3469 "digest (%s/DS)", namebuf);
3470 if (val->mustbesecure) {
3471 validator_log(val,
3472 ISC_LOG_WARNING,
3473 "must be secure failure, "
3474 "no supported algorithm/"
3475 "digest (%s/DS)",
3476 namebuf);
3477 result = DNS_R_MUSTBESECURE;
3478 goto out;
3479 }
3480 if (val->view->dlv == NULL ||
3481 DLVTRIED(val)) {
3482 markanswer(val,
3483 "proveunsecure (5)");
3484 result = ISC_R_SUCCESS;
3485 goto out;
3486 }
3487 return(startfinddlvsep(val, tname));
3488 }
3489 continue;
3490 }
3491 else if (!dns_rdataset_isassociated(&val->fsigrdataset))
3492 {
3493 validator_log(val, ISC_LOG_DEBUG(3),
3494 "DS is unsigned");
3495 result = DNS_R_NOVALIDSIG;
3496 goto out;
3497 }
3498 /*
3499 * Validate / re-validate answer.
3500 */
3501 result = create_validator(val, tname, dns_rdatatype_ds,
3502 &val->frdataset,
3503 &val->fsigrdataset,
3504 dsvalidated,
3505 "proveunsecure");
3506 if (result != ISC_R_SUCCESS)
3507 goto out;
3508 return (DNS_R_WAIT);
3509 } else if (result == DNS_R_NXDOMAIN ||
3510 result == DNS_R_NCACHENXDOMAIN) {
3511 /*
3512 * This is not a zone cut. Assuming things are
3513 * as expected, continue.
3514 */
3515 if (!dns_rdataset_isassociated(&val->frdataset)) {
3516 /*
3517 * There should be an NSEC here, since we
3518 * are still in a secure zone.
3519 */
3520 result = DNS_R_NOVALIDNSEC;
3521 goto out;
3522 } else if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3523 DNS_TRUST_ANSWER(val->frdataset.trust)) {
3524 /*
3525 * If we have "trust == answer" then this namespace
3526 * has switched from insecure to should be secure.
3527 */
3528 result = create_validator(val, tname,
3529 dns_rdatatype_ds,
3530 &val->frdataset,
3531 NULL, dsvalidated,
3532 "proveunsecure");
3533 if (result != ISC_R_SUCCESS)
3534 goto out;
3535 return (DNS_R_WAIT);
3536 } else if (val->frdataset.trust < dns_trust_secure) {
3537 /*
3538 * This shouldn't happen, since the negative
3539 * response should have been validated. Since
3540 * there's no way of validating existing
3541 * negative response blobs, give up.
3542 */
3543 validator_log(val, ISC_LOG_WARNING,
3544 "can't validate existing "
3545 "negative responses "
3546 "(not a zone cut)");
3547 result = DNS_R_NOVALIDSIG;
3548 goto out;
3549 }
3550 continue;
3551 } else if (result == ISC_R_NOTFOUND) {
3552 /*
3553 * We don't know anything about the DS. Find it.
3554 */
3555 result = create_fetch(val, tname, dns_rdatatype_ds,
3556 dsfetched2, "proveunsecure");
3557 if (result != ISC_R_SUCCESS)
3558 goto out;
3559 return (DNS_R_WAIT);
3560 } else if (result == DNS_R_BROKENCHAIN)
3561 return (result);
3562 }
3563
3564 /* Couldn't complete insecurity proof */
3565 validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed");
3566 return (DNS_R_NOTINSECURE);
3567
3568 out:
3569 if (dns_rdataset_isassociated(&val->frdataset))
3570 dns_rdataset_disassociate(&val->frdataset);
3571 if (dns_rdataset_isassociated(&val->fsigrdataset))
3572 dns_rdataset_disassociate(&val->fsigrdataset);
3573 return (result);
3574 }
3575
3576 /*%
3577 * Reset state and revalidate the answer using DLV.
3578 */
3579 static void
3580 dlv_validator_start(dns_validator_t *val) {
3581 isc_event_t *event;
3582
3583 validator_log(val, ISC_LOG_DEBUG(3), "dlv_validator_start");
3584
3585 /*
3586 * Reset state and try again.
3587 */
3588 val->attributes &= VALATTR_DLVTRIED;
3589 val->options &= ~DNS_VALIDATOR_DLV;
3590
3591 event = (isc_event_t *)val->event;
3592 isc_task_send(val->task, &event);
3593 }
3594
3595 /*%
3596 * Start the validation process.
3597 *
3598 * Attempt to validate the answer based on the category it appears to
3599 * fall in.
3600 * \li 1. secure positive answer.
3601 * \li 2. unsecure positive answer.
3602 * \li 3. a negative answer (secure or unsecure).
3603 *
3604 * Note a answer that appears to be a secure positive answer may actually
3605 * be an unsecure positive answer.
3606 */
3607 static void
3608 validator_start(isc_task_t *task, isc_event_t *event) {
3609 dns_validator_t *val;
3610 dns_validatorevent_t *vevent;
3611 isc_boolean_t want_destroy = ISC_FALSE;
3612 isc_result_t result = ISC_R_FAILURE;
3613
3614 UNUSED(task);
3615 REQUIRE(event->ev_type == DNS_EVENT_VALIDATORSTART);
3616 vevent = (dns_validatorevent_t *)event;
3617 val = vevent->validator;
3618
3619 /* If the validator has been canceled, val->event == NULL */
3620 if (val->event == NULL)
3621 return;
3622
3623 if (DLVTRIED(val))
3624 validator_log(val, ISC_LOG_DEBUG(3), "restarting using DLV");
3625 else
3626 validator_log(val, ISC_LOG_DEBUG(3), "starting");
3627
3628 LOCK(&val->lock);
3629
3630 if ((val->options & DNS_VALIDATOR_DLV) != 0 &&
3631 val->event->rdataset != NULL) {
3632 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV");
3633 result = startfinddlvsep(val, dns_rootname);
3634 } else if (val->event->rdataset != NULL &&
3635 val->event->sigrdataset != NULL) {
3636 isc_result_t saved_result;
3637
3638 /*
3639 * This looks like a simple validation. We say "looks like"
3640 * because it might end up requiring an insecurity proof.
3641 */
3642 validator_log(val, ISC_LOG_DEBUG(3),
3643 "attempting positive response validation");
3644
3645 INSIST(dns_rdataset_isassociated(val->event->rdataset));
3646 INSIST(dns_rdataset_isassociated(val->event->sigrdataset));
3647 result = start_positive_validation(val);
3648 if (result == DNS_R_NOVALIDSIG &&
3649 (val->attributes & VALATTR_TRIEDVERIFY) == 0)
3650 {
3651 saved_result = result;
3652 validator_log(val, ISC_LOG_DEBUG(3),
3653 "falling back to insecurity proof");
3654 val->attributes |= VALATTR_INSECURITY;
3655 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
3656 if (result == DNS_R_NOTINSECURE)
3657 result = saved_result;
3658 }
3659 } else if (val->event->rdataset != NULL &&
3660 val->event->rdataset->type != 0) {
3661 /*
3662 * This is either an unsecure subdomain or a response from
3663 * a broken server.
3664 */
3665 INSIST(dns_rdataset_isassociated(val->event->rdataset));
3666 validator_log(val, ISC_LOG_DEBUG(3),
3667 "attempting insecurity proof");
3668
3669 val->attributes |= VALATTR_INSECURITY;
3670 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
3671 if (result == DNS_R_NOTINSECURE)
3672 validator_log(val, ISC_LOG_INFO,
3673 "got insecure response; "
3674 "parent indicates it should be secure");
3675 } else if (val->event->rdataset == NULL &&
3676 val->event->sigrdataset == NULL)
3677 {
3678 /*
3679 * This is a nonexistence validation.
3680 */
3681 validator_log(val, ISC_LOG_DEBUG(3),
3682 "attempting negative response validation");
3683
3684 if (val->event->message->rcode == dns_rcode_nxdomain) {
3685 val->attributes |= VALATTR_NEEDNOQNAME;
3686 val->attributes |= VALATTR_NEEDNOWILDCARD;
3687 } else
3688 val->attributes |= VALATTR_NEEDNODATA;
3689 result = nsecvalidate(val, ISC_FALSE);
3690 } else if (val->event->rdataset != NULL &&
3691 NEGATIVE(val->event->rdataset))
3692 {
3693 /*
3694 * This is a nonexistence validation.
3695 */
3696 validator_log(val, ISC_LOG_DEBUG(3),
3697 "attempting negative response validation");
3698
3699 if (val->event->rdataset->covers == dns_rdatatype_any) {
3700 val->attributes |= VALATTR_NEEDNOQNAME;
3701 val->attributes |= VALATTR_NEEDNOWILDCARD;
3702 } else
3703 val->attributes |= VALATTR_NEEDNODATA;
3704 result = nsecvalidate(val, ISC_FALSE);
3705 } else {
3706 /*
3707 * This shouldn't happen.
3708 */
3709 INSIST(0);
3710 }
3711
3712 if (result != DNS_R_WAIT) {
3713 want_destroy = exit_check(val);
3714 validator_done(val, result);
3715 }
3716
3717 UNLOCK(&val->lock);
3718 if (want_destroy)
3719 destroy(val);
3720 }
3721
3722 isc_result_t
3723 dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
3724 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
3725 dns_message_t *message, unsigned int options,
3726 isc_task_t *task, isc_taskaction_t action, void *arg,
3727 dns_validator_t **validatorp)
3728 {
3729 isc_result_t result = ISC_R_FAILURE;
3730 dns_validator_t *val;
3731 isc_task_t *tclone = NULL;
3732 dns_validatorevent_t *event;
3733
3734 REQUIRE(name != NULL);
3735 REQUIRE(rdataset != NULL ||
3736 (rdataset == NULL && sigrdataset == NULL && message != NULL));
3737 REQUIRE(validatorp != NULL && *validatorp == NULL);
3738
3739 val = isc_mem_get(view->mctx, sizeof(*val));
3740 if (val == NULL)
3741 return (ISC_R_NOMEMORY);
3742 val->view = NULL;
3743 dns_view_weakattach(view, &val->view);
3744
3745 event = (dns_validatorevent_t *)
3746 isc_event_allocate(view->mctx, task,
3747 DNS_EVENT_VALIDATORSTART,
3748 validator_start, NULL,
3749 sizeof(dns_validatorevent_t));
3750 if (event == NULL) {
3751 result = ISC_R_NOMEMORY;
3752 goto cleanup_val;
3753 }
3754 isc_task_attach(task, &tclone);
3755 event->validator = val;
3756 event->result = ISC_R_FAILURE;
3757 event->name = name;
3758 event->type = type;
3759 event->rdataset = rdataset;
3760 event->sigrdataset = sigrdataset;
3761 event->message = message;
3762 memset(event->proofs, 0, sizeof(event->proofs));
3763 event->optout = ISC_FALSE;
3764 event->secure = ISC_FALSE;
3765 result = isc_mutex_init(&val->lock);
3766 if (result != ISC_R_SUCCESS)
3767 goto cleanup_event;
3768 val->event = event;
3769 val->options = options;
3770 val->attributes = 0;
3771 val->fetch = NULL;
3772 val->subvalidator = NULL;
3773 val->parent = NULL;
3774
3775 val->keytable = NULL;
3776 result = dns_view_getsecroots(val->view, &val->keytable);
3777 if (result != ISC_R_SUCCESS)
3778 goto cleanup_mutex;
3779 val->keynode = NULL;
3780 val->key = NULL;
3781 val->siginfo = NULL;
3782 val->task = task;
3783 val->action = action;
3784 val->arg = arg;
3785 val->labels = 0;
3786 val->currentset = NULL;
3787 val->keyset = NULL;
3788 val->dsset = NULL;
3789 dns_rdataset_init(&val->dlv);
3790 val->seensig = ISC_FALSE;
3791 val->havedlvsep = ISC_FALSE;
3792 val->depth = 0;
3793 val->authcount = 0;
3794 val->authfail = 0;
3795 val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
3796 dns_rdataset_init(&val->frdataset);
3797 dns_rdataset_init(&val->fsigrdataset);
3798 dns_fixedname_init(&val->wild);
3799 dns_fixedname_init(&val->nearest);
3800 dns_fixedname_init(&val->closest);
3801 isc_stdtime_get(&val->start);
3802 ISC_LINK_INIT(val, link);
3803 val->magic = VALIDATOR_MAGIC;
3804
3805 if ((options & DNS_VALIDATOR_DEFER) == 0)
3806 isc_task_send(task, ISC_EVENT_PTR(&event));
3807
3808 *validatorp = val;
3809
3810 return (ISC_R_SUCCESS);
3811
3812 cleanup_mutex:
3813 DESTROYLOCK(&val->lock);
3814
3815 cleanup_event:
3816 isc_task_detach(&tclone);
3817 isc_event_free(ISC_EVENT_PTR(&event));
3818
3819 cleanup_val:
3820 dns_view_weakdetach(&val->view);
3821 isc_mem_put(view->mctx, val, sizeof(*val));
3822
3823 return (result);
3824 }
3825
3826 void
3827 dns_validator_send(dns_validator_t *validator) {
3828 isc_event_t *event;
3829 REQUIRE(VALID_VALIDATOR(validator));
3830
3831 LOCK(&validator->lock);
3832
3833 INSIST((validator->options & DNS_VALIDATOR_DEFER) != 0);
3834 event = (isc_event_t *)validator->event;
3835 validator->options &= ~DNS_VALIDATOR_DEFER;
3836 UNLOCK(&validator->lock);
3837
3838 isc_task_send(validator->task, ISC_EVENT_PTR(&event));
3839 }
3840
3841 void
3842 dns_validator_cancel(dns_validator_t *validator) {
3843 dns_fetch_t *fetch = NULL;
3844
3845 REQUIRE(VALID_VALIDATOR(validator));
3846
3847 LOCK(&validator->lock);
3848
3849 validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
3850
3851 if ((validator->attributes & VALATTR_CANCELED) == 0) {
3852 validator->attributes |= VALATTR_CANCELED;
3853 if (validator->event != NULL) {
3854 fetch = validator->fetch;
3855 validator->fetch = NULL;
3856
3857 if (validator->subvalidator != NULL)
3858 dns_validator_cancel(validator->subvalidator);
3859 if ((validator->options & DNS_VALIDATOR_DEFER) != 0) {
3860 validator->options &= ~DNS_VALIDATOR_DEFER;
3861 validator_done(validator, ISC_R_CANCELED);
3862 }
3863 }
3864 }
3865 UNLOCK(&validator->lock);
3866
3867 /* Need to cancel and destroy the fetch outside validator lock */
3868 if (fetch != NULL) {
3869 dns_resolver_cancelfetch(fetch);
3870 dns_resolver_destroyfetch(&fetch);
3871 }
3872 }
3873
3874 static void
3875 destroy(dns_validator_t *val) {
3876 isc_mem_t *mctx;
3877
3878 REQUIRE(SHUTDOWN(val));
3879 REQUIRE(val->event == NULL);
3880 REQUIRE(val->fetch == NULL);
3881
3882 if (val->keynode != NULL)
3883 dns_keytable_detachkeynode(val->keytable, &val->keynode);
3884 else if (val->key != NULL)
3885 dst_key_free(&val->key);
3886 if (val->keytable != NULL)
3887 dns_keytable_detach(&val->keytable);
3888 if (val->subvalidator != NULL)
3889 dns_validator_destroy(&val->subvalidator);
3890 if (val->havedlvsep)
3891 dns_rdataset_disassociate(&val->dlv);
3892 if (dns_rdataset_isassociated(&val->frdataset))
3893 dns_rdataset_disassociate(&val->frdataset);
3894 if (dns_rdataset_isassociated(&val->fsigrdataset))
3895 dns_rdataset_disassociate(&val->fsigrdataset);
3896 mctx = val->view->mctx;
3897 if (val->siginfo != NULL)
3898 isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo));
3899 DESTROYLOCK(&val->lock);
3900 dns_view_weakdetach(&val->view);
3901 val->magic = 0;
3902 isc_mem_put(mctx, val, sizeof(*val));
3903 }
3904
3905 void
3906 dns_validator_destroy(dns_validator_t **validatorp) {
3907 dns_validator_t *val;
3908 isc_boolean_t want_destroy = ISC_FALSE;
3909
3910 REQUIRE(validatorp != NULL);
3911 val = *validatorp;
3912 REQUIRE(VALID_VALIDATOR(val));
3913
3914 LOCK(&val->lock);
3915
3916 val->attributes |= VALATTR_SHUTDOWN;
3917 validator_log(val, ISC_LOG_DEBUG(4), "dns_validator_destroy");
3918
3919 want_destroy = exit_check(val);
3920
3921 UNLOCK(&val->lock);
3922
3923 if (want_destroy)
3924 destroy(val);
3925
3926 *validatorp = NULL;
3927 }
3928
3929 static void
3930 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
3931 isc_logmodule_t *module, int level, const char *fmt, va_list ap)
3932 {
3933 char msgbuf[2048];
3934 static const char spaces[] = " *";
3935 int depth = val->depth * 2;
3936 const char *viewname, *sep1, *sep2;
3937
3938 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
3939
3940 if ((unsigned int) depth >= sizeof spaces)
3941 depth = sizeof spaces - 1;
3942
3943 /*
3944 * Log the view name unless it's:
3945 * * "_default/IN" (which means there's only one view
3946 * configured in the server), or
3947 * * "_dnsclient/IN" (which means this is being called
3948 * from an application using dns/client.c).
3949 */
3950 if (val->view->rdclass == dns_rdataclass_in &&
3951 (strcmp(val->view->name, "_default") == 0 ||
3952 strcmp(val->view->name, DNS_CLIENTVIEW_NAME) == 0))
3953 {
3954 sep1 = viewname = sep2 = "";
3955 } else {
3956 sep1 = "view ";
3957 viewname = val->view->name;
3958 sep2 = ": ";
3959 }
3960
3961 if (val->event != NULL && val->event->name != NULL) {
3962 char namebuf[DNS_NAME_FORMATSIZE];
3963 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3964
3965 dns_name_format(val->event->name, namebuf, sizeof(namebuf));
3966 dns_rdatatype_format(val->event->type, typebuf,
3967 sizeof(typebuf));
3968 isc_log_write(dns_lctx, category, module, level,
3969 "%s%s%s%.*svalidating %s/%s: %s",
3970 sep1, viewname, sep2, depth, spaces,
3971 namebuf, typebuf, msgbuf);
3972 } else {
3973 isc_log_write(dns_lctx, category, module, level,
3974 "%s%s%s%.*svalidator @%p: %s",
3975 sep1, viewname, sep2, depth, spaces,
3976 val, msgbuf);
3977 }
3978 }
3979
3980 static void
3981 validator_log(void *val, int level, const char *fmt, ...) {
3982 va_list ap;
3983
3984 if (! isc_log_wouldlog(dns_lctx, level))
3985 return;
3986
3987 va_start(ap, fmt);
3988
3989 validator_logv(val, DNS_LOGCATEGORY_DNSSEC,
3990 DNS_LOGMODULE_VALIDATOR, level, fmt, ap);
3991 va_end(ap);
3992 }
3993
3994 static void
3995 validator_logcreate(dns_validator_t *val,
3996 dns_name_t *name, dns_rdatatype_t type,
3997 const char *caller, const char *operation)
3998 {
3999 char namestr[DNS_NAME_FORMATSIZE];
4000 char typestr[DNS_RDATATYPE_FORMATSIZE];
4001
4002 dns_name_format(name, namestr, sizeof(namestr));
4003 dns_rdatatype_format(type, typestr, sizeof(typestr));
4004 validator_log(val, ISC_LOG_DEBUG(9), "%s: creating %s for %s %s",
4005 caller, operation, namestr, typestr);
4006 }
4007