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:
+70
-17
@@ -3573,42 +3573,95 @@ g_getgroup_info(const char *groupname, int *gid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* returns error */
|
#ifdef HAVE_GETGROUPLIST
|
||||||
/* if zero is returned, then ok is set */
|
int
|
||||||
/* does not work in win32 */
|
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
|
int
|
||||||
g_check_user_in_group(const char *username, int gid, int *ok)
|
g_check_user_in_group(const char *username, int gid, int *ok)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
return 1;
|
return 1;
|
||||||
#else
|
#else
|
||||||
struct group *groups;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
groups = getgrgid(gid);
|
struct passwd *pwd_1 = getpwnam(username);
|
||||||
|
struct group *groups = getgrgid(gid);
|
||||||
if (groups == 0)
|
if (pwd_1 == NULL || groups == NULL)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*ok = 0;
|
if (pwd_1->pw_gid == gid)
|
||||||
i = 0;
|
|
||||||
|
|
||||||
while (0 != groups->gr_mem[i])
|
|
||||||
{
|
{
|
||||||
if (0 == g_strcmp(groups->gr_mem[i], username))
|
*ok = 1;
|
||||||
{
|
}
|
||||||
*ok = 1;
|
else
|
||||||
break;
|
{
|
||||||
}
|
*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;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif // HAVE_GETGROUPLIST
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* returns the time since the Epoch (00:00:00 UTC, January 1, 1970),
|
/* returns the time since the Epoch (00:00:00 UTC, January 1, 1970),
|
||||||
|
|||||||
@@ -323,6 +323,15 @@ int g_getuser_info_by_name(const char *username, int *uid, int *gid,
|
|||||||
int g_getuser_info_by_uid(int uid, char **username, int *gid,
|
int g_getuser_info_by_uid(int uid, char **username, int *gid,
|
||||||
char **shell, char **dir, char **gecos);
|
char **shell, char **dir, char **gecos);
|
||||||
int g_getgroup_info(const char *groupname, int *gid);
|
int g_getgroup_info(const char *groupname, int *gid);
|
||||||
|
/**
|
||||||
|
* Checks whether a user is in the specified group
|
||||||
|
* @param username Name of user
|
||||||
|
* @param gid GID of group
|
||||||
|
* @param[out] ok Whether user is in group
|
||||||
|
* @return Non-zero if a system error occurred. In this instance OK is not set
|
||||||
|
*
|
||||||
|
* Primary group of username is also checked
|
||||||
|
*/
|
||||||
int g_check_user_in_group(const char *username, int gid, int *ok);
|
int g_check_user_in_group(const char *username, int gid, int *ok);
|
||||||
int g_time1(void);
|
int g_time1(void);
|
||||||
int g_time2(void);
|
int g_time2(void);
|
||||||
|
|||||||
Reference in New Issue
Block a user