]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/bind9/lib/dns/validator.c
MFC r233909:
[FreeBSD/stable/9.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_uint32_t ttl;
2079                         isc_stdtime_t now;
2080
2081                         isc_stdtime_get(&now);
2082                         ttl = ISC_MIN(event->rdataset->ttl,
2083                                       ISC_MIN(val->siginfo->originalttl,
2084                                               val->siginfo->timeexpire - now));
2085                         event->rdataset->ttl = ttl;
2086                         event->sigrdataset->ttl = ttl;
2087                 }
2088
2089                 if (val->keynode != NULL)
2090                         dns_keytable_detachkeynode(val->keytable,
2091                                                    &val->keynode);
2092                 else {
2093                         if (val->key != NULL)
2094                                 dst_key_free(&val->key);
2095                         if (val->keyset != NULL) {
2096                                 dns_rdataset_disassociate(val->keyset);
2097                                 val->keyset = NULL;
2098                         }
2099                 }
2100                 val->key = NULL;
2101                 if (NEEDNOQNAME(val)) {
2102                         if (val->event->message == NULL) {
2103                                 validator_log(val, ISC_LOG_DEBUG(3),
2104                                       "no message available for noqname proof");
2105                                 return (DNS_R_NOVALIDSIG);
2106                         }
2107                         validator_log(val, ISC_LOG_DEBUG(3),
2108                                       "looking for noqname proof");
2109                         return (nsecvalidate(val, ISC_FALSE));
2110                 } else if (result == ISC_R_SUCCESS) {
2111                         marksecure(event);
2112                         validator_log(val, ISC_LOG_DEBUG(3),
2113                                       "marking as secure, "
2114                                       "noqname proof not needed");
2115                         return (result);
2116                 } else {
2117                         validator_log(val, ISC_LOG_DEBUG(3),
2118                                       "verify failure: %s",
2119                                       isc_result_totext(result));
2120                         resume = ISC_FALSE;
2121                 }
2122         }
2123         if (result != ISC_R_NOMORE) {
2124                 validator_log(val, ISC_LOG_DEBUG(3),
2125                               "failed to iterate signatures: %s",
2126                               isc_result_totext(result));
2127                 return (result);
2128         }
2129
2130         validator_log(val, ISC_LOG_INFO, "no valid signature found");
2131         return (DNS_R_NOVALIDSIG);
2132 }
2133
2134 /*%
2135  * Check whether this DNSKEY (keyrdata) signed the DNSKEY RRset
2136  * (val->event->rdataset).
2137  */
2138 static isc_result_t
2139 checkkey(dns_validator_t *val, dns_rdata_t *keyrdata, isc_uint16_t keyid,
2140          dns_secalg_t algorithm)
2141 {
2142         dns_rdata_rrsig_t sig;
2143         dst_key_t *dstkey = NULL;
2144         isc_result_t result;
2145
2146         for (result = dns_rdataset_first(val->event->sigrdataset);
2147              result == ISC_R_SUCCESS;
2148              result = dns_rdataset_next(val->event->sigrdataset))
2149         {
2150                 dns_rdata_t rdata = DNS_RDATA_INIT;
2151
2152                 dns_rdataset_current(val->event->sigrdataset, &rdata);
2153                 result = dns_rdata_tostruct(&rdata, &sig, NULL);
2154                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2155                 if (keyid != sig.keyid || algorithm != sig.algorithm)
2156                         continue;
2157                 if (dstkey == NULL) {
2158                         result = dns_dnssec_keyfromrdata(val->event->name,
2159                                                          keyrdata,
2160                                                          val->view->mctx,
2161                                                          &dstkey);
2162                         if (result != ISC_R_SUCCESS)
2163                                 /*
2164                                  * This really shouldn't happen, but...
2165                                  */
2166                                 continue;
2167                 }
2168                 result = verify(val, dstkey, &rdata, sig.keyid);
2169                 if (result == ISC_R_SUCCESS)
2170                         break;
2171         }
2172         if (dstkey != NULL)
2173                 dst_key_free(&dstkey);
2174         return (result);
2175 }
2176
2177 /*%
2178  * Find the DNSKEY that corresponds to the DS.
2179  */
2180 static isc_result_t
2181 keyfromds(dns_validator_t *val, dns_rdataset_t *rdataset, dns_rdata_t *dsrdata,
2182           isc_uint8_t digest, isc_uint16_t keyid, dns_secalg_t algorithm,
2183           dns_rdata_t *keyrdata)
2184 {
2185         dns_keytag_t keytag;
2186         dns_rdata_dnskey_t key;
2187         isc_result_t result;
2188         unsigned char dsbuf[DNS_DS_BUFFERSIZE];
2189
2190         for (result = dns_rdataset_first(rdataset);
2191              result == ISC_R_SUCCESS;
2192              result = dns_rdataset_next(rdataset))
2193         {
2194                 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
2195
2196                 dns_rdata_reset(keyrdata);
2197                 dns_rdataset_current(rdataset, keyrdata);
2198                 result = dns_rdata_tostruct(keyrdata, &key, NULL);
2199                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2200                 keytag = compute_keytag(keyrdata, &key);
2201                 if (keyid != keytag || algorithm != key.algorithm)
2202                         continue;
2203                 dns_rdata_reset(&newdsrdata);
2204                 result = dns_ds_buildrdata(val->event->name, keyrdata, digest,
2205                                            dsbuf, &newdsrdata);
2206                 if (result != ISC_R_SUCCESS) {
2207                         validator_log(val, ISC_LOG_DEBUG(3),
2208                                       "dns_ds_buildrdata() -> %s",
2209                                       dns_result_totext(result));
2210                         continue;
2211                 }
2212                 if (dns_rdata_compare(dsrdata, &newdsrdata) == 0)
2213                         break;
2214         }
2215         return (result);
2216 }
2217
2218 /*%
2219  * Validate the DNSKEY RRset by looking for a DNSKEY that matches a
2220  * DLV record and that also verifies the DNSKEY RRset.
2221  */
2222 static isc_result_t
2223 dlv_validatezonekey(dns_validator_t *val) {
2224         dns_rdata_dlv_t dlv;
2225         dns_rdata_t dlvrdata = DNS_RDATA_INIT;
2226         dns_rdata_t keyrdata = DNS_RDATA_INIT;
2227         dns_rdataset_t trdataset;
2228         isc_boolean_t supported_algorithm;
2229         isc_result_t result;
2230         char digest_types[256];
2231
2232         validator_log(val, ISC_LOG_DEBUG(3), "dlv_validatezonekey");
2233
2234         /*
2235          * Look through the DLV record and find the keys that can sign the
2236          * key set and the matching signature.  For each such key, attempt
2237          * verification.
2238          */
2239         supported_algorithm = ISC_FALSE;
2240
2241         /*
2242          * If DNS_DSDIGEST_SHA256 is present we are required to prefer
2243          * it over DNS_DSDIGEST_SHA1.  This in practice means that we
2244          * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
2245          * is present.
2246          */
2247         memset(digest_types, 1, sizeof(digest_types));
2248         for (result = dns_rdataset_first(&val->dlv);
2249              result == ISC_R_SUCCESS;
2250              result = dns_rdataset_next(&val->dlv)) {
2251                 dns_rdata_reset(&dlvrdata);
2252                 dns_rdataset_current(&val->dlv, &dlvrdata);
2253                 result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
2254                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2255
2256                 if (!dns_resolver_algorithm_supported(val->view->resolver,
2257                                                       val->event->name,
2258                                                       dlv.algorithm))
2259                         continue;
2260
2261                 if (dlv.digest_type == DNS_DSDIGEST_SHA256 &&
2262                     dlv.length == ISC_SHA256_DIGESTLENGTH) {
2263                         digest_types[DNS_DSDIGEST_SHA1] = 0;
2264                         break;
2265                 }
2266         }
2267
2268         for (result = dns_rdataset_first(&val->dlv);
2269              result == ISC_R_SUCCESS;
2270              result = dns_rdataset_next(&val->dlv))
2271         {
2272                 dns_rdata_reset(&dlvrdata);
2273                 dns_rdataset_current(&val->dlv, &dlvrdata);
2274                 result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
2275                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2276
2277                 if (!dns_resolver_digest_supported(val->view->resolver,
2278                                                    dlv.digest_type))
2279                         continue;
2280
2281                 if (digest_types[dlv.digest_type] == 0)
2282                         continue;
2283
2284                 if (!dns_resolver_algorithm_supported(val->view->resolver,
2285                                                       val->event->name,
2286                                                       dlv.algorithm))
2287                         continue;
2288
2289                 supported_algorithm = ISC_TRUE;
2290
2291                 dns_rdataset_init(&trdataset);
2292                 dns_rdataset_clone(val->event->rdataset, &trdataset);
2293
2294                 /*
2295                  * Convert to DLV to DS and find matching DNSKEY.
2296                  */
2297                 dlvrdata.type = dns_rdatatype_ds;
2298                 result = keyfromds(val, &trdataset, &dlvrdata,
2299                                    dlv.digest_type, dlv.key_tag,
2300                                    dlv.algorithm, &keyrdata);
2301                 if (result != ISC_R_SUCCESS) {
2302                         dns_rdataset_disassociate(&trdataset);
2303                         validator_log(val, ISC_LOG_DEBUG(3),
2304                                       "no DNSKEY matching DLV");
2305                         continue;
2306                 }
2307
2308                 validator_log(val, ISC_LOG_DEBUG(3),
2309                       "Found matching DLV record: checking for signature");
2310                 /*
2311                  * Check that this DNSKEY signed the DNSKEY rrset.
2312                  */
2313                 result = checkkey(val, &keyrdata, dlv.key_tag, dlv.algorithm);
2314
2315                 dns_rdataset_disassociate(&trdataset);
2316                 if (result == ISC_R_SUCCESS)
2317                         break;
2318                 validator_log(val, ISC_LOG_DEBUG(3),
2319                               "no RRSIG matching DLV key");
2320         }
2321         if (result == ISC_R_SUCCESS) {
2322                 marksecure(val->event);
2323                 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (dlv)");
2324                 return (result);
2325         } else if (result == ISC_R_NOMORE && !supported_algorithm) {
2326                 if (val->mustbesecure) {
2327                         validator_log(val, ISC_LOG_WARNING,
2328                                       "must be secure failure,"
2329                                       "no supported algorithm/digest (dlv)");
2330                         return (DNS_R_MUSTBESECURE);
2331                 }
2332                 validator_log(val, ISC_LOG_DEBUG(3),
2333                               "no supported algorithm/digest (dlv)");
2334                 markanswer(val, "dlv_validatezonekey (2)");
2335                 return (ISC_R_SUCCESS);
2336         } else
2337                 return (DNS_R_NOVALIDSIG);
2338 }
2339
2340 /*%
2341  * Attempts positive response validation of an RRset containing zone keys
2342  * (i.e. a DNSKEY rrset).
2343  *
2344  * Returns:
2345  * \li  ISC_R_SUCCESS   Validation completed successfully
2346  * \li  DNS_R_WAIT      Validation has started but is waiting
2347  *                      for an event.
2348  * \li  Other return codes are possible and all indicate failure.
2349  */
2350 static isc_result_t
2351 validatezonekey(dns_validator_t *val) {
2352         isc_result_t result;
2353         dns_validatorevent_t *event;
2354         dns_rdataset_t trdataset;
2355         dns_rdata_t dsrdata = DNS_RDATA_INIT;
2356         dns_rdata_t keyrdata = DNS_RDATA_INIT;
2357         dns_rdata_t sigrdata = DNS_RDATA_INIT;
2358         char namebuf[DNS_NAME_FORMATSIZE];
2359         dns_rdata_ds_t ds;
2360         dns_rdata_rrsig_t sig;
2361         dst_key_t *dstkey;
2362         isc_boolean_t supported_algorithm;
2363         isc_boolean_t atsep = ISC_FALSE;
2364         char digest_types[256];
2365
2366         /*
2367          * Caller must be holding the validator lock.
2368          */
2369
2370         event = val->event;
2371
2372         if (val->havedlvsep && val->dlv.trust >= dns_trust_secure &&
2373             dns_name_equal(event->name, dns_fixedname_name(&val->dlvsep)))
2374                 return (dlv_validatezonekey(val));
2375
2376         if (val->dsset == NULL) {
2377
2378                 /*
2379                  * We have a dlv sep.  Skip looking up the SEP from
2380                  * {trusted,managed}-keys.  If the dlv sep is for the
2381                  * root then it will have been handled above so we don't
2382                  * need to check whether val->event->name is "." prior to
2383                  * looking up the DS.
2384                  */
2385                 if (val->havedlvsep)
2386                         goto find_ds;
2387
2388                 /*
2389                  * First, see if this key was signed by a trusted key.
2390                  */
2391                 for (result = dns_rdataset_first(val->event->sigrdataset);
2392                      result == ISC_R_SUCCESS;
2393                      result = dns_rdataset_next(val->event->sigrdataset))
2394                 {
2395                         dns_keynode_t *keynode = NULL;
2396                         dns_fixedname_t fixed;
2397                         dns_name_t *found;
2398
2399                         dns_fixedname_init(&fixed);
2400                         found = dns_fixedname_name(&fixed);
2401                         dns_rdata_reset(&sigrdata);
2402                         dns_rdataset_current(val->event->sigrdataset,
2403                                              &sigrdata);
2404                         result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
2405                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2406
2407                         if (!dns_name_equal(val->event->name, &sig.signer))
2408                                 continue;
2409
2410                         result = dns_keytable_findkeynode(val->keytable,
2411                                                           val->event->name,
2412                                                           sig.algorithm,
2413                                                           sig.keyid, &keynode);
2414                         if (result == ISC_R_NOTFOUND &&
2415                             dns_keytable_finddeepestmatch(val->keytable,
2416                                   val->event->name, found) != ISC_R_SUCCESS) {
2417                                 if (val->mustbesecure) {
2418                                         validator_log(val, ISC_LOG_WARNING,
2419                                                      "must be secure failure, "
2420                                                      "not beneath secure root");
2421                                         return (DNS_R_MUSTBESECURE);
2422                                 } else
2423                                         validator_log(val, ISC_LOG_DEBUG(3),
2424                                                      "not beneath secure root");
2425                                 if (val->view->dlv == NULL) {
2426                                         markanswer(val, "validatezonekey (1)");
2427                                         return (ISC_R_SUCCESS);
2428                                 }
2429                                 return (startfinddlvsep(val, dns_rootname));
2430                         }
2431                         if (result == DNS_R_PARTIALMATCH ||
2432                             result == ISC_R_SUCCESS)
2433                                 atsep = ISC_TRUE;
2434                         while (result == ISC_R_SUCCESS) {
2435                                 dns_keynode_t *nextnode = NULL;
2436                                 dstkey = dns_keynode_key(keynode);
2437                                 if (dstkey == NULL) {
2438                                         dns_keytable_detachkeynode(
2439                                                                 val->keytable,
2440                                                                 &keynode);
2441                                         break;
2442                                 }
2443                                 result = verify(val, dstkey, &sigrdata,
2444                                                 sig.keyid);
2445                                 if (result == ISC_R_SUCCESS) {
2446                                         dns_keytable_detachkeynode(
2447                                                                 val->keytable,
2448                                                                 &keynode);
2449                                         break;
2450                                 }
2451                                 result = dns_keytable_findnextkeynode(
2452                                                                 val->keytable,
2453                                                                 keynode,
2454                                                                 &nextnode);
2455                                 dns_keytable_detachkeynode(val->keytable,
2456                                                            &keynode);
2457                                 keynode = nextnode;
2458                         }
2459                         if (result == ISC_R_SUCCESS) {
2460                                 marksecure(event);
2461                                 validator_log(val, ISC_LOG_DEBUG(3),
2462                                               "signed by trusted key; "
2463                                               "marking as secure");
2464                                 return (result);
2465                         }
2466                 }
2467
2468                 if (atsep) {
2469                         /*
2470                          * We have not found a key to verify this DNSKEY
2471                          * RRset.  As this is a SEP we have to assume that
2472                          * the RRset is invalid.
2473                          */
2474                         dns_name_format(val->event->name, namebuf,
2475                                         sizeof(namebuf));
2476                         validator_log(val, ISC_LOG_NOTICE,
2477                                       "unable to find a DNSKEY which verifies "
2478                                       "the DNSKEY RRset and also matches a "
2479                                       "trusted key for '%s'",
2480                                       namebuf);
2481                         validator_log(val, ISC_LOG_NOTICE,
2482                                       "please check the 'trusted-keys' for "
2483                                       "'%s' in named.conf.", namebuf);
2484                         return (DNS_R_NOVALIDKEY);
2485                 }
2486
2487                 /*
2488                  * If this is the root name and there was no trusted key,
2489                  * give up, since there's no DS at the root.
2490                  */
2491                 if (dns_name_equal(event->name, dns_rootname)) {
2492                         if ((val->attributes & VALATTR_TRIEDVERIFY) != 0) {
2493                                 validator_log(val, ISC_LOG_DEBUG(3),
2494                                               "root key failed to validate");
2495                                 return (DNS_R_NOVALIDSIG);
2496                         } else {
2497                                 validator_log(val, ISC_LOG_DEBUG(3),
2498                                               "no trusted root key");
2499                                 return (DNS_R_NOVALIDDS);
2500                         }
2501                 }
2502  find_ds:
2503                 /*
2504                  * Otherwise, try to find the DS record.
2505                  */
2506                 result = view_find(val, val->event->name, dns_rdatatype_ds);
2507                 if (result == ISC_R_SUCCESS) {
2508                         /*
2509                          * We have DS records.
2510                          */
2511                         val->dsset = &val->frdataset;
2512                         if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
2513                              DNS_TRUST_ANSWER(val->frdataset.trust)) &&
2514                             dns_rdataset_isassociated(&val->fsigrdataset))
2515                         {
2516                                 result = create_validator(val,
2517                                                           val->event->name,
2518                                                           dns_rdatatype_ds,
2519                                                           &val->frdataset,
2520                                                           &val->fsigrdataset,
2521                                                           dsvalidated,
2522                                                           "validatezonekey");
2523                                 if (result != ISC_R_SUCCESS)
2524                                         return (result);
2525                                 return (DNS_R_WAIT);
2526                         } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
2527                                 /*
2528                                  * There should never be an unsigned DS.
2529                                  */
2530                                 dns_rdataset_disassociate(&val->frdataset);
2531                                 validator_log(val, ISC_LOG_DEBUG(2),
2532                                               "unsigned DS record");
2533                                 return (DNS_R_NOVALIDSIG);
2534                         } else {
2535                                 result = ISC_R_SUCCESS;
2536                                 POST(result);
2537                         }
2538                 } else if (result == ISC_R_NOTFOUND) {
2539                         /*
2540                          * We don't have the DS.  Find it.
2541                          */
2542                         result = create_fetch(val, val->event->name,
2543                                               dns_rdatatype_ds, dsfetched,
2544                                               "validatezonekey");
2545                         if (result != ISC_R_SUCCESS)
2546                                 return (result);
2547                         return (DNS_R_WAIT);
2548                 } else if (result == DNS_R_NCACHENXDOMAIN ||
2549                            result == DNS_R_NCACHENXRRSET ||
2550                            result == DNS_R_EMPTYNAME ||
2551                            result == DNS_R_NXDOMAIN ||
2552                            result == DNS_R_NXRRSET ||
2553                            result == DNS_R_CNAME)
2554                 {
2555                         /*
2556                          * The DS does not exist.
2557                          */
2558                         if (dns_rdataset_isassociated(&val->frdataset))
2559                                 dns_rdataset_disassociate(&val->frdataset);
2560                         if (dns_rdataset_isassociated(&val->fsigrdataset))
2561                                 dns_rdataset_disassociate(&val->fsigrdataset);
2562                         validator_log(val, ISC_LOG_DEBUG(2), "no DS record");
2563                         return (DNS_R_NOVALIDSIG);
2564                 } else if (result == DNS_R_BROKENCHAIN)
2565                         return (result);
2566         }
2567
2568         /*
2569          * We have a DS set.
2570          */
2571         INSIST(val->dsset != NULL);
2572
2573         if (val->dsset->trust < dns_trust_secure) {
2574                 if (val->mustbesecure) {
2575                         validator_log(val, ISC_LOG_WARNING,
2576                                       "must be secure failure,"
2577                                       " insecure DS");
2578                         return (DNS_R_MUSTBESECURE);
2579                 }
2580                 if (val->view->dlv == NULL || DLVTRIED(val)) {
2581                         markanswer(val, "validatezonekey (2)");
2582                         return (ISC_R_SUCCESS);
2583                 }
2584                 return (startfinddlvsep(val, val->event->name));
2585         }
2586
2587         /*
2588          * Look through the DS record and find the keys that can sign the
2589          * key set and the matching signature.  For each such key, attempt
2590          * verification.
2591          */
2592
2593         supported_algorithm = ISC_FALSE;
2594
2595         /*
2596          * If DNS_DSDIGEST_SHA256 is present we are required to prefer
2597          * it over DNS_DSDIGEST_SHA1.  This in practice means that we
2598          * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
2599          * is present.
2600          */
2601         memset(digest_types, 1, sizeof(digest_types));
2602         for (result = dns_rdataset_first(val->dsset);
2603              result == ISC_R_SUCCESS;
2604              result = dns_rdataset_next(val->dsset)) {
2605                 dns_rdata_reset(&dsrdata);
2606                 dns_rdataset_current(val->dsset, &dsrdata);
2607                 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
2608                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2609
2610                 if (!dns_resolver_algorithm_supported(val->view->resolver,
2611                                                       val->event->name,
2612                                                       ds.algorithm))
2613                         continue;
2614
2615                 if (ds.digest_type == DNS_DSDIGEST_SHA256 &&
2616                     ds.length == ISC_SHA256_DIGESTLENGTH) {
2617                         digest_types[DNS_DSDIGEST_SHA1] = 0;
2618                         break;
2619                 }
2620         }
2621
2622         for (result = dns_rdataset_first(val->dsset);
2623              result == ISC_R_SUCCESS;
2624              result = dns_rdataset_next(val->dsset))
2625         {
2626                 dns_rdata_reset(&dsrdata);
2627                 dns_rdataset_current(val->dsset, &dsrdata);
2628                 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
2629                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2630
2631                 if (!dns_resolver_digest_supported(val->view->resolver,
2632                                                    ds.digest_type))
2633                         continue;
2634
2635                 if (digest_types[ds.digest_type] == 0)
2636                         continue;
2637
2638                 if (!dns_resolver_algorithm_supported(val->view->resolver,
2639                                                       val->event->name,
2640                                                       ds.algorithm))
2641                         continue;
2642
2643                 supported_algorithm = ISC_TRUE;
2644
2645                 dns_rdataset_init(&trdataset);
2646                 dns_rdataset_clone(val->event->rdataset, &trdataset);
2647
2648                 /*
2649                  * Find matching DNSKEY from DS.
2650                  */
2651                 result = keyfromds(val, &trdataset, &dsrdata, ds.digest_type,
2652                                    ds.key_tag, ds.algorithm, &keyrdata);
2653                 if (result != ISC_R_SUCCESS) {
2654                         dns_rdataset_disassociate(&trdataset);
2655                         validator_log(val, ISC_LOG_DEBUG(3),
2656                                       "no DNSKEY matching DS");
2657                         continue;
2658                 }
2659
2660                 /*
2661                  * Check that this DNSKEY signed the DNSKEY rrset.
2662                  */
2663                 result = checkkey(val, &keyrdata, ds.key_tag, ds.algorithm);
2664
2665                 dns_rdataset_disassociate(&trdataset);
2666                 if (result == ISC_R_SUCCESS)
2667                         break;
2668                 validator_log(val, ISC_LOG_DEBUG(3),
2669                               "no RRSIG matching DS key");
2670         }
2671         if (result == ISC_R_SUCCESS) {
2672                 marksecure(event);
2673                 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (DS)");
2674                 return (result);
2675         } else if (result == ISC_R_NOMORE && !supported_algorithm) {
2676                 if (val->mustbesecure) {
2677                         validator_log(val, ISC_LOG_WARNING,
2678                                       "must be secure failure, "
2679                                       "no supported algorithm/digest (DS)");
2680                         return (DNS_R_MUSTBESECURE);
2681                 }
2682                 validator_log(val, ISC_LOG_DEBUG(3),
2683                               "no supported algorithm/digest (DS)");
2684                 markanswer(val, "validatezonekey (3)");
2685                 return (ISC_R_SUCCESS);
2686         } else {
2687                 validator_log(val, ISC_LOG_INFO,
2688                               "no valid signature found (DS)");
2689                 return (DNS_R_NOVALIDSIG);
2690         }
2691 }
2692
2693 /*%
2694  * Starts a positive response validation.
2695  *
2696  * Returns:
2697  * \li  ISC_R_SUCCESS   Validation completed successfully
2698  * \li  DNS_R_WAIT      Validation has started but is waiting
2699  *                      for an event.
2700  * \li  Other return codes are possible and all indicate failure.
2701  */
2702 static isc_result_t
2703 start_positive_validation(dns_validator_t *val) {
2704         /*
2705          * If this is not a key, go straight into validate().
2706          */
2707         if (val->event->type != dns_rdatatype_dnskey || !isselfsigned(val))
2708                 return (validate(val, ISC_FALSE));
2709
2710         return (validatezonekey(val));
2711 }
2712
2713 /*%
2714  * val_rdataset_first and val_rdataset_next provide iteration methods
2715  * that hide whether we are iterating across a message or a  negative
2716  * cache rdataset.
2717  */
2718 static isc_result_t
2719 val_rdataset_first(dns_validator_t *val, dns_name_t **namep,
2720                    dns_rdataset_t **rdatasetp)
2721 {
2722         dns_message_t *message = val->event->message;
2723         isc_result_t result;
2724
2725         REQUIRE(rdatasetp != NULL);
2726         REQUIRE(namep != NULL);
2727         if (message == NULL) {
2728                 REQUIRE(*rdatasetp != NULL);
2729                 REQUIRE(*namep != NULL);
2730         } else {
2731                 REQUIRE(*rdatasetp == NULL);
2732                 REQUIRE(*namep == NULL);
2733         }
2734
2735         if (message != NULL) {
2736                 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2737                 if (result != ISC_R_SUCCESS)
2738                         return (result);
2739                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, namep);
2740                 *rdatasetp = ISC_LIST_HEAD((*namep)->list);
2741                 INSIST(*rdatasetp != NULL);
2742         } else {
2743                 result = dns_rdataset_first(val->event->rdataset);
2744                 if (result == ISC_R_SUCCESS)
2745                         dns_ncache_current(val->event->rdataset, *namep,
2746                                            *rdatasetp);
2747         }
2748         return (result);
2749 }
2750
2751 static isc_result_t
2752 val_rdataset_next(dns_validator_t *val, dns_name_t **namep,
2753                   dns_rdataset_t **rdatasetp)
2754 {
2755         dns_message_t *message = val->event->message;
2756         isc_result_t result = ISC_R_SUCCESS;
2757
2758         REQUIRE(rdatasetp != NULL && *rdatasetp != NULL);
2759         REQUIRE(namep != NULL && *namep != NULL);
2760
2761         if (message != NULL) {
2762                 dns_rdataset_t *rdataset = *rdatasetp;
2763                 rdataset = ISC_LIST_NEXT(rdataset, link);
2764                 if (rdataset == NULL) {
2765                         *namep = NULL;
2766                         result = dns_message_nextname(message,
2767                                                       DNS_SECTION_AUTHORITY);
2768                         if (result == ISC_R_SUCCESS) {
2769                                 dns_message_currentname(message,
2770                                                         DNS_SECTION_AUTHORITY,
2771                                                         namep);
2772                                 rdataset = ISC_LIST_HEAD((*namep)->list);
2773                                 INSIST(rdataset != NULL);
2774                         }
2775                 }
2776                 *rdatasetp = rdataset;
2777         } else {
2778                 dns_rdataset_disassociate(*rdatasetp);
2779                 result = dns_rdataset_next(val->event->rdataset);
2780                 if (result == ISC_R_SUCCESS)
2781                         dns_ncache_current(val->event->rdataset, *namep,
2782                                            *rdatasetp);
2783         }
2784         return (result);
2785 }
2786
2787 /*%
2788  * Look for NODATA at the wildcard and NOWILDCARD proofs in the
2789  * previously validated NSEC records.  As these proofs are mutually
2790  * exclusive we stop when one is found.
2791  *
2792  * Returns
2793  * \li  ISC_R_SUCCESS
2794  */
2795 static isc_result_t
2796 checkwildcard(dns_validator_t *val, dns_rdatatype_t type, dns_name_t *zonename)
2797 {
2798         dns_name_t *name, *wild, tname;
2799         isc_result_t result;
2800         isc_boolean_t exists, data;
2801         char namebuf[DNS_NAME_FORMATSIZE];
2802         dns_rdataset_t *rdataset, trdataset;
2803
2804         dns_name_init(&tname, NULL);
2805         dns_rdataset_init(&trdataset);
2806         wild = dns_fixedname_name(&val->wild);
2807
2808         if (dns_name_countlabels(wild) == 0) {
2809                 validator_log(val, ISC_LOG_DEBUG(3),
2810                               "in checkwildcard: no wildcard to check");
2811                 return (ISC_R_SUCCESS);
2812         }
2813
2814         dns_name_format(wild, namebuf, sizeof(namebuf));
2815         validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf);
2816
2817         if (val->event->message == NULL) {
2818                 name = &tname;
2819                 rdataset = &trdataset;
2820         } else {
2821                 name = NULL;
2822                 rdataset = NULL;
2823         }
2824
2825         for (result = val_rdataset_first(val, &name, &rdataset);
2826              result == ISC_R_SUCCESS;
2827              result = val_rdataset_next(val, &name, &rdataset))
2828         {
2829                 if (rdataset->type != type ||
2830                     rdataset->trust != dns_trust_secure)
2831                         continue;
2832
2833                 if (rdataset->type == dns_rdatatype_nsec &&
2834                     (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
2835                     !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
2836                     nsecnoexistnodata(val, wild, name, rdataset,
2837                                       &exists, &data, NULL)
2838                                        == ISC_R_SUCCESS)
2839                 {
2840                         dns_name_t **proofs = val->event->proofs;
2841                         if (exists && !data)
2842                                 val->attributes |= VALATTR_FOUNDNODATA;
2843                         if (exists && !data && NEEDNODATA(val))
2844                                 proofs[DNS_VALIDATOR_NODATAPROOF] =
2845                                                  name;
2846                         if (!exists)
2847                                 val->attributes |=
2848                                          VALATTR_FOUNDNOWILDCARD;
2849                         if (!exists && NEEDNOQNAME(val))
2850                                 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
2851                                                  name;
2852                         if (dns_rdataset_isassociated(&trdataset))
2853                                 dns_rdataset_disassociate(&trdataset);
2854                         return (ISC_R_SUCCESS);
2855                 }
2856
2857                 if (rdataset->type == dns_rdatatype_nsec3 &&
2858                     (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
2859                     !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
2860                     nsec3noexistnodata(val, wild, name, rdataset,
2861                                        zonename, &exists, &data,
2862                                        NULL, NULL, NULL, NULL, NULL,
2863                                        NULL) == ISC_R_SUCCESS)
2864                 {
2865                         dns_name_t **proofs = val->event->proofs;
2866                         if (exists && !data)
2867                                 val->attributes |= VALATTR_FOUNDNODATA;
2868                         if (exists && !data && NEEDNODATA(val))
2869                                 proofs[DNS_VALIDATOR_NODATAPROOF] =
2870                                                  name;
2871                         if (!exists)
2872                                 val->attributes |=
2873                                          VALATTR_FOUNDNOWILDCARD;
2874                         if (!exists && NEEDNOQNAME(val))
2875                                 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
2876                                                  name;
2877                         if (dns_rdataset_isassociated(&trdataset))
2878                                 dns_rdataset_disassociate(&trdataset);
2879                         return (ISC_R_SUCCESS);
2880                 }
2881         }
2882         if (result == ISC_R_NOMORE)
2883                 result = ISC_R_SUCCESS;
2884         if (dns_rdataset_isassociated(&trdataset))
2885                 dns_rdataset_disassociate(&trdataset);
2886         return (result);
2887 }
2888
2889 static isc_result_t
2890 findnsec3proofs(dns_validator_t *val) {
2891         dns_name_t *name, tname;
2892         isc_result_t result;
2893         isc_boolean_t exists, data, optout, unknown;
2894         isc_boolean_t setclosest, setnearest, *setclosestp;
2895         dns_fixedname_t fclosest, fnearest, fzonename;
2896         dns_name_t *closest, *nearest, *zonename, *closestp;
2897         dns_name_t **proofs = val->event->proofs;
2898         dns_rdataset_t *rdataset, trdataset;
2899
2900         dns_name_init(&tname, NULL);
2901         dns_rdataset_init(&trdataset);
2902         dns_fixedname_init(&fclosest);
2903         dns_fixedname_init(&fnearest);
2904         dns_fixedname_init(&fzonename);
2905         closest = dns_fixedname_name(&fclosest);
2906         nearest = dns_fixedname_name(&fnearest);
2907         zonename = dns_fixedname_name(&fzonename);
2908
2909         if (val->event->message == NULL) {
2910                 name = &tname;
2911                 rdataset = &trdataset;
2912         } else {
2913                 name = NULL;
2914                 rdataset = NULL;
2915         }
2916
2917         for (result = val_rdataset_first(val, &name, &rdataset);
2918              result == ISC_R_SUCCESS;
2919              result = val_rdataset_next(val, &name, &rdataset))
2920         {
2921                 if (rdataset->type != dns_rdatatype_nsec3 ||
2922                     rdataset->trust != dns_trust_secure)
2923                         continue;
2924
2925                 result = nsec3noexistnodata(val, val->event->name,
2926                                             name, rdataset,
2927                                             zonename, NULL, NULL, NULL,
2928                                             NULL, NULL, NULL, NULL,
2929                                             NULL);
2930                 if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS) {
2931                         if (dns_rdataset_isassociated(&trdataset))
2932                                 dns_rdataset_disassociate(&trdataset);
2933                         return (result);
2934                 }
2935         }
2936         if (result != ISC_R_NOMORE)
2937                 result = ISC_R_SUCCESS;
2938         POST(result);
2939
2940         if (dns_name_countlabels(zonename) == 0)
2941                 return (ISC_R_SUCCESS);
2942
2943         /*
2944          * If the val->closest is set then we want to use it otherwise
2945          * we need to discover it.
2946          */
2947         if (dns_name_countlabels(dns_fixedname_name(&val->closest)) != 0) {
2948                 char namebuf[DNS_NAME_FORMATSIZE];
2949
2950                 dns_name_format(dns_fixedname_name(&val->closest),
2951                                  namebuf, sizeof(namebuf));
2952                 validator_log(val, ISC_LOG_DEBUG(3), "closest encloser from "
2953                               "wildcard signature '%s'", namebuf);
2954                 dns_name_copy(dns_fixedname_name(&val->closest), closest, NULL);
2955                 closestp = NULL;
2956                 setclosestp = NULL;
2957         } else {
2958                 closestp = closest;
2959                 setclosestp = &setclosest;
2960         }
2961
2962         for (result = val_rdataset_first(val, &name, &rdataset);
2963              result == ISC_R_SUCCESS;
2964              result = val_rdataset_next(val, &name, &rdataset))
2965         {
2966                 if (rdataset->type != dns_rdatatype_nsec3 ||
2967                     rdataset->trust != dns_trust_secure)
2968                         continue;
2969
2970                 /*
2971                  * We process all NSEC3 records to find the closest
2972                  * encloser and nearest name to the closest encloser.
2973                  */
2974                 setclosest = setnearest = ISC_FALSE;
2975                 optout = ISC_FALSE;
2976                 unknown = ISC_FALSE;
2977                 (void)nsec3noexistnodata(val, val->event->name, name, rdataset,
2978                                          zonename, &exists, &data, &optout,
2979                                          &unknown, setclosestp, &setnearest,
2980                                          closestp, nearest);
2981                 if (setclosest)
2982                         proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
2983                 if (unknown)
2984                         val->attributes |= VALATTR_FOUNDUNKNOWN;
2985                 if (result != ISC_R_SUCCESS)
2986                         continue;
2987                 if (exists && !data && NEEDNODATA(val)) {
2988                         val->attributes |= VALATTR_FOUNDNODATA;
2989                         proofs[DNS_VALIDATOR_NODATAPROOF] = name;
2990                 }
2991                 if (!exists && setnearest) {
2992                         val->attributes |= VALATTR_FOUNDNOQNAME;
2993                         proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name;
2994                         if (optout)
2995                                 val->attributes |= VALATTR_FOUNDOPTOUT;
2996                 }
2997         }
2998         if (result == ISC_R_NOMORE)
2999                 result = ISC_R_SUCCESS;
3000
3001         /*
3002          * To know we have a valid noqname and optout proofs we need to also
3003          * have a valid closest encloser.  Otherwise we could still be looking
3004          * at proofs from the parent zone.
3005          */
3006         if (dns_name_countlabels(closest) > 0 &&
3007             dns_name_countlabels(nearest) ==
3008             dns_name_countlabels(closest) + 1 &&
3009             dns_name_issubdomain(nearest, closest))
3010         {
3011                 val->attributes |= VALATTR_FOUNDCLOSEST;
3012                 result = dns_name_concatenate(dns_wildcardname, closest,
3013                                               dns_fixedname_name(&val->wild),
3014                                               NULL);
3015                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3016         } else {
3017                 val->attributes &= ~VALATTR_FOUNDNOQNAME;
3018                 val->attributes &= ~VALATTR_FOUNDOPTOUT;
3019                 proofs[DNS_VALIDATOR_NOQNAMEPROOF] = NULL;
3020         }
3021
3022         /*
3023          * Do we need to check for the wildcard?
3024          */
3025         if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
3026             ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
3027                 result = checkwildcard(val, dns_rdatatype_nsec3, zonename);
3028                 if (result != ISC_R_SUCCESS)
3029                         return (result);
3030         }
3031         return (result);
3032 }
3033
3034 /*%
3035  * Validate the authority section records.
3036  */
3037 static isc_result_t
3038 validate_authority(dns_validator_t *val, isc_boolean_t resume) {
3039         dns_name_t *name;
3040         dns_message_t *message = val->event->message;
3041         isc_result_t result;
3042
3043         if (!resume)
3044                 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
3045         else
3046                 result = ISC_R_SUCCESS;
3047
3048         for (;
3049              result == ISC_R_SUCCESS;
3050              result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
3051         {
3052                 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
3053
3054                 name = NULL;
3055                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
3056                 if (resume) {
3057                         rdataset = ISC_LIST_NEXT(val->currentset, link);
3058                         val->currentset = NULL;
3059                         resume = ISC_FALSE;
3060                 } else
3061                         rdataset = ISC_LIST_HEAD(name->list);
3062
3063                 for (;
3064                      rdataset != NULL;
3065                      rdataset = ISC_LIST_NEXT(rdataset, link))
3066                 {
3067                         if (rdataset->type == dns_rdatatype_rrsig)
3068                                 continue;
3069
3070                         for (sigrdataset = ISC_LIST_HEAD(name->list);
3071                              sigrdataset != NULL;
3072                              sigrdataset = ISC_LIST_NEXT(sigrdataset,
3073                                                          link))
3074                         {
3075                                 if (sigrdataset->type == dns_rdatatype_rrsig &&
3076                                     sigrdataset->covers == rdataset->type)
3077                                         break;
3078                         }
3079                         /*
3080                          * If a signed zone is missing the zone key, bad
3081                          * things could happen.  A query for data in the zone
3082                          * would lead to a query for the zone key, which
3083                          * would return a negative answer, which would contain
3084                          * an SOA and an NSEC signed by the missing key, which
3085                          * would trigger another query for the DNSKEY (since
3086                          * the first one is still in progress), and go into an
3087                          * infinite loop.  Avoid that.
3088                          */
3089                         if (val->event->type == dns_rdatatype_dnskey &&
3090                             rdataset->type == dns_rdatatype_nsec &&
3091                             dns_name_equal(name, val->event->name))
3092                         {
3093                                 dns_rdata_t nsec = DNS_RDATA_INIT;
3094
3095                                 result = dns_rdataset_first(rdataset);
3096                                 if (result != ISC_R_SUCCESS)
3097                                         return (result);
3098                                 dns_rdataset_current(rdataset, &nsec);
3099                                 if (dns_nsec_typepresent(&nsec,
3100                                                         dns_rdatatype_soa))
3101                                         continue;
3102                         }
3103                         val->currentset = rdataset;
3104                         result = create_validator(val, name, rdataset->type,
3105                                                   rdataset, sigrdataset,
3106                                                   authvalidated,
3107                                                   "validate_authority");
3108                         if (result != ISC_R_SUCCESS)
3109                                 return (result);
3110                         val->authcount++;
3111                         return (DNS_R_WAIT);
3112                 }
3113         }
3114         if (result == ISC_R_NOMORE)
3115                 result = ISC_R_SUCCESS;
3116         return (result);
3117 }
3118
3119 /*%
3120  * Validate the ncache elements.
3121  */
3122 static isc_result_t
3123 validate_ncache(dns_validator_t *val, isc_boolean_t resume) {
3124         dns_name_t *name;
3125         isc_result_t result;
3126
3127         if (!resume)
3128                 result = dns_rdataset_first(val->event->rdataset);
3129         else
3130                 result = dns_rdataset_next(val->event->rdataset);
3131
3132         for (;
3133              result == ISC_R_SUCCESS;
3134              result = dns_rdataset_next(val->event->rdataset))
3135         {
3136                 dns_rdataset_t *rdataset, *sigrdataset = NULL;
3137
3138                 if (dns_rdataset_isassociated(&val->frdataset))
3139                         dns_rdataset_disassociate(&val->frdataset);
3140                 if (dns_rdataset_isassociated(&val->fsigrdataset))
3141                         dns_rdataset_disassociate(&val->fsigrdataset);
3142
3143                 dns_fixedname_init(&val->fname);
3144                 name = dns_fixedname_name(&val->fname);
3145                 rdataset = &val->frdataset;
3146                 dns_ncache_current(val->event->rdataset, name, rdataset);
3147
3148                 if (val->frdataset.type == dns_rdatatype_rrsig)
3149                         continue;
3150
3151                 result = dns_ncache_getsigrdataset(val->event->rdataset, name,
3152                                                    rdataset->type,
3153                                                    &val->fsigrdataset);
3154                 if (result == ISC_R_SUCCESS)
3155                         sigrdataset = &val->fsigrdataset;
3156
3157                 /*
3158                  * If a signed zone is missing the zone key, bad
3159                  * things could happen.  A query for data in the zone
3160                  * would lead to a query for the zone key, which
3161                  * would return a negative answer, which would contain
3162                  * an SOA and an NSEC signed by the missing key, which
3163                  * would trigger another query for the DNSKEY (since
3164                  * the first one is still in progress), and go into an
3165                  * infinite loop.  Avoid that.
3166                  */
3167                 if (val->event->type == dns_rdatatype_dnskey &&
3168                     rdataset->type == dns_rdatatype_nsec &&
3169                     dns_name_equal(name, val->event->name))
3170                 {
3171                         dns_rdata_t nsec = DNS_RDATA_INIT;
3172
3173                         result = dns_rdataset_first(rdataset);
3174                         if (result != ISC_R_SUCCESS)
3175                                 return (result);
3176                         dns_rdataset_current(rdataset, &nsec);
3177                         if (dns_nsec_typepresent(&nsec,
3178                                                 dns_rdatatype_soa))
3179                                 continue;
3180                 }
3181                 val->currentset = rdataset;
3182                 result = create_validator(val, name, rdataset->type,
3183                                           rdataset, sigrdataset,
3184                                           authvalidated,
3185                                           "validate_ncache");
3186                 if (result != ISC_R_SUCCESS)
3187                         return (result);
3188                 val->authcount++;
3189                 return (DNS_R_WAIT);
3190         }
3191         if (result == ISC_R_NOMORE)
3192                 result = ISC_R_SUCCESS;
3193         return (result);
3194 }
3195
3196 /*%
3197  * Prove a negative answer is good or that there is a NOQNAME when the
3198  * answer is from a wildcard.
3199  *
3200  * Loop through the authority section looking for NODATA, NOWILDCARD
3201  * and NOQNAME proofs in the NSEC records by calling authvalidated().
3202  *
3203  * If the required proofs are found we are done.
3204  *
3205  * If the proofs are not found attempt to prove this is a unsecure
3206  * response.
3207  */
3208 static isc_result_t
3209 nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
3210         isc_result_t result;
3211
3212         if (resume)
3213                 validator_log(val, ISC_LOG_DEBUG(3), "resuming nsecvalidate");
3214
3215         if (val->event->message == NULL)
3216                 result = validate_ncache(val, resume);
3217         else
3218                 result = validate_authority(val, resume);
3219
3220         if (result != ISC_R_SUCCESS)
3221                 return (result);
3222
3223         /*
3224          * Do we only need to check for NOQNAME?  To get here we must have
3225          * had a secure wildcard answer.
3226          */
3227         if (!NEEDNODATA(val) && !NEEDNOWILDCARD(val) && NEEDNOQNAME(val)) {
3228                 if (!FOUNDNOQNAME(val))
3229                         findnsec3proofs(val);
3230                 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val)) {
3231                         validator_log(val, ISC_LOG_DEBUG(3),
3232                                       "marking as secure, noqname proof found");
3233                         marksecure(val->event);
3234                         return (ISC_R_SUCCESS);
3235                 } else if (FOUNDOPTOUT(val) &&
3236                            dns_name_countlabels(dns_fixedname_name(&val->wild))
3237                                          != 0) {
3238                         validator_log(val, ISC_LOG_DEBUG(3),
3239                                       "optout proof found");
3240                         val->event->optout = ISC_TRUE;
3241                         markanswer(val, "nsecvalidate (1)");
3242                         return (ISC_R_SUCCESS);
3243                 } else if ((val->attributes & VALATTR_FOUNDUNKNOWN) != 0) {
3244                         validator_log(val, ISC_LOG_DEBUG(3),
3245                                       "unknown NSEC3 hash algorithm found");
3246                         markanswer(val, "nsecvalidate (2)");
3247                         return (ISC_R_SUCCESS);
3248                 }
3249                 validator_log(val, ISC_LOG_DEBUG(3),
3250                               "noqname proof not found");
3251                 return (DNS_R_NOVALIDNSEC);
3252         }
3253
3254         if (!FOUNDNOQNAME(val) && !FOUNDNODATA(val))
3255                 findnsec3proofs(val);
3256
3257         /*
3258          * Do we need to check for the wildcard?
3259          */
3260         if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
3261             ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
3262                 result = checkwildcard(val, dns_rdatatype_nsec, NULL);
3263                 if (result != ISC_R_SUCCESS)
3264                         return (result);
3265         }
3266
3267         if ((NEEDNODATA(val) && (FOUNDNODATA(val) || FOUNDOPTOUT(val))) ||
3268             (NEEDNOQNAME(val) && FOUNDNOQNAME(val) &&
3269              NEEDNOWILDCARD(val) && FOUNDNOWILDCARD(val) &&
3270              FOUNDCLOSEST(val))) {
3271                 if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
3272                         val->event->optout = ISC_TRUE;
3273                 validator_log(val, ISC_LOG_DEBUG(3),
3274                               "nonexistence proof(s) found");
3275                 if (val->event->message == NULL)
3276                         marksecure(val->event);
3277                 return (ISC_R_SUCCESS);
3278         }
3279
3280         if (val->authfail != 0 && val->authcount == val->authfail)
3281                 return (DNS_R_BROKENCHAIN);
3282         validator_log(val, ISC_LOG_DEBUG(3),
3283                       "nonexistence proof(s) not found");
3284         val->attributes |= VALATTR_INSECURITY;
3285         return (proveunsecure(val, ISC_FALSE, ISC_FALSE));
3286 }
3287
3288 static isc_boolean_t
3289 check_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) {
3290         dns_rdata_t dsrdata = DNS_RDATA_INIT;
3291         dns_rdata_ds_t ds;
3292         isc_result_t result;
3293
3294         for (result = dns_rdataset_first(rdataset);
3295              result == ISC_R_SUCCESS;
3296              result = dns_rdataset_next(rdataset)) {
3297                 dns_rdataset_current(rdataset, &dsrdata);
3298                 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
3299                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3300
3301                 if (dns_resolver_digest_supported(val->view->resolver,
3302                                                   ds.digest_type) &&
3303                     dns_resolver_algorithm_supported(val->view->resolver,
3304                                                      name, ds.algorithm)) {
3305                         dns_rdata_reset(&dsrdata);
3306                         return (ISC_TRUE);
3307                 }
3308                 dns_rdata_reset(&dsrdata);
3309         }
3310         return (ISC_FALSE);
3311 }
3312
3313 static void
3314 dlvvalidated(isc_task_t *task, isc_event_t *event) {
3315         dns_validatorevent_t *devent;
3316         dns_validator_t *val;
3317         isc_result_t eresult;
3318         isc_boolean_t want_destroy;
3319
3320         UNUSED(task);
3321         INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
3322
3323         devent = (dns_validatorevent_t *)event;
3324         val = devent->ev_arg;
3325         eresult = devent->result;
3326
3327         isc_event_free(&event);
3328         dns_validator_destroy(&val->subvalidator);
3329
3330         INSIST(val->event != NULL);
3331
3332         validator_log(val, ISC_LOG_DEBUG(3), "in dlvvalidated");
3333         LOCK(&val->lock);
3334         if (CANCELED(val)) {
3335                 validator_done(val, ISC_R_CANCELED);
3336         } else if (eresult == ISC_R_SUCCESS) {
3337                 validator_log(val, ISC_LOG_DEBUG(3),
3338                               "dlvset with trust %s",
3339                               dns_trust_totext(val->frdataset.trust));
3340                 dns_rdataset_clone(&val->frdataset, &val->dlv);
3341                 val->havedlvsep = ISC_TRUE;
3342                 if (dlv_algorithm_supported(val))
3343                         dlv_validator_start(val);
3344                 else {
3345                         markanswer(val, "dlvvalidated");
3346                         validator_done(val, ISC_R_SUCCESS);
3347                 }
3348         } else {
3349                 if (eresult != DNS_R_BROKENCHAIN) {
3350                         if (dns_rdataset_isassociated(&val->frdataset))
3351                                 dns_rdataset_expire(&val->frdataset);
3352                         if (dns_rdataset_isassociated(&val->fsigrdataset))
3353                                 dns_rdataset_expire(&val->fsigrdataset);
3354                 }
3355                 validator_log(val, ISC_LOG_DEBUG(3),
3356                               "dlvvalidated: got %s",
3357                               isc_result_totext(eresult));
3358                 validator_done(val, DNS_R_BROKENCHAIN);
3359         }
3360         want_destroy = exit_check(val);
3361         UNLOCK(&val->lock);
3362         if (want_destroy)
3363                 destroy(val);
3364 }
3365
3366 /*%
3367  * Callback from fetching a DLV record.
3368  *
3369  * Resumes the DLV lookup process.
3370  */
3371 static void
3372 dlvfetched(isc_task_t *task, isc_event_t *event) {
3373         char namebuf[DNS_NAME_FORMATSIZE];
3374         dns_fetchevent_t *devent;
3375         dns_validator_t *val;
3376         isc_boolean_t want_destroy;
3377         isc_result_t eresult;
3378         isc_result_t result;
3379
3380         UNUSED(task);
3381         INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
3382         devent = (dns_fetchevent_t *)event;
3383         val = devent->ev_arg;
3384         eresult = devent->result;
3385
3386         /* Free resources which are not of interest. */
3387         if (devent->node != NULL)
3388                 dns_db_detachnode(devent->db, &devent->node);
3389         if (devent->db != NULL)
3390                 dns_db_detach(&devent->db);
3391         if (dns_rdataset_isassociated(&val->fsigrdataset))
3392                 dns_rdataset_disassociate(&val->fsigrdataset);
3393         isc_event_free(&event);
3394         dns_resolver_destroyfetch(&val->fetch);
3395
3396         INSIST(val->event != NULL);
3397         validator_log(val, ISC_LOG_DEBUG(3), "in dlvfetched: %s",
3398                       dns_result_totext(eresult));
3399
3400         LOCK(&val->lock);
3401         if (eresult == ISC_R_SUCCESS) {
3402                 dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
3403                                 sizeof(namebuf));
3404                 dns_rdataset_clone(&val->frdataset, &val->dlv);
3405                 val->havedlvsep = ISC_TRUE;
3406                 if (dlv_algorithm_supported(val)) {
3407                         validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found",
3408                                       namebuf);
3409                         dlv_validator_start(val);
3410                 } else {
3411                         validator_log(val, ISC_LOG_DEBUG(3),
3412                                       "DLV %s found with no supported algorithms",
3413                                       namebuf);
3414                         markanswer(val, "dlvfetched (1)");
3415                         validator_done(val, ISC_R_SUCCESS);
3416                 }
3417         } else if (eresult == DNS_R_NXRRSET ||
3418                    eresult == DNS_R_NXDOMAIN ||
3419                    eresult == DNS_R_NCACHENXRRSET ||
3420                    eresult == DNS_R_NCACHENXDOMAIN) {
3421                 result = finddlvsep(val, ISC_TRUE);
3422                 if (result == ISC_R_SUCCESS) {
3423                         if (dlv_algorithm_supported(val)) {
3424                                 dns_name_format(dns_fixedname_name(&val->dlvsep),
3425                                                 namebuf, sizeof(namebuf));
3426                                 validator_log(val, ISC_LOG_DEBUG(3),
3427                                               "DLV %s found", namebuf);
3428                                 dlv_validator_start(val);
3429                         } else {
3430                                 validator_log(val, ISC_LOG_DEBUG(3),
3431                                               "DLV %s found with no supported "
3432                                               "algorithms", namebuf);
3433                                 markanswer(val, "dlvfetched (2)");
3434                                 validator_done(val, ISC_R_SUCCESS);
3435                         }
3436                 } else if (result == ISC_R_NOTFOUND) {
3437                         validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
3438                         markanswer(val, "dlvfetched (3)");
3439                         validator_done(val, ISC_R_SUCCESS);
3440                 } else {
3441                         validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3442                                       dns_result_totext(result));
3443                         if (result != DNS_R_WAIT)
3444                                 validator_done(val, result);
3445                 }
3446         } else {
3447                 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3448                               dns_result_totext(eresult));
3449                 validator_done(val, eresult);
3450         }
3451         want_destroy = exit_check(val);
3452         UNLOCK(&val->lock);
3453         if (want_destroy)
3454                 destroy(val);
3455 }
3456
3457 /*%
3458  * Start the DLV lookup process.
3459  *
3460  * Returns
3461  * \li  ISC_R_SUCCESS
3462  * \li  DNS_R_WAIT
3463  * \li  Others on validation failures.
3464  */
3465 static isc_result_t
3466 startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) {
3467         char namebuf[DNS_NAME_FORMATSIZE];
3468         isc_result_t result;
3469
3470         INSIST(!DLVTRIED(val));
3471
3472         val->attributes |= VALATTR_DLVTRIED;
3473
3474         dns_name_format(unsecure, namebuf, sizeof(namebuf));
3475         validator_log(val, ISC_LOG_DEBUG(3),
3476                       "plain DNSSEC returns unsecure (%s): looking for DLV",
3477                       namebuf);
3478
3479         if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
3480                 validator_log(val, ISC_LOG_WARNING, "must be secure failure, "
3481                               " %s is under DLV (startfinddlvsep)", namebuf);
3482                 return (DNS_R_MUSTBESECURE);
3483         }
3484
3485         val->dlvlabels = dns_name_countlabels(unsecure) - 1;
3486         result = finddlvsep(val, ISC_FALSE);
3487         if (result == ISC_R_NOTFOUND) {
3488                 validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
3489                 markanswer(val, "startfinddlvsep (1)");
3490                 return (ISC_R_SUCCESS);
3491         }
3492         if (result != ISC_R_SUCCESS) {
3493                 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3494                               dns_result_totext(result));
3495                 return (result);
3496         }
3497         dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
3498                         sizeof(namebuf));
3499         if (dlv_algorithm_supported(val)) {
3500                 validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf);
3501                 dlv_validator_start(val);
3502                 return (DNS_R_WAIT);
3503         }
3504         validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found with no supported "
3505                       "algorithms", namebuf);
3506         markanswer(val, "startfinddlvsep (2)");
3507         validator_done(val, ISC_R_SUCCESS);
3508         return (ISC_R_SUCCESS);
3509 }
3510
3511 /*%
3512  * Continue the DLV lookup process.
3513  *
3514  * Returns
3515  * \li  ISC_R_SUCCESS
3516  * \li  ISC_R_NOTFOUND
3517  * \li  DNS_R_WAIT
3518  * \li  Others on validation failure.
3519  */
3520 static isc_result_t
3521 finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
3522         char namebuf[DNS_NAME_FORMATSIZE];
3523         dns_fixedname_t dlvfixed;
3524         dns_name_t *dlvname;
3525         dns_name_t *dlvsep;
3526         dns_name_t noroot;
3527         isc_result_t result;
3528         unsigned int labels;
3529
3530         INSIST(val->view->dlv != NULL);
3531
3532         if (!resume) {
3533                 if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
3534                         dns_name_format(val->event->name, namebuf,
3535                                         sizeof(namebuf));
3536                         validator_log(val, ISC_LOG_WARNING,
3537                                       "must be secure failure, "
3538                                       "%s is under DLV (finddlvsep)", namebuf);
3539                         return (DNS_R_MUSTBESECURE);
3540                 }
3541
3542                 dns_fixedname_init(&val->dlvsep);
3543                 dlvsep = dns_fixedname_name(&val->dlvsep);
3544                 dns_name_copy(val->event->name, dlvsep, NULL);
3545                 /*
3546                  * If this is a response to a DS query, we need to look in
3547                  * the parent zone for the trust anchor.
3548                  */
3549                 if (val->event->type == dns_rdatatype_ds) {
3550                         labels = dns_name_countlabels(dlvsep);
3551                         if (labels == 0)
3552                                 return (ISC_R_NOTFOUND);
3553                         dns_name_getlabelsequence(dlvsep, 1, labels - 1,
3554                                                   dlvsep);
3555                 }
3556         } else {
3557                 dlvsep = dns_fixedname_name(&val->dlvsep);
3558                 labels = dns_name_countlabels(dlvsep);
3559                 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3560         }
3561         dns_name_init(&noroot, NULL);
3562         dns_fixedname_init(&dlvfixed);
3563         dlvname = dns_fixedname_name(&dlvfixed);
3564         labels = dns_name_countlabels(dlvsep);
3565         if (labels == 0)
3566                 return (ISC_R_NOTFOUND);
3567         dns_name_getlabelsequence(dlvsep, 0, labels - 1, &noroot);
3568         result = dns_name_concatenate(&noroot, val->view->dlv, dlvname, NULL);
3569         while (result == ISC_R_NOSPACE) {
3570                 labels = dns_name_countlabels(dlvsep);
3571                 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3572                 dns_name_getlabelsequence(dlvsep, 0, labels - 2, &noroot);
3573                 result = dns_name_concatenate(&noroot, val->view->dlv,
3574                                               dlvname, NULL);
3575         }
3576         if (result != ISC_R_SUCCESS) {
3577                 validator_log(val, ISC_LOG_DEBUG(2), "DLV concatenate failed");
3578                 return (DNS_R_NOVALIDSIG);
3579         }
3580
3581         while (dns_name_countlabels(dlvname) >=
3582                dns_name_countlabels(val->view->dlv) + val->dlvlabels) {
3583                 dns_name_format(dlvname, namebuf, sizeof(namebuf));
3584                 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV %s",
3585                               namebuf);
3586                 result = view_find(val, dlvname, dns_rdatatype_dlv);
3587                 if (result == ISC_R_SUCCESS) {
3588                         if (DNS_TRUST_PENDING(val->frdataset.trust) &&
3589                             dns_rdataset_isassociated(&val->fsigrdataset))
3590                         {
3591                                 dns_fixedname_init(&val->fname);
3592                                 dns_name_copy(dlvname,
3593                                               dns_fixedname_name(&val->fname),
3594                                               NULL);
3595                                 result = create_validator(val,
3596                                                 dns_fixedname_name(&val->fname),
3597                                                           dns_rdatatype_dlv,
3598                                                           &val->frdataset,
3599                                                           &val->fsigrdataset,
3600                                                           dlvvalidated,
3601                                                           "finddlvsep");
3602                                 if (result != ISC_R_SUCCESS)
3603                                         return (result);
3604                                 return (DNS_R_WAIT);
3605                         }
3606                         if (val->frdataset.trust < dns_trust_secure) {
3607                                 validator_log(val, ISC_LOG_DEBUG(3),
3608                                               "DLV not validated");
3609                                 return (DNS_R_NOVALIDSIG);
3610                         }
3611                         val->havedlvsep = ISC_TRUE;
3612                         dns_rdataset_clone(&val->frdataset, &val->dlv);
3613                         return (ISC_R_SUCCESS);
3614                 }
3615                 if (result == ISC_R_NOTFOUND) {
3616                         result = create_fetch(val, dlvname, dns_rdatatype_dlv,
3617                                               dlvfetched, "finddlvsep");
3618                         if (result != ISC_R_SUCCESS)
3619                                 return (result);
3620                         return (DNS_R_WAIT);
3621                 }
3622                 if (result != DNS_R_NXRRSET &&
3623                     result != DNS_R_NXDOMAIN &&
3624                     result != DNS_R_EMPTYNAME &&
3625                     result != DNS_R_NCACHENXRRSET &&
3626                     result != DNS_R_NCACHENXDOMAIN)
3627                         return (result);
3628                 /*
3629                  * Strip first labels from both dlvsep and dlvname.
3630                  */
3631                 labels = dns_name_countlabels(dlvsep);
3632                 if (labels == 0)
3633                         break;
3634                 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3635                 labels = dns_name_countlabels(dlvname);
3636                 dns_name_getlabelsequence(dlvname, 1, labels - 1, dlvname);
3637         }
3638         return (ISC_R_NOTFOUND);
3639 }
3640
3641 /*%
3642  * proveunsecure walks down from the SEP looking for a break in the
3643  * chain of trust.  That occurs when we can prove the DS record does
3644  * not exist at a delegation point or the DS exists at a delegation
3645  * but we don't support the algorithm/digest.
3646  *
3647  * If DLV is active and we look for a DLV record at or below the
3648  * point we go insecure.  If found we restart the validation process.
3649  * If not found or DLV isn't active we mark the response as a answer.
3650  *
3651  * Returns:
3652  * \li  ISC_R_SUCCESS           val->event->name is in a unsecure zone
3653  * \li  DNS_R_WAIT              validation is in progress.
3654  * \li  DNS_R_MUSTBESECURE      val->event->name is supposed to be secure
3655  *                              (policy) but we proved that it is unsecure.
3656  * \li  DNS_R_NOVALIDSIG
3657  * \li  DNS_R_NOVALIDNSEC
3658  * \li  DNS_R_NOTINSECURE
3659  * \li  DNS_R_BROKENCHAIN
3660  */
3661 static isc_result_t
3662 proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
3663 {
3664         isc_result_t result;
3665         dns_fixedname_t fixedsecroot;
3666         dns_name_t *secroot;
3667         dns_name_t *tname;
3668         char namebuf[DNS_NAME_FORMATSIZE];
3669         dns_name_t *found;
3670         dns_fixedname_t fixedfound;
3671
3672         dns_fixedname_init(&fixedsecroot);
3673         secroot = dns_fixedname_name(&fixedsecroot);
3674         dns_fixedname_init(&fixedfound);
3675         found = dns_fixedname_name(&fixedfound);
3676         if (val->havedlvsep)
3677                 dns_name_copy(dns_fixedname_name(&val->dlvsep), secroot, NULL);
3678         else {
3679                 unsigned int labels;
3680                 dns_name_copy(val->event->name, secroot, NULL);
3681                 /*
3682                  * If this is a response to a DS query, we need to look in
3683                  * the parent zone for the trust anchor.
3684                  */
3685
3686                 labels = dns_name_countlabels(secroot);
3687                 if (val->event->type == dns_rdatatype_ds && labels > 1U)
3688                         dns_name_getlabelsequence(secroot, 1, labels - 1,
3689                                                   secroot);
3690                 result = dns_keytable_finddeepestmatch(val->keytable,
3691                                                        secroot, secroot);
3692                 if (result == ISC_R_NOTFOUND) {
3693                         if (val->mustbesecure) {
3694                                 validator_log(val, ISC_LOG_WARNING,
3695                                               "must be secure failure, "
3696                                               "not beneath secure root");
3697                                 result = DNS_R_MUSTBESECURE;
3698                                 goto out;
3699                         } else
3700                                 validator_log(val, ISC_LOG_DEBUG(3),
3701                                               "not beneath secure root");
3702                         if (val->view->dlv == NULL || DLVTRIED(val)) {
3703                                 markanswer(val, "proveunsecure (1)");
3704                                 return (ISC_R_SUCCESS);
3705                         }
3706                         return (startfinddlvsep(val, dns_rootname));
3707                 } else if (result != ISC_R_SUCCESS)
3708                         return (result);
3709         }
3710
3711         if (!resume) {
3712                 /*
3713                  * We are looking for breaks below the SEP so add a label.
3714                  */
3715                 val->labels = dns_name_countlabels(secroot) + 1;
3716         } else {
3717                 validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
3718                 /*
3719                  * If we have a DS rdataset and it is secure then check if
3720                  * the DS rdataset has a supported algorithm combination.
3721                  * If not this is an insecure delegation as far as this
3722                  * resolver is concerned.  Fall back to DLV if available.
3723                  */
3724                 if (have_ds && val->frdataset.trust >= dns_trust_secure &&
3725                     !check_ds(val, dns_fixedname_name(&val->fname),
3726                               &val->frdataset)) {
3727                         dns_name_format(dns_fixedname_name(&val->fname),
3728                                         namebuf, sizeof(namebuf));
3729                         if ((val->view->dlv == NULL || DLVTRIED(val)) &&
3730                             val->mustbesecure) {
3731                                 validator_log(val, ISC_LOG_WARNING,
3732                                               "must be secure failure at '%s', "
3733                                               "can't fall back to DLV",
3734                                               namebuf);
3735                                 result = DNS_R_MUSTBESECURE;
3736                                 goto out;
3737                         }
3738                         validator_log(val, ISC_LOG_DEBUG(3),
3739                                       "no supported algorithm/digest (%s/DS)",
3740                                       namebuf);
3741                         if (val->view->dlv == NULL || DLVTRIED(val)) {
3742                                 markanswer(val, "proveunsecure (2)");
3743                                 result = ISC_R_SUCCESS;
3744                                 goto out;
3745                         }
3746                         return(startfinddlvsep(val,
3747                                               dns_fixedname_name(&val->fname)));
3748                 }
3749                 val->labels++;
3750         }
3751
3752         for (;
3753              val->labels <= dns_name_countlabels(val->event->name);
3754              val->labels++)
3755         {
3756
3757                 dns_fixedname_init(&val->fname);
3758                 tname = dns_fixedname_name(&val->fname);
3759                 if (val->labels == dns_name_countlabels(val->event->name))
3760                         dns_name_copy(val->event->name, tname, NULL);
3761                 else
3762                         dns_name_split(val->event->name, val->labels,
3763                                        NULL, tname);
3764
3765                 dns_name_format(tname, namebuf, sizeof(namebuf));
3766                 validator_log(val, ISC_LOG_DEBUG(3),
3767                               "checking existence of DS at '%s'",
3768                               namebuf);
3769
3770                 result = view_find(val, tname, dns_rdatatype_ds);
3771                 if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
3772                         /*
3773                          * There is no DS.  If this is a delegation,
3774                          * we may be done.
3775                          */
3776                         /*
3777                          * If we have "trust == answer" then this namespace
3778                          * has switched from insecure to should be secure.
3779                          */
3780                         if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3781                             DNS_TRUST_ANSWER(val->frdataset.trust)) {
3782                                 result = create_validator(val, tname,
3783                                                           dns_rdatatype_ds,
3784                                                           &val->frdataset,
3785                                                           NULL, dsvalidated,
3786                                                           "proveunsecure");
3787                                 if (result != ISC_R_SUCCESS)
3788                                         goto out;
3789                                 return (DNS_R_WAIT);
3790                         }
3791                         /*
3792                          * Zones using NSEC3 don't return a NSEC RRset so
3793                          * we need to use dns_view_findzonecut2 to find
3794                          * the zone cut.
3795                          */
3796                         if (result == DNS_R_NXRRSET &&
3797                             !dns_rdataset_isassociated(&val->frdataset) &&
3798                             dns_view_findzonecut2(val->view, tname, found,
3799                                                  0, 0, ISC_FALSE, ISC_FALSE,
3800                                                  NULL, NULL) == ISC_R_SUCCESS &&
3801                             dns_name_equal(tname, found)) {
3802                                 if (val->mustbesecure) {
3803                                         validator_log(val, ISC_LOG_WARNING,
3804                                                       "must be secure failure, "
3805                                                       "no DS at zone cut");
3806                                         return (DNS_R_MUSTBESECURE);
3807                                 }
3808                                 if (val->view->dlv == NULL || DLVTRIED(val)) {
3809                                         markanswer(val, "proveunsecure (3)");
3810                                         return (ISC_R_SUCCESS);
3811                                 }
3812                                 return (startfinddlvsep(val, tname));
3813                         }
3814                         if (val->frdataset.trust < dns_trust_secure) {
3815                                 /*
3816                                  * This shouldn't happen, since the negative
3817                                  * response should have been validated.  Since
3818                                  * there's no way of validating existing
3819                                  * negative response blobs, give up.
3820                                  */
3821                                 validator_log(val, ISC_LOG_WARNING,
3822                                               "can't validate existing "
3823                                               "negative responses (no DS)");
3824                                 result = DNS_R_NOVALIDSIG;
3825                                 goto out;
3826                         }
3827                         if (isdelegation(tname, &val->frdataset, result)) {
3828                                 if (val->mustbesecure) {
3829                                         validator_log(val, ISC_LOG_WARNING,
3830                                                       "must be secure failure, "
3831                                                       "%s is a delegation",
3832                                                       namebuf);
3833                                         return (DNS_R_MUSTBESECURE);
3834                                 }
3835                                 if (val->view->dlv == NULL || DLVTRIED(val)) {
3836                                         markanswer(val, "proveunsecure (4)");
3837                                         return (ISC_R_SUCCESS);
3838                                 }
3839                                 return (startfinddlvsep(val, tname));
3840                         }
3841                         continue;
3842                 } else if (result == DNS_R_CNAME) {
3843                         if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3844                             DNS_TRUST_ANSWER(val->frdataset.trust)) {
3845                                 result = create_validator(val, tname,
3846                                                           dns_rdatatype_cname,
3847                                                           &val->frdataset,
3848                                                           NULL, cnamevalidated,
3849                                                           "proveunsecure "
3850                                                           "(cname)");
3851                                 if (result != ISC_R_SUCCESS)
3852                                         goto out;
3853                                 return (DNS_R_WAIT);
3854                         }
3855                         continue;
3856                 } else if (result == ISC_R_SUCCESS) {
3857                         /*
3858                          * There is a DS here.  Verify that it's secure and
3859                          * continue.
3860                          */
3861                         if (val->frdataset.trust >= dns_trust_secure) {
3862                                 if (!check_ds(val, tname, &val->frdataset)) {
3863                                         validator_log(val, ISC_LOG_DEBUG(3),
3864                                                      "no supported algorithm/"
3865                                                      "digest (%s/DS)", namebuf);
3866                                         if (val->mustbesecure) {
3867                                                 validator_log(val,
3868                                                               ISC_LOG_WARNING,
3869                                                       "must be secure failure, "
3870                                                       "no supported algorithm/"
3871                                                       "digest (%s/DS)",
3872                                                       namebuf);
3873                                                 result = DNS_R_MUSTBESECURE;
3874                                                 goto out;
3875                                         }
3876                                         if (val->view->dlv == NULL ||
3877                                             DLVTRIED(val)) {
3878                                                 markanswer(val,
3879                                                            "proveunsecure (5)");
3880                                                 result = ISC_R_SUCCESS;
3881                                                 goto out;
3882                                         }
3883                                         return(startfinddlvsep(val, tname));
3884                                 }
3885                                 continue;
3886                         }
3887                         else if (!dns_rdataset_isassociated(&val->fsigrdataset))
3888                         {
3889                                 validator_log(val, ISC_LOG_DEBUG(3),
3890                                               "DS is unsigned");
3891                                 result = DNS_R_NOVALIDSIG;
3892                                 goto out;
3893                         }
3894                         /*
3895                          * Validate / re-validate answer.
3896                          */
3897                         result = create_validator(val, tname, dns_rdatatype_ds,
3898                                                   &val->frdataset,
3899                                                   &val->fsigrdataset,
3900                                                   dsvalidated,
3901                                                   "proveunsecure");
3902                         if (result != ISC_R_SUCCESS)
3903                                 goto out;
3904                         return (DNS_R_WAIT);
3905                 } else if (result == DNS_R_NXDOMAIN ||
3906                            result == DNS_R_NCACHENXDOMAIN) {
3907                         /*
3908                          * This is not a zone cut.  Assuming things are
3909                          * as expected, continue.
3910                          */
3911                         if (!dns_rdataset_isassociated(&val->frdataset)) {
3912                                 /*
3913                                  * There should be an NSEC here, since we
3914                                  * are still in a secure zone.
3915                                  */
3916                                 result = DNS_R_NOVALIDNSEC;
3917                                 goto out;
3918                         } else if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3919                                    DNS_TRUST_ANSWER(val->frdataset.trust)) {
3920                                 /*
3921                                  * If we have "trust == answer" then this namespace
3922                                  * has switched from insecure to should be secure.
3923                                  */
3924                                 result = create_validator(val, tname,
3925                                                           dns_rdatatype_ds,
3926                                                           &val->frdataset,
3927                                                           NULL, dsvalidated,
3928                                                           "proveunsecure");
3929                                 if (result != ISC_R_SUCCESS)
3930                                         goto out;
3931                                 return (DNS_R_WAIT);
3932                         } else if (val->frdataset.trust < dns_trust_secure) {
3933                                 /*
3934                                  * This shouldn't happen, since the negative
3935                                  * response should have been validated.  Since
3936                                  * there's no way of validating existing
3937                                  * negative response blobs, give up.
3938                                  */
3939                                 validator_log(val, ISC_LOG_WARNING,
3940                                               "can't validate existing "
3941                                               "negative responses "
3942                                               "(not a zone cut)");
3943                                 result = DNS_R_NOVALIDSIG;
3944                                 goto out;
3945                         }
3946                         continue;
3947                 } else if (result == ISC_R_NOTFOUND) {
3948                         /*
3949                          * We don't know anything about the DS.  Find it.
3950                          */
3951                         result = create_fetch(val, tname, dns_rdatatype_ds,
3952                                               dsfetched2, "proveunsecure");
3953                         if (result != ISC_R_SUCCESS)
3954                                 goto out;
3955                         return (DNS_R_WAIT);
3956                 } else if (result == DNS_R_BROKENCHAIN)
3957                         return (result);
3958         }
3959
3960         /* Couldn't complete insecurity proof */
3961         validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed");
3962         return (DNS_R_NOTINSECURE);
3963
3964  out:
3965         if (dns_rdataset_isassociated(&val->frdataset))
3966                 dns_rdataset_disassociate(&val->frdataset);
3967         if (dns_rdataset_isassociated(&val->fsigrdataset))
3968                 dns_rdataset_disassociate(&val->fsigrdataset);
3969         return (result);
3970 }
3971
3972 /*%
3973  * Reset state and revalidate the answer using DLV.
3974  */
3975 static void
3976 dlv_validator_start(dns_validator_t *val) {
3977         isc_event_t *event;
3978
3979         validator_log(val, ISC_LOG_DEBUG(3), "dlv_validator_start");
3980
3981         /*
3982          * Reset state and try again.
3983          */
3984         val->attributes &= VALATTR_DLVTRIED;
3985         val->options &= ~DNS_VALIDATOR_DLV;
3986
3987         event = (isc_event_t *)val->event;
3988         isc_task_send(val->task, &event);
3989 }
3990
3991 /*%
3992  * Start the validation process.
3993  *
3994  * Attempt to validate the answer based on the category it appears to
3995  * fall in.
3996  * \li  1. secure positive answer.
3997  * \li  2. unsecure positive answer.
3998  * \li  3. a negative answer (secure or unsecure).
3999  *
4000  * Note a answer that appears to be a secure positive answer may actually
4001  * be an unsecure positive answer.
4002  */
4003 static void
4004 validator_start(isc_task_t *task, isc_event_t *event) {
4005         dns_validator_t *val;
4006         dns_validatorevent_t *vevent;
4007         isc_boolean_t want_destroy = ISC_FALSE;
4008         isc_result_t result = ISC_R_FAILURE;
4009
4010         UNUSED(task);
4011         REQUIRE(event->ev_type == DNS_EVENT_VALIDATORSTART);
4012         vevent = (dns_validatorevent_t *)event;
4013         val = vevent->validator;
4014
4015         /* If the validator has been canceled, val->event == NULL */
4016         if (val->event == NULL)
4017                 return;
4018
4019         if (DLVTRIED(val))
4020                 validator_log(val, ISC_LOG_DEBUG(3), "restarting using DLV");
4021         else
4022                 validator_log(val, ISC_LOG_DEBUG(3), "starting");
4023
4024         LOCK(&val->lock);
4025
4026         if ((val->options & DNS_VALIDATOR_DLV) != 0 &&
4027              val->event->rdataset != NULL) {
4028                 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV");
4029                 result = startfinddlvsep(val, dns_rootname);
4030         } else if (val->event->rdataset != NULL &&
4031                    val->event->sigrdataset != NULL) {
4032                 isc_result_t saved_result;
4033
4034                 /*
4035                  * This looks like a simple validation.  We say "looks like"
4036                  * because it might end up requiring an insecurity proof.
4037                  */
4038                 validator_log(val, ISC_LOG_DEBUG(3),
4039                               "attempting positive response validation");
4040
4041                 INSIST(dns_rdataset_isassociated(val->event->rdataset));
4042                 INSIST(dns_rdataset_isassociated(val->event->sigrdataset));
4043                 result = start_positive_validation(val);
4044                 if (result == DNS_R_NOVALIDSIG &&
4045                     (val->attributes & VALATTR_TRIEDVERIFY) == 0)
4046                 {
4047                         saved_result = result;
4048                         validator_log(val, ISC_LOG_DEBUG(3),
4049                                       "falling back to insecurity proof");
4050                         val->attributes |= VALATTR_INSECURITY;
4051                         result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
4052                         if (result == DNS_R_NOTINSECURE)
4053                                 result = saved_result;
4054                 }
4055         } else if (val->event->rdataset != NULL &&
4056                    val->event->rdataset->type != 0) {
4057                 /*
4058                  * This is either an unsecure subdomain or a response from
4059                  * a broken server.
4060                  */
4061                 INSIST(dns_rdataset_isassociated(val->event->rdataset));
4062                 validator_log(val, ISC_LOG_DEBUG(3),
4063                               "attempting insecurity proof");
4064
4065                 val->attributes |= VALATTR_INSECURITY;
4066                 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
4067                 if (result == DNS_R_NOTINSECURE)
4068                         validator_log(val, ISC_LOG_INFO,
4069                                       "got insecure response; "
4070                                       "parent indicates it should be secure");
4071         } else if (val->event->rdataset == NULL &&
4072                    val->event->sigrdataset == NULL)
4073         {
4074                 /*
4075                  * This is a nonexistence validation.
4076                  */
4077                 validator_log(val, ISC_LOG_DEBUG(3),
4078                               "attempting negative response validation");
4079
4080                 if (val->event->message->rcode == dns_rcode_nxdomain) {
4081                         val->attributes |= VALATTR_NEEDNOQNAME;
4082                         val->attributes |= VALATTR_NEEDNOWILDCARD;
4083                 } else
4084                         val->attributes |= VALATTR_NEEDNODATA;
4085                 result = nsecvalidate(val, ISC_FALSE);
4086         } else if (val->event->rdataset != NULL &&
4087                     NEGATIVE(val->event->rdataset))
4088         {
4089                 /*
4090                  * This is a nonexistence validation.
4091                  */
4092                 validator_log(val, ISC_LOG_DEBUG(3),
4093                               "attempting negative response validation");
4094
4095                 if (val->event->rdataset->covers == dns_rdatatype_any) {
4096                         val->attributes |= VALATTR_NEEDNOQNAME;
4097                         val->attributes |= VALATTR_NEEDNOWILDCARD;
4098                 } else
4099                         val->attributes |= VALATTR_NEEDNODATA;
4100                 result = nsecvalidate(val, ISC_FALSE);
4101         } else {
4102                 /*
4103                  * This shouldn't happen.
4104                  */
4105                 INSIST(0);
4106         }
4107
4108         if (result != DNS_R_WAIT) {
4109                 want_destroy = exit_check(val);
4110                 validator_done(val, result);
4111         }
4112
4113         UNLOCK(&val->lock);
4114         if (want_destroy)
4115                 destroy(val);
4116 }
4117
4118 isc_result_t
4119 dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
4120                      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
4121                      dns_message_t *message, unsigned int options,
4122                      isc_task_t *task, isc_taskaction_t action, void *arg,
4123                      dns_validator_t **validatorp)
4124 {
4125         isc_result_t result = ISC_R_FAILURE;
4126         dns_validator_t *val;
4127         isc_task_t *tclone = NULL;
4128         dns_validatorevent_t *event;
4129
4130         REQUIRE(name != NULL);
4131         REQUIRE(rdataset != NULL ||
4132                 (rdataset == NULL && sigrdataset == NULL && message != NULL));
4133         REQUIRE(validatorp != NULL && *validatorp == NULL);
4134
4135         val = isc_mem_get(view->mctx, sizeof(*val));
4136         if (val == NULL)
4137                 return (ISC_R_NOMEMORY);
4138         val->view = NULL;
4139         dns_view_weakattach(view, &val->view);
4140
4141         event = (dns_validatorevent_t *)
4142                 isc_event_allocate(view->mctx, task,
4143                                    DNS_EVENT_VALIDATORSTART,
4144                                    validator_start, NULL,
4145                                    sizeof(dns_validatorevent_t));
4146         if (event == NULL) {
4147                 result = ISC_R_NOMEMORY;
4148                 goto cleanup_val;
4149         }
4150         isc_task_attach(task, &tclone);
4151         event->validator = val;
4152         event->result = ISC_R_FAILURE;
4153         event->name = name;
4154         event->type = type;
4155         event->rdataset = rdataset;
4156         event->sigrdataset = sigrdataset;
4157         event->message = message;
4158         memset(event->proofs, 0, sizeof(event->proofs));
4159         event->optout = ISC_FALSE;
4160         result = isc_mutex_init(&val->lock);
4161         if (result != ISC_R_SUCCESS)
4162                 goto cleanup_event;
4163         val->event = event;
4164         val->options = options;
4165         val->attributes = 0;
4166         val->fetch = NULL;
4167         val->subvalidator = NULL;
4168         val->parent = NULL;
4169
4170         val->keytable = NULL;
4171         result = dns_view_getsecroots(val->view, &val->keytable);
4172         if (result != ISC_R_SUCCESS)
4173                 return (result);
4174
4175         val->keynode = NULL;
4176         val->key = NULL;
4177         val->siginfo = NULL;
4178         val->task = task;
4179         val->action = action;
4180         val->arg = arg;
4181         val->labels = 0;
4182         val->currentset = NULL;
4183         val->keyset = NULL;
4184         val->dsset = NULL;
4185         dns_rdataset_init(&val->dlv);
4186         val->seensig = ISC_FALSE;
4187         val->havedlvsep = ISC_FALSE;
4188         val->depth = 0;
4189         val->authcount = 0;
4190         val->authfail = 0;
4191         val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
4192         dns_rdataset_init(&val->frdataset);
4193         dns_rdataset_init(&val->fsigrdataset);
4194         dns_fixedname_init(&val->wild);
4195         dns_fixedname_init(&val->nearest);
4196         dns_fixedname_init(&val->closest);
4197         ISC_LINK_INIT(val, link);
4198         val->magic = VALIDATOR_MAGIC;
4199
4200         if ((options & DNS_VALIDATOR_DEFER) == 0)
4201                 isc_task_send(task, ISC_EVENT_PTR(&event));
4202
4203         *validatorp = val;
4204
4205         return (ISC_R_SUCCESS);
4206
4207  cleanup_event:
4208         isc_task_detach(&tclone);
4209         isc_event_free(ISC_EVENT_PTR(&event));
4210
4211  cleanup_val:
4212         dns_view_weakdetach(&val->view);
4213         isc_mem_put(view->mctx, val, sizeof(*val));
4214
4215         return (result);
4216 }
4217
4218 void
4219 dns_validator_send(dns_validator_t *validator) {
4220         isc_event_t *event;
4221         REQUIRE(VALID_VALIDATOR(validator));
4222
4223         LOCK(&validator->lock);
4224
4225         INSIST((validator->options & DNS_VALIDATOR_DEFER) != 0);
4226         event = (isc_event_t *)validator->event;
4227         validator->options &= ~DNS_VALIDATOR_DEFER;
4228         UNLOCK(&validator->lock);
4229
4230         isc_task_send(validator->task, ISC_EVENT_PTR(&event));
4231 }
4232
4233 void
4234 dns_validator_cancel(dns_validator_t *validator) {
4235         REQUIRE(VALID_VALIDATOR(validator));
4236
4237         LOCK(&validator->lock);
4238
4239         validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
4240
4241         if ((validator->attributes & VALATTR_CANCELED) == 0) {
4242                 validator->attributes |= VALATTR_CANCELED;
4243                 if (validator->event != NULL) {
4244                         if (validator->fetch != NULL)
4245                                 dns_resolver_cancelfetch(validator->fetch);
4246
4247                         if (validator->subvalidator != NULL)
4248                                 dns_validator_cancel(validator->subvalidator);
4249                         if ((validator->options & DNS_VALIDATOR_DEFER) != 0) {
4250                                 validator->options &= ~DNS_VALIDATOR_DEFER;
4251                                 validator_done(validator, ISC_R_CANCELED);
4252                         }
4253                 }
4254         }
4255         UNLOCK(&validator->lock);
4256 }
4257
4258 static void
4259 destroy(dns_validator_t *val) {
4260         isc_mem_t *mctx;
4261
4262         REQUIRE(SHUTDOWN(val));
4263         REQUIRE(val->event == NULL);
4264         REQUIRE(val->fetch == NULL);
4265
4266         if (val->keynode != NULL)
4267                 dns_keytable_detachkeynode(val->keytable, &val->keynode);
4268         else if (val->key != NULL)
4269                 dst_key_free(&val->key);
4270         if (val->keytable != NULL)
4271                 dns_keytable_detach(&val->keytable);
4272         if (val->subvalidator != NULL)
4273                 dns_validator_destroy(&val->subvalidator);
4274         if (val->havedlvsep)
4275                 dns_rdataset_disassociate(&val->dlv);
4276         if (dns_rdataset_isassociated(&val->frdataset))
4277                 dns_rdataset_disassociate(&val->frdataset);
4278         if (dns_rdataset_isassociated(&val->fsigrdataset))
4279                 dns_rdataset_disassociate(&val->fsigrdataset);
4280         mctx = val->view->mctx;
4281         if (val->siginfo != NULL)
4282                 isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo));
4283         DESTROYLOCK(&val->lock);
4284         dns_view_weakdetach(&val->view);
4285         val->magic = 0;
4286         isc_mem_put(mctx, val, sizeof(*val));
4287 }
4288
4289 void
4290 dns_validator_destroy(dns_validator_t **validatorp) {
4291         dns_validator_t *val;
4292         isc_boolean_t want_destroy = ISC_FALSE;
4293
4294         REQUIRE(validatorp != NULL);
4295         val = *validatorp;
4296         REQUIRE(VALID_VALIDATOR(val));
4297
4298         LOCK(&val->lock);
4299
4300         val->attributes |= VALATTR_SHUTDOWN;
4301         validator_log(val, ISC_LOG_DEBUG(3), "dns_validator_destroy");
4302
4303         want_destroy = exit_check(val);
4304
4305         UNLOCK(&val->lock);
4306
4307         if (want_destroy)
4308                 destroy(val);
4309
4310         *validatorp = NULL;
4311 }
4312
4313 static void
4314 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
4315                isc_logmodule_t *module, int level, const char *fmt, va_list ap)
4316 {
4317         char msgbuf[2048];
4318         static const char spaces[] = "        *";
4319         int depth = val->depth * 2;
4320
4321         vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
4322
4323         if ((unsigned int) depth >= sizeof spaces)
4324                 depth = sizeof spaces - 1;
4325
4326         if (val->event != NULL && val->event->name != NULL) {
4327                 char namebuf[DNS_NAME_FORMATSIZE];
4328                 char typebuf[DNS_RDATATYPE_FORMATSIZE];
4329
4330                 dns_name_format(val->event->name, namebuf, sizeof(namebuf));
4331                 dns_rdatatype_format(val->event->type, typebuf,
4332                                      sizeof(typebuf));
4333                 isc_log_write(dns_lctx, category, module, level,
4334                               "%.*svalidating @%p: %s %s: %s", depth, spaces,
4335                               val, namebuf, typebuf, msgbuf);
4336         } else {
4337                 isc_log_write(dns_lctx, category, module, level,
4338                               "%.*svalidator @%p: %s", depth, spaces,
4339                                val, msgbuf);
4340         }
4341 }
4342
4343 static void
4344 validator_log(dns_validator_t *val, int level, const char *fmt, ...) {
4345         va_list ap;
4346
4347         if (! isc_log_wouldlog(dns_lctx, level))
4348                 return;
4349
4350         va_start(ap, fmt);
4351
4352         validator_logv(val, DNS_LOGCATEGORY_DNSSEC,
4353                        DNS_LOGMODULE_VALIDATOR, level, fmt, ap);
4354         va_end(ap);
4355 }
4356
4357 static void
4358 validator_logcreate(dns_validator_t *val,
4359                     dns_name_t *name, dns_rdatatype_t type,
4360                     const char *caller, const char *operation)
4361 {
4362         char namestr[DNS_NAME_FORMATSIZE];
4363         char typestr[DNS_RDATATYPE_FORMATSIZE];
4364
4365         dns_name_format(name, namestr, sizeof(namestr));
4366         dns_rdatatype_format(type, typestr, sizeof(typestr));
4367         validator_log(val, ISC_LOG_DEBUG(9), "%s: creating %s for %s %s",
4368                       caller, operation, namestr, typestr);
4369 }