-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Fixes https://fedorahosted.org/sssd/ticket/818

Patch 0001: Create sysdb_get_rdn() function
This function takes a DN formatted string and returns the RDN
value from it.

Patch 0002: Add sysdb_attrs_primary_name()
This function will check a sysdb_attrs struct for the primary name
of the entity it represents. If there are multiple entries, it
will pick the one that matches the RDN. If none match, it will
throw an error.

Patch 0003: Handle multi-valued usernames correctly
Users in ldap with multiple values for their username attribute
will now be compared against the RDN of the entry to determine the
"primary" username. We will save all of the alternate names to the
ldb cache as well, so a lookup for any of them will return the
values for the primary name.
e.g.
getent passwd altusername
primaryuser:*:800014:800014:primaryuser:/home/primaryuser:/bin/sh

Patch 0004: RFC2307: Handle multi-valued group names correctly
Groups in ldap with multiple values for their groupname attribute
will now be compared against the RDN of the entry to determine the
"primary" group name. We will save all of the alternate names to the
ldb cache as well, so a lookup for any of them will return the
values for the primary name.
e.g.
getent group altgroup
primarygroup:*:800014:member1,member2

Patch 0005: RFC2307bis: Handle multi-valued group names correctly
Groups in ldap with multiple values for their groupname attribute
will now be compared against the RDN of the entry to determine the
"primary" group name. We will save all of the alternate names to the
ldb cache as well, so a lookup for any of them will return the
values for the primary name.
e.g.
getent group altgroup
primarygroup:*:800014:member1,member2


I tested with RFC2307, RFC2307bis and FreeIPA v2 data.

- -- 
Stephen Gallagher
RHCE 804006346421761

Delivering value year after year.
Red Hat ranks #1 in value among software vendors.
http://www.redhat.com/promo/vendor/
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iEYEARECAAYFAk2A8zQACgkQeiVVYja6o6NhlgCfctmTZdWDmsobpeV05vl1YBVd
MEUAn2+lKF0WKRSTWS2xvX1t+6FsCWQ5
=Y2s1
-----END PGP SIGNATURE-----
From 7628ad038f136c5c41b562e1535ef951c54a5169 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgall...@redhat.com>
Date: Wed, 16 Mar 2011 12:34:26 -0400
Subject: [PATCH 1/5] Create sysdb_get_rdn() function

This function takes a DN formatted string and returns the RDN
value from it.
---
 src/db/sysdb.c |   39 +++++++++++++++++++++++++++++----------
 src/db/sysdb.h |    2 ++
 2 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/src/db/sysdb.c b/src/db/sysdb.c
index 521ae9d2ae2b49bd3c8ecec8a3e0eaf172a2583c..9e2b0b563605d41493e5fe5789d41be8d641c247 100644
--- a/src/db/sysdb.c
+++ b/src/db/sysdb.c
@@ -204,33 +204,52 @@ struct ldb_dn *sysdb_netgroup_base_dn(struct sysdb_ctx *ctx, void *memctx,
     return ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_TMPL_NETGROUP_BASE, domain);
 }
 
-errno_t sysdb_group_dn_name(struct sysdb_ctx *ctx, void *memctx,
-                            const char *_dn, char **_name)
+errno_t sysdb_get_rdn(struct sysdb_ctx *ctx, void *memctx,
+                      const char *_dn, char **_name)
 {
+    errno_t ret;
     struct ldb_dn *dn;
     const struct ldb_val *val;
     *_name = NULL;
+    TALLOC_CTX *tmpctx;
 
-    dn = ldb_dn_new_fmt(memctx, ctx->ldb, "%s", _dn);
+    /* We have to create a tmpctx here because
+     * ldb_dn_new_fmt() fails if memctx is NULL
+     */
+    tmpctx = talloc_new(NULL);
+    if (!tmpctx) {
+        return ENOMEM;
+    }
+
+    dn = ldb_dn_new_fmt(tmpctx, ctx->ldb, "%s", _dn);
     if (dn == NULL) {
-        return ENOMEM;
+        ret = ENOMEM;
+        goto done;
     }
 
     val = ldb_dn_get_rdn_val(dn);
     if (val == NULL) {
-        talloc_zfree(dn);
-        return EINVAL;
+        ret = EINVAL;
+        goto done;
     }
 
     *_name = talloc_strndup(memctx, (char *) val->data, val->length);
     if (!*_name) {
-        talloc_zfree(dn);
-        return ENOMEM;
+        ret = ENOMEM;
+        goto done;
     }
 
-    talloc_zfree(dn);
+    ret = EOK;
 
-    return EOK;
+done:
+    talloc_zfree(tmpctx);
+    return ret;
+}
+
+errno_t sysdb_group_dn_name(struct sysdb_ctx *ctx, void *memctx,
+                            const char *_dn, char **_name)
+{
+    return sysdb_get_rdn(ctx, memctx, _dn, _name);
 }
 
 struct ldb_dn *sysdb_domain_dn(struct sysdb_ctx *ctx, void *memctx,
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index ae0b33ce1efcec4a895bd89633d27d4cc3c19182..2039ffd10fbc9d93967f9fc2c83dfb15dbf86bc1 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -220,6 +220,8 @@ int sysdb_attrs_users_from_ldb_vals(struct sysdb_attrs *attrs,
 int sysdb_error_to_errno(int ldberr);
 
 /* DNs related helper functions */
+errno_t sysdb_get_rdn(struct sysdb_ctx *ctx, void *memctx,
+                      const char *_dn, char **_name);
 struct ldb_dn *sysdb_user_dn(struct sysdb_ctx *ctx, void *memctx,
                              const char *domain, const char *name);
 struct ldb_dn *sysdb_group_dn(struct sysdb_ctx *ctx, void *memctx,
-- 
1.7.4

From 00b9f4d4945c8547f7c8351e65ec95b98e3d6041 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgall...@redhat.com>
Date: Wed, 16 Mar 2011 12:29:37 -0400
Subject: [PATCH 2/5] Add sysdb_attrs_primary_name()

This function will check a sysdb_attrs struct for the primary name
of the entity it represents. If there are multiple entries, it
will pick the one that matches the RDN. If none match, it will
throw an error.
---
 src/db/sysdb.c |   66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/db/sysdb.h |    4 +++
 2 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/src/db/sysdb.c b/src/db/sysdb.c
index 9e2b0b563605d41493e5fe5789d41be8d641c247..ab6e3d6c0abb710c7f452b7fdcefce3a585f7f69 100644
--- a/src/db/sysdb.c
+++ b/src/db/sysdb.c
@@ -2138,3 +2138,69 @@ done:
     talloc_free(tmp_ctx);
     return ret;
 }
+
+errno_t sysdb_attrs_primary_name(struct sysdb_ctx *sysdb,
+                                 struct sysdb_attrs *attrs,
+                                 struct ldb_message_element *names,
+                                 const char **_primary)
+{
+    errno_t ret;
+    char *rdn = NULL;
+    struct ldb_message_element *el;
+    size_t i;
+
+    ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el);
+    if (ret) {
+        goto done;
+    }
+    if (el->num_values == 0) {
+        DEBUG(7, ("Original DN is not available.\n"));
+    } else if (el->num_values == 1) {
+        ret = sysdb_get_rdn(sysdb, NULL,
+                            (const char *) el->values[0].data,
+                            &rdn);
+        if (ret != EOK) {
+            DEBUG(1, ("Could not get rdn from [%s]\n",
+                      (const char *) el->values[0].data));
+            goto done;
+        }
+    } else {
+        DEBUG(1, ("Should not have more than one origDN\n"));
+        ret = EINVAL;
+        goto done;
+    }
+
+    if (names->num_values == 1) {
+        *_primary = (const char *)names->values[0].data;
+    } else {
+        /* Multiple values for name. Check whether one matches the RDN */
+        for (i = 0; i < names->num_values; i++) {
+            if (strcasecmp(rdn, (const char *)names->values[i].data) == 0) {
+                /* This name matches the RDN. Use it */
+                break;
+            }
+        }
+        if (i < names->num_values) {
+            /* Match was found */
+            *_primary = (const char *)names->values[i].data;
+        } else {
+            /* If we can't match the name to the RDN, we just have to
+             * throw up our hands. There's no deterministic way to
+             * decide which name is correct.
+             */
+            DEBUG(1, ("Cannot save group. Unable to determine groupname\n"));
+            ret = EINVAL;
+            goto done;
+        }
+    }
+
+    ret = EOK;
+
+done:
+    if (ret != EOK) {
+        DEBUG(1, ("Could not determine primary name: [%d][%s]\n",
+                  ret, strerror(ret)));
+    }
+    talloc_free(rdn);
+    return ret;
+}
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 2039ffd10fbc9d93967f9fc2c83dfb15dbf86bc1..2c4b065243402be94953f1ac6af1e9262a9a01ef 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -215,6 +215,10 @@ int sysdb_attrs_users_from_ldb_vals(struct sysdb_attrs *attrs,
                                     const char *domain,
                                     struct ldb_val *values,
                                     int num_values);
+errno_t sysdb_attrs_primary_name(struct sysdb_ctx *sysdb,
+                                 struct sysdb_attrs *attrs,
+                                 struct ldb_message_element *names,
+                                 const char **_primary);
 
 /* convert an ldb error into an errno error */
 int sysdb_error_to_errno(int ldberr);
-- 
1.7.4

From 6dc3bcd1558179569063f78a759c6c6d1b100aa9 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgall...@redhat.com>
Date: Wed, 16 Mar 2011 12:35:27 -0400
Subject: [PATCH 3/5] Handle multi-valued usernames correctly

Users in ldap with multiple values for their username attribute
will now be compared against the RDN of the entry to determine the
"primary" username. We will save all of the alternate names to the
ldb cache as well, so a lookup for any of them will return the
values for the primary name.

e.g.
getent passwd altusername
primaryuser:*:800014:800014:primaryuser:/home/primaryuser:/bin/sh
---
 src/providers/ldap/sdap_async_accounts.c |   59 ++++++++++++++++++++++--------
 1 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/providers/ldap/sdap_async_accounts.c b/src/providers/ldap/sdap_async_accounts.c
index 3fedf07da7fbdc9409f5360ba8301158a65014cd..71c25c883fbaf03becbbe9804865ba0ac7cc7513 100644
--- a/src/providers/ldap/sdap_async_accounts.c
+++ b/src/providers/ldap/sdap_async_accounts.c
@@ -40,7 +40,7 @@ static int sdap_save_user(TALLOC_CTX *memctx,
 {
     struct ldb_message_element *el;
     int ret;
-    const char *name;
+    const char *name = NULL;
     const char *pwd;
     const char *gecos;
     const char *homedir;
@@ -49,15 +49,28 @@ static int sdap_save_user(TALLOC_CTX *memctx,
     gid_t gid;
     struct sysdb_attrs *user_attrs;
     char *upn = NULL;
-    int i;
+    size_t i;
     char *val = NULL;
     int cache_timeout;
     char *usn_value = NULL;
     size_t c;
     char **missing = NULL;
+    TALLOC_CTX *tmpctx = NULL;
 
     DEBUG(9, ("Save user\n"));
 
+    tmpctx = talloc_new(memctx);
+    if (!tmpctx) {
+        ret = ENOMEM;
+        goto fail;
+    }
+
+    user_attrs = sysdb_new_attrs(tmpctx);
+    if (user_attrs == NULL) {
+        ret = ENOMEM;
+        goto fail;
+    }
+
     ret = sysdb_attrs_get_el(attrs,
                              opts->user_map[SDAP_AT_USER_NAME].sys_name, &el);
     if (el->num_values == 0) {
@@ -65,9 +78,13 @@ static int sdap_save_user(TALLOC_CTX *memctx,
     }
     if (ret) {
         DEBUG(1, ("Failed to save the user - entry has no name attribute\n"));
-        return ret;
+        goto fail;
+    }
+
+    ret = sysdb_attrs_primary_name(ctx, attrs, el, &name);
+    if (ret != EOK) {
+        goto fail;
     }
-    name = (const char *)el->values[0].data;
 
     ret = sysdb_attrs_get_el(attrs,
                              opts->user_map[SDAP_AT_USER_PWD].sys_name, &el);
@@ -129,12 +146,6 @@ static int sdap_save_user(TALLOC_CTX *memctx,
         goto fail;
     }
 
-    user_attrs = sysdb_new_attrs(memctx);
-    if (user_attrs == NULL) {
-        ret = ENOMEM;
-        goto fail;
-    }
-
     ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el);
     if (ret) {
         goto fail;
@@ -151,6 +162,22 @@ static int sdap_save_user(TALLOC_CTX *memctx,
         }
     }
 
+    /* Save alternate names */
+    ret = sysdb_attrs_get_el(attrs, SYSDB_NAME, &el);
+    if (ret != EOK) {
+        goto fail;
+    }
+
+    for(i = 0; i < el->num_values; i++) {
+        DEBUG(7, ("Adding alternate name [%s] to attributes of [%s]\n",
+                  el->values[i].data, name));
+        ret = sysdb_attrs_add_string(user_attrs, SYSDB_NAME,
+                                     (const char *)el->values[i].data);
+        if (ret != EOK) {
+            goto fail;
+        }
+    }
+
     ret = sysdb_attrs_get_el(attrs, SYSDB_MEMBEROF, &el);
     if (ret) {
         goto fail;
@@ -271,7 +298,7 @@ static int sdap_save_user(TALLOC_CTX *memctx,
     /* Make sure that any attributes we requested from LDAP that we
      * did not receive are also removed from the sysdb
      */
-    ret = list_missing_attrs(NULL, opts->user_map, SDAP_OPTS_USER,
+    ret = list_missing_attrs(user_attrs, opts->user_map, SDAP_OPTS_USER,
                              ldap_attrs, attrs, &missing);
     if (ret != EOK) {
         goto fail;
@@ -285,21 +312,23 @@ static int sdap_save_user(TALLOC_CTX *memctx,
 
     DEBUG(6, ("Storing info for user %s\n", name));
 
-    ret = sysdb_store_user(memctx, ctx, dom,
+    ret = sysdb_store_user(user_attrs, ctx, dom,
                            name, pwd, uid, gid, gecos, homedir, shell,
                            user_attrs, missing, cache_timeout);
     if (ret) goto fail;
-    talloc_zfree(missing);
 
     if (_usn_value) {
         *_usn_value = usn_value;
     }
 
+    talloc_steal(memctx, user_attrs);
+    talloc_free(tmpctx);
     return EOK;
 
 fail:
-    DEBUG(2, ("Failed to save user %s\n", name));
-    talloc_free(missing);
+    DEBUG(2, ("Failed to save user [%s]\n",
+              name ? name : "Unknown"));
+    talloc_free(tmpctx);
     return ret;
 }
 
-- 
1.7.4

From 2fb9df3abd2bd63110cf2f9d829e8efbf47f7ef2 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgall...@redhat.com>
Date: Wed, 16 Mar 2011 09:09:28 -0400
Subject: [PATCH 4/5] RFC2307: Handle multi-valued group names correctly

Groups in ldap with multiple values for their groupname attribute
will now be compared against the RDN of the entry to determine the
"primary" group name. We will save all of the alternate names to the
ldb cache as well, so a lookup for any of them will return the
values for the primary name.

e.g.
getent group altgroup
primarygroup:*:800014:member1,member2
---
 src/providers/ldap/sdap_async_accounts.c |   64 +++++++++++++++++++++++------
 1 files changed, 50 insertions(+), 14 deletions(-)

diff --git a/src/providers/ldap/sdap_async_accounts.c b/src/providers/ldap/sdap_async_accounts.c
index 71c25c883fbaf03becbbe9804865ba0ac7cc7513..e7fc4001b9d1fa316e850fb2055c1f3e15c1875d 100644
--- a/src/providers/ldap/sdap_async_accounts.c
+++ b/src/providers/ldap/sdap_async_accounts.c
@@ -684,15 +684,37 @@ static int sdap_save_group(TALLOC_CTX *memctx,
     gid_t gid;
     int ret;
     char *usn_value = NULL;
+    TALLOC_CTX *tmpctx = NULL;
+    size_t i;
+
+    tmpctx = talloc_new(memctx);
+    if (!tmpctx) {
+        ret = ENOMEM;
+        goto fail;
+    }
+
+    group_attrs = sysdb_new_attrs(tmpctx);
+    if (group_attrs == NULL) {
+        ret = ENOMEM;
+        goto fail;
+    }
 
     ret = sysdb_attrs_get_el(attrs,
-                          opts->group_map[SDAP_AT_GROUP_NAME].sys_name, &el);
-    if (ret) goto fail;
+                             opts->group_map[SDAP_AT_GROUP_NAME].sys_name,
+                             &el);
     if (el->num_values == 0) {
         ret = EINVAL;
         goto fail;
     }
-    name = (const char *)el->values[0].data;
+    if (ret) {
+        DEBUG(1, ("Failed to save the group - entry has no name attribute\n"));
+        goto fail;
+    }
+
+    ret = sysdb_attrs_primary_name(ctx, attrs, el, &name);
+    if (ret != EOK) {
+        goto fail;
+    }
 
     ret = sysdb_attrs_get_uint32_t(attrs,
                                    opts->group_map[SDAP_AT_GROUP_GID].sys_name,
@@ -712,12 +734,6 @@ static int sdap_save_group(TALLOC_CTX *memctx,
         goto fail;
     }
 
-    group_attrs = sysdb_new_attrs(memctx);
-    if (!group_attrs) {
-        ret = ENOMEM;
-        goto fail;
-    }
-
     ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el);
     if (ret) {
         goto fail;
@@ -728,12 +744,28 @@ static int sdap_save_group(TALLOC_CTX *memctx,
         DEBUG(7, ("Adding original DN [%s] to attributes of [%s].\n",
                   el->values[0].data, name));
         ret = sysdb_attrs_add_string(group_attrs, SYSDB_ORIG_DN,
-                                     (const char *)el->values[0].data);
+                                     (const char *) el->values[0].data);
         if (ret) {
             goto fail;
         }
     }
 
+    /* Save alternate names */
+    ret = sysdb_attrs_get_el(attrs, SYSDB_NAME, &el);
+    if (ret != EOK) {
+        goto fail;
+    }
+
+    for(i = 0; i < el->num_values; i++) {
+        DEBUG(7, ("Adding alternate name [%s] to attributes of [%s]\n",
+                  el->values[i].data, name));
+        ret = sysdb_attrs_add_string(group_attrs, SYSDB_NAME,
+                                     (const char *)el->values[i].data);
+        if (ret != EOK) {
+            goto fail;
+        }
+    }
+
     ret = sysdb_attrs_get_el(attrs,
                       opts->group_map[SDAP_AT_GROUP_MODSTAMP].sys_name, &el);
     if (ret) {
@@ -766,7 +798,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
         if (ret) {
             goto fail;
         }
-        usn_value = talloc_strdup(memctx, (const char*)el->values[0].data);
+        usn_value = talloc_strdup(tmpctx, (const char*)el->values[0].data);
         if (!usn_value) {
             ret = ENOMEM;
             goto fail;
@@ -807,20 +839,24 @@ static int sdap_save_group(TALLOC_CTX *memctx,
 
     DEBUG(6, ("Storing info for group %s\n", name));
 
-    ret = sysdb_store_group(memctx, ctx, dom,
+    ret = sysdb_store_group(group_attrs, ctx, dom,
                             name, gid, group_attrs,
                             dp_opt_get_int(opts->basic,
                                            SDAP_ENTRY_CACHE_TIMEOUT));
     if (ret) goto fail;
 
     if (_usn_value) {
-        *_usn_value = usn_value;
+        *_usn_value = talloc_steal(memctx, usn_value);
     }
 
+    talloc_steal(memctx, group_attrs);
+    talloc_free(tmpctx);
     return EOK;
 
 fail:
-    DEBUG(2, ("Failed to save user %s\n", name));
+    DEBUG(2, ("Failed to save group [%s]\n",
+              name ? name : "Unknown"));
+    talloc_free(tmpctx);
     return ret;
 }
 
-- 
1.7.4

From b93cd886359e921e4319225cbc0da19c20075f9f Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgall...@redhat.com>
Date: Wed, 16 Mar 2011 12:59:33 -0400
Subject: [PATCH 5/5] RFC2307bis: Handle multi-valued group names correctly

Groups in ldap with multiple values for their groupname attribute
will now be compared against the RDN of the entry to determine the
"primary" group name. We will save all of the alternate names to the
ldb cache as well, so a lookup for any of them will return the
values for the primary name.

e.g.
getent group altgroup
primarygroup:*:800014:member1,member2
---
 src/providers/ldap/sdap_async_accounts.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/providers/ldap/sdap_async_accounts.c b/src/providers/ldap/sdap_async_accounts.c
index e7fc4001b9d1fa316e850fb2055c1f3e15c1875d..281c08a5a55b5290802f102d9e8eb61ff9366b61 100644
--- a/src/providers/ldap/sdap_async_accounts.c
+++ b/src/providers/ldap/sdap_async_accounts.c
@@ -2847,6 +2847,7 @@ static struct tevent_req *sdap_nested_group_process_send(
     const char *groupname;
     hash_key_t key;
     hash_value_t value;
+    struct ldb_message_element *el;
 
     req = tevent_req_create(mem_ctx, &state, struct sdap_nested_group_ctx);
     if (!req) {
@@ -2873,12 +2874,17 @@ static struct tevent_req *sdap_nested_group_process_send(
      */
     key.type = HASH_KEY_STRING;
 
-    ret = sysdb_attrs_get_string(
+    ret = sysdb_attrs_get_el(
             group,
             opts->group_map[SDAP_AT_GROUP_NAME].sys_name,
-            &groupname);
+            &el);
     if (ret != EOK) goto immediate;
 
+    ret = sysdb_attrs_primary_name(sysdb, group, el, &groupname);
+    if (ret != EOK) {
+        goto immediate;
+    }
+
     key.str = talloc_strdup(state, groupname);
     if (!key.str) {
         ret = ENOMEM;
-- 
1.7.4

Attachment: 0001-Create-sysdb_get_rdn-function.patch.sig
Description: PGP signature

Attachment: 0002-Add-sysdb_attrs_primary_name.patch.sig
Description: PGP signature

Attachment: 0003-Handle-multi-valued-usernames-correctly.patch.sig
Description: PGP signature

Attachment: 0004-RFC2307-Handle-multi-valued-group-names-correctly.patch.sig
Description: PGP signature

Attachment: 0005-RFC2307bis-Handle-multi-valued-group-names-correctly.patch.sig
Description: PGP signature

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to