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