Merge from vendor branch OPENSSH:
[dragonfly.git] / contrib / bind-9.3 / lib / dns / validator.c
1 /*
2  * Copyright (C) 2004, 2005  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2000-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and 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.91.2.5.8.21 2005/11/02 02:07:47 marka Exp $ */
19
20 #include <config.h>
21
22 #include <isc/mem.h>
23 #include <isc/print.h>
24 #include <isc/string.h>
25 #include <isc/task.h>
26 #include <isc/util.h>
27
28 #include <dns/db.h>
29 #include <dns/ds.h>
30 #include <dns/dnssec.h>
31 #include <dns/events.h>
32 #include <dns/keytable.h>
33 #include <dns/log.h>
34 #include <dns/message.h>
35 #include <dns/ncache.h>
36 #include <dns/nsec.h>
37 #include <dns/rdata.h>
38 #include <dns/rdatastruct.h>
39 #include <dns/rdataset.h>
40 #include <dns/rdatatype.h>
41 #include <dns/resolver.h>
42 #include <dns/result.h>
43 #include <dns/validator.h>
44 #include <dns/view.h>
45
46 #define VALIDATOR_MAGIC                 ISC_MAGIC('V', 'a', 'l', '?')
47 #define VALID_VALIDATOR(v)              ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
48
49 #define VALATTR_SHUTDOWN                0x0001
50 #define VALATTR_FOUNDNONEXISTENCE       0x0002
51 #define VALATTR_TRIEDVERIFY             0x0004
52 #define VALATTR_NEGATIVE                0x0008
53 #define VALATTR_INSECURITY              0x0010
54 #define VALATTR_DLVTRIED                0x0020
55
56 #define VALATTR_NEEDNOQNAME             0x0100
57 #define VALATTR_NEEDNOWILDCARD          0x0200
58 #define VALATTR_NEEDNODATA              0x0400
59
60 #define VALATTR_FOUNDNOQNAME            0x1000
61 #define VALATTR_FOUNDNOWILDCARD         0x2000
62 #define VALATTR_FOUNDNODATA             0x4000
63
64 #define NEEDNODATA(val) ((val->attributes & VALATTR_NEEDNODATA) != 0)
65 #define NEEDNOQNAME(val) ((val->attributes & VALATTR_NEEDNOQNAME) != 0)
66 #define NEEDNOWILDCARD(val) ((val->attributes & VALATTR_NEEDNOWILDCARD) != 0)
67 #define DLVTRIED(val) ((val->attributes & VALATTR_DLVTRIED) != 0)
68
69 #define SHUTDOWN(v)             (((v)->attributes & VALATTR_SHUTDOWN) != 0)
70
71 static void
72 destroy(dns_validator_t *val);
73
74 static isc_result_t
75 get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
76             dns_rdataset_t *rdataset);
77
78 static isc_result_t
79 validate(dns_validator_t *val, isc_boolean_t resume);
80
81 static isc_result_t
82 validatezonekey(dns_validator_t *val);
83
84 static isc_result_t
85 nsecvalidate(dns_validator_t *val, isc_boolean_t resume);
86
87 static isc_result_t
88 proveunsecure(dns_validator_t *val, isc_boolean_t resume);
89
90 static void
91 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
92                isc_logmodule_t *module, int level, const char *fmt, va_list ap)
93      ISC_FORMAT_PRINTF(5, 0);
94
95 static void
96 validator_log(dns_validator_t *val, int level, const char *fmt, ...)
97      ISC_FORMAT_PRINTF(3, 4);
98
99 static void
100 validator_logcreate(dns_validator_t *val,
101                     dns_name_t *name, dns_rdatatype_t type,
102                     const char *caller, const char *operation);
103
104 static isc_result_t
105 dlv_validatezonekey(dns_validator_t *val);
106
107 static isc_result_t
108 dlv_validator_start(dns_validator_t *val);
109
110 static isc_result_t
111 finddlvsep(dns_validator_t *val, isc_boolean_t resume);
112
113 static inline void
114 markanswer(dns_validator_t *val) {
115         validator_log(val, ISC_LOG_DEBUG(3), "marking as answer");
116         if (val->event->rdataset)
117                 val->event->rdataset->trust = dns_trust_answer;
118         if (val->event->sigrdataset)
119                 val->event->sigrdataset->trust = dns_trust_answer;
120 }
121
122 static void
123 validator_done(dns_validator_t *val, isc_result_t result) {
124         isc_task_t *task;
125
126         if (val->event == NULL)
127                 return;
128
129         /*
130          * Caller must be holding the lock.
131          */
132
133         val->event->result = result;
134         task = val->event->ev_sender;
135         val->event->ev_sender = val;
136         val->event->ev_type = DNS_EVENT_VALIDATORDONE;
137         val->event->ev_action = val->action;
138         val->event->ev_arg = val->arg;
139         isc_task_sendanddetach(&task, (isc_event_t **)&val->event);
140 }
141
142 static inline isc_boolean_t
143 exit_check(dns_validator_t *val) {
144         /*
145          * Caller must be holding the lock.
146          */
147         if (!SHUTDOWN(val))
148                 return (ISC_FALSE);
149
150         INSIST(val->event == NULL);
151
152         if (val->fetch != NULL || val->subvalidator != NULL)
153                 return (ISC_FALSE);
154
155         return (ISC_TRUE);
156 }
157
158 static void
159 auth_nonpending(dns_message_t *message) {
160         isc_result_t result;
161         dns_name_t *name;
162         dns_rdataset_t *rdataset;
163
164         for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
165              result == ISC_R_SUCCESS;
166              result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
167         {
168                 name = NULL;
169                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
170                 for (rdataset = ISC_LIST_HEAD(name->list);
171                      rdataset != NULL;
172                      rdataset = ISC_LIST_NEXT(rdataset, link))
173                 {
174                         if (rdataset->trust == dns_trust_pending)
175                                 rdataset->trust = dns_trust_authauthority;
176                 }
177         }
178 }
179
180 static isc_boolean_t
181 isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
182              isc_result_t dbresult)
183 {
184         dns_rdataset_t set;
185         dns_rdata_t rdata = DNS_RDATA_INIT;
186         isc_boolean_t found;
187         isc_result_t result;
188
189         REQUIRE(dbresult == DNS_R_NXRRSET || dbresult == DNS_R_NCACHENXRRSET);
190
191         dns_rdataset_init(&set);
192         if (dbresult == DNS_R_NXRRSET)
193                 dns_rdataset_clone(rdataset, &set);
194         else {
195                 result = dns_ncache_getrdataset(rdataset, name,
196                                                 dns_rdatatype_nsec, &set);
197                 if (result != ISC_R_SUCCESS)
198                         return (ISC_FALSE);
199         }
200
201         INSIST(set.type == dns_rdatatype_nsec);
202
203         found = ISC_FALSE;
204         result = dns_rdataset_first(&set);
205         if (result == ISC_R_SUCCESS) {
206                 dns_rdataset_current(&set, &rdata);
207                 found = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
208         }
209         dns_rdataset_disassociate(&set);
210         return (found);
211 }
212
213 static void
214 fetch_callback_validator(isc_task_t *task, isc_event_t *event) {
215         dns_fetchevent_t *devent;
216         dns_validator_t *val;
217         dns_rdataset_t *rdataset;
218         isc_boolean_t want_destroy;
219         isc_result_t result;
220         isc_result_t eresult;
221
222         UNUSED(task);
223         INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
224         devent = (dns_fetchevent_t *)event;
225         val = devent->ev_arg;
226         rdataset = &val->frdataset;
227         eresult = devent->result;
228
229         /* Free resources which are not of interest. */
230         if (devent->node != NULL)
231                 dns_db_detachnode(devent->db, &devent->node);
232         if (devent->db != NULL)
233                 dns_db_detach(&devent->db);
234         if (dns_rdataset_isassociated(&val->fsigrdataset))
235                 dns_rdataset_disassociate(&val->fsigrdataset);
236         isc_event_free(&event);
237         dns_resolver_destroyfetch(&val->fetch);
238
239         INSIST(val->event != NULL);
240
241         validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_validator");
242         LOCK(&val->lock);
243         if (eresult == ISC_R_SUCCESS) {
244                 validator_log(val, ISC_LOG_DEBUG(3),
245                               "keyset with trust %d", rdataset->trust);
246                 /*
247                  * Only extract the dst key if the keyset is secure.
248                  */
249                 if (rdataset->trust >= dns_trust_secure) {
250                         result = get_dst_key(val, val->siginfo, rdataset);
251                         if (result == ISC_R_SUCCESS)
252                                 val->keyset = &val->frdataset;
253                 }
254                 result = validate(val, ISC_TRUE);
255                 if (result != DNS_R_WAIT)
256                         validator_done(val, result);
257         } else {
258                 validator_log(val, ISC_LOG_DEBUG(3),
259                               "fetch_callback_validator: got %s",
260                               isc_result_totext(eresult));
261                 if (eresult == ISC_R_CANCELED)
262                         validator_done(val, eresult);
263                 else
264                         validator_done(val, DNS_R_NOVALIDKEY);
265         }
266         want_destroy = exit_check(val);
267         UNLOCK(&val->lock);
268         if (want_destroy)
269                 destroy(val);
270 }
271
272 static void
273 dsfetched(isc_task_t *task, isc_event_t *event) {
274         dns_fetchevent_t *devent;
275         dns_validator_t *val;
276         dns_rdataset_t *rdataset;
277         isc_boolean_t want_destroy;
278         isc_result_t result;
279         isc_result_t eresult;
280
281         UNUSED(task);
282         INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
283         devent = (dns_fetchevent_t *)event;
284         val = devent->ev_arg;
285         rdataset = &val->frdataset;
286         eresult = devent->result;
287
288         /* Free resources which are not of interest. */
289         if (devent->node != NULL)
290                 dns_db_detachnode(devent->db, &devent->node);
291         if (devent->db != NULL)
292                 dns_db_detach(&devent->db);
293         if (dns_rdataset_isassociated(&val->fsigrdataset))
294                 dns_rdataset_disassociate(&val->fsigrdataset);
295         isc_event_free(&event);
296         dns_resolver_destroyfetch(&val->fetch);
297
298         INSIST(val->event != NULL);
299
300         validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched");
301         LOCK(&val->lock);
302         if (eresult == ISC_R_SUCCESS) {
303                 validator_log(val, ISC_LOG_DEBUG(3),
304                               "dsset with trust %d", rdataset->trust);
305                 val->dsset = &val->frdataset;
306                 result = validatezonekey(val);
307                 if (result != DNS_R_WAIT)
308                         validator_done(val, result);
309         } else if (eresult == DNS_R_NXRRSET ||
310                    eresult == DNS_R_NCACHENXRRSET)
311         {
312                 validator_log(val, ISC_LOG_DEBUG(3),
313                               "falling back to insecurity proof");
314                 val->attributes |= VALATTR_INSECURITY;
315                 result = proveunsecure(val, ISC_FALSE);
316                 if (result != DNS_R_WAIT)
317                         validator_done(val, result);
318         } else {
319                 validator_log(val, ISC_LOG_DEBUG(3),
320                               "dsfetched: got %s",
321                               isc_result_totext(eresult));
322                 if (eresult == ISC_R_CANCELED)
323                         validator_done(val, eresult);
324                 else
325                         validator_done(val, DNS_R_NOVALIDDS);
326         }
327         want_destroy = exit_check(val);
328         UNLOCK(&val->lock);
329         if (want_destroy)
330                 destroy(val);
331 }
332
333 /*
334  * XXX there's too much duplicated code here.
335  */
336 static void
337 dsfetched2(isc_task_t *task, isc_event_t *event) {
338         dns_fetchevent_t *devent;
339         dns_validator_t *val;
340         dns_name_t *tname;
341         isc_boolean_t want_destroy;
342         isc_result_t result;
343         isc_result_t eresult;
344
345         UNUSED(task);
346         INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
347         devent = (dns_fetchevent_t *)event;
348         val = devent->ev_arg;
349         eresult = devent->result;
350
351         /* Free resources which are not of interest. */
352         if (devent->node != NULL)
353                 dns_db_detachnode(devent->db, &devent->node);
354         if (devent->db != NULL)
355                 dns_db_detach(&devent->db);
356         if (dns_rdataset_isassociated(&val->fsigrdataset))
357                 dns_rdataset_disassociate(&val->fsigrdataset);
358         dns_resolver_destroyfetch(&val->fetch);
359
360         INSIST(val->event != NULL);
361
362         validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched2");
363         LOCK(&val->lock);
364         if (eresult == DNS_R_NXRRSET || eresult == DNS_R_NCACHENXRRSET) {
365                 /*
366                  * There is no DS.  If this is a delegation, we're done.
367                  */
368                 tname = dns_fixedname_name(&devent->foundname);
369                 if (isdelegation(tname, &val->frdataset, eresult)) {
370                         if (val->mustbesecure) {
371                                 validator_log(val, ISC_LOG_WARNING,
372                                               "must be secure failure");
373                                 validator_done(val, DNS_R_MUSTBESECURE);
374                         } else {
375                                 markanswer(val);
376                                 validator_done(val, ISC_R_SUCCESS);
377                         }
378                 } else {
379                         result = proveunsecure(val, ISC_TRUE);
380                         if (result != DNS_R_WAIT)
381                                 validator_done(val, result);
382                 }
383         } else if (eresult == ISC_R_SUCCESS ||
384                    eresult == DNS_R_NXDOMAIN ||
385                    eresult == DNS_R_NCACHENXDOMAIN)
386         {
387                 /*
388                  * Either there is a DS or this is not a zone cut.  Continue.
389                  */
390                 result = proveunsecure(val, ISC_TRUE);
391                 if (result != DNS_R_WAIT)
392                         validator_done(val, result);
393         } else {
394                 if (eresult == ISC_R_CANCELED)
395                         validator_done(val, eresult);
396                 else
397                         validator_done(val, DNS_R_NOVALIDDS);
398         }
399         isc_event_free(&event);
400         want_destroy = exit_check(val);
401         UNLOCK(&val->lock);
402         if (want_destroy)
403                 destroy(val);
404 }
405
406 static void
407 keyvalidated(isc_task_t *task, isc_event_t *event) {
408         dns_validatorevent_t *devent;
409         dns_validator_t *val;
410         isc_boolean_t want_destroy;
411         isc_result_t result;
412         isc_result_t eresult;
413
414         UNUSED(task);
415         INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
416
417         devent = (dns_validatorevent_t *)event;
418         val = devent->ev_arg;
419         eresult = devent->result;
420
421         isc_event_free(&event);
422         dns_validator_destroy(&val->subvalidator);
423
424         INSIST(val->event != NULL);
425
426         validator_log(val, ISC_LOG_DEBUG(3), "in keyvalidated");
427         LOCK(&val->lock);
428         if (eresult == ISC_R_SUCCESS) {
429                 validator_log(val, ISC_LOG_DEBUG(3),
430                               "keyset with trust %d", val->frdataset.trust);
431                 /*
432                  * Only extract the dst key if the keyset is secure.
433                  */
434                 if (val->frdataset.trust >= dns_trust_secure)
435                         (void) get_dst_key(val, val->siginfo, &val->frdataset);
436                 result = validate(val, ISC_TRUE);
437                 if (result != DNS_R_WAIT)
438                         validator_done(val, result);
439         } else {
440                 validator_log(val, ISC_LOG_DEBUG(3),
441                               "keyvalidated: got %s",
442                               isc_result_totext(eresult));
443                 validator_done(val, eresult);
444         }
445         want_destroy = exit_check(val);
446         UNLOCK(&val->lock);
447         if (want_destroy)
448                 destroy(val);
449 }
450
451 static void
452 dsvalidated(isc_task_t *task, isc_event_t *event) {
453         dns_validatorevent_t *devent;
454         dns_validator_t *val;
455         isc_boolean_t want_destroy;
456         isc_result_t result;
457         isc_result_t eresult;
458
459         UNUSED(task);
460         INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
461
462         devent = (dns_validatorevent_t *)event;
463         val = devent->ev_arg;
464         eresult = devent->result;
465
466         isc_event_free(&event);
467         dns_validator_destroy(&val->subvalidator);
468
469         INSIST(val->event != NULL);
470
471         validator_log(val, ISC_LOG_DEBUG(3), "in dsvalidated");
472         LOCK(&val->lock);
473         if (eresult == ISC_R_SUCCESS) {
474                 validator_log(val, ISC_LOG_DEBUG(3),
475                               "dsset with trust %d", val->frdataset.trust);
476                 if ((val->attributes & VALATTR_INSECURITY) != 0)
477                         result = proveunsecure(val, ISC_TRUE);
478                 else
479                         result = validatezonekey(val);
480                 if (result != DNS_R_WAIT)
481                         validator_done(val, result);
482         } else {
483                 validator_log(val, ISC_LOG_DEBUG(3),
484                               "dsvalidated: got %s",
485                               isc_result_totext(eresult));
486                 validator_done(val, eresult);
487         }
488         want_destroy = exit_check(val);
489         UNLOCK(&val->lock);
490         if (want_destroy)
491                 destroy(val);
492 }
493
494 /*
495  * Return ISC_R_SUCCESS if we can determine that the name doesn't exist
496  * or we can determine whether there is data or not at the name.
497  * If the name does not exist return the wildcard name.
498  */
499 static isc_result_t
500 nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
501                   dns_rdataset_t *nsecset, isc_boolean_t *exists,
502                   isc_boolean_t *data, dns_name_t *wild)
503 {
504         int order;
505         dns_rdata_t rdata = DNS_RDATA_INIT;
506         isc_result_t result;
507         dns_namereln_t relation;
508         unsigned int olabels, nlabels, labels;
509         dns_rdata_nsec_t nsec;
510         isc_boolean_t atparent;
511
512         REQUIRE(exists != NULL);
513         REQUIRE(data != NULL);
514         REQUIRE(nsecset != NULL &&
515                 nsecset->type == dns_rdatatype_nsec);
516
517         result = dns_rdataset_first(nsecset);
518         if (result != ISC_R_SUCCESS) {
519                 validator_log(val, ISC_LOG_DEBUG(3),
520                         "failure processing NSEC set");
521                 return (result);
522         }
523         dns_rdataset_current(nsecset, &rdata);
524
525         validator_log(val, ISC_LOG_DEBUG(3), "looking for relevant nsec");
526         relation = dns_name_fullcompare(name, nsecname, &order, &olabels);
527
528         if (order < 0) {
529                 /*
530                  * The name is not within the NSEC range.
531                  */
532                 validator_log(val, ISC_LOG_DEBUG(3),
533                               "NSEC does not cover name, before NSEC");
534                 return (ISC_R_IGNORE);
535         }
536
537         if (order == 0) {
538                 /*
539                  * The names are the same.
540                  */
541                 atparent = dns_rdatatype_atparent(val->event->type);
542                 if (dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
543                     !dns_nsec_typepresent(&rdata, dns_rdatatype_soa))
544                 {
545                         if (!atparent) {
546                                 /*
547                                  * This NSEC record is from somewhere higher in
548                                  * the DNS, and at the parent of a delegation.
549                                  * It can not be legitimately used here.
550                                  */
551                                 validator_log(val, ISC_LOG_DEBUG(3),
552                                               "ignoring parent nsec");
553                                 return (ISC_R_IGNORE);
554                         }
555                 } else if (atparent) {
556                         /*
557                          * This NSEC record is from the child.
558                          * It can not be legitimately used here.
559                          */
560                         validator_log(val, ISC_LOG_DEBUG(3),
561                                       "ignoring child nsec");
562                         return (ISC_R_IGNORE);
563                 }
564                 *exists = ISC_TRUE;
565                 *data = dns_nsec_typepresent(&rdata, val->event->type);
566                 validator_log(val, ISC_LOG_DEBUG(3),
567                               "nsec proves name exists (owner) data=%d",
568                               *data);
569                 return (ISC_R_SUCCESS);
570         }
571
572         if (relation == dns_namereln_subdomain &&
573             dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
574             !dns_nsec_typepresent(&rdata, dns_rdatatype_soa))
575         {
576                 /*
577                  * This NSEC record is from somewhere higher in
578                  * the DNS, and at the parent of a delegation.
579                  * It can not be legitimately used here.
580                  */
581                 validator_log(val, ISC_LOG_DEBUG(3), "ignoring parent nsec");
582                 return (ISC_R_IGNORE);
583         }
584
585         result = dns_rdata_tostruct(&rdata, &nsec, NULL);
586         if (result != ISC_R_SUCCESS)
587                 return (result);
588         relation = dns_name_fullcompare(&nsec.next, name, &order, &nlabels);
589         if (order == 0) {
590                 dns_rdata_freestruct(&nsec);
591                 validator_log(val, ISC_LOG_DEBUG(3),
592                               "ignoring nsec matches next name");
593                 return (ISC_R_IGNORE);
594         }
595
596         if (order < 0 && !dns_name_issubdomain(nsecname, &nsec.next)) {
597                 /*
598                  * The name is not within the NSEC range.
599                  */
600                 dns_rdata_freestruct(&nsec);
601                 validator_log(val, ISC_LOG_DEBUG(3),
602                             "ignoring nsec because name is past end of range");
603                 return (ISC_R_IGNORE);
604         }
605
606         if (order > 0 && relation == dns_namereln_subdomain) {
607                 validator_log(val, ISC_LOG_DEBUG(3),
608                               "nsec proves name exist (empty)");
609                 dns_rdata_freestruct(&nsec);
610                 *exists = ISC_TRUE;
611                 *data = ISC_FALSE;
612                 return (ISC_R_SUCCESS);
613         }
614         if (wild != NULL) {
615                 dns_name_t common;
616                 dns_name_init(&common, NULL);
617                 if (olabels > nlabels) {
618                         labels = dns_name_countlabels(nsecname);
619                         dns_name_getlabelsequence(nsecname, labels - olabels,
620                                                   olabels, &common);
621                 } else {
622                         labels = dns_name_countlabels(&nsec.next);
623                         dns_name_getlabelsequence(&nsec.next, labels - nlabels,
624                                                   nlabels, &common);
625                 }
626                 result = dns_name_concatenate(dns_wildcardname, &common,
627                                                wild, NULL);
628                 if (result != ISC_R_SUCCESS) {
629                         validator_log(val, ISC_LOG_DEBUG(3),
630                                     "failure generating wilcard name");
631                         return (result);
632                 }
633         }
634         dns_rdata_freestruct(&nsec);
635         validator_log(val, ISC_LOG_DEBUG(3), "nsec range ok");
636         *exists = ISC_FALSE;
637         return (ISC_R_SUCCESS);
638 }
639
640 static void
641 authvalidated(isc_task_t *task, isc_event_t *event) {
642         dns_validatorevent_t *devent;
643         dns_validator_t *val;
644         dns_rdataset_t *rdataset;
645         isc_boolean_t want_destroy;
646         isc_result_t result;
647         isc_boolean_t exists, data;
648
649         UNUSED(task);
650         INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
651
652         devent = (dns_validatorevent_t *)event;
653         rdataset = devent->rdataset;
654         val = devent->ev_arg;
655         result = devent->result;
656         dns_validator_destroy(&val->subvalidator);
657
658         INSIST(val->event != NULL);
659
660         validator_log(val, ISC_LOG_DEBUG(3), "in authvalidated");
661         LOCK(&val->lock);
662         if (result != ISC_R_SUCCESS) {
663                 validator_log(val, ISC_LOG_DEBUG(3),
664                               "authvalidated: got %s",
665                               isc_result_totext(result));
666                 if (result == ISC_R_CANCELED)
667                         validator_done(val, result);
668                 else {
669                         result = nsecvalidate(val, ISC_TRUE);
670                         if (result != DNS_R_WAIT)
671                                 validator_done(val, result);
672                 }
673         } else {
674                 dns_name_t **proofs = val->event->proofs;
675                 
676                 if (rdataset->trust == dns_trust_secure)
677                         val->seensig = ISC_TRUE;
678
679                 if (rdataset->type == dns_rdatatype_nsec &&
680                     rdataset->trust == dns_trust_secure &&
681                     ((val->attributes & VALATTR_NEEDNODATA) != 0 ||
682                      (val->attributes & VALATTR_NEEDNOQNAME) != 0) &&
683                     (val->attributes & VALATTR_FOUNDNODATA) == 0 &&
684                     (val->attributes & VALATTR_FOUNDNOQNAME) == 0 &&
685                     nsecnoexistnodata(val, val->event->name, devent->name,
686                                       rdataset, &exists, &data,
687                                       dns_fixedname_name(&val->wild))
688                                       == ISC_R_SUCCESS)
689                  {
690                         if (exists && !data) {
691                                 val->attributes |= VALATTR_FOUNDNODATA;
692                                 if (NEEDNODATA(val))
693                                         proofs[DNS_VALIDATOR_NODATAPROOF] =
694                                                 devent->name;
695                         }
696                         if (!exists) {
697                                 val->attributes |= VALATTR_FOUNDNOQNAME;
698                                 if (NEEDNOQNAME(val))
699                                         proofs[DNS_VALIDATOR_NOQNAMEPROOF] =
700                                                 devent->name;
701                         }
702                 }
703                 result = nsecvalidate(val, ISC_TRUE);
704                 if (result != DNS_R_WAIT)
705                         validator_done(val, result);
706         }
707         want_destroy = exit_check(val);
708         UNLOCK(&val->lock);
709         if (want_destroy)
710                 destroy(val);
711
712         /*
713          * Free stuff from the event.
714          */
715         isc_event_free(&event);
716 }
717
718 static void
719 negauthvalidated(isc_task_t *task, isc_event_t *event) {
720         dns_validatorevent_t *devent;
721         dns_validator_t *val;
722         isc_boolean_t want_destroy;
723         isc_result_t eresult;
724
725         UNUSED(task);
726         INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
727
728         devent = (dns_validatorevent_t *)event;
729         val = devent->ev_arg;
730         eresult = devent->result;
731         isc_event_free(&event);
732         dns_validator_destroy(&val->subvalidator);
733
734         INSIST(val->event != NULL);
735
736         validator_log(val, ISC_LOG_DEBUG(3), "in negauthvalidated");
737         LOCK(&val->lock);
738         if (eresult == ISC_R_SUCCESS) {
739                 val->attributes |= VALATTR_FOUNDNONEXISTENCE;
740                 validator_log(val, ISC_LOG_DEBUG(3),
741                               "nonexistence proof found");
742                 auth_nonpending(val->event->message);
743                 validator_done(val, ISC_R_SUCCESS);
744         } else {
745                 validator_log(val, ISC_LOG_DEBUG(3),
746                               "negauthvalidated: got %s",
747                               isc_result_totext(eresult));
748                 validator_done(val, eresult);
749         }
750         want_destroy = exit_check(val);
751         UNLOCK(&val->lock);
752         if (want_destroy)
753                 destroy(val);
754 }
755
756 static inline isc_result_t
757 view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
758         dns_fixedname_t fixedname;
759         dns_name_t *foundname;
760         dns_rdata_nsec_t nsec;
761         dns_rdata_t rdata = DNS_RDATA_INIT;
762         isc_result_t result;
763         unsigned int options;
764         char buf1[DNS_NAME_FORMATSIZE];
765         char buf2[DNS_NAME_FORMATSIZE];
766         char buf3[DNS_NAME_FORMATSIZE];
767
768         if (dns_rdataset_isassociated(&val->frdataset))
769                 dns_rdataset_disassociate(&val->frdataset);
770         if (dns_rdataset_isassociated(&val->fsigrdataset))
771                 dns_rdataset_disassociate(&val->fsigrdataset);
772
773         if (val->view->zonetable == NULL)
774                 return (ISC_R_CANCELED);
775
776         options = DNS_DBFIND_PENDINGOK;
777         if (type == dns_rdatatype_dlv)
778                 options |= DNS_DBFIND_COVERINGNSEC;
779         dns_fixedname_init(&fixedname);
780         foundname = dns_fixedname_name(&fixedname);
781         result = dns_view_find(val->view, name, type, 0, options,
782                                ISC_FALSE, NULL, NULL, foundname,
783                                &val->frdataset, &val->fsigrdataset);
784         if (result == DNS_R_NXDOMAIN) {
785                 if (dns_rdataset_isassociated(&val->frdataset))
786                         dns_rdataset_disassociate(&val->frdataset);
787                 if (dns_rdataset_isassociated(&val->fsigrdataset))
788                         dns_rdataset_disassociate(&val->fsigrdataset);
789         } else if (result == DNS_R_COVERINGNSEC) {
790                 validator_log(val, ISC_LOG_DEBUG(3), "DNS_R_COVERINGNSEC");
791                 /*
792                  * Check if the returned NSEC covers the name.
793                  */
794                 INSIST(type == dns_rdatatype_dlv);
795                 if (val->frdataset.trust != dns_trust_secure) {
796                         validator_log(val, ISC_LOG_DEBUG(3),
797                                       "covering nsec: trust %u",
798                                       val->frdataset.trust);
799                         goto notfound;
800                 }
801                 result = dns_rdataset_first(&val->frdataset);
802                 if (result != ISC_R_SUCCESS)
803                         goto notfound;
804                 dns_rdataset_current(&val->frdataset, &rdata);
805                 if (dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
806                     !dns_nsec_typepresent(&rdata, dns_rdatatype_soa)) {
807                         /* Parent NSEC record. */
808                         if (dns_name_issubdomain(name, foundname)) {
809                                 validator_log(val, ISC_LOG_DEBUG(3),
810                                               "covering nsec: for parent");
811                                 goto notfound;
812                         }
813                 }
814                 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
815                 if (result != ISC_R_SUCCESS)
816                         goto notfound;
817                 if (dns_name_compare(foundname, &nsec.next) >= 0) {
818                         /* End of zone chain. */
819                         if (!dns_name_issubdomain(name, &nsec.next)) {
820                                 /*
821                                  * XXXMPA We could look for a parent NSEC
822                                  * at nsec.next and if found retest with
823                                  * this NSEC.
824                                  */
825                                 dns_rdata_freestruct(&nsec);
826                                 validator_log(val, ISC_LOG_DEBUG(3),
827                                               "covering nsec: not in zone");
828                                 goto notfound;
829                         }
830                 } else if (dns_name_compare(name, &nsec.next) >= 0) {
831                         /*
832                          * XXXMPA We could check if this NSEC is at a zone
833                          * apex and if the qname is not below it and look for
834                          * a parent NSEC with the same name.  This requires
835                          * that we can cache both NSEC records which we
836                          * currently don't support.
837                          */
838                         dns_rdata_freestruct(&nsec);
839                         validator_log(val, ISC_LOG_DEBUG(3),
840                                       "covering nsec: not in range");
841                         goto notfound;
842                 }
843                 if (isc_log_wouldlog(dns_lctx,ISC_LOG_DEBUG(3))) {
844                         dns_name_format(name, buf1, sizeof buf1);
845                         dns_name_format(foundname, buf2, sizeof buf2);
846                         dns_name_format(&nsec.next, buf3, sizeof buf3);
847                         validator_log(val, ISC_LOG_DEBUG(3),
848                                       "covering nsec found: '%s' '%s' '%s'",
849                                       buf1, buf2, buf3);
850                 }
851                 if (dns_rdataset_isassociated(&val->frdataset))
852                         dns_rdataset_disassociate(&val->frdataset);
853                 if (dns_rdataset_isassociated(&val->fsigrdataset))
854                         dns_rdataset_disassociate(&val->fsigrdataset);
855                 dns_rdata_freestruct(&nsec);
856                 result = DNS_R_NCACHENXDOMAIN;
857         } else if (result != ISC_R_SUCCESS &&
858                    result != DNS_R_GLUE &&
859                    result != DNS_R_HINT &&
860                    result != DNS_R_NCACHENXDOMAIN &&
861                    result != DNS_R_NCACHENXRRSET &&
862                    result != DNS_R_NXRRSET &&
863                    result != DNS_R_HINTNXRRSET &&
864                    result != ISC_R_NOTFOUND) {
865                 goto  notfound;
866         }
867         return (result);
868
869  notfound:
870         if (dns_rdataset_isassociated(&val->frdataset))
871                 dns_rdataset_disassociate(&val->frdataset);
872         if (dns_rdataset_isassociated(&val->fsigrdataset))
873                 dns_rdataset_disassociate(&val->fsigrdataset);
874         return (ISC_R_NOTFOUND);
875 }
876
877 static inline isc_boolean_t
878 check_deadlock(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
879         dns_validator_t *parent;
880
881         for (parent = val->parent; parent != NULL; parent = parent->parent) {
882                 if (parent->event != NULL &&
883                     parent->event->type == type &&
884                     dns_name_equal(parent->event->name, name))
885                 {
886                         validator_log(val, ISC_LOG_DEBUG(3),
887                                       "continuing validation would lead to "
888                                       "deadlock: aborting validation");
889                         return (ISC_TRUE);
890                 }
891         }
892         return (ISC_FALSE);
893 }
894
895 static inline isc_result_t
896 create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
897              isc_taskaction_t callback, const char *caller)
898 {
899         if (dns_rdataset_isassociated(&val->frdataset))
900                 dns_rdataset_disassociate(&val->frdataset);
901         if (dns_rdataset_isassociated(&val->fsigrdataset))
902                 dns_rdataset_disassociate(&val->fsigrdataset);
903
904         if (check_deadlock(val, name, type))
905                 return (DNS_R_NOVALIDSIG);
906
907         validator_logcreate(val, name, type, caller, "fetch");
908         return (dns_resolver_createfetch(val->view->resolver, name, type,
909                                          NULL, NULL, NULL, 0,
910                                          val->event->ev_sender,
911                                          callback, val,
912                                          &val->frdataset,
913                                          &val->fsigrdataset,
914                                          &val->fetch));
915 }
916
917 static inline isc_result_t
918 create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
919                  dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
920                  isc_taskaction_t action, const char *caller)
921 {
922         isc_result_t result;
923
924         if (check_deadlock(val, name, type))
925                 return (DNS_R_NOVALIDSIG);
926
927         validator_logcreate(val, name, type, caller, "validator");
928         result = dns_validator_create(val->view, name, type,
929                                       rdataset, sigrdataset, NULL, 0,
930                                       val->task, action, val,
931                                       &val->subvalidator);
932         if (result == ISC_R_SUCCESS) {
933                 val->subvalidator->parent = val;
934                 val->subvalidator->depth = val->depth + 1;
935         }
936         return (result);
937 }
938
939 /*
940  * Try to find a key that could have signed 'siginfo' among those
941  * in 'rdataset'.  If found, build a dst_key_t for it and point
942  * val->key at it.
943  *
944  * If val->key is non-NULL, this returns the next matching key.
945  */
946 static isc_result_t
947 get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
948             dns_rdataset_t *rdataset)
949 {
950         isc_result_t result;
951         isc_buffer_t b;
952         dns_rdata_t rdata = DNS_RDATA_INIT;
953         dst_key_t *oldkey = val->key;
954         isc_boolean_t foundold;
955
956         if (oldkey == NULL)
957                 foundold = ISC_TRUE;
958         else {
959                 foundold = ISC_FALSE;
960                 val->key = NULL;
961         }
962
963         result = dns_rdataset_first(rdataset);
964         if (result != ISC_R_SUCCESS)
965                 goto failure;
966         do {
967                 dns_rdataset_current(rdataset, &rdata);
968
969                 isc_buffer_init(&b, rdata.data, rdata.length);
970                 isc_buffer_add(&b, rdata.length);
971                 INSIST(val->key == NULL);
972                 result = dst_key_fromdns(&siginfo->signer, rdata.rdclass, &b,
973                                          val->view->mctx, &val->key);
974                 if (result != ISC_R_SUCCESS)
975                         goto failure;
976                 if (siginfo->algorithm ==
977                     (dns_secalg_t)dst_key_alg(val->key) &&
978                     siginfo->keyid ==
979                     (dns_keytag_t)dst_key_id(val->key) &&
980                     dst_key_iszonekey(val->key))
981                 {
982                         if (foundold)
983                                 /*
984                                  * This is the key we're looking for.
985                                  */
986                                 return (ISC_R_SUCCESS);
987                         else if (dst_key_compare(oldkey, val->key) == ISC_TRUE)
988                         {
989                                 foundold = ISC_TRUE;
990                                 dst_key_free(&oldkey);
991                         }
992                 }
993                 dst_key_free(&val->key);
994                 dns_rdata_reset(&rdata);
995                 result = dns_rdataset_next(rdataset);
996         } while (result == ISC_R_SUCCESS);
997         if (result == ISC_R_NOMORE)
998                 result = ISC_R_NOTFOUND;
999
1000  failure:
1001         if (oldkey != NULL)
1002                 dst_key_free(&oldkey);
1003
1004         return (result);
1005 }
1006
1007 static isc_result_t
1008 get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
1009         isc_result_t result;
1010         unsigned int nlabels;
1011         int order;
1012         dns_namereln_t namereln;
1013
1014         /*
1015          * Is the signer name appropriate for this signature?
1016          *
1017          * The signer name must be at the same level as the owner name
1018          * or closer to the the DNS root.
1019          */
1020         namereln = dns_name_fullcompare(val->event->name, &siginfo->signer,
1021                                         &order, &nlabels);
1022         if (namereln != dns_namereln_subdomain &&
1023             namereln != dns_namereln_equal)
1024                 return (DNS_R_CONTINUE);
1025
1026         if (namereln == dns_namereln_equal) {
1027                 /*
1028                  * If this is a self-signed keyset, it must not be a zone key
1029                  * (since get_key is not called from validatezonekey).
1030                  */
1031                 if (val->event->rdataset->type == dns_rdatatype_dnskey)
1032                         return (DNS_R_CONTINUE);
1033
1034                 /*
1035                  * Records appearing in the parent zone at delegation
1036                  * points cannot be self-signed.
1037                  */
1038                 if (dns_rdatatype_atparent(val->event->rdataset->type))
1039                         return (DNS_R_CONTINUE);
1040         }
1041
1042         /*
1043          * Do we know about this key?
1044          */
1045         result = view_find(val, &siginfo->signer, dns_rdatatype_dnskey);
1046         if (result == ISC_R_SUCCESS) {
1047                 /*
1048                  * We have an rrset for the given keyname.
1049                  */
1050                 val->keyset = &val->frdataset;
1051                 if (val->frdataset.trust == dns_trust_pending &&
1052                     dns_rdataset_isassociated(&val->fsigrdataset))
1053                 {
1054                         /*
1055                          * We know the key but haven't validated it yet.
1056                          */
1057                         result = create_validator(val, &siginfo->signer,
1058                                                   dns_rdatatype_dnskey,
1059                                                   &val->frdataset,
1060                                                   &val->fsigrdataset,
1061                                                   keyvalidated,
1062                                                   "get_key");
1063                         if (result != ISC_R_SUCCESS)
1064                                 return (result);
1065                         return (DNS_R_WAIT);
1066                 } else if (val->frdataset.trust == dns_trust_pending) {
1067                         /*
1068                          * Having a pending key with no signature means that
1069                          * something is broken.
1070                          */
1071                         result = DNS_R_CONTINUE;
1072                 } else if (val->frdataset.trust < dns_trust_secure) {
1073                         /*
1074                          * The key is legitimately insecure.  There's no
1075                          * point in even attempting verification.
1076                          */
1077                         val->key = NULL;
1078                         result = ISC_R_SUCCESS;
1079                 } else {
1080                         /*
1081                          * See if we've got the key used in the signature.
1082                          */
1083                         validator_log(val, ISC_LOG_DEBUG(3),
1084                                       "keyset with trust %d",
1085                                       val->frdataset.trust);
1086                         result = get_dst_key(val, siginfo, val->keyset);
1087                         if (result != ISC_R_SUCCESS) {
1088                                 /*
1089                                  * Either the key we're looking for is not
1090                                  * in the rrset, or something bad happened.
1091                                  * Give up.
1092                                  */
1093                                 result = DNS_R_CONTINUE;
1094                         }
1095                 }
1096         } else if (result == ISC_R_NOTFOUND) {
1097                 /*
1098                  * We don't know anything about this key.
1099                  */
1100                 result = create_fetch(val, &siginfo->signer, dns_rdatatype_dnskey,
1101                                       fetch_callback_validator, "get_key");
1102                 if (result != ISC_R_SUCCESS)
1103                         return (result);
1104                 return (DNS_R_WAIT);
1105         } else if (result ==  DNS_R_NCACHENXDOMAIN ||
1106                    result == DNS_R_NCACHENXRRSET ||
1107                    result == DNS_R_NXDOMAIN ||
1108                    result == DNS_R_NXRRSET)
1109         {
1110                 /*
1111                  * This key doesn't exist.
1112                  */
1113                 result = DNS_R_CONTINUE;
1114         }
1115
1116         if (dns_rdataset_isassociated(&val->frdataset) &&
1117             val->keyset != &val->frdataset)
1118                 dns_rdataset_disassociate(&val->frdataset);
1119         if (dns_rdataset_isassociated(&val->fsigrdataset))
1120                 dns_rdataset_disassociate(&val->fsigrdataset);
1121
1122         return (result);
1123 }
1124
1125 static dns_keytag_t
1126 compute_keytag(dns_rdata_t *rdata, dns_rdata_dnskey_t *key) {
1127         isc_region_t r;
1128
1129         dns_rdata_toregion(rdata, &r);
1130         return (dst_region_computeid(&r, key->algorithm));
1131 }
1132
1133 /*
1134  * Is this keyset self-signed?
1135  */
1136 static isc_boolean_t
1137 isselfsigned(dns_validator_t *val) {
1138         dns_rdataset_t *rdataset, *sigrdataset;
1139         dns_rdata_t rdata = DNS_RDATA_INIT;
1140         dns_rdata_t sigrdata = DNS_RDATA_INIT;
1141         dns_rdata_dnskey_t key;
1142         dns_rdata_rrsig_t sig;
1143         dns_keytag_t keytag;
1144         isc_result_t result;
1145
1146         rdataset = val->event->rdataset;
1147         sigrdataset = val->event->sigrdataset;
1148
1149         INSIST(rdataset->type == dns_rdatatype_dnskey);
1150
1151         for (result = dns_rdataset_first(rdataset);
1152              result == ISC_R_SUCCESS;
1153              result = dns_rdataset_next(rdataset))
1154         {
1155                 dns_rdata_reset(&rdata);
1156                 dns_rdataset_current(rdataset, &rdata);
1157                 (void)dns_rdata_tostruct(&rdata, &key, NULL);
1158                 keytag = compute_keytag(&rdata, &key);
1159                 for (result = dns_rdataset_first(sigrdataset);
1160                      result == ISC_R_SUCCESS;
1161                      result = dns_rdataset_next(sigrdataset))
1162                 {
1163                         dns_rdata_reset(&sigrdata);
1164                         dns_rdataset_current(sigrdataset, &sigrdata);
1165                         (void)dns_rdata_tostruct(&sigrdata, &sig, NULL);
1166
1167                         if (sig.algorithm == key.algorithm &&
1168                             sig.keyid == keytag)
1169                                 return (ISC_TRUE);
1170                 }
1171         }
1172         return (ISC_FALSE);
1173 }
1174
1175 static isc_result_t
1176 verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata) {
1177         isc_result_t result;
1178         dns_fixedname_t fixed;
1179
1180         val->attributes |= VALATTR_TRIEDVERIFY;
1181         dns_fixedname_init(&fixed);
1182         result = dns_dnssec_verify2(val->event->name, val->event->rdataset,
1183                                     key, ISC_FALSE, val->view->mctx, rdata,
1184                                     dns_fixedname_name(&fixed));
1185         validator_log(val, ISC_LOG_DEBUG(3),
1186                       "verify rdataset: %s",
1187                       isc_result_totext(result));
1188         if (result == DNS_R_FROMWILDCARD) {
1189                 if (!dns_name_equal(val->event->name,
1190                                     dns_fixedname_name(&fixed)))
1191                         val->attributes |= VALATTR_NEEDNOQNAME;
1192                 result = ISC_R_SUCCESS;
1193         }
1194         return (result);
1195 }
1196
1197 /*
1198  * Attempts positive response validation of a normal RRset.
1199  *
1200  * Returns:
1201  *      ISC_R_SUCCESS   Validation completed successfully
1202  *      DNS_R_WAIT      Validation has started but is waiting
1203  *                      for an event.
1204  *      Other return codes are possible and all indicate failure.
1205  */
1206 static isc_result_t
1207 validate(dns_validator_t *val, isc_boolean_t resume) {
1208         isc_result_t result;
1209         dns_validatorevent_t *event;
1210         dns_rdata_t rdata = DNS_RDATA_INIT;
1211
1212         /*
1213          * Caller must be holding the validator lock.
1214          */
1215
1216         event = val->event;
1217
1218         if (resume) {
1219                 /*
1220                  * We already have a sigrdataset.
1221                  */
1222                 result = ISC_R_SUCCESS;
1223                 validator_log(val, ISC_LOG_DEBUG(3), "resuming validate");
1224         } else {
1225                 result = dns_rdataset_first(event->sigrdataset);
1226         }
1227
1228         for (;
1229              result == ISC_R_SUCCESS;
1230              result = dns_rdataset_next(event->sigrdataset))
1231         {
1232                 dns_rdata_reset(&rdata);
1233                 dns_rdataset_current(event->sigrdataset, &rdata);
1234                 if (val->siginfo == NULL) {
1235                         val->siginfo = isc_mem_get(val->view->mctx,
1236                                                    sizeof(*val->siginfo));
1237                         if (val->siginfo == NULL)
1238                                 return (ISC_R_NOMEMORY);
1239                 }
1240                 result = dns_rdata_tostruct(&rdata, val->siginfo, NULL);
1241                 if (result != ISC_R_SUCCESS)
1242                         return (result);
1243
1244                 /*
1245                  * At this point we could check that the signature algorithm
1246                  * was known and "sufficiently good".
1247                  */
1248                 if (!dns_resolver_algorithm_supported(val->view->resolver,
1249                                                       event->name,
1250                                                       val->siginfo->algorithm))
1251                         continue;
1252
1253                 if (!resume) {
1254                         result = get_key(val, val->siginfo);
1255                         if (result == DNS_R_CONTINUE)
1256                                 continue; /* Try the next SIG RR. */
1257                         if (result != ISC_R_SUCCESS)
1258                                 return (result);
1259                 }
1260
1261                 /*
1262                  * The key is insecure, so mark the data as insecure also.
1263                  */
1264                 if (val->key == NULL) {
1265                         if (val->mustbesecure) {
1266                                 validator_log(val, ISC_LOG_WARNING,
1267                                               "must be secure failure");
1268                                 return (DNS_R_MUSTBESECURE);
1269                         }
1270                         markanswer(val);
1271                         return (ISC_R_SUCCESS);
1272                 }
1273
1274                 do {
1275                         result = verify(val, val->key, &rdata);
1276                         if (result == ISC_R_SUCCESS)
1277                                 break;
1278                         if (val->keynode != NULL) {
1279                                 dns_keynode_t *nextnode = NULL;
1280                                 result = dns_keytable_findnextkeynode(
1281                                                         val->keytable,
1282                                                         val->keynode,
1283                                                         &nextnode);
1284                                 dns_keytable_detachkeynode(val->keytable,
1285                                                            &val->keynode);
1286                                 val->keynode = nextnode;
1287                                 if (result != ISC_R_SUCCESS) {
1288                                         val->key = NULL;
1289                                         break;
1290                                 }
1291                                 val->key = dns_keynode_key(val->keynode);
1292                         } else {
1293                                 if (get_dst_key(val, val->siginfo, val->keyset)
1294                                     != ISC_R_SUCCESS)
1295                                         break;
1296                         }
1297                 } while (1);
1298                 if (result != ISC_R_SUCCESS)
1299                         validator_log(val, ISC_LOG_DEBUG(3),
1300                                       "failed to verify rdataset");
1301                 else {
1302                         isc_uint32_t ttl;
1303                         isc_stdtime_t now;
1304
1305                         isc_stdtime_get(&now);
1306                         ttl = ISC_MIN(event->rdataset->ttl,
1307                                       val->siginfo->timeexpire - now);
1308                         if (val->keyset != NULL)
1309                                 ttl = ISC_MIN(ttl, val->keyset->ttl);
1310                         event->rdataset->ttl = ttl;
1311                         event->sigrdataset->ttl = ttl;
1312                 }
1313
1314                 if (val->keynode != NULL)
1315                         dns_keytable_detachkeynode(val->keytable,
1316                                                    &val->keynode);
1317                 else {
1318                         if (val->key != NULL)
1319                                 dst_key_free(&val->key);
1320                         if (val->keyset != NULL) {
1321                                 dns_rdataset_disassociate(val->keyset);
1322                                 val->keyset = NULL;
1323                         }
1324                 }
1325                 val->key = NULL;
1326                 if ((val->attributes & VALATTR_NEEDNOQNAME) != 0) {
1327                         if (val->event->message == NULL) {
1328                                 validator_log(val, ISC_LOG_DEBUG(3),
1329                                       "no message available for noqname proof");
1330                                 return (DNS_R_NOVALIDSIG);
1331                         }
1332                         validator_log(val, ISC_LOG_DEBUG(3),
1333                                       "looking for noqname proof");
1334                         return (nsecvalidate(val, ISC_FALSE));
1335                 } else if (result == ISC_R_SUCCESS) {
1336                         event->rdataset->trust = dns_trust_secure;
1337                         event->sigrdataset->trust = dns_trust_secure;
1338                         validator_log(val, ISC_LOG_DEBUG(3),
1339                                       "marking as secure");
1340                         return (result);
1341                 } else {
1342                         validator_log(val, ISC_LOG_DEBUG(3),
1343                                       "verify failure: %s",
1344                                       isc_result_totext(result));
1345                         resume = ISC_FALSE;
1346                 }
1347         }
1348         if (result != ISC_R_NOMORE) {
1349                 validator_log(val, ISC_LOG_DEBUG(3),
1350                               "failed to iterate signatures: %s",
1351                               isc_result_totext(result));
1352                 return (result);
1353         }
1354
1355         validator_log(val, ISC_LOG_INFO, "no valid signature found");
1356         return (DNS_R_NOVALIDSIG);
1357 }
1358
1359 static isc_result_t
1360 dlv_validatezonekey(dns_validator_t *val) {
1361         dns_keytag_t keytag;
1362         dns_rdata_dlv_t dlv;
1363         dns_rdata_dnskey_t key;
1364         dns_rdata_rrsig_t sig;
1365         dns_rdata_t dlvrdata = DNS_RDATA_INIT;
1366         dns_rdata_t keyrdata = DNS_RDATA_INIT;
1367         dns_rdata_t newdsrdata = DNS_RDATA_INIT;
1368         dns_rdata_t sigrdata = DNS_RDATA_INIT;
1369         dns_rdataset_t trdataset;
1370         dst_key_t *dstkey;
1371         isc_boolean_t supported_algorithm;
1372         isc_result_t result;
1373         unsigned char dsbuf[DNS_DS_BUFFERSIZE];
1374
1375         validator_log(val, ISC_LOG_DEBUG(3), "dlv_validatezonekey");
1376         /*
1377          * Look through the DLV record and find the keys that can sign the
1378          * key set and the matching signature.  For each such key, attempt
1379          * verification.
1380          */
1381
1382         supported_algorithm = ISC_FALSE;
1383
1384         for (result = dns_rdataset_first(&val->dlv);
1385              result == ISC_R_SUCCESS;
1386              result = dns_rdataset_next(&val->dlv))
1387         {
1388                 dns_rdata_reset(&dlvrdata);
1389                 dns_rdataset_current(&val->dlv, &dlvrdata);
1390                 (void)dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
1391
1392                 if (dlv.digest_type != DNS_DSDIGEST_SHA1 ||
1393                     !dns_resolver_algorithm_supported(val->view->resolver,
1394                                                       val->event->name,
1395                                                       dlv.algorithm))
1396                         continue;
1397
1398                 supported_algorithm = ISC_TRUE;
1399
1400                 dns_rdataset_init(&trdataset);
1401                 dns_rdataset_clone(val->event->rdataset, &trdataset);
1402
1403                 for (result = dns_rdataset_first(&trdataset);
1404                      result == ISC_R_SUCCESS;
1405                      result = dns_rdataset_next(&trdataset))
1406                 {
1407                         dns_rdata_reset(&keyrdata);
1408                         dns_rdataset_current(&trdataset, &keyrdata);
1409                         (void)dns_rdata_tostruct(&keyrdata, &key, NULL);
1410                         keytag = compute_keytag(&keyrdata, &key);
1411                         if (dlv.key_tag != keytag ||
1412                             dlv.algorithm != key.algorithm)
1413                                 continue;
1414                         dns_rdata_reset(&newdsrdata);
1415                         result = dns_ds_buildrdata(val->event->name,
1416                                                    &keyrdata, dlv.digest_type,
1417                                                    dsbuf, &newdsrdata);
1418                         if (result != ISC_R_SUCCESS) {
1419                                 validator_log(val, ISC_LOG_DEBUG(3),
1420                                               "dns_ds_buildrdata() -> %s",
1421                                               dns_result_totext(result));
1422                                 continue;
1423                         }
1424                         /* Covert to DLV */
1425                         newdsrdata.type = dns_rdatatype_dlv;
1426                         if (dns_rdata_compare(&dlvrdata, &newdsrdata) == 0)
1427                                 break;
1428                 }
1429                 if (result != ISC_R_SUCCESS) {
1430                         validator_log(val, ISC_LOG_DEBUG(3),
1431                                       "no DNSKEY matching DLV");
1432                         continue;
1433                 }
1434                 validator_log(val, ISC_LOG_DEBUG(3),
1435                       "Found matching DLV record: checking for signature");
1436
1437                 for (result = dns_rdataset_first(val->event->sigrdataset);
1438                      result == ISC_R_SUCCESS;
1439                      result = dns_rdataset_next(val->event->sigrdataset))
1440                 {
1441                         dns_rdata_reset(&sigrdata);
1442                         dns_rdataset_current(val->event->sigrdataset,
1443                                              &sigrdata);
1444                         (void)dns_rdata_tostruct(&sigrdata, &sig, NULL);
1445                         if (dlv.key_tag != sig.keyid &&
1446                             dlv.algorithm != sig.algorithm)
1447                                 continue;
1448                         dstkey = NULL;
1449                         result = dns_dnssec_keyfromrdata(val->event->name,
1450                                                          &keyrdata,
1451                                                          val->view->mctx,
1452                                                          &dstkey);
1453                         if (result != ISC_R_SUCCESS)
1454                                 /*
1455                                  * This really shouldn't happen, but...
1456                                  */
1457                                 continue;
1458
1459                         result = verify(val, dstkey, &sigrdata);
1460                         dst_key_free(&dstkey);
1461                         if (result == ISC_R_SUCCESS)
1462                                 break;
1463                 }
1464                 dns_rdataset_disassociate(&trdataset);
1465                 if (result == ISC_R_SUCCESS)
1466                         break;
1467                 validator_log(val, ISC_LOG_DEBUG(3),
1468                               "no RRSIG matching DLV key");
1469         }
1470         if (result == ISC_R_SUCCESS) {
1471                 val->event->rdataset->trust = dns_trust_secure;
1472                 val->event->sigrdataset->trust = dns_trust_secure;
1473                 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure");
1474                 return (result);
1475         } else if (result == ISC_R_NOMORE && !supported_algorithm) {
1476                 if (val->mustbesecure) {
1477                         validator_log(val, ISC_LOG_WARNING,
1478                                       "must be secure failure");
1479                         return (DNS_R_MUSTBESECURE);
1480                 }
1481                 validator_log(val, ISC_LOG_DEBUG(3),
1482                               "no supported algorithm/digest (dlv)");
1483                 markanswer(val);
1484                 return (ISC_R_SUCCESS);
1485         } else
1486                 return (DNS_R_NOVALIDSIG);
1487 }
1488
1489 /*
1490  * Attempts positive response validation of an RRset containing zone keys.
1491  *
1492  * Returns:
1493  *      ISC_R_SUCCESS   Validation completed successfully
1494  *      DNS_R_WAIT      Validation has started but is waiting
1495  *                      for an event.
1496  *      Other return codes are possible and all indicate failure.
1497  */
1498 static isc_result_t
1499 validatezonekey(dns_validator_t *val) {
1500         isc_result_t result;
1501         dns_validatorevent_t *event;
1502         dns_rdataset_t trdataset;
1503         dns_rdata_t dsrdata = DNS_RDATA_INIT;
1504         dns_rdata_t newdsrdata = DNS_RDATA_INIT;
1505         dns_rdata_t keyrdata = DNS_RDATA_INIT;
1506         dns_rdata_t sigrdata = DNS_RDATA_INIT;
1507         unsigned char dsbuf[DNS_DS_BUFFERSIZE];
1508         dns_keytag_t keytag;
1509         dns_rdata_ds_t ds;
1510         dns_rdata_dnskey_t key;
1511         dns_rdata_rrsig_t sig;
1512         dst_key_t *dstkey;
1513         isc_boolean_t supported_algorithm;
1514
1515         /*
1516          * Caller must be holding the validator lock.
1517          */
1518
1519         event = val->event;
1520
1521         if (val->havedlvsep && val->dlv.trust >= dns_trust_secure &&
1522             dns_name_equal(event->name, dns_fixedname_name(&val->dlvsep)))
1523                 return (dlv_validatezonekey(val));
1524
1525         if (val->dsset == NULL) {
1526                 /*
1527                  * First, see if this key was signed by a trusted key.
1528                  */
1529                 for (result = dns_rdataset_first(val->event->sigrdataset);
1530                      result == ISC_R_SUCCESS;
1531                      result = dns_rdataset_next(val->event->sigrdataset))
1532                 {
1533                         dns_keynode_t *keynode = NULL, *nextnode = NULL;
1534
1535                         dns_rdata_reset(&sigrdata);
1536                         dns_rdataset_current(val->event->sigrdataset,
1537                                              &sigrdata);
1538                         (void)dns_rdata_tostruct(&sigrdata, &sig, NULL);
1539                         result = dns_keytable_findkeynode(val->keytable,
1540                                                           val->event->name,
1541                                                           sig.algorithm,
1542                                                           sig.keyid,
1543                                                           &keynode);
1544                         while (result == ISC_R_SUCCESS) {
1545                                 dstkey = dns_keynode_key(keynode);
1546                                 result = verify(val, dstkey, &sigrdata);
1547                                 if (result == ISC_R_SUCCESS) {
1548                                         dns_keytable_detachkeynode(val->keytable,
1549                                                                    &keynode);
1550                                         break;
1551                                 }
1552                                 result = dns_keytable_findnextkeynode(
1553                                                                 val->keytable,
1554                                                                 keynode,
1555                                                                 &nextnode);
1556                                 dns_keytable_detachkeynode(val->keytable,
1557                                                            &keynode);
1558                                 keynode = nextnode;
1559                         }
1560                         if (result == ISC_R_SUCCESS) {
1561                                 event->rdataset->trust = dns_trust_secure;
1562                                 event->sigrdataset->trust = dns_trust_secure;
1563                                 validator_log(val, ISC_LOG_DEBUG(3),
1564                                               "signed by trusted key; "
1565                                               "marking as secure");
1566                                 return (result);
1567                         }
1568                 }
1569
1570                 /*
1571                  * If this is the root name and there was no trusted key,
1572                  * give up, since there's no DS at the root.
1573                  */
1574                 if (dns_name_equal(event->name, dns_rootname)) {
1575                         if ((val->attributes & VALATTR_TRIEDVERIFY) != 0)
1576                                 return (DNS_R_NOVALIDSIG);
1577                         else
1578                                 return (DNS_R_NOVALIDDS);
1579                 }
1580
1581                 /*
1582                  * Otherwise, try to find the DS record.
1583                  */
1584                 result = view_find(val, val->event->name, dns_rdatatype_ds);
1585                 if (result == ISC_R_SUCCESS) {
1586                         /*
1587                          * We have DS records.
1588                          */
1589                         val->dsset = &val->frdataset;
1590                         if (val->frdataset.trust == dns_trust_pending &&
1591                             dns_rdataset_isassociated(&val->fsigrdataset))
1592                         {
1593                                 result = create_validator(val,
1594                                                           val->event->name,
1595                                                           dns_rdatatype_ds,
1596                                                           &val->frdataset,
1597                                                           &val->fsigrdataset,
1598                                                           dsvalidated,
1599                                                           "validatezonekey");
1600                                 if (result != ISC_R_SUCCESS)
1601                                         return (result);
1602                                 return (DNS_R_WAIT);
1603                         } else if (val->frdataset.trust == dns_trust_pending) {
1604                                 /*
1605                                  * There should never be an unsigned DS.
1606                                  */
1607                                 dns_rdataset_disassociate(&val->frdataset);
1608                                 validator_log(val, ISC_LOG_DEBUG(2),
1609                                               "unsigned DS record");
1610                                 return (DNS_R_NOVALIDSIG);
1611                         } else
1612                                 result = ISC_R_SUCCESS;
1613                 } else if (result == ISC_R_NOTFOUND) {
1614                         /*
1615                          * We don't have the DS.  Find it.
1616                          */
1617                         result = create_fetch(val, val->event->name,
1618                                               dns_rdatatype_ds, dsfetched,
1619                                               "validatezonekey");
1620                         if (result != ISC_R_SUCCESS)
1621                                 return (result);
1622                         return (DNS_R_WAIT);
1623                  } else if (result ==  DNS_R_NCACHENXDOMAIN ||
1624                            result == DNS_R_NCACHENXRRSET ||
1625                            result == DNS_R_NXDOMAIN ||
1626                            result == DNS_R_NXRRSET)
1627                 {
1628                         /*
1629                          * The DS does not exist.
1630                          */
1631                         if (dns_rdataset_isassociated(&val->frdataset))
1632                                 dns_rdataset_disassociate(&val->frdataset);
1633                         if (dns_rdataset_isassociated(&val->fsigrdataset))
1634                                 dns_rdataset_disassociate(&val->fsigrdataset);
1635                         validator_log(val, ISC_LOG_DEBUG(2), "no DS record");
1636                         return (DNS_R_NOVALIDSIG);
1637                 }
1638         }
1639
1640         /*
1641          * We have a DS set.
1642          */
1643         INSIST(val->dsset != NULL);
1644
1645         if (val->dsset->trust < dns_trust_secure) {
1646                 if (val->mustbesecure) {
1647                         validator_log(val, ISC_LOG_WARNING,
1648                                       "must be secure failure");
1649                         return (DNS_R_MUSTBESECURE);
1650                 }
1651                 markanswer(val);
1652                 return (ISC_R_SUCCESS);
1653         }
1654
1655         /*
1656          * Look through the DS record and find the keys that can sign the
1657          * key set and the matching signature.  For each such key, attempt
1658          * verification.
1659          */
1660
1661         supported_algorithm = ISC_FALSE;
1662
1663         for (result = dns_rdataset_first(val->dsset);
1664              result == ISC_R_SUCCESS;
1665              result = dns_rdataset_next(val->dsset))
1666         {
1667                 dns_rdata_reset(&dsrdata);
1668                 dns_rdataset_current(val->dsset, &dsrdata);
1669                 (void)dns_rdata_tostruct(&dsrdata, &ds, NULL);
1670
1671                 if (ds.digest_type != DNS_DSDIGEST_SHA1)
1672                         continue;
1673                 if (!dns_resolver_algorithm_supported(val->view->resolver,
1674                                                       val->event->name,
1675                                                       ds.algorithm))
1676                         continue;
1677
1678                 supported_algorithm = ISC_TRUE;
1679
1680                 dns_rdataset_init(&trdataset);
1681                 dns_rdataset_clone(val->event->rdataset, &trdataset);
1682
1683                 for (result = dns_rdataset_first(&trdataset);
1684                      result == ISC_R_SUCCESS;
1685                      result = dns_rdataset_next(&trdataset))
1686                 {
1687                         dns_rdata_reset(&keyrdata);
1688                         dns_rdataset_current(&trdataset, &keyrdata);
1689                         (void)dns_rdata_tostruct(&keyrdata, &key, NULL);
1690                         keytag = compute_keytag(&keyrdata, &key);
1691                         if (ds.key_tag != keytag ||
1692                             ds.algorithm != key.algorithm)
1693                                 continue;
1694                         dns_rdata_reset(&newdsrdata);
1695                         result = dns_ds_buildrdata(val->event->name,
1696                                                    &keyrdata, ds.digest_type,
1697                                                    dsbuf, &newdsrdata);
1698                         if (result != ISC_R_SUCCESS)
1699                                 continue;
1700                         if (dns_rdata_compare(&dsrdata, &newdsrdata) == 0)
1701                                 break;
1702                 }
1703                 if (result != ISC_R_SUCCESS) {
1704                         validator_log(val, ISC_LOG_DEBUG(3),
1705                                       "no DNSKEY matching DS");
1706                         continue;
1707                 }
1708                 
1709                 for (result = dns_rdataset_first(val->event->sigrdataset);
1710                      result == ISC_R_SUCCESS;
1711                      result = dns_rdataset_next(val->event->sigrdataset))
1712                 {
1713                         dns_rdata_reset(&sigrdata);
1714                         dns_rdataset_current(val->event->sigrdataset,
1715                                              &sigrdata);
1716                         (void)dns_rdata_tostruct(&sigrdata, &sig, NULL);
1717                         if (ds.key_tag != sig.keyid &&
1718                             ds.algorithm != sig.algorithm)
1719                                 continue;
1720
1721                         dstkey = NULL;
1722                         result = dns_dnssec_keyfromrdata(val->event->name,
1723                                                          &keyrdata,
1724                                                          val->view->mctx,
1725                                                          &dstkey);
1726                         if (result != ISC_R_SUCCESS)
1727                                 /*
1728                                  * This really shouldn't happen, but...
1729                                  */
1730                                 continue;
1731
1732                         result = verify(val, dstkey, &sigrdata);
1733                         dst_key_free(&dstkey);
1734                         if (result == ISC_R_SUCCESS)
1735                                 break;
1736                 }
1737                 dns_rdataset_disassociate(&trdataset);
1738                 if (result == ISC_R_SUCCESS)
1739                         break;
1740                 validator_log(val, ISC_LOG_DEBUG(3),
1741                               "no RRSIG matching DS key");
1742         }
1743         if (result == ISC_R_SUCCESS) {
1744                 event->rdataset->trust = dns_trust_secure;
1745                 event->sigrdataset->trust = dns_trust_secure;
1746                 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure");
1747                 return (result);
1748         } else if (result == ISC_R_NOMORE && !supported_algorithm) {
1749                 if (val->mustbesecure) {
1750                         validator_log(val, ISC_LOG_WARNING,
1751                                       "must be secure failure");
1752                         return (DNS_R_MUSTBESECURE);
1753                 }
1754                 validator_log(val, ISC_LOG_DEBUG(3),
1755                               "no supported algorithm/digest (DS)");
1756                 markanswer(val);
1757                 return (ISC_R_SUCCESS);
1758         } else
1759                 return (DNS_R_NOVALIDSIG);
1760 }
1761
1762 /*
1763  * Starts a positive response validation.
1764  *
1765  * Returns:
1766  *      ISC_R_SUCCESS   Validation completed successfully
1767  *      DNS_R_WAIT      Validation has started but is waiting
1768  *                      for an event.
1769  *      Other return codes are possible and all indicate failure.
1770  */
1771 static isc_result_t
1772 start_positive_validation(dns_validator_t *val) {
1773         /*
1774          * If this is not a key, go straight into validate().
1775          */
1776         if (val->event->type != dns_rdatatype_dnskey || !isselfsigned(val))
1777                 return (validate(val, ISC_FALSE));
1778
1779         return (validatezonekey(val));
1780 }
1781
1782 static isc_result_t
1783 checkwildcard(dns_validator_t *val) {
1784         dns_name_t *name, *wild;
1785         dns_message_t *message = val->event->message;
1786         isc_result_t result;
1787         isc_boolean_t exists, data;
1788         char namebuf[DNS_NAME_FORMATSIZE];
1789
1790         wild = dns_fixedname_name(&val->wild);
1791         dns_name_format(wild, namebuf, sizeof(namebuf));
1792         validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf);
1793
1794         for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
1795              result == ISC_R_SUCCESS;
1796              result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
1797         {
1798                 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
1799
1800                 name = NULL;
1801                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
1802
1803                 for (rdataset = ISC_LIST_HEAD(name->list);
1804                      rdataset != NULL;
1805                      rdataset = ISC_LIST_NEXT(rdataset, link))
1806                 {
1807                         if (rdataset->type != dns_rdatatype_nsec)
1808                                 continue;
1809                         val->nsecset = rdataset;
1810
1811                         for (sigrdataset = ISC_LIST_HEAD(name->list);
1812                              sigrdataset != NULL;
1813                              sigrdataset = ISC_LIST_NEXT(sigrdataset, link))
1814                         {
1815                                 if (sigrdataset->type == dns_rdatatype_rrsig &&
1816                                     sigrdataset->covers == rdataset->type)
1817                                         break;
1818                         }
1819                         if (sigrdataset == NULL)
1820                                 continue;
1821
1822                         if (rdataset->trust != dns_trust_secure)
1823                                 continue;
1824
1825                         if (((val->attributes & VALATTR_NEEDNODATA) != 0 ||
1826                              (val->attributes & VALATTR_NEEDNOWILDCARD) != 0) &&
1827                             (val->attributes & VALATTR_FOUNDNODATA) == 0 &&
1828                             (val->attributes & VALATTR_FOUNDNOWILDCARD) == 0 &&
1829                             nsecnoexistnodata(val, wild, name, rdataset,
1830                                               &exists, &data, NULL)
1831                                                == ISC_R_SUCCESS)
1832                         {
1833                                 dns_name_t **proofs = val->event->proofs;
1834                                 if (exists && !data)
1835                                         val->attributes |= VALATTR_FOUNDNODATA;
1836                                 if (exists && !data && NEEDNODATA(val))
1837                                         proofs[DNS_VALIDATOR_NODATAPROOF] =
1838                                                          name;
1839                                 if (!exists)
1840                                         val->attributes |=
1841                                                  VALATTR_FOUNDNOWILDCARD;
1842                                 if (!exists && NEEDNOQNAME(val))
1843                                         proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
1844                                                          name;
1845                                 return (ISC_R_SUCCESS);
1846                         }
1847                 }
1848         }
1849         if (result == ISC_R_NOMORE)
1850                 result = ISC_R_SUCCESS;
1851         return (result);
1852 }
1853
1854 static isc_result_t
1855 nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
1856         dns_name_t *name;
1857         dns_message_t *message = val->event->message;
1858         isc_result_t result;
1859
1860         if (!resume)
1861                 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
1862         else {
1863                 result = ISC_R_SUCCESS;
1864                 validator_log(val, ISC_LOG_DEBUG(3), "resuming nsecvalidate");
1865         }
1866
1867         for (;
1868              result == ISC_R_SUCCESS;
1869              result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
1870         {
1871                 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
1872
1873                 name = NULL;
1874                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
1875                 if (resume) {
1876                         rdataset = ISC_LIST_NEXT(val->currentset, link);
1877                         val->currentset = NULL;
1878                         resume = ISC_FALSE;
1879                 } else
1880                         rdataset = ISC_LIST_HEAD(name->list);
1881
1882                 for (;
1883                      rdataset != NULL;
1884                      rdataset = ISC_LIST_NEXT(rdataset, link))
1885                 {
1886                         if (rdataset->type == dns_rdatatype_rrsig)
1887                                 continue;
1888
1889                         if (rdataset->type == dns_rdatatype_soa) {
1890                                 val->soaset = rdataset;
1891                                 val->soaname = name;
1892                         } else if (rdataset->type == dns_rdatatype_nsec)
1893                                 val->nsecset = rdataset;
1894
1895                         for (sigrdataset = ISC_LIST_HEAD(name->list);
1896                              sigrdataset != NULL;
1897                              sigrdataset = ISC_LIST_NEXT(sigrdataset,
1898                                                          link))
1899                         {
1900                                 if (sigrdataset->type == dns_rdatatype_rrsig &&
1901                                     sigrdataset->covers == rdataset->type)
1902                                         break;
1903                         }
1904                         if (sigrdataset == NULL)
1905                                 continue;
1906                         /*
1907                          * If a signed zone is missing the zone key, bad
1908                          * things could happen.  A query for data in the zone
1909                          * would lead to a query for the zone key, which
1910                          * would return a negative answer, which would contain
1911                          * an SOA and an NSEC signed by the missing key, which
1912                          * would trigger another query for the DNSKEY (since
1913                          * the first one is still in progress), and go into an
1914                          * infinite loop.  Avoid that.
1915                          */
1916                         if (val->event->type == dns_rdatatype_dnskey &&
1917                             dns_name_equal(name, val->event->name))
1918                         {
1919                                 dns_rdata_t nsec = DNS_RDATA_INIT;
1920
1921                                 if (rdataset->type != dns_rdatatype_nsec)
1922                                         continue;
1923
1924                                 result = dns_rdataset_first(rdataset);
1925                                 if (result != ISC_R_SUCCESS)
1926                                         return (result);
1927                                 dns_rdataset_current(rdataset, &nsec);
1928                                 if (dns_nsec_typepresent(&nsec,
1929                                                         dns_rdatatype_soa))
1930                                         continue;
1931                         }
1932                         val->currentset = rdataset;
1933                         result = create_validator(val, name, rdataset->type,
1934                                                   rdataset, sigrdataset,
1935                                                   authvalidated,
1936                                                   "nsecvalidate");
1937                         if (result != ISC_R_SUCCESS)
1938                                 return (result);
1939                         return (DNS_R_WAIT);
1940
1941                 }
1942         }
1943         if (result == ISC_R_NOMORE)
1944                 result = ISC_R_SUCCESS;
1945         if (result != ISC_R_SUCCESS)
1946                 return (result);
1947
1948         /*
1949          * Do we only need to check for NOQNAME?
1950          */
1951         if ((val->attributes & VALATTR_NEEDNODATA) == 0 &&
1952             (val->attributes & VALATTR_NEEDNOWILDCARD) == 0 &&
1953             (val->attributes & VALATTR_NEEDNOQNAME) != 0) {
1954                 if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0) {
1955                         validator_log(val, ISC_LOG_DEBUG(3),
1956                                       "noqname proof found");
1957                         validator_log(val, ISC_LOG_DEBUG(3),
1958                                       "marking as secure");
1959                         val->event->rdataset->trust = dns_trust_secure;
1960                         val->event->sigrdataset->trust = dns_trust_secure;
1961                         return (ISC_R_SUCCESS);
1962                 }
1963                 validator_log(val, ISC_LOG_DEBUG(3),
1964                               "noqname proof not found");
1965                 return (DNS_R_NOVALIDNSEC);
1966         }
1967
1968         /*
1969          * Do we need to check for the wildcard?
1970          */
1971         if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
1972             (((val->attributes & VALATTR_NEEDNODATA) != 0 &&
1973               (val->attributes & VALATTR_FOUNDNODATA) == 0) ||
1974              (val->attributes & VALATTR_NEEDNOWILDCARD) != 0)) {
1975                 result = checkwildcard(val);
1976                 if (result != ISC_R_SUCCESS)
1977                         return (result);
1978         }
1979
1980         if (((val->attributes & VALATTR_NEEDNODATA) != 0 &&
1981              (val->attributes & VALATTR_FOUNDNODATA) != 0) ||
1982             ((val->attributes & VALATTR_NEEDNOQNAME) != 0 &&
1983              (val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
1984              (val->attributes & VALATTR_NEEDNOWILDCARD) != 0 &&
1985              (val->attributes & VALATTR_FOUNDNOWILDCARD) != 0))
1986                 val->attributes |= VALATTR_FOUNDNONEXISTENCE;
1987
1988         if ((val->attributes & VALATTR_FOUNDNONEXISTENCE) == 0) {
1989                 if (!val->seensig && val->soaset != NULL) {
1990                         result = create_validator(val, val->soaname,
1991                                                   dns_rdatatype_soa,
1992                                                   val->soaset, NULL,
1993                                                   negauthvalidated,
1994                                                   "nsecvalidate");
1995                         if (result != ISC_R_SUCCESS)
1996                                 return (result);
1997                         return (DNS_R_WAIT);
1998                 }
1999                 validator_log(val, ISC_LOG_DEBUG(3),
2000                               "nonexistence proof not found");
2001                 return (DNS_R_NOVALIDNSEC);
2002         } else {
2003                 validator_log(val, ISC_LOG_DEBUG(3),
2004                               "nonexistence proof found");
2005                 return (ISC_R_SUCCESS);
2006         }
2007 }
2008
2009 static isc_boolean_t
2010 check_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) {
2011         dns_rdata_t dsrdata = DNS_RDATA_INIT;
2012         dns_rdata_ds_t ds;
2013         isc_result_t result;
2014
2015         for (result = dns_rdataset_first(rdataset);
2016              result == ISC_R_SUCCESS;
2017              result = dns_rdataset_next(rdataset)) {
2018                 dns_rdataset_current(rdataset, &dsrdata);
2019                 (void)dns_rdata_tostruct(&dsrdata, &ds, NULL);
2020
2021                 if (ds.digest_type == DNS_DSDIGEST_SHA1 &&
2022                     dns_resolver_algorithm_supported(val->view->resolver,
2023                                                      name, ds.algorithm)) {
2024                         dns_rdata_reset(&dsrdata);
2025                         return (ISC_TRUE);
2026                 }
2027                 dns_rdata_reset(&dsrdata);
2028         }
2029         return (ISC_FALSE);
2030 }
2031
2032 static void
2033 dlvfetched(isc_task_t *task, isc_event_t *event) {
2034         char namebuf[DNS_NAME_FORMATSIZE];
2035         dns_fetchevent_t *devent;
2036         dns_validator_t *val;
2037         isc_boolean_t want_destroy;
2038         isc_result_t eresult;
2039         isc_result_t result;
2040
2041         UNUSED(task);
2042         INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
2043         devent = (dns_fetchevent_t *)event;
2044         val = devent->ev_arg;
2045         eresult = devent->result;
2046
2047         /* Free resources which are not of interest. */
2048         if (devent->node != NULL)
2049                 dns_db_detachnode(devent->db, &devent->node);
2050         if (devent->db != NULL)
2051                 dns_db_detach(&devent->db);
2052         if (dns_rdataset_isassociated(&val->fsigrdataset))
2053                 dns_rdataset_disassociate(&val->fsigrdataset);
2054         isc_event_free(&event);
2055         dns_resolver_destroyfetch(&val->fetch);
2056
2057         INSIST(val->event != NULL);
2058         validator_log(val, ISC_LOG_DEBUG(3), "in dlvfetched: %s",
2059                       dns_result_totext(eresult));
2060
2061         LOCK(&val->lock);
2062         if (eresult == ISC_R_SUCCESS) {
2063                 dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
2064                                 sizeof(namebuf));
2065                 dns_rdataset_clone(&val->frdataset, &val->dlv);
2066                 val->havedlvsep = ISC_TRUE;
2067                 validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf);
2068                 result = dlv_validator_start(val);
2069                 if (result != DNS_R_WAIT)
2070                         validator_done(val, result);
2071         } else if (eresult == DNS_R_NXRRSET ||
2072                    eresult == DNS_R_NXDOMAIN ||
2073                    eresult == DNS_R_NCACHENXRRSET ||
2074                    eresult == DNS_R_NCACHENXDOMAIN) {
2075                    result = finddlvsep(val, ISC_TRUE);
2076                 if (result == ISC_R_SUCCESS) {
2077                         dns_name_format(dns_fixedname_name(&val->dlvsep),
2078                                         namebuf, sizeof(namebuf));
2079                         validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found",
2080                                       namebuf);
2081                         result = dlv_validator_start(val);
2082                         if (result != DNS_R_WAIT)
2083                                 validator_done(val, result);
2084                 } else if (result == ISC_R_NOTFOUND) {
2085                         validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
2086                         markanswer(val);
2087                         validator_done(val, ISC_R_SUCCESS);
2088                 } else {
2089                         validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
2090                                       dns_result_totext(result));
2091                         if (result != DNS_R_WAIT)
2092                                 validator_done(val, result);
2093                 }
2094         } else {
2095                 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
2096                               dns_result_totext(eresult));
2097         }
2098         want_destroy = exit_check(val);
2099         UNLOCK(&val->lock);
2100         if (want_destroy)
2101                 destroy(val);
2102 }
2103
2104 static isc_result_t
2105 startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) {
2106         char namebuf[DNS_NAME_FORMATSIZE];
2107         isc_result_t result;
2108
2109         INSIST(!DLVTRIED(val));
2110
2111         val->attributes |= VALATTR_DLVTRIED;
2112
2113         dns_name_format(unsecure, namebuf, sizeof(namebuf));
2114         validator_log(val, ISC_LOG_DEBUG(3),
2115                       "plain DNSSEC returns unsecure (%s): looking for DLV",
2116                       namebuf);
2117
2118         if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
2119                 validator_log(val, ISC_LOG_WARNING, "must be secure failure");
2120                 return (DNS_R_MUSTBESECURE);
2121         }
2122
2123         val->dlvlabels = dns_name_countlabels(unsecure) - 1;
2124         result = finddlvsep(val, ISC_FALSE);
2125         if (result == ISC_R_NOTFOUND) {
2126                 validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
2127                 markanswer(val);
2128                 return (ISC_R_SUCCESS);
2129         }
2130         if (result != ISC_R_SUCCESS) {
2131                 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
2132                               dns_result_totext(result));
2133                 return (result);
2134         }
2135         dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
2136                         sizeof(namebuf));
2137         validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf);
2138         return (dlv_validator_start(val));
2139 }
2140
2141 static isc_result_t
2142 finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
2143         char namebuf[DNS_NAME_FORMATSIZE];
2144         dns_fixedname_t dlvfixed;
2145         dns_name_t *dlvname;
2146         dns_name_t *dlvsep;
2147         dns_name_t noroot;
2148         isc_result_t result;
2149         unsigned int labels;
2150                 
2151         INSIST(val->view->dlv != NULL);
2152
2153         if (!resume) {
2154
2155                 if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
2156                         validator_log(val, ISC_LOG_WARNING,
2157                                       "must be secure failure");
2158                         return (DNS_R_MUSTBESECURE);
2159                 }
2160
2161                 dns_fixedname_init(&val->dlvsep);
2162                 dlvsep = dns_fixedname_name(&val->dlvsep);
2163                 dns_name_copy(val->event->name, dlvsep, NULL);
2164                 if (val->event->type == dns_rdatatype_ds) {
2165                         labels = dns_name_countlabels(dlvsep);
2166                         if (labels == 0)
2167                                 return (ISC_R_NOTFOUND);
2168                         dns_name_getlabelsequence(dlvsep, 1, labels - 1,
2169                                                   dlvsep);
2170                 }
2171         } else {
2172                 dlvsep = dns_fixedname_name(&val->dlvsep);
2173                 labels = dns_name_countlabels(dlvsep);
2174                 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
2175         }
2176         dns_name_init(&noroot, NULL);
2177         dns_fixedname_init(&dlvfixed);
2178         dlvname = dns_fixedname_name(&dlvfixed);
2179         labels = dns_name_countlabels(dlvsep);
2180         if (labels == 0)
2181                 return (ISC_R_NOTFOUND);
2182         dns_name_getlabelsequence(dlvsep, 0, labels - 1, &noroot);
2183         result = dns_name_concatenate(&noroot, val->view->dlv, dlvname, NULL);
2184         while (result == ISC_R_NOSPACE) {
2185                 labels = dns_name_countlabels(dlvsep);
2186                 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
2187                 dns_name_getlabelsequence(dlvsep, 0, labels - 2, &noroot);
2188                 result = dns_name_concatenate(&noroot, val->view->dlv,
2189                                               dlvname, NULL);
2190         }
2191         if (result != ISC_R_SUCCESS) {
2192                 validator_log(val, ISC_LOG_DEBUG(2), "DLV concatenate failed");
2193                 return (DNS_R_NOVALIDSIG);
2194         }
2195
2196         while (dns_name_countlabels(dlvname) >=
2197                dns_name_countlabels(val->view->dlv) + val->dlvlabels) {
2198                 dns_name_format(dlvname, namebuf, sizeof(namebuf));
2199                 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV %s",
2200                               namebuf);
2201                 result = view_find(val, dlvname, dns_rdatatype_dlv);
2202                 if (result == ISC_R_SUCCESS) {
2203                         if (val->frdataset.trust < dns_trust_secure)
2204                                 return (DNS_R_NOVALIDSIG);
2205                         val->havedlvsep = ISC_TRUE;
2206                         dns_rdataset_clone(&val->frdataset, &val->dlv);
2207                         return (ISC_R_SUCCESS);
2208                 }
2209                 if (result == ISC_R_NOTFOUND) {
2210                         result = create_fetch(val, dlvname, dns_rdatatype_dlv,
2211                                               dlvfetched, "finddlvsep");
2212                         if (result != ISC_R_SUCCESS)
2213                                 return (result);
2214                         return (DNS_R_WAIT);
2215                 }
2216                 if (result != DNS_R_NXRRSET &&
2217                     result != DNS_R_NXDOMAIN &&
2218                     result != DNS_R_NCACHENXRRSET &&
2219                     result != DNS_R_NCACHENXDOMAIN)
2220                         return (result);
2221                 /*
2222                  * Strip first labels from both dlvsep and dlvname.
2223                  */
2224                 labels = dns_name_countlabels(dlvsep);
2225                 if (labels == 0)
2226                         break;
2227                 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
2228                 labels = dns_name_countlabels(dlvname);
2229                 dns_name_getlabelsequence(dlvname, 1, labels - 1, dlvname);
2230         }
2231         return (ISC_R_NOTFOUND);
2232 }
2233
2234 /*
2235  * proveunsecure walks down from the SEP looking for a break in the
2236  * chain of trust.   That occurs when we can prove the DS record does
2237  * not exist at a delegation point or the DS exists at a delegation
2238  * but we don't support the algorithm/digest.
2239  */
2240 static isc_result_t
2241 proveunsecure(dns_validator_t *val, isc_boolean_t resume) {
2242         isc_result_t result;
2243         dns_fixedname_t fixedsecroot;
2244         dns_name_t *secroot;
2245         dns_name_t *tname;
2246         char namebuf[DNS_NAME_FORMATSIZE];
2247
2248         dns_fixedname_init(&fixedsecroot);
2249         secroot = dns_fixedname_name(&fixedsecroot);
2250         if (val->havedlvsep)
2251                 dns_name_copy(dns_fixedname_name(&val->dlvsep), secroot, NULL);
2252         else {
2253                 result = dns_keytable_finddeepestmatch(val->keytable,
2254                                                        val->event->name,
2255                                                        secroot);
2256
2257                 if (result == ISC_R_NOTFOUND) {
2258                         validator_log(val, ISC_LOG_DEBUG(3),
2259                                       "not beneath secure root");
2260                         if (val->mustbesecure) {
2261                                 validator_log(val, ISC_LOG_WARNING,
2262                                               "must be secure failure");
2263                                 result = DNS_R_MUSTBESECURE;
2264                                 goto out;
2265                         }
2266                         if (val->view->dlv == NULL || DLVTRIED(val)) {
2267                                 markanswer(val);
2268                                 return (ISC_R_SUCCESS);
2269                         }
2270                         return (startfinddlvsep(val, dns_rootname));
2271                 } else if (result != ISC_R_SUCCESS)
2272                         return (result);
2273         }
2274
2275         if (!resume) {
2276                 /*
2277                  * We are looking for breaks below the SEP so add a label.
2278                  */
2279                 val->labels = dns_name_countlabels(secroot) + 1;
2280         } else {
2281                 validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
2282                 if (val->frdataset.trust >= dns_trust_secure &&
2283                     !check_ds(val, dns_fixedname_name(&val->fname),
2284                               &val->frdataset)) {
2285                         dns_name_format(dns_fixedname_name(&val->fname),
2286                                         namebuf, sizeof(namebuf));
2287                         if (val->mustbesecure) {
2288                                 validator_log(val, ISC_LOG_WARNING,
2289                                               "must be secure failure at '%s'",
2290                                               namebuf);
2291                                 result = DNS_R_MUSTBESECURE;
2292                                 goto out;
2293                         }
2294                         validator_log(val, ISC_LOG_DEBUG(3),
2295                                       "no supported algorithm/digest (%s/DS)",
2296                                       namebuf);
2297                         if (val->view->dlv == NULL || DLVTRIED(val)) {
2298                                 markanswer(val);
2299                                 result = ISC_R_SUCCESS;
2300                                 goto out;
2301                         }
2302                         result = startfinddlvsep(val,
2303                                               dns_fixedname_name(&val->fname));
2304                         goto out;
2305                 }
2306                 val->labels++;
2307         }
2308
2309         for (;
2310              val->labels <= dns_name_countlabels(val->event->name);
2311              val->labels++)
2312         {
2313
2314                 dns_fixedname_init(&val->fname);
2315                 tname = dns_fixedname_name(&val->fname);
2316                 if (val->labels == dns_name_countlabels(val->event->name))
2317                         dns_name_copy(val->event->name, tname, NULL);
2318                 else
2319                         dns_name_split(val->event->name, val->labels,
2320                                        NULL, tname);
2321
2322                 dns_name_format(tname, namebuf, sizeof(namebuf));
2323                 validator_log(val, ISC_LOG_DEBUG(3),
2324                               "checking existence of DS at '%s'",
2325                               namebuf);
2326
2327                 result = view_find(val, tname, dns_rdatatype_ds);
2328                 if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
2329                         /*
2330                          * There is no DS.  If this is a delegation,
2331                          * we maybe done.
2332                          */
2333                         if (val->frdataset.trust < dns_trust_secure) {
2334                                 /*
2335                                  * This shouldn't happen, since the negative
2336                                  * response should have been validated.  Since
2337                                  * there's no way of validating existing
2338                                  * negative response blobs, give up.
2339                                  */
2340                                 result = DNS_R_NOVALIDSIG;
2341                                 goto out;
2342                         }
2343                         if (isdelegation(tname, &val->frdataset, result)) {
2344                                 if (val->mustbesecure) {
2345                                         validator_log(val, ISC_LOG_WARNING,
2346                                                       "must be secure failure");
2347                                         return (DNS_R_MUSTBESECURE);
2348                                 }
2349                                 if (val->view->dlv == NULL || DLVTRIED(val)) {
2350                                         markanswer(val);
2351                                         return (ISC_R_SUCCESS);
2352                                 }
2353                                 return (startfinddlvsep(val, tname));
2354                         }
2355                         continue;
2356                 } else if (result == ISC_R_SUCCESS) {
2357                         /*
2358                          * There is a DS here.  Verify that it's secure and
2359                          * continue.
2360                          */
2361                         if (val->frdataset.trust >= dns_trust_secure) {
2362                                 if (!check_ds(val, tname, &val->frdataset)) {
2363                                         validator_log(val, ISC_LOG_DEBUG(3),
2364                                                      "no supported algorithm/"
2365                                                      "digest (%s/DS)", namebuf);
2366                                         if (val->mustbesecure) {
2367                                                 validator_log(val,
2368                                                               ISC_LOG_WARNING,
2369                                                       "must be secure failure");
2370                                                 result = DNS_R_MUSTBESECURE;
2371                                                 goto out;
2372                                         }
2373                                         if (val->view->dlv == NULL ||
2374                                             DLVTRIED(val)) {
2375                                                 markanswer(val);
2376                                                 result = ISC_R_SUCCESS;
2377                                                 goto out;
2378                                         }
2379                                         result = startfinddlvsep(val, tname);
2380                                         goto out;
2381                                 }
2382                                 continue;
2383                         }
2384                         else if (!dns_rdataset_isassociated(&val->fsigrdataset))
2385                         {
2386                                 result = DNS_R_NOVALIDSIG;
2387                                 goto out;
2388                         }
2389                         result = create_validator(val, tname, dns_rdatatype_ds,
2390                                                   &val->frdataset,
2391                                                   &val->fsigrdataset,
2392                                                   dsvalidated,
2393                                                   "proveunsecure");
2394                         if (result != ISC_R_SUCCESS)
2395                                 goto out;
2396                         return (DNS_R_WAIT);
2397                 } else if (result == DNS_R_NXDOMAIN ||
2398                            result == DNS_R_NCACHENXDOMAIN)
2399                 {
2400                         /*
2401                          * This is not a zone cut.  Assuming things are
2402                          * as expected, continue.
2403                          */
2404                         if (!dns_rdataset_isassociated(&val->frdataset)) {
2405                                 /*
2406                                  * There should be an NSEC here, since we
2407                                  * are still in a secure zone.
2408                                  */
2409                                 result = DNS_R_NOVALIDNSEC;
2410                                 goto out;
2411                         } else if (val->frdataset.trust < dns_trust_secure) {
2412                                 /*
2413                                  * This shouldn't happen, since the negative
2414                                  * response should have been validated.  Since
2415                                  * there's no way of validating existing
2416                                  * negative response blobs, give up.
2417                                  */
2418                                 result = DNS_R_NOVALIDSIG;
2419                                 goto out;
2420                         }
2421                         continue;
2422                 } else if (result == ISC_R_NOTFOUND) {
2423                         /*
2424                          * We don't know anything about the DS.  Find it.
2425                          */
2426                         result = create_fetch(val, tname, dns_rdatatype_ds,
2427                                               dsfetched2, "proveunsecure");
2428                         if (result != ISC_R_SUCCESS)
2429                                 goto out;
2430                         return (DNS_R_WAIT);
2431                 }
2432         }
2433         validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed");
2434         return (DNS_R_NOTINSECURE); /* Couldn't complete insecurity proof */
2435
2436  out:
2437         if (dns_rdataset_isassociated(&val->frdataset))
2438                 dns_rdataset_disassociate(&val->frdataset);
2439         if (dns_rdataset_isassociated(&val->fsigrdataset))
2440                 dns_rdataset_disassociate(&val->fsigrdataset);
2441         return (result);
2442 }
2443
2444 static isc_result_t
2445 dlv_validator_start(dns_validator_t *val) {
2446         isc_event_t *event;
2447
2448         validator_log(val, ISC_LOG_DEBUG(3), "dlv_validator_start");
2449
2450         /*
2451          * Reset state and try again.
2452          */
2453         val->attributes &= VALATTR_DLVTRIED;
2454         val->options &= ~DNS_VALIDATOR_DLV;
2455
2456         event = (isc_event_t *)val->event;
2457         isc_task_send(val->task, &event);
2458         return (DNS_R_WAIT);
2459 }
2460
2461 static void
2462 validator_start(isc_task_t *task, isc_event_t *event) {
2463         dns_validator_t *val;
2464         dns_validatorevent_t *vevent;
2465         isc_boolean_t want_destroy = ISC_FALSE;
2466         isc_result_t result = ISC_R_FAILURE;
2467
2468         UNUSED(task);
2469         REQUIRE(event->ev_type == DNS_EVENT_VALIDATORSTART);
2470         vevent = (dns_validatorevent_t *)event;
2471         val = vevent->validator;
2472
2473         /* If the validator has been cancelled, val->event == NULL */
2474         if (val->event == NULL)
2475                 return;
2476
2477         if (DLVTRIED(val))
2478                 validator_log(val, ISC_LOG_DEBUG(3), "restarting using DLV");
2479         else
2480                 validator_log(val, ISC_LOG_DEBUG(3), "starting");
2481
2482         LOCK(&val->lock);
2483
2484         if ((val->options & DNS_VALIDATOR_DLV) != 0) {
2485                 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV");
2486                 result = startfinddlvsep(val, dns_rootname);
2487         } else if (val->event->rdataset != NULL &&
2488                    val->event->sigrdataset != NULL) {
2489                 isc_result_t saved_result;
2490
2491                 /*
2492                  * This looks like a simple validation.  We say "looks like"
2493                  * because it might end up requiring an insecurity proof.
2494                  */
2495                 validator_log(val, ISC_LOG_DEBUG(3),
2496                               "attempting positive response validation");
2497
2498                 INSIST(dns_rdataset_isassociated(val->event->rdataset));
2499                 INSIST(dns_rdataset_isassociated(val->event->sigrdataset));
2500                 result = start_positive_validation(val);
2501                 if (result == DNS_R_NOVALIDSIG &&
2502                     (val->attributes & VALATTR_TRIEDVERIFY) == 0)
2503                 {
2504                         saved_result = result;
2505                         validator_log(val, ISC_LOG_DEBUG(3),
2506                                       "falling back to insecurity proof");
2507                         val->attributes |= VALATTR_INSECURITY;
2508                         result = proveunsecure(val, ISC_FALSE);
2509                         if (result == DNS_R_NOTINSECURE)
2510                                 result = saved_result;
2511                 }
2512         } else if (val->event->rdataset != NULL) {
2513                 /*
2514                  * This is either an unsecure subdomain or a response from
2515                  * a broken server.
2516                  */
2517                 INSIST(dns_rdataset_isassociated(val->event->rdataset));
2518                 validator_log(val, ISC_LOG_DEBUG(3),
2519                               "attempting insecurity proof");
2520
2521                 val->attributes |= VALATTR_INSECURITY;
2522                 result = proveunsecure(val, ISC_FALSE);
2523         } else if (val->event->rdataset == NULL &&
2524                    val->event->sigrdataset == NULL)
2525         {
2526                 /*
2527                  * This is a nonexistence validation.
2528                  */
2529                 validator_log(val, ISC_LOG_DEBUG(3),
2530                               "attempting negative response validation");
2531
2532                 val->attributes |= VALATTR_NEGATIVE;
2533                 if (val->event->message->rcode == dns_rcode_nxdomain) {
2534                         val->attributes |= VALATTR_NEEDNOQNAME;
2535                         val->attributes |= VALATTR_NEEDNOWILDCARD;
2536                 } else
2537                         val->attributes |= VALATTR_NEEDNODATA;
2538                 result = nsecvalidate(val, ISC_FALSE);
2539         } else {
2540                 /*
2541                  * This shouldn't happen.
2542                  */
2543                 INSIST(0);
2544         }
2545
2546         if (result != DNS_R_WAIT) {
2547                 want_destroy = exit_check(val);
2548                 validator_done(val, result);
2549         }
2550
2551         UNLOCK(&val->lock);
2552         if (want_destroy)
2553                 destroy(val);
2554 }
2555
2556 isc_result_t
2557 dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
2558                      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
2559                      dns_message_t *message, unsigned int options,
2560                      isc_task_t *task, isc_taskaction_t action, void *arg,
2561                      dns_validator_t **validatorp)
2562 {
2563         isc_result_t result;
2564         dns_validator_t *val;
2565         isc_task_t *tclone;
2566         dns_validatorevent_t *event;
2567
2568         REQUIRE(name != NULL);
2569         REQUIRE(type != 0);
2570         REQUIRE(rdataset != NULL ||
2571                 (rdataset == NULL && sigrdataset == NULL && message != NULL));
2572         REQUIRE(validatorp != NULL && *validatorp == NULL);
2573
2574         tclone = NULL;
2575         result = ISC_R_FAILURE;
2576
2577         val = isc_mem_get(view->mctx, sizeof(*val));
2578         if (val == NULL)
2579                 return (ISC_R_NOMEMORY);
2580         val->view = NULL;
2581         dns_view_weakattach(view, &val->view);
2582         event = (dns_validatorevent_t *)
2583                 isc_event_allocate(view->mctx, task,
2584                                    DNS_EVENT_VALIDATORSTART,
2585                                    validator_start, NULL,
2586                                    sizeof(dns_validatorevent_t));
2587         if (event == NULL) {
2588                 result = ISC_R_NOMEMORY;
2589                 goto cleanup_val;
2590         }
2591         isc_task_attach(task, &tclone);
2592         event->validator = val;
2593         event->result = ISC_R_FAILURE;
2594         event->name = name;
2595         event->type = type;
2596         event->rdataset = rdataset;
2597         event->sigrdataset = sigrdataset;
2598         event->message = message;
2599         memset(event->proofs, 0, sizeof(event->proofs));
2600         result = isc_mutex_init(&val->lock);
2601         if (result != ISC_R_SUCCESS)
2602                 goto cleanup_event;
2603         val->event = event;
2604         val->options = options;
2605         val->attributes = 0;
2606         val->fetch = NULL;
2607         val->subvalidator = NULL;
2608         val->parent = NULL;
2609         val->keytable = NULL;
2610         dns_keytable_attach(val->view->secroots, &val->keytable);
2611         val->keynode = NULL;
2612         val->key = NULL;
2613         val->siginfo = NULL;
2614         val->task = task;
2615         val->action = action;
2616         val->arg = arg;
2617         val->labels = 0;
2618         val->currentset = NULL;
2619         val->keyset = NULL;
2620         val->dsset = NULL;
2621         dns_rdataset_init(&val->dlv);
2622         val->soaset = NULL;
2623         val->nsecset = NULL;
2624         val->soaname = NULL;
2625         val->seensig = ISC_FALSE;
2626         val->havedlvsep = ISC_FALSE;
2627         val->depth = 0;
2628         val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
2629         dns_rdataset_init(&val->frdataset);
2630         dns_rdataset_init(&val->fsigrdataset);
2631         dns_fixedname_init(&val->wild);
2632         ISC_LINK_INIT(val, link);
2633         val->magic = VALIDATOR_MAGIC;
2634
2635         isc_task_send(task, ISC_EVENT_PTR(&event));
2636
2637         *validatorp = val;
2638
2639         return (ISC_R_SUCCESS);
2640
2641  cleanup_event:
2642         isc_task_detach(&tclone);
2643         isc_event_free((isc_event_t **)&val->event);
2644
2645  cleanup_val:
2646         dns_view_weakdetach(&val->view);
2647         isc_mem_put(view->mctx, val, sizeof(*val));
2648
2649         return (result);
2650 }
2651
2652 void
2653 dns_validator_cancel(dns_validator_t *validator) {
2654         REQUIRE(VALID_VALIDATOR(validator));
2655
2656         LOCK(&validator->lock);
2657
2658         validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
2659
2660         if (validator->event != NULL) {
2661                 if (validator->fetch != NULL)
2662                         dns_resolver_cancelfetch(validator->fetch);
2663
2664                 if (validator->subvalidator != NULL)
2665                         dns_validator_cancel(validator->subvalidator);
2666         }
2667         UNLOCK(&validator->lock);
2668 }
2669
2670 static void
2671 destroy(dns_validator_t *val) {
2672         isc_mem_t *mctx;
2673
2674         REQUIRE(SHUTDOWN(val));
2675         REQUIRE(val->event == NULL);
2676         REQUIRE(val->fetch == NULL);
2677
2678         if (val->keynode != NULL)
2679                 dns_keytable_detachkeynode(val->keytable, &val->keynode);
2680         else if (val->key != NULL)
2681                 dst_key_free(&val->key);
2682         if (val->keytable != NULL)
2683                 dns_keytable_detach(&val->keytable);
2684         if (val->subvalidator != NULL)
2685                 dns_validator_destroy(&val->subvalidator);
2686         if (val->havedlvsep)
2687                 dns_rdataset_disassociate(&val->dlv);
2688         if (dns_rdataset_isassociated(&val->frdataset))
2689                 dns_rdataset_disassociate(&val->frdataset);
2690         if (dns_rdataset_isassociated(&val->fsigrdataset))
2691                 dns_rdataset_disassociate(&val->fsigrdataset);
2692         mctx = val->view->mctx;
2693         if (val->siginfo != NULL)
2694                 isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo));
2695         DESTROYLOCK(&val->lock);
2696         dns_view_weakdetach(&val->view);
2697         val->magic = 0;
2698         isc_mem_put(mctx, val, sizeof(*val));
2699 }
2700
2701 void
2702 dns_validator_destroy(dns_validator_t **validatorp) {
2703         dns_validator_t *val;
2704         isc_boolean_t want_destroy = ISC_FALSE;
2705
2706         REQUIRE(validatorp != NULL);
2707         val = *validatorp;
2708         REQUIRE(VALID_VALIDATOR(val));
2709
2710         LOCK(&val->lock);
2711
2712         val->attributes |= VALATTR_SHUTDOWN;
2713         validator_log(val, ISC_LOG_DEBUG(3), "dns_validator_destroy");
2714
2715         want_destroy = exit_check(val);
2716
2717         UNLOCK(&val->lock);
2718
2719         if (want_destroy)
2720                 destroy(val);
2721
2722         *validatorp = NULL;
2723 }
2724
2725 static void
2726 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
2727                isc_logmodule_t *module, int level, const char *fmt, va_list ap)
2728 {
2729         char msgbuf[2048];
2730         static const char spaces[] = "        *";
2731         int depth = val->depth * 2;
2732
2733         vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
2734
2735         if ((unsigned int) depth >= sizeof spaces)
2736                 depth = sizeof spaces - 1;
2737
2738         if (val->event != NULL && val->event->name != NULL) {
2739                 char namebuf[DNS_NAME_FORMATSIZE];
2740                 char typebuf[DNS_RDATATYPE_FORMATSIZE];
2741
2742                 dns_name_format(val->event->name, namebuf, sizeof(namebuf));
2743                 dns_rdatatype_format(val->event->type, typebuf,
2744                                      sizeof(typebuf));
2745                 isc_log_write(dns_lctx, category, module, level,
2746                               "%.*svalidating @%p: %s %s: %s", depth, spaces,
2747                               val, namebuf, typebuf, msgbuf);
2748         } else {
2749                 isc_log_write(dns_lctx, category, module, level,
2750                               "%.*svalidator @%p: %s", depth, spaces,
2751                                val, msgbuf);
2752         }
2753 }
2754
2755 static void
2756 validator_log(dns_validator_t *val, int level, const char *fmt, ...) {
2757         va_list ap;
2758
2759         if (! isc_log_wouldlog(dns_lctx, level))
2760                 return;
2761
2762         va_start(ap, fmt);
2763
2764         validator_logv(val, DNS_LOGCATEGORY_DNSSEC,
2765                        DNS_LOGMODULE_VALIDATOR, level, fmt, ap);
2766         va_end(ap);
2767 }
2768
2769 static void
2770 validator_logcreate(dns_validator_t *val,
2771                     dns_name_t *name, dns_rdatatype_t type,
2772                     const char *caller, const char *operation)
2773 {
2774         char namestr[DNS_NAME_FORMATSIZE];
2775         char typestr[DNS_RDATATYPE_FORMATSIZE];
2776
2777         dns_name_format(name, namestr, sizeof(namestr));
2778         dns_rdatatype_format(type, typestr, sizeof(typestr));
2779         validator_log(val, ISC_LOG_DEBUG(9), "%s: creating %s for %s %s",
2780                       caller, operation, namestr, typestr);
2781 }