dc2a85bed7fcfceab0df1867fbc1d35796261dedTinderbox User * Copyright (C) 2000-2018 Internet Systems Consortium, Inc. ("ISC")
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Basic processing sequences.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li When called with rdataset and sigrdataset:
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * validator_start -> validate -> proveunsecure -> startfinddlvsep ->
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * dlv_validator_start -> validator_start -> validate -> proveunsecure
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * validator_start -> validate -> nsecvalidate (secure wildcard answer)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li When called with rdataset, sigrdataset and with DNS_VALIDATOR_DLV:
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * validator_start -> startfinddlvsep -> dlv_validator_start ->
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * validator_start -> validate -> proveunsecure
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li When called with rdataset:
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * validator_start -> proveunsecure -> startfinddlvsep ->
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * dlv_validator_start -> validator_start -> proveunsecure
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li When called with rdataset and with DNS_VALIDATOR_DLV:
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * validator_start -> startfinddlvsep -> dlv_validator_start ->
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * validator_start -> proveunsecure
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li When called without a rdataset:
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * validator_start -> nsecvalidate -> proveunsecure -> startfinddlvsep ->
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * dlv_validator_start -> validator_start -> nsecvalidate -> proveunsecure
d2ef84e07b67e72a4bd9c729c6b8228067d17584Mark Andrews * Note: there isn't a case for DNS_VALIDATOR_DLV here as we want nsecvalidate()
d2ef84e07b67e72a4bd9c729c6b8228067d17584Mark Andrews * to always validate the authority section even when it does not contain
d2ef84e07b67e72a4bd9c729c6b8228067d17584Mark Andrews * signatures.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * validator_start: determines what type of validation to do.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * validate: attempts to perform a positive validation.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * proveunsecure: attempts to prove the answer comes from a unsecure zone.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * nsecvalidate: attempts to prove a negative response.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * startfinddlvsep: starts the DLV record lookup.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * dlv_validator_start: resets state and restarts the lookup using the
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * DLV RRset found by startfinddlvsep.
92ef1a9b9dbd48ecb507b42ac62c15afefdaf838David Lawrence#define VALIDATOR_MAGIC ISC_MAGIC('V', 'a', 'l', '?')
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#define VALATTR_SHUTDOWN 0x0001 /*%< Shutting down. */
708383382ff1d3fdd27527e5d63120a3c6c6d3b3Francis Dupont#define VALATTR_CANCELED 0x0002 /*%< Canceled. */
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#define VALATTR_TRIEDVERIFY 0x0004 /*%< We have found a key and
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * have attempted a verify. */
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#define VALATTR_INSECURITY 0x0010 /*%< Attempting proveunsecure. */
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#define VALATTR_DLVTRIED 0x0020 /*%< Looked for a DLV record. */
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * NSEC proofs to be looked for.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * NSEC proofs that have been found.
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews#define NEEDNODATA(val) ((val->attributes & VALATTR_NEEDNODATA) != 0)
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews#define NEEDNOQNAME(val) ((val->attributes & VALATTR_NEEDNOQNAME) != 0)
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews#define NEEDNOWILDCARD(val) ((val->attributes & VALATTR_NEEDNOWILDCARD) != 0)
50105afc551903541608b11851d73278b23579a3Mark Andrews#define DLVTRIED(val) ((val->attributes & VALATTR_DLVTRIED) != 0)
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews#define FOUNDNODATA(val) ((val->attributes & VALATTR_FOUNDNODATA) != 0)
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews#define FOUNDNOQNAME(val) ((val->attributes & VALATTR_FOUNDNOQNAME) != 0)
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews#define FOUNDNOWILDCARD(val) ((val->attributes & VALATTR_FOUNDNOWILDCARD) != 0)
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews#define FOUNDCLOSEST(val) ((val->attributes & VALATTR_FOUNDCLOSEST) != 0)
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews#define FOUNDOPTOUT(val) ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley#define SHUTDOWN(v) (((v)->attributes & VALATTR_SHUTDOWN) != 0)
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews#define CANCELED(v) (((v)->attributes & VALATTR_CANCELED) != 0)
6de9744cf9c64be2145f663e4051196a4eaa9d45Evan Hunt#define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewsget_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrencevalidate(dns_validator_t *val, isc_boolean_t resume);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewsnsecvalidate(dns_validator_t *val, isc_boolean_t resume);
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrewsproveunsecure(dns_validator_t *val, isc_boolean_t have_ds,
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellingtonvalidator_logv(dns_validator_t *val, isc_logcategory_t *category,
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington isc_logmodule_t *module, int level, const char *fmt, va_list ap)
8462dfb880040cde3a60f047ec18808737fd7e85Mark Andrewsvalidator_log(void *val, int level, const char *fmt, ...)
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrewsfinddlvsep(dns_validator_t *val, isc_boolean_t resume);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrewsstartfinddlvsep(dns_validator_t *val, dns_name_t *unsecure);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Mark the RRsets as a answer.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrewsstatic inline void
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrewsmarkanswer(dns_validator_t *val, const char *where) {
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews validator_log(val, ISC_LOG_DEBUG(3), "marking as answer (%s)", where);
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews dns_rdataset_settrust(val->event->rdataset, dns_trust_answer);
0cae66577c69c89086cd065bb297690072b471b4Mark Andrewsstatic inline void
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews dns_rdataset_settrust(event->rdataset, dns_trust_secure);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews dns_rdataset_settrust(event->sigrdataset, dns_trust_secure);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halleyvalidator_done(dns_validator_t *val, isc_result_t result) {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * Caller must be holding the lock.
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff val->event->ev_type = DNS_EVENT_VALIDATORDONE;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley isc_task_sendanddetach(&task, (isc_event_t **)&val->event);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Caller must be holding the lock.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (val->fetch != NULL || val->subvalidator != NULL)
72dbc7216aae3626a66e6154443be219f5edcaf0Mark Andrews * Check that we have atleast one supported algorithm in the DLV RRset.
72dbc7216aae3626a66e6154443be219f5edcaf0Mark Andrews result = dns_rdata_tostruct(&rdata, &dlv, NULL);
72dbc7216aae3626a66e6154443be219f5edcaf0Mark Andrews if (!dns_resolver_algorithm_supported(val->view->resolver,
058e44186b74531402c1f99088eb9dbe4926f8daMark Andrews if (!dns_resolver_ds_digest_supported(val->view->resolver,
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Look in the NSEC record returned from a DS query to see if there is
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * a NS RRset at this name. If it is found we are at a delegation point.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsisdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews REQUIRE(dbresult == DNS_R_NXRRSET || dbresult == DNS_R_NCACHENXRRSET);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews result = dns_ncache_getrdataset(rdataset, name,
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews found = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * Iterate over the ncache entry.
7d211b458fed36326b9e125b9d74089f9dccc140Mark Andrews dns_name_downcase(name, dns_fixedname_name(&fixed), NULL);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews dns_ncache_current(rdataset, &nsec3name, &set);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews isc_buffer_init(&buffer, owner, sizeof(owner));
36e5ac00333d89001f0c518a7d381d16c38d0402Mark Andrews result = isc_base32hexnp_decoderegion(&hashlabel, &buffer);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews (void)dns_rdata_tostruct(&rdata, &nsec3, NULL);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * Does this optout span cover the name?
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews scope = memcmp(owner, nsec3.next, nsec3.next_length);
ff380b05fec3746934c74b78bb44f641d2acb359Francis Dupont * We have been asked to look for a key.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * If found resume the validation process.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * If not found fail the validation process.
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellingtonfetch_callback_validator(isc_task_t *task, isc_event_t *event) {
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews /* Free resources which are not of interest. */
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews if (dns_rdataset_isassociated(&val->fsigrdataset))
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_validator");
ea8278253210df030a24f0c89342b43fe279a127Mark Andrews "keyset with trust %s",
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * Only extract the dst key if the keyset is secure.
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington result = get_dst_key(val, val->siginfo, rdataset);
a27b3757fdd8976ce05e37f391ad9e7ac4638e5dMark Andrews "falling back to insecurity proof");
a27b3757fdd8976ce05e37f391ad9e7ac4638e5dMark Andrews result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson "fetch_callback_validator: got %s",
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * We were asked to look for a DS record as part of following a key chain
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * upwards. If found resume the validation process. If not found fail the
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * validation process.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsdsfetched(isc_task_t *task, isc_event_t *event) {
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews /* Free resources which are not of interest. */
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews if (dns_rdataset_isassociated(&val->fsigrdataset))
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched");
ea8278253210df030a24f0c89342b43fe279a127Mark Andrews "dsset with trust %s",
a05f23d07e1b60a1d88119678111a47014480611Mark Andrews eresult == DNS_R_SERVFAIL) /* RFC 1034 parent? */
a05f23d07e1b60a1d88119678111a47014480611Mark Andrews "falling back to insecurity proof (%s)",
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews "dsfetched: got %s",
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * We were asked to look for the DS record as part of proving that a
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * name is unsecure.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * If the DS record doesn't exist and the query name corresponds to
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * a delegation point we are transitioning from a secure zone to a
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * unsecure zone.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * If the DS record exists it will be secure. We can continue looking
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * for the break point in the chain of trust.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsdsfetched2(isc_task_t *task, isc_event_t *event) {
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews /* Free resources which are not of interest. */
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews if (dns_rdataset_isassociated(&val->fsigrdataset))
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched2: %s",
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * There is no DS. If this is a delegation, we're done.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews tname = dns_fixedname_name(&devent->foundname);
4b45a8fc5a47dcff7473003ceeac6f6bb3e21e79Mark Andrews isdelegation(tname, &val->frdataset, eresult)) {
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt "must be secure failure, no DS"
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt " and this is a delegation");
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews } else if (val->view->dlv == NULL || DLVTRIED(val)) {
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews result = proveunsecure(val, ISC_FALSE, ISC_TRUE);
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater * There is a DS which may or may not be a zone cut.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * In either case we are still in a secure zone resume
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * validation.
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews result = proveunsecure(val, ISC_TF(eresult == ISC_R_SUCCESS),
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Callback from when a DNSKEY RRset has been validated.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Resumes the stalled validation process.
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellingtonkeyvalidated(isc_task_t *task, isc_event_t *event) {
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson validator_log(val, ISC_LOG_DEBUG(3), "in keyvalidated");
ea8278253210df030a24f0c89342b43fe279a127Mark Andrews "keyset with trust %s",
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * Only extract the dst key if the keyset is secure.
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington if (val->frdataset.trust >= dns_trust_secure)
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington (void) get_dst_key(val, val->siginfo, &val->frdataset);
a27b3757fdd8976ce05e37f391ad9e7ac4638e5dMark Andrews "falling back to insecurity proof");
a27b3757fdd8976ce05e37f391ad9e7ac4638e5dMark Andrews result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews if (dns_rdataset_isassociated(&val->frdataset))
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews if (dns_rdataset_isassociated(&val->fsigrdataset))
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson "keyvalidated: got %s",
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Callback when the DS record has been validated.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Resumes validation of the zone key or the unsecure zone proof.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsdsvalidated(isc_task_t *task, isc_event_t *event) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews validator_log(val, ISC_LOG_DEBUG(3), "in dsvalidated");
ea8278253210df030a24f0c89342b43fe279a127Mark Andrews "%s with trust %s",
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews have_dsset = ISC_TF(val->frdataset.type == dns_rdatatype_ds);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if ((val->attributes & VALATTR_INSECURITY) != 0 &&
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews isdelegation(name, &val->frdataset, DNS_R_NCACHENXRRSET)) {
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews "must be secure failure, no DS "
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews "and this is a delegation");
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews } else if (val->view->dlv == NULL || DLVTRIED(val)) {
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews } else if ((val->attributes & VALATTR_INSECURITY) != 0) {
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews result = proveunsecure(val, have_dsset, ISC_TRUE);
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews if (dns_rdataset_isassociated(&val->frdataset))
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews if (dns_rdataset_isassociated(&val->fsigrdataset))
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews "dsvalidated: got %s",
4b45a8fc5a47dcff7473003ceeac6f6bb3e21e79Mark Andrews * Callback when the CNAME record has been validated.
4b45a8fc5a47dcff7473003ceeac6f6bb3e21e79Mark Andrews * Resumes validation of the unsecure zone proof.
4b45a8fc5a47dcff7473003ceeac6f6bb3e21e79Mark Andrewscnamevalidated(isc_task_t *task, isc_event_t *event) {
4b45a8fc5a47dcff7473003ceeac6f6bb3e21e79Mark Andrews INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
4b45a8fc5a47dcff7473003ceeac6f6bb3e21e79Mark Andrews INSIST((val->attributes & VALATTR_INSECURITY) != 0);
4b45a8fc5a47dcff7473003ceeac6f6bb3e21e79Mark Andrews validator_log(val, ISC_LOG_DEBUG(3), "in cnamevalidated");
ea8278253210df030a24f0c89342b43fe279a127Mark Andrews validator_log(val, ISC_LOG_DEBUG(3), "cname with trust %s",
4b45a8fc5a47dcff7473003ceeac6f6bb3e21e79Mark Andrews result = proveunsecure(val, ISC_FALSE, ISC_TRUE);
4b45a8fc5a47dcff7473003ceeac6f6bb3e21e79Mark Andrews if (dns_rdataset_isassociated(&val->frdataset))
4b45a8fc5a47dcff7473003ceeac6f6bb3e21e79Mark Andrews if (dns_rdataset_isassociated(&val->fsigrdataset))
4b45a8fc5a47dcff7473003ceeac6f6bb3e21e79Mark Andrews "cnamevalidated: got %s",
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Callback for when NSEC records have been validated.
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * Looks for NOQNAME, NODATA and OPTOUT proofs.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Resumes nsecvalidate.
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellingtonauthvalidated(isc_task_t *task, isc_event_t *event) {
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson validator_log(val, ISC_LOG_DEBUG(3), "in authvalidated");
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington "authvalidated: got %s",
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews dns_name_t *wild = dns_fixedname_name(&val->wild);
8462dfb880040cde3a60f047ec18808737fd7e85Mark Andrews dns_nsec_noexistnodata(val->event->type, val->event->name,
2fa1fc53324c0fca978c902e883c7cc011210536Mark Andrews * If we are validating a wildcard response
2fa1fc53324c0fca978c902e883c7cc011210536Mark Andrews * clabels will not be zero. We then need
2fa1fc53324c0fca978c902e883c7cc011210536Mark Andrews * to check if the generated wilcard from
2fa1fc53324c0fca978c902e883c7cc011210536Mark Andrews * dns_nsec_noexistnodata is consistent with
2fa1fc53324c0fca978c902e883c7cc011210536Mark Andrews * the wildcard used to generate the response.
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * The NSEC noqname proof also contains
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * the closest encloser.
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * Free stuff from the event.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Looks for the requested name and type in the view (zones and cache).
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * When looking for a DLV record also checks to make sure the NSEC record
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * returns covers the query name as part of aggressive negative caching.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li ISC_R_SUCCESS
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li ISC_R_NOTFOUND
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li DNS_R_NCACHENXDOMAIN
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li DNS_R_NCACHENXRRSET
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li DNS_R_NXRRSET
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li DNS_R_NXDOMAIN
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews * \li DNS_R_BROKENCHAIN
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsview_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington if (dns_rdataset_isassociated(&val->frdataset))
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_rdataset_disassociate(&val->frdataset);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (dns_rdataset_isassociated(&val->fsigrdataset))
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews dns_resolver_getbadcache(val->view->resolver, name, type, &now)) {
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews dns_name_format(name, namebuf, sizeof(namebuf));
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews dns_rdatatype_format(type, typebuf, sizeof(typebuf));
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews validator_log(val, ISC_LOG_INFO, "bad cache hit (%s/%s)",
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews result = dns_view_find(val->view, name, type, 0, options,
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (dns_rdataset_isassociated(&val->frdataset))
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (dns_rdataset_isassociated(&val->fsigrdataset))
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews validator_log(val, ISC_LOG_DEBUG(3), "DNS_R_COVERINGNSEC");
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews * Check if the returned NSEC covers the name.
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (val->frdataset.trust != dns_trust_secure) {
ea8278253210df030a24f0c89342b43fe279a127Mark Andrews "covering nsec: trust %s",
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews !dns_nsec_typepresent(&rdata, dns_rdatatype_soa)) {
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews /* Parent NSEC record. */
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews "covering nsec: for parent");
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews result = dns_rdata_tostruct(&rdata, &nsec, NULL);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (dns_name_compare(foundname, &nsec.next) >= 0) {
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews /* End of zone chain. */
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater * XXXMPA We could look for a parent NSEC
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews * at nsec.next and if found retest with
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews * this NSEC.
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews "covering nsec: not in zone");
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews } else if (dns_name_compare(name, &nsec.next) >= 0) {
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews * XXXMPA We could check if this NSEC is at a zone
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews * apex and if the qname is not below it and look for
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews * a parent NSEC with the same name. This requires
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews * that we can cache both NSEC records which we
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews * currently don't support.
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews "covering nsec: not in range");
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (isc_log_wouldlog(dns_lctx,ISC_LOG_DEBUG(3))) {
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews dns_name_format(&nsec.next, buf3, sizeof buf3);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews "covering nsec found: '%s' '%s' '%s'",
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (dns_rdataset_isassociated(&val->frdataset))
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (dns_rdataset_isassociated(&val->fsigrdataset))
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (dns_rdataset_isassociated(&val->frdataset))
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (dns_rdataset_isassociated(&val->fsigrdataset))
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Checks to make sure we are not going to loop. As we use a SHARED fetch
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * the validation process will stall if looping was to occur.
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewscheck_deadlock(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews for (parent = val; parent != NULL; parent = parent->parent) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * As NSEC3 records are meta data you sometimes
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * need to prove a NSEC3 record which says that
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * itself doesn't exist.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews "continuing validation would lead to "
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews "deadlock: aborting validation");
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Start a fetch for the requested name and type.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewscreate_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington if (dns_rdataset_isassociated(&val->frdataset))
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_rdataset_disassociate(&val->frdataset);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington if (dns_rdataset_isassociated(&val->fsigrdataset))
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_rdataset_disassociate(&val->fsigrdataset);
7048af0a551f13d2916a06cce21357714939a89bEvan Hunt if (check_deadlock(val, name, type, NULL, NULL)) {
7048af0a551f13d2916a06cce21357714939a89bEvan Hunt "deadlock found (create_fetch)");
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews validator_logcreate(val, name, type, caller, "fetch");
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (dns_resolver_createfetch(val->view->resolver, name, type,
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Start a subvalidation process.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewscreate_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
7048af0a551f13d2916a06cce21357714939a89bEvan Hunt if (check_deadlock(val, name, type, rdataset, sigrdataset)) {
7048af0a551f13d2916a06cce21357714939a89bEvan Hunt "deadlock found (create_validator)");
5d63868ad0d3865118ad294081cfa03df51d1de8Mark Andrews /* OK to clear other options, but preserve NOCDFLAG and NONTA. */
5d63868ad0d3865118ad294081cfa03df51d1de8Mark Andrews vopts |= (val->options & (DNS_VALIDATOR_NOCDFLAG|DNS_VALIDATOR_NONTA));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews validator_logcreate(val, name, type, caller, "validator");
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = dns_validator_create(val->view, name, type,
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson * Try to find a key that could have signed 'siginfo' among those
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson * in 'rdataset'. If found, build a dst_key_t for it and point
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson * val->key at it.
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * If val->key is non-NULL, this returns the next matching key.
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewsget_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&b, rdata.data, rdata.length);
5c29047792191d6141f69b2684314d0b762fedebBrian Wellington result = dst_key_fromdns(&siginfo->signer, rdata.rdclass, &b,
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * This is the key we're looking for.
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington else if (dst_key_compare(oldkey, val->key) == ISC_TRUE)
708383382ff1d3fdd27527e5d63120a3c6c6d3b3Francis Dupont * Get the key that generated this signature.
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewsget_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * Is the signer name appropriate for this signature?
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * The signer name must be at the same level as the owner name
3fb1637c9265cc593973326ae193783413f68699Tatuya JINMEI 神明達哉 * or closer to the DNS root.
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington namereln = dns_name_fullcompare(val->event->name, &siginfo->signer,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * If this is a self-signed keyset, it must not be a zone key
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * (since get_key is not called from validatezonekey).
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews if (val->event->rdataset->type == dns_rdatatype_dnskey)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Records appearing in the parent zone at delegation
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * points cannot be self-signed.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (dns_rdatatype_atparent(val->event->rdataset->type))
49960a74b5d82d000c281af09d7c668bdd1671a1Automatic Updater * SOA and NS RRsets can only be signed by a key with
50df1ec60af410fca6b7a85d5c85e8f31bb13bc3Mark Andrews * the same name.
50df1ec60af410fca6b7a85d5c85e8f31bb13bc3Mark Andrews if (val->event->rdataset->type == dns_rdatatype_soa ||
50df1ec60af410fca6b7a85d5c85e8f31bb13bc3Mark Andrews val->event->rdataset->type == dns_rdatatype_ns) {
50df1ec60af410fca6b7a85d5c85e8f31bb13bc3Mark Andrews if (val->event->rdataset->type == dns_rdatatype_soa)
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * Do we know about this key?
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews result = view_find(val, &siginfo->signer, dns_rdatatype_dnskey);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * We have an rrset for the given keyname.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
515c7f3c43f76d7b439905b18009105364b36100Automatic Updater DNS_TRUST_ANSWER(val->frdataset.trust)) &&
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_rdataset_isassociated(&val->fsigrdataset))
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * We know the key but haven't validated it yet or
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * we have a key of trust answer but a DS/DLV
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * record for the zone may have been added.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = create_validator(val, &siginfo->signer,
a39a5f4d816ca7d3f43106712ca668dd1ab31d69Mark Andrews } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * Having a pending key with no signature means that
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * something is broken.
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington } else if (val->frdataset.trust < dns_trust_secure) {
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * The key is legitimately insecure. There's no
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * point in even attempting verification.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * See if we've got the key used in the signature.
ea8278253210df030a24f0c89342b43fe279a127Mark Andrews "keyset with trust %s",
77c67dfb2607618f5e7940486daebafd42a502abBrian Wellington result = get_dst_key(val, siginfo, val->keyset);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * Either the key we're looking for is not
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * in the rrset, or something bad happened.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * We don't know anything about this key.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * This key doesn't exist.
77c67dfb2607618f5e7940486daebafd42a502abBrian Wellington if (dns_rdataset_isassociated(&val->frdataset) &&
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_rdataset_disassociate(&val->frdataset);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington if (dns_rdataset_isassociated(&val->fsigrdataset))
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_rdataset_disassociate(&val->fsigrdataset);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewscompute_keytag(dns_rdata_t *rdata, dns_rdata_dnskey_t *key) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (dst_region_computeid(&r, key->algorithm));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Is this keyset self-signed?
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews INSIST(rdataset->type == dns_rdatatype_dnskey);
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington for (result = dns_rdataset_first(rdataset);
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews result = dns_rdata_tostruct(&rdata, &key, NULL);
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews result = dns_dnssec_keyfromrdata(name, &rdata, mctx,
7865ea9545f28f12f046b32d24c989e8441b9812Mark Andrews result = dns_dnssec_verify3(name, rdataset, dstkey,
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Attempt to verify the rdataset using the given key and rdata (RRSIG).
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * The signature was good and from a wildcard record and the QNAME does
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * not match the wildcard we need to look for a NOQNAME proof.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li ISC_R_SUCCESS if the verification succeeds.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li Others if the verification fails.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrewsverify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata,
7865ea9545f28f12f046b32d24c989e8441b9812Mark Andrews result = dns_dnssec_verify3(val->event->name, val->event->rdataset,
25845da41a621f35e76dc8560ca40de6859e0a11Evan Hunt if ((result == DNS_R_SIGEXPIRED || result == DNS_R_SIGFUTURE) &&
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrews if (ignore && (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD))
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrews "accepted expired %sRRSIG (keyid=%u)",
25845da41a621f35e76dc8560ca40de6859e0a11Evan Hunt else if (result == DNS_R_SIGEXPIRED || result == DNS_R_SIGFUTURE)
25845da41a621f35e76dc8560ca40de6859e0a11Evan Hunt "verify failed due to bad signature (keyid=%u): "
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrews "verify rdataset (keyid=%u): %s",
ada40193c85276867c6904545601c7c01e3236c3Mark Andrews * Compute the closest encloser in case we need it
ada40193c85276867c6904545601c7c01e3236c3Mark Andrews * for the NSEC3 NOQNAME proof.
ada40193c85276867c6904545601c7c01e3236c3Mark Andrews dns_name_getlabelsequence(closest, 1, labels, closest);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Attempts positive response validation of a normal RRset.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li ISC_R_SUCCESS Validation completed successfully
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li DNS_R_WAIT Validation has started but is waiting
3ce4b8b03ebd017c1d1b320429219ba91e705ea4Andreas Gustafsson * for an event.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li Other return codes are possible and all indicate failure.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halleyvalidate(dns_validator_t *val, isc_boolean_t resume) {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * Caller must be holding the validator lock.
78951552dccf0d0004d61072bbc71fa4b1aab30fAndreas Gustafsson * We already have a sigrdataset.
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson validator_log(val, ISC_LOG_DEBUG(3), "resuming validate");
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson result = dns_rdataset_next(event->sigrdataset))
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley dns_rdataset_current(event->sigrdataset, &rdata);
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington val->siginfo = isc_mem_get(val->view->mctx,
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson result = dns_rdata_tostruct(&rdata, val->siginfo, NULL);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * At this point we could check that the signature algorithm
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews * was known and "sufficiently good".
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (!dns_resolver_algorithm_supported(val->view->resolver,
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson continue; /* Try the next SIG RR. */
a27b3757fdd8976ce05e37f391ad9e7ac4638e5dMark Andrews * There isn't a secure DNSKEY for this signature so move
a27b3757fdd8976ce05e37f391ad9e7ac4638e5dMark Andrews * onto the next RRSIG.
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington if (get_dst_key(val, val->siginfo, val->keyset)
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington "failed to verify rdataset");
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews "no message available for noqname proof");
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews "looking for noqname proof");
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt "marking as secure, "
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt "noqname proof not needed");
777ac454c0cdec27dc11d80b9b2a8d7239d833a8Brian Wellington "verify failure: %s",
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington "failed to iterate signatures: %s",
e1f16346db02486f751c6db683fffe53c866c186Andreas Gustafsson validator_log(val, ISC_LOG_INFO, "no valid signature found");
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews * Check whether this DNSKEY (keyrdata) signed the DNSKEY RRset
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews * (val->event->rdataset).
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrewscheckkey(dns_validator_t *val, dns_rdata_t *keyrdata, isc_uint16_t keyid,
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews for (result = dns_rdataset_first(val->event->sigrdataset);
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews result = dns_rdataset_next(val->event->sigrdataset))
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews dns_rdataset_current(val->event->sigrdataset, &rdata);
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews result = dns_rdata_tostruct(&rdata, &sig, NULL);
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews if (keyid != sig.keyid || algorithm != sig.algorithm)
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews result = dns_dnssec_keyfromrdata(val->event->name,
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews * This really shouldn't happen, but...
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews result = verify(val, dstkey, &rdata, sig.keyid);
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews * Find the DNSKEY that corresponds to the DS.
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrewskeyfromds(dns_validator_t *val, dns_rdataset_t *rdataset, dns_rdata_t *dsrdata,
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews isc_uint8_t digest, isc_uint16_t keyid, dns_secalg_t algorithm,
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews result = dns_rdata_tostruct(keyrdata, &key, NULL);
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews if (keyid != keytag || algorithm != key.algorithm)
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews result = dns_ds_buildrdata(val->event->name, keyrdata, digest,
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews "dns_ds_buildrdata() -> %s",
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews if (dns_rdata_compare(dsrdata, &newdsrdata) == 0)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Validate the DNSKEY RRset by looking for a DNSKEY that matches a
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * DLV record and that also verifies the DNSKEY RRset.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews validator_log(val, ISC_LOG_DEBUG(3), "dlv_validatezonekey");
50105afc551903541608b11851d73278b23579a3Mark Andrews * Look through the DLV record and find the keys that can sign the
50105afc551903541608b11851d73278b23579a3Mark Andrews * key set and the matching signature. For each such key, attempt
50105afc551903541608b11851d73278b23579a3Mark Andrews * verification.
9540b42695c15fdd5f01b4c663e21936e6c38c82Mukund Sivaraman * If DNS_DSDIGEST_SHA256 or DNS_DSDIGEST_SHA384 is present we
9540b42695c15fdd5f01b4c663e21936e6c38c82Mukund Sivaraman * are required to prefer it over DNS_DSDIGEST_SHA1. This in
9540b42695c15fdd5f01b4c663e21936e6c38c82Mukund Sivaraman * practice means that we need to ignore DNS_DSDIGEST_SHA1 if a
9540b42695c15fdd5f01b4c663e21936e6c38c82Mukund Sivaraman * DNS_DSDIGEST_SHA256 or DNS_DSDIGEST_SHA384 is present.
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
9540b42695c15fdd5f01b4c663e21936e6c38c82Mukund Sivaraman if (!dns_resolver_ds_digest_supported(val->view->resolver,
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews if (!dns_resolver_algorithm_supported(val->view->resolver,
9540b42695c15fdd5f01b4c663e21936e6c38c82Mukund Sivaraman if ((dlv.digest_type == DNS_DSDIGEST_SHA256 &&
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
058e44186b74531402c1f99088eb9dbe4926f8daMark Andrews if (!dns_resolver_ds_digest_supported(val->view->resolver,
50105afc551903541608b11851d73278b23579a3Mark Andrews if (!dns_resolver_algorithm_supported(val->view->resolver,
50105afc551903541608b11851d73278b23579a3Mark Andrews dns_rdataset_clone(val->event->rdataset, &trdataset);
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews * Convert to DLV to DS and find matching DNSKEY.
cc3aafe737334d444781f8a34ffaf459e075bb9aMark Andrews "no DNSKEY matching DLV");
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews "Found matching DLV record: checking for signature");
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews * Check that this DNSKEY signed the DNSKEY rrset.
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews result = checkkey(val, &keyrdata, dlv.key_tag, dlv.algorithm);
cc3aafe737334d444781f8a34ffaf459e075bb9aMark Andrews "no RRSIG matching DLV key");
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (dlv)");
50105afc551903541608b11851d73278b23579a3Mark Andrews } else if (result == ISC_R_NOMORE && !supported_algorithm) {
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt "must be secure failure,"
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt "no supported algorithm/digest (dlv)");
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews "no supported algorithm/digest (dlv)");
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * Attempts positive response validation of an RRset containing zone keys
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * (i.e. a DNSKEY rrset).
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li ISC_R_SUCCESS Validation completed successfully
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li DNS_R_WAIT Validation has started but is waiting
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * for an event.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li Other return codes are possible and all indicate failure.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Caller must be holding the validator lock.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (val->havedlvsep && val->dlv.trust >= dns_trust_secure &&
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews dns_name_equal(event->name, dns_fixedname_name(&val->dlvsep)))
e27d55e3ee06b6edcf625b8920a5c809da7f0b98Mark Andrews * We have a dlv sep. Skip looking up the SEP from
e27d55e3ee06b6edcf625b8920a5c809da7f0b98Mark Andrews * {trusted,managed}-keys. If the dlv sep is for the
e27d55e3ee06b6edcf625b8920a5c809da7f0b98Mark Andrews * root then it will have been handled above so we don't
e27d55e3ee06b6edcf625b8920a5c809da7f0b98Mark Andrews * need to check whether val->event->name is "." prior to
e27d55e3ee06b6edcf625b8920a5c809da7f0b98Mark Andrews * looking up the DS.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * First, see if this key was signed by a trusted key.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews for (result = dns_rdataset_first(val->event->sigrdataset);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = dns_rdataset_next(val->event->sigrdataset))
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
50df1ec60af410fca6b7a85d5c85e8f31bb13bc3Mark Andrews if (!dns_name_equal(val->event->name, &sig.signer))
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = dns_keytable_findkeynode(val->keytable,
e27d55e3ee06b6edcf625b8920a5c809da7f0b98Mark Andrews "must be secure failure, "
e27d55e3ee06b6edcf625b8920a5c809da7f0b98Mark Andrews "not beneath secure root");
e27d55e3ee06b6edcf625b8920a5c809da7f0b98Mark Andrews "not beneath secure root");
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews "signed by trusted key; "
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews "marking as secure");
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews * We have not found a key to verify this DNSKEY
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews * RRset. As this is a SEP we have to assume that
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews * the RRset is invalid.
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews "unable to find a DNSKEY which verifies "
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt "the DNSKEY RRset and also matches a "
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt "trusted key for '%s'",
e27d55e3ee06b6edcf625b8920a5c809da7f0b98Mark Andrews * If this is the root name and there was no trusted key,
e27d55e3ee06b6edcf625b8920a5c809da7f0b98Mark Andrews * give up, since there's no DS at the root.
e27d55e3ee06b6edcf625b8920a5c809da7f0b98Mark Andrews if (dns_name_equal(event->name, dns_rootname)) {
e27d55e3ee06b6edcf625b8920a5c809da7f0b98Mark Andrews if ((val->attributes & VALATTR_TRIEDVERIFY) != 0) {
e27d55e3ee06b6edcf625b8920a5c809da7f0b98Mark Andrews "root key failed to validate");
e27d55e3ee06b6edcf625b8920a5c809da7f0b98Mark Andrews "no trusted root key");
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Otherwise, try to find the DS record.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = view_find(val, val->event->name, dns_rdatatype_ds);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * We have DS records.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews "validatezonekey");
a39a5f4d816ca7d3f43106712ca668dd1ab31d69Mark Andrews } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * There should never be an unsigned DS.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews "unsigned DS record");
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * We don't have the DS. Find it.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews "validatezonekey");
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * The DS does not exist.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (dns_rdataset_isassociated(&val->frdataset))
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (dns_rdataset_isassociated(&val->fsigrdataset))
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews validator_log(val, ISC_LOG_DEBUG(2), "no DS record");
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * We have a DS set.
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt "must be secure failure,"
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt " insecure DS");
ea8278253210df030a24f0c89342b43fe279a127Mark Andrews return (startfinddlvsep(val, val->event->name));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Look through the DS record and find the keys that can sign the
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * key set and the matching signature. For each such key, attempt
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * verification.
9540b42695c15fdd5f01b4c663e21936e6c38c82Mukund Sivaraman * If DNS_DSDIGEST_SHA256 or DNS_DSDIGEST_SHA384 is present we
9540b42695c15fdd5f01b4c663e21936e6c38c82Mukund Sivaraman * are required to prefer it over DNS_DSDIGEST_SHA1. This in
9540b42695c15fdd5f01b4c663e21936e6c38c82Mukund Sivaraman * practice means that we need to ignore DNS_DSDIGEST_SHA1 if a
9540b42695c15fdd5f01b4c663e21936e6c38c82Mukund Sivaraman * DNS_DSDIGEST_SHA256 or DNS_DSDIGEST_SHA384 is present.
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
9540b42695c15fdd5f01b4c663e21936e6c38c82Mukund Sivaraman if (!dns_resolver_ds_digest_supported(val->view->resolver,
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews if (!dns_resolver_algorithm_supported(val->view->resolver,
9540b42695c15fdd5f01b4c663e21936e6c38c82Mukund Sivaraman if ((ds.digest_type == DNS_DSDIGEST_SHA256 &&
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
058e44186b74531402c1f99088eb9dbe4926f8daMark Andrews if (!dns_resolver_ds_digest_supported(val->view->resolver,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (!dns_resolver_algorithm_supported(val->view->resolver,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdataset_clone(val->event->rdataset, &trdataset);
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews * Find matching DNSKEY from DS.
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews result = keyfromds(val, &trdataset, &dsrdata, ds.digest_type,
cc3aafe737334d444781f8a34ffaf459e075bb9aMark Andrews "no DNSKEY matching DS");
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews * Check that this DNSKEY signed the DNSKEY rrset.
44f175a90a855326725439b2f1178f0dcca8f67dMark Andrews result = checkkey(val, &keyrdata, ds.key_tag, ds.algorithm);
cc3aafe737334d444781f8a34ffaf459e075bb9aMark Andrews "no RRSIG matching DS key");
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (DS)");
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews } else if (result == ISC_R_NOMORE && !supported_algorithm) {
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt "must be secure failure, "
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt "no supported algorithm/digest (DS)");
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews "no supported algorithm/digest (DS)");
7048af0a551f13d2916a06cce21357714939a89bEvan Hunt "no valid signature found (DS)");
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Starts a positive response validation.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li ISC_R_SUCCESS Validation completed successfully
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li DNS_R_WAIT Validation has started but is waiting
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * for an event.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li Other return codes are possible and all indicate failure.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstart_positive_validation(dns_validator_t *val) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * If this is not a key, go straight into validate().
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews if (val->event->type != dns_rdatatype_dnskey || !isselfsigned(val))
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * val_rdataset_first and val_rdataset_next provide iteration methods
515c7f3c43f76d7b439905b18009105364b36100Automatic Updater * that hide whether we are iterating across a message or a negative
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * cache rdataset.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrewsval_rdataset_first(dns_validator_t *val, dns_name_t **namep,
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews dns_message_currentname(message, DNS_SECTION_AUTHORITY, namep);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews result = dns_rdataset_first(val->event->rdataset);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews dns_ncache_current(val->event->rdataset, *namep,
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrewsval_rdataset_next(dns_validator_t *val, dns_name_t **namep,
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews REQUIRE(rdatasetp != NULL && *rdatasetp != NULL);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews result = dns_rdataset_next(val->event->rdataset);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews dns_ncache_current(val->event->rdataset, *namep,
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Look for NODATA at the wildcard and NOWILDCARD proofs in the
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * previously validated NSEC records. As these proofs are mutually
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * exclusive we stop when one is found.
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater * \li ISC_R_SUCCESS
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewscheckwildcard(dns_validator_t *val, dns_rdatatype_t type, dns_name_t *zonename)
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews "in checkwildcard: no wildcard to check");
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_name_format(wild, namebuf, sizeof(namebuf));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews for (result = val_rdataset_first(val, &name, &rdataset);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews result = val_rdataset_next(val, &name, &rdataset))
8462dfb880040cde3a60f047ec18808737fd7e85Mark Andrews dns_nsec_noexistnodata(val->event->type, wild, name,
8462dfb880040cde3a60f047ec18808737fd7e85Mark Andrews dns_nsec3_noexistnodata(val->event->type, wild, name,
ada40193c85276867c6904545601c7c01e3236c3Mark Andrews isc_boolean_t setclosest, setnearest, *setclosestp;
ada40193c85276867c6904545601c7c01e3236c3Mark Andrews dns_name_t *closest, *nearest, *zonename, *closestp;
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews for (result = val_rdataset_first(val, &name, &rdataset);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews result = val_rdataset_next(val, &name, &rdataset))
8462dfb880040cde3a60f047ec18808737fd7e85Mark Andrews result = dns_nsec3_noexistnodata(val->event->type,
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS) {
ada40193c85276867c6904545601c7c01e3236c3Mark Andrews * If the val->closest is set then we want to use it otherwise
ada40193c85276867c6904545601c7c01e3236c3Mark Andrews * we need to discover it.
ada40193c85276867c6904545601c7c01e3236c3Mark Andrews if (dns_name_countlabels(dns_fixedname_name(&val->closest)) != 0) {
ada40193c85276867c6904545601c7c01e3236c3Mark Andrews dns_name_format(dns_fixedname_name(&val->closest),
ada40193c85276867c6904545601c7c01e3236c3Mark Andrews validator_log(val, ISC_LOG_DEBUG(3), "closest encloser from "
dfc015bc7e99019373878f8eb4527f5ebd0e0969Automatic Updater dns_name_copy(dns_fixedname_name(&val->closest), closest, NULL);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews for (result = val_rdataset_first(val, &name, &rdataset);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews result = val_rdataset_next(val, &name, &rdataset))
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * We process all NSEC3 records to find the closest
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * encloser and nearest name to the closest encloser.
8462dfb880040cde3a60f047ec18808737fd7e85Mark Andrews result = dns_nsec3_noexistnodata(val->event->type,
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * To know we have a valid noqname and optout proofs we need to also
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * have a valid closest encloser. Otherwise we could still be looking
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * at proofs from the parent zone.
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews result = dns_name_concatenate(dns_wildcardname, closest,
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * Do we need to check for the wildcard?
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews result = checkwildcard(val, dns_rdatatype_nsec3, zonename);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * Validate the authority section records.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrewsvalidate_authority(dns_validator_t *val, isc_boolean_t resume) {
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington dns_message_t *message = val->event->message;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington rdataset = ISC_LIST_NEXT(val->currentset, link);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington for (sigrdataset = ISC_LIST_HEAD(name->list);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews if (sigrdataset->type == dns_rdatatype_rrsig &&
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington * If a signed zone is missing the zone key, bad
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington * things could happen. A query for data in the zone
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington * would lead to a query for the zone key, which
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington * would return a negative answer, which would contain
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * an SOA and an NSEC signed by the missing key, which
cc3aafe737334d444781f8a34ffaf459e075bb9aMark Andrews * would trigger another query for the DNSKEY (since
cc3aafe737334d444781f8a34ffaf459e075bb9aMark Andrews * the first one is still in progress), and go into an
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington * infinite loop. Avoid that.
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews if (val->event->type == dns_rdatatype_dnskey &&
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = create_validator(val, name, rdataset->type,
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews "validate_authority");
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * Validate the ncache elements.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrewsvalidate_ncache(dns_validator_t *val, isc_boolean_t resume) {
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews result = dns_rdataset_first(val->event->rdataset);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews result = dns_rdataset_next(val->event->rdataset);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews result = dns_rdataset_next(val->event->rdataset))
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (dns_rdataset_isassociated(&val->frdataset))
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (dns_rdataset_isassociated(&val->fsigrdataset))
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews dns_ncache_current(val->event->rdataset, name, rdataset);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (val->frdataset.type == dns_rdatatype_rrsig)
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews result = dns_ncache_getsigrdataset(val->event->rdataset, name,
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * If a signed zone is missing the zone key, bad
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * things could happen. A query for data in the zone
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * would lead to a query for the zone key, which
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * would return a negative answer, which would contain
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * an SOA and an NSEC signed by the missing key, which
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * would trigger another query for the DNSKEY (since
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * the first one is still in progress), and go into an
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * infinite loop. Avoid that.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (val->event->type == dns_rdatatype_dnskey &&
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews result = create_validator(val, name, rdataset->type,
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews "validate_ncache");
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * Prove a negative answer is good or that there is a NOQNAME when the
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * answer is from a wildcard.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * Loop through the authority section looking for NODATA, NOWILDCARD
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * and NOQNAME proofs in the NSEC records by calling authvalidated().
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * If the required proofs are found we are done.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * If the proofs are not found attempt to prove this is a unsecure
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrewsnsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews validator_log(val, ISC_LOG_DEBUG(3), "resuming nsecvalidate");
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Do we only need to check for NOQNAME? To get here we must have
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * had a secure wildcard answer.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (!NEEDNODATA(val) && !NEEDNOWILDCARD(val) && NEEDNOQNAME(val)) {
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt "marking as secure, noqname proof found");
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews dns_name_countlabels(dns_fixedname_name(&val->wild))
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews "optout proof found");
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews } else if ((val->attributes & VALATTR_FOUNDUNKNOWN) != 0) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews "unknown NSEC3 hash algorithm found");
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews "noqname proof not found");
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews * Do we need to check for the wildcard?
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews result = checkwildcard(val, dns_rdatatype_nsec, NULL);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if ((NEEDNODATA(val) && (FOUNDNODATA(val) || FOUNDOPTOUT(val))) ||
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews "nonexistence proof(s) found");
bb6d33103e672d21429ae1837ce10d91f2419800Mark Andrews if (val->authfail != 0 && val->authcount == val->authfail)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews "nonexistence proof(s) not found");
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews return (proveunsecure(val, ISC_FALSE, ISC_FALSE));
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrewscheck_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) {
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
058e44186b74531402c1f99088eb9dbe4926f8daMark Andrews if (dns_resolver_ds_digest_supported(val->view->resolver,
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews dns_resolver_algorithm_supported(val->view->resolver,
0cae66577c69c89086cd065bb297690072b471b4Mark Andrewsdlvvalidated(isc_task_t *task, isc_event_t *event) {
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews validator_log(val, ISC_LOG_DEBUG(3), "in dlvvalidated");
ea8278253210df030a24f0c89342b43fe279a127Mark Andrews "dlvset with trust %s",
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews dns_rdataset_clone(&val->frdataset, &val->dlv);
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews if (dns_rdataset_isassociated(&val->frdataset))
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews if (dns_rdataset_isassociated(&val->fsigrdataset))
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews "dlvvalidated: got %s",
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Callback from fetching a DLV record.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Resumes the DLV lookup process.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrewsdlvfetched(isc_task_t *task, isc_event_t *event) {
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews /* Free resources which are not of interest. */
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews if (dns_rdataset_isassociated(&val->fsigrdataset))
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews validator_log(val, ISC_LOG_DEBUG(3), "in dlvfetched: %s",
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews dns_rdataset_clone(&val->frdataset, &val->dlv);
72dbc7216aae3626a66e6154443be219f5edcaf0Mark Andrews validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found",
72dbc7216aae3626a66e6154443be219f5edcaf0Mark Andrews "DLV %s found with no supported algorithms",
72dbc7216aae3626a66e6154443be219f5edcaf0Mark Andrews dns_name_format(dns_fixedname_name(&val->dlvsep),
72dbc7216aae3626a66e6154443be219f5edcaf0Mark Andrews "DLV %s found with no supported "
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
708383382ff1d3fdd27527e5d63120a3c6c6d3b3Francis Dupont * Start the DLV lookup process.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li ISC_R_SUCCESS
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li DNS_R_WAIT
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li Others on validation failures.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrewsstartfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews dns_name_format(unsecure, namebuf, sizeof(namebuf));
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews "plain DNSSEC returns unsecure (%s): looking for DLV",
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt validator_log(val, ISC_LOG_WARNING, "must be secure failure, "
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews val->dlvlabels = dns_name_countlabels(unsecure) - 1;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
0cfb24736841b3e98bb25853229a0efabab88bddEvan Hunt validator_log(val, ISC_LOG_DEBUG(3), "DLV covered by NTA");
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
72dbc7216aae3626a66e6154443be219f5edcaf0Mark Andrews validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf);
72dbc7216aae3626a66e6154443be219f5edcaf0Mark Andrews validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found with no supported "
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Continue the DLV lookup process.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li ISC_R_SUCCESS
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li ISC_R_NOTFOUND
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li DNS_R_WAIT
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li Others on validation failure.
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrewsfinddlvsep(dns_validator_t *val, isc_boolean_t resume) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt "must be secure failure, "
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews * If this is a response to a DS query, we need to look in
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews * the parent zone for the trust anchor.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews dns_name_getlabelsequence(dlvsep, 1, labels - 1,
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews dns_name_getlabelsequence(dlvsep, 0, labels - 1, &noroot);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews result = dns_name_concatenate(&noroot, val->view->dlv, dlvname, NULL);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews dns_name_getlabelsequence(dlvsep, 0, labels - 2, &noroot);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews result = dns_name_concatenate(&noroot, val->view->dlv,
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews validator_log(val, ISC_LOG_DEBUG(2), "DLV concatenate failed");
b8a9632333a92d73a503afe1aaa7990016c8bee9Evan Hunt if (((val->options & DNS_VALIDATOR_NONTA) == 0) &&
b8a9632333a92d73a503afe1aaa7990016c8bee9Evan Hunt dns_view_ntacovers(val->view, val->start, dlvname, val->view->dlv))
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews dns_name_countlabels(val->view->dlv) + val->dlvlabels) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews dns_name_format(dlvname, namebuf, sizeof(namebuf));
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV %s",
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews result = view_find(val, dlvname, dns_rdatatype_dlv);
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews "finddlvsep");
7048af0a551f13d2916a06cce21357714939a89bEvan Hunt "DLV not validated");
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews dns_rdataset_clone(&val->frdataset, &val->dlv);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews result = create_fetch(val, dlvname, dns_rdatatype_dlv,
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews * Strip first labels from both dlvsep and dlvname.
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews dns_name_getlabelsequence(dlvname, 1, labels - 1, dlvname);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * proveunsecure walks down from the SEP looking for a break in the
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * chain of trust. That occurs when we can prove the DS record does
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * not exist at a delegation point or the DS exists at a delegation
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * but we don't support the algorithm/digest.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * If DLV is active and we look for a DLV record at or below the
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * point we go insecure. If found we restart the validation process.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * If not found or DLV isn't active we mark the response as a answer.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li ISC_R_SUCCESS val->event->name is in a unsecure zone
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li DNS_R_WAIT validation is in progress.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li DNS_R_MUSTBESECURE val->event->name is supposed to be secure
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * (policy) but we proved that it is unsecure.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li DNS_R_NOVALIDSIG
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li DNS_R_NOVALIDNSEC
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li DNS_R_NOTINSECURE
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews * \li DNS_R_BROKENCHAIN
e4d304b70b81ca9956c2eff7c24aacf4dd00266eEvan Huntproveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews dns_name_copy(dns_fixedname_name(&val->dlvsep), secroot, NULL);
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews dns_name_copy(val->event->name, secroot, NULL);
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews * If this is a response to a DS query, we need to look in
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews * the parent zone for the trust anchor.
9ead684875ab0ab5fdb8b5dd837a88f7dbd0e01dEvan Hunt if (val->event->type == dns_rdatatype_ds && labels > 1U)
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews result = dns_keytable_finddeepestmatch(val->keytable,
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt "must be secure failure, "
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt "not beneath secure root");
7048af0a551f13d2916a06cce21357714939a89bEvan Hunt "not beneath secure root");
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * We are looking for breaks below the SEP so add a label.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews val->labels = dns_name_countlabels(secroot) + 1;
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews * If we have a DS rdataset and it is secure then check if
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews * the DS rdataset has a supported algorithm combination.
bfe0517fdcbe1dc62fee18e460ecf467dd491d9bEvan Hunt * If not this is an insecure delegation as far as this
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews * resolver is concerned. Fall back to DLV if available.
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews if (have_ds && val->frdataset.trust >= dns_trust_secure &&
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews !check_ds(val, dns_fixedname_name(&val->fname),
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews dns_name_format(dns_fixedname_name(&val->fname),
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews if ((val->view->dlv == NULL || DLVTRIED(val)) &&
7048af0a551f13d2916a06cce21357714939a89bEvan Hunt "must be secure failure at '%s', "
7048af0a551f13d2916a06cce21357714939a89bEvan Hunt "can't fall back to DLV",
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews "no supported algorithm/digest (%s/DS)",
e407562a75eb93073bb72089cced150d7ffe4d4fTatuya JINMEI 神明達哉 val->labels <= dns_name_countlabels(val->event->name);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (val->labels == dns_name_countlabels(val->event->name))
e407562a75eb93073bb72089cced150d7ffe4d4fTatuya JINMEI 神明達哉 dns_name_split(val->event->name, val->labels,
6036112f4874637240d461c3ccbcb8dbfb1f405bAndreas Gustafsson dns_name_format(tname, namebuf, sizeof(namebuf));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews "checking existence of DS at '%s'",
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = view_find(val, tname, dns_rdatatype_ds);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * There is no DS. If this is a delegation,
bfe0517fdcbe1dc62fee18e460ecf467dd491d9bEvan Hunt * we may be done.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * If we have "trust == answer" then this namespace
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * has switched from insecure to should be secure.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews "proveunsecure");
e7eede965dbc67842cb32591a8c2ace2620e5359Mark Andrews * Zones using NSEC3 don't return a NSEC RRset so
e7eede965dbc67842cb32591a8c2ace2620e5359Mark Andrews * we need to use dns_view_findzonecut2 to find
e7eede965dbc67842cb32591a8c2ace2620e5359Mark Andrews * the zone cut.
7048af0a551f13d2916a06cce21357714939a89bEvan Hunt "must be secure failure, "
7048af0a551f13d2916a06cce21357714939a89bEvan Hunt "no DS at zone cut");
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * This shouldn't happen, since the negative
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * response should have been validated. Since
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * there's no way of validating existing
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * negative response blobs, give up.
7048af0a551f13d2916a06cce21357714939a89bEvan Hunt "can't validate existing "
7048af0a551f13d2916a06cce21357714939a89bEvan Hunt "negative responses (no DS)");
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (isdelegation(tname, &val->frdataset, result)) {
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt "must be secure failure, "
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt "%s is a delegation",
4b45a8fc5a47dcff7473003ceeac6f6bb3e21e79Mark Andrews "proveunsecure "
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * There is a DS here. Verify that it's secure and
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (val->frdataset.trust >= dns_trust_secure) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews "no supported algorithm/"
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt "must be secure failure, "
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt "no supported algorithm/"
be69d484434e10d920c4d8a8bb735356eb0c2cc8Evan Hunt "digest (%s/DS)",
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews "proveunsecure (5)");
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews else if (!dns_rdataset_isassociated(&val->fsigrdataset))
7048af0a551f13d2916a06cce21357714939a89bEvan Hunt "DS is unsigned");
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * Validate / re-validate answer.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = create_validator(val, tname, dns_rdatatype_ds,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews "proveunsecure");
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * This is not a zone cut. Assuming things are
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * as expected, continue.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (!dns_rdataset_isassociated(&val->frdataset)) {
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * There should be an NSEC here, since we
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * are still in a secure zone.
a27b3757fdd8976ce05e37f391ad9e7ac4638e5dMark Andrews } else if (DNS_TRUST_PENDING(val->frdataset.trust) ||
a27b3757fdd8976ce05e37f391ad9e7ac4638e5dMark Andrews * If we have "trust == answer" then this namespace
a27b3757fdd8976ce05e37f391ad9e7ac4638e5dMark Andrews * has switched from insecure to should be secure.
a27b3757fdd8976ce05e37f391ad9e7ac4638e5dMark Andrews "proveunsecure");
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews } else if (val->frdataset.trust < dns_trust_secure) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * This shouldn't happen, since the negative
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * response should have been validated. Since
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * there's no way of validating existing
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * negative response blobs, give up.
7048af0a551f13d2916a06cce21357714939a89bEvan Hunt "can't validate existing "
7048af0a551f13d2916a06cce21357714939a89bEvan Hunt "negative responses "
7048af0a551f13d2916a06cce21357714939a89bEvan Hunt "(not a zone cut)");
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * We don't know anything about the DS. Find it.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = create_fetch(val, tname, dns_rdatatype_ds,
bfe0517fdcbe1dc62fee18e460ecf467dd491d9bEvan Hunt /* Couldn't complete insecurity proof */
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed");
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington if (dns_rdataset_isassociated(&val->frdataset))
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_rdataset_disassociate(&val->frdataset);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington if (dns_rdataset_isassociated(&val->fsigrdataset))
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_rdataset_disassociate(&val->fsigrdataset);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Reset state and revalidate the answer using DLV.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews validator_log(val, ISC_LOG_DEBUG(3), "dlv_validator_start");
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * Reset state and try again.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Start the validation process.
708383382ff1d3fdd27527e5d63120a3c6c6d3b3Francis Dupont * Attempt to validate the answer based on the category it appears to
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li 1. secure positive answer.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li 2. unsecure positive answer.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * \li 3. a negative answer (secure or unsecure).
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Note a answer that appears to be a secure positive answer may actually
bfe0517fdcbe1dc62fee18e460ecf467dd491d9bEvan Hunt * be an unsecure positive answer.
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellingtonvalidator_start(isc_task_t *task, isc_event_t *event) {
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff REQUIRE(event->ev_type == DNS_EVENT_VALIDATORSTART);
708383382ff1d3fdd27527e5d63120a3c6c6d3b3Francis Dupont /* If the validator has been canceled, val->event == NULL */
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews validator_log(val, ISC_LOG_DEBUG(3), "restarting using DLV");
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews validator_log(val, ISC_LOG_DEBUG(3), "starting");
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV");
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * This looks like a simple validation. We say "looks like"
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * because it might end up requiring an insecurity proof.
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington "attempting positive response validation");
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews INSIST(dns_rdataset_isassociated(val->event->rdataset));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews INSIST(dns_rdataset_isassociated(val->event->sigrdataset));
6bc1a645619a14707da68b130dafe41721fd2f25Brian Wellington (val->attributes & VALATTR_TRIEDVERIFY) == 0)
6bc1a645619a14707da68b130dafe41721fd2f25Brian Wellington "falling back to insecurity proof");
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson * This is either an unsecure subdomain or a response from
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson * a broken server.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews INSIST(dns_rdataset_isassociated(val->event->rdataset));
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington "attempting insecurity proof");
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
bfe0517fdcbe1dc62fee18e460ecf467dd491d9bEvan Hunt "got insecure response; "
6b9728dde7c7ca15b19ea65ae35d9425c0d340caEvan Hunt "parent indicates it should be secure");
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * This is a nonexistence validation.
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington "attempting negative response validation");
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (val->event->message->rcode == dns_rcode_nxdomain) {
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * This is a nonexistence validation.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews "attempting negative response validation");
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (val->event->rdataset->covers == dns_rdatatype_any) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * This shouldn't happen.
ec371edc34e2adb9e337b774d1a6e613f5863655Brian Wellingtondns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley isc_task_t *task, isc_taskaction_t action, void *arg,
ec371edc34e2adb9e337b774d1a6e613f5863655Brian Wellington (rdataset == NULL && sigrdataset == NULL && message != NULL));
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley REQUIRE(validatorp != NULL && *validatorp == NULL);
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson val = isc_mem_get(view->mctx, sizeof(*val));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews memset(event->proofs, 0, sizeof(event->proofs));
95f2377b4f180a564d35343c8d150e8f03c98a52Evan Hunt result = dns_view_getsecroots(val->view, &val->keytable);
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson isc_mem_put(view->mctx, val, sizeof(*val));
305227476756aecb11cebbc811dba88a2d147b34Mark Andrewsdns_validator_send(dns_validator_t *validator) {
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews INSIST((validator->options & DNS_VALIDATOR_DEFER) != 0);
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews isc_task_send(validator->task, ISC_EVENT_PTR(&event));
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halleydns_validator_cancel(dns_validator_t *validator) {
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
22c4126ba51175af1453cd2254c303c6f65a766cMark Andrews if ((validator->attributes & VALATTR_CANCELED) == 0) {
22c4126ba51175af1453cd2254c303c6f65a766cMark Andrews if ((validator->options & DNS_VALIDATOR_DEFER) != 0) {
39bfdc2ff9da3c2ecdbc70d46cabfd56d66f24f6Mark Andrews /* Need to cancel and destroy the fetch outside validator lock */
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley dns_keytable_detachkeynode(val->keytable, &val->keynode);
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews if (dns_rdataset_isassociated(&val->frdataset))
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews if (dns_rdataset_isassociated(&val->fsigrdataset))
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo));
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halleydns_validator_destroy(dns_validator_t **validatorp) {
1d761cb453c76353deb8423c78e98d00c5f86ffaEvan Hunt validator_log(val, ISC_LOG_DEBUG(4), "dns_validator_destroy");
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafssonvalidator_logv(dns_validator_t *val, isc_logcategory_t *category,
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington isc_logmodule_t *module, int level, const char *fmt, va_list ap)
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington if (val->event != NULL && val->event->name != NULL) {
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson dns_name_format(val->event->name, namebuf, sizeof(namebuf));
18b7133679efa8f60fd4e396c628576f3f416b3eBrian Wellington dns_rdatatype_format(val->event->type, typebuf,
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson isc_log_write(dns_lctx, category, module, level,
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson isc_log_write(dns_lctx, category, module, level,
8462dfb880040cde3a60f047ec18808737fd7e85Mark Andrewsvalidator_log(void *val, int level, const char *fmt, ...) {
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson validator_logv(val, DNS_LOGCATEGORY_DNSSEC,
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson DNS_LOGMODULE_VALIDATOR, level, fmt, ap);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_format(name, namestr, sizeof(namestr));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdatatype_format(type, typestr, sizeof(typestr));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews validator_log(val, ISC_LOG_DEBUG(9), "%s: creating %s for %s %s",