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