From 3821d989c80fa9e02898404b990813795c03c101 Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Tue, 1 Jul 2008 17:14:23 -0400 Subject: - check whether or not to enforce access control - use shared functionality for checking if an entry defines a set - start a search callback --- src/back-sch.c | 227 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 153 insertions(+), 74 deletions(-) (limited to 'src/back-sch.c') 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); } -- cgit