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