validator.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 2000-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 #include <config.h>
00019 
00020 #include <isc/base32.h>
00021 #include <isc/mem.h>
00022 #include <isc/print.h>
00023 #include <isc/sha2.h>
00024 #include <isc/string.h>
00025 #include <isc/task.h>
00026 #include <isc/util.h>
00027 
00028 #include <dns/db.h>
00029 #include <dns/dnssec.h>
00030 #include <dns/ds.h>
00031 #include <dns/events.h>
00032 #include <dns/keytable.h>
00033 #include <dns/keyvalues.h>
00034 #include <dns/log.h>
00035 #include <dns/message.h>
00036 #include <dns/ncache.h>
00037 #include <dns/nsec.h>
00038 #include <dns/nsec3.h>
00039 #include <dns/rdata.h>
00040 #include <dns/rdataset.h>
00041 #include <dns/rdatatype.h>
00042 #include <dns/resolver.h>
00043 #include <dns/result.h>
00044 #include <dns/validator.h>
00045 #include <dns/view.h>
00046 
00047 /*! \file
00048  * \brief
00049  * Basic processing sequences.
00050  *
00051  * \li When called with rdataset and sigrdataset:
00052  * validator_start -> validate -> proveunsecure -> startfinddlvsep ->
00053  *      dlv_validator_start -> validator_start -> validate -> proveunsecure
00054  *
00055  * validator_start -> validate -> nsecvalidate  (secure wildcard answer)
00056  *
00057  * \li When called with rdataset, sigrdataset and with DNS_VALIDATOR_DLV:
00058  * validator_start -> startfinddlvsep -> dlv_validator_start ->
00059  *      validator_start -> validate -> proveunsecure
00060  *
00061  * \li When called with rdataset:
00062  * validator_start -> proveunsecure -> startfinddlvsep ->
00063  *      dlv_validator_start -> validator_start -> proveunsecure
00064  *
00065  * \li When called with rdataset and with DNS_VALIDATOR_DLV:
00066  * validator_start -> startfinddlvsep -> dlv_validator_start ->
00067  *      validator_start -> proveunsecure
00068  *
00069  * \li When called without a rdataset:
00070  * validator_start -> nsecvalidate -> proveunsecure -> startfinddlvsep ->
00071  *      dlv_validator_start -> validator_start -> nsecvalidate -> proveunsecure
00072  *
00073  * Note: there isn't a case for DNS_VALIDATOR_DLV here as we want nsecvalidate()
00074  * to always validate the authority section even when it does not contain
00075  * signatures.
00076  *
00077  * validator_start: determines what type of validation to do.
00078  * validate: attempts to perform a positive validation.
00079  * proveunsecure: attempts to prove the answer comes from a unsecure zone.
00080  * nsecvalidate: attempts to prove a negative response.
00081  * startfinddlvsep: starts the DLV record lookup.
00082  * dlv_validator_start: resets state and restarts the lookup using the
00083  *      DLV RRset found by startfinddlvsep.
00084  */
00085 
00086 #define VALIDATOR_MAGIC                 ISC_MAGIC('V', 'a', 'l', '?')
00087 #define VALID_VALIDATOR(v)              ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
00088 
00089 #define VALATTR_SHUTDOWN                0x0001  /*%< Shutting down. */
00090 #define VALATTR_CANCELED                0x0002  /*%< Canceled. */
00091 #define VALATTR_TRIEDVERIFY             0x0004  /*%< We have found a key and
00092                                                  * have attempted a verify. */
00093 #define VALATTR_INSECURITY              0x0010  /*%< Attempting proveunsecure. */
00094 #define VALATTR_DLVTRIED                0x0020  /*%< Looked for a DLV record. */
00095 
00096 /*!
00097  * NSEC proofs to be looked for.
00098  */
00099 #define VALATTR_NEEDNOQNAME             0x00000100
00100 #define VALATTR_NEEDNOWILDCARD          0x00000200
00101 #define VALATTR_NEEDNODATA              0x00000400
00102 
00103 /*!
00104  * NSEC proofs that have been found.
00105  */
00106 #define VALATTR_FOUNDNOQNAME            0x00001000
00107 #define VALATTR_FOUNDNOWILDCARD         0x00002000
00108 #define VALATTR_FOUNDNODATA             0x00004000
00109 #define VALATTR_FOUNDCLOSEST            0x00008000
00110 
00111 /*
00112  *
00113  */
00114 #define VALATTR_FOUNDOPTOUT             0x00010000
00115 #define VALATTR_FOUNDUNKNOWN            0x00020000
00116 
00117 #define NEEDNODATA(val) ((val->attributes & VALATTR_NEEDNODATA) != 0)
00118 #define NEEDNOQNAME(val) ((val->attributes & VALATTR_NEEDNOQNAME) != 0)
00119 #define NEEDNOWILDCARD(val) ((val->attributes & VALATTR_NEEDNOWILDCARD) != 0)
00120 #define DLVTRIED(val) ((val->attributes & VALATTR_DLVTRIED) != 0)
00121 #define FOUNDNODATA(val) ((val->attributes & VALATTR_FOUNDNODATA) != 0)
00122 #define FOUNDNOQNAME(val) ((val->attributes & VALATTR_FOUNDNOQNAME) != 0)
00123 #define FOUNDNOWILDCARD(val) ((val->attributes & VALATTR_FOUNDNOWILDCARD) != 0)
00124 #define FOUNDCLOSEST(val) ((val->attributes & VALATTR_FOUNDCLOSEST) != 0)
00125 #define FOUNDOPTOUT(val) ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
00126 
00127 #define SHUTDOWN(v)             (((v)->attributes & VALATTR_SHUTDOWN) != 0)
00128 #define CANCELED(v)             (((v)->attributes & VALATTR_CANCELED) != 0)
00129 
00130 #define NEGATIVE(r)     (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
00131 
00132 static void
00133 destroy(dns_validator_t *val);
00134 
00135 static isc_result_t
00136 get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
00137             dns_rdataset_t *rdataset);
00138 
00139 static isc_result_t
00140 validate(dns_validator_t *val, isc_boolean_t resume);
00141 
00142 static isc_result_t
00143 validatezonekey(dns_validator_t *val);
00144 
00145 static isc_result_t
00146 nsecvalidate(dns_validator_t *val, isc_boolean_t resume);
00147 
00148 static isc_result_t
00149 proveunsecure(dns_validator_t *val, isc_boolean_t have_ds,
00150               isc_boolean_t resume);
00151 
00152 static void
00153 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
00154                isc_logmodule_t *module, int level, const char *fmt, va_list ap)
00155      ISC_FORMAT_PRINTF(5, 0);
00156 
00157 static void
00158 validator_log(void *val, int level, const char *fmt, ...)
00159      ISC_FORMAT_PRINTF(3, 4);
00160 
00161 static void
00162 validator_logcreate(dns_validator_t *val,
00163                     dns_name_t *name, dns_rdatatype_t type,
00164                     const char *caller, const char *operation);
00165 
00166 static isc_result_t
00167 dlv_validatezonekey(dns_validator_t *val);
00168 
00169 static void
00170 dlv_validator_start(dns_validator_t *val);
00171 
00172 static isc_result_t
00173 finddlvsep(dns_validator_t *val, isc_boolean_t resume);
00174 
00175 static isc_result_t
00176 startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure);
00177 
00178 /*%
00179  * Mark the RRsets as a answer.
00180  */
00181 static inline void
00182 markanswer(dns_validator_t *val, const char *where) {
00183         validator_log(val, ISC_LOG_DEBUG(3), "marking as answer (%s)", where);
00184         if (val->event->rdataset != NULL)
00185                 dns_rdataset_settrust(val->event->rdataset, dns_trust_answer);
00186         if (val->event->sigrdataset != NULL)
00187                 dns_rdataset_settrust(val->event->sigrdataset,
00188                                       dns_trust_answer);
00189 }
00190 
00191 static inline void
00192 marksecure(dns_validatorevent_t *event) {
00193         dns_rdataset_settrust(event->rdataset, dns_trust_secure);
00194         if (event->sigrdataset != NULL)
00195                 dns_rdataset_settrust(event->sigrdataset, dns_trust_secure);
00196         event->secure = ISC_TRUE;
00197 }
00198 
00199 static void
00200 validator_done(dns_validator_t *val, isc_result_t result) {
00201         isc_task_t *task;
00202 
00203         if (val->event == NULL)
00204                 return;
00205 
00206         /*
00207          * Caller must be holding the lock.
00208          */
00209 
00210         val->event->result = result;
00211         task = val->event->ev_sender;
00212         val->event->ev_sender = val;
00213         val->event->ev_type = DNS_EVENT_VALIDATORDONE;
00214         val->event->ev_action = val->action;
00215         val->event->ev_arg = val->arg;
00216         isc_task_sendanddetach(&task, (isc_event_t **)&val->event);
00217 }
00218 
00219 static inline isc_boolean_t
00220 exit_check(dns_validator_t *val) {
00221         /*
00222          * Caller must be holding the lock.
00223          */
00224         if (!SHUTDOWN(val))
00225                 return (ISC_FALSE);
00226 
00227         INSIST(val->event == NULL);
00228 
00229         if (val->fetch != NULL || val->subvalidator != NULL)
00230                 return (ISC_FALSE);
00231 
00232         return (ISC_TRUE);
00233 }
00234 
00235 /*
00236  * Check that we have atleast one supported algorithm in the DLV RRset.
00237  */
00238 static inline isc_boolean_t
00239 dlv_algorithm_supported(dns_validator_t *val) {
00240         dns_rdata_t rdata = DNS_RDATA_INIT;
00241         dns_rdata_dlv_t dlv;
00242         isc_result_t result;
00243 
00244         for (result = dns_rdataset_first(&val->dlv);
00245              result == ISC_R_SUCCESS;
00246              result = dns_rdataset_next(&val->dlv)) {
00247                 dns_rdata_reset(&rdata);
00248                 dns_rdataset_current(&val->dlv, &rdata);
00249                 result = dns_rdata_tostruct(&rdata, &dlv, NULL);
00250                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
00251 
00252                 if (!dns_resolver_algorithm_supported(val->view->resolver,
00253                                                       val->event->name,
00254                                                       dlv.algorithm))
00255                         continue;
00256 
00257                 if (!dns_resolver_ds_digest_supported(val->view->resolver,
00258                                                       val->event->name,
00259                                                       dlv.digest_type))
00260                         continue;
00261 
00262                 return (ISC_TRUE);
00263         }
00264         return (ISC_FALSE);
00265 }
00266 
00267 /*%
00268  * Look in the NSEC record returned from a DS query to see if there is
00269  * a NS RRset at this name.  If it is found we are at a delegation point.
00270  */
00271 static isc_boolean_t
00272 isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
00273              isc_result_t dbresult)
00274 {
00275         dns_fixedname_t fixed;
00276         dns_label_t hashlabel;
00277         dns_name_t nsec3name;
00278         dns_rdata_nsec3_t nsec3;
00279         dns_rdata_t rdata = DNS_RDATA_INIT;
00280         dns_rdataset_t set;
00281         int order;
00282         int scope;
00283         isc_boolean_t found;
00284         isc_buffer_t buffer;
00285         isc_result_t result;
00286         unsigned char hash[NSEC3_MAX_HASH_LENGTH];
00287         unsigned char owner[NSEC3_MAX_HASH_LENGTH];
00288         unsigned int length;
00289 
00290         REQUIRE(dbresult == DNS_R_NXRRSET || dbresult == DNS_R_NCACHENXRRSET);
00291 
00292         dns_rdataset_init(&set);
00293         if (dbresult == DNS_R_NXRRSET)
00294                 dns_rdataset_clone(rdataset, &set);
00295         else {
00296                 result = dns_ncache_getrdataset(rdataset, name,
00297                                                 dns_rdatatype_nsec, &set);
00298                 if (result == ISC_R_NOTFOUND)
00299                         goto trynsec3;
00300                 if (result != ISC_R_SUCCESS)
00301                         return (ISC_FALSE);
00302         }
00303 
00304         INSIST(set.type == dns_rdatatype_nsec);
00305 
00306         found = ISC_FALSE;
00307         result = dns_rdataset_first(&set);
00308         if (result == ISC_R_SUCCESS) {
00309                 dns_rdataset_current(&set, &rdata);
00310                 found = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
00311                 dns_rdata_reset(&rdata);
00312         }
00313         dns_rdataset_disassociate(&set);
00314         return (found);
00315 
00316  trynsec3:
00317         /*
00318          * Iterate over the ncache entry.
00319          */
00320         found = ISC_FALSE;
00321         dns_name_init(&nsec3name, NULL);
00322         dns_fixedname_init(&fixed);
00323         dns_name_downcase(name, dns_fixedname_name(&fixed), NULL);
00324         name = dns_fixedname_name(&fixed);
00325         for (result = dns_rdataset_first(rdataset);
00326              result == ISC_R_SUCCESS;
00327              result = dns_rdataset_next(rdataset))
00328         {
00329                 dns_ncache_current(rdataset, &nsec3name, &set);
00330                 if (set.type != dns_rdatatype_nsec3) {
00331                         dns_rdataset_disassociate(&set);
00332                         continue;
00333                 }
00334                 dns_name_getlabel(&nsec3name, 0, &hashlabel);
00335                 isc_region_consume(&hashlabel, 1);
00336                 isc_buffer_init(&buffer, owner, sizeof(owner));
00337                 result = isc_base32hexnp_decoderegion(&hashlabel, &buffer);
00338                 if (result != ISC_R_SUCCESS) {
00339                         dns_rdataset_disassociate(&set);
00340                         continue;
00341                 }
00342                 for (result = dns_rdataset_first(&set);
00343                      result == ISC_R_SUCCESS;
00344                      result = dns_rdataset_next(&set))
00345                 {
00346                         dns_rdata_reset(&rdata);
00347                         dns_rdataset_current(&set, &rdata);
00348                         (void)dns_rdata_tostruct(&rdata, &nsec3, NULL);
00349                         if (nsec3.hash != 1)
00350                                 continue;
00351                         length = isc_iterated_hash(hash, nsec3.hash,
00352                                                    nsec3.iterations, nsec3.salt,
00353                                                    nsec3.salt_length,
00354                                                    name->ndata, name->length);
00355                         if (length != isc_buffer_usedlength(&buffer))
00356                                 continue;
00357                         order = memcmp(hash, owner, length);
00358                         if (order == 0) {
00359                                 found = dns_nsec3_typepresent(&rdata,
00360                                                               dns_rdatatype_ns);
00361                                 dns_rdataset_disassociate(&set);
00362                                 return (found);
00363                         }
00364                         if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) == 0)
00365                                 continue;
00366                         /*
00367                          * Does this optout span cover the name?
00368                          */
00369                         scope = memcmp(owner, nsec3.next, nsec3.next_length);
00370                         if ((scope < 0 && order > 0 &&
00371                              memcmp(hash, nsec3.next, length) < 0) ||
00372                             (scope >= 0 && (order > 0 ||
00373                                         memcmp(hash, nsec3.next, length) < 0)))
00374                         {
00375                                 dns_rdataset_disassociate(&set);
00376                                 return (ISC_TRUE);
00377                         }
00378                 }
00379                 dns_rdataset_disassociate(&set);
00380         }
00381         return (found);
00382 }
00383 
00384 /*%
00385  * We have been asked to look for a key.
00386  * If found resume the validation process.
00387  * If not found fail the validation process.
00388  */
00389 static void
00390 fetch_callback_validator(isc_task_t *task, isc_event_t *event) {
00391         dns_fetchevent_t *devent;
00392         dns_validator_t *val;
00393         dns_rdataset_t *rdataset;
00394         isc_boolean_t want_destroy;
00395         isc_result_t result;
00396         isc_result_t eresult;
00397         isc_result_t saved_result;
00398         dns_fetch_t *fetch;
00399 
00400         UNUSED(task);
00401         INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
00402         devent = (dns_fetchevent_t *)event;
00403         val = devent->ev_arg;
00404         rdataset = &val->frdataset;
00405         eresult = devent->result;
00406 
00407         /* Free resources which are not of interest. */
00408         if (devent->node != NULL)
00409                 dns_db_detachnode(devent->db, &devent->node);
00410         if (devent->db != NULL)
00411                 dns_db_detach(&devent->db);
00412         if (dns_rdataset_isassociated(&val->fsigrdataset))
00413                 dns_rdataset_disassociate(&val->fsigrdataset);
00414         isc_event_free(&event);
00415 
00416         INSIST(val->event != NULL);
00417 
00418         validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_validator");
00419         LOCK(&val->lock);
00420         fetch = val->fetch;
00421         val->fetch = NULL;
00422         if (CANCELED(val)) {
00423                 validator_done(val, ISC_R_CANCELED);
00424         } else if (eresult == ISC_R_SUCCESS) {
00425                 validator_log(val, ISC_LOG_DEBUG(3),
00426                               "keyset with trust %s",
00427                               dns_trust_totext(rdataset->trust));
00428                 /*
00429                  * Only extract the dst key if the keyset is secure.
00430                  */
00431                 if (rdataset->trust >= dns_trust_secure) {
00432                         result = get_dst_key(val, val->siginfo, rdataset);
00433                         if (result == ISC_R_SUCCESS)
00434                                 val->keyset = &val->frdataset;
00435                 }
00436                 result = validate(val, ISC_TRUE);
00437                 if (result == DNS_R_NOVALIDSIG &&
00438                     (val->attributes & VALATTR_TRIEDVERIFY) == 0)
00439                 {
00440                         saved_result = result;
00441                         validator_log(val, ISC_LOG_DEBUG(3),
00442                                       "falling back to insecurity proof");
00443                         val->attributes |= VALATTR_INSECURITY;
00444                         result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
00445                         if (result == DNS_R_NOTINSECURE)
00446                                 result = saved_result;
00447                 }
00448                 if (result != DNS_R_WAIT)
00449                         validator_done(val, result);
00450         } else {
00451                 validator_log(val, ISC_LOG_DEBUG(3),
00452                               "fetch_callback_validator: got %s",
00453                               isc_result_totext(eresult));
00454                 if (eresult == ISC_R_CANCELED)
00455                         validator_done(val, eresult);
00456                 else
00457                         validator_done(val, DNS_R_BROKENCHAIN);
00458         }
00459         want_destroy = exit_check(val);
00460         UNLOCK(&val->lock);
00461         if (fetch != NULL)
00462                 dns_resolver_destroyfetch(&fetch);
00463         if (want_destroy)
00464                 destroy(val);
00465 }
00466 
00467 /*%
00468  * We were asked to look for a DS record as part of following a key chain
00469  * upwards.  If found resume the validation process.  If not found fail the
00470  * validation process.
00471  */
00472 static void
00473 dsfetched(isc_task_t *task, isc_event_t *event) {
00474         dns_fetchevent_t *devent;
00475         dns_validator_t *val;
00476         dns_rdataset_t *rdataset;
00477         isc_boolean_t want_destroy;
00478         isc_result_t result;
00479         isc_result_t eresult;
00480         dns_fetch_t *fetch;
00481 
00482         UNUSED(task);
00483         INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
00484         devent = (dns_fetchevent_t *)event;
00485         val = devent->ev_arg;
00486         rdataset = &val->frdataset;
00487         eresult = devent->result;
00488 
00489         /* Free resources which are not of interest. */
00490         if (devent->node != NULL)
00491                 dns_db_detachnode(devent->db, &devent->node);
00492         if (devent->db != NULL)
00493                 dns_db_detach(&devent->db);
00494         if (dns_rdataset_isassociated(&val->fsigrdataset))
00495                 dns_rdataset_disassociate(&val->fsigrdataset);
00496         isc_event_free(&event);
00497 
00498         INSIST(val->event != NULL);
00499 
00500         validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched");
00501         LOCK(&val->lock);
00502         fetch = val->fetch;
00503         val->fetch = NULL;
00504         if (CANCELED(val)) {
00505                 validator_done(val, ISC_R_CANCELED);
00506         } else if (eresult == ISC_R_SUCCESS) {
00507                 validator_log(val, ISC_LOG_DEBUG(3),
00508                               "dsset with trust %s",
00509                                dns_trust_totext(rdataset->trust));
00510                 val->dsset = &val->frdataset;
00511                 result = validatezonekey(val);
00512                 if (result != DNS_R_WAIT)
00513                         validator_done(val, result);
00514         } else if (eresult == DNS_R_CNAME ||
00515                    eresult == DNS_R_NXRRSET ||
00516                    eresult == DNS_R_NCACHENXRRSET ||
00517                    eresult == DNS_R_SERVFAIL)   /* RFC 1034 parent? */
00518         {
00519                 validator_log(val, ISC_LOG_DEBUG(3),
00520                               "falling back to insecurity proof (%s)",
00521                               dns_result_totext(eresult));
00522                 val->attributes |= VALATTR_INSECURITY;
00523                 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
00524                 if (result != DNS_R_WAIT)
00525                         validator_done(val, result);
00526         } else {
00527                 validator_log(val, ISC_LOG_DEBUG(3),
00528                               "dsfetched: got %s",
00529                               isc_result_totext(eresult));
00530                 if (eresult == ISC_R_CANCELED)
00531                         validator_done(val, eresult);
00532                 else
00533                         validator_done(val, DNS_R_BROKENCHAIN);
00534         }
00535         want_destroy = exit_check(val);
00536         UNLOCK(&val->lock);
00537         if (fetch != NULL)
00538                 dns_resolver_destroyfetch(&fetch);
00539         if (want_destroy)
00540                 destroy(val);
00541 }
00542 
00543 /*%
00544  * We were asked to look for the DS record as part of proving that a
00545  * name is unsecure.
00546  *
00547  * If the DS record doesn't exist and the query name corresponds to
00548  * a delegation point we are transitioning from a secure zone to a
00549  * unsecure zone.
00550  *
00551  * If the DS record exists it will be secure.  We can continue looking
00552  * for the break point in the chain of trust.
00553  */
00554 static void
00555 dsfetched2(isc_task_t *task, isc_event_t *event) {
00556         dns_fetchevent_t *devent;
00557         dns_validator_t *val;
00558         dns_name_t *tname;
00559         isc_boolean_t want_destroy;
00560         isc_result_t result;
00561         isc_result_t eresult;
00562         dns_fetch_t *fetch;
00563 
00564         UNUSED(task);
00565         INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
00566         devent = (dns_fetchevent_t *)event;
00567         val = devent->ev_arg;
00568         eresult = devent->result;
00569 
00570         /* Free resources which are not of interest. */
00571         if (devent->node != NULL)
00572                 dns_db_detachnode(devent->db, &devent->node);
00573         if (devent->db != NULL)
00574                 dns_db_detach(&devent->db);
00575         if (dns_rdataset_isassociated(&val->fsigrdataset))
00576                 dns_rdataset_disassociate(&val->fsigrdataset);
00577 
00578         INSIST(val->event != NULL);
00579 
00580         validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched2: %s",
00581                       dns_result_totext(eresult));
00582         LOCK(&val->lock);
00583         fetch = val->fetch;
00584         val->fetch = NULL;
00585         if (CANCELED(val)) {
00586                 validator_done(val, ISC_R_CANCELED);
00587         } else if (eresult == DNS_R_CNAME ||
00588                    eresult == DNS_R_NXRRSET ||
00589                    eresult == DNS_R_NCACHENXRRSET)
00590         {
00591                 /*
00592                  * There is no DS.  If this is a delegation, we're done.
00593                  */
00594                 tname = dns_fixedname_name(&devent->foundname);
00595                 if (eresult != DNS_R_CNAME &&
00596                     isdelegation(tname, &val->frdataset, eresult)) {
00597                         if (val->mustbesecure) {
00598                                 validator_log(val, ISC_LOG_WARNING,
00599                                               "must be secure failure, no DS"
00600                                               " and this is a delegation");
00601                                 validator_done(val, DNS_R_MUSTBESECURE);
00602                         } else if (val->view->dlv == NULL || DLVTRIED(val)) {
00603                                 markanswer(val, "dsfetched2");
00604                                 validator_done(val, ISC_R_SUCCESS);
00605                         } else {
00606                                 result = startfinddlvsep(val, tname);
00607                                 if (result != DNS_R_WAIT)
00608                                         validator_done(val, result);
00609                         }
00610                 } else {
00611                         result = proveunsecure(val, ISC_FALSE, ISC_TRUE);
00612                         if (result != DNS_R_WAIT)
00613                                 validator_done(val, result);
00614                 }
00615         } else if (eresult == ISC_R_SUCCESS ||
00616                    eresult == DNS_R_NXDOMAIN ||
00617                    eresult == DNS_R_NCACHENXDOMAIN)
00618         {
00619                 /*
00620                  * There is a DS which may or may not be a zone cut.
00621                  * In either case we are still in a secure zone resume
00622                  * validation.
00623                  */
00624                 result = proveunsecure(val, ISC_TF(eresult == ISC_R_SUCCESS),
00625                                        ISC_TRUE);
00626                 if (result != DNS_R_WAIT)
00627                         validator_done(val, result);
00628         } else {
00629                 if (eresult == ISC_R_CANCELED)
00630                         validator_done(val, eresult);
00631                 else
00632                         validator_done(val, DNS_R_NOVALIDDS);
00633         }
00634         isc_event_free(&event);
00635         want_destroy = exit_check(val);
00636         UNLOCK(&val->lock);
00637         if (fetch != NULL)
00638                 dns_resolver_destroyfetch(&fetch);
00639         if (want_destroy)
00640                 destroy(val);
00641 }
00642 
00643 /*%
00644  * Callback from when a DNSKEY RRset has been validated.
00645  *
00646  * Resumes the stalled validation process.
00647  */
00648 static void
00649 keyvalidated(isc_task_t *task, isc_event_t *event) {
00650         dns_validatorevent_t *devent;
00651         dns_validator_t *val;
00652         isc_boolean_t want_destroy;
00653         isc_result_t result;
00654         isc_result_t eresult;
00655         isc_result_t saved_result;
00656 
00657         UNUSED(task);
00658         INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
00659 
00660         devent = (dns_validatorevent_t *)event;
00661         val = devent->ev_arg;
00662         eresult = devent->result;
00663 
00664         isc_event_free(&event);
00665         dns_validator_destroy(&val->subvalidator);
00666 
00667         INSIST(val->event != NULL);
00668 
00669         validator_log(val, ISC_LOG_DEBUG(3), "in keyvalidated");
00670         LOCK(&val->lock);
00671         if (CANCELED(val)) {
00672                 validator_done(val, ISC_R_CANCELED);
00673         } else if (eresult == ISC_R_SUCCESS) {
00674                 validator_log(val, ISC_LOG_DEBUG(3),
00675                               "keyset with trust %s",
00676                               dns_trust_totext(val->frdataset.trust));
00677                 /*
00678                  * Only extract the dst key if the keyset is secure.
00679                  */
00680                 if (val->frdataset.trust >= dns_trust_secure)
00681                         (void) get_dst_key(val, val->siginfo, &val->frdataset);
00682                 result = validate(val, ISC_TRUE);
00683                 if (result == DNS_R_NOVALIDSIG &&
00684                     (val->attributes & VALATTR_TRIEDVERIFY) == 0)
00685                 {
00686                         saved_result = result;
00687                         validator_log(val, ISC_LOG_DEBUG(3),
00688                                       "falling back to insecurity proof");
00689                         val->attributes |= VALATTR_INSECURITY;
00690                         result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
00691                         if (result == DNS_R_NOTINSECURE)
00692                                 result = saved_result;
00693                 }
00694                 if (result != DNS_R_WAIT)
00695                         validator_done(val, result);
00696         } else {
00697                 if (eresult != DNS_R_BROKENCHAIN) {
00698                         if (dns_rdataset_isassociated(&val->frdataset))
00699                                 dns_rdataset_expire(&val->frdataset);
00700                         if (dns_rdataset_isassociated(&val->fsigrdataset))
00701                                 dns_rdataset_expire(&val->fsigrdataset);
00702                 }
00703                 validator_log(val, ISC_LOG_DEBUG(3),
00704                               "keyvalidated: got %s",
00705                               isc_result_totext(eresult));
00706                 validator_done(val, DNS_R_BROKENCHAIN);
00707         }
00708         want_destroy = exit_check(val);
00709         UNLOCK(&val->lock);
00710         if (want_destroy)
00711                 destroy(val);
00712 }
00713 
00714 /*%
00715  * Callback when the DS record has been validated.
00716  *
00717  * Resumes validation of the zone key or the unsecure zone proof.
00718  */
00719 static void
00720 dsvalidated(isc_task_t *task, isc_event_t *event) {
00721         dns_validatorevent_t *devent;
00722         dns_validator_t *val;
00723         isc_boolean_t want_destroy;
00724         isc_result_t result;
00725         isc_result_t eresult;
00726 
00727         UNUSED(task);
00728         INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
00729 
00730         devent = (dns_validatorevent_t *)event;
00731         val = devent->ev_arg;
00732         eresult = devent->result;
00733 
00734         isc_event_free(&event);
00735         dns_validator_destroy(&val->subvalidator);
00736 
00737         INSIST(val->event != NULL);
00738 
00739         validator_log(val, ISC_LOG_DEBUG(3), "in dsvalidated");
00740         LOCK(&val->lock);
00741         if (CANCELED(val)) {
00742                 validator_done(val, ISC_R_CANCELED);
00743         } else if (eresult == ISC_R_SUCCESS) {
00744                 isc_boolean_t have_dsset;
00745                 dns_name_t *name;
00746                 validator_log(val, ISC_LOG_DEBUG(3),
00747                               "%s with trust %s",
00748                               val->frdataset.type == dns_rdatatype_ds ?
00749                               "dsset" : "ds non-existance",
00750                               dns_trust_totext(val->frdataset.trust));
00751                 have_dsset = ISC_TF(val->frdataset.type == dns_rdatatype_ds);
00752                 name = dns_fixedname_name(&val->fname);
00753                 if ((val->attributes & VALATTR_INSECURITY) != 0 &&
00754                     val->frdataset.covers == dns_rdatatype_ds &&
00755                     NEGATIVE(&val->frdataset) &&
00756                     isdelegation(name, &val->frdataset, DNS_R_NCACHENXRRSET)) {
00757                         if (val->mustbesecure) {
00758                                 validator_log(val, ISC_LOG_WARNING,
00759                                               "must be secure failure, no DS "
00760                                               "and this is a delegation");
00761                                 result = DNS_R_MUSTBESECURE;
00762                         } else if (val->view->dlv == NULL || DLVTRIED(val)) {
00763                                 markanswer(val, "dsvalidated");
00764                                 result = ISC_R_SUCCESS;;
00765                         } else
00766                                 result = startfinddlvsep(val, name);
00767                 } else if ((val->attributes & VALATTR_INSECURITY) != 0) {
00768                         result = proveunsecure(val, have_dsset, ISC_TRUE);
00769                 } else
00770                         result = validatezonekey(val);
00771                 if (result != DNS_R_WAIT)
00772                         validator_done(val, result);
00773         } else {
00774                 if (eresult != DNS_R_BROKENCHAIN) {
00775                         if (dns_rdataset_isassociated(&val->frdataset))
00776                                 dns_rdataset_expire(&val->frdataset);
00777                         if (dns_rdataset_isassociated(&val->fsigrdataset))
00778                                 dns_rdataset_expire(&val->fsigrdataset);
00779                 }
00780                 validator_log(val, ISC_LOG_DEBUG(3),
00781                               "dsvalidated: got %s",
00782                               isc_result_totext(eresult));
00783                 validator_done(val, DNS_R_BROKENCHAIN);
00784         }
00785         want_destroy = exit_check(val);
00786         UNLOCK(&val->lock);
00787         if (want_destroy)
00788                 destroy(val);
00789 }
00790 
00791 /*%
00792  * Callback when the CNAME record has been validated.
00793  *
00794  * Resumes validation of the unsecure zone proof.
00795  */
00796 static void
00797 cnamevalidated(isc_task_t *task, isc_event_t *event) {
00798         dns_validatorevent_t *devent;
00799         dns_validator_t *val;
00800         isc_boolean_t want_destroy;
00801         isc_result_t result;
00802         isc_result_t eresult;
00803 
00804         UNUSED(task);
00805         INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
00806 
00807         devent = (dns_validatorevent_t *)event;
00808         val = devent->ev_arg;
00809         eresult = devent->result;
00810 
00811         isc_event_free(&event);
00812         dns_validator_destroy(&val->subvalidator);
00813 
00814         INSIST(val->event != NULL);
00815         INSIST((val->attributes & VALATTR_INSECURITY) != 0);
00816 
00817         validator_log(val, ISC_LOG_DEBUG(3), "in cnamevalidated");
00818         LOCK(&val->lock);
00819         if (CANCELED(val)) {
00820                 validator_done(val, ISC_R_CANCELED);
00821         } else if (eresult == ISC_R_SUCCESS) {
00822                 validator_log(val, ISC_LOG_DEBUG(3), "cname with trust %s",
00823                               dns_trust_totext(val->frdataset.trust));
00824                 result = proveunsecure(val, ISC_FALSE, ISC_TRUE);
00825                 if (result != DNS_R_WAIT)
00826                         validator_done(val, result);
00827         } else {
00828                 if (eresult != DNS_R_BROKENCHAIN) {
00829                         if (dns_rdataset_isassociated(&val->frdataset))
00830                                 dns_rdataset_expire(&val->frdataset);
00831                         if (dns_rdataset_isassociated(&val->fsigrdataset))
00832                                 dns_rdataset_expire(&val->fsigrdataset);
00833                 }
00834                 validator_log(val, ISC_LOG_DEBUG(3),
00835                               "cnamevalidated: got %s",
00836                               isc_result_totext(eresult));
00837                 validator_done(val, DNS_R_BROKENCHAIN);
00838         }
00839         want_destroy = exit_check(val);
00840         UNLOCK(&val->lock);
00841         if (want_destroy)
00842                 destroy(val);
00843 }
00844 
00845 /*%
00846  * Callback for when NSEC records have been validated.
00847  *
00848  * Looks for NOQNAME, NODATA and OPTOUT proofs.
00849  *
00850  * Resumes nsecvalidate.
00851  */
00852 static void
00853 authvalidated(isc_task_t *task, isc_event_t *event) {
00854         dns_validatorevent_t *devent;
00855         dns_validator_t *val;
00856         dns_rdataset_t *rdataset;
00857         isc_boolean_t want_destroy;
00858         isc_result_t result;
00859         isc_boolean_t exists, data;
00860 
00861         UNUSED(task);
00862         INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
00863 
00864         devent = (dns_validatorevent_t *)event;
00865         rdataset = devent->rdataset;
00866         val = devent->ev_arg;
00867         result = devent->result;
00868         dns_validator_destroy(&val->subvalidator);
00869 
00870         INSIST(val->event != NULL);
00871 
00872         validator_log(val, ISC_LOG_DEBUG(3), "in authvalidated");
00873         LOCK(&val->lock);
00874         if (CANCELED(val)) {
00875                 validator_done(val, ISC_R_CANCELED);
00876         } else if (result != ISC_R_SUCCESS) {
00877                 validator_log(val, ISC_LOG_DEBUG(3),
00878                               "authvalidated: got %s",
00879                               isc_result_totext(result));
00880                 if (result == DNS_R_BROKENCHAIN)
00881                         val->authfail++;
00882                 if (result == ISC_R_CANCELED)
00883                         validator_done(val, result);
00884                 else {
00885                         result = nsecvalidate(val, ISC_TRUE);
00886                         if (result != DNS_R_WAIT)
00887                                 validator_done(val, result);
00888                 }
00889         } else {
00890                 dns_name_t **proofs = val->event->proofs;
00891                 dns_name_t *wild = dns_fixedname_name(&val->wild);
00892 
00893                 if (rdataset->trust == dns_trust_secure)
00894                         val->seensig = ISC_TRUE;
00895 
00896                 if (rdataset->type == dns_rdatatype_nsec &&
00897                     rdataset->trust == dns_trust_secure &&
00898                     (NEEDNODATA(val) || NEEDNOQNAME(val)) &&
00899                     !FOUNDNODATA(val) && !FOUNDNOQNAME(val) &&
00900                     dns_nsec_noexistnodata(val->event->type, val->event->name,
00901                                            devent->name, rdataset, &exists,
00902                                            &data, wild, validator_log, val)
00903                                       == ISC_R_SUCCESS)
00904                 {
00905                         if (exists && !data) {
00906                                 val->attributes |= VALATTR_FOUNDNODATA;
00907                                 if (NEEDNODATA(val))
00908                                         proofs[DNS_VALIDATOR_NODATAPROOF] =
00909                                                 devent->name;
00910                         }
00911                         if (!exists) {
00912                                 dns_name_t *closest;
00913                                 unsigned int clabels;
00914 
00915                                 val->attributes |= VALATTR_FOUNDNOQNAME;
00916 
00917                                 closest = dns_fixedname_name(&val->closest);
00918                                 clabels = dns_name_countlabels(closest);
00919                                 /*
00920                                  * If we are validating a wildcard response
00921                                  * clabels will not be zero.  We then need
00922                                  * to check if the generated wilcard from
00923                                  * dns_nsec_noexistnodata is consistent with
00924                                  * the wildcard used to generate the response.
00925                                  */
00926                                 if (clabels == 0 ||
00927                                     dns_name_countlabels(wild) == clabels + 1)
00928                                         val->attributes |= VALATTR_FOUNDCLOSEST;
00929                                 /*
00930                                  * The NSEC noqname proof also contains
00931                                  * the closest encloser.
00932                                  */
00933                                 if (NEEDNOQNAME(val))
00934                                         proofs[DNS_VALIDATOR_NOQNAMEPROOF] =
00935                                                 devent->name;
00936                         }
00937                 }
00938 
00939                 result = nsecvalidate(val, ISC_TRUE);
00940                 if (result != DNS_R_WAIT)
00941                         validator_done(val, result);
00942         }
00943         want_destroy = exit_check(val);
00944         UNLOCK(&val->lock);
00945         if (want_destroy)
00946                 destroy(val);
00947 
00948         /*
00949          * Free stuff from the event.
00950          */
00951         isc_event_free(&event);
00952 }
00953 
00954 /*%
00955  * Looks for the requested name and type in the view (zones and cache).
00956  *
00957  * When looking for a DLV record also checks to make sure the NSEC record
00958  * returns covers the query name as part of aggressive negative caching.
00959  *
00960  * Returns:
00961  * \li  ISC_R_SUCCESS
00962  * \li  ISC_R_NOTFOUND
00963  * \li  DNS_R_NCACHENXDOMAIN
00964  * \li  DNS_R_NCACHENXRRSET
00965  * \li  DNS_R_NXRRSET
00966  * \li  DNS_R_NXDOMAIN
00967  * \li  DNS_R_BROKENCHAIN
00968  */
00969 static inline isc_result_t
00970 view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
00971         dns_fixedname_t fixedname;
00972         dns_name_t *foundname;
00973         dns_rdata_nsec_t nsec;
00974         dns_rdata_t rdata = DNS_RDATA_INIT;
00975         isc_result_t result;
00976         unsigned int options;
00977         isc_time_t now;
00978         char buf1[DNS_NAME_FORMATSIZE];
00979         char buf2[DNS_NAME_FORMATSIZE];
00980         char buf3[DNS_NAME_FORMATSIZE];
00981         char namebuf[DNS_NAME_FORMATSIZE];
00982         char typebuf[DNS_RDATATYPE_FORMATSIZE];
00983 
00984         if (dns_rdataset_isassociated(&val->frdataset))
00985                 dns_rdataset_disassociate(&val->frdataset);
00986         if (dns_rdataset_isassociated(&val->fsigrdataset))
00987                 dns_rdataset_disassociate(&val->fsigrdataset);
00988 
00989         if (isc_time_now(&now) == ISC_R_SUCCESS &&
00990             dns_resolver_getbadcache(val->view->resolver, name, type, &now)) {
00991 
00992                 dns_name_format(name, namebuf, sizeof(namebuf));
00993                 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
00994                 validator_log(val, ISC_LOG_INFO, "bad cache hit (%s/%s)",
00995                               namebuf, typebuf);
00996                 return (DNS_R_BROKENCHAIN);
00997         }
00998 
00999         options = DNS_DBFIND_PENDINGOK;
01000         if (type == dns_rdatatype_dlv)
01001                 options |= DNS_DBFIND_COVERINGNSEC;
01002         dns_fixedname_init(&fixedname);
01003         foundname = dns_fixedname_name(&fixedname);
01004         result = dns_view_find(val->view, name, type, 0, options,
01005                                ISC_FALSE, NULL, NULL, foundname,
01006                                &val->frdataset, &val->fsigrdataset);
01007 
01008         if (result == DNS_R_NXDOMAIN) {
01009                 if (dns_rdataset_isassociated(&val->frdataset))
01010                         dns_rdataset_disassociate(&val->frdataset);
01011                 if (dns_rdataset_isassociated(&val->fsigrdataset))
01012                         dns_rdataset_disassociate(&val->fsigrdataset);
01013         } else if (result == DNS_R_COVERINGNSEC) {
01014                 validator_log(val, ISC_LOG_DEBUG(3), "DNS_R_COVERINGNSEC");
01015                 /*
01016                  * Check if the returned NSEC covers the name.
01017                  */
01018                 INSIST(type == dns_rdatatype_dlv);
01019                 if (val->frdataset.trust != dns_trust_secure) {
01020                         validator_log(val, ISC_LOG_DEBUG(3),
01021                                       "covering nsec: trust %s",
01022                                       dns_trust_totext(val->frdataset.trust));
01023                         goto notfound;
01024                 }
01025                 result = dns_rdataset_first(&val->frdataset);
01026                 if (result != ISC_R_SUCCESS)
01027                         goto notfound;
01028                 dns_rdataset_current(&val->frdataset, &rdata);
01029                 if (dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
01030                     !dns_nsec_typepresent(&rdata, dns_rdatatype_soa)) {
01031                         /* Parent NSEC record. */
01032                         if (dns_name_issubdomain(name, foundname)) {
01033                                 validator_log(val, ISC_LOG_DEBUG(3),
01034                                               "covering nsec: for parent");
01035                                 goto notfound;
01036                         }
01037                 }
01038                 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
01039                 if (result != ISC_R_SUCCESS)
01040                         goto notfound;
01041                 if (dns_name_compare(foundname, &nsec.next) >= 0) {
01042                         /* End of zone chain. */
01043                         if (!dns_name_issubdomain(name, &nsec.next)) {
01044                                 /*
01045                                  * XXXMPA We could look for a parent NSEC
01046                                  * at nsec.next and if found retest with
01047                                  * this NSEC.
01048                                  */
01049                                 dns_rdata_freestruct(&nsec);
01050                                 validator_log(val, ISC_LOG_DEBUG(3),
01051                                               "covering nsec: not in zone");
01052                                 goto notfound;
01053                         }
01054                 } else if (dns_name_compare(name, &nsec.next) >= 0) {
01055                         /*
01056                          * XXXMPA We could check if this NSEC is at a zone
01057                          * apex and if the qname is not below it and look for
01058                          * a parent NSEC with the same name.  This requires
01059                          * that we can cache both NSEC records which we
01060                          * currently don't support.
01061                          */
01062                         dns_rdata_freestruct(&nsec);
01063                         validator_log(val, ISC_LOG_DEBUG(3),
01064                                       "covering nsec: not in range");
01065                         goto notfound;
01066                 }
01067                 if (isc_log_wouldlog(dns_lctx,ISC_LOG_DEBUG(3))) {
01068                         dns_name_format(name, buf1, sizeof buf1);
01069                         dns_name_format(foundname, buf2, sizeof buf2);
01070                         dns_name_format(&nsec.next, buf3, sizeof buf3);
01071                         validator_log(val, ISC_LOG_DEBUG(3),
01072                                       "covering nsec found: '%s' '%s' '%s'",
01073                                       buf1, buf2, buf3);
01074                 }
01075                 if (dns_rdataset_isassociated(&val->frdataset))
01076                         dns_rdataset_disassociate(&val->frdataset);
01077                 if (dns_rdataset_isassociated(&val->fsigrdataset))
01078                         dns_rdataset_disassociate(&val->fsigrdataset);
01079                 dns_rdata_freestruct(&nsec);
01080                 result = DNS_R_NCACHENXDOMAIN;
01081         } else if (result != ISC_R_SUCCESS &&
01082                    result != DNS_R_NCACHENXDOMAIN &&
01083                    result != DNS_R_NCACHENXRRSET &&
01084                    result != DNS_R_EMPTYNAME &&
01085                    result != DNS_R_NXRRSET &&
01086                    result != ISC_R_NOTFOUND) {
01087                 goto  notfound;
01088         }
01089         return (result);
01090 
01091  notfound:
01092         if (dns_rdataset_isassociated(&val->frdataset))
01093                 dns_rdataset_disassociate(&val->frdataset);
01094         if (dns_rdataset_isassociated(&val->fsigrdataset))
01095                 dns_rdataset_disassociate(&val->fsigrdataset);
01096         return (ISC_R_NOTFOUND);
01097 }
01098 
01099 /*%
01100  * Checks to make sure we are not going to loop.  As we use a SHARED fetch
01101  * the validation process will stall if looping was to occur.
01102  */
01103 static inline isc_boolean_t
01104 check_deadlock(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
01105                dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
01106 {
01107         dns_validator_t *parent;
01108 
01109         for (parent = val; parent != NULL; parent = parent->parent) {
01110                 if (parent->event != NULL &&
01111                     parent->event->type == type &&
01112                     dns_name_equal(parent->event->name, name) &&
01113                     /*
01114                      * As NSEC3 records are meta data you sometimes
01115                      * need to prove a NSEC3 record which says that
01116                      * itself doesn't exist.
01117                      */
01118                     (parent->event->type != dns_rdatatype_nsec3 ||
01119                      rdataset == NULL || sigrdataset == NULL ||
01120                      parent->event->message == NULL ||
01121                      parent->event->rdataset != NULL ||
01122                      parent->event->sigrdataset != NULL))
01123                 {
01124                         validator_log(val, ISC_LOG_DEBUG(3),
01125                                       "continuing validation would lead to "
01126                                       "deadlock: aborting validation");
01127                         return (ISC_TRUE);
01128                 }
01129         }
01130         return (ISC_FALSE);
01131 }
01132 
01133 /*%
01134  * Start a fetch for the requested name and type.
01135  */
01136 static inline isc_result_t
01137 create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
01138              isc_taskaction_t callback, const char *caller)
01139 {
01140         unsigned int fopts = 0;
01141 
01142         if (dns_rdataset_isassociated(&val->frdataset))
01143                 dns_rdataset_disassociate(&val->frdataset);
01144         if (dns_rdataset_isassociated(&val->fsigrdataset))
01145                 dns_rdataset_disassociate(&val->fsigrdataset);
01146 
01147         if (check_deadlock(val, name, type, NULL, NULL)) {
01148                 validator_log(val, ISC_LOG_DEBUG(3),
01149                               "deadlock found (create_fetch)");
01150                 return (DNS_R_NOVALIDSIG);
01151         }
01152 
01153         if ((val->options & DNS_VALIDATOR_NOCDFLAG) != 0)
01154                 fopts |= DNS_FETCHOPT_NOCDFLAG;
01155 
01156         if ((val->options & DNS_VALIDATOR_NONTA) != 0)
01157                 fopts |= DNS_FETCHOPT_NONTA;
01158 
01159         validator_logcreate(val, name, type, caller, "fetch");
01160         return (dns_resolver_createfetch(val->view->resolver, name, type,
01161                                          NULL, NULL, NULL, fopts,
01162                                          val->event->ev_sender,
01163                                          callback, val,
01164                                          &val->frdataset,
01165                                          &val->fsigrdataset,
01166                                          &val->fetch));
01167 }
01168 
01169 /*%
01170  * Start a subvalidation process.
01171  */
01172 static inline isc_result_t
01173 create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
01174                  dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
01175                  isc_taskaction_t action, const char *caller)
01176 {
01177         isc_result_t result;
01178         unsigned int vopts = 0;
01179 
01180         if (check_deadlock(val, name, type, rdataset, sigrdataset)) {
01181                 validator_log(val, ISC_LOG_DEBUG(3),
01182                               "deadlock found (create_validator)");
01183                 return (DNS_R_NOVALIDSIG);
01184         }
01185 
01186         /* OK to clear other options, but preserve NOCDFLAG and NONTA. */
01187         vopts |= (val->options & (DNS_VALIDATOR_NOCDFLAG|DNS_VALIDATOR_NONTA));
01188 
01189         validator_logcreate(val, name, type, caller, "validator");
01190         result = dns_validator_create(val->view, name, type,
01191                                       rdataset, sigrdataset, NULL, vopts,
01192                                       val->task, action, val,
01193                                       &val->subvalidator);
01194         if (result == ISC_R_SUCCESS) {
01195                 val->subvalidator->parent = val;
01196                 val->subvalidator->depth = val->depth + 1;
01197         }
01198         return (result);
01199 }
01200 
01201 /*%
01202  * Try to find a key that could have signed 'siginfo' among those
01203  * in 'rdataset'.  If found, build a dst_key_t for it and point
01204  * val->key at it.
01205  *
01206  * If val->key is non-NULL, this returns the next matching key.
01207  */
01208 static isc_result_t
01209 get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
01210             dns_rdataset_t *rdataset)
01211 {
01212         isc_result_t result;
01213         isc_buffer_t b;
01214         dns_rdata_t rdata = DNS_RDATA_INIT;
01215         dst_key_t *oldkey = val->key;
01216         isc_boolean_t foundold;
01217 
01218         if (oldkey == NULL)
01219                 foundold = ISC_TRUE;
01220         else {
01221                 foundold = ISC_FALSE;
01222                 val->key = NULL;
01223         }
01224 
01225         result = dns_rdataset_first(rdataset);
01226         if (result != ISC_R_SUCCESS)
01227                 goto failure;
01228         do {
01229                 dns_rdataset_current(rdataset, &rdata);
01230 
01231                 isc_buffer_init(&b, rdata.data, rdata.length);
01232                 isc_buffer_add(&b, rdata.length);
01233                 INSIST(val->key == NULL);
01234                 result = dst_key_fromdns(&siginfo->signer, rdata.rdclass, &b,
01235                                          val->view->mctx, &val->key);
01236                 if (result != ISC_R_SUCCESS)
01237                         goto failure;
01238                 if (siginfo->algorithm ==
01239                     (dns_secalg_t)dst_key_alg(val->key) &&
01240                     siginfo->keyid ==
01241                     (dns_keytag_t)dst_key_id(val->key) &&
01242                     dst_key_iszonekey(val->key))
01243                 {
01244                         if (foundold)
01245                                 /*
01246                                  * This is the key we're looking for.
01247                                  */
01248                                 return (ISC_R_SUCCESS);
01249                         else if (dst_key_compare(oldkey, val->key) == ISC_TRUE)
01250                         {
01251                                 foundold = ISC_TRUE;
01252                                 dst_key_free(&oldkey);
01253                         }
01254                 }
01255                 dst_key_free(&val->key);
01256                 dns_rdata_reset(&rdata);
01257                 result = dns_rdataset_next(rdataset);
01258         } while (result == ISC_R_SUCCESS);
01259         if (result == ISC_R_NOMORE)
01260                 result = ISC_R_NOTFOUND;
01261 
01262  failure:
01263         if (oldkey != NULL)
01264                 dst_key_free(&oldkey);
01265 
01266         return (result);
01267 }
01268 
01269 /*%
01270  * Get the key that generated this signature.
01271  */
01272 static isc_result_t
01273 get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
01274         isc_result_t result;
01275         unsigned int nlabels;
01276         int order;
01277         dns_namereln_t namereln;
01278 
01279         /*
01280          * Is the signer name appropriate for this signature?
01281          *
01282          * The signer name must be at the same level as the owner name
01283          * or closer to the DNS root.
01284          */
01285         namereln = dns_name_fullcompare(val->event->name, &siginfo->signer,
01286                                         &order, &nlabels);
01287         if (namereln != dns_namereln_subdomain &&
01288             namereln != dns_namereln_equal)
01289                 return (DNS_R_CONTINUE);
01290 
01291         if (namereln == dns_namereln_equal) {
01292                 /*
01293                  * If this is a self-signed keyset, it must not be a zone key
01294                  * (since get_key is not called from validatezonekey).
01295                  */
01296                 if (val->event->rdataset->type == dns_rdatatype_dnskey)
01297                         return (DNS_R_CONTINUE);
01298 
01299                 /*
01300                  * Records appearing in the parent zone at delegation
01301                  * points cannot be self-signed.
01302                  */
01303                 if (dns_rdatatype_atparent(val->event->rdataset->type))
01304                         return (DNS_R_CONTINUE);
01305         } else {
01306                 /*
01307                  * SOA and NS RRsets can only be signed by a key with
01308                  * the same name.
01309                  */
01310                 if (val->event->rdataset->type == dns_rdatatype_soa ||
01311                     val->event->rdataset->type == dns_rdatatype_ns) {
01312                         const char *typename;
01313 
01314                         if (val->event->rdataset->type == dns_rdatatype_soa)
01315                                 typename = "SOA";
01316                         else
01317                                 typename = "NS";
01318                         validator_log(val, ISC_LOG_DEBUG(3),
01319                                       "%s signer mismatch", typename);
01320                         return (DNS_R_CONTINUE);
01321                 }
01322         }
01323 
01324         /*
01325          * Do we know about this key?
01326          */
01327         result = view_find(val, &siginfo->signer, dns_rdatatype_dnskey);
01328         if (result == ISC_R_SUCCESS) {
01329                 /*
01330                  * We have an rrset for the given keyname.
01331                  */
01332                 val->keyset = &val->frdataset;
01333                 if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
01334                      DNS_TRUST_ANSWER(val->frdataset.trust)) &&
01335                     dns_rdataset_isassociated(&val->fsigrdataset))
01336                 {
01337                         /*
01338                          * We know the key but haven't validated it yet or
01339                          * we have a key of trust answer but a DS/DLV
01340                          * record for the zone may have been added.
01341                          */
01342                         result = create_validator(val, &siginfo->signer,
01343                                                   dns_rdatatype_dnskey,
01344                                                   &val->frdataset,
01345                                                   &val->fsigrdataset,
01346                                                   keyvalidated,
01347                                                   "get_key");
01348                         if (result != ISC_R_SUCCESS)
01349                                 return (result);
01350                         return (DNS_R_WAIT);
01351                 } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
01352                         /*
01353                          * Having a pending key with no signature means that
01354                          * something is broken.
01355                          */
01356                         result = DNS_R_CONTINUE;
01357                 } else if (val->frdataset.trust < dns_trust_secure) {
01358                         /*
01359                          * The key is legitimately insecure.  There's no
01360                          * point in even attempting verification.
01361                          */
01362                         val->key = NULL;
01363                         result = ISC_R_SUCCESS;
01364                 } else {
01365                         /*
01366                          * See if we've got the key used in the signature.
01367                          */
01368                         validator_log(val, ISC_LOG_DEBUG(3),
01369                                       "keyset with trust %s",
01370                                       dns_trust_totext(val->frdataset.trust));
01371                         result = get_dst_key(val, siginfo, val->keyset);
01372                         if (result != ISC_R_SUCCESS) {
01373                                 /*
01374                                  * Either the key we're looking for is not
01375                                  * in the rrset, or something bad happened.
01376                                  * Give up.
01377                                  */
01378                                 result = DNS_R_CONTINUE;
01379                         }
01380                 }
01381         } else if (result == ISC_R_NOTFOUND) {
01382                 /*
01383                  * We don't know anything about this key.
01384                  */
01385                 result = create_fetch(val, &siginfo->signer,
01386                                       dns_rdatatype_dnskey,
01387                                       fetch_callback_validator, "get_key");
01388                 if (result != ISC_R_SUCCESS)
01389                         return (result);
01390                 return (DNS_R_WAIT);
01391         } else if (result ==  DNS_R_NCACHENXDOMAIN ||
01392                    result == DNS_R_NCACHENXRRSET ||
01393                    result == DNS_R_EMPTYNAME ||
01394                    result == DNS_R_NXDOMAIN ||
01395                    result == DNS_R_NXRRSET)
01396         {
01397                 /*
01398                  * This key doesn't exist.
01399                  */
01400                 result = DNS_R_CONTINUE;
01401         } else if (result == DNS_R_BROKENCHAIN)
01402                 return (result);
01403 
01404         if (dns_rdataset_isassociated(&val->frdataset) &&
01405             val->keyset != &val->frdataset)
01406                 dns_rdataset_disassociate(&val->frdataset);
01407         if (dns_rdataset_isassociated(&val->fsigrdataset))
01408                 dns_rdataset_disassociate(&val->fsigrdataset);
01409 
01410         return (result);
01411 }
01412 
01413 static dns_keytag_t
01414 compute_keytag(dns_rdata_t *rdata, dns_rdata_dnskey_t *key) {
01415         isc_region_t r;
01416 
01417         dns_rdata_toregion(rdata, &r);
01418         return (dst_region_computeid(&r, key->algorithm));
01419 }
01420 
01421 /*%
01422  * Is this keyset self-signed?
01423  */
01424 static isc_boolean_t
01425 isselfsigned(dns_validator_t *val) {
01426         dns_fixedname_t fixed;
01427         dns_rdataset_t *rdataset, *sigrdataset;
01428         dns_rdata_t rdata = DNS_RDATA_INIT;
01429         dns_rdata_t sigrdata = DNS_RDATA_INIT;
01430         dns_rdata_dnskey_t key;
01431         dns_rdata_rrsig_t sig;
01432         dns_keytag_t keytag;
01433         dns_name_t *name;
01434         isc_result_t result;
01435         dst_key_t *dstkey;
01436         isc_mem_t *mctx;
01437         isc_boolean_t answer = ISC_FALSE;
01438 
01439         rdataset = val->event->rdataset;
01440         sigrdataset = val->event->sigrdataset;
01441         name = val->event->name;
01442         mctx = val->view->mctx;
01443 
01444         if (rdataset->type == dns_rdatatype_cname ||
01445             rdataset->type == dns_rdatatype_dname)
01446                 return (answer);
01447 
01448         INSIST(rdataset->type == dns_rdatatype_dnskey);
01449 
01450         for (result = dns_rdataset_first(rdataset);
01451              result == ISC_R_SUCCESS;
01452              result = dns_rdataset_next(rdataset))
01453         {
01454                 dns_rdata_reset(&rdata);
01455                 dns_rdataset_current(rdataset, &rdata);
01456                 result = dns_rdata_tostruct(&rdata, &key, NULL);
01457                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
01458                 keytag = compute_keytag(&rdata, &key);
01459                 for (result = dns_rdataset_first(sigrdataset);
01460                      result == ISC_R_SUCCESS;
01461                      result = dns_rdataset_next(sigrdataset))
01462                 {
01463                         dns_rdata_reset(&sigrdata);
01464                         dns_rdataset_current(sigrdataset, &sigrdata);
01465                         result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
01466                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
01467 
01468                         if (sig.algorithm != key.algorithm ||
01469                             sig.keyid != keytag ||
01470                             !dns_name_equal(name, &sig.signer))
01471                                 continue;
01472 
01473                         dstkey = NULL;
01474                         result = dns_dnssec_keyfromrdata(name, &rdata, mctx,
01475                                                          &dstkey);
01476                         if (result != ISC_R_SUCCESS)
01477                                 continue;
01478 
01479                         result = dns_dnssec_verify3(name, rdataset, dstkey,
01480                                                     ISC_TRUE,
01481                                                     val->view->maxbits,
01482                                                     mctx, &sigrdata,
01483                                                     dns_fixedname_name(&fixed));
01484                         dst_key_free(&dstkey);
01485                         if (result != ISC_R_SUCCESS)
01486                                 continue;
01487                         if ((key.flags & DNS_KEYFLAG_REVOKE) == 0) {
01488                                 answer = ISC_TRUE;
01489                                 continue;
01490                         }
01491                         dns_view_untrust(val->view, name, &key, mctx);
01492                 }
01493         }
01494         return (answer);
01495 }
01496 
01497 /*%
01498  * Attempt to verify the rdataset using the given key and rdata (RRSIG).
01499  * The signature was good and from a wildcard record and the QNAME does
01500  * not match the wildcard we need to look for a NOQNAME proof.
01501  *
01502  * Returns:
01503  * \li  ISC_R_SUCCESS if the verification succeeds.
01504  * \li  Others if the verification fails.
01505  */
01506 static isc_result_t
01507 verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata,
01508        isc_uint16_t keyid)
01509 {
01510         isc_result_t result;
01511         dns_fixedname_t fixed;
01512         isc_boolean_t ignore = ISC_FALSE;
01513         dns_name_t *wild;
01514 
01515         val->attributes |= VALATTR_TRIEDVERIFY;
01516         dns_fixedname_init(&fixed);
01517         wild = dns_fixedname_name(&fixed);
01518  again:
01519         result = dns_dnssec_verify3(val->event->name, val->event->rdataset,
01520                                     key, ignore, val->view->maxbits,
01521                                     val->view->mctx, rdata, wild);
01522         if ((result == DNS_R_SIGEXPIRED || result == DNS_R_SIGFUTURE) &&
01523             val->view->acceptexpired)
01524         {
01525                 ignore = ISC_TRUE;
01526                 goto again;
01527         }
01528         if (ignore && (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD))
01529                 validator_log(val, ISC_LOG_INFO,
01530                               "accepted expired %sRRSIG (keyid=%u)",
01531                               (result == DNS_R_FROMWILDCARD) ?
01532                               "wildcard " : "", keyid);
01533         else if (result == DNS_R_SIGEXPIRED || result == DNS_R_SIGFUTURE)
01534                 validator_log(val, ISC_LOG_INFO,
01535                               "verify failed due to bad signature (keyid=%u): "
01536                               "%s", keyid, isc_result_totext(result));
01537         else
01538                 validator_log(val, ISC_LOG_DEBUG(3),
01539                               "verify rdataset (keyid=%u): %s",
01540                               keyid, isc_result_totext(result));
01541         if (result == DNS_R_FROMWILDCARD) {
01542                 if (!dns_name_equal(val->event->name, wild)) {
01543                         dns_name_t *closest;
01544                         unsigned int labels;
01545 
01546                         /*
01547                          * Compute the closest encloser in case we need it
01548                          * for the NSEC3 NOQNAME proof.
01549                          */
01550                         closest = dns_fixedname_name(&val->closest);
01551                         dns_name_copy(wild, closest, NULL);
01552                         labels = dns_name_countlabels(closest) - 1;
01553                         dns_name_getlabelsequence(closest, 1, labels, closest);
01554                         val->attributes |= VALATTR_NEEDNOQNAME;
01555                 }
01556                 result = ISC_R_SUCCESS;
01557         }
01558         return (result);
01559 }
01560 
01561 /*%
01562  * Attempts positive response validation of a normal RRset.
01563  *
01564  * Returns:
01565  * \li  ISC_R_SUCCESS   Validation completed successfully
01566  * \li  DNS_R_WAIT      Validation has started but is waiting
01567  *                      for an event.
01568  * \li  Other return codes are possible and all indicate failure.
01569  */
01570 static isc_result_t
01571 validate(dns_validator_t *val, isc_boolean_t resume) {
01572         isc_result_t result, vresult = DNS_R_NOVALIDSIG;
01573         dns_validatorevent_t *event;
01574         dns_rdata_t rdata = DNS_RDATA_INIT;
01575 
01576         /*
01577          * Caller must be holding the validator lock.
01578          */
01579 
01580         event = val->event;
01581 
01582         if (resume) {
01583                 /*
01584                  * We already have a sigrdataset.
01585                  */
01586                 result = ISC_R_SUCCESS;
01587                 validator_log(val, ISC_LOG_DEBUG(3), "resuming validate");
01588         } else {
01589                 result = dns_rdataset_first(event->sigrdataset);
01590         }
01591 
01592         for (;
01593              result == ISC_R_SUCCESS;
01594              result = dns_rdataset_next(event->sigrdataset))
01595         {
01596                 dns_rdata_reset(&rdata);
01597                 dns_rdataset_current(event->sigrdataset, &rdata);
01598                 if (val->siginfo == NULL) {
01599                         val->siginfo = isc_mem_get(val->view->mctx,
01600                                                    sizeof(*val->siginfo));
01601                         if (val->siginfo == NULL)
01602                                 return (ISC_R_NOMEMORY);
01603                 }
01604                 result = dns_rdata_tostruct(&rdata, val->siginfo, NULL);
01605                 if (result != ISC_R_SUCCESS)
01606                         return (result);
01607 
01608                 /*
01609                  * At this point we could check that the signature algorithm
01610                  * was known and "sufficiently good".
01611                  */
01612                 if (!dns_resolver_algorithm_supported(val->view->resolver,
01613                                                     event->name,
01614                                                     val->siginfo->algorithm)) {
01615                         resume = ISC_FALSE;
01616                         continue;
01617                 }
01618 
01619                 if (!resume) {
01620                         result = get_key(val, val->siginfo);
01621                         if (result == DNS_R_CONTINUE)
01622                                 continue; /* Try the next SIG RR. */
01623                         if (result != ISC_R_SUCCESS)
01624                                 return (result);
01625                 }
01626 
01627                 /*
01628                  * There isn't a secure DNSKEY for this signature so move
01629                  * onto the next RRSIG.
01630                  */
01631                 if (val->key == NULL) {
01632                         resume = ISC_FALSE;
01633                         continue;
01634                 }
01635 
01636                 do {
01637                         vresult = verify(val, val->key, &rdata,
01638                                         val->siginfo->keyid);
01639                         if (vresult == ISC_R_SUCCESS)
01640                                 break;
01641                         if (val->keynode != NULL) {
01642                                 dns_keynode_t *nextnode = NULL;
01643                                 result = dns_keytable_findnextkeynode(
01644                                                         val->keytable,
01645                                                         val->keynode,
01646                                                         &nextnode);
01647                                 dns_keytable_detachkeynode(val->keytable,
01648                                                            &val->keynode);
01649                                 val->keynode = nextnode;
01650                                 if (result != ISC_R_SUCCESS) {
01651                                         val->key = NULL;
01652                                         break;
01653                                 }
01654                                 val->key = dns_keynode_key(val->keynode);
01655                                 if (val->key == NULL)
01656                                         break;
01657                         } else {
01658                                 if (get_dst_key(val, val->siginfo, val->keyset)
01659                                     != ISC_R_SUCCESS)
01660                                         break;
01661                         }
01662                 } while (1);
01663                 if (vresult != ISC_R_SUCCESS)
01664                         validator_log(val, ISC_LOG_DEBUG(3),
01665                                       "failed to verify rdataset");
01666                 else {
01667                         dns_rdataset_trimttl(event->rdataset,
01668                                              event->sigrdataset,
01669                                              val->siginfo, val->start,
01670                                              val->view->acceptexpired);
01671                 }
01672 
01673                 if (val->keynode != NULL)
01674                         dns_keytable_detachkeynode(val->keytable,
01675                                                    &val->keynode);
01676                 else {
01677                         if (val->key != NULL)
01678                                 dst_key_free(&val->key);
01679                         if (val->keyset != NULL) {
01680                                 dns_rdataset_disassociate(val->keyset);
01681                                 val->keyset = NULL;
01682                         }
01683                 }
01684                 val->key = NULL;
01685                 if (NEEDNOQNAME(val)) {
01686                         if (val->event->message == NULL) {
01687                                 validator_log(val, ISC_LOG_DEBUG(3),
01688                                       "no message available for noqname proof");
01689                                 return (DNS_R_NOVALIDSIG);
01690                         }
01691                         validator_log(val, ISC_LOG_DEBUG(3),
01692                                       "looking for noqname proof");
01693                         return (nsecvalidate(val, ISC_FALSE));
01694                 } else if (vresult == ISC_R_SUCCESS) {
01695                         marksecure(event);
01696                         validator_log(val, ISC_LOG_DEBUG(3),
01697                                       "marking as secure, "
01698                                       "noqname proof not needed");
01699                         return (ISC_R_SUCCESS);
01700                 } else {
01701                         validator_log(val, ISC_LOG_DEBUG(3),
01702                                       "verify failure: %s",
01703                                       isc_result_totext(result));
01704                         resume = ISC_FALSE;
01705                 }
01706         }
01707         if (result != ISC_R_NOMORE) {
01708                 validator_log(val, ISC_LOG_DEBUG(3),
01709                               "failed to iterate signatures: %s",
01710                               isc_result_totext(result));
01711                 return (result);
01712         }
01713 
01714         validator_log(val, ISC_LOG_INFO, "no valid signature found");
01715         return (vresult);
01716 }
01717 
01718 /*%
01719  * Check whether this DNSKEY (keyrdata) signed the DNSKEY RRset
01720  * (val->event->rdataset).
01721  */
01722 static isc_result_t
01723 checkkey(dns_validator_t *val, dns_rdata_t *keyrdata, isc_uint16_t keyid,
01724          dns_secalg_t algorithm)
01725 {
01726         dns_rdata_rrsig_t sig;
01727         dst_key_t *dstkey = NULL;
01728         isc_result_t result;
01729 
01730         for (result = dns_rdataset_first(val->event->sigrdataset);
01731              result == ISC_R_SUCCESS;
01732              result = dns_rdataset_next(val->event->sigrdataset))
01733         {
01734                 dns_rdata_t rdata = DNS_RDATA_INIT;
01735 
01736                 dns_rdataset_current(val->event->sigrdataset, &rdata);
01737                 result = dns_rdata_tostruct(&rdata, &sig, NULL);
01738                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
01739                 if (keyid != sig.keyid || algorithm != sig.algorithm)
01740                         continue;
01741                 if (dstkey == NULL) {
01742                         result = dns_dnssec_keyfromrdata(val->event->name,
01743                                                          keyrdata,
01744                                                          val->view->mctx,
01745                                                          &dstkey);
01746                         if (result != ISC_R_SUCCESS)
01747                                 /*
01748                                  * This really shouldn't happen, but...
01749                                  */
01750                                 continue;
01751                 }
01752                 result = verify(val, dstkey, &rdata, sig.keyid);
01753                 if (result == ISC_R_SUCCESS)
01754                         break;
01755         }
01756         if (dstkey != NULL)
01757                 dst_key_free(&dstkey);
01758         return (result);
01759 }
01760 
01761 /*%
01762  * Find the DNSKEY that corresponds to the DS.
01763  */
01764 static isc_result_t
01765 keyfromds(dns_validator_t *val, dns_rdataset_t *rdataset, dns_rdata_t *dsrdata,
01766           isc_uint8_t digest, isc_uint16_t keyid, dns_secalg_t algorithm,
01767           dns_rdata_t *keyrdata)
01768 {
01769         dns_keytag_t keytag;
01770         dns_rdata_dnskey_t key;
01771         isc_result_t result;
01772         unsigned char dsbuf[DNS_DS_BUFFERSIZE];
01773 
01774         for (result = dns_rdataset_first(rdataset);
01775              result == ISC_R_SUCCESS;
01776              result = dns_rdataset_next(rdataset))
01777         {
01778                 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
01779 
01780                 dns_rdata_reset(keyrdata);
01781                 dns_rdataset_current(rdataset, keyrdata);
01782                 result = dns_rdata_tostruct(keyrdata, &key, NULL);
01783                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
01784                 keytag = compute_keytag(keyrdata, &key);
01785                 if (keyid != keytag || algorithm != key.algorithm)
01786                         continue;
01787                 dns_rdata_reset(&newdsrdata);
01788                 result = dns_ds_buildrdata(val->event->name, keyrdata, digest,
01789                                            dsbuf, &newdsrdata);
01790                 if (result != ISC_R_SUCCESS) {
01791                         validator_log(val, ISC_LOG_DEBUG(3),
01792                                       "dns_ds_buildrdata() -> %s",
01793                                       dns_result_totext(result));
01794                         continue;
01795                 }
01796                 if (dns_rdata_compare(dsrdata, &newdsrdata) == 0)
01797                         break;
01798         }
01799         return (result);
01800 }
01801 
01802 /*%
01803  * Validate the DNSKEY RRset by looking for a DNSKEY that matches a
01804  * DLV record and that also verifies the DNSKEY RRset.
01805  */
01806 static isc_result_t
01807 dlv_validatezonekey(dns_validator_t *val) {
01808         dns_rdata_dlv_t dlv;
01809         dns_rdata_t dlvrdata = DNS_RDATA_INIT;
01810         dns_rdata_t keyrdata = DNS_RDATA_INIT;
01811         dns_rdataset_t trdataset;
01812         isc_boolean_t supported_algorithm;
01813         isc_result_t result;
01814         char digest_types[256];
01815 
01816         validator_log(val, ISC_LOG_DEBUG(3), "dlv_validatezonekey");
01817 
01818         /*
01819          * Look through the DLV record and find the keys that can sign the
01820          * key set and the matching signature.  For each such key, attempt
01821          * verification.
01822          */
01823         supported_algorithm = ISC_FALSE;
01824 
01825         /*
01826          * If DNS_DSDIGEST_SHA256 is present we are required to prefer
01827          * it over DNS_DSDIGEST_SHA1.  This in practice means that we
01828          * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
01829          * is present.
01830          */
01831         memset(digest_types, 1, sizeof(digest_types));
01832         for (result = dns_rdataset_first(&val->dlv);
01833              result == ISC_R_SUCCESS;
01834              result = dns_rdataset_next(&val->dlv)) {
01835                 dns_rdata_reset(&dlvrdata);
01836                 dns_rdataset_current(&val->dlv, &dlvrdata);
01837                 result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
01838                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
01839 
01840                 if (!dns_resolver_algorithm_supported(val->view->resolver,
01841                                                       val->event->name,
01842                                                       dlv.algorithm))
01843                         continue;
01844 
01845                 if (dlv.digest_type == DNS_DSDIGEST_SHA256 &&
01846                     dlv.length == ISC_SHA256_DIGESTLENGTH) {
01847                         digest_types[DNS_DSDIGEST_SHA1] = 0;
01848                         break;
01849                 }
01850         }
01851 
01852         for (result = dns_rdataset_first(&val->dlv);
01853              result == ISC_R_SUCCESS;
01854              result = dns_rdataset_next(&val->dlv))
01855         {
01856                 dns_rdata_reset(&dlvrdata);
01857                 dns_rdataset_current(&val->dlv, &dlvrdata);
01858                 result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
01859                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
01860 
01861                 if (digest_types[dlv.digest_type] == 0)
01862                         continue;
01863 
01864                 if (!dns_resolver_ds_digest_supported(val->view->resolver,
01865                                                       val->event->name,
01866                                                       dlv.digest_type))
01867                         continue;
01868 
01869                 if (!dns_resolver_algorithm_supported(val->view->resolver,
01870                                                       val->event->name,
01871                                                       dlv.algorithm))
01872                         continue;
01873 
01874                 supported_algorithm = ISC_TRUE;
01875 
01876                 dns_rdataset_init(&trdataset);
01877                 dns_rdataset_clone(val->event->rdataset, &trdataset);
01878 
01879                 /*
01880                  * Convert to DLV to DS and find matching DNSKEY.
01881                  */
01882                 dlvrdata.type = dns_rdatatype_ds;
01883                 result = keyfromds(val, &trdataset, &dlvrdata,
01884                                    dlv.digest_type, dlv.key_tag,
01885                                    dlv.algorithm, &keyrdata);
01886                 if (result != ISC_R_SUCCESS) {
01887                         dns_rdataset_disassociate(&trdataset);
01888                         validator_log(val, ISC_LOG_DEBUG(3),
01889                                       "no DNSKEY matching DLV");
01890                         continue;
01891                 }
01892 
01893                 validator_log(val, ISC_LOG_DEBUG(3),
01894                       "Found matching DLV record: checking for signature");
01895                 /*
01896                  * Check that this DNSKEY signed the DNSKEY rrset.
01897                  */
01898                 result = checkkey(val, &keyrdata, dlv.key_tag, dlv.algorithm);
01899 
01900                 dns_rdataset_disassociate(&trdataset);
01901                 if (result == ISC_R_SUCCESS)
01902                         break;
01903                 validator_log(val, ISC_LOG_DEBUG(3),
01904                               "no RRSIG matching DLV key");
01905         }
01906         if (result == ISC_R_SUCCESS) {
01907                 marksecure(val->event);
01908                 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (dlv)");
01909                 return (result);
01910         } else if (result == ISC_R_NOMORE && !supported_algorithm) {
01911                 if (val->mustbesecure) {
01912                         validator_log(val, ISC_LOG_WARNING,
01913                                       "must be secure failure,"
01914                                       "no supported algorithm/digest (dlv)");
01915                         return (DNS_R_MUSTBESECURE);
01916                 }
01917                 validator_log(val, ISC_LOG_DEBUG(3),
01918                               "no supported algorithm/digest (dlv)");
01919                 markanswer(val, "dlv_validatezonekey (2)");
01920                 return (ISC_R_SUCCESS);
01921         } else
01922                 return (DNS_R_NOVALIDSIG);
01923 }
01924 
01925 /*%
01926  * Attempts positive response validation of an RRset containing zone keys
01927  * (i.e. a DNSKEY rrset).
01928  *
01929  * Returns:
01930  * \li  ISC_R_SUCCESS   Validation completed successfully
01931  * \li  DNS_R_WAIT      Validation has started but is waiting
01932  *                      for an event.
01933  * \li  Other return codes are possible and all indicate failure.
01934  */
01935 static isc_result_t
01936 validatezonekey(dns_validator_t *val) {
01937         isc_result_t result;
01938         dns_validatorevent_t *event;
01939         dns_rdataset_t trdataset;
01940         dns_rdata_t dsrdata = DNS_RDATA_INIT;
01941         dns_rdata_t keyrdata = DNS_RDATA_INIT;
01942         dns_rdata_t sigrdata = DNS_RDATA_INIT;
01943         char namebuf[DNS_NAME_FORMATSIZE];
01944         dns_rdata_ds_t ds;
01945         dns_rdata_rrsig_t sig;
01946         dst_key_t *dstkey;
01947         isc_boolean_t supported_algorithm;
01948         isc_boolean_t atsep = ISC_FALSE;
01949         char digest_types[256];
01950 
01951         /*
01952          * Caller must be holding the validator lock.
01953          */
01954 
01955         event = val->event;
01956 
01957         if (val->havedlvsep && val->dlv.trust >= dns_trust_secure &&
01958             dns_name_equal(event->name, dns_fixedname_name(&val->dlvsep)))
01959                 return (dlv_validatezonekey(val));
01960 
01961         if (val->dsset == NULL) {
01962 
01963                 /*
01964                  * We have a dlv sep.  Skip looking up the SEP from
01965                  * {trusted,managed}-keys.  If the dlv sep is for the
01966                  * root then it will have been handled above so we don't
01967                  * need to check whether val->event->name is "." prior to
01968                  * looking up the DS.
01969                  */
01970                 if (val->havedlvsep)
01971                         goto find_ds;
01972 
01973                 /*
01974                  * First, see if this key was signed by a trusted key.
01975                  */
01976                 for (result = dns_rdataset_first(val->event->sigrdataset);
01977                      result == ISC_R_SUCCESS;
01978                      result = dns_rdataset_next(val->event->sigrdataset))
01979                 {
01980                         dns_keynode_t *keynode = NULL;
01981                         dns_fixedname_t fixed;
01982                         dns_name_t *found;
01983 
01984                         dns_fixedname_init(&fixed);
01985                         found = dns_fixedname_name(&fixed);
01986                         dns_rdata_reset(&sigrdata);
01987                         dns_rdataset_current(val->event->sigrdataset,
01988                                              &sigrdata);
01989                         result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
01990                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
01991 
01992                         if (!dns_name_equal(val->event->name, &sig.signer))
01993                                 continue;
01994 
01995                         result = dns_keytable_findkeynode(val->keytable,
01996                                                           val->event->name,
01997                                                           sig.algorithm,
01998                                                           sig.keyid, &keynode);
01999                         if (result == ISC_R_NOTFOUND &&
02000                             dns_keytable_finddeepestmatch(val->keytable,
02001                                   val->event->name, found) != ISC_R_SUCCESS) {
02002                                 if (val->mustbesecure) {
02003                                         validator_log(val, ISC_LOG_WARNING,
02004                                                      "must be secure failure, "
02005                                                      "not beneath secure root");
02006                                         return (DNS_R_MUSTBESECURE);
02007                                 } else
02008                                         validator_log(val, ISC_LOG_DEBUG(3),
02009                                                      "not beneath secure root");
02010                                 if (val->view->dlv == NULL) {
02011                                         markanswer(val, "validatezonekey (1)");
02012                                         return (ISC_R_SUCCESS);
02013                                 }
02014                                 return (startfinddlvsep(val, dns_rootname));
02015                         }
02016                         if (result == DNS_R_PARTIALMATCH ||
02017                             result == ISC_R_SUCCESS)
02018                                 atsep = ISC_TRUE;
02019                         while (result == ISC_R_SUCCESS) {
02020                                 dns_keynode_t *nextnode = NULL;
02021                                 dstkey = dns_keynode_key(keynode);
02022                                 if (dstkey == NULL) {
02023                                         dns_keytable_detachkeynode(
02024                                                                 val->keytable,
02025                                                                 &keynode);
02026                                         break;
02027                                 }
02028                                 result = verify(val, dstkey, &sigrdata,
02029                                                 sig.keyid);
02030                                 if (result == ISC_R_SUCCESS) {
02031                                         dns_keytable_detachkeynode(
02032                                                                 val->keytable,
02033                                                                 &keynode);
02034                                         break;
02035                                 }
02036                                 result = dns_keytable_findnextkeynode(
02037                                                                 val->keytable,
02038                                                                 keynode,
02039                                                                 &nextnode);
02040                                 dns_keytable_detachkeynode(val->keytable,
02041                                                            &keynode);
02042                                 keynode = nextnode;
02043                         }
02044                         if (result == ISC_R_SUCCESS) {
02045                                 marksecure(event);
02046                                 validator_log(val, ISC_LOG_DEBUG(3),
02047                                               "signed by trusted key; "
02048                                               "marking as secure");
02049                                 return (result);
02050                         }
02051                 }
02052 
02053                 if (atsep) {
02054                         /*
02055                          * We have not found a key to verify this DNSKEY
02056                          * RRset.  As this is a SEP we have to assume that
02057                          * the RRset is invalid.
02058                          */
02059                         dns_name_format(val->event->name, namebuf,
02060                                         sizeof(namebuf));
02061                         validator_log(val, ISC_LOG_NOTICE,
02062                                       "unable to find a DNSKEY which verifies "
02063                                       "the DNSKEY RRset and also matches a "
02064                                       "trusted key for '%s'",
02065                                       namebuf);
02066                         return (DNS_R_NOVALIDKEY);
02067                 }
02068 
02069                 /*
02070                  * If this is the root name and there was no trusted key,
02071                  * give up, since there's no DS at the root.
02072                  */
02073                 if (dns_name_equal(event->name, dns_rootname)) {
02074                         if ((val->attributes & VALATTR_TRIEDVERIFY) != 0) {
02075                                 validator_log(val, ISC_LOG_DEBUG(3),
02076                                               "root key failed to validate");
02077                                 return (DNS_R_NOVALIDSIG);
02078                         } else {
02079                                 validator_log(val, ISC_LOG_DEBUG(3),
02080                                               "no trusted root key");
02081                                 return (DNS_R_NOVALIDDS);
02082                         }
02083                 }
02084  find_ds:
02085                 /*
02086                  * Otherwise, try to find the DS record.
02087                  */
02088                 result = view_find(val, val->event->name, dns_rdatatype_ds);
02089                 if (result == ISC_R_SUCCESS) {
02090                         /*
02091                          * We have DS records.
02092                          */
02093                         val->dsset = &val->frdataset;
02094                         if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
02095                              DNS_TRUST_ANSWER(val->frdataset.trust)) &&
02096                             dns_rdataset_isassociated(&val->fsigrdataset))
02097                         {
02098                                 result = create_validator(val,
02099                                                           val->event->name,
02100                                                           dns_rdatatype_ds,
02101                                                           &val->frdataset,
02102                                                           &val->fsigrdataset,
02103                                                           dsvalidated,
02104                                                           "validatezonekey");
02105                                 if (result != ISC_R_SUCCESS)
02106                                         return (result);
02107                                 return (DNS_R_WAIT);
02108                         } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
02109                                 /*
02110                                  * There should never be an unsigned DS.
02111                                  */
02112                                 dns_rdataset_disassociate(&val->frdataset);
02113                                 validator_log(val, ISC_LOG_DEBUG(2),
02114                                               "unsigned DS record");
02115                                 return (DNS_R_NOVALIDSIG);
02116                         } else {
02117                                 result = ISC_R_SUCCESS;
02118                                 POST(result);
02119                         }
02120                 } else if (result == ISC_R_NOTFOUND) {
02121                         /*
02122                          * We don't have the DS.  Find it.
02123                          */
02124                         result = create_fetch(val, val->event->name,
02125                                               dns_rdatatype_ds, dsfetched,
02126                                               "validatezonekey");
02127                         if (result != ISC_R_SUCCESS)
02128                                 return (result);
02129                         return (DNS_R_WAIT);
02130                 } else if (result == DNS_R_NCACHENXDOMAIN ||
02131                            result == DNS_R_NCACHENXRRSET ||
02132                            result == DNS_R_EMPTYNAME ||
02133                            result == DNS_R_NXDOMAIN ||
02134                            result == DNS_R_NXRRSET ||
02135                            result == DNS_R_CNAME)
02136                 {
02137                         /*
02138                          * The DS does not exist.
02139                          */
02140                         if (dns_rdataset_isassociated(&val->frdataset))
02141                                 dns_rdataset_disassociate(&val->frdataset);
02142                         if (dns_rdataset_isassociated(&val->fsigrdataset))
02143                                 dns_rdataset_disassociate(&val->fsigrdataset);
02144                         validator_log(val, ISC_LOG_DEBUG(2), "no DS record");
02145                         return (DNS_R_NOVALIDSIG);
02146                 } else if (result == DNS_R_BROKENCHAIN)
02147                         return (result);
02148         }
02149 
02150         /*
02151          * We have a DS set.
02152          */
02153         INSIST(val->dsset != NULL);
02154 
02155         if (val->dsset->trust < dns_trust_secure) {
02156                 if (val->mustbesecure) {
02157                         validator_log(val, ISC_LOG_WARNING,
02158                                       "must be secure failure,"
02159                                       " insecure DS");
02160                         return (DNS_R_MUSTBESECURE);
02161                 }
02162                 if (val->view->dlv == NULL || DLVTRIED(val)) {
02163                         markanswer(val, "validatezonekey (2)");
02164                         return (ISC_R_SUCCESS);
02165                 }
02166                 return (startfinddlvsep(val, val->event->name));
02167         }
02168 
02169         /*
02170          * Look through the DS record and find the keys that can sign the
02171          * key set and the matching signature.  For each such key, attempt
02172          * verification.
02173          */
02174 
02175         supported_algorithm = ISC_FALSE;
02176 
02177         /*
02178          * If DNS_DSDIGEST_SHA256 is present we are required to prefer
02179          * it over DNS_DSDIGEST_SHA1.  This in practice means that we
02180          * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
02181          * is present.
02182          */
02183         memset(digest_types, 1, sizeof(digest_types));
02184         for (result = dns_rdataset_first(val->dsset);
02185              result == ISC_R_SUCCESS;
02186              result = dns_rdataset_next(val->dsset)) {
02187                 dns_rdata_reset(&dsrdata);
02188                 dns_rdataset_current(val->dsset, &dsrdata);
02189                 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
02190                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
02191 
02192                 if (!dns_resolver_algorithm_supported(val->view->resolver,
02193                                                       val->event->name,
02194                                                       ds.algorithm))
02195                         continue;
02196 
02197                 if (ds.digest_type == DNS_DSDIGEST_SHA256 &&
02198                     ds.length == ISC_SHA256_DIGESTLENGTH) {
02199                         digest_types[DNS_DSDIGEST_SHA1] = 0;
02200                         break;
02201                 }
02202         }
02203 
02204         for (result = dns_rdataset_first(val->dsset);
02205              result == ISC_R_SUCCESS;
02206              result = dns_rdataset_next(val->dsset))
02207         {
02208                 dns_rdata_reset(&dsrdata);
02209                 dns_rdataset_current(val->dsset, &dsrdata);
02210                 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
02211                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
02212 
02213                 if (digest_types[ds.digest_type] == 0)
02214                         continue;
02215 
02216                 if (!dns_resolver_ds_digest_supported(val->view->resolver,
02217                                                       val->event->name,
02218                                                       ds.digest_type))
02219                         continue;
02220 
02221                 if (!dns_resolver_algorithm_supported(val->view->resolver,
02222                                                       val->event->name,
02223                                                       ds.algorithm))
02224                         continue;
02225 
02226                 supported_algorithm = ISC_TRUE;
02227 
02228                 dns_rdataset_init(&trdataset);
02229                 dns_rdataset_clone(val->event->rdataset, &trdataset);
02230 
02231                 /*
02232                  * Find matching DNSKEY from DS.
02233                  */
02234                 result = keyfromds(val, &trdataset, &dsrdata, ds.digest_type,
02235                                    ds.key_tag, ds.algorithm, &keyrdata);
02236                 if (result != ISC_R_SUCCESS) {
02237                         dns_rdataset_disassociate(&trdataset);
02238                         validator_log(val, ISC_LOG_DEBUG(3),
02239                                       "no DNSKEY matching DS");
02240                         continue;
02241                 }
02242 
02243                 /*
02244                  * Check that this DNSKEY signed the DNSKEY rrset.
02245                  */
02246                 result = checkkey(val, &keyrdata, ds.key_tag, ds.algorithm);
02247 
02248                 dns_rdataset_disassociate(&trdataset);
02249                 if (result == ISC_R_SUCCESS)
02250                         break;
02251                 validator_log(val, ISC_LOG_DEBUG(3),
02252                               "no RRSIG matching DS key");
02253         }
02254         if (result == ISC_R_SUCCESS) {
02255                 marksecure(event);
02256                 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (DS)");
02257                 return (result);
02258         } else if (result == ISC_R_NOMORE && !supported_algorithm) {
02259                 if (val->mustbesecure) {
02260                         validator_log(val, ISC_LOG_WARNING,
02261                                       "must be secure failure, "
02262                                       "no supported algorithm/digest (DS)");
02263                         return (DNS_R_MUSTBESECURE);
02264                 }
02265                 validator_log(val, ISC_LOG_DEBUG(3),
02266                               "no supported algorithm/digest (DS)");
02267                 markanswer(val, "validatezonekey (3)");
02268                 return (ISC_R_SUCCESS);
02269         } else {
02270                 validator_log(val, ISC_LOG_INFO,
02271                               "no valid signature found (DS)");
02272                 return (DNS_R_NOVALIDSIG);
02273         }
02274 }
02275 
02276 /*%
02277  * Starts a positive response validation.
02278  *
02279  * Returns:
02280  * \li  ISC_R_SUCCESS   Validation completed successfully
02281  * \li  DNS_R_WAIT      Validation has started but is waiting
02282  *                      for an event.
02283  * \li  Other return codes are possible and all indicate failure.
02284  */
02285 static isc_result_t
02286 start_positive_validation(dns_validator_t *val) {
02287         /*
02288          * If this is not a key, go straight into validate().
02289          */
02290         if (val->event->type != dns_rdatatype_dnskey || !isselfsigned(val))
02291                 return (validate(val, ISC_FALSE));
02292 
02293         return (validatezonekey(val));
02294 }
02295 
02296 /*%
02297  * val_rdataset_first and val_rdataset_next provide iteration methods
02298  * that hide whether we are iterating across a message or a  negative
02299  * cache rdataset.
02300  */
02301 static isc_result_t
02302 val_rdataset_first(dns_validator_t *val, dns_name_t **namep,
02303                    dns_rdataset_t **rdatasetp)
02304 {
02305         dns_message_t *message = val->event->message;
02306         isc_result_t result;
02307 
02308         REQUIRE(rdatasetp != NULL);
02309         REQUIRE(namep != NULL);
02310         if (message == NULL) {
02311                 REQUIRE(*rdatasetp != NULL);
02312                 REQUIRE(*namep != NULL);
02313         } else {
02314                 REQUIRE(*rdatasetp == NULL);
02315                 REQUIRE(*namep == NULL);
02316         }
02317 
02318         if (message != NULL) {
02319                 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
02320                 if (result != ISC_R_SUCCESS)
02321                         return (result);
02322                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, namep);
02323                 *rdatasetp = ISC_LIST_HEAD((*namep)->list);
02324                 INSIST(*rdatasetp != NULL);
02325         } else {
02326                 result = dns_rdataset_first(val->event->rdataset);
02327                 if (result == ISC_R_SUCCESS)
02328                         dns_ncache_current(val->event->rdataset, *namep,
02329                                            *rdatasetp);
02330         }
02331         return (result);
02332 }
02333 
02334 static isc_result_t
02335 val_rdataset_next(dns_validator_t *val, dns_name_t **namep,
02336                   dns_rdataset_t **rdatasetp)
02337 {
02338         dns_message_t *message = val->event->message;
02339         isc_result_t result = ISC_R_SUCCESS;
02340 
02341         REQUIRE(rdatasetp != NULL && *rdatasetp != NULL);
02342         REQUIRE(namep != NULL && *namep != NULL);
02343 
02344         if (message != NULL) {
02345                 dns_rdataset_t *rdataset = *rdatasetp;
02346                 rdataset = ISC_LIST_NEXT(rdataset, link);
02347                 if (rdataset == NULL) {
02348                         *namep = NULL;
02349                         result = dns_message_nextname(message,
02350                                                       DNS_SECTION_AUTHORITY);
02351                         if (result == ISC_R_SUCCESS) {
02352                                 dns_message_currentname(message,
02353                                                         DNS_SECTION_AUTHORITY,
02354                                                         namep);
02355                                 rdataset = ISC_LIST_HEAD((*namep)->list);
02356                                 INSIST(rdataset != NULL);
02357                         }
02358                 }
02359                 *rdatasetp = rdataset;
02360         } else {
02361                 dns_rdataset_disassociate(*rdatasetp);
02362                 result = dns_rdataset_next(val->event->rdataset);
02363                 if (result == ISC_R_SUCCESS)
02364                         dns_ncache_current(val->event->rdataset, *namep,
02365                                            *rdatasetp);
02366         }
02367         return (result);
02368 }
02369 
02370 /*%
02371  * Look for NODATA at the wildcard and NOWILDCARD proofs in the
02372  * previously validated NSEC records.  As these proofs are mutually
02373  * exclusive we stop when one is found.
02374  *
02375  * Returns
02376  * \li  ISC_R_SUCCESS
02377  */
02378 static isc_result_t
02379 checkwildcard(dns_validator_t *val, dns_rdatatype_t type, dns_name_t *zonename)
02380 {
02381         dns_name_t *name, *wild, tname;
02382         isc_result_t result;
02383         isc_boolean_t exists, data;
02384         char namebuf[DNS_NAME_FORMATSIZE];
02385         dns_rdataset_t *rdataset, trdataset;
02386 
02387         dns_name_init(&tname, NULL);
02388         dns_rdataset_init(&trdataset);
02389         wild = dns_fixedname_name(&val->wild);
02390 
02391         if (dns_name_countlabels(wild) == 0) {
02392                 validator_log(val, ISC_LOG_DEBUG(3),
02393                               "in checkwildcard: no wildcard to check");
02394                 return (ISC_R_SUCCESS);
02395         }
02396 
02397         dns_name_format(wild, namebuf, sizeof(namebuf));
02398         validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf);
02399 
02400         if (val->event->message == NULL) {
02401                 name = &tname;
02402                 rdataset = &trdataset;
02403         } else {
02404                 name = NULL;
02405                 rdataset = NULL;
02406         }
02407 
02408         for (result = val_rdataset_first(val, &name, &rdataset);
02409              result == ISC_R_SUCCESS;
02410              result = val_rdataset_next(val, &name, &rdataset))
02411         {
02412                 if (rdataset->type != type ||
02413                     rdataset->trust != dns_trust_secure)
02414                         continue;
02415 
02416                 if (rdataset->type == dns_rdatatype_nsec &&
02417                     (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
02418                     !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
02419                     dns_nsec_noexistnodata(val->event->type, wild, name,
02420                                            rdataset, &exists, &data, NULL,
02421                                            validator_log, val)
02422                                        == ISC_R_SUCCESS)
02423                 {
02424                         dns_name_t **proofs = val->event->proofs;
02425                         if (exists && !data)
02426                                 val->attributes |= VALATTR_FOUNDNODATA;
02427                         if (exists && !data && NEEDNODATA(val))
02428                                 proofs[DNS_VALIDATOR_NODATAPROOF] =
02429                                                  name;
02430                         if (!exists)
02431                                 val->attributes |=
02432                                          VALATTR_FOUNDNOWILDCARD;
02433                         if (!exists && NEEDNOQNAME(val))
02434                                 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
02435                                                  name;
02436                         if (dns_rdataset_isassociated(&trdataset))
02437                                 dns_rdataset_disassociate(&trdataset);
02438                         return (ISC_R_SUCCESS);
02439                 }
02440 
02441                 if (rdataset->type == dns_rdatatype_nsec3 &&
02442                     (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
02443                     !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
02444                     dns_nsec3_noexistnodata(val->event->type, wild, name,
02445                                             rdataset, zonename, &exists, &data,
02446                                             NULL, NULL, NULL, NULL, NULL, NULL,
02447                                             validator_log, val)
02448                                             == ISC_R_SUCCESS)
02449                 {
02450                         dns_name_t **proofs = val->event->proofs;
02451                         if (exists && !data)
02452                                 val->attributes |= VALATTR_FOUNDNODATA;
02453                         if (exists && !data && NEEDNODATA(val))
02454                                 proofs[DNS_VALIDATOR_NODATAPROOF] =
02455                                                  name;
02456                         if (!exists)
02457                                 val->attributes |=
02458                                          VALATTR_FOUNDNOWILDCARD;
02459                         if (!exists && NEEDNOQNAME(val))
02460                                 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
02461                                                  name;
02462                         if (dns_rdataset_isassociated(&trdataset))
02463                                 dns_rdataset_disassociate(&trdataset);
02464                         return (ISC_R_SUCCESS);
02465                 }
02466         }
02467         if (result == ISC_R_NOMORE)
02468                 result = ISC_R_SUCCESS;
02469         if (dns_rdataset_isassociated(&trdataset))
02470                 dns_rdataset_disassociate(&trdataset);
02471         return (result);
02472 }
02473 
02474 static isc_result_t
02475 findnsec3proofs(dns_validator_t *val) {
02476         dns_name_t *name, tname;
02477         isc_result_t result;
02478         isc_boolean_t exists, data, optout, unknown;
02479         isc_boolean_t setclosest, setnearest, *setclosestp;
02480         dns_fixedname_t fclosest, fnearest, fzonename;
02481         dns_name_t *closest, *nearest, *zonename, *closestp;
02482         dns_name_t **proofs = val->event->proofs;
02483         dns_rdataset_t *rdataset, trdataset;
02484 
02485         dns_name_init(&tname, NULL);
02486         dns_rdataset_init(&trdataset);
02487         dns_fixedname_init(&fclosest);
02488         dns_fixedname_init(&fnearest);
02489         dns_fixedname_init(&fzonename);
02490         closest = dns_fixedname_name(&fclosest);
02491         nearest = dns_fixedname_name(&fnearest);
02492         zonename = dns_fixedname_name(&fzonename);
02493 
02494         if (val->event->message == NULL) {
02495                 name = &tname;
02496                 rdataset = &trdataset;
02497         } else {
02498                 name = NULL;
02499                 rdataset = NULL;
02500         }
02501 
02502         for (result = val_rdataset_first(val, &name, &rdataset);
02503              result == ISC_R_SUCCESS;
02504              result = val_rdataset_next(val, &name, &rdataset))
02505         {
02506                 if (rdataset->type != dns_rdatatype_nsec3 ||
02507                     rdataset->trust != dns_trust_secure)
02508                         continue;
02509 
02510                 result = dns_nsec3_noexistnodata(val->event->type,
02511                                                  val->event->name, name,
02512                                                  rdataset, zonename, NULL,
02513                                                  NULL, NULL, NULL, NULL, NULL,
02514                                                  NULL, NULL, validator_log,
02515                                                  val);
02516                 if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS) {
02517                         if (dns_rdataset_isassociated(&trdataset))
02518                                 dns_rdataset_disassociate(&trdataset);
02519                         return (result);
02520                 }
02521         }
02522         if (result != ISC_R_NOMORE)
02523                 result = ISC_R_SUCCESS;
02524         POST(result);
02525 
02526         if (dns_name_countlabels(zonename) == 0)
02527                 return (ISC_R_SUCCESS);
02528 
02529         /*
02530          * If the val->closest is set then we want to use it otherwise
02531          * we need to discover it.
02532          */
02533         if (dns_name_countlabels(dns_fixedname_name(&val->closest)) != 0) {
02534                 char namebuf[DNS_NAME_FORMATSIZE];
02535 
02536                 dns_name_format(dns_fixedname_name(&val->closest),
02537                                  namebuf, sizeof(namebuf));
02538                 validator_log(val, ISC_LOG_DEBUG(3), "closest encloser from "
02539                               "wildcard signature '%s'", namebuf);
02540                 dns_name_copy(dns_fixedname_name(&val->closest), closest, NULL);
02541                 closestp = NULL;
02542                 setclosestp = NULL;
02543         } else {
02544                 closestp = closest;
02545                 setclosestp = &setclosest;
02546         }
02547 
02548         for (result = val_rdataset_first(val, &name, &rdataset);
02549              result == ISC_R_SUCCESS;
02550              result = val_rdataset_next(val, &name, &rdataset))
02551         {
02552                 if (rdataset->type != dns_rdatatype_nsec3 ||
02553                     rdataset->trust != dns_trust_secure)
02554                         continue;
02555 
02556                 /*
02557                  * We process all NSEC3 records to find the closest
02558                  * encloser and nearest name to the closest encloser.
02559                  */
02560                 setclosest = setnearest = ISC_FALSE;
02561                 optout = ISC_FALSE;
02562                 unknown = ISC_FALSE;
02563                 result = dns_nsec3_noexistnodata(val->event->type,
02564                                                  val->event->name,
02565                                                  name, rdataset, zonename,
02566                                                  &exists, &data, &optout,
02567                                                  &unknown, setclosestp,
02568                                                  &setnearest, closestp,
02569                                                  nearest, validator_log, val);
02570                 if (unknown)
02571                         val->attributes |= VALATTR_FOUNDUNKNOWN;
02572                 if (result != ISC_R_SUCCESS)
02573                         continue;
02574                 if (setclosest)
02575                         proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
02576                 if (exists && !data && NEEDNODATA(val)) {
02577                         val->attributes |= VALATTR_FOUNDNODATA;
02578                         proofs[DNS_VALIDATOR_NODATAPROOF] = name;
02579                 }
02580                 if (!exists && setnearest) {
02581                         val->attributes |= VALATTR_FOUNDNOQNAME;
02582                         proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name;
02583                         if (optout)
02584                                 val->attributes |= VALATTR_FOUNDOPTOUT;
02585                 }
02586         }
02587         if (result == ISC_R_NOMORE)
02588                 result = ISC_R_SUCCESS;
02589 
02590         /*
02591          * To know we have a valid noqname and optout proofs we need to also
02592          * have a valid closest encloser.  Otherwise we could still be looking
02593          * at proofs from the parent zone.
02594          */
02595         if (dns_name_countlabels(closest) > 0 &&
02596             dns_name_countlabels(nearest) ==
02597             dns_name_countlabels(closest) + 1 &&
02598             dns_name_issubdomain(nearest, closest))
02599         {
02600                 val->attributes |= VALATTR_FOUNDCLOSEST;
02601                 result = dns_name_concatenate(dns_wildcardname, closest,
02602                                               dns_fixedname_name(&val->wild),
02603                                               NULL);
02604                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
02605         } else {
02606                 val->attributes &= ~VALATTR_FOUNDNOQNAME;
02607                 val->attributes &= ~VALATTR_FOUNDOPTOUT;
02608                 proofs[DNS_VALIDATOR_NOQNAMEPROOF] = NULL;
02609         }
02610 
02611         /*
02612          * Do we need to check for the wildcard?
02613          */
02614         if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
02615             ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
02616                 result = checkwildcard(val, dns_rdatatype_nsec3, zonename);
02617                 if (result != ISC_R_SUCCESS)
02618                         return (result);
02619         }
02620         return (result);
02621 }
02622 
02623 /*%
02624  * Validate the authority section records.
02625  */
02626 static isc_result_t
02627 validate_authority(dns_validator_t *val, isc_boolean_t resume) {
02628         dns_name_t *name;
02629         dns_message_t *message = val->event->message;
02630         isc_result_t result;
02631 
02632         if (!resume)
02633                 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
02634         else
02635                 result = ISC_R_SUCCESS;
02636 
02637         for (;
02638              result == ISC_R_SUCCESS;
02639              result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
02640         {
02641                 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
02642 
02643                 name = NULL;
02644                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
02645                 if (resume) {
02646                         rdataset = ISC_LIST_NEXT(val->currentset, link);
02647                         val->currentset = NULL;
02648                         resume = ISC_FALSE;
02649                 } else
02650                         rdataset = ISC_LIST_HEAD(name->list);
02651 
02652                 for (;
02653                      rdataset != NULL;
02654                      rdataset = ISC_LIST_NEXT(rdataset, link))
02655                 {
02656                         if (rdataset->type == dns_rdatatype_rrsig)
02657                                 continue;
02658 
02659                         for (sigrdataset = ISC_LIST_HEAD(name->list);
02660                              sigrdataset != NULL;
02661                              sigrdataset = ISC_LIST_NEXT(sigrdataset,
02662                                                          link))
02663                         {
02664                                 if (sigrdataset->type == dns_rdatatype_rrsig &&
02665                                     sigrdataset->covers == rdataset->type)
02666                                         break;
02667                         }
02668                         /*
02669                          * If a signed zone is missing the zone key, bad
02670                          * things could happen.  A query for data in the zone
02671                          * would lead to a query for the zone key, which
02672                          * would return a negative answer, which would contain
02673                          * an SOA and an NSEC signed by the missing key, which
02674                          * would trigger another query for the DNSKEY (since
02675                          * the first one is still in progress), and go into an
02676                          * infinite loop.  Avoid that.
02677                          */
02678                         if (val->event->type == dns_rdatatype_dnskey &&
02679                             rdataset->type == dns_rdatatype_nsec &&
02680                             dns_name_equal(name, val->event->name))
02681                         {
02682                                 dns_rdata_t nsec = DNS_RDATA_INIT;
02683 
02684                                 result = dns_rdataset_first(rdataset);
02685                                 if (result != ISC_R_SUCCESS)
02686                                         return (result);
02687                                 dns_rdataset_current(rdataset, &nsec);
02688                                 if (dns_nsec_typepresent(&nsec,
02689                                                         dns_rdatatype_soa))
02690                                         continue;
02691                         }
02692                         val->currentset = rdataset;
02693                         result = create_validator(val, name, rdataset->type,
02694                                                   rdataset, sigrdataset,
02695                                                   authvalidated,
02696                                                   "validate_authority");
02697                         if (result != ISC_R_SUCCESS)
02698                                 return (result);
02699                         val->authcount++;
02700                         return (DNS_R_WAIT);
02701                 }
02702         }
02703         if (result == ISC_R_NOMORE)
02704                 result = ISC_R_SUCCESS;
02705         return (result);
02706 }
02707 
02708 /*%
02709  * Validate the ncache elements.
02710  */
02711 static isc_result_t
02712 validate_ncache(dns_validator_t *val, isc_boolean_t resume) {
02713         dns_name_t *name;
02714         isc_result_t result;
02715 
02716         if (!resume)
02717                 result = dns_rdataset_first(val->event->rdataset);
02718         else
02719                 result = dns_rdataset_next(val->event->rdataset);
02720 
02721         for (;
02722              result == ISC_R_SUCCESS;
02723              result = dns_rdataset_next(val->event->rdataset))
02724         {
02725                 dns_rdataset_t *rdataset, *sigrdataset = NULL;
02726 
02727                 if (dns_rdataset_isassociated(&val->frdataset))
02728                         dns_rdataset_disassociate(&val->frdataset);
02729                 if (dns_rdataset_isassociated(&val->fsigrdataset))
02730                         dns_rdataset_disassociate(&val->fsigrdataset);
02731 
02732                 dns_fixedname_init(&val->fname);
02733                 name = dns_fixedname_name(&val->fname);
02734                 rdataset = &val->frdataset;
02735                 dns_ncache_current(val->event->rdataset, name, rdataset);
02736 
02737                 if (val->frdataset.type == dns_rdatatype_rrsig)
02738                         continue;
02739 
02740                 result = dns_ncache_getsigrdataset(val->event->rdataset, name,
02741                                                    rdataset->type,
02742                                                    &val->fsigrdataset);
02743                 if (result == ISC_R_SUCCESS)
02744                         sigrdataset = &val->fsigrdataset;
02745 
02746                 /*
02747                  * If a signed zone is missing the zone key, bad
02748                  * things could happen.  A query for data in the zone
02749                  * would lead to a query for the zone key, which
02750                  * would return a negative answer, which would contain
02751                  * an SOA and an NSEC signed by the missing key, which
02752                  * would trigger another query for the DNSKEY (since
02753                  * the first one is still in progress), and go into an
02754                  * infinite loop.  Avoid that.
02755                  */
02756                 if (val->event->type == dns_rdatatype_dnskey &&
02757                     rdataset->type == dns_rdatatype_nsec &&
02758                     dns_name_equal(name, val->event->name))
02759                 {
02760                         dns_rdata_t nsec = DNS_RDATA_INIT;
02761 
02762                         result = dns_rdataset_first(rdataset);
02763                         if (result != ISC_R_SUCCESS)
02764                                 return (result);
02765                         dns_rdataset_current(rdataset, &nsec);
02766                         if (dns_nsec_typepresent(&nsec,
02767                                                 dns_rdatatype_soa))
02768                                 continue;
02769                 }
02770                 val->currentset = rdataset;
02771                 result = create_validator(val, name, rdataset->type,
02772                                           rdataset, sigrdataset,
02773                                           authvalidated,
02774                                           "validate_ncache");
02775                 if (result != ISC_R_SUCCESS)
02776                         return (result);
02777                 val->authcount++;
02778                 return (DNS_R_WAIT);
02779         }
02780         if (result == ISC_R_NOMORE)
02781                 result = ISC_R_SUCCESS;
02782         return (result);
02783 }
02784 
02785 /*%
02786  * Prove a negative answer is good or that there is a NOQNAME when the
02787  * answer is from a wildcard.
02788  *
02789  * Loop through the authority section looking for NODATA, NOWILDCARD
02790  * and NOQNAME proofs in the NSEC records by calling authvalidated().
02791  *
02792  * If the required proofs are found we are done.
02793  *
02794  * If the proofs are not found attempt to prove this is a unsecure
02795  * response.
02796  */
02797 static isc_result_t
02798 nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
02799         isc_result_t result;
02800 
02801         if (resume)
02802                 validator_log(val, ISC_LOG_DEBUG(3), "resuming nsecvalidate");
02803 
02804         if (val->event->message == NULL)
02805                 result = validate_ncache(val, resume);
02806         else
02807                 result = validate_authority(val, resume);
02808 
02809         if (result != ISC_R_SUCCESS)
02810                 return (result);
02811 
02812         /*
02813          * Do we only need to check for NOQNAME?  To get here we must have
02814          * had a secure wildcard answer.
02815          */
02816         if (!NEEDNODATA(val) && !NEEDNOWILDCARD(val) && NEEDNOQNAME(val)) {
02817                 if (!FOUNDNOQNAME(val))
02818                         findnsec3proofs(val);
02819                 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
02820                     !FOUNDOPTOUT(val)) {
02821                         validator_log(val, ISC_LOG_DEBUG(3),
02822                                       "marking as secure, noqname proof found");
02823                         marksecure(val->event);
02824                         return (ISC_R_SUCCESS);
02825                 } else if (FOUNDOPTOUT(val) &&
02826                            dns_name_countlabels(dns_fixedname_name(&val->wild))
02827                                          != 0) {
02828                         validator_log(val, ISC_LOG_DEBUG(3),
02829                                       "optout proof found");
02830                         val->event->optout = ISC_TRUE;
02831                         markanswer(val, "nsecvalidate (1)");
02832                         return (ISC_R_SUCCESS);
02833                 } else if ((val->attributes & VALATTR_FOUNDUNKNOWN) != 0) {
02834                         validator_log(val, ISC_LOG_DEBUG(3),
02835                                       "unknown NSEC3 hash algorithm found");
02836                         markanswer(val, "nsecvalidate (2)");
02837                         return (ISC_R_SUCCESS);
02838                 }
02839                 validator_log(val, ISC_LOG_DEBUG(3),
02840                               "noqname proof not found");
02841                 return (DNS_R_NOVALIDNSEC);
02842         }
02843 
02844         if (!FOUNDNOQNAME(val) && !FOUNDNODATA(val))
02845                 findnsec3proofs(val);
02846 
02847         /*
02848          * Do we need to check for the wildcard?
02849          */
02850         if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
02851             ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
02852                 result = checkwildcard(val, dns_rdatatype_nsec, NULL);
02853                 if (result != ISC_R_SUCCESS)
02854                         return (result);
02855         }
02856 
02857         if ((NEEDNODATA(val) && (FOUNDNODATA(val) || FOUNDOPTOUT(val))) ||
02858             (NEEDNOQNAME(val) && FOUNDNOQNAME(val) &&
02859              NEEDNOWILDCARD(val) && FOUNDNOWILDCARD(val) &&
02860              FOUNDCLOSEST(val))) {
02861                 if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
02862                         val->event->optout = ISC_TRUE;
02863                 validator_log(val, ISC_LOG_DEBUG(3),
02864                               "nonexistence proof(s) found");
02865                 if (val->event->message == NULL)
02866                         marksecure(val->event);
02867                 else
02868                         val->event->secure = ISC_TRUE;
02869                 return (ISC_R_SUCCESS);
02870         }
02871 
02872         if (val->authfail != 0 && val->authcount == val->authfail)
02873                 return (DNS_R_BROKENCHAIN);
02874         validator_log(val, ISC_LOG_DEBUG(3),
02875                       "nonexistence proof(s) not found");
02876         val->attributes |= VALATTR_INSECURITY;
02877         return (proveunsecure(val, ISC_FALSE, ISC_FALSE));
02878 }
02879 
02880 static isc_boolean_t
02881 check_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) {
02882         dns_rdata_t dsrdata = DNS_RDATA_INIT;
02883         dns_rdata_ds_t ds;
02884         isc_result_t result;
02885 
02886         for (result = dns_rdataset_first(rdataset);
02887              result == ISC_R_SUCCESS;
02888              result = dns_rdataset_next(rdataset)) {
02889                 dns_rdataset_current(rdataset, &dsrdata);
02890                 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
02891                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
02892 
02893                 if (dns_resolver_ds_digest_supported(val->view->resolver,
02894                                                      name, ds.digest_type) &&
02895                     dns_resolver_algorithm_supported(val->view->resolver,
02896                                                      name, ds.algorithm)) {
02897                         dns_rdata_reset(&dsrdata);
02898                         return (ISC_TRUE);
02899                 }
02900                 dns_rdata_reset(&dsrdata);
02901         }
02902         return (ISC_FALSE);
02903 }
02904 
02905 static void
02906 dlvvalidated(isc_task_t *task, isc_event_t *event) {
02907         dns_validatorevent_t *devent;
02908         dns_validator_t *val;
02909         isc_result_t eresult;
02910         isc_boolean_t want_destroy;
02911 
02912         UNUSED(task);
02913         INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
02914 
02915         devent = (dns_validatorevent_t *)event;
02916         val = devent->ev_arg;
02917         eresult = devent->result;
02918 
02919         isc_event_free(&event);
02920         dns_validator_destroy(&val->subvalidator);
02921 
02922         INSIST(val->event != NULL);
02923 
02924         validator_log(val, ISC_LOG_DEBUG(3), "in dlvvalidated");
02925         LOCK(&val->lock);
02926         if (CANCELED(val)) {
02927                 validator_done(val, ISC_R_CANCELED);
02928         } else if (eresult == ISC_R_SUCCESS) {
02929                 validator_log(val, ISC_LOG_DEBUG(3),
02930                               "dlvset with trust %s",
02931                               dns_trust_totext(val->frdataset.trust));
02932                 dns_rdataset_clone(&val->frdataset, &val->dlv);
02933                 val->havedlvsep = ISC_TRUE;
02934                 if (dlv_algorithm_supported(val))
02935                         dlv_validator_start(val);
02936                 else {
02937                         markanswer(val, "dlvvalidated");
02938                         validator_done(val, ISC_R_SUCCESS);
02939                 }
02940         } else {
02941                 if (eresult != DNS_R_BROKENCHAIN) {
02942                         if (dns_rdataset_isassociated(&val->frdataset))
02943                                 dns_rdataset_expire(&val->frdataset);
02944                         if (dns_rdataset_isassociated(&val->fsigrdataset))
02945                                 dns_rdataset_expire(&val->fsigrdataset);
02946                 }
02947                 validator_log(val, ISC_LOG_DEBUG(3),
02948                               "dlvvalidated: got %s",
02949                               isc_result_totext(eresult));
02950                 validator_done(val, DNS_R_BROKENCHAIN);
02951         }
02952         want_destroy = exit_check(val);
02953         UNLOCK(&val->lock);
02954         if (want_destroy)
02955                 destroy(val);
02956 }
02957 
02958 /*%
02959  * Callback from fetching a DLV record.
02960  *
02961  * Resumes the DLV lookup process.
02962  */
02963 static void
02964 dlvfetched(isc_task_t *task, isc_event_t *event) {
02965         char namebuf[DNS_NAME_FORMATSIZE];
02966         dns_fetchevent_t *devent;
02967         dns_validator_t *val;
02968         isc_boolean_t want_destroy;
02969         isc_result_t eresult;
02970         isc_result_t result;
02971         dns_fetch_t *fetch;
02972 
02973         UNUSED(task);
02974         INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
02975         devent = (dns_fetchevent_t *)event;
02976         val = devent->ev_arg;
02977         eresult = devent->result;
02978 
02979         /* Free resources which are not of interest. */
02980         if (devent->node != NULL)
02981                 dns_db_detachnode(devent->db, &devent->node);
02982         if (devent->db != NULL)
02983                 dns_db_detach(&devent->db);
02984         if (dns_rdataset_isassociated(&val->fsigrdataset))
02985                 dns_rdataset_disassociate(&val->fsigrdataset);
02986         isc_event_free(&event);
02987 
02988         INSIST(val->event != NULL);
02989         validator_log(val, ISC_LOG_DEBUG(3), "in dlvfetched: %s",
02990                       dns_result_totext(eresult));
02991 
02992         LOCK(&val->lock);
02993         fetch = val->fetch;
02994         val->fetch = NULL;
02995         if (eresult == ISC_R_SUCCESS) {
02996                 dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
02997                                 sizeof(namebuf));
02998                 dns_rdataset_clone(&val->frdataset, &val->dlv);
02999                 val->havedlvsep = ISC_TRUE;
03000                 if (dlv_algorithm_supported(val)) {
03001                         validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found",
03002                                       namebuf);
03003                         dlv_validator_start(val);
03004                 } else {
03005                         validator_log(val, ISC_LOG_DEBUG(3),
03006                                       "DLV %s found with no supported algorithms",
03007                                       namebuf);
03008                         markanswer(val, "dlvfetched (1)");
03009                         validator_done(val, ISC_R_SUCCESS);
03010                 }
03011         } else if (eresult == DNS_R_NXRRSET ||
03012                    eresult == DNS_R_NXDOMAIN ||
03013                    eresult == DNS_R_NCACHENXRRSET ||
03014                    eresult == DNS_R_NCACHENXDOMAIN) {
03015                 result = finddlvsep(val, ISC_TRUE);
03016                 if (result == ISC_R_SUCCESS) {
03017                         if (dlv_algorithm_supported(val)) {
03018                                 dns_name_format(dns_fixedname_name(&val->dlvsep),
03019                                                 namebuf, sizeof(namebuf));
03020                                 validator_log(val, ISC_LOG_DEBUG(3),
03021                                               "DLV %s found", namebuf);
03022                                 dlv_validator_start(val);
03023                         } else {
03024                                 validator_log(val, ISC_LOG_DEBUG(3),
03025                                               "DLV %s found with no supported "
03026                                               "algorithms", namebuf);
03027                                 markanswer(val, "dlvfetched (2)");
03028                                 validator_done(val, ISC_R_SUCCESS);
03029                         }
03030                 } else if (result == ISC_R_NOTFOUND) {
03031                         validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
03032                         markanswer(val, "dlvfetched (3)");
03033                         validator_done(val, ISC_R_SUCCESS);
03034                 } else {
03035                         validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
03036                                       dns_result_totext(result));
03037                         if (result != DNS_R_WAIT)
03038                                 validator_done(val, result);
03039                 }
03040         } else {
03041                 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
03042                               dns_result_totext(eresult));
03043                 validator_done(val, eresult);
03044         }
03045         want_destroy = exit_check(val);
03046         UNLOCK(&val->lock);
03047         if (fetch != NULL)
03048                 dns_resolver_destroyfetch(&fetch);
03049         if (want_destroy)
03050                 destroy(val);
03051 }
03052 
03053 /*%
03054  * Start the DLV lookup process.
03055  *
03056  * Returns
03057  * \li  ISC_R_SUCCESS
03058  * \li  DNS_R_WAIT
03059  * \li  Others on validation failures.
03060  */
03061 static isc_result_t
03062 startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) {
03063         char namebuf[DNS_NAME_FORMATSIZE];
03064         isc_result_t result;
03065 
03066         INSIST(!DLVTRIED(val));
03067 
03068         val->attributes |= VALATTR_DLVTRIED;
03069 
03070         dns_name_format(unsecure, namebuf, sizeof(namebuf));
03071         validator_log(val, ISC_LOG_DEBUG(3),
03072                       "plain DNSSEC returns unsecure (%s): looking for DLV",
03073                       namebuf);
03074 
03075         if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
03076                 validator_log(val, ISC_LOG_WARNING, "must be secure failure, "
03077                               " %s is under DLV (startfinddlvsep)", namebuf);
03078                 return (DNS_R_MUSTBESECURE);
03079         }
03080 
03081         val->dlvlabels = dns_name_countlabels(unsecure) - 1;
03082         result = finddlvsep(val, ISC_FALSE);
03083         if (result == ISC_R_NOTFOUND) {
03084                 validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
03085                 markanswer(val, "startfinddlvsep (1)");
03086                 return (ISC_R_SUCCESS);
03087         }
03088         if (result == DNS_R_NTACOVERED) {
03089                 validator_log(val, ISC_LOG_DEBUG(3), "DLV covered by NTA");
03090                 validator_done(val, ISC_R_SUCCESS);
03091                 return (ISC_R_SUCCESS);
03092         }
03093         if (result != ISC_R_SUCCESS) {
03094                 validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
03095                               dns_result_totext(result));
03096                 return (result);
03097         }
03098         dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
03099                         sizeof(namebuf));
03100         if (dlv_algorithm_supported(val)) {
03101                 validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf);
03102                 dlv_validator_start(val);
03103                 return (DNS_R_WAIT);
03104         }
03105         validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found with no supported "
03106                       "algorithms", namebuf);
03107         markanswer(val, "startfinddlvsep (2)");
03108         validator_done(val, ISC_R_SUCCESS);
03109         return (ISC_R_SUCCESS);
03110 }
03111 
03112 /*%
03113  * Continue the DLV lookup process.
03114  *
03115  * Returns
03116  * \li  ISC_R_SUCCESS
03117  * \li  ISC_R_NOTFOUND
03118  * \li  DNS_R_WAIT
03119  * \li  Others on validation failure.
03120  */
03121 static isc_result_t
03122 finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
03123         char namebuf[DNS_NAME_FORMATSIZE];
03124         dns_fixedname_t dlvfixed;
03125         dns_name_t *dlvname;
03126         dns_name_t *dlvsep;
03127         dns_name_t noroot;
03128         isc_result_t result;
03129         unsigned int labels;
03130 
03131         INSIST(val->view->dlv != NULL);
03132 
03133         if (!resume) {
03134                 if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
03135                         dns_name_format(val->event->name, namebuf,
03136                                         sizeof(namebuf));
03137                         validator_log(val, ISC_LOG_WARNING,
03138                                       "must be secure failure, "
03139                                       "%s is under DLV (finddlvsep)", namebuf);
03140                         return (DNS_R_MUSTBESECURE);
03141                 }
03142 
03143                 dns_fixedname_init(&val->dlvsep);
03144                 dlvsep = dns_fixedname_name(&val->dlvsep);
03145                 dns_name_copy(val->event->name, dlvsep, NULL);
03146                 /*
03147                  * If this is a response to a DS query, we need to look in
03148                  * the parent zone for the trust anchor.
03149                  */
03150                 if (val->event->type == dns_rdatatype_ds) {
03151                         labels = dns_name_countlabels(dlvsep);
03152                         if (labels == 0)
03153                                 return (ISC_R_NOTFOUND);
03154                         dns_name_getlabelsequence(dlvsep, 1, labels - 1,
03155                                                   dlvsep);
03156                 }
03157         } else {
03158                 dlvsep = dns_fixedname_name(&val->dlvsep);
03159                 labels = dns_name_countlabels(dlvsep);
03160                 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
03161         }
03162         dns_name_init(&noroot, NULL);
03163         dns_fixedname_init(&dlvfixed);
03164         dlvname = dns_fixedname_name(&dlvfixed);
03165         labels = dns_name_countlabels(dlvsep);
03166         if (labels == 0)
03167                 return (ISC_R_NOTFOUND);
03168         dns_name_getlabelsequence(dlvsep, 0, labels - 1, &noroot);
03169         result = dns_name_concatenate(&noroot, val->view->dlv, dlvname, NULL);
03170         while (result == ISC_R_NOSPACE) {
03171                 labels = dns_name_countlabels(dlvsep);
03172                 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
03173                 dns_name_getlabelsequence(dlvsep, 0, labels - 2, &noroot);
03174                 result = dns_name_concatenate(&noroot, val->view->dlv,
03175                                               dlvname, NULL);
03176         }
03177         if (result != ISC_R_SUCCESS) {
03178                 validator_log(val, ISC_LOG_DEBUG(2), "DLV concatenate failed");
03179                 return (DNS_R_NOVALIDSIG);
03180         }
03181 
03182         if (((val->options & DNS_VALIDATOR_NONTA) == 0) &&
03183             dns_view_ntacovers(val->view, val->start, dlvname, val->view->dlv))
03184                 return (DNS_R_NTACOVERED);
03185 
03186         while (dns_name_countlabels(dlvname) >=
03187                dns_name_countlabels(val->view->dlv) + val->dlvlabels) {
03188                 dns_name_format(dlvname, namebuf, sizeof(namebuf));
03189                 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV %s",
03190                               namebuf);
03191                 result = view_find(val, dlvname, dns_rdatatype_dlv);
03192                 if (result == ISC_R_SUCCESS) {
03193                         if (DNS_TRUST_PENDING(val->frdataset.trust) &&
03194                             dns_rdataset_isassociated(&val->fsigrdataset))
03195                         {
03196                                 dns_fixedname_init(&val->fname);
03197                                 dns_name_copy(dlvname,
03198                                               dns_fixedname_name(&val->fname),
03199                                               NULL);
03200                                 result = create_validator(val,
03201                                                 dns_fixedname_name(&val->fname),
03202                                                           dns_rdatatype_dlv,
03203                                                           &val->frdataset,
03204                                                           &val->fsigrdataset,
03205                                                           dlvvalidated,
03206                                                           "finddlvsep");
03207                                 if (result != ISC_R_SUCCESS)
03208                                         return (result);
03209                                 return (DNS_R_WAIT);
03210                         }
03211                         if (val->frdataset.trust < dns_trust_secure) {
03212                                 validator_log(val, ISC_LOG_DEBUG(3),
03213                                               "DLV not validated");
03214                                 return (DNS_R_NOVALIDSIG);
03215                         }
03216                         val->havedlvsep = ISC_TRUE;
03217                         dns_rdataset_clone(&val->frdataset, &val->dlv);
03218                         return (ISC_R_SUCCESS);
03219                 }
03220                 if (result == ISC_R_NOTFOUND) {
03221                         result = create_fetch(val, dlvname, dns_rdatatype_dlv,
03222                                               dlvfetched, "finddlvsep");
03223                         if (result != ISC_R_SUCCESS)
03224                                 return (result);
03225                         return (DNS_R_WAIT);
03226                 }
03227                 if (result != DNS_R_NXRRSET &&
03228                     result != DNS_R_NXDOMAIN &&
03229                     result != DNS_R_EMPTYNAME &&
03230                     result != DNS_R_NCACHENXRRSET &&
03231                     result != DNS_R_NCACHENXDOMAIN)
03232                         return (result);
03233                 /*
03234                  * Strip first labels from both dlvsep and dlvname.
03235                  */
03236                 labels = dns_name_countlabels(dlvsep);
03237                 if (labels == 0)
03238                         break;
03239                 dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
03240                 labels = dns_name_countlabels(dlvname);
03241                 dns_name_getlabelsequence(dlvname, 1, labels - 1, dlvname);
03242         }
03243         return (ISC_R_NOTFOUND);
03244 }
03245 
03246 /*%
03247  * proveunsecure walks down from the SEP looking for a break in the
03248  * chain of trust.  That occurs when we can prove the DS record does
03249  * not exist at a delegation point or the DS exists at a delegation
03250  * but we don't support the algorithm/digest.
03251  *
03252  * If DLV is active and we look for a DLV record at or below the
03253  * point we go insecure.  If found we restart the validation process.
03254  * If not found or DLV isn't active we mark the response as a answer.
03255  *
03256  * Returns:
03257  * \li  ISC_R_SUCCESS           val->event->name is in a unsecure zone
03258  * \li  DNS_R_WAIT              validation is in progress.
03259  * \li  DNS_R_MUSTBESECURE      val->event->name is supposed to be secure
03260  *                              (policy) but we proved that it is unsecure.
03261  * \li  DNS_R_NOVALIDSIG
03262  * \li  DNS_R_NOVALIDNSEC
03263  * \li  DNS_R_NOTINSECURE
03264  * \li  DNS_R_BROKENCHAIN
03265  */
03266 static isc_result_t
03267 proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
03268 {
03269         isc_result_t result;
03270         dns_fixedname_t fixedsecroot;
03271         dns_name_t *secroot;
03272         dns_name_t *tname;
03273         char namebuf[DNS_NAME_FORMATSIZE];
03274         dns_name_t *found;
03275         dns_fixedname_t fixedfound;
03276 
03277         dns_fixedname_init(&fixedsecroot);
03278         secroot = dns_fixedname_name(&fixedsecroot);
03279         dns_fixedname_init(&fixedfound);
03280         found = dns_fixedname_name(&fixedfound);
03281         if (val->havedlvsep)
03282                 dns_name_copy(dns_fixedname_name(&val->dlvsep), secroot, NULL);
03283         else {
03284                 unsigned int labels;
03285                 dns_name_copy(val->event->name, secroot, NULL);
03286                 /*
03287                  * If this is a response to a DS query, we need to look in
03288                  * the parent zone for the trust anchor.
03289                  */
03290 
03291                 labels = dns_name_countlabels(secroot);
03292                 if (val->event->type == dns_rdatatype_ds && labels > 1U)
03293                         dns_name_getlabelsequence(secroot, 1, labels - 1,
03294                                                   secroot);
03295                 result = dns_keytable_finddeepestmatch(val->keytable,
03296                                                        secroot, secroot);
03297                 if (result == ISC_R_NOTFOUND) {
03298                         if (val->mustbesecure) {
03299                                 validator_log(val, ISC_LOG_WARNING,
03300                                               "must be secure failure, "
03301                                               "not beneath secure root");
03302                                 result = DNS_R_MUSTBESECURE;
03303                                 goto out;
03304                         } else
03305                                 validator_log(val, ISC_LOG_DEBUG(3),
03306                                               "not beneath secure root");
03307                         if (val->view->dlv == NULL || DLVTRIED(val)) {
03308                                 markanswer(val, "proveunsecure (1)");
03309                                 return (ISC_R_SUCCESS);
03310                         }
03311                         return (startfinddlvsep(val, dns_rootname));
03312                 } else if (result != ISC_R_SUCCESS)
03313                         return (result);
03314         }
03315 
03316         if (!resume) {
03317                 /*
03318                  * We are looking for breaks below the SEP so add a label.
03319                  */
03320                 val->labels = dns_name_countlabels(secroot) + 1;
03321         } else {
03322                 validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
03323                 /*
03324                  * If we have a DS rdataset and it is secure then check if
03325                  * the DS rdataset has a supported algorithm combination.
03326                  * If not this is an insecure delegation as far as this
03327                  * resolver is concerned.  Fall back to DLV if available.
03328                  */
03329                 if (have_ds && val->frdataset.trust >= dns_trust_secure &&
03330                     !check_ds(val, dns_fixedname_name(&val->fname),
03331                               &val->frdataset)) {
03332                         dns_name_format(dns_fixedname_name(&val->fname),
03333                                         namebuf, sizeof(namebuf));
03334                         if ((val->view->dlv == NULL || DLVTRIED(val)) &&
03335                             val->mustbesecure) {
03336                                 validator_log(val, ISC_LOG_WARNING,
03337                                               "must be secure failure at '%s', "
03338                                               "can't fall back to DLV",
03339                                               namebuf);
03340                                 result = DNS_R_MUSTBESECURE;
03341                                 goto out;
03342                         }
03343                         validator_log(val, ISC_LOG_DEBUG(3),
03344                                       "no supported algorithm/digest (%s/DS)",
03345                                       namebuf);
03346                         if (val->view->dlv == NULL || DLVTRIED(val)) {
03347                                 markanswer(val, "proveunsecure (2)");
03348                                 result = ISC_R_SUCCESS;
03349                                 goto out;
03350                         }
03351                         return(startfinddlvsep(val,
03352                                               dns_fixedname_name(&val->fname)));
03353                 }
03354                 val->labels++;
03355         }
03356 
03357         for (;
03358              val->labels <= dns_name_countlabels(val->event->name);
03359              val->labels++)
03360         {
03361 
03362                 dns_fixedname_init(&val->fname);
03363                 tname = dns_fixedname_name(&val->fname);
03364                 if (val->labels == dns_name_countlabels(val->event->name))
03365                         dns_name_copy(val->event->name, tname, NULL);
03366                 else
03367                         dns_name_split(val->event->name, val->labels,
03368                                        NULL, tname);
03369 
03370                 dns_name_format(tname, namebuf, sizeof(namebuf));
03371                 validator_log(val, ISC_LOG_DEBUG(3),
03372                               "checking existence of DS at '%s'",
03373                               namebuf);
03374 
03375                 result = view_find(val, tname, dns_rdatatype_ds);
03376                 if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
03377                         /*
03378                          * There is no DS.  If this is a delegation,
03379                          * we may be done.
03380                          */
03381                         /*
03382                          * If we have "trust == answer" then this namespace
03383                          * has switched from insecure to should be secure.
03384                          */
03385                         if (DNS_TRUST_PENDING(val->frdataset.trust) ||
03386                             DNS_TRUST_ANSWER(val->frdataset.trust)) {
03387                                 result = create_validator(val, tname,
03388                                                           dns_rdatatype_ds,
03389                                                           &val->frdataset,
03390                                                           NULL, dsvalidated,
03391                                                           "proveunsecure");
03392                                 if (result != ISC_R_SUCCESS)
03393                                         goto out;
03394                                 return (DNS_R_WAIT);
03395                         }
03396                         /*
03397                          * Zones using NSEC3 don't return a NSEC RRset so
03398                          * we need to use dns_view_findzonecut2 to find
03399                          * the zone cut.
03400                          */
03401                         if (result == DNS_R_NXRRSET &&
03402                             !dns_rdataset_isassociated(&val->frdataset) &&
03403                             dns_view_findzonecut2(val->view, tname, found,
03404                                                  0, 0, ISC_FALSE, ISC_FALSE,
03405                                                  NULL, NULL) == ISC_R_SUCCESS &&
03406                             dns_name_equal(tname, found)) {
03407                                 if (val->mustbesecure) {
03408                                         validator_log(val, ISC_LOG_WARNING,
03409                                                       "must be secure failure, "
03410                                                       "no DS at zone cut");
03411                                         return (DNS_R_MUSTBESECURE);
03412                                 }
03413                                 if (val->view->dlv == NULL || DLVTRIED(val)) {
03414                                         markanswer(val, "proveunsecure (3)");
03415                                         return (ISC_R_SUCCESS);
03416                                 }
03417                                 return (startfinddlvsep(val, tname));
03418                         }
03419                         if (val->frdataset.trust < dns_trust_secure) {
03420                                 /*
03421                                  * This shouldn't happen, since the negative
03422                                  * response should have been validated.  Since
03423                                  * there's no way of validating existing
03424                                  * negative response blobs, give up.
03425                                  */
03426                                 validator_log(val, ISC_LOG_WARNING,
03427                                               "can't validate existing "
03428                                               "negative responses (no DS)");
03429                                 result = DNS_R_NOVALIDSIG;
03430                                 goto out;
03431                         }
03432                         if (isdelegation(tname, &val->frdataset, result)) {
03433                                 if (val->mustbesecure) {
03434                                         validator_log(val, ISC_LOG_WARNING,
03435                                                       "must be secure failure, "
03436                                                       "%s is a delegation",
03437                                                       namebuf);
03438                                         return (DNS_R_MUSTBESECURE);
03439                                 }
03440                                 if (val->view->dlv == NULL || DLVTRIED(val)) {
03441                                         markanswer(val, "proveunsecure (4)");
03442                                         return (ISC_R_SUCCESS);
03443                                 }
03444                                 return (startfinddlvsep(val, tname));
03445                         }
03446                         continue;
03447                 } else if (result == DNS_R_CNAME) {
03448                         if (DNS_TRUST_PENDING(val->frdataset.trust) ||
03449                             DNS_TRUST_ANSWER(val->frdataset.trust)) {
03450                                 result = create_validator(val, tname,
03451                                                           dns_rdatatype_cname,
03452                                                           &val->frdataset,
03453                                                           NULL, cnamevalidated,
03454                                                           "proveunsecure "
03455                                                           "(cname)");
03456                                 if (result != ISC_R_SUCCESS)
03457                                         goto out;
03458                                 return (DNS_R_WAIT);
03459                         }
03460                         continue;
03461                 } else if (result == ISC_R_SUCCESS) {
03462                         /*
03463                          * There is a DS here.  Verify that it's secure and
03464                          * continue.
03465                          */
03466                         if (val->frdataset.trust >= dns_trust_secure) {
03467                                 if (!check_ds(val, tname, &val->frdataset)) {
03468                                         validator_log(val, ISC_LOG_DEBUG(3),
03469                                                      "no supported algorithm/"
03470                                                      "digest (%s/DS)", namebuf);
03471                                         if (val->mustbesecure) {
03472                                                 validator_log(val,
03473                                                               ISC_LOG_WARNING,
03474                                                       "must be secure failure, "
03475                                                       "no supported algorithm/"
03476                                                       "digest (%s/DS)",
03477                                                       namebuf);
03478                                                 result = DNS_R_MUSTBESECURE;
03479                                                 goto out;
03480                                         }
03481                                         if (val->view->dlv == NULL ||
03482                                             DLVTRIED(val)) {
03483                                                 markanswer(val,
03484                                                            "proveunsecure (5)");
03485                                                 result = ISC_R_SUCCESS;
03486                                                 goto out;
03487                                         }
03488                                         return(startfinddlvsep(val, tname));
03489                                 }
03490                                 continue;
03491                         }
03492                         else if (!dns_rdataset_isassociated(&val->fsigrdataset))
03493                         {
03494                                 validator_log(val, ISC_LOG_DEBUG(3),
03495                                               "DS is unsigned");
03496                                 result = DNS_R_NOVALIDSIG;
03497                                 goto out;
03498                         }
03499                         /*
03500                          * Validate / re-validate answer.
03501                          */
03502                         result = create_validator(val, tname, dns_rdatatype_ds,
03503                                                   &val->frdataset,
03504                                                   &val->fsigrdataset,
03505                                                   dsvalidated,
03506                                                   "proveunsecure");
03507                         if (result != ISC_R_SUCCESS)
03508                                 goto out;
03509                         return (DNS_R_WAIT);
03510                 } else if (result == DNS_R_NXDOMAIN ||
03511                            result == DNS_R_NCACHENXDOMAIN) {
03512                         /*
03513                          * This is not a zone cut.  Assuming things are
03514                          * as expected, continue.
03515                          */
03516                         if (!dns_rdataset_isassociated(&val->frdataset)) {
03517                                 /*
03518                                  * There should be an NSEC here, since we
03519                                  * are still in a secure zone.
03520                                  */
03521                                 result = DNS_R_NOVALIDNSEC;
03522                                 goto out;
03523                         } else if (DNS_TRUST_PENDING(val->frdataset.trust) ||
03524                                    DNS_TRUST_ANSWER(val->frdataset.trust)) {
03525                                 /*
03526                                  * If we have "trust == answer" then this namespace
03527                                  * has switched from insecure to should be secure.
03528                                  */
03529                                 result = create_validator(val, tname,
03530                                                           dns_rdatatype_ds,
03531                                                           &val->frdataset,
03532                                                           NULL, dsvalidated,
03533                                                           "proveunsecure");
03534                                 if (result != ISC_R_SUCCESS)
03535                                         goto out;
03536                                 return (DNS_R_WAIT);
03537                         } else if (val->frdataset.trust < dns_trust_secure) {
03538                                 /*
03539                                  * This shouldn't happen, since the negative
03540                                  * response should have been validated.  Since
03541                                  * there's no way of validating existing
03542                                  * negative response blobs, give up.
03543                                  */
03544                                 validator_log(val, ISC_LOG_WARNING,
03545                                               "can't validate existing "
03546                                               "negative responses "
03547                                               "(not a zone cut)");
03548                                 result = DNS_R_NOVALIDSIG;
03549                                 goto out;
03550                         }
03551                         continue;
03552                 } else if (result == ISC_R_NOTFOUND) {
03553                         /*
03554                          * We don't know anything about the DS.  Find it.
03555                          */
03556                         result = create_fetch(val, tname, dns_rdatatype_ds,
03557                                               dsfetched2, "proveunsecure");
03558                         if (result != ISC_R_SUCCESS)
03559                                 goto out;
03560                         return (DNS_R_WAIT);
03561                 } else if (result == DNS_R_BROKENCHAIN)
03562                         return (result);
03563         }
03564 
03565         /* Couldn't complete insecurity proof */
03566         validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed");
03567         return (DNS_R_NOTINSECURE);
03568 
03569  out:
03570         if (dns_rdataset_isassociated(&val->frdataset))
03571                 dns_rdataset_disassociate(&val->frdataset);
03572         if (dns_rdataset_isassociated(&val->fsigrdataset))
03573                 dns_rdataset_disassociate(&val->fsigrdataset);
03574         return (result);
03575 }
03576 
03577 /*%
03578  * Reset state and revalidate the answer using DLV.
03579  */
03580 static void
03581 dlv_validator_start(dns_validator_t *val) {
03582         isc_event_t *event;
03583 
03584         validator_log(val, ISC_LOG_DEBUG(3), "dlv_validator_start");
03585 
03586         /*
03587          * Reset state and try again.
03588          */
03589         val->attributes &= VALATTR_DLVTRIED;
03590         val->options &= ~DNS_VALIDATOR_DLV;
03591 
03592         event = (isc_event_t *)val->event;
03593         isc_task_send(val->task, &event);
03594 }
03595 
03596 /*%
03597  * Start the validation process.
03598  *
03599  * Attempt to validate the answer based on the category it appears to
03600  * fall in.
03601  * \li  1. secure positive answer.
03602  * \li  2. unsecure positive answer.
03603  * \li  3. a negative answer (secure or unsecure).
03604  *
03605  * Note a answer that appears to be a secure positive answer may actually
03606  * be an unsecure positive answer.
03607  */
03608 static void
03609 validator_start(isc_task_t *task, isc_event_t *event) {
03610         dns_validator_t *val;
03611         dns_validatorevent_t *vevent;
03612         isc_boolean_t want_destroy = ISC_FALSE;
03613         isc_result_t result = ISC_R_FAILURE;
03614 
03615         UNUSED(task);
03616         REQUIRE(event->ev_type == DNS_EVENT_VALIDATORSTART);
03617         vevent = (dns_validatorevent_t *)event;
03618         val = vevent->validator;
03619 
03620         /* If the validator has been canceled, val->event == NULL */
03621         if (val->event == NULL)
03622                 return;
03623 
03624         if (DLVTRIED(val))
03625                 validator_log(val, ISC_LOG_DEBUG(3), "restarting using DLV");
03626         else
03627                 validator_log(val, ISC_LOG_DEBUG(3), "starting");
03628 
03629         LOCK(&val->lock);
03630 
03631         if ((val->options & DNS_VALIDATOR_DLV) != 0 &&
03632              val->event->rdataset != NULL) {
03633                 validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV");
03634                 result = startfinddlvsep(val, dns_rootname);
03635         } else if (val->event->rdataset != NULL &&
03636                    val->event->sigrdataset != NULL) {
03637                 isc_result_t saved_result;
03638 
03639                 /*
03640                  * This looks like a simple validation.  We say "looks like"
03641                  * because it might end up requiring an insecurity proof.
03642                  */
03643                 validator_log(val, ISC_LOG_DEBUG(3),
03644                               "attempting positive response validation");
03645 
03646                 INSIST(dns_rdataset_isassociated(val->event->rdataset));
03647                 INSIST(dns_rdataset_isassociated(val->event->sigrdataset));
03648                 result = start_positive_validation(val);
03649                 if (result == DNS_R_NOVALIDSIG &&
03650                     (val->attributes & VALATTR_TRIEDVERIFY) == 0)
03651                 {
03652                         saved_result = result;
03653                         validator_log(val, ISC_LOG_DEBUG(3),
03654                                       "falling back to insecurity proof");
03655                         val->attributes |= VALATTR_INSECURITY;
03656                         result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
03657                         if (result == DNS_R_NOTINSECURE)
03658                                 result = saved_result;
03659                 }
03660         } else if (val->event->rdataset != NULL &&
03661                    val->event->rdataset->type != 0) {
03662                 /*
03663                  * This is either an unsecure subdomain or a response from
03664                  * a broken server.
03665                  */
03666                 INSIST(dns_rdataset_isassociated(val->event->rdataset));
03667                 validator_log(val, ISC_LOG_DEBUG(3),
03668                               "attempting insecurity proof");
03669 
03670                 val->attributes |= VALATTR_INSECURITY;
03671                 result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
03672                 if (result == DNS_R_NOTINSECURE)
03673                         validator_log(val, ISC_LOG_INFO,
03674                                       "got insecure response; "
03675                                       "parent indicates it should be secure");
03676         } else if (val->event->rdataset == NULL &&
03677                    val->event->sigrdataset == NULL)
03678         {
03679                 /*
03680                  * This is a nonexistence validation.
03681                  */
03682                 validator_log(val, ISC_LOG_DEBUG(3),
03683                               "attempting negative response validation");
03684 
03685                 if (val->event->message->rcode == dns_rcode_nxdomain) {
03686                         val->attributes |= VALATTR_NEEDNOQNAME;
03687                         val->attributes |= VALATTR_NEEDNOWILDCARD;
03688                 } else
03689                         val->attributes |= VALATTR_NEEDNODATA;
03690                 result = nsecvalidate(val, ISC_FALSE);
03691         } else if (val->event->rdataset != NULL &&
03692                     NEGATIVE(val->event->rdataset))
03693         {
03694                 /*
03695                  * This is a nonexistence validation.
03696                  */
03697                 validator_log(val, ISC_LOG_DEBUG(3),
03698                               "attempting negative response validation");
03699 
03700                 if (val->event->rdataset->covers == dns_rdatatype_any) {
03701                         val->attributes |= VALATTR_NEEDNOQNAME;
03702                         val->attributes |= VALATTR_NEEDNOWILDCARD;
03703                 } else
03704                         val->attributes |= VALATTR_NEEDNODATA;
03705                 result = nsecvalidate(val, ISC_FALSE);
03706         } else {
03707                 /*
03708                  * This shouldn't happen.
03709                  */
03710                 INSIST(0);
03711         }
03712 
03713         if (result != DNS_R_WAIT) {
03714                 want_destroy = exit_check(val);
03715                 validator_done(val, result);
03716         }
03717 
03718         UNLOCK(&val->lock);
03719         if (want_destroy)
03720                 destroy(val);
03721 }
03722 
03723 isc_result_t
03724 dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
03725                      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
03726                      dns_message_t *message, unsigned int options,
03727                      isc_task_t *task, isc_taskaction_t action, void *arg,
03728                      dns_validator_t **validatorp)
03729 {
03730         isc_result_t result = ISC_R_FAILURE;
03731         dns_validator_t *val;
03732         isc_task_t *tclone = NULL;
03733         dns_validatorevent_t *event;
03734 
03735         REQUIRE(name != NULL);
03736         REQUIRE(rdataset != NULL ||
03737                 (rdataset == NULL && sigrdataset == NULL && message != NULL));
03738         REQUIRE(validatorp != NULL && *validatorp == NULL);
03739 
03740         val = isc_mem_get(view->mctx, sizeof(*val));
03741         if (val == NULL)
03742                 return (ISC_R_NOMEMORY);
03743         val->view = NULL;
03744         dns_view_weakattach(view, &val->view);
03745 
03746         event = (dns_validatorevent_t *)
03747                 isc_event_allocate(view->mctx, task,
03748                                    DNS_EVENT_VALIDATORSTART,
03749                                    validator_start, NULL,
03750                                    sizeof(dns_validatorevent_t));
03751         if (event == NULL) {
03752                 result = ISC_R_NOMEMORY;
03753                 goto cleanup_val;
03754         }
03755         isc_task_attach(task, &tclone);
03756         event->validator = val;
03757         event->result = ISC_R_FAILURE;
03758         event->name = name;
03759         event->type = type;
03760         event->rdataset = rdataset;
03761         event->sigrdataset = sigrdataset;
03762         event->message = message;
03763         memset(event->proofs, 0, sizeof(event->proofs));
03764         event->optout = ISC_FALSE;
03765         event->secure = ISC_FALSE;
03766         result = isc_mutex_init(&val->lock);
03767         if (result != ISC_R_SUCCESS)
03768                 goto cleanup_event;
03769         val->event = event;
03770         val->options = options;
03771         val->attributes = 0;
03772         val->fetch = NULL;
03773         val->subvalidator = NULL;
03774         val->parent = NULL;
03775 
03776         val->keytable = NULL;
03777         result = dns_view_getsecroots(val->view, &val->keytable);
03778         if (result != ISC_R_SUCCESS)
03779                 goto cleanup_mutex;
03780         val->keynode = NULL;
03781         val->key = NULL;
03782         val->siginfo = NULL;
03783         val->task = task;
03784         val->action = action;
03785         val->arg = arg;
03786         val->labels = 0;
03787         val->currentset = NULL;
03788         val->keyset = NULL;
03789         val->dsset = NULL;
03790         dns_rdataset_init(&val->dlv);
03791         val->seensig = ISC_FALSE;
03792         val->havedlvsep = ISC_FALSE;
03793         val->depth = 0;
03794         val->authcount = 0;
03795         val->authfail = 0;
03796         val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
03797         dns_rdataset_init(&val->frdataset);
03798         dns_rdataset_init(&val->fsigrdataset);
03799         dns_fixedname_init(&val->wild);
03800         dns_fixedname_init(&val->nearest);
03801         dns_fixedname_init(&val->closest);
03802         isc_stdtime_get(&val->start);
03803         ISC_LINK_INIT(val, link);
03804         val->magic = VALIDATOR_MAGIC;
03805 
03806         if ((options & DNS_VALIDATOR_DEFER) == 0)
03807                 isc_task_send(task, ISC_EVENT_PTR(&event));
03808 
03809         *validatorp = val;
03810 
03811         return (ISC_R_SUCCESS);
03812 
03813  cleanup_mutex:
03814         DESTROYLOCK(&val->lock);
03815 
03816  cleanup_event:
03817         isc_task_detach(&tclone);
03818         isc_event_free(ISC_EVENT_PTR(&event));
03819 
03820  cleanup_val:
03821         dns_view_weakdetach(&val->view);
03822         isc_mem_put(view->mctx, val, sizeof(*val));
03823 
03824         return (result);
03825 }
03826 
03827 void
03828 dns_validator_send(dns_validator_t *validator) {
03829         isc_event_t *event;
03830         REQUIRE(VALID_VALIDATOR(validator));
03831 
03832         LOCK(&validator->lock);
03833 
03834         INSIST((validator->options & DNS_VALIDATOR_DEFER) != 0);
03835         event = (isc_event_t *)validator->event;
03836         validator->options &= ~DNS_VALIDATOR_DEFER;
03837         UNLOCK(&validator->lock);
03838 
03839         isc_task_send(validator->task, ISC_EVENT_PTR(&event));
03840 }
03841 
03842 void
03843 dns_validator_cancel(dns_validator_t *validator) {
03844         dns_fetch_t *fetch = NULL;
03845 
03846         REQUIRE(VALID_VALIDATOR(validator));
03847 
03848         LOCK(&validator->lock);
03849 
03850         validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
03851 
03852         if ((validator->attributes & VALATTR_CANCELED) == 0) {
03853                 validator->attributes |= VALATTR_CANCELED;
03854                 if (validator->event != NULL) {
03855                         fetch = validator->fetch;
03856                         validator->fetch = NULL;
03857 
03858                         if (validator->subvalidator != NULL)
03859                                 dns_validator_cancel(validator->subvalidator);
03860                         if ((validator->options & DNS_VALIDATOR_DEFER) != 0) {
03861                                 validator->options &= ~DNS_VALIDATOR_DEFER;
03862                                 validator_done(validator, ISC_R_CANCELED);
03863                         }
03864                 }
03865         }
03866         UNLOCK(&validator->lock);
03867 
03868         /* Need to cancel and destroy the fetch outside validator lock */
03869         if (fetch != NULL) {
03870                 dns_resolver_cancelfetch(fetch);
03871                 dns_resolver_destroyfetch(&fetch);
03872         }
03873 }
03874 
03875 static void
03876 destroy(dns_validator_t *val) {
03877         isc_mem_t *mctx;
03878 
03879         REQUIRE(SHUTDOWN(val));
03880         REQUIRE(val->event == NULL);
03881         REQUIRE(val->fetch == NULL);
03882 
03883         if (val->keynode != NULL)
03884                 dns_keytable_detachkeynode(val->keytable, &val->keynode);
03885         else if (val->key != NULL)
03886                 dst_key_free(&val->key);
03887         if (val->keytable != NULL)
03888                 dns_keytable_detach(&val->keytable);
03889         if (val->subvalidator != NULL)
03890                 dns_validator_destroy(&val->subvalidator);
03891         if (val->havedlvsep)
03892                 dns_rdataset_disassociate(&val->dlv);
03893         if (dns_rdataset_isassociated(&val->frdataset))
03894                 dns_rdataset_disassociate(&val->frdataset);
03895         if (dns_rdataset_isassociated(&val->fsigrdataset))
03896                 dns_rdataset_disassociate(&val->fsigrdataset);
03897         mctx = val->view->mctx;
03898         if (val->siginfo != NULL)
03899                 isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo));
03900         DESTROYLOCK(&val->lock);
03901         dns_view_weakdetach(&val->view);
03902         val->magic = 0;
03903         isc_mem_put(mctx, val, sizeof(*val));
03904 }
03905 
03906 void
03907 dns_validator_destroy(dns_validator_t **validatorp) {
03908         dns_validator_t *val;
03909         isc_boolean_t want_destroy = ISC_FALSE;
03910 
03911         REQUIRE(validatorp != NULL);
03912         val = *validatorp;
03913         REQUIRE(VALID_VALIDATOR(val));
03914 
03915         LOCK(&val->lock);
03916 
03917         val->attributes |= VALATTR_SHUTDOWN;
03918         validator_log(val, ISC_LOG_DEBUG(4), "dns_validator_destroy");
03919 
03920         want_destroy = exit_check(val);
03921 
03922         UNLOCK(&val->lock);
03923 
03924         if (want_destroy)
03925                 destroy(val);
03926 
03927         *validatorp = NULL;
03928 }
03929 
03930 static void
03931 validator_logv(dns_validator_t *val, isc_logcategory_t *category,
03932                isc_logmodule_t *module, int level, const char *fmt, va_list ap)
03933 {
03934         char msgbuf[2048];
03935         static const char spaces[] = "        *";
03936         int depth = val->depth * 2;
03937 
03938         vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
03939 
03940         if ((unsigned int) depth >= sizeof spaces)
03941                 depth = sizeof spaces - 1;
03942 
03943         if (val->event != NULL && val->event->name != NULL) {
03944                 char namebuf[DNS_NAME_FORMATSIZE];
03945                 char typebuf[DNS_RDATATYPE_FORMATSIZE];
03946 
03947                 dns_name_format(val->event->name, namebuf, sizeof(namebuf));
03948                 dns_rdatatype_format(val->event->type, typebuf,
03949                                      sizeof(typebuf));
03950                 isc_log_write(dns_lctx, category, module, level,
03951                               "%.*svalidating %s/%s: %s", depth, spaces,
03952                               namebuf, typebuf, msgbuf);
03953         } else {
03954                 isc_log_write(dns_lctx, category, module, level,
03955                               "%.*svalidator @%p: %s", depth, spaces,
03956                                val, msgbuf);
03957         }
03958 }
03959 
03960 static void
03961 validator_log(void *val, int level, const char *fmt, ...) {
03962         va_list ap;
03963 
03964         if (! isc_log_wouldlog(dns_lctx, level))
03965                 return;
03966 
03967         va_start(ap, fmt);
03968 
03969         validator_logv(val, DNS_LOGCATEGORY_DNSSEC,
03970                        DNS_LOGMODULE_VALIDATOR, level, fmt, ap);
03971         va_end(ap);
03972 }
03973 
03974 static void
03975 validator_logcreate(dns_validator_t *val,
03976                     dns_name_t *name, dns_rdatatype_t type,
03977                     const char *caller, const char *operation)
03978 {
03979         char namestr[DNS_NAME_FORMATSIZE];
03980         char typestr[DNS_RDATATYPE_FORMATSIZE];
03981 
03982         dns_name_format(name, namestr, sizeof(namestr));
03983         dns_rdatatype_format(type, typestr, sizeof(typestr));
03984         validator_log(val, ISC_LOG_DEBUG(9), "%s: creating %s for %s %s",
03985                       caller, operation, namestr, typestr);
03986 }

Generated on Tue Apr 28 17:41:02 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha