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