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