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