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