From dda47008f3137218b5b751e09a8a8b4471316ff2 Mon Sep 17 00:00:00 2001 From: Christian Ambach Date: Mon, 14 Mar 2011 08:08:58 -0400 Subject: [PATCH] s3: use getgrset() when it is available When getgrouplist() is not defined, use getgrset() if it is defined instead of using the initgroups() + getgroups() combo Major contributions from Yannick Bergeron Autobuild-User: Volker Lendecke Autobuild-Date: Sat Mar 19 10:09:38 CET 2011 on sn-devel-104 (cherry picked from commit ed46dfc4f16e230645fae5f3b3b21c462694c30a) --- source3/configure.in | 1 + source3/lib/system_smbd.c | 59 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/source3/configure.in b/source3/configure.in index 4528cbf..b21e261 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -1023,6 +1023,7 @@ AC_CHECK_FUNCS(getrlimit fsync fdatasync setpgid) AC_CHECK_FUNCS(setsid glob strpbrk crypt16 getauthuid) AC_CHECK_FUNCS(sigprocmask sigblock sigaction sigset innetgr setnetgrent getnetgrent endnetgrent) AC_CHECK_FUNCS(initgroups select poll rdchk getgrnam getgrent pathconf) +AC_CHECK_FUNCS(getgrset) AC_CHECK_FUNCS(setpriv setgidx setuidx setgroups sysconf stat64 fstat64) AC_CHECK_FUNCS(lstat64 fopen64 atexit grantpt lseek64 ftruncate64 posix_fallocate posix_fallocate64) AC_CHECK_FUNCS(fseek64 fseeko64 ftell64 ftello64 setluid getpwanam) diff --git a/source3/lib/system_smbd.c b/source3/lib/system_smbd.c index b22d15f..5b285b4 100644 --- a/source3/lib/system_smbd.c +++ b/source3/lib/system_smbd.c @@ -27,6 +27,56 @@ #ifndef HAVE_GETGROUPLIST +#ifdef HAVE_GETGRSET +static int getgrouplist_getgrset(const char *user, gid_t gid, gid_t *groups, + int *grpcnt) +{ + char *grplist; + char *grp; + gid_t temp_gid; + int num_gids = 1; + int ret = 0; + long l; + + grplist = getgrset(user); + + DEBUG(10, ("getgrset returned %s\n", grplist)); + + if (grplist == NULL) { + return -1; + } + + if (*grpcnt > 0) { + groups[0] = gid; + } + + while ((grp = strsep(&grplist, ",")) != NULL) { + l = strtol(grp, NULL, 10); + temp_gid = (gid_t) l; + if (temp_gid == gid) { + continue; + } + + if (num_gids + 1 > *grpcnt) { + num_gids++; + continue; + } + groups[num_gids++] = temp_gid; + } + free(grplist); + + if (num_gids > *grpcnt) { + ret = -1; + } + *grpcnt = num_gids; + + DEBUG(10, ("Found %d groups for user %s\n", *grpcnt, user)); + + return ret; +} + +#else /* HAVE_GETGRSET */ + /* This is a *much* faster way of getting the list of groups for a user without changing the current supplementary group list. The old @@ -112,7 +162,8 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, free(gids_saved); return ret; } -#endif +#endif /* HAVE_GETGRSET */ +#endif /* HAVE_GETGROUPLIST */ static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt) { @@ -130,10 +181,14 @@ static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grp #ifdef HAVE_GETGROUPLIST retval = getgrouplist(user, gid, groups, grpcnt); #else +#ifdef HAVE_GETGRSET + retval = getgrouplist_getgrset(user, gid, groups, grpcnt); +#else become_root(); retval = getgrouplist_internals(user, gid, groups, grpcnt); unbecome_root(); -#endif +#endif /* HAVE_GETGRSET */ +#endif /* HAVE_GETGROUPLIST */ /* allow winbindd lookups, but only if they were not already disabled */ if (!winbind_env) { -- 1.7.3.4