For rt26172:

Add
      - optional "recursive-only yes|no" to the response-policy statement
      - optional max-policy-ttl to limit the lies that "recursive-only no"
          can introduce into resolvers' caches
      - test that queries with RD=0 are not rewritten by default
      - performance smoke test

    Change encoding of PASSTHRU action to "rpz-passthru".
          (The old encoding is still accepted.)
    Fix rt26180  assert botch in zone_findrdataset() in this branch
         as well.

    Fix missing signatures on NOERROR results despite RPZ hits
        when there are signatures and the client asks for DNSSEC,
This commit is contained in:
Vernon Schryver 2012-06-01 01:03:43 +00:00
parent f011dfffca
commit f05089ea5c
32 changed files with 1104 additions and 417 deletions

15
CHANGES
View file

@ -1,3 +1,18 @@
3330. [func] Fix missing signatures on NOERROR results despite
RPZ rewriting. Also
- add optional "recursive-only yes|no" to the
response-policy statement
- add optional "max-policy-ttl" to the response-policy
statement to limit the false data that
"recursive-only no" can introduce into
resolvers' caches
- add a RPZ performance test to bin/tests/system/rpz
when queryperf is available.
- the encoding of PASSTHRU action to "rpz-passthru".
(The old encoding is still accepted.)
[RT #26172]
3329. [bug] Handle RRSIG signer-name case consistently: We
generate RRSIG records with the signer-name in
lower case. We accept them with any case, but if

View file

@ -3845,6 +3845,13 @@ rpz_clean(dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep,
dns_rdataset_disassociate(*rdatasetp);
}
static void
rpz_match_clear(dns_rpz_st_t *st)
{
rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset);
st->m.version = NULL;
}
static inline isc_result_t
rpz_ready(ns_client_t *client, dns_zone_t **zonep, dns_db_t **dbp,
dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp)
@ -3864,10 +3871,9 @@ static void
rpz_st_clear(ns_client_t *client) {
dns_rpz_st_t *st = client->query.rpz_st;
rpz_clean(&st->m.zone, &st->m.db, &st->m.node, NULL);
st->m.version = 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)
@ -4023,6 +4029,9 @@ rpz_rewrite_ip(ns_client_t *client, dns_rdataset_t *rdataset,
for (rpz = ISC_LIST_HEAD(client->view->rpz_zones);
rpz != NULL;
rpz = ISC_LIST_NEXT(rpz, link)) {
if (!RECURSIONOK(client) && rpz->recursive_only)
continue;
/*
* Do not check policy zones that cannot replace a policy
* already known to match.
@ -4051,9 +4060,8 @@ rpz_rewrite_ip(ns_client_t *client, dns_rdataset_t *rdataset,
* hit, if any. Note the domain name and quality of the
* best hit.
*/
(void)dns_db_rpz_findips(rpz, rpz_type, zone, db, version,
rdataset, st,
client->query.rpz_st->qname);
dns_db_rpz_findips(rpz, rpz_type, zone, db, version,
rdataset, st, client->query.rpz_st->qname);
rpz_clean(&zone, &db, NULL, NULL);
}
return (ISC_R_SUCCESS);
@ -4158,8 +4166,8 @@ rpz_rewrite_rrsets(ns_client_t *client, dns_rpz_type_t rpz_type,
*/
static isc_result_t
rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef,
dns_name_t *sname, dns_rpz_type_t rpz_type, dns_zone_t **zonep,
dns_db_t **dbp, dns_dbversion_t **versionp,
dns_name_t *sname, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp,
dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp,
dns_rpz_policy_t *policyp)
{
@ -4204,7 +4212,7 @@ rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef,
if (result != ISC_R_SUCCESS) {
dns_db_detachnode(*dbp, nodep);
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type,
qnamef, "allrdatasets()", result);
qnamef, "allrdatasets() ", result);
*policyp = DNS_RPZ_POLICY_ERROR;
return (DNS_R_SERVFAIL);
}
@ -4221,7 +4229,7 @@ rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef,
if (result != ISC_R_SUCCESS) {
if (result != ISC_R_NOMORE) {
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
rpz_type, qnamef, "rdatasetiter",
rpz_type, qnamef, "rdatasetiter ",
result);
*policyp = DNS_RPZ_POLICY_ERROR;
return (DNS_R_SERVFAIL);
@ -4249,7 +4257,7 @@ rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef,
if ((*rdatasetp)->type != dns_rdatatype_cname) {
policy = DNS_RPZ_POLICY_RECORD;
} else {
policy = dns_rpz_decode_cname(*rdatasetp, sname);
policy = dns_rpz_decode_cname(rpz, *rdatasetp, sname);
if ((policy == DNS_RPZ_POLICY_RECORD ||
policy == DNS_RPZ_POLICY_WILDCNAME) &&
qtype != dns_rdatatype_cname &&
@ -4320,6 +4328,9 @@ rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
for (rpz = ISC_LIST_HEAD(client->view->rpz_zones);
rpz != NULL;
rpz = ISC_LIST_NEXT(rpz, link)) {
if (!RECURSIONOK(client) && rpz->recursive_only)
continue;
/*
* Do not check policy zones that cannot replace a policy
* already known to match.
@ -4365,11 +4376,11 @@ rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
}
/*
* See if the policy record exists.
* See if the policy record exists and get its policy.
*/
result = rpz_find(client, qtype, rpz_qname, qname, rpz_type,
&zone, &db, &version, &node, rdatasetp,
&policy);
result = rpz_find(client, qtype, rpz_qname, qname, rpz,
rpz_type, &zone, &db, &version, &node,
rdatasetp, &policy);
switch (result) {
case DNS_R_NXDOMAIN:
case DNS_R_EMPTYNAME:
@ -4405,8 +4416,7 @@ rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
continue;
}
rpz_clean(&st->m.zone, &st->m.db, &st->m.node,
&st->m.rdataset);
rpz_match_clear(st);
st->m.rpz = rpz;
st->m.type = rpz_type;
st->m.prefix = 0;
@ -4420,9 +4430,11 @@ rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
trdataset = st->m.rdataset;
st->m.rdataset = *rdatasetp;
*rdatasetp = trdataset;
st->m.ttl = st->m.rdataset->ttl;
st->m.ttl = ISC_MIN(st->m.rdataset->ttl,
rpz->max_policy_ttl);
} else {
st->m.ttl = DNS_RPZ_TTL_DEFAULT;
st->m.ttl = ISC_MIN(DNS_RPZ_TTL_DEFAULT,
rpz->max_policy_ttl);
}
st->m.node = node;
node = NULL;
@ -4517,13 +4529,13 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult,
case DNS_R_BROKENCHAIN:
rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL3, DNS_RPZ_TYPE_QNAME,
client->query.qname,
"stop on qresult in rpz_rewrite()",
"stop on qresult in rpz_rewrite() ",
qresult);
return (ISC_R_SUCCESS);
default:
rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, DNS_RPZ_TYPE_QNAME,
client->query.qname,
"stop on unrecognized qresult in rpz_rewrite()",
"stop on unrecognized qresult in rpz_rewrite() ",
qresult);
return (ISC_R_SUCCESS);
}
@ -4702,10 +4714,11 @@ cleanup:
if (st->m.policy == DNS_RPZ_POLICY_MISS ||
st->m.policy == DNS_RPZ_POLICY_PASSTHRU ||
st->m.policy == DNS_RPZ_POLICY_ERROR) {
if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU)
if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU &&
result != DNS_R_DELEGATION)
rpz_log_rewrite(client, "", st->m.policy, st->m.type,
st->qname);
rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset);
rpz_match_clear(st);
}
if (st->m.policy == DNS_RPZ_POLICY_ERROR) {
st->m.type = DNS_RPZ_TYPE_BAD;
@ -4718,6 +4731,64 @@ cleanup:
return (result);
}
/*
* See if response policy zone rewriting is allowed a lack of interest
* by the client in DNSSEC or a lack of signatures.
*/
static isc_boolean_t
rpz_ck_dnssec(ns_client_t *client, isc_result_t result,
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
{
dns_fixedname_t fixed;
dns_name_t *found;
dns_rdataset_t trdataset;
dns_rdatatype_t type;
if (client->view->rpz_break_dnssec)
return (ISC_TRUE);
/*
* sigrdataset == NULL if and only !WANTDNSSEC(client)
*/
if (sigrdataset == NULL)
return (ISC_TRUE);
if (dns_rdataset_isassociated(sigrdataset))
return (ISC_FALSE);
/*
* We are happy to rewrite nothing.
*/
if (rdataset == NULL || !dns_rdataset_isassociated(rdataset))
return (ISC_TRUE);
/*
* Do not rewrite if there is any sign of signatures.
*/
if (rdataset->type == dns_rdatatype_nsec ||
rdataset->type == dns_rdatatype_nsec3 ||
rdataset->type == dns_rdatatype_rrsig)
return (ISC_FALSE);
/*
* Look for a signature in a negative cache rdataset.
*/
if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) == 0)
return (ISC_TRUE);
dns_fixedname_init(&fixed);
found = dns_fixedname_name(&fixed);
dns_rdataset_init(&trdataset);
for (result = dns_rdataset_first(rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(rdataset)) {
dns_ncache_current(rdataset, found, &trdataset);
type = trdataset.type;
dns_rdataset_disassociate(&trdataset);
if (type == dns_rdatatype_nsec ||
type == dns_rdatatype_nsec3 ||
type == dns_rdatatype_rrsig)
return (ISC_FALSE);
}
return (ISC_TRUE);
}
/*
* Add a CNAME to the query response, including translating foo.evil.com and
* *.evil.com CNAME *.example.com
@ -4762,7 +4833,8 @@ rpz_add_cname(ns_client_t *client, dns_rpz_st_t *st,
* Turn off DNSSEC because the results of a
* response policy zone cannot verify.
*/
client->attributes &= ~NS_CLIENTATTR_WANTDNSSEC;
client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
DNS_MESSAGEFLAG_AD);
return (ISC_R_SUCCESS);
}
@ -5681,9 +5753,9 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
CTRACE("query_find: resume");
if (!ISC_LIST_EMPTY(client->view->rpz_zones) &&
RECURSIONOK(client) && !RECURSING(client) &&
(!WANTDNSSEC(client) || sigrdataset == NULL ||
!dns_rdataset_isassociated(sigrdataset)) &&
(RECURSIONOK(client) || !client->view->rpz_recursive_only) &&
rpz_ck_dnssec(client, result, rdataset, sigrdataset) &&
!RECURSING(client) &&
(client->query.rpz_st == NULL ||
(client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0) &&
!dns_name_equal(client->query.qname, dns_rootname)) {
@ -5757,10 +5829,22 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
break;
case DNS_RPZ_POLICY_RECORD:
result = rpz_st->m.result;
if (type == dns_rdatatype_any &&
result != DNS_R_CNAME &&
dns_rdataset_isassociated(rdataset))
dns_rdataset_disassociate(rdataset);
if (qtype == dns_rdatatype_any &&
result != DNS_R_CNAME) {
/*
* We will add all of the rdatasets of
* the node by iterating, setting the
* TTL then.
*/
if (dns_rdataset_isassociated(rdataset))
dns_rdataset_disassociate(rdataset);
} else {
/*
* We will add this rdataset.
*/
rdataset->ttl = ISC_MIN(rdataset->ttl,
rpz_st->m.ttl);
}
break;
case DNS_RPZ_POLICY_WILDCNAME:
result = dns_rdataset_first(rdataset);
@ -5799,7 +5883,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
* Turn off DNSSEC because the results of a
* response policy zone cannot verify.
*/
client->attributes &= ~NS_CLIENTATTR_WANTDNSSEC;
client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
DNS_MESSAGEFLAG_AD);
query_putrdataset(client, &sigrdataset);
is_zone = ISC_TRUE;
rpz_log_rewrite(client, "", rpz_st->m.policy,
@ -6747,6 +6832,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
noqname = rdataset;
else
noqname = NULL;
rpz_st = client->query.rpz_st;
if (rpz_st != NULL)
rdataset->ttl = ISC_MIN(rdataset->ttl,
rpz_st->m.ttl);
query_addrrset(client,
fname != NULL ? &fname : &tname,
&rdataset, NULL,
@ -7039,8 +7128,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
*/
rpz_st = client->query.rpz_st;
if (rpz_st != NULL && (rpz_st->state & DNS_RPZ_RECURSING) == 0) {
rpz_clean(&rpz_st->m.zone, &rpz_st->m.db, &rpz_st->m.node,
&rpz_st->m.rdataset);
rpz_match_clear(rpz_st);
rpz_st->state &= ~DNS_RPZ_DONE_QNAME;
}
if (rdataset != NULL)

View file

@ -1440,15 +1440,14 @@ cleanup:
}
static isc_result_t
configure_rpz(dns_view_t *view, const cfg_listelt_t *element) {
const cfg_obj_t *rpz_obj, *policy_obj;
configure_rpz(dns_view_t *view, const cfg_listelt_t *element,
isc_boolean_t recursive_only_def, dns_ttl_t ttl_def)
{
const cfg_obj_t *rpz_obj, *policy_obj, *obj;
const char *str;
dns_fixedname_t fixed;
dns_name_t *origin;
dns_rpz_zone_t *old, *new;
dns_zone_t *zone = NULL;
isc_result_t result;
unsigned int l1, l2;
new = isc_mem_get(view->mctx, sizeof(*new));
if (new == NULL) {
@ -1457,9 +1456,10 @@ configure_rpz(dns_view_t *view, const cfg_listelt_t *element) {
}
memset(new, 0, sizeof(*new));
dns_name_init(&new->nsdname, NULL);
dns_name_init(&new->origin, NULL);
dns_name_init(&new->nsdname, NULL);
dns_name_init(&new->cname, NULL);
dns_name_init(&new->passthru, NULL);
ISC_LIST_INITANDAPPEND(view->rpz_zones, new, link);
rpz_obj = cfg_listelt_value(element);
@ -1467,15 +1467,31 @@ configure_rpz(dns_view_t *view, const cfg_listelt_t *element) {
if (cfg_obj_isvoid(policy_obj)) {
new->policy = DNS_RPZ_POLICY_GIVEN;
} else {
str = cfg_obj_asstring(policy_obj);
str = cfg_obj_asstring(cfg_tuple_get(policy_obj,
"policy name"));
new->policy = dns_rpz_str2policy(str);
INSIST(new->policy != DNS_RPZ_POLICY_ERROR);
}
dns_fixedname_init(&fixed);
origin = dns_fixedname_name(&fixed);
str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "name"));
result = dns_name_fromstring(origin, str, DNS_NAME_DOWNCASE, NULL);
obj = cfg_tuple_get(rpz_obj, "recursive-only");
if (cfg_obj_isvoid(obj)) {
new->recursive_only = recursive_only_def;
} else {
new->recursive_only = cfg_obj_asboolean(obj);
}
if (!new->recursive_only)
view->rpz_recursive_only = ISC_FALSE;
obj = cfg_tuple_get(rpz_obj, "max-policy-ttl");
if (cfg_obj_isuint32(obj)) {
new->max_policy_ttl = cfg_obj_asuint32(obj);
} else {
new->max_policy_ttl = ttl_def;
}
str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "zone name"));
result = dns_name_fromstring(&new->origin, str, DNS_NAME_DOWNCASE,
view->mctx);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
"invalid zone '%s'", str);
@ -1483,31 +1499,28 @@ configure_rpz(dns_view_t *view, const cfg_listelt_t *element) {
}
result = dns_name_fromstring2(&new->nsdname, DNS_RPZ_NSDNAME_ZONE,
origin, DNS_NAME_DOWNCASE, view->mctx);
&new->origin, DNS_NAME_DOWNCASE,
view->mctx);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
"invalid zone '%s'", str);
goto cleanup;
}
/*
* The origin is part of 'nsdname' so we don't need to keep it
* seperately.
*/
l1 = dns_name_countlabels(&new->nsdname);
l2 = dns_name_countlabels(origin);
dns_name_getlabelsequence(&new->nsdname, l1 - l2, l2, &new->origin);
result = dns_name_fromstring(&new->passthru, DNS_RPZ_PASSTHRU_ZONE,
DNS_NAME_DOWNCASE, view->mctx);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
"invalid zone '%s'", str);
goto cleanup;
}
/*
* Are we configured to with the reponse policy zone?
*/
result = dns_view_findzone(view, &new->origin, &zone);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
"unknown zone '%s'", str);
goto cleanup;
}
if (dns_zone_gettype(zone) != dns_zone_master &&
dns_zone_gettype(zone) != dns_zone_slave) {
cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
@ -1531,8 +1544,9 @@ configure_rpz(dns_view_t *view, const cfg_listelt_t *element) {
}
if (new->policy == DNS_RPZ_POLICY_CNAME) {
str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "cname"));
result = dns_name_fromstring(&new->cname, str, 0, view->mctx);
str = cfg_obj_asstring(cfg_tuple_get(policy_obj, "cname"));
result = dns_name_fromstring(&new->cname, str,
DNS_NAME_DOWNCASE, view->mctx);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
"invalid cname '%s'", str);
@ -2858,19 +2872,39 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
* Make the list of response policy zone names for views that
* are used for real lookups and so care about hints.
*/
zonelist = NULL;
if (view->rdclass == dns_rdataclass_in && need_hints) {
obj = NULL;
result = ns_config_get(maps, "response-policy", &obj);
if (result == ISC_R_SUCCESS)
cfg_map_get(obj, "zone", &zonelist);
}
obj = NULL;
if (view->rdclass == dns_rdataclass_in && need_hints &&
ns_config_get(maps, "response-policy", &obj) == ISC_R_SUCCESS) {
const cfg_obj_t *recursive_only_obj;
const cfg_obj_t *break_dnssec_obj, *ttl_obj;
isc_boolean_t recursive_only_def;
dns_ttl_t ttl_def;
if (zonelist != NULL) {
for (element = cfg_list_first(zonelist);
recursive_only_obj = cfg_tuple_get(obj, "recursive-only");
if (!cfg_obj_isvoid(recursive_only_obj) &&
!cfg_obj_asboolean(recursive_only_obj))
recursive_only_def = ISC_FALSE;
else
recursive_only_def = ISC_TRUE;
break_dnssec_obj = cfg_tuple_get(obj, "break-dnssec");
if (!cfg_obj_isvoid(break_dnssec_obj) &&
cfg_obj_asboolean(break_dnssec_obj))
view->rpz_break_dnssec = ISC_TRUE;
else
view->rpz_break_dnssec = ISC_FALSE;
ttl_obj = cfg_tuple_get(obj, "max-policy-ttl");
if (cfg_obj_isuint32(ttl_obj))
ttl_def = cfg_obj_asuint32(ttl_obj);
else
ttl_def = DNS_RPZ_MAX_TTL_DEFAULT;
for (element = cfg_list_first(cfg_tuple_get(obj, "zone list"));
element != NULL;
element = cfg_list_next(element)) {
result = configure_rpz(view, element);
result = configure_rpz(view, element,
recursive_only_def, ttl_def);
if (result != ISC_R_SUCCESS)
goto cleanup;
dns_rpz_set_need(ISC_TRUE);

View file

@ -17,8 +17,8 @@
# Clean up after rpz tests.
rm -f proto.* dig.out* nsupdate.tmp
rm -f */named.memstats */named.run */named.rpz */session.key
rm -f ns3/bl*.db */*.jnl */*.core */*.pid
rm -f ns2/signed-tld2.db
rm -f ns2/K*.private ns2/K*.key dsset-*
rm -f proto.* dsset-* random.data trusted.conf dig.out* nsupdate.tmp ns*/*tmp
rm -f ns*/*.key ns*/*.private ns2/tld2s.db
rm -f ns3/bl*.db ns*/*switch ns5/requests ns5/example.db ns5/bl.db ns5/*.perf
rm -f */named.memstats */named.run */named.rpz */session.key
rm -f */*.jnl */*.core */*.pid

View file

@ -23,12 +23,9 @@ ns. A 10.53.0.1
; rewrite responses from this zone
tld2. NS ns.tld2.
ns.tld2. A 10.53.0.2
ns2.tld2. A 10.53.0.2
; rewrite responses from this zone unless dnssec requested
signed-tld2. NS ns.signed-tld2.
ns.signed-tld2. A 10.53.0.2
ns2.signed-tld2. A 10.53.0.2
; rewrite responses from this secure zone unless dnssec requested (DO=1)
tld2s. NS ns.tld2.
; requests come from here
tld3. NS ns.tld3.
@ -37,4 +34,3 @@ ns.tld3. A 10.53.0.3
; rewrite responses from this zone
tld4. NS ns.tld4.
ns.tld4. A 10.53.0.4
ns2.tld4. A 10.53.0.4

View file

@ -0,0 +1,31 @@
; Copyright (C) 2011 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.
; $Id: base-tld2s.db,v 1.1.2.1 2012/02/24 17:22:37 vjs Exp $
; RPZ rewrite responses from this signed zone
$TTL 120
@ SOA tld2s. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 )
NS ns
NS . ; check for RT 24985
ns A 10.53.0.2
a0-1 A 192.168.0.1
a0-1-scname CNAME a0-1.tld2.
a3-5 A 192.168.3.5

View file

@ -31,6 +31,7 @@ options {
notify no;
};
include "../trusted.conf";
zone "." { type hint; file "hints"; };
zone "tld2." {type master; file "tld2.db";};
@ -40,4 +41,5 @@ zone "sub2.tld2." {type master; file "tld2.db";};
zone "subsub.sub2.tld2." {type master; file "tld2.db";};
zone "sub3.tld2." {type master; file "tld2.db";};
zone "subsub.sub3.tld2." {type master; file "tld2.db";};
zone "signed-tld2." {type master; file "signed-tld2.db";};
zone "tld2s." {type master; file "tld2s.db";};

View file

@ -12,7 +12,7 @@
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
; $Id: tld2.db,v 1.4 2011/10/13 01:32:33 vjs Exp $
; $Id: tld2.db,v 1.4.4.2 2012/02/24 17:22:37 vjs Exp $
; RPZ rewrite responses from this zone
@ -20,10 +20,8 @@
$TTL 120
@ SOA tld2. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 )
NS ns
NS ns2
NS . ; check for RT 24985
ns A 10.53.0.2
ns2 A 10.53.0.2
txt-only TXT "txt-only-tld2"
@ -36,6 +34,8 @@ a12-cname CNAME a12
a0-1 A 192.168.0.1
AAAA 2001:2::1
TXT "a0-1 tld2 text"
a0-1-scname CNAME a0-1.tld2s.
a3-1 A 192.168.3.1
AAAA 2001:2:3::1
@ -115,3 +115,8 @@ a5-3 A 192.168.5.3
a5-4 A 192.168.5.4
TXT "a5-4 tld2 text"
a6-1 A 192.168.6.1
TXT "a6-1 tld2 text"
a6-2 A 192.168.6.2
TXT "a6-2 tld2 text"

View file

@ -12,14 +12,17 @@
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
; $Id: base.db,v 1.6 2011/10/13 01:32:33 vjs Exp $
; $Id: base.db,v 1.6.4.1 2011/10/15 23:03:38 vjs Exp $
; RPZ test
; This basic file is copied to several zone files before being used.
; Its contents are also changed with nsupdate
$TTL 120
@ SOA blx. hostmaster.ns.blx. ( 1 3600 1200 604800 60 )
NS ns.tld.
NS ns
ns A 10.53.0.3
; Poke the radix tree a little.
@ -34,6 +37,6 @@ ns A 10.53.0.3
; regression testing for some old crashes
redirect IN A 127.0.0.1
*.redirect IN A 127.0.0.1
*.credirect IN CNAME google.com.
redirect A 127.0.0.1
*.redirect A 127.0.0.1
*.credirect CNAME google.com.

View file

@ -21,8 +21,8 @@ $TTL 120
NS ns
ns A 10.53.0.3
; #18 in test1, crashed new ASSERT() in rbtdb.c
c1 A 172.16.1.1
; #24 in test1, crashed new ASSERT() in rbtdb.c
c1 A 172.16.1.24
; #16 in test2, crashed new ASSERT() in rbtdb.c
c2 A 172.16.1.16

View file

@ -17,6 +17,10 @@
/* $Id: named.conf,v 1.5 2011/10/28 11:46:50 marka Exp $ */
/*
* Main rpz test DNS server.
*/
options {
query-source address 10.53.0.3;
notify-source 10.53.0.3;
@ -29,13 +33,13 @@ options {
notify no;
response-policy {
zone "bl";
zone "bl" max-policy-ttl 100;
zone "bl-2";
zone "bl-given" policy given;
zone "bl-given" policy given recursive-only yes;
zone "bl-passthru" policy passthru;
zone "bl-no-op" policy no-op; # obsolete for passthru
zone "bl-no-op" policy no-op; # obsolete for passthru
zone "bl-disabled" policy disabled;
zone "bl-nodata" policy nodata;
zone "bl-nodata" policy nodata recursive-only no;
zone "bl-nxdomain" policy nxdomain;
zone "bl-cname" policy cname txt-only.tld2.;
zone "bl-wildcname" policy cname *.tld4.;
@ -63,6 +67,7 @@ logging {
};
// include "../trusted.conf";
zone "." { type hint; file "hints"; };
zone "bl." {type master; file "bl.db";

View file

@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: named.conf,v 1.2 2011/10/13 04:53:06 marka Exp $ */
/* $Id: named.conf,v 1.2.6.1 2012/02/24 17:22:37 vjs Exp $ */
controls { /* empty */ };
@ -30,6 +30,7 @@ options {
notify no;
};
include "../trusted.conf";
zone "." { type hint; file "hints"; };
zone "tld4." {type master; file "tld4.db";};

View file

@ -12,16 +12,14 @@
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
; $Id: tld4.db,v 1.2 2011/10/13 04:53:07 marka Exp $
; $Id: tld4.db,v 1.2.6.1 2012/02/24 17:22:37 vjs Exp $
; RPZ rewrite responses from this zone
$TTL 120
@ SOA tld4. hostmaster.ns.tld4. ( 1 3600 1200 604800 60 )
NS ns
NS ns2
ns A 10.53.0.4
ns2 A 10.53.0.4
txt-only TXT "txt-only-tld4"

View file

@ -0,0 +1,19 @@
; Copyright (C) 2011 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.
; $Id: hints,v 1.1.2.1 2011/10/15 23:00:04 vjs Exp $
. 0 NS ns1.
ns1. 0 A 10.53.0.1

View file

@ -0,0 +1,51 @@
/*
* Copyright (C) 2011 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.
*/
/* $Id: named.conf,v 1.1.2.2 2012/02/24 17:22:38 vjs Exp $ */
/*
* Test rpz performance.
*/
options {
query-source address 10.53.0.5;
notify-source 10.53.0.5;
transfer-source 10.53.0.5;
port 5300;
pid-file "named.pid";
session-keyfile "session.key";
listen-on { 10.53.0.5; };
listen-on-v6 { none; };
notify no;
# Eventually turn rpz on.
include "rpz-switch";
};
key rndc_key {
secret "1234abcd8765";
algorithm hmac-md5;
};
controls { inet 10.53.0.5 port 9953 allow { any; } keys { rndc_key; }; };
include "../trusted.conf";
zone "." {type hint; file "hints"; };
zone "example.com." {type master; file "example.db"; };
zone "bl." {type master; file "bl.db"; };

View file

@ -0,0 +1,27 @@
#! /bin/sh
#
# Copyright (C) 2011 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.
# $Id: qperf.sh,v 1.1.2.1 2011/10/15 23:03:37 vjs Exp $
for QDIR in `echo "$PATH" | tr : ' '` ../../../../contrib/queryperf; do
QPERF=$QDIR/queryperf
if test -f $QPERF -a -x $QPERF; then
echo $QPERF
exit 0
fi
done
exit 0

View file

@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rpz.c,v 1.3 2011/01/13 04:59:24 tbox Exp $ */
/* $Id: rpz.c,v 1.3.226.1 2011/10/15 23:03:37 vjs Exp $ */
#include <config.h>
@ -39,7 +39,7 @@ main(int argc, char **argv)
#else
return (1);
#endif
}
}
if (!strcasecmp(argv[1], "nsdname")) {
#ifdef ENABLE_RPZ_NSDNAME
@ -47,8 +47,8 @@ main(int argc, char **argv)
#else
return (1);
#endif
}
}
fputs(USAGE, stderr);
return (1);
fputs(USAGE, stderr);
return (1);
}

View file

@ -1,4 +1,4 @@
#!/bin/sh
#! /bin/sh
#
# Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
#
@ -16,16 +16,100 @@
# $Id: setup.sh,v 1.6 2012/01/07 23:46:53 tbox Exp $
set -e
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
. ./clean.sh
# NO-OP is an obsolete synonym for PASSHTRU
QPERF=`sh qperf.sh`
sh clean.sh
# set up test policy zones. bl-2 is used to check competing zones.
# bl-{given,disabled,passthru,no-data,nxdomain,cname,wildcard,garden}
# are used to check policy overrides in named.conf.
# NO-OP is an obsolete synonym for PASSHTRU
for NM in '' -2 -given -disabled -passthru -no-op -nodata -nxdomain -cname -wildcname -garden; do
sed -e "/SOA/s/blx/bl$NM/g" ns3/base.db >ns3/bl$NM.db
done
# sign the root and a zone in ns2
../../../tools/genrandom 400 random.data
$KEYGEN -Kns2 -q -r random.data -3 signed-tld2. > /dev/null 2>&1
$KEYGEN -Kns2 -q -r random.data -3fk signed-tld2. > /dev/null 2>&1
$SIGNER -S -Kns2 -o signed-tld2. -f ns2/signed-tld2.db ns2/tld2.db > /dev/null 2>&1
# $1=directory, $2=domain name, $3=input zone file, $4=output file
signzone () {
KEYNAME=`$KEYGEN -q -r random.data -b 512 -K $1 $2`
cat $1/$3 $1/$KEYNAME.key > $1/tmp
$SIGNER -Pp -K $1 -o $2 -f $1/$4 $1/tmp >/dev/null
sed -n -e 's/\(.*\) IN DNSKEY \([0-9]\{1,\} [0-9]\{1,\} [0-9]\{1,\}\) \(.*\)/trusted-keys {"\1" \2 "\3";};/p' $1/$KEYNAME.key >>trusted.conf
rm dsset-$2 $1/tmp
}
signzone ns2 tld2s. base-tld2s.db tld2s.db
# Performance checks.
# First with rpz off.
cat <<EOF >ns5/rpz-switch
response-policy {zone "bl";}
recursive-only no
max-policy-ttl 90
break-dnssec yes;
EOF
cat <<EOF >ns5/example.db
\$TTL 120
@ SOA . hostmaster.ns.example. ( 1 3600 1200 604800 60 )
NS ns
ns A 10.53.0.5
EOF
cat <<EOF >ns5/bl.db
\$TTL 120
@ SOA . hostmaster.ns.blperf. ( 1 3600 1200 604800 60 )
NS ns
ns A 10.53.0.5
; used only in failure for "recursive-only no" in #8 test5
a3-5.tld2 CNAME *.
; for "break-dnssec" in #9 test5
a3-5.tld2s CNAME *.
; for "max-policy-ttl 90" in test5
a3-17.tld2 500 A 17.17.17.17
; dummy NSDNAME policies to trigger lookups
ns-1.example.com.rpz-nsdname CNAME .
ns-2.example.com.rpz-nsdname CNAME .
ns-3.example.com.rpz-nsdname CNAME .
ns-4.example.com.rpz-nsdname CNAME .
ns-5.example.com.rpz-nsdname CNAME .
EOF
if test -n "$QPERF"; then
# do not build the full zones if we will not use them to avoid the long
# time otherwise required to shut down the server
$PERL -e 'for ($val = 1; $val <= 65535; ++$val) {
printf("host-%d-%d\tA 192.168.%d.%d\n",
$val/256, $val%256, $val/256, $val%256);
}' >>ns5/example.db
echo >>ns5/bl.db
echo "; rewrite some names" >>ns5/bl.db
$PERL -e 'for ($val = 2; $val <= 65535; $val += 69) {
printf("host-%d.sub%d.example.com\tCNAME\t.\n", $val/256, $val%256);
}' >>ns5/bl.db
echo >>ns5/bl.db
echo "; rewrite with some not entirely trivial patricia trees" >>ns5/bl.db
$PERL -e 'for ($val = 3; $val <= 65535; $val += 69) {
printf("32.%d.%d.168.192.rpz-ip \tCNAME\t.\n",
$val%256, $val/256);
printf("32.%d.%d.168.192.rpz-nsip\tCNAME\t.\n",
($val+1)%256, ($val+1)/256);
}' >>ns5/bl.db
fi
# some psuedo-random queryperf requests
$PERL -e 'for ($cnt = $val = 1; $cnt <= 2000; ++$cnt) {
printf("host-%d.sub%d.example.com A\n", $val%256, $val/256);
$val = ($val * 9 + 32771) % 65536;
}' >ns5/requests

View file

@ -25,13 +25,13 @@ server 10.53.0.3 5300
; QNAME tests
; NXDOMAIN
; 2, 20, 25
update add a0-1.tld2.bl. 300 CNAME .
update add a0-1.signed-tld2.bl. 300 CNAME .
;
; NODATA
; 3, 21
update add a3-1.tld2.bl. 300 CNAME *.
; and no assert-botch
; 5
; 5, 22
update add a3-2.tld2.bl. 300 DNAME example.com.
;
; NXDOMAIN for a4-2-cname.tld2 via its target a4-2.tld2.
@ -57,24 +57,32 @@ update add nxc2.sub1.tld2.bl. 300 CNAME a12-cname.tld2.
;
; prefer the first conflicting zone
; 13
update add a4-4.tld2.bl. 300 A 127.0.0.1
update add a4-4.tld2.bl. 300 A 127.4.4.1
update add a6-1.tld2.bl. 300 CNAME a6-1.tld2.
update add a6-2.tld2.bl. 300 A 127.6.2.1
update add a6-1.tld2.bl. 300 A 127.6.1.1
update add a6-2.tld2.bl. 300 CNAME a6-2.tld2.
send
update add a4-4.tld2.bl-2. 300 A 127.0.0.2
update add a4-4.tld2.bl-2. 300 A 127.4.4.2
send
;
; wildcard CNAME
; 14
update add a3-6.tld2.bl. 300 CNAME *.tld4.
; 15
update add *.sub1.tld2.bl. 300 CNAME *.tld4.
; CNAME chains
; 16
update add a4-5.tld2.bl. 300 A 127.0.0.16
update add a3-6.tld2.bl. 300 CNAME *.tld4.
; 17
update add *.sub1.tld2.bl. 300 CNAME *.tld4.
; CNAME chain
; 18
update add a4-5.tld2.bl. 300 A 127.0.0.16
; stop at first hit in CNAME chain
; 19
update add a4-6.tld2.bl. 300 CNAME .
update add a4-6-cname.tld2.bl. 300 A 127.0.0.17
; 18
;
; assert in rbtdb.c
; 24
update add c1.crash2.tld3.bl. 300 CNAME .
; DO=1 without signatures, DO=0 with signatures are rewritten
; 26 - 27
update add a0-1.tld2s.bl. 300 CNAME .
send

View file

@ -19,41 +19,54 @@
; single requests
; Separate update requests for distinct TLDs with blank lines or 'send'
; End the file with a blank line or 'send'
; CNAME targets are absolute even without trailing "."
; IP tests
server 10.53.0.3 5300
; NODATA a3-1.tld2
; 1
update add 32.1.3.168.192.rpz-ip.bl 300 CNAME *.
;
; NXDOMAIN for 192.168.4.0/24, the network of a4-1.tld2
; NXDOMAIN for 192.168.4.0/24, the network of a4-1.tld2 and a4-2.tld2
; 4
update add 24.0.4.168.192.rpz-ip.bl 300 CNAME .
;
; poke hole in NXDOMAIN CIDR block to leave a4-1.tld2 unchanged
; old passthru in NXDOMAIN CIDR block to leave a4-1.tld2 unchanged
; 3
update add 32.1.4.168.192.rpz-ip.bl 300 CNAME 32.1.4.168.192
;
; NODATA for a4-3.tld2
; 8
update add 32.3.4.168.192.rpz-ip.bl 300 CNAME *.
;
; NXDOMAIN for IPv6 a3-1.tld2
; 9
update add 128.1.zz.3.2.2001.rpz-ip.bl 300 CNAME .
;
; apply the policy with the lexically smallest address of 192.168.5.1
; to an RRset of more than one A RR
; 11
update add 32.1.5.168.192.rpz-ip.bl 300 A 127.0.0.1
update add 32.2.5.168.192.rpz-ip.bl 300 A 127.0.0.2
;
; prefer first conflicting IP zone for a5-3.tld2
; 12
update add 32.3.5.168.192.rpz-ip.bl 300 A 127.0.0.1
send
update add 32.3.5.168.192.rpz-ip.bl-2 300 A 127.0.0.2
send
; prefer QNAME to IP for a5-4.tld2
; 13
update add 32.4.5.168.192.rpz-ip.bl 300 CNAME a12.tld2.
update add a5-4.tld2.bl 300 CNAME a14.tld4.
;
; poke hole in NXDOMAIN CIDR block to leave a4-4.tld2 unchanged
; 15
update add 32.4.4.168.192.rpz-ip.bl 300 CNAME rpz-passthru.
;
; assert in rbtdb.c
; 16
update add 32.16.1.16.172.rpz-ip.bl 300 CNAME .

View file

@ -12,7 +12,7 @@
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
; $Id: test5,v 1.5 2011/10/13 01:32:33 vjs Exp $
; $Id: test5,v 1.5.4.1 2012/02/24 17:22:37 vjs Exp $
; Use comment lines instead of blank lines to combine update requests into
@ -24,22 +24,37 @@
server 10.53.0.3 5300
; 1
update add a3-1.tld2.bl-given. 300 A 127.0.0.1
send
; 2
update add a3-2.tld2.bl-passthru. 300 A 127.0.0.2
send
; 3
update add a3-3.tld2.bl-no-op. 300 A 127.0.0.3
send
; 4
update add a3-4.tld2.bl-disabled. 300 A 127.0.0.4
send
; 5 - 8
update add a3-5.tld2.bl-nodata. 300 A 127.0.0.5
; 9 - 10
update add a3-5.tld2s.bl-nodata. 300 A 127.0.0.9
send
update add a3-6.tld2.bl-nxdomain. 300 A 127.0.0.6
; 11
update add a3-6.tld2.bl-nxdomain. 300 A 127.0.0.11
send
update add a3-7.tld2.bl-cname. 300 A 127.0.0.7
; 12
update add a3-7.tld2.bl-cname. 300 A 127.0.0.12
send
update add a3-8.tld2.bl-wildcname. 300 A 127.0.0.8
update add *.sub9.tld2.bl-wildcname. 300 A 127.0.1.9
; 13
update add a3-8.tld2.bl-wildcname. 300 A 127.0.0.13
; 14
update add *.sub9.tld2.bl-wildcname. 300 A 127.0.1.14
send
update add a3-10.tld2.bl-garden. 300 A 127.0.0.10
; 15
update add a3-15.tld2.bl-garden. 300 A 127.0.0.15
send
; 16
update add a3-16.tld2.bl. 300 A 127.0.0.16
send

View file

@ -19,12 +19,12 @@
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
ns1=10.53.0.1 # root, defining the other two
ns2=10.53.0.2 # server whose answers are rewritten
ns3=10.53.0.3 # resolve that does the rewriting
ns4=10.53.0.4 # another server that is rewritten
RNDCCMD="$RNDC -c ../common/rndc.conf -s $ns3 -p 9953"
ns=10.53.0
ns1=$ns.1 # root, defining the others
ns2=$ns.2 # server whose answers are rewritten
ns3=$ns.3 # resolve that does the rewriting
ns4=$ns.4 # another server that is rewritten
ns5=$ns.5 # check performance with this server
HAVE_CORE=
@ -44,9 +44,18 @@ fi
trap 'exit 1' 1 2 15
RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p 9953 -s"
digcmd () {
#echo I:dig +noadd +noauth +nosearch +time=1 +tries=1 -p 5300 $* 1>&2
$DIG +noadd +noauth +nosearch +time=1 +tries=1 -p 5300 $*
digcmd_args="+noadd +nosearch +time=1 +tries=1 -p 5300 $*"
if ! expr "$digcmd_args" : '.*@' >/dev/null; then
digcmd_args="$digcmd_args @$ns3"
fi
if ! expr "$digcmd_args" : '.*+[no]*auth' >/dev/null; then
digcmd_args="+noauth $digcmd_args"
fi
#echo I:dig $digcmd_args 1>&2
$DIG $digcmd_args
}
# set DIGNM=file name for dig output
@ -77,20 +86,41 @@ load_db () {
}
restart () {
$RNDCCMD stop >/dev/null 2>&1
rm -f ns3/*.jnl
for NM in ns3/bl*.db; do
cp -f ns3/base.db $NM
done
(cd ..; $PERL start.pl --noclean --restart rpz ns3)
# try to ensure that the server really has stopped
# and won't mess with ns$1/name.pid
if test -z "$HAVE_CORE" -a -f ns$1/named.pid; then
$RNDCCMD $ns$1 halt >/dev/null 2>&1
if test -f ns$1/named.pid; then
sleep 1
PID=`cat ns$1/named.pid 2>/dev/null`
if test -n "$PID"; then
echo "I:killing ns$1 server $PID"
kill -9 $PID
fi
fi
fi
rm -f ns$1/*.jnl
if test -f ns$1/base.db; then
for NM in ns$1/bl*.db; do
cp -f ns$1/base.db $NM
done
fi
$PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns$1
load_db
}
# $1=server and irrelevant args $2=error message
ckalive () {
$RNDCCMD status >/dev/null 2>&1 && return 0
CKALIVE_NS=`expr "$1" : '.*@ns\([1-9]\).*'`
if test -z "$CKALIVE_NS"; then
CKALIVE_NS=3
fi
eval CKALIVE_IP=\$ns$CKALIVE_NS
$RNDCCMD $CKALIVE_IP status >/dev/null 2>&1 && return 0
HAVE_CORE=yes
setret "$1"
restart
setret "$2"
# restart the server to avoid stalling waiting for it to stop
restart $CKALIVE_NS
return 1
}
@ -113,15 +143,29 @@ end_group () {
sed -e 's/[ ]add[ ]/ delete /' $TEST_FILE | $NSUPDATE
TEST_FILE=
fi
ckalive $ns3 "I:failed; ns3 server crashed and restarted"
if test "$status" -eq 0; then
# look for complaints from rpz.c
EMSGS=`grep -l 'invalid rpz' */*.run`
if test -n "$EMSGS"; then
setret "I:'invalid rpz' complaints in $EMSGS starting with:"
grep 'invalid rpz' */*.run | sed -e '4,$d' -e 's/^/I: /'
fi
# look for complaints from rpz.c and query.c
EMSGS=`grep -l 'rpz .*failed' */*.run`
if test -n "$EMSGS"; then
setret "I:'rpz failed' complaints in $EMSGS starting with:"
grep 'rpz .*failed' */*.run | sed -e '4,$d' -e 's/^/I: /'
fi
fi
status=`expr $status + $ret`
ckalive "I:failed; server crashed"
GROUP_NM=
}
# $1=dig args $2=other dig output file
ckresult () {
#ckalive "I:server crashed by 'dig $1'" || return 1
if $PERL ../digcomp.pl $DIGNM $2 >/dev/null; then
#ckalive "$1" "I:server crashed by 'dig $1'" || return 1
if $PERL $SYSTEMTESTTOP/digcomp.pl $DIGNM $2 >/dev/null; then
rm -f ${DIGNM}*
return 0
fi
@ -132,8 +176,8 @@ ckresult () {
# check only that the server does not crash
# $1=target domain $2=optional query type
nocrash () {
digcmd $* @$ns3 >/dev/null
ckalive "I:server crashed by 'dig $*'"
digcmd $* >/dev/null
ckalive "$*" "I:server crashed by 'dig $*'"
}
@ -141,8 +185,10 @@ nocrash () {
# $1=target domain $2=optional query type
nxdomain () {
make_dignm
digcmd +noauth $* @$ns3 \
| sed -e 's/^[a-z].* IN CNAME /;xxx &/' >$DIGNM
digcmd $* \
| sed -e 's/^[a-z].* IN CNAME /;xxx &/' \
-e 's/^[a-z].* IN RRSIG /;xxx &/' \
>$DIGNM
ckresult "$*" proto.nxdomain
}
@ -150,33 +196,37 @@ nxdomain () {
# $1=target domain $2=optional query type
nodata () {
make_dignm
digcmd +noauth $* @$ns3 \
digcmd $* \
| sed -e 's/^[a-z].* IN CNAME /;xxx &/' >$DIGNM
ckresult "$*" proto.nodata
}
# check rewrite to an address
# modify the output so that it is easily compared, but save the original line
# $1=IPv4 address, $2=target domain $3=optional query type
# $1=IPv4 address $2=digcmd args $3=optional TTL
addr () {
ADDR=$1
shift
ADDR_ESC=`echo "$ADDR" | sed -e 's/\./\\\\./g'`
make_dignm
digcmd +noauth $* @$ns3 >$DIGNM
#ckalive "I:server crashed by 'dig $*'" || return
if grep -i '^[a-z].* A '"$ADDR_ESC"'$' $DIGNM >/dev/null; then
rm -f ${DIGNM}*
return 0
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 A\{1,4\} ${ADDR_ESC}\$/\1/p" $DIGNM`
if test -z "$ADDR_TTL"; then
setret "I:'dig $2' wrong; no address $ADDR record in $DIGNM"
return 1
fi
setret "I:'dig $*' wrong; no A $ADDR record in $DIGNM $2"
if test -n "$3" && test "$ADDR_TTL" -ne "$3"; then
setret "I:'dig $2' wrong; TTL=$ADDR_TTL instead of $3 in $DIGNM"
return 1
fi
rm -f ${DIGNM}*
}
# check that a response is not rewritten
# $1=target domain $2=optional query type
nochange () {
make_dignm
digcmd $* @$ns3 >$DIGNM
digcmd $* >$DIGNM
digcmd $* @$ns2 >${DIGNM}_OK
ckresult "$*" ${DIGNM}_OK && rm -f ${DIGNM}_OK
}
@ -185,23 +235,23 @@ nochange () {
here () {
make_dignm
sed -e 's/^[ ]*//' >${DIGNM}_OK
digcmd $* @$ns3 >$DIGNM
digcmd $* >$DIGNM
ckresult "$*" ${DIGNM}_OK
}
# make prototype files to check against rewritten results
digcmd +noauth nonexistent @$ns2 >proto.nxdomain
digcmd +noauth txt-only.tld2 @$ns2 >proto.nodata
digcmd nonexistent @$ns2 >proto.nxdomain
digcmd txt-only.tld2 @$ns2 >proto.nodata
status=0
start_group "QNAME rewrites" test1
nochange .
nxdomain a0-1.tld2
nodata a3-1.tld2
nodata a3-2.tld2
nodata sub.a3-2.tld2 # 5 no crash on DNAME
nochange . # 1 do not crash or rewrite root
nxdomain a0-1.tld2 # 2
nodata a3-1.tld2 # 3
nodata a3-2.tld2 # 4 no crash on DNAME
nodata sub.a3-2.tld2
nxdomain a4-2.tld2 # 6 rewrite based on CNAME target
nxdomain a4-2-cname.tld2 # 7
nodata a4-3-cname.tld2 # 8
@ -209,32 +259,43 @@ addr 12.12.12.12 a4-1.sub1.tld2 # 9 A replacement
addr 12.12.12.12 a4-1.sub2.tld2 # 10 A replacement with wildcard
addr 12.12.12.12 nxc1.sub1.tld2 # 11 replace NXDOMAIN with CNAME
addr 12.12.12.12 nxc2.sub1.tld2 # 12 replace NXDOMAIN with CNAME chain
addr 127.0.0.1 a4-4.tld2 # 13 prefer 1st conflicting QNAME zone
addr 56.56.56.56 a3-6.tld2 # 14 wildcard CNAME
addr 57.57.57.57 a3-7.sub1.tld2 # 15 wildcard CNAME
addr 127.0.0.16 a4-5-cname3.tld2 # 16 CNAME chain
addr 127.0.0.17 a4-6-cname3.tld2 # 17 stop short in CNAME chain
nxdomain c1.crash2.tld3 # 18 assert in rbtdb.c
nochange a0-1.tld2 +norecurse
nxdomain a0-1.tld2 +dnssec
nxdomain a0-1.signed-tld2
nochange a0-1.signed-tld2 +dnssec
addr 127.4.4.1 a4-4.tld2 # 13 prefer 1st conflicting QNAME zone
nochange a6-1.tld2 # 14
addr 127.6.2.1 a6-2.tld2 # 15
addr 56.56.56.56 a3-6.tld2 # 16 wildcard CNAME
addr 57.57.57.57 a3-7.sub1.tld2 # 17 wildcard CNAME
addr 127.0.0.16 a4-5-cname3.tld2 # 18 CNAME chain
addr 127.0.0.17 a4-6-cname3.tld2 # 19 stop short in CNAME chain
nochange a0-1.tld2 +norecurse # 20 check that RD=1 is required
nochange a3-1.tld2 +norecurse # 21
nochange a3-2.tld2 +norecurse # 22
nochange sub.a3-2.tld2 +norecurse # 23
nxdomain c1.crash2.tld3 # 24 assert in rbtdb.c
nxdomain a0-1.tld2 +dnssec # 25 simple DO=1 without signatures
nxdomain a0-1.tld2s # 26 simple DO=0 with signatures
nochange a0-1.tld2s +dnssec # 27 simple DO=1 with signatures
nxdomain a0-1s-cname.tld2s +dnssec # 28 DNSSEC too early in CNAME chain
nochange a0-1-scname.tld2 +dnssec # 29 DNSSEC on target in CNAME chain
nochange a0-1.tld2s srv +auth +dnssec # 30 no write for +DNSSEC and no record
nxdomain a0-1.tld2s srv # 31
end_group
start_group "IP rewrites" test2
nodata a3-1.tld2
nochange a3-2.tld2
nochange a4-1.tld2
nxdomain a4-2.tld2
nochange a4-2.tld2 -taaaa
nochange a4-2.tld2 -ttxt
nxdomain a4-2.tld2 -tany
nodata a4-3.tld2
nxdomain a3-1.tld2 -tAAAA
nochange a4-1-aaaa.tld2 -tAAAA
nodata a3-1.tld2 # 1 NODATA
nochange a3-2.tld2 # 2 no policy record so no change
nochange a4-1.tld2 # 3 obsolete PASSTHRU record style
nxdomain a4-2.tld2 # 4
nochange a4-2.tld2 -taaaa # 5 no A => no policy rewrite
nochange a4-2.tld2 -ttxt # 6 no A => no policy rewrite
nxdomain a4-2.tld2 -tany # 7 no A => no policy rewrite
nodata a4-3.tld2 # 8
nxdomain a3-1.tld2 -taaaa # 9 IPv6 policy
nochange a4-1-aaaa.tld2 -taaaa # 10
addr 127.0.0.1 a5-1-2.tld2 # 11 prefer smallest policy address
addr 127.0.0.1 a5-3.tld2 # 12 prefer first conflicting IP zone
addr 14.14.14.14 a5-4.tld2 # 13 prefer QNAME to IP
nochange a5-4.tld2 +norecurse # 14 check that RD=1 is required
nochange a4-4.tld2 # 15 PASSTHRU
nxdomain c2.crash2.tld3 # 16 assert in rbtdb.c
end_group
@ -256,7 +317,7 @@ end_group
if ./rpz nsdname; then
start_group "NSDNAME rewrites" test3
nochange a3-1.tld2
nochange a3-1.tld2 +dnssec # 2 this once caused problems
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
@ -284,21 +345,29 @@ else
fi
# policies in ./test5 overridden by response-policy{} in ns3/named.conf
# and in ns5/named.conf
start_group "policy overrides" test5
addr 127.0.0.1 a3-1.tld2 # 1 bl-given
nochange a3-2.tld2 # 2 bl-passthru
nochange a3-3.tld2 # 3 bl-no-op obsolete for passthru
nochange a3-4.tld2 # 4 bl-disabled
nodata a3-5.tld2 # 5 bl-nodata
nxdomain a3-6.tld2 # 6 bl-nxdomain
here +noauth a3-7.tld2 -tany <<'EOF' # 7 bl_cname
nodata a3-5.tld2 +norecurse # 6 bl-nodata recursive-only no
nodata a3-5.tld2 # 7 bl-nodata
nodata a3-5.tld2 +norecurse @$ns5 # 8 bl-nodata recursive-only no
nodata a3-5.tld2s @$ns5 # 9 bl-nodata
nodata a3-5.tld2s +dnssec @$ns5 # 10 bl-nodata break-dnssec
nxdomain a3-6.tld2 # 11 bl-nxdomain
here a3-7.tld2 -tany <<'EOF'
;; status: NOERROR, x
a3-7.tld2. 300 IN CNAME txt-only.tld2.
txt-only.tld2. 120 IN TXT "txt-only-tld2"
a3-7.tld2. x IN CNAME txt-only.tld2.
txt-only.tld2. x IN TXT "txt-only-tld2"
EOF
addr 58.58.58.58 a3-8.tld2 # 8 bl_wildcname
addr 59.59.59.59 a3-9.sub9.tld2 # 9 bl_wildcname
addr 12.12.12.12 a3-10.tld2 # 10 bl-garden
addr 58.58.58.58 a3-8.tld2 # 13 bl_wildcname
addr 59.59.59.59 a3-9.sub9.tld2 # 14 bl_wildcname
addr 12.12.12.12 a3-15.tld2 # 15 bl-garden via CNAME to a12.tld2
addr 127.0.0.16 a3-16.tld2 100 # 16 bl max-policy-ttl 100
addr 17.17.17.17 "a3-17.tld2 @$ns5" 90 # 17 ns5 bl max-policy-ttl 90
end_group
# check that miscellaneous bugs are still absent
@ -312,12 +381,61 @@ for Q in RRSIG SIG ANY 'ANY +dnssec'; do
done
end_group
# restart the server to see if that creates a core file
if test -z "$HAVE_CORE"; then
$RNDCCMD halt
restart
test -s ns3/named.core && setret "I:found stray core file; memory leak?"
# superficial test for major performance bugs
QPERF=`sh qperf.sh`
if test -n "$QPERF"; then
perf () {
echo "I:checking performance $1"
# don't measure the costs of -d99
$RNDCCMD $ns5 notrace >/dev/null
$QPERF -1 -l2 -d ns5/requests -s $ns5 -p 5300 >ns5/$2.perf
ckalive $ns5 "I:failed; server #5 crashed"
}
trim () {
sed -n -e 's/.*Queries per second: *\([0-9]*\).*/\1/p' ns5/$1.perf
}
# Dry run to prime disk cache
# Otherwise a first test of either flavor is 25% low
perf 'to prime disk cache' rpz
# get queries/second with rpz
perf 'with rpz' rpz
# turn off rpz and measure queries/second again
# Don't wait for a clean stop. Clean stops of this server need seconds
# until the sockets are close. 5 or 10 seconds after that, the
# server really stops and deletes named.pid.
echo "# rpz off" >ns5/rpz-switch
PID=`cat ns5/named.pid`
test -z "$PID" || kill -9 "$PID"
$PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns5
perf 'without rpz' norpz
NORPZ=`trim norpz`
RPZ=`trim rpz`
echo "I:$RPZ qps with RPZ versus $NORPZ qps without"
# fail if RPZ costs more than 100%
NORPZ2=`expr "$NORPZ" / 2`
if test "$RPZ" -le "$NORPZ2"; then
echo "I:rpz $RPZ qps too far below non-RPZ $NORPZ qps"
status=`expr $status + 1`
fi
else
echo "I:performance not checked; queryperf not available"
fi
# restart the main test RPZ server to see if that creates a core file
if test -z "$HAVE_CORE"; then
$PERL $SYSTEMTESTTOP/stop.pl . ns3
restart 3
HAVE_CORE=`find ns* -name '*core*' -print`
test -z "$HAVE_CORE" || setret "I:found $HAVE_CORE; memory leak?"
fi
echo "I:exit status: $status"
exit $status

View file

@ -5313,7 +5313,11 @@ badresp:1,adberr:0,findfail:0,valfail:0]
<optional> resolver-query-timeout <replaceable>number</replaceable> ; </optional>
<optional> deny-answer-addresses { <replaceable>address_match_list</replaceable> } <optional> except-from { <replaceable>namelist</replaceable> } </optional>;</optional>
<optional> deny-answer-aliases { <replaceable>namelist</replaceable> } <optional> except-from { <replaceable>namelist</replaceable> } </optional>;</optional>
<optional> response-policy { <replaceable>zone_name</replaceable> <optional> policy given | disabled | passthru | nxdomain | nodata | cname <replaceable>domain</replaceable> </optional> ; } ; </optional>
<optional> response-policy { <replaceable>zone_name</replaceable>
<optional> policy given | disabled | passthru | nxdomain | nodata | cname <replaceable>domain</replaceable> </optional>
<optional> recursive-only <replaceable>yes_or_no</replaceable> </optional> <optional> max-policy-ttl <replaceable>number</replaceable> </optional> ;
} <optional> recursive-only <replaceable>yes_or_no</replaceable> </optional> <optional> max-policy-ttl <replaceable>number</replaceable> </optional>
<optional> break-dnssec <replaceable>yes_or_no</replaceable> </optional> ; </optional>
};
</programlisting>
@ -9446,17 +9450,15 @@ deny-answer-aliases { "example.net"; };
<sect3>
<title>Response Policy Zone (RPZ) Rewriting</title>
<para>
<acronym>BIND</acronym> 9 includes an intentionally limited
mechanism to modify DNS responses for recursive requests
somewhat similar to email anti-spam DNS blacklists.
<acronym>BIND</acronym> 9 includes a limited
mechanism to modify DNS responses for requests
analogous to email anti-spam DNS blacklists.
Responses can be changed to deny the existence of domains(NXDOMAIN),
deny the existence of IP addresses for domains (NODATA),
or contain other IP addresses or data.
</para>
<para>
The actions encoded in a response policy zone (RPZ) are applied
only to queries that ask for recursion (RD=1).
Response policy zones are named in the
<command>response-policy</command> option for the view or among the
global options if there is no response-policy option for the view.
@ -9467,22 +9469,21 @@ deny-answer-aliases { "example.net"; };
</para>
<para>
There are four kinds of RPZ records, QNAME, IP, NSIP,
Four policy triggers are encoded in RPZ records, QNAME, IP, NSIP,
and NSDNAME.
QNAME records are applied to query names of requests and targets
QNAME RPZ records triggered by query names of requests and targets
of CNAME records resolved to generate the response.
The owner name of a QNAME RPZ record is the query name relativized
to the RPZ.
</para>
<para>
The second kind of RPZ record, an IP policy record,
is triggered by addresses in A and AAAA records
for the ANSWER sections of responses.
IP policy records have owner names that are
subdomains of <userinput>rpz-ip</userinput> relativized to the
RPZ origin name and encode an IP address or address block.
IPv4 addresses are encoded as
The second kind of RPZ trigger is an IP address in an A and AAAA
record in the ANSWER section of a response.
IP address triggers are encoded in records that have owner names
that are subdomains of <userinput>rpz-ip</userinput> relativized
to the RPZ origin name and encode an IP address or address block.
IPv4 trigger addresses are represented as
<userinput>prefixlength.B4.B3.B2.B1.rpz-ip</userinput>.
The prefix length must be between 1 and 32.
All four bytes, B4, B3, B2, and B1, must be present.
@ -9501,43 +9502,45 @@ deny-answer-aliases { "example.net"; };
</para>
<para>
NSDNAME policy records match names of authoritative servers
for the query name, a parent of the query name, a CNAME,
or a parent of a CNAME.
NSDNAME triggers match names of authoritative servers
for the query name, a parent of the query name, a CNAME for
query name, or a parent of a CNAME.
They are encoded as subdomains of
<userinput>rpz-nsdomain</userinput> relativized
to the RPZ origin name.
</para>
<para>
NSIP policy records match IP addresses in A and AAAA RRsets
for domains that can be checked against NSDNAME policy records.
The are encoded like IP policies except as subdomains of
NSIP triggers match IP addresses in A and
AAAA RRsets for domains that can be checked against NSDNAME
policy records.
NSIP triggers are encoded like IP triggers except as subdomains of
<userinput>rpz-nsip</userinput>.
</para>
<para>
The query response is checked against all RPZs, so
two or more policy records can apply to a single response.
Because DNS responses can be rewritten according by at most a
single policy record, a single policy (other than
<command>DISABLED</command> policies) must be chosen.
Policies are chosen in the following order:
two or more policy records can be triggered by a response.
Because DNS responses can be rewritten according to at most one
policy record, a single record encoding an action (other than
<command>DISABLED</command> actions) must be chosen.
Triggers or the records that encode them are chosen in
the following order:
<itemizedlist>
<listitem>Among applicable zones, use the RPZ that appears first
in the response-policy option.
<listitem>Choose the triggered record in the zone that appears
first in the response-policy option.
</listitem>
<listitem>Prefer QNAME to IP to NSDNAME to NSIP policy records
in a single RPZ
<listitem>Prefer QNAME to IP to NSDNAME to NSIP triggers
in a single zone.
</listitem>
<listitem>Among applicable NSDNAME policy records, prefer the
policy record that matches the lexically smallest name
<listitem>Among NSDNAME triggers, prefer the
trigger that matches the smallest name under the DNSSEC ordering.
</listitem>
<listitem>Among IP or NSIP policy records, prefer the record
<listitem>Among IP or NSIP triggers, prefer the trigger
with the longest prefix.
</listitem>
<listitem>Among records with the same prefex length,
prefer the IP or NSIP policy record that matches
<listitem>Among triggers with the same prefex length,
prefer the IP or NSIP trigger that matches
the smallest IP address.
</listitem>
</itemizedlist>
@ -9545,8 +9548,8 @@ deny-answer-aliases { "example.net"; };
<para>
When the processing of a response is restarted to resolve
DNAME or CNAME records and an applicable policy record set has
not been found,
DNAME or CNAME records and a policy record set has
not been triggered,
all RPZs are again consulted for the DNAME or CNAME names
and addresses.
</para>
@ -9563,55 +9566,56 @@ deny-answer-aliases { "example.net"; };
</para>
<para>
RPZ record sets are special CNAME records or one or more
of any types of DNS record except DNAME or DNSSEC.
Except when a policy record is a CNAME, there can be more
more than one record and more than one type
in a set of policy records.
Except for three kinds of CNAME records that are illegal except
in policy zones, the records in a set are used in the response as if
their owner name were the query name. They are copied to the
response as dictated by their types.
RPZ record sets are sets of any types of DNS record except
DNAME or DNSSEC that encode actions or responses to queries.
<itemizedlist>
<listitem>A CNAME whose target is the root domain (.)
specifies the <command>NXDOMAIN</command> policy,
which generates an NXDOMAIN response.
<listitem>The <command>NXDOMAIN</command> response is encoded
by a CNAME whose target is the root domain (.)
</listitem>
<listitem>A CNAME whose target is the wildcard top-level
domain (*.) specifies the <command>NODATA</command> policy,
domain (*.) specifies the <command>NODATA</command> action,
which rewrites the response to NODATA or ANCOUNT=1.
</listitem>
<listitem>A CNAME whose target is a wildcard hostname such
as *.example.com is used normally after the astrisk (*)
<listitem>The <command>Local Data</command> action is
represented by a set ordinary DNS records that are used
to answer queries. Queries for record types not the
set are answered with NODATA.
A special form of local data is a CNAME whose target is a
wildcard such as *.example.com.
It is used as if were an ordinary CNAME after the astrisk (*)
has been replaced with the query name.
These records are usually resolved with ordinary CNAMEs
outside the policy zones. They can be useful for logging.
The purpose for this special form is query logging in the
walled garden's authority DNS server.
</listitem>
<listitem>The <command>PASSTHRU</command> policy is specified
by a CNAME whose target is the variable part of its own
owner name. It causes the response to not be rewritten
by a CNAME whose target is <command>rpz_passthru.</command>
It causes the response to not be rewritten
and is most often used to "poke holes" in policies for
CIDR blocks.
(A CNAME whose target is the variable part of its owner name
is an obsolete specification of the PASSTHRU policy.)
</listitem>
</itemizedlist>
</para>
<para>
The policies specified in individual records
in an RPZ can be overridden with a <command>policy</command> clause
in the <command>response-policy</command> option.
The actions specified in an RPZ can be overridden with a
<command>policy</command> clause in the
<command>response-policy</command> option.
An organization using an RPZ provided by another organization might
use this mechanism to redirect domains to its own walled garden.
<itemizedlist>
<listitem><command>GIVEN</command> says "do not override."
<listitem><command>GIVEN</command> says "do not override but
perform the action specified in the zone."
</listitem>
<listitem><command>DISABLED</command> causes policy records to do
nothing but log what they might have done.
The response to the DNS query will be written according to
any matching policy records that are not disabled.
Policy zones overridden with <command>DISABLED</command> should
appear first, because they will often not be logged
if a higher precedence policy is found first.
any triggered policy records that are not disabled.
Disabled policy zones should appear first,
because they will often not be logged
if a higher precedence trigger is found first.
</listitem>
<listitem><command>PASSTHRU</command> causes all policy records
to act as if they were CNAME records with targets the variable
@ -9630,6 +9634,37 @@ deny-answer-aliases { "example.net"; };
</itemizedlist>
</para>
<para>
By default, the actions encoded in an RPZ are applied
only to queries that ask for recursion (RD=1).
That default can be changed for a single RPZ or all RPZs in a view
with a <command>recursive-only no</command> clause.
This feature is useful for serving the same zone files
both inside and outside an RFC 1918 cloud and using RPZ to
delete answers that would otherwise contain RFC 1918 values
on the externally visible name server or view.
</para>
<para>
Also by default, RPZ actions are applied only to DNS requests that
either do not request DNSSEC metadata (DO=0) or when no DNSSEC
records are available for request name in the original zone (not
the response policy zone).
This default can be changed for all RPZs in a view with a
<command>break-dnssec yes</command> clause.
In that case, RPZ actions are applied regardless of DNSSEC.
The name of the clause option reflects the fact that results
rewritten by RPZ actions cannot verify.
</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
to a maximum value.
The <command>max-policy-ttl</command> clause changes that
maximum from its default of 5.
</para>
<para>
For example, you might use this option statement
</para>
@ -9652,7 +9687,7 @@ bad.domain.com A 10.0.0.1 ; redirect to a walled garden
AAAA 2001:2::1
; do not rewrite (PASSTHRU) OK.DOMAIN.COM
ok.domain.com CNAME ok.domain.com.
ok.domain.com CNAME rpz-passthru.
bzone.domain.com CNAME garden.example.com.
@ -9662,7 +9697,7 @@ bzone.domain.com CNAME garden.example.com.
; IP policy records that rewrite all answers for 127/8 except 127.0.0.1
8.0.0.0.127.rpz-ip CNAME .
32.1.0.0.127.rpz-ip CNAME 32.1.0.0.127. ; PASSTHRU for 127.0.0.1
32.1.0.0.127.rpz-ip CNAME rpz-passthru.
; NSDNAME and NSIP policy records
ns.domain.com.rpz-nsdname CNAME .

View file

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: db.c,v 1.99 2011/10/13 01:32:33 vjs Exp $ */
/* $Id: db.c,v 1.99.4.1 2011/10/23 20:12:07 vjs Exp $ */
/*! \file */
@ -1014,14 +1014,13 @@ dns_db_rpz_enabled(dns_db_t *db, dns_rpz_st_t *st)
(db->methods->rpz_enabled)(db, st);
}
isc_result_t
void
dns_db_rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
dns_rdataset_t *ardataset, dns_rpz_st_t *st,
dns_name_t *query_qname)
{
if (db->methods->rpz_findips == NULL)
return (ISC_R_NOTIMPLEMENTED);
return ((db->methods->rpz_findips)(rpz, rpz_type, zone, db, version,
ardataset, st, query_qname));
if (db->methods->rpz_findips != NULL)
(db->methods->rpz_findips)(rpz, rpz_type, zone, db, version,
ardataset, st, query_qname);
}

View file

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: db.h,v 1.107 2011/10/13 01:32:34 vjs Exp $ */
/* $Id: db.h,v 1.107.4.1 2011/10/23 20:12:08 vjs Exp $ */
#ifndef DNS_DB_H
#define DNS_DB_H 1
@ -173,7 +173,7 @@ typedef struct dns_dbmethods {
isc_boolean_t (*isdnssec)(dns_db_t *db);
dns_stats_t *(*getrrsetstats)(dns_db_t *db);
void (*rpz_enabled)(dns_db_t *db, dns_rpz_st_t *st);
isc_result_t (*rpz_findips)(dns_rpz_zone_t *rpz,
void (*rpz_findips)(dns_rpz_zone_t *rpz,
dns_rpz_type_t rpz_type,
dns_zone_t *zone, dns_db_t *db,
dns_dbversion_t *version,
@ -1545,7 +1545,7 @@ dns_db_rpz_enabled(dns_db_t *db, dns_rpz_st_t *st);
* DNS_RPZ_TYPE_NSDNAME records.
*/
isc_result_t
void
dns_db_rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
dns_rdataset_t *ardataset, dns_rpz_st_t *st,
@ -1562,10 +1562,6 @@ dns_db_rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
* \li 'ardataset' is an A or AAAA rdataset of addresses to check
* \li 'found' specifies the previous best match if any or
* or NULL, an empty name, 0, DNS_RPZ_POLICY_MISS, and 0
*
* Returns:
* \li #ISC_R_SUCCESS
* \li #ISC_R_UNEXPECTED
*/
ISC_LANG_ENDDECLS

View file

@ -30,6 +30,7 @@ ISC_LANG_BEGINDECLS
#define DNS_RPZ_IP_ZONE "rpz-ip"
#define DNS_RPZ_NSIP_ZONE "rpz-nsip"
#define DNS_RPZ_NSDNAME_ZONE "rpz-nsdname"
#define DNS_RPZ_PASSTHRU_ZONE "rpz-passthru"
typedef isc_uint8_t dns_rpz_cidr_bits_t;
@ -66,11 +67,14 @@ typedef struct dns_rpz_zone dns_rpz_zone_t;
struct dns_rpz_zone {
ISC_LINK(dns_rpz_zone_t) link;
int num;
int num; /* ordinal in list of policy zones */
dns_name_t origin; /* Policy zone name */
dns_name_t nsdname; /* DNS_RPZ_NSDNAME_ZONE.origin */
dns_rpz_policy_t policy; /* DNS_RPZ_POLICY_GIVEN or override */
dns_name_t passthru;/* DNS_RPZ_PASSTHRU_ZONE. */
dns_name_t cname; /* override value for ..._CNAME */
dns_ttl_t max_policy_ttl;
dns_rpz_policy_t policy; /* DNS_RPZ_POLICY_GIVEN or override */
isc_boolean_t recursive_only;
};
/*
@ -143,6 +147,7 @@ typedef struct {
} dns_rpz_st_t;
#define DNS_RPZ_TTL_DEFAULT 5
#define DNS_RPZ_MAX_TTL_DEFAULT DNS_RPZ_TTL_DEFAULT
/*
* So various response policy zone messages can be turned up or down.
@ -152,6 +157,7 @@ typedef struct {
#define DNS_RPZ_DEBUG_LEVEL1 ISC_LOG_DEBUG(1)
#define DNS_RPZ_DEBUG_LEVEL2 ISC_LOG_DEBUG(2)
#define DNS_RPZ_DEBUG_LEVEL3 ISC_LOG_DEBUG(3)
#define DNS_RPZ_DEBUG_QUIET (DNS_RPZ_DEBUG_LEVEL3+1)
const char *
dns_rpz_type2str(dns_rpz_type_t type);
@ -192,7 +198,8 @@ dns_rpz_cidr_find(dns_rpz_cidr_t *cidr, const isc_netaddr_t *netaddr,
dns_name_t *search_name, dns_rpz_cidr_bits_t *prefix);
dns_rpz_policy_t
dns_rpz_decode_cname(dns_rdataset_t *, dns_name_t *selfname);
dns_rpz_decode_cname(dns_rpz_zone_t *rpz, dns_rdataset_t *rdataset,
dns_name_t *selfname);
ISC_LANG_ENDDECLS

View file

@ -162,6 +162,8 @@ struct dns_view {
dns_dns64list_t dns64;
unsigned int dns64cnt;
ISC_LIST(dns_rpz_zone_t) rpz_zones;
isc_boolean_t rpz_recursive_only;
isc_boolean_t rpz_break_dnssec;
/*
* Configurable data for server use only,

View file

@ -4572,7 +4572,7 @@ get_rpz_enabled(dns_db_t *db, dns_rpz_st_t *st)
* configured earlier than this policy zone and does not have a higher
* precedence type.
*/
static isc_result_t
static void
rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
dns_rdataset_t *ardataset, dns_rpz_st_t *st,
@ -4597,7 +4597,7 @@ rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
if (rbtdb->rpz_cidr == NULL) {
RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
return (ISC_R_UNEXPECTED);
return;
}
dns_fixedname_init(&selfnamef);
@ -4659,7 +4659,7 @@ rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
dns_name_format(qname, namebuf, sizeof(namebuf));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
"rpz_findips findnode(%s): %s",
"rpz_findips findnode(%s) failed: %s",
namebuf, isc_result_totext(result));
continue;
}
@ -4680,7 +4680,8 @@ rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
if (zrdataset.type != dns_rdatatype_cname) {
rpz_policy = DNS_RPZ_POLICY_RECORD;
} else {
rpz_policy = dns_rpz_decode_cname(&zrdataset,
rpz_policy = dns_rpz_decode_cname(rpz,
&zrdataset,
selfname);
if (rpz_policy == DNS_RPZ_POLICY_RECORD ||
rpz_policy == DNS_RPZ_POLICY_WILDCNAME)
@ -4738,7 +4739,7 @@ rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
st->m.type = rpz_type;
st->m.prefix = prefix;
st->m.policy = rpz_policy;
st->m.ttl = ttl;
st->m.ttl = ISC_MIN(ttl, rpz->max_policy_ttl);
st->m.result = result;
dns_name_copy(qname, st->qname, NULL);
if ((rpz_policy == DNS_RPZ_POLICY_RECORD ||
@ -4755,7 +4756,6 @@ rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
}
RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
return (ISC_R_SUCCESS);
}
#endif

View file

@ -118,9 +118,9 @@ struct dns_rpz_cidr {
isc_mem_t *mctx;
isc_boolean_t have_nsdname; /* zone has NSDNAME record */
dns_rpz_cidr_node_t *root;
dns_name_t ip_name; /* RPZ_IP_ZONE.LOCALHOST. */
dns_name_t nsip_name; /* RPZ_NSIP_ZONE.LOCALHOST. */
dns_name_t nsdname_name; /* RPZ_NSDNAME_ZONE.LOCALHOST */
dns_name_t ip_name; /* RPZ_IP_ZONE.origin. */
dns_name_t nsip_name; /* RPZ_NSIP_ZONE.origin. */
dns_name_t nsdname_name; /* RPZ_NSDNAME_ZONE.origin */
};
static isc_boolean_t have_rpz_zones = ISC_FALSE;
@ -183,7 +183,7 @@ dns_rpz_policy2str(dns_rpz_policy_t policy) {
str = "NODATA";
break;
case DNS_RPZ_POLICY_RECORD:
str = "records";
str = "Local-Data";
break;
case DNS_RPZ_POLICY_CNAME:
case DNS_RPZ_POLICY_WILDCNAME:
@ -255,6 +255,8 @@ dns_rpz_view_destroy(dns_view_t *view) {
ISC_LIST_UNLINK(view->rpz_zones, zone, link);
if (dns_name_dynamic(&zone->origin))
dns_name_free(&zone->origin, view->mctx);
if (dns_name_dynamic(&zone->passthru))
dns_name_free(&zone->passthru, view->mctx);
if (dns_name_dynamic(&zone->nsdname))
dns_name_free(&zone->nsdname, view->mctx);
if (dns_name_dynamic(&zone->cname))
@ -427,14 +429,16 @@ new_node(dns_rpz_cidr_t *cidr, const dns_rpz_cidr_key_t *ip,
}
static void
badname(int level, dns_name_t *name, const char *comment) {
badname(int level, dns_name_t *name, const char *str1, const char *str2) {
char printname[DNS_NAME_FORMATSIZE];
if (isc_log_wouldlog(dns_lctx, level)) {
if (level < DNS_RPZ_DEBUG_QUIET
&& isc_log_wouldlog(dns_lctx, level)) {
dns_name_format(name, printname, sizeof(printname));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
DNS_LOGMODULE_RBTDB, level,
"invalid rpz \"%s\"%s", printname, comment);
"invalid rpz IP address \"%s\"%s%s",
printname, str1, str2);
}
}
@ -566,11 +570,11 @@ name2ipkey(dns_rpz_cidr_t *cidr, int level, dns_name_t *src_name,
dns_rpz_type_t type, dns_rpz_cidr_key_t *tgt_ip,
dns_rpz_cidr_bits_t *tgt_prefix)
{
isc_buffer_t buffer;
unsigned char data[DNS_NAME_MAXWIRE+1];
isc_result_t result;
dns_fixedname_t fname;
dns_name_t *name;
const char *cp, *end;
dns_name_t *ipname;
char ipstr[DNS_NAME_FORMATSIZE];
const char *prefix_str, *cp, *end;
char *cp2;
int ip_labels;
dns_rpz_cidr_bits_t bits;
@ -585,37 +589,43 @@ name2ipkey(dns_rpz_cidr_t *cidr, int level, dns_name_t *src_name,
ip_labels -= dns_name_countlabels(&cidr->ip_name);
ip_labels--;
if (ip_labels < 1) {
badname(level, src_name, ", too short");
badname(level, src_name, "; too short", "");
return (ISC_R_FAILURE);
}
/*
* Get text for the IP address without RPZ_x_ZONE.rpz.LOCALHOST.
* Get text for the IP address
*/
dns_fixedname_init(&fname);
name = dns_fixedname_name(&fname);
ipname = dns_fixedname_name(&fname);
dns_name_split(src_name, dns_name_countlabels(&cidr->ip_name),
name, NULL);
isc_buffer_init(&buffer, data, sizeof(data));
dns_name_totext(name, ISC_TRUE, &buffer);
isc_buffer_putuint8(&buffer, '\0');
cp = isc_buffer_base(&buffer);
ipname, NULL);
dns_name_format(ipname, ipstr, sizeof(ipstr));
end = &ipstr[strlen(ipstr)+1];
prefix_str = ipstr;
prefix = strtoul(cp, &cp2, 10);
if (prefix < 1U || prefix > 128U || *cp2 != '.') {
badname(level, src_name, ", bad prefix length");
prefix = strtoul(prefix_str, &cp2, 10);
if (*cp2 != '.') {
badname(level, src_name,
"; invalid leading prefix length", "");
return (ISC_R_FAILURE);
}
*cp2 = '\0';
if (prefix < 1U || prefix > 128U) {
badname(level, src_name,
"; invalid prefix length of ", prefix_str);
return (ISC_R_FAILURE);
}
cp = cp2+1;
end = isc_buffer_used(&buffer);
if (ip_labels == 4 && !strchr(cp, 'z')) {
/*
* Convert an IPv4 address
* from the form "prefix.w.z.y.x"
*/
if (prefix > 32U) {
badname(level, src_name, "; bad IPv4 prefix length");
badname(level, src_name,
"; invalid IPv4 prefix length of ", prefix_str);
return (ISC_R_FAILURE);
}
prefix += 96;
@ -627,7 +637,10 @@ name2ipkey(dns_rpz_cidr_t *cidr, int level, dns_name_t *src_name,
for (i = 0; i < 32; i += 8) {
l = strtoul(cp, &cp2, 10);
if (l > 255U || (*cp2 != '.' && *cp2 != '\0')) {
badname(level, src_name, "; bad IPv4 address");
if (*cp2 == '.')
*cp2 = '\0';
badname(level, src_name,
"; invalid IPv4 octet ", cp);
return (ISC_R_FAILURE);
}
tgt_ip->w[3] |= l << i;
@ -654,7 +667,10 @@ name2ipkey(dns_rpz_cidr_t *cidr, int level, dns_name_t *src_name,
l = strtoul(cp, &cp2, 16);
if (l > 0xffffu ||
(*cp2 != '.' && *cp2 != '\0')) {
badname(level, src_name, "");
if (*cp2 == '.')
*cp2 = '\0';
badname(level, src_name,
"; invalid IPv6 word ", cp);
return (ISC_R_FAILURE);
}
if ((i & 1) == 0)
@ -667,7 +683,7 @@ name2ipkey(dns_rpz_cidr_t *cidr, int level, dns_name_t *src_name,
}
}
if (cp != end) {
badname(level, src_name, "");
badname(level, src_name, "", "");
return (ISC_R_FAILURE);
}
@ -681,7 +697,8 @@ name2ipkey(dns_rpz_cidr_t *cidr, int level, dns_name_t *src_name,
i = bits % DNS_RPZ_CIDR_WORD_BITS;
aword = tgt_ip->w[bits / DNS_RPZ_CIDR_WORD_BITS];
if ((aword & ~DNS_RPZ_WORD_MASK(i)) != 0) {
badname(level, src_name, "; wrong prefix length");
badname(level, src_name,
"; too small prefix length of ", prefix_str);
return (ISC_R_FAILURE);
}
bits -= i;
@ -689,13 +706,13 @@ name2ipkey(dns_rpz_cidr_t *cidr, int level, dns_name_t *src_name,
}
/*
* Convert the IPv6 address back to a canonical policy domain name
* Convert the address back to a canonical policy domain name
* to ensure that it is in canonical form.
*/
if (ISC_R_SUCCESS != ip2name(cidr, tgt_ip, (dns_rpz_cidr_bits_t)prefix,
type, NULL, name) ||
!dns_name_equal(src_name, name)) {
badname(level, src_name, "; not canonical");
result = ip2name(cidr, tgt_ip, (dns_rpz_cidr_bits_t) prefix,
type, NULL, ipname);
if (result != ISC_R_SUCCESS || !dns_name_equal(src_name, ipname)) {
badname(level, src_name, "; not canonical", "");
return (ISC_R_FAILURE);
}
@ -934,6 +951,7 @@ search(dns_rpz_cidr_t *cidr, const dns_rpz_cidr_key_t *tgt_ip,
*/
void
dns_rpz_cidr_addip(dns_rpz_cidr_t *cidr, dns_name_t *name) {
isc_result_t result;
dns_rpz_cidr_key_t tgt_ip;
dns_rpz_cidr_bits_t tgt_prefix;
dns_rpz_type_t type;
@ -956,19 +974,22 @@ dns_rpz_cidr_addip(dns_rpz_cidr_t *cidr, dns_name_t *name) {
case DNS_RPZ_TYPE_BAD:
return;
}
if (ISC_R_SUCCESS != name2ipkey(cidr, DNS_RPZ_ERROR_LEVEL, name,
type, &tgt_ip, &tgt_prefix))
result = name2ipkey(cidr, DNS_RPZ_ERROR_LEVEL, name,
type, &tgt_ip, &tgt_prefix);
if (result != ISC_R_SUCCESS)
return;
if (ISC_R_EXISTS == search(cidr, &tgt_ip, tgt_prefix, type,
ISC_TRUE, NULL) &&
isc_log_wouldlog(dns_lctx, DNS_RPZ_ERROR_LEVEL)) {
result = search(cidr, &tgt_ip, tgt_prefix, type, ISC_TRUE, NULL);
if (result == ISC_R_EXISTS &&
isc_log_wouldlog(dns_lctx, DNS_RPZ_ERROR_LEVEL))
{
char printname[DNS_NAME_FORMATSIZE];
dns_name_format(name, printname, sizeof(printname));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
"duplicate rpz name \"%s\"", printname);
"rpz add failed; \"%s\" is a duplicate name",
printname);
}
}
@ -978,6 +999,7 @@ dns_rpz_cidr_addip(dns_rpz_cidr_t *cidr, dns_name_t *name) {
*/
void
dns_rpz_cidr_deleteip(dns_rpz_cidr_t *cidr, dns_name_t *name) {
isc_result_t result;
dns_rpz_cidr_key_t tgt_ip;
dns_rpz_cidr_bits_t tgt_prefix;
dns_rpz_type_t type;
@ -1010,19 +1032,14 @@ dns_rpz_cidr_deleteip(dns_rpz_cidr_t *cidr, dns_name_t *name) {
/*
* Do not get excited about the deletion of interior rbt nodes.
*/
if (ISC_R_SUCCESS != name2ipkey(cidr, DNS_RPZ_DEBUG_LEVEL3, name,
type, &tgt_ip, &tgt_prefix))
result = name2ipkey(cidr, DNS_RPZ_DEBUG_QUIET, name,
type, &tgt_ip, &tgt_prefix);
if (result != ISC_R_SUCCESS)
return;
if (ISC_R_SUCCESS != search(cidr, &tgt_ip, tgt_prefix, type,
ISC_FALSE, &tgt)) {
if (isc_log_wouldlog(dns_lctx, DNS_RPZ_ERROR_LEVEL)) {
char printname[DNS_NAME_FORMATSIZE];
dns_name_format(name, printname, sizeof(printname));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
"missing rpz node \"%s\"", printname);
}
result = search(cidr, &tgt_ip, tgt_prefix, type, ISC_FALSE, &tgt);
if (result != ISC_R_SUCCESS) {
badname(DNS_RPZ_ERROR_LEVEL, name, "; missing rpz node", "");
return;
}
@ -1135,7 +1152,9 @@ dns_rpz_cidr_find(dns_rpz_cidr_t *cidr, const isc_netaddr_t *netaddr,
* Translate CNAME rdata to a QNAME response policy action.
*/
dns_rpz_policy_t
dns_rpz_decode_cname(dns_rdataset_t *rdataset, dns_name_t *selfname) {
dns_rpz_decode_cname(dns_rpz_zone_t *rpz, dns_rdataset_t *rdataset,
dns_name_t *selfname)
{
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_cname_t cname;
isc_result_t result;
@ -1171,7 +1190,13 @@ dns_rpz_decode_cname(dns_rdataset_t *rdataset, dns_name_t *selfname) {
}
/*
* 128.1.0.127.rpz-ip CNAME 128.1.0.0.127. means "do not rewrite"
* CNAME PASSTHRU.origin means "do not rewrite.
*/
if (dns_name_equal(&cname.cname, &rpz->passthru))
return (DNS_RPZ_POLICY_PASSTHRU);
/*
* 128.1.0.127.rpz-ip CNAME 128.1.0.0.127. is obsolete PASSTHRU
*/
if (selfname != NULL && dns_name_equal(&cname.cname, selfname))
return (DNS_RPZ_POLICY_PASSTHRU);

View file

@ -192,6 +192,8 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
view->v4_aaaa = dns_v4_aaaa_ok;
view->v4_aaaa_acl = NULL;
ISC_LIST_INIT(view->rpz_zones);
view->rpz_recursive_only = ISC_TRUE;
view->rpz_break_dnssec = ISC_FALSE;
dns_fixedname_init(&view->dlv_fixed);
view->managed_keys = NULL;
view->redirect = NULL;

View file

@ -1025,66 +1025,60 @@ static cfg_type_t cfg_type_masterformat = {
/*
/*%
* response-policy {
* zone <string> [ policy (given|disabled|passthru|
* nxdomain|nodata|cname <domain> ) ];
* };
*
* this is a chimera of doc_optional_keyvalue() and cfg_doc_enum()
* nxdomain|nodata|cname <domain> ) ]
* [ recursive-only yes|no ]
* [ max-policy-ttl number ] ;
* } [ recursive-only yes|no ] [ break-dnssec yes|no ]
* [ max-policy-ttl number ] ;
*/
static void
doc_rpz_policies(cfg_printer_t *pctx, const cfg_type_t *type) {
const keyword_type_t *kw;
doc_rpz_policy(cfg_printer_t *pctx, const cfg_type_t *type) {
const char * const *p;
kw = type->of;
cfg_print_chars(pctx, "[ ", 2);
cfg_print_cstr(pctx, kw->name);
cfg_print_chars(pctx, " ", 1);
/*
* This is cfg_doc_enum() without the trailing " )".
*/
cfg_print_chars(pctx, "( ", 2);
for (p = kw->type->of; *p != NULL; p++) {
for (p = type->of; *p != NULL; p++) {
cfg_print_cstr(pctx, *p);
if (p[1] != NULL)
cfg_print_chars(pctx, " | ", 3);
}
}
/*
* print_qstring() from parser.c
*/
static void
print_rpz_cname(cfg_printer_t *pctx, const cfg_obj_t *obj)
{
cfg_print_chars(pctx, "\"", 1);
cfg_print_ustring(pctx, obj);
cfg_print_chars(pctx, "\"", 1);
}
static void
doc_rpz_cname(cfg_printer_t *pctx, const cfg_type_t *type) {
cfg_doc_terminal(pctx, type);
cfg_print_chars(pctx, " ) ]", 4);
cfg_print_chars(pctx, " )", 2);
}
/*
* Parse
* given|disabled|passthru|nxdomain|nodata|cname <domain>
*/
static isc_result_t
parse_rpz(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
cfg_parse_rpz_policy(cfg_parser_t *pctx, const cfg_type_t *type,
cfg_obj_t **ret)
{
isc_result_t result;
cfg_obj_t *obj = NULL;
const cfg_tuplefielddef_t *fields = type->of;
cfg_obj_t *obj;
const cfg_tuplefielddef_t *fields;
CHECK(cfg_create_tuple(pctx, type, &obj));
fields = type->of;
CHECK(cfg_parse_obj(pctx, fields[0].type, &obj->value.tuple[0]));
CHECK(cfg_parse_obj(pctx, fields[1].type, &obj->value.tuple[1]));
/*
* parse cname domain only after "policy cname"
*/
if (cfg_obj_isvoid(obj->value.tuple[1]) ||
strcasecmp("cname", cfg_obj_asstring(obj->value.tuple[1]))) {
CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[2]));
if (strcasecmp("cname", cfg_obj_asstring(obj->value.tuple[0])) != 0) {
CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[1]));
} else {
CHECK(cfg_parse_obj(pctx, fields[2].type, &obj->value.tuple[2]));
CHECK(cfg_parse_obj(pctx, fields[1].type,
&obj->value.tuple[1]));
}
*ret = obj;
@ -1095,48 +1089,158 @@ cleanup:
return (result);
}
/*
* Parse a tuple consisting of any kind of required field followed
* by 2 or more optional keyvalues that can be in any order.
*/
static isc_result_t
cfg_parse_kv_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
const cfg_tuplefielddef_t *fields, *f;
cfg_obj_t *obj;
int fn;
isc_result_t result;
obj = NULL;
CHECK(cfg_create_tuple(pctx, type, &obj));
/*
* The zone first field is required and always first.
*/
fields = type->of;
CHECK(cfg_parse_obj(pctx, fields[0].type, &obj->value.tuple[0]));
for (;;) {
CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
if (pctx->token.type != isc_tokentype_string)
break;
for (fn = 1, f = &fields[1]; ; ++fn, ++f) {
if (f->name == NULL) {
cfg_parser_error(pctx, 0, "unexpected '%s'",
TOKEN_STRING(pctx));
result = ISC_R_UNEXPECTEDTOKEN;
goto cleanup;
}
if (obj->value.tuple[fn] == NULL &&
strcasecmp(f->name, TOKEN_STRING(pctx)) == 0)
break;
}
CHECK(cfg_gettoken(pctx, 0));
CHECK(cfg_parse_obj(pctx, f->type, &obj->value.tuple[fn]));
}
for (fn = 1, f = &fields[1]; f->name != NULL; ++fn, ++f) {
if (obj->value.tuple[fn] == NULL)
CHECK(cfg_parse_void(pctx, NULL,
&obj->value.tuple[fn]));
}
*ret = obj;
return (ISC_R_SUCCESS);
cleanup:
CLEANUP_OBJ(obj);
return (result);
}
static void
cfg_print_kv_tuple(cfg_printer_t *pctx, const cfg_obj_t *obj) {
unsigned int i;
const cfg_tuplefielddef_t *fields, *f;
const cfg_obj_t *fieldobj;
fields = obj->type->of;
for (f = fields, i = 0; f->name != NULL; f++, i++) {
fieldobj = obj->value.tuple[i];
if (fieldobj->type->print == cfg_print_void)
continue;
if (i != 0) {
cfg_print_chars(pctx, " ", 1);
cfg_print_cstr(pctx, f->name);
cfg_print_chars(pctx, " ", 1);
}
cfg_print_obj(pctx, fieldobj);
}
}
static void
cfg_doc_kv_tuple(cfg_printer_t *pctx, const cfg_type_t *type) {
const cfg_tuplefielddef_t *fields, *f;
fields = type->of;
for (f = fields; f->name != NULL; f++) {
if (f != fields) {
cfg_print_chars(pctx, " [ ", 3);
cfg_print_cstr(pctx, f->name);
if (f->type->doc != cfg_doc_void)
cfg_print_chars(pctx, " ", 1);
}
cfg_doc_obj(pctx, f->type);
if (f != fields)
cfg_print_chars(pctx, " ]", 2);
}
}
static keyword_type_t zone_kw = {"zone", &cfg_type_qstring};
static cfg_type_t cfg_type_rpz_zone = {
"zone", parse_keyvalue, print_keyvalue,
doc_keyvalue, &cfg_rep_string,
&zone_kw
};
static const char *rpz_policies[] = {
"given", "disabled", "passthru", "no-op", "nxdomain", "nodata",
"cname", NULL
};
static cfg_type_t cfg_type_rpz_policylist = {
"policies", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
&cfg_rep_string, &rpz_policies
static cfg_type_t cfg_type_rpz_policy_name = {
"policy name", cfg_parse_enum, cfg_print_ustring,
doc_rpz_policy, &cfg_rep_string,
&rpz_policies
};
static keyword_type_t rpz_policies_kw = {
"policy", &cfg_type_rpz_policylist
};
static cfg_type_t cfg_type_rpz_policy = {
"optional_policy", parse_optional_keyvalue, print_keyvalue,
doc_rpz_policies, &cfg_rep_string, &rpz_policies_kw
};
static cfg_type_t cfg_type_cname = {
"domain", cfg_parse_astring, print_rpz_cname, doc_rpz_cname,
&cfg_rep_string, NULL
};
static cfg_tuplefielddef_t rpzone_fields[] = {
{ "name", &cfg_type_astring, 0 },
{ "policy", &cfg_type_rpz_policy, 0 },
{ "cname", &cfg_type_cname, 0 },
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_type_rpzone = {
"rpzone", parse_rpz, cfg_print_tuple, cfg_doc_tuple,
&cfg_rep_tuple, rpzone_fields
};
static cfg_clausedef_t rpz_clauses[] = {
{ "zone", &cfg_type_rpzone, CFG_CLAUSEFLAG_MULTI },
{ NULL, NULL, 0 }
};
static cfg_clausedef_t *rpz_clausesets[] = {
rpz_clauses,
static cfg_type_t cfg_type_rpz_cname = {
"quoted_string", cfg_parse_astring, NULL,
doc_rpz_cname, &cfg_rep_string,
NULL
};
static cfg_type_t cfg_type_rpz = {
"rpz", cfg_parse_map, cfg_print_map, cfg_doc_map,
&cfg_rep_map, rpz_clausesets
static cfg_tuplefielddef_t rpz_policy_fields[] = {
{ "policy name", &cfg_type_rpz_policy_name, 0 },
{ "cname", &cfg_type_rpz_cname, 0 },
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_type_rpz_policy = {
"policy tuple", cfg_parse_rpz_policy,
cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
rpz_policy_fields
};
static cfg_tuplefielddef_t rpz_zone_fields[] = {
{ "zone name", &cfg_type_rpz_zone, 0 },
{ "policy", &cfg_type_rpz_policy, 0 },
{ "recursive-only", &cfg_type_boolean, 0 },
{ "max-policy-ttl", &cfg_type_uint32, 0 },
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_type_rpz_tuple = {
"rpz tuple", cfg_parse_kv_tuple,
cfg_print_kv_tuple, cfg_doc_kv_tuple, &cfg_rep_tuple,
rpz_zone_fields
};
static cfg_type_t cfg_type_rpz_list = {
"zone list", cfg_parse_bracketed_list, cfg_print_bracketed_list,
cfg_doc_bracketed_list, &cfg_rep_list,
&cfg_type_rpz_tuple
};
static cfg_tuplefielddef_t rpz_fields[] = {
{ "zone list", &cfg_type_rpz_list, 0 },
{ "recursive-only", &cfg_type_boolean, 0 },
{ "break-dnssec", &cfg_type_boolean, 0 },
{ "max-policy-ttl", &cfg_type_uint32, 0 },
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_type_rpz = {
"rpz", cfg_parse_kv_tuple,
cfg_print_kv_tuple, cfg_doc_kv_tuple, &cfg_rep_tuple,
rpz_fields
};
/*%

View file

@ -1137,6 +1137,7 @@
./bin/tests/system/rpz/clean.sh SH 2011,2012
./bin/tests/system/rpz/ns1/named.conf CONF-C 2011
./bin/tests/system/rpz/ns1/root.db ZONE 2011,2012
./bin/tests/system/rpz/ns2/base-tld2s.db ZONE 2012
./bin/tests/system/rpz/ns2/hints ZONE 2011
./bin/tests/system/rpz/ns2/named.conf CONF-C 2011,2012
./bin/tests/system/rpz/ns2/tld2.db ZONE 2011
@ -1145,9 +1146,12 @@
./bin/tests/system/rpz/ns3/crash2 X 2011
./bin/tests/system/rpz/ns3/hints ZONE 2011
./bin/tests/system/rpz/ns3/named.conf CONF-C 2011
./bin/tests/system/rpz/ns4/hints X 2011
./bin/tests/system/rpz/ns4/hints ZONE 2011
./bin/tests/system/rpz/ns4/named.conf CONF-C 2011
./bin/tests/system/rpz/ns4/tld4.db ZONE 2011
./bin/tests/system/rpz/ns5/hints ZONE 2011
./bin/tests/system/rpz/ns5/named.conf CONF-C 2012
./bin/tests/system/rpz/qperf.sh SH 2012
./bin/tests/system/rpz/rpz.c C 2011
./bin/tests/system/rpz/setup.sh SH 2011,2012
./bin/tests/system/rpz/test1 X 2011,2012