summaryrefslogtreecommitdiffstats
path: root/src/back-sch.c
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-07-01 17:14:23 -0400
committerNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-07-01 17:14:23 -0400
commit3821d989c80fa9e02898404b990813795c03c101 (patch)
tree5d26f317631a54e916745d8f6b90d7d5f1fb56a5 /src/back-sch.c
parent0c739424bca0f9c2273be8586d234d4f8524f85e (diff)
downloadslapi-nis-3821d989c80fa9e02898404b990813795c03c101.tar.gz
slapi-nis-3821d989c80fa9e02898404b990813795c03c101.tar.xz
slapi-nis-3821d989c80fa9e02898404b990813795c03c101.zip
- check whether or not to enforce access control
- use shared functionality for checking if an entry defines a set - start a search callback
Diffstat (limited to 'src/back-sch.c')
-rw-r--r--src/back-sch.c227
1 files changed, 153 insertions, 74 deletions
diff --git a/src/back-sch.c b/src/back-sch.c
index a744681..26a5952 100644
--- a/src/back-sch.c
+++ b/src/back-sch.c
@@ -56,9 +56,10 @@
struct backend_set_data {
struct backend_shr_set_data common;
/* Schema compatibility-specific data. */
- char *container_dn;
+ Slapi_DN *container_sdn;
char *rdn_format;
char **attribute_format;
+ bool_t check_aci;
};
struct backend_entry_data {
Slapi_Entry *e;
@@ -90,6 +91,7 @@ backend_set_config_free_config_contents(void *data)
format_free_attr_list(set_data->common.ref_attrs);
format_free_inref_attrs(set_data->common.inref_attrs);
free(set_data->common.entry_filter);
+ slapi_sdn_free(&set_data->container_sdn);
free(set_data->rdn_format);
backend_shr_free_strlist(set_data->attribute_format);
}
@@ -120,14 +122,15 @@ backend_copy_set_config(const struct backend_set_data *data)
format_dup_inref_attrs(data->common.inref_attrs) :
NULL;
ret->common.entry_filter = strdup(data->common.entry_filter);
- ret->container_dn = strdup(data->container_dn);
+ ret->container_sdn = slapi_sdn_dup(data->container_sdn);
ret->rdn_format = strdup(data->rdn_format);
ret->attribute_format = backend_shr_dup_strlist(data->attribute_format);
+ ret->check_aci = data->check_aci;
if ((ret->common.group == NULL) ||
(ret->common.set == NULL) ||
(ret->common.bases == NULL) ||
(ret->common.entry_filter == NULL) ||
- (ret->container_dn == NULL)) {
+ (ret->container_sdn == NULL)) {
backend_set_config_free_config(&ret->common);
return NULL;
}
@@ -141,7 +144,8 @@ backend_set_config_read_config(struct plugin_state *state, Slapi_Entry *e,
const char *group, const char *container,
bool_t *flag, struct backend_shr_set_data **pret)
{
- char **bases, *entry_filter, **attributes, *rdn_format;
+ char **bases, *entry_filter, **attributes, *rdn_format, *dn;
+ bool_t check_aci;
char *actual_attr;
const char *cvalue;
int i, j, disposition, buffer_flags, count;
@@ -206,6 +210,25 @@ backend_set_config_read_config(struct plugin_state *state, Slapi_Entry *e,
}
slapi_vattr_values_free(&values, &actual_attr, buffer_flags);
}
+ check_aci = TRUE;
+ if (slapi_vattr_values_get(e, SCH_CONTAINER_CONFIGURATION_ACCESS_ATTR,
+ &values,
+ &disposition, &actual_attr,
+ 0, &buffer_flags) == 0) {
+ i = slapi_valueset_first_value(values, &value);
+ if (i != -1) {
+ cvalue = slapi_value_get_string(value);
+ /* FIXME: use nl_langinfo(YESEXPR) here? */
+ if ((strcasecmp(cvalue, "yes") == 0) ||
+ (strcasecmp(cvalue, "on") == 0) ||
+ (strcasecmp(cvalue, "1") == 0)) {
+ check_aci = TRUE;
+ } else {
+ check_aci = FALSE;
+ }
+ }
+ slapi_vattr_values_free(&values, &actual_attr, buffer_flags);
+ }
attributes = NULL;
if (slapi_vattr_values_get(e, SCH_CONTAINER_CONFIGURATION_ATTR_ATTR,
&values,
@@ -233,9 +256,11 @@ backend_set_config_read_config(struct plugin_state *state, Slapi_Entry *e,
ret.common.entry_filter = entry_filter;
ret.common.ref_attrs = NULL;
ret.common.inref_attrs = NULL;
- ret.container_dn = slapi_dn_plus_rdn(ret.common.group, ret.common.set);
+ dn = slapi_dn_plus_rdn(ret.common.group, ret.common.set);
+ ret.container_sdn = slapi_sdn_new_dn_passin(dn);
ret.rdn_format = rdn_format;
ret.attribute_format = attributes;
+ ret.check_aci = check_aci;
*pret = backend_copy_set_config(&ret);
free(ret.common.group);
free(ret.common.set);
@@ -246,7 +271,7 @@ backend_set_config_read_config(struct plugin_state *state, Slapi_Entry *e,
free(ret.common.bases);
}
free(ret.common.entry_filter);
- slapi_ch_free((void **) &ret.container_dn);
+ slapi_sdn_free(&ret.container_sdn);
if (ret.attribute_format != NULL) {
for (i = 0; ret.attribute_format[i] != NULL; i++) {
free(ret.attribute_format[i]);
@@ -297,7 +322,7 @@ backend_set_entry_one(Slapi_Entry *e, struct backend_set_data *data)
&data->common.inref_attrs);
/* Now build the entry itself, and set the DN first. */
entry = slapi_entry_alloc();
- dn = slapi_dn_plus_rdn(data->container_dn, rdn);
+ dn = slapi_dn_plus_rdn(slapi_sdn_get_ndn(data->container_sdn), rdn);
slapi_entry_set_dn(entry, dn); /* NOTE: the entry now owns the dn */
/* Iterate through the set of attributes. */
if (data->attribute_format != NULL) {
@@ -599,61 +624,8 @@ bool_t
backend_entry_is_a_set(struct plugin_state *state,
Slapi_PBlock *pb, Slapi_Entry *e)
{
- Slapi_DN *entry_sdn, *plugin_sdn;
- Slapi_Filter *filter;
- bool_t ret;
- char configuration_filter[] = SCH_CONTAINER_CONFIGURATION_FILTER;
-
- /* First, just do the scope test. The item should be a direct child of
- * our plugin entry. */
- entry_sdn = slapi_sdn_new_ndn_byref(slapi_entry_get_ndn(e));
- if (entry_sdn == NULL) {
- return FALSE;
- } else {
- plugin_sdn = slapi_sdn_new_dn_byval(state->plugin_base);
- if (plugin_sdn == NULL) {
- slapi_sdn_free(&entry_sdn);
- return FALSE;
- }
- }
- if (slapi_sdn_scope_test(entry_sdn,
- plugin_sdn,
- LDAP_SCOPE_ONE) == 0) {
- /* Didn't match. */
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "entry \"%s\" is not a child of \"%s\"\n",
- slapi_sdn_get_ndn(entry_sdn),
- slapi_sdn_get_ndn(plugin_sdn));
- ret = FALSE;
- } else {
- ret = TRUE;
- }
- slapi_sdn_free(&plugin_sdn);
- slapi_sdn_free(&entry_sdn);
-
- /* If it's actually in our configuration tree, check if it's a valid
- * entry. */
- if (ret) {
- filter = slapi_str2filter(configuration_filter);
- if (filter != NULL) {
- if (slapi_vattr_filter_test(pb, e, filter, 0) != 0) {
- /* Didn't match. */
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "entry \"%s\" doesn't look "
- "like a container "
- "configuration "
- "(didn't match filter "
- "\"%s\")\n",
- slapi_sdn_get_ndn(entry_sdn),
- configuration_filter);
- ret = FALSE;
- }
- slapi_filter_free(filter, 1);
- }
- }
- return ret;
+ return backend_shr_entry_is_a_set(state, pb, e,
+ SCH_CONTAINER_CONFIGURATION_FILTER);
}
/* Re-read plugin-wide settings that may have changed. Nothing to do. */
@@ -662,10 +634,120 @@ backend_update_params(struct plugin_state *state)
{
}
+/* Intercept a search request, and if it belongs to one of our compatibility
+ * trees, answer from our cache before letting the default database have a
+ * crack at it. */
+struct backend_search_cbdata {
+ Slapi_PBlock *pb;
+ bool_t answered;
+ struct plugin_state *state;
+ char *target, *strfilter, **attrs;
+ int scope, sizelimit, timelimit, attrsonly;
+ bool_t check_aci;
+ Slapi_DN *target_dn;
+ Slapi_Filter *filter;
+};
+
+static bool_t
+backend_search_set_cb(const char *domain, const char *map, bool_t secure,
+ const char *key, unsigned int key_len,
+ const char *value, unsigned int value_len,
+ const char *id, int key_index,
+ void *backend_data, void *cb_data)
+{
+ Slapi_DN *sdn;
+ struct backend_search_cbdata *cbdata;
+ struct backend_entry_data *entry_data;
+ int result;
+
+ cbdata = cb_data;
+ entry_data = backend_data;
+ sdn = slapi_entry_get_sdn(entry_data->e);
+ if (slapi_sdn_scope_test(sdn, cbdata->target_dn, cbdata->scope) != 0) {
+ return TRUE;
+ }
+ result = slapi_filter_test(cbdata->pb, entry_data->e,
+ cbdata->filter, cbdata->check_aci);
+ if (result == 0) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ cbdata->state->plugin_desc->spd_id,
+ "search matches %s\n",
+ slapi_sdn_get_ndn(sdn));
+ }
+ return TRUE;
+}
+static bool_t
+backend_search_set(const char *group, const char *set, bool_t flag,
+ void *backend_data, void *cb_data)
+{
+ struct backend_search_cbdata *cbdata;
+ struct backend_set_data *set_data;
+ cbdata = cb_data;
+ set_data = backend_data;
+ cbdata->check_aci = set_data->check_aci;
+ /* First, do a scope test on this set. */
+ switch (cbdata->scope) {
+ case LDAP_SCOPE_BASE:
+ /* If the container is not the parent of the target, and it is
+ * not itself the target, then we're done with this set. */
+ if ((slapi_sdn_compare(set_data->container_sdn,
+ cbdata->target_dn) != 0) &&
+ (slapi_sdn_isparent(set_data->container_sdn,
+ cbdata->target_dn) != 1)) {
+ return TRUE;
+ }
+ break;
+ case LDAP_SCOPE_ONE:
+ /* If it's not a scope=one search of this set or the group to
+ * which the set belongs, then we're done with this set. */
+ if ((slapi_sdn_compare(set_data->container_sdn,
+ cbdata->target_dn) != 0) &&
+ (slapi_sdn_isparent(cbdata->target_dn,
+ set_data->container_sdn) != 1)) {
+ return TRUE;
+ }
+ break;
+ case LDAP_SCOPE_SUB:
+ /* If the target is not a child of this container, it is not
+ * the container itself, and it is not the group, then we're
+ * done with this set. */
+ if ((slapi_sdn_isparent(set_data->container_sdn,
+ cbdata->target_dn) != 1) &&
+ (slapi_sdn_compare(set_data->container_sdn,
+ cbdata->target_dn) != 0) &&
+ (slapi_sdn_isparent(cbdata->target_dn,
+ set_data->container_sdn) != 1)) {
+ return TRUE;
+ }
+ break;
+ }
+ slapi_log_error(SLAPI_LOG_PLUGIN, cbdata->state->plugin_desc->spd_id,
+ "scope test succeeds for %s, searching set\n",
+ slapi_sdn_get_ndn(set_data->container_sdn));
+ map_data_foreach_entry_id(cbdata->state, group, set, NULL,
+ backend_search_set_cb, cbdata);
+ return TRUE;
+}
+
static int
backend_search_cb(Slapi_PBlock *pb)
{
- return 0;
+ struct backend_search_cbdata cbdata;
+ cbdata.pb = pb;
+ slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state);
+ slapi_pblock_get(pb, SLAPI_SEARCH_TARGET, &cbdata.target);
+ cbdata.target_dn = slapi_sdn_new_dn_byval(cbdata.target);
+ slapi_pblock_get(pb, SLAPI_SEARCH_SCOPE, &cbdata.scope);
+ slapi_pblock_get(pb, SLAPI_SEARCH_SIZELIMIT, &cbdata.sizelimit);
+ slapi_pblock_get(pb, SLAPI_SEARCH_TIMELIMIT, &cbdata.timelimit);
+ slapi_pblock_get(pb, SLAPI_SEARCH_FILTER, &cbdata.filter);
+ slapi_pblock_get(pb, SLAPI_SEARCH_STRFILTER, &cbdata.strfilter);
+ slapi_pblock_get(pb, SLAPI_SEARCH_ATTRS, &cbdata.attrs);
+ slapi_pblock_get(pb, SLAPI_SEARCH_ATTRSONLY, &cbdata.attrsonly);
+ cbdata.answered = FALSE;
+ map_data_foreach_map(cbdata.state, NULL, backend_search_set, &cbdata);
+ slapi_sdn_free(&cbdata.target_dn);
+ return cbdata.answered ? -1 : 0;
}
/* Populate our data. */
@@ -675,24 +757,21 @@ backend_startup(struct plugin_state *state)
backend_shr_startup(state, SCH_CONTAINER_CONFIGURATION_FILTER);
}
-static void
-backend_preop_init(Slapi_PBlock *pb, struct plugin_state *state)
+void
+backend_init_preop(Slapi_PBlock *pb, struct plugin_state *state)
{
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "hooking up preoperation callbacks\n");
if (slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_SEARCH_FN,
backend_search_cb) != 0) {
slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
"error hooking up search callback\n");
}
}
-static void
-backend_postop_init(Slapi_PBlock *pb, struct plugin_state *state)
-{
- backend_shr_postop_init(pb, state);
-}
-/* Set up our callbacks. */
void
-backend_init(Slapi_PBlock *pb, struct plugin_state *state)
+backend_init_postop(Slapi_PBlock *pb, struct plugin_state *state)
{
- backend_preop_init(pb, state);
- backend_postop_init(pb, state);
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "hooking up postoperation callbacks\n");
+ backend_shr_postop_init(pb, state);
}