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