diff -Naur cyrus-imapd-2.3.10.orig/lib/auth_unix.c cyrus-imapd-2.3.10/lib/auth_unix.c --- cyrus-imapd-2.3.10.orig/lib/auth_unix.c 2007-09-27 22:02:45.000000000 +0200 +++ cyrus-imapd-2.3.10/lib/auth_unix.c 2007-11-01 11:36:56.000000000 +0100 @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -226,9 +227,12 @@ #ifdef HAVE_GETGROUPLIST gid_t gid, *groupids = NULL; int ret, ngroups = 0; -#else - char **mem; #endif + char **mem; + FILE *groupcache; + char fnamebuf[1024]; + const char *config_dir = + libcyrus_config_getstring(CYRUSOPT_CONFIG_DIR); identifier = mycanonifyid(identifier, 0); if (!identifier) return 0; @@ -245,6 +249,32 @@ pwd = getpwnam(identifier); +/* + * use the groupcache file if it exists, otherwise fall back + * to getgrouplist()/getgrent() + */ + strcpy(fnamebuf, config_dir); + strcat(fnamebuf, "/group.cache"); + groupcache = fopen(fnamebuf, "r"); + if (groupcache) { + setgrent(); + while ((grp = fgetgrent(groupcache))) { + for (mem = grp->gr_mem; *mem; mem++) { + if (!strcmp(*mem, identifier)) break; + } + + if (*mem || (pwd && pwd->pw_gid == grp->gr_gid)) { + newstate->ngroups++; + newstate->group = (char **)xrealloc((char *)newstate->group, + newstate->ngroups * sizeof(char *)); + newstate->group[newstate->ngroups-1] = xstrdup(grp->gr_name); + } + } + endgrent(); + fclose(groupcache); + } + else { /* begin !groupcache */ + #ifdef HAVE_GETGROUPLIST gid = pwd ? pwd->pw_gid : (gid_t) -1; @@ -302,6 +332,8 @@ endgrent(); #endif /* HAVE_GETGROUPLIST */ + } /* end !groupcache */ + return newstate; }