mirror of
https://github.com/isc-projects/bind9.git
synced 2026-04-24 15:47:18 -04:00
[master] DNS Response Policy Service API
4713. [func] Added support for the DNS Response Policy Service (DNSRPS) API, which allows named to use an external response policy daemon when built with "configure --enable-dnsrps". Thanks to Vernon Schryver and Farsight Security. [RT #43376]
This commit is contained in:
parent
8e014c45ae
commit
3363f3147a
53 changed files with 4443 additions and 310 deletions
6
CHANGES
6
CHANGES
|
|
@ -1,3 +1,9 @@
|
|||
4713. [func] Added support for the DNS Response Policy Service
|
||||
(DNSRPS) API, which allows named to use an external
|
||||
response policy daemon when built with
|
||||
"configure --enable-dnsrps". Thanks to Vernon
|
||||
Schryver and Farsight Security. [RT #43376]
|
||||
|
||||
4712. [bug] "dig +domain" and "dig +search" didn't retain the
|
||||
search domain when retrying with TCP. [RT #45547]
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@
|
|||
#include <dns/db.h>
|
||||
#include <dns/dispatch.h>
|
||||
#include <dns/dlz.h>
|
||||
#include <dns/dnsrps.h>
|
||||
#include <dns/dns64.h>
|
||||
#include <dns/dyndb.h>
|
||||
#include <dns/events.h>
|
||||
|
|
@ -1862,6 +1863,230 @@ cleanup:
|
|||
return (result);
|
||||
}
|
||||
|
||||
typedef struct conf_dnsrps_ctx conf_dnsrps_ctx_t;
|
||||
struct conf_dnsrps_ctx {
|
||||
isc_result_t result;
|
||||
char *cstr;
|
||||
size_t cstr_size;
|
||||
isc_mem_t *mctx;
|
||||
};
|
||||
|
||||
/*
|
||||
* Add to the DNSRPS configuration string.
|
||||
*/
|
||||
static isc_boolean_t
|
||||
conf_dnsrps_sadd(conf_dnsrps_ctx_t *ctx, const char *p, ...) {
|
||||
size_t new_len, cur_len, new_cstr_size;
|
||||
char *new_cstr;
|
||||
va_list args;
|
||||
|
||||
if (ctx->cstr == NULL) {
|
||||
ctx->cstr = isc_mem_get(ctx->mctx, 256);
|
||||
if (ctx->cstr == NULL) {
|
||||
ctx->result = ISC_R_NOMEMORY;
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
ctx->cstr[0] = '\0';
|
||||
ctx->cstr_size = 256;
|
||||
}
|
||||
|
||||
cur_len = strlen(ctx->cstr);
|
||||
va_start(args, p);
|
||||
new_len = vsnprintf(ctx->cstr + cur_len, ctx->cstr_size - cur_len,
|
||||
p, args) + 1;
|
||||
va_end(args);
|
||||
|
||||
if (cur_len + new_len <= ctx->cstr_size)
|
||||
return (ISC_TRUE);
|
||||
|
||||
new_cstr_size = ((cur_len + new_len)/256 + 1) * 256;
|
||||
new_cstr = isc_mem_get(ctx->mctx, new_cstr_size);
|
||||
if (new_cstr == NULL) {
|
||||
ctx->result = ISC_R_NOMEMORY;
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
memmove(new_cstr, ctx->cstr, cur_len);
|
||||
isc_mem_put(ctx->mctx, ctx->cstr, ctx->cstr_size);
|
||||
ctx->cstr_size = new_cstr_size;
|
||||
ctx->cstr = new_cstr;
|
||||
|
||||
/* cannot use args twice after a single va_start()on some systems */
|
||||
va_start(args, p);
|
||||
vsnprintf(ctx->cstr + cur_len, ctx->cstr_size - cur_len, p, args);
|
||||
va_end(args);
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get an DNSRPS configuration value using the global and view options
|
||||
* for the default. Return ISC_FALSE upon failure.
|
||||
*/
|
||||
static isc_boolean_t
|
||||
conf_dnsrps_get(const cfg_obj_t **sub_obj,
|
||||
const cfg_obj_t **maps ,const cfg_obj_t *obj,
|
||||
const char *name, conf_dnsrps_ctx_t *ctx)
|
||||
{
|
||||
if (ctx != NULL && ctx->result != ISC_R_SUCCESS) {
|
||||
*sub_obj = NULL;
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
*sub_obj = cfg_tuple_get(obj, name);
|
||||
if (cfg_obj_isvoid(*sub_obj)) {
|
||||
*sub_obj = NULL;
|
||||
if (maps != NULL &&
|
||||
ISC_R_SUCCESS != named_config_get(maps, name, sub_obj))
|
||||
*sub_obj = NULL;
|
||||
}
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle a DNSRPS boolean configuration value with the global and view
|
||||
* options providing the default.
|
||||
*/
|
||||
static void
|
||||
conf_dnsrps_yes_no(const cfg_obj_t *obj, const char* name,
|
||||
conf_dnsrps_ctx_t *ctx)
|
||||
{
|
||||
const cfg_obj_t *sub_obj;
|
||||
|
||||
if (!conf_dnsrps_get(&sub_obj, NULL, obj, name, ctx))
|
||||
return;
|
||||
if (sub_obj == NULL)
|
||||
return;
|
||||
if (ctx == NULL) {
|
||||
cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
|
||||
"\"%s\" without \"dnsrps-enable yes\"",
|
||||
name);
|
||||
return;
|
||||
}
|
||||
|
||||
conf_dnsrps_sadd(ctx, " %s %s", name,
|
||||
cfg_obj_asboolean(sub_obj) ? "yes" : "no");
|
||||
}
|
||||
|
||||
static void
|
||||
conf_dnsrps_num(const cfg_obj_t *obj, const char *name,
|
||||
conf_dnsrps_ctx_t *ctx)
|
||||
{
|
||||
const cfg_obj_t *sub_obj;
|
||||
|
||||
if (!conf_dnsrps_get(&sub_obj, NULL, obj, name, ctx))
|
||||
return;
|
||||
if (sub_obj == NULL)
|
||||
return;
|
||||
if (ctx == NULL) {
|
||||
cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
|
||||
"\"%s\" without \"dnsrps-enable yes\"",
|
||||
name);
|
||||
return;
|
||||
}
|
||||
|
||||
conf_dnsrps_sadd(ctx, " %s %d", name, cfg_obj_asuint32(sub_obj));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the parsed RPZ configuration statement to a string for
|
||||
* dns_rpz_new_zones().
|
||||
*/
|
||||
static isc_result_t
|
||||
conf_dnsrps(dns_view_t *view, const cfg_obj_t **maps,
|
||||
isc_boolean_t nsip_enabled, isc_boolean_t nsdname_enabled,
|
||||
dns_rpz_zbits_t *nsip_on, dns_rpz_zbits_t *nsdname_on,
|
||||
char **rps_cstr, size_t *rps_cstr_size,
|
||||
const cfg_obj_t *rpz_obj, const cfg_listelt_t *zone_element)
|
||||
{
|
||||
conf_dnsrps_ctx_t ctx;
|
||||
const cfg_obj_t *zone_obj, *obj;
|
||||
dns_rpz_num_t rpz_num;
|
||||
isc_boolean_t on;
|
||||
const char *s;
|
||||
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.result = ISC_R_SUCCESS;
|
||||
ctx.mctx = view->mctx;
|
||||
|
||||
for (rpz_num = 0;
|
||||
zone_element != NULL && ctx.result == ISC_R_SUCCESS;
|
||||
++rpz_num) {
|
||||
zone_obj = cfg_listelt_value(zone_element);
|
||||
|
||||
s = cfg_obj_asstring(cfg_tuple_get(zone_obj, "zone name"));
|
||||
conf_dnsrps_sadd(&ctx, "zone \"%s\"", s);
|
||||
|
||||
obj = cfg_tuple_get(zone_obj, "policy");
|
||||
if (!cfg_obj_isvoid(obj)) {
|
||||
s = cfg_obj_asstring(cfg_tuple_get(obj, "policy name"));
|
||||
conf_dnsrps_sadd(&ctx, " policy %s", s);
|
||||
if (strcasecmp(s, "cname") == 0) {
|
||||
s = cfg_obj_asstring(cfg_tuple_get(obj,
|
||||
"cname"));
|
||||
conf_dnsrps_sadd(&ctx, " %s", s);
|
||||
}
|
||||
}
|
||||
|
||||
conf_dnsrps_yes_no(zone_obj, "recursive-only", &ctx);
|
||||
conf_dnsrps_yes_no(zone_obj, "log", &ctx);
|
||||
conf_dnsrps_num(zone_obj, "max-policy-ttl", &ctx);
|
||||
obj = cfg_tuple_get(rpz_obj, "nsip-enable");
|
||||
if (!cfg_obj_isvoid(obj)) {
|
||||
if (cfg_obj_asboolean(obj))
|
||||
*nsip_on |= DNS_RPZ_ZBIT(rpz_num);
|
||||
else
|
||||
*nsip_on &= ~DNS_RPZ_ZBIT(rpz_num);
|
||||
}
|
||||
on = ((*nsip_on & DNS_RPZ_ZBIT(rpz_num)) != 0);
|
||||
if (nsip_enabled != on)
|
||||
conf_dnsrps_sadd(&ctx, on ? " nsip-enable yes " :
|
||||
" nsip-enable no ");
|
||||
obj = cfg_tuple_get(rpz_obj, "nsdname-enable");
|
||||
if (!cfg_obj_isvoid(obj)) {
|
||||
if (cfg_obj_asboolean(obj))
|
||||
*nsdname_on |= DNS_RPZ_ZBIT(rpz_num);
|
||||
else
|
||||
*nsdname_on &= ~DNS_RPZ_ZBIT(rpz_num);
|
||||
}
|
||||
on = ((*nsdname_on & DNS_RPZ_ZBIT(rpz_num)) != 0);
|
||||
if (nsdname_enabled != on)
|
||||
conf_dnsrps_sadd(&ctx, on
|
||||
? " nsdname-enable yes "
|
||||
: " nsdname-enable no ");
|
||||
conf_dnsrps_sadd(&ctx, ";\n");
|
||||
zone_element = cfg_list_next(zone_element);
|
||||
}
|
||||
|
||||
conf_dnsrps_yes_no(rpz_obj, "recursive-only", &ctx);
|
||||
conf_dnsrps_num(rpz_obj, "max-policy-ttl", &ctx);
|
||||
conf_dnsrps_num(rpz_obj, "min-ns-dots", &ctx);
|
||||
conf_dnsrps_yes_no(rpz_obj, "qname-wait-recurse", &ctx);
|
||||
conf_dnsrps_yes_no(rpz_obj, "break-dnssec", &ctx);
|
||||
if (!nsip_enabled)
|
||||
conf_dnsrps_sadd(&ctx, " nsip-enable no ");
|
||||
if (!nsdname_enabled)
|
||||
conf_dnsrps_sadd(&ctx, " nsdname-enable no ");
|
||||
|
||||
/*
|
||||
* Get the general dnsrpzd parameters from the response-policy
|
||||
* statement in the view and the general options.
|
||||
*/
|
||||
if (conf_dnsrps_get(&obj, maps, rpz_obj, "dnsrps-options", &ctx) &&
|
||||
obj != NULL)
|
||||
conf_dnsrps_sadd(&ctx, " %s\n", cfg_obj_asstring(obj));
|
||||
|
||||
if (ctx.result == ISC_R_SUCCESS) {
|
||||
*rps_cstr = ctx.cstr;
|
||||
*rps_cstr_size = ctx.cstr_size;
|
||||
} else {
|
||||
if (ctx.cstr != NULL)
|
||||
isc_mem_put(ctx.mctx, ctx.cstr, ctx.cstr_size);
|
||||
*rps_cstr = NULL;
|
||||
*rps_cstr_size = 0;
|
||||
}
|
||||
return (ctx.result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
configure_rpz_name(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name,
|
||||
const char *str, const char *msg)
|
||||
|
|
@ -1960,13 +2185,19 @@ configure_rpz_zone(dns_view_t *view, const cfg_listelt_t *element,
|
|||
"invalid zone name '%s'", str);
|
||||
return (DNS_R_EMPTYLABEL);
|
||||
}
|
||||
for (rpz_num = 0; rpz_num < view->rpzs->p.num_zones-1; ++rpz_num) {
|
||||
if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin,
|
||||
&zone->origin)) {
|
||||
cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL,
|
||||
"duplicate '%s'", str);
|
||||
result = DNS_R_DUPLICATE;
|
||||
return (result);
|
||||
if (!view->rpzs->p.dnsrps_enabled) {
|
||||
for (rpz_num = 0;
|
||||
rpz_num < view->rpzs->p.num_zones - 1;
|
||||
++rpz_num)
|
||||
{
|
||||
if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin,
|
||||
&zone->origin)) {
|
||||
cfg_obj_log(rpz_obj, named_g_lctx,
|
||||
DNS_RPZ_ERROR_LEVEL,
|
||||
"duplicate '%s'", str);
|
||||
result = DNS_R_DUPLICATE;
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*old_rpz_okp && !dns_name_equal(&old->origin, &zone->origin))
|
||||
|
|
@ -2030,12 +2261,17 @@ configure_rpz_zone(dns_view_t *view, const cfg_listelt_t *element,
|
|||
}
|
||||
|
||||
static isc_result_t
|
||||
configure_rpz(dns_view_t *view, const cfg_obj_t *rpz_obj,
|
||||
isc_boolean_t *old_rpz_okp)
|
||||
configure_rpz(dns_view_t *view, const cfg_obj_t **maps,
|
||||
const cfg_obj_t *rpz_obj, isc_boolean_t *old_rpz_okp)
|
||||
{
|
||||
isc_boolean_t dnsrps_enabled;
|
||||
const cfg_listelt_t *zone_element;
|
||||
char *rps_cstr;
|
||||
size_t rps_cstr_size;
|
||||
const cfg_obj_t *sub_obj;
|
||||
isc_boolean_t recursive_only_def;
|
||||
isc_boolean_t nsip_enabled, nsdname_enabled;
|
||||
dns_rpz_zbits_t nsip_on, nsdname_on;
|
||||
dns_ttl_t ttl_def;
|
||||
isc_uint32_t minupdateint_def;
|
||||
dns_rpz_zones_t *zones;
|
||||
|
|
@ -2051,13 +2287,80 @@ configure_rpz(dns_view_t *view, const cfg_obj_t *rpz_obj,
|
|||
if (zone_element == NULL)
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
result = dns_rpz_new_zones(&view->rpzs, view->mctx,
|
||||
#ifdef ENABLE_RPZ_NSIP
|
||||
nsip_enabled = ISC_TRUE;
|
||||
nsdname_enabled = ISC_TRUE;
|
||||
#else
|
||||
nsip_enabled = ISC_FALSE;
|
||||
nsdname_enabled = ISC_FALSE;
|
||||
#endif
|
||||
sub_obj = cfg_tuple_get(rpz_obj, "nsip-enable");
|
||||
if (!cfg_obj_isvoid(sub_obj))
|
||||
nsip_enabled = cfg_obj_asboolean(sub_obj);
|
||||
nsip_on = nsip_enabled ? DNS_RPZ_ALL_ZBITS : 0;
|
||||
|
||||
sub_obj = cfg_tuple_get(rpz_obj, "nsdname-enable");
|
||||
if (!cfg_obj_isvoid(sub_obj))
|
||||
nsdname_enabled = cfg_obj_asboolean(sub_obj);
|
||||
nsdname_on = nsdname_enabled ? DNS_RPZ_ALL_ZBITS : 0;
|
||||
|
||||
/*
|
||||
* "dnsrps-enable yes|no" can be either a global or response-policy
|
||||
* clause.
|
||||
*/
|
||||
dnsrps_enabled = ISC_FALSE;
|
||||
rps_cstr = NULL;
|
||||
rps_cstr_size = 0;
|
||||
sub_obj = NULL;
|
||||
(void)named_config_get(maps, "dnsrps-enable", &sub_obj);
|
||||
if (sub_obj != NULL) {
|
||||
dnsrps_enabled = cfg_obj_asboolean(sub_obj);
|
||||
}
|
||||
sub_obj = cfg_tuple_get(rpz_obj, "dnsrps-enable");
|
||||
if (!cfg_obj_isvoid(sub_obj)) {
|
||||
dnsrps_enabled = cfg_obj_asboolean(sub_obj);
|
||||
}
|
||||
#ifdef USE_DNSRPS
|
||||
if (dnsrps_enabled && librpz == NULL) {
|
||||
cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL,
|
||||
"\"dnsrps-enable yes\" but %s",
|
||||
librpz_lib_open_emsg.c);
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
#else
|
||||
if (dnsrps_enabled) {
|
||||
cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL,
|
||||
"\"dnsrps-enable yes\" but"
|
||||
" with `./configure --enable-dnsrps`");
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dnsrps_enabled) {
|
||||
/*
|
||||
* Generate the DNS Response Policy Service
|
||||
* configuration string.
|
||||
*/
|
||||
result = conf_dnsrps(view, maps,
|
||||
nsip_enabled, nsdname_enabled,
|
||||
&nsip_on, &nsdname_on,
|
||||
&rps_cstr, &rps_cstr_size,
|
||||
rpz_obj, zone_element);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
}
|
||||
|
||||
result = dns_rpz_new_zones(&view->rpzs, rps_cstr,
|
||||
rps_cstr_size, view->mctx,
|
||||
named_g_taskmgr, named_g_timermgr);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
zones = view->rpzs;
|
||||
|
||||
zones->p.nsip_on = nsip_on;
|
||||
zones->p.nsdname_on = nsdname_on;
|
||||
|
||||
sub_obj = cfg_tuple_get(rpz_obj, "recursive-only");
|
||||
if (!cfg_obj_isvoid(sub_obj) &&
|
||||
!cfg_obj_asboolean(sub_obj))
|
||||
|
|
@ -2141,15 +2444,33 @@ configure_rpz(dns_view_t *view, const cfg_obj_t *rpz_obj,
|
|||
* zones are unchanged, then use the same policy data.
|
||||
* Data for individual zones that must be reloaded will be merged.
|
||||
*/
|
||||
if (old != NULL && memcmp(&old->p, &zones->p, sizeof(zones->p)) != 0)
|
||||
if (*old_rpz_okp &&
|
||||
old != NULL && memcmp(&old->p, &zones->p, sizeof(zones->p)) != 0)
|
||||
{
|
||||
*old_rpz_okp = ISC_FALSE;
|
||||
}
|
||||
|
||||
if (*old_rpz_okp &&
|
||||
(old == NULL ||
|
||||
old->rps_cstr == NULL) != (zones->rps_cstr == NULL))
|
||||
{
|
||||
*old_rpz_okp = ISC_FALSE;
|
||||
}
|
||||
|
||||
if (*old_rpz_okp &&
|
||||
(zones->rps_cstr != NULL &&
|
||||
strcmp(old->rps_cstr, zones->rps_cstr) != 0))
|
||||
{
|
||||
*old_rpz_okp = ISC_FALSE;
|
||||
}
|
||||
|
||||
if (*old_rpz_okp) {
|
||||
dns_rpz_detach_rpzs(&view->rpzs);
|
||||
dns_rpz_attach_rpzs(pview->rpzs, &view->rpzs);
|
||||
} else if (old != NULL && pview != NULL) {
|
||||
pview->rpzs->rpz_ver += 1;
|
||||
++pview->rpzs->rpz_ver;
|
||||
view->rpzs->rpz_ver = pview->rpzs->rpz_ver;
|
||||
cfg_obj_log(rpz_obj, named_g_lctx, ISC_LOG_DEBUG(1),
|
||||
cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_DEBUG_LEVEL1,
|
||||
"updated RPZ policy: version %d",
|
||||
view->rpzs->rpz_ver);
|
||||
}
|
||||
|
|
@ -3429,7 +3750,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
|
|||
obj = NULL;
|
||||
if (view->rdclass == dns_rdataclass_in && need_hints &&
|
||||
named_config_get(maps, "response-policy", &obj) == ISC_R_SUCCESS) {
|
||||
CHECK(configure_rpz(view, obj, &old_rpz_ok));
|
||||
CHECK(configure_rpz(view, maps, obj, &old_rpz_ok));
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
|
|
@ -3460,6 +3781,32 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
|
|||
ISC_FALSE));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that a master or slave zone was found for each
|
||||
* zone named in the response policy statement
|
||||
* unless we are using RPZ service interface.
|
||||
*/
|
||||
if (view->rpzs != NULL && !view->rpzs->p.dnsrps_enabled) {
|
||||
dns_rpz_num_t n;
|
||||
|
||||
for (n = 0; n < view->rpzs->p.num_zones; ++n) {
|
||||
if ((view->rpzs->defined & DNS_RPZ_ZBIT(n)) == 0) {
|
||||
char namebuf[DNS_NAME_FORMATSIZE];
|
||||
|
||||
dns_name_format(&view->rpzs->zones[n]->origin,
|
||||
namebuf, sizeof(namebuf));
|
||||
isc_log_write(named_g_lctx,
|
||||
NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_SERVER,
|
||||
DNS_RPZ_ERROR_LEVEL, "rpz '%s'"
|
||||
" is not a master or slave zone",
|
||||
namebuf);
|
||||
result = ISC_R_NOTFOUND;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're allowing added zones, then load zone configuration
|
||||
* from the newzone file for zones that were added during previous
|
||||
|
|
@ -5567,10 +5914,14 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
|
|||
}
|
||||
|
||||
/*
|
||||
* Note whether this is a response policy zone and which one if so.
|
||||
* Note whether this is a response policy zone and which one if so,
|
||||
* unless we are using RPZ service interface. In that case, the
|
||||
* BIND zone database has nothing to do with rpz and so we don't care.
|
||||
*/
|
||||
for (rpz_num = 0; ; ++rpz_num) {
|
||||
if (view->rpzs == NULL || rpz_num >= view->rpzs->p.num_zones) {
|
||||
if (view->rpzs == NULL || rpz_num >= view->rpzs->p.num_zones ||
|
||||
view->rpzs->p.dnsrps_enabled)
|
||||
{
|
||||
rpz_num = DNS_RPZ_INVALID_NUM;
|
||||
break;
|
||||
}
|
||||
|
|
@ -8315,6 +8666,22 @@ load_configuration(const char *filename, named_server_t *server,
|
|||
|
||||
(void) named_server_loadnta(server);
|
||||
|
||||
#ifdef USE_DNSRPS
|
||||
/*
|
||||
* Start and connect to the DNS Response Policy Service
|
||||
* daemon, dnsrpzd, for each view that uses DNSRPS.
|
||||
*/
|
||||
for (view = ISC_LIST_HEAD(server->viewlist);
|
||||
view != NULL;
|
||||
view = ISC_LIST_NEXT(view, link)) {
|
||||
result = dns_dnsrps_connect(view->rpzs);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
view = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
|
|
@ -8757,6 +9124,12 @@ named_server_create(isc_mem_t *mctx, named_server_t **serverp) {
|
|||
server->mctx = mctx;
|
||||
server->task = NULL;
|
||||
server->zonemgr = NULL;
|
||||
|
||||
#ifdef USE_DNSRPS
|
||||
CHECKFATAL(dns_dnsrps_server_create(),
|
||||
"initializing RPZ service interface");
|
||||
#endif
|
||||
|
||||
/* Initialize server data structures. */
|
||||
server->interfacemgr = NULL;
|
||||
ISC_LIST_INIT(server->viewlist);
|
||||
|
|
@ -8913,6 +9286,10 @@ named_server_destroy(named_server_t **serverp) {
|
|||
dns_dt_detach(&server->dtenv);
|
||||
#endif /* HAVE_DNSTAP */
|
||||
|
||||
#ifdef USE_DNSRPS
|
||||
dns_dnsrps_server_destroy();
|
||||
#endif
|
||||
|
||||
named_controls_destroy(&server->controls);
|
||||
|
||||
isc_stats_detach(&server->zonestats);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ VERSION=@BIND9_VERSION@
|
|||
|
||||
@BIND9_MAKE_INCLUDES@
|
||||
|
||||
SUBDIRS = dlzexternal dyndb pipelined rndc rsabigexponent tkey
|
||||
SUBDIRS = dlzexternal dyndb pipelined rndc rpz rsabigexponent tkey
|
||||
|
||||
CINCLUDES = ${ISC_INCLUDES} ${DNS_INCLUDES}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ usage() {
|
|||
fprintf(stderr, "usage: feature-test <arg>\n");
|
||||
fprintf(stderr, "args:\n");
|
||||
fprintf(stderr, " --edns-version\n");
|
||||
fprintf(stderr, " --enable-dnsrps\n");
|
||||
fprintf(stderr, " --enable-filter-aaaa\n");
|
||||
fprintf(stderr, " --gethostname\n");
|
||||
fprintf(stderr, " --gssapi\n");
|
||||
|
|
@ -54,6 +55,14 @@ main(int argc, char **argv) {
|
|||
return (1);
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "--enable-dnsrps") == 0) {
|
||||
#ifdef USE_DNSRPS
|
||||
return (0);
|
||||
#else
|
||||
return (1);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "--enable-filter-aaaa") == 0) {
|
||||
#ifdef ALLOW_FILTER_AAAA
|
||||
return (0);
|
||||
|
|
|
|||
2
bin/tests/system/rpz/.gitignore
vendored
Normal file
2
bin/tests/system/rpz/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
alt-dnsrpzd-license.conf
|
||||
dnsrps
|
||||
45
bin/tests/system/rpz/Makefile.in
Normal file
45
bin/tests/system/rpz/Makefile.in
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# Copyright (C) 2011-2013, 2015, 2016 Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
VERSION=@BIND9_VERSION@
|
||||
|
||||
@BIND9_MAKE_INCLUDES@
|
||||
|
||||
CINCLUDES = ${ISC_INCLUDES} ${DNS_INCLUDES}
|
||||
|
||||
CDEFINES =
|
||||
CWARNINGS =
|
||||
|
||||
DNSLIBS =
|
||||
ISCLIBS = ../../../../lib/isc/libisc.@A@
|
||||
|
||||
DNSDEPLIBS =
|
||||
ISCDEPLIBS = ../../../../lib/isc/libisc.@A@
|
||||
|
||||
DEPLIBS = ${ISCDEPLIBS}
|
||||
|
||||
LIBS = ${ISCLIBS} @LIBS@
|
||||
|
||||
TARGETS = dnsrps@EXEEXT@
|
||||
|
||||
DNSRPSOBJS = dnsrps.@O@
|
||||
|
||||
SRCS = dnsrps.c
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
all: dnsrps@EXEEXT@
|
||||
|
||||
dnsrps@EXEEXT@: ${DNSRPSOBJS} ${DEPLIBS}
|
||||
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${DNSRPSOBJS} ${LIBS}
|
||||
|
||||
clean distclean::
|
||||
rm -f ${TARGETS}
|
||||
|
||||
161
bin/tests/system/rpz/ckdnsrps.sh
Normal file
161
bin/tests/system/rpz/ckdnsrps.sh
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
#! /bin/sh
|
||||
#
|
||||
# Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
set -e
|
||||
|
||||
# Say on stdout whether to test DNSRPS
|
||||
# and create dnsrps.conf and dnsrps-slave.conf
|
||||
# Note that dnsrps.conf and dnsrps-slave.conf are included in named.conf
|
||||
# and differ from dnsrpz.conf which is used by dnsrpzd.
|
||||
|
||||
|
||||
SYSTEMTESTTOP=..
|
||||
. $SYSTEMTESTTOP/conf.sh
|
||||
|
||||
DNSRPS_CMD=../rpz/dnsrps
|
||||
|
||||
AS_NS=
|
||||
TEST_DNSRPS=
|
||||
MCONF=dnsrps.conf
|
||||
SCONF=dnsrps-slave.conf
|
||||
USAGE="$0: [-xAD] [-M dnsrps.conf] [-S dnsrps-slave.conf]"
|
||||
while getopts "xADM:S:" c; do
|
||||
case $c in
|
||||
x) set -x; DEBUG=-x;;
|
||||
A) AS_NS=yes;;
|
||||
D) TEST_DNSRPS=yes;;
|
||||
M) MCONF="$OPTARG";;
|
||||
S) SCONF="$OPTARG";;
|
||||
*) echo "$USAGE" 1>&2; exit 1;;
|
||||
esac
|
||||
done
|
||||
shift `expr $OPTIND - 1 || true`
|
||||
if [ "$#" -ne 0 ]; then
|
||||
echo "$USAGE" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# erase any existing conf files
|
||||
cat /dev/null > $MCONF
|
||||
cat /dev/null > $SCONF
|
||||
|
||||
add_conf () {
|
||||
echo "$*" >>$MCONF
|
||||
echo "$*" >>$SCONF
|
||||
}
|
||||
|
||||
if ! $FEATURETEST --enable-dnsrps; then
|
||||
if [ -n "$TEST_DNSRPS" ]; then
|
||||
add_conf "## DNSRPS disabled at compile time"
|
||||
fi
|
||||
add_conf "#skip"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -z "$TEST_DNSRPS" ]; then
|
||||
add_conf "## DNSRPS testing is disabled"
|
||||
add_conf '#skip'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ! -x $DNSRPS_CMD ]; then
|
||||
add_conf "## make $DNSRPS_CMD to test DNSRPS"
|
||||
add_conf '#skip'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if $DNSRPS_CMD -a >/dev/null; then :
|
||||
else
|
||||
add_conf "## DNSRPS provider library is not available"
|
||||
add_conf '#skip'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
CMN=" dnsrps-options { dnsrpzd-conf ../dnsrpzd.conf
|
||||
dnsrpzd-sock ../dnsrpzd.sock
|
||||
dnsrpzd-rpzf ../dnsrpzd.rpzf
|
||||
dnsrpzd-args '-dddd -L stdout'
|
||||
log-level 3"
|
||||
|
||||
MASTER="$CMN"
|
||||
if [ -n "$AS_NS" ]; then
|
||||
MASTER="$MASTER
|
||||
qname-as-ns yes
|
||||
ip-as-ns yes"
|
||||
fi
|
||||
|
||||
# write dnsrps setttings for master resolver
|
||||
cat <<EOF >>$MCONF
|
||||
$MASTER };
|
||||
EOF
|
||||
|
||||
# write dnsrps setttings for resolvers that should not start dnsrpzd
|
||||
cat <<EOF >>$SCONF
|
||||
$CMN
|
||||
dnsrpzd '' }; # do not start dnsrpzd
|
||||
EOF
|
||||
|
||||
|
||||
# DNSRPS is available.
|
||||
# The test should fail if the license is bad.
|
||||
add_conf "dnsrps-enable yes;"
|
||||
|
||||
# Use alt-dnsrpzd-license.conf if it exists
|
||||
CUR_L=dnsrpzd-license-cur.conf
|
||||
ALT_L=alt-dnsrpzd-license.conf
|
||||
# try ../rpz/alt-dnsrpzd-license.conf if alt-dnsrpzd-license.conf does not exist
|
||||
[ -s $ALT_L ] || ALT_L=../rpz/alt-dnsrpzd-license.conf
|
||||
if [ -s $ALT_L ]; then
|
||||
SRC_L=$ALT_L
|
||||
USE_ALT=
|
||||
else
|
||||
SRC_L=../rpz/dnsrpzd-license.conf
|
||||
USE_ALT="## consider installing alt-dnsrpzd-license.conf"
|
||||
fi
|
||||
cp $SRC_L $CUR_L
|
||||
|
||||
# parse $CUR_L for the license zone name, master IP addresses, and optional
|
||||
# transfer-source IP addresses
|
||||
eval `sed -n -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'\
|
||||
-e 's/.*zone *\([-a-z0-9]*.license.fastrpz.com\).*/NAME=\1/p' \
|
||||
-e 's/.*farsight_fastrpz_license *\([0-9.]*\);.*/IPV4=\1/p' \
|
||||
-e 's/.*farsight_fastrpz_license *\([0-9a-f:]*\);.*/IPV6=\1/p' \
|
||||
-e 's/.*transfer-source *\([0-9.]*\);.*/TS4=-b\1/p' \
|
||||
-e 's/.*transfer-source *\([0-9a-f:]*\);.*/TS6=-b\1/p' \
|
||||
-e 's/.*transfer-source-v6 *\([0-9a-f:]*\);.*/TS6=-b\1/p' \
|
||||
$CUR_L`
|
||||
if [ -z "$NAME" ]; then
|
||||
add_conf "## no DNSRPS tests; no license domain name in $SRC_L"
|
||||
add_conf '#fail'
|
||||
exit 0
|
||||
fi
|
||||
if [ -z "$IPV4" ]; then
|
||||
IPV4=license1.fastrpz.com
|
||||
TS4=
|
||||
fi
|
||||
if [ -z "$IPV6" ]; then
|
||||
IPV6=license1.fastrpz.com
|
||||
TS6=
|
||||
fi
|
||||
|
||||
# This TSIG key is common and NOT a secret
|
||||
KEY='hmac-sha256:farsight_fastrpz_license:f405d02b4c8af54855fcebc1'
|
||||
|
||||
# Try IPv4 and then IPv6 to deal with IPv6 tunnel and connectivity problems
|
||||
if `$DIG -4 -t axfr -y$KEY $TS4 $NAME @$IPV4 \
|
||||
| grep -i "^$NAME.*TXT" >/dev/null`; then
|
||||
exit 0
|
||||
fi
|
||||
if `$DIG -6 -t axfr -y$KEY $TS6 $NAME @$IPV6 \
|
||||
| grep -i "^$NAME.*TXT" >/dev/null`; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
add_conf "## DNSRPS lacks a valid license via $SRC_L"
|
||||
[ -z "$USE_ALT" ] || add_conf "$USE_ALT"
|
||||
add_conf '#fail'
|
||||
|
|
@ -10,7 +10,9 @@ rm -f proto.* dsset-* trusted.conf dig.out* nsupdate.tmp ns*/*tmp
|
|||
rm -f ns*/*.key ns*/*.private ns2/tld2s.db ns2/bl.tld2.db
|
||||
rm -f ns3/bl*.db ns*/*switch ns*/empty.db ns*/empty.db.jnl
|
||||
rm -f ns5/requests ns5/example.db ns5/bl.db ns5/*.perf
|
||||
rm -f */named.memstats */named.run */named.stats */session.key
|
||||
rm -f */*.jnl */*.core */*.pid
|
||||
rm -f */named.memstats */*.run */named.stats */session.key
|
||||
rm -f */*.log */*.jnl */*core */*.pid
|
||||
rm -f */policy2.db
|
||||
rm -f ns*/named.lock
|
||||
rm -f dnsrps*.conf
|
||||
rm -f dnsrpzd-license-cur.conf dnsrpzd.rpzf dnsrpzd.sock dnsrpzd.pid
|
||||
|
|
|
|||
164
bin/tests/system/rpz/dnsrps.c
Normal file
164
bin/tests/system/rpz/dnsrps.c
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2013, 2016 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* -a exit(0) if dnsrps is available or dlopen() msg if not
|
||||
* -p print the path to dnsrpzd configured in dnsrps so that
|
||||
* dnsrpzd can be run by a setup.sh script.
|
||||
* Exit(1) if dnsrps is not available
|
||||
* -n domain print the serial number of a domain to check if a new
|
||||
* version of a policy zone has been transferred to dnsrpzd.
|
||||
* Exit(1) if dnsrps is not available
|
||||
* -w sec.ond wait for seconds, because `sleep 0.1` is not portable
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <isc/boolean.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#ifdef USE_DNSRPS
|
||||
#define LIBRPZ_LIB_OPEN DNSRPS_LIB_OPEN
|
||||
#include <dns/librpz.h>
|
||||
|
||||
librpz_t *librpz;
|
||||
#else
|
||||
typedef struct {char c[120];} librpz_emsg_t;
|
||||
#endif
|
||||
|
||||
|
||||
static isc_boolean_t link_dnsrps(librpz_emsg_t *emsg);
|
||||
|
||||
|
||||
#define USAGE "usage: [-ap] [-n domain] [-w sec.onds]\n"
|
||||
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
#ifdef USE_DNSRPS
|
||||
char cstr[sizeof("zone ")+1024+10];
|
||||
librpz_clist_t *clist;
|
||||
librpz_client_t *client;
|
||||
librpz_rsp_t *rsp;
|
||||
uint32_t serial;
|
||||
#endif
|
||||
double seconds;
|
||||
librpz_emsg_t emsg;
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
while ((i = getopt(argc, argv, "apn:w:")) != -1) {
|
||||
switch (i) {
|
||||
case 'a':
|
||||
if (!link_dnsrps(&emsg)) {
|
||||
printf("I:%s\n", emsg.c);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
|
||||
case 'p':
|
||||
if (!link_dnsrps(&emsg)) {
|
||||
fprintf(stderr, "## %s\n", emsg.c);
|
||||
return (1);
|
||||
}
|
||||
#ifdef USE_DNSRPS
|
||||
printf("%s\n", librpz->dnsrpzd_path);
|
||||
return (0);
|
||||
#else
|
||||
INSIST(0);
|
||||
#endif
|
||||
|
||||
case 'n':
|
||||
if (!link_dnsrps(&emsg)) {
|
||||
fprintf(stderr, "## %s\n", emsg.c);
|
||||
return (1);
|
||||
}
|
||||
#ifdef USE_DNSRPS
|
||||
/*
|
||||
* Get the serial number of a policy zone from
|
||||
* a running dnsrpzd daemon.
|
||||
*/
|
||||
clist = librpz->clist_create(&emsg, NULL, NULL,
|
||||
NULL, NULL, NULL);
|
||||
if (clist == NULL) {
|
||||
fprintf(stderr, "## %s: %s\n", optarg, emsg.c);
|
||||
return (1);
|
||||
}
|
||||
snprintf(cstr, sizeof(cstr),
|
||||
"zone %s; dnsrpzd \"\";"
|
||||
" dnsrpzd-sock dnsrpzd.sock;"
|
||||
" dnsrpzd-rpzf dnsrpzd.rpzf",
|
||||
optarg);
|
||||
client = librpz->client_create(&emsg, clist,
|
||||
cstr, true);
|
||||
if (client == NULL) {
|
||||
fprintf(stderr, "## %s\n", emsg.c);
|
||||
return (1);
|
||||
}
|
||||
|
||||
rsp = NULL;
|
||||
if (!librpz->rsp_create(&emsg, &rsp, NULL,
|
||||
client, true, false) ||
|
||||
rsp == NULL) {
|
||||
fprintf(stderr, "## %s\n", emsg.c);
|
||||
librpz->client_detach(&client);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (!librpz->soa_serial(&emsg, &serial, optarg, rsp)) {
|
||||
fprintf(stderr, "## %s\n", emsg.c);
|
||||
librpz->client_detach(&client);
|
||||
return (1);
|
||||
}
|
||||
librpz->rsp_detach(&rsp);
|
||||
librpz->client_detach(&client);
|
||||
printf("%d\n", serial);
|
||||
return (0);
|
||||
#else
|
||||
INSIST(0);
|
||||
#endif
|
||||
|
||||
case 'w':
|
||||
seconds = strtod(optarg, &p);
|
||||
if (seconds <= 0 || *p != '\0') {
|
||||
fputs(USAGE, stderr);
|
||||
return (1);
|
||||
}
|
||||
usleep((int)(seconds*1000.0*1000.0));
|
||||
return (0);
|
||||
|
||||
default:
|
||||
fputs(USAGE, stderr);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
fputs(USAGE, stderr);
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
static isc_boolean_t
|
||||
link_dnsrps(librpz_emsg_t *emsg) {
|
||||
#ifdef USE_DNSRPS
|
||||
librpz = librpz_lib_open(emsg, NULL, DNSRPS_LIBRPZ_PATH);
|
||||
if (librpz == NULL)
|
||||
return (ISC_FALSE);
|
||||
|
||||
return (ISC_TRUE);
|
||||
#else
|
||||
snprintf(emsg->c, sizeof(emsg->c), "DNSRPS not configured");
|
||||
return (ISC_FALSE);
|
||||
#endif
|
||||
}
|
||||
10
bin/tests/system/rpz/dnsrpzd-license.conf
Normal file
10
bin/tests/system/rpz/dnsrpzd-license.conf
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
zone isc.license.fastrpz.com {
|
||||
masters port 53 {
|
||||
KEY farsight_fastrpz_license 104.244.14.176;
|
||||
KEY farsight_fastrpz_license 2620:11c:f008::176;
|
||||
};
|
||||
};
|
||||
|
||||
key farsight_fastrpz_license {
|
||||
algorithm hmac-sha256; secret "f405d02b4c8af54855fcebc1";
|
||||
};
|
||||
49
bin/tests/system/rpz/dnsrpzd.conf
Normal file
49
bin/tests/system/rpz/dnsrpzd.conf
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# dnsrpzd configuration.
|
||||
|
||||
pid-file ../dnsrpzd.pid
|
||||
|
||||
include ../dnsrpzd-license-cur.conf
|
||||
|
||||
# configure NOTIFY and zone transfers
|
||||
port 5301;
|
||||
listen-on port 5301 { 10.53.0.3; };
|
||||
allow-notify { 10.53.0.0/24; };
|
||||
|
||||
zone "bl0" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl1" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl2" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl3" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl4" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl5" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl6" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl7" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl8" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl9" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl10" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl11" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl12" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl13" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl14" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl15" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl16" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl17" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl18" {type master; file "../ns5/bl.db"; };
|
||||
zone "bl19" {type master; file "../ns5/bl.db"; };
|
||||
|
||||
zone "bl" {type slave; masters port 5300 { 10.53.0.3; }; };
|
||||
zone "bl-2" {type slave; masters port 5300 { 10.53.0.3; }; };
|
||||
zone "bl-given" {type slave; masters port 5300 { 10.53.0.3; }; };
|
||||
zone "bl-passthru" {type slave; masters port 5300 { 10.53.0.3; }; };
|
||||
zone "bl-no-op" {type slave; masters port 5300 { 10.53.0.3; }; };
|
||||
zone "bl-disabled" {type slave; masters port 5300 { 10.53.0.3; }; };
|
||||
zone "bl-nodata" {type slave; masters port 5300 { 10.53.0.3; }; };
|
||||
zone "bl-nxdomain" {type slave; masters port 5300 { 10.53.0.3; }; };
|
||||
zone "bl-cname" {type slave; masters port 5300 { 10.53.0.3; }; };
|
||||
zone "bl-wildcname" {type slave; masters port 5300 { 10.53.0.3; }; };
|
||||
zone "bl-garden" {type slave; masters port 5300 { 10.53.0.3; }; };
|
||||
zone "bl-drop" {type slave; masters port 5300 { 10.53.0.3; }; };
|
||||
zone "bl-tcp-only" {type slave; masters port 5300 { 10.53.0.3; }; };
|
||||
zone "bl.tld2" {type slave; masters port 5300 { 10.53.0.3; }; };
|
||||
|
||||
zone "policy1" {type slave; masters port 5300 { 10.53.0.6; }; };
|
||||
zone "policy2" {type slave; masters port 5300 { 10.53.0.7; }; };
|
||||
3
bin/tests/system/rpz/fastrpz.license
Normal file
3
bin/tests/system/rpz/fastrpz.license
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
NAME='isc.license.fastrpz.com'
|
||||
KEY='hmac-sha256:farsight_fastrpz_license:f405d02b4c8af54855fcebc1'
|
||||
LSERVER=license1.fastrpz.com
|
||||
|
|
@ -43,4 +43,5 @@ zone "subsub.sub3.tld2." {type master; file "tld2.db";};
|
|||
|
||||
zone "tld2s." {type master; file "tld2s.db";};
|
||||
|
||||
zone "bl.tld2." {type master; file "bl.tld2.db"; notify yes; notify-delay 1;};
|
||||
zone "bl.tld2." {type master; file "bl.tld2.db";
|
||||
notify yes; notify-delay 0;};
|
||||
|
|
|
|||
|
|
@ -15,3 +15,5 @@ $TTL 300
|
|||
|
||||
; regression testing for some old crashes
|
||||
example.com NS example.org.
|
||||
|
||||
domain.com cname foobar.com
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ options {
|
|||
session-keyfile "session.key";
|
||||
listen-on { 10.53.0.3; };
|
||||
listen-on-v6 { none; };
|
||||
notify no;
|
||||
notify yes;
|
||||
minimal-responses no;
|
||||
|
||||
response-policy {
|
||||
|
|
@ -43,9 +43,17 @@ options {
|
|||
min-ns-dots 0
|
||||
qname-wait-recurse yes
|
||||
min-update-interval 0
|
||||
nsdname-enable yes
|
||||
nsip-enable yes
|
||||
;
|
||||
|
||||
include "../dnsrps.conf";
|
||||
also-notify { 10.53.0.3 port 5301; };
|
||||
notify-delay 0;
|
||||
};
|
||||
|
||||
logging { category rpz { default_debug; }; };
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-sha256;
|
||||
|
|
@ -87,5 +95,5 @@ zone "bl-tcp-only." {type master; file "bl-tcp-only.db";
|
|||
zone "bl.tld2." {type slave; file "bl.tld2.db"; masters {10.53.0.2;};
|
||||
request-ixfr no; masterfile-format text;};
|
||||
|
||||
zone "crash1.tld2" {type master; file "crash1";};
|
||||
zone "crash2.tld3." {type master; file "crash2";};
|
||||
zone "crash1.tld2" {type master; file "crash1"; notify no;};
|
||||
zone "crash2.tld3." {type master; file "crash2"; notify no;};
|
||||
|
|
|
|||
|
|
@ -22,12 +22,14 @@ options {
|
|||
listen-on { 10.53.0.5; };
|
||||
listen-on-v6 { none; };
|
||||
ixfr-from-differences yes;
|
||||
notify-delay 1;
|
||||
notify-delay 0;
|
||||
notify yes;
|
||||
minimal-responses no;
|
||||
|
||||
# turn rpz on or off
|
||||
include "rpz-switch";
|
||||
|
||||
include "../dnsrps-slave.conf";
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
|
|
|
|||
|
|
@ -25,3 +25,5 @@ example.tld5. NS ns
|
|||
NS ns1
|
||||
ns A 10.53.0.5
|
||||
ns1 A 10.53.0.5
|
||||
|
||||
as-ns TXT "rewritten with ip-as-ns and qname-as-ns"
|
||||
|
|
|
|||
|
|
@ -20,9 +20,17 @@ options {
|
|||
forwarders { 10.53.0.3; };
|
||||
minimal-responses no;
|
||||
|
||||
response-policy { zone "policy1" min-update-interval 0; };
|
||||
response-policy {
|
||||
zone "policy1" min-update-interval 0;
|
||||
} qname-wait-recurse yes
|
||||
nsip-enable yes
|
||||
nsdname-enable yes;
|
||||
|
||||
include "../dnsrps-slave.conf";
|
||||
};
|
||||
|
||||
logging { category rpz { default_debug; }; };
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-sha256;
|
||||
|
|
@ -38,5 +46,7 @@ zone "policy1" {
|
|||
type slave;
|
||||
masters { 10.53.0.5; };
|
||||
file "empty.db";
|
||||
also-notify { 10.53.0.3 port 5301; };
|
||||
notify-delay 0;
|
||||
allow-transfer { any; };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -18,11 +18,18 @@ options {
|
|||
listen-on-v6 { none; };
|
||||
minimal-responses no;
|
||||
|
||||
response-policy { zone "policy2"; }
|
||||
qname-wait-recurse no
|
||||
min-update-interval 0;
|
||||
response-policy {
|
||||
zone "policy2";
|
||||
} qname-wait-recurse no
|
||||
nsip-enable yes
|
||||
nsdname-enable yes
|
||||
min-update-interval 0;
|
||||
|
||||
include "../dnsrps-slave.conf";
|
||||
};
|
||||
|
||||
logging { category rpz { default_debug; }; };
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-sha256;
|
||||
|
|
@ -38,6 +45,8 @@ zone "policy2" {
|
|||
type slave;
|
||||
masters { 10.53.0.5; };
|
||||
file "policy2.db";
|
||||
also-notify { 10.53.0.3 port 5301; };
|
||||
notify-delay 0;
|
||||
allow-transfer { any; };
|
||||
request-ixfr no; // force axfr on rndc reload
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# touch dnsrps-off to not test with DNSRPS
|
||||
|
||||
set -e
|
||||
|
||||
SYSTEMTESTTOP=..
|
||||
|
|
@ -13,7 +15,28 @@ SYSTEMTESTTOP=..
|
|||
|
||||
QPERF=`$SHELL qperf.sh`
|
||||
|
||||
$SHELL clean.sh
|
||||
USAGE="$0: [-Dx]"
|
||||
DEBUG=
|
||||
while getopts "Dx" c; do
|
||||
case $c in
|
||||
x) set -x; DEBUG=-x;;
|
||||
D) TEST_DNSRPS="-D";;
|
||||
*) echo "$USAGE" 1>&2; exit 1;;
|
||||
esac
|
||||
done
|
||||
shift `expr $OPTIND - 1 || true`
|
||||
if test "$#" -ne 0; then
|
||||
echo "$USAGE" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$SHELL clean.sh $DEBUG
|
||||
|
||||
# decide whether to test DNSRPS
|
||||
# Note that dnsrps.conf and dnsrps-slave.conf are included in named.conf
|
||||
# and differ from dnsrpz.conf which is used by dnsrpzd.
|
||||
$SHELL ../rpz/ckdnsrps.sh -A $TEST_DNSRPS $DEBUG
|
||||
test -z "`grep 'dnsrps-enable yes' dnsrps.conf`" && TEST_DNSRPS=
|
||||
|
||||
# set up test policy zones.
|
||||
# bl is the main test zone
|
||||
|
|
@ -48,9 +71,11 @@ response-policy {
|
|||
zone "bl10"; zone "bl11"; zone "bl12"; zone "bl13"; zone "bl14";
|
||||
zone "bl15"; zone "bl16"; zone "bl17"; zone "bl18"; zone "bl19";
|
||||
} recursive-only no
|
||||
qname-wait-recurse no
|
||||
nsip-enable yes
|
||||
nsdname-enable yes
|
||||
max-policy-ttl 90
|
||||
break-dnssec yes
|
||||
qname-wait-recurse no
|
||||
;
|
||||
EOF
|
||||
|
||||
|
|
@ -110,3 +135,11 @@ $PERL -e 'for ($cnt = $val = 1; $cnt <= 3000; ++$cnt) {
|
|||
cp ns2/bl.tld2.db.in ns2/bl.tld2.db
|
||||
cp ns5/empty.db.in ns5/empty.db
|
||||
cp ns5/empty.db.in ns5/policy2.db
|
||||
|
||||
# Run dnsrpzd to get the license and prime the static policy zones
|
||||
if test -n "$TEST_DNSRPS"; then
|
||||
DNSRPZD="`../rpz/dnsrps -p`"
|
||||
cd ns3
|
||||
"$DNSRPZ" -D../dnsrpzd.rpzf -S../dnsrpzd.sock -C../dnsrpzd.conf \
|
||||
-w 0 -dddd -L stdout >./dnsrpzd.run 2>&1
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -36,4 +36,7 @@ update add a4-1.tld2.bl. 300 A 12.12.12.12
|
|||
; prefer policy for largest NS name
|
||||
update add ns.sub3.tld2.rpz-nsdname.bl. 300 A 127.0.0.1
|
||||
update add ns.subsub.sub3.tld2.rpz-nsdname.bl. 300 A 127.0.0.2
|
||||
|
||||
; ip-as-qname rewrites all of tld5
|
||||
update add ns.tld5.bl. 300 A 12.12.12.12
|
||||
send
|
||||
|
|
|
|||
|
|
@ -25,4 +25,7 @@ update add 24.0.0.168.192.rpz-ip.bl 300 CNAME 24.0.0.168.192.
|
|||
;
|
||||
; prefer NSIP policy to NSDNAME policy
|
||||
update add ns.tld2.rpz-nsdname.bl. 300 CNAME 10.0.0.1
|
||||
|
||||
; ip-as-ns rewrites all of tld5
|
||||
update add 32.5.0.53.10.rpz-ip.bl. 300 A 12.12.12.12
|
||||
send
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2011-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# $Id$
|
||||
|
||||
|
||||
# test response policy zones (RPZ)
|
||||
|
||||
# touch dnsrps-off to not test with DNSRPS
|
||||
# touch dnsrps-only to not test with classic RPZ
|
||||
|
||||
SYSTEMTESTTOP=..
|
||||
. $SYSTEMTESTTOP/conf.sh
|
||||
|
||||
|
|
@ -22,13 +24,20 @@ ns6=$ns.6 # a forwarding server
|
|||
ns7=$ns.7 # another rewriting resolver
|
||||
|
||||
HAVE_CORE=
|
||||
|
||||
status=0
|
||||
|
||||
DEBUG=
|
||||
SAVE_RESULTS=
|
||||
DNSRPS_TEST_MODE= # "" to test with and then without DNSRPS
|
||||
ARGS=
|
||||
|
||||
|
||||
USAGE="$0: [-x]"
|
||||
while getopts "x" c; do
|
||||
USAGE="$0: [-xS] [-D {1,2}]"
|
||||
while getopts "xSD:" c; do
|
||||
case $c in
|
||||
x) set -x;;
|
||||
x) set -x; DEBUG=-x; ARGS="$ARGS -x";;
|
||||
S) SAVE_RESULTS=-S; ARGS="$ARGS -S";;
|
||||
D) DNSRPS_TEST_MODE="$OPTARG";; # with or without DNSRPZ
|
||||
*) echo "$USAGE" 1>&2; exit 1;;
|
||||
esac
|
||||
done
|
||||
|
|
@ -48,8 +57,51 @@ comment () {
|
|||
fi
|
||||
}
|
||||
|
||||
DNSRPSCMD=./dnsrps
|
||||
RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p 9953 -s"
|
||||
|
||||
# Run the tests twice, first without DNSRPS and then with if it is available
|
||||
if [ -z "$DNSRPS_TEST_MODE" ]; then
|
||||
if [ -e dnsrps-only ]; then
|
||||
echo "I:'dnsrps-only' found: skipping native RPZ sub-test"
|
||||
else
|
||||
echo "I:running native RPZ sub-test"
|
||||
$SHELL ./$0 -D1 $ARGS || status=1
|
||||
fi
|
||||
|
||||
if [ -e dnsrps-off ]; then
|
||||
echo "I:'dnsrps-off' found: skipping DNSRPS sub-test"
|
||||
else
|
||||
echo "I:attempting to configure servers with DNSRPS..."
|
||||
$PERL $SYSTEMTESTTOP/stop.pl .
|
||||
$SHELL ./setup.sh -D $DEBUG
|
||||
sed -n 's/^## /I:/p' dnsrps.conf
|
||||
if grep '^#fail' dnsrps.conf >/dev/null; then
|
||||
echo "I:exit status: 1"
|
||||
exit 1
|
||||
fi
|
||||
if test -z "`grep '^#skip' dnsrps.conf`"; then
|
||||
echo "I:running DNSRPS sub-test"
|
||||
$PERL $SYSTEMTESTTOP/start.pl --noclean --restart .
|
||||
$SHELL ./$0 $ARGS -D2 || status=1
|
||||
else
|
||||
echo "I:DNSRPS sub-test skipped"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "I:exit status: $status"
|
||||
exit $status
|
||||
fi
|
||||
|
||||
if test -x $DNSRPSCMD; then
|
||||
# speed up the many delays for dnsrpzd by waiting only 0.1 seconds
|
||||
WAIT_CMD="$DNSRPSCMD -w 0.1"
|
||||
TEN_SECS=100
|
||||
else
|
||||
WAIT_CMD="sleep 1"
|
||||
TEN_SECS=10
|
||||
fi
|
||||
|
||||
digcmd () {
|
||||
if test "$1" = TCP; then
|
||||
shift
|
||||
|
|
@ -57,9 +109,9 @@ digcmd () {
|
|||
# Default to +noauth and @$ns3
|
||||
# Also default to -bX where X is the @value so that OS X will choose
|
||||
# the right IP source address.
|
||||
digcmd_args=`echo "+noadd +time=2 +tries=1 -p 5300 $*" | \
|
||||
sed -e "/@/!s/.*/& @$ns3/" \
|
||||
-e '/-b/!s/@\([^ ]*\)/@\1 -b\1/' \
|
||||
digcmd_args=`echo "+nocookie +noadd +time=2 +tries=1 -p 5300 $*" | \
|
||||
sed -e "/@/!s/.*/& @$ns3/" \
|
||||
-e '/-b/!s/@\([^ ]*\)/@\1 -b\1/' \
|
||||
-e '/+n?o?auth/!s/.*/+noauth &/'`
|
||||
#echo I:dig $digcmd_args 1>&2
|
||||
$DIG $digcmd_args
|
||||
|
|
@ -69,6 +121,7 @@ digcmd () {
|
|||
GROUP_NM=
|
||||
TEST_NUM=0
|
||||
make_dignm () {
|
||||
TEST_NUM=`expr $TEST_NUM : '\([0-9]*\).*'` # trim '+' characters
|
||||
TEST_NUM=`expr $TEST_NUM + 1`
|
||||
DIGNM=dig.out$GROUP_NM-$TEST_NUM
|
||||
while test -f $DIGNM; do
|
||||
|
|
@ -83,6 +136,72 @@ setret () {
|
|||
echo "$*"
|
||||
}
|
||||
|
||||
# set $SN to the SOA serial number of a zone
|
||||
# $1=domain $2=DNS server and client IP address
|
||||
get_sn() {
|
||||
SOA=`$DIG -p 5300 +short +norecurse soa "$1" "@$2" "-b$2"`
|
||||
SN=`expr "$SOA" : '[^ ]* [^ ]* \([^ ]*\) .*'`
|
||||
test "$SN" != "" && return
|
||||
echo "I:no serial number from \`dig -p 5300 soa $1 @$2\` in \"$SOA\""
|
||||
exit 1
|
||||
}
|
||||
|
||||
get_sn_fast () {
|
||||
RSN=`$DNSRPSCMD -n "$1"`
|
||||
#echo "dnsrps serial for $1 is $RSN"
|
||||
if test -z "$RSN"; then
|
||||
echo "I:dnsrps failed to get SOA serial number for $1"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# check that dnsrpzd has loaded its zones
|
||||
# $1=domain $2=DNS server IP address
|
||||
FZONES=`sed -n -e 's/^zone "\(.*\)".*\(10.53.0..\).*/Z=\1;M=\2/p' dnsrpzd.conf`
|
||||
dnsrps_loaded() {
|
||||
test "$DNSRPS_TEST_MODE" = 2 || return
|
||||
n=0
|
||||
for V in $FZONES; do
|
||||
eval "$V"
|
||||
get_sn $Z $M
|
||||
while true; do
|
||||
get_sn_fast "$Z"
|
||||
if test "$SN" -eq "0$RSN"; then
|
||||
#echo "$Z @$M serial=$SN"
|
||||
break
|
||||
fi
|
||||
n=`expr $n + 1`
|
||||
if test "$n" -gt $TEN_SECS; then
|
||||
echo "I:dnsrps serial for $Z is $RSN instead of $SN"
|
||||
exit 1
|
||||
fi
|
||||
$WAIT_CMD
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
# check the serial number in an SOA to ensure that a policy zone has
|
||||
# been (re)loaded
|
||||
# $1=serial number $2=domain $3=DNS server
|
||||
ck_soa() {
|
||||
n=0
|
||||
while true; do
|
||||
if test "$DNSRPS_TEST_MODE" = 2; then
|
||||
get_sn_fast "$2"
|
||||
test "$RSN" -eq "$1" && return
|
||||
else
|
||||
get_sn "$2" "$3"
|
||||
test "$SN" -eq "$1" && return
|
||||
fi
|
||||
n=`expr $n + 1`
|
||||
if test "$n" -gt $TEN_SECS; then
|
||||
echo "I:got serial number \"$SN\" instead of \"$1\" from $2 @$3"
|
||||
return
|
||||
fi
|
||||
$WAIT_CMD
|
||||
done
|
||||
}
|
||||
|
||||
# (re)load the reponse policy zones with the rules in the file $TEST_FILE
|
||||
load_db () {
|
||||
if test -n "$TEST_FILE"; then
|
||||
|
|
@ -118,6 +237,7 @@ restart () {
|
|||
fi
|
||||
$PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns$1
|
||||
load_db
|
||||
dnsrps_loaded
|
||||
}
|
||||
|
||||
# $1=server and irrelevant args $2=error message
|
||||
|
|
@ -179,6 +299,7 @@ start_group () {
|
|||
else
|
||||
GROUP_NM=
|
||||
fi
|
||||
dnsrps_loaded
|
||||
TEST_NUM=0
|
||||
}
|
||||
|
||||
|
|
@ -189,6 +310,7 @@ end_group () {
|
|||
TEST_FILE=
|
||||
fi
|
||||
ckalive $ns3 "I:failed; ns3 server crashed and restarted"
|
||||
dnsrps_loaded
|
||||
GROUP_NM=
|
||||
}
|
||||
|
||||
|
|
@ -257,7 +379,7 @@ addr () {
|
|||
digcmd $2 >$DIGNM
|
||||
#ckalive "$2" "I:server crashed by 'dig $2'" || return 1
|
||||
ADDR_ESC=`echo "$ADDR" | sed -e 's/\./\\\\./g'`
|
||||
ADDR_TTL=`sed -n -e "s/^[-.a-z0-9]\{1,\} *\([0-9]*\) IN AA* ${ADDR_ESC}\$/\1/p" $DIGNM`
|
||||
ADDR_TTL=`sed -n -e "s/^[-.a-z0-9]\{1,\}[ ]*\([0-9]*\) IN AA* ${ADDR_ESC}\$/\1/p" $DIGNM`
|
||||
if test -z "$ADDR_TTL"; then
|
||||
setret "I:'dig $2' wrong; no address $ADDR record in $DIGNM"
|
||||
return 1
|
||||
|
|
@ -306,9 +428,6 @@ drop () {
|
|||
digcmd nonexistent @$ns2 >proto.nxdomain
|
||||
digcmd txt-only.tld2 @$ns2 >proto.nodata
|
||||
|
||||
|
||||
status=0
|
||||
|
||||
start_group "QNAME rewrites" test1
|
||||
nochange . # 1 do not crash or rewrite root
|
||||
nxdomain a0-1.tld2 # 2
|
||||
|
|
@ -353,29 +472,28 @@ ckstats $ns5 test1 ns5 1
|
|||
ckstats $ns6 test1 ns6 0
|
||||
|
||||
start_group "NXDOMAIN/NODATA action on QNAME trigger" test1
|
||||
nxdomain a0-1.tld2 @$ns6 # 1
|
||||
nodata a3-1.tld2 @$ns6 # 2
|
||||
nodata a3-2.tld2 @$ns6 # 3 nodata at DNAME itself
|
||||
nxdomain a4-2.tld2 @$ns6 # 4 rewrite based on CNAME target
|
||||
nxdomain a4-2-cname.tld2 @$ns6 # 5
|
||||
nodata a4-3-cname.tld2 @$ns6 # 6
|
||||
nxdomain a0-1.tld2 @$ns6 # 1
|
||||
nodata a3-1.tld2 @$ns6 # 2
|
||||
nodata a3-2.tld2 @$ns6 # 3 nodata at DNAME itself
|
||||
nxdomain a4-2.tld2 @$ns6 # 4 rewrite based on CNAME target
|
||||
nxdomain a4-2-cname.tld2 @$ns6 # 5
|
||||
nodata a4-3-cname.tld2 @$ns6 # 6
|
||||
addr 12.12.12.12 "a4-1.sub1.tld2 @$ns6" # 7 A replacement
|
||||
addr 12.12.12.12 "a4-1.sub2.tld2 @$ns6" # 8 A replacement with wildcard
|
||||
addr 127.4.4.1 "a4-4.tld2 @$ns6" # 9 prefer 1st conflicting QNAME zone
|
||||
addr 127.4.4.1 "a4-4.tld2 @$ns6" # 9 prefer 1st conflicting QNAME zone
|
||||
addr 12.12.12.12 "nxc1.sub1.tld2 @$ns6" # 10 replace NXDOMAIN w/ CNAME
|
||||
addr 12.12.12.12 "nxc2.sub1.tld2 @$ns6" # 11 replace NXDOMAIN w/ CNAME chain
|
||||
addr 127.6.2.1 "a6-2.tld2 @$ns6" # 12
|
||||
addr 56.56.56.56 "a3-6.tld2 @$ns6" # 13 wildcard CNAME
|
||||
addr 127.6.2.1 "a6-2.tld2 @$ns6" # 12
|
||||
addr 56.56.56.56 "a3-6.tld2 @$ns6" # 13 wildcard CNAME
|
||||
addr 57.57.57.57 "a3-7.sub1.tld2 @$ns6" # 14 wildcard CNAME
|
||||
addr 127.0.0.16 "a4-5-cname3.tld2 @$ns6" # 15 CNAME chain
|
||||
addr 127.0.0.17 "a4-6-cname3.tld2 @$ns6" # 16 stop short in CNAME chain
|
||||
nxdomain c1.crash2.tld3 @$ns6 # 17 assert in rbtdb.c
|
||||
nxdomain a0-1.tld2 +dnssec @$ns6 # 18 simple DO=1 without sigs
|
||||
nxdomain c1.crash2.tld3 @$ns6 # 17 assert in rbtdb.c
|
||||
nxdomain a0-1.tld2 +dnssec @$ns6 # 18 simple DO=1 without sigs
|
||||
nxdomain a0-1s-cname.tld2s +dnssec @$ns6 # 19
|
||||
drop a3-8.tld2 any @$ns6 # 20 drop
|
||||
|
||||
drop a3-8.tld2 any @$ns6 # 20 drop
|
||||
end_group
|
||||
ckstatsrange $ns3 test1 ns3 22 28
|
||||
ckstatsrange $ns3 test1 ns3 22 30
|
||||
ckstats $ns5 test1 ns5 0
|
||||
ckstats $ns6 test1 ns6 0
|
||||
|
||||
|
|
@ -399,25 +517,13 @@ nxdomain c2.crash2.tld3 # 16 assert in rbtdb.c
|
|||
addr 127.0.0.17 "a4-4.tld2 -b $ns1" # 17 client-IP address trigger
|
||||
nxdomain a7-1.tld2 # 18 slave policy zone (RT34450)
|
||||
cp ns2/blv2.tld2.db.in ns2/bl.tld2.db
|
||||
$RNDCCMD 10.53.0.2 reload bl.tld2
|
||||
goodsoa="rpz.tld2. hostmaster.ns.tld2. 2 3600 1200 604800 60"
|
||||
for i in 0 1 2 3 4 5 6 7 8 9 10
|
||||
do
|
||||
soa=`$DIG -p 5300 +short soa bl.tld2 @10.53.0.3 -b10.53.0.3`
|
||||
test "$soa" = "$goodsoa" && break
|
||||
sleep 1
|
||||
done
|
||||
$RNDCCMD $ns2 reload bl.tld2
|
||||
ck_soa 2 bl.tld2 $ns3
|
||||
nochange a7-1.tld2 # 19 PASSTHRU
|
||||
sleep 1 # ensure that a clock tick has occured so that the reload takes effect
|
||||
sleep 1 # ensure that a clock tick has occured so that named will do the reload
|
||||
cp ns2/blv3.tld2.db.in ns2/bl.tld2.db
|
||||
goodsoa="rpz.tld2. hostmaster.ns.tld2. 3 3600 1200 604800 60"
|
||||
$RNDCCMD 10.53.0.2 reload bl.tld2
|
||||
for i in 0 1 2 3 4 5 6 7 8 9 10
|
||||
do
|
||||
soa=`$DIG -p 5300 +short soa bl.tld2 @10.53.0.3 -b10.53.0.3`
|
||||
test "$soa" = "$goodsoa" && break
|
||||
sleep 1
|
||||
done
|
||||
$RNDCCMD $ns2 reload bl.tld2
|
||||
ck_soa 3 bl.tld2 $ns3
|
||||
nxdomain a7-1.tld2 # 20 slave policy zone (RT34450)
|
||||
end_group
|
||||
ckstats $ns3 test2 ns3 12
|
||||
|
|
@ -438,47 +544,53 @@ nochange a5-1-2.tld2
|
|||
end_group
|
||||
ckstats $ns3 'radix tree deletions' ns3 0
|
||||
|
||||
if $FEATURETEST --rpz-nsdname; then
|
||||
# these tests assume "min-ns-dots 0"
|
||||
start_group "NSDNAME rewrites" test3
|
||||
nochange a3-1.tld2 # 1
|
||||
nochange a3-1.tld2 +dnssec # 2 this once caused problems
|
||||
nxdomain a3-1.sub1.tld2 # 3 NXDOMAIN *.sub1.tld2 by NSDNAME
|
||||
nxdomain a3-1.subsub.sub1.tld2
|
||||
nxdomain a3-1.subsub.sub1.tld2 -tany
|
||||
addr 12.12.12.12 a4-2.subsub.sub2.tld2 # 6 walled garden for *.sub2.tld2
|
||||
nochange a3-2.tld2. # 7 exempt rewrite by name
|
||||
nochange a0-1.tld2. # 8 exempt rewrite by address block
|
||||
addr 12.12.12.12 a4-1.tld2 # 9 prefer QNAME policy to NSDNAME
|
||||
addr 127.0.0.1 a3-1.sub3.tld2 # 10 prefer policy for largest NSDNAME
|
||||
addr 127.0.0.2 a3-1.subsub.sub3.tld2
|
||||
nxdomain xxx.crash1.tld2 # 12 dns_db_detachnode() crash
|
||||
end_group
|
||||
ckstats $ns3 test3 ns3 7
|
||||
# these tests assume "min-ns-dots 0"
|
||||
start_group "NSDNAME rewrites" test3
|
||||
nochange a3-1.tld2 # 1
|
||||
nochange a3-1.tld2 +dnssec # 2 this once caused problems
|
||||
nxdomain a3-1.sub1.tld2 # 3 NXDOMAIN *.sub1.tld2 by NSDNAME
|
||||
nxdomain a3-1.subsub.sub1.tld2
|
||||
nxdomain a3-1.subsub.sub1.tld2 -tany
|
||||
addr 12.12.12.12 a4-2.subsub.sub2.tld2 # 6 walled garden for *.sub2.tld2
|
||||
nochange a3-2.tld2. # 7 exempt rewrite by name
|
||||
nochange a0-1.tld2. # 8 exempt rewrite by address block
|
||||
addr 12.12.12.12 a4-1.tld2 # 9 prefer QNAME policy to NSDNAME
|
||||
addr 127.0.0.1 a3-1.sub3.tld2 # 10 prefer policy for largest NSDNAME
|
||||
addr 127.0.0.2 a3-1.subsub.sub3.tld2
|
||||
nxdomain xxx.crash1.tld2 # 12 dns_db_detachnode() crash
|
||||
if [ "$DNSRPS_TEST_MODE" = 2 ]; then
|
||||
addr 12.12.12.12 as-ns.tld5. # 13 qname-as-ns
|
||||
fi
|
||||
end_group
|
||||
if [ "$DNSRPS_TEST_MODE" = 2 ]; then
|
||||
ckstats $ns3 test3 ns3 8
|
||||
else
|
||||
echo "I:NSDNAME not checked; named configured with --disable-rpz-nsdname"
|
||||
ckstats $ns3 test3 ns3 7
|
||||
fi
|
||||
|
||||
if $FEATURETEST --rpz-nsip; then
|
||||
# these tests assume "min-ns-dots 0"
|
||||
start_group "NSIP rewrites" test4
|
||||
nxdomain a3-1.tld2 # 1 NXDOMAIN for all of tld2
|
||||
nochange a3-2.tld2. # 2 exempt rewrite by name
|
||||
nochange a0-1.tld2. # 3 exempt rewrite by address block
|
||||
nochange a3-1.tld4 # 4 different NS IP address
|
||||
end_group
|
||||
# these tests assume "min-ns-dots 0"
|
||||
start_group "NSIP rewrites" test4
|
||||
nxdomain a3-1.tld2 # 1 NXDOMAIN for all of tld2
|
||||
nochange a3-2.tld2. # 2 exempt rewrite by name
|
||||
nochange a0-1.tld2. # 3 exempt rewrite by address block
|
||||
nochange a3-1.tld4 # 4 different NS IP address
|
||||
if [ "$DNSRPS_TEST_MODE" = 2 ]; then
|
||||
addr 12.12.12.12 as-ns.tld5. # 5 ip-as-ns
|
||||
fi
|
||||
end_group
|
||||
|
||||
start_group "walled garden NSIP rewrites" test4a
|
||||
addr 41.41.41.41 a3-1.tld2 # 1 walled garden for all of tld2
|
||||
addr 2041::41 'a3-1.tld2 AAAA' # 2 walled garden for all of tld2
|
||||
here a3-1.tld2 TXT <<'EOF' # 3 text message for all of tld2
|
||||
start_group "walled garden NSIP rewrites" test4a
|
||||
addr 41.41.41.41 a3-1.tld2 # 1 walled garden for all of tld2
|
||||
addr 2041::41 'a3-1.tld2 AAAA' # 2 walled garden for all of tld2
|
||||
here a3-1.tld2 TXT <<'EOF' # 3 text message for all of tld2
|
||||
;; status: NOERROR, x
|
||||
a3-1.tld2. x IN TXT "NSIP walled garden"
|
||||
EOF
|
||||
end_group
|
||||
ckstats $ns3 test4 ns3 4
|
||||
end_group
|
||||
if [ "$DNSRPS_TEST_MODE" = 2 ]; then
|
||||
ckstats $ns3 test4 ns3 5
|
||||
else
|
||||
echo "I:NSIP not checked; named configured with --disable-rpz-nsip"
|
||||
ckstats $ns3 test4 ns3 4
|
||||
fi
|
||||
|
||||
# policies in ./test5 overridden by response-policy{} in ns3/named.conf
|
||||
|
|
@ -530,7 +642,6 @@ end_group
|
|||
ckstats $ns3 bugs ns3 8
|
||||
|
||||
|
||||
|
||||
# superficial test for major performance bugs
|
||||
QPERF=`sh qperf.sh`
|
||||
if test -n "$QPERF"; then
|
||||
|
|
@ -538,10 +649,10 @@ if test -n "$QPERF"; then
|
|||
date "+I:${TS}checking performance $1"
|
||||
# Dry run to prime everything
|
||||
comment "before dry run $1"
|
||||
$RNDCCMD $ns5 notrace
|
||||
$QPERF -c -1 -l30 -d ns5/requests -s $ns5 -p 5300 >/dev/null
|
||||
comment "before real test $1"
|
||||
PFILE="ns5/$2.perf"
|
||||
$RNDCCMD $ns5 notrace
|
||||
$QPERF -c -1 -l30 -d ns5/requests -s $ns5 -p 5300 >$PFILE
|
||||
comment "after test $1"
|
||||
X=`sed -n -e 's/.*Returned *\([^ ]*:\) *\([0-9]*\) .*/\1\2/p' $PFILE \
|
||||
|
|
@ -558,7 +669,6 @@ if test -n "$QPERF"; then
|
|||
# get qps with rpz
|
||||
perf 'with RPZ' rpz 'NOERROR:2900 NXDOMAIN:100 '
|
||||
RPZ=`trim rpz`
|
||||
|
||||
# turn off rpz and measure qps again
|
||||
echo "# RPZ off" >ns5/rpz-switch
|
||||
RNDCCMD_OUT=`$RNDCCMD $ns5 reload`
|
||||
|
|
@ -583,6 +693,27 @@ else
|
|||
echo "I:performance not checked; queryperf not available"
|
||||
fi
|
||||
|
||||
if [ "$DNSRPS_TEST_MODE" = 2 ]; then
|
||||
echo "I:checking that dnsrpzd is automatically restarted"
|
||||
OLD_PID=`cat dnsrpzd.pid`
|
||||
$KILL "$OLD_PID"
|
||||
n=0
|
||||
while true; do
|
||||
NEW_PID=`cat dnsrpzd.pid 2>/dev/null`
|
||||
if test -n "$NEW_PID" -a "0$OLD_PID" -ne "0$NEW_PID"; then
|
||||
#echo "OLD_PID=$OLD_PID NEW_PID=$NEW_PID"
|
||||
break;
|
||||
fi
|
||||
$DIG -p 5300 +short +norecurse a0-1.tld2 @$ns3 >/dev/null
|
||||
n=`expr $n + 1`
|
||||
if test "$n" -gt $TEN_SECS; then
|
||||
setret "I:dnsrpzd did not restart"
|
||||
break
|
||||
fi
|
||||
$WAIT_CMD
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# restart the main test RPZ server to see if that creates a core file
|
||||
if test -z "$HAVE_CORE"; then
|
||||
|
|
@ -604,7 +735,9 @@ $DIG +noall +answer -p 5300 @$ns3 any a3-2.tld2 > dig.out.any
|
|||
ttl=`awk '/a3-2 tld2 text/ {print $2}' dig.out.any`
|
||||
if test ${ttl:=0} -eq 0; then setret I:failed; fi
|
||||
|
||||
echo "I:checking rpz updates/transfers with parent nodes added after children"
|
||||
|
||||
echo "I:checking rpz updates/transfers with parent nodes added after children" \
|
||||
| tr -d '\n'
|
||||
# regression test for RT #36272: the success condition
|
||||
# is the slave server not crashing.
|
||||
nsd() {
|
||||
|
|
@ -617,26 +750,40 @@ send
|
|||
EOF
|
||||
sleep 2
|
||||
}
|
||||
|
||||
for i in 1 2 3 4 5; do
|
||||
nsd $ns5 add example.com.policy1. '*.example.com.policy1.'
|
||||
echo . | tr -d '\n'
|
||||
nsd $ns5 delete example.com.policy1. '*.example.com.policy1.'
|
||||
echo . | tr -d '\n'
|
||||
done
|
||||
for i in 1 2 3 4 5; do
|
||||
nsd $ns5 add '*.example.com.policy1.' example.com.policy1.
|
||||
echo . | tr -d '\n'
|
||||
nsd $ns5 delete '*.example.com.policy1.' example.com.policy1.
|
||||
echo . | tr -d '\n'
|
||||
done
|
||||
echo
|
||||
|
||||
echo "I:checking that going from a empty policy zone works"
|
||||
|
||||
echo "I:checking that going from an empty policy zone works"
|
||||
nsd $ns5 add '*.x.servfail.policy2.' x.servfail.policy2.
|
||||
sleep 1
|
||||
$RNDCCMD $ns7 reload policy2
|
||||
$DIG z.x.servfail -p 5300 @$ns7 > dig.out.ns7
|
||||
grep NXDOMAIN dig.out.ns7 > /dev/null || setret I:failed;
|
||||
grep NXDOMAIN dig.out.ns7 > /dev/null || setret I:failed
|
||||
|
||||
echo "I:checking rpz with delegation fails correctly"
|
||||
$DIG -p 5300 @$ns3 ns example.com > dig.out.delegation
|
||||
grep "status: SERVFAIL" dig.out.delegation > /dev/null || setret "I:failed"
|
||||
# dnsrps does not allow NS RRs in policy zones, so this check
|
||||
# with dnsrps results in no rewriting.
|
||||
if [ "$DNSRPS_TEST_MODE" = 1 ]; then
|
||||
echo "I:checking rpz with delegation fails correctly"
|
||||
$DIG -p 5300 @$ns3 ns example.com > dig.out.delegation
|
||||
grep "status: SERVFAIL" dig.out.delegation > /dev/null || setret "I:failed"
|
||||
fi
|
||||
|
||||
echo "I:exit status: $status"
|
||||
[ $status -ne 0 ] && pf=fail || pf=pass
|
||||
case $DNSRPS_TEST_MODE in
|
||||
1) echo "I:status (native RPZ sub-test): $status ($pf)";;
|
||||
2) echo "I:status (DNSRPS sub-test): $status ($pf)";;
|
||||
*) echo "I:invalid test mode";;
|
||||
esac
|
||||
[ $status -eq 0 ] || exit 1
|
||||
|
|
|
|||
|
|
@ -9,9 +9,11 @@
|
|||
rm -f dig.out.*
|
||||
rm -f ns*/named.lock
|
||||
rm -f ns*/named.memstats
|
||||
rm -f ns*/named.run
|
||||
rm -f ns*/*.run
|
||||
rm -f ns2/*.local
|
||||
rm -f ns2/*.queries
|
||||
rm -f ns2/named.[0-9]*.conf
|
||||
rm -f ns2/named.conf
|
||||
rm -f ns3/named.conf
|
||||
rm -f ns*/*core *core
|
||||
rm -f dnsrps*.conf dnsrpzd*
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ options {
|
|||
notify-source 10.53.0.1;
|
||||
transfer-source 10.53.0.1;
|
||||
port 5300;
|
||||
session-keyfile "session.key";
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.1; };
|
||||
listen-on-v6 { none; };
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ view "recursive" {
|
|||
response-policy {
|
||||
zone "clientip1";
|
||||
zone "clientip2";
|
||||
} qname-wait-recurse no;
|
||||
} qname-wait-recurse no
|
||||
nsdname-enable yes
|
||||
nsip-enable yes;
|
||||
|
||||
# policy zones to be tested
|
||||
zone "clientip1" { type master; file "db.clientip1"; };
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@ view "recursive" {
|
|||
# policy configuration to be tested
|
||||
response-policy {
|
||||
zone "clientip21";
|
||||
} qname-wait-recurse no;
|
||||
} qname-wait-recurse no
|
||||
nsdname-enable yes
|
||||
nsip-enable yes;
|
||||
|
||||
# policy zones to be tested
|
||||
zone "clientip21" { type master; file "db.clientip21"; };
|
||||
|
|
|
|||
|
|
@ -13,11 +13,15 @@ options {
|
|||
notify-source 10.53.0.2;
|
||||
transfer-source 10.53.0.2;
|
||||
port 5300;
|
||||
session-keyfile "session.key";
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.2; };
|
||||
listen-on-v6 { none; };
|
||||
recursion yes;
|
||||
querylog yes;
|
||||
|
||||
# let ns3 start dnsrpzd
|
||||
include "../dnsrps-slave.conf";
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@ view "recursive" {
|
|||
zone "log1" log no;
|
||||
zone "log2" log yes;
|
||||
zone "log3"; # missing log clause
|
||||
} qname-wait-recurse no;
|
||||
} qname-wait-recurse no
|
||||
nsdname-enable yes
|
||||
nsip-enable yes;
|
||||
|
||||
# policy zones to be tested
|
||||
zone "log1" { type master; file "db.log1"; };
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@ view "recursive" {
|
|||
# policy configuration to be tested
|
||||
response-policy {
|
||||
zone "wildcard1" policy NXDOMAIN;
|
||||
};
|
||||
} qname-wait-recurse yes
|
||||
nsdname-enable yes
|
||||
nsip-enable yes;
|
||||
|
||||
# policy zones to be tested
|
||||
zone "wildcard1" { type master; file "db.wildcard1"; };
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ view "recursive" {
|
|||
response-policy {
|
||||
zone "wildcard2a" policy NXDOMAIN;
|
||||
zone "wildcard2b" policy NXDOMAIN;
|
||||
};
|
||||
} qname-wait-recurse yes
|
||||
nsdname-enable yes
|
||||
nsip-enable yes;
|
||||
|
||||
# policy zones to be tested
|
||||
zone "wildcard2a" { type master; file "db.wildcard2a"; };
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@ view "recursive" {
|
|||
# policy configuration to be tested
|
||||
response-policy {
|
||||
zone "wildcard3" policy NXDOMAIN;
|
||||
};
|
||||
} qname-wait-recurse yes
|
||||
nsdname-enable yes
|
||||
nsip-enable yes;
|
||||
|
||||
# policy zones to be tested
|
||||
zone "wildcard3" { type master; file "db.wildcard3"; };
|
||||
|
|
|
|||
|
|
@ -17,11 +17,17 @@ options {
|
|||
notify-source 10.53.0.3;
|
||||
transfer-source 10.53.0.3;
|
||||
port 5300;
|
||||
session-keyfile "session.key";
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.3; };
|
||||
listen-on-v6 { none; };
|
||||
recursion yes;
|
||||
response-policy { zone "policy"; };
|
||||
response-policy { zone "policy"; }
|
||||
qname-wait-recurse yes
|
||||
nsip-enable yes
|
||||
nsdname-enable yes;
|
||||
|
||||
include "../dnsrps.conf";
|
||||
};
|
||||
|
||||
zone "policy" { type master; file "policy.db"; };
|
||||
|
|
|
|||
|
|
@ -21,7 +21,12 @@ options {
|
|||
listen-on { 10.53.0.3; };
|
||||
listen-on-v6 { none; };
|
||||
recursion yes;
|
||||
response-policy { zone "policy"; } nsip-wait-recurse no;
|
||||
response-policy { zone "policy"; } nsip-wait-recurse no
|
||||
qname-wait-recurse yes
|
||||
nsip-enable yes
|
||||
nsdname-enable yes;
|
||||
|
||||
include "../dnsrps.conf";
|
||||
};
|
||||
|
||||
zone "policy" { type master; file "policy.db"; };
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ options {
|
|||
notify-source 10.53.0.4;
|
||||
transfer-source 10.53.0.4;
|
||||
port 5300;
|
||||
session-keyfile "session.key";
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.4; };
|
||||
listen-on-v6 { none; };
|
||||
|
|
|
|||
|
|
@ -9,13 +9,4 @@
|
|||
SYSTEMTESTTOP=..
|
||||
. $SYSTEMTESTTOP/conf.sh
|
||||
|
||||
ret=0
|
||||
$FEATURETEST --rpz-nsdname || ret=1
|
||||
$FEATURETEST --rpz-nsip || ret=1
|
||||
|
||||
if [ $ret != 0 ]; then
|
||||
echo "I:This test requires NSIP AND NSDNAME support in RPZ." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec $SHELL ../testcrypto.sh
|
||||
|
|
|
|||
|
|
@ -6,9 +6,52 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# touch dnsrps-off to not test with DNSRPS
|
||||
|
||||
set -e
|
||||
|
||||
SYSTEMTESTTOP=..
|
||||
. $SYSTEMTESTTOP/conf.sh
|
||||
|
||||
perl testgen.pl
|
||||
USAGE="$0: [-xD]"
|
||||
DEBUG=
|
||||
while getopts "xD" c; do
|
||||
case $c in
|
||||
x) set -x; DEBUG=-x;;
|
||||
D) TEST_DNSRPS="-D";;
|
||||
*) echo "$USAGE" 1>&2; exit 1;;
|
||||
esac
|
||||
done
|
||||
shift `expr $OPTIND - 1 || true`
|
||||
if test "$#" -ne 0; then
|
||||
echo "$USAGE" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$SHELL clean.sh $DEBUG
|
||||
|
||||
$PERL testgen.pl
|
||||
cp -f ns2/named.default.conf ns2/named.conf
|
||||
cp -f ns3/named1.conf ns3/named.conf
|
||||
|
||||
# decide whether to test DNSRPS
|
||||
$SHELL ../rpz/ckdnsrps.sh $TEST_DNSRPS $DEBUG
|
||||
test -z "`grep 'dnsrps-enable yes' dnsrps.conf`" && TEST_DNSRPS=
|
||||
|
||||
CWD=`pwd`
|
||||
cat <<EOF >dnsrpzd.conf
|
||||
PID-FILE $CWD/dnsrpzd.pid;
|
||||
|
||||
include $CWD/dnsrpzd-license-cur.conf
|
||||
|
||||
zone "policy" { type master; file "`pwd`/ns3/policy.db"; };
|
||||
EOF
|
||||
sed -n -e 's/^ *//' -e "/zone.*.*master/s@file \"@&$CWD/ns2/@p" ns2/*.conf \
|
||||
>>dnsrpzd.conf
|
||||
|
||||
# Run dnsrpzd to get the license and prime the static policy zones
|
||||
if test -n "$TEST_DNSRPS"; then
|
||||
DNSRPZD="`../rpz/dnsrps -p`"
|
||||
"$DNSRPZD" -D./dnsrpzd.rpzf -S./dnsrpzd.sock -C./dnsrpzd.conf \
|
||||
-w 0 -dddd -L stdout >./dnsrpzd.run 2>&1
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -1,10 +1,18 @@
|
|||
#!/usr/bin/env perl
|
||||
#
|
||||
# Copyright (C) 2015, 2016 Internet Systems Consortium, Inc. ("ISC")
|
||||
# Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
|
@ -24,13 +32,13 @@ view "recursive" {
|
|||
EOB
|
||||
|
||||
my $no_option = <<'EOB';
|
||||
};
|
||||
} nsdname-enable yes nsip-enable yes;
|
||||
|
||||
# policy zones to be tested
|
||||
EOB
|
||||
|
||||
my $qname_wait_recurse = <<'EOB';
|
||||
} qname-wait-recurse no;
|
||||
} nsdname-enable yes nsip-enable yes qname-wait-recurse no;
|
||||
|
||||
# policy zones to be tested
|
||||
EOB
|
||||
|
|
|
|||
|
|
@ -6,12 +6,75 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# touch dnsrps-off to not test with DNSRPS
|
||||
# touch dnsrps-only to not test with classic RPZ
|
||||
|
||||
SYSTEMTESTTOP=..
|
||||
. $SYSTEMTESTTOP/conf.sh
|
||||
|
||||
status=0
|
||||
|
||||
t=0
|
||||
|
||||
DEBUG=
|
||||
DNSRPS_TEST_MODE= # "" to test with and then without DNSRPS
|
||||
ARGS=
|
||||
|
||||
USAGE="$0: [-xS] [-D {1,2}]"
|
||||
while getopts "xSD:" c; do
|
||||
case $c in
|
||||
x) set -x; DEBUG=-x; ARGS="$ARGS -x";;
|
||||
D) DNSRPS_TEST_MODE="$OPTARG";; # with or without DNSRPS
|
||||
*) echo "$USAGE" 1>&2; exit 1;;
|
||||
esac
|
||||
done
|
||||
shift `expr $OPTIND - 1 || true`
|
||||
if test "$#" -ne 0; then
|
||||
echo "$USAGE" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
# really quit on control-C
|
||||
trap 'exit 1' 1 2 15
|
||||
|
||||
|
||||
DNSRPSCMD=../rpz/dnsrps
|
||||
RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p 9953 -s"
|
||||
|
||||
# Run the tests twice, first without DNSRPS and then with if it is available
|
||||
if [ -z "$DNSRPS_TEST_MODE" ]; then
|
||||
if [ -e dnsrps-only ]; then
|
||||
echo "I:'dnsrps-only' found: skipping native RPZ sub-test"
|
||||
else
|
||||
echo "I:running native RPZ sub-test"
|
||||
$SHELL ./$0 -D1 $ARGS || status=1
|
||||
fi
|
||||
|
||||
if [ -e dnsrps-off ]; then
|
||||
echo "I:'dnsrps-off' found: skipping DNSRPS sub-test"
|
||||
else
|
||||
echo "I:attempting to configure servers with DNSRPS..."
|
||||
$SHELL ./setup.sh -D $DEBUG
|
||||
sed -n 's/^## /I:/p' dnsrps.conf
|
||||
if grep '^#fail' dnsrps.conf >/dev/null; then
|
||||
echo "I:exit status: 1"
|
||||
exit 1
|
||||
fi
|
||||
if test -z "`grep '^#skip' dnsrps.conf`"; then
|
||||
$RNDCCMD 10.53.0.2 reload
|
||||
$RNDCCMD 10.53.0.3 reload
|
||||
$RNDCCMD 10.53.0.2 flush
|
||||
$RNDCCMD 10.53.0.3 flush
|
||||
echo "I:running DNSRPS sub-test"
|
||||
$SHELL ./$0 -D2 $ARGS || status=1
|
||||
else
|
||||
echo "I:DNSRPS sub-test skipped"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "I:exit status: $status"
|
||||
exit $status
|
||||
fi
|
||||
|
||||
# $1 = test name (such as 1a, 1b, etc. for which named.$1.conf exists)
|
||||
run_server() {
|
||||
TESTNAME=$1
|
||||
|
|
@ -47,8 +110,8 @@ expect_norecurse() {
|
|||
t=`expr $t + 1`
|
||||
echo "I:testing $NAME doesn't recurse (${t})"
|
||||
run_query $TESTNAME $LINE || {
|
||||
echo "I:test ${t} failed"
|
||||
status=1
|
||||
echo "I:test ${t} failed"
|
||||
status=1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -62,11 +125,14 @@ expect_recurse() {
|
|||
t=`expr $t + 1`
|
||||
echo "I:testing $NAME recurses (${t})"
|
||||
run_query $TESTNAME $LINE && {
|
||||
echo "I:test ${t} failed"
|
||||
status=1
|
||||
echo "I:test ${t} failed"
|
||||
status=1
|
||||
}
|
||||
}
|
||||
|
||||
# show whether and why DNSRPS is enabled or disabled
|
||||
sed -n 's/^## /I:/p' dnsrps.conf
|
||||
|
||||
t=`expr $t + 1`
|
||||
echo "I:testing that l1.l0 exists without RPZ (${t})"
|
||||
$DIG $DIGOPTS l1.l0 ns @10.53.0.2 -p 5300 > dig.out.${t}
|
||||
|
|
@ -177,6 +243,7 @@ echo "I:adding an NSDNAME policy"
|
|||
cp ns2/db.6a.00.policy.local ns2/saved.policy.local
|
||||
cp ns2/db.6b.00.policy.local ns2/db.6a.00.policy.local
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 6a.00.policy.local 2>&1 | sed 's/^/I:ns2 /'
|
||||
test -f dnsrpzd.pid && kill -USR1 `cat dnsrpzd.pid`
|
||||
sleep 1
|
||||
t=`expr $t + 1`
|
||||
echo "I:running dig to follow CNAME (blocks, so runs in the background) (${t})"
|
||||
|
|
@ -185,6 +252,7 @@ sleep 1
|
|||
echo "I:removing the NSDNAME policy"
|
||||
cp ns2/db.6c.00.policy.local ns2/db.6a.00.policy.local
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 6a.00.policy.local 2>&1 | sed 's/^/I:ns2 /'
|
||||
test -f dnsrpzd.pid && kill -USR1 `cat dnsrpzd.pid`
|
||||
sleep 1
|
||||
echo "I:resuming authority server"
|
||||
if [ "$CYGWIN" ]; then
|
||||
|
|
@ -198,8 +266,8 @@ for n in 1 2 3 4 5 6 7 8 9; do
|
|||
sleep 1
|
||||
[ -s dig.out.${t} ] || continue
|
||||
grep "status: NOERROR" dig.out.${t} > /dev/null 2>&1 || {
|
||||
echo "I:test ${t} failed"
|
||||
status=1
|
||||
echo "I:test ${t} failed"
|
||||
status=1
|
||||
}
|
||||
done
|
||||
|
||||
|
|
@ -222,6 +290,7 @@ kill -TSTP $PID
|
|||
echo "I:adding an NSDNAME policy"
|
||||
cp ns2/db.6b.00.policy.local ns2/db.6a.00.policy.local
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 6a.00.policy.local 2>&1 | sed 's/^/I:ns2 /'
|
||||
test -f dnsrpzd.pid && kill -USR1 `cat dnsrpzd.pid`
|
||||
sleep 1
|
||||
t=`expr $t + 1`
|
||||
echo "I:running dig to follow CNAME (blocks, so runs in the background) (${t})"
|
||||
|
|
@ -230,6 +299,7 @@ sleep 1
|
|||
echo "I:removing the policy zone"
|
||||
cp ns2/named.default.conf ns2/named.conf
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reconfig 2>&1 | sed 's/^/I:ns2 /'
|
||||
test -f dnsrpzd.pid && kill -USR1 `cat dnsrpzd.pid`
|
||||
sleep 1
|
||||
echo "I:resuming authority server"
|
||||
if [ "$CYGWIN" ]; then
|
||||
|
|
@ -243,8 +313,8 @@ for n in 1 2 3 4 5 6 7 8 9; do
|
|||
sleep 1
|
||||
[ -s dig.out.${t} ] || continue
|
||||
grep "status: NOERROR" dig.out.${t} > /dev/null 2>&1 || {
|
||||
echo "I:test ${t} failed"
|
||||
status=1
|
||||
echo "I:test ${t} failed"
|
||||
status=1
|
||||
}
|
||||
done
|
||||
|
||||
|
|
@ -381,5 +451,10 @@ if test $p1 -le $p2; then ret=1; fi
|
|||
if test $ret != 0; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:exit status: $status"
|
||||
[ $status -ne 0 ] && pf=fail || pf=pass
|
||||
case $DNSRPS_TEST_MODE in
|
||||
1) echo "I:status (native RPZ sub-test): $status ($pf)";;
|
||||
2) echo "I:status (DNSRPS sub-test): $status ($pf)";;
|
||||
*) echo "I:invalid test mode";;
|
||||
esac
|
||||
[ $status -eq 0 ] || exit 1
|
||||
|
|
|
|||
16
config.h.in
16
config.h.in
|
|
@ -155,16 +155,22 @@ int sigwait(const unsigned int *set, int *sig);
|
|||
/* Define if you cannot bind() before connect() for TCP sockets. */
|
||||
#undef BROKEN_TCP_BIND_BEFORE_CONNECT
|
||||
|
||||
/* dnsrps $librpz_name */
|
||||
#undef DNSRPS_LIBRPZ_PATH
|
||||
|
||||
/* 0=no DNSRPS 1=static link 2=dlopen() */
|
||||
#undef DNSRPS_LIB_OPEN
|
||||
|
||||
/* Define to enable "rrset-order fixed" syntax. */
|
||||
#undef DNS_RDATASET_FIXED
|
||||
|
||||
/* Define to enable American Fuzzy Lop test harness */
|
||||
#undef ENABLE_AFL
|
||||
|
||||
/* Define to enable rpz-nsdname rules. */
|
||||
/* Define to enable rpz nsdname rules. */
|
||||
#undef ENABLE_RPZ_NSDNAME
|
||||
|
||||
/* Define to enable rpz-nsip rules. */
|
||||
/* Define to enable rpz nsip rules. */
|
||||
#undef ENABLE_RPZ_NSIP
|
||||
|
||||
/* Solaris hack to get select_large_fdset. */
|
||||
|
|
@ -530,6 +536,9 @@ int sigwait(const unsigned int *set, int *sig);
|
|||
/* Define to allow building of objects for dlopen(). */
|
||||
#undef ISC_DLZ_DLOPEN
|
||||
|
||||
/* have __attribute__s used in librpz.h */
|
||||
#undef LIBRPZ_HAVE_ATTR
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#undef LT_OBJDIR
|
||||
|
|
@ -578,6 +587,9 @@ int sigwait(const unsigned int *set, int *sig);
|
|||
/* Define to use large-system tuning. */
|
||||
#undef TUNE_LARGE
|
||||
|
||||
/* Enable DNS Response Policy Service API */
|
||||
#undef USE_DNSRPS
|
||||
|
||||
/* Defined if you need to use ioctl(FIONBIO) instead a fcntl call to make
|
||||
non-blocking. */
|
||||
#undef USE_FIONBIO_IOCTL
|
||||
|
|
|
|||
260
configure
vendored
260
configure
vendored
|
|
@ -935,6 +935,7 @@ infodir
|
|||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
|
|
@ -1022,6 +1023,10 @@ enable_atomic
|
|||
enable_fixed_rrset
|
||||
enable_rpz_nsip
|
||||
enable_rpz_nsdname
|
||||
enable_dnsrps_dl
|
||||
with_dnsrps_libname
|
||||
with_dnsrps_dir
|
||||
enable_dnsrps
|
||||
enable_filter_aaaa
|
||||
enable_dnstap
|
||||
with_protobuf_c
|
||||
|
|
@ -1092,6 +1097,7 @@ datadir='${datarootdir}'
|
|||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||
|
|
@ -1344,6 +1350,15 @@ do
|
|||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
||||
| --run | --ru | --r)
|
||||
ac_prev=runstatedir ;;
|
||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
| --run=* | --ru=* | --r=*)
|
||||
runstatedir=$ac_optarg ;;
|
||||
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
|
|
@ -1481,7 +1496,7 @@ fi
|
|||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
libdir localedir mandir
|
||||
libdir localedir mandir runstatedir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
|
|
@ -1634,6 +1649,7 @@ Fine tuning of the installation directories:
|
|||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
|
|
@ -1702,8 +1718,10 @@ Optional Features:
|
|||
--enable-atomic enable machine specific atomic operations
|
||||
[default=autodetect]
|
||||
--enable-fixed-rrset enable fixed rrset ordering [default=no]
|
||||
--disable-rpz-nsip disable rpz-nsip rules [default=enabled]
|
||||
--disable-rpz-nsdname disable rpz-nsdname rules [default=enabled]
|
||||
--disable-rpz-nsip disable rpz nsip rules [default=enabled]
|
||||
--disable-rpz-nsdname disable rpz nsdname rules [default=enabled]
|
||||
--enable-dnsrps-dl DNS Response Policy Service delayed link [default=$librpz_dl]
|
||||
--enable-dnsrps enable DNS Response Policy Service API
|
||||
--enable-filter-aaaa enable filtering of AAAA records [default=no]
|
||||
--enable-dnstap enable dnstap support (requires fstrm, protobuf-c)
|
||||
--enable-querytrace enable very verbose query trace logging [default=no]
|
||||
|
|
@ -1743,6 +1761,8 @@ Optional Packages:
|
|||
--with-kame=PATH use Kame IPv6 default path /usr/local/v6
|
||||
--with-readline=LIBSPEC specify readline library default auto
|
||||
|
||||
--with-dnsrps-libname DNSRPS provider library name (librpz.so)
|
||||
--with-dnsrps-dir path to DNSRPS provider library
|
||||
--with-protobuf-c=path Path where protobuf-c is installed, for dnstap
|
||||
--with-libfstrm=path Path where libfstrm is installed, for dnstap
|
||||
--with-docbook-xsl=PATH specify path for Docbook-XSL stylesheets
|
||||
|
|
@ -20613,6 +20633,232 @@ $as_echo "#define ENABLE_RPZ_NSDNAME 1" >>confdefs.h
|
|||
;;
|
||||
esac
|
||||
|
||||
#
|
||||
# Response policy rewriting using DNS Response Policy Service (DNSRPS)
|
||||
# interface.
|
||||
#
|
||||
# DNSRPS can be compiled into BIND everywhere with a reasonably
|
||||
# modern C compiler. It is enabled on systems with dlopen() and librpz.so.
|
||||
#
|
||||
dnsrps_avail=yes
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for librpz __attribute__s" >&5
|
||||
$as_echo_n "checking for librpz __attribute__s... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
extern void f(char *p __attribute__((unused)), ...)
|
||||
__attribute__((format(printf,1,2))) __attribute__((__noreturn__));
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
librpz_have_attr=yes
|
||||
|
||||
$as_echo "#define LIBRPZ_HAVE_ATTR 1" >>confdefs.h
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else
|
||||
librpz_have_attr=no
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
|
||||
$as_echo_n "checking for library containing dlopen... " >&6; }
|
||||
if ${ac_cv_search_dlopen+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_func_search_save_LIBS=$LIBS
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char dlopen ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return dlopen ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
for ac_lib in '' dl; do
|
||||
if test -z "$ac_lib"; then
|
||||
ac_res="none required"
|
||||
else
|
||||
ac_res=-l$ac_lib
|
||||
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
|
||||
fi
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_search_dlopen=$ac_res
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext
|
||||
if ${ac_cv_search_dlopen+:} false; then :
|
||||
break
|
||||
fi
|
||||
done
|
||||
if ${ac_cv_search_dlopen+:} false; then :
|
||||
|
||||
else
|
||||
ac_cv_search_dlopen=no
|
||||
fi
|
||||
rm conftest.$ac_ext
|
||||
LIBS=$ac_func_search_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
|
||||
$as_echo "$ac_cv_search_dlopen" >&6; }
|
||||
ac_res=$ac_cv_search_dlopen
|
||||
if test "$ac_res" != no; then :
|
||||
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
|
||||
|
||||
fi
|
||||
|
||||
librpz_dl=yes
|
||||
for ac_func in dlopen dlclose dlsym
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
else
|
||||
librpz_dl=no
|
||||
fi
|
||||
done
|
||||
|
||||
# Check whether --enable-dnsrps-dl was given.
|
||||
if test "${enable_dnsrps_dl+set}" = set; then :
|
||||
enableval=$enable_dnsrps_dl; enable_librpz_dl="$enableval"
|
||||
else
|
||||
enable_librpz_dl="$librpz_dl"
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --with-dnsrps-libname was given.
|
||||
if test "${with_dnsrps_libname+set}" = set; then :
|
||||
withval=$with_dnsrps_libname; librpz_name="$withval"
|
||||
else
|
||||
librpz_name="librpz.so"
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --with-dnsrps-dir was given.
|
||||
if test "${with_dnsrps_dir+set}" = set; then :
|
||||
withval=$with_dnsrps_dir; librpz_path="$withval/$librpz_name"
|
||||
else
|
||||
librpz_path="$librpz_name"
|
||||
fi
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define DNSRPS_LIBRPZ_PATH "$librpz_path"
|
||||
_ACEOF
|
||||
|
||||
if test "x$enable_librpz_dl" = "xyes"; then
|
||||
dnsrps_lib_open=2
|
||||
else
|
||||
dnsrps_lib_open=1
|
||||
# Add librpz.so to linked libraries if we are not using dlopen()
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing librpz_client_create" >&5
|
||||
$as_echo_n "checking for library containing librpz_client_create... " >&6; }
|
||||
if ${ac_cv_search_librpz_client_create+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_func_search_save_LIBS=$LIBS
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char librpz_client_create ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return librpz_client_create ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
for ac_lib in '' rpz; do
|
||||
if test -z "$ac_lib"; then
|
||||
ac_res="none required"
|
||||
else
|
||||
ac_res=-l$ac_lib
|
||||
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
|
||||
fi
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_search_librpz_client_create=$ac_res
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext
|
||||
if ${ac_cv_search_librpz_client_create+:} false; then :
|
||||
break
|
||||
fi
|
||||
done
|
||||
if ${ac_cv_search_librpz_client_create+:} false; then :
|
||||
|
||||
else
|
||||
ac_cv_search_librpz_client_create=no
|
||||
fi
|
||||
rm conftest.$ac_ext
|
||||
LIBS=$ac_func_search_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_librpz_client_create" >&5
|
||||
$as_echo "$ac_cv_search_librpz_client_create" >&6; }
|
||||
ac_res=$ac_cv_search_librpz_client_create
|
||||
if test "$ac_res" != no; then :
|
||||
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
|
||||
|
||||
else
|
||||
dnsrps_lib_open=0
|
||||
dnsrps_avail=no
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define DNSRPS_LIB_OPEN $dnsrps_lib_open
|
||||
_ACEOF
|
||||
|
||||
|
||||
# Check whether --enable-dnsrps was given.
|
||||
if test "${enable_dnsrps+set}" = set; then :
|
||||
enableval=$enable_dnsrps; enable_dnsrps=$enableval
|
||||
else
|
||||
enable_dnsrps=no
|
||||
fi
|
||||
|
||||
if test "x$enable_dnsrps" != "xno"; then
|
||||
if test "x$dnsrps_avail" != "xyes"; then
|
||||
as_fn_error $? "dlopen and librpz.so needed for DNSRPS" "$LINENO" 5
|
||||
fi
|
||||
if test "x$dnsrps_lib_open" = "x0"; then
|
||||
as_fn_error $? "dlopen and librpz.so needed for DNSRPS" "$LINENO" 5
|
||||
fi
|
||||
|
||||
$as_echo "#define USE_DNSRPS 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
#
|
||||
# Activate "filter-aaaa-on-v4/v6" or not?
|
||||
#
|
||||
|
|
@ -23306,7 +23552,7 @@ ac_config_commands="$ac_config_commands chmod"
|
|||
# elsewhere if there's a good reason for doing so.
|
||||
#
|
||||
|
||||
ac_config_files="$ac_config_files make/Makefile make/mkdep Makefile bin/Makefile bin/check/Makefile bin/confgen/Makefile bin/confgen/unix/Makefile bin/delv/Makefile bin/dig/Makefile bin/dnssec/Makefile bin/named/Makefile bin/named/unix/Makefile bin/nsupdate/Makefile bin/pkcs11/Makefile bin/python/Makefile bin/python/isc/Makefile bin/python/isc/utils.py bin/python/isc/tests/Makefile bin/python/dnssec-checkds.py bin/python/dnssec-coverage.py bin/python/dnssec-keymgr.py bin/python/isc/__init__.py bin/python/isc/checkds.py bin/python/isc/coverage.py bin/python/isc/dnskey.py bin/python/isc/eventlist.py bin/python/isc/keydict.py bin/python/isc/keyevent.py bin/python/isc/keymgr.py bin/python/isc/keyseries.py bin/python/isc/keyzone.py bin/python/isc/policy.py bin/python/isc/rndc.py bin/python/isc/tests/dnskey_test.py bin/python/isc/tests/policy_test.py bin/rndc/Makefile bin/tests/Makefile bin/tests/atomic/Makefile bin/tests/db/Makefile bin/tests/dst/Makefile bin/tests/dst/Kdh.+002+18602.key bin/tests/dst/Kdh.+002+18602.private bin/tests/dst/Kdh.+002+48957.key bin/tests/dst/Kdh.+002+48957.private bin/tests/dst/Ktest.+001+00002.key bin/tests/dst/Ktest.+001+54622.key bin/tests/dst/Ktest.+001+54622.private bin/tests/dst/Ktest.+003+23616.key bin/tests/dst/Ktest.+003+23616.private bin/tests/dst/Ktest.+003+49667.key bin/tests/dst/dst_2_data bin/tests/dst/t2_data_1 bin/tests/dst/t2_data_2 bin/tests/dst/t2_dsasig bin/tests/dst/t2_rsasig bin/tests/hashes/Makefile bin/tests/headerdep_test.sh bin/tests/master/Makefile bin/tests/mem/Makefile bin/tests/names/Makefile bin/tests/net/Makefile bin/tests/pkcs11/Makefile bin/tests/pkcs11/benchmarks/Makefile bin/tests/rbt/Makefile bin/tests/resolver/Makefile bin/tests/sockaddr/Makefile bin/tests/system/Makefile bin/tests/system/conf.sh bin/tests/system/dlz/prereq.sh bin/tests/system/dlzexternal/Makefile bin/tests/system/dlzexternal/ns1/named.conf bin/tests/system/dyndb/Makefile bin/tests/system/dyndb/driver/Makefile bin/tests/system/inline/checkdsa.sh bin/tests/system/pipelined/Makefile bin/tests/system/rndc/Makefile bin/tests/system/rsabigexponent/Makefile bin/tests/system/tkey/Makefile bin/tests/tasks/Makefile bin/tests/timers/Makefile bin/tests/virtual-time/Makefile bin/tests/virtual-time/conf.sh bin/tools/Makefile contrib/scripts/check-secure-delegation.pl contrib/scripts/zone-edit.sh doc/Makefile doc/arm/Makefile doc/arm/noteversion.xml doc/arm/pkgversion.xml doc/arm/releaseinfo.xml doc/doxygen/Doxyfile doc/doxygen/Makefile doc/doxygen/doxygen-input-filter doc/misc/Makefile doc/tex/Makefile doc/tex/armstyle.sty doc/xsl/Makefile doc/xsl/isc-docbook-chunk.xsl doc/xsl/isc-docbook-html.xsl doc/xsl/isc-manpage.xsl doc/xsl/isc-notes-html.xsl isc-config.sh lib/Makefile lib/bind9/Makefile lib/bind9/include/Makefile lib/bind9/include/bind9/Makefile lib/dns/Makefile lib/dns/include/Makefile lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile lib/dns/tests/Makefile lib/irs/Makefile lib/irs/include/Makefile lib/irs/include/irs/Makefile lib/irs/include/irs/netdb.h lib/irs/include/irs/platform.h lib/irs/tests/Makefile lib/isc/$arch/Makefile lib/isc/$arch/include/Makefile lib/isc/$arch/include/isc/Makefile lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h lib/isc/include/pk11/Makefile lib/isc/include/pkcs11/Makefile lib/isc/tests/Makefile lib/isc/nls/Makefile lib/isc/unix/Makefile lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile lib/isc/unix/include/pkcs11/Makefile lib/isccc/Makefile lib/isccc/include/Makefile lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile lib/isccfg/tests/Makefile lib/ns/Makefile lib/ns/include/Makefile lib/ns/include/ns/Makefile lib/ns/tests/Makefile lib/tests/Makefile lib/tests/include/Makefile lib/tests/include/tests/Makefile lib/samples/Makefile lib/samples/Makefile-postinstall unit/Makefile unit/unittest.sh"
|
||||
ac_config_files="$ac_config_files make/Makefile make/mkdep Makefile bin/Makefile bin/check/Makefile bin/confgen/Makefile bin/confgen/unix/Makefile bin/delv/Makefile bin/dig/Makefile bin/dnssec/Makefile bin/named/Makefile bin/named/unix/Makefile bin/nsupdate/Makefile bin/pkcs11/Makefile bin/python/Makefile bin/python/isc/Makefile bin/python/isc/utils.py bin/python/isc/tests/Makefile bin/python/dnssec-checkds.py bin/python/dnssec-coverage.py bin/python/dnssec-keymgr.py bin/python/isc/__init__.py bin/python/isc/checkds.py bin/python/isc/coverage.py bin/python/isc/dnskey.py bin/python/isc/eventlist.py bin/python/isc/keydict.py bin/python/isc/keyevent.py bin/python/isc/keymgr.py bin/python/isc/keyseries.py bin/python/isc/keyzone.py bin/python/isc/policy.py bin/python/isc/rndc.py bin/python/isc/tests/dnskey_test.py bin/python/isc/tests/policy_test.py bin/rndc/Makefile bin/tests/Makefile bin/tests/atomic/Makefile bin/tests/db/Makefile bin/tests/dst/Makefile bin/tests/dst/Kdh.+002+18602.key bin/tests/dst/Kdh.+002+18602.private bin/tests/dst/Kdh.+002+48957.key bin/tests/dst/Kdh.+002+48957.private bin/tests/dst/Ktest.+001+00002.key bin/tests/dst/Ktest.+001+54622.key bin/tests/dst/Ktest.+001+54622.private bin/tests/dst/Ktest.+003+23616.key bin/tests/dst/Ktest.+003+23616.private bin/tests/dst/Ktest.+003+49667.key bin/tests/dst/dst_2_data bin/tests/dst/t2_data_1 bin/tests/dst/t2_data_2 bin/tests/dst/t2_dsasig bin/tests/dst/t2_rsasig bin/tests/hashes/Makefile bin/tests/headerdep_test.sh bin/tests/master/Makefile bin/tests/mem/Makefile bin/tests/names/Makefile bin/tests/net/Makefile bin/tests/pkcs11/Makefile bin/tests/pkcs11/benchmarks/Makefile bin/tests/rbt/Makefile bin/tests/resolver/Makefile bin/tests/sockaddr/Makefile bin/tests/system/Makefile bin/tests/system/conf.sh bin/tests/system/dlz/prereq.sh bin/tests/system/dlzexternal/Makefile bin/tests/system/dlzexternal/ns1/named.conf bin/tests/system/dyndb/Makefile bin/tests/system/dyndb/driver/Makefile bin/tests/system/inline/checkdsa.sh bin/tests/system/pipelined/Makefile bin/tests/system/rndc/Makefile bin/tests/system/rpz/Makefile bin/tests/system/rsabigexponent/Makefile bin/tests/system/tkey/Makefile bin/tests/tasks/Makefile bin/tests/timers/Makefile bin/tests/virtual-time/Makefile bin/tests/virtual-time/conf.sh bin/tools/Makefile contrib/scripts/check-secure-delegation.pl contrib/scripts/zone-edit.sh doc/Makefile doc/arm/Makefile doc/arm/noteversion.xml doc/arm/pkgversion.xml doc/arm/releaseinfo.xml doc/doxygen/Doxyfile doc/doxygen/Makefile doc/doxygen/doxygen-input-filter doc/misc/Makefile doc/tex/Makefile doc/tex/armstyle.sty doc/xsl/Makefile doc/xsl/isc-docbook-chunk.xsl doc/xsl/isc-docbook-html.xsl doc/xsl/isc-manpage.xsl doc/xsl/isc-notes-html.xsl isc-config.sh lib/Makefile lib/bind9/Makefile lib/bind9/include/Makefile lib/bind9/include/bind9/Makefile lib/dns/Makefile lib/dns/include/Makefile lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile lib/dns/tests/Makefile lib/irs/Makefile lib/irs/include/Makefile lib/irs/include/irs/Makefile lib/irs/include/irs/netdb.h lib/irs/include/irs/platform.h lib/irs/tests/Makefile lib/isc/$arch/Makefile lib/isc/$arch/include/Makefile lib/isc/$arch/include/isc/Makefile lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h lib/isc/include/pk11/Makefile lib/isc/include/pkcs11/Makefile lib/isc/tests/Makefile lib/isc/nls/Makefile lib/isc/unix/Makefile lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile lib/isc/unix/include/pkcs11/Makefile lib/isccc/Makefile lib/isccc/include/Makefile lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile lib/isccfg/tests/Makefile lib/ns/Makefile lib/ns/include/Makefile lib/ns/include/ns/Makefile lib/ns/tests/Makefile lib/tests/Makefile lib/tests/include/Makefile lib/tests/include/tests/Makefile lib/samples/Makefile lib/samples/Makefile-postinstall unit/Makefile unit/unittest.sh"
|
||||
|
||||
|
||||
#
|
||||
|
|
@ -24376,6 +24622,7 @@ do
|
|||
"bin/tests/system/inline/checkdsa.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/inline/checkdsa.sh" ;;
|
||||
"bin/tests/system/pipelined/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/pipelined/Makefile" ;;
|
||||
"bin/tests/system/rndc/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/rndc/Makefile" ;;
|
||||
"bin/tests/system/rpz/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/rpz/Makefile" ;;
|
||||
"bin/tests/system/rsabigexponent/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/rsabigexponent/Makefile" ;;
|
||||
"bin/tests/system/tkey/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/tkey/Makefile" ;;
|
||||
"bin/tests/tasks/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/tasks/Makefile" ;;
|
||||
|
|
@ -25805,6 +26052,8 @@ report() {
|
|||
echo " ECDSA algorithm support (--with-ecdsa)"
|
||||
test "yes" = "$OPENSSL_ED25519" -o "$PKCS11_ED25519" && \
|
||||
echo " EDDSA algorithm support (--with-eddsa)"
|
||||
test "yes" = "$enable_dnsrps" && \
|
||||
echo " DNS Response Policy Service interface (--enable-dnsrps)"
|
||||
test "yes" = "$enable_fixed" && \
|
||||
echo " Allow 'fixed' rrset-order (--enable-fixed-rrset)"
|
||||
test "yes" = "$enable_filter" && \
|
||||
|
|
@ -25851,6 +26100,9 @@ report() {
|
|||
test "no" = "$use_geoip" && echo " GeoIP access control (--with-geoip)"
|
||||
test "no" = "$use_gssapi" && echo " GSS-API (--with-gssapi)"
|
||||
|
||||
test "no" = "$enable_dnsrps" && \
|
||||
echo " DNS Response Policy Service interface (--enable-dnsrps)"
|
||||
|
||||
test "yes" = "$enable_fixed" || \
|
||||
echo " Allow 'fixed' rrset-order (--enable-fixed-rrset)"
|
||||
|
||||
|
|
|
|||
74
configure.in
74
configure.in
|
|
@ -4235,13 +4235,13 @@ esac
|
|||
# Enable response policy rewriting using NS IP addresses
|
||||
#
|
||||
AC_ARG_ENABLE(rpz-nsip,
|
||||
[ --disable-rpz-nsip disable rpz-nsip rules [[default=enabled]]],
|
||||
[ --disable-rpz-nsip disable rpz nsip rules [[default=enabled]]],
|
||||
enable_nsip="$enableval",
|
||||
enable_nsip="yes")
|
||||
case "$enable_nsip" in
|
||||
yes)
|
||||
AC_DEFINE(ENABLE_RPZ_NSIP, 1,
|
||||
[Define to enable rpz-nsip rules.])
|
||||
[Define to enable rpz nsip rules.])
|
||||
;;
|
||||
no)
|
||||
;;
|
||||
|
|
@ -4253,13 +4253,13 @@ esac
|
|||
# Enable response policy rewriting using NS name
|
||||
#
|
||||
AC_ARG_ENABLE(rpz-nsdname,
|
||||
[ --disable-rpz-nsdname disable rpz-nsdname rules [[default=enabled]]],
|
||||
[ --disable-rpz-nsdname disable rpz nsdname rules [[default=enabled]]],
|
||||
enable_nsdname="$enableval",
|
||||
enable_nsdname="yes")
|
||||
case "$enable_nsdname" in
|
||||
yes)
|
||||
AC_DEFINE(ENABLE_RPZ_NSDNAME, 1,
|
||||
[Define to enable rpz-nsdname rules.])
|
||||
[Define to enable rpz nsdname rules.])
|
||||
;;
|
||||
no)
|
||||
;;
|
||||
|
|
@ -4267,6 +4267,66 @@ case "$enable_nsdname" in
|
|||
;;
|
||||
esac
|
||||
|
||||
#
|
||||
# Response policy rewriting using DNS Response Policy Service (DNSRPS)
|
||||
# interface.
|
||||
#
|
||||
# DNSRPS can be compiled into BIND everywhere with a reasonably
|
||||
# modern C compiler. It is enabled on systems with dlopen() and librpz.so.
|
||||
#
|
||||
dnsrps_avail=yes
|
||||
AC_MSG_CHECKING([for librpz __attribute__s])
|
||||
AC_TRY_COMPILE(,[
|
||||
extern void f(char *p __attribute__((unused)), ...)
|
||||
__attribute__((format(printf,1,2))) __attribute__((__noreturn__));],
|
||||
librpz_have_attr=yes
|
||||
AC_DEFINE([LIBRPZ_HAVE_ATTR], 1, [have __attribute__s used in librpz.h])
|
||||
AC_MSG_RESULT([yes]),
|
||||
librpz_have_attr=no
|
||||
AC_MSG_RESULT([no]))
|
||||
|
||||
AC_SEARCH_LIBS(dlopen, dl)
|
||||
librpz_dl=yes
|
||||
AC_CHECK_FUNCS(dlopen dlclose dlsym,,librpz_dl=no)
|
||||
AC_ARG_ENABLE([dnsrps-dl],
|
||||
[ --enable-dnsrps-dl DNS Response Policy Service delayed link [[default=$librpz_dl]]],
|
||||
[enable_librpz_dl="$enableval"],
|
||||
[enable_librpz_dl="$librpz_dl"])
|
||||
AC_ARG_WITH([dnsrps-libname],
|
||||
[ --with-dnsrps-libname DNSRPS provider library name (librpz.so)],
|
||||
[librpz_name="$withval"], [librpz_name="librpz.so"])
|
||||
AC_ARG_WITH([dnsrps-dir],
|
||||
[ --with-dnsrps-dir path to DNSRPS provider library],
|
||||
[librpz_path="$withval/$librpz_name"], [librpz_path="$librpz_name"])
|
||||
AC_DEFINE_UNQUOTED([DNSRPS_LIBRPZ_PATH], ["$librpz_path"],
|
||||
[dnsrps $librpz_name])
|
||||
if test "x$enable_librpz_dl" = "xyes"; then
|
||||
dnsrps_lib_open=2
|
||||
else
|
||||
dnsrps_lib_open=1
|
||||
# Add librpz.so to linked libraries if we are not using dlopen()
|
||||
AC_SEARCH_LIBS([librpz_client_create], [rpz], [],
|
||||
[dnsrps_lib_open=0
|
||||
dnsrps_avail=no])
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED([DNSRPS_LIB_OPEN], [$dnsrps_lib_open],
|
||||
[0=no DNSRPS 1=static link 2=dlopen()])
|
||||
|
||||
AC_ARG_ENABLE([dnsrps],
|
||||
AS_HELP_STRING([--enable-dnsrps],
|
||||
[enable DNS Response Policy Service API]),
|
||||
[enable_dnsrps=$enableval],
|
||||
[enable_dnsrps=no])
|
||||
if test "x$enable_dnsrps" != "xno"; then
|
||||
if test "x$dnsrps_avail" != "xyes"; then
|
||||
AC_MSG_ERROR([[dlopen and librpz.so needed for DNSRPS]])
|
||||
fi
|
||||
if test "x$dnsrps_lib_open" = "x0"; then
|
||||
AC_MSG_ERROR([[dlopen and librpz.so needed for DNSRPS]])
|
||||
fi
|
||||
AC_DEFINE([USE_DNSRPS], [1], [Enable DNS Response Policy Service API])
|
||||
fi
|
||||
|
||||
#
|
||||
# Activate "filter-aaaa-on-v4/v6" or not?
|
||||
#
|
||||
|
|
@ -5165,6 +5225,7 @@ AC_CONFIG_FILES([
|
|||
bin/tests/system/inline/checkdsa.sh
|
||||
bin/tests/system/pipelined/Makefile
|
||||
bin/tests/system/rndc/Makefile
|
||||
bin/tests/system/rpz/Makefile
|
||||
bin/tests/system/rsabigexponent/Makefile
|
||||
bin/tests/system/tkey/Makefile
|
||||
bin/tests/tasks/Makefile
|
||||
|
|
@ -5321,6 +5382,8 @@ report() {
|
|||
echo " ECDSA algorithm support (--with-ecdsa)"
|
||||
test "yes" = "$OPENSSL_ED25519" -o "$PKCS11_ED25519" && \
|
||||
echo " EDDSA algorithm support (--with-eddsa)"
|
||||
test "yes" = "$enable_dnsrps" && \
|
||||
echo " DNS Response Policy Service interface (--enable-dnsrps)"
|
||||
test "yes" = "$enable_fixed" && \
|
||||
echo " Allow 'fixed' rrset-order (--enable-fixed-rrset)"
|
||||
test "yes" = "$enable_filter" && \
|
||||
|
|
@ -5367,6 +5430,9 @@ report() {
|
|||
test "no" = "$use_geoip" && echo " GeoIP access control (--with-geoip)"
|
||||
test "no" = "$use_gssapi" && echo " GSS-API (--with-gssapi)"
|
||||
|
||||
test "no" = "$enable_dnsrps" && \
|
||||
echo " DNS Response Policy Service interface (--enable-dnsrps)"
|
||||
|
||||
test "yes" = "$enable_fixed" || \
|
||||
echo " Allow 'fixed' rrset-order (--enable-fixed-rrset)"
|
||||
|
||||
|
|
|
|||
|
|
@ -4521,7 +4521,9 @@ badresp:1,adberr:0,findfail:0,valfail:0]
|
|||
[ <command>recursive-only</command> <replaceable>yes_or_no</replaceable> ]
|
||||
[ <command>log</command> <replaceable>yes_or_no</replaceable> ]
|
||||
[ <command>max-policy-ttl</command> <replaceable>number</replaceable> ]
|
||||
[ <command>min-update-interval</command> <replaceable>number</replaceable> ] ;
|
||||
[ <command>min-update-interval</command> <replaceable>number</replaceable> ]
|
||||
[ <command>nsip-enable <replaceable>yes_or_no</replaceable> ]
|
||||
[ <command>nsdname-enable <replaceable>yes_or_no</replaceable> ] ;
|
||||
...
|
||||
<command>}</command> [ <command>recursive-only</command> <replaceable>yes_or_no</replaceable> ]
|
||||
[ <command>max-policy-ttl</command> <replaceable>number</replaceable> ]
|
||||
|
|
@ -4529,7 +4531,11 @@ badresp:1,adberr:0,findfail:0,valfail:0]
|
|||
[ <command>break-dnssec</command> <replaceable>yes_or_no</replaceable> ]
|
||||
[ <command>min-ns-dots</command> <replaceable>number</replaceable> ]
|
||||
[ <command>nsip-wait-recurse</command> <replaceable>yes_or_no</replaceable> ]
|
||||
[ <command>qname-wait-recurse</command> <replaceable>yes_or_no</replaceable> ] ; ]
|
||||
[ <command>qname-wait-recurse</command> <replaceable>yes_or_no</replaceable> ]
|
||||
[ <command>nsip-enable</command> <replaceable>yes_or_no</replaceable> ]
|
||||
[ <command>nsdname-enable</command> <replaceable>yes_or_no</replaceable> ]
|
||||
[ <command>dnsrps-enable</command> <replaceable>yes_or_no</replaceable> ]
|
||||
[ <command>dnsrps-options</command> { <replaceable>parameters</replaceable> } ] ; ]
|
||||
[ <command>catalog-zones {</command>
|
||||
<command>zone</command> <replaceable>quoted_string</replaceable>
|
||||
[ <option>default-masters</option> [ <command>port</command> <replaceable>ip_port</replaceable> ] [ <command>dscp</command> <replaceable>ip_dscp</replaceable> ] <command>{</command>
|
||||
|
|
@ -10212,6 +10218,9 @@ deny-answer-aliases { "example.net"; };
|
|||
NSIP triggers match IP addresses in A and
|
||||
AAAA RRsets for domains that can be checked against NSDNAME
|
||||
policy records.
|
||||
The <command>nsdname-enable</command> phrase turns NSDNAME
|
||||
triggers off or on for a single policy zone or all
|
||||
zones.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
|
@ -10227,6 +10236,9 @@ deny-answer-aliases { "example.net"; };
|
|||
least <command>min-ns-dots</command> dots.
|
||||
The default value of <command>min-ns-dots</command> is
|
||||
1, to exclude top level domains.
|
||||
The <command>nsip-enable</command> phrase turns NSIP
|
||||
triggers off or on for a single policy zone or all
|
||||
zones.
|
||||
</para>
|
||||
<para>
|
||||
If a name server's IP address is not yet known,
|
||||
|
|
@ -10475,11 +10487,11 @@ deny-answer-aliases { "example.net"; };
|
|||
servers for listed names. To prevent that information leak, by
|
||||
default any recursion needed for a request is done before any
|
||||
policy triggers are considered. Because listed domains often
|
||||
have slow authoritative servers, this default behavior can cost
|
||||
have slow authoritative servers, this behavior can cost
|
||||
significant time.
|
||||
The <command>qname-wait-recurse no</command> option
|
||||
overrides that default behavior when recursion cannot
|
||||
change a non-error response.
|
||||
The <command>qname-wait-recurse yes</command> option
|
||||
overrides the default and enables that behavior
|
||||
when recursion cannot change a non-error response.
|
||||
The option does not affect QNAME or client-IP triggers
|
||||
in policy zones listed
|
||||
after other zones containing IP, NSIP and NSDNAME triggers, because
|
||||
|
|
@ -10493,6 +10505,42 @@ deny-answer-aliases { "example.net"; };
|
|||
discover problems at the authoritative server.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <command>dnsrps-enable yes</command> option turns on
|
||||
the DNS Rsponse Policy Service (DNSRPS) interface, if it has been
|
||||
compiled in to <command>named</command> using
|
||||
<command>configure --enable-dnsrps</command>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <command>dnsrps-options</command> block provides additional
|
||||
RPZ configuration settings, which are passed through to the
|
||||
DNSRPS provider library.
|
||||
Multiple DNSRPS settings in an <command>dnsrps-options</command>
|
||||
string should be separated with semi-colons.
|
||||
The DNSRPS provider, librpz, is passed a configuration string
|
||||
consisting of the <command>dnsrps-options</command> text,
|
||||
concatenated with settings derived from the
|
||||
<command>response-policy</command> statement.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Note: The <command>dnsrps-options</command> text should only include
|
||||
configuration settings that are specific to the DNSRPS
|
||||
provider. For example, the DNSRPS provider from
|
||||
Farsight Security takes options such as
|
||||
<command>dnsrpzd-conf</command>,
|
||||
<command>dnsrpzd-sock</command>, and
|
||||
<command>dnzrpzd-args</command> (for details of these options,
|
||||
see the <command>librpz</command> documentation).
|
||||
Other RPZ configuration settings could be included in
|
||||
<command>dnsrps-options</command>
|
||||
as well, but if <command>named</command> were switched
|
||||
back to traditional RPZ by setting
|
||||
<command>dnsrps-enable</command> to "no", those options would
|
||||
be ignored.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The TTL of a record modified by RPZ policies is set from the
|
||||
TTL of the relevant record in policy zone. It is then limited
|
||||
|
|
|
|||
|
|
@ -181,6 +181,29 @@
|
|||
|
||||
<section xml:id="relnotes_features"><info><title>New Features</title></info>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Added support for the DNS Response Policy Service (DNSRPS) API,
|
||||
a mechanism to allow <command>named</command> to use an external
|
||||
response policy provider. (One example of such a provider is
|
||||
"FastRPZ" from Farsight Security, Inc.) This allows the same
|
||||
types of policy filtering as standard RPZ, but can reduce the
|
||||
workload for <command>named</command>, particularly when using
|
||||
large and frequently-updated policy zones. It also enables
|
||||
<command>named</command> to share response policy providers
|
||||
with other DNS implementations such as Unbound.
|
||||
</para>
|
||||
<para>
|
||||
This feature is avaiable if BIND is built with
|
||||
<command>configure --enable-dnsrps</command>
|
||||
and if <command>dnsrps-enable</command> is set to "yes" in
|
||||
<filename>named.conf</filename>.
|
||||
</para>
|
||||
<para>
|
||||
Thanks to Vernon Schryver and Farsight Security for the
|
||||
contribution. [RT #43376]
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Code implementing name server query processing has been moved
|
||||
|
|
|
|||
|
|
@ -60,8 +60,9 @@ DNSTAPOBJS = dnstap.@O@ dnstap.pb-c.@O@
|
|||
DNSOBJS = acl.@O@ adb.@O@ badcache.@O@ byaddr.@O@ \
|
||||
cache.@O@ callbacks.@O@ catz.@O@ clientinfo.@O@ compress.@O@ \
|
||||
db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \
|
||||
dlz.@O@ dns64.@O@ dnssec.@O@ ds.@O@ dyndb.@O@ ecs.@O@ \
|
||||
forward.@O@ ipkeylist.@O@ iptable.@O@ journal.@O@ keydata.@O@ \
|
||||
dlz.@O@ dns64.@O@ dnsrps.@O@ dnssec.@O@ ds.@O@ dyndb.@O@ \
|
||||
ecs.@O@ forward.@O@ \
|
||||
ipkeylist.@O@ iptable.@O@ journal.@O@ keydata.@O@ \
|
||||
keytable.@O@ lib.@O@ log.@O@ lookup.@O@ \
|
||||
master.@O@ masterdump.@O@ message.@O@ \
|
||||
name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ nta.@O@ \
|
||||
|
|
@ -103,7 +104,7 @@ DNSTAPSRCS = dnstap.c dnstap.pb-c.c
|
|||
DNSSRCS = acl.c adb.c badcache. byaddr.c \
|
||||
cache.c callbacks.c clientinfo.c compress.c \
|
||||
db.c dbiterator.c dbtable.c diff.c dispatch.c \
|
||||
dlz.c dns64.c dnssec.c ds.c dyndb.c ecs.c forward.c \
|
||||
dlz.c dns64.c dnsrps.c dnssec.c ds.c dyndb.c ecs.c forward.c \
|
||||
ipkeylist.c iptable.c journal.c keydata.c keytable.c lib.c \
|
||||
log.c lookup.c master.c masterdump.c message.c \
|
||||
name.c ncache.c nsec.c nsec3.c nta.c \
|
||||
|
|
|
|||
995
lib/dns/dnsrps.c
Normal file
995
lib/dns/dnsrps.c
Normal file
|
|
@ -0,0 +1,995 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef USE_DNSRPS
|
||||
|
||||
#include <isc/mem.h>
|
||||
#include <isc/stdlib.h>
|
||||
#include <isc/string.h>
|
||||
|
||||
#include <dns/db.h>
|
||||
#define LIBRPZ_LIB_OPEN DNSRPS_LIB_OPEN
|
||||
#include <dns/dnsrps.h>
|
||||
#include <dns/rdataset.h>
|
||||
#include <dns/rdatasetiter.h>
|
||||
#include <dns/result.h>
|
||||
#include <dns/rpz.h>
|
||||
|
||||
librpz_t *librpz;
|
||||
librpz_emsg_t librpz_lib_open_emsg;
|
||||
static void *librpz_handle;
|
||||
|
||||
#define RPSDB_MAGIC ISC_MAGIC('R', 'P', 'Z', 'F')
|
||||
#define VALID_RPSDB(rpsdb) ((rpsdb)->common.impmagic == RPSDB_MAGIC)
|
||||
|
||||
#define RD_DB(r) ((r)->private1)
|
||||
#define RD_CUR_RR(r) ((r)->private2)
|
||||
#define RD_NEXT_RR(r) ((r)->resign)
|
||||
#define RD_COUNT(r) ((r)->privateuint4)
|
||||
|
||||
typedef struct {
|
||||
dns_rdatasetiter_t common;
|
||||
dns_rdatatype_t type;
|
||||
dns_rdataclass_t class;
|
||||
uint32_t ttl;
|
||||
uint count;
|
||||
librpz_idx_t next_rr;
|
||||
} rpsdb_rdatasetiter_t;
|
||||
|
||||
static dns_dbmethods_t rpsdb_db_methods;
|
||||
static dns_rdatasetmethods_t rpsdb_rdataset_methods;
|
||||
static dns_rdatasetitermethods_t rpsdb_rdatasetiter_methods;
|
||||
|
||||
static librpz_clist_t *clist;
|
||||
|
||||
static isc_mutex_t dnsrps_mutex;
|
||||
|
||||
static void
|
||||
dnsrps_lock(void *mutex0) {
|
||||
isc_mutex_t *mutex = mutex0;
|
||||
|
||||
LOCK(mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
dnsrps_unlock(void *mutex0) {
|
||||
isc_mutex_t *mutex = mutex0;
|
||||
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
dnsrps_mutex_destroy(void *mutex0) {
|
||||
isc_mutex_t *mutex = mutex0;
|
||||
|
||||
DESTROYLOCK(mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
dnsrps_log_fnc(librpz_log_level_t level, void *ctxt, const char *buf) {
|
||||
int isc_level;
|
||||
|
||||
UNUSED(ctxt);
|
||||
|
||||
/* Setting librpz_log_level in the configuration overrides the
|
||||
* BIND9 logging levels. */
|
||||
if (level > LIBRPZ_LOG_TRACE1 &&
|
||||
level <= librpz->log_level_val(LIBRPZ_LOG_INVALID))
|
||||
level = LIBRPZ_LOG_TRACE1;
|
||||
|
||||
switch(level) {
|
||||
case LIBRPZ_LOG_FATAL:
|
||||
case LIBRPZ_LOG_ERROR: /* errors */
|
||||
default:
|
||||
isc_level = DNS_RPZ_ERROR_LEVEL;
|
||||
break;
|
||||
|
||||
case LIBRPZ_LOG_TRACE1: /* big events such as dnsrpzd starts */
|
||||
isc_level = DNS_RPZ_INFO_LEVEL;
|
||||
break;
|
||||
|
||||
case LIBRPZ_LOG_TRACE2: /* smaller dnsrpzd zone transfers */
|
||||
isc_level = DNS_RPZ_DEBUG_LEVEL1;
|
||||
break;
|
||||
|
||||
case LIBRPZ_LOG_TRACE3: /* librpz hits */
|
||||
isc_level = DNS_RPZ_DEBUG_LEVEL2;
|
||||
break;
|
||||
|
||||
case LIBRPZ_LOG_TRACE4: /* librpz lookups */
|
||||
isc_level = DNS_RPZ_DEBUG_LEVEL3;
|
||||
break;
|
||||
}
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RBTDB,
|
||||
isc_level, "dnsrps: %s", buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start dnsrps for the entire server.
|
||||
* This is not thread safe, but it is called by a single thread.
|
||||
*/
|
||||
isc_result_t
|
||||
dns_dnsrps_server_create(void) {
|
||||
librpz_emsg_t emsg;
|
||||
isc_result_t result;
|
||||
|
||||
INSIST(clist == NULL);
|
||||
INSIST(librpz == NULL);
|
||||
INSIST(librpz_handle == NULL);
|
||||
|
||||
/*
|
||||
* Notice if librpz is available.
|
||||
*/
|
||||
librpz = librpz_lib_open(&librpz_lib_open_emsg,
|
||||
&librpz_handle, DNSRPS_LIBRPZ_PATH);
|
||||
/*
|
||||
* Stop now without complaining if librpz is not available.
|
||||
* Complain later if and when librpz is needed for a view with
|
||||
* "dnsrps-enable yse" (including the default view).
|
||||
*/
|
||||
if (librpz == NULL)
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
result = isc_mutex_init(&dnsrps_mutex);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
librpz->set_log(&dnsrps_log_fnc, NULL);
|
||||
|
||||
clist = librpz->clist_create(&emsg, dnsrps_lock, dnsrps_unlock,
|
||||
dnsrps_mutex_destroy, &dnsrps_mutex,
|
||||
dns_lctx);
|
||||
if (clist == NULL) {
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
|
||||
DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
|
||||
"dnsrps: %s", emsg.c);
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop dnsrps for the entire server.
|
||||
* This is not thread safe.
|
||||
*/
|
||||
void
|
||||
dns_dnsrps_server_destroy(void) {
|
||||
if (clist != NULL)
|
||||
librpz->clist_detach(&clist);
|
||||
|
||||
#ifdef LIBRPZ_USE_DLOPEN
|
||||
if (librpz != NULL) {
|
||||
INSIST(librpz_handle != NULL);
|
||||
if (dlclose(librpz_handle) != 0)
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
|
||||
DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
|
||||
"dnsrps: dlclose(): %s", dlerror());
|
||||
librpz_handle = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Ready dnsrps for a view.
|
||||
*/
|
||||
isc_result_t
|
||||
dns_dnsrps_view_init(dns_rpz_zones_t *new, char *rps_cstr) {
|
||||
librpz_emsg_t emsg;
|
||||
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
|
||||
DNS_LOGMODULE_RBTDB, DNS_RPZ_DEBUG_LEVEL3,
|
||||
"dnsrps configuration \"%s\"", rps_cstr);
|
||||
|
||||
new->rps_client = librpz->client_create(&emsg, clist,
|
||||
rps_cstr, ISC_FALSE);
|
||||
if (new->rps_client == NULL) {
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
|
||||
DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
|
||||
"librpz->client_create(): %s", emsg.c);
|
||||
new->p.dnsrps_enabled = ISC_FALSE;
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
new->p.dnsrps_enabled = ISC_TRUE;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Connect to and start the dnsrps daemon, dnsrpzd.
|
||||
*/
|
||||
isc_result_t
|
||||
dns_dnsrps_connect(dns_rpz_zones_t *rpzs) {
|
||||
librpz_emsg_t emsg;
|
||||
|
||||
if (rpzs == NULL || !rpzs->p.dnsrps_enabled)
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
/*
|
||||
* Fail only if we failed to link to librpz.
|
||||
*/
|
||||
if (librpz == NULL) {
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
|
||||
DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
|
||||
"librpz->connect(): %s", librpz_lib_open_emsg.c);
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (!librpz->connect(&emsg, rpzs->rps_client, true)) {
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
|
||||
DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
|
||||
"librpz->connect(): %s", emsg.c);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RBTDB,
|
||||
DNS_RPZ_INFO_LEVEL, "dnsrps: librpz version %s",
|
||||
librpz->version);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get ready to try RPZ rewriting.
|
||||
*/
|
||||
isc_result_t
|
||||
dns_dnsrps_rewrite_init(librpz_emsg_t *emsg, dns_rpz_st_t *st,
|
||||
dns_rpz_zones_t *rpzs, const dns_name_t *qname,
|
||||
isc_mem_t *mctx, isc_boolean_t have_rd)
|
||||
{
|
||||
rpsdb_t *rpsdb;
|
||||
|
||||
rpsdb = isc_mem_get(mctx, sizeof(*rpsdb));
|
||||
if (rpsdb == NULL) {
|
||||
strlcpy(emsg->c, "no memory", sizeof(emsg->c));
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
memset(rpsdb, 0, sizeof(*rpsdb));
|
||||
|
||||
if (!librpz->rsp_create(emsg, &rpsdb->rsp, NULL,
|
||||
rpzs->rps_client, have_rd, false)) {
|
||||
isc_mem_put(mctx, rpsdb, sizeof(*rpsdb));
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
if (rpsdb->rsp == NULL) {
|
||||
isc_mem_put(mctx, rpsdb, sizeof(*rpsdb));
|
||||
return (DNS_R_DISALLOWED);
|
||||
}
|
||||
|
||||
rpsdb->common.magic = DNS_DB_MAGIC;
|
||||
rpsdb->common.impmagic = RPSDB_MAGIC;
|
||||
rpsdb->common.methods = &rpsdb_db_methods;
|
||||
rpsdb->common.rdclass = dns_rdataclass_in;
|
||||
dns_name_init(&rpsdb->common.origin, NULL);
|
||||
isc_mem_attach(mctx, &rpsdb->common.mctx);
|
||||
|
||||
rpsdb->ref_cnt = 1;
|
||||
rpsdb->qname = qname;
|
||||
|
||||
st->rpsdb = &rpsdb->common;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a dnsrps policy to a classic BIND9 RPZ policy.
|
||||
*/
|
||||
dns_rpz_policy_t
|
||||
dns_dnsrps_2policy(librpz_policy_t rps_policy) {
|
||||
switch (rps_policy) {
|
||||
case LIBRPZ_POLICY_UNDEFINED:
|
||||
return (DNS_RPZ_POLICY_MISS);
|
||||
case LIBRPZ_POLICY_PASSTHRU:
|
||||
return (DNS_RPZ_POLICY_PASSTHRU);
|
||||
case LIBRPZ_POLICY_DROP:
|
||||
return (DNS_RPZ_POLICY_DROP);
|
||||
case LIBRPZ_POLICY_TCP_ONLY:
|
||||
return (DNS_RPZ_POLICY_TCP_ONLY);
|
||||
case LIBRPZ_POLICY_NXDOMAIN:
|
||||
return (DNS_RPZ_POLICY_NXDOMAIN);
|
||||
case LIBRPZ_POLICY_NODATA:
|
||||
return (DNS_RPZ_POLICY_NODATA);
|
||||
case LIBRPZ_POLICY_RECORD:
|
||||
case LIBRPZ_POLICY_CNAME:
|
||||
return (DNS_RPZ_POLICY_RECORD);
|
||||
|
||||
case LIBRPZ_POLICY_DELETED:
|
||||
case LIBRPZ_POLICY_GIVEN:
|
||||
case LIBRPZ_POLICY_DISABLED:
|
||||
default:
|
||||
INSIST(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a dnsrps trigger to a classic BIND9 RPZ rewrite or trigger type.
|
||||
*/
|
||||
dns_rpz_type_t
|
||||
dns_dnsrps_trig2type(librpz_trig_t trig) {
|
||||
switch (trig) {
|
||||
case LIBRPZ_TRIG_BAD:
|
||||
default:
|
||||
return (DNS_RPZ_TYPE_BAD);
|
||||
case LIBRPZ_TRIG_CLIENT_IP:
|
||||
return (DNS_RPZ_TYPE_CLIENT_IP);
|
||||
case LIBRPZ_TRIG_QNAME:
|
||||
return (DNS_RPZ_TYPE_QNAME);
|
||||
case LIBRPZ_TRIG_IP:
|
||||
return (DNS_RPZ_TYPE_IP);
|
||||
case LIBRPZ_TRIG_NSDNAME:
|
||||
return (DNS_RPZ_TYPE_NSDNAME);
|
||||
case LIBRPZ_TRIG_NSIP:
|
||||
return (DNS_RPZ_TYPE_NSIP);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a classic BIND9 RPZ rewrite or trigger type to a librpz trigger type.
|
||||
*/
|
||||
librpz_trig_t
|
||||
dns_dnsrps_type2trig(dns_rpz_type_t type) {
|
||||
switch (type) {
|
||||
case DNS_RPZ_TYPE_BAD:
|
||||
default:
|
||||
return (LIBRPZ_TRIG_BAD);
|
||||
case DNS_RPZ_TYPE_CLIENT_IP:
|
||||
return (LIBRPZ_TRIG_CLIENT_IP);
|
||||
case DNS_RPZ_TYPE_QNAME:
|
||||
return (LIBRPZ_TRIG_QNAME);
|
||||
case DNS_RPZ_TYPE_IP:
|
||||
return (LIBRPZ_TRIG_IP);
|
||||
case DNS_RPZ_TYPE_NSDNAME:
|
||||
return (LIBRPZ_TRIG_NSDNAME);
|
||||
case DNS_RPZ_TYPE_NSIP:
|
||||
return (LIBRPZ_TRIG_NSIP);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rpsdb_attach(dns_db_t *source, dns_db_t **targetp) {
|
||||
rpsdb_t *rpsdb = (rpsdb_t *)source;
|
||||
|
||||
REQUIRE(VALID_RPSDB(rpsdb));
|
||||
|
||||
/*
|
||||
* Use a simple count because only one thread uses any single rpsdb_t
|
||||
*/
|
||||
++rpsdb->ref_cnt;
|
||||
*targetp = source;
|
||||
}
|
||||
|
||||
static void
|
||||
rpsdb_detach(dns_db_t **dbp) {
|
||||
rpsdb_t *rpsdb = (rpsdb_t *)*dbp;
|
||||
|
||||
REQUIRE(VALID_RPSDB(rpsdb));
|
||||
REQUIRE(rpsdb->ref_cnt > 0);
|
||||
|
||||
*dbp = NULL;
|
||||
|
||||
/*
|
||||
* Simple count because only one thread uses a rpsdb_t.
|
||||
*/
|
||||
if (--rpsdb->ref_cnt != 0)
|
||||
return;
|
||||
|
||||
librpz->rsp_detach(&rpsdb->rsp);
|
||||
rpsdb->common.impmagic = 0;
|
||||
isc_mem_putanddetach(&rpsdb->common.mctx, rpsdb, sizeof(*rpsdb));
|
||||
}
|
||||
|
||||
static void
|
||||
rpsdb_attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
|
||||
rpsdb_t *rpsdb = (rpsdb_t *)db;
|
||||
|
||||
REQUIRE(VALID_RPSDB(rpsdb));
|
||||
REQUIRE(targetp != NULL && *targetp == NULL);
|
||||
REQUIRE(source == &rpsdb->origin_node ||
|
||||
source == &rpsdb->data_node);
|
||||
|
||||
/*
|
||||
* Simple count because only one thread uses a rpsdb_t.
|
||||
*/
|
||||
++rpsdb->ref_cnt;
|
||||
*targetp = source;
|
||||
}
|
||||
|
||||
static void
|
||||
rpsdb_detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
|
||||
rpsdb_t *rpsdb = (rpsdb_t *)db;
|
||||
|
||||
REQUIRE(VALID_RPSDB(rpsdb));
|
||||
REQUIRE(*targetp == &rpsdb->origin_node ||
|
||||
*targetp == &rpsdb->data_node);
|
||||
|
||||
*targetp = NULL;
|
||||
rpsdb_detach(&db);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
rpsdb_findnode(dns_db_t *db, const dns_name_t *name, isc_boolean_t create,
|
||||
dns_dbnode_t **nodep)
|
||||
{
|
||||
rpsdb_t *rpsdb = (rpsdb_t *)db;
|
||||
dns_db_t *dbp;
|
||||
|
||||
REQUIRE(VALID_RPSDB(rpsdb));
|
||||
REQUIRE(nodep != NULL && *nodep == NULL);
|
||||
REQUIRE(!create);
|
||||
|
||||
/*
|
||||
* A fake/shim rpsdb has two nodes.
|
||||
* One is the origin to support query_addsoa() in bin/named/query.c.
|
||||
* The other contains rewritten RRs.
|
||||
*/
|
||||
if (dns_name_equal(name, &db->origin))
|
||||
*nodep = &rpsdb->origin_node;
|
||||
else
|
||||
*nodep = &rpsdb->data_node;
|
||||
dbp = NULL;
|
||||
rpsdb_attach(db, &dbp);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
rpsdb_bind_rdataset(dns_rdataset_t *rdataset, uint count, librpz_idx_t next_rr,
|
||||
dns_rdatatype_t type, uint16_t class, uint32_t ttl,
|
||||
rpsdb_t *rpsdb)
|
||||
{
|
||||
dns_db_t *dbp;
|
||||
|
||||
INSIST(rdataset->methods == NULL); /* We must be disassociated. */
|
||||
REQUIRE(type != dns_rdatatype_none);
|
||||
|
||||
rdataset->methods = &rpsdb_rdataset_methods;
|
||||
rdataset->rdclass = class;
|
||||
rdataset->type = type;
|
||||
rdataset->ttl = ttl;
|
||||
dbp = NULL;
|
||||
dns_db_attach(&rpsdb->common, &dbp);
|
||||
RD_DB(rdataset) = dbp;
|
||||
RD_COUNT(rdataset) = count;
|
||||
RD_NEXT_RR(rdataset) = next_rr;
|
||||
RD_CUR_RR(rdataset) = NULL;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
rpsdb_bind_soa(dns_rdataset_t *rdataset, rpsdb_t *rpsdb) {
|
||||
uint32_t ttl;
|
||||
librpz_emsg_t emsg;
|
||||
|
||||
if (!librpz->rsp_soa(&emsg, &ttl, NULL, NULL,
|
||||
&rpsdb->result, rpsdb->rsp)) {
|
||||
librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
rpsdb_bind_rdataset(rdataset, 1, LIBRPZ_IDX_BAD, dns_rdatatype_soa,
|
||||
dns_rdataclass_in, ttl, rpsdb);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Forge an rdataset of the desired type from a librpz result.
|
||||
* This is written for simplicity instead of speed, because RPZ rewriting
|
||||
* should be rare compared to normal BIND operations.
|
||||
*/
|
||||
static isc_result_t
|
||||
rpsdb_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
dns_rdatatype_t type, dns_rdatatype_t covers,
|
||||
isc_stdtime_t now, dns_rdataset_t *rdataset,
|
||||
dns_rdataset_t *sigrdataset)
|
||||
{
|
||||
rpsdb_t *rpsdb = (rpsdb_t *)db;
|
||||
dns_rdatatype_t foundtype;
|
||||
dns_rdataclass_t class;
|
||||
uint32_t ttl;
|
||||
uint count;
|
||||
librpz_emsg_t emsg;
|
||||
|
||||
UNUSED(version);
|
||||
UNUSED(covers);
|
||||
UNUSED(now);
|
||||
UNUSED(sigrdataset);
|
||||
|
||||
REQUIRE(VALID_RPSDB(rpsdb));
|
||||
|
||||
if (node == &rpsdb->origin_node) {
|
||||
if (type == dns_rdatatype_any)
|
||||
return (ISC_R_SUCCESS);
|
||||
if (type == dns_rdatatype_soa)
|
||||
return (rpsdb_bind_soa(rdataset, rpsdb));
|
||||
return (DNS_R_NXRRSET);
|
||||
}
|
||||
|
||||
REQUIRE(node == &rpsdb->data_node);
|
||||
|
||||
switch (rpsdb->result.policy) {
|
||||
case LIBRPZ_POLICY_UNDEFINED:
|
||||
case LIBRPZ_POLICY_DELETED:
|
||||
case LIBRPZ_POLICY_PASSTHRU:
|
||||
case LIBRPZ_POLICY_DROP:
|
||||
case LIBRPZ_POLICY_TCP_ONLY:
|
||||
case LIBRPZ_POLICY_GIVEN:
|
||||
case LIBRPZ_POLICY_DISABLED:
|
||||
default:
|
||||
librpz->log(LIBRPZ_LOG_ERROR, NULL,
|
||||
"impossible dnsrps policy %d at %s:%d",
|
||||
rpsdb->result.policy, __FILE__, __LINE__);
|
||||
return (DNS_R_SERVFAIL);
|
||||
|
||||
case LIBRPZ_POLICY_NXDOMAIN:
|
||||
return (DNS_R_NXDOMAIN);
|
||||
|
||||
case LIBRPZ_POLICY_NODATA:
|
||||
return (DNS_R_NXRRSET);
|
||||
|
||||
case LIBRPZ_POLICY_RECORD:
|
||||
case LIBRPZ_POLICY_CNAME:
|
||||
break;
|
||||
}
|
||||
|
||||
if (type == dns_rdatatype_soa)
|
||||
return (rpsdb_bind_soa(rdataset, rpsdb));
|
||||
|
||||
/*
|
||||
* There is little to do for an ANY query.
|
||||
*/
|
||||
if (type == dns_rdatatype_any)
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
/*
|
||||
* Reset to the start of the RRs.
|
||||
* This function is only used after a policy has been chosen,
|
||||
* and so without caring whether it is after recursion.
|
||||
*/
|
||||
if (!librpz->rsp_result(&emsg, &rpsdb->result, true, rpsdb->rsp)) {
|
||||
librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
if (!librpz->rsp_rr(&emsg, &foundtype, &class, &ttl, NULL,
|
||||
&rpsdb->result, rpsdb->qname->ndata,
|
||||
rpsdb->qname->length, rpsdb->rsp)) {
|
||||
librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
REQUIRE(foundtype != dns_rdatatype_none);
|
||||
|
||||
/*
|
||||
* Ho many of the target RR type are available?
|
||||
*/
|
||||
count = 0;
|
||||
do {
|
||||
if (type == foundtype || type == dns_rdatatype_any)
|
||||
++count;
|
||||
|
||||
if (!librpz->rsp_rr(&emsg, &foundtype, NULL, NULL, NULL,
|
||||
&rpsdb->result, rpsdb->qname->ndata,
|
||||
rpsdb->qname->length, rpsdb->rsp)) {
|
||||
librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
} while (foundtype != dns_rdatatype_none);
|
||||
if (count == 0)
|
||||
return (DNS_R_NXRRSET);
|
||||
rpsdb_bind_rdataset(rdataset, count, rpsdb->result.next_rr,
|
||||
type, class, ttl, rpsdb);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
rpsdb_finddb(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
|
||||
dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
|
||||
dns_dbnode_t **nodep, dns_name_t *foundname,
|
||||
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
|
||||
{
|
||||
dns_dbnode_t *node;
|
||||
isc_result_t result;
|
||||
|
||||
UNUSED(version);
|
||||
UNUSED(options);
|
||||
UNUSED(now);
|
||||
UNUSED(sigrdataset);
|
||||
|
||||
if (nodep == NULL) {
|
||||
node = NULL;
|
||||
nodep = &node;
|
||||
}
|
||||
rpsdb_findnode(db, name, false, nodep);
|
||||
result = dns_name_copy(name, foundname, NULL);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
return (rpsdb_findrdataset(db, *nodep, NULL, type, 0, 0,
|
||||
rdataset, sigrdataset));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
rpsdb_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
|
||||
{
|
||||
rpsdb_t *rpsdb = (rpsdb_t *)db;
|
||||
rpsdb_rdatasetiter_t *rpsdb_iter;
|
||||
|
||||
UNUSED(version);
|
||||
UNUSED(now);
|
||||
|
||||
REQUIRE(VALID_RPSDB(rpsdb));
|
||||
REQUIRE(node == &rpsdb->origin_node || node == &rpsdb->data_node);
|
||||
|
||||
rpsdb_iter = isc_mem_get(rpsdb->common.mctx, sizeof(*rpsdb_iter));
|
||||
if (rpsdb_iter == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
memset(rpsdb_iter, 0, sizeof(*rpsdb_iter));
|
||||
rpsdb_iter->common.magic = DNS_RDATASETITER_MAGIC;
|
||||
rpsdb_iter->common.methods = &rpsdb_rdatasetiter_methods;
|
||||
rpsdb_iter->common.db = db;
|
||||
rpsdb_attachnode(db, node, &rpsdb_iter->common.node);
|
||||
|
||||
*iteratorp = &rpsdb_iter->common;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_boolean_t
|
||||
rpsdb_issecure(dns_db_t *db) {
|
||||
UNUSED(db);
|
||||
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
rpsdb_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
|
||||
rpsdb_t *rpsdb = (rpsdb_t *)db;
|
||||
|
||||
REQUIRE(VALID_RPSDB(rpsdb));
|
||||
REQUIRE(nodep != NULL && *nodep == NULL);
|
||||
|
||||
rpsdb_attachnode(db, &rpsdb->origin_node, nodep);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
rpsdb_rdataset_disassociate(dns_rdataset_t *rdataset) {
|
||||
dns_db_t *db;
|
||||
|
||||
/*
|
||||
* Detach the last RR delivered.
|
||||
*/
|
||||
if (RD_CUR_RR(rdataset) != NULL) {
|
||||
free(RD_CUR_RR(rdataset));
|
||||
RD_CUR_RR(rdataset) = NULL;
|
||||
}
|
||||
|
||||
db = RD_DB(rdataset);
|
||||
RD_DB(rdataset) = NULL;
|
||||
dns_db_detach(&db);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
rpsdb_rdataset_next(dns_rdataset_t *rdataset) {
|
||||
rpsdb_t *rpsdb;
|
||||
uint16_t type;
|
||||
dns_rdataclass_t class;
|
||||
librpz_rr_t *rr;
|
||||
librpz_emsg_t emsg;
|
||||
|
||||
rpsdb = RD_DB(rdataset);
|
||||
|
||||
/*
|
||||
* Detach the previous RR.
|
||||
*/
|
||||
if (RD_CUR_RR(rdataset) != NULL) {
|
||||
free(RD_CUR_RR(rdataset));
|
||||
RD_CUR_RR(rdataset) = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the next RR of the specified type.
|
||||
* SOAs differ.
|
||||
*/
|
||||
if (rdataset->type == dns_rdatatype_soa) {
|
||||
if (RD_NEXT_RR(rdataset) == LIBRPZ_IDX_NULL)
|
||||
return (ISC_R_NOMORE);
|
||||
RD_NEXT_RR(rdataset) = LIBRPZ_IDX_NULL;
|
||||
if (!librpz->rsp_soa(&emsg, NULL, &rr, NULL,
|
||||
&rpsdb->result, rpsdb->rsp)) {
|
||||
librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
RD_CUR_RR(rdataset) = rr;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
rpsdb->result.next_rr = RD_NEXT_RR(rdataset);
|
||||
for (;;) {
|
||||
if (!librpz->rsp_rr(&emsg, &type, &class, NULL, &rr,
|
||||
&rpsdb->result, rpsdb->qname->ndata,
|
||||
rpsdb->qname->length, rpsdb->rsp)) {
|
||||
librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
if (rdataset->type == type &&
|
||||
rdataset->rdclass == class) {
|
||||
RD_CUR_RR(rdataset) = rr;
|
||||
RD_NEXT_RR(rdataset) = rpsdb->result.next_rr;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
if (type == dns_rdatatype_none)
|
||||
return (ISC_R_NOMORE);
|
||||
free(rr);
|
||||
}
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
rpsdb_rdataset_first(dns_rdataset_t *rdataset) {
|
||||
rpsdb_t *rpsdb;
|
||||
librpz_emsg_t emsg;
|
||||
|
||||
rpsdb = RD_DB(rdataset);
|
||||
REQUIRE(VALID_RPSDB(rpsdb));
|
||||
|
||||
if (RD_CUR_RR(rdataset) != NULL) {
|
||||
free(RD_CUR_RR(rdataset));
|
||||
RD_CUR_RR(rdataset) = NULL;
|
||||
}
|
||||
|
||||
if (!librpz->rsp_result(&emsg, &rpsdb->result, true, rpsdb->rsp)) {
|
||||
librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
if (rdataset->type == dns_rdatatype_soa)
|
||||
RD_NEXT_RR(rdataset) = LIBRPZ_IDX_BAD;
|
||||
else
|
||||
RD_NEXT_RR(rdataset) = rpsdb->result.next_rr;
|
||||
|
||||
return (rpsdb_rdataset_next(rdataset));
|
||||
}
|
||||
|
||||
static void
|
||||
rpsdb_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
|
||||
rpsdb_t *rpsdb;
|
||||
librpz_rr_t *rr;
|
||||
isc_region_t r;
|
||||
|
||||
rpsdb = RD_DB(rdataset);
|
||||
REQUIRE(VALID_RPSDB(rpsdb));
|
||||
rr = RD_CUR_RR(rdataset);
|
||||
REQUIRE(rr != NULL);
|
||||
|
||||
r.length = ntohs(rr->rdlength);
|
||||
r.base = rr->rdata;
|
||||
dns_rdata_fromregion(rdata, ntohs(rr->class), ntohs(rr->type), &r);
|
||||
}
|
||||
|
||||
static void
|
||||
rpsdb_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
|
||||
rpsdb_t *rpsdb;
|
||||
dns_db_t *dbp;
|
||||
|
||||
INSIST(!ISC_LINK_LINKED(target, link));
|
||||
*target = *source;
|
||||
ISC_LINK_INIT(target, link);
|
||||
rpsdb = RD_DB(source);
|
||||
REQUIRE(VALID_RPSDB(rpsdb));
|
||||
dbp = NULL;
|
||||
dns_db_attach(&rpsdb->common, &dbp);
|
||||
RD_DB(target) = dbp;
|
||||
RD_CUR_RR(target) = NULL;
|
||||
RD_NEXT_RR(target) = LIBRPZ_IDX_NULL;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
rpsdb_rdataset_count(dns_rdataset_t *rdataset) {
|
||||
rpsdb_t *rpsdb;
|
||||
|
||||
rpsdb = RD_DB(rdataset);
|
||||
REQUIRE(VALID_RPSDB(rpsdb));
|
||||
|
||||
return (RD_COUNT(rdataset));
|
||||
}
|
||||
|
||||
static void
|
||||
rpsdb_rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
|
||||
rpsdb_t *rpsdb;
|
||||
dns_rdatasetiter_t *iterator;
|
||||
isc_mem_t *mctx;
|
||||
|
||||
iterator = *iteratorp;
|
||||
rpsdb = (rpsdb_t *)iterator->db;
|
||||
REQUIRE(VALID_RPSDB(rpsdb));
|
||||
|
||||
mctx = iterator->db->mctx;
|
||||
dns_db_detachnode(iterator->db, &iterator->node);
|
||||
isc_mem_put(mctx, iterator, sizeof(rpsdb_rdatasetiter_t));
|
||||
*iteratorp = NULL;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
rpsdb_rdatasetiter_next(dns_rdatasetiter_t *iter) {
|
||||
rpsdb_t *rpsdb;
|
||||
rpsdb_rdatasetiter_t *rpsdb_iter;
|
||||
dns_rdatatype_t next_type, type;
|
||||
dns_rdataclass_t next_class, class;
|
||||
uint32_t ttl;
|
||||
librpz_emsg_t emsg;
|
||||
|
||||
rpsdb = (rpsdb_t *)iter->db;
|
||||
REQUIRE(VALID_RPSDB(rpsdb));
|
||||
rpsdb_iter = (rpsdb_rdatasetiter_t *)iter;
|
||||
|
||||
/*
|
||||
* This function is only used after a policy has been chosen,
|
||||
* and so without caring whether it is after recursion.
|
||||
*/
|
||||
if (!librpz->rsp_result(&emsg, &rpsdb->result, true, rpsdb->rsp)) {
|
||||
librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
/*
|
||||
* Find the next class and type after the current class and type
|
||||
* among the RRs in current result.
|
||||
* As a side effect, count the number of those RRs.
|
||||
*/
|
||||
rpsdb_iter->count = 0;
|
||||
next_class = dns_rdataclass_reserved0;
|
||||
next_type = dns_rdatatype_none;
|
||||
for (;;) {
|
||||
if (!librpz->rsp_rr(&emsg, &type, &class, &ttl,
|
||||
NULL, &rpsdb->result, rpsdb->qname->ndata,
|
||||
rpsdb->qname->length, rpsdb->rsp)) {
|
||||
librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
if (type == dns_rdatatype_none) {
|
||||
if (next_type == dns_rdatatype_none)
|
||||
return (ISC_R_NOMORE);
|
||||
rpsdb_iter->type = next_type;
|
||||
rpsdb_iter->class = next_class;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
/*
|
||||
* Skip RRs with the current class and type or before.
|
||||
*/
|
||||
if (rpsdb_iter->class > class ||
|
||||
(rpsdb_iter->class = class && rpsdb_iter->type >= type))
|
||||
continue;
|
||||
if (next_type == dns_rdatatype_none ||
|
||||
next_class > class ||
|
||||
(next_class == class && next_type > type)) {
|
||||
/*
|
||||
* This is the first of a subsequent class and type.
|
||||
*/
|
||||
next_type = type;
|
||||
next_class = class;
|
||||
rpsdb_iter->ttl = ttl;
|
||||
rpsdb_iter->count = 1;
|
||||
rpsdb_iter->next_rr = rpsdb->result.next_rr;
|
||||
} else if (next_type == type && next_class == class) {
|
||||
++rpsdb_iter->count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
rpsdb_rdatasetiter_first(dns_rdatasetiter_t *iterator) {
|
||||
rpsdb_t *rpsdb;
|
||||
rpsdb_rdatasetiter_t *rpsdb_iter;
|
||||
|
||||
rpsdb = (rpsdb_t *)iterator->db;
|
||||
REQUIRE(VALID_RPSDB(rpsdb));
|
||||
rpsdb_iter = (rpsdb_rdatasetiter_t *)iterator;
|
||||
|
||||
rpsdb_iter->type = dns_rdatatype_none;
|
||||
rpsdb_iter->class = dns_rdataclass_reserved0;
|
||||
return (rpsdb_rdatasetiter_next(iterator));
|
||||
}
|
||||
|
||||
static void
|
||||
rpsdb_rdatasetiter_current(dns_rdatasetiter_t *iterator,
|
||||
dns_rdataset_t *rdataset)
|
||||
{
|
||||
rpsdb_t *rpsdb;
|
||||
rpsdb_rdatasetiter_t *rpsdb_iter;
|
||||
|
||||
rpsdb = (rpsdb_t *)iterator->db;
|
||||
REQUIRE(VALID_RPSDB(rpsdb));
|
||||
rpsdb_iter = (rpsdb_rdatasetiter_t *)iterator;
|
||||
REQUIRE(rpsdb_iter->type != dns_rdatatype_none);
|
||||
|
||||
rpsdb_bind_rdataset(rdataset,
|
||||
rpsdb_iter->count, rpsdb_iter->next_rr,
|
||||
rpsdb_iter->type, rpsdb_iter->class,
|
||||
rpsdb_iter->ttl, rpsdb);
|
||||
}
|
||||
|
||||
static dns_dbmethods_t rpsdb_db_methods = {
|
||||
rpsdb_attach,
|
||||
rpsdb_detach,
|
||||
NULL, /* beginload */
|
||||
NULL, /* endload */
|
||||
NULL, /* serialize */
|
||||
NULL, /* dump */
|
||||
NULL, /* currentversion */
|
||||
NULL, /* newversion */
|
||||
NULL, /* attachversion */
|
||||
NULL, /* closeversion */
|
||||
rpsdb_findnode,
|
||||
rpsdb_finddb,
|
||||
NULL, /* findzonecut*/
|
||||
rpsdb_attachnode,
|
||||
rpsdb_detachnode,
|
||||
NULL, /* expirenode */
|
||||
NULL, /* printnode */
|
||||
NULL, /* createiterator */
|
||||
rpsdb_findrdataset,
|
||||
rpsdb_allrdatasets,
|
||||
NULL, /* addrdataset */
|
||||
NULL, /* subtractrdataset */
|
||||
NULL, /* deleterdataset */
|
||||
rpsdb_issecure,
|
||||
NULL, /* nodecount */
|
||||
NULL, /* ispersistent */
|
||||
NULL, /* overmem */
|
||||
NULL, /* settask */
|
||||
rpsdb_getoriginnode,
|
||||
NULL, /* transfernode */
|
||||
NULL, /* getnsec3parameters */
|
||||
NULL, /* findnsec3node */
|
||||
NULL, /* setsigningtime */
|
||||
NULL, /* getsigningtime */
|
||||
NULL, /* resigned */
|
||||
NULL, /* isdnssec */
|
||||
NULL, /* getrrsetstats */
|
||||
NULL, /* rpz_attach */
|
||||
NULL, /* rpz_ready */
|
||||
NULL, /* findnodeext */
|
||||
NULL, /* findext */
|
||||
NULL, /* setcachestats */
|
||||
NULL, /* hashsize */
|
||||
NULL, /* nodefullname */
|
||||
NULL /* getsize */
|
||||
};
|
||||
|
||||
static dns_rdatasetmethods_t rpsdb_rdataset_methods = {
|
||||
rpsdb_rdataset_disassociate,
|
||||
rpsdb_rdataset_first,
|
||||
rpsdb_rdataset_next,
|
||||
rpsdb_rdataset_current,
|
||||
rpsdb_rdataset_clone,
|
||||
rpsdb_rdataset_count,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
static dns_rdatasetitermethods_t rpsdb_rdatasetiter_methods = {
|
||||
rpsdb_rdatasetiter_destroy,
|
||||
rpsdb_rdatasetiter_first,
|
||||
rpsdb_rdatasetiter_next,
|
||||
rpsdb_rdatasetiter_current
|
||||
};
|
||||
|
||||
#endif /* USE_DNSRPS */
|
||||
|
|
@ -14,12 +14,12 @@ HEADERS = acl.h adb.h badcache.h bit.h byaddr.h \
|
|||
cache.h callbacks.h catz.h cert.h \
|
||||
client.h clientinfo.h compress.h \
|
||||
db.h dbiterator.h dbtable.h diff.h dispatch.h \
|
||||
dlz.h dlz_dlopen.h dns64.h dnssec.h ds.h dsdigest.h \
|
||||
dlz.h dlz_dlopen.h dns64.h dnsrps.h dnssec.h ds.h dsdigest.h \
|
||||
dnstap.h dyndb.h ecs.h \
|
||||
edns.h ecdb.h events.h fixedname.h forward.h geoip.h \
|
||||
ipkeylist.h iptable.h \
|
||||
journal.h keydata.h keyflags.h keytable.h keyvalues.h \
|
||||
lib.h lookup.h log.h master.h masterdump.h message.h \
|
||||
lib.h librpz.h lookup.h log.h master.h masterdump.h message.h \
|
||||
name.h ncache.h nsec.h nsec3.h nta.h opcode.h order.h \
|
||||
peer.h portlist.h private.h \
|
||||
rbt.h rcode.h rdata.h rdataclass.h rdatalist.h \
|
||||
|
|
|
|||
95
lib/dns/include/dns/dnsrps.h
Normal file
95
lib/dns/include/dns/dnsrps.h
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
#ifndef DNS_DNSRPS_H
|
||||
#define DNS_DNSRPS_H
|
||||
|
||||
#include <isc/lang.h>
|
||||
#include <dns/types.h>
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef USE_DNSRPS
|
||||
|
||||
#include <dns/librpz.h>
|
||||
#include <dns/rpz.h>
|
||||
|
||||
/*
|
||||
* Error message if dlopen(librpz) failed.
|
||||
*/
|
||||
extern librpz_emsg_t librpz_lib_open_emsg;
|
||||
|
||||
|
||||
/*
|
||||
* These shim BIND9 database, node, and rdataset are handles on RRs from librpz.
|
||||
*
|
||||
* All of these structures are used by a single thread and so need no locks.
|
||||
*
|
||||
* rpsdb_t holds the state for a set of RPZ queries.
|
||||
*
|
||||
* rpsnode_t is a link to the rpsdb_t for the set of RPZ queries
|
||||
* and a flag saying whether it is pretending to be a node with RRs for
|
||||
* the qname or the node with the SOA for the zone containing the rewritten
|
||||
* RRs or justifying NXDOMAIN.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t unused;
|
||||
} rpsnode_t;
|
||||
typedef struct rpsdb {
|
||||
dns_db_t common;
|
||||
int ref_cnt;
|
||||
librpz_result_id_t hit_id;
|
||||
librpz_result_t result;
|
||||
librpz_rsp_t* rsp;
|
||||
librpz_domain_buf_t origin_buf;
|
||||
const dns_name_t *qname;
|
||||
rpsnode_t origin_node;
|
||||
rpsnode_t data_node;
|
||||
} rpsdb_t;
|
||||
|
||||
|
||||
/*
|
||||
* Convert a dnsrps policy to a classic BIND9 RPZ policy.
|
||||
*/
|
||||
dns_rpz_policy_t dns_dnsrps_2policy(librpz_policy_t rps_policy);
|
||||
|
||||
/*
|
||||
* Convert a dnsrps trigger to a classic BIND9 RPZ rewrite or trigger type.
|
||||
*/
|
||||
dns_rpz_type_t dns_dnsrps_trig2type(librpz_trig_t trig);
|
||||
|
||||
/*
|
||||
* Convert a classic BIND9 RPZ rewrite or trigger type to a librpz trigger type.
|
||||
*/
|
||||
librpz_trig_t dns_dnsrps_type2trig(dns_rpz_type_t type);
|
||||
|
||||
/*
|
||||
* Start dnsrps for the entire server.
|
||||
*/
|
||||
isc_result_t dns_dnsrps_server_create(void);
|
||||
|
||||
/*
|
||||
* Stop dnsrps for the entire server.
|
||||
*/
|
||||
void dns_dnsrps_server_destroy(void);
|
||||
|
||||
/*
|
||||
* Ready dnsrps for a view.
|
||||
*/
|
||||
isc_result_t dns_dnsrps_view_init(dns_rpz_zones_t *new, char *rps_cstr);
|
||||
|
||||
/*
|
||||
* Connect to and start the dnsrps daemon, dnsrpzd.
|
||||
*/
|
||||
isc_result_t dns_dnsrps_connect(dns_rpz_zones_t *rpzs);
|
||||
|
||||
/*
|
||||
* Get ready to try dnsrps rewriting.
|
||||
*/
|
||||
isc_result_t dns_dnsrps_rewrite_init(librpz_emsg_t *emsg, dns_rpz_st_t *st,
|
||||
dns_rpz_zones_t *rpzs,
|
||||
const dns_name_t *qname, isc_mem_t *mctx,
|
||||
isc_boolean_t have_rd);
|
||||
|
||||
#endif /* USE_DNSRPS */
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* DNS_DNSRPS_H */
|
||||
963
lib/dns/include/dns/librpz.h
Normal file
963
lib/dns/include/dns/librpz.h
Normal file
|
|
@ -0,0 +1,963 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Define the interface from a DNS resolver to the Response Policy Zone
|
||||
* library, librpz.
|
||||
*
|
||||
* This file should be included only the interface functions between the
|
||||
* resolver and librpz to avoid name space pollution.
|
||||
*
|
||||
* Copyright (c) 2016-2017 Farsight Security, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* version 1.2.12
|
||||
*/
|
||||
|
||||
#ifndef LIBRPZ_H
|
||||
#define LIBRPZ_H
|
||||
|
||||
#include <arpa/nameser.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
/*
|
||||
* Allow either ordinary or dlopen() linking.
|
||||
*/
|
||||
#ifdef LIBRPZ_INTERNAL
|
||||
#define LIBDEF(t,s) extern t s;
|
||||
#define LIBDEF_F(f) LIBDEF(librpz_##f##_t, librpz_##f)
|
||||
#else
|
||||
#define LIBDEF(t,s)
|
||||
#define LIBDEF_F(f)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Response Policy Zone triggers.
|
||||
* Comparisons of trigger precedences require
|
||||
* LIBRPZ_TRIG_CLIENT_IP < LIBRPZ_TRIG_QNAME < LIBRPZ_TRIG_IP
|
||||
* < LIBRPZ_TRIG_NSDNAME < LIBRPZ_TRIG_NSIP}
|
||||
*/
|
||||
typedef enum {
|
||||
LIBRPZ_TRIG_BAD =0,
|
||||
LIBRPZ_TRIG_CLIENT_IP =1,
|
||||
LIBRPZ_TRIG_QNAME =2,
|
||||
LIBRPZ_TRIG_IP =3,
|
||||
LIBRPZ_TRIG_NSDNAME =4,
|
||||
LIBRPZ_TRIG_NSIP =5
|
||||
} librpz_trig_t;
|
||||
#define LIBRPZ_TRIG_SIZE 3 /* sizeof librpz_trig_t in bits */
|
||||
typedef uint8_t librpz_tbit_t; /* one bit for each of the TRIGS_NUM
|
||||
* trigger types */
|
||||
|
||||
|
||||
/*
|
||||
* Response Policy Zone Actions or policies
|
||||
*/
|
||||
typedef enum {
|
||||
LIBRPZ_POLICY_UNDEFINED =0, /* an empty entry or no decision yet */
|
||||
LIBRPZ_POLICY_DELETED =1, /* placeholder for a deleted policy */
|
||||
|
||||
LIBRPZ_POLICY_PASSTHRU =2, /* 'passthru': do not rewrite */
|
||||
LIBRPZ_POLICY_DROP =3, /* 'drop': do not respond */
|
||||
LIBRPZ_POLICY_TCP_ONLY =4, /* 'tcp-only': answer UDP with TC=1 */
|
||||
LIBRPZ_POLICY_NXDOMAIN =5, /* 'nxdomain': answer with NXDOMAIN */
|
||||
LIBRPZ_POLICY_NODATA =6, /* 'nodata': answer with ANCOUNT=0 */
|
||||
LIBRPZ_POLICY_RECORD =7, /* rewrite with the policy's RR */
|
||||
|
||||
/* only in client configurations to override the zone */
|
||||
LIBRPZ_POLICY_GIVEN, /* 'given': what policy record says */
|
||||
LIBRPZ_POLICY_DISABLED, /* at most log */
|
||||
LIBRPZ_POLICY_CNAME, /* answer with 'cname x' */
|
||||
} librpz_policy_t;
|
||||
#define LIBRPZ_POLICY_BITS 4
|
||||
|
||||
/*
|
||||
* Special policies that appear as targets of CNAMEs
|
||||
* NXDOMAIN is signaled by a CNAME with a "." target.
|
||||
* NODATA is signaled by a CNAME with a "*." target.
|
||||
*/
|
||||
#define LIBRPZ_RPZ_PREFIX "rpz-"
|
||||
#define LIBRPZ_RPZ_PASSTHRU LIBRPZ_RPZ_PREFIX"passthru"
|
||||
#define LIBRPZ_RPZ_DROP LIBRPZ_RPZ_PREFIX"drop"
|
||||
#define LIBRPZ_RPZ_TCP_ONLY LIBRPZ_RPZ_PREFIX"tcp-only"
|
||||
|
||||
|
||||
typedef uint16_t librpz_dznum_t; /* dnsrpzd zone # in [0,DZNUM_MAX] */
|
||||
typedef uint8_t librpz_cznum_t; /* client zone # in [0,CZNUM_MAX] */
|
||||
|
||||
|
||||
/*
|
||||
* CIDR block
|
||||
*/
|
||||
typedef struct librpz_prefix {
|
||||
union {
|
||||
struct in_addr in;
|
||||
struct in6_addr in6;
|
||||
} addr;
|
||||
uint8_t family;
|
||||
uint8_t len;
|
||||
} librpz_prefix_t;
|
||||
|
||||
/*
|
||||
* A domain
|
||||
*/
|
||||
typedef uint8_t librpz_dsize_t;
|
||||
typedef struct librpz_domain {
|
||||
librpz_dsize_t size; /* of only .d */
|
||||
uint8_t d[0]; /* variable length wire format */
|
||||
} librpz_domain_t;
|
||||
|
||||
/*
|
||||
* A maximal domain buffer
|
||||
*/
|
||||
typedef struct librpz_domain_buf {
|
||||
librpz_dsize_t size;
|
||||
uint8_t d[NS_MAXCDNAME];
|
||||
} librpz_domain_buf_t;
|
||||
|
||||
/*
|
||||
* A resource record without the owner name.
|
||||
* C compilers say that sizeof(librpz_rr_t)=12 instead of 10.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t type; /* network byte order */
|
||||
uint16_t class; /* network byte order */
|
||||
uint32_t ttl; /* network byte order */
|
||||
uint16_t rdlength; /* network byte order */
|
||||
uint8_t rdata[0]; /* variable length */
|
||||
} librpz_rr_t;
|
||||
|
||||
/*
|
||||
* The database file might be mapped with different starting addresses
|
||||
* by concurrent clients (resolvers), and so all pointers are offsets.
|
||||
*/
|
||||
typedef uint32_t librpz_idx_t;
|
||||
#define LIBRPZ_IDX_NULL 0
|
||||
#define LIBRPZ_IDX_MIN 1
|
||||
#define LIBRPZ_IDX_BAD ((librpz_idx_t)-1)
|
||||
/**
|
||||
* Partial decoded results of a set of RPZ queries for a single DNS response
|
||||
* or iteration through the mapped file.
|
||||
*/
|
||||
typedef int16_t librpz_result_id_t;
|
||||
typedef struct librpz_result {
|
||||
librpz_idx_t next_rr;
|
||||
librpz_result_id_t hit_id; /* trigger ID from resolver */
|
||||
librpz_policy_t zpolicy; /* policy from zone */
|
||||
librpz_policy_t policy; /* adjusted by client configuration */
|
||||
librpz_dznum_t dznum; /* dnsrpzd zone number */
|
||||
librpz_cznum_t cznum; /* librpz client zone number */
|
||||
librpz_trig_t trig:LIBRPZ_TRIG_SIZE;
|
||||
bool log:1; /* log rewrite given librpz_log_level */
|
||||
} librpz_result_t;
|
||||
|
||||
|
||||
/**
|
||||
* librpz trace or log levels.
|
||||
*/
|
||||
typedef enum {
|
||||
LIBRPZ_LOG_FATAL =0, /* always print fatal errors */
|
||||
LIBRPZ_LOG_ERROR =1, /* errors have this level */
|
||||
LIBRPZ_LOG_TRACE1 =2, /* big events such as dnsrpzd starts */
|
||||
LIBRPZ_LOG_TRACE2 =3, /* smaller dnsrpzd zone transfers */
|
||||
LIBRPZ_LOG_TRACE3 =4, /* librpz hits */
|
||||
LIBRPZ_LOG_TRACE4 =5, /* librpz lookups */
|
||||
LIBRPZ_LOG_INVALID =999,
|
||||
} librpz_log_level_t;
|
||||
typedef librpz_log_level_t (librpz_log_level_val_t)(librpz_log_level_t level);
|
||||
LIBDEF_F(log_level_val)
|
||||
|
||||
/**
|
||||
* Logging function that can be supplied by the resolver.
|
||||
* @param level is one of librpz_log_level_t
|
||||
* @param ctx is for use by the resolver's logging system.
|
||||
* NULL mean a context-free message.
|
||||
*/
|
||||
typedef void(librpz_log_fnc_t)(librpz_log_level_t level, void *ctx,
|
||||
const char *buf);
|
||||
|
||||
/**
|
||||
* Point librpz logging functions to the resolver's choice.
|
||||
*/
|
||||
typedef void (librpz_set_log_t)(librpz_log_fnc_t *new_log, const char *prog_nm);
|
||||
LIBDEF_F(set_log)
|
||||
|
||||
|
||||
/**
|
||||
* librpz error messages are put in these buffers.
|
||||
* Use a structure instead of naked char* to let the compiler check the length.
|
||||
* A function defined with "foo(char buf[120])" can be called with
|
||||
* "char sbuf[2]; foo(sbuf)" and suffer a buffer overrun.
|
||||
*/
|
||||
typedef struct {
|
||||
char c[120];
|
||||
} librpz_emsg_t;
|
||||
|
||||
|
||||
#ifdef LIBRPZ_HAVE_ATTR
|
||||
#define LIBRPZ_UNUSED __attribute__((unused))
|
||||
#define LIBRPZ_PF(f,l) __attribute__((format(printf,f,l)))
|
||||
#define LIBRPZ_NORET __attribute__((__noreturn__))
|
||||
#else
|
||||
#define LIBRPZ_UNUSED
|
||||
#define LIBRPZ_PF(f,l)
|
||||
#define LIBRPZ_NORET
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BUILTIN_EXPECT
|
||||
#define LIBRPZ_LIKELY(c) __builtin_expect(!!(c), 1)
|
||||
#define LIBRPZ_UNLIKELY(c) __builtin_expect(!!(c), 0)
|
||||
#else
|
||||
#define LIBRPZ_LIKELY(c) (c)
|
||||
#define LIBRPZ_UNLIKELY(c) (c)
|
||||
#endif
|
||||
|
||||
typedef bool (librpz_parse_log_opt_t)(librpz_emsg_t *emsg, const char *arg);
|
||||
LIBDEF_F(parse_log_opt)
|
||||
|
||||
typedef void (librpz_vpemsg_t)(librpz_emsg_t *emsg,
|
||||
const char *p, va_list args);
|
||||
LIBDEF_F(vpemsg)
|
||||
typedef void (librpz_pemsg_t)(librpz_emsg_t *emsg,
|
||||
const char *p, ...) LIBRPZ_PF(2,3);
|
||||
LIBDEF_F(pemsg)
|
||||
|
||||
typedef void (librpz_vlog_t)(librpz_log_level_t level, void *ctx,
|
||||
const char *p, va_list args);
|
||||
LIBDEF_F(vlog)
|
||||
typedef void (librpz_log_t)(librpz_log_level_t level, void *ctx,
|
||||
const char *p, ...) LIBRPZ_PF(3,4);
|
||||
LIBDEF_F(log)
|
||||
|
||||
typedef void (librpz_fatal_t)(int ex_code,
|
||||
const char *p, ...) LIBRPZ_PF(2,3);
|
||||
extern void librpz_fatal(int ex_code,
|
||||
const char *p, ...) LIBRPZ_PF(2,3) LIBRPZ_NORET;
|
||||
|
||||
typedef void (librpz_rpz_assert_t)(const char *file, unsigned line,
|
||||
const char *p, ...) LIBRPZ_PF(3,4);
|
||||
extern void librpz_rpz_assert(const char *file, unsigned line,
|
||||
const char *p, ...) LIBRPZ_PF(3,4) LIBRPZ_NORET;
|
||||
|
||||
typedef void (librpz_rpz_vassert_t)(const char *file, uint line,
|
||||
const char *p, va_list args);
|
||||
extern void librpz_rpz_vassert(const char *file, uint line,
|
||||
const char *p, va_list args) LIBRPZ_NORET;
|
||||
|
||||
|
||||
/*
|
||||
* As far as clients are concerned, all relative pointers or indexes in a
|
||||
* version of the mapped file except trie node parent pointers remain valid
|
||||
* forever. A client must release a version so that it can be garbage
|
||||
* collected by the file system. When dnsrpzd needs to expand the file,
|
||||
* it copies the old file to a new, larger file. Clients can continue
|
||||
* using the old file.
|
||||
*
|
||||
* Versions can also appear in a single file. Old nodes and trie values
|
||||
* within the file are not destroyed until all clients using the version
|
||||
* that contained the old values release the version.
|
||||
*
|
||||
* A client is marked as using version by connecting to the daemon. It is
|
||||
* marked as using all subsequent versions. A client releases all versions
|
||||
* by closing the connection or a range of versions by updating is slot
|
||||
* in the shared memory version table.
|
||||
*
|
||||
* As far as clients are concerned, there are the following possible librpz
|
||||
* failures:
|
||||
* - malloc() or other fatal internal librpz problems indicated by
|
||||
* a failing return from a librpz function
|
||||
* All operations will fail until client handle is destroyed and
|
||||
* recreated with librpz_client_detach() and librpz_client_create().
|
||||
* - corrupt database detected by librpz code, corrupt database detected
|
||||
* by dnsrpzd, or disconnection from the daemon.
|
||||
* Current operations will fail.
|
||||
*
|
||||
* Clients assume that the file has already been unlinked before
|
||||
* the corrupt flag is set so that they do not race with the server
|
||||
* over the corruption of a single file. A client that finds the
|
||||
* corrupt set knows that dnsrpzd has already crashed with
|
||||
* abort() and is restarting. The client can re-connect to dnsrpzd
|
||||
* and retransmit its configuration, backing off as usual if anything
|
||||
* goes wrong.
|
||||
*
|
||||
* Searches of the database by a client do not need locks against dnsrpzd or
|
||||
* other clients, but a lock is used to protect changes to the connection
|
||||
* by competing threads in the client. The client provides functions
|
||||
* to serialize the concurrent use of any single client handle.
|
||||
* Functions that do nothing are appropriate for applications that are
|
||||
* not "threaded" or that do not share client handles among threads.
|
||||
* Otherwise, functions must be provided to librpz_clientcreate().
|
||||
* Something like the following works with pthreads:
|
||||
*
|
||||
* static void
|
||||
* lock(void *mutex) { assert(pthread_mutex_lock(mutex) == 0); }
|
||||
*
|
||||
* static void
|
||||
* unlock(void *mutex) { assert(pthread_mutex_unlock(mutex) == 0); }
|
||||
*
|
||||
* static void
|
||||
* mutex_destroy(void *mutex) { assert(pthread_mutex_destroy(mutex) == 0); }
|
||||
*
|
||||
*
|
||||
*
|
||||
* At every instant, all of the data and pointers in the mapped file are valid.
|
||||
* Changes to trie node or other data are always made so that it and
|
||||
* all pointers in and to it remain valid for a time. Old versions are
|
||||
* eventually discarded.
|
||||
*
|
||||
* Dnsrpzd periodically defines a new version by setting aside all changes
|
||||
* made since the previous version was defined. Subsequent changes
|
||||
* made (only!) by dnsrpzd will be part of the next version.
|
||||
*
|
||||
* To discard an old version, dnsrpzd must know that all clients have stopped
|
||||
* using that version. Clients do that by using part of the mapped file
|
||||
* to tell dnsrpzd the oldest version that each client is using.
|
||||
* Dnsrpzd assigns each connecting client an entry in the cversions array
|
||||
* in the mapped file. The client puts version numbers into that entry
|
||||
* to signal to dnsrpzd which versions that can be discarded.
|
||||
* Dnsrpzd is free, as far as that client is concerned, to discard all
|
||||
* numerically smaller versions. A client can disclaim all versions with
|
||||
* the version number VERSIONS_ALL or 0.
|
||||
*
|
||||
* The race between a client changing its entry and dnsrpzd discarding a
|
||||
* version is resolved by allowing dnsrpzd to discard all versions
|
||||
* smaller or equal to the client's version number. If dnsrpzd is in
|
||||
* the midst of discarding or about to discard version N when the
|
||||
* client asserts N, no harm is done. The client depends only on
|
||||
* the consistency of version N+1.
|
||||
*
|
||||
* This version mechanism depends in part on not being exercised too frequently
|
||||
* Version numbers are 32 bits long and dnsrpzd creates new versions
|
||||
* at most once every 30 seconds.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Lock functions for concurrent use of a single librpz_client_t client handle.
|
||||
*/
|
||||
typedef void(librpz_mutex_t)(void *mutex);
|
||||
|
||||
/*
|
||||
* List of connections to dnsrpzd daemons.
|
||||
*/
|
||||
typedef struct librpz_clist librpz_clist_t;
|
||||
|
||||
/*
|
||||
* Client's handle on dnsrpzd.
|
||||
*/
|
||||
typedef struct librpz_client librpz_client_t;
|
||||
|
||||
/**
|
||||
* Create the list of connections to the dnsrpzd daemon.
|
||||
* @param[out] emsg: error message
|
||||
* @param lock: start exclusive access to the client handle
|
||||
* @param unlock: end exclusive access to the client handle
|
||||
* @param mutex_destroy: release the lock
|
||||
* @param mutex: pointer to the lock for the client handle
|
||||
* @param log_ctx: NULL or resolver's context log messages
|
||||
*/
|
||||
typedef librpz_clist_t *(librpz_clist_create_t)(librpz_emsg_t *emsg,
|
||||
librpz_mutex_t *lock,
|
||||
librpz_mutex_t *unlock,
|
||||
librpz_mutex_t *mutex_destroy,
|
||||
void *mutex, void *log_ctx);
|
||||
LIBDEF_F(clist_create)
|
||||
|
||||
|
||||
/**
|
||||
* Release the list of dnsrpzd connections.
|
||||
*/
|
||||
typedef void (librpz_clist_detach_t)(librpz_clist_t **clistp);
|
||||
LIBDEF_F(clist_detach)
|
||||
|
||||
/**
|
||||
* Create a librpz client handle.
|
||||
* @param[out] emsg: error message
|
||||
* @param: list of dnsrpzd connections
|
||||
* @param cstr: string of configuration settings separated by ';' or '\n'
|
||||
* @param use_expired: true to not ignore expired zones
|
||||
* @return client handle or NULL if the handle could not be created
|
||||
*/
|
||||
typedef librpz_client_t *(librpz_client_create_t)(librpz_emsg_t *emsg,
|
||||
librpz_clist_t *clist,
|
||||
const char *cstr,
|
||||
bool use_expired);
|
||||
LIBDEF_F(client_create)
|
||||
|
||||
/**
|
||||
* Start (if necessary) dnsrpzd and connect to it.
|
||||
* @param[out] emsg: error message
|
||||
* @param client handle
|
||||
* @param optional: true if it is ok if starting the daemon is not allowed
|
||||
*/
|
||||
typedef bool (librpz_connect_t)(librpz_emsg_t *emsg, librpz_client_t *client,
|
||||
bool optional);
|
||||
LIBDEF_F(connect)
|
||||
|
||||
/**
|
||||
* Start to destroy a librpz client handle.
|
||||
* It will not be destroyed until the last set of RPZ queries represented
|
||||
* by a librpz_rsp_t ends.
|
||||
* @param client handle to be released
|
||||
* @return false on error
|
||||
*/
|
||||
typedef void (librpz_client_detach_t)(librpz_client_t **clientp);
|
||||
LIBDEF_F(client_detach)
|
||||
|
||||
/**
|
||||
* State for a set of RPZ queries for a single DNS response
|
||||
* or for listing the database.
|
||||
*/
|
||||
typedef struct librpz_rsp librpz_rsp_t;
|
||||
|
||||
/**
|
||||
* Start a set of RPZ queries for a single DNS response.
|
||||
* @param[out] emsg: error message for false return or *rspp=NULL
|
||||
* @param[out] rspp created context or NULL
|
||||
* @param[out] min_ns_dotsp: NULL or pointer to configured MIN-NS-DOTS value
|
||||
* @param client state
|
||||
* @param have_rd: RD=1 in the DNS request
|
||||
* @param have_do: DO=1 in the DNS request
|
||||
* @return false on error
|
||||
*/
|
||||
typedef bool (librpz_rsp_create_t)(librpz_emsg_t *emsg, librpz_rsp_t **rspp,
|
||||
int *min_ns_dotsp, librpz_client_t *client,
|
||||
bool have_rd, bool have_do);
|
||||
LIBDEF_F(rsp_create)
|
||||
|
||||
/**
|
||||
* Finish RPZ work for a DNS response.
|
||||
*/
|
||||
typedef void (librpz_rsp_detach_t)(librpz_rsp_t **rspp);
|
||||
LIBDEF_F(rsp_detach)
|
||||
|
||||
/**
|
||||
* Get the final, accumulated result of a set of RPZ queries.
|
||||
* Yield LIBRPZ_POLICY_UNDEFINED if
|
||||
* - there were no hits,
|
||||
* - there was a dispositive hit, be we have not recursed and are required
|
||||
* to recurse so that evil DNS authorities will not know we are using RPZ
|
||||
* - we have a hit and have recursed, but later data such as NSIP could
|
||||
* override
|
||||
* @param[out] emsg
|
||||
* @param[out] result describes the hit
|
||||
* or result->policy=LIBRPZ_POLICY_UNDEFINED without a hit
|
||||
* @param[out] result: current policy rewrite values
|
||||
* @param recursed: recursion has now been done even if it was not done
|
||||
* when the hit was found
|
||||
* @param[in,out] rsp state from librpz_itr_start()
|
||||
* @return false on error
|
||||
*/
|
||||
typedef bool (librpz_rsp_result_t)(librpz_emsg_t *emsg, librpz_result_t *result,
|
||||
bool recursed, const librpz_rsp_t *rsp);
|
||||
LIBDEF_F(rsp_result)
|
||||
|
||||
/**
|
||||
* Might looking for a trigger be worthwhile?
|
||||
* @param trig: look for this type of trigger
|
||||
* @param ipv6: true if trig is LIBRPZ_TRIG_CLIENT_IP, LIBRPZ_TRIG_IP,
|
||||
* or LIBRPZ_TRIG_NSIP and the IP address is IPv6
|
||||
* @return: true if looking could be worthwhile
|
||||
*/
|
||||
typedef bool (librpz_have_trig_t)(librpz_trig_t trig, bool ipv6,
|
||||
const librpz_rsp_t *rsp);
|
||||
LIBDEF_F(have_trig)
|
||||
|
||||
/**
|
||||
* Might looking for NSDNAME and NSIP triggers be worthwhile?
|
||||
* @return: true if looking could be worthwhile
|
||||
*/
|
||||
typedef bool (librpz_have_ns_trig_t)(const librpz_rsp_t *rsp);
|
||||
LIBDEF_F(have_ns_trig)
|
||||
|
||||
/**
|
||||
* Convert the found client IP trie key to a CIDR block
|
||||
* @param[out] emsg
|
||||
* @param[out] prefix trigger
|
||||
* @param[in,out] rsp state from librpz_itr_start()
|
||||
* @return false on error
|
||||
*/
|
||||
typedef bool (librpz_rsp_clientip_prefix_t)(librpz_emsg_t *emsg,
|
||||
librpz_prefix_t *prefix,
|
||||
librpz_rsp_t *rsp);
|
||||
LIBDEF_F(rsp_clientip_prefix)
|
||||
|
||||
/**
|
||||
* Compute the owner name of the found or result trie key, usually to log it.
|
||||
* An IP address key might be returned as 8.0.0.0.127.rpz-client-ip.
|
||||
* example.com. might be a qname trigger. example.com.rpz-nsdname. could
|
||||
* be an NSDNAME trigger.
|
||||
* @param[out] emsg
|
||||
* @param[out] owner domain
|
||||
* @param[in,out] rsp state from librpz_itr_start()
|
||||
* @return false on error
|
||||
*/
|
||||
typedef bool (librpz_rsp_domain_t)(librpz_emsg_t *emsg,
|
||||
librpz_domain_buf_t *owner,
|
||||
librpz_rsp_t *rsp);
|
||||
LIBDEF_F(rsp_domain)
|
||||
|
||||
/**
|
||||
* Get the next RR of the LIBRPZ_POLICY_RECORD result after an initial use of
|
||||
* librpz_rsp_result() or librpz_itr_node() or after a previous use of
|
||||
* librpz_rsp_rr(). The RR is in uncompressed wire format including type,
|
||||
* class, ttl and length in network byte order.
|
||||
* @param[out] emsg
|
||||
* @param[out] typep: optional host byte order record type or ns_t_invalid (0)
|
||||
* @param[out] classp: class such as ns_c_in
|
||||
* @param[out] ttlp: TTL
|
||||
* @param[out] rrp: optional malloc() buffer containing the next RR or
|
||||
* NULL after the last RR
|
||||
* @param[out] result: current policy rewrite values
|
||||
* @param qname: used construct a wildcard CNAME
|
||||
* @param qname_size
|
||||
* @param[in,out] rsp state from librpz_itr_start()
|
||||
* @return false on error
|
||||
*/
|
||||
typedef bool (librpz_rsp_rr_t)(librpz_emsg_t *emsg, uint16_t *typep,
|
||||
uint16_t *classp, uint32_t *ttlp,
|
||||
librpz_rr_t **rrp, librpz_result_t *result,
|
||||
const uint8_t *qname, size_t qname_size,
|
||||
librpz_rsp_t *rsp);
|
||||
LIBDEF_F(rsp_rr)
|
||||
|
||||
/**
|
||||
* Get the next RR of the LIBRPZ_POLICY_RECORD result.
|
||||
* @param[out] emsg
|
||||
* @param[out] ttlp: TTL
|
||||
* @param[out] rrp: malloc() buffer with SOA RR without owner name
|
||||
* @param[out] result: current policy rewrite values
|
||||
* @param[out] origin: SOA owner name
|
||||
* @param[out] origin_size
|
||||
* @param[in,out] rsp state from librpz_itr_start()
|
||||
* @return false on error
|
||||
*/
|
||||
typedef bool (librpz_rsp_soa_t)(librpz_emsg_t *emsg, uint32_t *ttlp,
|
||||
librpz_rr_t **rrp, librpz_domain_buf_t *origin,
|
||||
librpz_result_t *result, librpz_rsp_t *rsp);
|
||||
LIBDEF_F(rsp_soa)
|
||||
|
||||
/**
|
||||
* Get the SOA serial number for a policy zone to compare with a known value
|
||||
* to check whether a zone transfer is complete.
|
||||
*/
|
||||
typedef bool (librpz_soa_serial_t)(librpz_emsg_t *emsg, uint32_t *serialp,
|
||||
const char *domain_nm, librpz_rsp_t *rsp);
|
||||
LIBDEF_F(soa_serial)
|
||||
|
||||
/**
|
||||
* Save the current policy checking state.
|
||||
* @param[out] emsg
|
||||
* @param[in,out] rsp state from librpz_itr_start()
|
||||
* @return false on error
|
||||
*/
|
||||
typedef bool (librpz_rsp_push_t)(librpz_emsg_t *emsg, librpz_rsp_t *rsp);
|
||||
LIBDEF_F(rsp_push)
|
||||
#define LIBRPZ_RSP_STACK_DEPTH 3
|
||||
|
||||
/**
|
||||
* Restore the previous policy checking state.
|
||||
* @param[out] emsg
|
||||
* @param[out] result: NULL or restored policy rewrite values
|
||||
* @param[in,out] rsp state from librpz_itr_start()
|
||||
* @return false on error
|
||||
*/
|
||||
typedef bool (librpz_rsp_pop_t)(librpz_emsg_t *emsg, librpz_result_t *result,
|
||||
librpz_rsp_t *rsp);
|
||||
LIBDEF_F(rsp_pop)
|
||||
|
||||
/**
|
||||
* Discard the most recently save policy checking state.
|
||||
* @param[out] emsg
|
||||
* @param[out] result: NULL or restored policy rewrite values
|
||||
* @return false on error
|
||||
*/
|
||||
typedef bool (librpz_rsp_pop_discard_t)(librpz_emsg_t *emsg, librpz_rsp_t *rsp);
|
||||
LIBDEF_F(rsp_pop_discard)
|
||||
|
||||
/**
|
||||
* Disable a zone.
|
||||
* @param[out] emsg
|
||||
* @param znum
|
||||
* @param[in,out] rsp state from librpz_itr_start()
|
||||
* @return false on error
|
||||
*/
|
||||
typedef bool (librpz_rsp_forget_zone_t)(librpz_emsg_t *emsg,
|
||||
librpz_cznum_t znum, librpz_rsp_t *rsp);
|
||||
LIBDEF_F(rsp_forget_zone)
|
||||
|
||||
/**
|
||||
* Apply RPZ to an IP address.
|
||||
* @param[out] emsg
|
||||
* @param addr: address to check
|
||||
* @param ipv6: true for 16 byte IPv6 instead of 4 byte IPv4
|
||||
* @param trig LIBRPZ_TRIG_CLIENT_IP, LIBRPZ_TRIG_IP, or LIBRPZ_TRIG_NSIP
|
||||
* @param hit_id: caller chosen
|
||||
* @param recursed: recursion has been done
|
||||
* @param[in,out] rsp state from librpz_itr_start()
|
||||
* @return false on error
|
||||
*/
|
||||
typedef bool (librpz_ck_ip_t)(librpz_emsg_t *emsg,
|
||||
const void *addr, uint family,
|
||||
librpz_trig_t trig, librpz_result_id_t hit_id,
|
||||
bool recursed, librpz_rsp_t *rsp);
|
||||
LIBDEF_F(ck_ip)
|
||||
|
||||
/**
|
||||
* Apply RPZ to a wire-format domain.
|
||||
* @param[out] emsg
|
||||
* @param domain in wire format
|
||||
* @param domain_size
|
||||
* @param trig LIBRPZ_TRIG_QNAME or LIBRPZ_TRIG_NSDNAME
|
||||
* @param hit_id: caller chosen
|
||||
* @param recursed: recursion has been done
|
||||
* @param[in,out] rsp state from librpz_itr_start()
|
||||
* @return false on error
|
||||
*/
|
||||
typedef bool (librpz_ck_domain_t)(librpz_emsg_t *emsg,
|
||||
const uint8_t *domain, size_t domain_size,
|
||||
librpz_trig_t trig, librpz_result_id_t hit_id,
|
||||
bool recursed, librpz_rsp_t *rsp);
|
||||
LIBDEF_F(ck_domain)
|
||||
|
||||
/**
|
||||
* Ask dnsrpzd to refresh a zone.
|
||||
* @param[out] emsg error message
|
||||
* @param librpz_domain_t domain to refresh
|
||||
* @param client context
|
||||
* @return false after error
|
||||
*/
|
||||
typedef bool (librpz_zone_refresh_t)(librpz_emsg_t *emsg, const char *domain,
|
||||
librpz_rsp_t *rsp);
|
||||
LIBDEF_F(zone_refresh)
|
||||
|
||||
/**
|
||||
* Get a string describing the database
|
||||
* @param license: include the license
|
||||
* @param cfiles: include the configuration file names
|
||||
* @param listens: include the local notify IP addresses
|
||||
* @param[out] emsg error message if the result is null
|
||||
* @param client context
|
||||
* @return malloc'ed string or NULL after error
|
||||
*/
|
||||
typedef char *(librpz_db_info_t)(librpz_emsg_t *emsg,
|
||||
bool license, bool cfiles, bool listens,
|
||||
librpz_rsp_t *rsp);
|
||||
LIBDEF_F(db_info)
|
||||
|
||||
/**
|
||||
* Start a context for listing the nodes and/or zones in the mapped file
|
||||
* @param[out] emsg: error message for false return or *rspp=NULL
|
||||
* @param[out[ rspp created context or NULL
|
||||
* @param client context
|
||||
* @return false after error
|
||||
*/
|
||||
typedef bool (librpz_itr_start_t)(librpz_emsg_t *emsg, librpz_rsp_t **rspp,
|
||||
librpz_client_t *client);
|
||||
LIBDEF_F(itr_start)
|
||||
|
||||
/**
|
||||
* Get mapped file memory allocation statistics.
|
||||
* @param[out] emsg: error message
|
||||
* @param rsp state from librpz_itr_start()
|
||||
* @return malloc'ed string or NULL after error
|
||||
*/
|
||||
typedef char *(librpz_mf_stats_t)(librpz_emsg_t *emsg, librpz_rsp_t *rsp);
|
||||
LIBDEF_F(mf_stats)
|
||||
|
||||
/**
|
||||
* Get versions currently used by clients.
|
||||
* @param[out] emsg: error message
|
||||
* @param[in,out] rsp: state from librpz_itr_start()
|
||||
* @return malloc'ed string or NULL after error
|
||||
*/
|
||||
typedef char *(librpz_vers_stats_t)(librpz_emsg_t *emsg, librpz_rsp_t *rsp);
|
||||
LIBDEF_F(vers_stats)
|
||||
|
||||
/**
|
||||
* Allocate a string describing the next zone or "" after the last zone.
|
||||
* @param[out] emsg
|
||||
* @param all_zones to list all instead of only requested zones
|
||||
* @param[in,out] rsp state from librpz_rsp_start()
|
||||
* @return malloc'ed string or NULL after error
|
||||
*/
|
||||
typedef char *(librpz_itr_zone_t)(librpz_emsg_t *emsg, bool all_zones,
|
||||
librpz_rsp_t *rsp);
|
||||
LIBDEF_F(itr_zone)
|
||||
|
||||
/**
|
||||
* Describe the next trie node while dumping the database.
|
||||
* @param[out] emsg
|
||||
* @param[out] result describes node
|
||||
* or result->policy=LIBRPZ_POLICY_UNDEFINED after the last node.
|
||||
* @param all_zones to list all instead of only requested zones
|
||||
* @param[in,out] rsp state from librpz_itr_start()
|
||||
* @return: false on error
|
||||
*/
|
||||
typedef bool (librpz_itr_node_t)(librpz_emsg_t *emsg, librpz_result_t *result,
|
||||
bool all_zones, librpz_rsp_t *rsp);
|
||||
LIBDEF_F(itr_node)
|
||||
|
||||
/**
|
||||
* RPZ policy to string with a backup buffer of POLICY2STR_SIZE size
|
||||
*/
|
||||
typedef const char *(librpz_policy2str_t)(librpz_policy_t policy,
|
||||
char *buf, size_t buf_size);
|
||||
#define POLICY2STR_SIZE sizeof("policy xxxxxx")
|
||||
LIBDEF_F(policy2str)
|
||||
|
||||
/**
|
||||
* Trigger type to string.
|
||||
*/
|
||||
typedef const char *(librpz_trig2str_t)(librpz_trig_t trig);
|
||||
LIBDEF_F(trig2str)
|
||||
|
||||
/**
|
||||
* Convert a number of seconds to a zone file duration string
|
||||
*/
|
||||
typedef const char *(librpz_secs2str_t)(time_t secs,
|
||||
char *buf, size_t buf_size);
|
||||
#define SECS2STR_SIZE sizeof("1234567w7d24h59m59s")
|
||||
LIBDEF_F(secs2str)
|
||||
|
||||
/**
|
||||
* Parse a duration with 's', 'm', 'h', 'd', and 'w' units.
|
||||
*/
|
||||
typedef bool (librpz_str2secs_t)(librpz_emsg_t *emsg, time_t *val,
|
||||
const char *str0);
|
||||
LIBDEF_F(str2secs)
|
||||
|
||||
/**
|
||||
* Translate selected rtypes to strings
|
||||
*/
|
||||
typedef const char *(librpz_rtype2str_t)(uint type, char *buf, size_t buf_size);
|
||||
#define RTYPE2STR_SIZE sizeof("type xxxxx")
|
||||
LIBDEF_F(rtype2str)
|
||||
|
||||
/**
|
||||
* Local version of ns_name_ntop() for portability.
|
||||
*/
|
||||
typedef int (librpz_domain_ntop_t)(const u_char *src, char *dst, size_t dstsiz);
|
||||
LIBDEF_F(domain_ntop)
|
||||
|
||||
/**
|
||||
* Local version of ns_name_pton().
|
||||
*/
|
||||
typedef int (librpz_domain_pton2_t)(const char *src, u_char *dst, size_t dstsiz,
|
||||
size_t *dstlen, bool lower);
|
||||
LIBDEF_F(domain_pton2)
|
||||
|
||||
typedef union socku socku_t;
|
||||
typedef socku_t *(librpz_mk_inet_su_t)(socku_t *su, const struct in_addr *addrp,
|
||||
in_port_t port);
|
||||
LIBDEF_F(mk_inet_su)
|
||||
|
||||
typedef socku_t *(librpz_mk_inet6_su_t)(socku_t *su, const
|
||||
struct in6_addr *addrp,
|
||||
uint32_t scope_id, in_port_t port);
|
||||
LIBDEF_F(mk_inet6_su)
|
||||
|
||||
typedef bool (librpz_str2su_t)(socku_t *sup, const char *str);
|
||||
LIBDEF_F(str2su)
|
||||
|
||||
typedef char *(librpz_su2str_t)(char *str, size_t str_len, const socku_t *su);
|
||||
LIBDEF_F(su2str)
|
||||
#define SU2STR_SIZE (INET6_ADDRSTRLEN+1+6+1)
|
||||
|
||||
|
||||
/**
|
||||
* default path to dnsrpzd
|
||||
*/
|
||||
const char *librpz_dnsrpzd_path;
|
||||
|
||||
|
||||
#undef LIBDEF
|
||||
|
||||
/*
|
||||
* This is the dlopen() interface to librpz.
|
||||
*/
|
||||
typedef const struct {
|
||||
const char *dnsrpzd_path;
|
||||
const char *version;
|
||||
librpz_parse_log_opt_t *parse_log_opt;
|
||||
librpz_log_level_val_t *log_level_val;
|
||||
librpz_set_log_t *set_log;
|
||||
librpz_vpemsg_t *vpemsg;
|
||||
librpz_pemsg_t *pemsg;
|
||||
librpz_vlog_t *vlog;
|
||||
librpz_log_t *log;
|
||||
librpz_fatal_t *fatal LIBRPZ_NORET;
|
||||
librpz_rpz_assert_t *rpz_assert LIBRPZ_NORET;
|
||||
librpz_rpz_vassert_t *rpz_vassert LIBRPZ_NORET;
|
||||
librpz_clist_create_t *clist_create;
|
||||
librpz_clist_detach_t *clist_detach;
|
||||
librpz_client_create_t *client_create;
|
||||
librpz_connect_t *connect;
|
||||
librpz_client_detach_t *client_detach;
|
||||
librpz_rsp_create_t *rsp_create;
|
||||
librpz_rsp_detach_t *rsp_detach;
|
||||
librpz_rsp_result_t *rsp_result;
|
||||
librpz_have_trig_t *have_trig;
|
||||
librpz_have_ns_trig_t *have_ns_trig;
|
||||
librpz_rsp_clientip_prefix_t *rsp_clientip_prefix;
|
||||
librpz_rsp_domain_t *rsp_domain;
|
||||
librpz_rsp_rr_t *rsp_rr;
|
||||
librpz_rsp_soa_t *rsp_soa;
|
||||
librpz_soa_serial_t *soa_serial;
|
||||
librpz_rsp_push_t *rsp_push;
|
||||
librpz_rsp_pop_t *rsp_pop;
|
||||
librpz_rsp_pop_discard_t *rsp_pop_discard;
|
||||
librpz_rsp_forget_zone_t *rsp_forget_zone;
|
||||
librpz_ck_ip_t *ck_ip;
|
||||
librpz_ck_domain_t *ck_domain;
|
||||
librpz_zone_refresh_t *zone_refresh;
|
||||
librpz_db_info_t *db_info;
|
||||
librpz_itr_start_t *itr_start;
|
||||
librpz_mf_stats_t *mf_stats;
|
||||
librpz_vers_stats_t *vers_stats;
|
||||
librpz_itr_zone_t *itr_zone;
|
||||
librpz_itr_node_t *itr_node;
|
||||
librpz_policy2str_t *policy2str;
|
||||
librpz_trig2str_t *trig2str;
|
||||
librpz_secs2str_t *secs2str;
|
||||
librpz_str2secs_t *str2secs;
|
||||
librpz_rtype2str_t *rtype2str;
|
||||
librpz_domain_ntop_t *domain_ntop;
|
||||
librpz_domain_pton2_t *domain_pton2;
|
||||
librpz_mk_inet_su_t *mk_inet_su;
|
||||
librpz_mk_inet6_su_t *mk_inet6_su;
|
||||
librpz_str2su_t *str2su;
|
||||
librpz_su2str_t *su2str;
|
||||
} librpz_0_t;
|
||||
extern librpz_0_t librpz_def_0;
|
||||
|
||||
/*
|
||||
* Future versions can be upward compatible by defining LIBRPZ_DEF as
|
||||
* librpz_X_t.
|
||||
*/
|
||||
#define LIBRPZ_DEF librpz_def_0
|
||||
#define LIBRPZ_DEF_STR "librpz_def_0"
|
||||
|
||||
typedef librpz_0_t librpz_t;
|
||||
extern librpz_t *librpz;
|
||||
|
||||
|
||||
#if LIBRPZ_LIB_OPEN == 2
|
||||
#include <dlfcn.h>
|
||||
|
||||
/**
|
||||
* link-load librpz
|
||||
* @param[out] emsg: error message
|
||||
* @param[in,out] dl_handle: NULL or pointer to new dlopen handle
|
||||
* @param[in] path: librpz.so path
|
||||
* @return address of interface structure or NULL on failure
|
||||
*/
|
||||
static inline librpz_t *
|
||||
librpz_lib_open(librpz_emsg_t *emsg, void **dl_handle, const char *path)
|
||||
{
|
||||
void *handle;
|
||||
librpz_t *new_librpz;
|
||||
|
||||
emsg->c[0] = '\0';
|
||||
|
||||
/*
|
||||
* Close a previously opened handle on librpz.so.
|
||||
*/
|
||||
if (dl_handle != NULL && *dl_handle != NULL) {
|
||||
if (dlclose(*dl_handle) != 0) {
|
||||
snprintf(emsg->c, sizeof(librpz_emsg_t),
|
||||
"dlopen(NULL): %s", dlerror());
|
||||
return (NULL);
|
||||
}
|
||||
*dl_handle = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* First try the main executable of the process in case it was
|
||||
* linked to librpz.
|
||||
* Do not worry if we cannot search the main executable of the process.
|
||||
*/
|
||||
handle = dlopen(NULL, RTLD_NOW | RTLD_LOCAL);
|
||||
if (handle != NULL) {
|
||||
new_librpz = dlsym(handle, LIBRPZ_DEF_STR);
|
||||
if (new_librpz != NULL) {
|
||||
if (dl_handle != NULL)
|
||||
*dl_handle = handle;
|
||||
return (new_librpz);
|
||||
}
|
||||
if (dlclose(handle) != 0) {
|
||||
snprintf(emsg->c, sizeof(librpz_emsg_t),
|
||||
"dlsym(NULL, "LIBRPZ_DEF_STR"): %s",
|
||||
dlerror());
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (path == NULL || path[0] == '\0') {
|
||||
snprintf(emsg->c, sizeof(librpz_emsg_t),
|
||||
"librpz not linked and no dlopen() path provided");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
handle = dlopen(path, RTLD_NOW | RTLD_LOCAL);
|
||||
if (handle == NULL) {
|
||||
snprintf(emsg->c, sizeof(librpz_emsg_t), "dlopen(%s): %s",
|
||||
path, dlerror());
|
||||
return (NULL);
|
||||
}
|
||||
new_librpz = dlsym(handle, LIBRPZ_DEF_STR);
|
||||
if (new_librpz != NULL) {
|
||||
if (dl_handle != NULL)
|
||||
*dl_handle = handle;
|
||||
return (new_librpz);
|
||||
}
|
||||
snprintf(emsg->c, sizeof(librpz_emsg_t),
|
||||
"dlsym(%s, "LIBRPZ_DEF_STR"): %s",
|
||||
path, dlerror());
|
||||
dlclose(handle);
|
||||
return (NULL);
|
||||
}
|
||||
#elif defined(LIBRPZ_LIB_OPEN)
|
||||
/*
|
||||
* Statically link to the librpz.so DSO on systems without dlopen()
|
||||
*/
|
||||
static inline librpz_t *
|
||||
librpz_lib_open(librpz_emsg_t *emsg, void **dl_handle, const char *path)
|
||||
{
|
||||
(void)(path);
|
||||
|
||||
if (dl_handle != NULL)
|
||||
*dl_handle = NULL;
|
||||
|
||||
#if LIBRPZ_LIB_OPEN == 1
|
||||
emsg->c[0] = '\0';
|
||||
return (&LIBRPZ_DEF);
|
||||
#else
|
||||
snprintf(emsg->c, sizeof(librpz_emsg_t),
|
||||
"librpz not available via ./configure");
|
||||
return (NULL);
|
||||
#endif /* LIBRPZ_LIB_OPEN */
|
||||
}
|
||||
#endif /* LIBRPZ_LIB_OPEN */
|
||||
|
||||
#endif /* LIBRPZ_H */
|
||||
|
|
@ -6,8 +6,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
|
||||
#ifndef DNS_RPZ_H
|
||||
#define DNS_RPZ_H 1
|
||||
|
|
@ -187,6 +185,9 @@ typedef struct dns_rpz_popt dns_rpz_popt_t;
|
|||
struct dns_rpz_popt {
|
||||
dns_rpz_zbits_t no_rd_ok;
|
||||
dns_rpz_zbits_t no_log;
|
||||
dns_rpz_zbits_t nsip_on;
|
||||
dns_rpz_zbits_t nsdname_on;
|
||||
isc_boolean_t dnsrps_enabled;
|
||||
isc_boolean_t break_dnssec;
|
||||
isc_boolean_t qname_wait_recurse;
|
||||
isc_boolean_t nsip_wait_recurse;
|
||||
|
|
@ -203,8 +204,9 @@ struct dns_rpz_zones {
|
|||
dns_rpz_triggers_t triggers[DNS_RPZ_MAX_ZONES];
|
||||
|
||||
/*
|
||||
* RPZ policy version number (initially 0, increases whenever
|
||||
* the server is reconfigured with new zones or policy)
|
||||
* RPZ policy version number.
|
||||
* It is initially 0 and it increases whenever the server is
|
||||
* reconfigured with new zones or policy.
|
||||
*/
|
||||
int rpz_ver;
|
||||
|
||||
|
|
@ -250,6 +252,13 @@ struct dns_rpz_zones {
|
|||
|
||||
dns_rpz_cidr_node_t *cidr;
|
||||
dns_rbt_t *rbt;
|
||||
|
||||
/*
|
||||
* DNSRPZ librpz configuration string and handle on librpz connection
|
||||
*/
|
||||
char *rps_cstr;
|
||||
size_t rps_cstr_size;
|
||||
struct librpz_client *rps_client;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -319,6 +328,11 @@ typedef struct {
|
|||
dns_rpz_popt_t popt;
|
||||
int rpz_ver;
|
||||
|
||||
/*
|
||||
* Shim db between BIND and DNRPS librpz.
|
||||
*/
|
||||
dns_db_t *rpsdb;
|
||||
|
||||
/*
|
||||
* p_name: current policy owner name
|
||||
* r_name: recursing for this name to possible policy triggers
|
||||
|
|
@ -360,7 +374,8 @@ dns_rpz_decode_cname(dns_rpz_zone_t *rpz, dns_rdataset_t *rdataset,
|
|||
dns_name_t *selfname);
|
||||
|
||||
isc_result_t
|
||||
dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, isc_mem_t *mctx,
|
||||
dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, char *rps_cstr,
|
||||
size_t rps_cstr_size, isc_mem_t *mctx,
|
||||
isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr);
|
||||
|
||||
isc_result_t
|
||||
|
|
|
|||
212
lib/dns/rpz.c
212
lib/dns/rpz.c
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <dns/db.h>
|
||||
#include <dns/dbiterator.h>
|
||||
#include <dns/dnsrps.h>
|
||||
#include <dns/events.h>
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/log.h>
|
||||
|
|
@ -397,11 +398,10 @@ fix_qname_skip_recurse(dns_rpz_zones_t *rpzs) {
|
|||
* qname_wait_recurse and qname_skip_recurse are used to
|
||||
* implement the "qname-wait-recurse" config option.
|
||||
*
|
||||
* By default, "qname-wait-recurse" is yes, so no
|
||||
* processing happens without recursion. In this case,
|
||||
* qname_wait_recurse is true, and qname_skip_recurse
|
||||
* (a bit field indicating which policy zones can be
|
||||
* processed without recursion) is set to all 0's by
|
||||
* When "qname-wait-recurse" is yes, no processing happens without
|
||||
* recursion. In this case, qname_wait_recurse is true, and
|
||||
* qname_skip_recurse (a bit field indicating which policy zones
|
||||
* can be processed without recursion) is set to all 0's by
|
||||
* fix_qname_skip_recurse().
|
||||
*
|
||||
* When "qname-wait-recurse" is no, qname_skip_recurse may be
|
||||
|
|
@ -681,6 +681,12 @@ badname(int level, const dns_name_t *name, const char *str1, const char *str2) {
|
|||
* Convert an IP address from radix tree binary (host byte order) to
|
||||
* to its canonical response policy domain name without the origin of the
|
||||
* policy zone.
|
||||
*
|
||||
* Generate a name for an IPv6 address that fits RFC 5952, except that our
|
||||
* reversed format requires that when the length of the consecutive 16-bit
|
||||
* 0 fields are equal (e.g., 1.0.0.1.0.0.db8.2001 corresponding to
|
||||
* 2001:db8:0:0:1:0:0:1), we shorted the last instead of the first
|
||||
* (e.g., 1.0.0.1.zz.db8.2001 corresponding to 2001:db8::1:0:0:1).
|
||||
*/
|
||||
static isc_result_t
|
||||
ip2name(const dns_rpz_cidr_key_t *tgt_ip, dns_rpz_prefix_t tgt_prefix,
|
||||
|
|
@ -693,7 +699,7 @@ ip2name(const dns_rpz_cidr_key_t *tgt_ip, dns_rpz_prefix_t tgt_prefix,
|
|||
char str[1+8+1+INET6_ADDRSTRLEN+1];
|
||||
isc_buffer_t buffer;
|
||||
isc_result_t result;
|
||||
isc_boolean_t zeros;
|
||||
int best_first, best_len, cur_first, cur_len;
|
||||
int i, n, len;
|
||||
|
||||
if (KEY_IS_IPV4(tgt_prefix, tgt_ip)) {
|
||||
|
|
@ -703,43 +709,53 @@ ip2name(const dns_rpz_cidr_key_t *tgt_ip, dns_rpz_prefix_t tgt_prefix,
|
|||
(tgt_ip->w[3]>>8) & 0xff,
|
||||
(tgt_ip->w[3]>>16) & 0xff,
|
||||
(tgt_ip->w[3]>>24) & 0xff);
|
||||
if (len < 0 || len > (int)sizeof(str))
|
||||
if (len < 0 || len > (int)sizeof(str)) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
} else {
|
||||
len = snprintf(str, sizeof(str), "%d", tgt_prefix);
|
||||
if (len == -1) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
for (i = 0; i < DNS_RPZ_CIDR_WORDS; i++) {
|
||||
w[i*2+1] = ((tgt_ip->w[DNS_RPZ_CIDR_WORDS-1-i] >> 16)
|
||||
& 0xffff);
|
||||
w[i*2] = tgt_ip->w[DNS_RPZ_CIDR_WORDS-1-i] & 0xffff;
|
||||
}
|
||||
zeros = ISC_FALSE;
|
||||
len = snprintf(str, sizeof(str), "%d", tgt_prefix);
|
||||
if (len == -1)
|
||||
return (ISC_R_FAILURE);
|
||||
i = 0;
|
||||
while (i < DNS_RPZ_CIDR_WORDS * 2) {
|
||||
if (w[i] != 0 || zeros ||
|
||||
i >= DNS_RPZ_CIDR_WORDS * 2 - 1 ||
|
||||
w[i+1] != 0) {
|
||||
INSIST((size_t)len <= sizeof(str));
|
||||
n = snprintf(&str[len], sizeof(str) - len,
|
||||
".%x", w[i++]);
|
||||
if (n < 0)
|
||||
return (ISC_R_FAILURE);
|
||||
len += n;
|
||||
/*
|
||||
* Find the start and length of the first longest sequence
|
||||
* of zeros in the address.
|
||||
*/
|
||||
best_first = -1;
|
||||
best_len = 0;
|
||||
cur_first = -1;
|
||||
cur_len = 0;
|
||||
for (n = 0; n <=7; ++n) {
|
||||
if (w[n] != 0) {
|
||||
cur_len = 0;
|
||||
cur_first = -1;
|
||||
} else {
|
||||
zeros = ISC_TRUE;
|
||||
INSIST((size_t)len <= sizeof(str));
|
||||
n = snprintf(&str[len], sizeof(str) - len,
|
||||
".zz");
|
||||
if (n < 0)
|
||||
return (ISC_R_FAILURE);
|
||||
len += n;
|
||||
i += 2;
|
||||
while (i < DNS_RPZ_CIDR_WORDS * 2 && w[i] == 0)
|
||||
++i;
|
||||
++cur_len;
|
||||
if (cur_first < 0) {
|
||||
cur_first = n;
|
||||
} else if (cur_len >= best_len) {
|
||||
best_first = cur_first;
|
||||
best_len = cur_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (n = 0; n <= 7; ++n) {
|
||||
INSIST(len < (int)sizeof(str));
|
||||
if (n == best_first) {
|
||||
len += snprintf(str + len, sizeof(str) - len,
|
||||
".zz");
|
||||
n += best_len - 1;
|
||||
} else {
|
||||
len += snprintf(str + len, sizeof(str) - len,
|
||||
".%x", w[n]);
|
||||
}
|
||||
if (len >= (int)sizeof(str))
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -750,26 +766,31 @@ ip2name(const dns_rpz_cidr_key_t *tgt_ip, dns_rpz_prefix_t tgt_prefix,
|
|||
}
|
||||
|
||||
/*
|
||||
* Determine the type a of a name in a response policy zone.
|
||||
* Determine the type of a name in a response policy zone.
|
||||
*/
|
||||
static dns_rpz_type_t
|
||||
type_from_name(dns_rpz_zone_t *rpz, const dns_name_t *name) {
|
||||
|
||||
if (dns_name_issubdomain(name, &rpz->ip))
|
||||
type_from_name(const dns_rpz_zones_t *rpzs,
|
||||
dns_rpz_zone_t *rpz, const dns_name_t *name)
|
||||
{
|
||||
if (dns_name_issubdomain(name, &rpz->ip)) {
|
||||
return (DNS_RPZ_TYPE_IP);
|
||||
}
|
||||
|
||||
if (dns_name_issubdomain(name, &rpz->client_ip))
|
||||
if (dns_name_issubdomain(name, &rpz->client_ip)) {
|
||||
return (DNS_RPZ_TYPE_CLIENT_IP);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_RPZ_NSIP
|
||||
if (dns_name_issubdomain(name, &rpz->nsip))
|
||||
if ((rpzs->p.nsip_on & DNS_RPZ_ZBIT(rpz->num)) != 0 &&
|
||||
dns_name_issubdomain(name, &rpz->nsip))
|
||||
{
|
||||
return (DNS_RPZ_TYPE_NSIP);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ENABLE_RPZ_NSDNAME
|
||||
if (dns_name_issubdomain(name, &rpz->nsdname))
|
||||
if ((rpzs->p.nsdname_on & DNS_RPZ_ZBIT(rpz->num)) != 0 &&
|
||||
dns_name_issubdomain(name, &rpz->nsdname))
|
||||
{
|
||||
return (DNS_RPZ_TYPE_NSDNAME);
|
||||
#endif
|
||||
}
|
||||
|
||||
return (DNS_RPZ_TYPE_QNAME);
|
||||
}
|
||||
|
|
@ -787,7 +808,7 @@ name2ipkey(int log_level,
|
|||
dns_rpz_addr_zbits_t *new_set)
|
||||
{
|
||||
dns_rpz_zone_t *rpz;
|
||||
char ip_str[DNS_NAME_FORMATSIZE];
|
||||
char ip_str[DNS_NAME_FORMATSIZE], ip2_str[DNS_NAME_FORMATSIZE];
|
||||
dns_offsets_t ip_name_offsets;
|
||||
dns_fixedname_t ip_name2f;
|
||||
dns_name_t ip_name, *ip_name2;
|
||||
|
|
@ -830,7 +851,6 @@ name2ipkey(int log_level,
|
|||
"; invalid leading prefix length", "");
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
*cp2 = '\0';
|
||||
if (prefix_num < 1U || prefix_num > 128U) {
|
||||
badname(log_level, src_name,
|
||||
"; invalid prefix length of ", prefix_str);
|
||||
|
|
@ -926,21 +946,27 @@ name2ipkey(int log_level,
|
|||
}
|
||||
|
||||
/*
|
||||
* XXXMUKS: Should the following check be enabled in a
|
||||
* production build? It can be expensive for large IP zones
|
||||
* from 3rd parties.
|
||||
* Complain about bad names but be generous and accept them.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Convert the address back to a canonical domain name
|
||||
* to ensure that the original name is in canonical form.
|
||||
*/
|
||||
dns_fixedname_init(&ip_name2f);
|
||||
ip_name2 = dns_fixedname_name(&ip_name2f);
|
||||
result = ip2name(tgt_ip, (dns_rpz_prefix_t)prefix_num, NULL, ip_name2);
|
||||
if (result != ISC_R_SUCCESS || !dns_name_equal(&ip_name, ip_name2)) {
|
||||
badname(log_level, src_name, "; not canonical", "");
|
||||
return (ISC_R_FAILURE);
|
||||
if (log_level < DNS_RPZ_DEBUG_QUIET &&
|
||||
isc_log_wouldlog(dns_lctx, log_level)) {
|
||||
/*
|
||||
* Convert the address back to a canonical domain name
|
||||
* to ensure that the original name is in canonical form.
|
||||
*/
|
||||
dns_fixedname_init(&ip_name2f);
|
||||
ip_name2 = dns_fixedname_name(&ip_name2f);
|
||||
result = ip2name(tgt_ip, (dns_rpz_prefix_t)prefix_num,
|
||||
NULL, ip_name2);
|
||||
if (result != ISC_R_SUCCESS ||
|
||||
!dns_name_equal(&ip_name, ip_name2)) {
|
||||
dns_name_format(ip_name2, ip2_str, sizeof(ip2_str));
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
|
||||
DNS_LOGMODULE_RBTDB, log_level,
|
||||
"rpz IP address \"%s\""
|
||||
" is not the canonical \"%s\"",
|
||||
ip_str, ip2_str);
|
||||
}
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
|
@ -1396,10 +1422,11 @@ rpz_node_deleter(void *nm_data, void *mctx) {
|
|||
}
|
||||
|
||||
/*
|
||||
* Get ready for a new set of policy zones.
|
||||
* Get ready for a new set of policy zones for a view.
|
||||
*/
|
||||
isc_result_t
|
||||
dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, isc_mem_t *mctx,
|
||||
dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, char *rps_cstr,
|
||||
size_t rps_cstr_size, isc_mem_t *mctx,
|
||||
isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr)
|
||||
{
|
||||
dns_rpz_zones_t *zones;
|
||||
|
|
@ -1424,7 +1451,20 @@ dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, isc_mem_t *mctx,
|
|||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_refcount;
|
||||
|
||||
result = dns_rbt_create(mctx, rpz_node_deleter, mctx, &zones->rbt);
|
||||
zones->rps_cstr = rps_cstr;
|
||||
zones->rps_cstr_size = rps_cstr_size;
|
||||
#ifdef USE_DNSRPS
|
||||
if (rps_cstr != NULL) {
|
||||
result = dns_dnsrps_view_init(zones, rps_cstr);
|
||||
}
|
||||
#else
|
||||
INSIST(!zones->p.dnsrps_enabled);
|
||||
#endif
|
||||
if (result == ISC_R_SUCCESS && !zones->p.dnsrps_enabled) {
|
||||
result = dns_rbt_create(mctx, rpz_node_deleter,
|
||||
mctx, &zones->rbt);
|
||||
}
|
||||
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_rbt;
|
||||
|
||||
|
|
@ -2074,26 +2114,38 @@ dns_rpz_detach_rpzs(dns_rpz_zones_t **rpzsp) {
|
|||
|
||||
*rpzsp = NULL;
|
||||
isc_refcount_decrement(&rpzs->refs, &refs);
|
||||
if (refs != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Forget the last of view's rpz machinery after the last reference.
|
||||
*/
|
||||
if (refs == 0) {
|
||||
for (rpz_num = 0; rpz_num < DNS_RPZ_MAX_ZONES; ++rpz_num) {
|
||||
rpz = rpzs->zones[rpz_num];
|
||||
rpzs->zones[rpz_num] = NULL;
|
||||
if (rpz != NULL)
|
||||
rpz_detach(&rpz, rpzs);
|
||||
for (rpz_num = 0; rpz_num < DNS_RPZ_MAX_ZONES; ++rpz_num) {
|
||||
rpz = rpzs->zones[rpz_num];
|
||||
rpzs->zones[rpz_num] = NULL;
|
||||
if (rpz != NULL) {
|
||||
rpz_detach(&rpz, rpzs);
|
||||
}
|
||||
|
||||
cidr_free(rpzs);
|
||||
dns_rbt_destroy(&rpzs->rbt);
|
||||
DESTROYLOCK(&rpzs->maint_lock);
|
||||
isc_rwlock_destroy(&rpzs->search_lock);
|
||||
isc_refcount_destroy(&rpzs->refs);
|
||||
isc_task_destroy(&rpzs->updater);
|
||||
isc_mem_putanddetach(&rpzs->mctx, rpzs, sizeof(*rpzs));
|
||||
}
|
||||
|
||||
if (rpzs->rps_cstr_size != 0) {
|
||||
#ifdef USE_DNSRPS
|
||||
librpz->client_detach(&rpzs->rps_client);
|
||||
#endif
|
||||
isc_mem_put(rpzs->mctx, rpzs->rps_cstr,
|
||||
rpzs->rps_cstr_size);
|
||||
}
|
||||
|
||||
cidr_free(rpzs);
|
||||
if (rpzs->rbt != NULL) {
|
||||
dns_rbt_destroy(&rpzs->rbt);
|
||||
}
|
||||
DESTROYLOCK(&rpzs->maint_lock);
|
||||
isc_rwlock_destroy(&rpzs->search_lock);
|
||||
isc_refcount_destroy(&rpzs->refs);
|
||||
isc_task_destroy(&rpzs->updater);
|
||||
isc_mem_putanddetach(&rpzs->mctx, rpzs, sizeof(*rpzs));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2140,7 +2192,7 @@ dns_rpz_add(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
|
|||
REQUIRE(rpz != NULL);
|
||||
RWLOCK(&rpzs->search_lock, isc_rwlocktype_write);
|
||||
|
||||
rpz_type = type_from_name(rpz, src_name);
|
||||
rpz_type = type_from_name(rpzs, rpz, src_name);
|
||||
|
||||
|
||||
switch (rpz_type) {
|
||||
|
|
@ -2350,7 +2402,7 @@ dns_rpz_delete(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
|
|||
|
||||
RWLOCK(&rpzs->search_lock, isc_rwlocktype_write);
|
||||
|
||||
rpz_type = type_from_name(rpz, src_name);
|
||||
rpz_type = type_from_name(rpzs, rpz, src_name);
|
||||
|
||||
switch (rpz_type) {
|
||||
case DNS_RPZ_TYPE_QNAME:
|
||||
|
|
|
|||
|
|
@ -1419,11 +1419,15 @@ static cfg_type_t cfg_type_dnstapoutput = {
|
|||
* zone <string> [ policy (given|disabled|passthru|drop|tcp-only|
|
||||
* nxdomain|nodata|cname <domain> ) ]
|
||||
* [ recursive-only yes|no ] [ log yes|no ]
|
||||
* [ max-policy-ttl number ] [ min-update-interval number ] ;
|
||||
* [ max-policy-ttl number ]
|
||||
* [ nsip-enable yes|no ] [ nsdname-enable yes|no ];
|
||||
* } [ recursive-only yes|no ] [ max-policy-ttl number ]
|
||||
* [ min-update-interval number ]
|
||||
* [ break-dnssec yes|no ] [ min-ns-dots number ]
|
||||
* [ qname-wait-recurse yes|no ] ;
|
||||
* [ qname-wait-recurse yes|no ]
|
||||
* [ nsip-enable yes|no ] [ nsdname-enable yes|no ]
|
||||
* [ dnsrps-enable yes|no ]
|
||||
* [ dnsrps-options { DNSRPS configuration string } ];
|
||||
*/
|
||||
|
||||
static void
|
||||
|
|
@ -1614,6 +1618,8 @@ static cfg_tuplefielddef_t rpz_zone_fields[] = {
|
|||
{ "min-update-interval", &cfg_type_uint32, 0 },
|
||||
{ "policy", &cfg_type_rpz_policy, 0 },
|
||||
{ "recursive-only", &cfg_type_boolean, 0 },
|
||||
{ "nsip-enable", &cfg_type_boolean, 0 },
|
||||
{ "nsdname-enable", &cfg_type_boolean, 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
static cfg_type_t cfg_type_rpz_tuple = {
|
||||
|
|
@ -1635,6 +1641,16 @@ static cfg_tuplefielddef_t rpz_fields[] = {
|
|||
{ "nsip-wait-recurse", &cfg_type_boolean, 0 },
|
||||
{ "qname-wait-recurse", &cfg_type_boolean, 0 },
|
||||
{ "recursive-only", &cfg_type_boolean, 0 },
|
||||
{ "nsip-enable", &cfg_type_boolean, 0 },
|
||||
{ "nsdname-enable", &cfg_type_boolean, 0 },
|
||||
#ifdef USE_DNSRPS
|
||||
{ "dnsrps-enable", &cfg_type_boolean, 0 },
|
||||
{ "dnsrps-options", &cfg_type_bracketed_text, 0 },
|
||||
#else
|
||||
{ "dnsrps-enable", &cfg_type_boolean, CFG_CLAUSEFLAG_NOTCONFIGURED },
|
||||
{ "dnsrps-options", &cfg_type_bracketed_text,
|
||||
CFG_CLAUSEFLAG_NOTCONFIGURED },
|
||||
#endif
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
static cfg_type_t cfg_type_rpz = {
|
||||
|
|
@ -1851,6 +1867,14 @@ view_clauses[] = {
|
|||
{ "dns64", &cfg_type_dns64, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "dns64-contact", &cfg_type_astring, 0 },
|
||||
{ "dns64-server", &cfg_type_astring, 0 },
|
||||
#ifdef USE_DNSRPS
|
||||
{ "dnsrps-enable", &cfg_type_boolean, 0 },
|
||||
{ "dnsrps-options", &cfg_type_bracketed_text, 0 },
|
||||
#else
|
||||
{ "dnsrps-enable", &cfg_type_boolean, CFG_CLAUSEFLAG_NOTCONFIGURED },
|
||||
{ "dnsrps-options", &cfg_type_bracketed_text,
|
||||
CFG_CLAUSEFLAG_NOTCONFIGURED },
|
||||
#endif
|
||||
{ "dnssec-accept-expired", &cfg_type_boolean, 0 },
|
||||
{ "dnssec-enable", &cfg_type_boolean, 0 },
|
||||
{ "dnssec-lookaside", &cfg_type_lookaside, CFG_CLAUSEFLAG_MULTI },
|
||||
|
|
|
|||
489
lib/ns/query.c
489
lib/ns/query.c
|
|
@ -29,6 +29,7 @@
|
|||
#include <dns/db.h>
|
||||
#include <dns/dlz.h>
|
||||
#include <dns/dns64.h>
|
||||
#include <dns/dnsrps.h>
|
||||
#include <dns/dnssec.h>
|
||||
#include <dns/events.h>
|
||||
#include <dns/message.h>
|
||||
|
|
@ -715,6 +716,7 @@ query_reset(ns_client_t *client, isc_boolean_t everything) {
|
|||
if (client->query.rpz_st != NULL) {
|
||||
rpz_st_clear(client);
|
||||
if (everything) {
|
||||
INSIST(client->query.rpz_st->rpsdb == NULL);
|
||||
isc_mem_put(client->mctx, client->query.rpz_st,
|
||||
sizeof(*client->query.rpz_st));
|
||||
client->query.rpz_st = NULL;
|
||||
|
|
@ -1285,8 +1287,7 @@ rpz_log_fail_helper(ns_client_t *client, int level, dns_name_t *p_name,
|
|||
{
|
||||
char qnamebuf[DNS_NAME_FORMATSIZE];
|
||||
char p_namebuf[DNS_NAME_FORMATSIZE];
|
||||
const char *failed;
|
||||
const char *slash;
|
||||
const char *failed, *via, *slash, *str_blank;
|
||||
const char *rpztypestr1;
|
||||
const char *rpztypestr2;
|
||||
|
||||
|
|
@ -1310,13 +1311,23 @@ rpz_log_fail_helper(ns_client_t *client, int level, dns_name_t *p_name,
|
|||
rpztypestr2 = "";
|
||||
}
|
||||
|
||||
str_blank = (*str != ' ' && *str != '\0') ? " " : "";
|
||||
|
||||
dns_name_format(client->query.qname, qnamebuf, sizeof(qnamebuf));
|
||||
dns_name_format(p_name, p_namebuf, sizeof(p_namebuf));
|
||||
|
||||
if (p_name != NULL) {
|
||||
via = " via ";
|
||||
dns_name_format(p_name, p_namebuf, sizeof(p_namebuf));
|
||||
} else {
|
||||
via = "";
|
||||
p_namebuf[0] = '\0';
|
||||
}
|
||||
|
||||
ns_client_log(client, NS_LOGCATEGORY_QUERY_ERRORS,
|
||||
NS_LOGMODULE_QUERY, level,
|
||||
"rpz %s%s%s rewrite %s via %s%s%s%s",
|
||||
"rpz %s%s%s rewrite %s%s%s%s%s%s : %s",
|
||||
rpztypestr1, slash, rpztypestr2,
|
||||
qnamebuf, p_namebuf,
|
||||
qnamebuf, via, p_namebuf, str_blank,
|
||||
str, failed, isc_result_totext(result));
|
||||
}
|
||||
|
||||
|
|
@ -2512,24 +2523,33 @@ rpz_st_clear(ns_client_t *client) {
|
|||
|
||||
CTRACE(ISC_LOG_DEBUG(3), "rpz_st_clear");
|
||||
|
||||
if (st->m.rdataset != NULL)
|
||||
if (st->m.rdataset != NULL) {
|
||||
query_putrdataset(client, &st->m.rdataset);
|
||||
}
|
||||
rpz_match_clear(st);
|
||||
|
||||
rpz_clean(NULL, &st->r.db, NULL, NULL);
|
||||
if (st->r.ns_rdataset != NULL)
|
||||
if (st->r.ns_rdataset != NULL) {
|
||||
query_putrdataset(client, &st->r.ns_rdataset);
|
||||
if (st->r.r_rdataset != NULL)
|
||||
}
|
||||
if (st->r.r_rdataset != NULL) {
|
||||
query_putrdataset(client, &st->r.r_rdataset);
|
||||
}
|
||||
|
||||
rpz_clean(&st->q.zone, &st->q.db, &st->q.node, NULL);
|
||||
if (st->q.rdataset != NULL)
|
||||
if (st->q.rdataset != NULL) {
|
||||
query_putrdataset(client, &st->q.rdataset);
|
||||
if (st->q.sigrdataset != NULL)
|
||||
}
|
||||
if (st->q.sigrdataset != NULL) {
|
||||
query_putrdataset(client, &st->q.sigrdataset);
|
||||
}
|
||||
st->state = 0;
|
||||
st->m.type = DNS_RPZ_TYPE_BAD;
|
||||
st->m.policy = DNS_RPZ_POLICY_MISS;
|
||||
if (st->rpsdb != NULL) {
|
||||
dns_db_detach(&st->rpsdb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static dns_rpz_zbits_t
|
||||
|
|
@ -2544,6 +2564,19 @@ rpz_get_zbits(ns_client_t *client,
|
|||
|
||||
st = client->query.rpz_st;
|
||||
|
||||
#ifdef USE_DNSRPS
|
||||
if (st->popt.dnsrps_enabled) {
|
||||
if (st->rpsdb == NULL ||
|
||||
librpz->have_trig(dns_dnsrps_type2trig(rpz_type),
|
||||
ip_type == dns_rdatatype_aaaa,
|
||||
((rpsdb_t *)st->rpsdb)->rsp))
|
||||
{
|
||||
return (DNS_RPZ_ALL_ZBITS);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (rpz_type) {
|
||||
case DNS_RPZ_TYPE_CLIENT_IP:
|
||||
zbits = st->have.client_ip;
|
||||
|
|
@ -2733,7 +2766,7 @@ rpz_rrset_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type,
|
|||
rpz_clean(NULL, dbp, &node, rdatasetp);
|
||||
version = NULL;
|
||||
dns_db_attach(client->view->cachedb, dbp);
|
||||
result = dns_db_findext(*dbp, name, version, dns_rdatatype_ns,
|
||||
result = dns_db_findext(*dbp, name, version, type,
|
||||
0, client->now, &node, found,
|
||||
&cm, &ci, *rdatasetp, NULL);
|
||||
}
|
||||
|
|
@ -2921,8 +2954,7 @@ rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype,
|
|||
p_name, rpz_type,
|
||||
" rdatasetiter", result);
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"rpz_find_p: rdatasetiter_destroy "
|
||||
"failed");
|
||||
"rpz_find_p: rdatasetiter failed");
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
/*
|
||||
|
|
@ -3017,6 +3049,283 @@ rpz_save_p(dns_rpz_st_t *st, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
|
|||
SAVE(st->m.version, version);
|
||||
}
|
||||
|
||||
#ifdef USE_DNSRPS
|
||||
/*
|
||||
* Check the results of a RPZ service interface lookup.
|
||||
* Stop after an error (<0) or not a hit on a disabled zone (0).
|
||||
* Continue after a hit on a disabled zone (>0).
|
||||
*/
|
||||
static int
|
||||
dnsrps_ck(librpz_emsg_t *emsg, ns_client_t *client, rpsdb_t *rpsdb,
|
||||
isc_boolean_t recursed)
|
||||
{
|
||||
isc_region_t region;
|
||||
librpz_domain_buf_t pname_buf;
|
||||
|
||||
if (!librpz->rsp_result(emsg, &rpsdb->result, recursed, rpsdb->rsp)) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Forget the state from before the IP address or domain check
|
||||
* if the lookup hit nothing.
|
||||
*/
|
||||
if (rpsdb->result.policy == LIBRPZ_POLICY_UNDEFINED ||
|
||||
rpsdb->result.hit_id != rpsdb->hit_id ||
|
||||
rpsdb->result.policy != LIBRPZ_POLICY_DISABLED)
|
||||
{
|
||||
if (!librpz->rsp_pop_discard(emsg, rpsdb->rsp)) {
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Log a hit on a disabled zone.
|
||||
* Forget the zone to not try it again, and restore the pre-hit state.
|
||||
*/
|
||||
if (!librpz->rsp_domain(emsg, &pname_buf, rpsdb->rsp)) {
|
||||
return (-1);
|
||||
}
|
||||
region.base = pname_buf.d;
|
||||
region.length = pname_buf.size;
|
||||
dns_name_fromregion(client->query.rpz_st->p_name, ®ion);
|
||||
rpz_log_rewrite(client, ISC_TRUE,
|
||||
dns_dnsrps_2policy(rpsdb->result.zpolicy),
|
||||
dns_dnsrps_trig2type(rpsdb->result.trig), NULL,
|
||||
client->query.rpz_st->p_name, NULL,
|
||||
rpsdb->result.cznum);
|
||||
|
||||
if (!librpz->rsp_forget_zone(emsg, rpsdb->result.cznum, rpsdb->rsp) ||
|
||||
!librpz->rsp_pop(emsg, &rpsdb->result, rpsdb->rsp))
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ready the shim database and rdataset for a DNSRPS hit.
|
||||
*/
|
||||
static isc_boolean_t
|
||||
dnsrps_set_p(librpz_emsg_t *emsg, ns_client_t *client, dns_rpz_st_t *st,
|
||||
dns_rdatatype_t qtype, dns_rdataset_t **p_rdatasetp,
|
||||
isc_boolean_t recursed)
|
||||
{
|
||||
rpsdb_t *rpsdb;
|
||||
librpz_domain_buf_t pname_buf;
|
||||
isc_region_t region;
|
||||
dns_zone_t *p_zone;
|
||||
dns_db_t *p_db;
|
||||
dns_dbnode_t *p_node;
|
||||
dns_rpz_policy_t policy;
|
||||
dns_fixedname_t foundf;
|
||||
dns_name_t *found;
|
||||
dns_rdatatype_t foundtype, searchtype;
|
||||
isc_result_t result;
|
||||
|
||||
rpsdb = (rpsdb_t *)st->rpsdb;
|
||||
|
||||
if (!librpz->rsp_result(emsg, &rpsdb->result, recursed, rpsdb->rsp)) {
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
if (rpsdb->result.policy == LIBRPZ_POLICY_UNDEFINED) {
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Give the fake or shim DNSRPS database its new origin.
|
||||
*/
|
||||
if (!librpz->rsp_soa(emsg, NULL, NULL, &rpsdb->origin_buf,
|
||||
&rpsdb->result, rpsdb->rsp))
|
||||
{
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
region.base = rpsdb->origin_buf.d;
|
||||
region.length = rpsdb->origin_buf.size;
|
||||
dns_name_fromregion(&rpsdb->common.origin, ®ion);
|
||||
|
||||
if (!librpz->rsp_domain(emsg, &pname_buf, rpsdb->rsp)) {
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
region.base = pname_buf.d;
|
||||
region.length = pname_buf.size;
|
||||
dns_name_fromregion(st->p_name, ®ion);
|
||||
|
||||
p_zone = NULL;
|
||||
p_db = NULL;
|
||||
p_node = NULL;
|
||||
rpz_ready(client, p_rdatasetp);
|
||||
dns_db_attach(st->rpsdb, &p_db);
|
||||
policy = dns_dnsrps_2policy(rpsdb->result.policy);
|
||||
if (policy != DNS_RPZ_POLICY_RECORD) {
|
||||
result = ISC_R_SUCCESS;
|
||||
} else if (qtype == dns_rdatatype_rrsig) {
|
||||
/*
|
||||
* dns_find_db() refuses to look for and fail to
|
||||
* find dns_rdatatype_rrsig.
|
||||
*/
|
||||
result = DNS_R_NXRRSET;
|
||||
policy = DNS_RPZ_POLICY_NODATA;
|
||||
} else {
|
||||
/*
|
||||
* Get the next (and so first) RR from the policy node.
|
||||
* If it is a CNAME, then look for it regardless of the
|
||||
* query type.
|
||||
*/
|
||||
if (!librpz->rsp_rr(emsg, &foundtype, NULL, NULL, NULL,
|
||||
&rpsdb->result, rpsdb->qname->ndata,
|
||||
rpsdb->qname->length, rpsdb->rsp))
|
||||
{
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
if (foundtype == dns_rdatatype_cname) {
|
||||
searchtype = dns_rdatatype_cname;
|
||||
} else {
|
||||
searchtype = qtype;
|
||||
}
|
||||
/*
|
||||
* Get the DNSPRS imitation rdataset.
|
||||
*/
|
||||
dns_fixedname_init(&foundf);
|
||||
found = dns_fixedname_name(&foundf);
|
||||
result = dns_db_find(p_db, st->p_name, NULL, searchtype,
|
||||
0, 0, &p_node, found, *p_rdatasetp, NULL);
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
if (searchtype == dns_rdatatype_cname &&
|
||||
qtype != dns_rdatatype_cname)
|
||||
{
|
||||
result = DNS_R_CNAME;
|
||||
}
|
||||
} else if (result == DNS_R_NXRRSET) {
|
||||
policy = DNS_RPZ_POLICY_NODATA;
|
||||
} else {
|
||||
snprintf(emsg->c, sizeof(emsg->c), "dns_db_find(): %s",
|
||||
isc_result_totext(result));
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
rpz_save_p(st, client->view->rpzs->zones[rpsdb->result.cznum],
|
||||
dns_dnsrps_trig2type(rpsdb->result.trig), policy,
|
||||
st->p_name, 0, result, &p_zone, &p_db, &p_node,
|
||||
p_rdatasetp, NULL);
|
||||
|
||||
rpz_clean(NULL, NULL, NULL, p_rdatasetp);
|
||||
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
dnsrps_rewrite_ip(ns_client_t *client, const isc_netaddr_t *netaddr,
|
||||
dns_rpz_type_t rpz_type, dns_rdataset_t **p_rdatasetp)
|
||||
{
|
||||
dns_rpz_st_t *st;
|
||||
rpsdb_t *rpsdb;
|
||||
librpz_trig_t trig = LIBRPZ_TRIG_CLIENT_IP;
|
||||
isc_boolean_t recursed = ISC_FALSE;
|
||||
int res;
|
||||
librpz_emsg_t emsg;
|
||||
isc_result_t result;
|
||||
|
||||
st = client->query.rpz_st;
|
||||
rpsdb = (rpsdb_t *)st->rpsdb;
|
||||
|
||||
result = rpz_ready(client, p_rdatasetp);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
st->m.policy = DNS_RPZ_POLICY_ERROR;
|
||||
return (result);
|
||||
}
|
||||
|
||||
switch (rpz_type) {
|
||||
case DNS_RPZ_TYPE_CLIENT_IP:
|
||||
trig = LIBRPZ_TRIG_CLIENT_IP;
|
||||
recursed = ISC_FALSE;
|
||||
break;
|
||||
case DNS_RPZ_TYPE_IP:
|
||||
trig = LIBRPZ_TRIG_IP;
|
||||
recursed = ISC_TRUE;
|
||||
break;
|
||||
case DNS_RPZ_TYPE_NSIP:
|
||||
trig = LIBRPZ_TRIG_NSIP;
|
||||
recursed = ISC_TRUE;
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
}
|
||||
|
||||
do {
|
||||
if (!librpz->rsp_push(&emsg, rpsdb->rsp) ||
|
||||
!librpz->ck_ip(&emsg,
|
||||
netaddr->family == AF_INET
|
||||
? (const void *)&netaddr->type.in
|
||||
: (const void *)&netaddr->type.in6,
|
||||
netaddr->family, trig, ++rpsdb->hit_id,
|
||||
recursed, rpsdb->rsp) ||
|
||||
(res = dnsrps_ck(&emsg, client, rpsdb, recursed)) < 0)
|
||||
{
|
||||
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL,
|
||||
rpz_type, emsg.c, DNS_R_SERVFAIL);
|
||||
st->m.policy = DNS_RPZ_POLICY_ERROR;
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
} while (res != 0);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
dnsrps_rewrite_name(ns_client_t *client, dns_name_t *trig_name,
|
||||
isc_boolean_t recursed, dns_rpz_type_t rpz_type,
|
||||
dns_rdataset_t **p_rdatasetp)
|
||||
{
|
||||
dns_rpz_st_t *st;
|
||||
rpsdb_t *rpsdb;
|
||||
librpz_trig_t trig = LIBRPZ_TRIG_CLIENT_IP;
|
||||
isc_region_t r;
|
||||
int res;
|
||||
librpz_emsg_t emsg;
|
||||
isc_result_t result;
|
||||
|
||||
st = client->query.rpz_st;
|
||||
rpsdb = (rpsdb_t *)st->rpsdb;
|
||||
|
||||
result = rpz_ready(client, p_rdatasetp);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
st->m.policy = DNS_RPZ_POLICY_ERROR;
|
||||
return (result);
|
||||
}
|
||||
|
||||
switch (rpz_type) {
|
||||
case DNS_RPZ_TYPE_QNAME:
|
||||
trig = LIBRPZ_TRIG_QNAME;
|
||||
break;
|
||||
case DNS_RPZ_TYPE_NSDNAME:
|
||||
trig = LIBRPZ_TRIG_NSDNAME;
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
}
|
||||
|
||||
dns_name_toregion(trig_name, &r);
|
||||
do {
|
||||
if (!librpz->rsp_push(&emsg, rpsdb->rsp) ||
|
||||
!librpz->ck_domain(&emsg, r.base, r.length,
|
||||
trig, ++rpsdb->hit_id,
|
||||
recursed, rpsdb->rsp) ||
|
||||
(res = dnsrps_ck(&emsg, client, rpsdb, recursed)) < 0)
|
||||
{
|
||||
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL,
|
||||
rpz_type, emsg.c, DNS_R_SERVFAIL);
|
||||
st->m.policy = DNS_RPZ_POLICY_ERROR;
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
} while (res != 0);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
#endif /* USE_DNSRPS */
|
||||
|
||||
/*
|
||||
* Check this address in every eligible policy zone.
|
||||
*/
|
||||
|
|
@ -3041,6 +3350,15 @@ rpz_rewrite_ip(ns_client_t *client, const isc_netaddr_t *netaddr,
|
|||
|
||||
CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip");
|
||||
|
||||
rpzs = client->view->rpzs;
|
||||
st = client->query.rpz_st;
|
||||
#ifdef USE_DNSRPS
|
||||
if (st->popt.dnsrps_enabled) {
|
||||
return (dnsrps_rewrite_ip(client, netaddr, rpz_type,
|
||||
p_rdatasetp));
|
||||
}
|
||||
#endif
|
||||
|
||||
dns_fixedname_init(&ip_namef);
|
||||
ip_name = dns_fixedname_name(&ip_namef);
|
||||
|
||||
|
|
@ -3048,8 +3366,6 @@ rpz_rewrite_ip(ns_client_t *client, const isc_netaddr_t *netaddr,
|
|||
p_db = NULL;
|
||||
p_node = NULL;
|
||||
|
||||
rpzs = client->view->rpzs;
|
||||
st = client->query.rpz_st;
|
||||
while (zbits != 0) {
|
||||
rpz_num = dns_rpz_find_ip(rpzs, rpz_type, zbits, netaddr,
|
||||
ip_name, &prefix);
|
||||
|
|
@ -3319,7 +3635,8 @@ rpz_rewrite_ip_rrsets(ns_client_t *client, dns_name_t *name,
|
|||
static isc_result_t
|
||||
rpz_rewrite_name(ns_client_t *client, dns_name_t *trig_name,
|
||||
dns_rdatatype_t qtype, dns_rpz_type_t rpz_type,
|
||||
dns_rpz_zbits_t allowed_zbits, dns_rdataset_t **rdatasetp)
|
||||
dns_rpz_zbits_t allowed_zbits, isc_boolean_t recursed,
|
||||
dns_rdataset_t **rdatasetp)
|
||||
{
|
||||
dns_rpz_zones_t *rpzs;
|
||||
dns_rpz_zone_t *rpz;
|
||||
|
|
@ -3335,15 +3652,27 @@ rpz_rewrite_name(ns_client_t *client, dns_name_t *trig_name,
|
|||
dns_rpz_policy_t policy;
|
||||
isc_result_t result;
|
||||
|
||||
#ifndef USE_DNSRPS
|
||||
UNUSED(recursed);
|
||||
#endif
|
||||
|
||||
CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_name");
|
||||
|
||||
rpzs = client->view->rpzs;
|
||||
st = client->query.rpz_st;
|
||||
|
||||
#ifdef USE_DNSRPS
|
||||
if (st->popt.dnsrps_enabled) {
|
||||
return (dnsrps_rewrite_name(client, trig_name, recursed,
|
||||
rpz_type, rdatasetp));
|
||||
}
|
||||
#endif
|
||||
|
||||
zbits = rpz_get_zbits(client, qtype, rpz_type);
|
||||
zbits &= allowed_zbits;
|
||||
if (zbits == 0)
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
rpzs = client->view->rpzs;
|
||||
|
||||
/*
|
||||
* Use the summary database to find the bit mask of policy zones
|
||||
* with policies for this trigger name. We do this even if there
|
||||
|
|
@ -3361,8 +3690,6 @@ rpz_rewrite_name(ns_client_t *client, dns_name_t *trig_name,
|
|||
p_db = NULL;
|
||||
p_node = NULL;
|
||||
|
||||
st = client->query.rpz_st;
|
||||
|
||||
/*
|
||||
* Check the trigger name in every policy zone that the summary data
|
||||
* says has a hit for the trigger name.
|
||||
|
|
@ -3513,6 +3840,15 @@ rpz_rewrite_ns_skip(ns_client_t *client, dns_name_t *nsname,
|
|||
st->r.label--;
|
||||
}
|
||||
|
||||
/*
|
||||
* RPZ query result types
|
||||
*/
|
||||
typedef enum {
|
||||
qresult_type_done = 0,
|
||||
qresult_type_restart = 1,
|
||||
qresult_type_recurse = 2
|
||||
} qresult_type_t;
|
||||
|
||||
/*
|
||||
* Look for response policy zone QNAME, NSIP, and NSDNAME rewriting.
|
||||
*/
|
||||
|
|
@ -3526,12 +3862,15 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype,
|
|||
dns_rdataset_t *rdataset;
|
||||
dns_fixedname_t nsnamef;
|
||||
dns_name_t *nsname;
|
||||
int qresult_type;
|
||||
qresult_type_t qresult_type;
|
||||
dns_rpz_zbits_t zbits;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
dns_rpz_have_t have;
|
||||
dns_rpz_popt_t popt;
|
||||
int rpz_ver;
|
||||
#ifdef USE_DNSRPS
|
||||
librpz_emsg_t emsg;
|
||||
#endif
|
||||
|
||||
CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite");
|
||||
|
||||
|
|
@ -3543,7 +3882,7 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype,
|
|||
return (DNS_R_DISALLOWED);
|
||||
|
||||
RWLOCK(&rpzs->search_lock, isc_rwlocktype_read);
|
||||
if (rpzs->p.num_zones == 0 ||
|
||||
if ((rpzs->p.num_zones == 0 && !rpzs->p.dnsrps_enabled) ||
|
||||
(!RECURSIONOK(client) && rpzs->p.no_rd_ok == 0) ||
|
||||
!rpz_ck_dnssec(client, qresult, ordataset, osigset))
|
||||
{
|
||||
|
|
@ -3560,6 +3899,7 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype,
|
|||
if (st == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
st->state = 0;
|
||||
st->rpsdb = NULL;
|
||||
}
|
||||
if (st->state == 0) {
|
||||
st->state |= DNS_RPZ_ACTIVE;
|
||||
|
|
@ -3579,6 +3919,26 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype,
|
|||
st->popt = popt;
|
||||
st->rpz_ver = rpz_ver;
|
||||
client->query.rpz_st = st;
|
||||
if (popt.dnsrps_enabled) {
|
||||
#ifdef USE_DNSRPS
|
||||
if (st->rpsdb != NULL) {
|
||||
dns_db_detach(&st->rpsdb);
|
||||
}
|
||||
result = dns_dnsrps_rewrite_init(&emsg, st, rpzs,
|
||||
client->query.qname,
|
||||
client->mctx,
|
||||
RECURSIONOK(client));
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
|
||||
NULL, DNS_RPZ_TYPE_QNAME,
|
||||
emsg.c, result);
|
||||
st->m.policy = DNS_RPZ_POLICY_ERROR;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
#else
|
||||
INSIST(0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -3588,7 +3948,7 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype,
|
|||
case ISC_R_SUCCESS:
|
||||
case DNS_R_GLUE:
|
||||
case DNS_R_ZONECUT:
|
||||
qresult_type = 0;
|
||||
qresult_type = qresult_type_done;
|
||||
break;
|
||||
case DNS_R_EMPTYNAME:
|
||||
case DNS_R_NXRRSET:
|
||||
|
|
@ -3598,7 +3958,7 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype,
|
|||
case DNS_R_NCACHENXRRSET:
|
||||
case DNS_R_CNAME:
|
||||
case DNS_R_DNAME:
|
||||
qresult_type = 1;
|
||||
qresult_type = qresult_type_restart;
|
||||
break;
|
||||
case DNS_R_DELEGATION:
|
||||
case ISC_R_NOTFOUND:
|
||||
|
|
@ -3608,19 +3968,19 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype,
|
|||
* can rewrite.
|
||||
*/
|
||||
if (RECURSIONOK(client))
|
||||
qresult_type = 2;
|
||||
qresult_type = qresult_type_recurse;
|
||||
else
|
||||
qresult_type = 1;
|
||||
qresult_type = qresult_type_restart;
|
||||
break;
|
||||
case ISC_R_FAILURE:
|
||||
case ISC_R_TIMEDOUT:
|
||||
case DNS_R_BROKENCHAIN:
|
||||
rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL3, client->query.qname,
|
||||
rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL3, NULL,
|
||||
DNS_RPZ_TYPE_QNAME,
|
||||
" stop on qresult in rpz_rewrite()", qresult);
|
||||
return (ISC_R_SUCCESS);
|
||||
default:
|
||||
rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, client->query.qname,
|
||||
rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, NULL,
|
||||
DNS_RPZ_TYPE_QNAME,
|
||||
" stop on unrecognized qresult in rpz_rewrite()",
|
||||
qresult);
|
||||
|
|
@ -3630,19 +3990,23 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype,
|
|||
rdataset = NULL;
|
||||
|
||||
if ((st->state & (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME)) !=
|
||||
(DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME)) {
|
||||
(DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME))
|
||||
{
|
||||
isc_netaddr_t netaddr;
|
||||
dns_rpz_zbits_t allowed;
|
||||
|
||||
if (qresult_type == 2) {
|
||||
if (!st->popt.dnsrps_enabled &&
|
||||
qresult_type == qresult_type_recurse)
|
||||
{
|
||||
/*
|
||||
* This request needs recursion that has not been done.
|
||||
* Get bits for the policy zones that do not need
|
||||
* to wait for the results of recursion.
|
||||
*/
|
||||
allowed = st->have.qname_skip_recurse;
|
||||
if (allowed == 0)
|
||||
if (allowed == 0) {
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
} else {
|
||||
allowed = DNS_RPZ_ALL_ZBITS;
|
||||
}
|
||||
|
|
@ -3671,9 +4035,12 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype,
|
|||
* There is a first time for each name in a CNAME chain
|
||||
*/
|
||||
if ((st->state & DNS_RPZ_DONE_QNAME) == 0) {
|
||||
isc_boolean_t norec =
|
||||
ISC_TF(qresult_type != qresult_type_recurse);
|
||||
result = rpz_rewrite_name(client, client->query.qname,
|
||||
qtype, DNS_RPZ_TYPE_QNAME,
|
||||
allowed, &rdataset);
|
||||
allowed, norec,
|
||||
&rdataset);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
|
|
@ -3699,7 +4066,7 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype,
|
|||
* Do not bother saving the work from this attempt,
|
||||
* because recusion is so slow.
|
||||
*/
|
||||
if (qresult_type == 2)
|
||||
if (qresult_type == qresult_type_recurse)
|
||||
goto cleanup;
|
||||
|
||||
/*
|
||||
|
|
@ -3710,13 +4077,14 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype,
|
|||
}
|
||||
|
||||
/*
|
||||
* Check known IP addresses for the query name if the database
|
||||
* lookup resulted in some addresses (qresult_type == 0)
|
||||
* Check known IP addresses for the query name if the database lookup
|
||||
* resulted in some addresses (qresult_type == qresult_type_done)
|
||||
* and if we have not already checked them.
|
||||
* Any recursion required for the query has already happened.
|
||||
* Do not check addresses that will not be in the ANSWER section.
|
||||
*/
|
||||
if ((st->state & DNS_RPZ_DONE_QNAME_IP) == 0 && qresult_type == 0 &&
|
||||
if ((st->state & DNS_RPZ_DONE_QNAME_IP) == 0 &&
|
||||
qresult_type == qresult_type_done &&
|
||||
rpz_get_zbits(client, qtype, DNS_RPZ_TYPE_IP) != 0) {
|
||||
result = rpz_rewrite_ip_rrsets(client,
|
||||
client->query.qname, qtype,
|
||||
|
|
@ -3799,13 +4167,13 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype,
|
|||
case ISC_R_FAILURE:
|
||||
rpz_rewrite_ns_skip(client, nsname, result,
|
||||
DNS_RPZ_DEBUG_LEVEL3,
|
||||
" NS rpz_rrset_find() ");
|
||||
" NS rpz_rrset_find()");
|
||||
continue;
|
||||
default:
|
||||
rpz_rewrite_ns_skip(client, nsname, result,
|
||||
DNS_RPZ_INFO_LEVEL,
|
||||
" unrecognized NS"
|
||||
" rpz_rrset_find() ");
|
||||
" rpz_rrset_find()");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
@ -3843,6 +4211,7 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype,
|
|||
qtype,
|
||||
DNS_RPZ_TYPE_NSDNAME,
|
||||
DNS_RPZ_ALL_ZBITS,
|
||||
ISC_TRUE,
|
||||
&rdataset);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_rdata_freestruct(&ns);
|
||||
|
|
@ -3879,6 +4248,17 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype,
|
|||
result = ISC_R_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
#ifdef USE_DNSRPS
|
||||
if (st->popt.dnsrps_enabled &&
|
||||
st->m.policy != DNS_RPZ_POLICY_ERROR &&
|
||||
!dnsrps_set_p(&emsg, client, st, qtype, &rdataset,
|
||||
ISC_TF(qresult_type != qresult_type_recurse)))
|
||||
{
|
||||
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL,
|
||||
DNS_RPZ_TYPE_BAD, emsg.c, DNS_R_SERVFAIL);
|
||||
st->m.policy = DNS_RPZ_POLICY_ERROR;
|
||||
}
|
||||
#endif
|
||||
if (st->m.policy != DNS_RPZ_POLICY_MISS &&
|
||||
st->m.policy != DNS_RPZ_POLICY_ERROR &&
|
||||
st->m.rpz->policy != DNS_RPZ_POLICY_GIVEN)
|
||||
|
|
@ -5427,7 +5807,8 @@ query_resume(query_ctx_t *qctx) {
|
|||
if (qctx->rpz_st->rpz_ver != qctx->client->view->rpzs->rpz_ver)
|
||||
{
|
||||
ns_client_log(qctx->client, NS_LOGCATEGORY_CLIENT,
|
||||
NS_LOGMODULE_QUERY, ISC_LOG_INFO,
|
||||
NS_LOGMODULE_QUERY,
|
||||
DNS_RPZ_INFO_LEVEL,
|
||||
"query_resume: RPZ settings "
|
||||
"out of date "
|
||||
"(rpz_ver %d, expected %d)",
|
||||
|
|
@ -5789,6 +6170,17 @@ query_checkrpz(query_ctx_t *qctx, isc_result_t result) {
|
|||
RESTORE(qctx->version, qctx->rpz_st->m.version);
|
||||
RESTORE(qctx->zone, qctx->rpz_st->m.zone);
|
||||
|
||||
/*
|
||||
* Add SOA record to additional section
|
||||
*/
|
||||
rresult = query_addsoa(qctx,
|
||||
dns_rdataset_isassociated(qctx->rdataset),
|
||||
DNS_SECTION_ADDITIONAL);
|
||||
if (rresult != ISC_R_SUCCESS) {
|
||||
QUERY_ERROR(qctx, result);
|
||||
return (ISC_R_COMPLETE);
|
||||
}
|
||||
|
||||
switch (qctx->rpz_st->m.policy) {
|
||||
case DNS_RPZ_POLICY_TCP_ONLY:
|
||||
qctx->client->message->flags |= DNS_MESSAGEFLAG_TC;
|
||||
|
|
@ -7584,7 +7976,6 @@ query_nodata(query_ctx_t *qctx, isc_result_t result) {
|
|||
*/
|
||||
isc_result_t
|
||||
query_sign_nodata(query_ctx_t *qctx) {
|
||||
dns_section_t section;
|
||||
isc_result_t result;
|
||||
/*
|
||||
* Look for a NSEC3 record if we don't have a NSEC record.
|
||||
|
|
@ -7688,16 +8079,16 @@ query_sign_nodata(query_ctx_t *qctx) {
|
|||
}
|
||||
|
||||
/*
|
||||
* Add SOA to the additional section if generated by a RPZ
|
||||
* rewrite.
|
||||
* The RPZ SOA has already been added to the additional section
|
||||
* if this was an RPZ rewrite, but if it wasn't, add it now.
|
||||
*/
|
||||
section = qctx->nxrewrite ? DNS_SECTION_ADDITIONAL
|
||||
: DNS_SECTION_AUTHORITY;
|
||||
|
||||
result = query_addsoa(qctx, ISC_UINT32_MAX, section);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
QUERY_ERROR(qctx, result);
|
||||
return (query_done(qctx));
|
||||
if (!qctx->nxrewrite) {
|
||||
result = query_addsoa(qctx, ISC_UINT32_MAX,
|
||||
DNS_SECTION_AUTHORITY);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
QUERY_ERROR(qctx, result);
|
||||
return (query_done(qctx));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in a new issue