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