mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-02 23:55:27 +00:00
Support PRIVATEOID/PRIVATEDNS in the validator
DS records need to checked against the DNSKEY RRset to find the private algorithm they correspond to.
This commit is contained in:
@@ -137,6 +137,7 @@ struct dns_validator {
|
|||||||
dns_rdataset_t fdsset;
|
dns_rdataset_t fdsset;
|
||||||
dns_rdataset_t frdataset;
|
dns_rdataset_t frdataset;
|
||||||
dns_rdataset_t fsigrdataset;
|
dns_rdataset_t fsigrdataset;
|
||||||
|
dns_rdataset_t dsrdataset;
|
||||||
dns_fixedname_t fname;
|
dns_fixedname_t fname;
|
||||||
dns_fixedname_t wild;
|
dns_fixedname_t wild;
|
||||||
dns_fixedname_t closest;
|
dns_fixedname_t closest;
|
||||||
|
@@ -146,7 +146,8 @@ static isc_result_t
|
|||||||
validate_nx(dns_validator_t *val, bool resume);
|
validate_nx(dns_validator_t *val, bool resume);
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
proveunsecure(dns_validator_t *val, bool have_ds, bool resume);
|
proveunsecure(dns_validator_t *val, bool have_ds, bool have_dnskey,
|
||||||
|
bool resume);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
validator_logv(dns_validator_t *val, isc_logcategory_t category,
|
validator_logv(dns_validator_t *val, isc_logcategory_t category,
|
||||||
@@ -397,6 +398,13 @@ fetch_callback_dnskey(void *arg) {
|
|||||||
dns_rdataset_t *rdataset = &val->frdataset;
|
dns_rdataset_t *rdataset = &val->frdataset;
|
||||||
isc_result_t eresult = resp->result;
|
isc_result_t eresult = resp->result;
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
|
bool trustchain;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set 'trustchain' to true if we're walking a chain of
|
||||||
|
* trust; false if we're attempting to prove insecurity.
|
||||||
|
*/
|
||||||
|
trustchain = ((val->attributes & VALATTR_INSECURITY) == 0);
|
||||||
|
|
||||||
/* Free resources which are not of interest. */
|
/* Free resources which are not of interest. */
|
||||||
if (resp->node != NULL) {
|
if (resp->node != NULL) {
|
||||||
@@ -418,34 +426,55 @@ fetch_callback_dnskey(void *arg) {
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (eresult) {
|
if (trustchain) {
|
||||||
case ISC_R_SUCCESS:
|
switch (eresult) {
|
||||||
case DNS_R_NCACHENXRRSET:
|
case ISC_R_SUCCESS:
|
||||||
/*
|
case DNS_R_NCACHENXRRSET:
|
||||||
* We have an answer to our DNSKEY query. Either the DNSKEY
|
/*
|
||||||
* RRset or a NODATA response.
|
* We have an answer to our DNSKEY query. Either the
|
||||||
*/
|
* DNSKEY RRset or a NODATA response.
|
||||||
validator_log(val, ISC_LOG_DEBUG(3), "%s with trust %s",
|
*/
|
||||||
eresult == ISC_R_SUCCESS ? "keyset"
|
validator_log(val, ISC_LOG_DEBUG(3), "%s with trust %s",
|
||||||
: "NCACHENXRRSET",
|
eresult == ISC_R_SUCCESS
|
||||||
dns_trust_totext(rdataset->trust));
|
? "keyset"
|
||||||
/*
|
: "NCACHENXRRSET",
|
||||||
* Only extract the dst key if the keyset exists and is secure.
|
dns_trust_totext(rdataset->trust));
|
||||||
*/
|
/*
|
||||||
if (eresult == ISC_R_SUCCESS &&
|
* Only extract the dst key if the keyset exists and is
|
||||||
rdataset->trust >= dns_trust_secure)
|
* secure.
|
||||||
{
|
*/
|
||||||
result = validate_helper_run(val,
|
if (eresult == ISC_R_SUCCESS &&
|
||||||
resume_answer_with_key);
|
rdataset->trust >= dns_trust_secure)
|
||||||
} else {
|
{
|
||||||
result = validate_async_run(val, resume_answer);
|
result = validate_helper_run(
|
||||||
|
val, resume_answer_with_key);
|
||||||
|
} else {
|
||||||
|
result = validate_async_run(val, resume_answer);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
validator_log(val, ISC_LOG_DEBUG(3),
|
||||||
|
"fetch_callback_dnskey: got %s",
|
||||||
|
isc_result_totext(eresult));
|
||||||
|
result = DNS_R_BROKENCHAIN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (eresult) {
|
||||||
|
case ISC_R_SUCCESS:
|
||||||
|
/*
|
||||||
|
* We have a DS (val->dsrdataset) and
|
||||||
|
* DNSKEY (val->fdataset).
|
||||||
|
*/
|
||||||
|
result = proveunsecure(val, false, true, true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
validator_log(val, ISC_LOG_DEBUG(3),
|
||||||
|
"fetch_callback_dnskey: got %s",
|
||||||
|
isc_result_totext(eresult));
|
||||||
|
result = DNS_R_BROKENCHAIN;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
default:
|
|
||||||
validator_log(val, ISC_LOG_DEBUG(3),
|
|
||||||
"fetch_callback_dnskey: got %s",
|
|
||||||
isc_result_totext(eresult));
|
|
||||||
result = DNS_R_BROKENCHAIN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
@@ -518,7 +547,7 @@ fetch_callback_ds(void *arg) {
|
|||||||
validator_log(val, ISC_LOG_DEBUG(3),
|
validator_log(val, ISC_LOG_DEBUG(3),
|
||||||
"falling back to insecurity proof (%s)",
|
"falling back to insecurity proof (%s)",
|
||||||
isc_result_totext(eresult));
|
isc_result_totext(eresult));
|
||||||
result = proveunsecure(val, false, false);
|
result = proveunsecure(val, false, false, false);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
validator_log(val, ISC_LOG_DEBUG(3),
|
validator_log(val, ISC_LOG_DEBUG(3),
|
||||||
@@ -537,7 +566,7 @@ fetch_callback_ds(void *arg) {
|
|||||||
* trust.
|
* trust.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
result = proveunsecure(val, false, true);
|
result = proveunsecure(val, false, false, true);
|
||||||
break;
|
break;
|
||||||
case ISC_R_SUCCESS:
|
case ISC_R_SUCCESS:
|
||||||
/*
|
/*
|
||||||
@@ -546,7 +575,7 @@ fetch_callback_ds(void *arg) {
|
|||||||
* so keep looking for the break in the chain
|
* so keep looking for the break in the chain
|
||||||
* of trust.
|
* of trust.
|
||||||
*/
|
*/
|
||||||
result = proveunsecure(val, true, true);
|
result = proveunsecure(val, true, false, true);
|
||||||
break;
|
break;
|
||||||
case DNS_R_NXRRSET:
|
case DNS_R_NXRRSET:
|
||||||
case DNS_R_NCACHENXRRSET:
|
case DNS_R_NCACHENXRRSET:
|
||||||
@@ -567,13 +596,14 @@ fetch_callback_ds(void *arg) {
|
|||||||
* Not a zone cut, so we have to keep looking for
|
* Not a zone cut, so we have to keep looking for
|
||||||
* the break point in the chain of trust.
|
* the break point in the chain of trust.
|
||||||
*/
|
*/
|
||||||
result = proveunsecure(val, false, true);
|
result = proveunsecure(val, false, false, true);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
validator_log(val, ISC_LOG_DEBUG(3),
|
validator_log(val, ISC_LOG_DEBUG(3),
|
||||||
"fetch_callback_ds: got %s",
|
"fetch_callback_ds: got %s",
|
||||||
isc_result_totext(eresult));
|
isc_result_totext(eresult));
|
||||||
result = DNS_R_BROKENCHAIN;
|
result = DNS_R_BROKENCHAIN;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,7 +703,7 @@ validator_callback_ds(void *arg) {
|
|||||||
{
|
{
|
||||||
result = markanswer(val, "validator_callback_ds");
|
result = markanswer(val, "validator_callback_ds");
|
||||||
} else if ((val->attributes & VALATTR_INSECURITY) != 0) {
|
} else if ((val->attributes & VALATTR_INSECURITY) != 0) {
|
||||||
result = proveunsecure(val, have_dsset, true);
|
result = proveunsecure(val, have_dsset, false, true);
|
||||||
} else {
|
} else {
|
||||||
result = validate_async_run(val, validate_dnskey);
|
result = validate_async_run(val, validate_dnskey);
|
||||||
}
|
}
|
||||||
@@ -724,7 +754,7 @@ validator_callback_cname(void *arg) {
|
|||||||
if (eresult == ISC_R_SUCCESS) {
|
if (eresult == ISC_R_SUCCESS) {
|
||||||
validator_log(val, ISC_LOG_DEBUG(3), "cname with trust %s",
|
validator_log(val, ISC_LOG_DEBUG(3), "cname with trust %s",
|
||||||
dns_trust_totext(val->frdataset.trust));
|
dns_trust_totext(val->frdataset.trust));
|
||||||
result = proveunsecure(val, false, true);
|
result = proveunsecure(val, false, false, true);
|
||||||
} else {
|
} else {
|
||||||
if (eresult != DNS_R_BROKENCHAIN) {
|
if (eresult != DNS_R_BROKENCHAIN) {
|
||||||
expire_rdatasets(val);
|
expire_rdatasets(val);
|
||||||
@@ -832,6 +862,7 @@ validator_callback_nsec(void *arg) {
|
|||||||
FALLTHROUGH;
|
FALLTHROUGH;
|
||||||
default:
|
default:
|
||||||
result = validate_nx(val, true);
|
result = validate_nx(val, true);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1364,6 +1395,7 @@ selfsigned_dnskey(dns_validator_t *val) {
|
|||||||
return ISC_R_QUOTA;
|
return ISC_R_QUOTA;
|
||||||
}
|
}
|
||||||
consume_validation_fail(val);
|
consume_validation_fail(val);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else if (rdataset->trust >= dns_trust_secure) {
|
} else if (rdataset->trust >= dns_trust_secure) {
|
||||||
/*
|
/*
|
||||||
@@ -1469,6 +1501,7 @@ again:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
consume_validation_fail(val);
|
consume_validation_fail(val);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1815,7 +1848,7 @@ validate_async_done(dns_validator_t *val, isc_result_t result) {
|
|||||||
isc_result_t saved_result = result;
|
isc_result_t saved_result = result;
|
||||||
validator_log(val, ISC_LOG_DEBUG(3),
|
validator_log(val, ISC_LOG_DEBUG(3),
|
||||||
"falling back to insecurity proof");
|
"falling back to insecurity proof");
|
||||||
result = proveunsecure(val, false, false);
|
result = proveunsecure(val, false, false, false);
|
||||||
if (result == DNS_R_NOTINSECURE) {
|
if (result == DNS_R_NOTINSECURE) {
|
||||||
result = saved_result;
|
result = saved_result;
|
||||||
}
|
}
|
||||||
@@ -1976,6 +2009,7 @@ validate_dnskey_dsset_done(dns_validator_t *val, isc_result_t result) {
|
|||||||
validator_log(val, ISC_LOG_INFO,
|
validator_log(val, ISC_LOG_INFO,
|
||||||
"no valid signature found (DS)");
|
"no valid signature found (DS)");
|
||||||
result = DNS_R_NOVALIDSIG;
|
result = DNS_R_NOVALIDSIG;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val->dsset == &val->fdsset) {
|
if (val->dsset == &val->fdsset) {
|
||||||
@@ -1992,6 +2026,7 @@ validate_dnskey_dsset(dns_validator_t *val) {
|
|||||||
dns_rdata_t keyrdata = DNS_RDATA_INIT;
|
dns_rdata_t keyrdata = DNS_RDATA_INIT;
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
dns_rdata_ds_t ds;
|
dns_rdata_ds_t ds;
|
||||||
|
dns_rdata_dnskey_t key;
|
||||||
|
|
||||||
dns_rdata_reset(&dsrdata);
|
dns_rdata_reset(&dsrdata);
|
||||||
dns_rdataset_current(val->dsset, &dsrdata);
|
dns_rdataset_current(val->dsset, &dsrdata);
|
||||||
@@ -2011,13 +2046,18 @@ validate_dnskey_dsset(dns_validator_t *val) {
|
|||||||
return DNS_R_BADALG;
|
return DNS_R_BADALG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dns_resolver_algorithm_supported(val->view->resolver, val->name,
|
if (ds.algorithm != DNS_KEYALG_PRIVATEDNS &&
|
||||||
ds.algorithm, NULL, 0))
|
ds.algorithm != DNS_KEYALG_PRIVATEOID)
|
||||||
{
|
{
|
||||||
if (val->unsupported_algorithm == 0) {
|
if (!dns_resolver_algorithm_supported(val->view->resolver,
|
||||||
val->unsupported_algorithm = ds.algorithm;
|
val->name, ds.algorithm,
|
||||||
|
NULL, 0))
|
||||||
|
{
|
||||||
|
if (val->unsupported_algorithm == 0) {
|
||||||
|
val->unsupported_algorithm = ds.algorithm;
|
||||||
|
}
|
||||||
|
return DNS_R_BADALG;
|
||||||
}
|
}
|
||||||
return DNS_R_BADALG;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2030,6 +2070,25 @@ validate_dnskey_dsset(dns_validator_t *val) {
|
|||||||
return DNS_R_NOKEYMATCH;
|
return DNS_R_NOKEYMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Figure out if the private algorithm is supported now that we have
|
||||||
|
* found a matching dnskey.
|
||||||
|
*/
|
||||||
|
dns_rdata_tostruct(&keyrdata, &key, NULL);
|
||||||
|
if (ds.algorithm == DNS_KEYALG_PRIVATEDNS ||
|
||||||
|
ds.algorithm == DNS_KEYALG_PRIVATEOID)
|
||||||
|
{
|
||||||
|
if (!dns_resolver_algorithm_supported(val->view->resolver,
|
||||||
|
val->name, key.algorithm,
|
||||||
|
key.data, key.datalen))
|
||||||
|
{
|
||||||
|
if (val->unsupported_algorithm == 0) {
|
||||||
|
val->unsupported_algorithm = key.algorithm;
|
||||||
|
}
|
||||||
|
return DNS_R_BADALG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ... and check that it signed the DNSKEY RRset.
|
* ... and check that it signed the DNSKEY RRset.
|
||||||
*/
|
*/
|
||||||
@@ -2896,7 +2955,31 @@ validate_nx(dns_validator_t *val, bool resume) {
|
|||||||
return DNS_R_BROKENCHAIN;
|
return DNS_R_BROKENCHAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
return proveunsecure(val, false, false);
|
return proveunsecure(val, false, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if any of the DS records has a private DNSSEC algorithm.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
check_ds_private(dns_rdataset_t *rdataset) {
|
||||||
|
dns_rdata_ds_t ds;
|
||||||
|
isc_result_t result;
|
||||||
|
|
||||||
|
for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
|
||||||
|
result = dns_rdataset_next(rdataset))
|
||||||
|
{
|
||||||
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||||
|
dns_rdataset_current(rdataset, &rdata);
|
||||||
|
result = dns_rdata_tostruct(&rdata, &ds, NULL);
|
||||||
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
if (ds.algorithm == DNS_KEYALG_PRIVATEDNS ||
|
||||||
|
ds.algorithm == DNS_KEYALG_PRIVATEOID)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*%
|
/*%
|
||||||
@@ -2905,20 +2988,65 @@ validate_nx(dns_validator_t *val, bool resume) {
|
|||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
check_ds_algs(dns_validator_t *val, dns_name_t *name,
|
check_ds_algs(dns_validator_t *val, dns_name_t *name,
|
||||||
dns_rdataset_t *rdataset) {
|
dns_rdataset_t *dsrdataset, dns_rdataset_t *dnskeyset) {
|
||||||
dns_rdata_ds_t ds;
|
dns_rdata_ds_t ds;
|
||||||
|
dns_rdata_dnskey_t key;
|
||||||
|
bool seen_private = false;
|
||||||
|
uint16_t key_tag = 0;
|
||||||
|
uint8_t algorithm = 0;
|
||||||
|
|
||||||
DNS_RDATASET_FOREACH (rdataset) {
|
DNS_RDATASET_FOREACH (dsrdataset) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
dns_rdata_t dsrdata = DNS_RDATA_INIT;
|
dns_rdata_t dsrdata = DNS_RDATA_INIT;
|
||||||
dns_rdataset_current(rdataset, &dsrdata);
|
dns_rdata_t keyrdata = DNS_RDATA_INIT;
|
||||||
|
unsigned char *data = NULL;
|
||||||
|
size_t datalen = 0;
|
||||||
|
|
||||||
|
dns_rdataset_current(dsrdataset, &dsrdata);
|
||||||
result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
|
result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
|
||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look for a matching DNSKEY to find the PRIVATE
|
||||||
|
* DNSSEC algorithm.
|
||||||
|
*/
|
||||||
|
if (ds.algorithm == DNS_KEYALG_PRIVATEOID ||
|
||||||
|
ds.algorithm == DNS_KEYALG_PRIVATEDNS)
|
||||||
|
{
|
||||||
|
switch (ds.digest_type) {
|
||||||
|
case DNS_DSDIGEST_SHA1:
|
||||||
|
case DNS_DSDIGEST_SHA256:
|
||||||
|
case DNS_DSDIGEST_SHA384:
|
||||||
|
if (dnskeyset == NULL) {
|
||||||
|
algorithm = ds.algorithm;
|
||||||
|
key_tag = ds.key_tag;
|
||||||
|
seen_private = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result = dns_dnssec_matchdskey(
|
||||||
|
name, &dsrdata, dnskeyset, &keyrdata);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
algorithm = ds.algorithm;
|
||||||
|
key_tag = ds.key_tag;
|
||||||
|
seen_private = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result = dns_rdata_tostruct(&keyrdata, &key,
|
||||||
|
NULL);
|
||||||
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
data = key.data;
|
||||||
|
datalen = key.datalen;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (dns_resolver_ds_digest_supported(val->view->resolver, name,
|
if (dns_resolver_ds_digest_supported(val->view->resolver, name,
|
||||||
ds.digest_type) &&
|
ds.digest_type) &&
|
||||||
dns_resolver_algorithm_supported(val->view->resolver, name,
|
dns_resolver_algorithm_supported(val->view->resolver, name,
|
||||||
ds.algorithm, NULL, 0))
|
ds.algorithm, data,
|
||||||
|
datalen))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2929,8 +3057,25 @@ check_ds_algs(dns_validator_t *val, dns_name_t *name,
|
|||||||
* unsecure flow always runs after a validate/validatenx flow. So if an
|
* unsecure flow always runs after a validate/validatenx flow. So if an
|
||||||
* unsupported alg/digest was found while building the chain of trust,
|
* unsupported alg/digest was found while building the chain of trust,
|
||||||
* it would be raised already.
|
* it would be raised already.
|
||||||
|
*
|
||||||
|
* If we have seen a private algorithm for which we couldn't find a
|
||||||
|
* DNSKEY we must assume the child zone is secure. With PRIVATEDNS and
|
||||||
|
* PRIVATEOID we can only make that determination if we match a DNSKEY
|
||||||
|
* for every DS with these algorithms. Since we don't know whether the
|
||||||
|
* private algorithm is unsupported or not, we are required to treat it
|
||||||
|
* as supported.
|
||||||
*/
|
*/
|
||||||
return false;
|
if (seen_private) {
|
||||||
|
char namebuf[DNS_NAME_FORMATSIZE];
|
||||||
|
dns_name_format(name, namebuf, sizeof(namebuf));
|
||||||
|
validator_log(val, ISC_LOG_INFO,
|
||||||
|
"No DNSKEY for %s/DS with %s algorithm, tag %u",
|
||||||
|
namebuf,
|
||||||
|
algorithm == DNS_KEYALG_PRIVATEDNS ? "PRIVATEDNS"
|
||||||
|
: "PRIVATEOID",
|
||||||
|
key_tag);
|
||||||
|
}
|
||||||
|
return seen_private;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*%
|
/*%
|
||||||
@@ -2973,7 +3118,49 @@ seek_ds(dns_validator_t *val, isc_result_t *resp) {
|
|||||||
* validated, continue walking down labels.
|
* validated, continue walking down labels.
|
||||||
*/
|
*/
|
||||||
if (val->frdataset.trust >= dns_trust_secure) {
|
if (val->frdataset.trust >= dns_trust_secure) {
|
||||||
if (!check_ds_algs(val, tname, &val->frdataset)) {
|
dns_rdataset_t *dssetp = &val->frdataset,
|
||||||
|
*keysetp = NULL;
|
||||||
|
|
||||||
|
if (check_ds_private(&val->frdataset)) {
|
||||||
|
if (dns_rdataset_isassociated(&val->dsrdataset))
|
||||||
|
{
|
||||||
|
dns_rdataset_disassociate(
|
||||||
|
&val->dsrdataset);
|
||||||
|
}
|
||||||
|
dns_rdataset_clone(&val->frdataset,
|
||||||
|
&val->dsrdataset);
|
||||||
|
dssetp = &val->dsrdataset;
|
||||||
|
dns_rdataset_disassociate(&val->frdataset);
|
||||||
|
result = view_find(val, tname,
|
||||||
|
dns_rdatatype_dnskey);
|
||||||
|
switch (result) {
|
||||||
|
case ISC_R_SUCCESS:
|
||||||
|
keysetp = &val->frdataset;
|
||||||
|
break;
|
||||||
|
case ISC_R_NOTFOUND:
|
||||||
|
/*
|
||||||
|
* We don't know anything about the
|
||||||
|
* DNSKEY. Find it.
|
||||||
|
*/
|
||||||
|
*resp = DNS_R_WAIT;
|
||||||
|
result = create_fetch(
|
||||||
|
val, tname,
|
||||||
|
dns_rdatatype_dnskey,
|
||||||
|
fetch_callback_dnskey,
|
||||||
|
"seek_ds");
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
*resp = result;
|
||||||
|
}
|
||||||
|
return ISC_R_COMPLETE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
validator_log(val, ISC_LOG_DEBUG(3),
|
||||||
|
"no DNSKEY found (%s/DS)",
|
||||||
|
namebuf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!check_ds_algs(val, tname, dssetp, keysetp)) {
|
||||||
validator_log(
|
validator_log(
|
||||||
val, ISC_LOG_DEBUG(3),
|
val, ISC_LOG_DEBUG(3),
|
||||||
"no supported algorithm/digest (%s/DS)",
|
"no supported algorithm/digest (%s/DS)",
|
||||||
@@ -3162,13 +3349,16 @@ seek_ds(dns_validator_t *val, isc_result_t *resp) {
|
|||||||
* \li DNS_R_BROKENCHAIN
|
* \li DNS_R_BROKENCHAIN
|
||||||
*/
|
*/
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
proveunsecure(dns_validator_t *val, bool have_ds, bool resume) {
|
proveunsecure(dns_validator_t *val, bool have_ds, bool have_dnskey,
|
||||||
|
bool resume) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
char namebuf[DNS_NAME_FORMATSIZE];
|
char namebuf[DNS_NAME_FORMATSIZE];
|
||||||
dns_fixedname_t fixedsecroot;
|
dns_fixedname_t fixedsecroot;
|
||||||
dns_name_t *secroot = dns_fixedname_initname(&fixedsecroot);
|
dns_name_t *secroot = dns_fixedname_initname(&fixedsecroot);
|
||||||
unsigned int labels;
|
unsigned int labels;
|
||||||
|
|
||||||
|
INSIST(!(have_ds && have_dnskey));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We're attempting to prove insecurity.
|
* We're attempting to prove insecurity.
|
||||||
*/
|
*/
|
||||||
@@ -3208,17 +3398,65 @@ proveunsecure(dns_validator_t *val, bool have_ds, bool resume) {
|
|||||||
* it has a supported algorithm combination. If not, this is
|
* it has a supported algorithm combination. If not, this is
|
||||||
* an insecure delegation as far as this resolver is concerned.
|
* an insecure delegation as far as this resolver is concerned.
|
||||||
*/
|
*/
|
||||||
if (have_ds && val->frdataset.trust >= dns_trust_secure &&
|
if (have_dnskey ||
|
||||||
!check_ds_algs(val, dns_fixedname_name(&val->fname),
|
(have_ds && val->frdataset.trust >= dns_trust_secure))
|
||||||
&val->frdataset))
|
|
||||||
{
|
{
|
||||||
dns_name_format(dns_fixedname_name(&val->fname),
|
dns_rdataset_t *dssetp = NULL, *keysetp = NULL;
|
||||||
namebuf, sizeof(namebuf));
|
dns_name_t *fname = dns_fixedname_name(&val->fname);
|
||||||
validator_log(val, ISC_LOG_DEBUG(3),
|
if (have_dnskey) {
|
||||||
"no supported algorithm/digest (%s/DS)",
|
dssetp = &val->dsrdataset;
|
||||||
namebuf);
|
keysetp = &val->frdataset;
|
||||||
result = markanswer(val, "proveunsecure (2)");
|
} else {
|
||||||
goto out;
|
dssetp = &val->frdataset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!have_dnskey && check_ds_private(&val->frdataset)) {
|
||||||
|
if (dns_rdataset_isassociated(&val->dsrdataset))
|
||||||
|
{
|
||||||
|
dns_rdataset_disassociate(
|
||||||
|
&val->dsrdataset);
|
||||||
|
}
|
||||||
|
dns_rdataset_clone(&val->frdataset,
|
||||||
|
&val->dsrdataset);
|
||||||
|
dssetp = &val->dsrdataset;
|
||||||
|
dns_rdataset_disassociate(&val->frdataset);
|
||||||
|
result = view_find(val, fname,
|
||||||
|
dns_rdatatype_dnskey);
|
||||||
|
switch (result) {
|
||||||
|
case ISC_R_SUCCESS:
|
||||||
|
keysetp = &val->frdataset;
|
||||||
|
break;
|
||||||
|
case ISC_R_NOTFOUND:
|
||||||
|
/*
|
||||||
|
* We don't know anything about the
|
||||||
|
* DNSKEY. Find it.
|
||||||
|
*/
|
||||||
|
result = create_fetch(
|
||||||
|
val, fname,
|
||||||
|
dns_rdatatype_dnskey,
|
||||||
|
fetch_callback_dnskey,
|
||||||
|
"seek_ds");
|
||||||
|
if (result == ISC_R_SUCCESS) {
|
||||||
|
result = DNS_R_WAIT;
|
||||||
|
}
|
||||||
|
goto out;
|
||||||
|
default:
|
||||||
|
validator_log(val, ISC_LOG_DEBUG(3),
|
||||||
|
"no DNSKEY found (%s/DS)",
|
||||||
|
namebuf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!check_ds_algs(val, fname, dssetp, keysetp)) {
|
||||||
|
dns_name_format(fname, namebuf,
|
||||||
|
sizeof(namebuf));
|
||||||
|
validator_log(
|
||||||
|
val, ISC_LOG_DEBUG(3),
|
||||||
|
"no supported algorithm/digest (%s/DS)",
|
||||||
|
namebuf);
|
||||||
|
result = markanswer(val, "proveunsecure (2)");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val->labels++;
|
val->labels++;
|
||||||
}
|
}
|
||||||
@@ -3309,7 +3547,7 @@ validator_start(void *arg) {
|
|||||||
validator_log(val, ISC_LOG_DEBUG(3),
|
validator_log(val, ISC_LOG_DEBUG(3),
|
||||||
"attempting insecurity proof");
|
"attempting insecurity proof");
|
||||||
|
|
||||||
result = proveunsecure(val, false, false);
|
result = proveunsecure(val, false, false, false);
|
||||||
if (result == DNS_R_NOTINSECURE) {
|
if (result == DNS_R_NOTINSECURE) {
|
||||||
validator_log(val, ISC_LOG_INFO,
|
validator_log(val, ISC_LOG_INFO,
|
||||||
"got insecure response; "
|
"got insecure response; "
|
||||||
@@ -3422,6 +3660,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
|
|||||||
dns_rdataset_init(&val->fdsset);
|
dns_rdataset_init(&val->fdsset);
|
||||||
dns_rdataset_init(&val->frdataset);
|
dns_rdataset_init(&val->frdataset);
|
||||||
dns_rdataset_init(&val->fsigrdataset);
|
dns_rdataset_init(&val->fsigrdataset);
|
||||||
|
dns_rdataset_init(&val->dsrdataset);
|
||||||
dns_fixedname_init(&val->wild);
|
dns_fixedname_init(&val->wild);
|
||||||
dns_fixedname_init(&val->closest);
|
dns_fixedname_init(&val->closest);
|
||||||
val->start = isc_stdtime_now();
|
val->start = isc_stdtime_now();
|
||||||
@@ -3497,6 +3736,9 @@ destroy_validator(dns_validator_t *val) {
|
|||||||
dns_keytable_detach(&val->keytable);
|
dns_keytable_detach(&val->keytable);
|
||||||
}
|
}
|
||||||
disassociate_rdatasets(val);
|
disassociate_rdatasets(val);
|
||||||
|
if (dns_rdataset_isassociated(&val->dsrdataset)) {
|
||||||
|
dns_rdataset_disassociate(&val->dsrdataset);
|
||||||
|
}
|
||||||
mctx = val->view->mctx;
|
mctx = val->view->mctx;
|
||||||
if (val->siginfo != NULL) {
|
if (val->siginfo != NULL) {
|
||||||
isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo));
|
isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo));
|
||||||
|
Reference in New Issue
Block a user