diff options
author | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-06-23 11:21:54 -0400 |
---|---|---|
committer | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-06-23 11:21:54 -0400 |
commit | 7a9ff3afd8c6d72544ff4629d96fa7095364a62e (patch) | |
tree | 2e81a27ab5d9a961587e7b3a2c57ca5c781f0939 | |
parent | d2b7df5c6e434c54a808d437adde2ec4143d3048 (diff) | |
parent | 96a2fc8a22faec046ab34f3b72e009ef812a6747 (diff) | |
download | slapi-nis-7a9ff3afd8c6d72544ff4629d96fa7095364a62e.tar.gz slapi-nis-7a9ff3afd8c6d72544ff4629d96fa7095364a62e.tar.xz slapi-nis-7a9ff3afd8c6d72544ff4629d96fa7095364a62e.zip |
Merge branch 'master' of git.fedorahosted.org:/git/slapi-nis
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | doc/configuration.txt | 9 | ||||
-rw-r--r-- | doc/design.txt | 2 | ||||
-rw-r--r-- | src/backend.c | 200 | ||||
-rw-r--r-- | src/defaults.c | 56 | ||||
-rw-r--r-- | src/defaults.h | 5 | ||||
-rw-r--r-- | src/dummymap.c | 17 | ||||
-rw-r--r-- | src/format.c | 84 | ||||
-rw-r--r-- | src/format.h | 2 | ||||
-rw-r--r-- | src/map.c | 311 | ||||
-rw-r--r-- | src/map.h | 22 | ||||
-rw-r--r-- | src/nis.c | 71 |
12 files changed, 532 insertions, 252 deletions
diff --git a/configure.ac b/configure.ac index 13f7f6f..d5f3de0 100644 --- a/configure.ac +++ b/configure.ac @@ -113,7 +113,7 @@ AC_DEFINE(DEFAULT_MAX_DGRAM_SIZE,YPMAXRECORD,[Define to the default maximum data AC_DEFINE(DEFAULT_MAX_VALUE_SIZE,(256 * 1024),[Define to the default maximum map entry key and value size.]) AC_DEFINE(DEFAULT_TARGET_REPLY_SIZE,(4 * 1024),[Define to the default target size for a connected reply fragment.]) -baseattr=base +baseattr=nis-base AC_DEFINE_UNQUOTED(MAP_CONFIGURATION_BASE_ATTR,"$baseattr", [Define to name of the attribute which lists the containers for entries for a given map.]) filterattr=nis-filter @@ -131,6 +131,9 @@ AC_DEFINE_UNQUOTED(MAP_CONFIGURATION_DOMAIN_ATTR,"$domainattr", mapattr=nis-map AC_DEFINE_UNQUOTED(MAP_CONFIGURATION_MAP_ATTR,"$mapattr", [Define to name of the map configuration attribute which holds the name of the map.]) +disallowedcharsattr=nis-disallowed-chars +AC_DEFINE_UNQUOTED(MAP_CONFIGURATION_DISALLOWED_CHARS_ATTR,"$disallowedcharsattr", + [Define to the list of characters which should not be allowed in attribute values which are being considered.]) secureattr=nis-secure AC_DEFINE_UNQUOTED(MAP_CONFIGURATION_SECURE_ATTR,"$secureattr", [Define to name of the map configuration attribute which determines whether or not the map is treated a 'secure' map.]) diff --git a/doc/configuration.txt b/doc/configuration.txt index 08376b0..63c33fc 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -82,11 +82,17 @@ beneath the plugin's entry. These attributes are recognized: * nis-key-format A format specifier which the plugin will use to convert the contents of the directory server entry into the corresponding key in the NIS - map. + map. If this attribute has more than one value, the resulting NIS + map will include each resulting key with the same corresponding + value. * nis-value-format A format specifier which the plugin will use to convert the contents of the directory server entry into the corresponding value in the NIS map. + * nis-disallowed-chars + A list of characters which, if found in an attribute value, will + cause that attribute value to be ignored when evaluating keys and + values. The nis-filter, nis-key-format, and nis-value-format all have default settings which vary based on the name of the NIS map, but they can be @@ -101,5 +107,6 @@ overridden. An example map definition might look like this: nis-filter: (&(mail=*)(uid=*)) nis-key-format: %{uid} nis-value-format: %{uid}:%{mail} + nis-disallowed-chars: : nis-secure: no diff --git a/doc/design.txt b/doc/design.txt index c4a98bd..92abf49 100644 --- a/doc/design.txt +++ b/doc/design.txt @@ -191,7 +191,7 @@ given domain (or domains) with the given map name (or names), and then performs a subtree search under the specified base (or bases, if there's more than one "nis-base" value) for entries which match the provided filter. Each entry found is then "added" to the map, using the format -specifier stored in "nis-key-format" to construct the key for the entry +specifiers stored in "nis-key-format" to construct the keys for the entry in the map, with the corresponding value in the map being constructed using the format specifier given as the "nis-value-format". The map is marked as a "secure" map according to the "nis-secure" attribute, if diff --git a/src/backend.c b/src/backend.c index 393cc9d..a40241a 100644 --- a/src/backend.c +++ b/src/backend.c @@ -55,7 +55,10 @@ /* The data we ask the map cache to keep, for us, for each map. */ struct backend_map_data { struct plugin_state *state; - char *domain, *map, **bases, *entry_filter, *key_format, *value_format; + char *domain, *map, **bases, *entry_filter, **key_formats; + char *value_format; + int n_key_formats; + char *disallowed_chars; char **ref_attrs; struct format_inref_attr **inref_attrs; }; @@ -120,6 +123,14 @@ backend_read_master_name(struct plugin_state *state, char **master) slapi_entry_free(config); return (*master != NULL) ? 0 : -1; } +static void +backend_free_strlist(char **strlist) +{ + int i; + if (strlist) { + free(strlist); + } +} static char ** backend_dup_strlist(char **strlist) { @@ -139,7 +150,7 @@ backend_dup_strlist(char **strlist) } /* Allocate space for the array of pointers (with NULL terminator) and * then the string data. */ - ret = malloc((i + 1) * sizeof(char *) + l); + ret = malloc(((i + 1) * sizeof(char *)) + l); if (ret != NULL) { /* Figure out where the string data will start. */ s = (char *) &ret[i + 1]; @@ -165,10 +176,11 @@ backend_free_map_data_contents(void *data) free(map_data->domain); free(map_data->map); free(map_data->bases); + free(map_data->disallowed_chars); format_free_attr_list(map_data->ref_attrs); format_free_inref_attrs(map_data->inref_attrs); free(map_data->entry_filter); - free(map_data->key_format); + backend_free_strlist(map_data->key_formats); free(map_data->value_format); } } @@ -191,6 +203,8 @@ backend_copy_cb_data(const struct backend_map_data *data) ret->domain = strdup(data->domain); ret->map = strdup(data->map); ret->bases = backend_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; @@ -198,13 +212,15 @@ backend_copy_cb_data(const struct backend_map_data *data) format_dup_inref_attrs(data->inref_attrs) : NULL; ret->entry_filter = strdup(data->entry_filter); - ret->key_format = strdup(data->key_format); + ret->key_formats = backend_dup_strlist(data->key_formats); + ret->n_key_formats = data->n_key_formats; ret->value_format = strdup(data->value_format); if ((ret->domain == NULL) || (ret->map == NULL) || (ret->bases == NULL) || + (ret->disallowed_chars == NULL) || (ret->entry_filter == NULL) || - (ret->key_format == NULL) || + (ret->key_formats == NULL) || (ret->value_format == NULL)) { backend_free_map_data(ret); return NULL; @@ -218,29 +234,43 @@ static int backend_map_config_entry_add_one_cb(Slapi_Entry *e, void *callback_data) { struct backend_map_data *data; - char *key, *value, *ndn; + char **keys, *value, *ndn; int i, j; data = callback_data; - /* Pull out the key and value for the entry. */ - key = format_get_data(data->state, NULL, e, data->domain, data->map, - data->key_format, - &data->ref_attrs, &data->inref_attrs); + /* Pull out the keys and value for the entry. */ + keys = malloc((data->n_key_formats + 1) * sizeof(char *)); + if (keys != NULL) { + for (i = 0; i < data->n_key_formats; i++) { + keys[i] = format_get_data(data->state, NULL, e, + data->domain, data->map, + data->key_formats[i], + data->disallowed_chars, + &data->ref_attrs, + &data->inref_attrs); + } + keys[i] = NULL; + } else { + return 0; + } value = format_get_data(data->state, NULL, e, data->domain, data->map, - data->value_format, + data->value_format, data->disallowed_chars, &data->ref_attrs, &data->inref_attrs); /* Pull out the NDN of this entry. */ ndn = slapi_entry_get_ndn(e); /* If we actually generated a value, then set it, otherwise clear it in * case there was one set before. */ - if ((key != NULL) && (value != NULL)) { - slapi_log_error(SLAPI_LOG_PLUGIN, - data->state->plugin_desc->spd_id, - "setting domain/map/key/value " - "\"%s\"/\"%s\"/\"%s\"(\"%s\")=\"%s\"\n", - data->domain, data->map, - key, ndn, value); + if ((keys != NULL) && (value != NULL)) { + for (i = 0; i < data->n_key_formats; i++) { + slapi_log_error(SLAPI_LOG_PLUGIN, + data->state->plugin_desc->spd_id, + "setting domain/map/key/value " + "\"%s\"/\"%s\"/\"%s\"(\"%s\")=\"%s\"\n", + data->domain, data->map, + keys[i], ndn, value); + } map_data_set_entry(data->state, data->domain, data->map, ndn, - -1, key, + data->n_key_formats, + NULL, keys, -1, value); } else { slapi_log_error(SLAPI_LOG_PLUGIN, @@ -253,7 +283,10 @@ backend_map_config_entry_add_one_cb(Slapi_Entry *e, void *callback_data) ndn); } format_free_data(value); - format_free_data(key); + for (i = 0; i < data->n_key_formats; i++) { + format_free_data(keys[i]); + } + free(keys); return 0; } @@ -372,18 +405,21 @@ backend_map_config_read_config(struct plugin_state *state, Slapi_Entry *e, const char *domain, const char *map, bool_t *secure, struct backend_map_data *ret) { - const char *default_filter, *default_key_format, *default_value_format; - char **bases, *entry_filter, *key_format, *value_format, *actual_attr; - char **ref_attrs; + const char *default_filter, **default_key_formats; + const char *default_value_format, *default_disallowed_chars; + char **bases, *entry_filter, **key_formats, *value_format, *actual_attr; + char **ref_attrs, *disallowed_chars; struct format_inref_attr **inref_attrs; - char **use_bases, *use_entry_filter, *use_key_format, *use_value_format; + char **use_bases, *use_entry_filter, **use_key_formats; + char *use_value_format, *use_disallowed_chars; const char *cvalue; - int i, disposition, buffer_flags, count; + 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_value_format); + &default_key_formats, &default_value_format, + &default_disallowed_chars); /* Read the values from the configuration entry. */ bases = NULL; if (slapi_vattr_values_get(e, MAP_CONFIGURATION_BASE_ATTR, &values, @@ -392,13 +428,14 @@ backend_map_config_read_config(struct plugin_state *state, Slapi_Entry *e, count = slapi_valueset_count(values); bases = malloc(sizeof(char *) * (count + 1)); if (bases != NULL) { - for (i = slapi_valueset_first_value(values, &value); - i != -1; - i = slapi_valueset_next_value(values, i, &value)) { + 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++] = strdup(cvalue); } - bases[count] = NULL; + bases[i] = NULL; } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); } @@ -413,16 +450,24 @@ backend_map_config_read_config(struct plugin_state *state, Slapi_Entry *e, } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); } - key_format = NULL; + key_formats = NULL; if (slapi_vattr_values_get(e, MAP_CONFIGURATION_KEY_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); - key_format = strdup(cvalue); + 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); } - slapi_vattr_values_free(&values, &actual_attr, buffer_flags); } value_format = NULL; if (slapi_vattr_values_get(e, MAP_CONFIGURATION_VALUE_ATTR, &values, @@ -435,6 +480,17 @@ backend_map_config_read_config(struct plugin_state *state, Slapi_Entry *e, } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); } + disallowed_chars = NULL; + if (slapi_vattr_values_get(e, 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, MAP_CONFIGURATION_SECURE_ATTR, &values, &disposition, &actual_attr, @@ -461,41 +517,49 @@ backend_map_config_read_config(struct plugin_state *state, Slapi_Entry *e, entry_filter : default_filter, domain, map); - use_key_format = key_format ? - strdup(key_format) : - strdup(default_key_format); + use_key_formats = key_formats ? + backend_dup_strlist(key_formats) : + backend_dup_strlist((char **) default_key_formats); use_value_format = value_format ? strdup(value_format) : strdup(default_value_format); use_bases = backend_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); - free(key_format); + backend_free_strlist(key_formats); free(entry_filter); - if (bases) { - for (i = 0; bases[i] != NULL; i++) { - free(bases[i]); - } - free(bases); - } + backend_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_format = use_key_format; + ret->key_formats = use_key_formats; ret->value_format = use_value_format; ret->ref_attrs = NULL; ret->inref_attrs = NULL; - 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_format, use_value_format); + 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++; + } } /* Given a directory server entry which represents a map's configuration, set @@ -513,13 +577,21 @@ backend_map_config_entry_add_one(struct plugin_state *state, Slapi_Entry *e, secure = FALSE; backend_map_config_read_config(state, e, domain, map, &secure, &cb_data); + map_cb_data = backend_copy_cb_data(&cb_data); + backend_free_map_data_contents(&cb_data); + if (map_cb_data == NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "incomplete map definition %s in %s (2)\n", + map, domain); + slapi_pblock_destroy(pb); + return 0; + } slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "initializing map %s in %s, secure=%s (2)\n", map, domain, secure ? "yes" : "no"); - map_cb_data = backend_copy_cb_data(&cb_data); - backend_free_map_data_contents(&cb_data); - map_data_set_map(state, domain, map, secure, + map_data_set_map(state, domain, map, map_cb_data->n_key_formats, secure, map_cb_data, &backend_free_map_data); map_data_clear_map(state, domain, map); /* Search under each base in turn, adding the matching directory @@ -803,12 +875,7 @@ void backend_free_map_config(char **bases, char *entry_filter) { int i; - if (bases != NULL) { - for (i = 0; bases[i] != NULL; i++) { - free(bases[i]); - } - } - free(bases); + backend_free_strlist(bases); free(entry_filter); } @@ -908,7 +975,8 @@ backend_get_map_config(struct plugin_state *state, cbdata.bases = NULL; cbdata.state = state; map_secure = FALSE; - defaults_get_map_config(map, &map_secure, &default_filter, NULL, NULL); + defaults_get_map_config(map, &map_secure, &default_filter, + NULL, NULL, NULL); cbdata.entry_filter = strdup(default_filter); slapi_search_internal_callback_pb(pb, &cbdata, NULL, diff --git a/src/defaults.c b/src/defaults.c index fe2474d..9ecd1f8 100644 --- a/src/defaults.c +++ b/src/defaults.c @@ -33,45 +33,53 @@ #define DEFAULT_KEY_FORMAT "%{cn}" #define DEFAULT_VALUE_FORMAT "%{nisMapEntry}" #define DEFAULT_MAP_SECURE FALSE +static const char *default_key_formats[] = {DEFAULT_KEY_FORMAT, NULL}; static struct configuration { char *map; enum { config_exact, config_glob } config_match; bool_t secure; - char *filter, *key_format, *value_format; + char *filter, *key_formats[3], *value_format, *disallowed_chars; } config[] = { {"passwd.byname", config_exact, FALSE, "(objectClass=posixAccount)", - "%{uid}", - "%{uid}:%regsub(\"userPassword\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%{uidNumber}:%{gidNumber}:%{cn!:}:%{homeDirectory:-/}:%{loginShell!:}"}, + {"%{uid}", NULL, NULL}, + "%{uid}:%regsub(\"userPassword\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%{uidNumber}:%{gidNumber}:%{gecos:-%{cn}}:%{homeDirectory:-/}:%{loginShell}", + ":"}, {"passwd.byuid", config_exact, FALSE, "(objectClass=posixAccount)", - "%{uidNumber}", - "%{uid}:%regsub(\"userPassword\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%{uidNumber}:%{gidNumber}:%{cn!:}:%{homeDirectory:-/}:%{loginShell!:}"}, + {"%{uidNumber}", NULL, NULL}, + "%{uid}:%regsub(\"userPassword\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%{uidNumber}:%{gidNumber}:%{gecos:-%{cn}}:%{homeDirectory:-/}:%{loginShell}", + ":"}, {"group.byname", config_exact, FALSE, "(objectClass=posixGroup)", - "%{cn}", - "%{cn}:%regsub(\"userPassword\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%{gidNumber}:%merge(\",\",\"%list(\\\",\\\",\\\"memberUid\\\")\",\"%deref(\\\",\\\",\\\"member\\\",\\\"uid\\\")\",\"%deref(\\\",\\\",\\\"uniqueMember\\\",\\\"uid\\\")\",\"%referred(\\\",\\\",\\\"passwd.byname\\\",\\\"memberOf\\\",\\\"uid\\\")\")"}, + {"%{cn}", NULL, NULL}, + "%{cn}:%regsub(\"userPassword\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%{gidNumber}:%merge(\",\",\"%list(\\\",\\\",\\\"memberUid\\\")\",\"%deref(\\\",\\\",\\\"member\\\",\\\"uid\\\")\",\"%deref(\\\",\\\",\\\"uniqueMember\\\",\\\"uid\\\")\",\"%referred(\\\",\\\",\\\"passwd.byname\\\",\\\"memberOf\\\",\\\"uid\\\")\")", + ":,"}, {"group.bygid", config_exact, FALSE, "(objectClass=posixGroup)", - "%{gidNumber}", - "%{cn}:%regsub(\"userPassword\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%{gidNumber}:%merge(\",\",\"%list(\\\",\\\",\\\"memberUid\\\")\",\"%deref(\\\",\\\",\\\"member\\\",\\\"uid\\\")\",\"%deref(\\\",\\\",\\\"uniqueMember\\\",\\\"uid\\\")\",\"%referred(\\\",\\\",\\\"passwd.byuid\\\",\\\"memberOf\\\",\\\"uid\\\")\")"}, + {"%{gidNumber}", NULL, NULL}, + "%{cn}:%regsub(\"userPassword\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%{gidNumber}:%merge(\",\",\"%list(\\\",\\\",\\\"memberUid\\\")\",\"%deref(\\\",\\\",\\\"member\\\",\\\"uid\\\")\",\"%deref(\\\",\\\",\\\"uniqueMember\\\",\\\"uid\\\")\",\"%referred(\\\",\\\",\\\"passwd.byuid\\\",\\\"memberOf\\\",\\\"uid\\\")\")", + ":,"}, {"netgroup", config_exact, FALSE, "(objectClass=nisNetgroup)", - "%{cn}", - "%list(\" \",\"nisNetgroupTriple\",\"memberNisNetgroup\")"}, + {"%{cn}", NULL, NULL}, + "%list(\" \",\"nisNetgroupTriple\",\"memberNisNetgroup\")", + NULL}, {"auto.*", config_glob, FALSE, "(objectClass=automount)", - "%{automountKey}", - "%{automountInformation}"}, + {"%{automountKey}", NULL, NULL}, + "%{automountInformation}", + NULL}, }; void defaults_get_map_config(const char *mapname, bool_t *secure, const char **filter, - const char **key_format, - const char **value_format) + const char ***key_formats, + const char **value_format, + const char **disallowed_chars) { unsigned int i; if (filter) { @@ -80,8 +88,8 @@ defaults_get_map_config(const char *mapname, if (secure) { *secure = DEFAULT_MAP_SECURE; } - if (key_format) { - *key_format = DEFAULT_KEY_FORMAT; + if (key_formats) { + *key_formats = default_key_formats; } if (value_format) { *value_format = DEFAULT_VALUE_FORMAT; @@ -96,12 +104,15 @@ defaults_get_map_config(const char *mapname, if (filter) { *filter = config[i].filter; } - if (key_format) { - *key_format = config[i].key_format; + if (key_formats) { + *key_formats = (const char **) config[i].key_formats; } if (value_format) { *value_format = config[i].value_format; } + if (disallowed_chars) { + *disallowed_chars = config[i].disallowed_chars; + } } break; case config_glob: @@ -113,12 +124,15 @@ defaults_get_map_config(const char *mapname, if (filter) { *filter = config[i].filter; } - if (key_format) { - *key_format = config[i].key_format; + if (key_formats) { + *key_formats = (const char **) config[i].key_formats; } if (value_format) { *value_format = config[i].value_format; } + if (disallowed_chars) { + *disallowed_chars = config[i].disallowed_chars; + } } break; } diff --git a/src/defaults.h b/src/defaults.h index 486b9e5..7b93398 100644 --- a/src/defaults.h +++ b/src/defaults.h @@ -24,6 +24,7 @@ void defaults_get_map_config(const char *mapname, bool_t *secure, const char **filter, - const char **key_format, - const char **value_format); + const char ***key_formats, + const char **value_format, + const char **disallowed_chars); #endif diff --git a/src/dummymap.c b/src/dummymap.c index ffb4ef7..f99ea6d 100644 --- a/src/dummymap.c +++ b/src/dummymap.c @@ -219,13 +219,16 @@ map_match(struct plugin_state *state, bool_t map_match_id(struct plugin_state *state, const char *domain, const char *map, bool_t *secure, - const char *in_id, + const char *in_id, unsigned int in_index, unsigned int *key_len, char **key, unsigned int *value_len, char **value, const char **id) { struct entry *entries; int i; + if (in_index != 0) { + return FALSE; + } if ((entries = map_find_entries(domain, map)) == NULL) { return FALSE; } @@ -251,7 +254,7 @@ map_first(struct plugin_state *state, const char *domain, const char *map, bool_t *secure, unsigned int *first_key_len, char **first_key, unsigned int *first_value_len, char **first_value, - const char **first_id) + const char **first_id, int *first_id_index) { struct entry *entries; if ((entries = map_find_entries(domain, map)) == NULL) { @@ -266,6 +269,7 @@ map_first(struct plugin_state *state, *first_value = entries[0].value; *first_value_len = strlen(entries[0].value); *first_id = entries[0].id; + *first_id_index = 0; return TRUE; } @@ -274,8 +278,7 @@ map_next(struct plugin_state *state, const char *domain, const char *map, bool_t *secure, unsigned int prev_len, const char *prev, unsigned int *next_key_len, char **next_key, - unsigned int *next_value_len, char **next_value, - const char **next_id) + unsigned int *next_value_len, char **next_value) { struct entry *entries; int i; @@ -299,17 +302,16 @@ map_next(struct plugin_state *state, *next_key_len = strlen(entries[i + 1].key); *next_value = entries[i + 1].value; *next_value_len = strlen(entries[i + 1].value); - *next_id = entries[i + 1].id; return TRUE; } bool_t map_next_id(struct plugin_state *state, const char *domain, const char *map, bool_t *secure, - const char *prev_id, + const char *prev_id, int prev_id_index, unsigned int *next_key_len, char **next_key, unsigned int *next_value_len, char **next_value, - const char **next_id) + const char **next_id, int *next_id_index) { struct entry *entries; int i; @@ -333,5 +335,6 @@ map_next_id(struct plugin_state *state, *next_value = entries[i + 1].value; *next_value_len = strlen(entries[i + 1].value); *next_id = entries[i + 1].id; + *next_id_index = 0; return TRUE; } diff --git a/src/format.c b/src/format.c index 49020fc..27f0364 100644 --- a/src/format.c +++ b/src/format.c @@ -50,7 +50,8 @@ #define MAX_BUFFER_SIZE 0x100000 static int format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, - const char *domain, const char *map, const char *fmt, + const char *domain, const char *map, + const char *fmt, const char *disallowed, char *outbuf, int outbuf_len, char ***ref_attrs, struct format_inref_attr ***inref_attrs, @@ -285,7 +286,8 @@ format_parse_args(struct plugin_state *state, const char *args, static int format_echo(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, const char *domain, const char *map, - const char *args, char *outbuf, int outbuf_len, + const char *args, const char *disallowed, + char *outbuf, int outbuf_len, char ***ref_attrs, struct format_inref_attr ***inref_attrs) { int ret, i, argc, len; @@ -325,7 +327,8 @@ format_echo(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, static int format_list(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, const char *domain, const char *map, - const char *args, char *outbuf, int outbuf_len, + const char *args, const char *disallowed, + char *outbuf, int outbuf_len, char ***ref_attrs, struct format_inref_attr ***inref_attrs) { int ret, i, j, len, slen, count, argc; @@ -404,7 +407,8 @@ format_list(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, static int format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, const char *domain, const char *map, - const char *args, char *outbuf, int outbuf_len, + const char *args, const char *disallowed, + char *outbuf, int outbuf_len, char ***ref_attrs, struct format_inref_attr ***inref_attrs) { int i, j, len, slen, ret, count, argc; @@ -629,7 +633,8 @@ format_referred_entry_cb(Slapi_Entry *e, void *callback_data) static int format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, const char *domain, const char *map, - const char *args, char *outbuf, int outbuf_len, + const char *args, const char *disallowed, + char *outbuf, int outbuf_len, char ***ref_attrs, struct format_inref_attr ***inref_attrs) { int i, j, len, slen, ret, count, argc; @@ -757,7 +762,8 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, static int format_merge(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, const char *domain, const char *map, - const char *args, char *outbuf, int outbuf_len, + const char *args, const char *disallowed, + char *outbuf, int outbuf_len, char ***ref_attrs, struct format_inref_attr ***inref_attrs) { int ret, i, argc, len, slen, count; @@ -779,7 +785,8 @@ format_merge(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, /* Expand this argument. */ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "merge: expanding ->%s<-\n", argv[i]); - len = format_expand(state, pb, e, domain, map, argv[i], + len = format_expand(state, pb, e, domain, map, + argv[i], disallowed, outbuf + ret + (count ? slen : 0), outbuf_len - (ret + (count ? slen : 0)), ref_attrs, inref_attrs, FALSE); @@ -885,6 +892,7 @@ format_match_generic(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, const char *domain, const char *map, const char *args, int min_args, int default_arg, + const char *disallowed, char *outbuf, int outbuf_len, char ***ref_attrs, struct format_inref_attr ***inref_attrs, @@ -1035,10 +1043,12 @@ static int format_match(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, const char *domain, const char *map, - const char *args, char *outbuf, int outbuf_len, + const char *args, const char *disallowed, + char *outbuf, int outbuf_len, char ***ref_attrs, struct format_inref_attr ***inref_attrs) { return format_match_generic(state, pb, e, domain, map, args, 2, 2, + disallowed, outbuf, outbuf_len, ref_attrs, inref_attrs, "format_match", format_match_cb); } @@ -1062,10 +1072,12 @@ static int format_regmatch(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, const char *domain, const char *map, - const char *args, char *outbuf, int outbuf_len, + const char *args, const char *disallowed, + char *outbuf, int outbuf_len, char ***ref_attrs, struct format_inref_attr ***inref_attrs) { return format_match_generic(state, pb, e, domain, map, args, 2, 2, + disallowed, outbuf, outbuf_len, ref_attrs, inref_attrs, "format_regmatch", format_regmatch_cb); } @@ -1182,10 +1194,12 @@ static int format_regsub(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, const char *domain, const char *map, - const char *args, char *outbuf, int outbuf_len, + const char *args, const char *disallowed, + char *outbuf, int outbuf_len, char ***ref_attrs, struct format_inref_attr ***inref_attrs) { return format_match_generic(state, pb, e, domain, map, args, 3, 3, + disallowed, outbuf, outbuf_len, ref_attrs, inref_attrs, "format_regsub", format_regsub_cb); } @@ -1200,7 +1214,7 @@ format_lookup_fn(const char *fnname) int (*fct_ptr)(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, const char *domain, const char *map, - const char *args, + const char *args, const char *disallowed, char *outbuf, int outbuf_len, char ***ref_attrs, struct format_inref_attr ***inref_attrs); @@ -1229,12 +1243,12 @@ format_lookup_fn(const char *fnname) * than one, fail. */ static char * format_single(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, - const char *attr) + const char *attr, const char *disallowed) { Slapi_ValueSet *value_set; Slapi_Value *value; char *ret, *actual_attr; - const char *cret; + const char *cret, *d; int count, disposition, buffer_flags; if (slapi_vattr_values_get(e, (char *) attr, &value_set, &disposition, &actual_attr, @@ -1247,7 +1261,17 @@ format_single(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, if (slapi_valueset_first_value(value_set, &value) == 0) { cret = slapi_value_get_string(value); if (cret != NULL) { - ret = strdup(cret); + if ((disallowed != NULL) && + ((d = strpbrk(cret, disallowed)) != NULL)) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "value for \"%s\" " + "contains disallowed " + "character %c\n", + attr, *d); + } else { + ret = strdup(cret); + } } } } else { @@ -1493,7 +1517,8 @@ static int format_expand_simple(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, const char *domain, const char *map, - const char *fmt, char *outbuf, int outbuf_len, + const char *fmt, const char *disallowed, + char *outbuf, int outbuf_len, char ***ref_attrs, struct format_inref_attr ***inref_attrs) { char *shortstart, *longstart, *shortend, *longend; @@ -1588,14 +1613,14 @@ format_expand_simple(struct plugin_state *state, } } /* Retrieve the value. */ - tmp = format_single(state, pb, e, attribute); + tmp = format_single(state, pb, e, attribute, disallowed); if (tmp == NULL) { /* The attribute is undefined, or we're treating it as if it * is. */ if (default_value != NULL) { /* Supply the default value, expanding it if needed. */ i = format_expand(state, pb, e, - domain, map, default_value, + domain, map, default_value, NULL, outbuf, outbuf_len, ref_attrs, inref_attrs, FALSE); free(expr); @@ -1611,7 +1636,7 @@ format_expand_simple(struct plugin_state *state, if (alternate_value != NULL) { /* Supply the alternate value. */ i = format_expand(state, pb, e, - domain, map, alternate_value, + domain, map, alternate_value, NULL, outbuf, outbuf_len, ref_attrs, inref_attrs, FALSE); free(tmp); @@ -1649,7 +1674,8 @@ format_expand_simple(struct plugin_state *state, * evaluate it, otherwise return it. */ static int format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, - const char *domain, const char *map, const char *fmt, + const char *domain, const char *map, + const char *fmt, const char *disallowed, char *outbuf, int outbuf_len, char ***ref_attrs, struct format_inref_attr ***inref_attrs, bool_t is_simple_expression) @@ -1665,7 +1691,8 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, size_t spn; int (*formatfn)(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, - const char *domain, const char *map, const char *args, + const char *domain, const char *map, + const char *args, const char *disallowed, char *outbuf, int outbuf_len, char ***ref_attrs, struct format_inref_attr ***inref_attrs); @@ -1731,6 +1758,7 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, domain, map, tmp, + disallowed, expr + j, exp_size - j, ref_attrs, @@ -1838,7 +1866,8 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, } /* Call the "function". */ exp_used = (*formatfn)(state, pb, e, - domain, map, tmp, + domain, map, + tmp, disallowed, expr + j, exp_size - j, ref_attrs, inref_attrs); free(tmp); @@ -1883,7 +1912,8 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, if (is_simple_expression) { exp_used = format_expand_simple(state, pb, e, domain, map, - expr, outbuf, outbuf_len, + expr, disallowed, + outbuf, outbuf_len, ref_attrs, inref_attrs); if (exp_used < 0) { free(expr); @@ -1907,7 +1937,7 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, static char * format_format(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, const char *domain, const char *map, - const char *fmt, + const char *fmt, const char *disallowed, char ***ref_attrs, struct format_inref_attr ***inref_attrs) { char *buf, *tmp, *ret, *spd_id; @@ -1928,8 +1958,8 @@ format_format(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, return NULL; } - i = format_expand(state, pb, e, domain, map, fmt, buf, buflen, - ref_attrs, inref_attrs, FALSE); + i = format_expand(state, pb, e, domain, map, fmt, disallowed, + buf, buflen, ref_attrs, inref_attrs, FALSE); if ((i >= 0) && (i < buflen)) { buf[i] = '\0'; ret = strdup(buf); @@ -1975,7 +2005,7 @@ format_format(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, char * format_get_data(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, const char *domain, const char *map, - const char *fmt, + const char *fmt, const char *disallowed, char ***ref_attrs, struct format_inref_attr ***inref_attrs) { @@ -1990,7 +2020,7 @@ format_get_data(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, local_pb = NULL; } - ret = format_format(state, pb, e, domain, map, fmt, + ret = format_format(state, pb, e, domain, map, fmt, disallowed, ref_attrs, inref_attrs); /* If we supplied a PBlock, clean it up. */ diff --git a/src/format.h b/src/format.h index 7bc4775..5728ff2 100644 --- a/src/format.h +++ b/src/format.h @@ -39,7 +39,7 @@ void format_free_data(char *data); char *format_get_data(struct plugin_state *state, struct slapi_pblock *pb, struct slapi_entry *e, const char *domain, const char *map, - const char *fmt, + const char *fmt, const char *disallowed_chars, char ***ref_attrs, struct format_inref_attr ***inref_attrs); @@ -64,14 +64,18 @@ struct { /* The name of the backend entry for this * entry. */ char *id; - /* Key and value. */ - char *key; - unsigned int key_len; + /* Keys and value. */ + unsigned int n_keys; + char **keys; + unsigned int *key_len; char *value; unsigned int value_len; + /* Key index for comparison. Used by the + * key_trees. */ + int key_index; } *entries; /* Search trees to speed up searches for entries. */ - void *key_tree; + void **key_trees; void *id_tree; /* Callback data supplied by the map writer. */ void *backend_data; @@ -105,23 +109,33 @@ t_compare_entry_by_id(const void *p1, const void *p2) return strcmp(e1->id, e2->id); } static int -t_compare_entry_by_key(const void *p1, const void *p2) +t_compare_entry_by_nth_key(const void *p1, const void *p2) { const struct map_entry *e1, *e2; unsigned int key_len; - int eq; + int eq, i; e1 = p1; e2 = p2; - if (e1->key_len == e2->key_len) { - return memcmp(e1->key, e2->key, e1->key_len); + /* Figure out which key index to use for comparison by pulling it out + * of the template (whichever one that is) -- real entries have + * key_index set to -1. */ + if (e1->key_index >= 0) { + i = e1->key_index; } else { - key_len = (e1->key_len < e2->key_len) ? - e1->key_len : e2->key_len; - eq = memcmp(e1->key, e2->key, key_len); + i = e2->key_index; + } + /* Same length -> straight comparison. */ + if (e1->key_len[i] == e2->key_len[i]) { + return memcmp(e1->keys[i], e2->keys[i], e1->key_len[i]); + } else { + /* Compare the common length. */ + key_len = (e1->key_len[i] < e2->key_len[i]) ? + e1->key_len[i] : e2->key_len[i]; + eq = memcmp(e1->keys[i], e2->keys[i], key_len); if (eq != 0) { return eq; } else { - return (e1->key_len < e2->key_len) ? -1 : 1; + return (e1->key_len[i] < e2->key_len[i]) ? -1 : 1; } } } @@ -166,13 +180,21 @@ map_data_find_map_entry(struct plugin_state *state, { struct map_entry **entry, entry_template; void **p; - if (map == NULL) { + unsigned int i; + if ((map == NULL) || (map->entries == NULL)) { return NULL; } - entry_template.key = (char *) key; - entry_template.key_len = key_len; - entry = tfind(&entry_template, &map->key_tree, t_compare_entry_by_key); - return entry ? *entry : NULL; + for (i = 0; i < map->entries->n_keys; i++) { + entry_template.keys = ((char **) &key) - i; + entry_template.key_len = (&key_len) - i; + entry_template.key_index = i; + entry = tfind(&entry_template, &map->key_trees[i], + t_compare_entry_by_nth_key); + if (entry != NULL) { + return *entry; + } + } + return NULL; } static struct map_entry * @@ -209,10 +231,12 @@ map_data_foreach_entry(struct plugin_state *state, bool_t secure, const char *key, unsigned int key_len, const char *value, unsigned int value_len, - const char *id, void *cbdata), + const char *id, int key_index, + void *cbdata), void *cbdata) { int i, j; + unsigned int k; struct domain *domain; struct map *map; struct map_entry *entry; @@ -226,14 +250,18 @@ map_data_foreach_entry(struct plugin_state *state, if (all || ((id != NULL) && (strcmp(id, entry->id) == 0))) { - if (!(*fn)(domain->name, map->name, - map->secure, - entry->key, - entry->key_len, - entry->value, - entry->value_len, - entry->id, cbdata)) { - return FALSE; + for (k = 0; k < entry->n_keys; k++) { + if (!(*fn)(domain->name, + map->name, + map->secure, + entry->keys[k], + entry->key_len[k], + entry->value, + entry->value_len, + entry->id, k, + cbdata)) { + return FALSE; + } } } } @@ -251,7 +279,8 @@ map_data_foreach_entry_id(struct plugin_state *state, const char *id, unsigned int key_len, const char *value, unsigned int value_len, - const char *id, void *cbdata), + const char *id, int key_index, + void *cbdata), void *cbdata) { return map_data_foreach_entry(state, FALSE, id, fn, cbdata); @@ -391,7 +420,7 @@ bool_t map_match_id(struct plugin_state *state, const char *domain_name, const char *map_name, bool_t *secure, - const char *in_id, + const char *in_id, unsigned int in_key_index, unsigned int *key_len, char **key, unsigned int *value_len, char **value, const char **id) @@ -406,9 +435,15 @@ map_match_id(struct plugin_state *state, if (entry == NULL) { return FALSE; } + if (entry->n_keys < 1) { + return FALSE; + } + if (in_key_index >= entry->n_keys) { + return FALSE; + } *secure = map->secure; - *key_len = entry->key_len; - *key = entry->key; + *key_len = entry->key_len[in_key_index]; + *key = entry->keys[in_key_index]; *value_len = entry->value_len; *value = entry->value; *id = entry->id; @@ -423,7 +458,7 @@ map_first(struct plugin_state *state, bool_t *secure, unsigned int *first_key_len, char **first_key, unsigned int *first_value_len, char **first_value, - const char **first_id) + const char **first_id, int *first_key_index) { struct map *map; struct map_entry *entry; @@ -436,11 +471,12 @@ map_first(struct plugin_state *state, return FALSE; } *secure = map->secure; - *first_key_len = entry->key_len; - *first_key = entry->key; + *first_key_len = entry->key_len[0]; + *first_key = entry->keys[0]; *first_value_len = entry->value_len; *first_value = entry->value; *first_id = entry->id; + *first_key_index = 0; return TRUE; } @@ -452,51 +488,80 @@ map_next(struct plugin_state *state, const char *domain_name, const char *map_name, bool_t *secure, unsigned int prev_len, const char *prev, unsigned int *next_key_len, char **next_key, - unsigned int *next_value_len, char **next_value, - const char **next_id) + unsigned int *next_value_len, char **next_value) { struct map *map; struct map_entry *entry; + unsigned int i; map = map_data_find_map(state, domain_name, map_name); if (map == NULL) { return FALSE; } entry = map_data_find_map_entry(state, map, prev_len, prev); - if ((entry == NULL) || (entry->next == NULL)) { + if (entry == NULL) { return FALSE; } *secure = map->secure; - *next_key_len = entry->next->key_len; - *next_key = entry->next->key; - *next_value_len = entry->next->value_len; - *next_value = entry->next->value; - *next_id = entry->next->id; + for (i = 0; i < entry->n_keys; i++) { + if ((prev_len == entry->key_len[i]) && + (memcmp(prev, entry->keys[i], prev_len) == 0)) { + break; + } + } + if (i + 1 < entry->n_keys) { + *next_key_len = entry->key_len[i + 1]; + *next_key = entry->keys[i + 1]; + *next_value_len = entry->value_len; + *next_value = entry->value; + } else { + if (entry->next == NULL) { + return FALSE; + } + *next_key_len = entry->next->key_len[0]; + *next_key = entry->next->keys[0]; + *next_value_len = entry->next->value_len; + *next_value = entry->next->value; + } return TRUE; } bool_t map_next_id(struct plugin_state *state, const char *domain_name, const char *map_name, bool_t *secure, - const char *prev_id, + const char *prev_id, int prev_key_index, unsigned int *next_key_len, char **next_key, unsigned int *next_value_len, char **next_value, - const char **next_id) + const char **next_id, int *next_key_index) { struct map *map; struct map_entry *entry; + unsigned int key_index; map = map_data_find_map(state, domain_name, map_name); if (map == NULL) { return FALSE; } entry = map_data_find_map_entry_id(state, map, prev_id); - if ((entry == NULL) || (entry->next == NULL)) { + if (entry == NULL) { return FALSE; } *secure = map->secure; - *next_key_len = entry->next->key_len; - *next_key = entry->next->key; - *next_value_len = entry->next->value_len; - *next_value = entry->next->value; - *next_id = entry->next->id; + if (prev_key_index + 1 < (int) entry->n_keys) { + *next_key_len = entry->key_len[prev_key_index + 1]; + *next_key = entry->keys[prev_key_index + 1]; + *next_value_len = entry->value_len; + *next_value = entry->value; + *next_id = entry->id; + *next_key_index = prev_key_index + 1; + } else { + if (entry->next == NULL) { + return FALSE; + } + *next_key_len = entry->next->key_len[0]; + *next_key = entry->next->keys[0]; + *next_value_len = entry->next->value_len; + *next_value = entry->next->value; + *next_id = entry->next->id; + *next_key_index = 0; + } return TRUE; } @@ -518,21 +583,31 @@ static void map_data_clear_map_map(struct plugin_state *state, struct map *map) { struct map_entry *entry, *next; + unsigned int i; /* Clear the entries list. */ if (map != NULL) { for (entry = map->entries; entry != NULL; entry = next) { + /* Remove every key for this entry from the applicable + * key trees, and then the ID tree. */ + for (i = 0; i < entry->n_keys; i++) { + entry->key_index = i; + tdelete(entry, &map->key_trees[i], + t_compare_entry_by_nth_key); + entry->key_index = -1; + } tdelete(entry, &map->id_tree, t_compare_entry_by_id); - tdelete(entry, &map->key_tree, t_compare_entry_by_key); next = entry->next; free(entry->id); entry->key_len = 0; - free(entry->key); + for (i = 0; i < entry->n_keys; i++) { + free(entry->keys[i]); + } + free(entry->keys); entry->value_len = 0; free(entry->value); free(entry); } map->entries = NULL; - map->key_tree = NULL; map->id_tree = NULL; } } @@ -610,6 +685,7 @@ void map_data_set_map(struct plugin_state *state, const char *domain_name, const char *map_name, + unsigned int n_keys, bool_t secure, void *backend_data, void (*free_backend_data)(void *backend_data)) @@ -666,13 +742,18 @@ map_data_set_map(struct plugin_state *state, map = &maps[domain->n_maps]; memset(map, 0, sizeof(*map)); map->name = strdup(map_name); + map->key_trees = malloc(n_keys * sizeof(void *)); map->secure = secure; map->backend_data = backend_data; map->free_backend_data = free_backend_data; - if (map->name != NULL) { + map->last_changed = time(NULL); + if ((map->name != NULL) && (map->key_trees != NULL)) { /* Copy in existing data. */ memcpy(maps, domain->maps, sizeof(*map) * domain->n_maps); + /* Clear the key tree set. */ + memset(map->key_trees, 0, + n_keys * sizeof(void *)); /* Switcheroo. */ free(domain->maps); domain->maps = maps; @@ -692,6 +773,7 @@ map_data_set_map(struct plugin_state *state, } map->backend_data = backend_data; map->free_backend_data = free_backend_data; + map->last_changed = time(NULL); } } @@ -702,6 +784,7 @@ map_data_unset_map_entry(struct plugin_state *state, struct map_entry *entry) { struct map_entry *prev, *next; + unsigned int i; if ((map != NULL) && (entry != NULL)) { prev = entry->prev; next = entry->next; @@ -714,31 +797,27 @@ map_data_unset_map_entry(struct plugin_state *state, if (map->entries == entry) { map->entries = next; } - tdelete(entry, &map->key_tree, t_compare_entry_by_key); + /* Remove every key for this entry from the applicable key + * trees, and then the ID tree. */ + for (i = 0; i < entry->n_keys; i++) { + entry->key_index = i; + tdelete(entry, &map->key_trees[i], + t_compare_entry_by_nth_key); + entry->key_index = -1; + } tdelete(entry, &map->id_tree, t_compare_entry_by_id); free(entry->id); - free(entry->key); + /* Free the keys list. */ + for (i = 0; i < entry->n_keys; i++) { + free(entry->keys[i]); + } + free(entry->keys); + /* The value and the key itself. */ free(entry->value); free(entry); } } -/* Remove the entry from the map which matches the passed-in key. */ -void -map_data_unset_entry_key(struct plugin_state *state, - const char *domain_name, - const char *map_name, - unsigned int key_len, - const char *key) -{ - struct map *map; - struct map_entry *entry; - map = map_data_find_map(state, domain_name, map_name); - entry = map_data_find_map_entry(state, map, key_len, key); - map_data_unset_map_entry(state, map, entry); - map->last_changed = time(NULL); -} - /* Remove the entry from the map which matches the passed-in ID. */ void map_data_unset_entry_id(struct plugin_state *state, @@ -760,17 +839,16 @@ map_data_set_entry(struct plugin_state *state, const char *domain_name, const char *map_name, const char *id, - unsigned int key_len, - char *key, + unsigned int n_keys, + unsigned int *key_lens, + char **keys, unsigned int value_len, char *value) { struct map *map; struct map_entry *entry; + unsigned int i, key_len; map = map_data_find_map(state, domain_name, map_name); - if (key_len == (unsigned int) -1) { - key_len = strlen(key); - } if (value_len == (unsigned int) -1) { value_len = strlen(value); } @@ -778,26 +856,81 @@ map_data_set_entry(struct plugin_state *state, entry = map_data_find_map_entry_id(state, map, id); if (entry != NULL) { /* There's already an entry with this ID, so let's - * replace its key and value. */ - tdelete(entry, &map->key_tree, t_compare_entry_by_key); + * replace its keys and value. */ + for (i = 0; i < entry->n_keys; i++) { + entry->key_index = i; + tdelete(entry, &map->key_trees[i], + t_compare_entry_by_nth_key); + entry->key_index = -1; + } tdelete(entry, &map->id_tree, t_compare_entry_by_id); - free(entry->key); - entry->key = xmemdup(key, key_len); - entry->key_len = key_len; + /* Free the keys. */ + for (i = 0; i < entry->n_keys; i++) { + free(entry->keys[i]); + } + free(entry->keys); + /* Create a new keys list. */ + entry->keys = malloc((n_keys + 1) * sizeof(char *)); + if (entry->keys != NULL) { + for (i = 0; i < n_keys; i++) { + if (key_lens != NULL) { + key_len = key_lens[i]; + } else { + key_len = -1; + } + if (key_len == (unsigned int) -1) { + key_len = strlen(keys[i]); + } + entry->keys[i] = xmemdup(keys[i], + key_len); + entry->key_len[i] = key_len; + } + entry->keys[i] = NULL; + } + entry->n_keys = n_keys; + /* Replace the value and ID. */ free(entry->value); + free(entry->id); entry->value = xmemdup(value, value_len); entry->value_len = value_len; - free(entry->id); entry->id = strdup(id); - tsearch(entry, &map->key_tree, t_compare_entry_by_key); + /* Add the ID to the tree and all of the keys to their + * trees. */ tsearch(entry, &map->id_tree, t_compare_entry_by_id); + for (i = 0; i < n_keys; i++) { + entry->key_index = i; + tsearch(entry, &map->key_trees[i], + t_compare_entry_by_nth_key); + entry->key_index = -1; + } } else { /* There's no entry with this ID, so create one. */ entry = malloc(sizeof(*entry)); if (entry != NULL) { memset(entry, 0, sizeof(*entry)); - entry->key = xmemdup(key, key_len); - entry->key_len = key_len; + entry->keys = malloc((n_keys + 1) * + sizeof(char *)); + entry->key_len = malloc(n_keys * sizeof(int)); + if ((entry->keys != NULL) && + (entry->key_len != NULL)) { + for (i = 0; i < n_keys; i++) { + if (key_lens != NULL) { + key_len = key_lens[i]; + } else { + key_len = -1; + } + if (key_len == (unsigned int) -1) { + key_len = + strlen(keys[i]); + } + entry->keys[i] = xmemdup(keys[i], + key_len); + entry->key_len[i] = key_len; + } + entry->keys[i] = NULL; + } + entry->n_keys = n_keys; + entry->key_index = -1; entry->value = xmemdup(value, value_len); entry->value_len = value_len; entry->id = strdup(id); @@ -806,8 +939,12 @@ map_data_set_entry(struct plugin_state *state, map->entries->prev = entry; } map->entries = entry; - tsearch(entry, &map->key_tree, - t_compare_entry_by_key); + for (i = 0; i < entry->n_keys; i++) { + entry->key_index = i; + tsearch(entry, &map->key_trees[i], + t_compare_entry_by_nth_key); + entry->key_index = -1; + } tsearch(entry, &map->id_tree, t_compare_entry_by_id); } else { @@ -41,7 +41,7 @@ bool_t map_match(struct plugin_state *state, unsigned int *value_len, char **value, const char **id); bool_t map_match_id(struct plugin_state *state, const char *domain, const char *map, bool_t *secure, - const char *id_in, + const char *id_in, unsigned int id_index, unsigned int *key_len, char **key, unsigned int *value_len, char **value, const char **id); @@ -49,19 +49,18 @@ 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, unsigned int *first_value_len, char **first_value, - const char **id); + const char **first_id, int *first_key_index); bool_t map_next(struct plugin_state *state, const char *domain, const char *map, bool_t *secure, unsigned int prev_len, const char *prev, unsigned int *next_key_len, char **next_key, - unsigned int *next_value_len, char **next_value, - const char **next_id); + unsigned int *next_value_len, char **next_value); bool_t map_next_id(struct plugin_state *state, const char *domain, const char *map, bool_t *secure, - const char *prev_id, + const char *prev_id, int prev_index, unsigned int *next_key_len, char **next_key, unsigned int *next_value_len, char **next_value, - const char **next_id); + const char **next_id, int *next_key_index); bool_t map_order(struct plugin_state *state, const char *domain, const char *map, bool_t *map_secure, unsigned int *order); @@ -72,18 +71,16 @@ void map_data_unset_map(struct plugin_state *state, const char *domain_name, const char *map_name); void map_data_set_map(struct plugin_state *state, const char *domain_name, const char *map_name, - bool_t secure, + unsigned int n_keys, bool_t secure, void *backend_data, void (*free_backend_data)(void *p)); -void map_data_unset_entry_key(struct plugin_state *state, - const char *domain_name, const char *map_name, - unsigned int key_len, const char *key); void map_data_unset_entry_id(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, - unsigned int key_len, char *key, + unsigned int n_keys, + unsigned int *key_len, char **keys, unsigned int value_len, char *value); bool_t map_data_check_entry(struct plugin_state *state, const char *domain_name, const char *map_name, @@ -96,7 +93,8 @@ bool_t map_data_foreach_entry_id(struct plugin_state *state, const char *id, unsigned int key_len, const char *value, unsigned int value_len, - const char *id, void *cbdata), + const char *id, int key_index, + void *cbdata), void *cbdata); bool_t map_data_foreach_map(struct plugin_state *state, const char *domain_name, bool_t (*fn)(const char *domain, @@ -143,6 +143,7 @@ nis_first(struct plugin_state *state, struct ypreq_nokey req_nokey; bool_t map_supported, map_secure; const char *entry_id; + int entry_key_index; memset(&req_nokey, 0, sizeof(req_nokey)); memset(reply_key_val, 0, sizeof(*reply_key_val)); @@ -154,7 +155,7 @@ nis_first(struct plugin_state *state, &reply_key_val->keydat.keydat_val, &reply_key_val->valdat.valdat_len, &reply_key_val->valdat.valdat_val, - &entry_id) && + &entry_id, &entry_key_index) && (map_secure ? client_secure : TRUE)) { reply_key_val->status = YP_TRUE; slapi_log_error(SLAPI_LOG_PLUGIN, @@ -199,17 +200,16 @@ nis_next(struct plugin_state *state, &reply_key_val->keydat.keydat_len, &reply_key_val->keydat.keydat_val, &reply_key_val->valdat.valdat_len, - &reply_key_val->valdat.valdat_val, - &entry_id) && + &reply_key_val->valdat.valdat_val) && (map_secure ? client_secure : TRUE)) { reply_key_val->status = YP_TRUE; slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "next(%.*s/%s/%s) -> %d\n", - req_key.keydat.keydat_len, - req_key.keydat.keydat_val, + "next(%s/%s/%.*s) -> %d\n", req_key.domain, req_key.map, + req_key.keydat.keydat_len, + req_key.keydat.keydat_val, reply_key_val->status); } else { if (map_match(state, req_key.domain, req_key.map, @@ -228,11 +228,11 @@ nis_next(struct plugin_state *state, } slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "next(%.*s/%s/%s) -> no more!\n", - req_key.keydat.keydat_len, - req_key.keydat.keydat_val, + "next(%s/%s/%.*s) -> no more!\n", req_key.domain, - req_key.map); + req_key.map, + req_key.keydat.keydat_len, + req_key.keydat.keydat_val); } (*reply_fn)(state, cdata, reply, reply_xdrs); map_unlock(); @@ -404,6 +404,7 @@ struct nis_all_cookie { cookie_end2, } state; unsigned int id_length; + int key_index; char id[1]; }; static void @@ -412,7 +413,8 @@ nis_all_free_cookie(struct nis_all_cookie *cookie) free(cookie); } static struct nis_all_cookie * -nis_all_make_cookie(enum nis_all_cookie_state state, const char *id) +nis_all_make_cookie(enum nis_all_cookie_state state, + const char *id, int key_index) { struct nis_all_cookie *cookie; int length; @@ -420,6 +422,9 @@ nis_all_make_cookie(enum nis_all_cookie_state state, const char *id) cookie = malloc(sizeof(*cookie) + length + 1); if (cookie != NULL) { cookie->state = state; + memset(cookie->id, '\0', sizeof(cookie->id)); + cookie->id_length = 0; + cookie->key_index = 0; switch (cookie->state) { case cookie_bad: case cookie_first: @@ -430,6 +435,7 @@ nis_all_make_cookie(enum nis_all_cookie_state state, const char *id) case cookie_this: case cookie_next: cookie->id_length = length; + cookie->key_index = key_index; if (length > 0) { memcpy(&cookie->id, id, cookie->id_length); cookie->id[length] = '\0'; @@ -458,6 +464,7 @@ nis_all(struct plugin_state *state, enum nis_all_cookie_state next_state; bool_t map_supported, map_secure, stop; const char *entry_id; + int entry_key_index; memset(&req_nokey, 0, sizeof(req_nokey)); reply_key = &reply_all->ypresp_all_u.val.keydat; @@ -468,11 +475,12 @@ nis_all(struct plugin_state *state, if (*continuation_cookie != NULL) { cookie = *continuation_cookie; } else { - cookie = nis_all_make_cookie(cookie_bad, NULL); + cookie = nis_all_make_cookie(cookie_bad, + NULL, 0); } *continuation_cookie = NULL; } else { - cookie = nis_all_make_cookie(cookie_bad, NULL); + cookie = nis_all_make_cookie(cookie_bad, NULL, 0); } /* Check if we even support the map. */ map_rdlock(); @@ -526,7 +534,8 @@ nis_all(struct plugin_state *state, &reply_key->keydat_val, &reply_val->valdat_len, &reply_val->valdat_val, - &entry_id) && + &entry_id, + &entry_key_index) && (map_secure ? client_secure : TRUE); if (found) { /* Next time grab the entry after this @@ -564,12 +573,13 @@ nis_all(struct plugin_state *state, * entry or send end0 or end1, * whichever is appropriate. */ cookie = nis_all_make_cookie(next_state, - entry_id); + entry_id, + entry_key_index); } else { /* Leave a note to try sending the * first entry again. */ cookie = nis_all_make_cookie(cookie_first, - NULL); + NULL, 0); stop = TRUE; } break; @@ -582,11 +592,13 @@ nis_all(struct plugin_state *state, req_nokey.map, &map_secure, cookie->id, + cookie->key_index, &reply_key->keydat_len, &reply_key->keydat_val, &reply_val->valdat_len, &reply_val->valdat_val, - &entry_id) && + &entry_id, + &entry_key_index) && (map_secure ? client_secure : TRUE); if (found) { slapi_log_error(SLAPI_LOG_PLUGIN, @@ -625,13 +637,15 @@ nis_all(struct plugin_state *state, * appropriate. */ nis_all_free_cookie(cookie); cookie = nis_all_make_cookie(next_state, - entry_id); + entry_id, + entry_key_index); } else { /* Leave a note to retry sending this * entry the next time. */ nis_all_free_cookie(cookie); cookie = nis_all_make_cookie(cookie_this, - entry_id); + entry_id, + entry_key_index); stop = TRUE; } break; @@ -644,22 +658,25 @@ nis_all(struct plugin_state *state, req_nokey.map, &map_secure, cookie->id, + cookie->key_index, &reply_key->keydat_len, &reply_key->keydat_val, &reply_val->valdat_len, &reply_val->valdat_val, &entry_id) && (map_secure ? client_secure : TRUE); + entry_key_index = cookie->key_index; if (found) { /* Next time grab the entry after this * one. */ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "all(%s/%s) \"%s\" " + "all(%s/%s) \"%s\":%d " "(retry)\n", req_nokey.domain, req_nokey.map, - cookie->id); + cookie->id, + cookie->key_index); skip = FALSE; reply_all->more = TRUE; reply_all->ypresp_all_u.val.status = YP_TRUE; @@ -669,11 +686,12 @@ nis_all(struct plugin_state *state, * state. */ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "all(%s/%s) \"%s\" " + "all(%s/%s) \"%s\":%d " "(disappeared?)\n", req_nokey.domain, req_nokey.map, - cookie->id); + cookie->id, + cookie->key_index); skip = TRUE; next_state = cookie_end1; } @@ -692,7 +710,8 @@ nis_all(struct plugin_state *state, * stuck. */ nis_all_free_cookie(cookie); cookie = nis_all_make_cookie(next_state, - entry_id); + entry_id, + entry_key_index); break; case cookie_end0: /* Send the end-of-map message as the first @@ -713,7 +732,7 @@ nis_all(struct plugin_state *state, /* Leave a note to finish the reply. */ nis_all_free_cookie(cookie); cookie = nis_all_make_cookie(cookie_end2, - NULL); + NULL, 0); } else { /* Leave the note alone, so that we'll * have to try again. */ @@ -740,7 +759,7 @@ nis_all(struct plugin_state *state, /* Leave a note to finish the reply. */ nis_all_free_cookie(cookie); cookie = nis_all_make_cookie(cookie_end2, - NULL); + NULL, 0); } else { /* Leave the note alone, so that we'll * have to try again. */ |