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