[SSSD] [PATCH] improve handling of users with multiple names

Jakub Hrozek jhrozek at redhat.com
Mon Sep 26 16:20:36 UTC 2011


On Mon, Sep 26, 2011 at 10:15:18AM +0200, Jakub Hrozek wrote:
> On Sun, Sep 25, 2011 at 10:38:32AM -0400, Simo Sorce wrote:
> > On Fri, 2011-09-23 at 15:52 +0200, Jakub Hrozek wrote:
> > > +    ret = sysdb_attrs_get_el(attrs,
> > > +                             SYSDB_NAME,
> > 
> > Shouldn't this be SYSDB_NAME_ALIAS ? ^^^^
> > 
> > > +                             &sysdb_name_el);
> > > +    if (sysdb_name_el->num_values == 0) {
> > > +        ret = EINVAL;
> > > +        goto done;
> > > +    } else if (sysdb_name_el->num_values == 1) {
> > > +        *_aliases = NULL;
> > > +        ret = EOK;
> > > +        goto done;
> > > +    } 
> 
> No, the function sysdb_attrs_get_aliases() you are referring to is a
> supplement to sysdb_attrs_primary_name().
> 
> Neither of them is supposed to operate on cache entries, but rather LDAP
> attributes translated. The name might be confusing, but I decided to stict
> to the same naming schema sysdb_attrs_primary_name() has.
> 
> The synopsis of _get_aliases() is this:
> the function takes a primary name as a parameter and returns all the other
> names as aliases so we can save the primary name as SYSDB_NAME into cache
> and the aliases as SYSDB_NAME_ALIAS.

After discussing the approach with Simo on #sssd, I added a comment
explaining what sysdb_attrs_get_aliases() does.

New patches attached.
-------------- next part --------------
From c68378d1a26a2489d1cbd1efd228db9b9a93c378 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 21 Sep 2011 10:39:06 +0200
Subject: [PATCH 1/4] Add sysdb interface to get name aliases

---
 src/db/sysdb.c |   64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/db/sysdb.h |    5 ++++
 2 files changed, 68 insertions(+), 1 deletions(-)

diff --git a/src/db/sysdb.c b/src/db/sysdb.c
index 7d030d8..18cf26a 100644
--- a/src/db/sysdb.c
+++ b/src/db/sysdb.c
@@ -2410,7 +2410,7 @@ errno_t sysdb_attrs_primary_name(struct sysdb_ctx *sysdb,
     if (strcasecmp(rdn_attr, ldap_attr) != 0) {
         /* Multiple entries, and the RDN attribute doesn't match.
          * We have no way of resolving this deterministically,
-         * so we'll punt.
+         * so we'll use the first value as a fallback.
          */
         DEBUG(3, ("The entry has multiple names and the RDN attribute does "
                   "not match. Will use the first value as fallback.\n"));
@@ -2450,6 +2450,68 @@ done:
     return ret;
 }
 
+/*
+ * An entity with multiple names would have multiple SYSDB_NAME attributes
+ * after being translated into sysdb names using a map.
+ * Given a primary name returned by sysdb_attrs_primary_name(), this function
+ * returns the other SYSDB_NAME attribute values so they can be saved as
+ * SYSDB_NAME_ALIAS into cache.
+ */
+errno_t sysdb_attrs_get_aliases(TALLOC_CTX *mem_ctx,
+                                struct sysdb_attrs *attrs,
+                                const char *primary,
+                                const char ***_aliases)
+{
+    TALLOC_CTX *tmp_ctx = NULL;
+    struct ldb_message_element *sysdb_name_el;
+    size_t i, ai;
+    errno_t ret;
+    const char **aliases = NULL;
+    const char *name;
+
+    if (_aliases == NULL) return EINVAL;
+
+    tmp_ctx = talloc_new(NULL);
+    if (!tmp_ctx) {
+        return ENOMEM;
+    }
+
+    ret = sysdb_attrs_get_el(attrs,
+                             SYSDB_NAME,
+                             &sysdb_name_el);
+    if (sysdb_name_el->num_values == 0) {
+        ret = EINVAL;
+        goto done;
+    } else if (sysdb_name_el->num_values == 1) {
+        *_aliases = NULL;
+        ret = EOK;
+        goto done;
+    }
+
+    aliases = talloc_array(tmp_ctx, const char *,
+                           sysdb_name_el->num_values);
+    if (!aliases) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ai = 0;
+    for (i=0; i < sysdb_name_el->num_values; i++) {
+        name = (const char *)sysdb_name_el->values[i].data;
+        if (strcmp(primary, name) != 0) {
+            aliases[ai] = name;
+            ai++;
+        }
+    }
+
+    aliases[ai] = NULL;
+    ret = EOK;
+done:
+    *_aliases = talloc_steal(mem_ctx, aliases);
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
 errno_t sysdb_attrs_primary_name_list(struct sysdb_ctx *sysdb,
                                       TALLOC_CTX *mem_ctx,
                                       struct sysdb_attrs **attr_list,
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index ee1c868..fc53e38 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -46,6 +46,7 @@
 #define SYSDB_NETGROUP_CLASS "netgroup"
 
 #define SYSDB_NAME "name"
+#define SYSDB_NAME_ALIAS "nameAlias"
 #define SYSDB_OBJECTCLASS "objectClass"
 
 #define SYSDB_NEXTID "nextID"
@@ -229,6 +230,10 @@ errno_t sysdb_attrs_primary_name(struct sysdb_ctx *sysdb,
                                  struct sysdb_attrs *attrs,
                                  const char *ldap_attr,
                                  const char **_primary);
+errno_t sysdb_attrs_get_aliases(TALLOC_CTX *mem_ctx,
+                                struct sysdb_attrs *attrs,
+                                const char *primary,
+                                const char ***_aliases);
 errno_t sysdb_attrs_primary_name_list(struct sysdb_ctx *sysdb,
                                       TALLOC_CTX *mem_ctx,
                                       struct sysdb_attrs **attr_list,
-- 
1.7.6.2

-------------- next part --------------
From f08de598ed83e99d05488be1471de065dabb9e73 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Thu, 22 Sep 2011 13:18:40 +0200
Subject: [PATCH 2/4] Add a sysdb_get_direct_parents function

---
 src/db/sysdb.h                             |    7 ++
 src/db/sysdb_search.c                      |   99 ++++++++++++++++++++++++++++
 src/providers/ldap/sdap_async_initgroups.c |   62 ++----------------
 3 files changed, 111 insertions(+), 57 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index fc53e38..138e7df 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -690,4 +690,11 @@ errno_t sysdb_remove_attrs(struct sysdb_ctx *sysdb,
                            enum sysdb_member_type type,
                            char **remove_attrs);
 
+errno_t sysdb_get_direct_parents(TALLOC_CTX *mem_ctx,
+                                 struct sysdb_ctx *sysdb,
+                                 struct sss_domain_info *dom,
+                                 enum sysdb_member_type mtype,
+                                 const char *name,
+                                 char ***_direct_parents);
+
 #endif /* __SYS_DB_H__ */
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
index 37d6e14..4859ffb 100644
--- a/src/db/sysdb_search.c
+++ b/src/db/sysdb_search.c
@@ -842,3 +842,102 @@ done:
     talloc_zfree(tmp_ctx);
     return ret;
 }
+
+errno_t sysdb_get_direct_parents(TALLOC_CTX *mem_ctx,
+                                 struct sysdb_ctx *sysdb,
+                                 struct sss_domain_info *dom,
+                                 enum sysdb_member_type mtype,
+                                 const char *name,
+                                 char ***_direct_parents)
+{
+    errno_t ret;
+    const char *dn;
+    struct ldb_dn *basedn;
+    static const char *group_attrs[] = { SYSDB_NAME, NULL };
+    const char *member_filter;
+    size_t direct_sysdb_count = 0;
+    struct ldb_message **direct_sysdb_groups = NULL;
+    char **direct_parents = NULL;
+    TALLOC_CTX *tmp_ctx = NULL;
+    int i, pi;
+    const char *tmp_str;
+
+    tmp_ctx = talloc_new(NULL);
+    if (!tmp_ctx) return ENOMEM;
+
+    if (mtype == SYSDB_MEMBER_USER) {
+        dn = sysdb_user_strdn(tmp_ctx, dom->name, name);
+    } else if (mtype == SYSDB_MEMBER_USER) {
+        dn = sysdb_group_strdn(tmp_ctx, dom->name, name);
+    } else {
+        DEBUG(1, ("Unknown member type\n"));
+        ret = EINVAL;
+        goto done;
+    }
+
+    if (!dn) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    member_filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)(%s=%s))",
+                                    SYSDB_OBJECTCLASS, SYSDB_GROUP_CLASS,
+                                    SYSDB_MEMBER, dn);
+    if (!member_filter) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    basedn = ldb_dn_new_fmt(tmp_ctx, sysdb_ctx_get_ldb(sysdb),
+                            SYSDB_TMPL_GROUP_BASE, dom->name);
+    if (!basedn) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    DEBUG(8, ("searching sysdb with filter [%s]\n", member_filter));
+
+    ret = sysdb_search_entry(tmp_ctx, sysdb, basedn,
+                             LDB_SCOPE_SUBTREE, member_filter, group_attrs,
+                             &direct_sysdb_count, &direct_sysdb_groups);
+    if (ret == EOK) {
+        /* Get the list of sysdb groups by name */
+        direct_parents = talloc_array(tmp_ctx, char *, direct_sysdb_count+1);
+        if (!direct_parents) {
+            ret = ENOMEM;
+            goto done;
+        }
+
+        pi = 0;
+        for(i = 0; i < direct_sysdb_count; i++) {
+            tmp_str = ldb_msg_find_attr_as_string(direct_sysdb_groups[i],
+                                                  SYSDB_NAME, NULL);
+            if (!tmp_str) {
+                /* This should never happen, but if it does, just continue */
+                continue;
+            }
+
+            direct_parents[pi] = talloc_strdup(direct_parents, tmp_str);
+            if (!direct_parents[pi]) {
+                DEBUG(1, ("A group with no name?\n"));
+                ret = EIO;
+                goto done;
+            }
+            pi++;
+        }
+        direct_parents[pi] = NULL;
+    } else if (ret == ENOENT) {
+        direct_parents = NULL;
+        direct_sysdb_count = 0;
+    } else {
+        DEBUG(2, ("sysdb_search_entry failed: [%d]: %s\n", ret, strerror(ret)));
+        goto done;
+    }
+    DEBUG(7, ("%s is a member of %d sysdb groups\n", name, direct_sysdb_count));
+
+    *_direct_parents = talloc_steal(mem_ctx, direct_parents);
+    ret = EOK;
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
index 2191c13..f5c3707 100644
--- a/src/providers/ldap/sdap_async_initgroups.c
+++ b/src/providers/ldap/sdap_async_initgroups.c
@@ -774,20 +774,13 @@ static int sdap_initgr_nested_store_group(struct sysdb_ctx *sysdb,
                                           int ngroups)
 {
     TALLOC_CTX *tmp_ctx;
-    const char *member_filter;
     const char *group_orig_dn;
     const char *group_name;
-    const char *group_dn;
     int ret;
-    int i;
-    struct ldb_message **direct_sysdb_groups = NULL;
-    size_t direct_sysdb_count = 0;
-    static const char *group_attrs[] = { SYSDB_NAME, NULL };
     struct ldb_dn *basedn;
     int ndirect;
     struct sysdb_attrs **direct_groups;
     char **sysdb_grouplist = NULL;
-    const char *tmp_str;
 
     tmp_ctx = talloc_new(NULL);
     if (!tmp_ctx) return ENOMEM;
@@ -813,58 +806,13 @@ static int sdap_initgr_nested_store_group(struct sysdb_ctx *sysdb,
     }
 
     /* Get direct sysdb parents */
-    group_dn = sysdb_group_strdn(tmp_ctx, dom->name, group_name);
-    if (!group_dn) {
-        ret = ENOMEM;
-        goto done;
-    }
-
-    member_filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)(%s=%s))",
-                                    SYSDB_OBJECTCLASS, SYSDB_GROUP_CLASS,
-                                    SYSDB_MEMBER, group_dn);
-    if (!member_filter) {
-        ret = ENOMEM;
-        goto done;
-    }
-
-    DEBUG(8, ("searching sysdb with filter %s\n", member_filter));
-
-    ret = sysdb_search_entry(tmp_ctx, sysdb, basedn,
-                             LDB_SCOPE_SUBTREE, member_filter, group_attrs,
-                             &direct_sysdb_count, &direct_sysdb_groups);
-    if (ret == EOK) {
-        /* Get the list of sysdb groups by name */
-        sysdb_grouplist = talloc_array(tmp_ctx, char *, direct_sysdb_count+1);
-        if (!sysdb_grouplist) {
-            ret = ENOMEM;
-            goto done;
-        }
-
-        for(i = 0; i < direct_sysdb_count; i++) {
-            tmp_str = ldb_msg_find_attr_as_string(direct_sysdb_groups[i],
-                                                SYSDB_NAME, NULL);
-            if (!tmp_str) {
-                /* This should never happen, but if it does, just continue */
-                continue;
-            }
-
-            sysdb_grouplist[i] = talloc_strdup(sysdb_grouplist, tmp_str);
-            if (!sysdb_grouplist[i]) {
-                DEBUG(1, ("A group with no name?\n"));
-                ret = EIO;
-                goto done;
-            }
-        }
-        sysdb_grouplist[i] = NULL;
-    } else if (ret == ENOENT) {
-        sysdb_grouplist = NULL;
-        direct_sysdb_count = 0;
-    } else {
-        DEBUG(2, ("sysdb_search_entry failed: [%d]: %s\n", ret, strerror(ret)));
+    ret = sysdb_get_direct_parents(tmp_ctx, sysdb, dom, SYSDB_MEMBER_GROUP,
+                                   group_name, &sysdb_grouplist);
+    if (ret) {
+        DEBUG(1, ("Could not get direct parents for %s: %d [%s]\n",
+                  group_name, ret, strerror(ret)));
         goto done;
     }
-    DEBUG(7, ("The group %s is a member of %d sysdb groups\n",
-              group_name, direct_sysdb_count));
 
     /* Filter only parents from full set */
     ret = sdap_initgr_nested_get_direct_parents(tmp_ctx, group, groups,
-- 
1.7.6.2

-------------- next part --------------
From 8ec58e0fdbeb52d60a6d83f511ee7715df5ccbd9 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 21 Sep 2011 10:50:18 +0200
Subject: [PATCH 3/4] Store name aliases for users, groups

Also checks fake users for aliases when storing a real users so that
getgrnam for a RFC2307 group that references a user by his secondary
name followed by getpwnam for this user by his primary name works
---
 src/providers/ldap/sdap_async.c            |   96 ++++++++++++++++++++
 src/providers/ldap/sdap_async.h            |    6 ++
 src/providers/ldap/sdap_async_groups.c     |  133 ++++++++++++++++++++--------
 src/providers/ldap/sdap_async_initgroups.c |    7 ++
 src/providers/ldap/sdap_async_users.c      |   25 +++++
 5 files changed, 230 insertions(+), 37 deletions(-)

diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c
index 0f9855b..c36c7e7 100644
--- a/src/providers/ldap/sdap_async.c
+++ b/src/providers/ldap/sdap_async.c
@@ -1887,3 +1887,99 @@ bool sdap_has_deref_support(struct sdap_handle *sh, struct sdap_options *opts)
 
     return false;
 }
+
+errno_t sdap_check_aliases(struct sysdb_ctx *sysdb,
+                           struct sysdb_attrs *user_attrs,
+                           struct sss_domain_info *dom,
+                           struct sdap_options *opts,
+                           bool steal_memberships)
+{
+    errno_t ret;
+    const char **aliases = NULL;
+    const char *name = NULL;
+    struct ldb_message *msg;
+    TALLOC_CTX *tmp_ctx = NULL;
+    char **parents;
+    uid_t alias_uid;
+    int i;
+
+    tmp_ctx = talloc_new(NULL);
+    if (!tmp_ctx) return ENOMEM;
+
+    ret = sysdb_attrs_primary_name(sysdb, user_attrs,
+                                   opts->user_map[SDAP_AT_USER_NAME].name,
+                                   &name);
+    if (ret != EOK) {
+        DEBUG(1, ("Could not get the primary name\n"));
+        goto done;
+    }
+
+    ret = sysdb_attrs_get_aliases(tmp_ctx, user_attrs, name, &aliases);
+    if (ret != EOK) {
+        DEBUG(1, ("Failed to get the alias list\n"));
+        goto done;
+    }
+
+    if (aliases == NULL) {
+        DEBUG(8, ("%s has no aliases\n", name));
+        ret = EOK;
+        goto done;
+    }
+
+    for (i = 0; aliases[i]; i++) {
+        /* In RFC2307 schema, another group might be referencing user
+         * using secondary name, so there might be fake users in the cache
+         * from a previous getgr call */
+        ret = sysdb_search_user_by_name(tmp_ctx, sysdb,
+                                        aliases[i], NULL, &msg);
+        if (ret && ret != ENOENT) {
+            DEBUG(1, ("Error searching the cache\n"));
+            goto done;
+        } else if (ret == ENOENT) {
+            DEBUG(9, ("No user with primary name same as alias %s\n", aliases[i]));
+            continue;
+        }
+
+        alias_uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
+        if (alias_uid) {
+            DEBUG(1, ("Cache contains non-fake user with same name "
+                      "as alias %s\n", aliases[i]));
+            ret = EIO;
+            goto done;
+        }
+        DEBUG(7, ("%s is a fake user\n", aliases[i]));
+
+        if (steal_memberships) {
+            /* Get direct sysdb parents */
+            ret = sysdb_get_direct_parents(tmp_ctx, sysdb, dom,
+                                           SYSDB_MEMBER_USER,
+                                           aliases[i], &parents);
+            if (ret) {
+                DEBUG(1, ("Could not get direct parents for %s: %d [%s]\n",
+                          aliases[i], ret, strerror(ret)));
+                goto done;
+            }
+
+            ret = sysdb_update_members(sysdb, name, SYSDB_MEMBER_USER,
+                                    (const char *const *) parents,
+                                    NULL);
+            if (ret != EOK) {
+                DEBUG(1, ("Membership update failed [%d]: %s\n",
+                          ret, strerror(ret)));
+                goto done;
+            }
+        }
+
+        ret = sysdb_delete_user(sysdb, aliases[i], alias_uid);
+        if (ret) {
+            DEBUG(1, ("Error deleting fake user %s\n", aliases[i]));
+            goto done;
+        }
+    }
+
+    ret = EOK;
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
index 9b5a307..8714e2b 100644
--- a/src/providers/ldap/sdap_async.h
+++ b/src/providers/ldap/sdap_async.h
@@ -169,4 +169,10 @@ int sdap_deref_search_recv(struct tevent_req *req,
                            TALLOC_CTX *mem_ctx,
                            size_t *reply_count,
                            struct sdap_deref_attrs ***reply);
+
+errno_t sdap_check_aliases(struct sysdb_ctx *sysdb,
+                           struct sysdb_attrs *user_attrs,
+                           struct sss_domain_info *dom,
+                           struct sdap_options *opts,
+                           bool steal_memberships);
 #endif /* _SDAP_ASYNC_H_ */
diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
index f887651..82352ac 100644
--- a/src/providers/ldap/sdap_async_groups.c
+++ b/src/providers/ldap/sdap_async_groups.c
@@ -222,9 +222,11 @@ static int sdap_save_group(TALLOC_CTX *memctx,
     const char *name = NULL;
     gid_t gid;
     int ret;
+    int i;
     char *usn_value = NULL;
     TALLOC_CTX *tmpctx = NULL;
     bool posix_group;
+    const char **aliases = NULL;
 
     tmpctx = talloc_new(memctx);
     if (!tmpctx) {
@@ -367,6 +369,24 @@ static int sdap_save_group(TALLOC_CTX *memctx,
         }
     }
 
+    ret = sysdb_attrs_get_aliases(tmpctx, attrs, name, &aliases);
+    if (ret != EOK) {
+        DEBUG(1, ("Failed to get the alias list\n"));
+        goto fail;
+    }
+
+    if (!aliases) {
+        DEBUG(7, ("Entry only contains the primary name\n"));
+    } else {
+        for (i = 0; aliases[i]; i++) {
+            ret = sysdb_attrs_add_string(group_attrs, SYSDB_NAME_ALIAS,
+                                         aliases[i]);
+            if (ret) {
+                goto fail;
+            }
+        }
+    }
+
     DEBUG(6, ("Storing info for group %s\n", name));
 
     ret = sdap_store_group_with_gid(group_attrs, ctx, dom,
@@ -853,17 +873,73 @@ sdap_process_group_members_2307bis(struct tevent_req *req,
 }
 
 static int
+sdap_add_group_member_2307(struct sdap_process_group_state *state,
+                           const char *username)
+{
+    char *strdn;
+
+    strdn = sysdb_user_strdn(state->sysdb_dns->values,
+                             state->dom->name, username);
+    if (!strdn) {
+        return ENOMEM;
+    }
+
+    state->sysdb_dns->values[state->sysdb_dns->num_values].data =
+            (uint8_t *) strdn;
+    state->sysdb_dns->values[state->sysdb_dns->num_values].length =
+            strlen(strdn);
+    state->sysdb_dns->num_values++;
+
+    return EOK;
+}
+
+static int
 sdap_process_missing_member_2307(struct sdap_process_group_state *state,
-                                 char *username, bool *in_transaction)
+                                 char *member_name, bool *in_transaction)
 {
     int ret, sret;
-    struct ldb_dn *dn;
-    char* dn_string;
-
-    DEBUG(7, ("Adding a dummy entry\n"));
+    TALLOC_CTX *tmp_ctx;
+    const char *filter;
+    const char *username;
+    size_t count;
+    struct ldb_message **msgs = NULL;
+    static const char *attrs[] = { SYSDB_NAME, NULL };
 
     if (!in_transaction) return EINVAL;
 
+    tmp_ctx = talloc_new(NULL);
+    if (!tmp_ctx) return ENOMEM;
+
+    /* Check for the alias in the sysdb */
+    filter = talloc_asprintf(tmp_ctx, "(%s=%s)", SYSDB_NAME_ALIAS, member_name);
+    if (!filter) {
+        ret = ENOMEM;
+        goto fail;
+    }
+
+    ret = sysdb_search_users(tmp_ctx, state->sysdb, filter,
+                             attrs, &count, &msgs);
+    if (ret == EOK && count > 0) {
+        /* Entry exists but the group references it with an alias. */
+
+        if (count != 1) {
+            DEBUG(1, ("More than one entry with this alias?\n"));
+            ret = EIO;
+            goto fail;
+        }
+
+        /* fill username with primary name */
+        username = ldb_msg_find_attr_as_string(msgs[0], SYSDB_NAME, NULL);
+        goto done;
+    } else if (ret != EOK && ret != ENOENT) {
+        ret = EIO;
+        goto fail;
+    }
+
+    username = member_name;
+    /* The entry really does not exist, add a fake entry */
+    DEBUG(7, ("Adding a dummy entry\n"));
+
     if (!*in_transaction) {
         ret = sysdb_transaction_start(state->sysdb);
         if (ret != EOK) {
@@ -885,27 +961,17 @@ sdap_process_missing_member_2307(struct sdap_process_group_state *state,
      * Convert the just received DN into the corresponding sysdb DN
      * for saving into member attribute of the group
      */
-    dn = sysdb_user_dn(state->sysdb, state, state->dom->name,
-                       (char*) username);
-    if (!dn) {
-        ret = ENOMEM;
-        goto fail;
-    }
-
-    dn_string = ldb_dn_alloc_linearized(state->sysdb_dns->values, dn);
-    if (!dn_string) {
-        ret = ENOMEM;
+done:
+    ret = sdap_add_group_member_2307(state, username);
+    if (ret != EOK) {
+        DEBUG(1, ("Could not add group member %s\n", username));
         goto fail;
     }
 
-    state->sysdb_dns->values[state->sysdb_dns->num_values].data =
-            (uint8_t *) dn_string;
-    state->sysdb_dns->values[state->sysdb_dns->num_values].length =
-            strlen(dn_string);
-    state->sysdb_dns->num_values++;
-
+    talloc_free(tmp_ctx);
     return EOK;
 fail:
+    talloc_free(tmp_ctx);
     if (*in_transaction) {
         sret = sysdb_transaction_cancel(state->sysdb);
         if (sret == EOK) {
@@ -925,7 +991,6 @@ sdap_process_group_members_2307(struct sdap_process_group_state *state,
     struct ldb_message *msg;
     bool in_transaction = false;
     char *member_name;
-    char *strdn;
     int ret;
     errno_t sret;
     int i;
@@ -939,23 +1004,17 @@ sdap_process_group_members_2307(struct sdap_process_group_state *state,
         ret = sysdb_search_user_by_name(state, state->sysdb,
                                         member_name, NULL, &msg);
         if (ret == EOK) {
-            strdn = sysdb_user_strdn(state->sysdb_dns->values,
-                                     state->dom->name,
-                                     member_name);
-            if (!strdn) {
-                ret = ENOMEM;
+            /*
+             * User already cached in sysdb. Remember the sysdb DN for later
+             * use by sdap_save_groups()
+             */
+            DEBUG(7, ("Member already cached in sysdb: %s\n", member_name));
+
+            ret = sdap_add_group_member_2307(state, member_name);
+            if (ret != EOK) {
+                DEBUG(1, ("Could not add member %s into sysdb\n", member_name));
                 goto done;
             }
-            /*
-            * User already cached in sysdb. Remember the sysdb DN for later
-            * use by sdap_save_groups()
-            */
-            DEBUG(7,("Member already cached in sysdb: %s\n", strdn));
-            state->sysdb_dns->values[state->sysdb_dns->num_values].data =
-                    (uint8_t *) strdn;
-            state->sysdb_dns->values[state->sysdb_dns->num_values].length =
-                    strlen(strdn);
-            state->sysdb_dns->num_values++;
         } else if (ret == ENOENT) {
             /* The user is not in sysdb, need to add it */
             DEBUG(7, ("member #%d (%s): not found in sysdb\n",
diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
index f5c3707..4cf5a53 100644
--- a/src/providers/ldap/sdap_async_initgroups.c
+++ b/src/providers/ldap/sdap_async_initgroups.c
@@ -1851,6 +1851,13 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
 
     switch (state->opts->schema_type) {
     case SDAP_SCHEMA_RFC2307:
+        ret = sdap_check_aliases(state->sysdb, state->orig_user, state->dom,
+                                 state->opts, false);
+        if (ret != EOK) {
+            tevent_req_error(req, ret);
+            return;
+        }
+
         subreq = sdap_initgr_rfc2307_send(state, state->ev, state->opts,
                                     state->sysdb, state->dom, state->sh,
                                     dp_opt_get_string(state->opts->basic,
diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c
index 82338dc..d7fa17f 100644
--- a/src/providers/ldap/sdap_async_users.c
+++ b/src/providers/ldap/sdap_async_users.c
@@ -56,6 +56,7 @@ int sdap_save_user(TALLOC_CTX *memctx,
     char *usn_value = NULL;
     size_t c;
     char **missing = NULL;
+    const char **aliases = NULL;
     TALLOC_CTX *tmpctx = NULL;
 
     DEBUG(9, ("Save user\n"));
@@ -282,6 +283,24 @@ int sdap_save_user(TALLOC_CTX *memctx,
         }
     }
 
+    ret = sysdb_attrs_get_aliases(tmpctx, attrs, name, &aliases);
+    if (ret != EOK) {
+        DEBUG(1, ("Failed to get the alias list"));
+        goto fail;
+    }
+
+    if (!aliases) {
+        DEBUG(7, ("Entry only contains the primary name\n"));
+    } else {
+        for (i = 0; aliases[i]; i++) {
+            ret = sysdb_attrs_add_string(user_attrs, SYSDB_NAME_ALIAS,
+                                         aliases[i]);
+            if (ret) {
+                goto fail;
+            }
+        }
+    }
+
     /* Make sure that any attributes we requested from LDAP that we
      * did not receive are also removed from the sysdb
      */
@@ -366,6 +385,12 @@ int sdap_save_users(TALLOC_CTX *memctx,
             DEBUG(9, ("User %d processed!\n", i));
         }
 
+        ret = sdap_check_aliases(sysdb, users[i], dom,
+                                 opts, true);
+        if (ret) {
+            DEBUG(2, ("Failed to check aliases for user %d. Ignoring.\n", i));
+        }
+
         if (usn_value) {
             if (higher_usn) {
                 if ((strlen(usn_value) > strlen(higher_usn)) ||
-- 
1.7.6.2

-------------- next part --------------
From b218e63b3a55642fb1b0bdd7a77c78ecb6369442 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 21 Sep 2011 12:51:49 +0200
Subject: [PATCH 4/4] Return users and groups based on alias

https://fedorahosted.org/sssd/ticket/926
---
 src/db/sysdb.h                       |    6 +++---
 src/db/sysdb_search.c                |    7 ++++---
 src/responder/pam/pam_LOCAL_domain.c |    5 +++--
 3 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 138e7df..2985a1a 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -108,15 +108,15 @@
 #define SYSDB_NC "objectclass="SYSDB_NETGROUP_CLASS
 #define SYSDB_MPGC "|("SYSDB_UC")("SYSDB_GC")"
 
-#define SYSDB_PWNAM_FILTER "(&("SYSDB_UC")("SYSDB_NAME"=%s))"
+#define SYSDB_PWNAM_FILTER "(&("SYSDB_UC")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))"
 #define SYSDB_PWUID_FILTER "(&("SYSDB_UC")("SYSDB_UIDNUM"=%lu))"
 #define SYSDB_PWENT_FILTER "("SYSDB_UC")"
 
-#define SYSDB_GRNAM_FILTER "(&("SYSDB_GC")("SYSDB_NAME"=%s))"
+#define SYSDB_GRNAM_FILTER "(&("SYSDB_GC")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))"
 #define SYSDB_GRNA2_FILTER "(&("SYSDB_UC")("SYSDB_MEMBEROF"=%s))"
 #define SYSDB_GRGID_FILTER "(&("SYSDB_GC")("SYSDB_GIDNUM"=%lu))"
 #define SYSDB_GRENT_FILTER "("SYSDB_GC")"
-#define SYSDB_GRNAM_MPG_FILTER "(&("SYSDB_MPGC")("SYSDB_NAME"=%s))"
+#define SYSDB_GRNAM_MPG_FILTER "(&("SYSDB_MPGC")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))"
 #define SYSDB_GRGID_MPG_FILTER "(&("SYSDB_MPGC")("SYSDB_GIDNUM"=%lu))"
 #define SYSDB_GRENT_MPG_FILTER "("SYSDB_MPGC")"
 
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
index 4859ffb..f356908 100644
--- a/src/db/sysdb_search.c
+++ b/src/db/sysdb_search.c
@@ -58,7 +58,7 @@ int sysdb_getpwnam(TALLOC_CTX *mem_ctx,
 
     ret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn,
                      LDB_SCOPE_SUBTREE, attrs, SYSDB_PWNAM_FILTER,
-                     sanitized_name);
+                     sanitized_name, sanitized_name);
     if (ret) {
         ret = sysdb_error_to_errno(ret);
         goto done;
@@ -228,7 +228,7 @@ int sysdb_getgrnam(TALLOC_CTX *mem_ctx,
 
     ret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn,
                      LDB_SCOPE_SUBTREE, attrs, fmt_filter,
-                     sanitized_name);
+                     sanitized_name, sanitized_name);
     if (ret) {
         ret = sysdb_error_to_errno(ret);
         goto done;
@@ -476,7 +476,8 @@ int sysdb_get_user_attr(TALLOC_CTX *mem_ctx,
 
     ret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn,
                      LDB_SCOPE_SUBTREE, attributes,
-                     SYSDB_PWNAM_FILTER, sanitized_name);
+                     SYSDB_PWNAM_FILTER, sanitized_name,
+                     sanitized_name);
     if (ret) {
         ret = sysdb_error_to_errno(ret);
         goto done;
diff --git a/src/responder/pam/pam_LOCAL_domain.c b/src/responder/pam/pam_LOCAL_domain.c
index 66f3a88..baf8cc6 100644
--- a/src/responder/pam/pam_LOCAL_domain.c
+++ b/src/responder/pam/pam_LOCAL_domain.c
@@ -258,11 +258,12 @@ int LOCAL_pam_handler(struct pam_auth_req *preq)
 
     if (res->count < 1) {
         DEBUG(4, ("No user found with filter ["SYSDB_PWNAM_FILTER"]\n",
-                  pd->user));
+                  pd->user, pd->user));
         pd->pam_status = PAM_USER_UNKNOWN;
         goto done;
     } else if (res->count > 1) {
-        DEBUG(4, ("More than one object found with filter ["SYSDB_PWNAM_FILTER"]\n"));
+        DEBUG(4, ("More than one object found with filter ["SYSDB_PWNAM_FILTER"]\n",
+                  pd->user, pd->user));
         lreq->error = EFAULT;
         goto done;
     }
-- 
1.7.6.2



More information about the sssd-devel mailing list