static isc_result_t
configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config,
const char *aclname, const char *acltuplename,
- cfg_aclconfctx_t *aclctx, isc_mem_t *mctx,
+ cfg_aclconfctx_t *aclctx, isc_mem_t *mctx, bool *expp,
dns_acl_t **aclp) {
isc_result_t result;
const cfg_obj_t *maps[4];
aclobj = cfg_tuple_get(aclobj, acltuplename);
}
+ if (expp != NULL) {
+ /*
+ * Note whether the ACL was explicitly configured,
+ * not cloned during the merge process.
+ */
+ *expp = !cfg_obj_iscloned(aclobj);
+ }
+
result = cfg_acl_fromconfig(aclobj, config, aclctx, mctx, 0, aclp);
return result;
* can be retrieved.)
*/
CHECK(configure_view_acl(vconfig, config, "match-clients", NULL, aclctx,
- isc_g_mctx, &view->matchclients));
+ isc_g_mctx, NULL, &view->matchclients));
CHECK(configure_view_acl(vconfig, config, "match-destinations", NULL,
- aclctx, isc_g_mctx, &view->matchdestinations));
+ aclctx, isc_g_mctx, NULL,
+ &view->matchdestinations));
/*
* Configure the "match-recursive-only" option.
view->root_key_sentinel = cfg_obj_asboolean(obj);
/*
- * Set the "allow-query", "allow-query-cache", "allow-recursion",
- * "allow-recursion-on" and "allow-query-cache-on" ACLs if
- * configured in named.conf, but NOT from the global defaults.
- * This is done by leaving the third argument to configure_view_acl()
- * NULL.
- *
- * We ignore the global defaults here because these ACLs
- * can inherit from each other. If any are still unset after
- * applying the inheritance rules, we'll look up the defaults at
- * that time.
+ * The "allow-query", "allow-query-cache", "allow-recursion",
+ * "allow-recursion-on" and "allow-query-cache-on" ACLs can
+ * inherit from one other, so there's special handling based
+ * on whether they're explicitly set in named.conf or cloned
+ * from the defaults.
*/
-
- /* named.conf only */
+ bool aq, aqc, ar, aro, aqco;
CHECK(configure_view_acl(vconfig, config, "allow-query", NULL, aclctx,
- isc_g_mctx, &view->queryacl));
+ isc_g_mctx, &aq, &view->queryacl));
+ CHECK(configure_view_acl(vconfig, config, "allow-query-on", NULL,
+ aclctx, isc_g_mctx, NULL, &view->queryonacl));
- /* named.conf only */
CHECK(configure_view_acl(vconfig, config, "allow-query-cache", NULL,
- aclctx, isc_g_mctx, &view->cacheacl));
- /* named.conf only */
+ aclctx, isc_g_mctx, &aqc, &view->cacheacl));
CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on", NULL,
- aclctx, isc_g_mctx, &view->cacheonacl));
-
- CHECK(configure_view_acl(vconfig, config, "allow-query-on", NULL,
- aclctx, isc_g_mctx, &view->queryonacl));
+ aclctx, isc_g_mctx, &aqco, &view->cacheonacl));
CHECK(configure_view_acl(vconfig, config, "allow-proxy", NULL, aclctx,
- isc_g_mctx, &view->proxyacl));
+ isc_g_mctx, NULL, &view->proxyacl));
CHECK(configure_view_acl(vconfig, config, "allow-proxy-on", NULL,
- aclctx, isc_g_mctx, &view->proxyonacl));
+ aclctx, isc_g_mctx, NULL, &view->proxyonacl));
if (strcmp(view->name, "_bind") != 0 &&
view->rdclass != dns_rdataclass_chaos)
{
- /* named.conf only */
CHECK(configure_view_acl(vconfig, config, "allow-recursion",
- NULL, aclctx, isc_g_mctx,
+ NULL, aclctx, isc_g_mctx, &ar,
&view->recursionacl));
- /* named.conf only */
CHECK(configure_view_acl(vconfig, config, "allow-recursion-on",
- NULL, aclctx, isc_g_mctx,
+ NULL, aclctx, isc_g_mctx, &aro,
&view->recursiononacl));
}
- if (view->recursion == false) {
+ if (view->recursion) {
/*
- * We're not recursive; if the query-cache ACLs haven't
- * been set at the options/view level, set them to none.
+ * "allow-query-cache" inherits from "allow-recursion" if set,
+ * otherwise from "allow-query" if set.
*/
- if (view->cacheacl == NULL) {
- CHECK(dns_acl_none(mctx, &view->cacheacl));
+ if (!aqc) {
+ if (ar) {
+ dns_acl_detach(&view->cacheacl);
+ dns_acl_attach(view->recursionacl,
+ &view->cacheacl);
+ } else if (aq) {
+ dns_acl_detach(&view->cacheacl);
+ dns_acl_attach(view->queryacl, &view->cacheacl);
+ }
}
- if (view->cacheonacl == NULL) {
- CHECK(dns_acl_none(mctx, &view->cacheonacl));
+
+ /*
+ * "allow-recursion" inherits from "allow-query-cache" if set,
+ * otherwise from "allow-query" if set.
+ */
+ if (!ar) {
+ if (aqc) {
+ dns_acl_detach(&view->recursionacl);
+ dns_acl_attach(view->cacheacl,
+ &view->recursionacl);
+ } else if (aq) {
+ dns_acl_detach(&view->recursionacl);
+ dns_acl_attach(view->queryacl,
+ &view->recursionacl);
+ }
}
- }
- /*
- * Finished setting recursion and query-cache ACLs, so now we
- * can get the allow-query default if it wasn't set in named.conf
- */
- if (view->queryacl == NULL) {
- /* global default only */
- CHECK(configure_view_acl(NULL, NULL, "allow-query", NULL,
- aclctx, isc_g_mctx, &view->queryacl));
+ /*
+ * "allow-query-cache-on" inherits from "allow-recursion-on"
+ * if set, and vice versa.
+ */
+ if (!aqco && aro) {
+ dns_acl_detach(&view->cacheonacl);
+ dns_acl_attach(view->recursiononacl, &view->cacheonacl);
+ } else if (!aro && aqco) {
+ dns_acl_detach(&view->recursiononacl);
+ dns_acl_attach(view->cacheonacl, &view->recursiononacl);
+ }
}
/*
* and is needed by some broken clients.
*/
CHECK(configure_view_acl(vconfig, config, "no-case-compress", NULL,
- aclctx, isc_g_mctx, &view->nocasecompress));
+ aclctx, isc_g_mctx, NULL,
+ &view->nocasecompress));
/*
* Disable name compression completely, this is a tradeoff
* Filter setting on addresses in the answer section.
*/
CHECK(configure_view_acl(vconfig, config, "deny-answer-addresses",
- "acl", aclctx, isc_g_mctx,
+ "acl", aclctx, isc_g_mctx, NULL,
&view->denyansweracl));
CHECK(configure_view_nametable(vconfig, config, "deny-answer-addresses",
"except-from", isc_g_mctx,
*/
if (view->transferacl == NULL) {
CHECK(configure_view_acl(vconfig, config, "allow-transfer",
- NULL, aclctx, isc_g_mctx,
+ NULL, aclctx, isc_g_mctx, NULL,
&view->transferacl));
}
if (view->notifyacl == NULL) {
CHECK(configure_view_acl(vconfig, config, "allow-notify", NULL,
- aclctx, isc_g_mctx, &view->notifyacl));
+ aclctx, isc_g_mctx, NULL,
+ &view->notifyacl));
}
obj = NULL;
* no default.
*/
result = configure_view_acl(NULL, effectiveconfig, "blackhole", NULL,
- aclctx, isc_g_mctx,
+ aclctx, isc_g_mctx, NULL,
&server->sctx->blackholeacl);
if (result != ISC_R_SUCCESS) {
goto cleanup_tls;
cfg_list_addclone(effectiveobj, defaultobj, false);
}
+static void
+cloneto(cfg_obj_t *options, const cfg_obj_t *obj, const char *clausename) {
+ isc_result_t result;
+ const cfg_clausedef_t *clause = cfg_map_findclause(options->type,
+ clausename);
+
+ result = cfg_map_addclone(options, obj, clause);
+ INSIST(result == ISC_R_SUCCESS);
+}
+
static void
options_merge_defaultacl(cfg_obj_t *effectiveoptions,
const cfg_obj_t *defaultoptions, const char *aclname,
result = cfg_map_get(defaultoptions, aclname, &obj);
INSIST(result == ISC_R_SUCCESS);
- cfg_obj_ref(UNCONST(obj));
- result = cfg_map_add(effectiveoptions, UNCONST(obj), aclname);
- INSIST(result == ISC_R_SUCCESS);
+ cloneto(effectiveoptions, obj, aclname);
}
static void
if (result != ISC_R_SUCCESS) {
result = cfg_map_get(effectiveoptions, "allow-recursion", &obj);
if (result == ISC_R_SUCCESS) {
- cfg_obj_ref(UNCONST(obj));
- result = cfg_map_add(effectiveoptions, UNCONST(obj),
- "allow-query-cache");
- INSIST(result == ISC_R_SUCCESS);
+ cloneto(effectiveoptions, obj, "allow-query-cache");
} else {
result = cfg_map_get(effectiveoptions, "allow-query",
&obj);
if (result == ISC_R_SUCCESS) {
- cfg_obj_ref(UNCONST(obj));
- result = cfg_map_add(effectiveoptions,
- UNCONST(obj),
- "allow-query-cache");
- INSIST(result == ISC_R_SUCCESS);
+ cloneto(effectiveoptions, obj,
+ "allow-query-cache");
} else {
noquerycacheacl = true;
}
result = cfg_map_get(effectiveoptions, "allow-query-cache",
&obj);
if (result == ISC_R_SUCCESS) {
- cfg_obj_ref(UNCONST(obj));
- result = cfg_map_add(effectiveoptions, UNCONST(obj),
- "allow-recursion");
- INSIST(result == ISC_R_SUCCESS);
+ cloneto(effectiveoptions, obj, "allow-recursion");
} else {
result = cfg_map_get(effectiveoptions, "allow-query",
&obj);
if (result == ISC_R_SUCCESS) {
- cfg_obj_ref(UNCONST(obj));
- result = cfg_map_add(effectiveoptions,
- UNCONST(obj),
- "allow-recursion");
- INSIST(result == ISC_R_SUCCESS);
+ cloneto(effectiveoptions, obj,
+ "allow-recursion");
} else {
norecursionacl = true;
}
result = cfg_map_get(effectiveoptions, "allow-recursion-on",
&obj);
if (result == ISC_R_SUCCESS) {
- cfg_obj_ref(UNCONST(obj));
- result = cfg_map_add(effectiveoptions, UNCONST(obj),
- "allow-query-cache-on");
- INSIST(result == ISC_R_SUCCESS);
+ cloneto(effectiveoptions, obj, "allow-query-cache-on");
} else {
noquerycacheonacl = true;
}
result = cfg_map_get(effectiveoptions, "allow-query-cache-on",
&obj);
if (result == ISC_R_SUCCESS) {
- cfg_obj_ref(UNCONST(obj));
- result = cfg_map_add(effectiveoptions, UNCONST(obj),
- "allow-recursion-on");
- INSIST(result == ISC_R_SUCCESS);
+ cloneto(effectiveoptions, obj, "allow-recursion-on");
} else {
norecursiononacl = true;
}
cfg_obj_create(source->mctx, source->file, source->line, source->type,
target);
+ (*target)->cloned = source->cloned;
source->type->rep->copy(*target, source);
}
return &(*clauseset)[*idx];
}
+const cfg_clausedef_t *
+cfg_map_findclause(const cfg_type_t *map, const char *name) {
+ const cfg_clausedef_t *found = NULL;
+ const void *clauses = NULL;
+ unsigned int idx;
+
+ REQUIRE(map != NULL && map->rep == &cfg_rep_map);
+ REQUIRE(name != NULL);
+
+ found = cfg_map_firstclause(map, &clauses, &idx);
+ while (name != NULL && strcasecmp(name, found->name)) {
+ found = cfg_map_nextclause(map, &clauses, &idx);
+ }
+
+ return ((cfg_clausedef_t *)clauses) + idx;
+}
+
/* Parse an arbitrary token, storing its raw text representation. */
static isc_result_t
parse_token(cfg_parser_t *pctx, const cfg_type_t *type ISC_ATTR_UNUSED,
return obj->type == type;
}
+bool
+cfg_obj_iscloned(const cfg_obj_t *obj) {
+ REQUIRE(VALID_CFGOBJ(obj));
+ return obj->cloned;
+}
+
/*
* Destroy 'obj'.
*/
cfg_doc_obj(&pctx, type);
}
-static const cfg_clausedef_t *
-map_lookup_clause(const cfg_obj_t *mapobj, const char *clausename) {
- const cfg_map_t *map;
- const cfg_clausedef_t *const *clauseset = NULL;
- const cfg_clausedef_t *clause = NULL;
-
- map = &mapobj->value.map;
- for (clauseset = map->clausesets; *clauseset != NULL; clauseset++) {
- for (clause = *clauseset; clause->name != NULL; clause++) {
- if (strcasecmp(clause->name, clausename) == 0) {
- return clause;
- }
- }
- }
-
- return NULL;
-}
-
static isc_result_t
map_define(cfg_obj_t *mapobj, cfg_obj_t *obj, const cfg_clausedef_t *clause) {
isc_result_t result;
REQUIRE(mapobj->type->rep == &cfg_rep_map);
REQUIRE(clausename != NULL);
- clause = map_lookup_clause(mapobj, clausename);
+ clause = cfg_map_findclause(mapobj->type, clausename);
if (clause == NULL || clause->name == NULL) {
return ISC_R_FAILURE;
}
elt = cfg_list_first(obj);
while (elt != NULL && result == ISC_R_SUCCESS) {
cfg_obj_clone(elt->obj, &clone);
+ clone->cloned = true;
+
result = map_define(map, clone, clause);
elt = cfg_list_next(elt);
}
} else {
cfg_obj_clone(obj, &clone);
+ clone->cloned = true;
result = map_define(map, clone, clause);
}