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