diff --git a/bin/named/server.c b/bin/named/server.c index 899b0e027a..476c408b78 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -2395,6 +2396,18 @@ configure_rpz_zone(dns_view_t *view, const cfg_listelt_t *element, *old_rpz_okp = false; } + obj = cfg_tuple_get(rpz_obj, "ede"); + if (!cfg_obj_isstring(obj)) { + zone->ede = 0; + } else { + str = cfg_obj_asstring(obj); + zone->ede = dns_rpz_str2ede(str); + INSIST(zone->ede != UINT16_MAX); + } + if (*old_rpz_okp && zone->ede != old->ede) { + *old_rpz_okp = false; + } + obj = cfg_tuple_get(rpz_obj, "add-soa"); if (cfg_obj_isvoid(obj)) { zone->addsoa = add_soa_default; diff --git a/doc/man/named.conf.5in b/doc/man/named.conf.5in index cbc565134c..47ef15b08e 100644 --- a/doc/man/named.conf.5in +++ b/doc/man/named.conf.5in @@ -312,7 +312,7 @@ options { resolver\-query\-timeout ; resolver\-retry\-interval ; response\-padding { ; ... } block\-size ; - response\-policy { zone [ add\-soa ] [ log ] [ max\-policy\-ttl ] [ min\-update\-interval ] [ policy ( cname | disabled | drop | given | no\-op | nodata | nxdomain | passthru | tcp\-only ) ] [ recursive\-only ] [ nsip\-enable ] [ nsdname\-enable ]; ... } [ add\-soa ] [ break\-dnssec ] [ max\-policy\-ttl ] [ min\-update\-interval ] [ min\-ns\-dots ] [ nsip\-wait\-recurse ] [ nsdname\-wait\-recurse ] [ qname\-wait\-recurse ] [ recursive\-only ] [ nsip\-enable ] [ nsdname\-enable ] [ dnsrps\-enable ] [ dnsrps\-options { } ]; + response\-policy { zone [ add\-soa ] [ log ] [ max\-policy\-ttl ] [ min\-update\-interval ] [ policy ( cname | disabled | drop | given | no\-op | nodata | nxdomain | passthru | tcp\-only ) ] [ recursive\-only ] [ nsip\-enable ] [ nsdname\-enable ] [ ede ]; ... } [ add\-soa ] [ break\-dnssec ] [ max\-policy\-ttl ] [ min\-update\-interval ] [ min\-ns\-dots ] [ nsip\-wait\-recurse ] [ nsdname\-wait\-recurse ] [ qname\-wait\-recurse ] [ recursive\-only ] [ nsip\-enable ] [ nsdname\-enable ] [ dnsrps\-enable ] [ dnsrps\-options { } ]; reuseport ; root\-delegation\-only [ exclude { ; ... } ]; root\-key\-sentinel ; @@ -590,7 +590,7 @@ view [ ] { resolver\-query\-timeout ; resolver\-retry\-interval ; response\-padding { ; ... } block\-size ; - response\-policy { zone [ add\-soa ] [ log ] [ max\-policy\-ttl ] [ min\-update\-interval ] [ policy ( cname | disabled | drop | given | no\-op | nodata | nxdomain | passthru | tcp\-only ) ] [ recursive\-only ] [ nsip\-enable ] [ nsdname\-enable ]; ... } [ add\-soa ] [ break\-dnssec ] [ max\-policy\-ttl ] [ min\-update\-interval ] [ min\-ns\-dots ] [ nsip\-wait\-recurse ] [ nsdname\-wait\-recurse ] [ qname\-wait\-recurse ] [ recursive\-only ] [ nsip\-enable ] [ nsdname\-enable ] [ dnsrps\-enable ] [ dnsrps\-options { } ]; + response\-policy { zone [ add\-soa ] [ log ] [ max\-policy\-ttl ] [ min\-update\-interval ] [ policy ( cname | disabled | drop | given | no\-op | nodata | nxdomain | passthru | tcp\-only ) ] [ recursive\-only ] [ nsip\-enable ] [ nsdname\-enable ] [ ede ]; ... } [ add\-soa ] [ break\-dnssec ] [ max\-policy\-ttl ] [ min\-update\-interval ] [ min\-ns\-dots ] [ nsip\-wait\-recurse ] [ nsdname\-wait\-recurse ] [ qname\-wait\-recurse ] [ recursive\-only ] [ nsip\-enable ] [ nsdname\-enable ] [ dnsrps\-enable ] [ dnsrps\-options { } ]; root\-delegation\-only [ exclude { ; ... } ]; root\-key\-sentinel ; rrset\-order { [ class ] [ type ] [ name ] ; ... }; diff --git a/doc/misc/options b/doc/misc/options index 1681be1514..6b0609394f 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -255,7 +255,7 @@ options { resolver-query-timeout ; resolver-retry-interval ; response-padding { ; ... } block-size ; - response-policy { zone [ add-soa ] [ log ] [ max-policy-ttl ] [ min-update-interval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only ) ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ]; ... } [ add-soa ] [ break-dnssec ] [ max-policy-ttl ] [ min-update-interval ] [ min-ns-dots ] [ nsip-wait-recurse ] [ nsdname-wait-recurse ] [ qname-wait-recurse ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ] [ dnsrps-enable ] [ dnsrps-options { } ]; + response-policy { zone [ add-soa ] [ log ] [ max-policy-ttl ] [ min-update-interval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only ) ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ] [ ede ]; ... } [ add-soa ] [ break-dnssec ] [ max-policy-ttl ] [ min-update-interval ] [ min-ns-dots ] [ nsip-wait-recurse ] [ nsdname-wait-recurse ] [ qname-wait-recurse ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ] [ dnsrps-enable ] [ dnsrps-options { } ]; reuseport ; root-delegation-only [ exclude { ; ... } ]; root-key-sentinel ; @@ -533,7 +533,7 @@ view [ ] { resolver-query-timeout ; resolver-retry-interval ; response-padding { ; ... } block-size ; - response-policy { zone [ add-soa ] [ log ] [ max-policy-ttl ] [ min-update-interval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only ) ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ]; ... } [ add-soa ] [ break-dnssec ] [ max-policy-ttl ] [ min-update-interval ] [ min-ns-dots ] [ nsip-wait-recurse ] [ nsdname-wait-recurse ] [ qname-wait-recurse ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ] [ dnsrps-enable ] [ dnsrps-options { } ]; + response-policy { zone [ add-soa ] [ log ] [ max-policy-ttl ] [ min-update-interval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only ) ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ] [ ede ]; ... } [ add-soa ] [ break-dnssec ] [ max-policy-ttl ] [ min-update-interval ] [ min-ns-dots ] [ nsip-wait-recurse ] [ nsdname-wait-recurse ] [ qname-wait-recurse ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ] [ dnsrps-enable ] [ dnsrps-options { } ]; root-delegation-only [ exclude { ; ... } ]; root-key-sentinel ; rrset-order { [ class ] [ type ] [ name ] ; ... }; diff --git a/lib/bind9/check.c b/lib/bind9/check.c index f24d02c02d..2ddd90b270 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -53,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -4958,6 +4960,49 @@ check_rpz_catz(const char *rpz_catz, const cfg_obj_t *rpz_obj, return (result); } +static isc_result_t +check_rpz(const cfg_obj_t *rpz_obj, isc_log_t *logctx) { + const cfg_listelt_t *element; + const cfg_obj_t *obj, *nameobj, *edeobj; + const char *zonename; + isc_result_t result = ISC_R_SUCCESS, tresult; + dns_fixedname_t fixed; + dns_name_t *name = dns_fixedname_initname(&fixed); + + obj = cfg_tuple_get(rpz_obj, "zone list"); + + for (element = cfg_list_first(obj); element != NULL; + element = cfg_list_next(element)) + { + obj = cfg_listelt_value(element); + nameobj = cfg_tuple_get(obj, "zone name"); + zonename = cfg_obj_asstring(nameobj); + + tresult = dns_name_fromstring(name, zonename, 0, NULL); + if (tresult != ISC_R_SUCCESS) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "bad domain name '%s'", zonename); + if (result == ISC_R_SUCCESS) { + result = tresult; + continue; + } + } + + edeobj = cfg_tuple_get(obj, "ede"); + if (edeobj != NULL && cfg_obj_isstring(edeobj)) { + const char *str = cfg_obj_asstring(edeobj); + + if (dns_rpz_str2ede(str) == UINT16_MAX) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "unsupported EDE type '%s'", str); + result = ISC_R_FAILURE; + } + } + } + + return (result); +} + static isc_result_t check_catz(const cfg_obj_t *catz_obj, const char *viewname, isc_mem_t *mctx, isc_log_t *logctx) { @@ -5214,6 +5259,19 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions, } } + /* + * Check response-policy configuration. + */ + if (opts != NULL) { + obj = NULL; + if ((cfg_map_get(opts, "response-policy", &obj) == + ISC_R_SUCCESS) && + (check_rpz(obj, logctx) != ISC_R_SUCCESS)) + { + result = ISC_R_FAILURE; + } + } + /* * Check catalog-zones configuration. */ diff --git a/lib/dns/include/dns/rpz.h b/lib/dns/include/dns/rpz.h index c46168d538..4bd421b22f 100644 --- a/lib/dns/include/dns/rpz.h +++ b/lib/dns/include/dns/rpz.h @@ -143,6 +143,7 @@ struct dns_rpz_zone { dns_name_t cname; /* override value for ..._CNAME */ dns_ttl_t max_policy_ttl; dns_rpz_policy_t policy; /* DNS_RPZ_POLICY_GIVEN or override */ + uint16_t ede; /* Extended DNS Error */ uint32_t min_update_interval; /* minimal interval between * updates */ @@ -379,6 +380,9 @@ dns_rpz_str2policy(const char *str); const char * dns_rpz_policy2str(dns_rpz_policy_t policy); +uint16_t +dns_rpz_str2ede(const char *str); + dns_rpz_policy_t dns_rpz_decode_cname(dns_rpz_zone_t *rpz, dns_rdataset_t *rdataset, dns_name_t *selfname); diff --git a/lib/dns/rpz.c b/lib/dns/rpz.c index 4e78b57609..cfeac54dea 100644 --- a/lib/dns/rpz.c +++ b/lib/dns/rpz.c @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -278,6 +279,32 @@ dns_rpz_policy2str(dns_rpz_policy_t policy) { return (str); } +uint16_t +dns_rpz_str2ede(const char *str) { + static struct { + const char *str; + uint16_t ede; + } tbl[] = { + { "none", 0 }, + { "forged", DNS_EDE_FORGEDANSWER }, + { "blocked", DNS_EDE_BLOCKED }, + { "censored", DNS_EDE_CENSORED }, + { "filtered", DNS_EDE_FILTERED }, + { "prohibited", DNS_EDE_PROHIBITED }, + }; + unsigned int n; + + if (str == NULL) { + return (UINT16_MAX); + } + for (n = 0; n < sizeof(tbl) / sizeof(tbl[0]); ++n) { + if (!strcasecmp(tbl[n].str, str)) { + return (tbl[n].ede); + } + } + return (UINT16_MAX); +} + /* * Return the bit number of the highest set bit in 'zbit'. * (for example, 0x01 returns 0, 0xFF returns 7, etc.) diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 64d0ddb494..481bc9827b 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -1833,6 +1833,7 @@ static cfg_tuplefielddef_t rpz_zone_fields[] = { { "recursive-only", &cfg_type_boolean, 0 }, { "nsip-enable", &cfg_type_boolean, 0 }, { "nsdname-enable", &cfg_type_boolean, 0 }, + { "ede", &cfg_type_ustring, 0 }, { NULL, NULL, 0 } }; static cfg_type_t cfg_type_rpz_tuple = { "rpz tuple", cfg_parse_kv_tuple,