Add getgrouplist() support to os_calls

On enterprise systems, using getgrouplist() (if available)
is more efficient than iterating over the members of the group,
and is also more likely to work
This commit is contained in:
matt335672
2023-10-02 11:04:47 +01:00
parent 84a0befd30
commit cf677da22c
2 changed files with 79 additions and 17 deletions
+70 -17
View File
@@ -3573,42 +3573,95 @@ g_getgroup_info(const char *groupname, int *gid)
}
/*****************************************************************************/
/* returns error */
/* if zero is returned, then ok is set */
/* does not work in win32 */
#ifdef HAVE_GETGROUPLIST
int
g_check_user_in_group(const char *username, int gid, int *ok)
{
int rv = 1;
struct passwd *pwd_1 = getpwnam(username);
if (pwd_1 != NULL)
{
// Get number of groups for user
//
// Some implementations of getgrouplist() (i.e. muslc) don't
// allow ngroups to be <1 on entry
int ngroups = 1;
GETGROUPS_T dummy;
getgrouplist(username, pwd_1->pw_gid, &dummy, &ngroups);
if (ngroups > 0) // Should always be true
{
GETGROUPS_T *grouplist;
grouplist = (GETGROUPS_T *)malloc(ngroups * sizeof(grouplist[0]));
if (grouplist != NULL)
{
// Now get the actual groups. The number of groups returned
// by this call is not necessarily the same as the number
// returned by the first call.
int allocgroups = ngroups;
getgrouplist(username, pwd_1->pw_gid, grouplist, &ngroups);
ngroups = MIN(ngroups, allocgroups);
rv = 0;
*ok = 0;
int i;
for (i = 0 ; i < ngroups; ++i)
{
if (grouplist[i] == (GETGROUPS_T)gid)
{
*ok = 1;
break;
}
}
free(grouplist);
}
}
}
return rv;
}
/*****************************************************************************/
#else // HAVE_GETGROUPLIST
int
g_check_user_in_group(const char *username, int gid, int *ok)
{
#if defined(_WIN32)
return 1;
#else
struct group *groups;
int i;
groups = getgrgid(gid);
if (groups == 0)
struct passwd *pwd_1 = getpwnam(username);
struct group *groups = getgrgid(gid);
if (pwd_1 == NULL || groups == NULL)
{
return 1;
}
*ok = 0;
i = 0;
while (0 != groups->gr_mem[i])
if (pwd_1->pw_gid == gid)
{
if (0 == g_strcmp(groups->gr_mem[i], username))
{
*ok = 1;
break;
}
*ok = 1;
}
else
{
*ok = 0;
i = 0;
i++;
while (0 != groups->gr_mem[i])
{
if (0 == g_strcmp(groups->gr_mem[i], username))
{
*ok = 1;
break;
}
i++;
}
}
return 0;
#endif
}
#endif // HAVE_GETGROUPLIST
/*****************************************************************************/
/* returns the time since the Epoch (00:00:00 UTC, January 1, 1970),