diff options
| author | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-07-03 13:47:01 -0400 |
|---|---|---|
| committer | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-07-03 13:47:01 -0400 |
| commit | be91b0030506410a0c8239ca977c5e1ba4c5d78f (patch) | |
| tree | 7348d48adf1fa11d13a5ff3b1d10f47f589d4936 /src | |
| parent | d0bd372e6602d68a948521950a52650619f5d1c6 (diff) | |
| parent | afeacf387f97ca097a856612d94f01e695fb1a9c (diff) | |
Merge branch 'master' of git.fedoraproject.org:/git/slapi-nis
Diffstat (limited to 'src')
| -rw-r--r-- | src/back-nis.c | 108 | ||||
| -rw-r--r-- | src/back-nis.h | 26 | ||||
| -rw-r--r-- | src/back-sch.c | 687 | ||||
| -rw-r--r-- | src/back-sch.h | 34 | ||||
| -rw-r--r-- | src/back-shr.c | 63 | ||||
| -rw-r--r-- | src/back-shr.h | 8 | ||||
| -rw-r--r-- | src/backend.h | 28 | ||||
| -rw-r--r-- | src/dummymap.c | 17 | ||||
| -rw-r--r-- | src/format.c | 168 | ||||
| -rw-r--r-- | src/map.c | 65 | ||||
| -rw-r--r-- | src/map.h | 24 | ||||
| -rw-r--r-- | src/nis.c | 14 | ||||
| -rw-r--r-- | src/plug-sch.c | 54 |
13 files changed, 946 insertions, 350 deletions
diff --git a/src/back-nis.c b/src/back-nis.c index ced47db..63d5a44 100644 --- a/src/back-nis.c +++ b/src/back-nis.c @@ -142,7 +142,7 @@ backend_copy_set_data(const struct backend_set_data *data) * determine which value should be associated with those keys, and add them to * the map cache. */ void -backend_set_entry_one(Slapi_Entry *e, struct backend_set_data *data) +backend_set_entry(Slapi_Entry *e, struct backend_set_data *data) { char **keys, ***key_sets, **all_keys, *value, *ndn, *plugin_id; int i, j, k, n_key_sets; @@ -174,10 +174,10 @@ backend_set_entry_one(Slapi_Entry *e, struct backend_set_data *data) data->key_formats[i], data->common.group, data->common.set, ndn); - map_data_unset_entry_id(data->common.state, - data->common.group, - data->common.set, - ndn); + map_data_unset_entry(data->common.state, + data->common.group, + data->common.set, + ndn); for (k = 0; k < j; k++) { format_free_data(keys[k]); } @@ -271,9 +271,8 @@ backend_set_entry_one(Slapi_Entry *e, struct backend_set_data *data) "no value for %s, unsetting domain/map/id" "\"%s\"/\"%s\"/(\"%s\")\n", ndn, data->common.group, data->common.set, ndn); - map_data_unset_entry_id(data->common.state, - data->common.group, data->common.set, - ndn); + map_data_unset_entry(data->common.state, + data->common.group, data->common.set, ndn); } format_free_data(value); free(all_keys); @@ -643,9 +642,9 @@ backend_set_config_entry_add_cb(Slapi_Entry *e, void *callback_data) } for (i = 0; (domains != NULL) && (domains[i] != NULL); i++) { for (j = 0; (maps != NULL) && (maps[j] != NULL); j++) { - ret = backend_shr_set_config_entry_add_one(state, e, - domains[i], - maps[j]); + ret = backend_shr_set_config_entry_add(state, e, + domains[i], + maps[j]); } } if (domains != NULL) { @@ -801,7 +800,13 @@ struct backend_get_set_config_cb { void backend_free_set_config(char **bases, char *entry_filter) { - backend_shr_free_strlist(bases); + int i; + if (bases != NULL) { + for (i = 0; bases[i] != NULL; i++) { + free(bases[i]); + } + free(bases); + } free(entry_filter); } @@ -813,7 +818,7 @@ backend_get_set_config_entry_cb(Slapi_Entry *e, void *callback_data) struct backend_get_set_config_cb *cbdata; char *actual_attr; const char *cvalue; - int disposition, buffer_flags, i, count; + int disposition, buffer_flags, i, count, len; cbdata = callback_data; slapi_log_error(SLAPI_LOG_PLUGIN, @@ -846,7 +851,19 @@ backend_get_set_config_entry_cb(Slapi_Entry *e, void *callback_data) cvalue = slapi_value_get_string(value); if (cvalue != NULL) { free(cbdata->entry_filter); - cbdata->entry_filter = strdup(cvalue); + cbdata->entry_filter = NULL; + if ((cvalue[0] != '(') || + (cvalue[strlen(cvalue) - 1] != ')')) { + len = strlen(cvalue) + 3; + cbdata->entry_filter = malloc(len); + if (cbdata->entry_filter != NULL) { + sprintf(cbdata->entry_filter, + "(%s)", cvalue); + } + } + if (cbdata->entry_filter == NULL) { + cbdata->entry_filter = strdup(cvalue); + } } } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); @@ -922,63 +939,12 @@ backend_get_set_config(struct plugin_state *state, free(filter); } -/* Given an entry, return true if it describes a NIS map. */ -bool_t -backend_entry_is_a_set(struct plugin_state *state, - Slapi_PBlock *pb, Slapi_Entry *e) +/* Given an entry, return the filter which will match a container entry beneath + * the plugin's configuration entry. */ +const char * +backend_entry_get_set_config_entry_filter(void) { - Slapi_DN *entry_sdn, *plugin_sdn; - Slapi_Filter *filter; - bool_t ret; - char map_configuration_filter[] = NIS_MAP_CONFIGURATION_FILTER; - - /* First, just do the scope test. */ - 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 part of our configuration tree, check if it's a - * valid entry. */ - if (ret) { - filter = slapi_str2filter(map_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 map configuration " - "(didn't match filter " - "\"%s\")\n", - slapi_sdn_get_ndn(entry_sdn), - NIS_MAP_CONFIGURATION_FILTER); - ret = FALSE; - } - slapi_filter_free(filter, 1); - } - } - return ret; + return NIS_MAP_CONFIGURATION_FILTER; } /* Scan for the list of configured domains and maps. */ @@ -992,5 +958,7 @@ backend_startup(struct plugin_state *state) void backend_init(Slapi_PBlock *pb, struct plugin_state *state) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "hooking up postoperation callbacks\n"); backend_shr_postop_init(pb, state); } diff --git a/src/back-nis.h b/src/back-nis.h deleted file mode 100644 index 1f9aa9c..0000000 --- a/src/back-nis.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2008 Red Hat, Inc. - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This Program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this Program; if not, write to the - * - * Free Software Foundation, Inc. - * 59 Temple Place, Suite 330 - * Boston, MA 02111-1307 USA - * - */ - -#ifndef back_nis_h -#define back_nis_h -struct plugin_state; -struct slapi_pblock; -#endif diff --git a/src/back-sch.c b/src/back-sch.c index c141551..29216c8 100644 --- a/src/back-sch.c +++ b/src/back-sch.c @@ -50,15 +50,20 @@ #include "plugin.h" #include "map.h" -#define SCH_CONTAINER_CONFIGURATION_FILTER "(&(objectClass=*)(" SCH_CONTAINER_CONFIGURATION_GROUP_ATTR "=*)(" SCH_CONTAINER_CONFIGURATION_CONTAINER_ATTR "=*)(" SCH_CONTAINER_CONFIGURATION_BASE_ATTR "=*)(" SCH_CONTAINER_CONFIGURATION_FILTER_ATTR "=*)(" SCH_CONTAINER_CONFIGURATION_RDN_ATTR "=*)(" SCH_CONTAINER_CONFIGURATION_ATTR_ATTR "=*))" +#define SCH_CONTAINER_CONFIGURATION_FILTER "(&(objectClass=*)(" SCH_CONTAINER_CONFIGURATION_GROUP_ATTR "=*)(" SCH_CONTAINER_CONFIGURATION_CONTAINER_ATTR "=*)(" SCH_CONTAINER_CONFIGURATION_BASE_ATTR "=*)(" SCH_CONTAINER_CONFIGURATION_FILTER_ATTR "=*)(" SCH_CONTAINER_CONFIGURATION_RDN_ATTR "=*))" /* The data we ask the map cache to keep, for us, for each set. */ 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_access; +}; +struct backend_entry_data { + Slapi_DN *original_entry_dn; + Slapi_Entry *e; }; /* Read the name of the NIS master. A dummy function for the schema @@ -87,6 +92,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); } @@ -117,14 +123,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_access = data->check_access; 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; } @@ -138,7 +145,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_access; char *actual_attr; const char *cvalue; int i, j, disposition, buffer_flags, count; @@ -203,6 +211,25 @@ backend_set_config_read_config(struct plugin_state *state, Slapi_Entry *e, } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); } + check_access = 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_access = TRUE; + } else { + check_access = FALSE; + } + } + slapi_vattr_values_free(&values, &actual_attr, buffer_flags); + } attributes = NULL; if (slapi_vattr_values_get(e, SCH_CONTAINER_CONFIGURATION_ATTR_ATTR, &values, @@ -230,9 +257,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_access = check_access; *pret = backend_copy_set_config(&ret); free(ret.common.group); free(ret.common.set); @@ -243,7 +272,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]); @@ -253,16 +282,44 @@ backend_set_config_read_config(struct plugin_state *state, Slapi_Entry *e, free(ret.rdn_format); } +/* Create and destroy entry-specific data. */ +static struct backend_entry_data * +backend_entry_make_entry_data(Slapi_DN *original_entry_dn, Slapi_Entry *e) +{ + struct backend_entry_data *ret; + ret = malloc(sizeof(*ret)); + if (ret != NULL) { + ret->original_entry_dn = slapi_sdn_dup(original_entry_dn); + ret->e = e; + } else { + slapi_entry_free(e); + } + return ret; +} +static void +backend_entry_free_entry_data(void *p) +{ + struct backend_entry_data *data; + data = p; + slapi_entry_free(data->e); + slapi_sdn_free(&data->original_entry_dn); + free(data); +} + /* Given a map-entry directory entry, determine a key, a value, and extra data * to be stored in the map cache, and add them to the map cache. */ void -backend_set_entry_one(Slapi_Entry *e, struct backend_set_data *data) +backend_set_entry(Slapi_Entry *e, struct backend_set_data *data) { char *dn, *rdn, *ndn, *ldif, *plugin_id, *keys[2], **ava, *val; + const char *rdnstr; int len, i, j; Slapi_Entry *entry; + Slapi_DN *e_dn; + Slapi_RDN *srdn; plugin_id = data->common.state->plugin_desc->spd_id; + e_dn = slapi_entry_get_sdn(e); ndn = slapi_entry_get_ndn(e); /* Generate the RDN for the entry. */ rdn = format_get_data(data->common.state, e, @@ -272,7 +329,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) { @@ -287,7 +344,7 @@ backend_set_entry_one(Slapi_Entry *e, struct backend_set_data *data) if (ava != NULL) { for (j = 0; ava[j] != NULL; j++) { val = strchr(ava[j], '='); - if (val != NULL) { + if ((val != NULL) && (val[1] != '\0')) { *val = '\0'; slapi_entry_add_string(entry, ava[j], @@ -303,38 +360,52 @@ backend_set_entry_one(Slapi_Entry *e, struct backend_set_data *data) if (!slapi_entry_rdn_values_present(entry)) { slapi_entry_add_rdn_values(entry); } - /* Perform a schema check. */ if (slapi_entry_schema_check(NULL, entry) != 0) { slapi_entry_add_string(entry, "objectClass", "extensibleObject"); } - /* Produce some LDIF. */ + /* Clean up some LDIF. */ ldif = slapi_entry2str(entry, &len); + /* Recreate the entry. */ + slapi_entry_free(entry); + entry = slapi_str2entry(ldif, + SLAPI_STR2ENTRY_REMOVEDUPVALS | + SLAPI_STR2ENTRY_ADDRDNVALS | + SLAPI_STR2ENTRY_EXPAND_OBJECTCLASSES | + SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF); + slapi_ch_free((void **) &ldif); + /* Normalize the RDN, so that we can use it as a key. */ + srdn = slapi_rdn_new_sdn(slapi_entry_get_sdn(entry)); + if (srdn != NULL) { + rdnstr = slapi_rdn_get_rdn(srdn); + } else { + rdnstr = NULL; + } /* If we actually generated a useful new entry for this entry, then set * it, otherwise clear it in case there was one set before. */ - if ((rdn != NULL) && (ldif != NULL)) { + if ((rdnstr != NULL) && (slapi_entry_get_ndn(entry) != NULL)) { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id, "setting group/container/key/value " "\"%s\"/\"%s\"/\"%s\"(\"%s\")=\"%s\"\n", data->common.group, data->common.set, - rdn, ndn, ldif); - keys[0] = rdn; + rdn, ndn, slapi_entry_get_ndn(entry)); + keys[0] = (char *) rdnstr; keys[1] = NULL; map_data_set_entry(data->common.state, data->common.group, data->common.set, ndn, - NULL, keys, len, ldif, - NULL, NULL); + NULL, keys, -1, slapi_entry_get_ndn(entry), + backend_entry_make_entry_data(e_dn, entry), + backend_entry_free_entry_data); } else { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id, "no value for %s, unsetting domain/map/id" "\"%s\"/\"%s\"/(\"%s\")\n", ndn, data->common.group, data->common.set, ndn); - map_data_unset_entry_id(data->common.state, - data->common.group, data->common.set, - ndn); + map_data_unset_entry(data->common.state, + data->common.group, data->common.set, ndn); slapi_entry_free(entry); } - slapi_ch_free((void **) &ldif); + slapi_rdn_free(&srdn); format_free_data(rdn); } @@ -392,9 +463,9 @@ backend_set_config_entry_add_cb(Slapi_Entry *e, void *callback_data) for (j = 0; (containers != NULL) && (containers[j] != NULL); j++) { - ret = backend_shr_set_config_entry_add_one(state, e, - groups[i], - containers[j]); + ret = backend_shr_set_config_entry_add(state, e, + groups[i], + containers[j]); } } if (groups != NULL) { @@ -437,7 +508,13 @@ struct backend_get_set_config_cb { void backend_free_set_config(char **bases, char *entry_filter) { - backend_shr_free_strlist(bases); + int i; + if (bases != NULL) { + for (i = 0; bases[i] != NULL; i++) { + free(bases[i]); + } + free(bases); + } free(entry_filter); } @@ -449,7 +526,7 @@ backend_get_set_config_entry_cb(Slapi_Entry *e, void *callback_data) struct backend_get_set_config_cb *cbdata; char *actual_attr; const char *cvalue; - int disposition, buffer_flags, i, count; + int disposition, buffer_flags, i, count, len; cbdata = callback_data; slapi_log_error(SLAPI_LOG_PLUGIN, @@ -484,7 +561,19 @@ backend_get_set_config_entry_cb(Slapi_Entry *e, void *callback_data) cvalue = slapi_value_get_string(value); if (cvalue != NULL) { free(cbdata->entry_filter); - cbdata->entry_filter = strdup(cvalue); + cbdata->entry_filter = NULL; + if ((cvalue[0] != '(') || + (cvalue[strlen(cvalue) - 1] != ')')) { + len = strlen(cvalue) + 3; + cbdata->entry_filter = malloc(len); + if (cbdata->entry_filter != NULL) { + sprintf(cbdata->entry_filter, + "(%s)", cvalue); + } + } + if (cbdata->entry_filter == NULL) { + cbdata->entry_filter = strdup(cvalue); + } } } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); @@ -509,7 +598,7 @@ backend_get_set_config(struct plugin_state *state, filter = malloc(strlen("(&(" SCH_CONTAINER_CONFIGURATION_GROUP_ATTR "=)(" SCH_CONTAINER_CONFIGURATION_CONTAINER_ATTR "=)" - "()") + + ")") + strlen(group) + strlen(container) + strlen(SCH_CONTAINER_CONFIGURATION_FILTER) + 1); if (filter == NULL) { @@ -521,7 +610,7 @@ backend_get_set_config(struct plugin_state *state, } sprintf(filter, "(&(" SCH_CONTAINER_CONFIGURATION_GROUP_ATTR "=%s)(" - SCH_CONTAINER_CONFIGURATION_CONTAINER_ATTR "=%s)(%s)", + SCH_CONTAINER_CONFIGURATION_CONTAINER_ATTR "=%s)%s)", group, container, SCH_CONTAINER_CONFIGURATION_FILTER); /* Perform the search. */ @@ -551,105 +640,507 @@ backend_get_set_config(struct plugin_state *state, slapi_pblock_destroy(pb); } -/* Given an entry, return true if it describes a compatibility container. */ -bool_t -backend_entry_is_a_set(struct plugin_state *state, - Slapi_PBlock *pb, Slapi_Entry *e) +/* Given an entry, return the filter which will match a container entry beneath + * the plugin's configuration entry. */ +const char * +backend_entry_get_set_config_entry_filter(void) +{ + return SCH_CONTAINER_CONFIGURATION_FILTER; +} + +/* Re-read plugin-wide settings that may have changed. Nothing to do. */ +void +backend_update_params(struct plugin_state *state) { - Slapi_DN *entry_sdn, *plugin_sdn; +} + +/* 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; + struct plugin_state *state; + char *target, *strfilter, **attrs; + int scope, sizelimit, timelimit, attrsonly; + bool_t check_access; + Slapi_DN *target_dn; 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; + + bool_t answer; + int result; + const char *matched, *text; + int n_entries; +}; +static bool_t +backend_search_entry_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); + /* We've already done the scope check, so just check the entry against + * the filter. */ + result = slapi_filter_test(cbdata->pb, entry_data->e, + cbdata->filter, cbdata->check_access); + switch (result) { + case -1: + /* Not a match. */ + break; + case 0: + /* Match. Return the entry. */ + slapi_log_error(SLAPI_LOG_PLUGIN, + cbdata->state->plugin_desc->spd_id, + "search matched %s\n", + slapi_sdn_get_ndn(sdn)); + slapi_send_ldap_search_entry(cbdata->pb, entry_data->e, NULL, + cbdata->attrs, cbdata->attrsonly); + cbdata->n_entries++; + break; + default: + /* Return an LDAP error. */ + slapi_log_error(SLAPI_LOG_PLUGIN, + cbdata->state->plugin_desc->spd_id, + "search got error %d checking %s\n", + result, slapi_sdn_get_ndn(sdn)); + cbdata->answer = TRUE; + if (cbdata->result == 0) { + cbdata->result = result; } + break; } - 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; + return TRUE; +} +static bool_t +backend_search_set_cb(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; + Slapi_Entry *set_entry; + int result; + const char *ndn; + + cbdata = cb_data; + set_data = backend_data; + cbdata->check_access = set_data->check_access; + /* Check the set itself. */ + if (slapi_sdn_scope_test(set_data->container_sdn, cbdata->target_dn, + cbdata->scope)) { + set_entry = slapi_entry_alloc(); + slapi_entry_add_string(set_entry, + "objectClass", "extensibleObject"); + slapi_entry_set_sdn(set_entry, set_data->container_sdn); + if (!slapi_entry_rdn_values_present(set_entry)) { + slapi_entry_add_rdn_values(set_entry); + } + ndn = slapi_sdn_get_ndn(set_data->container_sdn); + result = slapi_filter_test(cbdata->pb, set_entry, + cbdata->filter, + cbdata->check_access); + switch (result) { + case -1: + /* Not a match. */ + break; + case 0: + /* Match. Return the entry. */ + slapi_log_error(SLAPI_LOG_PLUGIN, + cbdata->state->plugin_desc->spd_id, + "search matched %s\n", ndn); + slapi_send_ldap_search_entry(cbdata->pb, set_entry, + NULL, cbdata->attrs, + cbdata->attrsonly); + cbdata->n_entries++; + break; + default: + /* Return an LDAP error. */ + slapi_log_error(SLAPI_LOG_PLUGIN, + cbdata->state->plugin_desc->spd_id, + "search got error %d checking %s\n", + result, ndn); + cbdata->answer = TRUE; + if (cbdata->result == 0) { + cbdata->result = result; } - slapi_filter_free(filter, 1); + break; } + slapi_entry_free(set_entry); } - return ret; + /* Now scope-check the set's contents so that we only do it once. */ + switch (cbdata->scope) { + case LDAP_SCOPE_BASE: + /* If the container is not the parent of the target, then we're + * done with this set. */ + if (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, then we're done + * with this set. */ + if (slapi_sdn_compare(set_data->container_sdn, + cbdata->target_dn) != 0) { + return TRUE; + } + break; + case LDAP_SCOPE_SUB: + /* If the search suffix is not a suffix of the set and it's not + * the set itself, then we're done with this set. */ + if ((slapi_sdn_compare(set_data->container_sdn, + cbdata->target_dn) != 0) && + (slapi_sdn_issuffix(set_data->container_sdn, + cbdata->target_dn) != 1)) { + return TRUE; + } + break; + } + /* Walk the set of entries in this set. */ + map_data_foreach_entry_id(cbdata->state, group, set, NULL, + backend_search_entry_cb, cbdata); + return TRUE; } -/* Re-read plugin-wide settings that may have changed. Nothing to do. */ -void -backend_update_params(struct plugin_state *state) +static bool_t +backend_search_group_cb(const char *group, void *cb_data) { + struct backend_search_cbdata *cbdata; + Slapi_DN *group_dn; + Slapi_Entry *group_entry; + int result; + + cbdata = cb_data; + /* Check the group itself. */ + group_dn = slapi_sdn_new_dn_byref(group); + if (slapi_sdn_scope_test(group_dn, cbdata->target_dn, cbdata->scope)) { + group_entry = slapi_entry_alloc(); + slapi_entry_add_string(group_entry, + "objectClass", "extensibleObject"); + slapi_entry_set_sdn(group_entry, group_dn); + if (!slapi_entry_rdn_values_present(group_entry)) { + slapi_entry_add_rdn_values(group_entry); + } + result = slapi_filter_test(cbdata->pb, group_entry, + cbdata->filter, + cbdata->check_access); + switch (result) { + case -1: + /* Not a match. */ + break; + case 0: + /* Match. Return the entry. */ + slapi_log_error(SLAPI_LOG_PLUGIN, + cbdata->state->plugin_desc->spd_id, + "search matched %s\n", group); + slapi_send_ldap_search_entry(cbdata->pb, group_entry, + NULL, cbdata->attrs, + cbdata->attrsonly); + cbdata->n_entries++; + break; + default: + /* Return an LDAP error. */ + slapi_log_error(SLAPI_LOG_PLUGIN, + cbdata->state->plugin_desc->spd_id, + "search got error %d checking %s\n", + result, group); + cbdata->answer = TRUE; + if (cbdata->result == 0) { + cbdata->result = result; + } + break; + } + slapi_entry_free(group_entry); + } + /* Now check the group's sets and their contents. */ + map_data_foreach_map(cbdata->state, group, + backend_search_set_cb, cbdata); + /* If the search is confined to this group, we need to send the result + * ourselves. */ + if (slapi_sdn_scope_test(cbdata->target_dn, group_dn, LDAP_SCOPE_SUB)) { + cbdata->answer = TRUE; + } + slapi_sdn_free(&group_dn); + 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); + slapi_log_error(SLAPI_LOG_PLUGIN, cbdata.state->plugin_desc->spd_id, + "searching from \"%s\" for \"%s\" with scope %d\n", + cbdata.target, cbdata.strfilter, cbdata.scope); + cbdata.answer = FALSE; + cbdata.result = 0; + cbdata.matched = ""; + cbdata.text = ""; + cbdata.n_entries = 0; + map_rdlock(); + map_data_foreach_domain(cbdata.state, backend_search_group_cb, &cbdata); + map_unlock(); + slapi_sdn_free(&cbdata.target_dn); + if (cbdata.answer) { + slapi_send_ldap_result(cbdata.pb, cbdata.result, + (char *) cbdata.matched, + (char *) cbdata.text, + cbdata.n_entries, NULL); + } + return cbdata.answer ? -1 : 0; +} + +/* Locate the entry for a given DN. */ +struct backend_locate_cbdata { + struct plugin_state *state; + char *target; + Slapi_DN *target_dn; + + struct backend_entry_data *entry_data; +}; +/* Check if the target DN is an entry in this container's set of entries. If + * it is, pull the entry's data out and save it. */ +static bool_t +backend_locate_cb(const char *group, const char *set, bool_t flag, + void *backend_set_data, void *cb_data) +{ + struct backend_locate_cbdata *cbdata; + struct backend_set_data *set_data; + struct backend_entry_data *entry_data; + Slapi_RDN *rdn; + const char *rdnstr, *ndn, *original_dn; + unsigned int ndnlen; + + cbdata = cb_data; + set_data = backend_set_data; + /* Check if the target DN looks like it would be part of this set. */ + if (slapi_sdn_scope_test(cbdata->target_dn, set_data->container_sdn, + LDAP_SCOPE_ONE)) { + /* Pull out the RDN and check for an entry which is using the + * RDN as a key. */ + rdn = slapi_rdn_new_sdn(cbdata->target_dn); + if (rdn != NULL) { + rdnstr = slapi_rdn_get_rdn(rdn); + if (map_match(cbdata->state, group, set, &flag, + strlen(rdnstr), rdnstr, + &ndnlen, &ndn, + &original_dn, (void **) &entry_data)) { + if (entry_data != NULL) { + cbdata->entry_data = entry_data; + } + } + slapi_rdn_free(&rdn); + } + } + return TRUE; +} +static void +backend_locate(Slapi_PBlock *pb, struct backend_entry_data **data) +{ + struct backend_locate_cbdata cbdata; + + slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state); + slapi_pblock_get(pb, SLAPI_TARGET_DN, &cbdata.target); + cbdata.target_dn = slapi_sdn_new_dn_byval(cbdata.target); + cbdata.entry_data = NULL; + map_data_foreach_map(cbdata.state, NULL, backend_locate_cb, &cbdata); + *data = cbdata.entry_data; + slapi_sdn_free(&cbdata.target_dn); +} + +/* Check if the target DN is part of this group's tree. If it is, return an + * insufficient-access error. */ +struct backend_group_check_scope_cbdata { + struct plugin_state *state; + const char *target; + Slapi_DN *target_dn; + bool_t ours; +}; +static bool_t +backend_group_check_scope_cb(const char *group, void *cb_data) +{ + struct backend_group_check_scope_cbdata *cbdata; + Slapi_DN *group_dn; + + cbdata = cb_data; + group_dn = slapi_sdn_new_dn_byref(group); + if (slapi_sdn_scope_test(cbdata->target_dn, group_dn, LDAP_SCOPE_SUB)) { + cbdata->ours = TRUE; + } + slapi_sdn_free(&group_dn); + return TRUE; +} +static bool_t +backend_check_scope(struct plugin_state *state, const char *target) +{ + struct backend_group_check_scope_cbdata cbdata; + + cbdata.state = state; + cbdata.target = target; + cbdata.target_dn = slapi_sdn_new_dn_byval(cbdata.target); + cbdata.ours = FALSE; + map_rdlock(); + map_data_foreach_domain(cbdata.state, backend_group_check_scope_cb, + &cbdata); + map_unlock(); + slapi_sdn_free(&cbdata.target_dn); + return cbdata.ours; } +static bool_t +backend_check_scope_pb(Slapi_PBlock *pb) +{ + struct plugin_state *state; + char *target; -/* Populate our data. */ + slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); + slapi_pblock_get(pb, SLAPI_TARGET_DN, &target); + return backend_check_scope(state, target); +} +static int +backend_write_cb(Slapi_PBlock *pb) +{ + int ret; + map_rdlock(); + if (backend_check_scope_pb(pb)) { + slapi_send_ldap_result(pb, LDAP_INSUFFICIENT_ACCESS, + NULL, NULL, 0, NULL); + ret = -1; + } else { + ret = 0; + } + map_unlock(); + return ret; +} +static int +backend_bind_cb(Slapi_PBlock *pb) +{ + struct backend_entry_data *data; + int ret; + struct berval ref; + struct berval *urls[] = {&ref, NULL}; + const char *ndn; + + map_rdlock(); + backend_locate(pb, &data); + if (data != NULL) { + ndn = slapi_sdn_get_ndn(data->original_entry_dn); + ref.bv_len = strlen("ldap:///") + strlen(ndn); + ref.bv_val = malloc(ref.bv_len + 1); + if (ref.bv_val != NULL) { + sprintf(ref.bv_val, "ldap:///%s", ndn); + slapi_send_ldap_result(pb, LDAP_REFERRAL, + NULL, NULL, 0, urls); + free(ref.bv_val); + } else { + slapi_send_ldap_result(pb, LDAP_BUSY, + NULL, NULL, 0, NULL); + } + ret = -1; + } else { + if (backend_check_scope_pb(pb)) { + slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, + NULL, NULL, 0, NULL); + ret = -1; + } else { + ret = 0; + } + } + map_unlock(); + return ret; +} +static int +backend_compare_cb(Slapi_PBlock *pb) +{ + int ret; + map_rdlock(); + if (backend_check_scope_pb(pb)) { + slapi_send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, + NULL, NULL, 0, NULL); + ret = -1; + } else { + ret = 0; + } + map_unlock(); + return ret; +} + +/* Populate our data cache. */ void 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"); + /* Intercept bind requests and return a referral or failure for entries + * that we're managing. */ + if (slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_BIND_FN, + backend_bind_cb) != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "error hooking up bind callback\n"); + } + /* Intercept compare requests and return the right data. */ + if (slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_COMPARE_FN, + backend_compare_cb) != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "error hooking up bind callback\n"); + } + /* Intercept search requests and return the right data. */ 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"); } + /* Intercept write requests and return an insufficient-access error for + * attempts to write to anything we're managing. */ + if (slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ADD_FN, + backend_write_cb) != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "error hooking up add callback\n"); + } + if (slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_MODIFY_FN, + backend_write_cb) != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "error hooking up modify callback\n"); + } + if (slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_MODRDN_FN, + backend_write_cb) != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "error hooking up modrdn callback\n"); + } + if (slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_DELETE_FN, + backend_write_cb) != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "error hooking up delete callback\n"); + } + /* We don't hook abandonment requests. */ + /* We don't hook unbind requests. */ } -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); } diff --git a/src/back-sch.h b/src/back-sch.h deleted file mode 100644 index a97fc18..0000000 --- a/src/back-sch.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2008 Red Hat, Inc. - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This Program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this Program; if not, write to the - * - * Free Software Foundation, Inc. - * 59 Temple Place, Suite 330 - * Boston, MA 02111-1307 USA - * - */ - -#ifndef back_nis_h -#define back_nis_h -struct plugin_state; -struct slapi_pblock; -int backend_read_master_name(struct plugin_state *state, char **master); -void backend_free_master_name(struct plugin_state *state, char *master); -void backend_startup(struct plugin_state *state); -void backend_init(struct slapi_pblock *pb, struct plugin_state *state); -void backend_get_map_config(struct plugin_state *state, - const char *domain, const char *map, - char ***bases, char **entry_filter); -void backend_free_map_config(char **bases, char *entry_filter); -#endif diff --git a/src/back-shr.c b/src/back-shr.c index 4b6701c..15bc7f6 100644 --- a/src/back-shr.c +++ b/src/back-shr.c @@ -202,14 +202,14 @@ backend_shr_add_strlist(char ***strlist, const char *value) /* Set or unset the entry using information in the callback data. */ void -backend_shr_set_entry_one(Slapi_Entry *e, struct backend_set_data *set_data) +backend_shr_set_entry(Slapi_Entry *e, struct backend_set_data *set_data) { - backend_set_entry_one(e, set_data); + backend_set_entry(e, set_data); } int -backend_shr_set_entry_one_cb(Slapi_Entry *e, void *set_data) +backend_shr_set_entry_cb(Slapi_Entry *e, void *set_data) { - backend_shr_set_entry_one(e, set_data); + backend_shr_set_entry(e, set_data); return 0; } @@ -236,7 +236,7 @@ backend_shr_set_config_entry_set_one_dn(struct plugin_state *state, state->plugin_desc->spd_id, "failure reading entry \"%s\"\n", dn); } else { - backend_shr_set_entry_one(entry, set_data); + backend_shr_set_entry(entry, set_data); slapi_entry_free(entry); } slapi_sdn_free(&sdn); @@ -299,8 +299,8 @@ backend_shr_set_config_free_config(void *cb_data) } int -backend_shr_set_config_entry_add_one(struct plugin_state *state, Slapi_Entry *e, - const char *group, const char *set) +backend_shr_set_config_entry_add(struct plugin_state *state, Slapi_Entry *e, + const char *group, const char *set) { Slapi_PBlock *pb; int i; @@ -347,7 +347,7 @@ backend_shr_set_config_entry_add_one(struct plugin_state *state, Slapi_Entry *e, 0); slapi_search_internal_callback_pb(pb, set_data, NULL, - backend_shr_set_entry_one_cb, + backend_shr_set_entry_cb, NULL); slapi_free_search_results_internal(pb); } @@ -508,14 +508,13 @@ backend_shr_entry_matches_set(struct backend_shr_set_data *set_data, } /* Given an entry, return true if it describes a set. */ -bool_t +static bool_t backend_shr_entry_is_a_set(struct plugin_state *state, - Slapi_PBlock *pb, Slapi_Entry *e, - const char *set_configuration_filter) + Slapi_PBlock *pb, Slapi_Entry *e) { return backend_shr_entry_matches(pb, e, state->plugin_base, LDAP_SCOPE_ONE, - set_configuration_filter); + backend_entry_get_set_config_entry_filter()); } /* Update any entries to which the passed-in entry in the passed-in map refers @@ -611,7 +610,7 @@ backend_shr_update_references_cb(const char *group, const char *set, 0); slapi_search_internal_callback_pb(cbdata->pb, set_data, NULL, - backend_shr_set_entry_one_cb, + backend_shr_set_entry_cb, NULL); } free(filter); @@ -721,7 +720,7 @@ backend_shr_add_entry_cb(const char *group, const char *set, bool_t secure, /* Set the entry in the map which corresponds to this entry, or clear * any that might if this entry doesn't have a key and value. */ - backend_set_entry_one(cbdata->e, set_data->self); + backend_set_entry(cbdata->e, set_data->self); return TRUE; } @@ -763,7 +762,7 @@ backend_shr_add_cb(Slapi_PBlock *pb) /* If it's a map configuration entry, add and populate the maps it * describes. */ - if (backend_entry_is_a_set(cbdata.state, pb, cbdata.e)) { + if (backend_shr_entry_is_a_set(cbdata.state, pb, cbdata.e)) { slapi_log_error(SLAPI_LOG_PLUGIN, cbdata.state->plugin_desc->spd_id, "new entry \"%s\" is a set\n", cbdata.ndn); @@ -806,10 +805,10 @@ backend_shr_modify_entry_cb(const char *group, const char *set, bool_t flag, set_data->group, set_data->set, cbdata->ndn); - map_data_unset_entry_id(cbdata->state, - set_data->group, - set_data->set, - cbdata->ndn); + map_data_unset_entry(cbdata->state, + set_data->group, + set_data->set, + cbdata->ndn); } /* If the entry now matches the map, add it (or re-add it). */ if (backend_shr_entry_matches_set(set_data, cbdata->pb, @@ -817,7 +816,7 @@ backend_shr_modify_entry_cb(const char *group, const char *set, bool_t flag, /* Set the entry in the set which corresponds to this entry, or * remove any that might if this entry doesn't produce a useful * value. */ - backend_shr_set_entry_one(cbdata->e_post, set_data->self); + backend_shr_set_entry(cbdata->e_post, set_data->self); } return TRUE; } @@ -866,14 +865,14 @@ backend_shr_modify_cb(Slapi_PBlock *pb) backend_shr_update_references(cbdata.state, cbdata.e_post); /* If it's a map configuration entry, reconfigure, clear, and * repopulate the map. */ - if (backend_entry_is_a_set(cbdata.state, pb, cbdata.e_pre)) { + if (backend_shr_entry_is_a_set(cbdata.state, pb, cbdata.e_pre)) { slapi_log_error(SLAPI_LOG_PLUGIN, cbdata.state->plugin_desc->spd_id, "modified entry \"%s\" was a set\n", cbdata.ndn); backend_set_config_entry_delete_cb(cbdata.e_pre, cbdata.state); } - if (backend_entry_is_a_set(cbdata.state, pb, cbdata.e_post)) { + if (backend_shr_entry_is_a_set(cbdata.state, pb, cbdata.e_post)) { slapi_log_error(SLAPI_LOG_PLUGIN, cbdata.state->plugin_desc->spd_id, "modified entry \"%s\" is now a set\n", @@ -926,10 +925,10 @@ backend_shr_modrdn_entry_cb(const char *group, const char *set, bool_t secure, set_data->group, set_data->set, cbdata->ndn_pre); - map_data_unset_entry_id(cbdata->state, - set_data->group, - set_data->set, - cbdata->ndn_pre); + map_data_unset_entry(cbdata->state, + set_data->group, + set_data->set, + cbdata->ndn_pre); } /* Set the entry in the map which corresponds to this entry, or clear * any that might if this entry doesn't have a key and value. */ @@ -937,7 +936,7 @@ backend_shr_modrdn_entry_cb(const char *group, const char *set, bool_t secure, cbdata->pb, cbdata->e_post); if (matched_post) { - backend_set_entry_one(cbdata->e_post, set_data->self); + backend_set_entry(cbdata->e_post, set_data->self); } return TRUE; } @@ -980,14 +979,14 @@ backend_shr_modrdn_cb(Slapi_PBlock *pb) } /* If it's a set configuration entry, reconfigure, clear, and * repopulate the set. */ - if (backend_entry_is_a_set(cbdata.state, pb, cbdata.e_pre)) { + if (backend_shr_entry_is_a_set(cbdata.state, pb, cbdata.e_pre)) { slapi_log_error(SLAPI_LOG_PLUGIN, cbdata.state->plugin_desc->spd_id, "renamed entry \"%s\" was a set\n", cbdata.e_pre); backend_set_config_entry_delete_cb(cbdata.e_pre, cbdata.state); } - if (backend_entry_is_a_set(cbdata.state, pb, cbdata.e_post)) { + if (backend_shr_entry_is_a_set(cbdata.state, pb, cbdata.e_post)) { slapi_log_error(SLAPI_LOG_PLUGIN, cbdata.state->plugin_desc->spd_id, "renamed entry \"%s\" is now a set\n", @@ -1024,7 +1023,7 @@ backend_shr_delete_entry_cb(const char *group, const char *set, bool_t flag, "\"%s\"/\"%s\"=\"%s\"/\"%s\"/(\"%s\")\n", group, set, set_data->group, set_data->set, cbdata->ndn); - map_data_unset_entry_id(cbdata->state, group, set, cbdata->ndn); + map_data_unset_entry(cbdata->state, group, set, cbdata->ndn); } return TRUE; } @@ -1058,7 +1057,7 @@ backend_shr_delete_cb(Slapi_PBlock *pb) "\"%s\"\n", cbdata.ndn); } /* If it's a map configuration entry, remove the map. */ - if (backend_entry_is_a_set(cbdata.state, pb, cbdata.e)) { + if (backend_shr_entry_is_a_set(cbdata.state, pb, cbdata.e)) { slapi_log_error(SLAPI_LOG_PLUGIN, cbdata.state->plugin_desc->spd_id, "deleted entry \"%s\" is a set\n", cbdata.ndn); @@ -1075,8 +1074,6 @@ backend_shr_delete_cb(Slapi_PBlock *pb) void backend_shr_postop_init(Slapi_PBlock *pb, struct plugin_state *state) { - slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "hooking up postoperation callbacks\n"); if (slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN, backend_shr_add_cb) != 0) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, diff --git a/src/back-shr.h b/src/back-shr.h index 2471676..f477362 100644 --- a/src/back-shr.h +++ b/src/back-shr.h @@ -38,10 +38,10 @@ void backend_shr_postop_init(Slapi_PBlock *pb, struct plugin_state *state); bool_t backend_shr_entry_matches(Slapi_PBlock *pb, Slapi_Entry *e, const char *containing_ndn, int scope, const char *check_filter); -int backend_shr_set_config_entry_add_one(struct plugin_state *state, - Slapi_Entry *e, - const char *group_name, - const char *set_name); +int backend_shr_set_config_entry_add(struct plugin_state *state, + Slapi_Entry *e, + const char *group_name, + const char *set_name); int backend_shr_set_config_entry_delete(struct plugin_state *state, Slapi_Entry *e, const char *group_attr, diff --git a/src/backend.h b/src/backend.h index 5924d78..bd44fc7 100644 --- a/src/backend.h +++ b/src/backend.h @@ -1,3 +1,24 @@ +/* + * Copyright 2008 Red Hat, Inc. + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This Program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this Program; if not, write to the + * + * Free Software Foundation, Inc. + * 59 Temple Place, Suite 330 + * Boston, MA 02111-1307 USA + * + */ + #ifndef backend_h #define backend_h struct backend_set_data; @@ -16,6 +37,8 @@ struct backend_shr_set_data { /* Startup/initialization functions called through the map. */ void backend_startup(struct plugin_state *state); void backend_init(struct slapi_pblock *pb, struct plugin_state *state); +void backend_init_preop(struct slapi_pblock *pb, struct plugin_state *state); +void backend_init_postop(struct slapi_pblock *pb, struct plugin_state *state); /* Read the server's name. */ int backend_read_master_name(struct plugin_state *state, char **master); @@ -29,13 +52,12 @@ void backend_get_set_config(struct plugin_state *state, void backend_free_set_config(char **bases, char *entry_filter); /* Check if an entry is a set configuration, and add or remove one. */ -bool_t backend_entry_is_a_set(struct plugin_state *state, - Slapi_PBlock *pb, Slapi_Entry *e); +const char *backend_entry_get_set_config_entry_filter(void); int backend_set_config_entry_add_cb(Slapi_Entry *e, void *callback_data); int backend_set_config_entry_delete_cb(Slapi_Entry *e, void *callback_data); /* Set an entry in a set. */ -void backend_set_entry_one(Slapi_Entry *e, struct backend_set_data *set_data); +void backend_set_entry(Slapi_Entry *e, struct backend_set_data *set_data); /* Read and free set configurations. */ void backend_set_config_read_config(struct plugin_state *state, diff --git a/src/dummymap.c b/src/dummymap.c index fc705d2..2687ab3 100644 --- a/src/dummymap.c +++ b/src/dummymap.c @@ -192,8 +192,9 @@ map_find_entries(const char *domain, const char *map) bool_t map_match(struct plugin_state *state, const char *domain, const char *map, bool_t *secure, - unsigned int key_len, char *key, - unsigned int *value_len, char **value, const char **id) + unsigned int key_len, const char *key, + unsigned int *value_len, const char **value, + const char **id, void **backend_data) { struct entry *entries; int i; @@ -213,6 +214,9 @@ map_match(struct plugin_state *state, *value = entries[i].value; *value_len = strlen(entries[i].value); *id = entries[i].key; + if (backend_data != NULL) { + *backend_data = NULL; + } return TRUE; } @@ -220,9 +224,9 @@ bool_t map_match_id(struct plugin_state *state, const char *domain, const char *map, bool_t *secure, const char *in_id, unsigned int in_index, - unsigned int *key_len, char **key, - unsigned int *value_len, char **value, - const char **id) + unsigned int *key_len, const char **key, + unsigned int *value_len, const char **value, + const char **id, void **backend_data) { struct entry *entries; int i; @@ -246,6 +250,9 @@ map_match_id(struct plugin_state *state, *value = entries[i].value; *value_len = strlen(entries[i].value); *id = entries[i].id; + if (backend_data != NULL) { + *backend_data = NULL; + } return TRUE; } diff --git a/src/format.c b/src/format.c index 82dac70..2b20305 100644 --- a/src/format.c +++ b/src/format.c @@ -490,36 +490,60 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, int disposition, ref_disposition, buffer_flags, ref_buffer_flags; char **argv, *attrs[3], *actual_attr, *actual_ref_attr; const char *sep, *cvalue, *cref; + char *ref_attr, *target_attr, **choices; ret = format_parse_args(state, args, &argc, &argv); if (ret != 0) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "deref: error parsing arguments\n"); return -EINVAL; } - if (argc < 3) { - slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "deref: requires 3 arguments\n"); - format_free_parsed_args(argv); - return -EINVAL; + if (outbuf_choices == NULL) { + if (argc != 3) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "deref: requires 3 arguments\n"); + format_free_parsed_args(argv); + return -EINVAL; + } + sep = argv[0]; + ref_attr = argv[1]; + target_attr = argv[2]; + } else { + if (argc != 2) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "deref: requires 2 arguments\n"); + format_free_parsed_args(argv); + return -EINVAL; + } + sep = NULL; + ref_attr = argv[0]; + target_attr = argv[1]; } /* Note that the attribute in this entry refers to other entries. */ if (ref_attrs != NULL) { - backend_shr_add_strlist(ref_attrs, argv[1]); + backend_shr_add_strlist(ref_attrs, ref_attr); } /* Get the names of the reference attribute. */ - if (slapi_vattr_values_get(e, argv[1], &ref_values, + if (slapi_vattr_values_get(e, ref_attr, &ref_values, &ref_disposition, &actual_ref_attr, 0, &ref_buffer_flags) != 0) { /* No references. */ format_free_parsed_args(argv); - return 0; + if (outbuf_choices == NULL) { + return 0; + } else { + return -ENOENT; + } } /* Retrieve these attributes from the referred-to entries. */ - attrs[0] = argv[1]; - attrs[1] = argv[2]; + attrs[0] = ref_attr; + attrs[1] = target_attr; attrs[2] = NULL; /* Iterate through the names of the referred-to entries. */ + ret = 0; count = 0; + choices = NULL; for (i = slapi_valueset_first_value(ref_values, &ref_value); i != -1; i = slapi_valueset_next_value(ref_values, i, &ref_value)) { @@ -547,9 +571,13 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, slapi_sdn_free(&refdn); continue; } + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "deref: reading \"%s\" from \"%s\"\n", + target_attr, slapi_sdn_get_ndn(refdn)); slapi_sdn_free(&refdn); /* Pull out the attribute from the referred-to entry. */ - if (slapi_vattr_values_get(ref, argv[2], &values, + if (slapi_vattr_values_get(ref, target_attr, &values, &disposition, &actual_attr, 0, &buffer_flags) != 0) { slapi_entry_free(ref); @@ -580,10 +608,15 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, if (len == 0) { continue; } + /* If we're keeping a list of choices, just add it to + * the list of values we've retrieved and keep going. */ + if (outbuf_choices != NULL) { + backend_shr_add_strlist(&choices, cvalue); + continue; + } /* If we need to, add the separator. */ if (count > 0) { /* Get the length of the separator. */ - sep = argv[0]; slen = strlen(sep); /* Check if there's space for the separator. */ if (ret + len + slen > outbuf_len) { @@ -616,6 +649,16 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, &actual_ref_attr, ref_buffer_flags); format_free_parsed_args(argv); + if (outbuf_choices != NULL) { + if (choices != NULL) { + /* Return the values we found. */ + format_add_choice(outbuf_choices, outbuf, choices); + backend_shr_free_strlist(choices); + } else { + /* Return a no-result error. */ + ret = -ENOENT; + } + } return ret; } @@ -628,6 +671,8 @@ struct format_referred_cbdata { char *attr, *separator; char *outbuf; int outbuf_len; + struct format_choice **outbuf_choices; + char **choices; int count; int ret; }; @@ -673,8 +718,14 @@ format_referred_entry_cb(Slapi_Entry *e, void *callback_data) slapi_log_error(SLAPI_LOG_PLUGIN, cbdata->state->plugin_desc->spd_id, "referred: got value \"%s\"\n", cvalue); - slen = strlen(cbdata->separator); + /* If we're keeping a list of choices, just add it to the list + * of values we've retrieved and keep going. */ + if (cbdata->outbuf_choices != NULL) { + backend_shr_add_strlist(&cbdata->choices, cvalue); + continue; + } /* Check if there's space for the value. */ + slen = strlen(cbdata->separator); if (len + (cbdata->count ? slen : 0) > cbdata->outbuf_len) { slapi_log_error(SLAPI_LOG_PLUGIN, cbdata->state->plugin_desc->spd_id, @@ -711,8 +762,8 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, { int i, ret, argc; Slapi_PBlock *local_pb; - char **argv, *attrs[2], *filter, *tndn; - char *map_filter, **map_bases; + char **argv, *attrs[2], *filter, *tndn, *sep, *attr, *other_attr; + char *other_set, *set_filter, **set_bases, *use_filter; struct format_referred_cbdata cbdata; ret = format_parse_args(state, args, &argc, &argv); @@ -721,15 +772,34 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, "referred: error parsing arguments\n"); return -EINVAL; } - if (argc < 4) { - slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "referred: requires 4 arguments\n"); - format_free_parsed_args(argv); - return -EINVAL; + if (outbuf_choices == NULL) { + if (argc != 4) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "referred: requires 4 arguments\n"); + format_free_parsed_args(argv); + return -EINVAL; + } + sep = argv[0]; + other_set = argv[1]; + other_attr = argv[2]; + attr = argv[3]; + } else { + if (argc != 3) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "referred: requires 3 arguments\n"); + format_free_parsed_args(argv); + return -EINVAL; + } + sep = NULL; + other_set = argv[0]; + other_attr = argv[1]; + attr = argv[2]; } /* Build the attribute list. */ - attrs[0] = argv[3]; + attrs[0] = attr; attrs[1] = NULL; /* Set up to search for matches. */ @@ -741,30 +811,31 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, return -ENOMEM; } cbdata.state = state; - cbdata.attr = argv[3]; - cbdata.separator = argv[0]; + cbdata.attr = attr; + cbdata.separator = sep; cbdata.outbuf = outbuf; cbdata.outbuf_len = outbuf_len; + cbdata.outbuf_choices = outbuf_choices; + cbdata.choices = NULL; cbdata.count = 0; cbdata.ret = 0; /* Retrieve the map-specific paramters. */ - map_filter = NULL; - map_bases = NULL; - backend_get_set_config(state, group, argv[1], &map_bases, &map_filter); - if (map_filter == NULL) { - map_filter = "(objectClass=*)"; - } - if (map_bases == NULL) { + set_filter = NULL; + set_bases = NULL; + backend_get_set_config(state, group, other_set, + &set_bases, &set_filter); + if (set_bases == NULL) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "no search bases defined for \"%s\"/\"%s\"?\n", - group, argv[1]); + group, other_set); } /* Note that the attribute in this map refers to this entry. */ if (inref_attrs != NULL) { - format_add_inref_attrs(inref_attrs, group, argv[1], argv[2]); + format_add_inref_attrs(inref_attrs, group, + other_set, other_attr); } tndn = format_escape_for_filter(slapi_entry_get_ndn(e)); @@ -772,30 +843,31 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "referred: out of memory\n"); - backend_free_set_config(map_bases, map_filter); + backend_free_set_config(set_bases, set_filter); slapi_pblock_destroy(local_pb); format_free_parsed_args(argv); return -ENOMEM; } /* Now just search through the entries used for the map. */ - for (i = 0; (map_bases != NULL) && (map_bases[i] != NULL); i++) { + use_filter = set_filter ? set_filter : "(objectClass=*)"; + for (i = 0; (set_bases != NULL) && (set_bases[i] != NULL); i++) { /* Build the search filter. */ - filter = malloc(strlen(map_filter) + strlen(argv[2]) + + filter = malloc(strlen(use_filter) + strlen(other_attr) + strlen(tndn) + 7); if (filter == NULL) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "referred: out of memory\n"); - backend_free_set_config(map_bases, map_filter); + backend_free_set_config(set_bases, set_filter); slapi_pblock_destroy(local_pb); format_free_parsed_args(argv); return -ENOMEM; } - sprintf(filter, "(&(%s=%s)%s)", argv[2], tndn, map_filter); + sprintf(filter, "(&(%s=%s)%s)", other_attr, tndn, use_filter); /* Set up the search. */ slapi_search_internal_set_pb(local_pb, - map_bases[i], LDAP_SCOPE_SUB, + set_bases[i], LDAP_SCOPE_SUB, filter, attrs, FALSE, NULL, NULL, state->plugin_identity, 0); @@ -803,7 +875,7 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "searching under \"%s\" for \"%s\"\n", - map_bases[i], filter); + set_bases[i], filter); slapi_search_internal_callback_pb(local_pb, &cbdata, NULL, format_referred_entry_cb, @@ -816,7 +888,19 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, } free(tndn); - backend_free_set_config(map_bases, map_filter); + if (outbuf_choices != NULL) { + if (cbdata.choices != NULL) { + /* Return the values we found. */ + format_add_choice(outbuf_choices, outbuf, + cbdata.choices); + backend_shr_free_strlist(cbdata.choices); + } else { + /* Return a no-result error. */ + cbdata.ret = -ENOENT; + } + } + + backend_free_set_config(set_bases, set_filter); slapi_pblock_destroy(local_pb); format_free_parsed_args(argv); return cbdata.ret ? cbdata.ret : cbdata.outbuf - outbuf; @@ -2086,6 +2170,10 @@ format_get_data_set(struct plugin_state *state, Slapi_Entry *e, } combinations *= this_choice->n_values; } + if (combinations == 0) { + format_free_choices(choices); + return NULL; + } template_len = strlen(template); ret = malloc((combinations + 1) * sizeof(char *)); if (ret != NULL) { @@ -47,7 +47,7 @@ #include "wrap.h" /* The singleton for the cache. */ -struct { +static struct { char *master; struct domain { char *name; @@ -228,7 +228,8 @@ map_data_find_map_entry_id(struct plugin_state *state, * returns FALSE, then we abort and return FALSE, otherwise we return TRUE. */ static bool_t map_data_foreach_entry(struct plugin_state *state, - bool_t all, const char *id, + const char *domain_name, const char *map_name, + const char *id, bool_t (*fn)(const char *domain, const char *map, bool_t secure, const char *key, unsigned int key_len, @@ -245,14 +246,21 @@ map_data_foreach_entry(struct plugin_state *state, struct map_entry *entry; for (i = 0; i < map_data.n_domains; i++) { domain = &map_data.domains[i]; + if ((domain_name != NULL) && + (strcmp(domain_name, domain->name) != 0)) { + continue; + } for (j = 0; j < domain->n_maps; j++) { map = &domain->maps[j]; + if ((map_name != NULL) && + (strcmp(map_name, map->name) != 0)) { + continue; + } for (entry = map->entries; entry != NULL; entry = entry->next) { - if (all || - ((id != NULL) && - (strcmp(id, entry->id) == 0))) { + if ((id == NULL) || + (strcmp(id, entry->id) == 0)) { for (k = 0; k < entry->n_keys; k++) { if (!(*fn)(domain->name, map->name, @@ -276,7 +284,8 @@ map_data_foreach_entry(struct plugin_state *state, /* Iterate over every entry which matches the corresponding ID. */ bool_t -map_data_foreach_entry_id(struct plugin_state *state, const char *id, +map_data_foreach_entry_id(struct plugin_state *state, + const char *domain, const char *map, const char *id, bool_t (*fn)(const char *domain, const char *map, bool_t secure, const char *key, @@ -287,7 +296,23 @@ map_data_foreach_entry_id(struct plugin_state *state, const char *id, void *backend_data, void *cbdata), void *cbdata) { - return map_data_foreach_entry(state, FALSE, id, fn, cbdata); + return map_data_foreach_entry(state, domain, map, id, fn, cbdata); +} + +/* Iterate over all domains, calling the callback with information about the + * domain. */ +bool_t +map_data_foreach_domain(struct plugin_state *state, + bool_t (*fn)(const char *domain, void *cbdata), + void *cbdata) +{ + int i, j; + for (i = 0; i < map_data.n_domains; i++) { + if (!(*fn)(map_data.domains[i].name, cbdata)) { + return FALSE; + } + } + return TRUE; } /* Iterate over all maps, calling the callback with information about the map @@ -398,9 +423,9 @@ bool_t map_match(struct plugin_state *state, const char *domain_name, const char *map_name, bool_t *secure, - unsigned int key_len, char *key, - unsigned int *value_len, char **value, - const char **id) + unsigned int key_len, const char *key, + unsigned int *value_len, const char **value, + const char **id, void **backend_data) { struct map *map; struct map_entry *entry; @@ -416,6 +441,9 @@ map_match(struct plugin_state *state, *value_len = entry->value_len; *value = entry->value; *id = entry->id; + if (backend_data != NULL) { + *backend_data = entry->backend_data; + } return TRUE; } @@ -424,9 +452,9 @@ map_match_id(struct plugin_state *state, const char *domain_name, const char *map_name, bool_t *secure, const char *in_id, unsigned int in_key_index, - unsigned int *key_len, char **key, - unsigned int *value_len, char **value, - const char **id) + unsigned int *key_len, const char **key, + unsigned int *value_len, const char **value, + const char **id, void **backend_data) { struct map *map; struct map_entry *entry; @@ -450,6 +478,9 @@ map_match_id(struct plugin_state *state, *value_len = entry->value_len; *value = entry->value; *id = entry->id; + if (backend_data != NULL) { + *backend_data = entry->backend_data; + } return TRUE; } @@ -827,10 +858,10 @@ map_data_unset_map_entry(struct plugin_state *state, /* Remove the entry from the map which matches the passed-in ID. */ void -map_data_unset_entry_id(struct plugin_state *state, - const char *domain_name, - const char *map_name, - const char *id) +map_data_unset_entry(struct plugin_state *state, + const char *domain_name, + const char *map_name, + const char *id) { struct map *map; struct map_entry *entry; @@ -37,14 +37,15 @@ bool_t map_supports_map(struct plugin_state *state, bool_t *secure); bool_t map_match(struct plugin_state *state, const char *domain, const char *map, bool_t *secure, - unsigned int key_len, char *key, - unsigned int *value_len, char **value, const char **id); + unsigned int key_len, const char *key, + unsigned int *value_len, const char **value, + const char **id, void **backend_data); bool_t map_match_id(struct plugin_state *state, const char *domain, const char *map, bool_t *secure, const char *id_in, unsigned int id_index, - unsigned int *key_len, char **key, - unsigned int *value_len, char **value, - const char **id); + unsigned int *key_len, const char **key, + unsigned int *value_len, const char **value, + const char **id, void **backend_data); bool_t map_first(struct plugin_state *state, const char *domain, const char *map, bool_t *secure, unsigned int *first_key_len, char **first_key, @@ -73,9 +74,9 @@ void map_data_set_map(struct plugin_state *state, const char *domain_name, const char *map_name, bool_t secure, void *backend_data, void (*free_backend_data)(void *p)); -void map_data_unset_entry_id(struct plugin_state *state, - const char *domain_name, const char *map_name, - const char *id); +void map_data_unset_entry(struct plugin_state *state, + const char *domain_name, const char *map_name, + const char *id); void map_data_set_entry(struct plugin_state *state, const char *domain_name, const char *map_name, const char *id, @@ -85,7 +86,9 @@ void map_data_set_entry(struct plugin_state *state, bool_t map_data_check_entry(struct plugin_state *state, const char *domain_name, const char *map_name, const char *id); -bool_t map_data_foreach_entry_id(struct plugin_state *state, const char *id, +bool_t map_data_foreach_entry_id(struct plugin_state *state, + const char *domain, const char *map, + const char *id, bool_t (*fn)(const char *domain, const char *map, bool_t secure, @@ -97,6 +100,9 @@ bool_t map_data_foreach_entry_id(struct plugin_state *state, const char *id, void *backend_data, void *cbdata), void *cbdata); +bool_t map_data_foreach_domain(struct plugin_state *state, + bool_t (*fn)(const char *domain, void *cbdata), + void *cbdata); bool_t map_data_foreach_map(struct plugin_state *state, const char *domain_name, bool_t (*fn)(const char *domain, const char *map, @@ -106,8 +106,8 @@ nis_match(struct plugin_state *state, req_key.keydat.keydat_len, req_key.keydat.keydat_val, &reply_val->valdat.valdat_len, - &reply_val->valdat.valdat_val, - &entry_id) && + (const char **) &reply_val->valdat.valdat_val, + &entry_id, NULL) && (map_secure ? client_secure : TRUE)) { reply_val->status = YP_TRUE; slapi_log_error(SLAPI_LOG_PLUGIN, @@ -217,8 +217,8 @@ nis_next(struct plugin_state *state, req_key.keydat.keydat_len, req_key.keydat.keydat_val, &reply_key_val->valdat.valdat_len, - &reply_key_val->valdat.valdat_val, - &entry_id) && + (const char **) &reply_key_val->valdat.valdat_val, + &entry_id, NULL) && (map_secure ? client_secure : TRUE)) { /* Have data for this key, but not the next. */ reply_key_val->status = YP_NOMORE; @@ -660,10 +660,10 @@ nis_all(struct plugin_state *state, cookie->id, cookie->key_index, &reply_key->keydat_len, - &reply_key->keydat_val, + (const char **) &reply_key->keydat_val, &reply_val->valdat_len, - &reply_val->valdat_val, - &entry_id) && + (const char **) &reply_val->valdat_val, + &entry_id, NULL) && (map_secure ? client_secure : TRUE); entry_key_index = cookie->key_index; if (found) { diff --git a/src/plug-sch.c b/src/plug-sch.c index fdb819a..6bd8f33 100644 --- a/src/plug-sch.c +++ b/src/plug-sch.c @@ -58,14 +58,19 @@ #include "portmap.h" #include "wrap.h" +#define PLUGIN_ID "schema-compat-plugin" +#define PLUGIN_PREOP_ID PLUGIN_ID "-preop" +#define PLUGIN_POSTOP_ID PLUGIN_ID "-postop" + /* the module initialization function */ static Slapi_PluginDesc plugin_description = { - .spd_id = "schema-compat-plugin", + .spd_id = PLUGIN_ID, .spd_vendor = "redhat.com", .spd_version = PACKAGE_VERSION, .spd_description = "Schema Compatibility Plugin", }; +static struct plugin_state *global_plugin_state; /* Handle the part of startup that needs to be done before we drop privileges. */ @@ -99,15 +104,38 @@ plugin_startup(Slapi_PBlock *pb) struct plugin_state *state; slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); slapi_pblock_get(pb, SLAPI_TARGET_DN, &state->plugin_base); + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "startup: target-dn is %s%s%s\n", + state->plugin_base ? "\"" : "", + state->plugin_base ? state->plugin_base : "NULL", + state->plugin_base ? "\"" : ""); backend_startup(state); return 0; } +static int +schema_compat_plugin_init_preop(Slapi_PBlock *pb) +{ + slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_03); + slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, &plugin_description); + slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, global_plugin_state); + backend_init_preop(pb, global_plugin_state); + return 0; +} +static int +schema_compat_plugin_init_postop(Slapi_PBlock *pb) +{ + slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_03); + slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, &plugin_description); + slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, global_plugin_state); + backend_init_postop(pb, global_plugin_state); + return 0; +} int schema_compat_plugin_init(Slapi_PBlock *pb) { struct plugin_state *state = NULL; - /* Allocate a memory pool and start listening for connections. */ + /* Allocate a memory pool. */ if (plugin_state_init(pb, &state) == -1) { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_description.spd_id, "error setting up plugin\n"); @@ -120,8 +148,26 @@ schema_compat_plugin_init(Slapi_PBlock *pb) slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, state); /* Let the backend do its setup. */ map_init(pb, state); - backend_init(pb, state); slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "registered plugin hooks\n"); + "registered plugin\n"); + /* Register the sub-plugins. */ + global_plugin_state = state; + if (slapi_register_plugin("preoperation", TRUE, + "schema_compat_plugin_init_preop", + schema_compat_plugin_init_preop, + PLUGIN_PREOP_ID, NULL, + state->plugin_identity) != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "error registering preoperation plugin\n"); + } + if (slapi_register_plugin("postoperation", TRUE, + "schema_compat_plugin_init_postop", + schema_compat_plugin_init_postop, + PLUGIN_POSTOP_ID, NULL, + state->plugin_identity) != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "error registering postoperation plugin\n"); + } + global_plugin_state = NULL; return 0; } |
