[PATCH] cyrus-imapd: use getgrouplist instead of set/getgrent on systems supporting it

Tomas Janousek tjanouse at redhat.com
Tue Jun 12 07:21:47 EDT 2007


Hello,

I'm attaching the fix for [rhbz#195501] (ported to cyrus-imapd 2.3). I think
it might be worth applying.

[rhbz#195501] https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=195501

The function getgrouplist is, as opposed to getgrent, cached by nscd. Simon
Matter also dealt with this problem in his cyrus-imapd RPM, but his solution
was sort of a private caching mechanism. This seems to be a cleaner solution.

Regards,
-- 
Tomas Janousek, SW Engineer, Red Hat, Inc.
-------------- next part --------------
--- cyrus-imapd-2.3.8/lib/auth_unix.c.getgrouplist	2007-06-12 12:28:02.000000000 +0200
+++ cyrus-imapd-2.3.8/lib/auth_unix.c	2007-06-12 12:57:43.000000000 +0200
@@ -257,7 +257,48 @@
 	return newstate;
 
     pwd = getpwnam(identifier);
-	
+#ifdef HAVE_GETGROUPLIST
+    gid_t gid = pwd ? pwd->pw_gid : (gid_t) -1;
+
+    // get number of groups user is member of into newstate->ngroups
+    getgrouplist(identifier, gid, NULL, &(newstate->ngroups));
+    // get the actual group ids.
+    int ret, ngroups;
+    gid_t *groupids = 0;
+    do {
+	if (groupids)
+	    free(groupids);
+	groupids = (gid_t *)xmalloc(newstate->ngroups * sizeof(gid_t));
+
+	ngroups = newstate->ngroups;
+	ret = getgrouplist(identifier, gid, groupids, &(newstate->ngroups));
+	/*
+	 * This is tricky. We do this as long as getgrouplist tells us to
+	 * realloc _and_ the number of groups changes. It tells us to realloc
+	 * also in the case of failure...
+	 */
+    } while (ret != -1 && ngroups != newstate->ngroups);
+
+    if (ret == -1) {
+	newstate->ngroups = 0;
+	newstate->group = NULL;
+	goto err;
+    }
+
+    newstate->group = (char **)xmalloc(newstate->ngroups * sizeof(char *));
+    int i;
+    for (i = 0; i < newstate->ngroups; ++i ) {
+	struct group *group;
+
+	if (pwd || groupids[i] != gid) {
+	    if ((group = getgrgid(groupids[i])))
+		newstate->group[i] = xstrdup(group->gr_name);
+	}
+    }
+
+err:
+    free( groupids );
+#else
     setgrent();
     while ((grp = getgrent())) {
 	for (mem = grp->gr_mem; *mem; mem++) {
@@ -272,6 +313,8 @@
 	}
     }
     endgrent();
+#endif
+
     return newstate;
 }
 
--- cyrus-imapd-2.3.8/configure.in.getgrouplist	2006-11-30 18:11:16.000000000 +0100
+++ cyrus-imapd-2.3.8/configure.in	2007-06-12 12:43:34.000000000 +0200
@@ -119,7 +119,7 @@
 
 AC_CHECK_HEADERS(unistd.h sys/select.h sys/param.h stdarg.h)
 AC_REPLACE_FUNCS(memmove strcasecmp ftruncate strerror)
-AC_CHECK_FUNCS(strlcat strlcpy)
+AC_CHECK_FUNCS(strlcat strlcpy getgrouplist)
 AC_HEADER_DIRENT
 
 dnl do this before Berkeley DB/IPv6 detection


More information about the Cyrus-devel mailing list