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