]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/bind9/lib/dns/validator.c
MFC r254651:
[FreeBSD/stable/9.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_verify3(name, rdataset, dstkey,
1463                                                     ISC_TRUE,
1464                                                     val->view->maxbits,
1465                                                     mctx, &sigrdata,
1466                                                     dns_fixedname_name(&fixed));
1467                         dst_key_free(&dstkey);
1468                         if (result != ISC_R_SUCCESS)
1469                                 continue;
1470                         if ((key.flags & DNS_KEYFLAG_REVOKE) == 0) {
1471                                 answer = ISC_TRUE;
1472                                 continue;
1473                         }
1474                         dns_view_untrust(val->view, name, &key, mctx);
1475                 }
1476         }
1477         return (answer);
1478 }
1479
1480 /*%
1481  * Attempt to verify the rdataset using the given key and rdata (RRSIG).
1482  * The signature was good and from a wildcard record and the QNAME does
1483  * not match the wildcard we need to look for a NOQNAME proof.
1484  *
1485  * Returns:
1486  * \li  ISC_R_SUCCESS if the verification succeeds.
1487  * \li  Others if the verification fails.
1488  */
1489 static isc_result_t
1490 verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata,
1491        isc_uint16_t keyid)
1492 {
1493         isc_result_t result;
1494         dns_fixedname_t fixed;
1495         isc_boolean_t ignore = ISC_FALSE;
1496         dns_name_t *wild;
1497
1498         val->attributes |= VALATTR_TRIEDVERIFY;
1499         dns_fixedname_init(&fixed);
1500         wild = dns_fixedname_name(&fixed);
1501  again:
1502         result = dns_dnssec_verify3(val->event->name, val->event->rdataset,
1503                                     key, ignore, val->view->maxbits,
1504                                     val->view->mctx, rdata, wild);
1505         if ((result == DNS_R_SIGEXPIRED || result == DNS_R_SIGFUTURE) &&
1506             val->view->acceptexpired)
1507         {
1508                 ignore = ISC_TRUE;
1509                 goto again;
1510         }
1511         if (ignore && (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD))
1512                 validator_log(val, ISC_LOG_INFO,
1513                               "accepted expired %sRRSIG (keyid=%u)",
1514                               (result == DNS_R_FROMWILDCARD) ?
1515                               "wildcard " : "", keyid);
1516         else if (result == DNS_R_SIGEXPIRED || result == DNS_R_SIGFUTURE)
1517                 validator_log(val, ISC_LOG_INFO,
1518                               "verify failed due to bad signature (keyid=%u): "
1519                               "%s", keyid, isc_result_totext(result));
1520         else
1521                 validator_log(val, ISC_LOG_DEBUG(3),
1522                               "verify rdataset (keyid=%u): %s",
1523                               keyid, isc_result_totext(result));
1524         if (result == DNS_R_FROMWILDCARD) {
1525                 if (!dns_name_equal(val->event->name, wild)) {
1526                         dns_name_t *closest;
1527                         unsigned int labels;
1528
1529                         /*
1530                          * Compute the closest encloser in case we need it
1531                          * for the NSEC3 NOQNAME proof.
1532                          */
1533                         closest = dns_fixedname_name(&val->closest);
1534                         dns_name_copy(wild, closest, NULL);
1535                         labels = dns_name_countlabels(closest) - 1;
1536                         dns_name_getlabelsequence(closest, 1, labels, closest);
1537                         val->attributes |= VALATTR_NEEDNOQNAME;
1538                 }
1539                 result = ISC_R_SUCCESS;
1540         }
1541         return (result);
1542 }
1543
1544 /*%
1545  * Attempts positive response validation of a normal RRset.
1546  *
1547  * Returns:
1548  * \li  ISC_R_SUCCESS   Validation completed successfully
1549  * \li  DNS_R_WAIT      Validation has started but is waiting
1550  *                      for an event.
1551  * \li  Other return codes are possible and all indicate failure.
1552  */
1553 static isc_result_t
1554 validate(dns_validator_t *val, isc_boolean_t resume) {
1555         isc_result_t result;
1556         dns_validatorevent_t *event;
1557         dns_rdata_t rdata = DNS_RDATA_INIT;
1558
1559         /*
1560          * Caller must be holding the validator lock.
1561          */
1562
1563         event = val->event;
1564
1565         if (resume) {
1566                 /*
1567                  * We already have a sigrdataset.
1568                  */
1569                 result = ISC_R_SUCCESS;
1570                 validator_log(val, ISC_LOG_DEBUG(3), "resuming validate");
1571         } else {
1572                 result = dns_rdataset_first(event->sigrdataset);
1573         }
1574
1575         for (;
1576              result == ISC_R_SUCCESS;
1577              result = dns_rdataset_next(event->sigrdataset))
1578         {
1579                 dns_rdata_reset(&rdata);
1580                 dns_rdataset_current(event->sigrdataset, &rdata);
1581                 if (val->siginfo == NULL) {
1582                         val->siginfo = isc_mem_get(val->view->mctx,
1583                                                    sizeof(*val->siginfo));
1584                         if (val->siginfo == NULL)
1585                                 return (ISC_R_NOMEMORY);
1586                 }
1587                 result = dns_rdata_tostruct(&rdata, val->siginfo, NULL);
1588                 if (result != ISC_R_SUCCESS)
1589                         return (result);
1590
1591                 /*
1592                  * At this point we could check that the signature algorithm
1593                  * was known and "sufficiently good".
1594                  */
1595                 if (!dns_resolver_algorithm_supported(val->view->resolver,
1596                                                     event->name,
1597                                                     val->siginfo->algorithm)) {
1598                         resume = ISC_FALSE;
1599                         continue;
1600                 }
1601
1602                 if (!resume) {
1603                         result = get_key(val, val->siginfo);
1604                         if (result == DNS_R_CONTINUE)
1605                                 continue; /* Try the next SIG RR. */
1606                         if (result != ISC_R_SUCCESS)
1607                                 return (result);
1608                 }
1609
1610                 /*
1611                  * There isn't a secure DNSKEY for this signature so move
1612                  * onto the next RRSIG.
1613                  */
1614                 if (val->key == NULL) {
1615                         resume = ISC_FALSE;
1616                         continue;
1617                 }
1618
1619                 do {
1620                         result = verify(val, val->key, &rdata,
1621                                         val->siginfo->keyid);
1622                         if (result == ISC_R_SUCCESS)
1623                                 break;
1624                         if (val->keynode != NULL) {
1625                                 dns_keynode_t *nextnode = NULL;
1626                                 result = dns_keytable_findnextkeynode(
1627                                                         val->keytable,
1628                                                         val->keynode,
1629                                                         &nextnode);
1630                                 dns_keytable_detachkeynode(val->keytable,
1631                                                            &val->keynode);
1632                                 val->keynode = nextnode;
1633                                 if (result != ISC_R_SUCCESS) {
1634                                         val->key = NULL;
1635                                         break;
1636                                 }
1637                                 val->key = dns_keynode_key(val->keynode);
1638                                 if (val->key == NULL)
1639                                         break;
1640                         } else {
1641                                 if (get_dst_key(val, val->siginfo, val->keyset)
1642                                     != ISC_R_SUCCESS)
1643                                         break;
1644                         }
1645                 } while (1);
1646                 if (result != ISC_R_SUCCESS)
1647                         validator_log(val, ISC_LOG_DEBUG(3),
1648                                       "failed to verify rdataset");
1649                 else {
1650                         isc_stdtime_t now;
1651
1652                         isc_stdtime_get(&now);
1653                         dns_rdataset_trimttl(event->rdataset,
1654                                              event->sigrdataset,
1655                                              val->siginfo, now,
1656                                              val->view->acceptexpired);
1657                 }
1658
1659                 if (val->keynode != NULL)
1660                         dns_keytable_detachkeynode(val->keytable,
1661                                                    &val->keynode);
1662                 else {
1663                         if (val->key != NULL)
1664                                 dst_key_free(&val->key);
1665                         if (val->keyset != NULL) {
1666                                 dns_rdataset_disassociate(val->keyset);
1667                                 val->keyset = NULL;
1668                         }
1669                 }
1670                 val->key = NULL;
1671                 if (NEEDNOQNAME(val)) {
1672                         if (val->event->message == NULL) {
1673                                 validator_log(val, ISC_LOG_DEBUG(3),
1674                                       "no message available for noqname proof");
1675                                 return (DNS_R_NOVALIDSIG);
1676                         }
1677                         validator_log(val, ISC_LOG_DEBUG(3),
1678                                       "looking for noqname proof");
1679                         return (nsecvalidate(val, ISC_FALSE));
1680                 } else if (result == ISC_R_SUCCESS) {
1681                         marksecure(event);
1682                         validator_log(val, ISC_LOG_DEBUG(3),
1683                                       "marking as secure, "
1684                                       "noqname proof not needed");
1685                         return (result);
1686                 } else {
1687                         validator_log(val, ISC_LOG_DEBUG(3),
1688                                       "verify failure: %s",
1689                                       isc_result_totext(result));
1690                         resume = ISC_FALSE;
1691                 }
1692         }
1693         if (result != ISC_R_NOMORE) {
1694                 validator_log(val, ISC_LOG_DEBUG(3),
1695                               "failed to iterate signatures: %s",
1696                               isc_result_totext(result));
1697                 return (result);
1698         }
1699
1700         validator_log(val, ISC_LOG_INFO, "no valid signature found");
1701         return (DNS_R_NOVALIDSIG);
1702 }
1703
1704 /*%
1705  * Check whether this DNSKEY (keyrdata) signed the DNSKEY RRset
1706  * (val->event->rdataset).
1707  */
1708 static isc_result_t
1709 checkkey(dns_validator_t *val, dns_rdata_t *keyrdata, isc_uint16_t keyid,
1710          dns_secalg_t algorithm)
1711 {
1712         dns_rdata_rrsig_t sig;
1713         dst_key_t *dstkey = NULL;
1714         isc_result_t result;
1715
1716         for (result = dns_rdataset_first(val->event->sigrdataset);
1717              result == ISC_R_SUCCESS;
1718              result = dns_rdataset_next(val->event->sigrdataset))
1719         {
1720                 dns_rdata_t rdata = DNS_RDATA_INIT;
1721
1722                 dns_rdataset_current(val->event->sigrdataset, &rdata);
1723                 result = dns_rdata_tostruct(&rdata, &sig, NULL);
1724                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1725                 if (keyid != sig.keyid || algorithm != sig.algorithm)
1726                         continue;
1727                 if (dstkey == NULL) {
1728                         result = dns_dnssec_keyfromrdata(val->event->name,
1729                                                          keyrdata,
1730                                                          val->view->mctx,
1731                                                          &dstkey);
1732                         if (result != ISC_R_SUCCESS)
1733                                 /*
1734                                  * This really shouldn't happen, but...
1735                                  */
1736                                 continue;
1737                 }
1738                 result = verify(val, dstkey, &rdata, sig.keyid);
1739                 if (result == ISC_R_SUCCESS)
1740                         break;
1741         }
1742         if (dstkey != NULL)
1743                 dst_key_free(&dstkey);
1744         return (result);
1745 }
1746
1747 /*%
1748  * Find the DNSKEY that corresponds to the DS.
1749  */
1750 static isc_result_t
1751 keyfromds(dns_validator_t *val, dns_rdataset_t *rdataset, dns_rdata_t *dsrdata,
1752           isc_uint8_t digest, isc_uint16_t keyid, dns_secalg_t algorithm,
1753           dns_rdata_t *keyrdata)
1754 {
1755         dns_keytag_t keytag;
1756         dns_rdata_dnskey_t key;
1757         isc_result_t result;
1758         unsigned char dsbuf[DNS_DS_BUFFERSIZE];
1759
1760         for (result = dns_rdataset_first(rdataset);
1761              result == ISC_R_SUCCESS;
1762              result = dns_rdataset_next(rdataset))
1763         {
1764                 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
1765
1766                 dns_rdata_reset(keyrdata);
1767                 dns_rdataset_current(rdataset, keyrdata);
1768                 result = dns_rdata_tostruct(keyrdata, &key, NULL);
1769                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1770                 keytag = compute_keytag(keyrdata, &key);
1771                 if (keyid != keytag || algorithm != key.algorithm)
1772                         continue;
1773                 dns_rdata_reset(&newdsrdata);
1774                 result = dns_ds_buildrdata(val->event->name, keyrdata, digest,
1775                                            dsbuf, &newdsrdata);
1776                 if (result != ISC_R_SUCCESS) {
1777                         validator_log(val, ISC_LOG_DEBUG(3),
1778                                       "dns_ds_buildrdata() -> %s",
1779                                       dns_result_totext(result));
1780                         continue;
1781                 }
1782                 if (dns_rdata_compare(dsrdata, &newdsrdata) == 0)
1783                         break;
1784         }
1785         return (result);
1786 }
1787
1788 /*%
1789  * Validate the DNSKEY RRset by looking for a DNSKEY that matches a
1790  * DLV record and that also verifies the DNSKEY RRset.
1791  */
1792 static isc_result_t
1793 dlv_validatezonekey(dns_validator_t *val) {
1794         dns_rdata_dlv_t dlv;
1795         dns_rdata_t dlvrdata = DNS_RDATA_INIT;
1796         dns_rdata_t keyrdata = DNS_RDATA_INIT;
1797         dns_rdataset_t trdataset;
1798         isc_boolean_t supported_algorithm;
1799         isc_result_t result;
1800         char digest_types[256];
1801
1802         validator_log(val, ISC_LOG_DEBUG(3), "dlv_validatezonekey");
1803
1804         /*
1805          * Look through the DLV record and find the keys that can sign the
1806          * key set and the matching signature.  For each such key, attempt
1807          * verification.
1808          */
1809         supported_algorithm = ISC_FALSE;
1810
1811         /*
1812          * If DNS_DSDIGEST_SHA256 is present we are required to prefer
1813          * it over DNS_DSDIGEST_SHA1.  This in practice means that we
1814          * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
1815          * is present.
1816          */
1817         memset(digest_types, 1, sizeof(digest_types));
1818         for (result = dns_rdataset_first(&val->dlv);
1819              result == ISC_R_SUCCESS;
1820              result = dns_rdataset_next(&val->dlv)) {
1821                 dns_rdata_reset(&dlvrdata);
1822                 dns_rdataset_current(&val->dlv, &dlvrdata);
1823                 result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
1824                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1825
1826                 if (!dns_resolver_algorithm_supported(val->view->resolver,
1827                                                       val->event->name,
1828                                                       dlv.algorithm))
1829                         continue;
1830
1831                 if (dlv.digest_type == DNS_DSDIGEST_SHA256 &&
1832                     dlv.length == ISC_SHA256_DIGESTLENGTH) {
1833                         digest_types[DNS_DSDIGEST_SHA1] = 0;
1834                         break;
1835                 }
1836         }
1837
1838         for (result = dns_rdataset_first(&val->dlv);
1839              result == ISC_R_SUCCESS;
1840              result = dns_rdataset_next(&val->dlv))
1841         {
1842                 dns_rdata_reset(&dlvrdata);
1843                 dns_rdataset_current(&val->dlv, &dlvrdata);
1844                 result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
1845                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1846
1847                 if (!dns_resolver_digest_supported(val->view->resolver,
1848                                                    dlv.digest_type))
1849                         continue;
1850
1851                 if (digest_types[dlv.digest_type] == 0)
1852                         continue;
1853
1854                 if (!dns_resolver_algorithm_supported(val->view->resolver,
1855                                                       val->event->name,
1856                                                       dlv.algorithm))
1857                         continue;
1858
1859                 supported_algorithm = ISC_TRUE;
1860
1861                 dns_rdataset_init(&trdataset);
1862                 dns_rdataset_clone(val->event->rdataset, &trdataset);
1863
1864                 /*
1865                  * Convert to DLV to DS and find matching DNSKEY.
1866                  */
1867                 dlvrdata.type = dns_rdatatype_ds;
1868                 result = keyfromds(val, &trdataset, &dlvrdata,
1869                                    dlv.digest_type, dlv.key_tag,
1870                                    dlv.algorithm, &keyrdata);
1871                 if (result != ISC_R_SUCCESS) {
1872                         dns_rdataset_disassociate(&trdataset);
1873                         validator_log(val, ISC_LOG_DEBUG(3),
1874                                       "no DNSKEY matching DLV");
1875                         continue;
1876                 }
1877
1878                 validator_log(val, ISC_LOG_DEBUG(3),
1879                       "Found matching DLV record: checking for signature");
1880                 /*
1881                  * Check that this DNSKEY signed the DNSKEY rrset.
1882                  */
1883                 result = checkkey(val, &keyrdata, dlv.key_tag, dlv.algorithm);
1884
1885                 dns_rdataset_disassociate(&trdataset);
1886                 if (result == ISC_R_SUCCESS)
1887                         break;
1888                 validator_log(val, ISC_LOG_DEBUG(3),
1889                               "no RRSIG matching DLV key");
1890         }
1891         if (result == ISC_R_SUCCESS) {
1892                 marksecure(val->event);
1893                 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (dlv)");
1894                 return (result);
1895         } else if (result == ISC_R_NOMORE && !supported_algorithm) {
1896                 if (val->mustbesecure) {
1897                         validator_log(val, ISC_LOG_WARNING,
1898                                       "must be secure failure,"
1899                                       "no supported algorithm/digest (dlv)");
1900                         return (DNS_R_MUSTBESECURE);
1901                 }
1902                 validator_log(val, ISC_LOG_DEBUG(3),
1903                               "no supported algorithm/digest (dlv)");
1904                 markanswer(val, "dlv_validatezonekey (2)");
1905                 return (ISC_R_SUCCESS);
1906         } else
1907                 return (DNS_R_NOVALIDSIG);
1908 }
1909
1910 /*%
1911  * Attempts positive response validation of an RRset containing zone keys
1912  * (i.e. a DNSKEY rrset).
1913  *
1914  * Returns:
1915  * \li  ISC_R_SUCCESS   Validation completed successfully
1916  * \li  DNS_R_WAIT      Validation has started but is waiting
1917  *                      for an event.
1918  * \li  Other return codes are possible and all indicate failure.
1919  */
1920 static isc_result_t
1921 validatezonekey(dns_validator_t *val) {
1922         isc_result_t result;
1923         dns_validatorevent_t *event;
1924         dns_rdataset_t trdataset;
1925         dns_rdata_t dsrdata = DNS_RDATA_INIT;
1926         dns_rdata_t keyrdata = DNS_RDATA_INIT;
1927         dns_rdata_t sigrdata = DNS_RDATA_INIT;
1928         char namebuf[DNS_NAME_FORMATSIZE];
1929         dns_rdata_ds_t ds;
1930         dns_rdata_rrsig_t sig;
1931         dst_key_t *dstkey;
1932         isc_boolean_t supported_algorithm;
1933         isc_boolean_t atsep = ISC_FALSE;
1934         char digest_types[256];
1935
1936         /*
1937          * Caller must be holding the validator lock.
1938          */
1939
1940         event = val->event;
1941
1942         if (val->havedlvsep && val->dlv.trust >= dns_trust_secure &&
1943             dns_name_equal(event->name, dns_fixedname_name(&val->dlvsep)))
1944                 return (dlv_validatezonekey(val));
1945
1946         if (val->dsset == NULL) {
1947
1948                 /*
1949                  * We have a dlv sep.  Skip looking up the SEP from
1950                  * {trusted,managed}-keys.  If the dlv sep is for the
1951                  * root then it will have been handled above so we don't
1952                  * need to check whether val->event->name is "." prior to
1953                  * looking up the DS.
1954                  */
1955                 if (val->havedlvsep)
1956                         goto find_ds;
1957
1958                 /*
1959                  * First, see if this key was signed by a trusted key.
1960                  */
1961                 for (result = dns_rdataset_first(val->event->sigrdataset);
1962                      result == ISC_R_SUCCESS;
1963                      result = dns_rdataset_next(val->event->sigrdataset))
1964                 {
1965                         dns_keynode_t *keynode = NULL;
1966                         dns_fixedname_t fixed;
1967                         dns_name_t *found;
1968
1969                         dns_fixedname_init(&fixed);
1970                         found = dns_fixedname_name(&fixed);
1971                         dns_rdata_reset(&sigrdata);
1972                         dns_rdataset_current(val->event->sigrdataset,
1973                                              &sigrdata);
1974                         result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
1975                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
1976
1977                         if (!dns_name_equal(val->event->name, &sig.signer))
1978                                 continue;
1979
1980                         result = dns_keytable_findkeynode(val->keytable,
1981                                                           val->event->name,
1982                                                           sig.algorithm,
1983                                                           sig.keyid, &keynode);
1984                         if (result == ISC_R_NOTFOUND &&
1985                             dns_keytable_finddeepestmatch(val->keytable,
1986                                   val->event->name, found) != ISC_R_SUCCESS) {
1987                                 if (val->mustbesecure) {
1988                                         validator_log(val, ISC_LOG_WARNING,
1989                                                      "must be secure failure, "
1990                                                      "not beneath secure root");
1991                                         return (DNS_R_MUSTBESECURE);
1992                                 } else
1993                                         validator_log(val, ISC_LOG_DEBUG(3),
1994                                                      "not beneath secure root");
1995                                 if (val->view->dlv == NULL) {
1996                                         markanswer(val, "validatezonekey (1)");
1997                                         return (ISC_R_SUCCESS);
1998                                 }
1999                                 return (startfinddlvsep(val, dns_rootname));
2000                         }
2001                         if (result == DNS_R_PARTIALMATCH ||
2002                             result == ISC_R_SUCCESS)
2003                                 atsep = ISC_TRUE;
2004                         while (result == ISC_R_SUCCESS) {
2005                                 dns_keynode_t *nextnode = NULL;
2006                                 dstkey = dns_keynode_key(keynode);
2007                                 if (dstkey == NULL) {
2008                                         dns_keytable_detachkeynode(
2009                                                                 val->keytable,
2010                                                                 &keynode);
2011                                         break;
2012                                 }
2013                                 result = verify(val, dstkey, &sigrdata,
2014                                                 sig.keyid);
2015                                 if (result == ISC_R_SUCCESS) {
2016                                         dns_keytable_detachkeynode(
2017                                                                 val->keytable,
2018                                                                 &keynode);
2019                                         break;
2020                                 }
2021                                 result = dns_keytable_findnextkeynode(
2022                                                                 val->keytable,
2023                                                                 keynode,
2024                                                                 &nextnode);
2025                                 dns_keytable_detachkeynode(val->keytable,
2026                                                            &keynode);
2027                                 keynode = nextnode;
2028                         }
2029                         if (result == ISC_R_SUCCESS) {
2030                                 marksecure(event);
2031                                 validator_log(val, ISC_LOG_DEBUG(3),
2032                                               "signed by trusted key; "
2033                                               "marking as secure");
2034                                 return (result);
2035                         }
2036                 }
2037
2038                 if (atsep) {
2039                         /*
2040                          * We have not found a key to verify this DNSKEY
2041                          * RRset.  As this is a SEP we have to assume that
2042                          * the RRset is invalid.
2043                          */
2044                         dns_name_format(val->event->name, namebuf,
2045                                         sizeof(namebuf));
2046                         validator_log(val, ISC_LOG_NOTICE,
2047                                       "unable to find a DNSKEY which verifies "
2048                                       "the DNSKEY RRset and also matches a "
2049                                       "trusted key for '%s'",
2050                                       namebuf);
2051                         validator_log(val, ISC_LOG_NOTICE,
2052                                       "please check the 'trusted-keys' for "
2053                                       "'%s' in named.conf.", namebuf);
2054                         return (DNS_R_NOVALIDKEY);
2055                 }
2056
2057                 /*
2058                  * If this is the root name and there was no trusted key,
2059                  * give up, since there's no DS at the root.
2060                  */
2061                 if (dns_name_equal(event->name, dns_rootname)) {
2062                         if ((val->attributes & VALATTR_TRIEDVERIFY) != 0) {
2063                                 validator_log(val, ISC_LOG_DEBUG(3),
2064                                               "root key failed to validate");
2065                                 return (DNS_R_NOVALIDSIG);
2066                         } else {
2067                                 validator_log(val, ISC_LOG_DEBUG(3),
2068                                               "no trusted root key");
2069                                 return (DNS_R_NOVALIDDS);
2070                         }
2071                 }
2072  find_ds:
2073                 /*
2074                  * Otherwise, try to find the DS record.
2075                  */
2076                 result = view_find(val, val->event->name, dns_rdatatype_ds);
2077                 if (result == ISC_R_SUCCESS) {
2078                         /*
2079                          * We have DS records.
2080                          */
2081                         val->dsset = &val->frdataset;
2082                         if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
2083                              DNS_TRUST_ANSWER(val->frdataset.trust)) &&
2084                             dns_rdataset_isassociated(&val->fsigrdataset))
2085                         {
2086                                 result = create_validator(val,
2087                                                           val->event->name,
2088                                                           dns_rdatatype_ds,
2089                                                           &val->frdataset,
2090                                                           &val->fsigrdataset,
2091                                                           dsvalidated,
2092                                                           "validatezonekey");
2093                                 if (result != ISC_R_SUCCESS)
2094                                         return (result);
2095                                 return (DNS_R_WAIT);
2096                         } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
2097                                 /*
2098                                  * There should never be an unsigned DS.
2099                                  */
2100                                 dns_rdataset_disassociate(&val->frdataset);
2101                                 validator_log(val, ISC_LOG_DEBUG(2),
2102                                               "unsigned DS record");
2103                                 return (DNS_R_NOVALIDSIG);
2104                         } else {
2105                                 result = ISC_R_SUCCESS;
2106                                 POST(result);
2107                         }
2108                 } else if (result == ISC_R_NOTFOUND) {
2109                         /*
2110                          * We don't have the DS.  Find it.
2111                          */
2112                         result = create_fetch(val, val->event->name,
2113                                               dns_rdatatype_ds, dsfetched,
2114                                               "validatezonekey");
2115                         if (result != ISC_R_SUCCESS)
2116                                 return (result);
2117                         return (DNS_R_WAIT);
2118                 } else if (result == DNS_R_NCACHENXDOMAIN ||
2119                            result == DNS_R_NCACHENXRRSET ||
2120                            result == DNS_R_EMPTYNAME ||
2121                            result == DNS_R_NXDOMAIN ||
2122                            result == DNS_R_NXRRSET ||
2123                            result == DNS_R_CNAME)
2124                 {
2125                         /*
2126                          * The DS does not exist.
2127                          */
2128                         if (dns_rdataset_isassociated(&val->frdataset))
2129                                 dns_rdataset_disassociate(&val->frdataset);
2130                         if (dns_rdataset_isassociated(&val->fsigrdataset))
2131                                 dns_rdataset_disassociate(&val->fsigrdataset);
2132                         validator_log(val, ISC_LOG_DEBUG(2), "no DS record");
2133                         return (DNS_R_NOVALIDSIG);
2134                 } else if (result == DNS_R_BROKENCHAIN)
2135                         return (result);
2136         }
2137
2138         /*
2139          * We have a DS set.
2140          */
2141         INSIST(val->dsset != NULL);
2142
2143         if (val->dsset->trust < dns_trust_secure) {
2144                 if (val->mustbesecure) {
2145                         validator_log(val, ISC_LOG_WARNING,
2146                                       "must be secure failure,"
2147                                       " insecure DS");
2148                         return (DNS_R_MUSTBESECURE);
2149                 }
2150                 if (val->view->dlv == NULL || DLVTRIED(val)) {
2151                         markanswer(val, "validatezonekey (2)");
2152                         return (ISC_R_SUCCESS);
2153                 }
2154                 return (startfinddlvsep(val, val->event->name));
2155         }
2156
2157         /*
2158          * Look through the DS record and find the keys that can sign the
2159          * key set and the matching signature.  For each such key, attempt
2160          * verification.
2161          */
2162
2163         supported_algorithm = ISC_FALSE;
2164
2165         /*
2166          * If DNS_DSDIGEST_SHA256 is present we are required to prefer
2167          * it over DNS_DSDIGEST_SHA1.  This in practice means that we
2168          * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
2169          * is present.
2170          */
2171         memset(digest_types, 1, sizeof(digest_types));
2172         for (result = dns_rdataset_first(val->dsset);
2173              result == ISC_R_SUCCESS;
2174              result = dns_rdataset_next(val->dsset)) {
2175                 dns_rdata_reset(&dsrdata);
2176                 dns_rdataset_current(val->dsset, &dsrdata);
2177                 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
2178                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2179
2180                 if (!dns_resolver_algorithm_supported(val->view->resolver,
2181                                                       val->event->name,
2182                                                       ds.algorithm))
2183                         continue;
2184
2185                 if (ds.digest_type == DNS_DSDIGEST_SHA256 &&
2186                     ds.length == ISC_SHA256_DIGESTLENGTH) {
2187                         digest_types[DNS_DSDIGEST_SHA1] = 0;
2188                         break;
2189                 }
2190         }
2191
2192         for (result = dns_rdataset_first(val->dsset);
2193              result == ISC_R_SUCCESS;
2194              result = dns_rdataset_next(val->dsset))
2195         {
2196                 dns_rdata_reset(&dsrdata);
2197                 dns_rdataset_current(val->dsset, &dsrdata);
2198                 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
2199                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2200
2201                 if (!dns_resolver_digest_supported(val->view->resolver,
2202                                                    ds.digest_type))
2203                         continue;
2204
2205                 if (digest_types[ds.digest_type] == 0)
2206                         continue;
2207
2208                 if (!dns_resolver_algorithm_supported(val->view->resolver,
2209                                                       val->event->name,
2210                                                       ds.algorithm))
2211                         continue;
2212
2213                 supported_algorithm = ISC_TRUE;
2214
2215                 dns_rdataset_init(&trdataset);
2216                 dns_rdataset_clone(val->event->rdataset, &trdataset);
2217
2218                 /*
2219                  * Find matching DNSKEY from DS.
2220                  */
2221                 result = keyfromds(val, &trdataset, &dsrdata, ds.digest_type,
2222                                    ds.key_tag, ds.algorithm, &keyrdata);
2223                 if (result != ISC_R_SUCCESS) {
2224                         dns_rdataset_disassociate(&trdataset);
2225                         validator_log(val, ISC_LOG_DEBUG(3),
2226                                       "no DNSKEY matching DS");
2227                         continue;
2228                 }
2229
2230                 /*
2231                  * Check that this DNSKEY signed the DNSKEY rrset.
2232                  */
2233                 result = checkkey(val, &keyrdata, ds.key_tag, ds.algorithm);
2234
2235                 dns_rdataset_disassociate(&trdataset);
2236                 if (result == ISC_R_SUCCESS)
2237                         break;
2238                 validator_log(val, ISC_LOG_DEBUG(3),
2239                               "no RRSIG matching DS key");
2240         }
2241         if (result == ISC_R_SUCCESS) {
2242                 marksecure(event);
2243                 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (DS)");
2244                 return (result);
2245         } else if (result == ISC_R_NOMORE && !supported_algorithm) {
2246                 if (val->mustbesecure) {
2247                         validator_log(val, ISC_LOG_WARNING,
2248                                       "must be secure failure, "
2249                                       "no supported algorithm/digest (DS)");
2250                         return (DNS_R_MUSTBESECURE);
2251                 }
2252                 validator_log(val, ISC_LOG_DEBUG(3),
2253                               "no supported algorithm/digest (DS)");
2254                 markanswer(val, "validatezonekey (3)");
2255                 return (ISC_R_SUCCESS);
2256         } else {
2257                 validator_log(val, ISC_LOG_INFO,
2258                               "no valid signature found (DS)");
2259                 return (DNS_R_NOVALIDSIG);
2260         }
2261 }
2262
2263 /*%
2264  * Starts a positive response validation.
2265  *
2266  * Returns:
2267  * \li  ISC_R_SUCCESS   Validation completed successfully
2268  * \li  DNS_R_WAIT      Validation has started but is waiting
2269  *                      for an event.
2270  * \li  Other return codes are possible and all indicate failure.
2271  */
2272 static isc_result_t
2273 start_positive_validation(dns_validator_t *val) {
2274         /*
2275          * If this is not a key, go straight into validate().
2276          */
2277         if (val->event->type != dns_rdatatype_dnskey || !isselfsigned(val))
2278                 return (validate(val, ISC_FALSE));
2279
2280         return (validatezonekey(val));
2281 }
2282
2283 /*%
2284  * val_rdataset_first and val_rdataset_next provide iteration methods
2285  * that hide whether we are iterating across a message or a  negative
2286  * cache rdataset.
2287  */
2288 static isc_result_t
2289 val_rdataset_first(dns_validator_t *val, dns_name_t **namep,
2290                    dns_rdataset_t **rdatasetp)
2291 {
2292         dns_message_t *message = val->event->message;
2293         isc_result_t result;
2294
2295         REQUIRE(rdatasetp != NULL);
2296         REQUIRE(namep != NULL);
2297         if (message == NULL) {
2298                 REQUIRE(*rdatasetp != NULL);
2299                 REQUIRE(*namep != NULL);
2300         } else {
2301                 REQUIRE(*rdatasetp == NULL);
2302                 REQUIRE(*namep == NULL);
2303         }
2304
2305         if (message != NULL) {
2306                 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2307                 if (result != ISC_R_SUCCESS)
2308                         return (result);
2309                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, namep);
2310                 *rdatasetp = ISC_LIST_HEAD((*namep)->list);
2311                 INSIST(*rdatasetp != NULL);
2312         } else {
2313                 result = dns_rdataset_first(val->event->rdataset);
2314                 if (result == ISC_R_SUCCESS)
2315                         dns_ncache_current(val->event->rdataset, *namep,
2316                                            *rdatasetp);
2317         }
2318         return (result);
2319 }
2320
2321 static isc_result_t
2322 val_rdataset_next(dns_validator_t *val, dns_name_t **namep,
2323                   dns_rdataset_t **rdatasetp)
2324 {
2325         dns_message_t *message = val->event->message;
2326         isc_result_t result = ISC_R_SUCCESS;
2327
2328         REQUIRE(rdatasetp != NULL && *rdatasetp != NULL);
2329         REQUIRE(namep != NULL && *namep != NULL);
2330
2331         if (message != NULL) {
2332                 dns_rdataset_t *rdataset = *rdatasetp;
2333                 rdataset = ISC_LIST_NEXT(rdataset, link);
2334                 if (rdataset == NULL) {
2335                         *namep = NULL;
2336                         result = dns_message_nextname(message,
2337                                                       DNS_SECTION_AUTHORITY);
2338                         if (result == ISC_R_SUCCESS) {
2339                                 dns_message_currentname(message,
2340                                                         DNS_SECTION_AUTHORITY,
2341                                                         namep);
2342                                 rdataset = ISC_LIST_HEAD((*namep)->list);
2343                                 INSIST(rdataset != NULL);
2344                         }
2345                 }
2346                 *rdatasetp = rdataset;
2347         } else {
2348                 dns_rdataset_disassociate(*rdatasetp);
2349                 result = dns_rdataset_next(val->event->rdataset);
2350                 if (result == ISC_R_SUCCESS)
2351                         dns_ncache_current(val->event->rdataset, *namep,
2352                                            *rdatasetp);
2353         }
2354         return (result);
2355 }
2356
2357 /*%
2358  * Look for NODATA at the wildcard and NOWILDCARD proofs in the
2359  * previously validated NSEC records.  As these proofs are mutually
2360  * exclusive we stop when one is found.
2361  *
2362  * Returns
2363  * \li  ISC_R_SUCCESS
2364  */
2365 static isc_result_t
2366 checkwildcard(dns_validator_t *val, dns_rdatatype_t type, dns_name_t *zonename)
2367 {
2368         dns_name_t *name, *wild, tname;
2369         isc_result_t result;
2370         isc_boolean_t exists, data;
2371         char namebuf[DNS_NAME_FORMATSIZE];
2372         dns_rdataset_t *rdataset, trdataset;
2373
2374         dns_name_init(&tname, NULL);
2375         dns_rdataset_init(&trdataset);
2376         wild = dns_fixedname_name(&val->wild);
2377
2378         if (dns_name_countlabels(wild) == 0) {
2379                 validator_log(val, ISC_LOG_DEBUG(3),
2380                               "in checkwildcard: no wildcard to check");
2381                 return (ISC_R_SUCCESS);
2382         }
2383
2384         dns_name_format(wild, namebuf, sizeof(namebuf));
2385         validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf);
2386
2387         if (val->event->message == NULL) {
2388                 name = &tname;
2389                 rdataset = &trdataset;
2390         } else {
2391                 name = NULL;
2392                 rdataset = NULL;
2393         }
2394
2395         for (result = val_rdataset_first(val, &name, &rdataset);
2396              result == ISC_R_SUCCESS;
2397              result = val_rdataset_next(val, &name, &rdataset))
2398         {
2399                 if (rdataset->type != type ||
2400                     rdataset->trust != dns_trust_secure)
2401                         continue;
2402
2403                 if (rdataset->type == dns_rdatatype_nsec &&
2404                     (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
2405                     !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
2406                     dns_nsec_noexistnodata(val->event->type, wild, name,
2407                                            rdataset, &exists, &data, NULL,
2408                                            validator_log, val)
2409                                        == ISC_R_SUCCESS)
2410                 {
2411                         dns_name_t **proofs = val->event->proofs;
2412                         if (exists && !data)
2413                                 val->attributes |= VALATTR_FOUNDNODATA;
2414                         if (exists && !data && NEEDNODATA(val))
2415                                 proofs[DNS_VALIDATOR_NODATAPROOF] =
2416                                                  name;
2417                         if (!exists)
2418                                 val->attributes |=
2419                                          VALATTR_FOUNDNOWILDCARD;
2420                         if (!exists && NEEDNOQNAME(val))
2421                                 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
2422                                                  name;
2423                         if (dns_rdataset_isassociated(&trdataset))
2424                                 dns_rdataset_disassociate(&trdataset);
2425                         return (ISC_R_SUCCESS);
2426                 }
2427
2428                 if (rdataset->type == dns_rdatatype_nsec3 &&
2429                     (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
2430                     !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
2431                     dns_nsec3_noexistnodata(val->event->type, wild, name,
2432                                             rdataset, zonename, &exists, &data,
2433                                             NULL, NULL, NULL, NULL, NULL, NULL,
2434                                             validator_log, val)
2435                                             == ISC_R_SUCCESS)
2436                 {
2437                         dns_name_t **proofs = val->event->proofs;
2438                         if (exists && !data)
2439                                 val->attributes |= VALATTR_FOUNDNODATA;
2440                         if (exists && !data && NEEDNODATA(val))
2441                                 proofs[DNS_VALIDATOR_NODATAPROOF] =
2442                                                  name;
2443                         if (!exists)
2444                                 val->attributes |=
2445                                          VALATTR_FOUNDNOWILDCARD;
2446                         if (!exists && NEEDNOQNAME(val))
2447                                 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
2448                                                  name;
2449                         if (dns_rdataset_isassociated(&trdataset))
2450                                 dns_rdataset_disassociate(&trdataset);
2451                         return (ISC_R_SUCCESS);
2452                 }
2453         }
2454         if (result == ISC_R_NOMORE)
2455                 result = ISC_R_SUCCESS;
2456         if (dns_rdataset_isassociated(&trdataset))
2457                 dns_rdataset_disassociate(&trdataset);
2458         return (result);
2459 }
2460
2461 static isc_result_t
2462 findnsec3proofs(dns_validator_t *val) {
2463         dns_name_t *name, tname;
2464         isc_result_t result;
2465         isc_boolean_t exists, data, optout, unknown;
2466         isc_boolean_t setclosest, setnearest, *setclosestp;
2467         dns_fixedname_t fclosest, fnearest, fzonename;
2468         dns_name_t *closest, *nearest, *zonename, *closestp;
2469         dns_name_t **proofs = val->event->proofs;
2470         dns_rdataset_t *rdataset, trdataset;
2471
2472         dns_name_init(&tname, NULL);
2473         dns_rdataset_init(&trdataset);
2474         dns_fixedname_init(&fclosest);
2475         dns_fixedname_init(&fnearest);
2476         dns_fixedname_init(&fzonename);
2477         closest = dns_fixedname_name(&fclosest);
2478         nearest = dns_fixedname_name(&fnearest);
2479         zonename = dns_fixedname_name(&fzonename);
2480
2481         if (val->event->message == NULL) {
2482                 name = &tname;
2483                 rdataset = &trdataset;
2484         } else {
2485                 name = NULL;
2486                 rdataset = NULL;
2487         }
2488
2489         for (result = val_rdataset_first(val, &name, &rdataset);
2490              result == ISC_R_SUCCESS;
2491              result = val_rdataset_next(val, &name, &rdataset))
2492         {
2493                 if (rdataset->type != dns_rdatatype_nsec3 ||
2494                     rdataset->trust != dns_trust_secure)
2495                         continue;
2496
2497                 result = dns_nsec3_noexistnodata(val->event->type,
2498                                                  val->event->name, name,
2499                                                  rdataset, zonename, NULL,
2500                                                  NULL, NULL, NULL, NULL, NULL,
2501                                                  NULL, NULL, validator_log,
2502                                                  val);
2503                 if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS) {
2504                         if (dns_rdataset_isassociated(&trdataset))
2505                                 dns_rdataset_disassociate(&trdataset);
2506                         return (result);
2507                 }
2508         }
2509         if (result != ISC_R_NOMORE)
2510                 result = ISC_R_SUCCESS;
2511         POST(result);
2512
2513         if (dns_name_countlabels(zonename) == 0)
2514                 return (ISC_R_SUCCESS);
2515
2516         /*
2517          * If the val->closest is set then we want to use it otherwise
2518          * we need to discover it.
2519          */
2520         if (dns_name_countlabels(dns_fixedname_name(&val->closest)) != 0) {
2521                 char namebuf[DNS_NAME_FORMATSIZE];
2522
2523                 dns_name_format(dns_fixedname_name(&val->closest),
2524                                  namebuf, sizeof(namebuf));
2525                 validator_log(val, ISC_LOG_DEBUG(3), "closest encloser from "
2526                               "wildcard signature '%s'", namebuf);
2527                 dns_name_copy(dns_fixedname_name(&val->closest), closest, NULL);
2528                 closestp = NULL;
2529                 setclosestp = NULL;
2530         } else {
2531                 closestp = closest;
2532                 setclosestp = &setclosest;
2533         }
2534
2535         for (result = val_rdataset_first(val, &name, &rdataset);
2536              result == ISC_R_SUCCESS;
2537              result = val_rdataset_next(val, &name, &rdataset))
2538         {
2539                 if (rdataset->type != dns_rdatatype_nsec3 ||
2540                     rdataset->trust != dns_trust_secure)
2541                         continue;
2542
2543                 /*
2544                  * We process all NSEC3 records to find the closest
2545                  * encloser and nearest name to the closest encloser.
2546                  */
2547                 setclosest = setnearest = ISC_FALSE;
2548                 optout = ISC_FALSE;
2549                 unknown = ISC_FALSE;
2550                 result = dns_nsec3_noexistnodata(val->event->type,
2551                                                  val->event->name,
2552                                                  name, rdataset, zonename,
2553                                                  &exists, &data, &optout,
2554                                                  &unknown, setclosestp,
2555                                                  &setnearest, closestp,
2556                                                  nearest, validator_log, val);
2557                 if (unknown)
2558                         val->attributes |= VALATTR_FOUNDUNKNOWN;
2559                 if (result != ISC_R_SUCCESS)
2560                         continue;
2561                 if (setclosest)
2562                         proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
2563                 if (exists && !data && NEEDNODATA(val)) {
2564                         val->attributes |= VALATTR_FOUNDNODATA;
2565                         proofs[DNS_VALIDATOR_NODATAPROOF] = name;
2566                 }
2567                 if (!exists && setnearest) {
2568                         val->attributes |= VALATTR_FOUNDNOQNAME;
2569                         proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name;
2570                         if (optout)
2571                                 val->attributes |= VALATTR_FOUNDOPTOUT;
2572                 }
2573         }
2574         if (result == ISC_R_NOMORE)
2575                 result = ISC_R_SUCCESS;
2576
2577         /*
2578          * To know we have a valid noqname and optout proofs we need to also
2579          * have a valid closest encloser.  Otherwise we could still be looking
2580          * at proofs from the parent zone.
2581          */
2582         if (dns_name_countlabels(closest) > 0 &&
2583             dns_name_countlabels(nearest) ==
2584             dns_name_countlabels(closest) + 1 &&
2585             dns_name_issubdomain(nearest, closest))
2586         {
2587                 val->attributes |= VALATTR_FOUNDCLOSEST;
2588                 result = dns_name_concatenate(dns_wildcardname, closest,
2589                                               dns_fixedname_name(&val->wild),
2590                                               NULL);
2591                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2592         } else {
2593                 val->attributes &= ~VALATTR_FOUNDNOQNAME;
2594                 val->attributes &= ~VALATTR_FOUNDOPTOUT;
2595                 proofs[DNS_VALIDATOR_NOQNAMEPROOF] = NULL;
2596         }
2597
2598         /*
2599          * Do we need to check for the wildcard?
2600          */
2601         if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
2602             ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
2603                 result = checkwildcard(val, dns_rdatatype_nsec3, zonename);
2604                 if (result != ISC_R_SUCCESS)
2605                         return (result);
2606         }
2607         return (result);
2608 }
2609
2610 /*%
2611  * Validate the authority section records.
2612  */
2613 static isc_result_t
2614 validate_authority(dns_validator_t *val, isc_boolean_t resume) {
2615         dns_name_t *name;
2616         dns_message_t *message = val->event->message;
2617         isc_result_t result;
2618
2619         if (!resume)
2620                 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2621         else
2622                 result = ISC_R_SUCCESS;
2623
2624         for (;
2625              result == ISC_R_SUCCESS;
2626              result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
2627         {
2628                 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2629
2630                 name = NULL;
2631                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
2632                 if (resume) {
2633                         rdataset = ISC_LIST_NEXT(val->currentset, link);
2634                         val->currentset = NULL;
2635                         resume = ISC_FALSE;
2636                 } else
2637                         rdataset = ISC_LIST_HEAD(name->list);
2638
2639                 for (;
2640                      rdataset != NULL;
2641                      rdataset = ISC_LIST_NEXT(rdataset, link))
2642                 {
2643                         if (rdataset->type == dns_rdatatype_rrsig)
2644                                 continue;
2645
2646                         for (sigrdataset = ISC_LIST_HEAD(name->list);
2647                              sigrdataset != NULL;
2648                              sigrdataset = ISC_LIST_NEXT(sigrdataset,
2649                                                          link))
2650                         {
2651                                 if (sigrdataset->type == dns_rdatatype_rrsig &&
2652                                     sigrdataset->covers == rdataset->type)
2653                                         break;
2654                         }
2655                         /*
2656                          * If a signed zone is missing the zone key, bad
2657                          * things could happen.  A query for data in the zone
2658                          * would lead to a query for the zone key, which
2659                          * would return a negative answer, which would contain
2660                          * an SOA and an NSEC signed by the missing key, which
2661                          * would trigger another query for the DNSKEY (since
2662                          * the first one is still in progress), and go into an
2663                          * infinite loop.  Avoid that.
2664                          */
2665                         if (val->event->type == dns_rdatatype_dnskey &&
2666                             rdataset->type == dns_rdatatype_nsec &&
2667                             dns_name_equal(name, val->event->name))
2668                         {
2669                                 dns_rdata_t nsec = DNS_RDATA_INIT;
2670
2671                                 result = dns_rdataset_first(rdataset);
2672                                 if (result != ISC_R_SUCCESS)
2673                                         return (result);
2674                                 dns_rdataset_current(rdataset, &nsec);
2675                                 if (dns_nsec_typepresent(&nsec,
2676                                                         dns_rdatatype_soa))
2677                                         continue;
2678                         }
2679                         val->currentset = rdataset;
2680                         result = create_validator(val, name, rdataset->type,
2681                                                   rdataset, sigrdataset,
2682                                                   authvalidated,
2683                                                   "validate_authority");
2684                         if (result != ISC_R_SUCCESS)
2685                                 return (result);
2686                         val->authcount++;
2687                         return (DNS_R_WAIT);
2688                 }
2689         }
2690         if (result == ISC_R_NOMORE)
2691                 result = ISC_R_SUCCESS;
2692         return (result);
2693 }
2694
2695 /*%
2696  * Validate the ncache elements.
2697  */
2698 static isc_result_t
2699 validate_ncache(dns_validator_t *val, isc_boolean_t resume) {
2700         dns_name_t *name;
2701         isc_result_t result;
2702
2703         if (!resume)
2704                 result = dns_rdataset_first(val->event->rdataset);
2705         else
2706                 result = dns_rdataset_next(val->event->rdataset);
2707
2708         for (;
2709              result == ISC_R_SUCCESS;
2710              result = dns_rdataset_next(val->event->rdataset))
2711         {
2712                 dns_rdataset_t *rdataset, *sigrdataset = NULL;
2713
2714                 if (dns_rdataset_isassociated(&val->frdataset))
2715                         dns_rdataset_disassociate(&val->frdataset);
2716                 if (dns_rdataset_isassociated(&val->fsigrdataset))
2717                         dns_rdataset_disassociate(&val->fsigrdataset);
2718
2719                 dns_fixedname_init(&val->fname);
2720                 name = dns_fixedname_name(&val->fname);
2721                 rdataset = &val->frdataset;
2722                 dns_ncache_current(val->event->rdataset, name, rdataset);
2723
2724                 if (val->frdataset.type == dns_rdatatype_rrsig)
2725                         continue;
2726
2727                 result = dns_ncache_getsigrdataset(val->event->rdataset, name,
2728                                                    rdataset->type,
2729                                                    &val->fsigrdataset);
2730                 if (result == ISC_R_SUCCESS)
2731                         sigrdataset = &val->fsigrdataset;
2732
2733                 /*
2734                  * If a signed zone is missing the zone key, bad
2735                  * things could happen.  A query for data in the zone
2736                  * would lead to a query for the zone key, which
2737                  * would return a negative answer, which would contain
2738                  * an SOA and an NSEC signed by the missing key, which
2739                  * would trigger another query for the DNSKEY (since
2740                  * the first one is still in progress), and go into an
2741                  * infinite loop.  Avoid that.
2742                  */
2743                 if (val->event->type == dns_rdatatype_dnskey &&
2744                     rdataset->type == dns_rdatatype_nsec &&
2745                     dns_name_equal(name, val->event->name))
2746                 {
2747                         dns_rdata_t nsec = DNS_RDATA_INIT;
2748
2749                         result = dns_rdataset_first(rdataset);
2750                         if (result != ISC_R_SUCCESS)
2751                                 return (result);
2752                         dns_rdataset_current(rdataset, &nsec);
2753                         if (dns_nsec_typepresent(&nsec,
2754                                                 dns_rdatatype_soa))
2755                                 continue;
2756                 }
2757                 val->currentset = rdataset;
2758                 result = create_validator(val, name, rdataset->type,
2759                                           rdataset, sigrdataset,
2760                                           authvalidated,
2761                                           "validate_ncache");
2762                 if (result != ISC_R_SUCCESS)
2763                         return (result);
2764                 val->authcount++;
2765                 return (DNS_R_WAIT);
2766         }
2767         if (result == ISC_R_NOMORE)
2768                 result = ISC_R_SUCCESS;
2769         return (result);
2770 }
2771
2772 /*%
2773  * Prove a negative answer is good or that there is a NOQNAME when the
2774  * answer is from a wildcard.
2775  *
2776  * Loop through the authority section looking for NODATA, NOWILDCARD
2777  * and NOQNAME proofs in the NSEC records by calling authvalidated().
2778  *
2779  * If the required proofs are found we are done.
2780  *
2781  * If the proofs are not found attempt to prove this is a unsecure
2782  * response.
2783  */
2784 static isc_result_t
2785 nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
2786         isc_result_t result;
2787
2788         if (resume)
2789                 validator_log(val, ISC_LOG_DEBUG(3), "resuming nsecvalidate");
2790
2791         if (val->event->message == NULL)
2792                 result = validate_ncache(val, resume);
2793         else
2794                 result = validate_authority(val, resume);
2795
2796         if (result != ISC_R_SUCCESS)
2797                 return (result);
2798
2799         /*
2800          * Do we only need to check for NOQNAME?  To get here we must have
2801          * had a secure wildcard answer.
2802          */
2803         if (!NEEDNODATA(val) && !NEEDNOWILDCARD(val) && NEEDNOQNAME(val)) {
2804                 if (!FOUNDNOQNAME(val))
2805                         findnsec3proofs(val);
2806                 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val)) {
2807                         validator_log(val, ISC_LOG_DEBUG(3),
2808                                       "marking as secure, noqname proof found");
2809                         marksecure(val->event);
2810                         return (ISC_R_SUCCESS);
2811                 } else if (FOUNDOPTOUT(val) &&
2812                            dns_name_countlabels(dns_fixedname_name(&val->wild))
2813                                          != 0) {
2814                         validator_log(val, ISC_LOG_DEBUG(3),
2815                                       "optout proof found");
2816                         val->event->optout = ISC_TRUE;
2817                         markanswer(val, "nsecvalidate (1)");
2818                         return (ISC_R_SUCCESS);
2819                 } else if ((val->attributes & VALATTR_FOUNDUNKNOWN) != 0) {
2820                         validator_log(val, ISC_LOG_DEBUG(3),
2821                                       "unknown NSEC3 hash algorithm found");
2822                         markanswer(val, "nsecvalidate (2)");
2823                         return (ISC_R_SUCCESS);
2824                 }
2825                 validator_log(val, ISC_LOG_DEBUG(3),
2826                               "noqname proof not found");
2827                 return (DNS_R_NOVALIDNSEC);
2828         }
2829
2830         if (!FOUNDNOQNAME(val) && !FOUNDNODATA(val))
2831                 findnsec3proofs(val);
2832
2833         /*
2834          * Do we need to check for the wildcard?
2835          */
2836         if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
2837             ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
2838                 result = checkwildcard(val, dns_rdatatype_nsec, NULL);
2839                 if (result != ISC_R_SUCCESS)
2840                         return (result);
2841         }
2842
2843         if ((NEEDNODATA(val) && (FOUNDNODATA(val) || FOUNDOPTOUT(val))) ||
2844             (NEEDNOQNAME(val) && FOUNDNOQNAME(val) &&
2845              NEEDNOWILDCARD(val) && FOUNDNOWILDCARD(val) &&
2846              FOUNDCLOSEST(val))) {
2847                 if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
2848                         val->event->optout = ISC_TRUE;
2849                 validator_log(val, ISC_LOG_DEBUG(3),
2850                               "nonexistence proof(s) found");
2851                 if (val->event->message == NULL)
2852                         marksecure(val->event);
2853                 else
2854                         val->event->secure = ISC_TRUE;
2855                 return (ISC_R_SUCCESS);
2856         }
2857
2858         if (val->authfail != 0 && val->authcount == val->authfail)
2859                 return (DNS_R_BROKENCHAIN);
2860         validator_log(val, ISC_LOG_DEBUG(3),
2861                       "nonexistence proof(s) not found");
2862         val->attributes |= VALATTR_INSECURITY;
2863         return (proveunsecure(val, ISC_FALSE, ISC_FALSE));
2864 }
2865
2866 static isc_boolean_t
2867 check_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) {
2868         dns_rdata_t dsrdata = DNS_RDATA_INIT;
2869         dns_rdata_ds_t ds;
2870         isc_result_t result;
2871
2872         for (result = dns_rdataset_first(rdataset);
2873              result == ISC_R_SUCCESS;
2874              result = dns_rdataset_next(rdataset)) {
2875                 dns_rdataset_current(rdataset, &dsrdata);
2876                 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
2877                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2878
2879                 if (dns_resolver_digest_supported(val->view->resolver,
2880                                                   ds.digest_type) &&
2881                     dns_resolver_algorithm_supported(val->view->resolver,
2882                                                      name, ds.algorithm)) {
2883                         dns_rdata_reset(&dsrdata);
2884                         return (ISC_TRUE);
2885                 }
2886                 dns_rdata_reset(&dsrdata);
2887         }
2888         return (ISC_FALSE);
2889 }
2890
2891 static void
2892 dlvvalidated(isc_task_t *task, isc_event_t *event) {
2893         dns_validatorevent_t *devent;
2894         dns_validator_t *val;
2895         isc_result_t eresult;
2896         isc_boolean_t want_destroy;
2897
2898         UNUSED(task);
2899         INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
2900
2901         devent = (dns_validatorevent_t *)event;
2902         val = devent->ev_arg;
2903         eresult = devent->result;
2904
2905         isc_event_free(&event);
2906         dns_validator_destroy(&val->subvalidator);
2907
2908         INSIST(val->event != NULL);
2909
2910         validator_log(val, ISC_LOG_DEBUG(3), "in dlvvalidated");
2911         LOCK(&val->lock);
2912         if (CANCELED(val)) {
2913                 validator_done(val, ISC_R_CANCELED);
2914         } else if (eresult == ISC_R_SUCCESS) {
2915                 validator_log(val, ISC_LOG_DEBUG(3),
2916                               "dlvset with trust %s",
2917                               dns_trust_totext(val->frdataset.trust));
2918                 dns_rdataset_clone(&val->frdataset, &val->dlv);
2919                 val->havedlvsep = ISC_TRUE;
2920                 if (dlv_algorithm_supported(val))
2921                         dlv_validator_start(val);
2922                 else {
2923                         markanswer(val, "dlvvalidated");
2924                         validator_done(val, ISC_R_SUCCESS);
2925                 }
2926         } else {
2927                 if (eresult != DNS_R_BROKENCHAIN) {
2928                         if (dns_rdataset_isassociated(&val->frdataset))
2929                                 dns_rdataset_expire(&val->frdataset);
2930                         if (dns_rdataset_isassociated(&val->fsigrdataset))
2931                                 dns_rdataset_expire(&val->fsigrdataset);
2932                 }
2933                 validator_log(val, ISC_LOG_DEBUG(3),
2934                               "dlvvalidated: got %s",
2935                               isc_result_totext(eresult));
2936                 validator_done(val, DNS_R_BROKENCHAIN);
2937         }
2938         want_destroy = exit_check(val);
2939         UNLOCK(&val->lock);
2940         if (want_destroy)
2941                 destroy(val);
2942 }
2943
2944 /*%
2945  * Callback from fetching a DLV record.
2946  *
2947  * Resumes the DLV lookup process.
2948  */
2949 static void
2950 dlvfetched(isc_task_t *task, isc_event_t *event) {
2951         char namebuf[DNS_NAME_FORMATSIZE];
2952         dns_fetchevent_t *devent;
2953         dns_validator_t *val;
2954         isc_boolean_t want_destroy;
2955         isc_result_t eresult;
2956         isc_result_t result;
2957         dns_fetch_t *fetch;
2958
2959         UNUSED(task);
2960         INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
2961         devent = (dns_fetchevent_t *)event;
2962         val = devent->ev_arg;
2963         eresult = devent->result;
2964
2965         /* Free resources which are not of interest. */
2966         if (devent->node != NULL)
2967                 dns_db_detachnode(devent->db, &devent->node);
2968         if (devent->db != NULL)
2969                 dns_db_detach(&devent->db);
2970         if (dns_rdataset_isassociated(&val->fsigrdataset))
2971                 dns_rdataset_disassociate(&val->fsigrdataset);
2972         isc_event_free(&event);
2973
2974         INSIST(val->event != NULL);
2975         validator_log(val, ISC_LOG_DEBUG(3), "in dlvfetched: %s",
2976                       dns_result_totext(eresult));
2977
2978         LOCK(&val->lock);
2979         fetch = val->fetch;
2980         val->fetch = NULL;
2981         if (eresult == ISC_R_SUCCESS) {
2982                 dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
2983                                 sizeof(namebuf));
2984                 dns_rdataset_clone(&val->frdataset, &val->dlv);
2985                 val->havedlvsep = ISC_TRUE;
2986                 if (dlv_algorithm_supported(val)) {
2987                         validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found",
2988                                       namebuf);
2989                         dlv_validator_start(val);
2990                 } else {
2991                         validator_log(val, ISC_LOG_DEBUG(3),
2992                                       "DLV %s found with no supported algorithms",
2993                                       namebuf);
2994                         markanswer(val, "dlvfetched (1)");
2995                         validator_done(val, ISC_R_SUCCESS);
2996                 }
2997         } else if (eresult == DNS_R_NXRRSET ||
2998                    eresult == DNS_R_NXDOMAIN ||
2999                    eresult == DNS_R_NCACHENXRRSET ||
3000                    eresult == DNS_R_NCACHENXDOMAIN) {
3001                 result = finddlvsep(val, ISC_TRUE);
3002                 if (result == ISC_R_SUCCESS) {
3003                         if (dlv_algorithm_supported(val)) {
3004                                 dns_name_format(dns_fixedname_name(&val->dlvsep),
3005                                                 namebuf, sizeof(namebuf));
3006                                 validator_log(val, ISC_LOG_DEBUG(3),
3007                                               "DLV %s found", namebuf);
3008                                 dlv_validator_start(val);
3009                         } else {
3010                                 validator_log(val, ISC_LOG_DEBUG(3),
3011                                               "DLV %s found with no supported "
3012                                               "algorithms", namebuf);
3013                                 markanswer(val, "dlvfetched (2)");
3014                                 validator_done(val, ISC_R_SUCCESS);
3015                         }
3016                 } else if (result == ISC_R_NOTFOUND) {
3017                         validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
3018                         markanswer(val, "dlvfetched (3)");
3019                         validator_done(val, ISC_R_SUCCESS);
3020                 } else {
3021                         validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3022                                       dns_result_totext(result));
3023                         if (result != DNS_R_WAIT)
3024                                 validator_done(val, result);
3025                 }
3026         } else {
3027                 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3028                               dns_result_totext(eresult));
3029                 validator_done(val, eresult);
3030         }
3031         want_destroy = exit_check(val);
3032         UNLOCK(&val->lock);
3033         if (fetch != NULL)
3034                 dns_resolver_destroyfetch(&fetch);
3035         if (want_destroy)
3036                 destroy(val);
3037 }
3038
3039 /*%
3040  * Start the DLV lookup process.
3041  *
3042  * Returns
3043  * \li  ISC_R_SUCCESS
3044  * \li  DNS_R_WAIT
3045  * \li  Others on validation failures.
3046  */
3047 static isc_result_t
3048 startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) {
3049         char namebuf[DNS_NAME_FORMATSIZE];
3050         isc_result_t result;
3051
3052         INSIST(!DLVTRIED(val));
3053
3054         val->attributes |= VALATTR_DLVTRIED;
3055
3056         dns_name_format(unsecure, namebuf, sizeof(namebuf));
3057         validator_log(val, ISC_LOG_DEBUG(3),
3058                       "plain DNSSEC returns unsecure (%s): looking for DLV",
3059                       namebuf);
3060
3061         if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
3062                 validator_log(val, ISC_LOG_WARNING, "must be secure failure, "
3063                               " %s is under DLV (startfinddlvsep)", namebuf);
3064                 return (DNS_R_MUSTBESECURE);
3065         }
3066
3067         val->dlvlabels = dns_name_countlabels(unsecure) - 1;
3068         result = finddlvsep(val, ISC_FALSE);
3069         if (result == ISC_R_NOTFOUND) {
3070                 validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
3071                 markanswer(val, "startfinddlvsep (1)");
3072                 return (ISC_R_SUCCESS);
3073         }
3074         if (result != ISC_R_SUCCESS) {
3075                 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3076                               dns_result_totext(result));
3077                 return (result);
3078         }
3079         dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
3080                         sizeof(namebuf));
3081         if (dlv_algorithm_supported(val)) {
3082                 validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf);
3083                 dlv_validator_start(val);
3084                 return (DNS_R_WAIT);
3085         }
3086         validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found with no supported "
3087                       "algorithms", namebuf);
3088         markanswer(val, "startfinddlvsep (2)");
3089         validator_done(val, ISC_R_SUCCESS);
3090         return (ISC_R_SUCCESS);
3091 }
3092
3093 /*%
3094  * Continue the DLV lookup process.
3095  *
3096  * Returns
3097  * \li  ISC_R_SUCCESS
3098  * \li  ISC_R_NOTFOUND
3099  * \li  DNS_R_WAIT
3100  * \li  Others on validation failure.
3101  */
3102 static isc_result_t
3103 finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
3104         char namebuf[DNS_NAME_FORMATSIZE];
3105         dns_fixedname_t dlvfixed;
3106         dns_name_t *dlvname;
3107         dns_name_t *dlvsep;
3108         dns_name_t noroot;
3109         isc_result_t result;
3110         unsigned int labels;
3111
3112         INSIST(val->view->dlv != NULL);
3113
3114         if (!resume) {
3115                 if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
3116                         dns_name_format(val->event->name, namebuf,
3117                                         sizeof(namebuf));
3118                         validator_log(val, ISC_LOG_WARNING,
3119                                       "must be secure failure, "
3120                                       "%s is under DLV (finddlvsep)", namebuf);
3121                         return (DNS_R_MUSTBESECURE);
3122                 }
3123
3124                 dns_fixedname_init(&val->dlvsep);
3125                 dlvsep = dns_fixedname_name(&val->dlvsep);
3126                 dns_name_copy(val->event->name, dlvsep, NULL);
3127                 /*
3128                  * If this is a response to a DS query, we need to look in
3129                  * the parent zone for the trust anchor.
3130                  */
3131                 if (val->event->type == dns_rdatatype_ds) {
3132                         labels = dns_name_countlabels(dlvsep);
3133                         if (labels == 0)
3134                                 return (ISC_R_NOTFOUND);
3135                         dns_name_getlabelsequence(dlvsep, 1, labels - 1,
3136                                                   dlvsep);
3137                 }
3138         } else {
3139                 dlvsep = dns_fixedname_name(&val->dlvsep);
3140                 labels = dns_name_countlabels(dlvsep);
3141                 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3142         }
3143         dns_name_init(&noroot, NULL);
3144         dns_fixedname_init(&dlvfixed);
3145         dlvname = dns_fixedname_name(&dlvfixed);
3146         labels = dns_name_countlabels(dlvsep);
3147         if (labels == 0)
3148                 return (ISC_R_NOTFOUND);
3149         dns_name_getlabelsequence(dlvsep, 0, labels - 1, &noroot);
3150         result = dns_name_concatenate(&noroot, val->view->dlv, dlvname, NULL);
3151         while (result == ISC_R_NOSPACE) {
3152                 labels = dns_name_countlabels(dlvsep);
3153                 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3154                 dns_name_getlabelsequence(dlvsep, 0, labels - 2, &noroot);
3155                 result = dns_name_concatenate(&noroot, val->view->dlv,
3156                                               dlvname, NULL);
3157         }
3158         if (result != ISC_R_SUCCESS) {
3159                 validator_log(val, ISC_LOG_DEBUG(2), "DLV concatenate failed");
3160                 return (DNS_R_NOVALIDSIG);
3161         }
3162
3163         while (dns_name_countlabels(dlvname) >=
3164                dns_name_countlabels(val->view->dlv) + val->dlvlabels) {
3165                 dns_name_format(dlvname, namebuf, sizeof(namebuf));
3166                 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV %s",
3167                               namebuf);
3168                 result = view_find(val, dlvname, dns_rdatatype_dlv);
3169                 if (result == ISC_R_SUCCESS) {
3170                         if (DNS_TRUST_PENDING(val->frdataset.trust) &&
3171                             dns_rdataset_isassociated(&val->fsigrdataset))
3172                         {
3173                                 dns_fixedname_init(&val->fname);
3174                                 dns_name_copy(dlvname,
3175                                               dns_fixedname_name(&val->fname),
3176                                               NULL);
3177                                 result = create_validator(val,
3178                                                 dns_fixedname_name(&val->fname),
3179                                                           dns_rdatatype_dlv,
3180                                                           &val->frdataset,
3181                                                           &val->fsigrdataset,
3182                                                           dlvvalidated,
3183                                                           "finddlvsep");
3184                                 if (result != ISC_R_SUCCESS)
3185                                         return (result);
3186                                 return (DNS_R_WAIT);
3187                         }
3188                         if (val->frdataset.trust < dns_trust_secure) {
3189                                 validator_log(val, ISC_LOG_DEBUG(3),
3190                                               "DLV not validated");
3191                                 return (DNS_R_NOVALIDSIG);
3192                         }
3193                         val->havedlvsep = ISC_TRUE;
3194                         dns_rdataset_clone(&val->frdataset, &val->dlv);
3195                         return (ISC_R_SUCCESS);
3196                 }
3197                 if (result == ISC_R_NOTFOUND) {
3198                         result = create_fetch(val, dlvname, dns_rdatatype_dlv,
3199                                               dlvfetched, "finddlvsep");
3200                         if (result != ISC_R_SUCCESS)
3201                                 return (result);
3202                         return (DNS_R_WAIT);
3203                 }
3204                 if (result != DNS_R_NXRRSET &&
3205                     result != DNS_R_NXDOMAIN &&
3206                     result != DNS_R_EMPTYNAME &&
3207                     result != DNS_R_NCACHENXRRSET &&
3208                     result != DNS_R_NCACHENXDOMAIN)
3209                         return (result);
3210                 /*
3211                  * Strip first labels from both dlvsep and dlvname.
3212                  */
3213                 labels = dns_name_countlabels(dlvsep);
3214                 if (labels == 0)
3215                         break;
3216                 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3217                 labels = dns_name_countlabels(dlvname);
3218                 dns_name_getlabelsequence(dlvname, 1, labels - 1, dlvname);
3219         }
3220         return (ISC_R_NOTFOUND);
3221 }
3222
3223 /*%
3224  * proveunsecure walks down from the SEP looking for a break in the
3225  * chain of trust.  That occurs when we can prove the DS record does
3226  * not exist at a delegation point or the DS exists at a delegation
3227  * but we don't support the algorithm/digest.
3228  *
3229  * If DLV is active and we look for a DLV record at or below the
3230  * point we go insecure.  If found we restart the validation process.
3231  * If not found or DLV isn't active we mark the response as a answer.
3232  *
3233  * Returns:
3234  * \li  ISC_R_SUCCESS           val->event->name is in a unsecure zone
3235  * \li  DNS_R_WAIT              validation is in progress.
3236  * \li  DNS_R_MUSTBESECURE      val->event->name is supposed to be secure
3237  *                              (policy) but we proved that it is unsecure.
3238  * \li  DNS_R_NOVALIDSIG
3239  * \li  DNS_R_NOVALIDNSEC
3240  * \li  DNS_R_NOTINSECURE
3241  * \li  DNS_R_BROKENCHAIN
3242  */
3243 static isc_result_t
3244 proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
3245 {
3246         isc_result_t result;
3247         dns_fixedname_t fixedsecroot;
3248         dns_name_t *secroot;
3249         dns_name_t *tname;
3250         char namebuf[DNS_NAME_FORMATSIZE];
3251         dns_name_t *found;
3252         dns_fixedname_t fixedfound;
3253
3254         dns_fixedname_init(&fixedsecroot);
3255         secroot = dns_fixedname_name(&fixedsecroot);
3256         dns_fixedname_init(&fixedfound);
3257         found = dns_fixedname_name(&fixedfound);
3258         if (val->havedlvsep)
3259                 dns_name_copy(dns_fixedname_name(&val->dlvsep), secroot, NULL);
3260         else {
3261                 unsigned int labels;
3262                 dns_name_copy(val->event->name, secroot, NULL);
3263                 /*
3264                  * If this is a response to a DS query, we need to look in
3265                  * the parent zone for the trust anchor.
3266                  */
3267
3268                 labels = dns_name_countlabels(secroot);
3269                 if (val->event->type == dns_rdatatype_ds && labels > 1U)
3270                         dns_name_getlabelsequence(secroot, 1, labels - 1,
3271                                                   secroot);
3272                 result = dns_keytable_finddeepestmatch(val->keytable,
3273                                                        secroot, secroot);
3274                 if (result == ISC_R_NOTFOUND) {
3275                         if (val->mustbesecure) {
3276                                 validator_log(val, ISC_LOG_WARNING,
3277                                               "must be secure failure, "
3278                                               "not beneath secure root");
3279                                 result = DNS_R_MUSTBESECURE;
3280                                 goto out;
3281                         } else
3282                                 validator_log(val, ISC_LOG_DEBUG(3),
3283                                               "not beneath secure root");
3284                         if (val->view->dlv == NULL || DLVTRIED(val)) {
3285                                 markanswer(val, "proveunsecure (1)");
3286                                 return (ISC_R_SUCCESS);
3287                         }
3288                         return (startfinddlvsep(val, dns_rootname));
3289                 } else if (result != ISC_R_SUCCESS)
3290                         return (result);
3291         }
3292
3293         if (!resume) {
3294                 /*
3295                  * We are looking for breaks below the SEP so add a label.
3296                  */
3297                 val->labels = dns_name_countlabels(secroot) + 1;
3298         } else {
3299                 validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
3300                 /*
3301                  * If we have a DS rdataset and it is secure then check if
3302                  * the DS rdataset has a supported algorithm combination.
3303                  * If not this is an insecure delegation as far as this
3304                  * resolver is concerned.  Fall back to DLV if available.
3305                  */
3306                 if (have_ds && val->frdataset.trust >= dns_trust_secure &&
3307                     !check_ds(val, dns_fixedname_name(&val->fname),
3308                               &val->frdataset)) {
3309                         dns_name_format(dns_fixedname_name(&val->fname),
3310                                         namebuf, sizeof(namebuf));
3311                         if ((val->view->dlv == NULL || DLVTRIED(val)) &&
3312                             val->mustbesecure) {
3313                                 validator_log(val, ISC_LOG_WARNING,
3314                                               "must be secure failure at '%s', "
3315                                               "can't fall back to DLV",
3316                                               namebuf);
3317                                 result = DNS_R_MUSTBESECURE;
3318                                 goto out;
3319                         }
3320                         validator_log(val, ISC_LOG_DEBUG(3),
3321                                       "no supported algorithm/digest (%s/DS)",
3322                                       namebuf);
3323                         if (val->view->dlv == NULL || DLVTRIED(val)) {
3324                                 markanswer(val, "proveunsecure (2)");
3325                                 result = ISC_R_SUCCESS;
3326                                 goto out;
3327                         }
3328                         return(startfinddlvsep(val,
3329                                               dns_fixedname_name(&val->fname)));
3330                 }
3331                 val->labels++;
3332         }
3333
3334         for (;
3335              val->labels <= dns_name_countlabels(val->event->name);
3336              val->labels++)
3337         {
3338
3339                 dns_fixedname_init(&val->fname);
3340                 tname = dns_fixedname_name(&val->fname);
3341                 if (val->labels == dns_name_countlabels(val->event->name))
3342                         dns_name_copy(val->event->name, tname, NULL);
3343                 else
3344                         dns_name_split(val->event->name, val->labels,
3345                                        NULL, tname);
3346
3347                 dns_name_format(tname, namebuf, sizeof(namebuf));
3348                 validator_log(val, ISC_LOG_DEBUG(3),
3349                               "checking existence of DS at '%s'",
3350                               namebuf);
3351
3352                 result = view_find(val, tname, dns_rdatatype_ds);
3353                 if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
3354                         /*
3355                          * There is no DS.  If this is a delegation,
3356                          * we may be done.
3357                          */
3358                         /*
3359                          * If we have "trust == answer" then this namespace
3360                          * has switched from insecure to should be secure.
3361                          */
3362                         if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3363                             DNS_TRUST_ANSWER(val->frdataset.trust)) {
3364                                 result = create_validator(val, tname,
3365                                                           dns_rdatatype_ds,
3366                                                           &val->frdataset,
3367                                                           NULL, dsvalidated,
3368                                                           "proveunsecure");
3369                                 if (result != ISC_R_SUCCESS)
3370                                         goto out;
3371                                 return (DNS_R_WAIT);
3372                         }
3373                         /*
3374                          * Zones using NSEC3 don't return a NSEC RRset so
3375                          * we need to use dns_view_findzonecut2 to find
3376                          * the zone cut.
3377                          */
3378                         if (result == DNS_R_NXRRSET &&
3379                             !dns_rdataset_isassociated(&val->frdataset) &&
3380                             dns_view_findzonecut2(val->view, tname, found,
3381                                                  0, 0, ISC_FALSE, ISC_FALSE,
3382                                                  NULL, NULL) == ISC_R_SUCCESS &&
3383                             dns_name_equal(tname, found)) {
3384                                 if (val->mustbesecure) {
3385                                         validator_log(val, ISC_LOG_WARNING,
3386                                                       "must be secure failure, "
3387                                                       "no DS at zone cut");
3388                                         return (DNS_R_MUSTBESECURE);
3389                                 }
3390                                 if (val->view->dlv == NULL || DLVTRIED(val)) {
3391                                         markanswer(val, "proveunsecure (3)");
3392                                         return (ISC_R_SUCCESS);
3393                                 }
3394                                 return (startfinddlvsep(val, tname));
3395                         }
3396                         if (val->frdataset.trust < dns_trust_secure) {
3397                                 /*
3398                                  * This shouldn't happen, since the negative
3399                                  * response should have been validated.  Since
3400                                  * there's no way of validating existing
3401                                  * negative response blobs, give up.
3402                                  */
3403                                 validator_log(val, ISC_LOG_WARNING,
3404                                               "can't validate existing "
3405                                               "negative responses (no DS)");
3406                                 result = DNS_R_NOVALIDSIG;
3407                                 goto out;
3408                         }
3409                         if (isdelegation(tname, &val->frdataset, result)) {
3410                                 if (val->mustbesecure) {
3411                                         validator_log(val, ISC_LOG_WARNING,
3412                                                       "must be secure failure, "
3413                                                       "%s is a delegation",
3414                                                       namebuf);
3415                                         return (DNS_R_MUSTBESECURE);
3416                                 }
3417                                 if (val->view->dlv == NULL || DLVTRIED(val)) {
3418                                         markanswer(val, "proveunsecure (4)");
3419                                         return (ISC_R_SUCCESS);
3420                                 }
3421                                 return (startfinddlvsep(val, tname));
3422                         }
3423                         continue;
3424                 } else if (result == DNS_R_CNAME) {
3425                         if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3426                             DNS_TRUST_ANSWER(val->frdataset.trust)) {
3427                                 result = create_validator(val, tname,
3428                                                           dns_rdatatype_cname,
3429                                                           &val->frdataset,
3430                                                           NULL, cnamevalidated,
3431                                                           "proveunsecure "
3432                                                           "(cname)");
3433                                 if (result != ISC_R_SUCCESS)
3434                                         goto out;
3435                                 return (DNS_R_WAIT);
3436                         }
3437                         continue;
3438                 } else if (result == ISC_R_SUCCESS) {
3439                         /*
3440                          * There is a DS here.  Verify that it's secure and
3441                          * continue.
3442                          */
3443                         if (val->frdataset.trust >= dns_trust_secure) {
3444                                 if (!check_ds(val, tname, &val->frdataset)) {
3445                                         validator_log(val, ISC_LOG_DEBUG(3),
3446                                                      "no supported algorithm/"
3447                                                      "digest (%s/DS)", namebuf);
3448                                         if (val->mustbesecure) {
3449                                                 validator_log(val,
3450                                                               ISC_LOG_WARNING,
3451                                                       "must be secure failure, "
3452                                                       "no supported algorithm/"
3453                                                       "digest (%s/DS)",
3454                                                       namebuf);
3455                                                 result = DNS_R_MUSTBESECURE;
3456                                                 goto out;
3457                                         }
3458                                         if (val->view->dlv == NULL ||
3459                                             DLVTRIED(val)) {
3460                                                 markanswer(val,
3461                                                            "proveunsecure (5)");
3462                                                 result = ISC_R_SUCCESS;
3463                                                 goto out;
3464                                         }
3465                                         return(startfinddlvsep(val, tname));
3466                                 }
3467                                 continue;
3468                         }
3469                         else if (!dns_rdataset_isassociated(&val->fsigrdataset))
3470                         {
3471                                 validator_log(val, ISC_LOG_DEBUG(3),
3472                                               "DS is unsigned");
3473                                 result = DNS_R_NOVALIDSIG;
3474                                 goto out;
3475                         }
3476                         /*
3477                          * Validate / re-validate answer.
3478                          */
3479                         result = create_validator(val, tname, dns_rdatatype_ds,
3480                                                   &val->frdataset,
3481                                                   &val->fsigrdataset,
3482                                                   dsvalidated,
3483                                                   "proveunsecure");
3484                         if (result != ISC_R_SUCCESS)
3485                                 goto out;
3486                         return (DNS_R_WAIT);
3487                 } else if (result == DNS_R_NXDOMAIN ||
3488                            result == DNS_R_NCACHENXDOMAIN) {
3489                         /*
3490                          * This is not a zone cut.  Assuming things are
3491                          * as expected, continue.
3492                          */
3493                         if (!dns_rdataset_isassociated(&val->frdataset)) {
3494                                 /*
3495                                  * There should be an NSEC here, since we
3496                                  * are still in a secure zone.
3497                                  */
3498                                 result = DNS_R_NOVALIDNSEC;
3499                                 goto out;
3500                         } else if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3501                                    DNS_TRUST_ANSWER(val->frdataset.trust)) {
3502                                 /*
3503                                  * If we have "trust == answer" then this namespace
3504                                  * has switched from insecure to should be secure.
3505                                  */
3506                                 result = create_validator(val, tname,
3507                                                           dns_rdatatype_ds,
3508                                                           &val->frdataset,
3509                                                           NULL, dsvalidated,
3510                                                           "proveunsecure");
3511                                 if (result != ISC_R_SUCCESS)
3512                                         goto out;
3513                                 return (DNS_R_WAIT);
3514                         } else if (val->frdataset.trust < dns_trust_secure) {
3515                                 /*
3516                                  * This shouldn't happen, since the negative
3517                                  * response should have been validated.  Since
3518                                  * there's no way of validating existing
3519                                  * negative response blobs, give up.
3520                                  */
3521                                 validator_log(val, ISC_LOG_WARNING,
3522                                               "can't validate existing "
3523                                               "negative responses "
3524                                               "(not a zone cut)");
3525                                 result = DNS_R_NOVALIDSIG;
3526                                 goto out;
3527                         }
3528                         continue;
3529                 } else if (result == ISC_R_NOTFOUND) {
3530                         /*
3531                          * We don't know anything about the DS.  Find it.
3532                          */
3533                         result = create_fetch(val, tname, dns_rdatatype_ds,
3534                                               dsfetched2, "proveunsecure");
3535                         if (result != ISC_R_SUCCESS)
3536                                 goto out;
3537                         return (DNS_R_WAIT);
3538                 } else if (result == DNS_R_BROKENCHAIN)
3539                         return (result);
3540         }
3541
3542         /* Couldn't complete insecurity proof */
3543         validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed");
3544         return (DNS_R_NOTINSECURE);
3545
3546  out:
3547         if (dns_rdataset_isassociated(&val->frdataset))
3548                 dns_rdataset_disassociate(&val->frdataset);
3549         if (dns_rdataset_isassociated(&val->fsigrdataset))
3550                 dns_rdataset_disassociate(&val->fsigrdataset);
3551         return (result);
3552 }
3553
3554 /*%
3555  * Reset state and revalidate the answer using DLV.
3556  */
3557 static void
3558 dlv_validator_start(dns_validator_t *val) {
3559         isc_event_t *event;
3560
3561         validator_log(val, ISC_LOG_DEBUG(3), "dlv_validator_start");
3562
3563         /*
3564          * Reset state and try again.
3565          */
3566         val->attributes &= VALATTR_DLVTRIED;
3567         val->options &= ~DNS_VALIDATOR_DLV;
3568
3569         event = (isc_event_t *)val->event;
3570         isc_task_send(val->task, &event);
3571 }
3572
3573 /*%
3574  * Start the validation process.
3575  *
3576  * Attempt to validate the answer based on the category it appears to
3577  * fall in.
3578  * \li  1. secure positive answer.
3579  * \li  2. unsecure positive answer.
3580  * \li  3. a negative answer (secure or unsecure).
3581  *
3582  * Note a answer that appears to be a secure positive answer may actually
3583  * be an unsecure positive answer.
3584  */
3585 static void
3586 validator_start(isc_task_t *task, isc_event_t *event) {
3587         dns_validator_t *val;
3588         dns_validatorevent_t *vevent;
3589         isc_boolean_t want_destroy = ISC_FALSE;
3590         isc_result_t result = ISC_R_FAILURE;
3591
3592         UNUSED(task);
3593         REQUIRE(event->ev_type == DNS_EVENT_VALIDATORSTART);
3594         vevent = (dns_validatorevent_t *)event;
3595         val = vevent->validator;
3596
3597         /* If the validator has been canceled, val->event == NULL */
3598         if (val->event == NULL)
3599                 return;
3600
3601         if (DLVTRIED(val))
3602                 validator_log(val, ISC_LOG_DEBUG(3), "restarting using DLV");
3603         else
3604                 validator_log(val, ISC_LOG_DEBUG(3), "starting");
3605
3606         LOCK(&val->lock);
3607
3608         if ((val->options & DNS_VALIDATOR_DLV) != 0 &&
3609              val->event->rdataset != NULL) {
3610                 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV");
3611                 result = startfinddlvsep(val, dns_rootname);
3612         } else if (val->event->rdataset != NULL &&
3613                    val->event->sigrdataset != NULL) {
3614                 isc_result_t saved_result;
3615
3616                 /*
3617                  * This looks like a simple validation.  We say "looks like"
3618                  * because it might end up requiring an insecurity proof.
3619                  */
3620                 validator_log(val, ISC_LOG_DEBUG(3),
3621                               "attempting positive response validation");
3622
3623                 INSIST(dns_rdataset_isassociated(val->event->rdataset));
3624                 INSIST(dns_rdataset_isassociated(val->event->sigrdataset));
3625                 result = start_positive_validation(val);
3626                 if (result == DNS_R_NOVALIDSIG &&
3627                     (val->attributes & VALATTR_TRIEDVERIFY) == 0)
3628                 {
3629                         saved_result = result;
3630                         validator_log(val, ISC_LOG_DEBUG(3),
3631                                       "falling back to insecurity proof");
3632                         val->attributes |= VALATTR_INSECURITY;
3633                         result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
3634                         if (result == DNS_R_NOTINSECURE)
3635                                 result = saved_result;
3636                 }
3637         } else if (val->event->rdataset != NULL &&
3638                    val->event->rdataset->type != 0) {
3639                 /*
3640                  * This is either an unsecure subdomain or a response from
3641                  * a broken server.
3642                  */
3643                 INSIST(dns_rdataset_isassociated(val->event->rdataset));
3644                 validator_log(val, ISC_LOG_DEBUG(3),
3645                               "attempting insecurity proof");
3646
3647                 val->attributes |= VALATTR_INSECURITY;
3648                 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
3649                 if (result == DNS_R_NOTINSECURE)
3650                         validator_log(val, ISC_LOG_INFO,
3651                                       "got insecure response; "
3652                                       "parent indicates it should be secure");
3653         } else if (val->event->rdataset == NULL &&
3654                    val->event->sigrdataset == NULL)
3655         {
3656                 /*
3657                  * This is a nonexistence validation.
3658                  */
3659                 validator_log(val, ISC_LOG_DEBUG(3),
3660                               "attempting negative response validation");
3661
3662                 if (val->event->message->rcode == dns_rcode_nxdomain) {
3663                         val->attributes |= VALATTR_NEEDNOQNAME;
3664                         val->attributes |= VALATTR_NEEDNOWILDCARD;
3665                 } else
3666                         val->attributes |= VALATTR_NEEDNODATA;
3667                 result = nsecvalidate(val, ISC_FALSE);
3668         } else if (val->event->rdataset != NULL &&
3669                     NEGATIVE(val->event->rdataset))
3670         {
3671                 /*
3672                  * This is a nonexistence validation.
3673                  */
3674                 validator_log(val, ISC_LOG_DEBUG(3),
3675                               "attempting negative response validation");
3676
3677                 if (val->event->rdataset->covers == dns_rdatatype_any) {
3678                         val->attributes |= VALATTR_NEEDNOQNAME;
3679                         val->attributes |= VALATTR_NEEDNOWILDCARD;
3680                 } else
3681                         val->attributes |= VALATTR_NEEDNODATA;
3682                 result = nsecvalidate(val, ISC_FALSE);
3683         } else {
3684                 /*
3685                  * This shouldn't happen.
3686                  */
3687                 INSIST(0);
3688         }
3689
3690         if (result != DNS_R_WAIT) {
3691                 want_destroy = exit_check(val);
3692                 validator_done(val, result);
3693         }
3694
3695         UNLOCK(&val->lock);
3696         if (want_destroy)
3697                 destroy(val);
3698 }
3699
3700 isc_result_t
3701 dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
3702                      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
3703                      dns_message_t *message, unsigned int options,
3704                      isc_task_t *task, isc_taskaction_t action, void *arg,
3705                      dns_validator_t **validatorp)
3706 {
3707         isc_result_t result = ISC_R_FAILURE;
3708         dns_validator_t *val;
3709         isc_task_t *tclone = NULL;
3710         dns_validatorevent_t *event;
3711
3712         REQUIRE(name != NULL);
3713         REQUIRE(rdataset != NULL ||
3714                 (rdataset == NULL && sigrdataset == NULL && message != NULL));
3715         REQUIRE(validatorp != NULL && *validatorp == NULL);
3716
3717         val = isc_mem_get(view->mctx, sizeof(*val));
3718         if (val == NULL)
3719                 return (ISC_R_NOMEMORY);
3720         val->view = NULL;
3721         dns_view_weakattach(view, &val->view);
3722
3723         event = (dns_validatorevent_t *)
3724                 isc_event_allocate(view->mctx, task,
3725                                    DNS_EVENT_VALIDATORSTART,
3726                                    validator_start, NULL,
3727                                    sizeof(dns_validatorevent_t));
3728         if (event == NULL) {
3729                 result = ISC_R_NOMEMORY;
3730                 goto cleanup_val;
3731         }
3732         isc_task_attach(task, &tclone);
3733         event->validator = val;
3734         event->result = ISC_R_FAILURE;
3735         event->name = name;
3736         event->type = type;
3737         event->rdataset = rdataset;
3738         event->sigrdataset = sigrdataset;
3739         event->message = message;
3740         memset(event->proofs, 0, sizeof(event->proofs));
3741         event->optout = ISC_FALSE;
3742         event->secure = ISC_FALSE;
3743         result = isc_mutex_init(&val->lock);
3744         if (result != ISC_R_SUCCESS)
3745                 goto cleanup_event;
3746         val->event = event;
3747         val->options = options;
3748         val->attributes = 0;
3749         val->fetch = NULL;
3750         val->subvalidator = NULL;
3751         val->parent = NULL;
3752
3753         val->keytable = NULL;
3754         result = dns_view_getsecroots(val->view, &val->keytable);
3755         if (result != ISC_R_SUCCESS)
3756                 return (result);
3757
3758         val->keynode = NULL;
3759         val->key = NULL;
3760         val->siginfo = NULL;
3761         val->task = task;
3762         val->action = action;
3763         val->arg = arg;
3764         val->labels = 0;
3765         val->currentset = NULL;
3766         val->keyset = NULL;
3767         val->dsset = NULL;
3768         dns_rdataset_init(&val->dlv);
3769         val->seensig = ISC_FALSE;
3770         val->havedlvsep = ISC_FALSE;
3771         val->depth = 0;
3772         val->authcount = 0;
3773         val->authfail = 0;
3774         val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
3775         dns_rdataset_init(&val->frdataset);
3776         dns_rdataset_init(&val->fsigrdataset);
3777         dns_fixedname_init(&val->wild);
3778         dns_fixedname_init(&val->nearest);
3779         dns_fixedname_init(&val->closest);
3780         ISC_LINK_INIT(val, link);
3781         val->magic = VALIDATOR_MAGIC;
3782
3783         if ((options & DNS_VALIDATOR_DEFER) == 0)
3784                 isc_task_send(task, ISC_EVENT_PTR(&event));
3785
3786         *validatorp = val;
3787
3788         return (ISC_R_SUCCESS);
3789
3790  cleanup_event:
3791         isc_task_detach(&tclone);
3792         isc_event_free(ISC_EVENT_PTR(&event));
3793
3794  cleanup_val:
3795         dns_view_weakdetach(&val->view);
3796         isc_mem_put(view->mctx, val, sizeof(*val));
3797
3798         return (result);
3799 }
3800
3801 void
3802 dns_validator_send(dns_validator_t *validator) {
3803         isc_event_t *event;
3804         REQUIRE(VALID_VALIDATOR(validator));
3805
3806         LOCK(&validator->lock);
3807
3808         INSIST((validator->options & DNS_VALIDATOR_DEFER) != 0);
3809         event = (isc_event_t *)validator->event;
3810         validator->options &= ~DNS_VALIDATOR_DEFER;
3811         UNLOCK(&validator->lock);
3812
3813         isc_task_send(validator->task, ISC_EVENT_PTR(&event));
3814 }
3815
3816 void
3817 dns_validator_cancel(dns_validator_t *validator) {
3818         dns_fetch_t *fetch = NULL;
3819
3820         REQUIRE(VALID_VALIDATOR(validator));
3821
3822         LOCK(&validator->lock);
3823
3824         validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
3825
3826         if ((validator->attributes & VALATTR_CANCELED) == 0) {
3827                 validator->attributes |= VALATTR_CANCELED;
3828                 if (validator->event != NULL) {
3829                         fetch = validator->fetch;
3830                         validator->fetch = NULL;
3831
3832                         if (validator->subvalidator != NULL)
3833                                 dns_validator_cancel(validator->subvalidator);
3834                         if ((validator->options & DNS_VALIDATOR_DEFER) != 0) {
3835                                 validator->options &= ~DNS_VALIDATOR_DEFER;
3836                                 validator_done(validator, ISC_R_CANCELED);
3837                         }
3838                 }
3839         }
3840         UNLOCK(&validator->lock);
3841
3842         /* Need to cancel and destroy the fetch outside validator lock */
3843         if (fetch != NULL) {
3844                 dns_resolver_cancelfetch(fetch);
3845                 dns_resolver_destroyfetch(&fetch);
3846         }
3847 }
3848
3849 static void
3850 destroy(dns_validator_t *val) {
3851         isc_mem_t *mctx;
3852
3853         REQUIRE(SHUTDOWN(val));
3854         REQUIRE(val->event == NULL);
3855         REQUIRE(val->fetch == NULL);
3856
3857         if (val->keynode != NULL)
3858                 dns_keytable_detachkeynode(val->keytable, &val->keynode);
3859         else if (val->key != NULL)
3860                 dst_key_free(&val->key);
3861         if (val->keytable != NULL)
3862                 dns_keytable_detach(&val->keytable);
3863         if (val->subvalidator != NULL)
3864                 dns_validator_destroy(&val->subvalidator);
3865         if (val->havedlvsep)
3866                 dns_rdataset_disassociate(&val->dlv);
3867         if (dns_rdataset_isassociated(&val->frdataset))
3868                 dns_rdataset_disassociate(&val->frdataset);
3869         if (dns_rdataset_isassociated(&val->fsigrdataset))
3870                 dns_rdataset_disassociate(&val->fsigrdataset);
3871         mctx = val->view->mctx;
3872         if (val->siginfo != NULL)
3873                 isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo));
3874         DESTROYLOCK(&val->lock);
3875         dns_view_weakdetach(&val->view);
3876         val->magic = 0;
3877         isc_mem_put(mctx, val, sizeof(*val));
3878 }
3879
3880 void
3881 dns_validator_destroy(dns_validator_t **validatorp) {
3882         dns_validator_t *val;
3883         isc_boolean_t want_destroy = ISC_FALSE;
3884
3885         REQUIRE(validatorp != NULL);
3886         val = *validatorp;
3887         REQUIRE(VALID_VALIDATOR(val));
3888
3889         LOCK(&val->lock);
3890
3891         val->attributes |= VALATTR_SHUTDOWN;
3892         validator_log(val, ISC_LOG_DEBUG(3), "dns_validator_destroy");
3893
3894         want_destroy = exit_check(val);
3895
3896         UNLOCK(&val->lock);
3897
3898         if (want_destroy)
3899                 destroy(val);
3900
3901         *validatorp = NULL;
3902 }
3903
3904 static void
3905 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
3906                isc_logmodule_t *module, int level, const char *fmt, va_list ap)
3907 {
3908         char msgbuf[2048];
3909         static const char spaces[] = "        *";
3910         int depth = val->depth * 2;
3911
3912         vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
3913
3914         if ((unsigned int) depth >= sizeof spaces)
3915                 depth = sizeof spaces - 1;
3916
3917         if (val->event != NULL && val->event->name != NULL) {
3918                 char namebuf[DNS_NAME_FORMATSIZE];
3919                 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3920
3921                 dns_name_format(val->event->name, namebuf, sizeof(namebuf));
3922                 dns_rdatatype_format(val->event->type, typebuf,
3923                                      sizeof(typebuf));
3924                 isc_log_write(dns_lctx, category, module, level,
3925                               "%.*svalidating @%p: %s %s: %s", depth, spaces,
3926                               val, namebuf, typebuf, msgbuf);
3927         } else {
3928                 isc_log_write(dns_lctx, category, module, level,
3929                               "%.*svalidator @%p: %s", depth, spaces,
3930                                val, msgbuf);
3931         }
3932 }
3933
3934 static void
3935 validator_log(void *val, int level, const char *fmt, ...) {
3936         va_list ap;
3937
3938         if (! isc_log_wouldlog(dns_lctx, level))
3939                 return;
3940
3941         va_start(ap, fmt);
3942
3943         validator_logv(val, DNS_LOGCATEGORY_DNSSEC,
3944                        DNS_LOGMODULE_VALIDATOR, level, fmt, ap);
3945         va_end(ap);
3946 }
3947
3948 static void
3949 validator_logcreate(dns_validator_t *val,
3950                     dns_name_t *name, dns_rdatatype_t type,
3951                     const char *caller, const char *operation)
3952 {
3953         char namestr[DNS_NAME_FORMATSIZE];
3954         char typestr[DNS_RDATATYPE_FORMATSIZE];
3955
3956         dns_name_format(name, namestr, sizeof(namestr));
3957         dns_rdatatype_format(type, typestr, sizeof(typestr));
3958         validator_log(val, ISC_LOG_DEBUG(9), "%s: creating %s for %s %s",
3959                       caller, operation, namestr, typestr);
3960 }