mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 14:35:26 +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
|
2232. [bug] dns_adb_findaddrinfo() could fail and return
|
||||||
ISC_R_SUCCESS. [RT #17137]
|
ISC_R_SUCCESS. [RT #17137]
|
||||||
|
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* 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 */
|
/*! \file */
|
||||||
|
|
||||||
@@ -1014,7 +1014,7 @@ update_listener(ns_controls_t *cp, controllistener_t **listenerp,
|
|||||||
if (control != NULL && type == isc_sockettype_tcp) {
|
if (control != NULL && type == isc_sockettype_tcp) {
|
||||||
allow = cfg_tuple_get(control, "allow");
|
allow = cfg_tuple_get(control, "allow");
|
||||||
result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
|
result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
|
||||||
aclconfctx, listener->mctx,
|
aclconfctx, listener->mctx, 0,
|
||||||
&new_acl);
|
&new_acl);
|
||||||
} else {
|
} else {
|
||||||
result = dns_acl_any(listener->mctx, &new_acl);
|
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) {
|
if (control != NULL && type == isc_sockettype_tcp) {
|
||||||
allow = cfg_tuple_get(control, "allow");
|
allow = cfg_tuple_get(control, "allow");
|
||||||
result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
|
result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
|
||||||
aclconfctx, mctx, &new_acl);
|
aclconfctx, mctx, 0,
|
||||||
|
&new_acl);
|
||||||
} else {
|
} else {
|
||||||
result = dns_acl_any(mctx, &new_acl);
|
result = dns_acl_any(mctx, &new_acl);
|
||||||
}
|
}
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* 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 */
|
/*! \file */
|
||||||
|
|
||||||
@@ -483,7 +483,7 @@ static isc_result_t
|
|||||||
clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
|
clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
|
||||||
dns_acl_t *newacl = NULL;
|
dns_acl_t *newacl = NULL;
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
result = dns_acl_create(mctx, 10, &newacl);
|
result = dns_acl_create(mctx, 0, &newacl);
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
return (result);
|
return (result);
|
||||||
dns_acl_detach(aclp);
|
dns_acl_detach(aclp);
|
||||||
@@ -494,36 +494,31 @@ clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
|
|||||||
|
|
||||||
static isc_boolean_t
|
static isc_boolean_t
|
||||||
listenon_is_ip6_any(ns_listenelt_t *elt) {
|
listenon_is_ip6_any(ns_listenelt_t *elt) {
|
||||||
if (elt->acl->length != 1)
|
REQUIRE(elt && elt->acl);
|
||||||
return (ISC_FALSE);
|
return dns_acl_isany(elt->acl);
|
||||||
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 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
|
setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
dns_aclelement_t elt;
|
|
||||||
unsigned int family;
|
|
||||||
unsigned int prefixlen;
|
unsigned int prefixlen;
|
||||||
|
isc_netaddr_t *netaddr;
|
||||||
|
|
||||||
family = interface->address.family;
|
netaddr = &interface->address;
|
||||||
|
|
||||||
elt.type = dns_aclelementtype_ipprefix;
|
/* First add localhost address */
|
||||||
elt.negative = ISC_FALSE;
|
prefixlen = (netaddr->family == AF_INET) ? 32 : 128;
|
||||||
elt.u.ip_prefix.address = interface->address;
|
result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable,
|
||||||
elt.u.ip_prefix.prefixlen = (family == AF_INET) ? 32 : 128;
|
netaddr, prefixlen, ISC_TRUE);
|
||||||
result = dns_acl_appendelement(mgr->aclenv.localhost, &elt);
|
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
return (result);
|
return (result);
|
||||||
|
|
||||||
|
/* Then add localnets prefix */
|
||||||
result = isc_netaddr_masktoprefixlen(&interface->netmask,
|
result = isc_netaddr_masktoprefixlen(&interface->netmask,
|
||||||
&prefixlen);
|
&prefixlen);
|
||||||
|
|
||||||
/* Non contigious netmasks not allowed by IPv6 arch. */
|
/* 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);
|
return (result);
|
||||||
|
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
@@ -533,17 +528,14 @@ setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
|
|||||||
"localnets ACL: %s",
|
"localnets ACL: %s",
|
||||||
interface->name,
|
interface->name,
|
||||||
isc_result_totext(result));
|
isc_result_totext(result));
|
||||||
} else {
|
return (ISC_R_SUCCESS);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable,
|
||||||
|
netaddr, prefixlen, ISC_TRUE);
|
||||||
|
if (result != ISC_R_SUCCESS)
|
||||||
|
return (result);
|
||||||
|
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* 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 */
|
/*! \file */
|
||||||
|
|
||||||
@@ -307,7 +307,51 @@ configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config,
|
|||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
|
|
||||||
result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx,
|
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);
|
return (result);
|
||||||
}
|
}
|
||||||
@@ -1598,8 +1642,11 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
|
|||||||
"allow-query-cache", actx,
|
"allow-query-cache", actx,
|
||||||
ns_g_mctx, &view->queryacl));
|
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;
|
obj = NULL;
|
||||||
result = ns_config_get(maps, "request-ixfr", &obj);
|
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;
|
ns_listenelt_t *lelt = NULL;
|
||||||
dns_acl_t *src_acl = NULL;
|
dns_acl_t *src_acl = NULL;
|
||||||
dns_aclelement_t aelt;
|
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
isc_sockaddr_t any_sa6;
|
isc_sockaddr_t any_sa6;
|
||||||
|
isc_netaddr_t netaddr;
|
||||||
|
|
||||||
REQUIRE(isc_sockaddr_pf(addr) == AF_INET6);
|
REQUIRE(isc_sockaddr_pf(addr) == AF_INET6);
|
||||||
|
|
||||||
isc_sockaddr_any6(&any_sa6);
|
isc_sockaddr_any6(&any_sa6);
|
||||||
if (!isc_sockaddr_equal(&any_sa6, addr) &&
|
if (!isc_sockaddr_equal(&any_sa6, addr) &&
|
||||||
(wcardport_ok || isc_sockaddr_getport(addr) != 0)) {
|
(wcardport_ok || isc_sockaddr_getport(addr) != 0)) {
|
||||||
aelt.type = dns_aclelementtype_ipprefix;
|
isc_netaddr_fromin6(&netaddr, &addr->type.sin6.sin6_addr);
|
||||||
aelt.negative = ISC_FALSE;
|
|
||||||
aelt.u.ip_prefix.prefixlen = 128;
|
|
||||||
isc_netaddr_fromin6(&aelt.u.ip_prefix.address,
|
|
||||||
&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)
|
if (result != ISC_R_SUCCESS)
|
||||||
return (result);
|
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)
|
if (result != ISC_R_SUCCESS)
|
||||||
goto clean;
|
goto clean;
|
||||||
|
|
||||||
@@ -4391,7 +4436,8 @@ ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
|
|||||||
return (result);
|
return (result);
|
||||||
|
|
||||||
result = cfg_acl_fromconfig(cfg_tuple_get(listener, "acl"),
|
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) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
ns_listenelt_destroy(delt);
|
ns_listenelt_destroy(delt);
|
||||||
return (result);
|
return (result);
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* 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 */
|
/*! \file */
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ ns_sortlist_setup(dns_acl_t *acl, isc_netaddr_t *clientaddr,
|
|||||||
const dns_aclelement_t *matched_elt = NULL;
|
const dns_aclelement_t *matched_elt = NULL;
|
||||||
|
|
||||||
if (e->type == dns_aclelementtype_nestedacl) {
|
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)
|
if (inner->length < 1 || inner->length > 2)
|
||||||
goto dont_sort;
|
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 != NULL) {
|
||||||
if (order_elt->type ==
|
if (order_elt->type ==
|
||||||
dns_aclelementtype_nestedacl) {
|
dns_aclelementtype_nestedacl) {
|
||||||
*argp = order_elt->u.nestedacl;
|
*argp = order_elt->nestedacl;
|
||||||
return (NS_SORTLISTTYPE_2ELEMENT);
|
return (NS_SORTLISTTYPE_2ELEMENT);
|
||||||
} else if (order_elt->type ==
|
} else if (order_elt->type ==
|
||||||
dns_aclelementtype_localhost &&
|
dns_aclelementtype_localhost &&
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* 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,
|
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)
|
if (result != ISC_R_SUCCESS)
|
||||||
return (result);
|
return (result);
|
||||||
(*setzacl)(zone, dacl);
|
(*setzacl)(zone, dacl);
|
||||||
|
@@ -18,7 +18,7 @@
|
|||||||
- PERFORMANCE OF THIS SOFTWARE.
|
- 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">
|
<book xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||||
<title>BIND 9 Administrator Reference Manual</title>
|
<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
|
Address match lists are primarily used to determine access
|
||||||
control for various server operations. They are also used in
|
control for various server operations. They are also used in
|
||||||
the <command>listen-on</command> and <command>sortlist</command>
|
the <command>listen-on</command> and <command>sortlist</command>
|
||||||
statements. The elements
|
statements. The elements which constitute an address match
|
||||||
which constitute an address match list can be any of the
|
list can be any of the following:
|
||||||
following:
|
|
||||||
</para>
|
</para>
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>
|
<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>
|
<para>
|
||||||
Elements can be negated with a leading exclamation mark (`!'),
|
Elements can be negated with a leading exclamation mark (`!'),
|
||||||
and the match list names "any", "none", "localhost", and
|
and the match list names "any", "none", "localhost", and
|
||||||
"localnets"
|
"localnets" are predefined. More information on those names
|
||||||
are predefined. More information on those names can be found in
|
can be found in the description of the acl statement.
|
||||||
the description of the acl statement.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The addition of the key clause made the name of this syntactic
|
The addition of the key clause made the name of this syntactic
|
||||||
element something of a misnomer, since security keys can be used
|
element something of a misnomer, since security keys can be used
|
||||||
to validate access without regard to a host or network address.
|
to validate access without regard to a host or network address.
|
||||||
Nonetheless,
|
Nonetheless, the term "address match list" is still used
|
||||||
the term "address match list" is still used throughout the
|
throughout the documentation.
|
||||||
documentation.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
When a given IP address or prefix is compared to an address
|
When a given IP address or prefix is compared to an address
|
||||||
match list, the list is traversed in order until an element
|
match list, the comparison takes place in approximately O(1)
|
||||||
matches.
|
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
|
The interpretation of a match depends on whether the list is being
|
||||||
used
|
used for access control, defining listen-on ports, or in a
|
||||||
for access control, defining listen-on ports, or in a sortlist,
|
sortlist, and whether the element was negated.
|
||||||
and whether the element was negated.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<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>allow-update-forwarding</command>, and
|
||||||
<command>blackhole</command> all use address match
|
<command>blackhole</command> all use address match
|
||||||
lists. Similarly, the listen-on option will cause the
|
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.
|
addresses which do not match the list.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Because of the first-match aspect of the algorithm, an element
|
Order of insertion is signficant. If more than one element
|
||||||
that defines a subset of another element in the list should come
|
in an ACL is found to match a given IP address or prefix,
|
||||||
before the broader element, regardless of whether either is
|
preference will be given to the one that came
|
||||||
negated. For
|
<emphasis>first</emphasis> in the ACL definition.
|
||||||
example, in
|
Because of this first-match behavior, an element that
|
||||||
<command>1.2.3/24; ! 1.2.3.13;</command> the 1.2.3.13
|
defines a subset of another element in the list should
|
||||||
element is
|
come before the broader element, regardless of whether
|
||||||
completely useless because the algorithm will match any lookup for
|
either is negated. For example, in
|
||||||
1.2.3.13 to the 1.2.3/24 element.
|
<command>1.2.3/24; ! 1.2.3.13;</command>
|
||||||
Using <command>! 1.2.3.13; 1.2.3/24</command> fixes
|
the 1.2.3.13 element is completely useless because the
|
||||||
that problem by having 1.2.3.13 blocked by the negation but all
|
algorithm will match any lookup for 1.2.3.13 to the 1.2.3/24
|
||||||
other 1.2.3.* hosts fall through.
|
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>
|
</para>
|
||||||
</sect3>
|
</sect3>
|
||||||
</sect2>
|
</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>
|
<para>
|
||||||
Note that an address match list's name must be defined
|
Note that an address match list's name must be defined
|
||||||
with <command>acl</command> before it can be used
|
with <command>acl</command> before it can be used
|
||||||
elsewhere; no
|
elsewhere; no forward references are allowed.
|
||||||
forward references are allowed.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* 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 */
|
/*! \file */
|
||||||
|
|
||||||
@@ -379,7 +379,8 @@ checkacl(const char *aclname, cfg_aclconfctx_t *actx, const cfg_obj_t *zconfig,
|
|||||||
}
|
}
|
||||||
if (aclobj == NULL)
|
if (aclobj == NULL)
|
||||||
return (ISC_R_SUCCESS);
|
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)
|
if (acl != NULL)
|
||||||
dns_acl_detach(&acl);
|
dns_acl_detach(&acl);
|
||||||
return (result);
|
return (result);
|
||||||
@@ -459,7 +460,7 @@ check_recursionacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
tresult = cfg_acl_fromconfig(aclobj, config, logctx,
|
tresult = cfg_acl_fromconfig(aclobj, config, logctx,
|
||||||
actx, mctx, &acl);
|
actx, mctx, 0, &acl);
|
||||||
|
|
||||||
if (tresult != ISC_R_SUCCESS)
|
if (tresult != ISC_R_SUCCESS)
|
||||||
result = tresult;
|
result = tresult;
|
||||||
@@ -1932,7 +1933,7 @@ bind9_check_controls(const cfg_obj_t *config, isc_log_t *logctx,
|
|||||||
control = cfg_listelt_value(element2);
|
control = cfg_listelt_value(element2);
|
||||||
allow = cfg_tuple_get(control, "allow");
|
allow = cfg_tuple_get(control, "allow");
|
||||||
tresult = cfg_acl_fromconfig(allow, config, logctx,
|
tresult = cfg_acl_fromconfig(allow, config, logctx,
|
||||||
&actx, mctx, &acl);
|
&actx, mctx, 0, &acl);
|
||||||
if (acl != NULL)
|
if (acl != NULL)
|
||||||
dns_acl_detach(&acl);
|
dns_acl_detach(&acl);
|
||||||
if (tresult != ISC_R_SUCCESS)
|
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);
|
cfg_map_get(config, "acl", &acls);
|
||||||
if (tresult == ISC_R_SUCCESS) {
|
|
||||||
|
if (acls != NULL) {
|
||||||
const cfg_listelt_t *elt;
|
const cfg_listelt_t *elt;
|
||||||
const cfg_listelt_t *elt2;
|
const cfg_listelt_t *elt2;
|
||||||
const char *aclname;
|
const char *aclname;
|
||||||
@@ -2124,6 +2126,7 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
|
|||||||
elt != NULL;
|
elt != NULL;
|
||||||
elt = cfg_list_next(elt)) {
|
elt = cfg_list_next(elt)) {
|
||||||
const cfg_obj_t *acl = cfg_listelt_value(elt);
|
const cfg_obj_t *acl = cfg_listelt_value(elt);
|
||||||
|
unsigned int line = cfg_obj_line(acl);
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
|
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"));
|
"name"));
|
||||||
if (strcasecmp(aclname, name) == 0) {
|
if (strcasecmp(aclname, name) == 0) {
|
||||||
const char *file = cfg_obj_file(acl);
|
const char *file = cfg_obj_file(acl);
|
||||||
unsigned int line = cfg_obj_line(acl);
|
|
||||||
|
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
file = "<unknown file>";
|
file = "<unknown file>";
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
# PERFORMANCE OF THIS SOFTWARE.
|
# 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@
|
srcdir = @srcdir@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
@@ -53,8 +53,8 @@ DSTOBJS = @DST_EXTRA_OBJS@ \
|
|||||||
DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \
|
DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \
|
||||||
cache.@O@ callbacks.@O@ compress.@O@ \
|
cache.@O@ callbacks.@O@ compress.@O@ \
|
||||||
db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \
|
db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \
|
||||||
dlz.@O@ dnssec.@O@ ds.@O@ forward.@O@ journal.@O@ keytable.@O@ \
|
dlz.@O@ dnssec.@O@ ds.@O@ forward.@O@ iptable.@O@ journal.@O@ \
|
||||||
lib.@O@ log.@O@ lookup.@O@ \
|
keytable.@O@ lib.@O@ log.@O@ lookup.@O@ \
|
||||||
master.@O@ masterdump.@O@ message.@O@ \
|
master.@O@ masterdump.@O@ message.@O@ \
|
||||||
name.@O@ ncache.@O@ nsec.@O@ order.@O@ peer.@O@ portlist.@O@ \
|
name.@O@ ncache.@O@ nsec.@O@ order.@O@ peer.@O@ portlist.@O@ \
|
||||||
rbt.@O@ rbtdb.@O@ rbtdb64.@O@ rcode.@O@ rdata.@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 \
|
DNSSRCS = acache.c acl.c adb.c byaddr.c \
|
||||||
cache.c callbacks.c compress.c \
|
cache.c callbacks.c compress.c \
|
||||||
db.c dbiterator.c dbtable.c diff.c dispatch.c \
|
db.c dbiterator.c dbtable.c diff.c dispatch.c \
|
||||||
dlz.c dnssec.c ds.c forward.c journal.c keytable.c \
|
dlz.c dnssec.c ds.c forward.c iptable.c journal.c \
|
||||||
lib.c log.c lookup.c \
|
keytable.c lib.c log.c lookup.c \
|
||||||
master.c masterdump.c message.c \
|
master.c masterdump.c message.c \
|
||||||
name.c ncache.c nsec.c order.c peer.c portlist.c \
|
name.c ncache.c nsec.c order.c peer.c portlist.c \
|
||||||
rbt.c rbtdb.c rbtdb64.c rcode.c rdata.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.
|
* 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 */
|
/*! \file */
|
||||||
|
|
||||||
@@ -26,7 +26,13 @@
|
|||||||
#include <isc/util.h>
|
#include <isc/util.h>
|
||||||
|
|
||||||
#include <dns/acl.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
|
isc_result_t
|
||||||
dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
|
dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
|
||||||
isc_result_t result;
|
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);
|
return (ISC_R_NOMEMORY);
|
||||||
acl->mctx = mctx;
|
acl->mctx = mctx;
|
||||||
acl->name = NULL;
|
acl->name = NULL;
|
||||||
|
|
||||||
result = isc_refcount_init(&acl->refcount, 1);
|
result = isc_refcount_init(&acl->refcount, 1);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
isc_mem_put(mctx, acl, sizeof(*acl));
|
isc_mem_put(mctx, acl, sizeof(*acl));
|
||||||
return (result);
|
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->elements = NULL;
|
||||||
acl->alloc = 0;
|
acl->alloc = 0;
|
||||||
acl->length = 0;
|
acl->length = 0;
|
||||||
@@ -73,111 +87,234 @@ dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
|
|||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
/*
|
||||||
dns_acl_appendelement(dns_acl_t *acl, const dns_aclelement_t *elt) {
|
* Create a new ACL and initialize it with the value "any" or "none",
|
||||||
if (acl->length + 1 > acl->alloc) {
|
* depending on the value of the "neg" parameter.
|
||||||
/*
|
* "any" is a positive iptable entry with bit length 0.
|
||||||
* Resize the ACL.
|
* "none" is the same as "!any".
|
||||||
*/
|
*/
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
dns_acl_anyornone(isc_mem_t *mctx, isc_boolean_t neg, dns_acl_t **target) {
|
dns_acl_anyornone(isc_mem_t *mctx, isc_boolean_t neg, dns_acl_t **target) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
dns_acl_t *acl = NULL;
|
dns_acl_t *acl = NULL;
|
||||||
result = dns_acl_create(mctx, 1, &acl);
|
result = dns_acl_create(mctx, 0, &acl);
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
return (result);
|
return (result);
|
||||||
acl->elements[0].negative = neg;
|
dns_iptable_addprefix(acl->iptable, NULL, 0, ISC_TF(!neg));
|
||||||
acl->elements[0].type = dns_aclelementtype_any;
|
|
||||||
acl->length = 1;
|
|
||||||
*target = acl;
|
*target = acl;
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new ACL that matches everything.
|
||||||
|
*/
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_acl_any(isc_mem_t *mctx, dns_acl_t **target) {
|
dns_acl_any(isc_mem_t *mctx, dns_acl_t **target) {
|
||||||
return (dns_acl_anyornone(mctx, ISC_FALSE, target));
|
return (dns_acl_anyornone(mctx, ISC_FALSE, target));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new ACL that matches nothing.
|
||||||
|
*/
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_acl_none(isc_mem_t *mctx, dns_acl_t **target) {
|
dns_acl_none(isc_mem_t *mctx, dns_acl_t **target) {
|
||||||
return (dns_acl_anyornone(mctx, ISC_TRUE, 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
|
isc_result_t
|
||||||
dns_acl_match(const isc_netaddr_t *reqaddr,
|
dns_acl_match(const isc_netaddr_t *reqaddr,
|
||||||
const dns_name_t *reqsigner,
|
const dns_name_t *reqsigner,
|
||||||
const dns_acl_t *acl,
|
const dns_acl_t *acl,
|
||||||
const dns_aclenv_t *env,
|
const dns_aclenv_t *env,
|
||||||
int *match,
|
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;
|
unsigned int i;
|
||||||
|
|
||||||
REQUIRE(reqaddr != NULL);
|
REQUIRE(reqaddr != NULL);
|
||||||
REQUIRE(matchelt == NULL || *matchelt == 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++) {
|
for (i = 0; i < acl->length; i++) {
|
||||||
dns_aclelement_t *e = &acl->elements[i];
|
dns_aclelement_t *e = &acl->elements[i];
|
||||||
|
|
||||||
if (dns_aclelement_match(reqaddr, reqsigner,
|
if (dns_aclelement_match(reqaddr, reqsigner,
|
||||||
e, env, matchelt)) {
|
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);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* No match. */
|
|
||||||
*match = 0;
|
|
||||||
return (ISC_R_SUCCESS);
|
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
|
isc_result_t
|
||||||
dns_acl_elementmatch(const dns_acl_t *acl,
|
dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos)
|
||||||
const dns_aclelement_t *elt,
|
|
||||||
const dns_aclelement_t **matchelt)
|
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int newalloc, nelem, i;
|
||||||
|
int max_node = 0, nodes;
|
||||||
|
|
||||||
REQUIRE(elt != NULL);
|
/* Resize the element array if needed. */
|
||||||
REQUIRE(matchelt == NULL || *matchelt == NULL);
|
if (dest->length + source->length > dest->alloc) {
|
||||||
|
void *newmem;
|
||||||
|
|
||||||
for (i = 0; i < acl->length; i++) {
|
newalloc = dest->alloc + source->alloc;
|
||||||
dns_aclelement_t *e = &acl->elements[i];
|
if (newalloc < 4)
|
||||||
|
newalloc = 4;
|
||||||
|
|
||||||
if (dns_aclelement_equal(e, elt) == ISC_TRUE) {
|
newmem = isc_mem_get(dest->mctx,
|
||||||
if (matchelt != NULL)
|
newalloc * sizeof(dns_aclelement_t));
|
||||||
*matchelt = e;
|
if (newmem == NULL)
|
||||||
return (ISC_R_SUCCESS);
|
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
|
isc_boolean_t
|
||||||
dns_aclelement_match(const isc_netaddr_t *reqaddr,
|
dns_aclelement_match(const isc_netaddr_t *reqaddr,
|
||||||
const dns_name_t *reqsigner,
|
const dns_name_t *reqsigner,
|
||||||
@@ -186,89 +323,65 @@ dns_aclelement_match(const isc_netaddr_t *reqaddr,
|
|||||||
const dns_aclelement_t **matchelt)
|
const dns_aclelement_t **matchelt)
|
||||||
{
|
{
|
||||||
dns_acl_t *inner = NULL;
|
dns_acl_t *inner = NULL;
|
||||||
const isc_netaddr_t *addr;
|
|
||||||
isc_netaddr_t v4addr;
|
|
||||||
int indirectmatch;
|
int indirectmatch;
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
|
|
||||||
switch (e->type) {
|
switch (e->type) {
|
||||||
case dns_aclelementtype_ipprefix:
|
case dns_aclelementtype_keyname:
|
||||||
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:
|
|
||||||
if (reqsigner != NULL &&
|
if (reqsigner != NULL &&
|
||||||
dns_name_equal(reqsigner, &e->u.keyname))
|
dns_name_equal(reqsigner, &e->keyname)) {
|
||||||
goto matched;
|
if (matchelt != NULL)
|
||||||
break;
|
*matchelt = e;
|
||||||
|
return (ISC_TRUE);
|
||||||
|
} else {
|
||||||
|
return (ISC_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
case dns_aclelementtype_nestedacl:
|
case dns_aclelementtype_nestedacl:
|
||||||
inner = e->u.nestedacl;
|
inner = e->nestedacl;
|
||||||
nested:
|
break;
|
||||||
result = dns_acl_match(reqaddr, reqsigner,
|
|
||||||
inner,
|
|
||||||
env,
|
|
||||||
&indirectmatch, matchelt);
|
|
||||||
INSIST(result == ISC_R_SUCCESS);
|
|
||||||
|
|
||||||
/*
|
case dns_aclelementtype_localhost:
|
||||||
* Treat negative matches in indirect ACLs as
|
if (env == NULL || env->localhost == NULL)
|
||||||
* "no match".
|
return (ISC_FALSE);
|
||||||
* That way, a negated indirect ACL will never become
|
inner = env->localhost;
|
||||||
* a surprise positive match through double negation.
|
break;
|
||||||
* XXXDCL this should be documented.
|
|
||||||
*/
|
|
||||||
if (indirectmatch > 0)
|
|
||||||
goto matchelt_set;
|
|
||||||
|
|
||||||
/*
|
case dns_aclelementtype_localnets:
|
||||||
* A negative indirect match may have set *matchelt,
|
if (env == NULL || env->localnets == NULL)
|
||||||
* but we don't want it set when we return.
|
return (ISC_FALSE);
|
||||||
*/
|
inner = env->localnets;
|
||||||
if (matchelt != NULL)
|
break;
|
||||||
*matchelt = NULL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case dns_aclelementtype_any:
|
default:
|
||||||
matched:
|
/* Should be impossible */
|
||||||
if (matchelt != NULL)
|
INSIST(0);
|
||||||
*matchelt = e;
|
}
|
||||||
matchelt_set:
|
|
||||||
return (ISC_TRUE);
|
|
||||||
|
|
||||||
case dns_aclelementtype_localhost:
|
result = dns_acl_match(reqaddr, reqsigner, inner, env,
|
||||||
if (env != NULL && env->localhost != NULL) {
|
&indirectmatch, matchelt);
|
||||||
inner = env->localhost;
|
INSIST(result == ISC_R_SUCCESS);
|
||||||
goto nested;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case dns_aclelementtype_localnets:
|
/*
|
||||||
if (env != NULL && env->localnets != NULL) {
|
* Treat negative matches in indirect ACLs as "no match".
|
||||||
inner = env->localnets;
|
* That way, a negated indirect ACL will never become a
|
||||||
goto nested;
|
* surprise positive match through double negation.
|
||||||
} else {
|
* XXXDCL this should be documented.
|
||||||
break;
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
if (indirectmatch > 0) {
|
||||||
INSIST(0);
|
if (matchelt != NULL)
|
||||||
break;
|
*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);
|
return (ISC_FALSE);
|
||||||
}
|
}
|
||||||
@@ -285,15 +398,8 @@ destroy(dns_acl_t *dacl) {
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
for (i = 0; i < dacl->length; i++) {
|
for (i = 0; i < dacl->length; i++) {
|
||||||
dns_aclelement_t *de = &dacl->elements[i];
|
dns_aclelement_t *de = &dacl->elements[i];
|
||||||
switch (de->type) {
|
if (de->type == dns_aclelementtype_keyname) {
|
||||||
case dns_aclelementtype_keyname:
|
dns_name_free(&de->keyname, dacl->mctx);
|
||||||
dns_name_free(&de->u.keyname, dacl->mctx);
|
|
||||||
break;
|
|
||||||
case dns_aclelementtype_nestedacl:
|
|
||||||
dns_acl_detach(&de->u.nestedacl);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dacl->elements != NULL)
|
if (dacl->elements != NULL)
|
||||||
@@ -301,6 +407,8 @@ destroy(dns_acl_t *dacl) {
|
|||||||
dacl->alloc * sizeof(dns_aclelement_t));
|
dacl->alloc * sizeof(dns_aclelement_t));
|
||||||
if (dacl->name != NULL)
|
if (dacl->name != NULL)
|
||||||
isc_mem_free(dacl->mctx, dacl->name);
|
isc_mem_free(dacl->mctx, dacl->name);
|
||||||
|
if (dacl->iptable != NULL)
|
||||||
|
dns_iptable_detach(&dacl->iptable);
|
||||||
isc_refcount_destroy(&dacl->refcount);
|
isc_refcount_destroy(&dacl->refcount);
|
||||||
dacl->magic = 0;
|
dacl->magic = 0;
|
||||||
isc_mem_put(dacl->mctx, dacl, sizeof(*dacl));
|
isc_mem_put(dacl->mctx, dacl, sizeof(*dacl));
|
||||||
@@ -317,69 +425,62 @@ dns_acl_detach(dns_acl_t **aclp) {
|
|||||||
*aclp = NULL;
|
*aclp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_boolean_t
|
static isc_boolean_t insecure_prefix_found;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isc_boolean_t
|
/*
|
||||||
dns_acl_equal(const dns_acl_t *a, const dns_acl_t *b) {
|
* Called via isc_radix_walk() to find IP table nodes that are
|
||||||
unsigned int i;
|
* insecure.
|
||||||
if (a == b)
|
*/
|
||||||
return (ISC_TRUE);
|
static void
|
||||||
if (a->length != b->length)
|
is_insecure(isc_prefix_t *prefix, isc_boolean_t *data) {
|
||||||
return (ISC_FALSE);
|
/* Negated entries are always secure */
|
||||||
for (i = 0; i < a->length; i++) {
|
if(* (isc_boolean_t *)data == ISC_FALSE) {
|
||||||
if (! dns_aclelement_equal(&a->elements[i],
|
return;
|
||||||
&b->elements[i]))
|
}
|
||||||
return (ISC_FALSE);
|
|
||||||
}
|
|
||||||
return (ISC_TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static isc_boolean_t
|
/* If loopback prefix found, return */
|
||||||
is_loopback(const dns_aclipprefix_t *p) {
|
switch (prefix->family) {
|
||||||
switch (p->address.family) {
|
case AF_INET:
|
||||||
case AF_INET:
|
if (prefix->bitlen == 32 &&
|
||||||
if (p->prefixlen == 32 &&
|
htonl(prefix->add.sin.s_addr) == INADDR_LOOPBACK)
|
||||||
htonl(p->address.type.in.s_addr) == INADDR_LOOPBACK)
|
return;
|
||||||
return (ISC_TRUE);
|
|
||||||
break;
|
break;
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
if (p->prefixlen == 128 &&
|
if (prefix->bitlen == 128 &&
|
||||||
IN6_IS_ADDR_LOOPBACK(&p->address.type.in6))
|
IN6_IS_ADDR_LOOPBACK(&prefix->add.sin6))
|
||||||
return (ISC_TRUE);
|
return;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
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
|
isc_boolean_t
|
||||||
dns_acl_isinsecure(const dns_acl_t *a) {
|
dns_acl_isinsecure(const dns_acl_t *a) {
|
||||||
unsigned int i;
|
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++) {
|
for (i = 0; i < a->length; i++) {
|
||||||
dns_aclelement_t *e = &a->elements[i];
|
dns_aclelement_t *e = &a->elements[i];
|
||||||
|
|
||||||
@@ -388,34 +489,31 @@ dns_acl_isinsecure(const dns_acl_t *a) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (e->type) {
|
switch (e->type) {
|
||||||
case dns_aclelementtype_ipprefix:
|
case dns_aclelementtype_keyname:
|
||||||
/* The loopback address is considered secure. */
|
case dns_aclelementtype_localhost:
|
||||||
if (! is_loopback(&e->u.ip_prefix))
|
|
||||||
return (ISC_TRUE);
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case dns_aclelementtype_keyname:
|
case dns_aclelementtype_nestedacl:
|
||||||
case dns_aclelementtype_localhost:
|
if (dns_acl_isinsecure(e->nestedacl))
|
||||||
continue;
|
return (ISC_TRUE);
|
||||||
|
continue;
|
||||||
|
|
||||||
case dns_aclelementtype_nestedacl:
|
case dns_aclelementtype_localnets:
|
||||||
if (dns_acl_isinsecure(e->u.nestedacl))
|
|
||||||
return (ISC_TRUE);
|
|
||||||
continue;
|
|
||||||
|
|
||||||
case dns_aclelementtype_localnets:
|
|
||||||
case dns_aclelementtype_any:
|
|
||||||
return (ISC_TRUE);
|
return (ISC_TRUE);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
INSIST(0);
|
INSIST(0);
|
||||||
return (ISC_TRUE);
|
return (ISC_TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No insecure elements were found. */
|
/* No insecure elements were found. */
|
||||||
return (ISC_FALSE);
|
return (ISC_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize ACL environment, setting up localhost and localnets ACLs
|
||||||
|
*/
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env) {
|
dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
# PERFORMANCE OF THIS SOFTWARE.
|
# 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@
|
srcdir = @srcdir@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
@@ -24,7 +24,7 @@ top_srcdir = @top_srcdir@
|
|||||||
HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h \
|
HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h \
|
||||||
cert.h compress.h \
|
cert.h compress.h \
|
||||||
db.h dbiterator.h dbtable.h diff.h dispatch.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 \
|
keytable.h keyvalues.h lib.h log.h master.h masterdump.h \
|
||||||
message.h name.h ncache.h \
|
message.h name.h ncache.h \
|
||||||
nsec.h peer.h portlist.h rbt.h rcode.h \
|
nsec.h peer.h portlist.h rbt.h rcode.h \
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* 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
|
#ifndef DNS_ACL_H
|
||||||
#define DNS_ACL_H 1
|
#define DNS_ACL_H 1
|
||||||
@@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
#include <dns/name.h>
|
#include <dns/name.h>
|
||||||
#include <dns/types.h>
|
#include <dns/types.h>
|
||||||
|
#include <dns/iptable.h>
|
||||||
|
|
||||||
/***
|
/***
|
||||||
*** Types
|
*** Types
|
||||||
@@ -64,17 +65,17 @@ struct dns_aclipprefix {
|
|||||||
struct dns_aclelement {
|
struct dns_aclelement {
|
||||||
dns_aclelemettype_t type;
|
dns_aclelemettype_t type;
|
||||||
isc_boolean_t negative;
|
isc_boolean_t negative;
|
||||||
union {
|
dns_name_t keyname;
|
||||||
dns_aclipprefix_t ip_prefix;
|
dns_acl_t *nestedacl;
|
||||||
dns_name_t keyname;
|
int node_num;
|
||||||
dns_acl_t *nestedacl;
|
|
||||||
} u;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dns_acl {
|
struct dns_acl {
|
||||||
unsigned int magic;
|
unsigned int magic;
|
||||||
isc_mem_t *mctx;
|
isc_mem_t *mctx;
|
||||||
isc_refcount_t refcount;
|
isc_refcount_t refcount;
|
||||||
|
dns_iptable_t *iptable;
|
||||||
|
#define node_count iptable->radix->num_added_node
|
||||||
dns_aclelement_t *elements;
|
dns_aclelement_t *elements;
|
||||||
unsigned int alloc; /*%< Elements allocated */
|
unsigned int alloc; /*%< Elements allocated */
|
||||||
unsigned int length; /*%< Elements initialized */
|
unsigned int length; /*%< Elements initialized */
|
||||||
@@ -100,14 +101,9 @@ ISC_LANG_BEGINDECLS
|
|||||||
isc_result_t
|
isc_result_t
|
||||||
dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target);
|
dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target);
|
||||||
/*%<
|
/*%<
|
||||||
* Create a new ACL with room for 'n' elements.
|
* Create a new ACL, including an IP table and an array with room
|
||||||
* The elements are uninitialized and the length is 0.
|
* for 'n' ACL 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.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
isc_result_t
|
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.
|
* 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
|
void
|
||||||
dns_acl_attach(dns_acl_t *source, dns_acl_t **target);
|
dns_acl_attach(dns_acl_t *source, dns_acl_t **target);
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_acl_detach(dns_acl_t **aclp);
|
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
|
isc_boolean_t
|
||||||
dns_acl_isinsecure(const dns_acl_t *a);
|
dns_acl_isinsecure(const dns_acl_t *a);
|
||||||
/*%<
|
/*%<
|
||||||
@@ -147,6 +161,9 @@ dns_acl_isinsecure(const dns_acl_t *a);
|
|||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env);
|
dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env);
|
||||||
|
/*%<
|
||||||
|
* Initialize ACL environment, setting up localhost and localnets ACLs
|
||||||
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s);
|
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',
|
* Match the address 'reqaddr', and optionally the key name 'reqsigner',
|
||||||
* against 'acl'. 'reqsigner' may be NULL.
|
* against 'acl'. 'reqsigner' may be NULL.
|
||||||
*
|
*
|
||||||
* If there is a positive match, '*match' will be set to a positive value
|
* If there is a match, '*match' will be set to an integer whose absolute
|
||||||
* indicating the distance from the beginning of the list.
|
* 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
|
||||||
* If there is a negative match, '*match' will be set to a negative value
|
* negative match, it will be negative.
|
||||||
* 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 no match, *match will be set to zero.
|
* 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:
|
* Returns:
|
||||||
*\li #ISC_R_SUCCESS Always succeeds.
|
*\li #ISC_R_SUCCESS Always succeeds.
|
||||||
*/
|
*/
|
||||||
@@ -193,30 +208,14 @@ dns_aclelement_match(const isc_netaddr_t *reqaddr,
|
|||||||
const dns_aclelement_t **matchelt);
|
const dns_aclelement_t **matchelt);
|
||||||
/*%<
|
/*%<
|
||||||
* Like dns_acl_match, but matches against the single ACL element 'e'
|
* 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
|
* To determine whether the match was prositive or negative, the
|
||||||
* caller should examine e->negative. Since the element 'e' may be
|
* 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.
|
* 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
|
ISC_LANG_ENDDECLS
|
||||||
|
|
||||||
#endif /* DNS_ACL_H */
|
#endif /* DNS_ACL_H */
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* 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
|
#ifndef DNS_TYPES_H
|
||||||
#define DNS_TYPES_H 1
|
#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_fixedname dns_fixedname_t;
|
||||||
typedef struct dns_forwarders dns_forwarders_t;
|
typedef struct dns_forwarders dns_forwarders_t;
|
||||||
typedef struct dns_fwdtable dns_fwdtable_t;
|
typedef struct dns_fwdtable dns_fwdtable_t;
|
||||||
|
typedef struct dns_iptable dns_iptable_t;
|
||||||
typedef isc_uint16_t dns_keyflags_t;
|
typedef isc_uint16_t dns_keyflags_t;
|
||||||
typedef struct dns_keynode dns_keynode_t;
|
typedef struct dns_keynode dns_keynode_t;
|
||||||
typedef struct dns_keytable dns_keytable_t;
|
typedef struct dns_keytable dns_keytable_t;
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* 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 */
|
/*! \file */
|
||||||
|
|
||||||
@@ -1144,11 +1144,7 @@ zone_isdynamic(dns_zone_t *zone) {
|
|||||||
zone->type == dns_zone_stub ||
|
zone->type == dns_zone_stub ||
|
||||||
(!zone->update_disabled && zone->ssutable != NULL) ||
|
(!zone->update_disabled && zone->ssutable != NULL) ||
|
||||||
(!zone->update_disabled && zone->update_acl != NULL &&
|
(!zone->update_disabled && zone->update_acl != NULL &&
|
||||||
! (zone->update_acl->length == 1 &&
|
!dns_acl_isnone(zone->update_acl))));
|
||||||
zone->update_acl->elements[0].negative == ISC_TRUE
|
|
||||||
&&
|
|
||||||
zone->update_acl->elements[0].type ==
|
|
||||||
dns_aclelementtype_any))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
# PERFORMANCE OF THIS SOFTWARE.
|
# 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@
|
srcdir = @srcdir@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
@@ -58,7 +58,7 @@ OBJS = @ISC_EXTRA_OBJS@ \
|
|||||||
lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \
|
lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \
|
||||||
md5.@O@ mem.@O@ mutexblock.@O@ \
|
md5.@O@ mem.@O@ mutexblock.@O@ \
|
||||||
netaddr.@O@ netscope.@O@ ondestroy.@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@ \
|
ratelimiter.@O@ refcount.@O@ region.@O@ result.@O@ rwlock.@O@ \
|
||||||
serial.@O@ sha1.@O@ sha2.@O@ sockaddr.@O@ \
|
serial.@O@ sha1.@O@ sha2.@O@ sockaddr.@O@ \
|
||||||
string.@O@ strtoul.@O@ symtab.@O@ task.@O@ taskpool.@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 \
|
lex.c lfsr.c lib.c log.c \
|
||||||
md5.c mem.c mutexblock.c \
|
md5.c mem.c mutexblock.c \
|
||||||
netaddr.c netscope.c ondestroy.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 \
|
ratelimiter.c refcount.c region.c result.c rwlock.c \
|
||||||
serial.c sha1.c sha2.c sockaddr.c string.c strtoul.c \
|
serial.c sha1.c sha2.c sockaddr.c string.c strtoul.c \
|
||||||
symtab.c task.c taskpool.c timer.c version.c
|
symtab.c task.c taskpool.c timer.c version.c
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* 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>
|
#include <config.h>
|
||||||
|
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
#include <isccfg/aclconf.h>
|
#include <isccfg/aclconf.h>
|
||||||
|
|
||||||
#include <dns/acl.h>
|
#include <dns/acl.h>
|
||||||
|
#include <dns/iptable.h>
|
||||||
#include <dns/fixedname.h>
|
#include <dns/fixedname.h>
|
||||||
#include <dns/log.h>
|
#include <dns/log.h>
|
||||||
|
|
||||||
@@ -40,6 +41,7 @@ cfg_aclconfctx_init(cfg_aclconfctx_t *ctx) {
|
|||||||
void
|
void
|
||||||
cfg_aclconfctx_destroy(cfg_aclconfctx_t *ctx) {
|
cfg_aclconfctx_destroy(cfg_aclconfctx_t *ctx) {
|
||||||
dns_acl_t *dacl, *next;
|
dns_acl_t *dacl, *next;
|
||||||
|
|
||||||
for (dacl = ISC_LIST_HEAD(ctx->named_acl_cache);
|
for (dacl = ISC_LIST_HEAD(ctx->named_acl_cache);
|
||||||
dacl != NULL;
|
dacl != NULL;
|
||||||
dacl = next)
|
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 cfg_obj_t *acl = cfg_listelt_value(elt);
|
||||||
const char *aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
|
const char *aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
|
||||||
if (strcasecmp(aclname, name) == 0) {
|
if (strcasecmp(aclname, name) == 0) {
|
||||||
*ret = cfg_tuple_get(acl, "value");
|
if (ret != NULL) {
|
||||||
|
*ret = cfg_tuple_get(acl, "value");
|
||||||
|
}
|
||||||
return (ISC_R_SUCCESS);
|
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
|
static isc_result_t
|
||||||
convert_named_acl(const cfg_obj_t *nameobj, const cfg_obj_t *cctx,
|
convert_named_acl(const cfg_obj_t *nameobj, const cfg_obj_t *cctx,
|
||||||
isc_log_t *lctx, cfg_aclconfctx_t *ctx,
|
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;
|
isc_result_t result;
|
||||||
const cfg_obj_t *cacl = NULL;
|
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);
|
DE_CONST(aclname, loop.name);
|
||||||
loop.magic = LOOP_MAGIC;
|
loop.magic = LOOP_MAGIC;
|
||||||
ISC_LIST_APPEND(ctx->named_acl_cache, &loop, nextincache);
|
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);
|
ISC_LIST_UNLINK(ctx->named_acl_cache, &loop, nextincache);
|
||||||
loop.magic = 0;
|
loop.magic = 0;
|
||||||
loop.name = NULL;
|
loop.name = NULL;
|
||||||
@@ -160,25 +166,47 @@ cfg_acl_fromconfig(const cfg_obj_t *caml,
|
|||||||
isc_log_t *lctx,
|
isc_log_t *lctx,
|
||||||
cfg_aclconfctx_t *ctx,
|
cfg_aclconfctx_t *ctx,
|
||||||
isc_mem_t *mctx,
|
isc_mem_t *mctx,
|
||||||
|
int nest_level,
|
||||||
dns_acl_t **target)
|
dns_acl_t **target)
|
||||||
{
|
{
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
unsigned int count;
|
dns_acl_t *dacl = NULL, *inneracl = NULL;
|
||||||
dns_acl_t *dacl = NULL;
|
|
||||||
dns_aclelement_t *de;
|
dns_aclelement_t *de;
|
||||||
const cfg_listelt_t *elt;
|
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;
|
if (*target != NULL) {
|
||||||
for (elt = cfg_list_first(caml);
|
/*
|
||||||
elt != NULL;
|
* If target already points to an ACL, then we're being
|
||||||
elt = cfg_list_next(elt))
|
* called recursively to configure a nested ACL. The
|
||||||
count++;
|
* nested ACL's contents should just be absorbed into its
|
||||||
|
* parent ACL.
|
||||||
result = dns_acl_create(mctx, count, &dacl);
|
*/
|
||||||
if (result != ISC_R_SUCCESS)
|
dacl = *target;
|
||||||
return (result);
|
} 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;
|
de = dacl->elements;
|
||||||
for (elt = cfg_list_first(caml);
|
for (elt = cfg_list_first(caml);
|
||||||
@@ -186,56 +214,114 @@ cfg_acl_fromconfig(const cfg_obj_t *caml,
|
|||||||
elt = cfg_list_next(elt))
|
elt = cfg_list_next(elt))
|
||||||
{
|
{
|
||||||
const cfg_obj_t *ce = cfg_listelt_value(elt);
|
const cfg_obj_t *ce = cfg_listelt_value(elt);
|
||||||
|
isc_boolean_t neg;
|
||||||
|
|
||||||
if (cfg_obj_istuple(ce)) {
|
if (cfg_obj_istuple(ce)) {
|
||||||
/* This must be a negated element. */
|
/* This must be a negated element. */
|
||||||
ce = cfg_tuple_get(ce, "value");
|
ce = cfg_tuple_get(ce, "value");
|
||||||
de->negative = ISC_TRUE;
|
neg = ISC_TRUE;
|
||||||
} else {
|
} else
|
||||||
de->negative = ISC_FALSE;
|
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)) {
|
if (cfg_obj_isnetprefix(ce)) {
|
||||||
/* Network prefix */
|
/* Network prefix */
|
||||||
de->type = dns_aclelementtype_ipprefix;
|
isc_netaddr_t addr;
|
||||||
|
unsigned int bitlen;
|
||||||
|
|
||||||
cfg_obj_asnetprefix(ce,
|
cfg_obj_asnetprefix(ce, &addr, &bitlen);
|
||||||
&de->u.ip_prefix.address,
|
result = dns_iptable_addprefix(iptab, &addr, bitlen,
|
||||||
&de->u.ip_prefix.prefixlen);
|
ISC_TF(!neg));
|
||||||
} 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);
|
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
continue;
|
||||||
} else if (cfg_obj_islist(ce)) {
|
} else if (cfg_obj_islist(ce)) {
|
||||||
/* Nested ACL */
|
/*
|
||||||
de->type = dns_aclelementtype_nestedacl;
|
* If we're nesting ACLs, put the nested
|
||||||
result = cfg_acl_fromconfig(ce, cctx, lctx, ctx,
|
* ACL onto the elements list; otherwise
|
||||||
mctx, &de->u.nestedacl);
|
* 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)
|
if (result != ISC_R_SUCCESS)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
continue;
|
||||||
} else if (cfg_obj_isstring(ce)) {
|
} else if (cfg_obj_isstring(ce)) {
|
||||||
/* ACL name */
|
/* ACL name */
|
||||||
const char *name = cfg_obj_asstring(ce);
|
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->type = dns_aclelementtype_localhost;
|
||||||
|
de->negative = neg;
|
||||||
} else if (strcasecmp(name, "localnets") == 0) {
|
} else if (strcasecmp(name, "localnets") == 0) {
|
||||||
de->type = dns_aclelementtype_localnets;
|
de->type = dns_aclelementtype_localnets;
|
||||||
} else if (strcasecmp(name, "any") == 0) {
|
de->negative = neg;
|
||||||
de->type = dns_aclelementtype_any;
|
|
||||||
} else if (strcasecmp(name, "none") == 0) {
|
|
||||||
de->type = dns_aclelementtype_any;
|
|
||||||
de->negative = ISC_TF(! de->negative);
|
|
||||||
} else {
|
} else {
|
||||||
de->type = dns_aclelementtype_nestedacl;
|
result = get_acl_def(cctx, name, NULL);
|
||||||
result = convert_named_acl(ce, cctx, lctx,
|
if (result == ISC_R_SUCCESS) {
|
||||||
ctx, mctx,
|
/* found it in acl definitions */
|
||||||
&de->u.nestedacl);
|
inneracl = NULL;
|
||||||
|
result = convert_named_acl(ce, cctx,
|
||||||
|
lctx, ctx, mctx,
|
||||||
|
nest_level
|
||||||
|
? (nest_level - 1)
|
||||||
|
: 0,
|
||||||
|
&inneracl);
|
||||||
|
}
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
goto cleanup;
|
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 {
|
} else {
|
||||||
cfg_obj_log(ce, lctx, ISC_LOG_WARNING,
|
cfg_obj_log(ce, lctx, ISC_LOG_WARNING,
|
||||||
"address match list contains "
|
"address match list contains "
|
||||||
@@ -243,6 +329,16 @@ cfg_acl_fromconfig(const cfg_obj_t *caml,
|
|||||||
result = ISC_R_FAILURE;
|
result = ISC_R_FAILURE;
|
||||||
goto cleanup;
|
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++;
|
de++;
|
||||||
dacl->length++;
|
dacl->length++;
|
||||||
}
|
}
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* 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
|
#ifndef ISCCFG_ACLCONF_H
|
||||||
#define ISCCFG_ACLCONF_H 1
|
#define ISCCFG_ACLCONF_H 1
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
typedef struct cfg_aclconfctx {
|
typedef struct cfg_aclconfctx {
|
||||||
ISC_LIST(dns_acl_t) named_acl_cache;
|
ISC_LIST(dns_acl_t) named_acl_cache;
|
||||||
|
ISC_LIST(dns_iptable_t) named_iptable_cache;
|
||||||
} cfg_aclconfctx_t;
|
} cfg_aclconfctx_t;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@@ -54,6 +55,7 @@ cfg_acl_fromconfig(const cfg_obj_t *caml,
|
|||||||
isc_log_t *lctx,
|
isc_log_t *lctx,
|
||||||
cfg_aclconfctx_t *ctx,
|
cfg_aclconfctx_t *ctx,
|
||||||
isc_mem_t *mctx,
|
isc_mem_t *mctx,
|
||||||
|
int nest_level,
|
||||||
dns_acl_t **target);
|
dns_acl_t **target);
|
||||||
/*
|
/*
|
||||||
* Construct a new dns_acl_t from configuration data in 'caml' and
|
* Construct a new dns_acl_t from configuration data in 'caml' and
|
||||||
|
Reference in New Issue
Block a user