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