mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 14:07:59 +00:00
Add support for O(1) ACL processing, based on radix tree code originally
written by kevin brintnall. [RT #16288]
This commit is contained in:
4
CHANGES
4
CHANGES
@@ -1,3 +1,7 @@
|
||||
2233. [func] Add support for O(1) ACL processing, based on
|
||||
radix tree code originally written by kevin
|
||||
brintnall. [RT #16288]
|
||||
|
||||
2232. [bug] dns_adb_findaddrinfo() could fail and return
|
||||
ISC_R_SUCCESS. [RT #17137]
|
||||
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: controlconf.c,v 1.54 2007/06/18 23:47:18 tbox Exp $ */
|
||||
/* $Id: controlconf.c,v 1.55 2007/09/12 01:09:07 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -1014,7 +1014,7 @@ update_listener(ns_controls_t *cp, controllistener_t **listenerp,
|
||||
if (control != NULL && type == isc_sockettype_tcp) {
|
||||
allow = cfg_tuple_get(control, "allow");
|
||||
result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
|
||||
aclconfctx, listener->mctx,
|
||||
aclconfctx, listener->mctx, 0,
|
||||
&new_acl);
|
||||
} else {
|
||||
result = dns_acl_any(listener->mctx, &new_acl);
|
||||
@@ -1101,7 +1101,8 @@ add_listener(ns_controls_t *cp, controllistener_t **listenerp,
|
||||
if (control != NULL && type == isc_sockettype_tcp) {
|
||||
allow = cfg_tuple_get(control, "allow");
|
||||
result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
|
||||
aclconfctx, mctx, &new_acl);
|
||||
aclconfctx, mctx, 0,
|
||||
&new_acl);
|
||||
} else {
|
||||
result = dns_acl_any(mctx, &new_acl);
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: interfacemgr.c,v 1.89 2007/06/18 23:47:18 tbox Exp $ */
|
||||
/* $Id: interfacemgr.c,v 1.90 2007/09/12 01:09:07 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -483,7 +483,7 @@ static isc_result_t
|
||||
clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
|
||||
dns_acl_t *newacl = NULL;
|
||||
isc_result_t result;
|
||||
result = dns_acl_create(mctx, 10, &newacl);
|
||||
result = dns_acl_create(mctx, 0, &newacl);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
dns_acl_detach(aclp);
|
||||
@@ -494,36 +494,31 @@ clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
|
||||
|
||||
static isc_boolean_t
|
||||
listenon_is_ip6_any(ns_listenelt_t *elt) {
|
||||
if (elt->acl->length != 1)
|
||||
return (ISC_FALSE);
|
||||
if (elt->acl->elements[0].negative == ISC_FALSE &&
|
||||
elt->acl->elements[0].type == dns_aclelementtype_any)
|
||||
return (ISC_TRUE); /* listen-on-v6 { any; } */
|
||||
return (ISC_FALSE); /* All others */
|
||||
REQUIRE(elt && elt->acl);
|
||||
return dns_acl_isany(elt->acl);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
|
||||
isc_result_t result;
|
||||
dns_aclelement_t elt;
|
||||
unsigned int family;
|
||||
unsigned int prefixlen;
|
||||
isc_netaddr_t *netaddr;
|
||||
|
||||
family = interface->address.family;
|
||||
netaddr = &interface->address;
|
||||
|
||||
elt.type = dns_aclelementtype_ipprefix;
|
||||
elt.negative = ISC_FALSE;
|
||||
elt.u.ip_prefix.address = interface->address;
|
||||
elt.u.ip_prefix.prefixlen = (family == AF_INET) ? 32 : 128;
|
||||
result = dns_acl_appendelement(mgr->aclenv.localhost, &elt);
|
||||
/* First add localhost address */
|
||||
prefixlen = (netaddr->family == AF_INET) ? 32 : 128;
|
||||
result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable,
|
||||
netaddr, prefixlen, ISC_TRUE);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
/* Then add localnets prefix */
|
||||
result = isc_netaddr_masktoprefixlen(&interface->netmask,
|
||||
&prefixlen);
|
||||
|
||||
/* Non contigious netmasks not allowed by IPv6 arch. */
|
||||
if (result != ISC_R_SUCCESS && family == AF_INET6)
|
||||
if (result != ISC_R_SUCCESS && netaddr->family == AF_INET6)
|
||||
return (result);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
@@ -533,17 +528,14 @@ setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
|
||||
"localnets ACL: %s",
|
||||
interface->name,
|
||||
isc_result_totext(result));
|
||||
} else {
|
||||
elt.u.ip_prefix.prefixlen = prefixlen;
|
||||
if (dns_acl_elementmatch(mgr->aclenv.localnets, &elt,
|
||||
NULL) == ISC_R_NOTFOUND) {
|
||||
result = dns_acl_appendelement(mgr->aclenv.localnets,
|
||||
&elt);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable,
|
||||
netaddr, prefixlen, ISC_TRUE);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: server.c,v 1.489 2007/07/09 02:12:42 marka Exp $ */
|
||||
/* $Id: server.c,v 1.490 2007/09/12 01:09:07 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -307,7 +307,51 @@ configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config,
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx,
|
||||
actx, mctx, aclp);
|
||||
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
|
||||
* nest_level value of 2.
|
||||
*/
|
||||
static isc_result_t
|
||||
configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config,
|
||||
cfg_aclconfctx_t *actx, isc_mem_t *mctx,
|
||||
dns_acl_t **aclp)
|
||||
{
|
||||
isc_result_t result;
|
||||
const cfg_obj_t *maps[3];
|
||||
const cfg_obj_t *aclobj = NULL;
|
||||
int i = 0;
|
||||
|
||||
if (*aclp != NULL)
|
||||
dns_acl_detach(aclp);
|
||||
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, "sortlist", &aclobj);
|
||||
if (aclobj == NULL)
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
/*
|
||||
* Use a nest level of 2 for the "top level" of the sortlist;
|
||||
* this means each entry in the top two levels will be stored as
|
||||
* lists of separate, nested ACLs, rather than merged together
|
||||
* into IP tables as is usually done with ACLs.
|
||||
*/
|
||||
result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx,
|
||||
actx, mctx, 2, aclp);
|
||||
|
||||
return (result);
|
||||
}
|
||||
@@ -1598,8 +1642,11 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
|
||||
"allow-query-cache", actx,
|
||||
ns_g_mctx, &view->queryacl));
|
||||
|
||||
CHECK(configure_view_acl(vconfig, config, "sortlist",
|
||||
actx, ns_g_mctx, &view->sortlist));
|
||||
/*
|
||||
* Configure sortlist, if set
|
||||
*/
|
||||
CHECK(configure_view_sortlist(vconfig, config, actx, ns_g_mctx,
|
||||
&view->sortlist));
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "request-ixfr", &obj);
|
||||
@@ -2490,25 +2537,23 @@ add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr,
|
||||
{
|
||||
ns_listenelt_t *lelt = NULL;
|
||||
dns_acl_t *src_acl = NULL;
|
||||
dns_aclelement_t aelt;
|
||||
isc_result_t result;
|
||||
isc_sockaddr_t any_sa6;
|
||||
isc_netaddr_t netaddr;
|
||||
|
||||
REQUIRE(isc_sockaddr_pf(addr) == AF_INET6);
|
||||
|
||||
isc_sockaddr_any6(&any_sa6);
|
||||
if (!isc_sockaddr_equal(&any_sa6, addr) &&
|
||||
(wcardport_ok || isc_sockaddr_getport(addr) != 0)) {
|
||||
aelt.type = dns_aclelementtype_ipprefix;
|
||||
aelt.negative = ISC_FALSE;
|
||||
aelt.u.ip_prefix.prefixlen = 128;
|
||||
isc_netaddr_fromin6(&aelt.u.ip_prefix.address,
|
||||
&addr->type.sin6.sin6_addr);
|
||||
isc_netaddr_fromin6(&netaddr, &addr->type.sin6.sin6_addr);
|
||||
|
||||
result = dns_acl_create(mctx, 1, &src_acl);
|
||||
result = dns_acl_create(mctx, 0, &src_acl);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
result = dns_acl_appendelement(src_acl, &aelt);
|
||||
|
||||
result = dns_iptable_addprefix(src_acl->iptable,
|
||||
&netaddr, 128, ISC_TRUE);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto clean;
|
||||
|
||||
@@ -4391,7 +4436,8 @@ ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
|
||||
return (result);
|
||||
|
||||
result = cfg_acl_fromconfig(cfg_tuple_get(listener, "acl"),
|
||||
config, ns_g_lctx, actx, mctx, &delt->acl);
|
||||
config, ns_g_lctx, actx, mctx, 0,
|
||||
&delt->acl);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ns_listenelt_destroy(delt);
|
||||
return (result);
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: sortlist.c,v 1.15 2007/06/19 23:46:59 tbox Exp $ */
|
||||
/* $Id: sortlist.c,v 1.16 2007/09/12 01:09:07 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -51,7 +51,7 @@ ns_sortlist_setup(dns_acl_t *acl, isc_netaddr_t *clientaddr,
|
||||
const dns_aclelement_t *matched_elt = NULL;
|
||||
|
||||
if (e->type == dns_aclelementtype_nestedacl) {
|
||||
dns_acl_t *inner = e->u.nestedacl;
|
||||
dns_acl_t *inner = e->nestedacl;
|
||||
|
||||
if (inner->length < 1 || inner->length > 2)
|
||||
goto dont_sort;
|
||||
@@ -74,7 +74,7 @@ ns_sortlist_setup(dns_acl_t *acl, isc_netaddr_t *clientaddr,
|
||||
if (order_elt != NULL) {
|
||||
if (order_elt->type ==
|
||||
dns_aclelementtype_nestedacl) {
|
||||
*argp = order_elt->u.nestedacl;
|
||||
*argp = order_elt->nestedacl;
|
||||
return (NS_SORTLISTTYPE_2ELEMENT);
|
||||
} else if (order_elt->type ==
|
||||
dns_aclelementtype_localhost &&
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: zoneconf.c,v 1.137 2007/06/19 23:46:59 tbox Exp $ */
|
||||
/* $Id: zoneconf.c,v 1.138 2007/09/12 01:09:07 each Exp $ */
|
||||
|
||||
/*% */
|
||||
|
||||
@@ -90,7 +90,7 @@ configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
|
||||
}
|
||||
|
||||
result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, actx,
|
||||
dns_zone_getmctx(zone), &dacl);
|
||||
dns_zone_getmctx(zone), 0, &dacl);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
(*setzacl)(zone, dacl);
|
||||
|
@@ -18,7 +18,7 @@
|
||||
- PERFORMANCE OF THIS SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- File: $Id: Bv9ARM-book.xml,v 1.333 2007/09/07 07:29:22 marka Exp $ -->
|
||||
<!-- File: $Id: Bv9ARM-book.xml,v 1.334 2007/09/12 01:09:08 each Exp $ -->
|
||||
<book xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<title>BIND 9 Administrator Reference Manual</title>
|
||||
|
||||
@@ -3023,9 +3023,8 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
|
||||
Address match lists are primarily used to determine access
|
||||
control for various server operations. They are also used in
|
||||
the <command>listen-on</command> and <command>sortlist</command>
|
||||
statements. The elements
|
||||
which constitute an address match list can be any of the
|
||||
following:
|
||||
statements. The elements which constitute an address match
|
||||
list can be any of the following:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
@@ -3053,28 +3052,30 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
|
||||
<para>
|
||||
Elements can be negated with a leading exclamation mark (`!'),
|
||||
and the match list names "any", "none", "localhost", and
|
||||
"localnets"
|
||||
are predefined. More information on those names can be found in
|
||||
the description of the acl statement.
|
||||
"localnets" are predefined. More information on those names
|
||||
can be found in the description of the acl statement.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The addition of the key clause made the name of this syntactic
|
||||
element something of a misnomer, since security keys can be used
|
||||
to validate access without regard to a host or network address.
|
||||
Nonetheless,
|
||||
the term "address match list" is still used throughout the
|
||||
documentation.
|
||||
Nonetheless, the term "address match list" is still used
|
||||
throughout the documentation.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When a given IP address or prefix is compared to an address
|
||||
match list, the list is traversed in order until an element
|
||||
matches.
|
||||
match list, the comparison takes place in approximately O(1)
|
||||
time. However, key comparisons require that the list of keys
|
||||
be traversed until a matching key is found, and therefore may
|
||||
be somewhat slower.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The interpretation of a match depends on whether the list is being
|
||||
used
|
||||
for access control, defining listen-on ports, or in a sortlist,
|
||||
and whether the element was negated.
|
||||
used for access control, defining listen-on ports, or in a
|
||||
sortlist, and whether the element was negated.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -3093,23 +3094,25 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
|
||||
<command>allow-update-forwarding</command>, and
|
||||
<command>blackhole</command> all use address match
|
||||
lists. Similarly, the listen-on option will cause the
|
||||
server to not accept queries on any of the machine's
|
||||
server to refuse queries on any of the machine's
|
||||
addresses which do not match the list.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Because of the first-match aspect of the algorithm, an element
|
||||
that defines a subset of another element in the list should come
|
||||
before the broader element, regardless of whether either is
|
||||
negated. For
|
||||
example, in
|
||||
<command>1.2.3/24; ! 1.2.3.13;</command> the 1.2.3.13
|
||||
element is
|
||||
completely useless because the algorithm will match any lookup for
|
||||
1.2.3.13 to the 1.2.3/24 element.
|
||||
Using <command>! 1.2.3.13; 1.2.3/24</command> fixes
|
||||
that problem by having 1.2.3.13 blocked by the negation but all
|
||||
other 1.2.3.* hosts fall through.
|
||||
Order of insertion is signficant. If more than one element
|
||||
in an ACL is found to match a given IP address or prefix,
|
||||
preference will be given to the one that came
|
||||
<emphasis>first</emphasis> in the ACL definition.
|
||||
Because of this first-match behavior, an element that
|
||||
defines a subset of another element in the list should
|
||||
come before the broader element, regardless of whether
|
||||
either is negated. For example, in
|
||||
<command>1.2.3/24; ! 1.2.3.13;</command>
|
||||
the 1.2.3.13 element is completely useless because the
|
||||
algorithm will match any lookup for 1.2.3.13 to the 1.2.3/24
|
||||
element. Using <command>! 1.2.3.13; 1.2.3/24</command> fixes
|
||||
that problem by having 1.2.3.13 blocked by the negation, but
|
||||
all other 1.2.3.* hosts fall through.
|
||||
</para>
|
||||
</sect3>
|
||||
</sect2>
|
||||
@@ -3390,8 +3393,7 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
|
||||
<para>
|
||||
Note that an address match list's name must be defined
|
||||
with <command>acl</command> before it can be used
|
||||
elsewhere; no
|
||||
forward references are allowed.
|
||||
elsewhere; no forward references are allowed.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: check.c,v 1.81 2007/08/29 03:23:46 marka Exp $ */
|
||||
/* $Id: check.c,v 1.82 2007/09/12 01:09:08 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -379,7 +379,8 @@ checkacl(const char *aclname, cfg_aclconfctx_t *actx, const cfg_obj_t *zconfig,
|
||||
}
|
||||
if (aclobj == NULL)
|
||||
return (ISC_R_SUCCESS);
|
||||
result = cfg_acl_fromconfig(aclobj, config, logctx, actx, mctx, &acl);
|
||||
result = cfg_acl_fromconfig(aclobj, config, logctx,
|
||||
actx, mctx, 0, &acl);
|
||||
if (acl != NULL)
|
||||
dns_acl_detach(&acl);
|
||||
return (result);
|
||||
@@ -459,7 +460,7 @@ check_recursionacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
|
||||
continue;
|
||||
|
||||
tresult = cfg_acl_fromconfig(aclobj, config, logctx,
|
||||
actx, mctx, &acl);
|
||||
actx, mctx, 0, &acl);
|
||||
|
||||
if (tresult != ISC_R_SUCCESS)
|
||||
result = tresult;
|
||||
@@ -1932,7 +1933,7 @@ bind9_check_controls(const cfg_obj_t *config, isc_log_t *logctx,
|
||||
control = cfg_listelt_value(element2);
|
||||
allow = cfg_tuple_get(control, "allow");
|
||||
tresult = cfg_acl_fromconfig(allow, config, logctx,
|
||||
&actx, mctx, &acl);
|
||||
&actx, mctx, 0, &acl);
|
||||
if (acl != NULL)
|
||||
dns_acl_detach(&acl);
|
||||
if (tresult != ISC_R_SUCCESS)
|
||||
@@ -2114,8 +2115,9 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
|
||||
}
|
||||
}
|
||||
|
||||
tresult = cfg_map_get(config, "acl", &acls);
|
||||
if (tresult == ISC_R_SUCCESS) {
|
||||
cfg_map_get(config, "acl", &acls);
|
||||
|
||||
if (acls != NULL) {
|
||||
const cfg_listelt_t *elt;
|
||||
const cfg_listelt_t *elt2;
|
||||
const char *aclname;
|
||||
@@ -2124,6 +2126,7 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
|
||||
elt != NULL;
|
||||
elt = cfg_list_next(elt)) {
|
||||
const cfg_obj_t *acl = cfg_listelt_value(elt);
|
||||
unsigned int line = cfg_obj_line(acl);
|
||||
unsigned int i;
|
||||
|
||||
aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
|
||||
@@ -2148,7 +2151,6 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
|
||||
"name"));
|
||||
if (strcasecmp(aclname, name) == 0) {
|
||||
const char *file = cfg_obj_file(acl);
|
||||
unsigned int line = cfg_obj_line(acl);
|
||||
|
||||
if (file == NULL)
|
||||
file = "<unknown file>";
|
||||
|
@@ -13,7 +13,7 @@
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id: Makefile.in,v 1.157 2007/06/19 23:47:16 tbox Exp $
|
||||
# $Id: Makefile.in,v 1.158 2007/09/12 01:09:08 each Exp $
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
@@ -53,8 +53,8 @@ DSTOBJS = @DST_EXTRA_OBJS@ \
|
||||
DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \
|
||||
cache.@O@ callbacks.@O@ compress.@O@ \
|
||||
db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \
|
||||
dlz.@O@ dnssec.@O@ ds.@O@ forward.@O@ journal.@O@ keytable.@O@ \
|
||||
lib.@O@ log.@O@ lookup.@O@ \
|
||||
dlz.@O@ dnssec.@O@ ds.@O@ forward.@O@ iptable.@O@ journal.@O@ \
|
||||
keytable.@O@ lib.@O@ log.@O@ lookup.@O@ \
|
||||
master.@O@ masterdump.@O@ message.@O@ \
|
||||
name.@O@ ncache.@O@ nsec.@O@ order.@O@ peer.@O@ portlist.@O@ \
|
||||
rbt.@O@ rbtdb.@O@ rbtdb64.@O@ rcode.@O@ rdata.@O@ \
|
||||
@@ -79,8 +79,8 @@ DSTSRCS = @DST_EXTRA_SRCS@ \
|
||||
DNSSRCS = acache.c acl.c adb.c byaddr.c \
|
||||
cache.c callbacks.c compress.c \
|
||||
db.c dbiterator.c dbtable.c diff.c dispatch.c \
|
||||
dlz.c dnssec.c ds.c forward.c journal.c keytable.c \
|
||||
lib.c log.c lookup.c \
|
||||
dlz.c dnssec.c ds.c forward.c iptable.c journal.c \
|
||||
keytable.c lib.c log.c lookup.c \
|
||||
master.c masterdump.c message.c \
|
||||
name.c ncache.c nsec.c order.c peer.c portlist.c \
|
||||
rbt.c rbtdb.c rbtdb64.c rcode.c rdata.c \
|
||||
|
504
lib/dns/acl.c
504
lib/dns/acl.c
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: acl.c,v 1.32 2007/06/19 23:47:16 tbox Exp $ */
|
||||
/* $Id: acl.c,v 1.33 2007/09/12 01:09:08 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -26,7 +26,13 @@
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/acl.h>
|
||||
#include <dns/iptable.h>
|
||||
|
||||
/*
|
||||
* Create a new ACL, including an IP table and an array with room
|
||||
* for 'n' ACL elements. The elements are uninitialized and the
|
||||
* length is 0.
|
||||
*/
|
||||
isc_result_t
|
||||
dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
|
||||
isc_result_t result;
|
||||
@@ -43,11 +49,19 @@ dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
|
||||
return (ISC_R_NOMEMORY);
|
||||
acl->mctx = mctx;
|
||||
acl->name = NULL;
|
||||
|
||||
result = isc_refcount_init(&acl->refcount, 1);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mem_put(mctx, acl, sizeof(*acl));
|
||||
return (result);
|
||||
}
|
||||
|
||||
result = dns_iptable_create(mctx, &acl->iptable);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mem_put(mctx, acl, sizeof(*acl));
|
||||
return (result);
|
||||
}
|
||||
|
||||
acl->elements = NULL;
|
||||
acl->alloc = 0;
|
||||
acl->length = 0;
|
||||
@@ -73,111 +87,234 @@ dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_acl_appendelement(dns_acl_t *acl, const dns_aclelement_t *elt) {
|
||||
if (acl->length + 1 > acl->alloc) {
|
||||
/*
|
||||
* Resize the ACL.
|
||||
*/
|
||||
unsigned int newalloc;
|
||||
void *newmem;
|
||||
|
||||
newalloc = acl->alloc * 2;
|
||||
if (newalloc < 4)
|
||||
newalloc = 4;
|
||||
newmem = isc_mem_get(acl->mctx,
|
||||
newalloc * sizeof(dns_aclelement_t));
|
||||
if (newmem == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
memcpy(newmem, acl->elements,
|
||||
acl->length * sizeof(dns_aclelement_t));
|
||||
isc_mem_put(acl->mctx, acl->elements,
|
||||
acl->alloc * sizeof(dns_aclelement_t));
|
||||
acl->elements = newmem;
|
||||
acl->alloc = newalloc;
|
||||
}
|
||||
/*
|
||||
* Append the new element.
|
||||
*/
|
||||
acl->elements[acl->length++] = *elt;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new ACL and initialize it with the value "any" or "none",
|
||||
* depending on the value of the "neg" parameter.
|
||||
* "any" is a positive iptable entry with bit length 0.
|
||||
* "none" is the same as "!any".
|
||||
*/
|
||||
static isc_result_t
|
||||
dns_acl_anyornone(isc_mem_t *mctx, isc_boolean_t neg, dns_acl_t **target) {
|
||||
isc_result_t result;
|
||||
dns_acl_t *acl = NULL;
|
||||
result = dns_acl_create(mctx, 1, &acl);
|
||||
result = dns_acl_create(mctx, 0, &acl);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
acl->elements[0].negative = neg;
|
||||
acl->elements[0].type = dns_aclelementtype_any;
|
||||
acl->length = 1;
|
||||
dns_iptable_addprefix(acl->iptable, NULL, 0, ISC_TF(!neg));
|
||||
*target = acl;
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new ACL that matches everything.
|
||||
*/
|
||||
isc_result_t
|
||||
dns_acl_any(isc_mem_t *mctx, dns_acl_t **target) {
|
||||
return (dns_acl_anyornone(mctx, ISC_FALSE, target));
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new ACL that matches nothing.
|
||||
*/
|
||||
isc_result_t
|
||||
dns_acl_none(isc_mem_t *mctx, dns_acl_t **target) {
|
||||
return (dns_acl_anyornone(mctx, ISC_TRUE, target));
|
||||
}
|
||||
|
||||
/*
|
||||
* If pos is ISC_TRUE, test whether acl is set to "{ any; }"
|
||||
* If pos is ISC_FALSE, test whether acl is set to "{ none; }"
|
||||
*/
|
||||
static isc_boolean_t
|
||||
dns_acl_isanyornone(dns_acl_t *acl, isc_boolean_t pos)
|
||||
{
|
||||
/* Should never happen but let's be safe */
|
||||
if (acl == NULL ||
|
||||
acl->iptable == NULL ||
|
||||
acl->iptable->radix == NULL ||
|
||||
acl->iptable->radix->head == NULL ||
|
||||
acl->iptable->radix->head->prefix == NULL)
|
||||
return (ISC_FALSE);
|
||||
|
||||
if (acl->length != 0 && acl->node_count != 1)
|
||||
return (ISC_FALSE);
|
||||
|
||||
if (acl->iptable->radix->head->prefix->bitlen == 0 &&
|
||||
*(isc_boolean_t *) (acl->iptable->radix->head->data) == pos)
|
||||
return (ISC_TRUE);
|
||||
|
||||
return (ISC_FALSE); /* All others */
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether acl is set to "{ any; }"
|
||||
*/
|
||||
isc_boolean_t
|
||||
dns_acl_isany(dns_acl_t *acl)
|
||||
{
|
||||
return (dns_acl_isanyornone(acl, ISC_TRUE));
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether acl is set to "{ none; }"
|
||||
*/
|
||||
isc_boolean_t
|
||||
dns_acl_isnone(dns_acl_t *acl)
|
||||
{
|
||||
return (dns_acl_isanyornone(acl, ISC_FALSE));
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine whether a given address or signer matches a given ACL.
|
||||
* For a match with a positive ACL element or iptable radix entry,
|
||||
* return with a positive value in match; for a match with a negated ACL
|
||||
* element or radix entry, return with a negative value in match.
|
||||
*/
|
||||
isc_result_t
|
||||
dns_acl_match(const isc_netaddr_t *reqaddr,
|
||||
const dns_name_t *reqsigner,
|
||||
const dns_acl_t *acl,
|
||||
const dns_aclenv_t *env,
|
||||
int *match,
|
||||
dns_aclelement_t const**matchelt)
|
||||
const dns_aclelement_t **matchelt)
|
||||
{
|
||||
isc_uint16_t bitlen;
|
||||
isc_prefix_t pfx;
|
||||
isc_radix_node_t *node;
|
||||
const isc_netaddr_t *addr;
|
||||
isc_netaddr_t v4addr;
|
||||
isc_result_t result;
|
||||
int match_num = -1;
|
||||
unsigned int i;
|
||||
|
||||
REQUIRE(reqaddr != NULL);
|
||||
REQUIRE(matchelt == NULL || *matchelt == NULL);
|
||||
|
||||
if (env == NULL || env->match_mapped == ISC_FALSE ||
|
||||
reqaddr->family != AF_INET6 ||
|
||||
!IN6_IS_ADDR_V4MAPPED(&reqaddr->type.in6))
|
||||
addr = reqaddr;
|
||||
else {
|
||||
isc_netaddr_fromv4mapped(&v4addr, reqaddr);
|
||||
addr = &v4addr;
|
||||
}
|
||||
|
||||
/* Always match with host addresses. */
|
||||
bitlen = reqaddr->family == AF_INET6 ? 128 : 32;
|
||||
NETADDR_TO_PREFIX_T(addr, pfx, bitlen);
|
||||
|
||||
/* Assume no match. */
|
||||
*match = 0;
|
||||
|
||||
/* Search radix. */
|
||||
result = isc_radix_search(acl->iptable->radix, &node, &pfx);
|
||||
|
||||
/* Found a match. */
|
||||
if (result == ISC_R_SUCCESS && node != NULL) {
|
||||
match_num = node->node_num;
|
||||
if (*(isc_boolean_t *) node->data == ISC_TRUE)
|
||||
*match = match_num;
|
||||
else
|
||||
*match = -match_num;
|
||||
}
|
||||
|
||||
/* Now search non-radix elements for a match with a lower node_num. */
|
||||
for (i = 0; i < acl->length; i++) {
|
||||
dns_aclelement_t *e = &acl->elements[i];
|
||||
|
||||
if (dns_aclelement_match(reqaddr, reqsigner,
|
||||
e, env, matchelt)) {
|
||||
*match = e->negative ? -((int)i+1) : ((int)i+1);
|
||||
if (match_num == -1 || e->node_num < match_num) {
|
||||
if (e->negative)
|
||||
*match = -e->node_num;
|
||||
else
|
||||
*match = e->node_num;
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
}
|
||||
/* No match. */
|
||||
*match = 0;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Merge the contents of one ACL into another. Call dns_iptable_merge()
|
||||
* for the IP tables, then concatenate the element arrays.
|
||||
*
|
||||
* If pos is set to false, then the nested ACL is to be negated. This
|
||||
* means reverse the sense of each *positive* element or IP table node,
|
||||
* but leave negatives alone, so as to prevent a double-negative causing
|
||||
* an unexpected postive match in the parent ACL.
|
||||
*/
|
||||
isc_result_t
|
||||
dns_acl_elementmatch(const dns_acl_t *acl,
|
||||
const dns_aclelement_t *elt,
|
||||
const dns_aclelement_t **matchelt)
|
||||
dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int newalloc, nelem, i;
|
||||
int max_node = 0, nodes;
|
||||
|
||||
REQUIRE(elt != NULL);
|
||||
REQUIRE(matchelt == NULL || *matchelt == NULL);
|
||||
/* Resize the element array if needed. */
|
||||
if (dest->length + source->length > dest->alloc) {
|
||||
void *newmem;
|
||||
|
||||
for (i = 0; i < acl->length; i++) {
|
||||
dns_aclelement_t *e = &acl->elements[i];
|
||||
newalloc = dest->alloc + source->alloc;
|
||||
if (newalloc < 4)
|
||||
newalloc = 4;
|
||||
|
||||
if (dns_aclelement_equal(e, elt) == ISC_TRUE) {
|
||||
if (matchelt != NULL)
|
||||
*matchelt = e;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
}
|
||||
newmem = isc_mem_get(dest->mctx,
|
||||
newalloc * sizeof(dns_aclelement_t));
|
||||
if (newmem == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
return (ISC_R_NOTFOUND);
|
||||
/* Copy in the original elements */
|
||||
memcpy(newmem, dest->elements,
|
||||
dest->length * sizeof(dns_aclelement_t));
|
||||
|
||||
/* Release the memory for the old elements array */
|
||||
isc_mem_put(dest->mctx, dest->elements,
|
||||
dest->alloc * sizeof(dns_aclelement_t));
|
||||
dest->elements = newmem;
|
||||
dest->alloc = newalloc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now copy in the new elements, increasing their node_num
|
||||
* values so as to keep the new ACL consistent. If we're
|
||||
* negating, then negate positive elements, but keep negative
|
||||
* elements the same for security reasons.
|
||||
*/
|
||||
nelem = dest->length;
|
||||
memcpy(&dest->elements[nelem], source->elements,
|
||||
(source->length * sizeof(dns_aclelement_t)));
|
||||
for (i = 0; i < source->length; i++) {
|
||||
dest->elements[nelem + i].node_num =
|
||||
source->elements[i].node_num + dest->node_count;
|
||||
if (source->elements[i].node_num > max_node)
|
||||
max_node = source->elements[i].node_num;
|
||||
if (!pos && source->elements[i].negative == ISC_FALSE)
|
||||
dest->elements[nelem + i].negative = ISC_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Merge the iptables. Make sure the destination ACL's
|
||||
* node_count value is set correctly afterward.
|
||||
*/
|
||||
nodes = max_node + dest->node_count;
|
||||
dns_iptable_merge(dest->iptable, source->iptable, pos);
|
||||
if (nodes > dest->node_count)
|
||||
dest->node_count = nodes;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Like dns_acl_match, but matches against the single ACL element 'e'
|
||||
* rather than a complete ACL, and returns ISC_TRUE iff it matched.
|
||||
*
|
||||
* To determine whether the match was prositive or negative, the
|
||||
* caller should examine e->negative. Since the element 'e' may be
|
||||
* a reference to a named ACL or a nested ACL, a matching element
|
||||
* returned through 'matchelt' is not necessarily 'e' itself.
|
||||
*/
|
||||
isc_boolean_t
|
||||
dns_aclelement_match(const isc_netaddr_t *reqaddr,
|
||||
const dns_name_t *reqsigner,
|
||||
@@ -186,89 +323,65 @@ dns_aclelement_match(const isc_netaddr_t *reqaddr,
|
||||
const dns_aclelement_t **matchelt)
|
||||
{
|
||||
dns_acl_t *inner = NULL;
|
||||
const isc_netaddr_t *addr;
|
||||
isc_netaddr_t v4addr;
|
||||
int indirectmatch;
|
||||
isc_result_t result;
|
||||
|
||||
switch (e->type) {
|
||||
case dns_aclelementtype_ipprefix:
|
||||
if (env == NULL ||
|
||||
env->match_mapped == ISC_FALSE ||
|
||||
reqaddr->family != AF_INET6 ||
|
||||
!IN6_IS_ADDR_V4MAPPED(&reqaddr->type.in6))
|
||||
addr = reqaddr;
|
||||
else {
|
||||
isc_netaddr_fromv4mapped(&v4addr, reqaddr);
|
||||
addr = &v4addr;
|
||||
}
|
||||
|
||||
if (isc_netaddr_eqprefix(addr,
|
||||
&e->u.ip_prefix.address,
|
||||
e->u.ip_prefix.prefixlen))
|
||||
goto matched;
|
||||
break;
|
||||
|
||||
case dns_aclelementtype_keyname:
|
||||
switch (e->type) {
|
||||
case dns_aclelementtype_keyname:
|
||||
if (reqsigner != NULL &&
|
||||
dns_name_equal(reqsigner, &e->u.keyname))
|
||||
goto matched;
|
||||
break;
|
||||
dns_name_equal(reqsigner, &e->keyname)) {
|
||||
if (matchelt != NULL)
|
||||
*matchelt = e;
|
||||
return (ISC_TRUE);
|
||||
} else {
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
case dns_aclelementtype_nestedacl:
|
||||
inner = e->u.nestedacl;
|
||||
nested:
|
||||
result = dns_acl_match(reqaddr, reqsigner,
|
||||
inner,
|
||||
env,
|
||||
&indirectmatch, matchelt);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
case dns_aclelementtype_nestedacl:
|
||||
inner = e->nestedacl;
|
||||
break;
|
||||
|
||||
/*
|
||||
* Treat negative matches in indirect ACLs as
|
||||
* "no match".
|
||||
* That way, a negated indirect ACL will never become
|
||||
* a surprise positive match through double negation.
|
||||
* XXXDCL this should be documented.
|
||||
*/
|
||||
if (indirectmatch > 0)
|
||||
goto matchelt_set;
|
||||
case dns_aclelementtype_localhost:
|
||||
if (env == NULL || env->localhost == NULL)
|
||||
return (ISC_FALSE);
|
||||
inner = env->localhost;
|
||||
break;
|
||||
|
||||
/*
|
||||
* A negative indirect match may have set *matchelt,
|
||||
* but we don't want it set when we return.
|
||||
*/
|
||||
if (matchelt != NULL)
|
||||
*matchelt = NULL;
|
||||
break;
|
||||
case dns_aclelementtype_localnets:
|
||||
if (env == NULL || env->localnets == NULL)
|
||||
return (ISC_FALSE);
|
||||
inner = env->localnets;
|
||||
break;
|
||||
|
||||
case dns_aclelementtype_any:
|
||||
matched:
|
||||
if (matchelt != NULL)
|
||||
*matchelt = e;
|
||||
matchelt_set:
|
||||
return (ISC_TRUE);
|
||||
default:
|
||||
/* Should be impossible */
|
||||
INSIST(0);
|
||||
}
|
||||
|
||||
case dns_aclelementtype_localhost:
|
||||
if (env != NULL && env->localhost != NULL) {
|
||||
inner = env->localhost;
|
||||
goto nested;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
result = dns_acl_match(reqaddr, reqsigner, inner, env,
|
||||
&indirectmatch, matchelt);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
|
||||
case dns_aclelementtype_localnets:
|
||||
if (env != NULL && env->localnets != NULL) {
|
||||
inner = env->localnets;
|
||||
goto nested;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Treat negative matches in indirect ACLs as "no match".
|
||||
* That way, a negated indirect ACL will never become a
|
||||
* surprise positive match through double negation.
|
||||
* XXXDCL this should be documented.
|
||||
*/
|
||||
|
||||
default:
|
||||
INSIST(0);
|
||||
break;
|
||||
}
|
||||
if (indirectmatch > 0) {
|
||||
if (matchelt != NULL)
|
||||
*matchelt = e;
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* A negative indirect match may have set *matchelt, but we don't
|
||||
* want it set when we return.
|
||||
*/
|
||||
|
||||
if (matchelt != NULL)
|
||||
*matchelt = NULL;
|
||||
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
@@ -285,15 +398,8 @@ destroy(dns_acl_t *dacl) {
|
||||
unsigned int i;
|
||||
for (i = 0; i < dacl->length; i++) {
|
||||
dns_aclelement_t *de = &dacl->elements[i];
|
||||
switch (de->type) {
|
||||
case dns_aclelementtype_keyname:
|
||||
dns_name_free(&de->u.keyname, dacl->mctx);
|
||||
break;
|
||||
case dns_aclelementtype_nestedacl:
|
||||
dns_acl_detach(&de->u.nestedacl);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (de->type == dns_aclelementtype_keyname) {
|
||||
dns_name_free(&de->keyname, dacl->mctx);
|
||||
}
|
||||
}
|
||||
if (dacl->elements != NULL)
|
||||
@@ -301,6 +407,8 @@ destroy(dns_acl_t *dacl) {
|
||||
dacl->alloc * sizeof(dns_aclelement_t));
|
||||
if (dacl->name != NULL)
|
||||
isc_mem_free(dacl->mctx, dacl->name);
|
||||
if (dacl->iptable != NULL)
|
||||
dns_iptable_detach(&dacl->iptable);
|
||||
isc_refcount_destroy(&dacl->refcount);
|
||||
dacl->magic = 0;
|
||||
isc_mem_put(dacl->mctx, dacl, sizeof(*dacl));
|
||||
@@ -317,69 +425,62 @@ dns_acl_detach(dns_acl_t **aclp) {
|
||||
*aclp = NULL;
|
||||
}
|
||||
|
||||
isc_boolean_t
|
||||
dns_aclelement_equal(const dns_aclelement_t *ea, const dns_aclelement_t *eb) {
|
||||
if (ea->type != eb->type)
|
||||
return (ISC_FALSE);
|
||||
switch (ea->type) {
|
||||
case dns_aclelementtype_ipprefix:
|
||||
if (ea->u.ip_prefix.prefixlen !=
|
||||
eb->u.ip_prefix.prefixlen)
|
||||
return (ISC_FALSE);
|
||||
return (isc_netaddr_eqprefix(&ea->u.ip_prefix.address,
|
||||
&eb->u.ip_prefix.address,
|
||||
ea->u.ip_prefix.prefixlen));
|
||||
case dns_aclelementtype_keyname:
|
||||
return (dns_name_equal(&ea->u.keyname, &eb->u.keyname));
|
||||
case dns_aclelementtype_nestedacl:
|
||||
return (dns_acl_equal(ea->u.nestedacl, eb->u.nestedacl));
|
||||
case dns_aclelementtype_localhost:
|
||||
case dns_aclelementtype_localnets:
|
||||
case dns_aclelementtype_any:
|
||||
return (ISC_TRUE);
|
||||
default:
|
||||
INSIST(0);
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
}
|
||||
static isc_boolean_t insecure_prefix_found;
|
||||
|
||||
isc_boolean_t
|
||||
dns_acl_equal(const dns_acl_t *a, const dns_acl_t *b) {
|
||||
unsigned int i;
|
||||
if (a == b)
|
||||
return (ISC_TRUE);
|
||||
if (a->length != b->length)
|
||||
return (ISC_FALSE);
|
||||
for (i = 0; i < a->length; i++) {
|
||||
if (! dns_aclelement_equal(&a->elements[i],
|
||||
&b->elements[i]))
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
/*
|
||||
* Called via isc_radix_walk() to find IP table nodes that are
|
||||
* insecure.
|
||||
*/
|
||||
static void
|
||||
is_insecure(isc_prefix_t *prefix, isc_boolean_t *data) {
|
||||
/* Negated entries are always secure */
|
||||
if(* (isc_boolean_t *)data == ISC_FALSE) {
|
||||
return;
|
||||
}
|
||||
|
||||
static isc_boolean_t
|
||||
is_loopback(const dns_aclipprefix_t *p) {
|
||||
switch (p->address.family) {
|
||||
case AF_INET:
|
||||
if (p->prefixlen == 32 &&
|
||||
htonl(p->address.type.in.s_addr) == INADDR_LOOPBACK)
|
||||
return (ISC_TRUE);
|
||||
/* If loopback prefix found, return */
|
||||
switch (prefix->family) {
|
||||
case AF_INET:
|
||||
if (prefix->bitlen == 32 &&
|
||||
htonl(prefix->add.sin.s_addr) == INADDR_LOOPBACK)
|
||||
return;
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (p->prefixlen == 128 &&
|
||||
IN6_IS_ADDR_LOOPBACK(&p->address.type.in6))
|
||||
return (ISC_TRUE);
|
||||
case AF_INET6:
|
||||
if (prefix->bitlen == 128 &&
|
||||
IN6_IS_ADDR_LOOPBACK(&prefix->add.sin6))
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (ISC_FALSE);
|
||||
|
||||
/* Non-negated, non-loopback */
|
||||
insecure_prefix_found = ISC_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return ISC_TRUE iff the acl 'a' is considered insecure, that is,
|
||||
* if it contains IP addresses other than those of the local host.
|
||||
* This is intended for applications such as printing warning
|
||||
* messages for suspect ACLs; it is not intended for making access
|
||||
* control decisions. We make no guarantee that an ACL for which
|
||||
* this function returns ISC_FALSE is safe.
|
||||
*/
|
||||
isc_boolean_t
|
||||
dns_acl_isinsecure(const dns_acl_t *a) {
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* Walk radix tree to find out if there are any non-negated,
|
||||
* non-loopback prefixes.
|
||||
*/
|
||||
insecure_prefix_found = ISC_FALSE;
|
||||
isc_radix_process(a->iptable->radix, is_insecure);
|
||||
if(insecure_prefix_found)
|
||||
return(ISC_TRUE);
|
||||
|
||||
/* Now check non-radix elements */
|
||||
for (i = 0; i < a->length; i++) {
|
||||
dns_aclelement_t *e = &a->elements[i];
|
||||
|
||||
@@ -388,34 +489,31 @@ dns_acl_isinsecure(const dns_acl_t *a) {
|
||||
continue;
|
||||
|
||||
switch (e->type) {
|
||||
case dns_aclelementtype_ipprefix:
|
||||
/* The loopback address is considered secure. */
|
||||
if (! is_loopback(&e->u.ip_prefix))
|
||||
return (ISC_TRUE);
|
||||
case dns_aclelementtype_keyname:
|
||||
case dns_aclelementtype_localhost:
|
||||
continue;
|
||||
|
||||
case dns_aclelementtype_keyname:
|
||||
case dns_aclelementtype_localhost:
|
||||
continue;
|
||||
case dns_aclelementtype_nestedacl:
|
||||
if (dns_acl_isinsecure(e->nestedacl))
|
||||
return (ISC_TRUE);
|
||||
continue;
|
||||
|
||||
case dns_aclelementtype_nestedacl:
|
||||
if (dns_acl_isinsecure(e->u.nestedacl))
|
||||
return (ISC_TRUE);
|
||||
continue;
|
||||
|
||||
case dns_aclelementtype_localnets:
|
||||
case dns_aclelementtype_any:
|
||||
case dns_aclelementtype_localnets:
|
||||
return (ISC_TRUE);
|
||||
|
||||
default:
|
||||
default:
|
||||
INSIST(0);
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* No insecure elements were found. */
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize ACL environment, setting up localhost and localnets ACLs
|
||||
*/
|
||||
isc_result_t
|
||||
dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env) {
|
||||
isc_result_t result;
|
||||
|
@@ -13,7 +13,7 @@
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id: Makefile.in,v 1.52 2007/06/19 23:47:16 tbox Exp $
|
||||
# $Id: Makefile.in,v 1.53 2007/09/12 01:09:08 each Exp $
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
@@ -24,7 +24,7 @@ top_srcdir = @top_srcdir@
|
||||
HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h \
|
||||
cert.h compress.h \
|
||||
db.h dbiterator.h dbtable.h diff.h dispatch.h \
|
||||
dnssec.h ds.h events.h fixedname.h journal.h keyflags.h \
|
||||
dnssec.h ds.h events.h fixedname.h iptable.h journal.h keyflags.h \
|
||||
keytable.h keyvalues.h lib.h log.h master.h masterdump.h \
|
||||
message.h name.h ncache.h \
|
||||
nsec.h peer.h portlist.h rbt.h rcode.h \
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: acl.h,v 1.29 2007/06/19 23:47:16 tbox Exp $ */
|
||||
/* $Id: acl.h,v 1.30 2007/09/12 01:09:08 each Exp $ */
|
||||
|
||||
#ifndef DNS_ACL_H
|
||||
#define DNS_ACL_H 1
|
||||
@@ -40,6 +40,7 @@
|
||||
|
||||
#include <dns/name.h>
|
||||
#include <dns/types.h>
|
||||
#include <dns/iptable.h>
|
||||
|
||||
/***
|
||||
*** Types
|
||||
@@ -64,17 +65,17 @@ struct dns_aclipprefix {
|
||||
struct dns_aclelement {
|
||||
dns_aclelemettype_t type;
|
||||
isc_boolean_t negative;
|
||||
union {
|
||||
dns_aclipprefix_t ip_prefix;
|
||||
dns_name_t keyname;
|
||||
dns_acl_t *nestedacl;
|
||||
} u;
|
||||
dns_name_t keyname;
|
||||
dns_acl_t *nestedacl;
|
||||
int node_num;
|
||||
};
|
||||
|
||||
struct dns_acl {
|
||||
unsigned int magic;
|
||||
isc_mem_t *mctx;
|
||||
isc_refcount_t refcount;
|
||||
dns_iptable_t *iptable;
|
||||
#define node_count iptable->radix->num_added_node
|
||||
dns_aclelement_t *elements;
|
||||
unsigned int alloc; /*%< Elements allocated */
|
||||
unsigned int length; /*%< Elements initialized */
|
||||
@@ -100,14 +101,9 @@ ISC_LANG_BEGINDECLS
|
||||
isc_result_t
|
||||
dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target);
|
||||
/*%<
|
||||
* Create a new ACL with room for 'n' elements.
|
||||
* The elements are uninitialized and the length is 0.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_acl_appendelement(dns_acl_t *acl, const dns_aclelement_t *elt);
|
||||
/*%<
|
||||
* Append an element to an existing ACL.
|
||||
* Create a new ACL, including an IP table and an array with room
|
||||
* for 'n' ACL elements. The elements are uninitialized and the
|
||||
* length is 0.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
@@ -122,18 +118,36 @@ dns_acl_none(isc_mem_t *mctx, dns_acl_t **target);
|
||||
* Create a new ACL that matches nothing.
|
||||
*/
|
||||
|
||||
isc_boolean_t
|
||||
dns_acl_isany(dns_acl_t *acl);
|
||||
/*%<
|
||||
* Test whether ACL is set to "{ any; }"
|
||||
*/
|
||||
|
||||
isc_boolean_t
|
||||
dns_acl_isnone(dns_acl_t *acl);
|
||||
/*%<
|
||||
* Test whether ACL is set to "{ none; }"
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos);
|
||||
/*%<
|
||||
* Merge the contents of one ACL into another. Call dns_iptable_merge()
|
||||
* for the IP tables, then concatenate the element arrays.
|
||||
*
|
||||
* If pos is set to false, then the nested ACL is to be negated. This
|
||||
* means reverse the sense of each *positive* element or IP table node,
|
||||
* but leave negatives alone, so as to prevent a double-negative causing
|
||||
* an unexpected postive match in the parent ACL.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_acl_attach(dns_acl_t *source, dns_acl_t **target);
|
||||
|
||||
void
|
||||
dns_acl_detach(dns_acl_t **aclp);
|
||||
|
||||
isc_boolean_t
|
||||
dns_aclelement_equal(const dns_aclelement_t *ea, const dns_aclelement_t *eb);
|
||||
|
||||
isc_boolean_t
|
||||
dns_acl_equal(const dns_acl_t *a, const dns_acl_t *b);
|
||||
|
||||
isc_boolean_t
|
||||
dns_acl_isinsecure(const dns_acl_t *a);
|
||||
/*%<
|
||||
@@ -147,6 +161,9 @@ dns_acl_isinsecure(const dns_acl_t *a);
|
||||
|
||||
isc_result_t
|
||||
dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env);
|
||||
/*%<
|
||||
* Initialize ACL environment, setting up localhost and localnets ACLs
|
||||
*/
|
||||
|
||||
void
|
||||
dns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s);
|
||||
@@ -168,19 +185,17 @@ dns_acl_match(const isc_netaddr_t *reqaddr,
|
||||
* Match the address 'reqaddr', and optionally the key name 'reqsigner',
|
||||
* against 'acl'. 'reqsigner' may be NULL.
|
||||
*
|
||||
* If there is a positive match, '*match' will be set to a positive value
|
||||
* indicating the distance from the beginning of the list.
|
||||
*
|
||||
* If there is a negative match, '*match' will be set to a negative value
|
||||
* whose absolute value indicates the distance from the beginning of
|
||||
* the list.
|
||||
*
|
||||
* If there is a match (either positive or negative) and 'matchelt' is
|
||||
* non-NULL, *matchelt will be attached to the primitive
|
||||
* (non-indirect) address match list element that matched.
|
||||
* If there is a match, '*match' will be set to an integer whose absolute
|
||||
* value corresponds to the order in which the matching value was inserted
|
||||
* into the ACL. For a positive match, this value will be positive; for a
|
||||
* negative match, it will be negative.
|
||||
*
|
||||
* If there is no match, *match will be set to zero.
|
||||
*
|
||||
* If there is a match in the element list (either positive or negative)
|
||||
* and 'matchelt' is non-NULL, *matchelt will be pointed to the matching
|
||||
* element.
|
||||
*
|
||||
* Returns:
|
||||
*\li #ISC_R_SUCCESS Always succeeds.
|
||||
*/
|
||||
@@ -193,30 +208,14 @@ dns_aclelement_match(const isc_netaddr_t *reqaddr,
|
||||
const dns_aclelement_t **matchelt);
|
||||
/*%<
|
||||
* Like dns_acl_match, but matches against the single ACL element 'e'
|
||||
* rather than a complete list and returns ISC_TRUE iff it matched.
|
||||
* rather than a complete ACL, and returns ISC_TRUE iff it matched.
|
||||
*
|
||||
* To determine whether the match was prositive or negative, the
|
||||
* caller should examine e->negative. Since the element 'e' may be
|
||||
* a reference to a named ACL or a nested ACL, the matching element
|
||||
* a reference to a named ACL or a nested ACL, a matching element
|
||||
* returned through 'matchelt' is not necessarily 'e' itself.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_acl_elementmatch(const dns_acl_t *acl,
|
||||
const dns_aclelement_t *elt,
|
||||
const dns_aclelement_t **matchelt);
|
||||
/*%<
|
||||
* Search for an ACL element in 'acl' which is exactly the same as 'elt'.
|
||||
* If there is one, and 'matchelt' is non NULL, then '*matchelt' will point
|
||||
* to the entry.
|
||||
*
|
||||
* This function is intended to be used for avoiding duplicated ACL entries
|
||||
* before adding an entry.
|
||||
*
|
||||
* Returns:
|
||||
*\li #ISC_R_SUCCESS Match succeeds.
|
||||
*\li #ISC_R_NOTFOUND Match fails.
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* DNS_ACL_H */
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: types.h,v 1.125 2007/06/19 23:47:17 tbox Exp $ */
|
||||
/* $Id: types.h,v 1.126 2007/09/12 01:09:08 each Exp $ */
|
||||
|
||||
#ifndef DNS_TYPES_H
|
||||
#define DNS_TYPES_H 1
|
||||
@@ -68,6 +68,7 @@ typedef struct dns_fetch dns_fetch_t;
|
||||
typedef struct dns_fixedname dns_fixedname_t;
|
||||
typedef struct dns_forwarders dns_forwarders_t;
|
||||
typedef struct dns_fwdtable dns_fwdtable_t;
|
||||
typedef struct dns_iptable dns_iptable_t;
|
||||
typedef isc_uint16_t dns_keyflags_t;
|
||||
typedef struct dns_keynode dns_keynode_t;
|
||||
typedef struct dns_keytable dns_keytable_t;
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: zone.c,v 1.467 2007/08/30 05:08:42 marka Exp $ */
|
||||
/* $Id: zone.c,v 1.468 2007/09/12 01:09:08 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -1144,11 +1144,7 @@ zone_isdynamic(dns_zone_t *zone) {
|
||||
zone->type == dns_zone_stub ||
|
||||
(!zone->update_disabled && zone->ssutable != NULL) ||
|
||||
(!zone->update_disabled && zone->update_acl != NULL &&
|
||||
! (zone->update_acl->length == 1 &&
|
||||
zone->update_acl->elements[0].negative == ISC_TRUE
|
||||
&&
|
||||
zone->update_acl->elements[0].type ==
|
||||
dns_aclelementtype_any))));
|
||||
!dns_acl_isnone(zone->update_acl))));
|
||||
}
|
||||
|
||||
|
||||
|
@@ -13,7 +13,7 @@
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id: Makefile.in,v 1.91 2007/06/19 23:47:17 tbox Exp $
|
||||
# $Id: Makefile.in,v 1.92 2007/09/12 01:09:08 each Exp $
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
@@ -58,7 +58,7 @@ OBJS = @ISC_EXTRA_OBJS@ \
|
||||
lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \
|
||||
md5.@O@ mem.@O@ mutexblock.@O@ \
|
||||
netaddr.@O@ netscope.@O@ ondestroy.@O@ \
|
||||
parseint.@O@ quota.@O@ random.@O@ \
|
||||
parseint.@O@ quota.@O@ radix.@O@ random.@O@ \
|
||||
ratelimiter.@O@ refcount.@O@ region.@O@ result.@O@ rwlock.@O@ \
|
||||
serial.@O@ sha1.@O@ sha2.@O@ sockaddr.@O@ \
|
||||
string.@O@ strtoul.@O@ symtab.@O@ task.@O@ taskpool.@O@ \
|
||||
@@ -73,7 +73,7 @@ SRCS = @ISC_EXTRA_SRCS@ \
|
||||
lex.c lfsr.c lib.c log.c \
|
||||
md5.c mem.c mutexblock.c \
|
||||
netaddr.c netscope.c ondestroy.c \
|
||||
parseint.c quota.c random.c \
|
||||
parseint.c quota.c radix.c random.c \
|
||||
ratelimiter.c refcount.c region.c result.c rwlock.c \
|
||||
serial.c sha1.c sha2.c sockaddr.c string.c strtoul.c \
|
||||
symtab.c task.c taskpool.c timer.c version.c
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: aclconf.c,v 1.9 2007/06/19 23:47:22 tbox Exp $ */
|
||||
/* $Id: aclconf.c,v 1.10 2007/09/12 01:09:08 each Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <isccfg/aclconf.h>
|
||||
|
||||
#include <dns/acl.h>
|
||||
#include <dns/iptable.h>
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/log.h>
|
||||
|
||||
@@ -40,6 +41,7 @@ cfg_aclconfctx_init(cfg_aclconfctx_t *ctx) {
|
||||
void
|
||||
cfg_aclconfctx_destroy(cfg_aclconfctx_t *ctx) {
|
||||
dns_acl_t *dacl, *next;
|
||||
|
||||
for (dacl = ISC_LIST_HEAD(ctx->named_acl_cache);
|
||||
dacl != NULL;
|
||||
dacl = next)
|
||||
@@ -67,7 +69,9 @@ get_acl_def(const cfg_obj_t *cctx, const char *name, const cfg_obj_t **ret) {
|
||||
const cfg_obj_t *acl = cfg_listelt_value(elt);
|
||||
const char *aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
|
||||
if (strcasecmp(aclname, name) == 0) {
|
||||
*ret = cfg_tuple_get(acl, "value");
|
||||
if (ret != NULL) {
|
||||
*ret = cfg_tuple_get(acl, "value");
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
}
|
||||
@@ -77,7 +81,8 @@ get_acl_def(const cfg_obj_t *cctx, const char *name, const cfg_obj_t **ret) {
|
||||
static isc_result_t
|
||||
convert_named_acl(const cfg_obj_t *nameobj, const cfg_obj_t *cctx,
|
||||
isc_log_t *lctx, cfg_aclconfctx_t *ctx,
|
||||
isc_mem_t *mctx, dns_acl_t **target)
|
||||
isc_mem_t *mctx, int nest_level,
|
||||
dns_acl_t **target)
|
||||
{
|
||||
isc_result_t result;
|
||||
const cfg_obj_t *cacl = NULL;
|
||||
@@ -115,7 +120,8 @@ convert_named_acl(const cfg_obj_t *nameobj, const cfg_obj_t *cctx,
|
||||
DE_CONST(aclname, loop.name);
|
||||
loop.magic = LOOP_MAGIC;
|
||||
ISC_LIST_APPEND(ctx->named_acl_cache, &loop, nextincache);
|
||||
result = cfg_acl_fromconfig(cacl, cctx, lctx, ctx, mctx, &dacl);
|
||||
result = cfg_acl_fromconfig(cacl, cctx, lctx, ctx, mctx,
|
||||
nest_level, &dacl);
|
||||
ISC_LIST_UNLINK(ctx->named_acl_cache, &loop, nextincache);
|
||||
loop.magic = 0;
|
||||
loop.name = NULL;
|
||||
@@ -160,25 +166,47 @@ cfg_acl_fromconfig(const cfg_obj_t *caml,
|
||||
isc_log_t *lctx,
|
||||
cfg_aclconfctx_t *ctx,
|
||||
isc_mem_t *mctx,
|
||||
int nest_level,
|
||||
dns_acl_t **target)
|
||||
{
|
||||
isc_result_t result;
|
||||
unsigned int count;
|
||||
dns_acl_t *dacl = NULL;
|
||||
dns_acl_t *dacl = NULL, *inneracl = NULL;
|
||||
dns_aclelement_t *de;
|
||||
const cfg_listelt_t *elt;
|
||||
dns_iptable_t *iptab;
|
||||
|
||||
REQUIRE(target != NULL && *target == NULL);
|
||||
REQUIRE(target != NULL);
|
||||
REQUIRE(*target == NULL || ISC_MAGIC_VALID(target, DNS_ACL_MAGIC));
|
||||
|
||||
count = 0;
|
||||
for (elt = cfg_list_first(caml);
|
||||
elt != NULL;
|
||||
elt = cfg_list_next(elt))
|
||||
count++;
|
||||
|
||||
result = dns_acl_create(mctx, count, &dacl);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
if (*target != NULL) {
|
||||
/*
|
||||
* If target already points to an ACL, then we're being
|
||||
* called recursively to configure a nested ACL. The
|
||||
* nested ACL's contents should just be absorbed into its
|
||||
* parent ACL.
|
||||
*/
|
||||
dacl = *target;
|
||||
} else {
|
||||
/*
|
||||
* Need to allocate a new ACL structure. Count the items
|
||||
* in the ACL definition and allocate space for that many
|
||||
* elements (even though some or all of them may end up in
|
||||
* the iptable instead of the element array).
|
||||
*/
|
||||
unsigned int element_count = 0;
|
||||
for (elt = cfg_list_first(caml);
|
||||
elt != NULL;
|
||||
elt = cfg_list_next(elt)) {
|
||||
const cfg_obj_t *ce = cfg_listelt_value(elt);
|
||||
if (cfg_obj_istuple(ce))
|
||||
ce = cfg_tuple_get(ce, "value");
|
||||
if (cfg_obj_isnetprefix(ce))
|
||||
element_count++;
|
||||
}
|
||||
result = dns_acl_create(mctx, element_count, &dacl);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
}
|
||||
|
||||
de = dacl->elements;
|
||||
for (elt = cfg_list_first(caml);
|
||||
@@ -186,56 +214,114 @@ cfg_acl_fromconfig(const cfg_obj_t *caml,
|
||||
elt = cfg_list_next(elt))
|
||||
{
|
||||
const cfg_obj_t *ce = cfg_listelt_value(elt);
|
||||
isc_boolean_t neg;
|
||||
|
||||
if (cfg_obj_istuple(ce)) {
|
||||
/* This must be a negated element. */
|
||||
ce = cfg_tuple_get(ce, "value");
|
||||
de->negative = ISC_TRUE;
|
||||
} else {
|
||||
de->negative = ISC_FALSE;
|
||||
}
|
||||
neg = ISC_TRUE;
|
||||
} else
|
||||
neg = ISC_FALSE;
|
||||
|
||||
/*
|
||||
* If nest_level is nonzero, then every element is
|
||||
* to be stored as a separate, nested ACL rather than
|
||||
* merged into the main iptable.
|
||||
*/
|
||||
iptab = dacl->iptable;
|
||||
if (nest_level) {
|
||||
result = dns_acl_create(mctx, 0, &de->nestedacl);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
iptab = de->nestedacl->iptable;
|
||||
}
|
||||
|
||||
if (cfg_obj_isnetprefix(ce)) {
|
||||
/* Network prefix */
|
||||
de->type = dns_aclelementtype_ipprefix;
|
||||
isc_netaddr_t addr;
|
||||
unsigned int bitlen;
|
||||
|
||||
cfg_obj_asnetprefix(ce,
|
||||
&de->u.ip_prefix.address,
|
||||
&de->u.ip_prefix.prefixlen);
|
||||
} else if (cfg_obj_istype(ce, &cfg_type_keyref)) {
|
||||
/* Key name */
|
||||
de->type = dns_aclelementtype_keyname;
|
||||
dns_name_init(&de->u.keyname, NULL);
|
||||
result = convert_keyname(ce, lctx, mctx,
|
||||
&de->u.keyname);
|
||||
cfg_obj_asnetprefix(ce, &addr, &bitlen);
|
||||
result = dns_iptable_addprefix(iptab, &addr, bitlen,
|
||||
ISC_TF(!neg));
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
continue;
|
||||
} else if (cfg_obj_islist(ce)) {
|
||||
/* Nested ACL */
|
||||
de->type = dns_aclelementtype_nestedacl;
|
||||
result = cfg_acl_fromconfig(ce, cctx, lctx, ctx,
|
||||
mctx, &de->u.nestedacl);
|
||||
/*
|
||||
* If we're nesting ACLs, put the nested
|
||||
* ACL onto the elements list; otherwise
|
||||
* merge it into *this* ACL.
|
||||
*/
|
||||
if (nest_level == 0) {
|
||||
result = cfg_acl_fromconfig(ce,
|
||||
cctx, lctx, ctx, mctx, 0,
|
||||
&dacl);
|
||||
} else {
|
||||
de->type = dns_aclelementtype_nestedacl;
|
||||
de->negative = neg;
|
||||
result = cfg_acl_fromconfig(ce,
|
||||
cctx, lctx, ctx, mctx,
|
||||
nest_level - 1,
|
||||
&de->nestedacl);
|
||||
}
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
goto cleanup;
|
||||
continue;
|
||||
} else if (cfg_obj_isstring(ce)) {
|
||||
/* ACL name */
|
||||
const char *name = cfg_obj_asstring(ce);
|
||||
if (strcasecmp(name, "localhost") == 0) {
|
||||
if (strcasecmp(name, "any") == 0) {
|
||||
/* iptable entry with zero bit length */
|
||||
dns_iptable_addprefix(iptab, NULL, 0,
|
||||
ISC_TRUE);
|
||||
continue;
|
||||
} else if (strcasecmp(name, "none") == 0) {
|
||||
/* negated "any" */
|
||||
dns_iptable_addprefix(iptab, NULL, 0,
|
||||
ISC_FALSE);
|
||||
continue;
|
||||
} else if (strcasecmp(name, "localhost") == 0) {
|
||||
de->type = dns_aclelementtype_localhost;
|
||||
de->negative = neg;
|
||||
} else if (strcasecmp(name, "localnets") == 0) {
|
||||
de->type = dns_aclelementtype_localnets;
|
||||
} else if (strcasecmp(name, "any") == 0) {
|
||||
de->type = dns_aclelementtype_any;
|
||||
} else if (strcasecmp(name, "none") == 0) {
|
||||
de->type = dns_aclelementtype_any;
|
||||
de->negative = ISC_TF(! de->negative);
|
||||
de->negative = neg;
|
||||
} else {
|
||||
de->type = dns_aclelementtype_nestedacl;
|
||||
result = convert_named_acl(ce, cctx, lctx,
|
||||
ctx, mctx,
|
||||
&de->u.nestedacl);
|
||||
result = get_acl_def(cctx, name, NULL);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
/* found it in acl definitions */
|
||||
inneracl = NULL;
|
||||
result = convert_named_acl(ce, cctx,
|
||||
lctx, ctx, mctx,
|
||||
nest_level
|
||||
? (nest_level - 1)
|
||||
: 0,
|
||||
&inneracl);
|
||||
}
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
if (nest_level) {
|
||||
de->type = dns_aclelementtype_nestedacl,
|
||||
de->negative = neg;
|
||||
de->nestedacl = inneracl;
|
||||
} else {
|
||||
dns_acl_merge(dacl, inneracl,
|
||||
ISC_TF(!neg));
|
||||
dns_acl_detach(&inneracl);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else if (cfg_obj_istype(ce, &cfg_type_keyref)) {
|
||||
/* Key name */
|
||||
de->type = dns_aclelementtype_keyname;
|
||||
de->negative = neg;
|
||||
dns_name_init(&de->keyname, NULL);
|
||||
result = convert_keyname(ce, lctx, mctx,
|
||||
&de->keyname);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
} else {
|
||||
cfg_obj_log(ce, lctx, ISC_LOG_WARNING,
|
||||
"address match list contains "
|
||||
@@ -243,6 +329,16 @@ cfg_acl_fromconfig(const cfg_obj_t *caml,
|
||||
result = ISC_R_FAILURE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX each: This should only be reached for localhost,
|
||||
* localnets and keyname elements -- probably should
|
||||
* be refactored for clearer flow
|
||||
*/
|
||||
if (nest_level && de->type != dns_aclelementtype_nestedacl)
|
||||
dns_acl_detach(&de->nestedacl);
|
||||
|
||||
de->node_num = dacl->node_count++;
|
||||
de++;
|
||||
dacl->length++;
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: aclconf.h,v 1.8 2007/06/19 23:47:22 tbox Exp $ */
|
||||
/* $Id: aclconf.h,v 1.9 2007/09/12 01:09:08 each Exp $ */
|
||||
|
||||
#ifndef ISCCFG_ACLCONF_H
|
||||
#define ISCCFG_ACLCONF_H 1
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
typedef struct cfg_aclconfctx {
|
||||
ISC_LIST(dns_acl_t) named_acl_cache;
|
||||
ISC_LIST(dns_iptable_t) named_iptable_cache;
|
||||
} cfg_aclconfctx_t;
|
||||
|
||||
/***
|
||||
@@ -54,6 +55,7 @@ cfg_acl_fromconfig(const cfg_obj_t *caml,
|
||||
isc_log_t *lctx,
|
||||
cfg_aclconfctx_t *ctx,
|
||||
isc_mem_t *mctx,
|
||||
int nest_level,
|
||||
dns_acl_t **target);
|
||||
/*
|
||||
* Construct a new dns_acl_t from configuration data in 'caml' and
|
||||
|
Reference in New Issue
Block a user