[SSSD] [PATCH] Canonicalize user aliases in the proxy provider

Jakub Hrozek jhrozek at redhat.com
Wed Apr 18 19:56:21 UTC 2012


On Wed, Apr 18, 2012 at 12:36:58PM -0400, Stephen Gallagher wrote:
> On Thu, 2012-04-12 at 20:01 +0200, Jakub Hrozek wrote:
> > On Thu, Apr 05, 2012 at 04:02:41PM -0700, Stephen Gallagher wrote:
> > > On Thu, 2012-03-29 at 16:27 -0400, Jakub Hrozek wrote:
> > > > https://fedorahosted.org/sssd/ticket/1249
> > > > 
> > > > The patch also reduces code duplication between several error handling
> > > > switch/case statements and fixes a bug in get_initgr where we would try
> > > > to cancel a transaction immediately after committing it.
> > > > 
> > > > Do we also want to canonicalize group names in a similar fashion? To be
> > > > honest, downloading the whole group twice just for the sake of
> > > > determining the correct group name seems a little too much to me..
> > > 
> > > Nack. As Jakub and I discussed on IRC, we do need to canonicalize group
> > > names for correctness' sake. We can also opt to add a new option to
> > > prioritize speed over correctness.
> > 
> > I'm sorry for the delay. Attached are two patches - one that always
> > canonicalizes group and user names and one that adds a new option to
> > canonicalize from cache.
> 
> 
> Patch 0001:
> Ack
> 
> Patch 0002: Nack (minor)
> 
> Please lower the debug level on the cache-miss for sysdb_get*id(). It's
> going to be fairly common and SSSDBG_MINOR_FAILURE is too noisy. Use
> SSSDBG_TRACE_FUNC instead.
> 
> 

Right, fixed patches are attached.
-------------- next part --------------
>From 0b82bec477b89704001218e833ade97e91032e79 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 28 Mar 2012 01:04:52 +0200
Subject: [PATCH 1/2] proxy: Canonicalize user and group names

https://fedorahosted.org/sssd/ticket/1249
---
 src/providers/proxy/proxy_id.c |  680 +++++++++++++++++++++-------------------
 1 files changed, 361 insertions(+), 319 deletions(-)

diff --git a/src/providers/proxy/proxy_id.c b/src/providers/proxy/proxy_id.c
index 4f2dbd882df437a14b123de4d046590c2d52c733..d92fc4eacfc6f3801a19d6577e39d1b202b53bd0 100644
--- a/src/providers/proxy/proxy_id.c
+++ b/src/providers/proxy/proxy_id.c
@@ -27,11 +27,13 @@
 
 /* =Getpwnam-wrapper======================================================*/
 
-static int delete_user(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
-                       struct sss_domain_info *domain, const char *name);
-
 static int save_user(struct sysdb_ctx *sysdb, bool lowercase,
-                     struct passwd *pwd, uint64_t cache_timeout);
+                     struct passwd *pwd, const char *alias,
+                     uint64_t cache_timeout);
+
+static int
+handle_getpw_result(enum nss_status status, struct passwd *pwd,
+                    struct sss_domain_info *dom, bool *del_user);
 
 static int get_pw_name(TALLOC_CTX *mem_ctx,
                        struct proxy_id_ctx *ctx,
@@ -45,10 +47,12 @@ static int get_pw_name(TALLOC_CTX *mem_ctx,
     char *buffer;
     size_t buflen;
     int ret;
+    uid_t uid;
+    bool del_user;
 
-    DEBUG(7, ("Searching user by name (%s)\n", name));
+    DEBUG(SSSDBG_TRACE_FUNC, ("Searching user by name (%s)\n", name));
 
-    tmpctx = talloc_new(mem_ctx);
+    tmpctx = talloc_new(NULL);
     if (!tmpctx) {
         return ENOMEM;
     }
@@ -71,67 +75,114 @@ static int get_pw_name(TALLOC_CTX *mem_ctx,
     /* FIXME: should we move this call outside the transaction to keep the
      * transaction as short as possible ? */
     status = ctx->ops.getpwnam_r(name, pwd, buffer, buflen, &ret);
+    ret = handle_getpw_result(status, pwd, dom, &del_user);
+    if (ret) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("getpwnam failed [%d]: %s\n", ret, strerror(ret)));
+        goto done;
+    }
+
+    if (del_user) {
+        DEBUG(SSSDBG_TRACE_FUNC,
+              ("User %s does not exist (or is invalid) on remote server,"
+               " deleting!\n", name));
+        ret = sysdb_delete_user(sysdb, name, 0);
+        goto done;
+    }
+
+    uid = pwd->pw_uid;
+    memset(buffer, 0, buflen);
+
+    /* Canonicalize the username in case it was actually an alias */
+    status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret);
+    ret = handle_getpw_result(status, pwd, dom, &del_user);
+    if (ret) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("getpwuid failed [%d]: %s\n", ret, strerror(ret)));
+        goto done;
+    }
+
+    if (del_user) {
+        DEBUG(SSSDBG_TRACE_FUNC,
+              ("User %s does not exist (or is invalid) on remote server,"
+               " deleting!\n", name));
+        ret = sysdb_delete_user(sysdb, name, uid);
+        goto done;
+    }
+
+    /* Both lookups went fine, we can save the user now */
+    ret = save_user(sysdb, !dom->case_sensitive, pwd,
+                    name, dom->user_timeout);
+
+done:
+    talloc_zfree(tmpctx);
+    if (ret) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("proxy -> getpwnam_r failed for '%s' <%d>\n",
+               name, status));
+    }
+    return ret;
+}
+
+static int
+handle_getpw_result(enum nss_status status, struct passwd *pwd,
+                    struct sss_domain_info *dom, bool *del_user)
+{
+    int ret = EOK;
+
+    if (!del_user) {
+        return EINVAL;
+    }
+    *del_user = false;
 
     switch (status) {
     case NSS_STATUS_NOTFOUND:
 
-        DEBUG(7, ("User %s not found.\n", name));
-        ret = delete_user(tmpctx, sysdb, dom, name);
-        if (ret) {
-            goto done;
-        }
+        DEBUG(SSSDBG_MINOR_FAILURE, ("User not found.\n"));
+        *del_user = true;
         break;
 
     case NSS_STATUS_SUCCESS:
 
-        DEBUG(7, ("User %s found: (%s, %d, %d)\n",
-                  name, pwd->pw_name, pwd->pw_uid, pwd->pw_gid));
+        DEBUG(SSSDBG_TRACE_FUNC, ("User found: (%s, %d, %d)\n",
+              pwd->pw_name, pwd->pw_uid, pwd->pw_gid));
 
         /* uid=0 or gid=0 are invalid values */
         /* also check that the id is in the valid range for this domain */
         if (OUT_OF_ID_RANGE(pwd->pw_uid, dom->id_min, dom->id_max) ||
             OUT_OF_ID_RANGE(pwd->pw_gid, dom->id_min, dom->id_max)) {
 
-            DEBUG(2, ("User [%s] filtered out! (id out of range)\n", name));
-            ret = delete_user(tmpctx, sysdb, dom, name);
-            if (ret) {
-                goto done;
-            }
+            DEBUG(SSSDBG_MINOR_FAILURE,
+                  ("User filtered out! (id out of range)\n"));
+            *del_user = true;
             break;
         }
-
-        ret = save_user(sysdb, !dom->case_sensitive, pwd, dom->user_timeout);
-        if (ret) {
-            goto done;
-        }
         break;
 
     case NSS_STATUS_UNAVAIL:
-        /* "remote" backend unavailable. Enter offline mode */
+        DEBUG(SSSDBG_MINOR_FAILURE,
+              ("Remote back end is not available. Entering offline mode\n"));
         ret = ENXIO;
-        goto done;
+        break;
 
     default:
+        DEBUG(SSSDBG_OP_FAILURE, ("Unknown return code %d\n", status));
         ret = EIO;
-        goto done;
+        break;
     }
 
-done:
-    talloc_zfree(tmpctx);
-    if (ret) {
-        DEBUG(2, ("proxy -> getpwnam_r failed for '%s' <%d>\n",
-                  name, status));
-    }
     return ret;
 }
 
 static int save_user(struct sysdb_ctx *sysdb, bool lowercase,
-                     struct passwd *pwd, uint64_t cache_timeout)
+                     struct passwd *pwd, const char *alias,
+                     uint64_t cache_timeout)
 {
     const char *shell;
     char *lower;
     struct sysdb_attrs *attrs = NULL;
     errno_t ret;
+    const char *cased_alias;
 
     if (pwd->pw_shell && pwd->pw_shell[0] != '\0') {
         shell = pwd->pw_shell;
@@ -139,13 +190,15 @@ static int save_user(struct sysdb_ctx *sysdb, bool lowercase,
         shell = NULL;
     }
 
-    if (lowercase) {
+    if (!lowercase || alias) {
         attrs = sysdb_new_attrs(NULL);
         if (!attrs) {
             DEBUG(SSSDBG_CRIT_FAILURE, ("Allocation error ?!\n"));
             return ENOMEM;
         }
+    }
 
+    if (lowercase) {
         lower = sss_tc_utf8_str_tolower(attrs, pwd->pw_name);
         if (!lower) {
             DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot convert name to lowercase\n"));
@@ -161,6 +214,21 @@ static int save_user(struct sysdb_ctx *sysdb, bool lowercase,
         }
     }
 
+    if (alias) {
+        cased_alias = sss_get_cased_name(attrs, alias, !lowercase);
+        if (!cased_alias) {
+            talloc_zfree(attrs);
+            return ENOMEM;
+        }
+
+        ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, cased_alias);
+        if (ret) {
+            DEBUG(SSSDBG_OP_FAILURE, ("Could not add name alias\n"));
+            talloc_zfree(attrs);
+            return ret;
+        }
+    }
+
     ret = sysdb_store_user(sysdb,
                            pwd->pw_name,
                            pwd->pw_passwd,
@@ -182,22 +250,6 @@ static int save_user(struct sysdb_ctx *sysdb, bool lowercase,
     return EOK;
 }
 
-static int delete_user(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
-                       struct sss_domain_info *domain, const char *name)
-{
-    struct ldb_dn *dn;
-
-    DEBUG(7, ("User %s does not exist (or is invalid) on remote server,"
-              " deleting!\n", name));
-
-    dn = sysdb_user_dn(sysdb, mem_ctx, domain->name, name);
-    if (!dn) {
-        return ENOMEM;
-    }
-
-    return sysdb_delete_entry(sysdb, dn, true);
-}
-
 /* =Getpwuid-wrapper======================================================*/
 
 static int get_pw_uid(TALLOC_CTX *mem_ctx,
@@ -214,9 +266,9 @@ static int get_pw_uid(TALLOC_CTX *mem_ctx,
     bool del_user = false;
     int ret;
 
-    DEBUG(7, ("Searching user by uid (%d)\n", uid));
+    DEBUG(SSSDBG_TRACE_FUNC, ("Searching user by uid (%d)\n", uid));
 
-    tmpctx = talloc_new(mem_ctx);
+    tmpctx = talloc_new(NULL);
     if (!tmpctx) {
         return ENOMEM;
     }
@@ -224,75 +276,40 @@ static int get_pw_uid(TALLOC_CTX *mem_ctx,
     pwd = talloc_zero(tmpctx, struct passwd);
     if (!pwd) {
         ret = ENOMEM;
-        DEBUG(1, ("proxy -> getpwuid_r failed for '%d': [%d] %s\n",
-                  uid, ret, strerror(ret)));
-        return ret;
+        goto done;
     }
 
     buflen = DEFAULT_BUFSIZE;
     buffer = talloc_size(tmpctx, buflen);
     if (!buffer) {
         ret = ENOMEM;
-        DEBUG(1, ("proxy -> getpwuid_r failed for '%d': [%d] %s\n",
-                  uid, ret, strerror(ret)));
-        return ret;
+        goto done;
     }
 
     status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret);
-
-    switch (status) {
-    case NSS_STATUS_NOTFOUND:
-
-        DEBUG(7, ("User %d not found.\n", uid));
-        del_user = true;
-        break;
-
-    case NSS_STATUS_SUCCESS:
-
-        DEBUG(7, ("User %d found (%s, %d, %d)\n",
-                  uid, pwd->pw_name, pwd->pw_uid, pwd->pw_gid));
-
-        /* uid=0 or gid=0 are invalid values */
-        /* also check that the id is in the valid range for this domain */
-        if (OUT_OF_ID_RANGE(pwd->pw_uid, dom->id_min, dom->id_max) ||
-            OUT_OF_ID_RANGE(pwd->pw_gid, dom->id_min, dom->id_max)) {
-
-            DEBUG(2, ("User [%s] filtered out! (id out of range)\n",
-                      pwd->pw_name));
-            del_user = true;
-            break;
-        }
-
-        ret = save_user(sysdb, !dom->case_sensitive, pwd, dom->user_timeout);
-        if (ret) {
-            goto done;
-        }
-        break;
-
-    case NSS_STATUS_UNAVAIL:
-        /* "remote" backend unavailable. Enter offline mode */
-        ret = ENXIO;
-        goto done;
-
-    default:
-        ret = EIO;
+    ret = handle_getpw_result(status, pwd, dom, &del_user);
+    if (ret) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("getpwuid failed [%d]: %s\n", ret, strerror(ret)));
         goto done;
     }
 
     if (del_user) {
-        DEBUG(7, ("User %d does not exist (or is invalid) on remote server,"
-                  " deleting!\n", uid));
-
+        DEBUG(SSSDBG_TRACE_FUNC,
+              ("User %d does not exist (or is invalid) on remote server,"
+               " deleting!\n", uid));
         ret = sysdb_delete_user(sysdb, NULL, uid);
-        if (ret) {
-            goto done;
-        }
+        goto done;
     }
 
+    ret = save_user(sysdb, !dom->case_sensitive, pwd,
+                    NULL, dom->user_timeout);
+
 done:
     talloc_zfree(tmpctx);
     if (ret) {
-        DEBUG(2, ("proxy -> getpwuid_r failed for '%d' <%d>\n", uid, status));
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              ("proxy -> getpwuid_r failed for '%d' <%d>\n", uid, status));
     }
     return ret;
 }
@@ -394,7 +411,8 @@ again:
             goto again; /* skip */
         }
 
-        ret = save_user(sysdb, !dom->case_sensitive, pwd, dom->user_timeout);
+        ret = save_user(sysdb, !dom->case_sensitive, pwd,
+                        NULL, dom->user_timeout);
         if (ret) {
             /* Do not fail completely on errors.
              * Just report the failure to save and go on */
@@ -448,11 +466,13 @@ static errno_t proxy_process_missing_users(struct sysdb_ctx *sysdb,
                                            struct group *grp,
                                            time_t now);
 static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom,
-                      struct group *grp, uint64_t cache_timeout)
+                      struct group *grp, const char *alias,
+                      uint64_t cache_timeout)
 {
     errno_t ret, sret;
     struct sysdb_attrs *attrs = NULL;
     char *lower;
+    const char *cased_alias;
     TALLOC_CTX *tmp_ctx;
     time_t now = time(NULL);
     bool in_transaction = false;
@@ -492,7 +512,7 @@ static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom,
         }
     }
 
-    if (dom->case_sensitive == false) {
+    if (dom->case_sensitive == false || alias) {
         if (!attrs) {
             attrs = sysdb_new_attrs(tmp_ctx);
             if (!attrs) {
@@ -502,18 +522,35 @@ static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom,
             }
         }
 
-        lower = sss_tc_utf8_str_tolower(attrs, grp->gr_name);
-        if (!lower) {
-            DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot convert name to lowercase\n"));
-            ret = ENOMEM;
-            goto done;
+        if (dom->case_sensitive == false) {
+            lower = sss_tc_utf8_str_tolower(attrs, grp->gr_name);
+            if (!lower) {
+                DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot convert name to lowercase\n"));
+                ret = ENOMEM;
+                goto done;
+            }
+
+            ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, lower);
+            if (ret) {
+                DEBUG(SSSDBG_OP_FAILURE, ("Could not add name alias\n"));
+                ret = ENOMEM;
+                goto done;
+            }
         }
 
-        ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, lower);
-        if (ret) {
-            DEBUG(SSSDBG_OP_FAILURE, ("Could not add name alias\n"));
-            ret = ENOMEM;
-            goto done;
+        if (alias) {
+            cased_alias = sss_get_cased_name(attrs, alias, dom->case_sensitive);
+            if (!cased_alias) {
+                talloc_zfree(attrs);
+                return ENOMEM;
+            }
+
+            ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, cased_alias);
+            if (ret) {
+                DEBUG(SSSDBG_OP_FAILURE, ("Could not add name alias\n"));
+                ret = ENOMEM;
+                goto done;
+            }
         }
     }
 
@@ -600,6 +637,73 @@ done:
 }
 
 /* =Getgrnam-wrapper======================================================*/
+static char *
+grow_group_buffer(TALLOC_CTX *mem_ctx,
+                  char **buffer, size_t *buflen)
+{
+    char *newbuf;
+
+    if (*buflen == 0) {
+        *buflen = DEFAULT_BUFSIZE;
+    }
+    if (*buflen < MAX_BUF_SIZE) {
+        *buflen *= 2;
+    }
+    if (*buflen > MAX_BUF_SIZE) {
+        *buflen = MAX_BUF_SIZE;
+    }
+
+    newbuf = talloc_realloc_size(mem_ctx, *buffer, *buflen);
+    if (!newbuf) {
+        return NULL;
+    }
+    *buffer = newbuf;
+
+    return *buffer;
+}
+
+static errno_t
+handle_getgr_result(enum nss_status status, struct group *grp,
+                    struct sss_domain_info *dom,
+                    bool *delete_group)
+{
+    switch (status) {
+    case NSS_STATUS_TRYAGAIN:
+        DEBUG(SSSDBG_MINOR_FAILURE, ("Buffer too small\n"));
+        return EAGAIN;
+
+    case NSS_STATUS_NOTFOUND:
+        DEBUG(SSSDBG_MINOR_FAILURE, ("Group not found.\n"));
+        *delete_group = true;
+        break;
+
+    case NSS_STATUS_SUCCESS:
+        DEBUG(SSSDBG_FUNC_DATA, ("Group found: (%s, %d)\n",
+              grp->gr_name, grp->gr_gid));
+
+        /* gid=0 is an invalid value */
+        /* also check that the id is in the valid range for this domain */
+        if (OUT_OF_ID_RANGE(grp->gr_gid, dom->id_min, dom->id_max)) {
+            DEBUG(SSSDBG_MINOR_FAILURE,
+                  ("Group filtered out! (id out of range)\n"));
+            *delete_group = true;
+            break;
+        }
+        break;
+
+    case NSS_STATUS_UNAVAIL:
+        DEBUG(SSSDBG_MINOR_FAILURE,
+              ("Remote back end is not available. Entering offline mode\n"));
+        return ENXIO;
+
+    default:
+        DEBUG(SSSDBG_OP_FAILURE, ("Unknown return code %d\n", status));
+        return EIO;
+    }
+
+    return EOK;
+}
+
 static int get_gr_name(TALLOC_CTX *mem_ctx,
                        struct proxy_id_ctx *ctx,
                        struct sysdb_ctx *sysdb,
@@ -609,15 +713,15 @@ static int get_gr_name(TALLOC_CTX *mem_ctx,
     TALLOC_CTX *tmpctx;
     struct group *grp;
     enum nss_status status;
-    char *buffer;
-    char *newbuf;
-    size_t buflen;
+    char *buffer = 0;
+    size_t buflen = 0;
     bool delete_group = false;
     int ret;
+    gid_t gid;
 
-    DEBUG(7, ("Searching group by name (%s)\n", name));
+    DEBUG(SSSDBG_FUNC_DATA, ("Searching group by name (%s)\n", name));
 
-    tmpctx = talloc_new(mem_ctx);
+    tmpctx = talloc_new(NULL);
     if (!tmpctx) {
         return ENOMEM;
     }
@@ -625,111 +729,83 @@ static int get_gr_name(TALLOC_CTX *mem_ctx,
     grp = talloc(tmpctx, struct group);
     if (!grp) {
         ret = ENOMEM;
-        DEBUG(1, ("proxy -> getgrnam_r failed for '%s': [%d] %s\n",
-                  name, ret, strerror(ret)));
-        return ret;
-    }
-
-    buflen = DEFAULT_BUFSIZE;
-    buffer = talloc_size(tmpctx, buflen);
-    if (!buffer) {
-        ret = ENOMEM;
-        DEBUG(1, ("proxy -> getgrnam_r failed for '%s': [%d] %s\n",
-                  name, ret, strerror(ret)));
-        return ret;
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              ("proxy -> getgrnam_r failed for '%s': [%d] %s\n",
+              name, ret, strerror(ret)));
+        goto done;
     }
 
-    /* FIXME: should we move this call outside the transaction to keep the
-     * transaction as short as possible ? */
-again:
-    /* always zero out the grp structure */
-    memset(grp, 0, sizeof(struct group));
-
-    status = ctx->ops.getgrnam_r(name, grp, buffer, buflen, &ret);
-
-    switch (status) {
-    case NSS_STATUS_TRYAGAIN:
-        /* buffer too small ? */
-        if (buflen < MAX_BUF_SIZE) {
-            buflen *= 2;
-        }
-        if (buflen > MAX_BUF_SIZE) {
-            buflen = MAX_BUF_SIZE;
-        }
-        newbuf = talloc_realloc_size(tmpctx, buffer, buflen);
-        if (!newbuf) {
+    do {
+        /* always zero out the grp structure */
+        memset(grp, 0, sizeof(struct group));
+        buffer = grow_group_buffer(tmpctx, &buffer, &buflen);
+        if (!buffer) {
             ret = ENOMEM;
             goto done;
         }
-        buffer = newbuf;
-        goto again;
-
-    case NSS_STATUS_NOTFOUND:
 
-        DEBUG(7, ("Group %s not found.\n", name));
-        delete_group = true;
-        break;
+        status = ctx->ops.getgrnam_r(name, grp, buffer, buflen, &ret);
 
-    case NSS_STATUS_SUCCESS:
+        ret = handle_getgr_result(status, grp, dom, &delete_group);
+    } while (ret == EAGAIN);
 
-        DEBUG(7, ("Group %s found: (%s, %d)\n",
-                  name, grp->gr_name, grp->gr_gid));
-
-        /* gid=0 is an invalid value */
-        /* also check that the id is in the valid range for this domain */
-        if (OUT_OF_ID_RANGE(grp->gr_gid, dom->id_min, dom->id_max)) {
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("getgrnam failed [%d]: %s\n", ret, strerror(ret)));
+        goto done;
+    }
 
-                DEBUG(2, ("Group [%s] filtered out! (id out of range)\n",
-                          name));
-            delete_group = true;
-            break;
-        }
+    gid = grp->gr_gid;
+    talloc_zfree(buffer);
+    buflen = 0;
 
-        ret = save_group(sysdb, dom, grp, dom->group_timeout);
-        if (ret) {
+    /* Canonicalize the group name in case it was actually an alias */
+    do {
+        memset(grp, 0, sizeof(struct group));
+        buffer = grow_group_buffer(tmpctx, &buffer, &buflen);
+        if (!buffer) {
+            ret = ENOMEM;
             goto done;
         }
-        break;
 
-    case NSS_STATUS_UNAVAIL:
-        /* "remote" backend unavailable. Enter offline mode */
-        ret = ENXIO;
-        goto done;
+        status = ctx->ops.getgrgid_r(gid, grp, buffer, buflen, &ret);
+
+        ret = handle_getgr_result(status, grp, dom, &delete_group);
+    } while(ret == EAGAIN);
 
-    default:
-        ret = EIO;
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("getgrgid failed [%d]: %s\n", ret, strerror(ret)));
         goto done;
     }
 
     if (delete_group) {
-        struct ldb_dn *dn;
+        DEBUG(SSSDBG_TRACE_FUNC,
+              ("Group %s does not exist (or is invalid) on remote server,"
+               " deleting!\n", name));
 
-        DEBUG(7, ("Group %s does not exist (or is invalid) on remote server,"
-                  " deleting!\n", name));
+        ret = sysdb_delete_group(sysdb, NULL, gid);
+        goto done;
+    }
 
-        dn = sysdb_group_dn(sysdb, tmpctx, dom->name, name);
-        if (!dn) {
-            ret = ENOMEM;
-            goto done;
-        }
-
-        ret = sysdb_delete_entry(sysdb, dn, true);
-        if (ret) {
-            goto done;
-        }
+    ret = save_group(sysdb, dom, grp, name, dom->group_timeout);
+    if (ret) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("Cannot save group [%d]: %s\n", ret, strerror(ret)));
+        goto done;
     }
 
 done:
     talloc_zfree(tmpctx);
     if (ret) {
-        DEBUG(2, ("proxy -> getgrnam_r failed for '%s' <%d>\n",
-                  name, status));
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("proxy -> getgrnam_r failed for '%s' <%d>\n",
+              name, status));
     }
     return ret;
 }
 
 /* =Getgrgid-wrapper======================================================*/
-
 static int get_gr_gid(TALLOC_CTX *mem_ctx,
                       struct proxy_id_ctx *ctx,
                       struct sysdb_ctx *sysdb,
@@ -740,13 +816,12 @@ static int get_gr_gid(TALLOC_CTX *mem_ctx,
     TALLOC_CTX *tmpctx;
     struct group *grp;
     enum nss_status status;
-    char *buffer;
-    char *newbuf;
-    size_t buflen;
+    char *buffer = NULL;
+    size_t buflen = 0;
     bool delete_group = false;
     int ret;
 
-    DEBUG(7, ("Searching group by gid (%d)\n", gid));
+    DEBUG(SSSDBG_TRACE_FUNC, ("Searching group by gid (%d)\n", gid));
 
     tmpctx = talloc_new(mem_ctx);
     if (!tmpctx) {
@@ -756,96 +831,45 @@ static int get_gr_gid(TALLOC_CTX *mem_ctx,
     grp = talloc(tmpctx, struct group);
     if (!grp) {
         ret = ENOMEM;
-        DEBUG(1, ("proxy -> getgrgid_r failed for '%d': [%d] %s\n",
-                  gid, ret, strerror(ret)));
-        return ret;
+        goto done;
     }
 
-    buflen = DEFAULT_BUFSIZE;
-    buffer = talloc_size(tmpctx, buflen);
-    if (!buffer) {
-        ret = ENOMEM;
-        DEBUG(1, ("proxy -> getgrgid_r failed for '%d': [%d] %s\n",
-                  gid, ret, strerror(ret)));
-        return ret;
-    }
-
-again:
-    /* always zero out the group structure */
-    memset(grp, 0, sizeof(struct group));
-
-    status = ctx->ops.getgrgid_r(gid, grp, buffer, buflen, &ret);
-
-    switch (status) {
-    case NSS_STATUS_TRYAGAIN:
-        /* buffer too small ? */
-        if (buflen < MAX_BUF_SIZE) {
-            buflen *= 2;
-        }
-        if (buflen > MAX_BUF_SIZE) {
-            buflen = MAX_BUF_SIZE;
-        }
-        newbuf = talloc_realloc_size(tmpctx, buffer, buflen);
-        if (!newbuf) {
+    do {
+        /* always zero out the grp structure */
+        memset(grp, 0, sizeof(struct group));
+        buffer = grow_group_buffer(tmpctx, &buffer, &buflen);
+        if (!buffer) {
             ret = ENOMEM;
             goto done;
         }
-        buffer = newbuf;
-        goto again;
 
-    case NSS_STATUS_NOTFOUND:
+        status = ctx->ops.getgrgid_r(gid, grp, buffer, buflen, &ret);
 
-        DEBUG(7, ("Group %d not found.\n", gid));
-        delete_group = true;
-        break;
-
-    case NSS_STATUS_SUCCESS:
-
-        DEBUG(7, ("Group %d found (%s, %d)\n",
-                  gid, grp->gr_name, grp->gr_gid));
-
-        /* gid=0 is an invalid value */
-        /* also check that the id is in the valid range for this domain */
-        if (OUT_OF_ID_RANGE(grp->gr_gid, dom->id_min, dom->id_max)) {
-
-                DEBUG(2, ("Group [%s] filtered out! (id out of range)\n",
-                          grp->gr_name));
-            delete_group = true;
-            break;
-        }
-
-        ret = save_group(sysdb, dom, grp, dom->group_timeout);
-        if (ret) {
-            goto done;
-        }
-        break;
-
-    case NSS_STATUS_UNAVAIL:
-        /* "remote" backend unavailable. Enter offline mode */
-        ret = ENXIO;
-        goto done;
-
-    default:
-        ret = EIO;
-        goto done;
-    }
+        ret = handle_getgr_result(status, grp, dom, &delete_group);
+    } while (ret == EAGAIN);
 
     if (delete_group) {
-
-        DEBUG(7, ("Group %d does not exist (or is invalid) on remote server,"
-                  " deleting!\n", gid));
+        DEBUG(SSSDBG_TRACE_FUNC,
+              ("Group %d does not exist (or is invalid) on remote server,"
+               " deleting!\n", gid));
 
         ret = sysdb_delete_group(sysdb, NULL, gid);
-        if (ret) {
-            goto done;
-        }
+        goto done;
+    }
+
+    ret = save_group(sysdb, dom, grp, NULL, dom->group_timeout);
+    if (ret) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("Cannot save user [%d]: %s\n", ret, strerror(ret)));
+        goto done;
     }
 
 done:
     talloc_zfree(tmpctx);
     if (ret) {
-        DEBUG(2, ("proxy -> getgrgid_r failed for '%d' <%d>\n",
-                  gid, status));
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("proxy -> getgrgid_r failed for '%d' <%d>\n",
+               gid, status));
     }
     return ret;
 }
@@ -946,7 +970,7 @@ again:
             goto again; /* skip */
         }
 
-        ret = save_group(sysdb, dom, grp, dom->group_timeout);
+        ret = save_group(sysdb, dom, grp, NULL, dom->group_timeout);
         if (ret) {
             /* Do not fail completely on errors.
              * Just report the failure to save and go on */
@@ -997,6 +1021,8 @@ static int get_initgr(TALLOC_CTX *mem_ctx,
     char *buffer;
     size_t buflen;
     int ret;
+    bool del_user;
+    uid_t uid;
 
     tmpctx = talloc_new(mem_ctx);
     if (!tmpctx) {
@@ -1006,74 +1032,90 @@ static int get_initgr(TALLOC_CTX *mem_ctx,
     pwd = talloc_zero(tmpctx, struct passwd);
     if (!pwd) {
         ret = ENOMEM;
-        goto done;
+        goto fail;
     }
 
     buflen = DEFAULT_BUFSIZE;
     buffer = talloc_size(tmpctx, buflen);
     if (!buffer) {
         ret = ENOMEM;
-        goto done;
+        goto fail;
     }
 
     ret = sysdb_transaction_start(sysdb);
     if (ret) {
-        goto done;
+        goto fail;
     }
     in_transaction = true;
 
     /* FIXME: should we move this call outside the transaction to keep the
      * transaction as short as possible ? */
     status = ctx->ops.getpwnam_r(name, pwd, buffer, buflen, &ret);
-
-    switch (status) {
-    case NSS_STATUS_NOTFOUND:
-
-        DEBUG(7, ("User %s not found.\n", name));
-        ret = delete_user(tmpctx, sysdb, dom, name);
+    ret = handle_getpw_result(status, pwd, dom, &del_user);
+    if (ret) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("getpwnam failed [%d]: %s\n", ret, strerror(ret)));
+        goto fail;
+    }
+
+    if (del_user) {
+        DEBUG(SSSDBG_TRACE_FUNC,
+              ("User %s does not exist (or is invalid) on remote server,"
+               " deleting!\n", name));
+        ret = sysdb_delete_user(sysdb, name, 0);
         if (ret) {
-            goto done;
-        }
-        break;
-
-    case NSS_STATUS_SUCCESS:
-
-        /* uid=0 or gid=0 are invalid values */
-        /* also check that the id is in the valid range for this domain */
-        if (OUT_OF_ID_RANGE(pwd->pw_uid, dom->id_min, dom->id_max) ||
-            OUT_OF_ID_RANGE(pwd->pw_gid, dom->id_min, dom->id_max)) {
-
-            DEBUG(2, ("User [%s] filtered out! (id out of range)\n",
-                      name));
-            ret = delete_user(tmpctx, sysdb, dom, name);
-            break;
+            DEBUG(SSSDBG_OP_FAILURE, ("Could not delete user\n"));
+            goto fail;
         }
-
-        ret = save_user(sysdb, !dom->case_sensitive, pwd, dom->user_timeout);
+        goto done;
+    }
+
+    uid = pwd->pw_uid;
+    memset(buffer, 0, buflen);
+
+    /* Canonicalize the username in case it was actually an alias */
+    status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret);
+    ret = handle_getpw_result(status, pwd, dom, &del_user);
+    if (ret) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("getpwuid failed [%d]: %s\n", ret, strerror(ret)));
+        goto fail;
+    }
+
+    if (del_user) {
+        DEBUG(SSSDBG_TRACE_FUNC,
+              ("User %s does not exist (or is invalid) on remote server,"
+               " deleting!\n", name));
+        ret = sysdb_delete_user(sysdb, name, uid);
         if (ret) {
-            goto done;
-        }
-
-        ret = get_initgr_groups_process(tmpctx, ctx, sysdb, dom, pwd);
-        if (ret == EOK) {
-            ret = sysdb_transaction_commit(sysdb);
-            in_transaction = true;
+            DEBUG(SSSDBG_OP_FAILURE, ("Could not delete user\n"));
+            goto fail;
         }
-        break;
-
-    case NSS_STATUS_UNAVAIL:
-        /* "remote" backend unavailable. Enter offline mode */
-        ret = ENXIO;
-        break;
-
-    default:
-        DEBUG(2, ("proxy -> getpwnam_r failed for '%s' <%d>\n",
-                  name, status));
-        ret = EIO;
-        break;
+        goto done;
+    }
+
+    ret = save_user(sysdb, !dom->case_sensitive, pwd,
+                    name, dom->user_timeout);
+    if (ret) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Could not save user\n"));
+        goto fail;
+    }
+
+    ret = get_initgr_groups_process(tmpctx, ctx, sysdb, dom, pwd);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Could not process initgroups\n"));
+        goto fail;
     }
 
 done:
+    ret = sysdb_transaction_commit(sysdb);
+    if (ret) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Failed to commit transaction\n"));
+        goto fail;
+    }
+    in_transaction = false;
+
+fail:
     talloc_zfree(tmpctx);
     if (in_transaction) {
         sysdb_transaction_cancel(sysdb);
-- 
1.7.7.6

-------------- next part --------------
>From 74ef153cdc28215f52369f31a44c936f28bd50e1 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Thu, 12 Apr 2012 18:21:48 +0200
Subject: [PATCH 2/2] proxy: new option proxy_fast_alias

---
 src/confdb/confdb.h                       |    1 +
 src/config/SSSDConfig.py                  |    1 +
 src/config/etc/sssd.api.d/sssd-proxy.conf |    1 +
 src/man/sssd.conf.5.xml                   |   17 +++
 src/providers/proxy/proxy.h               |    1 +
 src/providers/proxy/proxy_id.c            |  163 +++++++++++++++++++++--------
 src/providers/proxy/proxy_init.c          |    4 +
 7 files changed, 144 insertions(+), 44 deletions(-)

diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index aebf5d888002aa30af709ec57d3663de9f554a10..83a0fea90f4e2da8837a7bbb3643d520a74583ac 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -158,6 +158,7 @@
 /* Proxy Provider */
 #define CONFDB_PROXY_LIBNAME "proxy_lib_name"
 #define CONFDB_PROXY_PAM_TARGET "proxy_pam_target"
+#define CONFDB_PROXY_FAST_ALIAS "proxy_fast_alias"
 
 struct confdb_ctx;
 struct config_file_ctx;
diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py
index 488220a67fa94be7c96dc1a02487700ebfe89a40..f4987997248dfadc1383537b981d4797104affe1 100644
--- a/src/config/SSSDConfig.py
+++ b/src/config/SSSDConfig.py
@@ -300,6 +300,7 @@ option_strings = {
 
     # [provider/proxy/id]
     'proxy_lib_name' : _('The name of the NSS library to use'),
+    'proxy_fast_alias' : _('Whether to look up canonical group name from cache if possible'),
 
     # [provider/proxy/auth]
     'proxy_pam_target' : _('PAM stack to use')
diff --git a/src/config/etc/sssd.api.d/sssd-proxy.conf b/src/config/etc/sssd.api.d/sssd-proxy.conf
index 7ecf6b33b66be979c06393de99f93df142552df2..39f6a63cdec8d5ac5b84e93b16bdd8b668cf7623 100644
--- a/src/config/etc/sssd.api.d/sssd-proxy.conf
+++ b/src/config/etc/sssd.api.d/sssd-proxy.conf
@@ -2,6 +2,7 @@
 
 [provider/proxy/id]
 proxy_lib_name = str, None, true
+proxy_fast_alias = bool, None, true
 
 [provider/proxy/auth]
 proxy_pam_target = str, None, true
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index 1a8ae2bb4985aabcac7e4c4100142feb9dd1160f..c164d121547b5153124955e75b5d9b39fa62a821 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -1190,6 +1190,23 @@
                         </para>
                     </listitem>
                 </varlistentry>
+
+                <varlistentry>
+                    <term>proxy_fast_alias (boolean)</term>
+                    <listitem>
+                        <para>
+                            When a user or group is looked up by name in
+                            the proxy provider, a second lookup by ID is
+                            performed to "canonicalize" the name in case
+                            the requested name was an alias. Setting this
+                            option to true would cause the SSSD to perform
+                            the ID lookup from cache for performance reasons.
+                        </para>
+                        <para>
+                            Default: false
+                        </para>
+                    </listitem>
+                </varlistentry>
             </variablelist>
         </para>
 
diff --git a/src/providers/proxy/proxy.h b/src/providers/proxy/proxy.h
index 3641d6ee544c69982d23e1f675c40da69b8de604..cea03382517231cdf2b96069ab93dfb7967b46a6 100644
--- a/src/providers/proxy/proxy.h
+++ b/src/providers/proxy/proxy.h
@@ -100,6 +100,7 @@ struct authtok_conv {
 
 struct proxy_id_ctx {
     struct be_ctx *be;
+    bool fast_alias;
     struct proxy_nss_ops ops;
     void *handle;
 };
diff --git a/src/providers/proxy/proxy_id.c b/src/providers/proxy/proxy_id.c
index d92fc4eacfc6f3801a19d6577e39d1b202b53bd0..e1325b74d3f97cde38e182ec659f50aed93e185a 100644
--- a/src/providers/proxy/proxy_id.c
+++ b/src/providers/proxy/proxy_id.c
@@ -28,8 +28,8 @@
 /* =Getpwnam-wrapper======================================================*/
 
 static int save_user(struct sysdb_ctx *sysdb, bool lowercase,
-                     struct passwd *pwd, const char *alias,
-                     uint64_t cache_timeout);
+                     struct passwd *pwd, const char *real_name,
+                     const char *alias, uint64_t cache_timeout);
 
 static int
 handle_getpw_result(enum nss_status status, struct passwd *pwd,
@@ -49,6 +49,8 @@ static int get_pw_name(TALLOC_CTX *mem_ctx,
     int ret;
     uid_t uid;
     bool del_user;
+    struct ldb_result *cached_pwd = NULL;
+    const char *real_name = NULL;
 
     DEBUG(SSSDBG_TRACE_FUNC, ("Searching user by name (%s)\n", name));
 
@@ -91,15 +93,38 @@ static int get_pw_name(TALLOC_CTX *mem_ctx,
     }
 
     uid = pwd->pw_uid;
-    memset(buffer, 0, buflen);
 
     /* Canonicalize the username in case it was actually an alias */
-    status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret);
-    ret = handle_getpw_result(status, pwd, dom, &del_user);
-    if (ret) {
-        DEBUG(SSSDBG_OP_FAILURE,
-              ("getpwuid failed [%d]: %s\n", ret, strerror(ret)));
-        goto done;
+
+    if (ctx->fast_alias == true) {
+        ret = sysdb_getpwuid(tmpctx, sysdb, uid, &cached_pwd);
+        if (ret != EOK) {
+            /* Non-fatal, attempt to canonicalize online */
+            DEBUG(SSSDBG_TRACE_FUNC, ("Request to cache failed [%d]: %s\n",
+                  ret, strerror(ret)));
+        }
+
+        if (ret == EOK && cached_pwd->count == 1) {
+            real_name = ldb_msg_find_attr_as_string(cached_pwd->msgs[0],
+                                                    SYSDB_NAME, NULL);
+            if (!real_name) {
+                DEBUG(SSSDBG_MINOR_FAILURE, ("Cached user has no name?\n"));
+            }
+        }
+    }
+
+    if (real_name == NULL) {
+        memset(buffer, 0, buflen);
+
+        status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret);
+        ret = handle_getpw_result(status, pwd, dom, &del_user);
+        if (ret) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                ("getpwuid failed [%d]: %s\n", ret, strerror(ret)));
+            goto done;
+        }
+
+        real_name = pwd->pw_name;
     }
 
     if (del_user) {
@@ -112,7 +137,7 @@ static int get_pw_name(TALLOC_CTX *mem_ctx,
 
     /* Both lookups went fine, we can save the user now */
     ret = save_user(sysdb, !dom->case_sensitive, pwd,
-                    name, dom->user_timeout);
+                    real_name, name, dom->user_timeout);
 
 done:
     talloc_zfree(tmpctx);
@@ -175,8 +200,8 @@ handle_getpw_result(enum nss_status status, struct passwd *pwd,
 }
 
 static int save_user(struct sysdb_ctx *sysdb, bool lowercase,
-                     struct passwd *pwd, const char *alias,
-                     uint64_t cache_timeout)
+                     struct passwd *pwd, const char *real_name,
+                     const char *alias, uint64_t cache_timeout)
 {
     const char *shell;
     char *lower;
@@ -230,7 +255,7 @@ static int save_user(struct sysdb_ctx *sysdb, bool lowercase,
     }
 
     ret = sysdb_store_user(sysdb,
-                           pwd->pw_name,
+                           real_name,
                            pwd->pw_passwd,
                            pwd->pw_uid,
                            pwd->pw_gid,
@@ -303,7 +328,7 @@ static int get_pw_uid(TALLOC_CTX *mem_ctx,
     }
 
     ret = save_user(sysdb, !dom->case_sensitive, pwd,
-                    NULL, dom->user_timeout);
+                    pwd->pw_name, NULL, dom->user_timeout);
 
 done:
     talloc_zfree(tmpctx);
@@ -412,7 +437,7 @@ again:
         }
 
         ret = save_user(sysdb, !dom->case_sensitive, pwd,
-                        NULL, dom->user_timeout);
+                        pwd->pw_name, NULL, dom->user_timeout);
         if (ret) {
             /* Do not fail completely on errors.
              * Just report the failure to save and go on */
@@ -466,8 +491,8 @@ static errno_t proxy_process_missing_users(struct sysdb_ctx *sysdb,
                                            struct group *grp,
                                            time_t now);
 static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom,
-                      struct group *grp, const char *alias,
-                      uint64_t cache_timeout)
+                      struct group *grp, const char *real_name,
+                      const char *alias, uint64_t cache_timeout)
 {
     errno_t ret, sret;
     struct sysdb_attrs *attrs = NULL;
@@ -555,7 +580,7 @@ static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom,
     }
 
     ret = sysdb_store_group(sysdb,
-                            grp->gr_name,
+                            real_name,
                             grp->gr_gid,
                             attrs,
                             cache_timeout,
@@ -718,6 +743,8 @@ static int get_gr_name(TALLOC_CTX *mem_ctx,
     bool delete_group = false;
     int ret;
     gid_t gid;
+    struct ldb_result *cached_grp = NULL;
+    const char *real_name = NULL;
 
     DEBUG(SSSDBG_FUNC_DATA, ("Searching group by name (%s)\n", name));
 
@@ -756,27 +783,49 @@ static int get_gr_name(TALLOC_CTX *mem_ctx,
     }
 
     gid = grp->gr_gid;
-    talloc_zfree(buffer);
-    buflen = 0;
 
     /* Canonicalize the group name in case it was actually an alias */
-    do {
-        memset(grp, 0, sizeof(struct group));
-        buffer = grow_group_buffer(tmpctx, &buffer, &buflen);
-        if (!buffer) {
-            ret = ENOMEM;
+    if (ctx->fast_alias == true) {
+        ret = sysdb_getgrgid(tmpctx, sysdb, gid, &cached_grp);
+        if (ret != EOK) {
+            /* Non-fatal, attempt to canonicalize online */
+            DEBUG(SSSDBG_TRACE_FUNC, ("Request to cache failed [%d]: %s\n",
+                  ret, strerror(ret)));
+        }
+
+        if (ret == EOK && cached_grp->count == 1) {
+            real_name = ldb_msg_find_attr_as_string(cached_grp->msgs[0],
+                                                    SYSDB_NAME, NULL);
+            if (!real_name) {
+                DEBUG(SSSDBG_MINOR_FAILURE, ("Cached group has no name?\n"));
+            }
+        }
+    }
+
+    if (real_name == NULL) {
+        talloc_zfree(buffer);
+        buflen = 0;
+
+        do {
+            memset(grp, 0, sizeof(struct group));
+            buffer = grow_group_buffer(tmpctx, &buffer, &buflen);
+            if (!buffer) {
+                ret = ENOMEM;
+                goto done;
+            }
+
+            status = ctx->ops.getgrgid_r(gid, grp, buffer, buflen, &ret);
+
+            ret = handle_getgr_result(status, grp, dom, &delete_group);
+        } while (ret == EAGAIN);
+
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                ("getgrgid failed [%d]: %s\n", ret, strerror(ret)));
             goto done;
         }
 
-        status = ctx->ops.getgrgid_r(gid, grp, buffer, buflen, &ret);
-
-        ret = handle_getgr_result(status, grp, dom, &delete_group);
-    } while(ret == EAGAIN);
-
-    if (ret != EOK) {
-        DEBUG(SSSDBG_OP_FAILURE,
-              ("getgrgid failed [%d]: %s\n", ret, strerror(ret)));
-        goto done;
+        real_name = grp->gr_name;
     }
 
     if (delete_group) {
@@ -788,7 +837,7 @@ static int get_gr_name(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
-    ret = save_group(sysdb, dom, grp, name, dom->group_timeout);
+    ret = save_group(sysdb, dom, grp, real_name, name, dom->group_timeout);
     if (ret) {
         DEBUG(SSSDBG_OP_FAILURE,
               ("Cannot save group [%d]: %s\n", ret, strerror(ret)));
@@ -857,7 +906,7 @@ static int get_gr_gid(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
-    ret = save_group(sysdb, dom, grp, NULL, dom->group_timeout);
+    ret = save_group(sysdb, dom, grp, grp->gr_name, NULL, dom->group_timeout);
     if (ret) {
         DEBUG(SSSDBG_OP_FAILURE,
               ("Cannot save user [%d]: %s\n", ret, strerror(ret)));
@@ -970,7 +1019,8 @@ again:
             goto again; /* skip */
         }
 
-        ret = save_group(sysdb, dom, grp, NULL, dom->group_timeout);
+        ret = save_group(sysdb, dom, grp, grp->gr_name,
+                         NULL, dom->group_timeout);
         if (ret) {
             /* Do not fail completely on errors.
              * Just report the failure to save and go on */
@@ -1023,6 +1073,8 @@ static int get_initgr(TALLOC_CTX *mem_ctx,
     int ret;
     bool del_user;
     uid_t uid;
+    struct ldb_result *cached_pwd = NULL;
+    const char *real_name = NULL;
 
     tmpctx = talloc_new(mem_ctx);
     if (!tmpctx) {
@@ -1074,12 +1126,35 @@ static int get_initgr(TALLOC_CTX *mem_ctx,
     memset(buffer, 0, buflen);
 
     /* Canonicalize the username in case it was actually an alias */
-    status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret);
-    ret = handle_getpw_result(status, pwd, dom, &del_user);
-    if (ret) {
-        DEBUG(SSSDBG_OP_FAILURE,
-              ("getpwuid failed [%d]: %s\n", ret, strerror(ret)));
-        goto fail;
+    if (ctx->fast_alias == true) {
+        ret = sysdb_getpwuid(tmpctx, sysdb, uid, &cached_pwd);
+        if (ret != EOK) {
+            /* Non-fatal, attempt to canonicalize online */
+            DEBUG(SSSDBG_TRACE_FUNC, ("Request to cache failed [%d]: %s\n",
+                  ret, strerror(ret)));
+        }
+
+        if (ret == EOK && cached_pwd->count == 1) {
+            real_name = ldb_msg_find_attr_as_string(cached_pwd->msgs[0],
+                                                    SYSDB_NAME, NULL);
+            if (!real_name) {
+                DEBUG(SSSDBG_MINOR_FAILURE, ("Cached user has no name?\n"));
+            }
+        }
+    }
+
+    if (real_name == NULL) {
+        memset(buffer, 0, buflen);
+
+        status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret);
+        ret = handle_getpw_result(status, pwd, dom, &del_user);
+        if (ret) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                ("getpwuid failed [%d]: %s\n", ret, strerror(ret)));
+            goto done;
+        }
+
+        real_name = pwd->pw_name;
     }
 
     if (del_user) {
@@ -1095,7 +1170,7 @@ static int get_initgr(TALLOC_CTX *mem_ctx,
     }
 
     ret = save_user(sysdb, !dom->case_sensitive, pwd,
-                    name, dom->user_timeout);
+                    real_name, name, dom->user_timeout);
     if (ret) {
         DEBUG(SSSDBG_OP_FAILURE, ("Could not save user\n"));
         goto fail;
diff --git a/src/providers/proxy/proxy_init.c b/src/providers/proxy/proxy_init.c
index 46b2e7c36e5515b737c1f0e4e887ad5897b8d332..de4d7b615aabb1d151a55c5eb6ac620be1f244cf 100644
--- a/src/providers/proxy/proxy_init.c
+++ b/src/providers/proxy/proxy_init.c
@@ -109,6 +109,10 @@ int sssm_proxy_id_init(struct be_ctx *bectx,
         goto done;
     }
 
+    ret = confdb_get_bool(bectx->cdb, bectx->conf_path,
+                          CONFDB_PROXY_FAST_ALIAS, false, &ctx->fast_alias);
+    if (ret != EOK) goto done;
+
     libpath = talloc_asprintf(ctx, "libnss_%s.so.2", libname);
     if (!libpath) {
         ret = ENOMEM;
-- 
1.7.7.6



More information about the sssd-devel mailing list