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