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