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