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