"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.16.7/lib/dns/validator.c" (4 Sep 2020, 88618 Bytes) of package /linux/misc/dns/bind9/9.16.7/bind-9.16.7.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "validator.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 9.17.2_vs_9.17.3.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 #include <inttypes.h>
   13 #include <stdbool.h>
   14 
   15 #include <isc/base32.h>
   16 #include <isc/md.h>
   17 #include <isc/mem.h>
   18 #include <isc/print.h>
   19 #include <isc/string.h>
   20 #include <isc/task.h>
   21 #include <isc/util.h>
   22 
   23 #include <dns/client.h>
   24 #include <dns/db.h>
   25 #include <dns/dnssec.h>
   26 #include <dns/ds.h>
   27 #include <dns/events.h>
   28 #include <dns/keytable.h>
   29 #include <dns/keyvalues.h>
   30 #include <dns/log.h>
   31 #include <dns/message.h>
   32 #include <dns/ncache.h>
   33 #include <dns/nsec.h>
   34 #include <dns/nsec3.h>
   35 #include <dns/rdata.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 /*! \file
   44  * \brief
   45  * Basic processing sequences:
   46  *
   47  * \li When called with rdataset and sigrdataset:
   48  *     validator_start -> validate_answer -> proveunsecure
   49  *     validator_start -> validate_answer -> validate_nx (if secure wildcard)
   50  *
   51  * \li When called with rdataset but no sigrdataset:
   52  *     validator_start -> proveunsecure
   53  *
   54  * \li When called with no rdataset or sigrdataset:
   55  *     validator_start -> validate_nx-> proveunsecure
   56  *
   57  * validator_start:   determine what type of validation to do.
   58  * validate_answer:   attempt to perform a positive validation.
   59  * proveunsecure:     attempt to prove the answer comes from an unsecure zone.
   60  * validate_nx:       attempt to prove a negative response.
   61  */
   62 
   63 #define VALIDATOR_MAGIC    ISC_MAGIC('V', 'a', 'l', '?')
   64 #define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
   65 
   66 #define VALATTR_SHUTDOWN 0x0001 /*%< Shutting down. */
   67 #define VALATTR_CANCELED 0x0002 /*%< Canceled. */
   68 #define VALATTR_TRIEDVERIFY                                    \
   69     0x0004            /*%< We have found a key and \
   70                    * have attempted a verify. */
   71 #define VALATTR_INSECURITY 0x0010 /*%< Attempting proveunsecure. */
   72 
   73 /*!
   74  * NSEC proofs to be looked for.
   75  */
   76 #define VALATTR_NEEDNOQNAME    0x00000100
   77 #define VALATTR_NEEDNOWILDCARD 0x00000200
   78 #define VALATTR_NEEDNODATA     0x00000400
   79 
   80 /*!
   81  * NSEC proofs that have been found.
   82  */
   83 #define VALATTR_FOUNDNOQNAME    0x00001000
   84 #define VALATTR_FOUNDNOWILDCARD 0x00002000
   85 #define VALATTR_FOUNDNODATA 0x00004000
   86 #define VALATTR_FOUNDCLOSEST    0x00008000
   87 #define VALATTR_FOUNDOPTOUT 0x00010000
   88 #define VALATTR_FOUNDUNKNOWN    0x00020000
   89 
   90 #define NEEDNODATA(val)      ((val->attributes & VALATTR_NEEDNODATA) != 0)
   91 #define NEEDNOQNAME(val)     ((val->attributes & VALATTR_NEEDNOQNAME) != 0)
   92 #define NEEDNOWILDCARD(val)  ((val->attributes & VALATTR_NEEDNOWILDCARD) != 0)
   93 #define FOUNDNODATA(val)     ((val->attributes & VALATTR_FOUNDNODATA) != 0)
   94 #define FOUNDNOQNAME(val)    ((val->attributes & VALATTR_FOUNDNOQNAME) != 0)
   95 #define FOUNDNOWILDCARD(val) ((val->attributes & VALATTR_FOUNDNOWILDCARD) != 0)
   96 #define FOUNDCLOSEST(val)    ((val->attributes & VALATTR_FOUNDCLOSEST) != 0)
   97 #define FOUNDOPTOUT(val)     ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
   98 
   99 #define SHUTDOWN(v) (((v)->attributes & VALATTR_SHUTDOWN) != 0)
  100 #define CANCELED(v) (((v)->attributes & VALATTR_CANCELED) != 0)
  101 
  102 #define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
  103 #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
  104 
  105 static void
  106 destroy(dns_validator_t *val);
  107 
  108 static isc_result_t
  109 select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset);
  110 
  111 static isc_result_t
  112 validate_answer(dns_validator_t *val, bool resume);
  113 
  114 static isc_result_t
  115 validate_dnskey(dns_validator_t *val);
  116 
  117 static isc_result_t
  118 validate_nx(dns_validator_t *val, bool resume);
  119 
  120 static isc_result_t
  121 proveunsecure(dns_validator_t *val, bool have_ds, bool resume);
  122 
  123 static void
  124 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
  125            isc_logmodule_t *module, int level, const char *fmt, va_list ap)
  126     ISC_FORMAT_PRINTF(5, 0);
  127 
  128 static void
  129 validator_log(void *val, int level, const char *fmt, ...)
  130     ISC_FORMAT_PRINTF(3, 4);
  131 
  132 static void
  133 validator_logcreate(dns_validator_t *val, dns_name_t *name,
  134             dns_rdatatype_t type, const char *caller,
  135             const char *operation);
  136 
  137 /*%
  138  * Ensure the validator's rdatasets are marked as expired.
  139  */
  140 static void
  141 expire_rdatasets(dns_validator_t *val) {
  142     if (dns_rdataset_isassociated(&val->frdataset)) {
  143         dns_rdataset_expire(&val->frdataset);
  144     }
  145     if (dns_rdataset_isassociated(&val->fsigrdataset)) {
  146         dns_rdataset_expire(&val->fsigrdataset);
  147     }
  148 }
  149 
  150 /*%
  151  * Ensure the validator's rdatasets are disassociated.
  152  */
  153 static void
  154 disassociate_rdatasets(dns_validator_t *val) {
  155     if (dns_rdataset_isassociated(&val->fdsset)) {
  156         dns_rdataset_disassociate(&val->fdsset);
  157     }
  158     if (dns_rdataset_isassociated(&val->frdataset)) {
  159         dns_rdataset_disassociate(&val->frdataset);
  160     }
  161     if (dns_rdataset_isassociated(&val->fsigrdataset)) {
  162         dns_rdataset_disassociate(&val->fsigrdataset);
  163     }
  164 }
  165 
  166 /*%
  167  * Mark the rdatasets in val->event with trust level "answer",
  168  * indicating that they did not validate, but could be cached as insecure.
  169  *
  170  * If we are validating a name that is marked as "must be secure", log a
  171  * warning and return DNS_R_MUSTBESECURE instead.
  172  */
  173 static inline isc_result_t
  174 markanswer(dns_validator_t *val, const char *where, const char *mbstext) {
  175     if (val->mustbesecure && mbstext != NULL) {
  176         validator_log(val, ISC_LOG_WARNING,
  177                   "must be secure failure, %s", mbstext);
  178         return (DNS_R_MUSTBESECURE);
  179     }
  180 
  181     validator_log(val, ISC_LOG_DEBUG(3), "marking as answer (%s)", where);
  182     if (val->event->rdataset != NULL) {
  183         dns_rdataset_settrust(val->event->rdataset, dns_trust_answer);
  184     }
  185     if (val->event->sigrdataset != NULL) {
  186         dns_rdataset_settrust(val->event->sigrdataset,
  187                       dns_trust_answer);
  188     }
  189 
  190     return (ISC_R_SUCCESS);
  191 }
  192 
  193 /*%
  194  * Mark the RRsets in val->event with trust level secure.
  195  */
  196 static inline void
  197 marksecure(dns_validatorevent_t *event) {
  198     dns_rdataset_settrust(event->rdataset, dns_trust_secure);
  199     if (event->sigrdataset != NULL) {
  200         dns_rdataset_settrust(event->sigrdataset, dns_trust_secure);
  201     }
  202     event->secure = true;
  203 }
  204 
  205 /*
  206  * Validator 'val' is finished; send the completion event to the task
  207  * that called dns_validator_create(), with result `result`.
  208  */
  209 static void
  210 validator_done(dns_validator_t *val, isc_result_t result) {
  211     isc_task_t *task;
  212 
  213     if (val->event == NULL) {
  214         return;
  215     }
  216 
  217     /*
  218      * Caller must be holding the lock.
  219      */
  220 
  221     val->event->result = result;
  222     task = val->event->ev_sender;
  223     val->event->ev_sender = val;
  224     val->event->ev_type = DNS_EVENT_VALIDATORDONE;
  225     val->event->ev_action = val->action;
  226     val->event->ev_arg = val->arg;
  227     isc_task_sendanddetach(&task, (isc_event_t **)&val->event);
  228 }
  229 
  230 /*
  231  * Called when deciding whether to destroy validator 'val'.
  232  */
  233 static inline bool
  234 exit_check(dns_validator_t *val) {
  235     /*
  236      * Caller must be holding the lock.
  237      */
  238     if (!SHUTDOWN(val)) {
  239         return (false);
  240     }
  241 
  242     INSIST(val->event == NULL);
  243 
  244     if (val->fetch != NULL || val->subvalidator != NULL) {
  245         return (false);
  246     }
  247 
  248     return (true);
  249 }
  250 
  251 /*%
  252  * Look in the NSEC record returned from a DS query to see if there is
  253  * a NS RRset at this name.  If it is found we are at a delegation point.
  254  */
  255 static bool
  256 isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
  257          isc_result_t dbresult) {
  258     dns_fixedname_t fixed;
  259     dns_label_t hashlabel;
  260     dns_name_t nsec3name;
  261     dns_rdata_nsec3_t nsec3;
  262     dns_rdata_t rdata = DNS_RDATA_INIT;
  263     dns_rdataset_t set;
  264     int order;
  265     int scope;
  266     bool found;
  267     isc_buffer_t buffer;
  268     isc_result_t result;
  269     unsigned char hash[NSEC3_MAX_HASH_LENGTH];
  270     unsigned char owner[NSEC3_MAX_HASH_LENGTH];
  271     unsigned int length;
  272 
  273     REQUIRE(dbresult == DNS_R_NXRRSET || dbresult == DNS_R_NCACHENXRRSET);
  274 
  275     dns_rdataset_init(&set);
  276     if (dbresult == DNS_R_NXRRSET) {
  277         dns_rdataset_clone(rdataset, &set);
  278     } else {
  279         result = dns_ncache_getrdataset(rdataset, name,
  280                         dns_rdatatype_nsec, &set);
  281         if (result == ISC_R_NOTFOUND) {
  282             goto trynsec3;
  283         }
  284         if (result != ISC_R_SUCCESS) {
  285             return (false);
  286         }
  287     }
  288 
  289     INSIST(set.type == dns_rdatatype_nsec);
  290 
  291     found = false;
  292     result = dns_rdataset_first(&set);
  293     if (result == ISC_R_SUCCESS) {
  294         dns_rdataset_current(&set, &rdata);
  295         found = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
  296         dns_rdata_reset(&rdata);
  297     }
  298     dns_rdataset_disassociate(&set);
  299     return (found);
  300 
  301 trynsec3:
  302     /*
  303      * Iterate over the ncache entry.
  304      */
  305     found = false;
  306     dns_name_init(&nsec3name, NULL);
  307     dns_fixedname_init(&fixed);
  308     dns_name_downcase(name, dns_fixedname_name(&fixed), NULL);
  309     name = dns_fixedname_name(&fixed);
  310     for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
  311          result = dns_rdataset_next(rdataset))
  312     {
  313         dns_ncache_current(rdataset, &nsec3name, &set);
  314         if (set.type != dns_rdatatype_nsec3) {
  315             dns_rdataset_disassociate(&set);
  316             continue;
  317         }
  318         dns_name_getlabel(&nsec3name, 0, &hashlabel);
  319         isc_region_consume(&hashlabel, 1);
  320         isc_buffer_init(&buffer, owner, sizeof(owner));
  321         result = isc_base32hexnp_decoderegion(&hashlabel, &buffer);
  322         if (result != ISC_R_SUCCESS) {
  323             dns_rdataset_disassociate(&set);
  324             continue;
  325         }
  326         for (result = dns_rdataset_first(&set); result == ISC_R_SUCCESS;
  327              result = dns_rdataset_next(&set))
  328         {
  329             dns_rdata_reset(&rdata);
  330             dns_rdataset_current(&set, &rdata);
  331             (void)dns_rdata_tostruct(&rdata, &nsec3, NULL);
  332             if (nsec3.hash != 1) {
  333                 continue;
  334             }
  335             length = isc_iterated_hash(
  336                 hash, nsec3.hash, nsec3.iterations, nsec3.salt,
  337                 nsec3.salt_length, name->ndata, name->length);
  338             if (length != isc_buffer_usedlength(&buffer)) {
  339                 continue;
  340             }
  341             order = memcmp(hash, owner, length);
  342             if (order == 0) {
  343                 found = dns_nsec3_typepresent(&rdata,
  344                                   dns_rdatatype_ns);
  345                 dns_rdataset_disassociate(&set);
  346                 return (found);
  347             }
  348             if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) == 0) {
  349                 continue;
  350             }
  351             /*
  352              * Does this optout span cover the name?
  353              */
  354             scope = memcmp(owner, nsec3.next, nsec3.next_length);
  355             if ((scope < 0 && order > 0 &&
  356                  memcmp(hash, nsec3.next, length) < 0) ||
  357                 (scope >= 0 &&
  358                  (order > 0 ||
  359                   memcmp(hash, nsec3.next, length) < 0)))
  360             {
  361                 dns_rdataset_disassociate(&set);
  362                 return (true);
  363             }
  364         }
  365         dns_rdataset_disassociate(&set);
  366     }
  367     return (found);
  368 }
  369 
  370 /*%
  371  * We have been asked to look for a key.
  372  * If found, resume the validation process.
  373  * If not found, fail the validation process.
  374  */
  375 static void
  376 fetch_callback_dnskey(isc_task_t *task, isc_event_t *event) {
  377     dns_fetchevent_t *devent;
  378     dns_validator_t *val;
  379     dns_rdataset_t *rdataset;
  380     bool want_destroy;
  381     isc_result_t result;
  382     isc_result_t eresult;
  383     isc_result_t saved_result;
  384     dns_fetch_t *fetch;
  385 
  386     UNUSED(task);
  387     INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
  388     devent = (dns_fetchevent_t *)event;
  389     val = devent->ev_arg;
  390     rdataset = &val->frdataset;
  391     eresult = devent->result;
  392 
  393     /* Free resources which are not of interest. */
  394     if (devent->node != NULL) {
  395         dns_db_detachnode(devent->db, &devent->node);
  396     }
  397     if (devent->db != NULL) {
  398         dns_db_detach(&devent->db);
  399     }
  400     if (dns_rdataset_isassociated(&val->fsigrdataset)) {
  401         dns_rdataset_disassociate(&val->fsigrdataset);
  402     }
  403     isc_event_free(&event);
  404 
  405     INSIST(val->event != NULL);
  406 
  407     validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_dnskey");
  408     LOCK(&val->lock);
  409     fetch = val->fetch;
  410     val->fetch = NULL;
  411     if (CANCELED(val)) {
  412         validator_done(val, ISC_R_CANCELED);
  413     } else if (eresult == ISC_R_SUCCESS) {
  414         validator_log(val, ISC_LOG_DEBUG(3), "keyset with trust %s",
  415                   dns_trust_totext(rdataset->trust));
  416         /*
  417          * Only extract the dst key if the keyset is secure.
  418          */
  419         if (rdataset->trust >= dns_trust_secure) {
  420             result = select_signing_key(val, rdataset);
  421             if (result == ISC_R_SUCCESS) {
  422                 val->keyset = &val->frdataset;
  423             }
  424         }
  425         result = validate_answer(val, true);
  426         if (result == DNS_R_NOVALIDSIG &&
  427             (val->attributes & VALATTR_TRIEDVERIFY) == 0) {
  428             saved_result = result;
  429             validator_log(val, ISC_LOG_DEBUG(3),
  430                       "falling back to insecurity proof");
  431             result = proveunsecure(val, false, false);
  432             if (result == DNS_R_NOTINSECURE) {
  433                 result = saved_result;
  434             }
  435         }
  436         if (result != DNS_R_WAIT) {
  437             validator_done(val, result);
  438         }
  439     } else {
  440         validator_log(val, ISC_LOG_DEBUG(3),
  441                   "fetch_callback_dnskey: got %s",
  442                   isc_result_totext(eresult));
  443         if (eresult == ISC_R_CANCELED) {
  444             validator_done(val, eresult);
  445         } else {
  446             validator_done(val, DNS_R_BROKENCHAIN);
  447         }
  448     }
  449 
  450     want_destroy = exit_check(val);
  451     UNLOCK(&val->lock);
  452 
  453     if (fetch != NULL) {
  454         dns_resolver_destroyfetch(&fetch);
  455     }
  456 
  457     if (want_destroy) {
  458         destroy(val);
  459     }
  460 }
  461 
  462 /*%
  463  * We have been asked to look for a DS. This may be part of
  464  * walking a trust chain, or an insecurity proof.
  465  */
  466 static void
  467 fetch_callback_ds(isc_task_t *task, isc_event_t *event) {
  468     dns_fetchevent_t *devent;
  469     dns_validator_t *val;
  470     dns_rdataset_t *rdataset;
  471     bool want_destroy, trustchain;
  472     isc_result_t result;
  473     isc_result_t eresult;
  474     dns_fetch_t *fetch;
  475 
  476     UNUSED(task);
  477     INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
  478     devent = (dns_fetchevent_t *)event;
  479     val = devent->ev_arg;
  480     rdataset = &val->frdataset;
  481     eresult = devent->result;
  482 
  483     /*
  484      * Set 'trustchain' to true if we're walking a chain of
  485      * trust; false if we're attempting to prove insecurity.
  486      */
  487     trustchain = ((val->attributes & VALATTR_INSECURITY) == 0);
  488 
  489     /* Free resources which are not of interest. */
  490     if (devent->node != NULL) {
  491         dns_db_detachnode(devent->db, &devent->node);
  492     }
  493     if (devent->db != NULL) {
  494         dns_db_detach(&devent->db);
  495     }
  496     if (dns_rdataset_isassociated(&val->fsigrdataset)) {
  497         dns_rdataset_disassociate(&val->fsigrdataset);
  498     }
  499 
  500     INSIST(val->event != NULL);
  501 
  502     validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_ds");
  503     LOCK(&val->lock);
  504     fetch = val->fetch;
  505     val->fetch = NULL;
  506 
  507     if (CANCELED(val)) {
  508         validator_done(val, ISC_R_CANCELED);
  509         goto done;
  510     }
  511 
  512     switch (eresult) {
  513     case DNS_R_NXDOMAIN:
  514     case DNS_R_NCACHENXDOMAIN:
  515         /*
  516          * These results only make sense if we're attempting
  517          * an insecurity proof, not when walking a chain of trust.
  518          */
  519         if (trustchain) {
  520             goto unexpected;
  521         }
  522 
  523     /* FALLTHROUGH */
  524     case ISC_R_SUCCESS:
  525         if (trustchain) {
  526             /*
  527              * We looked for a DS record as part of
  528              * following a key chain upwards; resume following
  529              * the chain.
  530              */
  531             validator_log(val, ISC_LOG_DEBUG(3),
  532                       "dsset with trust %s",
  533                       dns_trust_totext(rdataset->trust));
  534             val->dsset = &val->frdataset;
  535             result = validate_dnskey(val);
  536             if (result != DNS_R_WAIT) {
  537                 validator_done(val, result);
  538             }
  539         } else {
  540             /*
  541              * There is a DS which may or may not be a zone cut.
  542              * In either case we are still in a secure zone,
  543              * so keep looking for the break in the chain
  544              * of trust.
  545              */
  546             result = proveunsecure(val, (eresult == ISC_R_SUCCESS),
  547                            true);
  548             if (result != DNS_R_WAIT) {
  549                 validator_done(val, result);
  550             }
  551         }
  552         break;
  553     case DNS_R_CNAME:
  554     case DNS_R_NXRRSET:
  555     case DNS_R_NCACHENXRRSET:
  556     case DNS_R_SERVFAIL: /* RFC 1034 parent? */
  557         if (trustchain) {
  558             /*
  559              * Failed to find a DS while following the
  560              * chain of trust; now we need to prove insecurity.
  561              */
  562             validator_log(val, ISC_LOG_DEBUG(3),
  563                       "falling back to insecurity proof (%s)",
  564                       dns_result_totext(eresult));
  565             result = proveunsecure(val, false, false);
  566             if (result != DNS_R_WAIT) {
  567                 validator_done(val, result);
  568             }
  569         } else if (eresult == DNS_R_SERVFAIL) {
  570             goto unexpected;
  571         } else if (eresult != DNS_R_CNAME &&
  572                isdelegation(dns_fixedname_name(&devent->foundname),
  573                     &val->frdataset, eresult))
  574         {
  575             /*
  576              * Failed to find a DS while trying to prove
  577              * insecurity. If this is a zone cut, that
  578              * means we're insecure.
  579              */
  580             result = markanswer(val, "fetch_callback_ds",
  581                         "no DS and this is a delegation");
  582             validator_done(val, result);
  583         } else {
  584             /*
  585              * Not a zone cut, so we have to keep looking for
  586              * the break point in the chain of trust.
  587              */
  588             result = proveunsecure(val, false, true);
  589             if (result != DNS_R_WAIT) {
  590                 validator_done(val, result);
  591             }
  592         }
  593         break;
  594 
  595     default:
  596     unexpected:
  597         validator_log(val, ISC_LOG_DEBUG(3),
  598                   "fetch_callback_ds: got %s",
  599                   isc_result_totext(eresult));
  600         if (eresult == ISC_R_CANCELED) {
  601             validator_done(val, eresult);
  602         } else {
  603             validator_done(val, DNS_R_BROKENCHAIN);
  604         }
  605     }
  606 done:
  607 
  608     isc_event_free(&event);
  609     want_destroy = exit_check(val);
  610     UNLOCK(&val->lock);
  611 
  612     if (fetch != NULL) {
  613         dns_resolver_destroyfetch(&fetch);
  614     }
  615 
  616     if (want_destroy) {
  617         destroy(val);
  618     }
  619 }
  620 
  621 /*%
  622  * Callback from when a DNSKEY RRset has been validated.
  623  *
  624  * Resumes the stalled validation process.
  625  */
  626 static void
  627 validator_callback_dnskey(isc_task_t *task, isc_event_t *event) {
  628     dns_validatorevent_t *devent;
  629     dns_validator_t *val;
  630     bool want_destroy;
  631     isc_result_t result;
  632     isc_result_t eresult;
  633     isc_result_t saved_result;
  634 
  635     UNUSED(task);
  636     INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
  637 
  638     devent = (dns_validatorevent_t *)event;
  639     val = devent->ev_arg;
  640     eresult = devent->result;
  641 
  642     isc_event_free(&event);
  643     dns_validator_destroy(&val->subvalidator);
  644 
  645     INSIST(val->event != NULL);
  646 
  647     validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_dnskey");
  648     LOCK(&val->lock);
  649     if (CANCELED(val)) {
  650         validator_done(val, ISC_R_CANCELED);
  651     } else if (eresult == ISC_R_SUCCESS) {
  652         validator_log(val, ISC_LOG_DEBUG(3), "keyset with trust %s",
  653                   dns_trust_totext(val->frdataset.trust));
  654         /*
  655          * Only extract the dst key if the keyset is secure.
  656          */
  657         if (val->frdataset.trust >= dns_trust_secure) {
  658             (void)select_signing_key(val, &val->frdataset);
  659         }
  660         result = validate_answer(val, true);
  661         if (result == DNS_R_NOVALIDSIG &&
  662             (val->attributes & VALATTR_TRIEDVERIFY) == 0) {
  663             saved_result = result;
  664             validator_log(val, ISC_LOG_DEBUG(3),
  665                       "falling back to insecurity proof");
  666             result = proveunsecure(val, false, false);
  667             if (result == DNS_R_NOTINSECURE) {
  668                 result = saved_result;
  669             }
  670         }
  671         if (result != DNS_R_WAIT) {
  672             validator_done(val, result);
  673         }
  674     } else {
  675         if (eresult != DNS_R_BROKENCHAIN) {
  676             expire_rdatasets(val);
  677         }
  678         validator_log(val, ISC_LOG_DEBUG(3),
  679                   "validator_callback_dnskey: got %s",
  680                   isc_result_totext(eresult));
  681         validator_done(val, DNS_R_BROKENCHAIN);
  682     }
  683 
  684     want_destroy = exit_check(val);
  685     UNLOCK(&val->lock);
  686     if (want_destroy) {
  687         destroy(val);
  688     }
  689 }
  690 
  691 /*%
  692  * Callback when the DS record has been validated.
  693  *
  694  * Resumes validation of the zone key or the unsecure zone proof.
  695  */
  696 static void
  697 validator_callback_ds(isc_task_t *task, isc_event_t *event) {
  698     dns_validatorevent_t *devent;
  699     dns_validator_t *val;
  700     bool want_destroy;
  701     isc_result_t result;
  702     isc_result_t eresult;
  703 
  704     UNUSED(task);
  705     INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
  706 
  707     devent = (dns_validatorevent_t *)event;
  708     val = devent->ev_arg;
  709     eresult = devent->result;
  710 
  711     isc_event_free(&event);
  712     dns_validator_destroy(&val->subvalidator);
  713 
  714     INSIST(val->event != NULL);
  715 
  716     validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_ds");
  717     LOCK(&val->lock);
  718     if (CANCELED(val)) {
  719         validator_done(val, ISC_R_CANCELED);
  720     } else if (eresult == ISC_R_SUCCESS) {
  721         bool have_dsset;
  722         dns_name_t *name;
  723         validator_log(val, ISC_LOG_DEBUG(3), "%s with trust %s",
  724                   val->frdataset.type == dns_rdatatype_ds ? "dsset"
  725                                       : "ds "
  726                                     "non-"
  727                                     "existe"
  728                                     "nce",
  729                   dns_trust_totext(val->frdataset.trust));
  730         have_dsset = (val->frdataset.type == dns_rdatatype_ds);
  731         name = dns_fixedname_name(&val->fname);
  732         if ((val->attributes & VALATTR_INSECURITY) != 0 &&
  733             val->frdataset.covers == dns_rdatatype_ds &&
  734             NEGATIVE(&val->frdataset) &&
  735             isdelegation(name, &val->frdataset, DNS_R_NCACHENXRRSET))
  736         {
  737             result = markanswer(val, "validator_callback_ds",
  738                         "no DS and this is a delegation");
  739         } else if ((val->attributes & VALATTR_INSECURITY) != 0) {
  740             result = proveunsecure(val, have_dsset, true);
  741         } else {
  742             result = validate_dnskey(val);
  743         }
  744         if (result != DNS_R_WAIT) {
  745             validator_done(val, result);
  746         }
  747     } else {
  748         if (eresult != DNS_R_BROKENCHAIN) {
  749             expire_rdatasets(val);
  750         }
  751         validator_log(val, ISC_LOG_DEBUG(3),
  752                   "validator_callback_ds: got %s",
  753                   isc_result_totext(eresult));
  754         validator_done(val, DNS_R_BROKENCHAIN);
  755     }
  756 
  757     want_destroy = exit_check(val);
  758     UNLOCK(&val->lock);
  759     if (want_destroy) {
  760         destroy(val);
  761     }
  762 }
  763 
  764 /*%
  765  * Callback when the CNAME record has been validated.
  766  *
  767  * Resumes validation of the unsecure zone proof.
  768  */
  769 static void
  770 validator_callback_cname(isc_task_t *task, isc_event_t *event) {
  771     dns_validatorevent_t *devent;
  772     dns_validator_t *val;
  773     bool want_destroy;
  774     isc_result_t result;
  775     isc_result_t eresult;
  776 
  777     UNUSED(task);
  778     INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
  779 
  780     devent = (dns_validatorevent_t *)event;
  781     val = devent->ev_arg;
  782     eresult = devent->result;
  783 
  784     isc_event_free(&event);
  785     dns_validator_destroy(&val->subvalidator);
  786 
  787     INSIST(val->event != NULL);
  788     INSIST((val->attributes & VALATTR_INSECURITY) != 0);
  789 
  790     validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_cname");
  791     LOCK(&val->lock);
  792     if (CANCELED(val)) {
  793         validator_done(val, ISC_R_CANCELED);
  794     } else if (eresult == ISC_R_SUCCESS) {
  795         validator_log(val, ISC_LOG_DEBUG(3), "cname with trust %s",
  796                   dns_trust_totext(val->frdataset.trust));
  797         result = proveunsecure(val, false, true);
  798         if (result != DNS_R_WAIT) {
  799             validator_done(val, result);
  800         }
  801     } else {
  802         if (eresult != DNS_R_BROKENCHAIN) {
  803             expire_rdatasets(val);
  804         }
  805         validator_log(val, ISC_LOG_DEBUG(3),
  806                   "validator_callback_cname: got %s",
  807                   isc_result_totext(eresult));
  808         validator_done(val, DNS_R_BROKENCHAIN);
  809     }
  810 
  811     want_destroy = exit_check(val);
  812     UNLOCK(&val->lock);
  813     if (want_destroy) {
  814         destroy(val);
  815     }
  816 }
  817 
  818 /*%
  819  * Callback for when NSEC records have been validated.
  820  *
  821  * Looks for NOQNAME, NODATA and OPTOUT proofs.
  822  *
  823  * Resumes the negative response validation by calling validate_nx().
  824  */
  825 static void
  826 validator_callback_nsec(isc_task_t *task, isc_event_t *event) {
  827     dns_validatorevent_t *devent;
  828     dns_validator_t *val;
  829     dns_rdataset_t *rdataset;
  830     bool want_destroy;
  831     isc_result_t result;
  832     bool exists, data;
  833 
  834     UNUSED(task);
  835     INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
  836 
  837     devent = (dns_validatorevent_t *)event;
  838     rdataset = devent->rdataset;
  839     val = devent->ev_arg;
  840     result = devent->result;
  841     dns_validator_destroy(&val->subvalidator);
  842 
  843     INSIST(val->event != NULL);
  844 
  845     validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_nsec");
  846     LOCK(&val->lock);
  847     if (CANCELED(val)) {
  848         validator_done(val, ISC_R_CANCELED);
  849     } else if (result != ISC_R_SUCCESS) {
  850         validator_log(val, ISC_LOG_DEBUG(3),
  851                   "validator_callback_nsec: got %s",
  852                   isc_result_totext(result));
  853         if (result == DNS_R_BROKENCHAIN) {
  854             val->authfail++;
  855         }
  856         if (result == ISC_R_CANCELED) {
  857             validator_done(val, result);
  858         } else {
  859             result = validate_nx(val, true);
  860             if (result != DNS_R_WAIT) {
  861                 validator_done(val, result);
  862             }
  863         }
  864     } else {
  865         dns_name_t **proofs = val->event->proofs;
  866         dns_name_t *wild = dns_fixedname_name(&val->wild);
  867 
  868         if (rdataset->type == dns_rdatatype_nsec &&
  869             rdataset->trust == dns_trust_secure &&
  870             (NEEDNODATA(val) || NEEDNOQNAME(val)) &&
  871             !FOUNDNODATA(val) && !FOUNDNOQNAME(val) &&
  872             dns_nsec_noexistnodata(val->event->type, val->event->name,
  873                        devent->name, rdataset, &exists,
  874                        &data, wild, validator_log,
  875                        val) == ISC_R_SUCCESS)
  876         {
  877             if (exists && !data) {
  878                 val->attributes |= VALATTR_FOUNDNODATA;
  879                 if (NEEDNODATA(val)) {
  880                     proofs[DNS_VALIDATOR_NODATAPROOF] =
  881                         devent->name;
  882                 }
  883             }
  884             if (!exists) {
  885                 dns_name_t *closest;
  886                 unsigned int clabels;
  887 
  888                 val->attributes |= VALATTR_FOUNDNOQNAME;
  889 
  890                 closest = dns_fixedname_name(&val->closest);
  891                 clabels = dns_name_countlabels(closest);
  892                 /*
  893                  * If we are validating a wildcard response
  894                  * clabels will not be zero.  We then need
  895                  * to check if the generated wildcard from
  896                  * dns_nsec_noexistnodata is consistent with
  897                  * the wildcard used to generate the response.
  898                  */
  899                 if (clabels == 0 ||
  900                     dns_name_countlabels(wild) == clabels + 1) {
  901                     val->attributes |= VALATTR_FOUNDCLOSEST;
  902                 }
  903                 /*
  904                  * The NSEC noqname proof also contains
  905                  * the closest encloser.
  906                  */
  907                 if (NEEDNOQNAME(val)) {
  908                     proofs[DNS_VALIDATOR_NOQNAMEPROOF] =
  909                         devent->name;
  910                 }
  911             }
  912         }
  913 
  914         result = validate_nx(val, true);
  915         if (result != DNS_R_WAIT) {
  916             validator_done(val, result);
  917         }
  918     }
  919 
  920     want_destroy = exit_check(val);
  921     UNLOCK(&val->lock);
  922     if (want_destroy) {
  923         destroy(val);
  924     }
  925 
  926     /*
  927      * Free stuff from the event.
  928      */
  929     isc_event_free(&event);
  930 }
  931 
  932 /*%
  933  * Looks for the requested name and type in the view (zones and cache).
  934  *
  935  * Returns:
  936  * \li  ISC_R_SUCCESS
  937  * \li  ISC_R_NOTFOUND
  938  * \li  DNS_R_NCACHENXDOMAIN
  939  * \li  DNS_R_NCACHENXRRSET
  940  * \li  DNS_R_NXRRSET
  941  * \li  DNS_R_NXDOMAIN
  942  * \li  DNS_R_BROKENCHAIN
  943  */
  944 static inline isc_result_t
  945 view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
  946     dns_fixedname_t fixedname;
  947     dns_name_t *foundname;
  948     isc_result_t result;
  949     unsigned int options;
  950     isc_time_t now;
  951     char namebuf[DNS_NAME_FORMATSIZE];
  952     char typebuf[DNS_RDATATYPE_FORMATSIZE];
  953 
  954     disassociate_rdatasets(val);
  955 
  956     if (isc_time_now(&now) == ISC_R_SUCCESS &&
  957         dns_resolver_getbadcache(val->view->resolver, name, type, &now))
  958     {
  959         dns_name_format(name, namebuf, sizeof(namebuf));
  960         dns_rdatatype_format(type, typebuf, sizeof(typebuf));
  961         validator_log(val, ISC_LOG_INFO, "bad cache hit (%s/%s)",
  962                   namebuf, typebuf);
  963         return (DNS_R_BROKENCHAIN);
  964     }
  965 
  966     options = DNS_DBFIND_PENDINGOK;
  967     foundname = dns_fixedname_initname(&fixedname);
  968     result = dns_view_find(val->view, name, type, 0, options, false, false,
  969                    NULL, NULL, foundname, &val->frdataset,
  970                    &val->fsigrdataset);
  971 
  972     if (result == DNS_R_NXDOMAIN) {
  973         goto notfound;
  974     } else if (result != ISC_R_SUCCESS && result != DNS_R_NCACHENXDOMAIN &&
  975            result != DNS_R_NCACHENXRRSET && result != DNS_R_EMPTYNAME &&
  976            result != DNS_R_NXRRSET && result != ISC_R_NOTFOUND)
  977     {
  978         result = ISC_R_NOTFOUND;
  979         goto notfound;
  980     }
  981 
  982     return (result);
  983 
  984 notfound:
  985     disassociate_rdatasets(val);
  986 
  987     return (result);
  988 }
  989 
  990 /*%
  991  * Checks to make sure we are not going to loop.  As we use a SHARED fetch
  992  * the validation process will stall if looping was to occur.
  993  */
  994 static inline bool
  995 check_deadlock(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
  996            dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
  997     dns_validator_t *parent;
  998 
  999     for (parent = val; parent != NULL; parent = parent->parent) {
 1000         if (parent->event != NULL && parent->event->type == type &&
 1001             dns_name_equal(parent->event->name, name) &&
 1002             /*
 1003              * As NSEC3 records are meta data you sometimes
 1004              * need to prove a NSEC3 record which says that
 1005              * itself doesn't exist.
 1006              */
 1007             (parent->event->type != dns_rdatatype_nsec3 ||
 1008              rdataset == NULL || sigrdataset == NULL ||
 1009              parent->event->message == NULL ||
 1010              parent->event->rdataset != NULL ||
 1011              parent->event->sigrdataset != NULL))
 1012         {
 1013             validator_log(val, ISC_LOG_DEBUG(3),
 1014                       "continuing validation would lead to "
 1015                       "deadlock: aborting validation");
 1016             return (true);
 1017         }
 1018     }
 1019     return (false);
 1020 }
 1021 
 1022 /*%
 1023  * Start a fetch for the requested name and type.
 1024  */
 1025 static inline isc_result_t
 1026 create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
 1027          isc_taskaction_t callback, const char *caller) {
 1028     unsigned int fopts = 0;
 1029 
 1030     disassociate_rdatasets(val);
 1031 
 1032     if (check_deadlock(val, name, type, NULL, NULL)) {
 1033         validator_log(val, ISC_LOG_DEBUG(3),
 1034                   "deadlock found (create_fetch)");
 1035         return (DNS_R_NOVALIDSIG);
 1036     }
 1037 
 1038     if ((val->options & DNS_VALIDATOR_NOCDFLAG) != 0) {
 1039         fopts |= DNS_FETCHOPT_NOCDFLAG;
 1040     }
 1041 
 1042     if ((val->options & DNS_VALIDATOR_NONTA) != 0) {
 1043         fopts |= DNS_FETCHOPT_NONTA;
 1044     }
 1045 
 1046     validator_logcreate(val, name, type, caller, "fetch");
 1047     return (dns_resolver_createfetch(
 1048         val->view->resolver, name, type, NULL, NULL, NULL, NULL, 0,
 1049         fopts, 0, NULL, val->event->ev_sender, callback, val,
 1050         &val->frdataset, &val->fsigrdataset, &val->fetch));
 1051 }
 1052 
 1053 /*%
 1054  * Start a subvalidation process.
 1055  */
 1056 static inline isc_result_t
 1057 create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
 1058          dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
 1059          isc_taskaction_t action, const char *caller) {
 1060     isc_result_t result;
 1061     unsigned int vopts = 0;
 1062     dns_rdataset_t *sig = NULL;
 1063 
 1064     if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
 1065         sig = sigrdataset;
 1066     }
 1067 
 1068     if (check_deadlock(val, name, type, rdataset, sig)) {
 1069         validator_log(val, ISC_LOG_DEBUG(3),
 1070                   "deadlock found (create_validator)");
 1071         return (DNS_R_NOVALIDSIG);
 1072     }
 1073 
 1074     /* OK to clear other options, but preserve NOCDFLAG and NONTA. */
 1075     vopts |= (val->options &
 1076           (DNS_VALIDATOR_NOCDFLAG | DNS_VALIDATOR_NONTA));
 1077 
 1078     validator_logcreate(val, name, type, caller, "validator");
 1079     result = dns_validator_create(val->view, name, type, rdataset, sig,
 1080                       NULL, vopts, val->task, action, val,
 1081                       &val->subvalidator);
 1082     if (result == ISC_R_SUCCESS) {
 1083         val->subvalidator->parent = val;
 1084         val->subvalidator->depth = val->depth + 1;
 1085     }
 1086     return (result);
 1087 }
 1088 
 1089 /*%
 1090  * Try to find a key that could have signed val->siginfo among those in
 1091  * 'rdataset'.  If found, build a dst_key_t for it and point val->key at
 1092  * it.
 1093  *
 1094  * If val->key is already non-NULL, locate it in the rdataset and then
 1095  * search past it for the *next* key that could have signed 'siginfo', then
 1096  * set val->key to that.
 1097  *
 1098  * Returns ISC_R_SUCCESS if a possible matching key has been found,
 1099  * ISC_R_NOTFOUND if not. Any other value indicates error.
 1100  */
 1101 static isc_result_t
 1102 select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) {
 1103     isc_result_t result;
 1104     dns_rdata_rrsig_t *siginfo = val->siginfo;
 1105     isc_buffer_t b;
 1106     dns_rdata_t rdata = DNS_RDATA_INIT;
 1107     dst_key_t *oldkey = val->key;
 1108     bool foundold;
 1109 
 1110     if (oldkey == NULL) {
 1111         foundold = true;
 1112     } else {
 1113         foundold = false;
 1114         val->key = NULL;
 1115     }
 1116 
 1117     result = dns_rdataset_first(rdataset);
 1118     if (result != ISC_R_SUCCESS) {
 1119         goto failure;
 1120     }
 1121     do {
 1122         dns_rdataset_current(rdataset, &rdata);
 1123 
 1124         isc_buffer_init(&b, rdata.data, rdata.length);
 1125         isc_buffer_add(&b, rdata.length);
 1126         INSIST(val->key == NULL);
 1127         result = dst_key_fromdns(&siginfo->signer, rdata.rdclass, &b,
 1128                      val->view->mctx, &val->key);
 1129         if (result == ISC_R_SUCCESS) {
 1130             if (siginfo->algorithm ==
 1131                     (dns_secalg_t)dst_key_alg(val->key) &&
 1132                 siginfo->keyid ==
 1133                     (dns_keytag_t)dst_key_id(val->key) &&
 1134                 dst_key_iszonekey(val->key))
 1135             {
 1136                 if (foundold) {
 1137                     /*
 1138                      * This is the key we're looking for.
 1139                      */
 1140                     return (ISC_R_SUCCESS);
 1141                 } else if (dst_key_compare(oldkey, val->key)) {
 1142                     foundold = true;
 1143                     dst_key_free(&oldkey);
 1144                 }
 1145             }
 1146             dst_key_free(&val->key);
 1147         }
 1148         dns_rdata_reset(&rdata);
 1149         result = dns_rdataset_next(rdataset);
 1150     } while (result == ISC_R_SUCCESS);
 1151 
 1152     if (result == ISC_R_NOMORE) {
 1153         result = ISC_R_NOTFOUND;
 1154     }
 1155 
 1156 failure:
 1157     if (oldkey != NULL) {
 1158         dst_key_free(&oldkey);
 1159     }
 1160 
 1161     return (result);
 1162 }
 1163 
 1164 /*%
 1165  * Get the key that generated the signature in val->siginfo.
 1166  */
 1167 static isc_result_t
 1168 seek_dnskey(dns_validator_t *val) {
 1169     isc_result_t result;
 1170     dns_rdata_rrsig_t *siginfo = val->siginfo;
 1171     unsigned int nlabels;
 1172     int order;
 1173     dns_namereln_t namereln;
 1174 
 1175     /*
 1176      * Is the signer name appropriate for this signature?
 1177      *
 1178      * The signer name must be at the same level as the owner name
 1179      * or closer to the DNS root.
 1180      */
 1181     namereln = dns_name_fullcompare(val->event->name, &siginfo->signer,
 1182                     &order, &nlabels);
 1183     if (namereln != dns_namereln_subdomain &&
 1184         namereln != dns_namereln_equal) {
 1185         return (DNS_R_CONTINUE);
 1186     }
 1187 
 1188     if (namereln == dns_namereln_equal) {
 1189         /*
 1190          * If this is a self-signed keyset, it must not be a zone key
 1191          * (since seek_dnskey is not called from validate_dnskey).
 1192          */
 1193         if (val->event->rdataset->type == dns_rdatatype_dnskey) {
 1194             return (DNS_R_CONTINUE);
 1195         }
 1196 
 1197         /*
 1198          * Records appearing in the parent zone at delegation
 1199          * points cannot be self-signed.
 1200          */
 1201         if (dns_rdatatype_atparent(val->event->rdataset->type)) {
 1202             return (DNS_R_CONTINUE);
 1203         }
 1204     } else {
 1205         /*
 1206          * SOA and NS RRsets can only be signed by a key with
 1207          * the same name.
 1208          */
 1209         if (val->event->rdataset->type == dns_rdatatype_soa ||
 1210             val->event->rdataset->type == dns_rdatatype_ns)
 1211         {
 1212             const char *type;
 1213 
 1214             if (val->event->rdataset->type == dns_rdatatype_soa) {
 1215                 type = "SOA";
 1216             } else {
 1217                 type = "NS";
 1218             }
 1219             validator_log(val, ISC_LOG_DEBUG(3),
 1220                       "%s signer mismatch", type);
 1221             return (DNS_R_CONTINUE);
 1222         }
 1223     }
 1224 
 1225     /*
 1226      * Do we know about this key?
 1227      */
 1228     result = view_find(val, &siginfo->signer, dns_rdatatype_dnskey);
 1229     switch (result) {
 1230     case ISC_R_SUCCESS:
 1231         /*
 1232          * We have an rrset for the given keyname.
 1233          */
 1234         val->keyset = &val->frdataset;
 1235         if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
 1236              DNS_TRUST_ANSWER(val->frdataset.trust)) &&
 1237             dns_rdataset_isassociated(&val->fsigrdataset))
 1238         {
 1239             /*
 1240              * We know the key but haven't validated it yet or
 1241              * we have a key of trust answer but a DS
 1242              * record for the zone may have been added.
 1243              */
 1244             result = create_validator(
 1245                 val, &siginfo->signer, dns_rdatatype_dnskey,
 1246                 &val->frdataset, &val->fsigrdataset,
 1247                 validator_callback_dnskey, "seek_dnskey");
 1248             if (result != ISC_R_SUCCESS) {
 1249                 return (result);
 1250             }
 1251             return (DNS_R_WAIT);
 1252         } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
 1253             /*
 1254              * Having a pending key with no signature means that
 1255              * something is broken.
 1256              */
 1257             result = DNS_R_CONTINUE;
 1258         } else if (val->frdataset.trust < dns_trust_secure) {
 1259             /*
 1260              * The key is legitimately insecure.  There's no
 1261              * point in even attempting verification.
 1262              */
 1263             val->key = NULL;
 1264             result = ISC_R_SUCCESS;
 1265         } else {
 1266             /*
 1267              * See if we've got the key used in the signature.
 1268              */
 1269             validator_log(val, ISC_LOG_DEBUG(3),
 1270                       "keyset with trust %s",
 1271                       dns_trust_totext(val->frdataset.trust));
 1272             result = select_signing_key(val, val->keyset);
 1273             if (result != ISC_R_SUCCESS) {
 1274                 /*
 1275                  * Either the key we're looking for is not
 1276                  * in the rrset, or something bad happened.
 1277                  * Give up.
 1278                  */
 1279                 result = DNS_R_CONTINUE;
 1280             }
 1281         }
 1282         break;
 1283 
 1284     case ISC_R_NOTFOUND:
 1285         /*
 1286          * We don't know anything about this key.
 1287          */
 1288         result = create_fetch(val, &siginfo->signer,
 1289                       dns_rdatatype_dnskey,
 1290                       fetch_callback_dnskey, "seek_dnskey");
 1291         if (result != ISC_R_SUCCESS) {
 1292             return (result);
 1293         }
 1294         return (DNS_R_WAIT);
 1295 
 1296     case DNS_R_NCACHENXDOMAIN:
 1297     case DNS_R_NCACHENXRRSET:
 1298     case DNS_R_EMPTYNAME:
 1299     case DNS_R_NXDOMAIN:
 1300     case DNS_R_NXRRSET:
 1301         /*
 1302          * This key doesn't exist.
 1303          */
 1304         result = DNS_R_CONTINUE;
 1305         break;
 1306 
 1307     case DNS_R_BROKENCHAIN:
 1308         return (result);
 1309 
 1310     default:
 1311         break;
 1312     }
 1313 
 1314     if (dns_rdataset_isassociated(&val->frdataset) &&
 1315         val->keyset != &val->frdataset)
 1316     {
 1317         dns_rdataset_disassociate(&val->frdataset);
 1318     }
 1319     if (dns_rdataset_isassociated(&val->fsigrdataset)) {
 1320         dns_rdataset_disassociate(&val->fsigrdataset);
 1321     }
 1322 
 1323     return (result);
 1324 }
 1325 
 1326 /*
 1327  * Compute the tag for a key represented in a DNSKEY rdata.
 1328  */
 1329 static dns_keytag_t
 1330 compute_keytag(dns_rdata_t *rdata) {
 1331     isc_region_t r;
 1332 
 1333     dns_rdata_toregion(rdata, &r);
 1334     return (dst_region_computeid(&r));
 1335 }
 1336 
 1337 /*%
 1338  * Is the DNSKEY rrset in val->event->rdataset self-signed?
 1339  */
 1340 static bool
 1341 selfsigned_dnskey(dns_validator_t *val) {
 1342     dns_rdataset_t *rdataset = val->event->rdataset;
 1343     dns_rdataset_t *sigrdataset = val->event->sigrdataset;
 1344     dns_name_t *name = val->event->name;
 1345     isc_result_t result;
 1346     isc_mem_t *mctx = val->view->mctx;
 1347     bool answer = false;
 1348 
 1349     if (rdataset->type != dns_rdatatype_dnskey) {
 1350         return (false);
 1351     }
 1352 
 1353     for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
 1354          result = dns_rdataset_next(rdataset))
 1355     {
 1356         dns_rdata_t keyrdata = DNS_RDATA_INIT;
 1357         dns_rdata_t sigrdata = DNS_RDATA_INIT;
 1358         dns_rdata_dnskey_t key;
 1359         dns_rdata_rrsig_t sig;
 1360         dns_keytag_t keytag;
 1361 
 1362         dns_rdata_reset(&keyrdata);
 1363         dns_rdataset_current(rdataset, &keyrdata);
 1364         result = dns_rdata_tostruct(&keyrdata, &key, NULL);
 1365         RUNTIME_CHECK(result == ISC_R_SUCCESS);
 1366         keytag = compute_keytag(&keyrdata);
 1367 
 1368         for (result = dns_rdataset_first(sigrdataset);
 1369              result == ISC_R_SUCCESS;
 1370              result = dns_rdataset_next(sigrdataset))
 1371         {
 1372             dst_key_t *dstkey = NULL;
 1373 
 1374             dns_rdata_reset(&sigrdata);
 1375             dns_rdataset_current(sigrdataset, &sigrdata);
 1376             result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
 1377             RUNTIME_CHECK(result == ISC_R_SUCCESS);
 1378 
 1379             if (sig.algorithm != key.algorithm ||
 1380                 sig.keyid != keytag ||
 1381                 !dns_name_equal(name, &sig.signer))
 1382             {
 1383                 continue;
 1384             }
 1385 
 1386             result = dns_dnssec_keyfromrdata(name, &keyrdata, mctx,
 1387                              &dstkey);
 1388             if (result != ISC_R_SUCCESS) {
 1389                 continue;
 1390             }
 1391 
 1392             result = dns_dnssec_verify(name, rdataset, dstkey, true,
 1393                            val->view->maxbits, mctx,
 1394                            &sigrdata, NULL);
 1395             dst_key_free(&dstkey);
 1396             if (result != ISC_R_SUCCESS) {
 1397                 continue;
 1398             }
 1399 
 1400             if ((key.flags & DNS_KEYFLAG_REVOKE) == 0) {
 1401                 answer = true;
 1402                 continue;
 1403             }
 1404 
 1405             dns_view_untrust(val->view, name, &key);
 1406         }
 1407     }
 1408 
 1409     return (answer);
 1410 }
 1411 
 1412 /*%
 1413  * Attempt to verify the rdataset using the given key and rdata (RRSIG).
 1414  * The signature was good and from a wildcard record and the QNAME does
 1415  * not match the wildcard we need to look for a NOQNAME proof.
 1416  *
 1417  * Returns:
 1418  * \li  ISC_R_SUCCESS if the verification succeeds.
 1419  * \li  Others if the verification fails.
 1420  */
 1421 static isc_result_t
 1422 verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata,
 1423        uint16_t keyid) {
 1424     isc_result_t result;
 1425     dns_fixedname_t fixed;
 1426     bool ignore = false;
 1427     dns_name_t *wild;
 1428 
 1429     val->attributes |= VALATTR_TRIEDVERIFY;
 1430     wild = dns_fixedname_initname(&fixed);
 1431 again:
 1432     result = dns_dnssec_verify(val->event->name, val->event->rdataset, key,
 1433                    ignore, val->view->maxbits, val->view->mctx,
 1434                    rdata, wild);
 1435     if ((result == DNS_R_SIGEXPIRED || result == DNS_R_SIGFUTURE) &&
 1436         val->view->acceptexpired)
 1437     {
 1438         ignore = true;
 1439         goto again;
 1440     }
 1441 
 1442     if (ignore && (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD))
 1443     {
 1444         validator_log(val, ISC_LOG_INFO,
 1445                   "accepted expired %sRRSIG (keyid=%u)",
 1446                   (result == DNS_R_FROMWILDCARD) ? "wildcard " : "",
 1447                   keyid);
 1448     } else if (result == DNS_R_SIGEXPIRED || result == DNS_R_SIGFUTURE) {
 1449         validator_log(val, ISC_LOG_INFO,
 1450                   "verify failed due to bad signature (keyid=%u): "
 1451                   "%s",
 1452                   keyid, isc_result_totext(result));
 1453     } else {
 1454         validator_log(val, ISC_LOG_DEBUG(3),
 1455                   "verify rdataset (keyid=%u): %s", keyid,
 1456                   isc_result_totext(result));
 1457     }
 1458     if (result == DNS_R_FROMWILDCARD) {
 1459         if (!dns_name_equal(val->event->name, wild)) {
 1460             dns_name_t *closest;
 1461             unsigned int labels;
 1462 
 1463             /*
 1464              * Compute the closest encloser in case we need it
 1465              * for the NSEC3 NOQNAME proof.
 1466              */
 1467             closest = dns_fixedname_name(&val->closest);
 1468             dns_name_copynf(wild, closest);
 1469             labels = dns_name_countlabels(closest) - 1;
 1470             dns_name_getlabelsequence(closest, 1, labels, closest);
 1471             val->attributes |= VALATTR_NEEDNOQNAME;
 1472         }
 1473         result = ISC_R_SUCCESS;
 1474     }
 1475     return (result);
 1476 }
 1477 
 1478 /*%
 1479  * Attempts positive response validation of a normal RRset.
 1480  *
 1481  * Returns:
 1482  * \li  ISC_R_SUCCESS   Validation completed successfully
 1483  * \li  DNS_R_WAIT  Validation has started but is waiting
 1484  *          for an event.
 1485  * \li  Other return codes are possible and all indicate failure.
 1486  */
 1487 static isc_result_t
 1488 validate_answer(dns_validator_t *val, bool resume) {
 1489     isc_result_t result, vresult = DNS_R_NOVALIDSIG;
 1490     dns_validatorevent_t *event;
 1491     dns_rdata_t rdata = DNS_RDATA_INIT;
 1492 
 1493     /*
 1494      * Caller must be holding the validator lock.
 1495      */
 1496 
 1497     event = val->event;
 1498 
 1499     if (resume) {
 1500         /*
 1501          * We already have a sigrdataset.
 1502          */
 1503         result = ISC_R_SUCCESS;
 1504         validator_log(val, ISC_LOG_DEBUG(3), "resuming validate");
 1505     } else {
 1506         result = dns_rdataset_first(event->sigrdataset);
 1507     }
 1508 
 1509     for (; result == ISC_R_SUCCESS;
 1510          result = dns_rdataset_next(event->sigrdataset)) {
 1511         dns_rdata_reset(&rdata);
 1512         dns_rdataset_current(event->sigrdataset, &rdata);
 1513         if (val->siginfo == NULL) {
 1514             val->siginfo = isc_mem_get(val->view->mctx,
 1515                            sizeof(*val->siginfo));
 1516         }
 1517         result = dns_rdata_tostruct(&rdata, val->siginfo, NULL);
 1518         if (result != ISC_R_SUCCESS) {
 1519             return (result);
 1520         }
 1521 
 1522         /*
 1523          * At this point we could check that the signature algorithm
 1524          * was known and "sufficiently good".
 1525          */
 1526         if (!dns_resolver_algorithm_supported(val->view->resolver,
 1527                               event->name,
 1528                               val->siginfo->algorithm))
 1529         {
 1530             resume = false;
 1531             continue;
 1532         }
 1533 
 1534         if (!resume) {
 1535             result = seek_dnskey(val);
 1536             if (result == DNS_R_CONTINUE) {
 1537                 continue; /* Try the next SIG RR. */
 1538             }
 1539             if (result != ISC_R_SUCCESS) {
 1540                 return (result);
 1541             }
 1542         }
 1543 
 1544         /*
 1545          * There isn't a secure DNSKEY for this signature so move
 1546          * onto the next RRSIG.
 1547          */
 1548         if (val->key == NULL) {
 1549             resume = false;
 1550             continue;
 1551         }
 1552 
 1553         do {
 1554             isc_result_t tresult;
 1555             vresult = verify(val, val->key, &rdata,
 1556                      val->siginfo->keyid);
 1557             if (vresult == ISC_R_SUCCESS) {
 1558                 break;
 1559             }
 1560 
 1561             tresult = select_signing_key(val, val->keyset);
 1562             if (tresult != ISC_R_SUCCESS) {
 1563                 break;
 1564             }
 1565         } while (1);
 1566         if (vresult != ISC_R_SUCCESS) {
 1567             validator_log(val, ISC_LOG_DEBUG(3),
 1568                       "failed to verify rdataset");
 1569         } else {
 1570             dns_rdataset_trimttl(event->rdataset,
 1571                          event->sigrdataset, val->siginfo,
 1572                          val->start,
 1573                          val->view->acceptexpired);
 1574         }
 1575 
 1576         if (val->key != NULL) {
 1577             dst_key_free(&val->key);
 1578         }
 1579         if (val->keyset != NULL) {
 1580             dns_rdataset_disassociate(val->keyset);
 1581             val->keyset = NULL;
 1582         }
 1583         val->key = NULL;
 1584         if (NEEDNOQNAME(val)) {
 1585             if (val->event->message == NULL) {
 1586                 validator_log(val, ISC_LOG_DEBUG(3),
 1587                           "no message available "
 1588                           "for noqname proof");
 1589                 return (DNS_R_NOVALIDSIG);
 1590             }
 1591             validator_log(val, ISC_LOG_DEBUG(3),
 1592                       "looking for noqname proof");
 1593             return (validate_nx(val, false));
 1594         } else if (vresult == ISC_R_SUCCESS) {
 1595             marksecure(event);
 1596             validator_log(val, ISC_LOG_DEBUG(3),
 1597                       "marking as secure, "
 1598                       "noqname proof not needed");
 1599             return (ISC_R_SUCCESS);
 1600         } else {
 1601             validator_log(val, ISC_LOG_DEBUG(3),
 1602                       "verify failure: %s",
 1603                       isc_result_totext(result));
 1604             resume = false;
 1605         }
 1606     }
 1607     if (result != ISC_R_NOMORE) {
 1608         validator_log(val, ISC_LOG_DEBUG(3),
 1609                   "failed to iterate signatures: %s",
 1610                   isc_result_totext(result));
 1611         return (result);
 1612     }
 1613 
 1614     validator_log(val, ISC_LOG_INFO, "no valid signature found");
 1615     return (vresult);
 1616 }
 1617 
 1618 /*%
 1619  * Check whether this DNSKEY (keyrdata) signed the DNSKEY RRset
 1620  * (val->event->rdataset).
 1621  */
 1622 static isc_result_t
 1623 check_signer(dns_validator_t *val, dns_rdata_t *keyrdata, uint16_t keyid,
 1624          dns_secalg_t algorithm) {
 1625     dns_rdata_rrsig_t sig;
 1626     dst_key_t *dstkey = NULL;
 1627     isc_result_t result;
 1628 
 1629     for (result = dns_rdataset_first(val->event->sigrdataset);
 1630          result == ISC_R_SUCCESS;
 1631          result = dns_rdataset_next(val->event->sigrdataset))
 1632     {
 1633         dns_rdata_t rdata = DNS_RDATA_INIT;
 1634 
 1635         dns_rdataset_current(val->event->sigrdataset, &rdata);
 1636         result = dns_rdata_tostruct(&rdata, &sig, NULL);
 1637         RUNTIME_CHECK(result == ISC_R_SUCCESS);
 1638         if (keyid != sig.keyid || algorithm != sig.algorithm) {
 1639             continue;
 1640         }
 1641         if (dstkey == NULL) {
 1642             result = dns_dnssec_keyfromrdata(
 1643                 val->event->name, keyrdata, val->view->mctx,
 1644                 &dstkey);
 1645             if (result != ISC_R_SUCCESS) {
 1646                 /*
 1647                  * This really shouldn't happen, but...
 1648                  */
 1649                 continue;
 1650             }
 1651         }
 1652         result = verify(val, dstkey, &rdata, sig.keyid);
 1653         if (result == ISC_R_SUCCESS) {
 1654             break;
 1655         }
 1656     }
 1657 
 1658     if (dstkey != NULL) {
 1659         dst_key_free(&dstkey);
 1660     }
 1661 
 1662     return (result);
 1663 }
 1664 
 1665 /*
 1666  * get_dsset() is called to look up a DS RRset corresponding to the name
 1667  * of a DNSKEY record, either in the cache or, if necessary, by starting a
 1668  * fetch. This is done in the context of validating a zone key to build a
 1669  * trust chain.
 1670  *
 1671  * Returns:
 1672  * \li  ISC_R_COMPLETE      a DS has not been found; the caller should
 1673  *              stop trying to validate the zone key and
 1674  *              return the result code in '*resp'.
 1675  * \li  DNS_R_CONTINUE      a DS has been found and the caller may
 1676  *              continue the zone key validation.
 1677  */
 1678 static isc_result_t
 1679 get_dsset(dns_validator_t *val, dns_name_t *tname, isc_result_t *resp) {
 1680     isc_result_t result;
 1681 
 1682     result = view_find(val, tname, dns_rdatatype_ds);
 1683     switch (result) {
 1684     case ISC_R_SUCCESS:
 1685         /*
 1686          * We have a DS RRset.
 1687          */
 1688         val->dsset = &val->frdataset;
 1689         if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
 1690              DNS_TRUST_ANSWER(val->frdataset.trust)) &&
 1691             dns_rdataset_isassociated(&val->fsigrdataset))
 1692         {
 1693             /*
 1694              * ... which is signed but not yet validated.
 1695              */
 1696             result = create_validator(
 1697                 val, tname, dns_rdatatype_ds, &val->frdataset,
 1698                 &val->fsigrdataset, validator_callback_ds,
 1699                 "validate_dnskey");
 1700             *resp = DNS_R_WAIT;
 1701             if (result != ISC_R_SUCCESS) {
 1702                 *resp = result;
 1703             }
 1704             return (ISC_R_COMPLETE);
 1705         } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
 1706             /*
 1707              * There should never be an unsigned DS.
 1708              */
 1709             disassociate_rdatasets(val);
 1710             validator_log(val, ISC_LOG_DEBUG(2),
 1711                       "unsigned DS record");
 1712             *resp = DNS_R_NOVALIDSIG;
 1713             return (ISC_R_COMPLETE);
 1714         }
 1715         break;
 1716 
 1717     case ISC_R_NOTFOUND:
 1718         /*
 1719          * We don't have the DS.  Find it.
 1720          */
 1721         result = create_fetch(val, tname, dns_rdatatype_ds,
 1722                       fetch_callback_ds, "validate_dnskey");
 1723         *resp = DNS_R_WAIT;
 1724         if (result != ISC_R_SUCCESS) {
 1725             *resp = result;
 1726         }
 1727         return (ISC_R_COMPLETE);
 1728 
 1729     case DNS_R_NCACHENXDOMAIN:
 1730     case DNS_R_NCACHENXRRSET:
 1731     case DNS_R_EMPTYNAME:
 1732     case DNS_R_NXDOMAIN:
 1733     case DNS_R_NXRRSET:
 1734     case DNS_R_CNAME:
 1735         /*
 1736          * The DS does not exist.
 1737          */
 1738         disassociate_rdatasets(val);
 1739         validator_log(val, ISC_LOG_DEBUG(2), "no DS record");
 1740         *resp = DNS_R_NOVALIDSIG;
 1741         return (ISC_R_COMPLETE);
 1742 
 1743     case DNS_R_BROKENCHAIN:
 1744         *resp = result;
 1745         return (ISC_R_COMPLETE);
 1746 
 1747     default:
 1748         break;
 1749     }
 1750 
 1751     return (DNS_R_CONTINUE);
 1752 }
 1753 
 1754 /*%
 1755  * Attempts positive response validation of an RRset containing zone keys
 1756  * (i.e. a DNSKEY rrset).
 1757  *
 1758  * Caller must be holding the validator lock.
 1759  *
 1760  * Returns:
 1761  * \li  ISC_R_SUCCESS   Validation completed successfully
 1762  * \li  DNS_R_WAIT  Validation has started but is waiting
 1763  *          for an event.
 1764  * \li  Other return codes are possible and all indicate failure.
 1765  */
 1766 static isc_result_t
 1767 validate_dnskey(dns_validator_t *val) {
 1768     isc_result_t result;
 1769     dns_rdata_t dsrdata = DNS_RDATA_INIT;
 1770     dns_rdata_t keyrdata = DNS_RDATA_INIT;
 1771     dns_keynode_t *keynode = NULL;
 1772     dns_rdata_ds_t ds;
 1773     bool supported_algorithm;
 1774     char digest_types[256];
 1775 
 1776     /*
 1777      * If we don't already have a DS RRset, check to see if there's
 1778      * a DS style trust anchor configured for this key.
 1779      */
 1780     if (val->dsset == NULL) {
 1781         result = dns_keytable_find(val->keytable, val->event->name,
 1782                        &keynode);
 1783         if (result == ISC_R_SUCCESS) {
 1784             if (dns_keynode_dsset(keynode, &val->fdsset)) {
 1785                 val->dsset = &val->fdsset;
 1786             }
 1787             dns_keytable_detachkeynode(val->keytable, &keynode);
 1788         }
 1789     }
 1790 
 1791     /*
 1792      * No trust anchor for this name, so we look up the DS at the parent.
 1793      */
 1794     if (val->dsset == NULL) {
 1795         isc_result_t tresult = ISC_R_SUCCESS;
 1796 
 1797         /*
 1798          * If this is the root name and there was no trust anchor,
 1799          * we can give up now, since there's no DS at the root.
 1800          */
 1801         if (dns_name_equal(val->event->name, dns_rootname)) {
 1802             if ((val->attributes & VALATTR_TRIEDVERIFY) != 0) {
 1803                 validator_log(val, ISC_LOG_DEBUG(3),
 1804                           "root key failed to validate");
 1805             } else {
 1806                 validator_log(val, ISC_LOG_DEBUG(3),
 1807                           "no trusted root key");
 1808             }
 1809             result = DNS_R_NOVALIDSIG;
 1810             goto cleanup;
 1811         }
 1812 
 1813         /*
 1814          * Look up the DS RRset for this name.
 1815          */
 1816         result = get_dsset(val, val->event->name, &tresult);
 1817         if (result == ISC_R_COMPLETE) {
 1818             result = tresult;
 1819             goto cleanup;
 1820         }
 1821     }
 1822 
 1823     /*
 1824      * We have a DS set.
 1825      */
 1826     INSIST(val->dsset != NULL);
 1827 
 1828     if (val->dsset->trust < dns_trust_secure) {
 1829         result = markanswer(val, "validate_dnskey (2)", "insecure DS");
 1830         goto cleanup;
 1831     }
 1832 
 1833     /*
 1834      * Look through the DS record and find the keys that can sign the
 1835      * key set and the matching signature.  For each such key, attempt
 1836      * verification.
 1837      */
 1838 
 1839     supported_algorithm = false;
 1840 
 1841     /*
 1842      * If DNS_DSDIGEST_SHA256 or DNS_DSDIGEST_SHA384 is present we
 1843      * are required to prefer it over DNS_DSDIGEST_SHA1.  This in
 1844      * practice means that we need to ignore DNS_DSDIGEST_SHA1 if a
 1845      * DNS_DSDIGEST_SHA256 or DNS_DSDIGEST_SHA384 is present.
 1846      */
 1847     memset(digest_types, 1, sizeof(digest_types));
 1848     for (result = dns_rdataset_first(val->dsset); result == ISC_R_SUCCESS;
 1849          result = dns_rdataset_next(val->dsset))
 1850     {
 1851         dns_rdata_reset(&dsrdata);
 1852         dns_rdataset_current(val->dsset, &dsrdata);
 1853         result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
 1854         RUNTIME_CHECK(result == ISC_R_SUCCESS);
 1855 
 1856         if (!dns_resolver_ds_digest_supported(val->view->resolver,
 1857                               val->event->name,
 1858                               ds.digest_type))
 1859         {
 1860             continue;
 1861         }
 1862 
 1863         if (!dns_resolver_algorithm_supported(val->view->resolver,
 1864                               val->event->name,
 1865                               ds.algorithm))
 1866         {
 1867             continue;
 1868         }
 1869 
 1870         if ((ds.digest_type == DNS_DSDIGEST_SHA256 &&
 1871              ds.length == ISC_SHA256_DIGESTLENGTH) ||
 1872             (ds.digest_type == DNS_DSDIGEST_SHA384 &&
 1873              ds.length == ISC_SHA384_DIGESTLENGTH))
 1874         {
 1875             digest_types[DNS_DSDIGEST_SHA1] = 0;
 1876             break;
 1877         }
 1878     }
 1879 
 1880     for (result = dns_rdataset_first(val->dsset); result == ISC_R_SUCCESS;
 1881          result = dns_rdataset_next(val->dsset))
 1882     {
 1883         dns_rdata_reset(&dsrdata);
 1884         dns_rdataset_current(val->dsset, &dsrdata);
 1885         result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
 1886         RUNTIME_CHECK(result == ISC_R_SUCCESS);
 1887 
 1888         if (digest_types[ds.digest_type] == 0) {
 1889             continue;
 1890         }
 1891 
 1892         if (!dns_resolver_ds_digest_supported(val->view->resolver,
 1893                               val->event->name,
 1894                               ds.digest_type))
 1895         {
 1896             continue;
 1897         }
 1898 
 1899         if (!dns_resolver_algorithm_supported(val->view->resolver,
 1900                               val->event->name,
 1901                               ds.algorithm))
 1902         {
 1903             continue;
 1904         }
 1905 
 1906         supported_algorithm = true;
 1907 
 1908         /*
 1909          * Find the DNSKEY matching the DS...
 1910          */
 1911         result = dns_dnssec_matchdskey(val->event->name, &dsrdata,
 1912                            val->event->rdataset, &keyrdata);
 1913         if (result != ISC_R_SUCCESS) {
 1914             validator_log(val, ISC_LOG_DEBUG(3),
 1915                       "no DNSKEY matching DS");
 1916             continue;
 1917         }
 1918 
 1919         /*
 1920          * ... and check that it signed the DNSKEY RRset.
 1921          */
 1922         result = check_signer(val, &keyrdata, ds.key_tag, ds.algorithm);
 1923         if (result == ISC_R_SUCCESS) {
 1924             break;
 1925         }
 1926         validator_log(val, ISC_LOG_DEBUG(3),
 1927                   "no RRSIG matching DS key");
 1928     }
 1929 
 1930     if (result == ISC_R_SUCCESS) {
 1931         marksecure(val->event);
 1932         validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (DS)");
 1933     } else if (result == ISC_R_NOMORE && !supported_algorithm) {
 1934         validator_log(val, ISC_LOG_DEBUG(3),
 1935                   "no supported algorithm/digest (DS)");
 1936         result = markanswer(val, "validate_dnskey (3)",
 1937                     "no supported algorithm/digest (DS)");
 1938     } else {
 1939         validator_log(val, ISC_LOG_INFO,
 1940                   "no valid signature found (DS)");
 1941         result = DNS_R_NOVALIDSIG;
 1942     }
 1943 
 1944 cleanup:
 1945     if (val->dsset == &val->fdsset) {
 1946         val->dsset = NULL;
 1947         dns_rdataset_disassociate(&val->fdsset);
 1948     }
 1949 
 1950     return (result);
 1951 }
 1952 
 1953 /*%
 1954  * val_rdataset_first and val_rdataset_next provide iteration methods
 1955  * that hide whether we are iterating across the AUTHORITY section of
 1956  * a message, or a negative cache rdataset.
 1957  */
 1958 static isc_result_t
 1959 val_rdataset_first(dns_validator_t *val, dns_name_t **namep,
 1960            dns_rdataset_t **rdatasetp) {
 1961     dns_message_t *message = val->event->message;
 1962     isc_result_t result;
 1963 
 1964     REQUIRE(rdatasetp != NULL);
 1965     REQUIRE(namep != NULL);
 1966     if (message == NULL) {
 1967         REQUIRE(*rdatasetp != NULL);
 1968         REQUIRE(*namep != NULL);
 1969     } else {
 1970         REQUIRE(*rdatasetp == NULL);
 1971         REQUIRE(*namep == NULL);
 1972     }
 1973 
 1974     if (message != NULL) {
 1975         result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
 1976         if (result != ISC_R_SUCCESS) {
 1977             return (result);
 1978         }
 1979         dns_message_currentname(message, DNS_SECTION_AUTHORITY, namep);
 1980         *rdatasetp = ISC_LIST_HEAD((*namep)->list);
 1981         INSIST(*rdatasetp != NULL);
 1982     } else {
 1983         result = dns_rdataset_first(val->event->rdataset);
 1984         if (result == ISC_R_SUCCESS) {
 1985             dns_ncache_current(val->event->rdataset, *namep,
 1986                        *rdatasetp);
 1987         }
 1988     }
 1989     return (result);
 1990 }
 1991 
 1992 static isc_result_t
 1993 val_rdataset_next(dns_validator_t *val, dns_name_t **namep,
 1994           dns_rdataset_t **rdatasetp) {
 1995     dns_message_t *message = val->event->message;
 1996     isc_result_t result = ISC_R_SUCCESS;
 1997 
 1998     REQUIRE(rdatasetp != NULL && *rdatasetp != NULL);
 1999     REQUIRE(namep != NULL && *namep != NULL);
 2000 
 2001     if (message != NULL) {
 2002         dns_rdataset_t *rdataset = *rdatasetp;
 2003         rdataset = ISC_LIST_NEXT(rdataset, link);
 2004         if (rdataset == NULL) {
 2005             *namep = NULL;
 2006             result = dns_message_nextname(message,
 2007                               DNS_SECTION_AUTHORITY);
 2008             if (result == ISC_R_SUCCESS) {
 2009                 dns_message_currentname(
 2010                     message, DNS_SECTION_AUTHORITY, namep);
 2011                 rdataset = ISC_LIST_HEAD((*namep)->list);
 2012                 INSIST(rdataset != NULL);
 2013             }
 2014         }
 2015         *rdatasetp = rdataset;
 2016     } else {
 2017         dns_rdataset_disassociate(*rdatasetp);
 2018         result = dns_rdataset_next(val->event->rdataset);
 2019         if (result == ISC_R_SUCCESS) {
 2020             dns_ncache_current(val->event->rdataset, *namep,
 2021                        *rdatasetp);
 2022         }
 2023     }
 2024     return (result);
 2025 }
 2026 
 2027 /*%
 2028  * Look for NODATA at the wildcard and NOWILDCARD proofs in the
 2029  * previously validated NSEC records.  As these proofs are mutually
 2030  * exclusive we stop when one is found.
 2031  *
 2032  * Returns
 2033  * \li  ISC_R_SUCCESS
 2034  */
 2035 static isc_result_t
 2036 checkwildcard(dns_validator_t *val, dns_rdatatype_t type,
 2037           dns_name_t *zonename) {
 2038     dns_name_t *name, *wild, tname;
 2039     isc_result_t result;
 2040     bool exists, data;
 2041     char namebuf[DNS_NAME_FORMATSIZE];
 2042     dns_rdataset_t *rdataset, trdataset;
 2043 
 2044     dns_name_init(&tname, NULL);
 2045     dns_rdataset_init(&trdataset);
 2046     wild = dns_fixedname_name(&val->wild);
 2047 
 2048     if (dns_name_countlabels(wild) == 0) {
 2049         validator_log(val, ISC_LOG_DEBUG(3),
 2050                   "in checkwildcard: no wildcard to check");
 2051         return (ISC_R_SUCCESS);
 2052     }
 2053 
 2054     dns_name_format(wild, namebuf, sizeof(namebuf));
 2055     validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf);
 2056 
 2057     if (val->event->message == NULL) {
 2058         name = &tname;
 2059         rdataset = &trdataset;
 2060     } else {
 2061         name = NULL;
 2062         rdataset = NULL;
 2063     }
 2064 
 2065     for (result = val_rdataset_first(val, &name, &rdataset);
 2066          result == ISC_R_SUCCESS;
 2067          result = val_rdataset_next(val, &name, &rdataset))
 2068     {
 2069         if (rdataset->type != type ||
 2070             rdataset->trust != dns_trust_secure) {
 2071             continue;
 2072         }
 2073 
 2074         if (rdataset->type == dns_rdatatype_nsec &&
 2075             (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
 2076             !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
 2077             dns_nsec_noexistnodata(val->event->type, wild, name,
 2078                        rdataset, &exists, &data, NULL,
 2079                        validator_log, val) == ISC_R_SUCCESS)
 2080         {
 2081             dns_name_t **proofs = val->event->proofs;
 2082             if (exists && !data) {
 2083                 val->attributes |= VALATTR_FOUNDNODATA;
 2084             }
 2085             if (exists && !data && NEEDNODATA(val)) {
 2086                 proofs[DNS_VALIDATOR_NODATAPROOF] = name;
 2087             }
 2088             if (!exists) {
 2089                 val->attributes |= VALATTR_FOUNDNOWILDCARD;
 2090             }
 2091             if (!exists && NEEDNOQNAME(val)) {
 2092                 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] = name;
 2093             }
 2094             if (dns_rdataset_isassociated(&trdataset)) {
 2095                 dns_rdataset_disassociate(&trdataset);
 2096             }
 2097             return (ISC_R_SUCCESS);
 2098         }
 2099 
 2100         if (rdataset->type == dns_rdatatype_nsec3 &&
 2101             (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
 2102             !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
 2103             dns_nsec3_noexistnodata(
 2104                 val->event->type, wild, name, rdataset, zonename,
 2105                 &exists, &data, NULL, NULL, NULL, NULL, NULL, NULL,
 2106                 validator_log, val) == ISC_R_SUCCESS)
 2107         {
 2108             dns_name_t **proofs = val->event->proofs;
 2109             if (exists && !data) {
 2110                 val->attributes |= VALATTR_FOUNDNODATA;
 2111             }
 2112             if (exists && !data && NEEDNODATA(val)) {
 2113                 proofs[DNS_VALIDATOR_NODATAPROOF] = name;
 2114             }
 2115             if (!exists) {
 2116                 val->attributes |= VALATTR_FOUNDNOWILDCARD;
 2117             }
 2118             if (!exists && NEEDNOQNAME(val)) {
 2119                 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] = name;
 2120             }
 2121             if (dns_rdataset_isassociated(&trdataset)) {
 2122                 dns_rdataset_disassociate(&trdataset);
 2123             }
 2124             return (ISC_R_SUCCESS);
 2125         }
 2126     }
 2127     if (result == ISC_R_NOMORE) {
 2128         result = ISC_R_SUCCESS;
 2129     }
 2130     if (dns_rdataset_isassociated(&trdataset)) {
 2131         dns_rdataset_disassociate(&trdataset);
 2132     }
 2133     return (result);
 2134 }
 2135 
 2136 /*
 2137  * Look for the needed proofs for a negative or wildcard response
 2138  * from a zone using NSEC3, and set flags in the validator as they
 2139  * are found.
 2140  */
 2141 static isc_result_t
 2142 findnsec3proofs(dns_validator_t *val) {
 2143     dns_name_t *name, tname;
 2144     isc_result_t result;
 2145     bool exists, data, optout, unknown;
 2146     bool setclosest, setnearest, *setclosestp;
 2147     dns_fixedname_t fclosest, fnearest, fzonename;
 2148     dns_name_t *closest, *nearest, *zonename, *closestp;
 2149     dns_name_t **proofs = val->event->proofs;
 2150     dns_rdataset_t *rdataset, trdataset;
 2151 
 2152     dns_name_init(&tname, NULL);
 2153     dns_rdataset_init(&trdataset);
 2154     closest = dns_fixedname_initname(&fclosest);
 2155     nearest = dns_fixedname_initname(&fnearest);
 2156     zonename = dns_fixedname_initname(&fzonename);
 2157 
 2158     if (val->event->message == NULL) {
 2159         name = &tname;
 2160         rdataset = &trdataset;
 2161     } else {
 2162         name = NULL;
 2163         rdataset = NULL;
 2164     }
 2165 
 2166     for (result = val_rdataset_first(val, &name, &rdataset);
 2167          result == ISC_R_SUCCESS;
 2168          result = val_rdataset_next(val, &name, &rdataset))
 2169     {
 2170         if (rdataset->type != dns_rdatatype_nsec3 ||
 2171             rdataset->trust != dns_trust_secure)
 2172         {
 2173             continue;
 2174         }
 2175 
 2176         result = dns_nsec3_noexistnodata(
 2177             val->event->type, val->event->name, name, rdataset,
 2178             zonename, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 2179             NULL, validator_log, val);
 2180         if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS) {
 2181             if (dns_rdataset_isassociated(&trdataset)) {
 2182                 dns_rdataset_disassociate(&trdataset);
 2183             }
 2184             return (result);
 2185         }
 2186     }
 2187     if (result != ISC_R_NOMORE) {
 2188         result = ISC_R_SUCCESS;
 2189     }
 2190     POST(result);
 2191 
 2192     if (dns_name_countlabels(zonename) == 0) {
 2193         return (ISC_R_SUCCESS);
 2194     }
 2195 
 2196     /*
 2197      * If the val->closest is set then we want to use it otherwise
 2198      * we need to discover it.
 2199      */
 2200     if (dns_name_countlabels(dns_fixedname_name(&val->closest)) != 0) {
 2201         char namebuf[DNS_NAME_FORMATSIZE];
 2202 
 2203         dns_name_format(dns_fixedname_name(&val->closest), namebuf,
 2204                 sizeof(namebuf));
 2205         validator_log(val, ISC_LOG_DEBUG(3),
 2206                   "closest encloser from wildcard signature '%s'",
 2207                   namebuf);
 2208         dns_name_copynf(dns_fixedname_name(&val->closest), closest);
 2209         closestp = NULL;
 2210         setclosestp = NULL;
 2211     } else {
 2212         closestp = closest;
 2213         setclosestp = &setclosest;
 2214     }
 2215 
 2216     for (result = val_rdataset_first(val, &name, &rdataset);
 2217          result == ISC_R_SUCCESS;
 2218          result = val_rdataset_next(val, &name, &rdataset))
 2219     {
 2220         if (rdataset->type != dns_rdatatype_nsec3 ||
 2221             rdataset->trust != dns_trust_secure)
 2222         {
 2223             continue;
 2224         }
 2225 
 2226         /*
 2227          * We process all NSEC3 records to find the closest
 2228          * encloser and nearest name to the closest encloser.
 2229          */
 2230         setclosest = setnearest = false;
 2231         optout = false;
 2232         unknown = false;
 2233         result = dns_nsec3_noexistnodata(
 2234             val->event->type, val->event->name, name, rdataset,
 2235             zonename, &exists, &data, &optout, &unknown,
 2236             setclosestp, &setnearest, closestp, nearest,
 2237             validator_log, val);
 2238         if (unknown) {
 2239             val->attributes |= VALATTR_FOUNDUNKNOWN;
 2240         }
 2241         if (result != ISC_R_SUCCESS) {
 2242             continue;
 2243         }
 2244         if (setclosest) {
 2245             proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
 2246         }
 2247         if (exists && !data && NEEDNODATA(val)) {
 2248             val->attributes |= VALATTR_FOUNDNODATA;
 2249             proofs[DNS_VALIDATOR_NODATAPROOF] = name;
 2250         }
 2251         if (!exists && setnearest) {
 2252             val->attributes |= VALATTR_FOUNDNOQNAME;
 2253             proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name;
 2254             if (optout) {
 2255                 val->attributes |= VALATTR_FOUNDOPTOUT;
 2256             }
 2257         }
 2258     }
 2259     if (result == ISC_R_NOMORE) {
 2260         result = ISC_R_SUCCESS;
 2261     }
 2262 
 2263     /*
 2264      * To know we have a valid noqname and optout proofs we need to also
 2265      * have a valid closest encloser.  Otherwise we could still be looking
 2266      * at proofs from the parent zone.
 2267      */
 2268     if (dns_name_countlabels(closest) > 0 &&
 2269         dns_name_countlabels(nearest) ==
 2270             dns_name_countlabels(closest) + 1 &&
 2271         dns_name_issubdomain(nearest, closest))
 2272     {
 2273         val->attributes |= VALATTR_FOUNDCLOSEST;
 2274         result = dns_name_concatenate(dns_wildcardname, closest,
 2275                           dns_fixedname_name(&val->wild),
 2276                           NULL);
 2277         RUNTIME_CHECK(result == ISC_R_SUCCESS);
 2278     } else {
 2279         val->attributes &= ~VALATTR_FOUNDNOQNAME;
 2280         val->attributes &= ~VALATTR_FOUNDOPTOUT;
 2281         proofs[DNS_VALIDATOR_NOQNAMEPROOF] = NULL;
 2282     }
 2283 
 2284     /*
 2285      * Do we need to check for the wildcard?
 2286      */
 2287     if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
 2288         ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val)))
 2289     {
 2290         result = checkwildcard(val, dns_rdatatype_nsec3, zonename);
 2291         if (result != ISC_R_SUCCESS) {
 2292             return (result);
 2293         }
 2294     }
 2295     return (result);
 2296 }
 2297 
 2298 /*
 2299  * Start a validator for negative response data.
 2300  *
 2301  * Returns:
 2302  * \li  DNS_R_CONTINUE  Validation skipped, continue
 2303  * \li  DNS_R_WAIT  Validation is in progress
 2304  *
 2305  * \li  Other return codes indicate failure.
 2306  */
 2307 static isc_result_t
 2308 validate_neg_rrset(dns_validator_t *val, dns_name_t *name,
 2309            dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
 2310     isc_result_t result;
 2311 
 2312     /*
 2313      * If a signed zone is missing the zone key, bad
 2314      * things could happen.  A query for data in the zone
 2315      * would lead to a query for the zone key, which
 2316      * would return a negative answer, which would contain
 2317      * an SOA and an NSEC signed by the missing key, which
 2318      * would trigger another query for the DNSKEY (since
 2319      * the first one is still in progress), and go into an
 2320      * infinite loop.  Avoid that.
 2321      */
 2322     if (val->event->type == dns_rdatatype_dnskey &&
 2323         rdataset->type == dns_rdatatype_nsec &&
 2324         dns_name_equal(name, val->event->name))
 2325     {
 2326         dns_rdata_t nsec = DNS_RDATA_INIT;
 2327 
 2328         result = dns_rdataset_first(rdataset);
 2329         if (result != ISC_R_SUCCESS) {
 2330             return (result);
 2331         }
 2332         dns_rdataset_current(rdataset, &nsec);
 2333         if (dns_nsec_typepresent(&nsec, dns_rdatatype_soa)) {
 2334             return (DNS_R_CONTINUE);
 2335         }
 2336     }
 2337 
 2338     val->currentset = rdataset;
 2339     result = create_validator(val, name, rdataset->type, rdataset,
 2340                   sigrdataset, validator_callback_nsec,
 2341                   "validate_neg_rrset");
 2342     if (result != ISC_R_SUCCESS) {
 2343         return (result);
 2344     }
 2345 
 2346     val->authcount++;
 2347     return (DNS_R_WAIT);
 2348 }
 2349 
 2350 /*%
 2351  * Validate the authority section records.
 2352  */
 2353 static isc_result_t
 2354 validate_authority(dns_validator_t *val, bool resume) {
 2355     dns_name_t *name;
 2356     dns_message_t *message = val->event->message;
 2357     isc_result_t result;
 2358 
 2359     if (!resume) {
 2360         result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
 2361     } else {
 2362         result = ISC_R_SUCCESS;
 2363     }
 2364 
 2365     for (; result == ISC_R_SUCCESS;
 2366          result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
 2367     {
 2368         dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
 2369 
 2370         name = NULL;
 2371         dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
 2372         if (resume) {
 2373             rdataset = ISC_LIST_NEXT(val->currentset, link);
 2374             val->currentset = NULL;
 2375             resume = false;
 2376         } else {
 2377             rdataset = ISC_LIST_HEAD(name->list);
 2378         }
 2379 
 2380         for (; rdataset != NULL;
 2381              rdataset = ISC_LIST_NEXT(rdataset, link)) {
 2382             if (rdataset->type == dns_rdatatype_rrsig) {
 2383                 continue;
 2384             }
 2385 
 2386             for (sigrdataset = ISC_LIST_HEAD(name->list);
 2387                  sigrdataset != NULL;
 2388                  sigrdataset = ISC_LIST_NEXT(sigrdataset, link))
 2389             {
 2390                 if (sigrdataset->type == dns_rdatatype_rrsig &&
 2391                     sigrdataset->covers == rdataset->type)
 2392                 {
 2393                     break;
 2394                 }
 2395             }
 2396 
 2397             result = validate_neg_rrset(val, name, rdataset,
 2398                             sigrdataset);
 2399             if (result != DNS_R_CONTINUE) {
 2400                 return (result);
 2401             }
 2402         }
 2403     }
 2404     if (result == ISC_R_NOMORE) {
 2405         result = ISC_R_SUCCESS;
 2406     }
 2407     return (result);
 2408 }
 2409 
 2410 /*%
 2411  * Validate negative cache elements.
 2412  */
 2413 static isc_result_t
 2414 validate_ncache(dns_validator_t *val, bool resume) {
 2415     dns_name_t *name;
 2416     isc_result_t result;
 2417 
 2418     if (!resume) {
 2419         result = dns_rdataset_first(val->event->rdataset);
 2420     } else {
 2421         result = dns_rdataset_next(val->event->rdataset);
 2422     }
 2423 
 2424     for (; result == ISC_R_SUCCESS;
 2425          result = dns_rdataset_next(val->event->rdataset))
 2426     {
 2427         dns_rdataset_t *rdataset, *sigrdataset = NULL;
 2428 
 2429         disassociate_rdatasets(val);
 2430 
 2431         name = dns_fixedname_initname(&val->fname);
 2432         rdataset = &val->frdataset;
 2433         dns_ncache_current(val->event->rdataset, name, rdataset);
 2434 
 2435         if (val->frdataset.type == dns_rdatatype_rrsig) {
 2436             continue;
 2437         }
 2438 
 2439         result = dns_ncache_getsigrdataset(val->event->rdataset, name,
 2440                            rdataset->type,
 2441                            &val->fsigrdataset);
 2442         if (result == ISC_R_SUCCESS) {
 2443             sigrdataset = &val->fsigrdataset;
 2444         }
 2445 
 2446         result = validate_neg_rrset(val, name, rdataset, sigrdataset);
 2447         if (result == DNS_R_CONTINUE) {
 2448             continue;
 2449         }
 2450 
 2451         return (result);
 2452     }
 2453     if (result == ISC_R_NOMORE) {
 2454         result = ISC_R_SUCCESS;
 2455     }
 2456 
 2457     return (result);
 2458 }
 2459 
 2460 /*%
 2461  * Prove a negative answer is good or that there is a NOQNAME when the
 2462  * answer is from a wildcard.
 2463  *
 2464  * Loop through the authority section looking for NODATA, NOWILDCARD
 2465  * and NOQNAME proofs in the NSEC records by calling
 2466  * validator_callback_nsec().
 2467  *
 2468  * If the required proofs are found we are done.
 2469  *
 2470  * If the proofs are not found attempt to prove this is an unsecure
 2471  * response.
 2472  */
 2473 static isc_result_t
 2474 validate_nx(dns_validator_t *val, bool resume) {
 2475     isc_result_t result;
 2476 
 2477     if (resume) {
 2478         validator_log(val, ISC_LOG_DEBUG(3), "resuming validate_nx");
 2479     }
 2480 
 2481     if (val->event->message == NULL) {
 2482         result = validate_ncache(val, resume);
 2483     } else {
 2484         result = validate_authority(val, resume);
 2485     }
 2486 
 2487     if (result != ISC_R_SUCCESS) {
 2488         return (result);
 2489     }
 2490 
 2491     /*
 2492      * Do we only need to check for NOQNAME?  To get here we must have
 2493      * had a secure wildcard answer.
 2494      */
 2495     if (!NEEDNODATA(val) && !NEEDNOWILDCARD(val) && NEEDNOQNAME(val)) {
 2496         if (!FOUNDNOQNAME(val)) {
 2497             findnsec3proofs(val);
 2498         }
 2499 
 2500         if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) && !FOUNDOPTOUT(val))
 2501         {
 2502             validator_log(val, ISC_LOG_DEBUG(3),
 2503                       "marking as secure, noqname proof found");
 2504             marksecure(val->event);
 2505             return (ISC_R_SUCCESS);
 2506         } else if (FOUNDOPTOUT(val) &&
 2507                dns_name_countlabels(
 2508                    dns_fixedname_name(&val->wild)) != 0)
 2509         {
 2510             validator_log(val, ISC_LOG_DEBUG(3),
 2511                       "optout proof found");
 2512             val->event->optout = true;
 2513             markanswer(val, "validate_nx (1)", NULL);
 2514             return (ISC_R_SUCCESS);
 2515         } else if ((val->attributes & VALATTR_FOUNDUNKNOWN) != 0) {
 2516             validator_log(val, ISC_LOG_DEBUG(3),
 2517                       "unknown NSEC3 hash algorithm found");
 2518             markanswer(val, "validate_nx (2)", NULL);
 2519             return (ISC_R_SUCCESS);
 2520         }
 2521 
 2522         validator_log(val, ISC_LOG_DEBUG(3), "noqname proof not found");
 2523         return (DNS_R_NOVALIDNSEC);
 2524     }
 2525 
 2526     if (!FOUNDNOQNAME(val) && !FOUNDNODATA(val)) {
 2527         findnsec3proofs(val);
 2528     }
 2529 
 2530     /*
 2531      * Do we need to check for the wildcard?
 2532      */
 2533     if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
 2534         ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val)))
 2535     {
 2536         result = checkwildcard(val, dns_rdatatype_nsec, NULL);
 2537         if (result != ISC_R_SUCCESS) {
 2538             return (result);
 2539         }
 2540     }
 2541 
 2542     if ((NEEDNODATA(val) && (FOUNDNODATA(val) || FOUNDOPTOUT(val))) ||
 2543         (NEEDNOQNAME(val) && FOUNDNOQNAME(val) && NEEDNOWILDCARD(val) &&
 2544          FOUNDNOWILDCARD(val) && FOUNDCLOSEST(val)))
 2545     {
 2546         if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0) {
 2547             val->event->optout = true;
 2548         }
 2549         validator_log(val, ISC_LOG_DEBUG(3),
 2550                   "nonexistence proof(s) found");
 2551         if (val->event->message == NULL) {
 2552             marksecure(val->event);
 2553         } else {
 2554             val->event->secure = true;
 2555         }
 2556         return (ISC_R_SUCCESS);
 2557     }
 2558 
 2559     if (val->authfail != 0 && val->authcount == val->authfail) {
 2560         return (DNS_R_BROKENCHAIN);
 2561     }
 2562 
 2563     validator_log(val, ISC_LOG_DEBUG(3), "nonexistence proof(s) not found");
 2564     return (proveunsecure(val, false, false));
 2565 }
 2566 
 2567 /*%
 2568  * Check that DS rdataset has at least one record with
 2569  * a supported algorithm and digest.
 2570  */
 2571 static bool
 2572 check_ds_algs(dns_validator_t *val, dns_name_t *name,
 2573           dns_rdataset_t *rdataset) {
 2574     dns_rdata_t dsrdata = DNS_RDATA_INIT;
 2575     dns_rdata_ds_t ds;
 2576     isc_result_t result;
 2577 
 2578     for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
 2579          result = dns_rdataset_next(rdataset))
 2580     {
 2581         dns_rdataset_current(rdataset, &dsrdata);
 2582         result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
 2583         RUNTIME_CHECK(result == ISC_R_SUCCESS);
 2584 
 2585         if (dns_resolver_ds_digest_supported(val->view->resolver, name,
 2586                              ds.digest_type) &&
 2587             dns_resolver_algorithm_supported(val->view->resolver, name,
 2588                              ds.algorithm))
 2589         {
 2590             dns_rdata_reset(&dsrdata);
 2591             return (true);
 2592         }
 2593         dns_rdata_reset(&dsrdata);
 2594     }
 2595     return (false);
 2596 }
 2597 
 2598 /*%
 2599  * seek_ds is called to look up DS rrsets at the label of val->event->name
 2600  * indicated by val->labels. This is done while building an insecurity
 2601  * proof, and so it will attempt validation of NXDOMAIN, NXRRSET or CNAME
 2602  * responses.
 2603  *
 2604  * Returns:
 2605  * \li  ISC_R_COMPLETE      a result has been determined and copied
 2606  *              into `*resp`; ISC_R_SUCCESS indicates that
 2607  *              the name has been proven insecure and any
 2608  *              other result indicates failure.
 2609  * \li  DNS_R_CONTINUE      result is indeterminate; caller should
 2610  *              continue walking down labels.
 2611  */
 2612 static isc_result_t
 2613 seek_ds(dns_validator_t *val, isc_result_t *resp) {
 2614     isc_result_t result;
 2615     char namebuf[DNS_NAME_FORMATSIZE];
 2616     dns_fixedname_t fixedfound;
 2617     dns_name_t *found = dns_fixedname_initname(&fixedfound);
 2618     dns_name_t *tname = dns_fixedname_initname(&val->fname);
 2619 
 2620     if (val->labels == dns_name_countlabels(val->event->name)) {
 2621         dns_name_copynf(val->event->name, tname);
 2622     } else {
 2623         dns_name_split(val->event->name, val->labels, NULL, tname);
 2624     }
 2625 
 2626     dns_name_format(tname, namebuf, sizeof(namebuf));
 2627     validator_log(val, ISC_LOG_DEBUG(3), "checking existence of DS at '%s'",
 2628               namebuf);
 2629 
 2630     result = view_find(val, tname, dns_rdatatype_ds);
 2631     switch (result) {
 2632     case ISC_R_SUCCESS:
 2633         /*
 2634          * There is a DS here.  If it's already been
 2635          * validated, continue walking down labels.
 2636          */
 2637         if (val->frdataset.trust >= dns_trust_secure) {
 2638             if (!check_ds_algs(val, tname, &val->frdataset)) {
 2639                 validator_log(val, ISC_LOG_DEBUG(3),
 2640                           "no supported algorithm/"
 2641                           "digest (%s/DS)",
 2642                           namebuf);
 2643                 *resp = markanswer(val, "proveunsecure (5)",
 2644                            "no supported "
 2645                            "algorithm/digest (DS)");
 2646                 return (ISC_R_COMPLETE);
 2647             }
 2648 
 2649             break;
 2650         }
 2651 
 2652         /*
 2653          * Otherwise, try to validate it now.
 2654          */
 2655         if (dns_rdataset_isassociated(&val->fsigrdataset)) {
 2656             result = create_validator(
 2657                 val, tname, dns_rdatatype_ds, &val->frdataset,
 2658                 &val->fsigrdataset, validator_callback_ds,
 2659                 "proveunsecure");
 2660             *resp = DNS_R_WAIT;
 2661             if (result != ISC_R_SUCCESS) {
 2662                 *resp = result;
 2663             }
 2664         } else {
 2665             /*
 2666              * There should never be an unsigned DS.
 2667              */
 2668             validator_log(val, ISC_LOG_DEBUG(3),
 2669                       "unsigned DS record");
 2670             *resp = DNS_R_NOVALIDSIG;
 2671         }
 2672 
 2673         return (ISC_R_COMPLETE);
 2674 
 2675     case ISC_R_NOTFOUND:
 2676         /*
 2677          * We don't know anything about the DS.  Find it.
 2678          */
 2679         *resp = DNS_R_WAIT;
 2680         result = create_fetch(val, tname, dns_rdatatype_ds,
 2681                       fetch_callback_ds, "proveunsecure");
 2682         if (result != ISC_R_SUCCESS) {
 2683             *resp = result;
 2684         }
 2685         return (ISC_R_COMPLETE);
 2686 
 2687     case DNS_R_NXRRSET:
 2688     case DNS_R_NCACHENXRRSET:
 2689         /*
 2690          * There is no DS.  If this is a delegation,
 2691          * we may be done.
 2692          *
 2693          * If we have "trust == answer" then this namespace
 2694          * has switched from insecure to should be secure.
 2695          */
 2696         if (DNS_TRUST_PENDING(val->frdataset.trust) ||
 2697             DNS_TRUST_ANSWER(val->frdataset.trust))
 2698         {
 2699             result = create_validator(
 2700                 val, tname, dns_rdatatype_ds, &val->frdataset,
 2701                 &val->fsigrdataset, validator_callback_ds,
 2702                 "proveunsecure");
 2703             *resp = DNS_R_WAIT;
 2704             if (result != ISC_R_SUCCESS) {
 2705                 *resp = result;
 2706             }
 2707             return (ISC_R_COMPLETE);
 2708         }
 2709 
 2710         /*
 2711          * Zones using NSEC3 don't return a NSEC RRset so
 2712          * we need to use dns_view_findzonecut2 to find
 2713          * the zone cut.
 2714          */
 2715         if (result == DNS_R_NXRRSET &&
 2716             !dns_rdataset_isassociated(&val->frdataset) &&
 2717             dns_view_findzonecut(val->view, tname, found, NULL, 0, 0,
 2718                      false, false, NULL,
 2719                      NULL) == ISC_R_SUCCESS &&
 2720             dns_name_equal(tname, found))
 2721         {
 2722             *resp = markanswer(val, "proveunsecure (3)",
 2723                        "no DS at zone cut");
 2724             return (ISC_R_COMPLETE);
 2725         }
 2726 
 2727         if (val->frdataset.trust < dns_trust_secure) {
 2728             /*
 2729              * This shouldn't happen, since the negative
 2730              * response should have been validated.  Since
 2731              * there's no way of validating existing
 2732              * negative response blobs, give up.
 2733              */
 2734             validator_log(val, ISC_LOG_WARNING,
 2735                       "can't validate existing "
 2736                       "negative responses (no DS)");
 2737             *resp = DNS_R_MUSTBESECURE;
 2738             return (ISC_R_COMPLETE);
 2739         }
 2740 
 2741         if (isdelegation(tname, &val->frdataset, result)) {
 2742             *resp = markanswer(val, "proveunsecure (4)",
 2743                        "this is a delegation");
 2744             return (ISC_R_COMPLETE);
 2745         }
 2746 
 2747         break;
 2748 
 2749     case DNS_R_NXDOMAIN:
 2750     case DNS_R_NCACHENXDOMAIN:
 2751         /*
 2752          * This is not a zone cut. Assuming things are
 2753          * as expected, continue.
 2754          */
 2755         if (!dns_rdataset_isassociated(&val->frdataset)) {
 2756             /*
 2757              * There should be an NSEC here, since we
 2758              * are still in a secure zone.
 2759              */
 2760             *resp = DNS_R_NOVALIDNSEC;
 2761             return (ISC_R_COMPLETE);
 2762         } else if (DNS_TRUST_PENDING(val->frdataset.trust) ||
 2763                DNS_TRUST_ANSWER(val->frdataset.trust))
 2764         {
 2765             /*
 2766              * If we have "trust == answer" then this
 2767              * namespace has switched from insecure to
 2768              * should be secure.
 2769              */
 2770             *resp = DNS_R_WAIT;
 2771             result = create_validator(
 2772                 val, tname, dns_rdatatype_ds, &val->frdataset,
 2773                 &val->fsigrdataset, validator_callback_ds,
 2774                 "proveunsecure");
 2775             if (result != ISC_R_SUCCESS) {
 2776                 *resp = result;
 2777             }
 2778             return (ISC_R_COMPLETE);
 2779         } else if (val->frdataset.trust < dns_trust_secure) {
 2780             /*
 2781              * This shouldn't happen, since the negative
 2782              * response should have been validated.  Since
 2783              * there's no way of validating existing
 2784              * negative response blobs, give up.
 2785              */
 2786             validator_log(val, ISC_LOG_WARNING,
 2787                       "can't validate existing "
 2788                       "negative responses "
 2789                       "(not a zone cut)");
 2790             *resp = DNS_R_NOVALIDSIG;
 2791             return (ISC_R_COMPLETE);
 2792         }
 2793 
 2794         break;
 2795 
 2796     case DNS_R_CNAME:
 2797         if (DNS_TRUST_PENDING(val->frdataset.trust) ||
 2798             DNS_TRUST_ANSWER(val->frdataset.trust))
 2799         {
 2800             result = create_validator(
 2801                 val, tname, dns_rdatatype_cname,
 2802                 &val->frdataset, &val->fsigrdataset,
 2803                 validator_callback_cname,
 2804                 "proveunsecure "
 2805                 "(cname)");
 2806             *resp = DNS_R_WAIT;
 2807             if (result != ISC_R_SUCCESS) {
 2808                 *resp = result;
 2809             }
 2810             return (ISC_R_COMPLETE);
 2811         }
 2812 
 2813         break;
 2814 
 2815     default:
 2816         *resp = result;
 2817         return (ISC_R_COMPLETE);
 2818     }
 2819 
 2820     /*
 2821      * No definite answer yet; continue walking down labels.
 2822      */
 2823     return (DNS_R_CONTINUE);
 2824 }
 2825 
 2826 /*%
 2827  * proveunsecure walks down, label by label, from the closest enclosing
 2828  * trust anchor to the name that is being validated, looking for an
 2829  * endpoint in the chain of trust.  That occurs when we can prove that
 2830  * a DS record does not exist at a delegation point, or that a DS exists
 2831  * at a delegation point but we don't support its algorithm/digest.  If
 2832  * no such endpoint is found, then the response should have been secure.
 2833  *
 2834  * Returns:
 2835  * \li  ISC_R_SUCCESS       val->event->name is in an unsecure zone
 2836  * \li  DNS_R_WAIT      validation is in progress.
 2837  * \li  DNS_R_MUSTBESECURE  val->event->name is supposed to be secure
 2838  *              (policy) but we proved that it is unsecure.
 2839  * \li  DNS_R_NOVALIDSIG
 2840  * \li  DNS_R_NOVALIDNSEC
 2841  * \li  DNS_R_NOTINSECURE
 2842  * \li  DNS_R_BROKENCHAIN
 2843  */
 2844 static isc_result_t
 2845 proveunsecure(dns_validator_t *val, bool have_ds, bool resume) {
 2846     isc_result_t result;
 2847     char namebuf[DNS_NAME_FORMATSIZE];
 2848     dns_fixedname_t fixedsecroot;
 2849     dns_name_t *secroot = dns_fixedname_initname(&fixedsecroot);
 2850     unsigned int labels;
 2851 
 2852     /*
 2853      * We're attempting to prove insecurity.
 2854      */
 2855     val->attributes |= VALATTR_INSECURITY;
 2856 
 2857     dns_name_copynf(val->event->name, secroot);
 2858 
 2859     /*
 2860      * If this is a response to a DS query, we need to look in
 2861      * the parent zone for the trust anchor.
 2862      */
 2863     labels = dns_name_countlabels(secroot);
 2864     if (val->event->type == dns_rdatatype_ds && labels > 1U) {
 2865         dns_name_getlabelsequence(secroot, 1, labels - 1, secroot);
 2866     }
 2867 
 2868     result = dns_keytable_finddeepestmatch(val->keytable, secroot, secroot);
 2869     if (result == ISC_R_NOTFOUND) {
 2870         validator_log(val, ISC_LOG_DEBUG(3), "not beneath secure root");
 2871         return (markanswer(val, "proveunsecure (1)",
 2872                    "not beneath secure root"));
 2873     } else if (result != ISC_R_SUCCESS) {
 2874         return (result);
 2875     }
 2876 
 2877     if (!resume) {
 2878         /*
 2879          * We are looking for interruptions in the chain of trust.
 2880          * That can only happen *below* the trust anchor, so we
 2881          * start looking at the next label down.
 2882          */
 2883         val->labels = dns_name_countlabels(secroot) + 1;
 2884     } else {
 2885         validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
 2886 
 2887         /*
 2888          * If we have a DS rdataset and it is secure, check whether
 2889          * it has a supported algorithm combination.  If not, this is
 2890          * an insecure delegation as far as this resolver is concerned.
 2891          */
 2892         if (have_ds && val->frdataset.trust >= dns_trust_secure &&
 2893             !check_ds_algs(val, dns_fixedname_name(&val->fname),
 2894                    &val->frdataset))
 2895         {
 2896             dns_name_format(dns_fixedname_name(&val->fname),
 2897                     namebuf, sizeof(namebuf));
 2898             validator_log(val, ISC_LOG_DEBUG(3),
 2899                       "no supported algorithm/digest (%s/DS)",
 2900                       namebuf);
 2901             result = markanswer(val, "proveunsecure (2)", namebuf);
 2902             goto out;
 2903         }
 2904         val->labels++;
 2905     }
 2906 
 2907     /*
 2908      * Walk down through each of the remaining labels in the name,
 2909      * looking for DS records.
 2910      */
 2911     while (val->labels <= dns_name_countlabels(val->event->name)) {
 2912         isc_result_t tresult;
 2913 
 2914         result = seek_ds(val, &tresult);
 2915         if (result == ISC_R_COMPLETE) {
 2916             result = tresult;
 2917             goto out;
 2918         }
 2919 
 2920         INSIST(result == DNS_R_CONTINUE);
 2921         val->labels++;
 2922     }
 2923 
 2924     /* Couldn't complete insecurity proof. */
 2925     validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed: %s",
 2926               isc_result_totext(result));
 2927     return (DNS_R_NOTINSECURE);
 2928 
 2929 out:
 2930     if (result != DNS_R_WAIT) {
 2931         disassociate_rdatasets(val);
 2932     }
 2933     return (result);
 2934 }
 2935 
 2936 /*%
 2937  * Start the validation process.
 2938  *
 2939  * Attempt to validate the answer based on the category it appears to
 2940  * fall in.
 2941  * \li  1. secure positive answer.
 2942  * \li  2. unsecure positive answer.
 2943  * \li  3. a negative answer (secure or unsecure).
 2944  *
 2945  * Note an answer that appears to be a secure positive answer may actually
 2946  * be an unsecure positive answer.
 2947  */
 2948 static void
 2949 validator_start(isc_task_t *task, isc_event_t *event) {
 2950     dns_validator_t *val;
 2951     dns_validatorevent_t *vevent;
 2952     bool want_destroy = false;
 2953     isc_result_t result = ISC_R_FAILURE;
 2954 
 2955     UNUSED(task);
 2956     REQUIRE(event->ev_type == DNS_EVENT_VALIDATORSTART);
 2957     vevent = (dns_validatorevent_t *)event;
 2958     val = vevent->validator;
 2959 
 2960     /* If the validator has been canceled, val->event == NULL */
 2961     if (val->event == NULL) {
 2962         return;
 2963     }
 2964 
 2965     validator_log(val, ISC_LOG_DEBUG(3), "starting");
 2966 
 2967     LOCK(&val->lock);
 2968 
 2969     if (val->event->rdataset != NULL && val->event->sigrdataset != NULL) {
 2970         isc_result_t saved_result;
 2971 
 2972         /*
 2973          * This looks like a simple validation.  We say "looks like"
 2974          * because it might end up requiring an insecurity proof.
 2975          */
 2976         validator_log(val, ISC_LOG_DEBUG(3),
 2977                   "attempting positive response validation");
 2978 
 2979         INSIST(dns_rdataset_isassociated(val->event->rdataset));
 2980         INSIST(dns_rdataset_isassociated(val->event->sigrdataset));
 2981         if (selfsigned_dnskey(val)) {
 2982             result = validate_dnskey(val);
 2983         } else {
 2984             result = validate_answer(val, false);
 2985         }
 2986         if (result == DNS_R_NOVALIDSIG &&
 2987             (val->attributes & VALATTR_TRIEDVERIFY) == 0) {
 2988             saved_result = result;
 2989             validator_log(val, ISC_LOG_DEBUG(3),
 2990                       "falling back to insecurity proof");
 2991             result = proveunsecure(val, false, false);
 2992             if (result == DNS_R_NOTINSECURE) {
 2993                 result = saved_result;
 2994             }
 2995         }
 2996     } else if (val->event->rdataset != NULL &&
 2997            val->event->rdataset->type != 0) {
 2998         /*
 2999          * This is either an unsecure subdomain or a response
 3000          * from a broken server.
 3001          */
 3002         INSIST(dns_rdataset_isassociated(val->event->rdataset));
 3003         validator_log(val, ISC_LOG_DEBUG(3),
 3004                   "attempting insecurity proof");
 3005 
 3006         result = proveunsecure(val, false, false);
 3007         if (result == DNS_R_NOTINSECURE) {
 3008             validator_log(val, ISC_LOG_INFO,
 3009                       "got insecure response; "
 3010                       "parent indicates it should be secure");
 3011         }
 3012     } else if ((val->event->rdataset == NULL &&
 3013             val->event->sigrdataset == NULL)) {
 3014         /*
 3015          * This is a validation of a negative response.
 3016          */
 3017         validator_log(val, ISC_LOG_DEBUG(3),
 3018                   "attempting negative response validation "
 3019                   "from message");
 3020 
 3021         if (val->event->message->rcode == dns_rcode_nxdomain) {
 3022             val->attributes |= VALATTR_NEEDNOQNAME;
 3023             val->attributes |= VALATTR_NEEDNOWILDCARD;
 3024         } else {
 3025             val->attributes |= VALATTR_NEEDNODATA;
 3026         }
 3027 
 3028         result = validate_nx(val, false);
 3029     } else if ((val->event->rdataset != NULL &&
 3030             NEGATIVE(val->event->rdataset))) {
 3031         /*
 3032          * This is a delayed validation of a negative cache entry.
 3033          */
 3034         validator_log(val, ISC_LOG_DEBUG(3),
 3035                   "attempting negative response validation "
 3036                   "from cache");
 3037 
 3038         if (NXDOMAIN(val->event->rdataset)) {
 3039             val->attributes |= VALATTR_NEEDNOQNAME;
 3040             val->attributes |= VALATTR_NEEDNOWILDCARD;
 3041         } else {
 3042             val->attributes |= VALATTR_NEEDNODATA;
 3043         }
 3044 
 3045         result = validate_nx(val, false);
 3046     } else {
 3047         INSIST(0);
 3048         ISC_UNREACHABLE();
 3049     }
 3050 
 3051     if (result != DNS_R_WAIT) {
 3052         want_destroy = exit_check(val);
 3053         validator_done(val, result);
 3054     }
 3055 
 3056     UNLOCK(&val->lock);
 3057     if (want_destroy) {
 3058         destroy(val);
 3059     }
 3060 }
 3061 
 3062 isc_result_t
 3063 dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
 3064              dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
 3065              dns_message_t *message, unsigned int options,
 3066              isc_task_t *task, isc_taskaction_t action, void *arg,
 3067              dns_validator_t **validatorp) {
 3068     isc_result_t result = ISC_R_FAILURE;
 3069     dns_validator_t *val;
 3070     isc_task_t *tclone = NULL;
 3071     dns_validatorevent_t *event;
 3072 
 3073     REQUIRE(name != NULL);
 3074     REQUIRE(rdataset != NULL ||
 3075         (rdataset == NULL && sigrdataset == NULL && message != NULL));
 3076     REQUIRE(validatorp != NULL && *validatorp == NULL);
 3077 
 3078     event = (dns_validatorevent_t *)isc_event_allocate(
 3079         view->mctx, task, DNS_EVENT_VALIDATORSTART, validator_start,
 3080         NULL, sizeof(dns_validatorevent_t));
 3081 
 3082     isc_task_attach(task, &tclone);
 3083     event->result = ISC_R_FAILURE;
 3084     event->name = name;
 3085     event->type = type;
 3086     event->rdataset = rdataset;
 3087     event->sigrdataset = sigrdataset;
 3088     event->message = message;
 3089     memset(event->proofs, 0, sizeof(event->proofs));
 3090     event->optout = false;
 3091     event->secure = false;
 3092 
 3093     val = isc_mem_get(view->mctx, sizeof(*val));
 3094     *val = (dns_validator_t){ .event = event,
 3095                   .options = options,
 3096                   .task = task,
 3097                   .action = action,
 3098                   .arg = arg };
 3099 
 3100     dns_view_weakattach(view, &val->view);
 3101     isc_mutex_init(&val->lock);
 3102 
 3103     result = dns_view_getsecroots(val->view, &val->keytable);
 3104     if (result != ISC_R_SUCCESS) {
 3105         goto cleanup;
 3106     }
 3107 
 3108     val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
 3109     dns_rdataset_init(&val->fdsset);
 3110     dns_rdataset_init(&val->frdataset);
 3111     dns_rdataset_init(&val->fsigrdataset);
 3112     dns_fixedname_init(&val->wild);
 3113     dns_fixedname_init(&val->closest);
 3114     isc_stdtime_get(&val->start);
 3115     ISC_LINK_INIT(val, link);
 3116     val->magic = VALIDATOR_MAGIC;
 3117 
 3118     event->validator = val;
 3119 
 3120     if ((options & DNS_VALIDATOR_DEFER) == 0) {
 3121         isc_task_send(task, ISC_EVENT_PTR(&event));
 3122     }
 3123 
 3124     *validatorp = val;
 3125 
 3126     return (ISC_R_SUCCESS);
 3127 
 3128 cleanup:
 3129     isc_mutex_destroy(&val->lock);
 3130 
 3131     isc_task_detach(&tclone);
 3132     isc_event_free(ISC_EVENT_PTR(&event));
 3133 
 3134     dns_view_weakdetach(&val->view);
 3135     isc_mem_put(view->mctx, val, sizeof(*val));
 3136 
 3137     return (result);
 3138 }
 3139 
 3140 void
 3141 dns_validator_send(dns_validator_t *validator) {
 3142     isc_event_t *event;
 3143     REQUIRE(VALID_VALIDATOR(validator));
 3144 
 3145     LOCK(&validator->lock);
 3146 
 3147     INSIST((validator->options & DNS_VALIDATOR_DEFER) != 0);
 3148     event = (isc_event_t *)validator->event;
 3149     validator->options &= ~DNS_VALIDATOR_DEFER;
 3150     UNLOCK(&validator->lock);
 3151 
 3152     isc_task_send(validator->task, ISC_EVENT_PTR(&event));
 3153 }
 3154 
 3155 void
 3156 dns_validator_cancel(dns_validator_t *validator) {
 3157     dns_fetch_t *fetch = NULL;
 3158 
 3159     REQUIRE(VALID_VALIDATOR(validator));
 3160 
 3161     LOCK(&validator->lock);
 3162 
 3163     validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
 3164 
 3165     if ((validator->attributes & VALATTR_CANCELED) == 0) {
 3166         validator->attributes |= VALATTR_CANCELED;
 3167         if (validator->event != NULL) {
 3168             fetch = validator->fetch;
 3169             validator->fetch = NULL;
 3170 
 3171             if (validator->subvalidator != NULL) {
 3172                 dns_validator_cancel(validator->subvalidator);
 3173             }
 3174             if ((validator->options & DNS_VALIDATOR_DEFER) != 0) {
 3175                 validator->options &= ~DNS_VALIDATOR_DEFER;
 3176                 validator_done(validator, ISC_R_CANCELED);
 3177             }
 3178         }
 3179     }
 3180     UNLOCK(&validator->lock);
 3181 
 3182     /* Need to cancel and destroy the fetch outside validator lock */
 3183     if (fetch != NULL) {
 3184         dns_resolver_cancelfetch(fetch);
 3185         dns_resolver_destroyfetch(&fetch);
 3186     }
 3187 }
 3188 
 3189 static void
 3190 destroy(dns_validator_t *val) {
 3191     isc_mem_t *mctx;
 3192 
 3193     REQUIRE(SHUTDOWN(val));
 3194     REQUIRE(val->event == NULL);
 3195     REQUIRE(val->fetch == NULL);
 3196 
 3197     val->magic = 0;
 3198     if (val->key != NULL) {
 3199         dst_key_free(&val->key);
 3200     }
 3201     if (val->keytable != NULL) {
 3202         dns_keytable_detach(&val->keytable);
 3203     }
 3204     if (val->subvalidator != NULL) {
 3205         dns_validator_destroy(&val->subvalidator);
 3206     }
 3207     disassociate_rdatasets(val);
 3208     mctx = val->view->mctx;
 3209     if (val->siginfo != NULL) {
 3210         isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo));
 3211     }
 3212     isc_mutex_destroy(&val->lock);
 3213     dns_view_weakdetach(&val->view);
 3214     isc_mem_put(mctx, val, sizeof(*val));
 3215 }
 3216 
 3217 void
 3218 dns_validator_destroy(dns_validator_t **validatorp) {
 3219     dns_validator_t *val;
 3220     bool want_destroy = false;
 3221 
 3222     REQUIRE(validatorp != NULL);
 3223     val = *validatorp;
 3224     *validatorp = NULL;
 3225     REQUIRE(VALID_VALIDATOR(val));
 3226 
 3227     LOCK(&val->lock);
 3228 
 3229     val->attributes |= VALATTR_SHUTDOWN;
 3230     validator_log(val, ISC_LOG_DEBUG(4), "dns_validator_destroy");
 3231 
 3232     want_destroy = exit_check(val);
 3233     UNLOCK(&val->lock);
 3234     if (want_destroy) {
 3235         destroy(val);
 3236     }
 3237 }
 3238 
 3239 static void
 3240 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
 3241            isc_logmodule_t *module, int level, const char *fmt,
 3242            va_list ap) {
 3243     char msgbuf[2048];
 3244     static const char spaces[] = "        *";
 3245     int depth = val->depth * 2;
 3246     const char *viewname, *sep1, *sep2;
 3247 
 3248     vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
 3249 
 3250     if ((unsigned int)depth >= sizeof spaces) {
 3251         depth = sizeof spaces - 1;
 3252     }
 3253 
 3254     /*
 3255      * Log the view name unless it's:
 3256      * * "_default/IN" (which means there's only one view
 3257      *   configured in the server), or
 3258      * * "_dnsclient/IN" (which means this is being called
 3259      *   from an application using dns/client.c).
 3260      */
 3261     if (val->view->rdclass == dns_rdataclass_in &&
 3262         (strcmp(val->view->name, "_default") == 0 ||
 3263          strcmp(val->view->name, DNS_CLIENTVIEW_NAME) == 0))
 3264     {
 3265         sep1 = viewname = sep2 = "";
 3266     } else {
 3267         sep1 = "view ";
 3268         viewname = val->view->name;
 3269         sep2 = ": ";
 3270     }
 3271 
 3272     if (val->event != NULL && val->event->name != NULL) {
 3273         char namebuf[DNS_NAME_FORMATSIZE];
 3274         char typebuf[DNS_RDATATYPE_FORMATSIZE];
 3275 
 3276         dns_name_format(val->event->name, namebuf, sizeof(namebuf));
 3277         dns_rdatatype_format(val->event->type, typebuf,
 3278                      sizeof(typebuf));
 3279         isc_log_write(dns_lctx, category, module, level,
 3280                   "%s%s%s%.*svalidating %s/%s: %s", sep1, viewname,
 3281                   sep2, depth, spaces, namebuf, typebuf, msgbuf);
 3282     } else {
 3283         isc_log_write(dns_lctx, category, module, level,
 3284                   "%s%s%s%.*svalidator @%p: %s", sep1, viewname,
 3285                   sep2, depth, spaces, val, msgbuf);
 3286     }
 3287 }
 3288 
 3289 static void
 3290 validator_log(void *val, int level, const char *fmt, ...) {
 3291     va_list ap;
 3292 
 3293     if (!isc_log_wouldlog(dns_lctx, level)) {
 3294         return;
 3295     }
 3296 
 3297     va_start(ap, fmt);
 3298 
 3299     validator_logv(val, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_VALIDATOR,
 3300                level, fmt, ap);
 3301     va_end(ap);
 3302 }
 3303 
 3304 static void
 3305 validator_logcreate(dns_validator_t *val, dns_name_t *name,
 3306             dns_rdatatype_t type, const char *caller,
 3307             const char *operation) {
 3308     char namestr[DNS_NAME_FORMATSIZE];
 3309     char typestr[DNS_RDATATYPE_FORMATSIZE];
 3310 
 3311     dns_name_format(name, namestr, sizeof(namestr));
 3312     dns_rdatatype_format(type, typestr, sizeof(typestr));
 3313     validator_log(val, ISC_LOG_DEBUG(9), "%s: creating %s for %s %s",
 3314               caller, operation, namestr, typestr);
 3315 }