mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 14:07:59 +00:00
2604. [func] Add support for DNS rebinding attack prevention through
new options, deny-answer-addresses and deny-answer-aliases. Based on contributed code from JD Nurmi, Google. [RT #18192]
This commit is contained in:
parent
fc7ecc628d
commit
40d0f115a6
5
CHANGES
5
CHANGES
@ -1,3 +1,8 @@
|
||||
2604. [func] Add support for DNS rebinding attack prevention through
|
||||
new options, deny-answer-addresses and
|
||||
deny-answer-aliases. Based on contributed code from
|
||||
JD Nurmi, Google. [RT #18192]
|
||||
|
||||
2603. [port] win32: handle .exe extension of named-checkzone and
|
||||
named-comilezone argv[0] names under windows.
|
||||
[RT #19767]
|
||||
|
2
README
2
README
@ -54,6 +54,8 @@ BIND 9.7.0
|
||||
internal information about query failures, especially about
|
||||
server failures.
|
||||
|
||||
Add support for DNS rebinding attack prevention.
|
||||
|
||||
BIND 9.6.0
|
||||
|
||||
BIND 9.6.0 includes a number of changes from BIND 9.5 and earlier
|
||||
|
@ -1,25 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2009 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: bind.keys.h,v 1.3 2009/03/05 23:47:35 tbox Exp $ */
|
||||
|
||||
#define TRUSTED_KEYS "\
|
||||
trusted-keys {\n\
|
||||
# NOTE: This key expires September 2009 \n\
|
||||
# Go to https://www.isc.org/solutions/dlv to download a replacement\n\
|
||||
# NOTE: This key expires September 2009 \n\
|
||||
# Go to https://www.isc.org/solutions/dlv to download a replacement\n\
|
||||
dlv.isc.org. 257 3 5 \"BEAAAAPHMu/5onzrEE7z1egmhg/WPO0+juoZrW3euWEn4MxDCE1+lLy2 brhQv5rN32RKtMzX6Mj70jdzeND4XknW58dnJNPCxn8+jAGl2FZLK8t+ 1uq4W+nnA3qO2+DL+k6BD4mewMLbIYFwe0PG73Te9fZ2kJb56dhgMde5 ymX4BI/oQ+cAK50/xvJv00Frf8kw6ucMTwFlgPe+jnGxPPEmHAte/URk Y62ZfkLoBAADLHQ9IrS2tryAe7mbBZVcOwIeU/Rw/mRx/vwwMCTgNboM QKtUdvNXDrYJDSHZws3xiRXF1Rf+al9UmZfSav/4NWLKjHzpT59k/VSt TDN0YUuWrBNh\";\n\
|
||||
};\n\
|
||||
"
|
||||
|
@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: server.c,v 1.530 2009/03/04 23:48:01 tbox Exp $ */
|
||||
/* $Id: server.c,v 1.531 2009/05/29 22:22:35 jinmei Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@ -278,8 +278,8 @@ end_reserved_dispatches(ns_server_t *server, isc_boolean_t all);
|
||||
*/
|
||||
static isc_result_t
|
||||
configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config,
|
||||
const char *aclname, cfg_aclconfctx_t *actx,
|
||||
isc_mem_t *mctx, dns_acl_t **aclp)
|
||||
const char *aclname, const char *acltuplename,
|
||||
cfg_aclconfctx_t *actx, isc_mem_t *mctx, dns_acl_t **aclp)
|
||||
{
|
||||
isc_result_t result;
|
||||
const cfg_obj_t *maps[3];
|
||||
@ -305,13 +305,21 @@ configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config,
|
||||
*/
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
if (acltuplename != NULL) {
|
||||
/*
|
||||
* If the ACL is given in an optional tuple, retrieve it.
|
||||
* The parser should have ensured that a valid object be
|
||||
* returned.
|
||||
*/
|
||||
aclobj = cfg_tuple_get(aclobj, acltuplename);
|
||||
}
|
||||
|
||||
result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx,
|
||||
actx, mctx, 0, aclp);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
/*%
|
||||
* Configure a sortlist at '*aclp'. Essentially the same as
|
||||
* configure_view_acl() except it calls cfg_acl_fromconfig with a
|
||||
@ -355,6 +363,80 @@ configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config,
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config,
|
||||
const char *confname, const char *conftuplename,
|
||||
isc_mem_t *mctx, dns_rbt_t **rbtp)
|
||||
{
|
||||
isc_result_t result;
|
||||
const cfg_obj_t *maps[3];
|
||||
const cfg_obj_t *obj = NULL;
|
||||
const cfg_listelt_t *element;
|
||||
int i = 0;
|
||||
dns_fixedname_t fixed;
|
||||
dns_name_t *name;
|
||||
isc_buffer_t b;
|
||||
const char *str;
|
||||
const cfg_obj_t *nameobj;
|
||||
|
||||
if (*rbtp != NULL)
|
||||
dns_rbt_destroy(rbtp);
|
||||
if (vconfig != NULL)
|
||||
maps[i++] = cfg_tuple_get(vconfig, "options");
|
||||
if (config != NULL) {
|
||||
const cfg_obj_t *options = NULL;
|
||||
(void)cfg_map_get(config, "options", &options);
|
||||
if (options != NULL)
|
||||
maps[i++] = options;
|
||||
}
|
||||
maps[i] = NULL;
|
||||
|
||||
(void)ns_config_get(maps, confname, &obj);
|
||||
if (obj == NULL)
|
||||
/*
|
||||
* No value available. *rbtp == NULL.
|
||||
*/
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
if (conftuplename != NULL) {
|
||||
obj = cfg_tuple_get(obj, conftuplename);
|
||||
if (cfg_obj_isvoid(obj))
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
result = dns_rbt_create(mctx, NULL, NULL, rbtp);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
dns_fixedname_init(&fixed);
|
||||
name = dns_fixedname_name(&fixed);
|
||||
for (element = cfg_list_first(obj);
|
||||
element != NULL;
|
||||
element = cfg_list_next(element)) {
|
||||
nameobj = cfg_listelt_value(element);
|
||||
str = cfg_obj_asstring(nameobj);
|
||||
isc_buffer_init(&b, str, strlen(str));
|
||||
isc_buffer_add(&b, strlen(str));
|
||||
CHECK(dns_name_fromtext(name, &b, dns_rootname,
|
||||
ISC_FALSE, NULL));
|
||||
/*
|
||||
* We don't need the node data, but need to set dummy data to
|
||||
* avoid a partial match with an empty node. For example, if
|
||||
* we have foo.example.com and bar.example.com, we'd get a match
|
||||
* for baz.example.com, which is not the expected result.
|
||||
* We simply use (void *)1 as the dummy data.
|
||||
*/
|
||||
CHECK(dns_rbt_addname(*rbtp, name, (void *)1));
|
||||
}
|
||||
|
||||
return (result);
|
||||
|
||||
cleanup:
|
||||
dns_rbt_destroy(rbtp);
|
||||
return (result);
|
||||
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key,
|
||||
dns_keytable_t *keytable, isc_mem_t *mctx)
|
||||
@ -1722,10 +1804,10 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
|
||||
/*
|
||||
* Configure the "match-clients" and "match-destinations" ACL.
|
||||
*/
|
||||
CHECK(configure_view_acl(vconfig, config, "match-clients", actx,
|
||||
CHECK(configure_view_acl(vconfig, config, "match-clients", NULL, actx,
|
||||
ns_g_mctx, &view->matchclients));
|
||||
CHECK(configure_view_acl(vconfig, config, "match-destinations", actx,
|
||||
ns_g_mctx, &view->matchdestinations));
|
||||
CHECK(configure_view_acl(vconfig, config, "match-destinations", NULL,
|
||||
actx, ns_g_mctx, &view->matchdestinations));
|
||||
|
||||
/*
|
||||
* Configure the "match-recursive-only" option.
|
||||
@ -1797,20 +1879,20 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
|
||||
* "allow-recursion", and "allow-recursion-on" acls if
|
||||
* configured in named.conf.
|
||||
*/
|
||||
CHECK(configure_view_acl(vconfig, config, "allow-query-cache",
|
||||
CHECK(configure_view_acl(vconfig, config, "allow-query-cache", NULL,
|
||||
actx, ns_g_mctx, &view->queryacl));
|
||||
CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on",
|
||||
CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on", NULL,
|
||||
actx, ns_g_mctx, &view->queryonacl));
|
||||
if (view->queryonacl == NULL)
|
||||
CHECK(configure_view_acl(NULL, ns_g_config,
|
||||
"allow-query-cache-on", actx,
|
||||
"allow-query-cache-on", NULL, actx,
|
||||
ns_g_mctx, &view->queryonacl));
|
||||
if (strcmp(view->name, "_bind") != 0) {
|
||||
CHECK(configure_view_acl(vconfig, config, "allow-recursion",
|
||||
actx, ns_g_mctx,
|
||||
NULL, actx, ns_g_mctx,
|
||||
&view->recursionacl));
|
||||
CHECK(configure_view_acl(vconfig, config, "allow-recursion-on",
|
||||
actx, ns_g_mctx,
|
||||
NULL, actx, ns_g_mctx,
|
||||
&view->recursiononacl));
|
||||
}
|
||||
|
||||
@ -1823,7 +1905,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
|
||||
if (view->queryacl == NULL && view->recursionacl != NULL)
|
||||
dns_acl_attach(view->recursionacl, &view->queryacl);
|
||||
if (view->queryacl == NULL && view->recursion)
|
||||
CHECK(configure_view_acl(vconfig, config, "allow-query",
|
||||
CHECK(configure_view_acl(vconfig, config, "allow-query", NULL,
|
||||
actx, ns_g_mctx, &view->queryacl));
|
||||
if (view->recursion &&
|
||||
view->recursionacl == NULL && view->queryacl != NULL)
|
||||
@ -1835,19 +1917,20 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
|
||||
*/
|
||||
if (view->recursionacl == NULL && view->recursion)
|
||||
CHECK(configure_view_acl(NULL, ns_g_config,
|
||||
"allow-recursion",
|
||||
"allow-recursion", NULL,
|
||||
actx, ns_g_mctx,
|
||||
&view->recursionacl));
|
||||
if (view->recursiononacl == NULL && view->recursion)
|
||||
CHECK(configure_view_acl(NULL, ns_g_config,
|
||||
"allow-recursion-on",
|
||||
"allow-recursion-on", NULL,
|
||||
actx, ns_g_mctx,
|
||||
&view->recursiononacl));
|
||||
if (view->queryacl == NULL) {
|
||||
if (view->recursion)
|
||||
CHECK(configure_view_acl(NULL, ns_g_config,
|
||||
"allow-query-cache", actx,
|
||||
ns_g_mctx, &view->queryacl));
|
||||
"allow-query-cache", NULL,
|
||||
actx, ns_g_mctx,
|
||||
&view->queryacl));
|
||||
else {
|
||||
if (view->queryacl != NULL)
|
||||
dns_acl_detach(&view->queryacl);
|
||||
@ -1855,6 +1938,25 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Filter setting on addresses in the answer section.
|
||||
*/
|
||||
CHECK(configure_view_acl(vconfig, config, "deny-answer-addresses",
|
||||
"acl", actx, ns_g_mctx, &view->denyansweracl));
|
||||
CHECK(configure_view_nametable(vconfig, config, "deny-answer-addresses",
|
||||
"except-from", ns_g_mctx,
|
||||
&view->answeracl_exclude));
|
||||
|
||||
/*
|
||||
* Filter setting on names (CNAME/DNAME targets) in the answer section.
|
||||
*/
|
||||
CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases",
|
||||
"name", ns_g_mctx,
|
||||
&view->denyanswernames));
|
||||
CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases",
|
||||
"except-from", ns_g_mctx,
|
||||
&view->answernames_exclude));
|
||||
|
||||
/*
|
||||
* Configure sortlist, if set
|
||||
*/
|
||||
@ -1868,19 +1970,19 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
|
||||
*/
|
||||
if (view->notifyacl == NULL)
|
||||
CHECK(configure_view_acl(NULL, ns_g_config,
|
||||
"allow-notify", actx,
|
||||
"allow-notify", NULL, actx,
|
||||
ns_g_mctx, &view->notifyacl));
|
||||
if (view->transferacl == NULL)
|
||||
CHECK(configure_view_acl(NULL, ns_g_config,
|
||||
"allow-transfer", actx,
|
||||
"allow-transfer", NULL, actx,
|
||||
ns_g_mctx, &view->transferacl));
|
||||
if (view->updateacl == NULL)
|
||||
CHECK(configure_view_acl(NULL, ns_g_config,
|
||||
"allow-update", actx,
|
||||
"allow-update", NULL, actx,
|
||||
ns_g_mctx, &view->updateacl));
|
||||
if (view->upfwdacl == NULL)
|
||||
CHECK(configure_view_acl(NULL, ns_g_config,
|
||||
"allow-update-forwarding", actx,
|
||||
"allow-update-forwarding", NULL, actx,
|
||||
ns_g_mctx, &view->upfwdacl));
|
||||
|
||||
obj = NULL;
|
||||
@ -3301,7 +3403,7 @@ load_configuration(const char *filename, ns_server_t *server,
|
||||
else
|
||||
isc_quota_soft(&server->recursionquota, 0);
|
||||
|
||||
CHECK(configure_view_acl(NULL, config, "blackhole", &aclconfctx,
|
||||
CHECK(configure_view_acl(NULL, config, "blackhole", NULL, &aclconfctx,
|
||||
ns_g_mctx, &server->blackholeacl));
|
||||
if (server->blackholeacl != NULL)
|
||||
dns_dispatchmgr_setblackhole(ns_g_dispatchmgr,
|
||||
|
@ -15,7 +15,7 @@
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id: ans.pl,v 1.10 2007/09/24 04:13:25 marka Exp $
|
||||
# $Id: ans.pl,v 1.11 2009/05/29 22:22:36 jinmei Exp $
|
||||
|
||||
#
|
||||
# Ad hoc name server
|
||||
@ -52,6 +52,7 @@ for (;;) {
|
||||
|
||||
my @questions = $packet->question;
|
||||
my $qname = $questions[0]->qname;
|
||||
my $qtype = $questions[0]->qtype;
|
||||
|
||||
if ($qname eq "cname1.example.com") {
|
||||
# Data for the "cname + other data / 1" test
|
||||
@ -61,6 +62,32 @@ for (;;) {
|
||||
# Data for the "cname + other data / 2" test: same RRs in opposite order
|
||||
$packet->push("answer", new Net::DNS::RR("cname2.example.com 300 A 1.2.3.4"));
|
||||
$packet->push("answer", new Net::DNS::RR("cname2.example.com 300 CNAME cname2.example.com"));
|
||||
} elsif ($qname eq "www.example.org" || $qname eq "www.example.net" ||
|
||||
$qname eq "badcname.example.org" ||
|
||||
$qname eq "goodcname.example.org" ||
|
||||
$qname eq "foo.baddname.example.org" ||
|
||||
$qname eq "foo.gooddname.example.org") {
|
||||
# Data for address/alias filtering.
|
||||
if ($qtype eq "A") {
|
||||
$packet->push("answer",
|
||||
new Net::DNS::RR($qname .
|
||||
" 300 A 192.0.2.1"));
|
||||
} elsif ($qtype eq "AAAA") {
|
||||
$packet->push("answer",
|
||||
new Net::DNS::RR($qname .
|
||||
" 300 AAAA 2001:db8:beef::1"));
|
||||
}
|
||||
} elsif ($qname eq "badcname.example.net" ||
|
||||
$qname eq "goodcname.example.net") {
|
||||
# Data for CNAME/DNAME filtering. We need to make one-level
|
||||
# delegation to avoid automatic acceptance for subdomain aliases
|
||||
$packet->push("authority", new Net::DNS::RR("example.net 300 NS ns.example.net"));
|
||||
$packet->push("additional", new Net::DNS::RR("ns.example.net 300 A 10.53.0.3"));
|
||||
} elsif ($qname =~ /sub\.example\.org/) {
|
||||
# Data for CNAME/DNAME filtering. The final answers are
|
||||
# expected to be accepted regardless of the filter setting.
|
||||
$packet->push("authority", new Net::DNS::RR("sub.example.org 300 NS ns.sub.example.org"));
|
||||
$packet->push("additional", new Net::DNS::RR("ns.sub.example.org 300 A 10.53.0.3"));
|
||||
} else {
|
||||
# Data for the "bogus referrals" test
|
||||
$packet->push("authority", new Net::DNS::RR("below.www.example.com 300 NS ns.below.www.example.com"));
|
||||
|
@ -15,7 +15,7 @@
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id: ans.pl,v 1.9 2007/09/24 04:13:25 marka Exp $
|
||||
# $Id: ans.pl,v 1.10 2009/05/29 22:22:36 jinmei Exp $
|
||||
|
||||
#
|
||||
# Ad hoc name server
|
||||
@ -50,7 +50,42 @@ for (;;) {
|
||||
|
||||
$packet->header->qr(1);
|
||||
|
||||
$packet->push("answer", new Net::DNS::RR("www.example.com 300 A 1.2.3.4"));
|
||||
my @questions = $packet->question;
|
||||
my $qname = $questions[0]->qname;
|
||||
|
||||
if ($qname eq "badcname.example.net") {
|
||||
$packet->push("answer",
|
||||
new Net::DNS::RR($qname .
|
||||
" 300 CNAME badcname.example.org"));
|
||||
} elsif ($qname eq "foo.baddname.example.net") {
|
||||
$packet->push("answer",
|
||||
new Net::DNS::RR("baddname.example.net" .
|
||||
" 300 DNAME baddname.example.org"));
|
||||
} elsif ($qname eq "foo.gooddname.example.net") {
|
||||
$packet->push("answer",
|
||||
new Net::DNS::RR("gooddname.example.net" .
|
||||
" 300 DNAME gooddname.example.org"));
|
||||
} elsif ($qname eq "goodcname.example.net") {
|
||||
$packet->push("answer",
|
||||
new Net::DNS::RR($qname .
|
||||
" 300 CNAME goodcname.example.org"));
|
||||
} elsif ($qname eq "cname.sub.example.org") {
|
||||
$packet->push("answer",
|
||||
new Net::DNS::RR($qname .
|
||||
" 300 CNAME ok.sub.example.org"));
|
||||
} elsif ($qname eq "ok.sub.example.org") {
|
||||
$packet->push("answer",
|
||||
new Net::DNS::RR($qname . " 300 A 192.0.2.1"));
|
||||
} elsif ($qname eq "www.dname.sub.example.org") {
|
||||
$packet->push("answer",
|
||||
new Net::DNS::RR("dname.sub.example.org" .
|
||||
" 300 DNAME ok.sub.example.org"));
|
||||
} elsif ($qname eq "www.ok.sub.example.org") {
|
||||
$packet->push("answer",
|
||||
new Net::DNS::RR($qname . " 300 A 192.0.2.1"));
|
||||
} else {
|
||||
$packet->push("answer", new Net::DNS::RR("www.example.com 300 A 1.2.3.4"));
|
||||
}
|
||||
|
||||
$sock->send($packet->data);
|
||||
|
||||
|
@ -14,9 +14,10 @@
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id: clean.sh,v 1.1 2008/07/17 01:15:34 marka Exp $
|
||||
# $Id: clean.sh,v 1.2 2009/05/29 22:22:36 jinmei Exp $
|
||||
|
||||
#
|
||||
# Clean up after resolver tests.
|
||||
#
|
||||
rm -f */named.memstats
|
||||
rm -f dig.out
|
||||
|
@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: named.conf,v 1.13 2007/06/18 23:47:30 tbox Exp $ */
|
||||
/* $Id: named.conf,v 1.14 2009/05/29 22:22:36 jinmei Exp $ */
|
||||
|
||||
controls { /* empty */ };
|
||||
|
||||
@ -29,6 +29,11 @@ options {
|
||||
listen-on-v6 { none; };
|
||||
recursion yes;
|
||||
acache-enable yes;
|
||||
deny-answer-addresses { 192.0.2.0/24; 2001:db8:beef::/48; }
|
||||
except-from { "example.org"; };
|
||||
deny-answer-aliases { "example.org"; }
|
||||
except-from { "goodcname.example.net";
|
||||
"gooddname.example.net"; };
|
||||
};
|
||||
|
||||
zone "." {
|
||||
|
@ -15,7 +15,7 @@
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id: tests.sh,v 1.9 2007/06/19 23:47:05 tbox Exp $
|
||||
# $Id: tests.sh,v 1.10 2009/05/29 22:22:36 jinmei Exp $
|
||||
|
||||
SYSTEMTESTTOP=..
|
||||
. $SYSTEMTESTTOP/conf.sh
|
||||
@ -35,5 +35,75 @@ $DIG +tcp cname2.example.com. a @10.53.0.1 -p 5300 >/dev/null || status=1
|
||||
echo "I:check that server is still running"
|
||||
$DIG +tcp www.example.com. a @10.53.0.1 -p 5300 >/dev/null || status=1
|
||||
|
||||
echo "I:checking answer IPv4 address filtering (deny)"
|
||||
ret=0
|
||||
$DIG +tcp www.example.net @10.53.0.1 a -p 5300 > dig.out || ret=1
|
||||
grep "status: SERVFAIL" dig.out > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking answer IPv6 address filtering (deny)"
|
||||
ret=0
|
||||
$DIG +tcp www.example.net @10.53.0.1 aaaa -p 5300 > dig.out || ret=1
|
||||
grep "status: SERVFAIL" dig.out > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking answer IPv4 address filtering (accept)"
|
||||
ret=0
|
||||
$DIG +tcp www.example.org @10.53.0.1 a -p 5300 > dig.out || ret=1
|
||||
grep "status: NOERROR" dig.out > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking answer IPv6 address filtering (accept)"
|
||||
ret=0
|
||||
$DIG +tcp www.example.org @10.53.0.1 aaaa -p 5300 > dig.out || ret=1
|
||||
grep "status: NOERROR" dig.out > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking CNAME target filtering (deny)"
|
||||
ret=0
|
||||
$DIG +tcp badcname.example.net @10.53.0.1 a -p 5300 > dig.out || ret=1
|
||||
grep "status: SERVFAIL" dig.out > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking CNAME target filtering (accept)"
|
||||
ret=0
|
||||
$DIG +tcp goodcname.example.net @10.53.0.1 a -p 5300 > dig.out || ret=1
|
||||
grep "status: NOERROR" dig.out > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking CNAME target filtering (accept due to subdomain)"
|
||||
ret=0
|
||||
$DIG +tcp cname.sub.example.org @10.53.0.1 a -p 5300 > dig.out || ret=1
|
||||
grep "status: NOERROR" dig.out > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking DNAME target filtering (deny)"
|
||||
ret=0
|
||||
$DIG +tcp foo.baddname.example.net @10.53.0.1 a -p 5300 > dig.out || ret=1
|
||||
grep "status: SERVFAIL" dig.out > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking DNAME target filtering (accept)"
|
||||
ret=0
|
||||
$DIG +tcp foo.gooddname.example.net @10.53.0.1 a -p 5300 > dig.out || ret=1
|
||||
grep "status: NOERROR" dig.out > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking DNAME target filtering (accept due to subdomain)"
|
||||
ret=0
|
||||
$DIG +tcp www.dname.sub.example.org @10.53.0.1 a -p 5300 > dig.out || ret=1
|
||||
grep "status: NOERROR" dig.out > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:exit status: $status"
|
||||
exit $status
|
||||
|
@ -18,7 +18,7 @@
|
||||
- PERFORMANCE OF THIS SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- File: $Id: Bv9ARM-book.xml,v 1.409 2009/05/14 20:46:04 jreed Exp $ -->
|
||||
<!-- File: $Id: Bv9ARM-book.xml,v 1.410 2009/05/29 22:22:36 jinmei Exp $ -->
|
||||
<book xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<title>BIND 9 Administrator Reference Manual</title>
|
||||
|
||||
@ -2861,6 +2861,19 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
|
||||
</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row rowsep="0">
|
||||
<entry colname="1">
|
||||
<para>
|
||||
<varname>namelist</varname>
|
||||
</para>
|
||||
</entry>
|
||||
<entry colname="2">
|
||||
<para>
|
||||
A list of one or more <varname>domain_name</varname>
|
||||
elements.
|
||||
</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row rowsep="0">
|
||||
<entry colname="1">
|
||||
<para>
|
||||
@ -4951,6 +4964,8 @@ badresp:1,adberr:0,findfail:0,valfail:0]
|
||||
<optional> disable-empty-zone <replaceable>zone_name</replaceable> ; </optional>
|
||||
<optional> zero-no-soa-ttl <replaceable>yes_or_no</replaceable> ; </optional>
|
||||
<optional> zero-no-soa-ttl-cache <replaceable>yes_or_no</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>
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
@ -8426,6 +8441,142 @@ XXX: end of RFC1918 addresses #defined out -->
|
||||
|
||||
</sect3>
|
||||
|
||||
<sect3>
|
||||
<title>Content Filtering</title>
|
||||
<para>
|
||||
<acronym>BIND</acronym> 9 provides the ability to filter
|
||||
out DNS responses from external DNS servers containing
|
||||
certain types of data in the answer section.
|
||||
Specifically, it can reject address (A or AAAA) records if
|
||||
the corresponding IPv4 or IPv6 addresses match the given
|
||||
<varname>address_match_list</varname> of the
|
||||
<command>deny-answer-addresses</command> option.
|
||||
It can also reject CNAME or DNAME records if the "alias"
|
||||
name (i.e., the CNAME alias or the substituted query name
|
||||
due to DNAME) matches the
|
||||
given <varname>namelist</varname> of the
|
||||
<command>deny-answer-aliases</command> option, where
|
||||
"match" means the alias name is a subdomain of one of
|
||||
the <varname>name_list</varname> elements.
|
||||
If the optional <varname>namelist</varname> is specified
|
||||
with <command>except-from</command>, records whose query name
|
||||
matches the list will be accepted regardless of the filter
|
||||
setting.
|
||||
Likewise, if the alias name is a subdomain of the
|
||||
corresponding zone, the <command>deny-answer-aliases</command>
|
||||
filter will not apply;
|
||||
for example, even if "example.com" is specified for
|
||||
<command>deny-answer-aliases</command>,
|
||||
</para>
|
||||
<programlisting>www.example.com. CNAME xxx.example.com.</programlisting>
|
||||
|
||||
<para>
|
||||
returned by an "example.com" server will be accepted.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In the <varname>address_match_list</varname> of the
|
||||
<command>deny-answer-addresses</command> option, only
|
||||
<varname>ip_addr</varname>
|
||||
and <varname>ip_prefix</varname>
|
||||
are meaningful;
|
||||
any <varname>key_id</varname> will be silently ignored.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If a response message is rejected due to the filtering,
|
||||
the entire message is discarded without being cached, and
|
||||
a SERVFAIL error will be returned to the client.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This filtering is intended to prevent "DNS rebinding attacks," in
|
||||
which an attacker, in response to a query for a domain name the
|
||||
attacker controls, returns an IP address within your own network or
|
||||
an alias name within your own domain.
|
||||
A naive web browser or script could then serve as an
|
||||
unintended proxy, allowing the attacker
|
||||
to get access to an internal node of your local network
|
||||
that couldn't be externally accessed otherwise.
|
||||
See the paper available at
|
||||
<ulink>
|
||||
http://portal.acm.org/citation.cfm?id=1315245.1315298
|
||||
</ulink>
|
||||
for more details about the attacks.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For example, if you own a domain named "example.net" and
|
||||
your internal network uses an IPv4 prefix 192.0.2.0/24,
|
||||
you might specify the following rules:
|
||||
</para>
|
||||
|
||||
<programlisting>deny-answer-addresses { 192.0.2.0/24; } except-from { "example.net"; };
|
||||
deny-answer-aliases { "example.net"; };
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
If an external attacker lets a web browser in your local
|
||||
network look up an IPv4 address of "attacker.example.com",
|
||||
the attacker's DNS server would return a response like this:
|
||||
</para>
|
||||
|
||||
<programlisting>attacker.example.com. A 192.0.2.1</programlisting>
|
||||
|
||||
<para>
|
||||
in the answer section.
|
||||
Since the rdata of this record (the IPv4 address) matches
|
||||
the specified prefix 192.0.2.0/24, this response will be
|
||||
ignored.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
On the other hand, if the browser looks up a legitimate
|
||||
internal web server "www.example.net" and the
|
||||
following response is returned to
|
||||
the <acronym>BIND</acronym> 9 server
|
||||
</para>
|
||||
|
||||
<programlisting>www.example.net. A 192.0.2.2</programlisting>
|
||||
|
||||
<para>
|
||||
it will be accepted since the owner name "www.example.net"
|
||||
matches the <command>except-from</command> element,
|
||||
"example.net".
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Note that this is not really an attack on the DNS per se.
|
||||
In fact, there is nothing wrong for an "external" name to
|
||||
be mapped to your "internal" IP address or domain name
|
||||
from the DNS point of view.
|
||||
It might actually be provided for a legitimate purpose,
|
||||
such as for debugging.
|
||||
As long as the mapping is provided by the correct owner,
|
||||
it is not possible or does not make sense to detect
|
||||
whether the intent of the mapping is legitimate or not
|
||||
within the DNS.
|
||||
The "rebinding" attack must primarily be protected at the
|
||||
application that uses the DNS.
|
||||
For a large site, however, it may be difficult to protect
|
||||
all possible applications at once.
|
||||
This filtering feature is provided only to help such an
|
||||
operational environment;
|
||||
it is generally discouraged to turn it on unless you are
|
||||
very sure you have no other choice and the attack is a
|
||||
real threat for your applications.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Care should be particularly taken if you want to use this
|
||||
option for addresses within 127.0.0.0/8.
|
||||
These addresses are obviously "internal", but many
|
||||
applications conventionally rely on a DNS mapping from
|
||||
some name to such an address.
|
||||
Filtering out DNS records containing this address
|
||||
spuriously can break such applications.
|
||||
</para>
|
||||
</sect3>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="server_statement_grammar">
|
||||
|
@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: view.h,v 1.116 2009/01/27 22:29:59 jinmei Exp $ */
|
||||
/* $Id: view.h,v 1.117 2009/05/29 22:22:37 jinmei Exp $ */
|
||||
|
||||
#ifndef DNS_VIEW_H
|
||||
#define DNS_VIEW_H 1
|
||||
@ -128,6 +128,10 @@ struct dns_view {
|
||||
dns_acl_t * transferacl;
|
||||
dns_acl_t * updateacl;
|
||||
dns_acl_t * upfwdacl;
|
||||
dns_acl_t * denyansweracl;
|
||||
dns_rbt_t * answeracl_exclude;
|
||||
dns_rbt_t * denyanswernames;
|
||||
dns_rbt_t * answernames_exclude;
|
||||
isc_boolean_t requestixfr;
|
||||
isc_boolean_t provideixfr;
|
||||
isc_boolean_t requestnsid;
|
||||
|
@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: resolver.c,v 1.398 2009/05/11 02:38:35 tbox Exp $ */
|
||||
/* $Id: resolver.c,v 1.399 2009/05/29 22:22:36 jinmei Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@ -4837,6 +4837,134 @@ dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, dns_name_t *oname,
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_boolean_t
|
||||
is_answeraddress_allowed(dns_view_t *view, dns_name_t *name,
|
||||
dns_rdataset_t *rdataset)
|
||||
{
|
||||
isc_result_t result;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
struct in_addr ina;
|
||||
struct in6_addr in6a;
|
||||
isc_netaddr_t netaddr;
|
||||
char addrbuf[ISC_NETADDR_FORMATSIZE];
|
||||
char namebuf[DNS_NAME_FORMATSIZE];
|
||||
char classbuf[64];
|
||||
char typebuf[64];
|
||||
int match;
|
||||
|
||||
/* By default, we allow any addresses. */
|
||||
if (view->denyansweracl == NULL)
|
||||
return (ISC_TRUE);
|
||||
|
||||
/*
|
||||
* If the owner name matches one in the exclusion list, either exactly
|
||||
* or partially, allow it.
|
||||
*/
|
||||
if (view->answeracl_exclude != NULL) {
|
||||
dns_rbtnode_t *node = NULL;
|
||||
|
||||
result = dns_rbt_findnode(view->answeracl_exclude, name, NULL,
|
||||
&node, NULL, 0, NULL, NULL);
|
||||
|
||||
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, search the filter list for a match for each address
|
||||
* record. If a match is found, the address should be filtered,
|
||||
* so should the entire answer.
|
||||
*/
|
||||
for (result = dns_rdataset_first(rdataset);
|
||||
result == ISC_R_SUCCESS;
|
||||
result = dns_rdataset_next(rdataset)) {
|
||||
dns_rdata_reset(&rdata);
|
||||
dns_rdataset_current(rdataset, &rdata);
|
||||
if (rdataset->type == dns_rdatatype_a) {
|
||||
INSIST(rdata.length == sizeof(ina.s_addr));
|
||||
memcpy(&ina.s_addr, rdata.data, sizeof(ina.s_addr));
|
||||
isc_netaddr_fromin(&netaddr, &ina);
|
||||
} else {
|
||||
INSIST(rdata.length == sizeof(in6a.s6_addr));
|
||||
memcpy(in6a.s6_addr, rdata.data, sizeof(in6a.s6_addr));
|
||||
isc_netaddr_fromin6(&netaddr, &in6a);
|
||||
}
|
||||
|
||||
result = dns_acl_match(&netaddr, NULL, view->denyansweracl,
|
||||
&view->aclenv, &match, NULL);
|
||||
|
||||
if (result == ISC_R_SUCCESS && match > 0) {
|
||||
isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
|
||||
dns_name_format(name, namebuf, sizeof(namebuf));
|
||||
dns_rdatatype_format(rdataset->type, typebuf,
|
||||
sizeof(typebuf));
|
||||
dns_rdataclass_format(rdataset->rdclass, classbuf,
|
||||
sizeof(classbuf));
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
|
||||
DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
|
||||
"answer address %s denied for %s/%s/%s",
|
||||
addrbuf, namebuf, typebuf, classbuf);
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
static isc_boolean_t
|
||||
is_answertarget_allowed(dns_view_t *view, dns_name_t *name,
|
||||
dns_rdatatype_t type, dns_name_t *tname,
|
||||
dns_name_t *domain)
|
||||
{
|
||||
isc_result_t result;
|
||||
dns_rbtnode_t *node = NULL;
|
||||
char qnamebuf[DNS_NAME_FORMATSIZE];
|
||||
char tnamebuf[DNS_NAME_FORMATSIZE];
|
||||
char classbuf[64];
|
||||
char typebuf[64];
|
||||
|
||||
/* By default, we allow any target name. */
|
||||
if (view->denyanswernames == NULL)
|
||||
return (ISC_TRUE);
|
||||
|
||||
/*
|
||||
* If the owner name matches one in the exclusion list, either exactly
|
||||
* or partially, allow it.
|
||||
*/
|
||||
if (view->answernames_exclude != NULL) {
|
||||
result = dns_rbt_findnode(view->answernames_exclude, name, NULL,
|
||||
&node, NULL, 0, NULL, NULL);
|
||||
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the target name is a subdomain of the search domain, allow it.
|
||||
*/
|
||||
if (dns_name_issubdomain(tname, domain))
|
||||
return (ISC_TRUE);
|
||||
|
||||
/*
|
||||
* Otherwise, apply filters.
|
||||
*/
|
||||
result = dns_rbt_findnode(view->denyanswernames, tname, NULL, &node,
|
||||
NULL, 0, NULL, NULL);
|
||||
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
|
||||
dns_name_format(name, qnamebuf, sizeof(qnamebuf));
|
||||
dns_name_format(tname, tnamebuf, sizeof(tnamebuf));
|
||||
dns_rdatatype_format(type, typebuf, sizeof(typebuf));
|
||||
dns_rdataclass_format(view->rdclass, classbuf,
|
||||
sizeof(classbuf));
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
|
||||
DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
|
||||
"%s target %s denied for %s/%s",
|
||||
typebuf, tnamebuf, qnamebuf, classbuf);
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle a no-answer response (NXDOMAIN, NXRRSET, or referral).
|
||||
* If bind8_ns_resp is ISC_TRUE, this is a suspected BIND 8
|
||||
@ -5194,6 +5322,7 @@ answer_response(fetchctx_t *fctx) {
|
||||
unsigned int aflag;
|
||||
dns_rdatatype_t type;
|
||||
dns_fixedname_t dname, fqname;
|
||||
dns_view_t *view;
|
||||
|
||||
FCTXTRACE("answer_response");
|
||||
|
||||
@ -5216,6 +5345,7 @@ answer_response(fetchctx_t *fctx) {
|
||||
aa = ISC_FALSE;
|
||||
qname = &fctx->name;
|
||||
type = fctx->type;
|
||||
view = fctx->res->view;
|
||||
result = dns_message_firstname(message, DNS_SECTION_ANSWER);
|
||||
while (!done && result == ISC_R_SUCCESS) {
|
||||
name = NULL;
|
||||
@ -5236,6 +5366,18 @@ answer_response(fetchctx_t *fctx) {
|
||||
*/
|
||||
return (DNS_R_FORMERR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply filters, if given, on answers to reject
|
||||
* a malicious attempt of rebinding.
|
||||
*/
|
||||
if ((rdataset->type == dns_rdatatype_a ||
|
||||
rdataset->type == dns_rdatatype_aaaa) &&
|
||||
!is_answeraddress_allowed(view, name,
|
||||
rdataset)) {
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
|
||||
if (rdataset->type == type && !found_cname) {
|
||||
/*
|
||||
* We've found an ordinary answer.
|
||||
@ -5284,6 +5426,14 @@ answer_response(fetchctx_t *fctx) {
|
||||
&tname);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
/* Apply filters on the target name. */
|
||||
if (!is_answertarget_allowed(view,
|
||||
name,
|
||||
rdataset->type,
|
||||
&tname,
|
||||
&fctx->domain)) {
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
} else if (rdataset->type == dns_rdatatype_rrsig
|
||||
&& rdataset->covers ==
|
||||
dns_rdatatype_cname
|
||||
@ -5386,6 +5536,8 @@ answer_response(fetchctx_t *fctx) {
|
||||
rdataset != NULL;
|
||||
rdataset = ISC_LIST_NEXT(rdataset, link)) {
|
||||
isc_boolean_t found_dname = ISC_FALSE;
|
||||
dns_name_t *dname_name;
|
||||
|
||||
found = ISC_FALSE;
|
||||
aflag = 0;
|
||||
if (rdataset->type == dns_rdatatype_dname) {
|
||||
@ -5415,6 +5567,15 @@ answer_response(fetchctx_t *fctx) {
|
||||
return (result);
|
||||
else
|
||||
found_dname = ISC_TRUE;
|
||||
|
||||
dname_name = dns_fixedname_name(&dname);
|
||||
if (!is_answertarget_allowed(view,
|
||||
qname,
|
||||
rdataset->type,
|
||||
dname_name,
|
||||
&fctx->domain)) {
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
} else if (rdataset->type == dns_rdatatype_rrsig
|
||||
&& rdataset->covers ==
|
||||
dns_rdatatype_dname) {
|
||||
|
@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: view.c,v 1.153 2009/01/27 22:29:59 jinmei Exp $ */
|
||||
/* $Id: view.c,v 1.154 2009/05/29 22:22:37 jinmei Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
#include <dns/masterdump.h>
|
||||
#include <dns/order.h>
|
||||
#include <dns/peer.h>
|
||||
#include <dns/rbt.h>
|
||||
#include <dns/rdataset.h>
|
||||
#include <dns/request.h>
|
||||
#include <dns/resolver.h>
|
||||
@ -178,6 +179,10 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
|
||||
view->notifyacl = NULL;
|
||||
view->updateacl = NULL;
|
||||
view->upfwdacl = NULL;
|
||||
view->denyansweracl = NULL;
|
||||
view->answeracl_exclude = NULL;
|
||||
view->denyanswernames = NULL;
|
||||
view->answernames_exclude = NULL;
|
||||
view->requestixfr = ISC_TRUE;
|
||||
view->provideixfr = ISC_TRUE;
|
||||
view->maxcachettl = 7 * 24 * 3600;
|
||||
@ -313,6 +318,14 @@ destroy(dns_view_t *view) {
|
||||
dns_acl_detach(&view->updateacl);
|
||||
if (view->upfwdacl != NULL)
|
||||
dns_acl_detach(&view->upfwdacl);
|
||||
if (view->denyansweracl != NULL)
|
||||
dns_acl_detach(&view->denyansweracl);
|
||||
if (view->answeracl_exclude != NULL)
|
||||
dns_rbt_destroy(&view->answeracl_exclude);
|
||||
if (view->denyanswernames != NULL)
|
||||
dns_rbt_destroy(&view->denyanswernames);
|
||||
if (view->answernames_exclude != NULL)
|
||||
dns_rbt_destroy(&view->answernames_exclude);
|
||||
if (view->delonly != NULL) {
|
||||
dns_name_t *name;
|
||||
int i;
|
||||
|
@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: namedconf.c,v 1.95 2009/03/04 02:42:31 each Exp $ */
|
||||
/* $Id: namedconf.c,v 1.96 2009/05/29 22:22:37 jinmei Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@ -736,6 +736,34 @@ static cfg_type_t cfg_type_optional_exclude = {
|
||||
"optional_exclude", parse_optional_keyvalue, print_keyvalue,
|
||||
doc_optional_keyvalue, &cfg_rep_list, &exclude_kw };
|
||||
|
||||
static keyword_type_t exceptionnames_kw = { "except-from", &cfg_type_namelist };
|
||||
|
||||
static cfg_type_t cfg_type_optional_exceptionnames = {
|
||||
"optional_allow", parse_optional_keyvalue, print_keyvalue,
|
||||
doc_optional_keyvalue, &cfg_rep_list, &exceptionnames_kw };
|
||||
|
||||
static cfg_tuplefielddef_t denyaddresses_fields[] = {
|
||||
{ "acl", &cfg_type_bracketed_aml, 0 },
|
||||
{ "except-from", &cfg_type_optional_exceptionnames, 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
static cfg_type_t cfg_type_denyaddresses = {
|
||||
"denyaddresses", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
|
||||
&cfg_rep_tuple, denyaddresses_fields
|
||||
};
|
||||
|
||||
static cfg_tuplefielddef_t denyaliases_fields[] = {
|
||||
{ "name", &cfg_type_namelist, 0 },
|
||||
{ "except-from", &cfg_type_optional_exceptionnames, 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
static cfg_type_t cfg_type_denyaliases = {
|
||||
"denyaliases", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
|
||||
&cfg_rep_tuple, denyaliases_fields
|
||||
};
|
||||
|
||||
static cfg_type_t cfg_type_algorithmlist = {
|
||||
"algorithmlist", cfg_parse_bracketed_list, cfg_print_bracketed_list,
|
||||
cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring };
|
||||
@ -813,6 +841,8 @@ view_clauses[] = {
|
||||
{ "check-names", &cfg_type_checknames, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "cleaning-interval", &cfg_type_uint32, 0 },
|
||||
{ "clients-per-query", &cfg_type_uint32, 0 },
|
||||
{ "deny-answer-addresses", &cfg_type_denyaddresses, 0 },
|
||||
{ "deny-answer-aliases", &cfg_type_denyaliases, 0 },
|
||||
{ "disable-algorithms", &cfg_type_disablealgorithm,
|
||||
CFG_CLAUSEFLAG_MULTI },
|
||||
{ "disable-empty-zone", &cfg_type_astring, CFG_CLAUSEFLAG_MULTI },
|
||||
|
Loading…
x
Reference in New Issue
Block a user