Add extended DNS error configuration option for RPZ zones

Implement the configuration option with its checking and parsing parts.

The option should be later used by BIND to set an extended error
code (EDE) for the queries modified in the result of RPZ processing.
This commit is contained in:
Aram Sargsyan 2022-08-26 14:11:47 +00:00
parent 77024e6ad6
commit 77f12ecba7
7 changed files with 107 additions and 4 deletions

View file

@ -18,6 +18,7 @@
#include <limits.h>
#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
@ -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;

View file

@ -312,7 +312,7 @@ options {
resolver\-query\-timeout <integer>;
resolver\-retry\-interval <integer>;
response\-padding { <address_match_element>; ... } block\-size <integer>;
response\-policy { zone <string> [ add\-soa <boolean> ] [ log <boolean> ] [ max\-policy\-ttl <duration> ] [ min\-update\-interval <duration> ] [ policy ( cname | disabled | drop | given | no\-op | nodata | nxdomain | passthru | tcp\-only <quoted_string> ) ] [ recursive\-only <boolean> ] [ nsip\-enable <boolean> ] [ nsdname\-enable <boolean> ]; ... } [ add\-soa <boolean> ] [ break\-dnssec <boolean> ] [ max\-policy\-ttl <duration> ] [ min\-update\-interval <duration> ] [ min\-ns\-dots <integer> ] [ nsip\-wait\-recurse <boolean> ] [ nsdname\-wait\-recurse <boolean> ] [ qname\-wait\-recurse <boolean> ] [ recursive\-only <boolean> ] [ nsip\-enable <boolean> ] [ nsdname\-enable <boolean> ] [ dnsrps\-enable <boolean> ] [ dnsrps\-options { <unspecified\-text> } ];
response\-policy { zone <string> [ add\-soa <boolean> ] [ log <boolean> ] [ max\-policy\-ttl <duration> ] [ min\-update\-interval <duration> ] [ policy ( cname | disabled | drop | given | no\-op | nodata | nxdomain | passthru | tcp\-only <quoted_string> ) ] [ recursive\-only <boolean> ] [ nsip\-enable <boolean> ] [ nsdname\-enable <boolean> ] [ ede <string> ]; ... } [ add\-soa <boolean> ] [ break\-dnssec <boolean> ] [ max\-policy\-ttl <duration> ] [ min\-update\-interval <duration> ] [ min\-ns\-dots <integer> ] [ nsip\-wait\-recurse <boolean> ] [ nsdname\-wait\-recurse <boolean> ] [ qname\-wait\-recurse <boolean> ] [ recursive\-only <boolean> ] [ nsip\-enable <boolean> ] [ nsdname\-enable <boolean> ] [ dnsrps\-enable <boolean> ] [ dnsrps\-options { <unspecified\-text> } ];
reuseport <boolean>;
root\-delegation\-only [ exclude { <string>; ... } ];
root\-key\-sentinel <boolean>;
@ -590,7 +590,7 @@ view <string> [ <class> ] {
resolver\-query\-timeout <integer>;
resolver\-retry\-interval <integer>;
response\-padding { <address_match_element>; ... } block\-size <integer>;
response\-policy { zone <string> [ add\-soa <boolean> ] [ log <boolean> ] [ max\-policy\-ttl <duration> ] [ min\-update\-interval <duration> ] [ policy ( cname | disabled | drop | given | no\-op | nodata | nxdomain | passthru | tcp\-only <quoted_string> ) ] [ recursive\-only <boolean> ] [ nsip\-enable <boolean> ] [ nsdname\-enable <boolean> ]; ... } [ add\-soa <boolean> ] [ break\-dnssec <boolean> ] [ max\-policy\-ttl <duration> ] [ min\-update\-interval <duration> ] [ min\-ns\-dots <integer> ] [ nsip\-wait\-recurse <boolean> ] [ nsdname\-wait\-recurse <boolean> ] [ qname\-wait\-recurse <boolean> ] [ recursive\-only <boolean> ] [ nsip\-enable <boolean> ] [ nsdname\-enable <boolean> ] [ dnsrps\-enable <boolean> ] [ dnsrps\-options { <unspecified\-text> } ];
response\-policy { zone <string> [ add\-soa <boolean> ] [ log <boolean> ] [ max\-policy\-ttl <duration> ] [ min\-update\-interval <duration> ] [ policy ( cname | disabled | drop | given | no\-op | nodata | nxdomain | passthru | tcp\-only <quoted_string> ) ] [ recursive\-only <boolean> ] [ nsip\-enable <boolean> ] [ nsdname\-enable <boolean> ] [ ede <string> ]; ... } [ add\-soa <boolean> ] [ break\-dnssec <boolean> ] [ max\-policy\-ttl <duration> ] [ min\-update\-interval <duration> ] [ min\-ns\-dots <integer> ] [ nsip\-wait\-recurse <boolean> ] [ nsdname\-wait\-recurse <boolean> ] [ qname\-wait\-recurse <boolean> ] [ recursive\-only <boolean> ] [ nsip\-enable <boolean> ] [ nsdname\-enable <boolean> ] [ dnsrps\-enable <boolean> ] [ dnsrps\-options { <unspecified\-text> } ];
root\-delegation\-only [ exclude { <string>; ... } ];
root\-key\-sentinel <boolean>;
rrset\-order { [ class <string> ] [ type <string> ] [ name <quoted_string> ] <string> <string>; ... };

View file

@ -255,7 +255,7 @@ options {
resolver-query-timeout <integer>;
resolver-retry-interval <integer>;
response-padding { <address_match_element>; ... } block-size <integer>;
response-policy { zone <string> [ add-soa <boolean> ] [ log <boolean> ] [ max-policy-ttl <duration> ] [ min-update-interval <duration> ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only <quoted_string> ) ] [ recursive-only <boolean> ] [ nsip-enable <boolean> ] [ nsdname-enable <boolean> ]; ... } [ add-soa <boolean> ] [ break-dnssec <boolean> ] [ max-policy-ttl <duration> ] [ min-update-interval <duration> ] [ min-ns-dots <integer> ] [ nsip-wait-recurse <boolean> ] [ nsdname-wait-recurse <boolean> ] [ qname-wait-recurse <boolean> ] [ recursive-only <boolean> ] [ nsip-enable <boolean> ] [ nsdname-enable <boolean> ] [ dnsrps-enable <boolean> ] [ dnsrps-options { <unspecified-text> } ];
response-policy { zone <string> [ add-soa <boolean> ] [ log <boolean> ] [ max-policy-ttl <duration> ] [ min-update-interval <duration> ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only <quoted_string> ) ] [ recursive-only <boolean> ] [ nsip-enable <boolean> ] [ nsdname-enable <boolean> ] [ ede <string> ]; ... } [ add-soa <boolean> ] [ break-dnssec <boolean> ] [ max-policy-ttl <duration> ] [ min-update-interval <duration> ] [ min-ns-dots <integer> ] [ nsip-wait-recurse <boolean> ] [ nsdname-wait-recurse <boolean> ] [ qname-wait-recurse <boolean> ] [ recursive-only <boolean> ] [ nsip-enable <boolean> ] [ nsdname-enable <boolean> ] [ dnsrps-enable <boolean> ] [ dnsrps-options { <unspecified-text> } ];
reuseport <boolean>;
root-delegation-only [ exclude { <string>; ... } ];
root-key-sentinel <boolean>;
@ -533,7 +533,7 @@ view <string> [ <class> ] {
resolver-query-timeout <integer>;
resolver-retry-interval <integer>;
response-padding { <address_match_element>; ... } block-size <integer>;
response-policy { zone <string> [ add-soa <boolean> ] [ log <boolean> ] [ max-policy-ttl <duration> ] [ min-update-interval <duration> ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only <quoted_string> ) ] [ recursive-only <boolean> ] [ nsip-enable <boolean> ] [ nsdname-enable <boolean> ]; ... } [ add-soa <boolean> ] [ break-dnssec <boolean> ] [ max-policy-ttl <duration> ] [ min-update-interval <duration> ] [ min-ns-dots <integer> ] [ nsip-wait-recurse <boolean> ] [ nsdname-wait-recurse <boolean> ] [ qname-wait-recurse <boolean> ] [ recursive-only <boolean> ] [ nsip-enable <boolean> ] [ nsdname-enable <boolean> ] [ dnsrps-enable <boolean> ] [ dnsrps-options { <unspecified-text> } ];
response-policy { zone <string> [ add-soa <boolean> ] [ log <boolean> ] [ max-policy-ttl <duration> ] [ min-update-interval <duration> ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only <quoted_string> ) ] [ recursive-only <boolean> ] [ nsip-enable <boolean> ] [ nsdname-enable <boolean> ] [ ede <string> ]; ... } [ add-soa <boolean> ] [ break-dnssec <boolean> ] [ max-policy-ttl <duration> ] [ min-update-interval <duration> ] [ min-ns-dots <integer> ] [ nsip-wait-recurse <boolean> ] [ nsdname-wait-recurse <boolean> ] [ qname-wait-recurse <boolean> ] [ recursive-only <boolean> ] [ nsip-enable <boolean> ] [ nsdname-enable <boolean> ] [ dnsrps-enable <boolean> ] [ dnsrps-options { <unspecified-text> } ];
root-delegation-only [ exclude { <string>; ... } ];
root-key-sentinel <boolean>;
rrset-order { [ class <string> ] [ type <string> ] [ name <quoted_string> ] <string> <string>; ... };

View file

@ -16,6 +16,7 @@
#include <ctype.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <openssl/opensslv.h>
@ -53,6 +54,7 @@
#include <dns/rbt.h>
#include <dns/rdataclass.h>
#include <dns/rdatatype.h>
#include <dns/rpz.h>
#include <dns/rrl.h>
#include <dns/secalg.h>
#include <dns/ssu.h>
@ -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.
*/

View file

@ -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);

View file

@ -15,6 +15,7 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <isc/buffer.h>
@ -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.)

View file

@ -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,