summaryrefslogtreecommitdiff
path: root/lib/isccfg/aclconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/isccfg/aclconf.c')
-rw-r--r--lib/isccfg/aclconf.c97
1 files changed, 76 insertions, 21 deletions
diff --git a/lib/isccfg/aclconf.c b/lib/isccfg/aclconf.c
index af5659909e100..e1b68971738af 100644
--- a/lib/isccfg/aclconf.c
+++ b/lib/isccfg/aclconf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2012, 2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -213,14 +213,16 @@ convert_keyname(const cfg_obj_t *keyobj, isc_log_t *lctx, isc_mem_t *mctx,
* elements table after all the nested ACLs have been merged in to the
* parent.
*/
-static int
+static isc_result_t
count_acl_elements(const cfg_obj_t *caml, const cfg_obj_t *cctx,
- isc_boolean_t *has_negative)
+ isc_log_t *lctx, cfg_aclconfctx_t *ctx, isc_mem_t *mctx,
+ isc_uint32_t *count, isc_boolean_t *has_negative)
{
const cfg_listelt_t *elt;
- const cfg_obj_t *cacl = NULL;
isc_result_t result;
- int n = 0;
+ isc_uint32_t n = 0;
+
+ REQUIRE(count != NULL);
if (has_negative != NULL)
*has_negative = ISC_FALSE;
@@ -241,7 +243,12 @@ count_acl_elements(const cfg_obj_t *caml, const cfg_obj_t *cctx,
n++;
} else if (cfg_obj_islist(ce)) {
isc_boolean_t negative;
- n += count_acl_elements(ce, cctx, &negative);
+ isc_uint32_t sub;
+ result = count_acl_elements(ce, cctx, lctx, ctx, mctx,
+ &sub, &negative);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ n += sub;
if (negative)
n++;
} else if (cfg_obj_isstring(ce)) {
@@ -251,26 +258,45 @@ count_acl_elements(const cfg_obj_t *caml, const cfg_obj_t *cctx,
n++;
} else if (strcasecmp(name, "any") != 0 &&
strcasecmp(name, "none") != 0) {
- result = get_acl_def(cctx, name, &cacl);
- if (result == ISC_R_SUCCESS)
- n += count_acl_elements(cacl, cctx,
- NULL) + 1;
+ dns_acl_t *inneracl = NULL;
+ /*
+ * Convert any named acls we reference now if
+ * they have not already been converted.
+ */
+ result = convert_named_acl(ce, cctx, lctx, ctx,
+ mctx, 0, &inneracl);
+ if (result == ISC_R_SUCCESS) {
+ if (inneracl->has_negatives)
+ n++;
+ else
+ n += inneracl->length;
+ dns_acl_detach(&inneracl);
+ } else
+ return (result);
}
}
}
- return n;
+ *count = n;
+ return (ISC_R_SUCCESS);
}
isc_result_t
-cfg_acl_fromconfig(const cfg_obj_t *caml,
- const cfg_obj_t *cctx,
- isc_log_t *lctx,
- cfg_aclconfctx_t *ctx,
- isc_mem_t *mctx,
- unsigned int nest_level,
+cfg_acl_fromconfig(const cfg_obj_t *caml, const cfg_obj_t *cctx,
+ isc_log_t *lctx, cfg_aclconfctx_t *ctx,
+ isc_mem_t *mctx, unsigned int nest_level,
dns_acl_t **target)
{
+ return (cfg_acl_fromconfig2(caml, cctx, lctx, ctx, mctx,
+ nest_level, 0, target));
+}
+
+isc_result_t
+cfg_acl_fromconfig2(const cfg_obj_t *caml, const cfg_obj_t *cctx,
+ isc_log_t *lctx, cfg_aclconfctx_t *ctx,
+ isc_mem_t *mctx, unsigned int nest_level,
+ isc_uint16_t family, dns_acl_t **target)
+{
isc_result_t result;
dns_acl_t *dacl = NULL, *inneracl = NULL;
dns_aclelement_t *de;
@@ -300,11 +326,14 @@ cfg_acl_fromconfig(const cfg_obj_t *caml,
* elements table. (Note that if nest_level is nonzero,
* *everything* goes in the elements table.)
*/
- int nelem;
+ isc_uint32_t nelem;
- if (nest_level == 0)
- nelem = count_acl_elements(caml, cctx, NULL);
- else
+ if (nest_level == 0) {
+ result = count_acl_elements(caml, cctx, lctx, ctx,
+ mctx, &nelem, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ } else
nelem = cfg_list_length(caml, ISC_FALSE);
result = dns_acl_create(mctx, nelem, &dacl);
@@ -319,6 +348,8 @@ cfg_acl_fromconfig(const cfg_obj_t *caml,
const cfg_obj_t *ce = cfg_listelt_value(elt);
isc_boolean_t neg;
+ INSIST(dacl->length <= dacl->alloc);
+
if (cfg_obj_istuple(ce)) {
/* This must be a negated element. */
ce = cfg_tuple_get(ce, "value");
@@ -349,6 +380,16 @@ cfg_acl_fromconfig(const cfg_obj_t *caml,
unsigned int bitlen;
cfg_obj_asnetprefix(ce, &addr, &bitlen);
+ if (family != 0 && family != addr.family) {
+ char buf[ISC_NETADDR_FORMATSIZE + 1];
+ isc_netaddr_format(&addr, buf, sizeof(buf));
+ cfg_obj_log(ce, lctx, ISC_LOG_WARNING,
+ "'%s': incorrect address family; "
+ "ignoring", buf);
+ if (nest_level != 0)
+ dns_acl_detach(&de->nestedacl);
+ continue;
+ }
/*
* If nesting ACLs (nest_level != 0), we negate
@@ -360,6 +401,7 @@ cfg_acl_fromconfig(const cfg_obj_t *caml,
goto cleanup;
if (nest_level > 0) {
+ INSIST(dacl->length < dacl->alloc);
de->type = dns_aclelementtype_nestedacl;
de->negative = neg;
} else
@@ -381,6 +423,7 @@ cfg_acl_fromconfig(const cfg_obj_t *caml,
goto cleanup;
nested_acl:
if (nest_level > 0 || inneracl->has_negatives) {
+ INSIST(dacl->length < dacl->alloc);
de->type = dns_aclelementtype_nestedacl;
de->negative = neg;
if (de->nestedacl != NULL)
@@ -390,14 +433,18 @@ nested_acl:
dns_acl_detach(&inneracl);
/* Fall through. */
} else {
+ INSIST(dacl->length + inneracl->length
+ <= dacl->alloc);
dns_acl_merge(dacl, inneracl,
ISC_TF(!neg));
de += inneracl->length; /* elements added */
dns_acl_detach(&inneracl);
+ INSIST(dacl->length <= dacl->alloc);
continue;
}
} else if (cfg_obj_istype(ce, &cfg_type_keyref)) {
/* Key name. */
+ INSIST(dacl->length < dacl->alloc);
de->type = dns_aclelementtype_keyname;
de->negative = neg;
dns_name_init(&de->keyname, NULL);
@@ -416,6 +463,7 @@ nested_acl:
goto cleanup;
if (nest_level != 0) {
+ INSIST(dacl->length < dacl->alloc);
de->type = dns_aclelementtype_nestedacl;
de->negative = neg;
} else
@@ -437,19 +485,26 @@ nested_acl:
dacl->has_negatives = !neg;
if (nest_level != 0) {
+ INSIST(dacl->length < dacl->alloc);
de->type = dns_aclelementtype_nestedacl;
de->negative = !neg;
} else
continue;
} else if (strcasecmp(name, "localhost") == 0) {
+ INSIST(dacl->length < dacl->alloc);
de->type = dns_aclelementtype_localhost;
de->negative = neg;
} else if (strcasecmp(name, "localnets") == 0) {
+ INSIST(dacl->length < dacl->alloc);
de->type = dns_aclelementtype_localnets;
de->negative = neg;
} else {
if (inneracl != NULL)
dns_acl_detach(&inneracl);
+ /*
+ * This call should just find the cached
+ * of the named acl.
+ */
result = convert_named_acl(ce, cctx, lctx, ctx,
mctx, new_nest_level,
&inneracl);