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