/* * 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 * */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include #include #include #include #ifdef HAVE_DIRSRV_SLAPI_PLUGIN_H #include #include #include #else #include #endif #include #include #ifdef HAVE_TCPD_H #include #endif #include "backend.h" #include "back-shr.h" #include "defs-nis.h" #include "disp-nis.h" #include "format.h" #include "plugin.h" #include "map.h" #define NIS_MAP_CONFIGURATION_FILTER "(&(objectClass=*)(" NIS_MAP_CONFIGURATION_BASE_ATTR "=*)(" NIS_MAP_CONFIGURATION_DOMAIN_ATTR "=*)(" NIS_MAP_CONFIGURATION_MAP_ATTR "=*))" /* The data we ask the map cache to keep, for us, for each map. */ struct backend_set_data { /* Common data. */ struct plugin_state *state; char *domain, *map, **bases, *entry_filter; char **ref_attrs; struct format_inref_attr **inref_attrs; /* NIS-specific data. */ char **key_formats, **keys_formats, *value_format; int n_key_formats, n_keys_formats; char *disallowed_chars; }; /* Read the name of the NIS master. Used by the map module on behalf of the * NIS service logic. */ void backend_free_master_name(struct plugin_state *state, char *master) { backend_shr_free_server_name(state, master); } int backend_read_master_name(struct plugin_state *state, char **master) { return backend_shr_read_server_name(state, master); } /* Manipulate map configuration data. */ struct plugin_state * backend_set_config_get_state(struct backend_set_data *set_data) { return set_data->state; } char ** backend_set_config_get_bases(struct backend_set_data *set_data) { return set_data->bases; } char * backend_set_config_get_filter(struct backend_set_data *set_data) { return set_data->entry_filter; } char * backend_set_config_get_group(struct backend_set_data *set_data) { return set_data->domain; } char * backend_set_config_get_set(struct backend_set_data *set_data) { return set_data->map; } struct format_inref_attr ** backend_set_config_get_inref_attrs(struct backend_set_data *set_data) { return set_data->inref_attrs; } char ** backend_set_config_get_ref_attrs(struct backend_set_data *set_data) { return set_data->ref_attrs; } static void backend_free_set_data_contents(void *data) { struct backend_set_data *set_data = data; if (set_data != NULL) { free(set_data->domain); free(set_data->map); free(set_data->bases); free(set_data->disallowed_chars); format_free_attr_list(set_data->ref_attrs); format_free_inref_attrs(set_data->inref_attrs); free(set_data->entry_filter); backend_shr_free_strlist(set_data->key_formats); backend_shr_free_strlist(set_data->keys_formats); free(set_data->value_format); } } void backend_set_config_free_config(struct backend_set_data *data) { backend_free_set_data_contents(data); free(data); } static struct backend_set_data * backend_copy_set_data(const struct backend_set_data *data) { struct backend_set_data *ret; ret = malloc(sizeof(*ret)); if (ret == NULL) { return NULL; } ret->state = data->state; ret->domain = strdup(data->domain); ret->map = strdup(data->map); ret->bases = backend_shr_dup_strlist(data->bases); ret->disallowed_chars = data->disallowed_chars ? strdup(data->disallowed_chars) : NULL; ret->ref_attrs = data->ref_attrs ? format_dup_attr_list(data->ref_attrs) : NULL; ret->inref_attrs = data->inref_attrs ? format_dup_inref_attrs(data->inref_attrs) : NULL; ret->entry_filter = strdup(data->entry_filter); ret->key_formats = backend_shr_dup_strlist(data->key_formats); ret->keys_formats = backend_shr_dup_strlist(data->keys_formats); ret->n_key_formats = data->n_key_formats; ret->n_keys_formats = data->n_keys_formats; ret->value_format = strdup(data->value_format); if ((ret->domain == NULL) || (ret->map == NULL) || (ret->bases == NULL) || (ret->entry_filter == NULL) || ((ret->key_formats == NULL) && (ret->keys_formats == NULL)) || (ret->value_format == NULL)) { backend_set_config_free_config(ret); return NULL; } return ret; } /* Given a map-entry directory entry, determine which keys it should have, * 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) { char **keys, ***key_sets, **all_keys, *value, *ndn, *plugin_id; int i, j, k, n_key_sets; plugin_id = data->state->plugin_desc->spd_id; /* Pull out the NDN of this entry. */ ndn = slapi_entry_get_ndn(e); /* Pull out the keys and value for the entry. */ if (data->n_key_formats > 0) { keys = malloc((data->n_key_formats + 1) * sizeof(char *)); } else { keys = NULL; } if (keys != NULL) { for (i = 0, j = 0; i < data->n_key_formats; i++) { keys[j] = format_get_data(data->state, e, data->domain, data->map, data->key_formats[i], data->disallowed_chars, &data->ref_attrs, &data->inref_attrs); if (keys[j] != NULL) { j++; } else { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id, "no key for %s, " "unsetting domain/map/id" "\"%s\"/\"%s\"/(\"%s\")\n", data->key_formats[i], data->domain, data->map, ndn); map_data_unset_entry_id(data->state, data->domain, data->map, ndn); for (k = 0; k < j; k++) { format_free_data(keys[k]); } free(keys); return; } } keys[j] = NULL; } if (data->n_keys_formats > 0) { key_sets = malloc((data->n_keys_formats + 1) * sizeof(char **)); } else { key_sets = NULL; } n_key_sets = 0; if (key_sets != NULL) { for (i = 0, j = 0; i < data->n_keys_formats; i++) { key_sets[j] = format_get_data_set(data->state, e, data->domain, data->map, data->keys_formats[i], data->disallowed_chars, &data->ref_attrs, &data->inref_attrs); if (key_sets[j] != NULL) { j++; } } key_sets[j] = NULL; n_key_sets = j; } value = format_get_data(data->state, e, data->domain, data->map, data->value_format, data->disallowed_chars, &data->ref_attrs, &data->inref_attrs); /* Build one big list of all of the keys and key sets. */ k = 0; if (keys != NULL) { for (i = 0; keys[i] != NULL; i++) { continue; } k += i; } if (key_sets != NULL) { for (i = 0; key_sets[i] != NULL; i++) { for (j = 0; key_sets[i][j] != NULL; j++) { continue; } k += j; } } if (k > 0) { all_keys = malloc(sizeof(char *) * (k + 1)); if (all_keys != NULL) { k = 0; if (keys != NULL) { for (i = 0; keys[i] != NULL; i++) { all_keys[k++] = keys[i]; } } if (key_sets != NULL) { for (i = 0; key_sets[i] != NULL; i++) { for (j = 0; key_sets[i][j] != NULL; j++) { all_keys[k++] = key_sets[i][j]; } } } all_keys[k] = NULL; } } else { all_keys = NULL; } /* If we actually generated a value, then set it, otherwise clear it in * case there was one set before. */ if ((all_keys != NULL) && (value != NULL)) { for (i = 0; all_keys[i] != NULL; i++) { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id, "setting domain/map/key/value " "\"%s\"/\"%s\"/\"%s\"(\"%s\")=\"%s\"\n", data->domain, data->map, all_keys[i], ndn, value); } map_data_set_entry(data->state, data->domain, data->map, ndn, NULL, all_keys, -1, value, NULL, NULL); } else { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id, "no value for %s, unsetting domain/map/id" "\"%s\"/\"%s\"/(\"%s\")\n", ndn, data->domain, data->map, ndn); map_data_unset_entry_id(data->state, data->domain, data->map, ndn); } format_free_data(value); free(all_keys); if (key_sets != NULL) { for (i = 0; key_sets[i] != NULL; i++) { format_free_data_set(key_sets[i]); } free(key_sets); } if (keys != NULL) { for (i = 0; i < data->n_key_formats; i++) { format_free_data(keys[i]); } free(keys); } } /* * Generate a copy of the filter string, with specific sequences replaced: * %d -> name of the domain * %m -> name of the map * %% -> literal '%' */ static char * backend_map_config_filter(const char *format, const char *domain, const char *map) { char *ret; int i, j, l; l = 0; for (i = 0; format[i] != '\0'; i++) { if (format[i] == '%') { switch (format[i + 1]) { case 'd': l += strlen(domain); i++; break; case 'm': l += strlen(map); i++; break; case '%': l++; i++; break; default: l++; break; } } else { l++; } } ret = malloc(l + 1); for (i = j = 0; format[i] != '\0'; i++) { if (format[i] == '%') { switch (format[i + 1]) { case 'd': strcpy(ret + j, domain); i++; j += strlen(domain); break; case 'm': strcpy(ret + j, map); i++; j += strlen(map); break; case '%': i++; ret[j++] = format[i]; break; default: ret[j++] = format[i]; break; } } else { ret[j++] = format[i]; } } ret[j] = '\0'; return ret; } /* Given a map configuration entry and domain and map names, read the rest of * the map configuration settings. */ void backend_set_config_read_config(struct plugin_state *state, Slapi_Entry *e, const char *domain, const char *map, bool_t *secure, struct backend_set_data **pret) { struct backend_set_data ret; const char *default_filter, *default_key_format, *default_keys_format; const char *default_value_format, *default_disallowed_chars; char **bases, *entry_filter; char **key_formats, **keys_formats, *value_format, *actual_attr; char *disallowed_chars; char **use_bases, *use_entry_filter; char **use_key_formats, **use_keys_formats; char *use_value_format, *use_disallowed_chars; const char *cvalue; int i, j, disposition, buffer_flags, count; Slapi_ValueSet *values; Slapi_Value *value; /* Read the hard-coded defaults for a map with this name. */ defaults_get_map_config(map, secure, &default_filter, &default_key_format, &default_keys_format, &default_value_format, &default_disallowed_chars); /* Read the values from the configuration entry. */ bases = NULL; if (slapi_vattr_values_get(e, NIS_MAP_CONFIGURATION_BASE_ATTR, &values, &disposition, &actual_attr, 0, &buffer_flags) == 0) { count = slapi_valueset_count(values); bases = malloc(sizeof(char *) * (count + 1)); if (bases != NULL) { i = 0; for (j = slapi_valueset_first_value(values, &value); j != -1; j = slapi_valueset_next_value(values, j, &value)) { cvalue = slapi_value_get_string(value); bases[i++] = strdup(cvalue); } bases[i] = NULL; } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); } entry_filter = NULL; if (slapi_vattr_values_get(e, NIS_MAP_CONFIGURATION_FILTER_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); if (strlen(cvalue) > 1) { if ((cvalue[0] != '(') || (cvalue[strlen(cvalue) - 1] != ')')) { entry_filter = malloc(strlen(cvalue) + 3); if (entry_filter != NULL) { sprintf(entry_filter, "(%s)", cvalue); } } } if (entry_filter == NULL) { entry_filter = strdup(cvalue); } } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); } key_formats = NULL; if (slapi_vattr_values_get(e, NIS_MAP_CONFIGURATION_KEY_ATTR, &values, &disposition, &actual_attr, 0, &buffer_flags) == 0) { key_formats = malloc((slapi_valueset_count(values) + 1) * sizeof (char *)); if (key_formats != NULL) { i = 0; for (j = slapi_valueset_first_value(values, &value); j != -1; j = slapi_valueset_next_value(values, j, &value)) { cvalue = slapi_value_get_string(value); key_formats[i++] = strdup(cvalue); } key_formats[i] = NULL; } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); } keys_formats = NULL; if (slapi_vattr_values_get(e, NIS_MAP_CONFIGURATION_KEYS_ATTR, &values, &disposition, &actual_attr, 0, &buffer_flags) == 0) { keys_formats = malloc((slapi_valueset_count(values) + 1) * sizeof (char *)); if (keys_formats != NULL) { i = 0; for (j = slapi_valueset_first_value(values, &value); j != -1; j = slapi_valueset_next_value(values, j, &value)) { cvalue = slapi_value_get_string(value); keys_formats[i++] = strdup(cvalue); } keys_formats[i] = NULL; } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); } value_format = NULL; if (slapi_vattr_values_get(e, NIS_MAP_CONFIGURATION_VALUE_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); value_format = strdup(cvalue); } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); } disallowed_chars = NULL; if (slapi_vattr_values_get(e, NIS_MAP_CONFIGURATION_DISALLOWED_CHARS_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); disallowed_chars = strdup(cvalue); } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); } *secure = FALSE; if (slapi_vattr_values_get(e, NIS_MAP_CONFIGURATION_SECURE_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)) { *secure = TRUE; } else { *secure = FALSE; } } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); } /* Build a filter, using either the configured value or the default as * a template, we need to do this because RFC2307bis sometimes stores * the map name in each entry, so it's useful to be able to filter on * it. */ use_entry_filter = backend_map_config_filter(entry_filter ? entry_filter : default_filter, domain, map); use_key_formats = key_formats ? backend_shr_dup_strlist(key_formats) : default_key_format ? backend_shr_dup_strlist_n((char **) &default_key_format, 1) : NULL; use_keys_formats = keys_formats ? backend_shr_dup_strlist(keys_formats) : default_keys_format ? backend_shr_dup_strlist_n((char **) &default_keys_format, 1) : NULL; use_value_format = value_format ? strdup(value_format) : strdup(default_value_format); use_bases = backend_shr_dup_strlist(bases); use_disallowed_chars = disallowed_chars ? disallowed_chars : (default_disallowed_chars ? strdup(default_disallowed_chars) : NULL); /* Free the values we read from the entry. */ free(value_format); backend_shr_free_strlist(key_formats); backend_shr_free_strlist(keys_formats); free(entry_filter); backend_shr_free_strlist(bases); /* Populate the returned structure. */ ret.state = state; ret.domain = strdup(domain); ret.map = strdup(map); ret.bases = use_bases; ret.disallowed_chars = use_disallowed_chars; ret.entry_filter = use_entry_filter; ret.key_formats = use_key_formats; ret.n_key_formats = 0; ret.keys_formats = use_keys_formats; ret.n_keys_formats = 0; ret.value_format = use_value_format; ret.ref_attrs = NULL; ret.inref_attrs = NULL; ret.n_key_formats = 0; for (i = 0; (use_key_formats != NULL) && (use_key_formats[i] != NULL); i++) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "initializing map %s in %s (3): " "filter \"%s\", " "key \"%s\", " "value \"%s\"\n", map, domain, use_entry_filter, use_key_formats[i], use_value_format); ret.n_key_formats++; } for (i = 0; (use_keys_formats != NULL) && (use_keys_formats[i] != NULL); i++) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "initializing map %s in %s (3): " "filter \"%s\", " "keys \"%s\", " "value \"%s\"\n", map, domain, use_entry_filter, use_keys_formats[i], use_value_format); ret.n_keys_formats++; } *pret = backend_copy_set_data(&ret); free(ret.domain); free(ret.map); backend_shr_free_strlist(ret.bases); free(ret.disallowed_chars); free(ret.entry_filter); backend_shr_free_strlist(ret.key_formats); backend_shr_free_strlist(ret.keys_formats); free(ret.value_format); } /* Process a map configuration directory entry. Pull out the domain and map * names which are valid for this configuration and configure such a map for * each in turn. */ int backend_set_config_entry_add_cb(Slapi_Entry *e, void *callback_data) { char **domains, **maps, *actual_attr; const char *cvalue; Slapi_ValueSet *values; Slapi_Value *value; int i, j, ret, disposition, buffer_flags, count; struct plugin_state *state; state = callback_data; domains = NULL; if (slapi_vattr_values_get(e, NIS_MAP_CONFIGURATION_DOMAIN_ATTR, &values, &disposition, &actual_attr, 0, &buffer_flags) == 0) { count = slapi_valueset_count(values); domains = malloc(sizeof(char *) * (count + 1)); if (domains != NULL) { for (i = slapi_valueset_first_value(values, &value); i != -1; i = slapi_valueset_next_value(values, i, &value)) { cvalue = slapi_value_get_string(value); domains[i] = strdup(cvalue); } domains[count] = NULL; } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); } maps = NULL; if (slapi_vattr_values_get(e, NIS_MAP_CONFIGURATION_MAP_ATTR, &values, &disposition, &actual_attr, 0, &buffer_flags) == 0) { count = slapi_valueset_count(values); maps = malloc(sizeof(char *) * (count + 1)); if (maps != NULL) { for (i = slapi_valueset_first_value(values, &value); i != -1; i = slapi_valueset_next_value(values, i, &value)) { cvalue = slapi_value_get_string(value); maps[i] = strdup(cvalue); } maps[count] = NULL; } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); } 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]); } } if (domains != NULL) { for (i = 0; (domains != NULL) && (domains[i] != NULL); i++) { free(domains[i]); } free(domains); } if (maps != NULL) { for (i = 0; (maps != NULL) && (maps[i] != NULL); i++) { free(maps[i]); } free(maps); } return 0; } /* Update/initialize parameters stored in the plugin's configuration entry. */ void backend_update_params(struct plugin_state *state) { Slapi_DN *our_dn; Slapi_Entry *our_entry; Slapi_ValueSet *values; Slapi_Value *value; char *actual_attr; const char *cvalue; int disposition, buffer_flags, i, j; unsigned int uvalue; char *attrs[] = { NIS_PLUGIN_CONFIGURATION_MAXVALUE_ATTR, NIS_PLUGIN_CONFIGURATION_MAXDGRAM_ATTR, NIS_PLUGIN_CONFIGURATION_PORT_ATTR, NIS_PLUGIN_CONFIGURATION_SECURENET_ATTR, NIS_PLUGIN_CONFIGURATION_TCPWRAPNAME_ATTR, NULL, }; our_dn = slapi_sdn_new_dn_byval(state->plugin_base); if (our_dn == NULL) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "backend_update_params: " "error parsing %s%s%s\n", state->plugin_base ? "\"" : "", state->plugin_base ? state->plugin_base : "NULL", state->plugin_base ? "\"" : ""); return; } slapi_search_internal_get_entry(our_dn, attrs, &our_entry, state->plugin_identity); slapi_sdn_free(&our_dn); our_dn = NULL; if (our_entry == NULL) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "backend_update_params: failure reading entry " "\"%s\"\n", state->plugin_base); return; } /* Pull out the attribute values. */ for (i = 0; attrs[i] != NULL; i++) { if (slapi_vattr_values_get(our_entry, attrs[i], &values, &disposition, &actual_attr, 0, &buffer_flags) == 0) { value = NULL; j = slapi_valueset_first_value(values, &value); if (j != -1) { switch (i) { case 0: /* max value size */ uvalue = slapi_value_get_uint(value); if (uvalue != 0) { state->max_value_size = uvalue; } else { state->max_value_size = DEFAULT_MAX_VALUE_SIZE; } slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "backend_update_params: " "setting max value " "size %u\n", state->max_value_size); break; case 1: /* max dgram size */ uvalue = slapi_value_get_uint(value); if (uvalue != 0) { state->max_dgram_size = uvalue; } else { state->max_dgram_size = DEFAULT_MAX_DGRAM_SIZE; } slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "backend_update_params: " "setting max dgram " "size %u\n", state->max_dgram_size); break; case 3: /* securenet entry */ dispatch_securenets_clear(state); while (j != -1) { cvalue = slapi_value_get_string(value); dispatch_securenets_add(state, cvalue); j = slapi_valueset_next_value(values, j, &value); } break; case 4: /* tcp-wrappers name */ #ifdef HAVE_TCPD_H cvalue = slapi_value_get_string(value); request_set(state->request_info, RQ_DAEMON, cvalue); #endif break; default: break; } } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); } else { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "backend_update_params: no \"%s\" value " "for \"%s\", using default\n", attrs[i], state->plugin_base); } } slapi_entry_free(our_entry); } /* Process a map configuration directory entry. Pull out the domain and map * names which are specified in the entry and delete each in turn. */ int backend_set_config_entry_delete_cb(Slapi_Entry *e, void *callback_data) { struct plugin_state *state; state = callback_data; return backend_shr_set_config_entry_delete(state, e, NIS_MAP_CONFIGURATION_DOMAIN_ATTR, NIS_MAP_CONFIGURATION_MAP_ATTR); } /* Read enough of the map configuration for the formatting code to be able to * resolver references correctly. */ struct backend_get_set_config_cb { struct plugin_state *state; char **bases; char *entry_filter; }; void backend_free_set_config(char **bases, char *entry_filter) { backend_shr_free_strlist(bases); free(entry_filter); } static bool_t backend_get_set_config_entry_cb(Slapi_Entry *e, void *callback_data) { Slapi_ValueSet *values; Slapi_Value *value; struct backend_get_set_config_cb *cbdata; char *actual_attr; const char *cvalue; int disposition, buffer_flags, i, count; cbdata = callback_data; slapi_log_error(SLAPI_LOG_PLUGIN, cbdata->state->plugin_desc->spd_id, "reading map configuration from \"%s\"\n", slapi_entry_get_ndn(e)); values = NULL; value = NULL; if (slapi_vattr_values_get(e, NIS_MAP_CONFIGURATION_BASE_ATTR, &values, &disposition, &actual_attr, 0, &buffer_flags) == 0) { count = slapi_valueset_count(values); cbdata->bases = malloc(sizeof(char *) * (count + 1)); if (cbdata->bases != NULL) { for (i = slapi_valueset_first_value(values, &value); i != -1; i = slapi_valueset_next_value(values, i, &value)) { cvalue = slapi_value_get_string(value); cbdata->bases[i] = strdup(cvalue); } cbdata->bases[count] = NULL; } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); } if (slapi_vattr_values_get(e, NIS_MAP_CONFIGURATION_FILTER_ATTR, &values, &disposition, &actual_attr, 0, &buffer_flags) == 0) { if (slapi_valueset_first_value(values, &value) != -1) { cvalue = slapi_value_get_string(value); if (cvalue != NULL) { free(cbdata->entry_filter); cbdata->entry_filter = strdup(cvalue); } } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); } return TRUE; } void backend_get_set_config(struct plugin_state *state, const char *domain, const char *map, char ***bases, char **entry_filter) { Slapi_PBlock *pb; char *filter; char *attrs[] = {NIS_MAP_CONFIGURATION_FILTER_ATTR, NIS_MAP_CONFIGURATION_BASE_ATTR, NULL}; const char *default_filter; bool_t map_secure; struct backend_get_set_config_cb cbdata; /* Build the search filter. */ filter = malloc(strlen("(&(" NIS_MAP_CONFIGURATION_DOMAIN_ATTR "=)(" NIS_MAP_CONFIGURATION_MAP_ATTR "=)(" NIS_MAP_CONFIGURATION_BASE_ATTR "=*))") + strlen(domain) + strlen(map) + strlen(NIS_MAP_CONFIGURATION_FILTER) + 1); if (filter == NULL) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "out of memory reading configuration for " "\"%s\"/\"%s\"!\n", domain, map); return; } sprintf(filter, "(&(" NIS_MAP_CONFIGURATION_DOMAIN_ATTR "=%s)(" NIS_MAP_CONFIGURATION_MAP_ATTR "=%s)(" NIS_MAP_CONFIGURATION_BASE_ATTR "=*)%s)", domain, map, NIS_MAP_CONFIGURATION_FILTER); /* Perform the search. */ pb = slapi_pblock_new(); slapi_search_internal_set_pb(pb, state->plugin_base, LDAP_SCOPE_SUB, filter, attrs, FALSE, NULL, NULL, state->plugin_identity, 0); cbdata.bases = NULL; cbdata.state = state; map_secure = FALSE; defaults_get_map_config(map, &map_secure, &default_filter, NULL, NULL, NULL, NULL); cbdata.entry_filter = strdup(default_filter); slapi_search_internal_callback_pb(pb, &cbdata, NULL, backend_get_set_config_entry_cb, NULL); /* Return the results. */ *bases = cbdata.bases; *entry_filter = backend_map_config_filter(cbdata.entry_filter, domain, map); free(cbdata.entry_filter); /* Clean up. */ slapi_pblock_destroy(pb); 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) { 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; } /* Scan for the list of configured domains and maps. */ void backend_startup(struct plugin_state *state) { backend_shr_startup(state, NIS_MAP_CONFIGURATION_FILTER); } /* Set up our post-op callbacks. */ void backend_init(Slapi_PBlock *pb, struct plugin_state *state) { backend_shr_postop_init(pb, state); }