From 48b84576d52fe94ad8c00dde567084b8a7d345c0 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Wed, 19 Jan 2011 15:39:02 -0500
Subject: [PATCH 1/2] Add the user's primary group to the initgroups lookup

The user may not be a direct member of their primary group, but
we still want to make sure that group is cached on the system.
---
 src/providers/ldap/ldap_id.c             |   11 +++---
 src/providers/ldap/sdap_async.h          |    4 +--
 src/providers/ldap/sdap_async_accounts.c |   55 ++++++++++++++++++++++++++---
 3 files changed, 56 insertions(+), 14 deletions(-)

diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index ed27620ce3b4e5829f5cf2b3847ff5b82be077a3..09f0026b00cda442f90e07e30e0d083a53206d85 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -588,11 +588,12 @@ static void groups_by_user_connect_done(struct tevent_req *subreq)
         return;
     }
 
-    subreq = sdap_get_initgr_send(state, state->ev,
-                                  state->ctx->be->domain,
-                                  state->ctx->be->sysdb,
-                                  state->ctx->opts, sdap_id_op_handle(state->op),
-                                  state->name, state->attrs);
+    subreq = sdap_get_initgr_send(state,
+                                  state->ev,
+                                  sdap_id_op_handle(state->op),
+                                  state->ctx,
+                                  state->name,
+                                  state->attrs);
     if (!subreq) {
         tevent_req_error(req, ENOMEM);
         return;
diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
index 5e3771439a5f72d5b659e5ad80cbd7056b6dde9a..f7b7b568dc42b17056909864da49c1104b037d97 100644
--- a/src/providers/ldap/sdap_async.h
+++ b/src/providers/ldap/sdap_async.h
@@ -106,10 +106,8 @@ int sdap_auth_recv(struct tevent_req *req,
 
 struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
                                         struct tevent_context *ev,
-                                        struct sss_domain_info *dom,
-                                        struct sysdb_ctx *sysdb,
-                                        struct sdap_options *opts,
                                         struct sdap_handle *sh,
+                                        struct sdap_id_ctx *id_ctx,
                                         const char *name,
                                         const char **grp_attrs);
 int sdap_get_initgr_recv(struct tevent_req *req);
diff --git a/src/providers/ldap/sdap_async_accounts.c b/src/providers/ldap/sdap_async_accounts.c
index 67c0db444d3c26496487b35e71fba1169ffcfcd9..4f57c6a18c242f3e33ce83f763607123ac489dda 100644
--- a/src/providers/ldap/sdap_async_accounts.c
+++ b/src/providers/ldap/sdap_async_accounts.c
@@ -2327,6 +2327,7 @@ struct sdap_get_initgr_state {
     struct sdap_options *opts;
     struct sss_domain_info *dom;
     struct sdap_handle *sh;
+    struct sdap_id_ctx *id_ctx;
     const char *name;
     const char **grp_attrs;
     const char **ldap_attrs;
@@ -2339,10 +2340,8 @@ static void sdap_get_initgr_done(struct tevent_req *subreq);
 
 struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
                                         struct tevent_context *ev,
-                                        struct sss_domain_info *dom,
-                                        struct sysdb_ctx *sysdb,
-                                        struct sdap_options *opts,
                                         struct sdap_handle *sh,
+                                        struct sdap_id_ctx *id_ctx,
                                         const char *name,
                                         const char **grp_attrs)
 {
@@ -2358,10 +2357,11 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
     if (!req) return NULL;
 
     state->ev = ev;
-    state->opts = opts;
-    state->sysdb = sysdb;
-    state->dom = dom;
+    state->opts = id_ctx->opts;
+    state->sysdb = id_ctx->be->sysdb;
+    state->dom = id_ctx->be->domain;
     state->sh = sh;
+    state->id_ctx = id_ctx;
     state->name = name;
     state->grp_attrs = grp_attrs;
     state->orig_user = NULL;
@@ -2530,6 +2530,7 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
 }
 
 static int sdap_initgr_rfc2307bis_recv(struct tevent_req *req);
+static void sdap_get_initgr_pgid(struct tevent_req *req);
 static void sdap_get_initgr_done(struct tevent_req *subreq)
 {
     struct tevent_req *req = tevent_req_callback_data(subreq,
@@ -2537,6 +2538,8 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
     struct sdap_get_initgr_state *state = tevent_req_data(req,
                                                struct sdap_get_initgr_state);
     int ret;
+    gid_t primary_gid;
+    char *gid;
 
     DEBUG(9, ("Initgroups done\n"));
 
@@ -2568,6 +2571,46 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
         return;
     }
 
+    /* We also need to update the user's primary group, since
+     * the user may not be an explicit member of that group
+     */
+    ret = sysdb_attrs_get_uint32_t(state->orig_user, SYSDB_GIDNUM, &primary_gid);
+    if (ret != EOK) {
+        DEBUG(6, ("Could not find user's primary GID\n"));
+        tevent_req_error(req, ret);
+        return;
+    }
+
+    gid = talloc_asprintf(state, "%lu", (unsigned long)primary_gid);
+    if (gid == NULL) {
+        tevent_req_error(req, ENOMEM);
+        return;
+    }
+
+    subreq = groups_get_send(req, state->ev, state->id_ctx, gid,
+                             BE_FILTER_IDNUM, BE_ATTR_ALL);
+    if (!subreq) {
+        tevent_req_error(req, ENOMEM);
+        return;
+    }
+    tevent_req_set_callback(subreq, sdap_get_initgr_pgid, req);
+
+    tevent_req_done(req);
+}
+
+static void sdap_get_initgr_pgid(struct tevent_req *subreq)
+{
+    struct tevent_req *req =
+            tevent_req_callback_data(subreq, struct tevent_req);
+    errno_t ret;
+
+    ret = groups_get_recv(subreq, NULL);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        tevent_req_error(req, ret);
+        return;
+    }
+
     tevent_req_done(req);
 }
 
-- 
1.7.3.4

