rem: usr: Remove dnssec-must-be-secure feature

Closes #4482

Merge branch '4482-remove-dnssec-must-be-secure-feature' into 'main'

See merge request isc-projects/bind9!9851
This commit is contained in:
Ondřej Surý 2024-12-09 12:10:48 +00:00
commit f5f792f1ed
23 changed files with 19 additions and 230 deletions

View file

@ -1233,36 +1233,6 @@ cleanup:
return result;
}
static isc_result_t
mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) {
const cfg_listelt_t *element;
const cfg_obj_t *obj;
const char *str;
dns_fixedname_t fixed;
dns_name_t *name;
bool value;
isc_result_t result;
isc_buffer_t b;
name = dns_fixedname_initname(&fixed);
for (element = cfg_list_first(mbs); element != NULL;
element = cfg_list_next(element))
{
obj = cfg_listelt_value(element);
str = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
isc_buffer_constinit(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
value = cfg_obj_asboolean(cfg_tuple_get(obj, "value"));
CHECK(dns_resolver_setmustbesecure(resolver, name, value));
}
result = ISC_R_SUCCESS;
cleanup:
return result;
}
/*%
* Get a dispatch appropriate for the resolver of a given view.
*/
@ -5375,12 +5345,6 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
CHECK(configure_view_dnsseckeys(view, vconfig, config, bindkeys,
auto_root));
obj = NULL;
result = named_config_get(maps, "dnssec-must-be-secure", &obj);
if (result == ISC_R_SUCCESS) {
CHECK(mustbesecure(obj, view->resolver));
}
obj = NULL;
result = named_config_get(maps, "nta-recheck", &obj);
INSIST(result == ISC_R_SUCCESS);

View file

@ -52,10 +52,6 @@ ns.secure A 10.53.0.3
insecure NS ns.insecure
ns.insecure A 10.53.0.3
; A insecure subdomain
mustbesecure NS ns.mustbesecure
ns.mustbesecure A 10.53.0.3
z A 10.0.0.26
nsec3 NS ns.nsec3

View file

@ -52,10 +52,6 @@ ns.secure A 10.53.0.3
insecure NS ns.insecure
ns.insecure A 10.53.0.3
; A insecure subdomain
mustbesecure NS ns.mustbesecure
ns.mustbesecure A 10.53.0.3
z A 10.0.0.26
nsec3 NS ns.nsec3

View file

@ -23,7 +23,6 @@ options {
listen-on-v6 { none; };
recursion yes;
dnssec-validation yes;
dnssec-must-be-secure mustbesecure.example yes;
};
zone "." {

View file

@ -15,8 +15,6 @@ options {
dnssec-validation yes;
max-zone-ttl 600;
dnssec-must-be-secure mustbesecure.example yes;
sortlist { };
};

View file

@ -186,7 +186,6 @@ $CHECKCONF deprecated.conf >checkconf.out$n.1 2>&1 || ret=1
grep "option 'managed-keys' is deprecated" <checkconf.out$n.1 >/dev/null || ret=1
grep "option 'trusted-keys' is deprecated" <checkconf.out$n.1 >/dev/null || ret=1
grep "option 'max-zone-ttl' is deprecated" <checkconf.out$n.1 >/dev/null || ret=1
grep "option 'dnssec-must-be-secure' is deprecated" <checkconf.out$n.1 >/dev/null || ret=1
grep "option 'sortlist' is deprecated" <checkconf.out$n.1 >/dev/null || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status + ret))

View file

@ -71,10 +71,6 @@ ns.badds A 10.53.0.3
dynamic NS dynamic
dynamic A 10.53.0.3
; A insecure subdomain
mustbesecure NS ns.mustbesecure
ns.mustbesecure A 10.53.0.3
; A subdomain with expired signatures
expired NS ns.expired
ns.expired A 10.53.0.3

View file

@ -67,10 +67,6 @@ ns.badds A 10.53.0.3
dynamic NS dynamic
dynamic A 10.53.0.3
; A insecure subdomain
mustbesecure NS ns.mustbesecure
ns.mustbesecure A 10.53.0.3
; A subdomain with expired signatures
expired NS ns.expired
ns.expired A 10.53.0.3

View file

@ -23,7 +23,6 @@ options {
listen-on-v6 { none; };
recursion yes;
dnssec-validation yes;
dnssec-must-be-secure mustbesecure.example yes;
minimal-responses no;
nta-lifetime 12s;

View file

@ -25,7 +25,6 @@ options {
listen-on-v6 { none; };
recursion yes;
dnssec-validation yes;
dnssec-must-be-secure . yes;
/* only SHA-256 is enabled */
disable-ds-digests . { SHA-1; SHA-384; 5; 6; 7; 8; 9; };

View file

@ -38,17 +38,6 @@ def test_dsdigest_good():
assert res.flags & dns.flags.AD
def test_dsdigest_bad():
"""Check that validation with not supported digest types
and "dnssec-must-be-secure yes;" results in SERVFAIL"""
msg = dns.message.make_query("a.bad.", "A", want_dnssec=True)
res = isctest.query.tcp(
msg,
"10.53.0.3",
)
isctest.check.servfail(res)
def test_dsdigest_insecure():
"""Check that validation with not supported digest algorithms is insecure"""
msg_ds = dns.message.make_query("bad.", "DS", want_dnssec=True)

View file

@ -63,10 +63,6 @@ ns.bogus A 10.53.0.3
dynamic NS dynamic
dynamic A 10.53.0.3
; A insecure subdomain
mustbesecure NS ns.mustbesecure
ns.mustbesecure A 10.53.0.3
; A rfc2535 signed zone w/ CNAME
rfc2535 NS ns.rfc2535
ns.rfc2535 A 10.53.0.3

View file

@ -1680,19 +1680,6 @@ default is used.
If all supported digest types are disabled, the zones covered by
:any:`disable-ds-digests` are treated as insecure.
.. namedconf:statement:: dnssec-must-be-secure
:tags: deprecated
:short: Defines hierarchies that must or may not be secure (signed and validated).
This option is deprecated and will be removed in a future release.
This specifies hierarchies which must be or may not be secure (signed and
validated). If ``yes``, then :iscman:`named` only accepts answers if
they are secure. If ``no``, then normal DNSSEC validation applies,
allowing insecure answers to be accepted. The specified domain
must be defined as a trust anchor, for instance in a :any:`trust-anchors`
statement, or ``dnssec-validation auto`` must be active.
.. namedconf:statement:: dns64
:tags: query
:short: Instructs :iscman:`named` to return mapped IPv4 addresses to AAAA queries when there are no AAAA records.

View file

@ -124,7 +124,6 @@ options {
dnssec-accept-expired <boolean>;
dnssec-dnskey-kskonly <boolean>; // obsolete
dnssec-loadkeys-interval <integer>;
dnssec-must-be-secure <string> <boolean>; // may occur multiple times, deprecated
dnssec-policy <string>;
dnssec-secure-to-insecure <boolean>; // obsolete
dnssec-update-mode ( maintain | no-resign ); // obsolete
@ -431,7 +430,6 @@ view <string> [ <class> ] {
dnssec-accept-expired <boolean>;
dnssec-dnskey-kskonly <boolean>; // obsolete
dnssec-loadkeys-interval <integer>;
dnssec-must-be-secure <string> <boolean>; // may occur multiple times, deprecated
dnssec-policy <string>;
dnssec-secure-to-insecure <boolean>; // obsolete
dnssec-update-mode ( maintain | no-resign ); // obsolete

View file

@ -448,13 +448,6 @@ dns_resolver_ds_digest_supported(dns_resolver_t *resolver,
* crypto libraries if it was not specifically disabled.
*/
isc_result_t
dns_resolver_setmustbesecure(dns_resolver_t *resolver, const dns_name_t *name,
bool value);
bool
dns_resolver_getmustbesecure(dns_resolver_t *resolver, const dns_name_t *name);
void
dns_resolver_settimeout(dns_resolver_t *resolver, unsigned int timeout);
/*%<

View file

@ -141,7 +141,6 @@ struct dns_validator {
dns_fixedname_t wild;
dns_fixedname_t closest;
ISC_LINK(dns_validator_t) link;
bool mustbesecure;
unsigned int depth;
unsigned int authcount;
unsigned int authfail;

View file

@ -559,7 +559,6 @@ struct dns_resolver {
ISC_LIST(alternate_t) alternates;
dns_nametree_t *algorithms;
dns_nametree_t *digests;
dns_nametree_t *mustbesecure;
unsigned int spillatmax;
unsigned int spillatmin;
isc_timer_t *spillattimer;
@ -9939,7 +9938,6 @@ dns_resolver__destroy(dns_resolver_t *res) {
dns_nametree_detach(&res->algorithms);
dns_nametree_detach(&res->digests);
dns_nametree_detach(&res->mustbesecure);
if (res->querystats != NULL) {
dns_stats_detach(&res->querystats);
@ -10088,8 +10086,6 @@ dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr, isc_nm_t *nm,
&res->algorithms);
dns_nametree_create(res->mctx, DNS_NAMETREE_BITS, "ds-digests",
&res->digests);
dns_nametree_create(res->mctx, DNS_NAMETREE_BOOL,
"dnssec-must-be-secure", &res->mustbesecure);
res->namepools = isc_mem_cget(res->mctx, res->nloops,
sizeof(res->namepools[0]));
@ -10798,24 +10794,6 @@ dns_resolver_ds_digest_supported(dns_resolver_t *resolver,
return dst_ds_digest_supported(digest_type);
}
isc_result_t
dns_resolver_setmustbesecure(dns_resolver_t *resolver, const dns_name_t *name,
bool value) {
isc_result_t result;
REQUIRE(VALID_RESOLVER(resolver));
result = dns_nametree_add(resolver->mustbesecure, name, value);
return result;
}
bool
dns_resolver_getmustbesecure(dns_resolver_t *resolver, const dns_name_t *name) {
REQUIRE(VALID_RESOLVER(resolver));
return dns_nametree_covered(resolver->mustbesecure, name, NULL, 0);
}
void
dns_resolver_getclientsperquery(dns_resolver_t *resolver, uint32_t *cur,
uint32_t *min, uint32_t *max) {

View file

@ -193,18 +193,9 @@ disassociate_rdatasets(dns_validator_t *val) {
/*%
* Mark the rdatasets in val->vstat with trust level "answer",
* indicating that they did not validate, but could be cached as insecure.
*
* If we are validating a name that is marked as "must be secure", log a
* warning and return DNS_R_MUSTBESECURE instead.
*/
static isc_result_t
markanswer(dns_validator_t *val, const char *where, const char *mbstext) {
if (val->mustbesecure && mbstext != NULL) {
validator_log(val, ISC_LOG_WARNING,
"must be secure failure, %s", mbstext);
return DNS_R_MUSTBESECURE;
}
markanswer(dns_validator_t *val, const char *where) {
validator_log(val, ISC_LOG_DEBUG(3), "marking as answer (%s)", where);
if (val->rdataset != NULL) {
dns_rdataset_settrust(val->rdataset, dns_trust_answer);
@ -557,9 +548,7 @@ fetch_callback_ds(void *arg) {
* insecurity. If this is a zone cut, that
* means we're insecure.
*/
result = markanswer(
val, "fetch_callback_ds",
"no DS and this is a delegation");
result = markanswer(val, "fetch_callback_ds");
break;
}
FALLTHROUGH;
@ -667,8 +656,7 @@ validator_callback_ds(void *arg) {
NEGATIVE(&val->frdataset) &&
isdelegation(name, &val->frdataset, DNS_R_NCACHENXRRSET))
{
result = markanswer(val, "validator_callback_ds",
"no DS and this is a delegation");
result = markanswer(val, "validator_callback_ds");
} else if ((val->attributes & VALATTR_INSECURITY) != 0) {
result = proveunsecure(val, have_dsset, true);
} else {
@ -1983,9 +1971,7 @@ validate_dnskey_dsset_done(dns_validator_t *val, isc_result_t result) {
if (!val->supported_algorithm) {
validator_log(val, ISC_LOG_DEBUG(3),
"no supported algorithm/digest (DS)");
result = markanswer(
val, "validate_dnskey (3)",
"no supported algorithm/digest (DS)");
result = markanswer(val, "validate_dnskey (3)");
break;
}
FALLTHROUGH;
@ -2195,7 +2181,7 @@ validate_dnskey(void *arg) {
INSIST(val->dsset != NULL);
if (val->dsset->trust < dns_trust_secure) {
result = markanswer(val, "validate_dnskey (2)", "insecure DS");
result = markanswer(val, "validate_dnskey (2)");
goto cleanup;
}
@ -2838,7 +2824,7 @@ validate_nx(dns_validator_t *val, bool resume) {
if (result == DNS_R_NSEC3ITERRANGE) {
validator_log(val, ISC_LOG_DEBUG(3),
"too many iterations");
markanswer(val, "validate_nx (3)", NULL);
markanswer(val, "validate_nx (3)");
return ISC_R_SUCCESS;
}
}
@ -2856,12 +2842,12 @@ validate_nx(dns_validator_t *val, bool resume) {
validator_log(val, ISC_LOG_DEBUG(3),
"optout proof found");
val->optout = true;
markanswer(val, "validate_nx (1)", NULL);
markanswer(val, "validate_nx (1)");
return ISC_R_SUCCESS;
} else if ((val->attributes & VALATTR_FOUNDUNKNOWN) != 0) {
validator_log(val, ISC_LOG_DEBUG(3),
"unknown NSEC3 hash algorithm found");
markanswer(val, "validate_nx (2)", NULL);
markanswer(val, "validate_nx (2)");
return ISC_R_SUCCESS;
}
@ -2874,7 +2860,7 @@ validate_nx(dns_validator_t *val, bool resume) {
if (result == DNS_R_NSEC3ITERRANGE) {
validator_log(val, ISC_LOG_DEBUG(3),
"too many iterations");
markanswer(val, "validate_nx (4)", NULL);
markanswer(val, "validate_nx (4)");
return ISC_R_SUCCESS;
}
}
@ -2991,9 +2977,7 @@ seek_ds(dns_validator_t *val, isc_result_t *resp) {
val, ISC_LOG_DEBUG(3),
"no supported algorithm/digest (%s/DS)",
namebuf);
*resp = markanswer(val, "proveunsecure (5)",
"no supported "
"algorithm/digest (DS)");
*resp = markanswer(val, "proveunsecure (5)");
return ISC_R_COMPLETE;
}
@ -3070,8 +3054,7 @@ seek_ds(dns_validator_t *val, isc_result_t *resp) {
NULL) == ISC_R_SUCCESS &&
dns_name_equal(tname, found))
{
*resp = markanswer(val, "proveunsecure (3)",
"no DS at zone cut");
*resp = markanswer(val, "proveunsecure (3)");
return ISC_R_COMPLETE;
}
@ -3085,13 +3068,12 @@ seek_ds(dns_validator_t *val, isc_result_t *resp) {
validator_log(val, ISC_LOG_WARNING,
"can't validate existing "
"negative responses (no DS)");
*resp = DNS_R_MUSTBESECURE;
*resp = DNS_R_NOVALIDSIG;
return ISC_R_COMPLETE;
}
if (isdelegation(tname, &val->frdataset, result)) {
*resp = markanswer(val, "proveunsecure (4)",
"this is a delegation");
*resp = markanswer(val, "proveunsecure (4)");
return ISC_R_COMPLETE;
}
@ -3185,8 +3167,6 @@ seek_ds(dns_validator_t *val, isc_result_t *resp) {
* Returns:
* \li ISC_R_SUCCESS val->name is in an unsecure zone
* \li DNS_R_WAIT validation is in progress.
* \li DNS_R_MUSTBESECURE val->name is supposed to be secure
* (policy) but we proved that it is unsecure.
* \li DNS_R_NOVALIDSIG
* \li DNS_R_NOVALIDNSEC
* \li DNS_R_NOTINSECURE
@ -3219,8 +3199,7 @@ proveunsecure(dns_validator_t *val, bool have_ds, bool resume) {
result = dns_keytable_finddeepestmatch(val->keytable, secroot, secroot);
if (result == ISC_R_NOTFOUND) {
validator_log(val, ISC_LOG_DEBUG(3), "not beneath secure root");
return markanswer(val, "proveunsecure (1)",
"not beneath secure root");
return markanswer(val, "proveunsecure (1)");
} else if (result != ISC_R_SUCCESS) {
return result;
}
@ -3249,7 +3228,7 @@ proveunsecure(dns_validator_t *val, bool have_ds, bool resume) {
validator_log(val, ISC_LOG_DEBUG(3),
"no supported algorithm/digest (%s/DS)",
namebuf);
result = markanswer(val, "proveunsecure (2)", namebuf);
result = markanswer(val, "proveunsecure (2)");
goto out;
}
val->labels++;
@ -3441,7 +3420,6 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
isc_counter_attach(gqc, &val->gqc);
}
val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
dns_rdataset_init(&val->fdsset);
dns_rdataset_init(&val->frdataset);
dns_rdataset_init(&val->fsigrdataset);

View file

@ -21666,7 +21666,7 @@ nsfetch_done(void *arg) {
if (!dns_rdataset_isassociated(nssigset)) {
dnssec_log(zone, ISC_LOG_WARNING, "No NS RRSIGs found for '%s'",
pnamebuf);
result = DNS_R_MUSTBESECURE;
result = DNS_R_NOVALIDSIG;
goto done;
}
@ -21675,7 +21675,7 @@ nsfetch_done(void *arg) {
dnssec_log(zone, ISC_LOG_WARNING,
"Invalid NS RRset for '%s' trust level %u", pnamebuf,
nsrrset->trust);
result = DNS_R_MUSTBESECURE;
result = DNS_R_NOVALIDSIG;
goto done;
}

View file

@ -195,7 +195,6 @@ typedef enum isc_result {
DNS_R_BADNAME,
DNS_R_DYNAMIC,
DNS_R_UNKNOWNCOMMAND,
DNS_R_MUSTBESECURE,
DNS_R_COVERINGNSEC,
DNS_R_MXISADDRESS,
DNS_R_DUPLICATE,

View file

@ -194,7 +194,6 @@ static const char *description[ISC_R_NRESULTS] = {
[DNS_R_BADNAME] = "bad name (check-names)",
[DNS_R_DYNAMIC] = "dynamic zone",
[DNS_R_UNKNOWNCOMMAND] = "unknown command",
[DNS_R_MUSTBESECURE] = "must-be-secure",
[DNS_R_COVERINGNSEC] = "covering NSEC record returned",
[DNS_R_MXISADDRESS] = "MX is an address",
[DNS_R_DUPLICATE] = "duplicate query",
@ -449,7 +448,6 @@ static const char *identifier[ISC_R_NRESULTS] = {
[DNS_R_BADNAME] = "DNS_R_BADNAME",
[DNS_R_DYNAMIC] = "DNS_R_DYNAMIC",
[DNS_R_UNKNOWNCOMMAND] = "DNS_R_UNKNOWNCOMMAND",
[DNS_R_MUSTBESECURE] = "DNS_R_MUSTBESECURE",
[DNS_R_COVERINGNSEC] = "DNS_R_COVERINGNSEC",
[DNS_R_MXISADDRESS] = "DNS_R_MXISADDRESS",
[DNS_R_DUPLICATE] = "DNS_R_DUPLICATE",

View file

@ -466,34 +466,6 @@ exists(const cfg_obj_t *obj, const char *name, int value, isc_symtab_t *symtab,
return result;
}
static isc_result_t
mustbesecure(const cfg_obj_t *secure, isc_symtab_t *symtab, isc_mem_t *mctx) {
const cfg_obj_t *obj;
char namebuf[DNS_NAME_FORMATSIZE];
const char *str;
dns_fixedname_t fixed;
dns_name_t *name;
isc_buffer_t b;
isc_result_t result = ISC_R_SUCCESS;
name = dns_fixedname_initname(&fixed);
obj = cfg_tuple_get(secure, "name");
str = cfg_obj_asstring(obj);
isc_buffer_constinit(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(obj, ISC_LOG_ERROR, "bad domain name '%s'", str);
} else {
dns_name_format(name, namebuf, sizeof(namebuf));
result = exists(secure, namebuf, 1, symtab,
"dnssec-must-be-secure '%s': already exists "
"previous definition: %s:%u",
mctx);
}
return result;
}
static isc_result_t
checkacl(const char *aclname, cfg_aclconfctx_t *actx, const cfg_obj_t *zconfig,
const cfg_obj_t *voptions, const cfg_obj_t *config, isc_mem_t *mctx) {
@ -1223,7 +1195,6 @@ check_options(const cfg_obj_t *options, const cfg_obj_t *config,
unsigned int i;
const cfg_obj_t *obj = NULL;
const cfg_listelt_t *element;
isc_symtab_t *symtab = NULL;
const char *str;
isc_buffer_t b;
uint32_t lifetime = 3600;
@ -1622,34 +1593,6 @@ check_options(const cfg_obj_t *options, const cfg_obj_t *config,
}
}
/*
* Check dnssec-must-be-secure.
*/
obj = NULL;
(void)cfg_map_get(options, "dnssec-must-be-secure", &obj);
if (obj != NULL) {
tresult = isc_symtab_create(mctx, 100, freekey, mctx, false,
&symtab);
if (tresult != ISC_R_SUCCESS) {
result = tresult;
} else {
for (element = cfg_list_first(obj); element != NULL;
element = cfg_list_next(element))
{
obj = cfg_listelt_value(element);
tresult = mustbesecure(obj, symtab, mctx);
if (result == ISC_R_SUCCESS &&
tresult != ISC_R_SUCCESS)
{
result = tresult;
}
}
}
if (symtab != NULL) {
isc_symtab_destroy(&symtab);
}
}
/*
* Check server/contacts for syntactic validity.
*/

View file

@ -1447,17 +1447,6 @@ static cfg_type_t cfg_type_disabledsdigest = {
cfg_doc_tuple, &cfg_rep_tuple, disabledsdigest_fields
};
static cfg_tuplefielddef_t mustbesecure_fields[] = {
{ "name", &cfg_type_astring, 0 },
{ "value", &cfg_type_boolean, 0 },
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_type_mustbesecure = {
"mustbesecure", cfg_parse_tuple, cfg_print_tuple,
cfg_doc_tuple, &cfg_rep_tuple, mustbesecure_fields
};
static const char *masterformat_enums[] = { "raw", "text", NULL };
static cfg_type_t cfg_type_masterformat = {
"masterformat", cfg_parse_enum, cfg_print_ustring,
@ -2070,8 +2059,8 @@ static cfg_clausedef_t view_clauses[] = {
{ "dnssec-enable", NULL, CFG_CLAUSEFLAG_ANCIENT },
{ "dnssec-lookaside", NULL,
CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_ANCIENT },
{ "dnssec-must-be-secure", &cfg_type_mustbesecure,
CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_DEPRECATED },
{ "dnssec-must-be-secure", NULL,
CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_ANCIENT },
{ "dnssec-validation", &cfg_type_boolorauto, 0 },
#ifdef HAVE_DNSTAP
{ "dnstap", &cfg_type_dnstap, CFG_CLAUSEFLAG_OPTIONAL },