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