diff -Naur cyrus-imapd-2.3.8.orig/configure.in cyrus-imapd-2.3.8/configure.in --- cyrus-imapd-2.3.8.orig/configure.in Thu Nov 30 18:11:16 2006 +++ cyrus-imapd-2.3.8/configure.in Tue Jun 12 15:40:12 2007 @@ -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 diff -Naur cyrus-imapd-2.3.8.orig/lib/auth_unix.c cyrus-imapd-2.3.8/lib/auth_unix.c --- cyrus-imapd-2.3.8.orig/lib/auth_unix.c Thu Nov 30 18:11:22 2006 +++ cyrus-imapd-2.3.8/lib/auth_unix.c Tue Jun 12 15:42:22 2007 @@ -224,6 +224,12 @@ struct passwd *pwd; struct group *grp; char **mem; +#ifdef HAVE_GETGROUPLIST + gid_t gid; + int ret, ngroups; + gid_t *groupids = 0; + int i; +#endif identifier = mycanonifyid(identifier, 0); if (!identifier) return 0; @@ -239,7 +245,45 @@ return newstate; pwd = getpwnam(identifier); - +#ifdef HAVE_GETGROUPLIST + 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. + 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 *)); + 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++) { @@ -254,6 +298,8 @@ } } endgrent(); +#endif + return newstate; }