summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-05-16 18:35:28 -0400
committerNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-05-16 18:35:28 -0400
commit82ec8e499f87136252e4e9361dcf8ea2c14c6294 (patch)
tree0f7dce5718c15231eedde81cf5c4324018a0c56d /src
parent8ab5f4b2f802331090068ab3fb655238e561a9a8 (diff)
downloadslapi-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/Makefile2
-rw-r--r--src/backend.c42
-rw-r--r--src/defaults.c46
-rw-r--r--src/defaults.h7
-rw-r--r--src/format.c158
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) &&