summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2014-07-04 16:58:11 +0200
committerJakub Hrozek <jhrozek@redhat.com>2014-07-08 20:28:03 +0200
commiteed2073f6f7bed7df0327b9fc0f2d410975d5332 (patch)
tree77d1b5b6d79dcc9ae6f617949fd600e792362446
parente592d5f157be869151983bd1b46d6f4f7a29daaf (diff)
downloadsssd-eed2073f6f7bed7df0327b9fc0f2d410975d5332.tar.gz
sssd-eed2073f6f7bed7df0327b9fc0f2d410975d5332.tar.xz
sssd-eed2073f6f7bed7df0327b9fc0f2d410975d5332.zip
LDAP: Try all attributes when saving an entry
The same LDAP attribute might be used several times for the same user or group attribute. For instance, some servers have a global "ID" number that should be used for both UID and GID. However, our sdap_parse_entry() function only copied the LDAP attribute to the first matching sysdb attribute. This patch adds a second nested loop that checks if any of the other LDAP attributes are eligible. Reviewed-by: Michal Židek <mzidek@redhat.com>
-rw-r--r--src/providers/ldap/sdap.c27
-rw-r--r--src/tests/cmocka/test_sdap.c55
2 files changed, 79 insertions, 3 deletions
diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
index e8d23c9dc..133e6dcf3 100644
--- a/src/providers/ldap/sdap.c
+++ b/src/providers/ldap/sdap.c
@@ -302,7 +302,7 @@ int sdap_parse_entry(TALLOC_CTX *memctx,
struct ldb_val v;
char *str;
int lerrno;
- int a, i, ret;
+ int a, i, ret, ai;
const char *name;
bool store;
bool base64;
@@ -480,8 +480,29 @@ int sdap_parse_entry(TALLOC_CTX *memctx,
v.length = vals[i]->bv_len;
}
- ret = sysdb_attrs_add_val(attrs, name, &v);
- if (ret) goto done;
+ if (map) {
+ /* The same LDAP attr might be used for more sysdb
+ * attrs in case there is a map. Find all that match
+ * and copy the value
+ */
+ for (ai = a; ai < attrs_num; ai++) {
+ /* check if this attr is valid with the chosen
+ * schema */
+ if (!map[ai].name) continue;
+
+ /* check if it is an attr we are interested in */
+ if (strcasecmp(base_attr, map[ai].name) == 0) {
+ ret = sysdb_attrs_add_val(attrs,
+ map[ai].sys_name,
+ &v);
+ if (ret) goto done;
+ }
+ }
+ } else {
+ /* No map, just store the attribute */
+ ret = sysdb_attrs_add_val(attrs, name, &v);
+ if (ret) goto done;
+ }
}
ldap_value_free_len(vals);
}
diff --git a/src/tests/cmocka/test_sdap.c b/src/tests/cmocka/test_sdap.c
index 3990d7a3e..8fdf1a4a2 100644
--- a/src/tests/cmocka/test_sdap.c
+++ b/src/tests/cmocka/test_sdap.c
@@ -372,6 +372,58 @@ void test_parse_no_attrs(void **state)
talloc_free(attrs);
}
+void test_parse_dups(void **state)
+{
+ int ret;
+ struct sysdb_attrs *attrs;
+ struct parse_test_ctx *test_ctx = talloc_get_type_abort(*state,
+ struct parse_test_ctx);
+ struct mock_ldap_entry test_dupattr_user;
+ struct sdap_attr_map *map;
+ int i;
+
+ const char *oc_values[] = { "posixAccount", NULL };
+ const char *uid_values[] = { "1234", NULL };
+ struct mock_ldap_attr test_dupattr_attrs[] = {
+ { .name = "objectClass", .values = oc_values },
+ { .name = "idNumber", .values = uid_values },
+ { NULL, NULL }
+ };
+
+ test_dupattr_user.dn = "cn=dupuser,dc=example,dc=com";
+ test_dupattr_user.attrs = test_dupattr_attrs;
+ set_entry_parse(&test_dupattr_user);
+
+ ret = sdap_copy_map(test_ctx, rfc2307_user_map, SDAP_OPTS_USER, &map);
+ assert_int_equal(ret, ERR_OK);
+ /* Set both uidNumber and gidNumber to idNumber */
+ for (i = 0; i < SDAP_OPTS_USER; i++) {
+ if (map[i].name == NULL) continue;
+
+ if (strcmp(map[i].name, "uidNumber") == 0
+ || strcmp(map[i].name, "gidNumber") == 0) {
+ map[i].name = discard_const("idNumber");
+ }
+ }
+
+ ret = sdap_parse_entry(test_ctx, &test_ctx->sh, &test_ctx->sm,
+ map, SDAP_OPTS_USER,
+ &attrs, NULL, false);
+ assert_int_equal(ret, ERR_OK);
+
+ assert_int_equal(attrs->num, 3);
+
+ /* Every entry has a DN */
+ assert_entry_has_attr(attrs, SYSDB_ORIG_DN,
+ "cn=dupuser,dc=example,dc=com");
+ /* Test the single-valued attribute */
+ assert_entry_has_attr(attrs, SYSDB_UIDNUM, "1234");
+ assert_entry_has_attr(attrs, SYSDB_GIDNUM, "1234");
+
+ talloc_free(map);
+ talloc_free(attrs);
+}
+
/* Negative test - objectclass doesn't match the map */
void test_parse_bad_oc(void **state)
{
@@ -493,6 +545,9 @@ int main(int argc, const char *argv[])
unit_test_setup_teardown(test_parse_no_attrs,
parse_entry_test_setup,
parse_entry_test_teardown),
+ unit_test_setup_teardown(test_parse_dups,
+ parse_entry_test_setup,
+ parse_entry_test_teardown),
/* Negative tests */
unit_test_setup_teardown(test_parse_no_oc,
parse_entry_test_setup,