]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - contrib/bind9/lib/dns/validator.c
Update to BIND 9.6.3, the latest from ISC on the 9.6 branch.
[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.23 2010-11-16 02:23:44 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                 /*
2223                  * We have a dlv sep.  Skip looking up the SEP from
2224                  * {trusted,managed}-keys.  If the dlv sep is for the
2225                  * root then it will have been handled above so we don't
2226                  * need to check whether val->event->name is "." prior to
2227                  * looking up the DS.
2228                  */
2229                 if (val->havedlvsep)
2230                         goto find_ds;
2231
2232                 /*
2233                  * First, see if this key was signed by a trusted key.
2234                  */
2235                 for (result = dns_rdataset_first(val->event->sigrdataset);
2236                      result == ISC_R_SUCCESS;
2237                      result = dns_rdataset_next(val->event->sigrdataset))
2238                 {
2239                         dns_keynode_t *keynode = NULL;
2240                         dns_fixedname_t fixed;
2241                         dns_name_t *found;
2242
2243                         dns_fixedname_init(&fixed);
2244                         found = dns_fixedname_name(&fixed);
2245                         dns_rdata_reset(&sigrdata);
2246                         dns_rdataset_current(val->event->sigrdataset,
2247                                              &sigrdata);
2248                         result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
2249                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2250
2251                         if (!dns_name_equal(val->event->name, &sig.signer))
2252                                 continue;
2253
2254                         result = dns_keytable_findkeynode(val->keytable,
2255                                                           val->event->name,
2256                                                           sig.algorithm,
2257                                                           sig.keyid,
2258                                                           &keynode);
2259                         if (result == ISC_R_NOTFOUND &&
2260                             dns_keytable_finddeepestmatch(val->keytable,
2261                                   val->event->name, found) != ISC_R_SUCCESS) {
2262                                 if (val->mustbesecure) {
2263                                         validator_log(val, ISC_LOG_WARNING,
2264                                                      "must be secure failure, "
2265                                                      "not beneath secure root");
2266                                         return (DNS_R_MUSTBESECURE);
2267                                 } else
2268                                         validator_log(val, ISC_LOG_DEBUG(3),
2269                                                      "not beneath secure root");
2270                                 if (val->view->dlv == NULL) {
2271                                         markanswer(val, "validatezonekey (1)");
2272                                         return (ISC_R_SUCCESS);
2273                                 }
2274                                 return (startfinddlvsep(val, dns_rootname));
2275                         }
2276                         if (result == DNS_R_PARTIALMATCH ||
2277                             result == ISC_R_SUCCESS)
2278                                 atsep = ISC_TRUE;
2279                         while (result == ISC_R_SUCCESS) {
2280                                 dns_keynode_t *nextnode = NULL;
2281                                 dstkey = dns_keynode_key(keynode);
2282                                 result = verify(val, dstkey, &sigrdata,
2283                                                 sig.keyid);
2284                                 if (result == ISC_R_SUCCESS) {
2285                                         dns_keytable_detachkeynode(val->keytable,
2286                                                                    &keynode);
2287                                         break;
2288                                 }
2289                                 result = dns_keytable_findnextkeynode(
2290                                                                 val->keytable,
2291                                                                 keynode,
2292                                                                 &nextnode);
2293                                 dns_keytable_detachkeynode(val->keytable,
2294                                                            &keynode);
2295                                 keynode = nextnode;
2296                         }
2297                         if (result == ISC_R_SUCCESS) {
2298                                 marksecure(event);
2299                                 validator_log(val, ISC_LOG_DEBUG(3),
2300                                               "signed by trusted key; "
2301                                               "marking as secure");
2302                                 return (result);
2303                         }
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                  * If this is the root name and there was no trusted key,
2327                  * give up, since there's no DS at the root.
2328                  */
2329                 if (dns_name_equal(event->name, dns_rootname)) {
2330                         if ((val->attributes & VALATTR_TRIEDVERIFY) != 0) {
2331                                 validator_log(val, ISC_LOG_DEBUG(3),
2332                                               "root key failed to validate");
2333                                 return (DNS_R_NOVALIDSIG);
2334                         } else {
2335                                 validator_log(val, ISC_LOG_DEBUG(3),
2336                                               "no trusted root key");
2337                                 return (DNS_R_NOVALIDDS);
2338                         }
2339                 }
2340  find_ds:
2341                 /*
2342                  * Otherwise, try to find the DS record.
2343                  */
2344                 result = view_find(val, val->event->name, dns_rdatatype_ds);
2345                 if (result == ISC_R_SUCCESS) {
2346                         /*
2347                          * We have DS records.
2348                          */
2349                         val->dsset = &val->frdataset;
2350                         if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
2351                              DNS_TRUST_ANSWER(val->frdataset.trust)) &&
2352                             dns_rdataset_isassociated(&val->fsigrdataset))
2353                         {
2354                                 result = create_validator(val,
2355                                                           val->event->name,
2356                                                           dns_rdatatype_ds,
2357                                                           &val->frdataset,
2358                                                           &val->fsigrdataset,
2359                                                           dsvalidated,
2360                                                           "validatezonekey");
2361                                 if (result != ISC_R_SUCCESS)
2362                                         return (result);
2363                                 return (DNS_R_WAIT);
2364                         } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
2365                                 /*
2366                                  * There should never be an unsigned DS.
2367                                  */
2368                                 dns_rdataset_disassociate(&val->frdataset);
2369                                 validator_log(val, ISC_LOG_DEBUG(2),
2370                                               "unsigned DS record");
2371                                 return (DNS_R_NOVALIDSIG);
2372                         } else
2373                                 result = ISC_R_SUCCESS;
2374                 } else if (result == ISC_R_NOTFOUND) {
2375                         /*
2376                          * We don't have the DS.  Find it.
2377                          */
2378                         result = create_fetch(val, val->event->name,
2379                                               dns_rdatatype_ds, dsfetched,
2380                                               "validatezonekey");
2381                         if (result != ISC_R_SUCCESS)
2382                                 return (result);
2383                         return (DNS_R_WAIT);
2384                 } else if (result ==  DNS_R_NCACHENXDOMAIN ||
2385                            result == DNS_R_NCACHENXRRSET ||
2386                            result == DNS_R_EMPTYNAME ||
2387                            result == DNS_R_NXDOMAIN ||
2388                            result == DNS_R_NXRRSET)
2389                 {
2390                         /*
2391                          * The DS does not exist.
2392                          */
2393                         if (dns_rdataset_isassociated(&val->frdataset))
2394                                 dns_rdataset_disassociate(&val->frdataset);
2395                         if (dns_rdataset_isassociated(&val->fsigrdataset))
2396                                 dns_rdataset_disassociate(&val->fsigrdataset);
2397                         validator_log(val, ISC_LOG_DEBUG(2), "no DS record");
2398                         return (DNS_R_NOVALIDSIG);
2399                 } else if (result == DNS_R_BROKENCHAIN)
2400                         return (result);
2401         }
2402
2403         /*
2404          * We have a DS set.
2405          */
2406         INSIST(val->dsset != NULL);
2407
2408         if (val->dsset->trust < dns_trust_secure) {
2409                 if (val->mustbesecure) {
2410                         validator_log(val, ISC_LOG_WARNING,
2411                                       "must be secure failure");
2412                         return (DNS_R_MUSTBESECURE);
2413                 }
2414                 markanswer(val, "validatezonekey (2)");
2415                 return (ISC_R_SUCCESS);
2416         }
2417
2418         /*
2419          * Look through the DS record and find the keys that can sign the
2420          * key set and the matching signature.  For each such key, attempt
2421          * verification.
2422          */
2423
2424         supported_algorithm = ISC_FALSE;
2425
2426         /*
2427          * If DNS_DSDIGEST_SHA256 is present we are required to prefer
2428          * it over DNS_DSDIGEST_SHA1.  This in practice means that we
2429          * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
2430          * is present.
2431          */
2432         digest_type = DNS_DSDIGEST_SHA1;
2433         for (result = dns_rdataset_first(val->dsset);
2434              result == ISC_R_SUCCESS;
2435              result = dns_rdataset_next(val->dsset)) {
2436                 dns_rdata_reset(&dsrdata);
2437                 dns_rdataset_current(val->dsset, &dsrdata);
2438                 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
2439                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2440
2441                 if (!dns_resolver_algorithm_supported(val->view->resolver,
2442                                                       val->event->name,
2443                                                       ds.algorithm))
2444                         continue;
2445
2446                 if (ds.digest_type == DNS_DSDIGEST_SHA256 &&
2447                     ds.length == ISC_SHA256_DIGESTLENGTH) {
2448                         digest_type = DNS_DSDIGEST_SHA256;
2449                         break;
2450                 }
2451         }
2452
2453         for (result = dns_rdataset_first(val->dsset);
2454              result == ISC_R_SUCCESS;
2455              result = dns_rdataset_next(val->dsset))
2456         {
2457                 dns_rdata_reset(&dsrdata);
2458                 dns_rdataset_current(val->dsset, &dsrdata);
2459                 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
2460                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2461
2462                 if (!dns_resolver_digest_supported(val->view->resolver,
2463                                                    ds.digest_type))
2464                         continue;
2465
2466                 if (ds.digest_type != digest_type)
2467                         continue;
2468
2469                 if (!dns_resolver_algorithm_supported(val->view->resolver,
2470                                                       val->event->name,
2471                                                       ds.algorithm))
2472                         continue;
2473
2474                 supported_algorithm = ISC_TRUE;
2475
2476                 dns_rdataset_init(&trdataset);
2477                 dns_rdataset_clone(val->event->rdataset, &trdataset);
2478
2479                 /*
2480                  * Look for the KEY that matches the DS record.
2481                  */
2482                 for (result = dns_rdataset_first(&trdataset);
2483                      result == ISC_R_SUCCESS;
2484                      result = dns_rdataset_next(&trdataset))
2485                 {
2486                         dns_rdata_reset(&keyrdata);
2487                         dns_rdataset_current(&trdataset, &keyrdata);
2488                         result = dns_rdata_tostruct(&keyrdata, &key, NULL);
2489                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2490                         keytag = compute_keytag(&keyrdata, &key);
2491                         if (ds.key_tag != keytag ||
2492                             ds.algorithm != key.algorithm)
2493                                 continue;
2494                         dns_rdata_reset(&newdsrdata);
2495                         result = dns_ds_buildrdata(val->event->name,
2496                                                    &keyrdata, ds.digest_type,
2497                                                    dsbuf, &newdsrdata);
2498                         if (result != ISC_R_SUCCESS)
2499                                 continue;
2500                         if (dns_rdata_compare(&dsrdata, &newdsrdata) == 0)
2501                                 break;
2502                 }
2503                 if (result != ISC_R_SUCCESS) {
2504                         dns_rdataset_disassociate(&trdataset);
2505                         validator_log(val, ISC_LOG_DEBUG(3),
2506                                       "no DNSKEY matching DS");
2507                         continue;
2508                 }
2509
2510                 for (result = dns_rdataset_first(val->event->sigrdataset);
2511                      result == ISC_R_SUCCESS;
2512                      result = dns_rdataset_next(val->event->sigrdataset))
2513                 {
2514                         dns_rdata_reset(&sigrdata);
2515                         dns_rdataset_current(val->event->sigrdataset,
2516                                              &sigrdata);
2517                         result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
2518                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2519                         if (ds.key_tag != sig.keyid ||
2520                             ds.algorithm != sig.algorithm)
2521                                 continue;
2522                         if (!dns_name_equal(val->event->name, &sig.signer)) {
2523                                 validator_log(val, ISC_LOG_DEBUG(3),
2524                                               "DNSKEY signer mismatch");
2525                                 continue;
2526                         }
2527                         dstkey = NULL;
2528                         result = dns_dnssec_keyfromrdata(val->event->name,
2529                                                          &keyrdata,
2530                                                          val->view->mctx,
2531                                                          &dstkey);
2532                         if (result != ISC_R_SUCCESS)
2533                                 /*
2534                                  * This really shouldn't happen, but...
2535                                  */
2536                                 continue;
2537                         result = verify(val, dstkey, &sigrdata, sig.keyid);
2538                         dst_key_free(&dstkey);
2539                         if (result == ISC_R_SUCCESS)
2540                                 break;
2541                 }
2542                 dns_rdataset_disassociate(&trdataset);
2543                 if (result == ISC_R_SUCCESS)
2544                         break;
2545                 validator_log(val, ISC_LOG_DEBUG(3),
2546                               "no RRSIG matching DS key");
2547         }
2548         if (result == ISC_R_SUCCESS) {
2549                 marksecure(event);
2550                 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure");
2551                 return (result);
2552         } else if (result == ISC_R_NOMORE && !supported_algorithm) {
2553                 if (val->mustbesecure) {
2554                         validator_log(val, ISC_LOG_WARNING,
2555                                       "must be secure failure");
2556                         return (DNS_R_MUSTBESECURE);
2557                 }
2558                 validator_log(val, ISC_LOG_DEBUG(3),
2559                               "no supported algorithm/digest (DS)");
2560                 markanswer(val, "validatezonekey (3)");
2561                 return (ISC_R_SUCCESS);
2562         } else
2563                 return (DNS_R_NOVALIDSIG);
2564 }
2565
2566 /*%
2567  * Starts a positive response validation.
2568  *
2569  * Returns:
2570  * \li  ISC_R_SUCCESS   Validation completed successfully
2571  * \li  DNS_R_WAIT      Validation has started but is waiting
2572  *                      for an event.
2573  * \li  Other return codes are possible and all indicate failure.
2574  */
2575 static isc_result_t
2576 start_positive_validation(dns_validator_t *val) {
2577         /*
2578          * If this is not a key, go straight into validate().
2579          */
2580         if (val->event->type != dns_rdatatype_dnskey || !isselfsigned(val))
2581                 return (validate(val, ISC_FALSE));
2582
2583         return (validatezonekey(val));
2584 }
2585
2586 /*%
2587  * val_rdataset_first and val_rdataset_next provide iteration methods
2588  * that hide whether we are iterating across a message or a  negative
2589  * cache rdataset.
2590  */
2591 static isc_result_t
2592 val_rdataset_first(dns_validator_t *val, dns_name_t **namep,
2593                    dns_rdataset_t **rdatasetp)
2594 {
2595         dns_message_t *message = val->event->message;
2596         isc_result_t result;
2597
2598         REQUIRE(rdatasetp != NULL);
2599         REQUIRE(namep != NULL);
2600         if (message == NULL) {
2601                 REQUIRE(*rdatasetp != NULL);
2602                 REQUIRE(*namep != NULL);
2603         } else {
2604                 REQUIRE(*rdatasetp == NULL);
2605                 REQUIRE(*namep == NULL);
2606         }
2607
2608         if (message != NULL) {
2609                 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2610                 if (result != ISC_R_SUCCESS)
2611                         return (result);
2612                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, namep);
2613                 *rdatasetp = ISC_LIST_HEAD((*namep)->list);
2614                 INSIST(*rdatasetp != NULL);
2615         } else {
2616                 result = dns_rdataset_first(val->event->rdataset);
2617                 if (result == ISC_R_SUCCESS)
2618                         dns_ncache_current(val->event->rdataset, *namep,
2619                                            *rdatasetp);
2620         }
2621         return (result);
2622 }
2623
2624 static isc_result_t
2625 val_rdataset_next(dns_validator_t *val, dns_name_t **namep,
2626                   dns_rdataset_t **rdatasetp)
2627 {
2628         dns_message_t *message = val->event->message;
2629         isc_result_t result = ISC_R_SUCCESS;
2630
2631         REQUIRE(rdatasetp != NULL && *rdatasetp != NULL);
2632         REQUIRE(namep != NULL && *namep != NULL);
2633
2634         if (message != NULL) {
2635                 dns_rdataset_t *rdataset = *rdatasetp;
2636                 rdataset = ISC_LIST_NEXT(rdataset, link);
2637                 if (rdataset == NULL) {
2638                         *namep = NULL;
2639                         result = dns_message_nextname(message,
2640                                                       DNS_SECTION_AUTHORITY);
2641                         if (result == ISC_R_SUCCESS) {
2642                                 dns_message_currentname(message,
2643                                                         DNS_SECTION_AUTHORITY,
2644                                                         namep);
2645                                 rdataset = ISC_LIST_HEAD((*namep)->list);
2646                                 INSIST(rdataset != NULL);
2647                         }
2648                 }
2649                 *rdatasetp = rdataset;
2650         } else {
2651                 dns_rdataset_disassociate(*rdatasetp);
2652                 result = dns_rdataset_next(val->event->rdataset);
2653                 if (result == ISC_R_SUCCESS)
2654                         dns_ncache_current(val->event->rdataset, *namep,
2655                                            *rdatasetp);
2656         }
2657         return (result);
2658 }
2659
2660 /*%
2661  * Look for NODATA at the wildcard and NOWILDCARD proofs in the
2662  * previously validated NSEC records.  As these proofs are mutually
2663  * exclusive we stop when one is found.
2664  *
2665  * Returns
2666  * \li  ISC_R_SUCCESS
2667  */
2668 static isc_result_t
2669 checkwildcard(dns_validator_t *val, dns_rdatatype_t type, dns_name_t *zonename)
2670 {
2671         dns_name_t *name, *wild, tname;
2672         isc_result_t result;
2673         isc_boolean_t exists, data;
2674         char namebuf[DNS_NAME_FORMATSIZE];
2675         dns_rdataset_t *rdataset, trdataset;
2676
2677         dns_name_init(&tname, NULL);
2678         dns_rdataset_init(&trdataset);
2679         wild = dns_fixedname_name(&val->wild);
2680
2681         if (dns_name_countlabels(wild) == 0) {
2682                 validator_log(val, ISC_LOG_DEBUG(3),
2683                               "in checkwildcard: no wildcard to check");
2684                 return (ISC_R_SUCCESS);
2685         }
2686
2687         dns_name_format(wild, namebuf, sizeof(namebuf));
2688         validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf);
2689
2690         if (val->event->message == NULL) {
2691                 name = &tname;
2692                 rdataset = &trdataset;
2693         } else {
2694                 name = NULL;
2695                 rdataset = NULL;
2696         }
2697
2698         for (result = val_rdataset_first(val, &name, &rdataset);
2699              result == ISC_R_SUCCESS;
2700              result = val_rdataset_next(val, &name, &rdataset))
2701         {
2702                 if (rdataset->type != type ||
2703                     rdataset->trust != dns_trust_secure)
2704                         continue;
2705
2706                 if (rdataset->type == dns_rdatatype_nsec &&
2707                     (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
2708                     !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
2709                     nsecnoexistnodata(val, wild, name, rdataset,
2710                                       &exists, &data, NULL)
2711                                        == ISC_R_SUCCESS)
2712                 {
2713                         dns_name_t **proofs = val->event->proofs;
2714                         if (exists && !data)
2715                                 val->attributes |= VALATTR_FOUNDNODATA;
2716                         if (exists && !data && NEEDNODATA(val))
2717                                 proofs[DNS_VALIDATOR_NODATAPROOF] =
2718                                                  name;
2719                         if (!exists)
2720                                 val->attributes |=
2721                                          VALATTR_FOUNDNOWILDCARD;
2722                         if (!exists && NEEDNOQNAME(val))
2723                                 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
2724                                                  name;
2725                         if (dns_rdataset_isassociated(&trdataset))
2726                                 dns_rdataset_disassociate(&trdataset);
2727                         return (ISC_R_SUCCESS);
2728                 }
2729
2730                 if (rdataset->type == dns_rdatatype_nsec3 &&
2731                     (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
2732                     !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
2733                     nsec3noexistnodata(val, wild, name, rdataset,
2734                                        zonename, &exists, &data,
2735                                        NULL, NULL, NULL, NULL, NULL,
2736                                        NULL) == ISC_R_SUCCESS)
2737                 {
2738                         dns_name_t **proofs = val->event->proofs;
2739                         if (exists && !data)
2740                                 val->attributes |= VALATTR_FOUNDNODATA;
2741                         if (exists && !data && NEEDNODATA(val))
2742                                 proofs[DNS_VALIDATOR_NODATAPROOF] =
2743                                                  name;
2744                         if (!exists)
2745                                 val->attributes |=
2746                                          VALATTR_FOUNDNOWILDCARD;
2747                         if (!exists && NEEDNOQNAME(val))
2748                                 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
2749                                                  name;
2750                         if (dns_rdataset_isassociated(&trdataset))
2751                                 dns_rdataset_disassociate(&trdataset);
2752                         return (ISC_R_SUCCESS);
2753                 }
2754         }
2755         if (result == ISC_R_NOMORE)
2756                 result = ISC_R_SUCCESS;
2757         if (dns_rdataset_isassociated(&trdataset))
2758                 dns_rdataset_disassociate(&trdataset);
2759         return (result);
2760 }
2761
2762 static isc_result_t
2763 findnsec3proofs(dns_validator_t *val) {
2764         dns_name_t *name, tname;
2765         isc_result_t result;
2766         isc_boolean_t exists, data, optout, unknown;
2767         isc_boolean_t setclosest, setnearest;
2768         dns_fixedname_t fclosest, fnearest, fzonename;
2769         dns_name_t *closest, *nearest, *zonename;
2770         dns_name_t **proofs = val->event->proofs;
2771         dns_rdataset_t *rdataset, trdataset;
2772
2773         dns_name_init(&tname, NULL);
2774         dns_rdataset_init(&trdataset);
2775         dns_fixedname_init(&fclosest);
2776         dns_fixedname_init(&fnearest);
2777         dns_fixedname_init(&fzonename);
2778         closest = dns_fixedname_name(&fclosest);
2779         nearest = dns_fixedname_name(&fnearest);
2780         zonename = dns_fixedname_name(&fzonename);
2781
2782         if (val->event->message == NULL) {
2783                 name = &tname;
2784                 rdataset = &trdataset;
2785         } else {
2786                 name = NULL;
2787                 rdataset = NULL;
2788         }
2789
2790         for (result = val_rdataset_first(val, &name, &rdataset);
2791              result == ISC_R_SUCCESS;
2792              result = val_rdataset_next(val, &name, &rdataset))
2793         {
2794                 if (rdataset->type != dns_rdatatype_nsec3 ||
2795                     rdataset->trust != dns_trust_secure)
2796                         continue;
2797
2798                 result = nsec3noexistnodata(val, val->event->name,
2799                                             name, rdataset,
2800                                             zonename, NULL, NULL, NULL,
2801                                             NULL, NULL, NULL, NULL,
2802                                             NULL);
2803                 if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS) {
2804                         if (dns_rdataset_isassociated(&trdataset))
2805                                 dns_rdataset_disassociate(&trdataset);
2806                         return (result);
2807                 }
2808         }
2809         if (result != ISC_R_NOMORE)
2810                 result = ISC_R_SUCCESS;
2811
2812         if (dns_name_countlabels(zonename) == 0)
2813                 return (ISC_R_SUCCESS);
2814
2815         for (result = val_rdataset_first(val, &name, &rdataset);
2816              result == ISC_R_SUCCESS;
2817              result = val_rdataset_next(val, &name, &rdataset))
2818         {
2819                 if (rdataset->type != dns_rdatatype_nsec3 ||
2820                     rdataset->trust != dns_trust_secure)
2821                         continue;
2822
2823                 /*
2824                  * We process all NSEC3 records to find the closest
2825                  * encloser and nearest name to the closest encloser.
2826                  */
2827                 setclosest = setnearest = ISC_FALSE;
2828                 optout = ISC_FALSE;
2829                 unknown = ISC_FALSE;
2830                 (void)nsec3noexistnodata(val, val->event->name, name, rdataset,
2831                                          zonename, &exists, &data, &optout,
2832                                          &unknown, &setclosest, &setnearest,
2833                                          closest, nearest);
2834                 if (setclosest)
2835                         proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
2836                 if (unknown)
2837                         val->attributes |= VALATTR_FOUNDUNKNOWN;
2838                 if (result != ISC_R_SUCCESS)
2839                         continue;
2840                 if (exists && !data && NEEDNODATA(val)) {
2841                         val->attributes |= VALATTR_FOUNDNODATA;
2842                         proofs[DNS_VALIDATOR_NODATAPROOF] = name;
2843                 }
2844                 if (!exists && setnearest) {
2845                         val->attributes |= VALATTR_FOUNDNOQNAME;
2846                         proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name;
2847                         if (optout)
2848                                 val->attributes |= VALATTR_FOUNDOPTOUT;
2849                 }
2850         }
2851         if (result == ISC_R_NOMORE)
2852                 result = ISC_R_SUCCESS;
2853
2854         /*
2855          * To know we have a valid noqname and optout proofs we need to also
2856          * have a valid closest encloser.  Otherwise we could still be looking
2857          * at proofs from the parent zone.
2858          */
2859         if (dns_name_countlabels(closest) > 0 &&
2860             dns_name_countlabels(nearest) ==
2861             dns_name_countlabels(closest) + 1 &&
2862             dns_name_issubdomain(nearest, closest))
2863         {
2864                 val->attributes |= VALATTR_FOUNDCLOSEST;
2865                 result = dns_name_concatenate(dns_wildcardname, closest,
2866                                               dns_fixedname_name(&val->wild),
2867                                               NULL);
2868                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2869         } else {
2870                 val->attributes &= ~VALATTR_FOUNDNOQNAME;
2871                 val->attributes &= ~VALATTR_FOUNDOPTOUT;
2872                 proofs[DNS_VALIDATOR_NOQNAMEPROOF] = NULL;
2873         }
2874
2875         /*
2876          * Do we need to check for the wildcard?
2877          */
2878         if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
2879             ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
2880                 result = checkwildcard(val, dns_rdatatype_nsec3, zonename);
2881                 if (result != ISC_R_SUCCESS)
2882                         return (result);
2883         }
2884         return (result);
2885 }
2886
2887 /*%
2888  * Validate the authority section records.
2889  */
2890 static isc_result_t
2891 validate_authority(dns_validator_t *val, isc_boolean_t resume) {
2892         dns_name_t *name;
2893         dns_message_t *message = val->event->message;
2894         isc_result_t result;
2895
2896         if (!resume)
2897                 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2898         else
2899                 result = ISC_R_SUCCESS;
2900
2901         for (;
2902              result == ISC_R_SUCCESS;
2903              result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
2904         {
2905                 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2906
2907                 name = NULL;
2908                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
2909                 if (resume) {
2910                         rdataset = ISC_LIST_NEXT(val->currentset, link);
2911                         val->currentset = NULL;
2912                         resume = ISC_FALSE;
2913                 } else
2914                         rdataset = ISC_LIST_HEAD(name->list);
2915
2916                 for (;
2917                      rdataset != NULL;
2918                      rdataset = ISC_LIST_NEXT(rdataset, link))
2919                 {
2920                         if (rdataset->type == dns_rdatatype_rrsig)
2921                                 continue;
2922
2923                         for (sigrdataset = ISC_LIST_HEAD(name->list);
2924                              sigrdataset != NULL;
2925                              sigrdataset = ISC_LIST_NEXT(sigrdataset,
2926                                                          link))
2927                         {
2928                                 if (sigrdataset->type == dns_rdatatype_rrsig &&
2929                                     sigrdataset->covers == rdataset->type)
2930                                         break;
2931                         }
2932                         /*
2933                          * If a signed zone is missing the zone key, bad
2934                          * things could happen.  A query for data in the zone
2935                          * would lead to a query for the zone key, which
2936                          * would return a negative answer, which would contain
2937                          * an SOA and an NSEC signed by the missing key, which
2938                          * would trigger another query for the DNSKEY (since
2939                          * the first one is still in progress), and go into an
2940                          * infinite loop.  Avoid that.
2941                          */
2942                         if (val->event->type == dns_rdatatype_dnskey &&
2943                             dns_name_equal(name, val->event->name))
2944                         {
2945                                 dns_rdata_t nsec = DNS_RDATA_INIT;
2946
2947                                 if (rdataset->type != dns_rdatatype_nsec)
2948                                         continue;
2949
2950                                 result = dns_rdataset_first(rdataset);
2951                                 if (result != ISC_R_SUCCESS)
2952                                         return (result);
2953                                 dns_rdataset_current(rdataset, &nsec);
2954                                 if (dns_nsec_typepresent(&nsec,
2955                                                         dns_rdatatype_soa))
2956                                         continue;
2957                         }
2958                         val->currentset = rdataset;
2959                         result = create_validator(val, name, rdataset->type,
2960                                                   rdataset, sigrdataset,
2961                                                   authvalidated,
2962                                                   "validate_authority");
2963                         if (result != ISC_R_SUCCESS)
2964                                 return (result);
2965                         val->authcount++;
2966                         return (DNS_R_WAIT);
2967                 }
2968         }
2969         if (result == ISC_R_NOMORE)
2970                 result = ISC_R_SUCCESS;
2971         return (result);
2972 }
2973
2974 /*%
2975  * Validate the ncache elements.
2976  */
2977 static isc_result_t
2978 validate_ncache(dns_validator_t *val, isc_boolean_t resume) {
2979         dns_name_t *name;
2980         isc_result_t result;
2981
2982         if (!resume)
2983                 result = dns_rdataset_first(val->event->rdataset);
2984         else
2985                 result = dns_rdataset_next(val->event->rdataset);
2986
2987         for (;
2988              result == ISC_R_SUCCESS;
2989              result = dns_rdataset_next(val->event->rdataset))
2990         {
2991                 dns_rdataset_t *rdataset, *sigrdataset = NULL;
2992
2993                 if (dns_rdataset_isassociated(&val->frdataset))
2994                         dns_rdataset_disassociate(&val->frdataset);
2995                 if (dns_rdataset_isassociated(&val->fsigrdataset))
2996                         dns_rdataset_disassociate(&val->fsigrdataset);
2997
2998                 dns_fixedname_init(&val->fname);
2999                 name = dns_fixedname_name(&val->fname);
3000                 rdataset = &val->frdataset;
3001                 dns_ncache_current(val->event->rdataset, name, rdataset);
3002
3003                 if (val->frdataset.type == dns_rdatatype_rrsig)
3004                         continue;
3005
3006                 result = dns_ncache_getsigrdataset(val->event->rdataset, name,
3007                                                    rdataset->type,
3008                                                    &val->fsigrdataset);
3009                 if (result == ISC_R_SUCCESS)
3010                         sigrdataset = &val->fsigrdataset;
3011
3012                 /*
3013                  * If a signed zone is missing the zone key, bad
3014                  * things could happen.  A query for data in the zone
3015                  * would lead to a query for the zone key, which
3016                  * would return a negative answer, which would contain
3017                  * an SOA and an NSEC signed by the missing key, which
3018                  * would trigger another query for the DNSKEY (since
3019                  * the first one is still in progress), and go into an
3020                  * infinite loop.  Avoid that.
3021                  */
3022                 if (val->event->type == dns_rdatatype_dnskey &&
3023                     dns_name_equal(name, val->event->name))
3024                 {
3025                         dns_rdata_t nsec = DNS_RDATA_INIT;
3026
3027                         if (rdataset->type != dns_rdatatype_nsec)
3028                                 continue;
3029
3030                         result = dns_rdataset_first(rdataset);
3031                         if (result != ISC_R_SUCCESS)
3032                                 return (result);
3033                         dns_rdataset_current(rdataset, &nsec);
3034                         if (dns_nsec_typepresent(&nsec,
3035                                                 dns_rdatatype_soa))
3036                                 continue;
3037                 }
3038                 val->currentset = rdataset;
3039                 result = create_validator(val, name, rdataset->type,
3040                                           rdataset, sigrdataset,
3041                                           authvalidated,
3042                                           "validate_ncache");
3043                 if (result != ISC_R_SUCCESS)
3044                         return (result);
3045                 val->authcount++;
3046                 return (DNS_R_WAIT);
3047         }
3048         if (result == ISC_R_NOMORE)
3049                 result = ISC_R_SUCCESS;
3050         return (result);
3051 }
3052
3053 /*%
3054  * Prove a negative answer is good or that there is a NOQNAME when the
3055  * answer is from a wildcard.
3056  *
3057  * Loop through the authority section looking for NODATA, NOWILDCARD
3058  * and NOQNAME proofs in the NSEC records by calling authvalidated().
3059  *
3060  * If the required proofs are found we are done.
3061  *
3062  * If the proofs are not found attempt to prove this is a unsecure
3063  * response.
3064  */
3065 static isc_result_t
3066 nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
3067         isc_result_t result;
3068
3069         if (resume)
3070                 validator_log(val, ISC_LOG_DEBUG(3), "resuming nsecvalidate");
3071
3072         if (val->event->message == NULL)
3073                 result = validate_ncache(val, resume);
3074         else
3075                 result = validate_authority(val, resume);
3076
3077         if (result != ISC_R_SUCCESS)
3078                 return (result);
3079
3080         /*
3081          * Do we only need to check for NOQNAME?  To get here we must have
3082          * had a secure wildcard answer.
3083          */
3084         if (!NEEDNODATA(val) && !NEEDNOWILDCARD(val) && NEEDNOQNAME(val)) {
3085                 if (!FOUNDNOQNAME(val))
3086                         findnsec3proofs(val);
3087                 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val)) {
3088                         validator_log(val, ISC_LOG_DEBUG(3),
3089                                       "noqname proof found");
3090                         validator_log(val, ISC_LOG_DEBUG(3),
3091                                       "marking as secure");
3092                         marksecure(val->event);
3093                         return (ISC_R_SUCCESS);
3094                 } else if (FOUNDOPTOUT(val) &&
3095                            dns_name_countlabels(dns_fixedname_name(&val->wild))
3096                                          != 0) {
3097                         validator_log(val, ISC_LOG_DEBUG(3),
3098                                       "optout proof found");
3099                         val->event->optout = ISC_TRUE;
3100                         markanswer(val, "nsecvalidate (1)");
3101                         return (ISC_R_SUCCESS);
3102                 } else if ((val->attributes & VALATTR_FOUNDUNKNOWN) != 0) {
3103                         validator_log(val, ISC_LOG_DEBUG(3),
3104                                       "unknown NSEC3 hash algorithm found");
3105                         markanswer(val, "nsecvalidate (2)");
3106                         return (ISC_R_SUCCESS);
3107                 }
3108                 validator_log(val, ISC_LOG_DEBUG(3),
3109                               "noqname proof not found");
3110                 return (DNS_R_NOVALIDNSEC);
3111         }
3112
3113         if (!FOUNDNOQNAME(val) && !FOUNDNODATA(val))
3114                 findnsec3proofs(val);
3115
3116         /*
3117          * Do we need to check for the wildcard?
3118          */
3119         if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
3120             ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
3121                 result = checkwildcard(val, dns_rdatatype_nsec, NULL);
3122                 if (result != ISC_R_SUCCESS)
3123                         return (result);
3124         }
3125
3126         if ((NEEDNODATA(val) && (FOUNDNODATA(val) || FOUNDOPTOUT(val))) ||
3127             (NEEDNOQNAME(val) && FOUNDNOQNAME(val) &&
3128              NEEDNOWILDCARD(val) && FOUNDNOWILDCARD(val) &&
3129              FOUNDCLOSEST(val))) {
3130                 if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
3131                         val->event->optout = ISC_TRUE;
3132                 validator_log(val, ISC_LOG_DEBUG(3),
3133                               "nonexistence proof(s) found");
3134                 if (val->event->message == NULL)
3135                         marksecure(val->event);
3136                 return (ISC_R_SUCCESS);
3137         }
3138                 findnsec3proofs(val);
3139
3140         if (val->authfail != 0 && val->authcount == val->authfail)
3141                 return (DNS_R_BROKENCHAIN);
3142         validator_log(val, ISC_LOG_DEBUG(3),
3143                       "nonexistence proof(s) not found");
3144         val->attributes |= VALATTR_INSECURITY;
3145         return (proveunsecure(val, ISC_FALSE, ISC_FALSE));
3146 }
3147
3148 static isc_boolean_t
3149 check_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) {
3150         dns_rdata_t dsrdata = DNS_RDATA_INIT;
3151         dns_rdata_ds_t ds;
3152         isc_result_t result;
3153
3154         for (result = dns_rdataset_first(rdataset);
3155              result == ISC_R_SUCCESS;
3156              result = dns_rdataset_next(rdataset)) {
3157                 dns_rdataset_current(rdataset, &dsrdata);
3158                 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
3159                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3160
3161                 if (dns_resolver_digest_supported(val->view->resolver,
3162                                                   ds.digest_type) &&
3163                     dns_resolver_algorithm_supported(val->view->resolver,
3164                                                      name, ds.algorithm)) {
3165                         dns_rdata_reset(&dsrdata);
3166                         return (ISC_TRUE);
3167                 }
3168                 dns_rdata_reset(&dsrdata);
3169         }
3170         return (ISC_FALSE);
3171 }
3172
3173 static void
3174 dlvvalidated(isc_task_t *task, isc_event_t *event) {
3175         dns_validatorevent_t *devent;
3176         dns_validator_t *val;
3177         isc_result_t eresult;
3178         isc_boolean_t want_destroy;
3179
3180         UNUSED(task);
3181         INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
3182
3183         devent = (dns_validatorevent_t *)event;
3184         val = devent->ev_arg;
3185         eresult = devent->result;
3186
3187         isc_event_free(&event);
3188         dns_validator_destroy(&val->subvalidator);
3189
3190         INSIST(val->event != NULL);
3191
3192         validator_log(val, ISC_LOG_DEBUG(3), "in dlvvalidated");
3193         LOCK(&val->lock);
3194         if (CANCELED(val)) {
3195                 validator_done(val, ISC_R_CANCELED);
3196         } else if (eresult == ISC_R_SUCCESS) {
3197                 validator_log(val, ISC_LOG_DEBUG(3),
3198                               "dlvset with trust %d", val->frdataset.trust);
3199                 dns_rdataset_clone(&val->frdataset, &val->dlv);
3200                 val->havedlvsep = ISC_TRUE;
3201                 if (dlv_algorithm_supported(val))
3202                         dlv_validator_start(val);
3203                 else {
3204                         markanswer(val, "dlvvalidated");
3205                         validator_done(val, ISC_R_SUCCESS);
3206                 }
3207         } else {
3208                 if (eresult != DNS_R_BROKENCHAIN) {
3209                         if (dns_rdataset_isassociated(&val->frdataset))
3210                                 dns_rdataset_expire(&val->frdataset);
3211                         if (dns_rdataset_isassociated(&val->fsigrdataset))
3212                                 dns_rdataset_expire(&val->fsigrdataset);
3213                 }
3214                 validator_log(val, ISC_LOG_DEBUG(3),
3215                               "dlvvalidated: got %s",
3216                               isc_result_totext(eresult));
3217                 validator_done(val, DNS_R_BROKENCHAIN);
3218         }
3219         want_destroy = exit_check(val);
3220         UNLOCK(&val->lock);
3221         if (want_destroy)
3222                 destroy(val);
3223 }
3224
3225 /*%
3226  * Callback from fetching a DLV record.
3227  *
3228  * Resumes the DLV lookup process.
3229  */
3230 static void
3231 dlvfetched(isc_task_t *task, isc_event_t *event) {
3232         char namebuf[DNS_NAME_FORMATSIZE];
3233         dns_fetchevent_t *devent;
3234         dns_validator_t *val;
3235         isc_boolean_t want_destroy;
3236         isc_result_t eresult;
3237         isc_result_t result;
3238
3239         UNUSED(task);
3240         INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
3241         devent = (dns_fetchevent_t *)event;
3242         val = devent->ev_arg;
3243         eresult = devent->result;
3244
3245         /* Free resources which are not of interest. */
3246         if (devent->node != NULL)
3247                 dns_db_detachnode(devent->db, &devent->node);
3248         if (devent->db != NULL)
3249                 dns_db_detach(&devent->db);
3250         if (dns_rdataset_isassociated(&val->fsigrdataset))
3251                 dns_rdataset_disassociate(&val->fsigrdataset);
3252         isc_event_free(&event);
3253         dns_resolver_destroyfetch(&val->fetch);
3254
3255         INSIST(val->event != NULL);
3256         validator_log(val, ISC_LOG_DEBUG(3), "in dlvfetched: %s",
3257                       dns_result_totext(eresult));
3258
3259         LOCK(&val->lock);
3260         if (eresult == ISC_R_SUCCESS) {
3261                 dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
3262                                 sizeof(namebuf));
3263                 dns_rdataset_clone(&val->frdataset, &val->dlv);
3264                 val->havedlvsep = ISC_TRUE;
3265                 if (dlv_algorithm_supported(val)) {
3266                         validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found",
3267                                       namebuf);
3268                         dlv_validator_start(val);
3269                 } else {
3270                         validator_log(val, ISC_LOG_DEBUG(3),
3271                                       "DLV %s found with no supported algorithms",
3272                                       namebuf);
3273                         markanswer(val, "dlvfetched (1)");
3274                         validator_done(val, ISC_R_SUCCESS);
3275                 }
3276         } else if (eresult == DNS_R_NXRRSET ||
3277                    eresult == DNS_R_NXDOMAIN ||
3278                    eresult == DNS_R_NCACHENXRRSET ||
3279                    eresult == DNS_R_NCACHENXDOMAIN) {
3280                 result = finddlvsep(val, ISC_TRUE);
3281                 if (result == ISC_R_SUCCESS) {
3282                         if (dlv_algorithm_supported(val)) {
3283                                 dns_name_format(dns_fixedname_name(&val->dlvsep),
3284                                                 namebuf, sizeof(namebuf));
3285                                 validator_log(val, ISC_LOG_DEBUG(3),
3286                                               "DLV %s found", namebuf);
3287                                 dlv_validator_start(val);
3288                         } else {
3289                                 validator_log(val, ISC_LOG_DEBUG(3),
3290                                               "DLV %s found with no supported "
3291                                               "algorithms", namebuf);
3292                                 markanswer(val, "dlvfetched (2)");
3293                                 validator_done(val, ISC_R_SUCCESS);
3294                         }
3295                 } else if (result == ISC_R_NOTFOUND) {
3296                         validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
3297                         markanswer(val, "dlvfetched (3)");
3298                         validator_done(val, ISC_R_SUCCESS);
3299                 } else {
3300                         validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3301                                       dns_result_totext(result));
3302                         if (result != DNS_R_WAIT)
3303                                 validator_done(val, result);
3304                 }
3305         } else {
3306                 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3307                               dns_result_totext(eresult));
3308                 validator_done(val, eresult);
3309         }
3310         want_destroy = exit_check(val);
3311         UNLOCK(&val->lock);
3312         if (want_destroy)
3313                 destroy(val);
3314 }
3315
3316 /*%
3317  * Start the DLV lookup process.
3318  *
3319  * Returns
3320  * \li  ISC_R_SUCCESS
3321  * \li  DNS_R_WAIT
3322  * \li  Others on validation failures.
3323  */
3324 static isc_result_t
3325 startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) {
3326         char namebuf[DNS_NAME_FORMATSIZE];
3327         isc_result_t result;
3328
3329         INSIST(!DLVTRIED(val));
3330
3331         val->attributes |= VALATTR_DLVTRIED;
3332
3333         dns_name_format(unsecure, namebuf, sizeof(namebuf));
3334         validator_log(val, ISC_LOG_DEBUG(3),
3335                       "plain DNSSEC returns unsecure (%s): looking for DLV",
3336                       namebuf);
3337
3338         if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
3339                 validator_log(val, ISC_LOG_WARNING, "must be secure failure");
3340                 return (DNS_R_MUSTBESECURE);
3341         }
3342
3343         val->dlvlabels = dns_name_countlabels(unsecure) - 1;
3344         result = finddlvsep(val, ISC_FALSE);
3345         if (result == ISC_R_NOTFOUND) {
3346                 validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
3347                 markanswer(val, "startfinddlvsep (1)");
3348                 return (ISC_R_SUCCESS);
3349         }
3350         if (result != ISC_R_SUCCESS) {
3351                 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
3352                               dns_result_totext(result));
3353                 return (result);
3354         }
3355         dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
3356                         sizeof(namebuf));
3357         if (dlv_algorithm_supported(val)) {
3358                 validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf);
3359                 dlv_validator_start(val);
3360                 return (DNS_R_WAIT);
3361         }
3362         validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found with no supported "
3363                       "algorithms", namebuf);
3364         markanswer(val, "startfinddlvsep (2)");
3365         validator_done(val, ISC_R_SUCCESS);
3366         return (ISC_R_SUCCESS);
3367 }
3368
3369 /*%
3370  * Continue the DLV lookup process.
3371  *
3372  * Returns
3373  * \li  ISC_R_SUCCESS
3374  * \li  ISC_R_NOTFOUND
3375  * \li  DNS_R_WAIT
3376  * \li  Others on validation failure.
3377  */
3378 static isc_result_t
3379 finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
3380         char namebuf[DNS_NAME_FORMATSIZE];
3381         dns_fixedname_t dlvfixed;
3382         dns_name_t *dlvname;
3383         dns_name_t *dlvsep;
3384         dns_name_t noroot;
3385         isc_result_t result;
3386         unsigned int labels;
3387
3388         INSIST(val->view->dlv != NULL);
3389
3390         if (!resume) {
3391
3392                 if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
3393                         validator_log(val, ISC_LOG_WARNING,
3394                                       "must be secure failure");
3395                         return (DNS_R_MUSTBESECURE);
3396                 }
3397
3398                 dns_fixedname_init(&val->dlvsep);
3399                 dlvsep = dns_fixedname_name(&val->dlvsep);
3400                 dns_name_copy(val->event->name, dlvsep, NULL);
3401                 /*
3402                  * If this is a response to a DS query, we need to look in
3403                  * the parent zone for the trust anchor.
3404                  */
3405                 if (val->event->type == dns_rdatatype_ds) {
3406                         labels = dns_name_countlabels(dlvsep);
3407                         if (labels == 0)
3408                                 return (ISC_R_NOTFOUND);
3409                         dns_name_getlabelsequence(dlvsep, 1, labels - 1,
3410                                                   dlvsep);
3411                 }
3412         } else {
3413                 dlvsep = dns_fixedname_name(&val->dlvsep);
3414                 labels = dns_name_countlabels(dlvsep);
3415                 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3416         }
3417         dns_name_init(&noroot, NULL);
3418         dns_fixedname_init(&dlvfixed);
3419         dlvname = dns_fixedname_name(&dlvfixed);
3420         labels = dns_name_countlabels(dlvsep);
3421         if (labels == 0)
3422                 return (ISC_R_NOTFOUND);
3423         dns_name_getlabelsequence(dlvsep, 0, labels - 1, &noroot);
3424         result = dns_name_concatenate(&noroot, val->view->dlv, dlvname, NULL);
3425         while (result == ISC_R_NOSPACE) {
3426                 labels = dns_name_countlabels(dlvsep);
3427                 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3428                 dns_name_getlabelsequence(dlvsep, 0, labels - 2, &noroot);
3429                 result = dns_name_concatenate(&noroot, val->view->dlv,
3430                                               dlvname, NULL);
3431         }
3432         if (result != ISC_R_SUCCESS) {
3433                 validator_log(val, ISC_LOG_DEBUG(2), "DLV concatenate failed");
3434                 return (DNS_R_NOVALIDSIG);
3435         }
3436
3437         while (dns_name_countlabels(dlvname) >=
3438                dns_name_countlabels(val->view->dlv) + val->dlvlabels) {
3439                 dns_name_format(dlvname, namebuf, sizeof(namebuf));
3440                 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV %s",
3441                               namebuf);
3442                 result = view_find(val, dlvname, dns_rdatatype_dlv);
3443                 if (result == ISC_R_SUCCESS) {
3444                         if (DNS_TRUST_PENDING(val->frdataset.trust) &&
3445                             dns_rdataset_isassociated(&val->fsigrdataset))
3446                         {
3447                                 dns_fixedname_init(&val->fname);
3448                                 dns_name_copy(dlvname,
3449                                               dns_fixedname_name(&val->fname),
3450                                               NULL);
3451                                 result = create_validator(val,
3452                                                 dns_fixedname_name(&val->fname),
3453                                                           dns_rdatatype_dlv,
3454                                                           &val->frdataset,
3455                                                           &val->fsigrdataset,
3456                                                           dlvvalidated,
3457                                                           "finddlvsep");
3458                                 if (result != ISC_R_SUCCESS)
3459                                         return (result);
3460                                 return (DNS_R_WAIT);
3461                         }
3462                         if (val->frdataset.trust < dns_trust_secure)
3463                                 return (DNS_R_NOVALIDSIG);
3464                         val->havedlvsep = ISC_TRUE;
3465                         dns_rdataset_clone(&val->frdataset, &val->dlv);
3466                         return (ISC_R_SUCCESS);
3467                 }
3468                 if (result == ISC_R_NOTFOUND) {
3469                         result = create_fetch(val, dlvname, dns_rdatatype_dlv,
3470                                               dlvfetched, "finddlvsep");
3471                         if (result != ISC_R_SUCCESS)
3472                                 return (result);
3473                         return (DNS_R_WAIT);
3474                 }
3475                 if (result != DNS_R_NXRRSET &&
3476                     result != DNS_R_NXDOMAIN &&
3477                     result != DNS_R_EMPTYNAME &&
3478                     result != DNS_R_NCACHENXRRSET &&
3479                     result != DNS_R_NCACHENXDOMAIN)
3480                         return (result);
3481                 /*
3482                  * Strip first labels from both dlvsep and dlvname.
3483                  */
3484                 labels = dns_name_countlabels(dlvsep);
3485                 if (labels == 0)
3486                         break;
3487                 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
3488                 labels = dns_name_countlabels(dlvname);
3489                 dns_name_getlabelsequence(dlvname, 1, labels - 1, dlvname);
3490         }
3491         return (ISC_R_NOTFOUND);
3492 }
3493
3494 /*%
3495  * proveunsecure walks down from the SEP looking for a break in the
3496  * chain of trust.  That occurs when we can prove the DS record does
3497  * not exist at a delegation point or the DS exists at a delegation
3498  * but we don't support the algorithm/digest.
3499  *
3500  * If DLV is active and we look for a DLV record at or below the
3501  * point we go insecure.  If found we restart the validation process.
3502  * If not found or DLV isn't active we mark the response as a answer.
3503  *
3504  * Returns:
3505  * \li  ISC_R_SUCCESS           val->event->name is in a unsecure zone
3506  * \li  DNS_R_WAIT              validation is in progress.
3507  * \li  DNS_R_MUSTBESECURE      val->event->name is supposed to be secure
3508  *                              (policy) but we proved that it is unsecure.
3509  * \li  DNS_R_NOVALIDSIG
3510  * \li  DNS_R_NOVALIDNSEC
3511  * \li  DNS_R_NOTINSECURE
3512  * \li  DNS_R_BROKENCHAIN
3513  */
3514 static isc_result_t
3515 proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
3516 {
3517         isc_result_t result;
3518         dns_fixedname_t fixedsecroot;
3519         dns_name_t *secroot;
3520         dns_name_t *tname;
3521         char namebuf[DNS_NAME_FORMATSIZE];
3522         dns_name_t *found;
3523         dns_fixedname_t fixedfound;
3524
3525         dns_fixedname_init(&fixedsecroot);
3526         secroot = dns_fixedname_name(&fixedsecroot);
3527         dns_fixedname_init(&fixedfound);
3528         found = dns_fixedname_name(&fixedfound);
3529         if (val->havedlvsep)
3530                 dns_name_copy(dns_fixedname_name(&val->dlvsep), secroot, NULL);
3531         else {
3532                 unsigned int labels;
3533                 dns_name_copy(val->event->name, secroot, NULL);
3534                 /*
3535                  * If this is a response to a DS query, we need to look in
3536                  * the parent zone for the trust anchor.
3537                  */
3538
3539                 labels = dns_name_countlabels(secroot);
3540                 if (val->event->type == dns_rdatatype_ds && labels > 1U)
3541                         dns_name_getlabelsequence(secroot, 1, labels - 1,
3542                                                   secroot);
3543                 result = dns_keytable_finddeepestmatch(val->keytable,
3544                                                        secroot, secroot);
3545                 if (result == ISC_R_NOTFOUND) {
3546                         if (val->mustbesecure) {
3547                                 validator_log(val, ISC_LOG_WARNING,
3548                                               "must be secure failure");
3549                                 result = DNS_R_MUSTBESECURE;
3550                                 goto out;
3551                         }
3552                         if (val->view->dlv == NULL || DLVTRIED(val)) {
3553                                 markanswer(val, "proveunsecure (1)");
3554                                 return (ISC_R_SUCCESS);
3555                         }
3556                         return (startfinddlvsep(val, dns_rootname));
3557                 } else if (result != ISC_R_SUCCESS)
3558                         return (result);
3559         }
3560
3561         if (!resume) {
3562                 /*
3563                  * We are looking for breaks below the SEP so add a label.
3564                  */
3565                 val->labels = dns_name_countlabels(secroot) + 1;
3566         } else {
3567                 validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
3568                 /*
3569                  * If we have a DS rdataset and it is secure then check if
3570                  * the DS rdataset has a supported algorithm combination.
3571                  * If not this is a insecure delegation as far as this
3572                  * resolver is concerned.  Fall back to DLV if available.
3573                  */
3574                 if (have_ds && val->frdataset.trust >= dns_trust_secure &&
3575                     !check_ds(val, dns_fixedname_name(&val->fname),
3576                               &val->frdataset)) {
3577                         dns_name_format(dns_fixedname_name(&val->fname),
3578                                         namebuf, sizeof(namebuf));
3579                         if ((val->view->dlv == NULL || DLVTRIED(val)) &&
3580                             val->mustbesecure) {
3581                                 validator_log(val, ISC_LOG_WARNING,
3582                                               "must be secure failure at '%s'",
3583                                               namebuf);
3584                                 result = DNS_R_MUSTBESECURE;
3585                                 goto out;
3586                         }
3587                         validator_log(val, ISC_LOG_DEBUG(3),
3588                                       "no supported algorithm/digest (%s/DS)",
3589                                       namebuf);
3590                         if (val->view->dlv == NULL || DLVTRIED(val)) {
3591                                 markanswer(val, "proveunsecure (2)");
3592                                 result = ISC_R_SUCCESS;
3593                                 goto out;
3594                         }
3595                         result = startfinddlvsep(val,
3596                                               dns_fixedname_name(&val->fname));
3597                         goto out;
3598                 }
3599                 val->labels++;
3600         }
3601
3602         for (;
3603              val->labels <= dns_name_countlabels(val->event->name);
3604              val->labels++)
3605         {
3606
3607                 dns_fixedname_init(&val->fname);
3608                 tname = dns_fixedname_name(&val->fname);
3609                 if (val->labels == dns_name_countlabels(val->event->name))
3610                         dns_name_copy(val->event->name, tname, NULL);
3611                 else
3612                         dns_name_split(val->event->name, val->labels,
3613                                        NULL, tname);
3614
3615                 dns_name_format(tname, namebuf, sizeof(namebuf));
3616                 validator_log(val, ISC_LOG_DEBUG(3),
3617                               "checking existence of DS at '%s'",
3618                               namebuf);
3619
3620                 result = view_find(val, tname, dns_rdatatype_ds);
3621                 if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
3622                         /*
3623                          * There is no DS.  If this is a delegation,
3624                          * we maybe done.
3625                          */
3626                         /*
3627                          * If we have "trust == answer" then this namespace
3628                          * has switched from insecure to should be secure.
3629                          */
3630                         if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3631                             DNS_TRUST_ANSWER(val->frdataset.trust)) {
3632                                 result = create_validator(val, tname,
3633                                                           dns_rdatatype_ds,
3634                                                           &val->frdataset,
3635                                                           NULL, dsvalidated,
3636                                                           "proveunsecure");
3637                                  if (result != ISC_R_SUCCESS)
3638                                         goto out;
3639                                 return (DNS_R_WAIT);
3640                         }
3641                         /*
3642                          * Zones using NSEC3 don't return a NSEC RRset so
3643                          * we need to use dns_view_findzonecut2 to find
3644                          * the zone cut.
3645                          */
3646                         if (result == DNS_R_NXRRSET &&
3647                             !dns_rdataset_isassociated(&val->frdataset) &&
3648                             dns_view_findzonecut2(val->view, tname, found,
3649                                                   0, 0, ISC_FALSE, ISC_FALSE,
3650                                                   NULL, NULL) == ISC_R_SUCCESS &&
3651                             dns_name_equal(tname, found)) {
3652                                 if (val->mustbesecure) {
3653                                         validator_log(val, ISC_LOG_WARNING,
3654                                                       "must be secure failure");
3655                                         return (DNS_R_MUSTBESECURE);
3656                                 }
3657                                 if (val->view->dlv == NULL || DLVTRIED(val)) {
3658                                         markanswer(val, "proveunsecure (3)");
3659                                         return (ISC_R_SUCCESS);
3660                                 }
3661                                 return (startfinddlvsep(val, tname));
3662                         }
3663                         if (val->frdataset.trust < dns_trust_secure) {
3664                                 /*
3665                                  * This shouldn't happen, since the negative
3666                                  * response should have been validated.  Since
3667                                  * there's no way of validating existing
3668                                  * negative response blobs, give up.
3669                                  */
3670                                 result = DNS_R_NOVALIDSIG;
3671                                 goto out;
3672                         }
3673                         if (isdelegation(tname, &val->frdataset, result)) {
3674                                 if (val->mustbesecure) {
3675                                         validator_log(val, ISC_LOG_WARNING,
3676                                                       "must be secure failure");
3677                                         return (DNS_R_MUSTBESECURE);
3678                                 }
3679                                 if (val->view->dlv == NULL || DLVTRIED(val)) {
3680                                         markanswer(val, "proveunsecure (4)");
3681                                         return (ISC_R_SUCCESS);
3682                                 }
3683                                 return (startfinddlvsep(val, tname));
3684                         }
3685                         continue;
3686                 } else if (result == ISC_R_SUCCESS) {
3687                         /*
3688                          * There is a DS here.  Verify that it's secure and
3689                          * continue.
3690                          */
3691                         if (val->frdataset.trust >= dns_trust_secure) {
3692                                 if (!check_ds(val, tname, &val->frdataset)) {
3693                                         validator_log(val, ISC_LOG_DEBUG(3),
3694                                                      "no supported algorithm/"
3695                                                      "digest (%s/DS)", namebuf);
3696                                         if (val->mustbesecure) {
3697                                                 validator_log(val,
3698                                                               ISC_LOG_WARNING,
3699                                                       "must be secure failure");
3700                                                 result = DNS_R_MUSTBESECURE;
3701                                                 goto out;
3702                                         }
3703                                         if (val->view->dlv == NULL ||
3704                                             DLVTRIED(val)) {
3705                                                 markanswer(val,
3706                                                            "proveunsecure (5)");
3707                                                 result = ISC_R_SUCCESS;
3708                                                 goto out;
3709                                         }
3710                                         result = startfinddlvsep(val, tname);
3711                                         goto out;
3712                                 }
3713                                 continue;
3714                         }
3715                         else if (!dns_rdataset_isassociated(&val->fsigrdataset))
3716                         {
3717                                 result = DNS_R_NOVALIDSIG;
3718                                 goto out;
3719                         }
3720                         /*
3721                          * Validate / re-validate answer.
3722                          */
3723                         result = create_validator(val, tname, dns_rdatatype_ds,
3724                                                   &val->frdataset,
3725                                                   &val->fsigrdataset,
3726                                                   dsvalidated,
3727                                                   "proveunsecure");
3728                         if (result != ISC_R_SUCCESS)
3729                                 goto out;
3730                         return (DNS_R_WAIT);
3731                 } else if (result == DNS_R_NXDOMAIN ||
3732                            result == DNS_R_NCACHENXDOMAIN) {
3733                         /*
3734                          * This is not a zone cut.  Assuming things are
3735                          * as expected, continue.
3736                          */
3737                         if (!dns_rdataset_isassociated(&val->frdataset)) {
3738                                 /*
3739                                  * There should be an NSEC here, since we
3740                                  * are still in a secure zone.
3741                                  */
3742                                 result = DNS_R_NOVALIDNSEC;
3743                                 goto out;
3744                         } else if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3745                                    DNS_TRUST_ANSWER(val->frdataset.trust)) {
3746                                 /*
3747                                  * If we have "trust == answer" then this namespace
3748                                  * has switched from insecure to should be secure.
3749                                  */
3750                                 result = create_validator(val, tname,
3751                                                           dns_rdatatype_ds,
3752                                                           &val->frdataset,
3753                                                           NULL, dsvalidated,
3754                                                           "proveunsecure");
3755                                 if (result != ISC_R_SUCCESS)
3756                                         goto out;
3757                                 return (DNS_R_WAIT);
3758                         } else if (val->frdataset.trust < dns_trust_secure) {
3759                                 /*
3760                                  * This shouldn't happen, since the negative
3761                                  * response should have been validated.  Since
3762                                  * there's no way of validating existing
3763                                  * negative response blobs, give up.
3764                                  */
3765                                 result = DNS_R_NOVALIDSIG;
3766                                 goto out;
3767                         }
3768                         continue;
3769                 } else if (result == ISC_R_NOTFOUND) {
3770                         /*
3771                          * We don't know anything about the DS.  Find it.
3772                          */
3773                         result = create_fetch(val, tname, dns_rdatatype_ds,
3774                                               dsfetched2, "proveunsecure");
3775                         if (result != ISC_R_SUCCESS)
3776                                 goto out;
3777                         return (DNS_R_WAIT);
3778                 } else if (result == DNS_R_BROKENCHAIN)
3779                         return (result);
3780         }
3781
3782         /* Couldn't complete insecurity proof */
3783         validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed");
3784         return (DNS_R_NOTINSECURE); /* Couldn't complete insecurity proof */
3785
3786  out:
3787         if (dns_rdataset_isassociated(&val->frdataset))
3788                 dns_rdataset_disassociate(&val->frdataset);
3789         if (dns_rdataset_isassociated(&val->fsigrdataset))
3790                 dns_rdataset_disassociate(&val->fsigrdataset);
3791         return (result);
3792 }
3793
3794 /*%
3795  * Reset state and revalidate the answer using DLV.
3796  */
3797 static void
3798 dlv_validator_start(dns_validator_t *val) {
3799         isc_event_t *event;
3800
3801         validator_log(val, ISC_LOG_DEBUG(3), "dlv_validator_start");
3802
3803         /*
3804          * Reset state and try again.
3805          */
3806         val->attributes &= VALATTR_DLVTRIED;
3807         val->options &= ~DNS_VALIDATOR_DLV;
3808
3809         event = (isc_event_t *)val->event;
3810         isc_task_send(val->task, &event);
3811 }
3812
3813 /*%
3814  * Start the validation process.
3815  *
3816  * Attempt to validate the answer based on the category it appears to
3817  * fall in.
3818  * \li  1. secure positive answer.
3819  * \li  2. unsecure positive answer.
3820  * \li  3. a negative answer (secure or unsecure).
3821  *
3822  * Note a answer that appears to be a secure positive answer may actually
3823  * be a unsecure positive answer.
3824  */
3825 static void
3826 validator_start(isc_task_t *task, isc_event_t *event) {
3827         dns_validator_t *val;
3828         dns_validatorevent_t *vevent;
3829         isc_boolean_t want_destroy = ISC_FALSE;
3830         isc_result_t result = ISC_R_FAILURE;
3831
3832         UNUSED(task);
3833         REQUIRE(event->ev_type == DNS_EVENT_VALIDATORSTART);
3834         vevent = (dns_validatorevent_t *)event;
3835         val = vevent->validator;
3836
3837         /* If the validator has been canceled, val->event == NULL */
3838         if (val->event == NULL)
3839                 return;
3840
3841         if (DLVTRIED(val))
3842                 validator_log(val, ISC_LOG_DEBUG(3), "restarting using DLV");
3843         else
3844                 validator_log(val, ISC_LOG_DEBUG(3), "starting");
3845
3846         LOCK(&val->lock);
3847
3848         if ((val->options & DNS_VALIDATOR_DLV) != 0 &&
3849              val->event->rdataset != NULL) {
3850                 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV");
3851                 result = startfinddlvsep(val, dns_rootname);
3852         } else if (val->event->rdataset != NULL &&
3853                    val->event->sigrdataset != NULL) {
3854                 isc_result_t saved_result;
3855
3856                 /*
3857                  * This looks like a simple validation.  We say "looks like"
3858                  * because it might end up requiring an insecurity proof.
3859                  */
3860                 validator_log(val, ISC_LOG_DEBUG(3),
3861                               "attempting positive response validation");
3862
3863                 INSIST(dns_rdataset_isassociated(val->event->rdataset));
3864                 INSIST(dns_rdataset_isassociated(val->event->sigrdataset));
3865                 result = start_positive_validation(val);
3866                 if (result == DNS_R_NOVALIDSIG &&
3867                     (val->attributes & VALATTR_TRIEDVERIFY) == 0)
3868                 {
3869                         saved_result = result;
3870                         validator_log(val, ISC_LOG_DEBUG(3),
3871                                       "falling back to insecurity proof");
3872                         val->attributes |= VALATTR_INSECURITY;
3873                         result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
3874                         if (result == DNS_R_NOTINSECURE)
3875                                 result = saved_result;
3876                 }
3877         } else if (val->event->rdataset != NULL &&
3878                    val->event->rdataset->type != 0) {
3879                 /*
3880                  * This is either an unsecure subdomain or a response from
3881                  * a broken server.
3882                  */
3883                 INSIST(dns_rdataset_isassociated(val->event->rdataset));
3884                 validator_log(val, ISC_LOG_DEBUG(3),
3885                               "attempting insecurity proof");
3886
3887                 val->attributes |= VALATTR_INSECURITY;
3888                 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
3889         } else if (val->event->rdataset == NULL &&
3890                    val->event->sigrdataset == NULL)
3891         {
3892                 /*
3893                  * This is a nonexistence validation.
3894                  */
3895                 validator_log(val, ISC_LOG_DEBUG(3),
3896                               "attempting negative response validation");
3897
3898                 if (val->event->message->rcode == dns_rcode_nxdomain) {
3899                         val->attributes |= VALATTR_NEEDNOQNAME;
3900                         val->attributes |= VALATTR_NEEDNOWILDCARD;
3901                 } else
3902                         val->attributes |= VALATTR_NEEDNODATA;
3903                 result = nsecvalidate(val, ISC_FALSE);
3904         } else if (val->event->rdataset != NULL &&
3905                     val->event->rdataset->type == 0)
3906         {
3907                 /*
3908                  * This is a nonexistence validation.
3909                  */
3910                 validator_log(val, ISC_LOG_DEBUG(3),
3911                               "attempting negative response validation");
3912
3913                 if (val->event->rdataset->covers == dns_rdatatype_any) {
3914                         val->attributes |= VALATTR_NEEDNOQNAME;
3915                         val->attributes |= VALATTR_NEEDNOWILDCARD;
3916                 } else
3917                         val->attributes |= VALATTR_NEEDNODATA;
3918                 result = nsecvalidate(val, ISC_FALSE);
3919         } else {
3920                 /*
3921                  * This shouldn't happen.
3922                  */
3923                 INSIST(0);
3924         }
3925
3926         if (result != DNS_R_WAIT) {
3927                 want_destroy = exit_check(val);
3928                 validator_done(val, result);
3929         }
3930
3931         UNLOCK(&val->lock);
3932         if (want_destroy)
3933                 destroy(val);
3934 }
3935
3936 isc_result_t
3937 dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
3938                      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
3939                      dns_message_t *message, unsigned int options,
3940                      isc_task_t *task, isc_taskaction_t action, void *arg,
3941                      dns_validator_t **validatorp)
3942 {
3943         isc_result_t result;
3944         dns_validator_t *val;
3945         isc_task_t *tclone;
3946         dns_validatorevent_t *event;
3947
3948         REQUIRE(name != NULL);
3949         REQUIRE(rdataset != NULL ||
3950                 (rdataset == NULL && sigrdataset == NULL && message != NULL));
3951         REQUIRE(validatorp != NULL && *validatorp == NULL);
3952
3953         tclone = NULL;
3954         result = ISC_R_FAILURE;
3955
3956         val = isc_mem_get(view->mctx, sizeof(*val));
3957         if (val == NULL)
3958                 return (ISC_R_NOMEMORY);
3959         val->view = NULL;
3960         dns_view_weakattach(view, &val->view);
3961         event = (dns_validatorevent_t *)
3962                 isc_event_allocate(view->mctx, task,
3963                                    DNS_EVENT_VALIDATORSTART,
3964                                    validator_start, NULL,
3965                                    sizeof(dns_validatorevent_t));
3966         if (event == NULL) {
3967                 result = ISC_R_NOMEMORY;
3968                 goto cleanup_val;
3969         }
3970         isc_task_attach(task, &tclone);
3971         event->validator = val;
3972         event->result = ISC_R_FAILURE;
3973         event->name = name;
3974         event->type = type;
3975         event->rdataset = rdataset;
3976         event->sigrdataset = sigrdataset;
3977         event->message = message;
3978         memset(event->proofs, 0, sizeof(event->proofs));
3979         event->optout = ISC_FALSE;
3980         result = isc_mutex_init(&val->lock);
3981         if (result != ISC_R_SUCCESS)
3982                 goto cleanup_event;
3983         val->event = event;
3984         val->options = options;
3985         val->attributes = 0;
3986         val->fetch = NULL;
3987         val->subvalidator = NULL;
3988         val->parent = NULL;
3989         val->keytable = NULL;
3990         dns_keytable_attach(val->view->secroots, &val->keytable);
3991         val->keynode = NULL;
3992         val->key = NULL;
3993         val->siginfo = NULL;
3994         val->task = task;
3995         val->action = action;
3996         val->arg = arg;
3997         val->labels = 0;
3998         val->currentset = NULL;
3999         val->keyset = NULL;
4000         val->dsset = NULL;
4001         dns_rdataset_init(&val->dlv);
4002         val->seensig = ISC_FALSE;
4003         val->havedlvsep = ISC_FALSE;
4004         val->depth = 0;
4005         val->authcount = 0;
4006         val->authfail = 0;
4007         val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
4008         dns_rdataset_init(&val->frdataset);
4009         dns_rdataset_init(&val->fsigrdataset);
4010         dns_fixedname_init(&val->wild);
4011         dns_fixedname_init(&val->nearest);
4012         dns_fixedname_init(&val->closest);
4013         ISC_LINK_INIT(val, link);
4014         val->magic = VALIDATOR_MAGIC;
4015
4016         if ((options & DNS_VALIDATOR_DEFER) == 0)
4017                 isc_task_send(task, ISC_EVENT_PTR(&event));
4018
4019         *validatorp = val;
4020
4021         return (ISC_R_SUCCESS);
4022
4023  cleanup_event:
4024         isc_task_detach(&tclone);
4025         isc_event_free(ISC_EVENT_PTR(&event));
4026
4027  cleanup_val:
4028         dns_view_weakdetach(&val->view);
4029         isc_mem_put(view->mctx, val, sizeof(*val));
4030
4031         return (result);
4032 }
4033
4034 void
4035 dns_validator_send(dns_validator_t *validator) {
4036         isc_event_t *event;
4037         REQUIRE(VALID_VALIDATOR(validator));
4038
4039         LOCK(&validator->lock);
4040
4041         INSIST((validator->options & DNS_VALIDATOR_DEFER) != 0);
4042         event = (isc_event_t *)validator->event;
4043         validator->options &= ~DNS_VALIDATOR_DEFER;
4044         UNLOCK(&validator->lock);
4045
4046         isc_task_send(validator->task, ISC_EVENT_PTR(&event));
4047 }
4048
4049 void
4050 dns_validator_cancel(dns_validator_t *validator) {
4051         REQUIRE(VALID_VALIDATOR(validator));
4052
4053         LOCK(&validator->lock);
4054
4055         validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
4056
4057         if ((validator->attributes & VALATTR_CANCELED) == 0) {
4058                 validator->attributes |= VALATTR_CANCELED;
4059                 if (validator->event != NULL) {
4060                         if (validator->fetch != NULL)
4061                                 dns_resolver_cancelfetch(validator->fetch);
4062
4063                         if (validator->subvalidator != NULL)
4064                                 dns_validator_cancel(validator->subvalidator);
4065                         if ((validator->options & DNS_VALIDATOR_DEFER) != 0) {
4066                                 validator->options &= ~DNS_VALIDATOR_DEFER;
4067                                 validator_done(validator, ISC_R_CANCELED);
4068                         }
4069                 }
4070         }
4071         UNLOCK(&validator->lock);
4072 }
4073
4074 static void
4075 destroy(dns_validator_t *val) {
4076         isc_mem_t *mctx;
4077
4078         REQUIRE(SHUTDOWN(val));
4079         REQUIRE(val->event == NULL);
4080         REQUIRE(val->fetch == NULL);
4081
4082         if (val->keynode != NULL)
4083                 dns_keytable_detachkeynode(val->keytable, &val->keynode);
4084         else if (val->key != NULL)
4085                 dst_key_free(&val->key);
4086         if (val->keytable != NULL)
4087                 dns_keytable_detach(&val->keytable);
4088         if (val->subvalidator != NULL)
4089                 dns_validator_destroy(&val->subvalidator);
4090         if (val->havedlvsep)
4091                 dns_rdataset_disassociate(&val->dlv);
4092         if (dns_rdataset_isassociated(&val->frdataset))
4093                 dns_rdataset_disassociate(&val->frdataset);
4094         if (dns_rdataset_isassociated(&val->fsigrdataset))
4095                 dns_rdataset_disassociate(&val->fsigrdataset);
4096         mctx = val->view->mctx;
4097         if (val->siginfo != NULL)
4098                 isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo));
4099         DESTROYLOCK(&val->lock);
4100         dns_view_weakdetach(&val->view);
4101         val->magic = 0;
4102         isc_mem_put(mctx, val, sizeof(*val));
4103 }
4104
4105 void
4106 dns_validator_destroy(dns_validator_t **validatorp) {
4107         dns_validator_t *val;
4108         isc_boolean_t want_destroy = ISC_FALSE;
4109
4110         REQUIRE(validatorp != NULL);
4111         val = *validatorp;
4112         REQUIRE(VALID_VALIDATOR(val));
4113
4114         LOCK(&val->lock);
4115
4116         val->attributes |= VALATTR_SHUTDOWN;
4117         validator_log(val, ISC_LOG_DEBUG(3), "dns_validator_destroy");
4118
4119         want_destroy = exit_check(val);
4120
4121         UNLOCK(&val->lock);
4122
4123         if (want_destroy)
4124                 destroy(val);
4125
4126         *validatorp = NULL;
4127 }
4128
4129 static void
4130 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
4131                isc_logmodule_t *module, int level, const char *fmt, va_list ap)
4132 {
4133         char msgbuf[2048];
4134         static const char spaces[] = "        *";
4135         int depth = val->depth * 2;
4136
4137         vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
4138
4139         if ((unsigned int) depth >= sizeof spaces)
4140                 depth = sizeof spaces - 1;
4141
4142         if (val->event != NULL && val->event->name != NULL) {
4143                 char namebuf[DNS_NAME_FORMATSIZE];
4144                 char typebuf[DNS_RDATATYPE_FORMATSIZE];
4145
4146                 dns_name_format(val->event->name, namebuf, sizeof(namebuf));
4147                 dns_rdatatype_format(val->event->type, typebuf,
4148                                      sizeof(typebuf));
4149                 isc_log_write(dns_lctx, category, module, level,
4150                               "%.*svalidating @%p: %s %s: %s", depth, spaces,
4151                               val, namebuf, typebuf, msgbuf);
4152         } else {
4153                 isc_log_write(dns_lctx, category, module, level,
4154                               "%.*svalidator @%p: %s", depth, spaces,
4155                                val, msgbuf);
4156         }
4157 }
4158
4159 static void
4160 validator_log(dns_validator_t *val, int level, const char *fmt, ...) {
4161         va_list ap;
4162
4163         if (! isc_log_wouldlog(dns_lctx, level))
4164                 return;
4165
4166         va_start(ap, fmt);
4167
4168         validator_logv(val, DNS_LOGCATEGORY_DNSSEC,
4169                        DNS_LOGMODULE_VALIDATOR, level, fmt, ap);
4170         va_end(ap);
4171 }
4172
4173 static void
4174 validator_logcreate(dns_validator_t *val,
4175                     dns_name_t *name, dns_rdatatype_t type,
4176                     const char *caller, const char *operation)
4177 {
4178         char namestr[DNS_NAME_FORMATSIZE];
4179         char typestr[DNS_RDATATYPE_FORMATSIZE];
4180
4181         dns_name_format(name, namestr, sizeof(namestr));
4182         dns_rdatatype_format(type, typestr, sizeof(typestr));
4183         validator_log(val, ISC_LOG_DEBUG(9), "%s: creating %s for %s %s",
4184                       caller, operation, namestr, typestr);
4185 }