diff options
| author | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-05-16 18:35:28 -0400 |
|---|---|---|
| committer | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-05-16 18:35:28 -0400 |
| commit | 82ec8e499f87136252e4e9361dcf8ea2c14c6294 (patch) | |
| tree | 0f7dce5718c15231eedde81cf5c4324018a0c56d /src | |
| parent | 8ab5f4b2f802331090068ab3fb655238e561a9a8 (diff) | |
| download | slapi-nis-82ec8e499f87136252e4e9361dcf8ea2c14c6294.tar.gz slapi-nis-82ec8e499f87136252e4e9361dcf8ea2c14c6294.tar.xz slapi-nis-82ec8e499f87136252e4e9361dcf8ea2c14c6294.zip | |
- add a table of defaults
- add a "match" format function ("regmatch" is still needed)
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile | 2 | ||||
| -rw-r--r-- | src/backend.c | 42 | ||||
| -rw-r--r-- | src/defaults.c | 46 | ||||
| -rw-r--r-- | src/defaults.h | 7 | ||||
| -rw-r--r-- | src/format.c | 158 |
5 files changed, 227 insertions, 28 deletions
diff --git a/src/Makefile b/src/Makefile index 6d2f1f3..39a1a05 100644 --- a/src/Makefile +++ b/src/Makefile @@ -3,7 +3,7 @@ LDFLAGS = -lnsl -lpthread all:: plugin.so dummyplugin.so portmap -plugin.so: backend.c dispatch.c map.c nis.c plugin.c portmap.c defaults.h format.c +plugin.so: backend.c dispatch.c map.c nis.c plugin.c portmap.c defaults.h format.c defaults.c $(CC) $(CFLAGS) -shared -o $@ $^ $(LDFLAGS) dummyplugin.so: dispatch.c dummymap.c nis.c plugin.c plugin.h portmap.c $(CC) $(CFLAGS) -shared -o $@ $^ $(LDFLAGS) diff --git a/src/backend.c b/src/backend.c index a004eae..8347497 100644 --- a/src/backend.c +++ b/src/backend.c @@ -286,43 +286,38 @@ backend_map_config_entry(struct plugin_state *state, Slapi_Entry *e, Slapi_PBlock *pb; char **base; int i; - char *entry_filter, *use_entry_filter, *key_attribute, *value_attribute; - char *use_key_attribute, *use_value_attribute; - char *use_attrs[3]; /* XXX */ + char *entry_filter, *use_entry_filter, *key_format, *value_format; + const char *use_key_format, *use_value_format; + const char *default_filter, *default_key_format, *default_value_format; struct backend_map_data cb_data; pb = slapi_pblock_new(); - /* Read the NIS entry search base, entry search filter, and the names - * of the key and value attributes. */ + /* Read the NIS entry search base, entry search filter, and the key and + * value formats. */ + defaults_get_map_config(map, &default_filter, + &default_key_format, &default_value_format); base = slapi_entry_attr_get_charray(e, "base"); entry_filter = slapi_entry_attr_get_charptr(e, "filter"); - key_attribute = slapi_entry_attr_get_charptr(e, "key"); - value_attribute = slapi_entry_attr_get_charptr(e, "value"); + key_format = slapi_entry_attr_get_charptr(e, "keyFormat"); + value_format = slapi_entry_attr_get_charptr(e, "valueFormat"); /* Perform substitutions on the filter, so that it can include the map * name without having to explicitly list it. We need this because * RFC2307bis actually 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_ENTRY_FILTER, + default_filter, domain, map); - /* If the key and value attributes aren't set, we'll use compiled-in + /* If the key and value formats aren't set, we'll use compiled-in * defaults. */ - use_key_attribute = key_attribute ? - key_attribute : - DEFAULT_KEY_ATTRIBUTE; - use_value_attribute = value_attribute ? - value_attribute : - DEFAULT_VALUE_ATTRIBUTE; + use_key_format = key_format ? key_format : default_key_format; + use_value_format = value_format ? value_format : default_value_format; /* Now get ready to search for entries which need to be in the map. */ - use_attrs[0] = use_key_attribute; /* XXX */ - use_attrs[1] = use_value_attribute; /* XXX */ - use_attrs[2] = NULL; /* XXX */ cb_data.state = state; cb_data.domain = (char *) domain; cb_data.map = (char *) map; - cb_data.key_fmt = use_key_attribute; - cb_data.value_fmt = use_value_attribute; + cb_data.key_fmt = strdup(use_key_format); + cb_data.value_fmt = strdup(use_value_format); cb_data.filter = use_entry_filter; cb_data.bases = base; slapi_log_error(SLAPI_LOG_PLUGIN, @@ -344,7 +339,7 @@ backend_map_config_entry(struct plugin_state *state, Slapi_Entry *e, base[i], LDAP_SCOPE_SUB, use_entry_filter, - use_attrs, 0, + NULL, 0, NULL, NULL, state->plugin_identity, @@ -356,9 +351,8 @@ backend_map_config_entry(struct plugin_state *state, Slapi_Entry *e, slapi_free_search_results_internal(pb); } /* Clean up. */ - free(use_entry_filter); - slapi_ch_free_string(&value_attribute); - slapi_ch_free_string(&key_attribute); + slapi_ch_free_string(&value_format); + slapi_ch_free_string(&key_format); slapi_ch_free_string(&entry_filter); slapi_ch_array_free(base); slapi_pblock_destroy(pb); diff --git a/src/defaults.c b/src/defaults.c new file mode 100644 index 0000000..43b229b --- /dev/null +++ b/src/defaults.c @@ -0,0 +1,46 @@ +#include <string.h> + +#define DEFAULT_ENTRY_FILTER "(&(nisMapName=%m)(objectClass=nisObject))" +#define DEFAULT_KEY_FORMAT "%{cn}" +#define DEFAULT_VALUE_FORMAT "%{nisMapEntry}" + +static struct configuration { + char *map, *filter, *key_format, *value_format; +} config[] = { + {"passwd.byname", + "(objectClass=posixAccount)", + "%{uid}", + "%{uid}:%regmatch(\"userPassword\",\"^{CRYPT}.............*\",\"*\"):%{uidNumber}:%{gidNumber}:%{gecos:-%{cn}}:%{homeDirectory:-/}:%{loginShell:-}"}, + {"passwd.bynumber", + "(objectClass=posixAccount)", + "%{uidNumber}", + "%{uid}:%regmatch(\"userPassword\",\"^{CRYPT}.............*\",\"*\"):%{uidNumber}:%{gidNumber}:%{gecos:-%{cn}}:%{homeDirectory:-/}:%{loginShell:-}"}, + {"group.byname", + "(objectClass=posixGroup)", + "%{cn}", + "%{cn}:%regmatch(\"userPassword\",\"^{CRYPT}.............*\",\"*\"):%{gidNumber}:%list(\",\",\"memberUid\")"}, + {"group.bynumber", + "(objectClass=posixGroup)", + "%{gidNumber}", + "%{cn}:%regmatch(\"userPassword\",\"^{CRYPT}.............*\",\"*\"):%{gidNumber}:%list(\",\",\"memberUid\")"}, +}; + +void +defaults_get_map_config(const char *mapname, + const char **filter, + const char **key_format, + const char **value_format) +{ + unsigned int i; + *filter = DEFAULT_ENTRY_FILTER; + *key_format = DEFAULT_KEY_FORMAT; + *value_format = DEFAULT_VALUE_FORMAT; + for (i = 0; i < sizeof(config) / sizeof(config[0]); i++) { + if (strcmp(mapname, config[i].map) == 0) { + *filter = config[i].filter; + *key_format = config[i].key_format; + *value_format = config[i].value_format; + break; + } + } +} diff --git a/src/defaults.h b/src/defaults.h index 96872ad..a4c8133 100644 --- a/src/defaults.h +++ b/src/defaults.h @@ -1,3 +1,4 @@ -#define DEFAULT_ENTRY_FILTER "(&(nisMapName=%m)(objectClass=nisObject))" -#define DEFAULT_KEY_ATTRIBUTE "%{cn}" -#define DEFAULT_VALUE_ATTRIBUTE "%{nisMapEntry}" +void defaults_get_map_config(const char *mapname, + const char **filter, + const char **key_format, + const char **value_format); diff --git a/src/format.c b/src/format.c index 42e79fb..3a96187 100644 --- a/src/format.c +++ b/src/format.c @@ -1,5 +1,6 @@ #include <sys/types.h> #include <rpcsvc/yp.h> +#include <fnmatch.h> #include <stdlib.h> #include "defaults.h" #include "format.h" @@ -414,6 +415,162 @@ format_merge(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, return ret; } +/* Look up the entry's values for the attribute named by the second argument, + * and use the callback to check if they match the first argument. If we find + * exactly one match, store it in the output buffer, otherwise store the text + * of the third argument if given, or return an error if no third argument was + * given. */ +static int +format_match_generic(struct plugin_state *state, + Slapi_PBlock *pb, Slapi_Entry *e, + const char *args, char *outbuf, int outbuf_len, + char ***visited_ndns, + const char *fnname, + PRBool (*match_fn)(const char *pattern, const char *value)) +{ + Slapi_ValueSet *values; + Slapi_Value *value; + const char *cvalue, *matched; + char *actual_attr, **argv; + int i, count, argc, disposition, buffer_flags, ret, len; + + ret = format_parse_args(state, args, &argc, &argv); + if (ret != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "%s: error parsing arguments\n", fnname); + return -1; + } + if (argc < 2) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "%s: requires at least 2 arguments\n", fnname); + format_free_parsed_args(argv); + return -1; + } + /* Walk the list of values for the attribute. */ + matched = NULL; + count = 0; + values = NULL; + if (slapi_vattr_values_get(e, argv[1], &values, + &disposition, &actual_attr, + 0, &buffer_flags) == 0) { + for (i = slapi_valueset_first_value(values, &value); + i != -1; + i = slapi_valueset_next_value(values, i, &value)) { + cvalue = slapi_value_get_string(value); + if (match_fn(argv[0], cvalue)) { + count++; + if (count > 1) { + break; + } + matched = cvalue; + } + } + } else { + if (argv[2] != NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "%s: no values found for " + "\"%s\", using default value \"%s\"\n", + fnname, argv[1], argv[2]); + count = 1; + matched = argv[2]; + } else { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "%s: no values found for " + "\"%s\", and no default value\n", + fnname, argv[1]); + } + } + /* Make sure matched is either the single match, the default, or NULL + * if we had no default. */ + switch (count) { + case 0: + /* No matches. */ + if (argv[2] != NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "%s: no matching values for " + "\"%s\", using default value \"%s\"\n", + fnname, argv[1], argv[2]); + matched = argv[2]; + } else { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "%s: no matching values for " + "\"%s\", and no default value \"%s\"\n", + fnname, argv[1]); + if (values != NULL) { + slapi_vattr_values_free(&values, &actual_attr, + buffer_flags); + } + format_free_parsed_args(argv); + return -1; + } + break; + case 1: + /* No errors. */ + break; + default: + /* Too many matches. */ + if (argv[2] != NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "%s: too many matching values for " + "\"%s\", using default value \"%s\"\n", + fnname, argv[1], argv[2]); + matched = argv[2]; + } else { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "%s: too many matching values for " + "\"%s\", and no default value \"%s\"\n", + fnname, argv[1]); + if (values != NULL) { + slapi_vattr_values_free(&values, &actual_attr, + buffer_flags); + } + format_free_parsed_args(argv); + return -1; + } + break; + } + len = strlen(matched); + if (len > outbuf_len) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "%s: out of space\n", fnname); + if (values != NULL) { + slapi_vattr_values_free(&values, &actual_attr, + buffer_flags); + } + format_free_parsed_args(argv); + return -1; + } + memcpy(outbuf, matched, len); + if (values != NULL) { + slapi_vattr_values_free(&values, &actual_attr, buffer_flags); + } + format_free_parsed_args(argv); + return len; +} + +/* Check for glob-style matched values. */ +static PRBool +format_match_cb(const char *pattern, const char *value) +{ + return fnmatch(pattern, value, 0) == 0; +} +static int +format_match(struct plugin_state *state, + Slapi_PBlock *pb, Slapi_Entry *e, + const char *args, char *outbuf, int outbuf_len, + char ***visited_ndns) +{ + return format_match_generic(state, pb, e, args, + outbuf, outbuf_len, visited_ndns, + "format_match", format_match_cb); +} + /* Choose a formatting function by name. */ static void * format_lookup_fn(const char *fnname) @@ -431,6 +588,7 @@ format_lookup_fn(const char *fnname) {"list", format_list}, {"deref", format_deref}, {"merge", format_merge}, + {"match", format_match}, }; for (i = 0; i < sizeof(fns) / sizeof(fns[0]); i++) { if ((fns[i].name != NULL) && |
