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