Merge from vendor branch NTPD:
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / dns / validator.c
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2000-2002  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and 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.91.2.8 2004/04/15 02:16:28 marka Exp $ */
19
20 #include <config.h>
21
22 #include <isc/mem.h>
23 #include <isc/print.h>
24 #include <isc/task.h>
25 #include <isc/util.h>
26
27 #include <dns/db.h>
28 #include <dns/dnssec.h>
29 #include <dns/events.h>
30 #include <dns/keytable.h>
31 #include <dns/log.h>
32 #include <dns/message.h>
33 #include <dns/nxt.h>
34 #include <dns/rdata.h>
35 #include <dns/rdatastruct.h>
36 #include <dns/rdataset.h>
37 #include <dns/rdatatype.h>
38 #include <dns/resolver.h>
39 #include <dns/result.h>
40 #include <dns/validator.h>
41 #include <dns/view.h>
42
43 #define VALIDATOR_MAGIC                 ISC_MAGIC('V', 'a', 'l', '?')
44 #define VALID_VALIDATOR(v)              ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
45
46 #define VALATTR_SHUTDOWN                0x01
47 #define VALATTR_FOUNDNONEXISTENCE       0x02
48 #define VALATTR_TRIEDVERIFY             0x04
49 #define SHUTDOWN(v)             (((v)->attributes & VALATTR_SHUTDOWN) != 0)
50
51 static void
52 nullkeyvalidated(isc_task_t *task, isc_event_t *event);
53
54 static inline isc_boolean_t
55 containsnullkey(dns_validator_t *val, dns_rdataset_t *rdataset);
56
57 static inline isc_result_t
58 get_dst_key(dns_validator_t *val, dns_rdata_sig_t *siginfo,
59             dns_rdataset_t *rdataset);
60
61 static inline isc_result_t
62 validate(dns_validator_t *val, isc_boolean_t resume);
63
64 static inline isc_result_t
65 nxtvalidate(dns_validator_t *val, isc_boolean_t resume);
66
67 static inline isc_result_t
68 proveunsecure(dns_validator_t *val, isc_boolean_t resume);
69
70 static void
71 validator_log(dns_validator_t *val, int level, const char *fmt, ...)
72      ISC_FORMAT_PRINTF(3, 4);
73
74 static void
75 validator_done(dns_validator_t *val, isc_result_t result) {
76         isc_task_t *task;
77
78         if (val->event == NULL)
79                 return;
80
81         /*
82          * Caller must be holding the lock.
83          */
84
85         val->event->result = result;
86         task = val->event->ev_sender;
87         val->event->ev_sender = val;
88         val->event->ev_type = DNS_EVENT_VALIDATORDONE;
89         val->event->ev_action = val->action;
90         val->event->ev_arg = val->arg;
91         isc_task_sendanddetach(&task, (isc_event_t **)&val->event);
92
93 }
94
95 static void
96 auth_nonpending(dns_message_t *message) {
97         isc_result_t result;
98         dns_name_t *name;
99         dns_rdataset_t *rdataset;
100
101         for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
102              result == ISC_R_SUCCESS;
103              result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
104         {
105                 name = NULL;
106                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
107                 for (rdataset = ISC_LIST_HEAD(name->list);
108                      rdataset != NULL;
109                      rdataset = ISC_LIST_NEXT(rdataset, link))
110                 {
111                         if (rdataset->trust == dns_trust_pending)
112                                 rdataset->trust = dns_trust_authauthority;
113                 }
114         }
115 }
116
117 static void
118 fetch_callback_validator(isc_task_t *task, isc_event_t *event) {
119         dns_fetchevent_t *devent;
120         dns_validator_t *val;
121         dns_rdataset_t *rdataset;
122         isc_result_t result;
123         isc_result_t eresult;
124
125         UNUSED(task);
126         INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
127         devent = (dns_fetchevent_t *)event;
128         val = devent->ev_arg;
129         rdataset = &val->frdataset;
130         eresult = devent->result;
131
132         isc_event_free(&event);
133         dns_resolver_destroyfetch(&val->fetch);
134
135         if (SHUTDOWN(val)) {
136                 dns_validator_destroy(&val);
137                 return;
138         }
139
140         if (val->event == NULL) {
141                 validator_log(val, ISC_LOG_DEBUG(3),
142                               "fetch_callback_validator: event == NULL");
143                 return;
144         }
145
146         validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_validator");
147         LOCK(&val->lock);
148         if (eresult == ISC_R_SUCCESS) {
149                 validator_log(val, ISC_LOG_DEBUG(3),
150                               "keyset with trust %d", rdataset->trust);
151                 /*
152                  * Only extract the dst key if the keyset is secure.
153                  */
154                 if (rdataset->trust >= dns_trust_secure) {
155                         result = get_dst_key(val, val->siginfo, rdataset);
156                         if (result == ISC_R_SUCCESS)
157                                 val->keyset = &val->frdataset;
158                 }
159                 result = validate(val, ISC_TRUE);
160                 if (result != DNS_R_WAIT) {
161                         validator_done(val, result);
162                         goto out;
163                 }
164         } else {
165                 validator_log(val, ISC_LOG_DEBUG(3),
166                               "fetch_callback_validator: got %s",
167                               dns_result_totext(eresult));
168                 validator_done(val, DNS_R_NOVALIDKEY);
169         }
170
171  out:
172         UNLOCK(&val->lock);
173         /*
174          * Free stuff from the event.
175          */
176         if (dns_rdataset_isassociated(&val->frdataset) &&
177             val->keyset != &val->frdataset)
178                 dns_rdataset_disassociate(&val->frdataset);
179         if (dns_rdataset_isassociated(&val->fsigrdataset))
180                 dns_rdataset_disassociate(&val->fsigrdataset);
181 }
182
183 static void
184 fetch_callback_nullkey(isc_task_t *task, isc_event_t *event) {
185         dns_fetchevent_t *devent;
186         dns_validator_t *val;
187         dns_rdataset_t *rdataset, *sigrdataset;
188         isc_result_t result;
189         isc_result_t eresult;
190
191         UNUSED(task);
192         INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
193         devent = (dns_fetchevent_t *)event;
194         val = devent->ev_arg;
195         rdataset = &val->frdataset;
196         sigrdataset = &val->fsigrdataset;
197         eresult = devent->result;
198
199         dns_resolver_destroyfetch(&val->fetch);
200
201         if (SHUTDOWN(val)) {
202                 dns_validator_destroy(&val);
203                 isc_event_free(&event);
204                 return;
205         }
206
207         if (val->event == NULL) {
208                 validator_log(val, ISC_LOG_DEBUG(3),
209                               "fetch_callback_nullkey: event == NULL");
210                 isc_event_free(&event);
211                 return;
212         }
213
214         validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_nullkey");
215
216         LOCK(&val->lock);
217         if (eresult == ISC_R_SUCCESS) {
218                 if (!containsnullkey(val, rdataset)) {
219                         /*
220                          * No null key.
221                          */
222                         validator_log(val, ISC_LOG_DEBUG(3),
223                                       "found a keyset, no null key");
224                         result = proveunsecure(val, ISC_TRUE);
225                         if (result != DNS_R_WAIT)
226                                 validator_done(val, result);
227                         else {
228                                 /*
229                                  * Don't free rdataset & sigrdataset, since
230                                  * they'll be freed in nullkeyvalidated.
231                                  */
232                                 isc_event_free(&event);
233                                 UNLOCK(&val->lock);
234                                 return;
235                         }
236                 } else {
237                         validator_log(val, ISC_LOG_DEBUG(3),
238                                       "found a keyset with a null key");
239                         if (rdataset->trust >= dns_trust_secure) {
240                                 validator_log(val, ISC_LOG_DEBUG(3),
241                                               "insecurity proof succeeded");
242                                 val->event->rdataset->trust = dns_trust_answer;
243                                 validator_done(val, ISC_R_SUCCESS);
244                         } else if (!dns_rdataset_isassociated(sigrdataset)) {
245                                 validator_log(val, ISC_LOG_DEBUG(3),
246                                               "insecurity proof failed");
247                                 validator_done(val, DNS_R_NOTINSECURE);
248                         } else {
249                                 dns_name_t *tname;
250                                 tname = dns_fixedname_name(&devent->foundname);
251                                 result = dns_validator_create(val->view, tname,
252                                                            dns_rdatatype_key,
253                                                            rdataset,
254                                                            sigrdataset, NULL,
255                                                            0, val->task,
256                                                            nullkeyvalidated,
257                                                            val,
258                                                            &val->keyvalidator);
259                                 if (result != ISC_R_SUCCESS)
260                                         validator_done(val, result);
261                                 /*
262                                  * Don't free rdataset & sigrdataset, since
263                                  * they'll be freed in nullkeyvalidated.
264                                  */
265                                 isc_event_free(&event);
266                                 UNLOCK(&val->lock);
267                                 return;
268                         }
269                 }
270         } else if (eresult ==  DNS_R_NCACHENXDOMAIN ||
271                    eresult == DNS_R_NCACHENXRRSET ||
272                    eresult == DNS_R_NXDOMAIN ||
273                    eresult == DNS_R_NXRRSET)
274         {
275                 /*
276                  * No keys.
277                  */
278                 validator_log(val, ISC_LOG_DEBUG(3),
279                               "no keys found");
280                 result = proveunsecure(val, ISC_TRUE);
281                 if (result != DNS_R_WAIT)
282                         validator_done(val, result);
283         } else {
284                 validator_log(val, ISC_LOG_DEBUG(3),
285                               "fetch_callback_nullkey: got %s",
286                               dns_result_totext(eresult));
287                 validator_done(val, DNS_R_NOVALIDKEY);
288         }
289         UNLOCK(&val->lock);
290
291         /*
292          * Free stuff from the event.
293          */
294         if (dns_rdataset_isassociated(&val->frdataset))
295                 dns_rdataset_disassociate(&val->frdataset);
296         if (dns_rdataset_isassociated(&val->fsigrdataset))
297                 dns_rdataset_disassociate(&val->fsigrdataset);
298         isc_event_free(&event);
299 }
300
301 static void
302 keyvalidated(isc_task_t *task, isc_event_t *event) {
303         dns_validatorevent_t *devent;
304         dns_validator_t *val;
305         isc_result_t result;
306         isc_result_t eresult;
307
308         UNUSED(task);
309         INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
310
311         devent = (dns_validatorevent_t *)event;
312         val = devent->ev_arg;
313         eresult = devent->result;
314
315         isc_event_free(&event);
316
317         if (SHUTDOWN(val)) {
318                 dns_validator_destroy(&val);
319                 return;
320         }
321
322         if (val->event == NULL)
323                 return;
324
325         validator_log(val, ISC_LOG_DEBUG(3), "in keyvalidated");
326         LOCK(&val->lock);
327         if (eresult == ISC_R_SUCCESS) {
328                 validator_log(val, ISC_LOG_DEBUG(3),
329                               "keyset with trust %d", val->frdataset.trust);
330                 /*
331                  * Only extract the dst key if the keyset is secure.
332                  */
333                 if (val->frdataset.trust >= dns_trust_secure)
334                         (void) get_dst_key(val, val->siginfo, &val->frdataset);
335                 result = validate(val, ISC_TRUE);
336                 if (result != DNS_R_WAIT) {
337                         validator_done(val, result);
338                         goto out;
339                 }
340         } else {
341                 validator_log(val, ISC_LOG_DEBUG(3),
342                               "keyvalidated: got %s",
343                               dns_result_totext(eresult));
344                 validator_done(val, eresult);
345         }
346  out:
347
348         UNLOCK(&val->lock);
349         dns_validator_destroy(&val->keyvalidator);
350         /*
351          * Free stuff from the event.
352          */
353         if (dns_rdataset_isassociated(&val->frdataset))
354                 dns_rdataset_disassociate(&val->frdataset);
355         if (dns_rdataset_isassociated(&val->fsigrdataset))
356                 dns_rdataset_disassociate(&val->fsigrdataset);
357 }
358
359 static isc_boolean_t
360 nxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,
361                       dns_rdataset_t *nxtset, dns_rdataset_t *signxtset)
362 {
363         int order;
364         dns_rdata_t rdata = DNS_RDATA_INIT;
365         isc_boolean_t isnxdomain;
366         isc_result_t result;
367
368         INSIST(DNS_MESSAGE_VALID(val->event->message));
369
370         if (val->event->message->rcode == dns_rcode_nxdomain)
371                 isnxdomain = ISC_TRUE;
372         else
373                 isnxdomain = ISC_FALSE;
374
375         result = dns_rdataset_first(nxtset);
376         if (result != ISC_R_SUCCESS) {
377                 validator_log(val, ISC_LOG_DEBUG(3),
378                         "failure processing NXT set");
379                 return (ISC_FALSE);
380         }
381         dns_rdataset_current(nxtset, &rdata);
382
383         validator_log(val, ISC_LOG_DEBUG(3),
384                       "looking for relevant nxt");
385         order = dns_name_compare(val->event->name, nxtname);
386         if (order == 0) {
387                 /*
388                  * The names are the same.  Look for the type present bit.
389                  */
390                 if (isnxdomain) {
391                         validator_log(val, ISC_LOG_DEBUG(3),
392                                       "NXT record seen at nonexistent name");
393                         return (ISC_FALSE);
394                 }
395                 if (val->event->type >= 128) {
396                         validator_log(val, ISC_LOG_DEBUG(3), "invalid type %d",
397                                       val->event->type);
398                         return (ISC_FALSE);
399                 }
400
401                 if (dns_nxt_typepresent(&rdata, val->event->type)) {
402                         validator_log(val, ISC_LOG_DEBUG(3),
403                                       "type should not be present");
404                         return (ISC_FALSE);
405                 }
406                 validator_log(val, ISC_LOG_DEBUG(3), "nxt bitmask ok");
407         } else if (order > 0) {
408                 dns_rdata_nxt_t nxt;
409
410                 /*
411                  * The NXT owner name is less than the nonexistent name.
412                  */
413                 if (!isnxdomain) {
414                         validator_log(val, ISC_LOG_DEBUG(3),
415                                       "missing NXT record at name");
416                         return (ISC_FALSE);
417                 }
418                 if (dns_name_issubdomain(val->event->name, nxtname) &&
419                     dns_nxt_typepresent(&rdata, dns_rdatatype_ns) &&
420                     !dns_nxt_typepresent(&rdata, dns_rdatatype_soa))
421                 {
422                         /*
423                          * This NXT record is from somewhere higher in
424                          * the DNS, and at the parent of a delegation.
425                          * It can not be legitimately used here.
426                          */
427                         validator_log(val, ISC_LOG_DEBUG(3),
428                                       "ignoring parent nxt");
429                         return (ISC_FALSE);
430                 }
431                 result = dns_rdata_tostruct(&rdata, &nxt, NULL);
432                 if (result != ISC_R_SUCCESS)
433                         return (ISC_FALSE);
434                 dns_rdata_reset(&rdata);
435                 order = dns_name_compare(val->event->name, &nxt.next);
436                 if (order >= 0) {
437                         /*
438                          * The NXT next name is less than the nonexistent
439                          * name.  This is only ok if the next name is the zone
440                          * name.
441                          */
442                         dns_rdata_sig_t siginfo;
443                         result = dns_rdataset_first(signxtset);
444                         if (result != ISC_R_SUCCESS) {
445                                 validator_log(val, ISC_LOG_DEBUG(3),
446                                         "failure processing SIG NXT set");
447                                 dns_rdata_freestruct(&nxt);
448                                 return (ISC_FALSE);
449                         }
450                         dns_rdataset_current(signxtset, &rdata);
451                         result = dns_rdata_tostruct(&rdata, &siginfo, NULL);
452                         if (result != ISC_R_SUCCESS) {
453                                 validator_log(val, ISC_LOG_DEBUG(3),
454                                         "failure processing SIG NXT set");
455                                 dns_rdata_freestruct(&nxt);
456                                 return (ISC_FALSE);
457                         }
458                         if (!dns_name_equal(&siginfo.signer, &nxt.next)) {
459                                 validator_log(val, ISC_LOG_DEBUG(3),
460                                         "next name is not greater");
461                                 dns_rdata_freestruct(&nxt);
462                                 return (ISC_FALSE);
463                         }
464                         validator_log(val, ISC_LOG_DEBUG(3),
465                                       "nxt points to zone apex, ok");
466                 }
467                 dns_rdata_freestruct(&nxt);
468                 validator_log(val, ISC_LOG_DEBUG(3),
469                               "nxt range ok");
470         } else {
471                 validator_log(val, ISC_LOG_DEBUG(3),
472                         "nxt owner name is not less");
473                 /*
474                  * The NXT owner name is greater than the supposedly
475                  * nonexistent name.  This NXT is irrelevant.
476                  */
477                 return (ISC_FALSE);
478         }
479         return (ISC_TRUE);
480 }
481
482 static void
483 authvalidated(isc_task_t *task, isc_event_t *event) {
484         dns_validatorevent_t *devent;
485         dns_validator_t *val;
486         dns_rdataset_t *rdataset, *sigrdataset;
487         isc_result_t result;
488         isc_result_t eresult;
489
490         UNUSED(task);
491         INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
492
493         devent = (dns_validatorevent_t *)event;
494         rdataset = devent->rdataset;
495         sigrdataset = devent->sigrdataset;
496         val = devent->ev_arg;
497         eresult = devent->result;
498         dns_validator_destroy(&val->authvalidator);
499
500         if (SHUTDOWN(val)) {
501                 dns_validator_destroy(&val);
502                 return;
503         }
504
505         if (val->event == NULL)
506                 return;
507
508         validator_log(val, ISC_LOG_DEBUG(3), "in authvalidated");
509         LOCK(&val->lock);
510         if (eresult != ISC_R_SUCCESS) {
511                 validator_log(val, ISC_LOG_DEBUG(3),
512                               "authvalidated: got %s",
513                               dns_result_totext(eresult));
514                 result = nxtvalidate(val, ISC_TRUE);
515                 if (result != DNS_R_WAIT)
516                         validator_done(val, result);
517         } else {
518                 if (rdataset->type == dns_rdatatype_nxt &&
519                     nxtprovesnonexistence(val, devent->name, rdataset,
520                                           sigrdataset))
521                         val->attributes |= VALATTR_FOUNDNONEXISTENCE;
522
523                 result = nxtvalidate(val, ISC_TRUE);
524                 if (result != DNS_R_WAIT)
525                         validator_done(val, result);
526         }
527         UNLOCK(&val->lock);
528
529         /*
530          * Free stuff from the event.
531          */
532         isc_event_free(&event);
533 }
534
535 static void
536 negauthvalidated(isc_task_t *task, isc_event_t *event) {
537         dns_validatorevent_t *devent;
538         dns_validator_t *val;
539         isc_result_t eresult;
540
541         UNUSED(task);
542         INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
543
544         devent = (dns_validatorevent_t *)event;
545         val = devent->ev_arg;
546         eresult = devent->result;
547         isc_event_free(&event);
548         dns_validator_destroy(&val->authvalidator);
549
550         if (SHUTDOWN(val)) {
551                 dns_validator_destroy(&val);
552                 return;
553         }
554
555         if (val->event == NULL)
556                 return;
557
558         validator_log(val, ISC_LOG_DEBUG(3), "in negauthvalidated");
559         LOCK(&val->lock);
560         if (eresult == ISC_R_SUCCESS) {
561                 val->attributes |= VALATTR_FOUNDNONEXISTENCE;
562                 validator_log(val, ISC_LOG_DEBUG(3),
563                               "nonexistence proof found");
564                 auth_nonpending(val->event->message);
565                 validator_done(val, ISC_R_SUCCESS);
566         } else {
567                 validator_log(val, ISC_LOG_DEBUG(3),
568                               "negauthvalidated: got %s",
569                               dns_result_totext(eresult));
570                 validator_done(val, eresult);
571         }
572         UNLOCK(&val->lock);
573
574         /*
575          * Free stuff from the event.
576          */
577         if (dns_rdataset_isassociated(&val->frdataset))
578                 dns_rdataset_disassociate(&val->frdataset);
579 }
580
581 static void
582 nullkeyvalidated(isc_task_t *task, isc_event_t *event) {
583         dns_validatorevent_t *devent;
584         dns_validator_t *val;
585         isc_result_t result;
586         isc_result_t eresult;
587
588         UNUSED(task);
589         INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
590
591         devent = (dns_validatorevent_t *)event;
592         val = devent->ev_arg;
593         eresult = devent->result;
594
595         dns_name_free(devent->name, val->view->mctx);
596         isc_mem_put(val->view->mctx, devent->name, sizeof(dns_name_t));
597         dns_validator_destroy(&val->keyvalidator);
598         isc_event_free(&event);
599
600         if (SHUTDOWN(val)) {
601                 dns_validator_destroy(&val);
602                 return;
603         }
604
605         if (val->event == NULL)
606                 return;
607
608         validator_log(val, ISC_LOG_DEBUG(3), "in nullkeyvalidated");
609         LOCK(&val->lock);
610         if (eresult == ISC_R_SUCCESS) {
611                 validator_log(val, ISC_LOG_DEBUG(3),
612                               "proved that name is in an unsecure domain");
613                 validator_log(val, ISC_LOG_DEBUG(3), "marking as answer");
614                 val->event->rdataset->trust = dns_trust_answer;
615                 validator_done(val, ISC_R_SUCCESS);
616         } else {
617                 result = proveunsecure(val, ISC_TRUE);
618                 if (result != DNS_R_WAIT)
619                         validator_done(val, result);
620         }
621         UNLOCK(&val->lock);
622
623         /*
624          * Free stuff from the event.
625          */
626         if (dns_rdataset_isassociated(&val->frdataset))
627                 dns_rdataset_disassociate(&val->frdataset);
628         if (dns_rdataset_isassociated(&val->fsigrdataset))
629                 dns_rdataset_disassociate(&val->fsigrdataset);
630 }
631
632 /*
633  * Try to find a null zone key among those in 'rdataset'.  If found, build
634  * a dst_key_t for it and point val->key at it.
635  */
636 static inline isc_boolean_t
637 containsnullkey(dns_validator_t *val, dns_rdataset_t *rdataset) {
638         isc_result_t result;
639         dst_key_t *key = NULL;
640         isc_buffer_t b;
641         dns_rdata_t rdata = DNS_RDATA_INIT;
642         isc_boolean_t found = ISC_FALSE;
643
644         result = dns_rdataset_first(rdataset);
645         if (result != ISC_R_SUCCESS)
646                 return (ISC_FALSE);
647         while (result == ISC_R_SUCCESS && !found) {
648                 dns_rdataset_current(rdataset, &rdata);
649                 isc_buffer_init(&b, rdata.data, rdata.length);
650                 isc_buffer_add(&b, rdata.length);
651                 key = NULL;
652                 /*
653                  * The key name is unimportant, so we can avoid any name/text
654                  * conversion.
655                  */
656                 result = dst_key_fromdns(dns_rootname, rdata.rdclass, &b,
657                                          val->view->mctx, &key);
658                 if (result != ISC_R_SUCCESS)
659                         continue;
660                 if (dst_key_isnullkey(key))
661                         found = ISC_TRUE;
662                 dst_key_free(&key);
663                 dns_rdata_reset(&rdata);
664                 result = dns_rdataset_next(rdataset);
665         }
666         return (found);
667 }
668
669 /*
670  * Try to find a key that could have signed 'siginfo' among those
671  * in 'rdataset'.  If found, build a dst_key_t for it and point
672  * val->key at it.
673  *
674  * If val->key is non-NULL, this returns the next matching key.
675  */
676 static inline isc_result_t
677 get_dst_key(dns_validator_t *val, dns_rdata_sig_t *siginfo,
678             dns_rdataset_t *rdataset)
679 {
680         isc_result_t result;
681         isc_buffer_t b;
682         dns_rdata_t rdata = DNS_RDATA_INIT;
683         dst_key_t *oldkey = val->key;
684         isc_boolean_t foundold;
685
686         if (oldkey == NULL)
687                 foundold = ISC_TRUE;
688         else {
689                 foundold = ISC_FALSE;
690                 val->key = NULL;
691         }
692
693         result = dns_rdataset_first(rdataset);
694         if (result != ISC_R_SUCCESS)
695                 goto failure;
696         do {
697                 dns_rdataset_current(rdataset, &rdata);
698
699                 isc_buffer_init(&b, rdata.data, rdata.length);
700                 isc_buffer_add(&b, rdata.length);
701                 INSIST(val->key == NULL);
702                 result = dst_key_fromdns(&siginfo->signer, rdata.rdclass, &b,
703                                          val->view->mctx, &val->key);
704                 if (result != ISC_R_SUCCESS)
705                         goto failure;
706                 if (siginfo->algorithm ==
707                     (dns_secalg_t)dst_key_alg(val->key) &&
708                     siginfo->keyid ==
709                     (dns_keytag_t)dst_key_id(val->key) &&
710                     dst_key_iszonekey(val->key))
711                 {
712                         if (foundold)
713                                 /*
714                                  * This is the key we're looking for.
715                                  */
716                                 return (ISC_R_SUCCESS);
717                         else if (dst_key_compare(oldkey, val->key) == ISC_TRUE)
718                         {
719                                 foundold = ISC_TRUE;
720                                 dst_key_free(&oldkey);
721                         }
722                 }
723                 dst_key_free(&val->key);
724                 dns_rdata_reset(&rdata);
725                 result = dns_rdataset_next(rdataset);
726         } while (result == ISC_R_SUCCESS);
727         if (result == ISC_R_NOMORE)
728                 result = ISC_R_NOTFOUND;
729
730  failure:
731         if (oldkey != NULL)
732                 dst_key_free(&oldkey);
733
734         return (result);
735 }
736
737 static inline isc_result_t
738 get_key(dns_validator_t *val, dns_rdata_sig_t *siginfo) {
739         isc_result_t result;
740         dns_validatorevent_t *event;
741         unsigned int nbits, nlabels;
742         int order;
743         dns_namereln_t namereln;
744
745         event = val->event;
746
747         /*
748          * Is the key name appropriate for this signature?
749          * This previously checked for self-signed keys.  Now, if the key
750          * is self signed with a preconfigured key, it's ok.
751          */
752         namereln = dns_name_fullcompare(event->name, &siginfo->signer,
753                                         &order, &nlabels, &nbits);
754         if (namereln != dns_namereln_subdomain &&
755             namereln != dns_namereln_equal) {
756                 /*
757                  * The key name is not at the same level
758                  * as 'rdataset', nor is it closer to the
759                  * DNS root.
760                  */
761                 return (DNS_R_CONTINUE);
762         }
763
764         /*
765          * Is the key used for the signature a security root?
766          */
767         INSIST(val->keynode == NULL);
768         val->keytable = val->view->secroots;
769         result = dns_keytable_findkeynode(val->view->secroots,
770                                           &siginfo->signer,
771                                           siginfo->algorithm, siginfo->keyid,
772                                           &val->keynode);
773         if (result == ISC_R_SUCCESS) {
774                 /*
775                  * The key is a security root.
776                  */
777                 val->key = dns_keynode_key(val->keynode);
778                 return (ISC_R_SUCCESS);
779         }
780
781         /*
782          * A key set may not be self-signed unless the signing key is a
783          * security root.  We don't want a KEY RR to authenticate
784          * itself, so we ignore the signature if it was not made by
785          * an ancestor of the KEY or a preconfigured key.
786          */
787         if (event->rdataset->type == dns_rdatatype_key &&
788             namereln == dns_namereln_equal)
789         {
790                 validator_log(val, ISC_LOG_DEBUG(3),
791                               "keyset was self-signed but not preconfigured");
792                 return (DNS_R_CONTINUE);
793         }
794
795         /*
796          * Do we know about this key?
797          */
798         if (dns_rdataset_isassociated(&val->frdataset))
799                 dns_rdataset_disassociate(&val->frdataset);
800         if (dns_rdataset_isassociated(&val->fsigrdataset))
801                 dns_rdataset_disassociate(&val->fsigrdataset);
802         result = dns_view_simplefind(val->view, &siginfo->signer,
803                                      dns_rdatatype_key, 0,
804                                      DNS_DBFIND_PENDINGOK, ISC_FALSE,
805                                      &val->frdataset, &val->fsigrdataset);
806         if (result == ISC_R_SUCCESS) {
807                 /*
808                  * We have an rrset for the given keyname.
809                  */
810                 val->keyset = &val->frdataset;
811                 if (val->frdataset.trust == dns_trust_pending &&
812                     dns_rdataset_isassociated(&val->fsigrdataset))
813                 {
814                         /*
815                          * We know the key but haven't validated it yet.
816                          */
817                         result = dns_validator_create(val->view,
818                                                       &siginfo->signer,
819                                                       dns_rdatatype_key,
820                                                       &val->frdataset,
821                                                       &val->fsigrdataset,
822                                                       NULL,
823                                                       0,
824                                                       val->task,
825                                                       keyvalidated,
826                                                       val,
827                                                       &val->keyvalidator);
828                         if (result != ISC_R_SUCCESS)
829                                 return (result);
830                         return (DNS_R_WAIT);
831                 } else if (val->frdataset.trust == dns_trust_pending) {
832                         /*
833                          * Having a pending key with no signature means that
834                          * something is broken.
835                          */
836                         result = DNS_R_CONTINUE;
837                 } else if (val->frdataset.trust < dns_trust_secure) {
838                         /*
839                          * The key is legitimately insecure.  There's no
840                          * point in even attempting verification.
841                          */
842                         val->key = NULL;
843                         result = ISC_R_SUCCESS;
844                 } else {
845                         /*
846                          * See if we've got the key used in the signature.
847                          */
848                         validator_log(val, ISC_LOG_DEBUG(3),
849                                       "keyset with trust %d",
850                                       val->frdataset.trust);
851                         result = get_dst_key(val, siginfo, val->keyset);
852                         if (result != ISC_R_SUCCESS) {
853                                 /*
854                                  * Either the key we're looking for is not
855                                  * in the rrset, or something bad happened.
856                                  * Give up.
857                                  */
858                                 result = DNS_R_CONTINUE;
859                         }
860                 }
861         } else if (result == ISC_R_NOTFOUND) {
862                 /*
863                  * We don't know anything about this key.
864                  */
865                 val->fetch = NULL;
866                 result = dns_resolver_createfetch(val->view->resolver,
867                                                   &siginfo->signer,
868                                                   dns_rdatatype_key,
869                                                   NULL, NULL, NULL, 0,
870                                                   val->event->ev_sender,
871                                                   fetch_callback_validator,
872                                                   val,
873                                                   &val->frdataset,
874                                                   &val->fsigrdataset,
875                                                   &val->fetch);
876                 if (result != ISC_R_SUCCESS)
877                         return (result);
878                 return (DNS_R_WAIT);
879         } else if (result ==  DNS_R_NCACHENXDOMAIN ||
880                    result == DNS_R_NCACHENXRRSET ||
881                    result == DNS_R_NXDOMAIN ||
882                    result == DNS_R_NXRRSET)
883         {
884                 /*
885                  * This key doesn't exist.
886                  */
887                 result = DNS_R_CONTINUE;
888         }
889
890         if (dns_rdataset_isassociated(&val->frdataset) &&
891             val->keyset != &val->frdataset)
892                 dns_rdataset_disassociate(&val->frdataset);
893         if (dns_rdataset_isassociated(&val->fsigrdataset))
894                 dns_rdataset_disassociate(&val->fsigrdataset);
895
896         return (result);
897 }
898
899 /*
900  * If the rdataset being validated is a key set, is each key a security root?
901  */
902 static isc_boolean_t
903 issecurityroot(dns_validator_t *val) {
904         dns_name_t *name;
905         dns_rdataset_t *rdataset;
906         isc_mem_t *mctx;
907         dns_keytable_t *secroots;
908         dns_rdata_t rdata = DNS_RDATA_INIT;
909         isc_result_t result;
910         dns_keynode_t *keynode, *nextnode;
911         dst_key_t *key, *secrootkey;
912         isc_boolean_t match = ISC_FALSE;
913
914         name = val->event->name;
915         rdataset = val->event->rdataset;
916         mctx = val->view->mctx;
917         secroots = val->view->secroots;
918
919         for (result = dns_rdataset_first(rdataset);
920              result == ISC_R_SUCCESS;
921              result = dns_rdataset_next(rdataset))
922         {
923                 dns_rdataset_current(rdataset, &rdata);
924                 key = NULL;
925                 result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &key);
926                 dns_rdata_reset(&rdata);
927                 if (result != ISC_R_SUCCESS)
928                          continue;
929                 keynode = NULL;
930                 result = dns_keytable_findkeynode(
931                                                 secroots, name,
932                                                 (dns_secalg_t)dst_key_alg(key),
933                                                 dst_key_id(key),
934                                                 &keynode);
935
936                 match = ISC_FALSE;
937                 while (result == ISC_R_SUCCESS) {
938                         secrootkey = dns_keynode_key(keynode);
939                         if (dst_key_compare(key, secrootkey)) {
940                                 match = ISC_TRUE;
941                                 dns_keytable_detachkeynode(secroots, &keynode);
942                                 break;
943                         }
944                         nextnode = NULL;
945                         result = dns_keytable_findnextkeynode(secroots,
946                                                               keynode,
947                                                               &nextnode);
948                         dns_keytable_detachkeynode(secroots, &keynode);
949                 }
950
951                 dst_key_free(&key);
952                 if (!match)
953                         return (ISC_FALSE);
954         }
955         return (match);
956 }
957
958 /*
959  * Attempts positive response validation.
960  *
961  * Returns:
962  *      ISC_R_SUCCESS   Validation completed successfully
963  *      DNS_R_WAIT      Validation has started but is waiting
964  *                      for an event.
965  *      Other return codes are possible and all indicate failure.
966  */
967 static inline isc_result_t
968 validate(dns_validator_t *val, isc_boolean_t resume) {
969         isc_result_t result;
970         dns_validatorevent_t *event;
971         dns_rdata_t rdata = DNS_RDATA_INIT;
972
973         /*
974          * Caller must be holding the validator lock.
975          */
976
977         event = val->event;
978
979         /*
980          * If this is a security root, it's ok.
981          */
982         if (!resume) {
983                 dns_fixedname_t fsecroot;
984                 dns_name_t *secroot;
985
986                 dns_fixedname_init(&fsecroot);
987                 secroot = dns_fixedname_name(&fsecroot);
988                 result = dns_keytable_finddeepestmatch(val->view->secroots,
989                                                        val->event->name,
990                                                        secroot);
991                 if (result == ISC_R_SUCCESS &&
992                     val->event->type == dns_rdatatype_key &&
993                     dns_name_equal(val->event->name, secroot) &&
994                     issecurityroot(val))
995                 {
996                         val->event->rdataset->trust = dns_trust_secure;
997                         return (ISC_R_SUCCESS);
998                 }
999         }
1000
1001         if (resume) {
1002                 /*
1003                  * We already have a sigrdataset.
1004                  */
1005                 result = ISC_R_SUCCESS;
1006                 validator_log(val, ISC_LOG_DEBUG(3), "resuming validate");
1007         } else {
1008                 result = dns_rdataset_first(event->sigrdataset);
1009         }
1010
1011         for (;
1012              result == ISC_R_SUCCESS;
1013              result = dns_rdataset_next(event->sigrdataset))
1014         {
1015                 dns_rdata_reset(&rdata);
1016                 dns_rdataset_current(event->sigrdataset, &rdata);
1017                 if (val->siginfo != NULL)
1018                         isc_mem_put(val->view->mctx, val->siginfo,
1019                                     sizeof *val->siginfo);
1020                 val->siginfo = isc_mem_get(val->view->mctx,
1021                                            sizeof *val->siginfo);
1022                 if (val->siginfo == NULL)
1023                         return (ISC_R_NOMEMORY);
1024                 dns_rdata_tostruct(&rdata, val->siginfo, NULL);
1025
1026                 /*
1027                  * At this point we could check that the signature algorithm
1028                  * was known and "sufficiently good".  For now, any algorithm
1029                  * is acceptable.
1030                  */
1031
1032                 if (!resume) {
1033                         result = get_key(val, val->siginfo);
1034                         if (result == DNS_R_CONTINUE)
1035                                 continue; /* Try the next SIG RR. */
1036                         if (result != ISC_R_SUCCESS)
1037                                 return (result);
1038                 }
1039
1040                 if (val->key == NULL) {
1041                         event->rdataset->trust = dns_trust_answer;
1042                         event->sigrdataset->trust = dns_trust_answer;
1043                         validator_log(val, ISC_LOG_DEBUG(3),
1044                                       "marking as answer");
1045                         return (ISC_R_SUCCESS);
1046
1047                 }
1048
1049                 do {
1050                         val->attributes |= VALATTR_TRIEDVERIFY;
1051                         result = dns_dnssec_verify(event->name,
1052                                                    event->rdataset,
1053                                                    val->key, ISC_FALSE,
1054                                                    val->view->mctx, &rdata);
1055                         validator_log(val, ISC_LOG_DEBUG(3),
1056                                       "verify rdataset: %s",
1057                                       isc_result_totext(result));
1058                         if (result == ISC_R_SUCCESS)
1059                                 break;
1060                         if (val->keynode != NULL) {
1061                                 dns_keynode_t *nextnode = NULL;
1062                                 result = dns_keytable_findnextkeynode(
1063                                                         val->keytable,
1064                                                         val->keynode,
1065                                                         &nextnode);
1066                                 dns_keytable_detachkeynode(val->keytable,
1067                                                            &val->keynode);
1068                                 val->keynode = nextnode;
1069                                 if (result != ISC_R_SUCCESS) {
1070                                         val->key = NULL;
1071                                         break;
1072                                 }
1073                                 val->key = dns_keynode_key(val->keynode);
1074                         } else {
1075                                 if (get_dst_key(val, val->siginfo, val->keyset)
1076                                     != ISC_R_SUCCESS)
1077                                         break;
1078                         }
1079                 } while (1);
1080                 if (result != ISC_R_SUCCESS)
1081                         validator_log(val, ISC_LOG_DEBUG(3),
1082                                       "failed to verify rdataset");
1083                 else {
1084                         isc_uint32_t ttl;
1085                         isc_stdtime_t now;
1086
1087                         isc_stdtime_get(&now);
1088                         ttl = ISC_MIN(event->rdataset->ttl,
1089                                       val->siginfo->timeexpire - now);
1090                         if (val->keyset != NULL)
1091                                 ttl = ISC_MIN(ttl, val->keyset->ttl);
1092                         event->rdataset->ttl = ttl;
1093                         event->sigrdataset->ttl = ttl;
1094                 }
1095
1096                 if (val->keynode != NULL)
1097                         dns_keytable_detachkeynode(val->keytable,
1098                                                    &val->keynode);
1099                 else {
1100                         if (val->key != NULL)
1101                                 dst_key_free(&val->key);
1102                         if (val->keyset != NULL) {
1103                                 dns_rdataset_disassociate(val->keyset);
1104                                 val->keyset = NULL;
1105                         }
1106                 }
1107                 val->key = NULL;
1108                 if (result == ISC_R_SUCCESS) {
1109                         event->rdataset->trust = dns_trust_secure;
1110                         event->sigrdataset->trust = dns_trust_secure;
1111                         validator_log(val, ISC_LOG_DEBUG(3),
1112                                       "marking as secure");
1113                         return (result);
1114                 } else {
1115                         validator_log(val, ISC_LOG_DEBUG(3),
1116                                       "verify failure: %s",
1117                                       isc_result_totext(result));
1118                         resume = ISC_FALSE;
1119                 }
1120         }
1121         if (result != ISC_R_NOMORE) {
1122                 validator_log(val, ISC_LOG_DEBUG(3),
1123                               "failed to iterate signatures: %s",
1124                               isc_result_totext(result));
1125                 return (result);
1126         }
1127
1128         validator_log(val, ISC_LOG_INFO, "no valid signature found");
1129         return (DNS_R_NOVALIDSIG);
1130 }
1131
1132
1133 static inline isc_result_t
1134 nxtvalidate(dns_validator_t *val, isc_boolean_t resume) {
1135         dns_name_t *name;
1136         dns_message_t *message = val->event->message;
1137         isc_result_t result;
1138
1139         if (!resume) {
1140                 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
1141                 if (result != ISC_R_SUCCESS)
1142                         validator_done(val, ISC_R_NOTFOUND);
1143         } else {
1144                 result = ISC_R_SUCCESS;
1145                 validator_log(val, ISC_LOG_DEBUG(3), "resuming nxtvalidate");
1146         }
1147
1148         for (;
1149              result == ISC_R_SUCCESS;
1150              result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
1151         {
1152                 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
1153
1154                 name = NULL;
1155                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
1156                 if (resume) {
1157                         rdataset = ISC_LIST_NEXT(val->currentset, link);
1158                         val->currentset = NULL;
1159                         resume = ISC_FALSE;
1160                 }
1161                 else
1162                         rdataset = ISC_LIST_HEAD(name->list);
1163
1164                 for (;
1165                      rdataset != NULL;
1166                      rdataset = ISC_LIST_NEXT(rdataset, link))
1167                 {
1168                         if (rdataset->type == dns_rdatatype_sig)
1169                                 continue;
1170
1171                         for (sigrdataset = ISC_LIST_HEAD(name->list);
1172                              sigrdataset != NULL;
1173                              sigrdataset = ISC_LIST_NEXT(sigrdataset,
1174                                                          link))
1175                         {
1176                                 if (sigrdataset->type == dns_rdatatype_sig &&
1177                                     sigrdataset->covers == rdataset->type)
1178                                         break;
1179                         }
1180                         if (sigrdataset == NULL)
1181                                 continue;
1182                         val->seensig = ISC_TRUE;
1183                         /*
1184                          * If a signed zone is missing the zone key, bad
1185                          * things could happen.  A query for data in the zone
1186                          * would lead to a query for the zone key, which
1187                          * would return a negative answer, which would contain
1188                          * an SOA and an NXT signed by the missing key, which
1189                          * would trigger another query for the KEY (since the
1190                          * first one is still in progress), and go into an
1191                          * infinite loop.  Avoid that.
1192                          */
1193                         if (val->event->type == dns_rdatatype_key &&
1194                             dns_name_equal(name, val->event->name))
1195                         {
1196                                 dns_rdata_t nxt = DNS_RDATA_INIT;
1197
1198                                 if (rdataset->type != dns_rdatatype_nxt)
1199                                         continue;
1200
1201                                 result = dns_rdataset_first(rdataset);
1202                                 if (result != ISC_R_SUCCESS)
1203                                         return (result);
1204                                 dns_rdataset_current(rdataset, &nxt);
1205                                 if (dns_nxt_typepresent(&nxt,
1206                                                         dns_rdatatype_soa))
1207                                         continue;
1208                         }
1209                         val->authvalidator = NULL;
1210                         val->currentset = rdataset;
1211                         result = dns_validator_create(val->view, name,
1212                                                       rdataset->type,
1213                                                       rdataset,
1214                                                       sigrdataset,
1215                                                       NULL, 0,
1216                                                       val->task,
1217                                                       authvalidated,
1218                                                       val,
1219                                                       &val->authvalidator);
1220                         if (result != ISC_R_SUCCESS)
1221                                 return (result);
1222                         return (DNS_R_WAIT);
1223
1224                 }
1225         }
1226         if (result == ISC_R_NOMORE)
1227                 result = ISC_R_SUCCESS;
1228         if (result != ISC_R_SUCCESS)
1229                 validator_done(val, result);
1230
1231         if ((val->attributes & VALATTR_FOUNDNONEXISTENCE) == 0) {
1232                 if (!val->seensig) {
1233                         result = dns_validator_create(val->view, name,
1234                                                       dns_rdatatype_soa,
1235                                                       &val->frdataset,
1236                                                       NULL, NULL, 0,
1237                                                       val->task,
1238                                                       negauthvalidated,
1239                                                       val,
1240                                                       &val->authvalidator);
1241                         if (result != ISC_R_SUCCESS)
1242                                 return (result);
1243                         return (DNS_R_WAIT);
1244                 }
1245                 validator_log(val, ISC_LOG_DEBUG(3),
1246                               "nonexistence proof not found");
1247                 return (DNS_R_NOVALIDNXT);
1248         } else {
1249                 validator_log(val, ISC_LOG_DEBUG(3),
1250                               "nonexistence proof found");
1251                 return (ISC_R_SUCCESS);
1252         }
1253 }
1254
1255 static inline isc_result_t
1256 proveunsecure(dns_validator_t *val, isc_boolean_t resume) {
1257         isc_result_t result;
1258         dns_fixedname_t secroot, tfname;
1259         dns_name_t *tname;
1260
1261         dns_fixedname_init(&secroot);
1262         dns_fixedname_init(&tfname);
1263         result = dns_keytable_finddeepestmatch(val->view->secroots,
1264                                                val->event->name,
1265                                                dns_fixedname_name(&secroot));
1266         /*
1267          * If the name is not under a security root, it must be insecure.
1268          */
1269         if (result == ISC_R_NOTFOUND)
1270                 return (ISC_R_SUCCESS);
1271
1272         else if (result != ISC_R_SUCCESS)
1273                 return (result);
1274
1275         /*
1276          * If this is a security root, it's ok.
1277          */
1278         if (val->event->type == dns_rdatatype_key &&
1279             dns_name_equal(val->event->name, dns_fixedname_name(&secroot)) &&
1280             issecurityroot(val))
1281         {
1282                 val->event->rdataset->trust = dns_trust_secure;
1283                 return (ISC_R_SUCCESS);
1284         }
1285
1286         if (!resume)
1287                 val->labels = dns_name_depth(dns_fixedname_name(&secroot)) + 1;
1288         else {
1289                 validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
1290                 val->labels++;
1291         }
1292
1293         for (;
1294              val->labels <= dns_name_depth(val->event->name);
1295              val->labels++)
1296         {
1297                 char namebuf[1024];
1298
1299                 if (val->labels == dns_name_depth(val->event->name)) {
1300                         if (val->event->type == dns_rdatatype_key)
1301                                 break;
1302                         tname = val->event->name;
1303                 } else {
1304                         tname = dns_fixedname_name(&tfname);
1305                         result = dns_name_splitatdepth(val->event->name,
1306                                                        val->labels,
1307                                                        NULL, tname);
1308                         if (result != ISC_R_SUCCESS)
1309                                 return (result);
1310                 }
1311
1312                 dns_name_format(tname, namebuf, sizeof(namebuf));
1313                 validator_log(val, ISC_LOG_DEBUG(3),
1314                               "looking for null keyset at '%s'",
1315                               namebuf);
1316
1317                 if (dns_rdataset_isassociated(&val->frdataset))
1318                         dns_rdataset_disassociate(&val->frdataset);
1319                 if (dns_rdataset_isassociated(&val->fsigrdataset))
1320                         dns_rdataset_disassociate(&val->fsigrdataset);
1321
1322                 result = dns_view_simplefind(val->view, tname,
1323                                              dns_rdatatype_key, 0,
1324                                              DNS_DBFIND_PENDINGOK, ISC_FALSE,
1325                                              &val->frdataset,
1326                                              &val->fsigrdataset);
1327                 if (result == ISC_R_SUCCESS) {
1328                         dns_name_t *fname = NULL;
1329
1330                         if (!dns_rdataset_isassociated(&val->fsigrdataset)) {
1331                                 result = DNS_R_NOTINSECURE;
1332                                 goto out;
1333                         }
1334                         validator_log(val, ISC_LOG_DEBUG(3),
1335                                       "found keyset, looking for null key");
1336                         if (!containsnullkey(val, &val->frdataset))
1337                                 continue;
1338
1339                         if (val->frdataset.trust >= dns_trust_secure) {
1340                                 validator_log(val, ISC_LOG_DEBUG(3),
1341                                               "insecurity proof succeeded");
1342                                 val->event->rdataset->trust = dns_trust_answer;
1343                                 result = ISC_R_SUCCESS;
1344                                 goto out;
1345                         }
1346
1347                         fname = isc_mem_get(val->view->mctx, sizeof *fname);
1348                         if (fname == NULL)
1349                                 return (ISC_R_NOMEMORY);
1350                         dns_name_init(fname, NULL);
1351                         result = dns_name_dup(tname, val->view->mctx, fname);
1352                         if (result != ISC_R_SUCCESS) {
1353                                 isc_mem_put(val->view->mctx, fname,
1354                                             sizeof *fname);
1355                                 result = ISC_R_NOMEMORY;
1356                                 goto out;
1357                         }
1358
1359                         result = dns_validator_create(val->view,
1360                                                       fname,
1361                                                       dns_rdatatype_key,
1362                                                       &val->frdataset,
1363                                                       &val->fsigrdataset,
1364                                                       NULL,
1365                                                       0,
1366                                                       val->task,
1367                                                       nullkeyvalidated,
1368                                                       val,
1369                                                       &val->keyvalidator);
1370                         if (result != ISC_R_SUCCESS)
1371                                 goto out;
1372                         return (DNS_R_WAIT);
1373                 } else if (result == ISC_R_NOTFOUND) {
1374                         val->fetch = NULL;
1375                         result = dns_resolver_createfetch(val->view->resolver,
1376                                                         tname,
1377                                                         dns_rdatatype_key,
1378                                                         NULL, NULL, NULL, 0,
1379                                                         val->event->ev_sender,
1380                                                         fetch_callback_nullkey,
1381                                                         val,
1382                                                         &val->frdataset,
1383                                                         &val->fsigrdataset,
1384                                                         &val->fetch);
1385                         if (result != ISC_R_SUCCESS)
1386                                 goto out;
1387                         return (DNS_R_WAIT);
1388                 } else if (result == DNS_R_NCACHENXDOMAIN ||
1389                          result == DNS_R_NCACHENXRRSET ||
1390                          result == DNS_R_NXDOMAIN ||
1391                          result == DNS_R_NXRRSET)
1392                 {
1393                         continue;
1394                 } else
1395                         goto out;
1396         }
1397         validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed");
1398         return (DNS_R_NOTINSECURE); /* Didn't find a null key */
1399
1400  out:
1401         if (dns_rdataset_isassociated(&val->frdataset))
1402                 dns_rdataset_disassociate(&val->frdataset);
1403         if (dns_rdataset_isassociated(&val->fsigrdataset))
1404                 dns_rdataset_disassociate(&val->fsigrdataset);
1405         return (result);
1406 }
1407
1408 static void
1409 validator_start(isc_task_t *task, isc_event_t *event) {
1410         dns_validator_t *val;
1411         dns_validatorevent_t *vevent;
1412         isc_result_t result = ISC_R_FAILURE;
1413
1414         UNUSED(task);
1415         REQUIRE(event->ev_type == DNS_EVENT_VALIDATORSTART);
1416         vevent = (dns_validatorevent_t *)event;
1417         val = vevent->validator;
1418
1419         /* If the validator has been cancelled, val->event == NULL */
1420         if (val->event == NULL)
1421                 return;
1422
1423         validator_log(val, ISC_LOG_DEBUG(3), "starting");
1424
1425         LOCK(&val->lock);
1426
1427         if (val->event->rdataset != NULL && val->event->sigrdataset != NULL) {
1428                 isc_result_t saved_result;
1429
1430                 /*
1431                  * This looks like a simple validation.  We say "looks like"
1432                  * because we don't know if wildcards are involved yet so it
1433                  * could still get complicated.
1434                  */
1435                 validator_log(val, ISC_LOG_DEBUG(3),
1436                               "attempting positive response validation");
1437
1438                 result = validate(val, ISC_FALSE);
1439                 if (result == DNS_R_NOVALIDSIG &&
1440                     (val->attributes & VALATTR_TRIEDVERIFY) == 0)
1441                 {
1442                         saved_result = result;
1443                         validator_log(val, ISC_LOG_DEBUG(3),
1444                                       "falling back to insecurity proof");
1445                         result = proveunsecure(val, ISC_FALSE);
1446                         if (result == DNS_R_NOTINSECURE)
1447                                 result = saved_result;
1448                 }
1449         } else if (val->event->rdataset != NULL) {
1450                 /*
1451                  * This is either an unsecure subdomain or a response from
1452                  * a broken server.
1453                  */
1454                 validator_log(val, ISC_LOG_DEBUG(3),
1455                               "attempting insecurity proof");
1456
1457                 result = proveunsecure(val, ISC_FALSE);
1458         } else if (val->event->rdataset == NULL &&
1459                  val->event->sigrdataset == NULL)
1460         {
1461                 /*
1462                  * This is a nonexistence validation.
1463                  */
1464                 validator_log(val, ISC_LOG_DEBUG(3),
1465                               "attempting negative response validation");
1466
1467                 result = nxtvalidate(val, ISC_FALSE);
1468         } else {
1469                 /*
1470                  * This shouldn't happen.
1471                  */
1472                 INSIST(0);
1473         }
1474
1475         if (result != DNS_R_WAIT)
1476                 validator_done(val, result);
1477
1478         UNLOCK(&val->lock);
1479 }
1480
1481 isc_result_t
1482 dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
1483                      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
1484                      dns_message_t *message, unsigned int options,
1485                      isc_task_t *task, isc_taskaction_t action, void *arg,
1486                      dns_validator_t **validatorp)
1487 {
1488         isc_result_t result;
1489         dns_validator_t *val;
1490         isc_task_t *tclone;
1491         dns_validatorevent_t *event;
1492
1493         REQUIRE(name != NULL);
1494         REQUIRE(type != 0);
1495         REQUIRE(rdataset != NULL ||
1496                 (rdataset == NULL && sigrdataset == NULL && message != NULL));
1497         REQUIRE(options == 0);
1498         REQUIRE(validatorp != NULL && *validatorp == NULL);
1499
1500         tclone = NULL;
1501         result = ISC_R_FAILURE;
1502
1503         val = isc_mem_get(view->mctx, sizeof *val);
1504         if (val == NULL)
1505                 return (ISC_R_NOMEMORY);
1506         val->view = NULL;
1507         dns_view_weakattach(view, &val->view);
1508         event = (dns_validatorevent_t *)
1509                 isc_event_allocate(view->mctx, task,
1510                                    DNS_EVENT_VALIDATORSTART,
1511                                    validator_start, NULL,
1512                                    sizeof (dns_validatorevent_t));
1513         if (event == NULL) {
1514                 result = ISC_R_NOMEMORY;
1515                 goto cleanup_val;
1516         }
1517         isc_task_attach(task, &tclone);
1518         event->validator = val;
1519         event->result = ISC_R_FAILURE;
1520         event->name = name;
1521         event->type = type;
1522         event->rdataset = rdataset;
1523         event->sigrdataset = sigrdataset;
1524         event->message = message;
1525         result = isc_mutex_init(&val->lock);
1526         if (result != ISC_R_SUCCESS)
1527                 goto cleanup_event;
1528         val->event = event;
1529         val->options = options;
1530         val->attributes = 0;
1531         val->fetch = NULL;
1532         val->keyvalidator = NULL;
1533         val->authvalidator = NULL;
1534         val->keynode = NULL;
1535         val->key = NULL;
1536         val->siginfo = NULL;
1537         val->task = task;
1538         val->action = action;
1539         val->arg = arg;
1540         val->labels = 0;
1541         val->currentset = NULL;
1542         val->keyset = NULL;
1543         val->seensig = ISC_FALSE;
1544         dns_rdataset_init(&val->frdataset);
1545         dns_rdataset_init(&val->fsigrdataset);
1546         ISC_LINK_INIT(val, link);
1547         val->magic = VALIDATOR_MAGIC;
1548
1549         isc_task_send(task, ISC_EVENT_PTR(&event));
1550
1551         *validatorp = val;
1552
1553         return (ISC_R_SUCCESS);
1554
1555  cleanup_event:
1556         isc_task_detach(&tclone);
1557         isc_event_free((isc_event_t **)&val->event);
1558
1559  cleanup_val:
1560         dns_view_weakdetach(&val->view);
1561         isc_mem_put(view->mctx, val, sizeof *val);
1562
1563         return (result);
1564 }
1565
1566 void
1567 dns_validator_cancel(dns_validator_t *validator) {
1568         REQUIRE(VALID_VALIDATOR(validator));
1569
1570         LOCK(&validator->lock);
1571
1572         validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
1573
1574         if (validator->event != NULL) {
1575                 validator_done(validator, ISC_R_CANCELED);
1576
1577                 if (validator->fetch != NULL)
1578                         dns_resolver_cancelfetch(validator->fetch);
1579
1580                 if (validator->keyvalidator != NULL)
1581                         dns_validator_cancel(validator->keyvalidator);
1582
1583                 if (validator->authvalidator != NULL)
1584                         dns_validator_cancel(validator->authvalidator);
1585         }
1586         UNLOCK(&validator->lock);
1587 }
1588
1589 static void
1590 destroy(dns_validator_t *val) {
1591         isc_mem_t *mctx;
1592
1593         REQUIRE(SHUTDOWN(val));
1594         REQUIRE(val->event == NULL);
1595         REQUIRE(val->fetch == NULL);
1596
1597         if (val->keynode != NULL)
1598                 dns_keytable_detachkeynode(val->keytable, &val->keynode);
1599         else if (val->key != NULL)
1600                 dst_key_free(&val->key);
1601         if (val->keyvalidator != NULL)
1602                 dns_validator_destroy(&val->keyvalidator);
1603         if (val->authvalidator != NULL)
1604                 dns_validator_destroy(&val->authvalidator);
1605         mctx = val->view->mctx;
1606         if (val->siginfo != NULL)
1607                 isc_mem_put(mctx, val->siginfo, sizeof *val->siginfo);
1608         DESTROYLOCK(&val->lock);
1609         dns_view_weakdetach(&val->view);
1610         val->magic = 0;
1611         isc_mem_put(mctx, val, sizeof *val);
1612 }
1613
1614 void
1615 dns_validator_destroy(dns_validator_t **validatorp) {
1616         dns_validator_t *val;
1617         isc_boolean_t want_destroy = ISC_FALSE;
1618
1619         REQUIRE(validatorp != NULL);
1620         val = *validatorp;
1621         REQUIRE(VALID_VALIDATOR(val));
1622
1623         LOCK(&val->lock);
1624
1625         REQUIRE(val->event == NULL);
1626
1627         validator_log(val, ISC_LOG_DEBUG(3), "dns_validator_destroy");
1628
1629         val->attributes |= VALATTR_SHUTDOWN;
1630         if (val->fetch == NULL && val->keyvalidator == NULL &&
1631             val->authvalidator == NULL)
1632                 want_destroy = ISC_TRUE;
1633
1634         UNLOCK(&val->lock);
1635
1636         if (want_destroy)
1637                 destroy(val);
1638
1639         *validatorp = NULL;
1640 }
1641
1642
1643 static void
1644 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
1645                isc_logmodule_t *module, int level, const char *fmt, va_list ap)
1646      ISC_FORMAT_PRINTF(5, 0);
1647
1648 static void
1649 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
1650                isc_logmodule_t *module, int level, const char *fmt, va_list ap)
1651 {
1652         char msgbuf[2048];
1653
1654         vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
1655
1656         if (val->event != NULL && val->event->name != NULL) {
1657                 char namebuf[1024];
1658                 char typebuf[256];
1659                 isc_buffer_t b;
1660                 isc_region_t r;
1661
1662                 dns_name_format(val->event->name, namebuf, sizeof(namebuf));
1663
1664                 isc_buffer_init(&b, (unsigned char *)typebuf, sizeof(typebuf));
1665                 if (dns_rdatatype_totext(val->event->type, &b)
1666                     != ISC_R_SUCCESS)
1667                 {
1668                         isc_buffer_clear(&b);
1669                         isc_buffer_putstr(&b, "<bad type>");
1670                 }
1671                 isc_buffer_usedregion(&b, &r);
1672                 isc_log_write(dns_lctx, category, module, level,
1673                               "validating %s %.*s: %s", namebuf,
1674                               (int)r.length, (char *)r.base, msgbuf);
1675         } else {
1676                 isc_log_write(dns_lctx, category, module, level,
1677                               "validator @%p: %s", val, msgbuf);
1678
1679         }
1680 }
1681
1682 static void
1683 validator_log(dns_validator_t *val, int level, const char *fmt, ...)
1684 {
1685         va_list ap;
1686
1687         if (! isc_log_wouldlog(dns_lctx, level))
1688                 return;
1689
1690         va_start(ap, fmt);
1691         validator_logv(val, DNS_LOGCATEGORY_DNSSEC,
1692                        DNS_LOGMODULE_VALIDATOR, level, fmt, ap);
1693         va_end(ap);
1694 }
1695