Tomas Janousek 17523a2
--- cyrus/lib/auth_unix.c	2007/02/13 16:42:49	1.41
Tomas Janousek 17523a2
+++ cyrus/lib/auth_unix.c	2007/09/17 14:36:40	1.45
Tomas Janousek 17523a2
@@ -41,7 +41,7 @@
Tomas Janousek 17523a2
  */
Tomas Janousek f8de2a3
 
Tomas Janousek 17523a2
 /*
Tomas Janousek 17523a2
- * $Id: auth_unix.c,v 1.41 2007/02/13 16:42:49 murch Exp $
Tomas Janousek 17523a2
+ * $Id: auth_unix.c,v 1.45 2007/09/17 14:36:40 murch Exp $
Tomas Janousek 17523a2
  */
Tomas Janousek f8de2a3
 
Tomas Janousek 17523a2
 #include <config.h>
Tomas Janousek 17523a2
@@ -224,6 +224,10 @@ static struct auth_state *mynewstate(con
Tomas Janousek f8de2a3
     struct passwd *pwd;
Tomas Janousek f8de2a3
     struct group *grp;
Tomas Janousek f8de2a3
     char **mem;
Tomas Janousek f8de2a3
+#ifdef HAVE_GETGROUPLIST
Tomas Janousek 17523a2
+    gid_t gid, *groupids = NULL;
Tomas Janousek 17523a2
+    int ret, ngroups = 0;
Tomas Janousek f8de2a3
+#endif
Tomas Janousek f8de2a3
 
Tomas Janousek f8de2a3
     identifier = mycanonifyid(identifier, 0);
Tomas Janousek f8de2a3
     if (!identifier) return 0;
Tomas Janousek 17523a2
@@ -239,7 +243,48 @@ static struct auth_state *mynewstate(con
Tomas Janousek f8de2a3
 	return newstate;
Tomas Janousek f8de2a3
 
Tomas Janousek f8de2a3
     pwd = getpwnam(identifier);
Tomas Janousek f8de2a3
-	
Tomas Janousek 17523a2
+
Tomas Janousek f8de2a3
+#ifdef HAVE_GETGROUPLIST
Tomas Janousek f8de2a3
+    gid = pwd ? pwd->pw_gid : (gid_t) -1;
Tomas Janousek f8de2a3
+
Tomas Janousek 17523a2
+    /* get number of groups user is member of into ngroups */
Tomas Janousek 17523a2
+    getgrouplist(identifier, gid, NULL, &ngroups);
Tomas Janousek 17523a2
+
Tomas Janousek 17523a2
+    /* get the actual group ids */
Tomas Janousek f8de2a3
+    do {
Tomas Janousek 17523a2
+	groupids = (gid_t *)xrealloc((gid_t *)groupids,
Tomas Janousek 17523a2
+				     ngroups * sizeof(gid_t));
Tomas Janousek f8de2a3
+
Tomas Janousek 17523a2
+	newstate->ngroups = ngroups; /* copy of ngroups for comparision */
Tomas Janousek 17523a2
+	ret = getgrouplist(identifier, gid, groupids, &ngroups);
Tomas Janousek f8de2a3
+	/*
Tomas Janousek f8de2a3
+	 * This is tricky. We do this as long as getgrouplist tells us to
Tomas Janousek f8de2a3
+	 * realloc _and_ the number of groups changes. It tells us to realloc
Tomas Janousek f8de2a3
+	 * also in the case of failure...
Tomas Janousek f8de2a3
+	 */
Tomas Janousek f8de2a3
+    } while (ret != -1 && ngroups != newstate->ngroups);
Tomas Janousek f8de2a3
+
Tomas Janousek f8de2a3
+    if (ret == -1) {
Tomas Janousek f8de2a3
+	newstate->ngroups = 0;
Tomas Janousek f8de2a3
+	newstate->group = NULL;
Tomas Janousek f8de2a3
+	goto err;
Tomas Janousek f8de2a3
+    }
Tomas Janousek f8de2a3
+
Tomas Janousek 17523a2
+    newstate->ngroups = 0;
Tomas Janousek 17523a2
+    newstate->group = (char **)xmalloc(ngroups * sizeof(char *));
Tomas Janousek 17523a2
+    while (ngroups--) {
Tomas Janousek 17523a2
+	if (pwd || groupids[ngroups] != gid) {
Tomas Janousek 17523a2
+	    if ((grp = getgrgid(groupids[ngroups]))) {
Tomas Janousek 17523a2
+		newstate->ngroups++;
Tomas Janousek 17523a2
+		newstate->group[newstate->ngroups-1] = xstrdup(grp->gr_name);
Tomas Janousek 17523a2
+	    }
Tomas Janousek f8de2a3
+	}
Tomas Janousek f8de2a3
+    }
Tomas Janousek f8de2a3
+
Tomas Janousek f8de2a3
+err:
Tomas Janousek 17523a2
+    if (groupids) free(groupids);
Tomas Janousek 17523a2
+
Tomas Janousek 17523a2
+#else /* !HAVE_GETGROUPLIST */
Tomas Janousek f8de2a3
     setgrent();
Tomas Janousek f8de2a3
     while ((grp = getgrent())) {
Tomas Janousek f8de2a3
 	for (mem = grp->gr_mem; *mem; mem++) {
Tomas Janousek 17523a2
@@ -254,6 +299,8 @@ static struct auth_state *mynewstate(con
Tomas Janousek f8de2a3
 	}
Tomas Janousek f8de2a3
     }
Tomas Janousek f8de2a3
     endgrent();
Tomas Janousek 17523a2
+#endif /* HAVE_GETGROUPLIST */
Tomas Janousek f8de2a3
+
Tomas Janousek f8de2a3
     return newstate;
Tomas Janousek f8de2a3
 }
Tomas Janousek f8de2a3