in src/common/commonutils/UserUtils.c [446:576]
int EnumerateUserGroups(SimplifiedUser* user, SimplifiedGroup** groupList, unsigned int* size, char** reason, OsConfigLogHandle log)
{
gid_t* groupIds = NULL;
int numberOfGroups = MAX_GROUPS_USER_CAN_BE_IN;
struct group* groupEntry = NULL;
size_t groupNameLength = 0;
int i = 0;
int getGroupListResult = 0;
int status = 0;
if ((NULL == user) || (NULL == groupList) || (NULL == size))
{
OsConfigLogError(log, "EnumerateUserGroups: invalid arguments");
return EINVAL;
}
else if (NULL == user->username)
{
OsConfigLogError(log, "EnumerateUserGroups: unable to enumerate groups for user without name");
return ENOENT;
}
*groupList = NULL;
*size = 0;
if (NULL == (groupIds = malloc(numberOfGroups * sizeof(gid_t))))
{
OsConfigLogError(log, "EnumerateUserGroups: out of memory allocating list of %d group identifiers", numberOfGroups);
numberOfGroups = 0;
status = ENOMEM;
}
else if (-1 == (getGroupListResult = getgrouplist(user->username, user->groupId, groupIds, &numberOfGroups)))
{
OsConfigLogDebug(log, "EnumerateUserGroups: first call to getgrouplist for user %u (%u) returned %d and %d", user->userId, user->groupId, getGroupListResult, numberOfGroups);
FREE_MEMORY(groupIds);
if (0 < numberOfGroups)
{
if (NULL != (groupIds = malloc(numberOfGroups * sizeof(gid_t))))
{
getGroupListResult = getgrouplist(user->username, user->groupId, groupIds, &numberOfGroups);
OsConfigLogDebug(log, "EnumerateUserGroups: second call to getgrouplist for user '%u' (%u) returned %d and %d", user->userId, user->groupId, getGroupListResult, numberOfGroups);
}
else
{
OsConfigLogError(log, "EnumerateUserGroups: out of memory allocating list of %d group identifiers", numberOfGroups);
numberOfGroups = 0;
status = ENOMEM;
}
}
else
{
OsConfigLogInfo(log, "EnumerateUserGroups: first call to getgrouplist for user %u (%u) returned -1 and %d groups", user->userId, user->groupId, numberOfGroups);
status = ENOENT;
}
}
if ((0 == status) && (0 < numberOfGroups))
{
OsConfigLogDebug(log, "EnumerateUserGroups: user %u ('%s', gid: %u) is in %d group%s",
user->userId, IsSystemAccount(user) ? user->username : g_redacted, user->groupId, numberOfGroups, (1 == numberOfGroups) ? "" : "s");
if (NULL == (*groupList = malloc(sizeof(SimplifiedGroup) * numberOfGroups)))
{
OsConfigLogError(log, "EnumerateUserGroups: out of memory");
status = ENOMEM;
}
else
{
*size = numberOfGroups;
for (i = 0; i < numberOfGroups; i++)
{
if (NULL == (groupEntry = getgrgid(groupIds[i])))
{
if (0 == errno)
{
OsConfigLogInfo(log, "EnumerateUserGroups: group %u does not exist (errno: %d)", (unsigned int)groupIds[i], errno);
*size -= 1;
continue;
}
else
{
OsConfigLogInfo(log, "EnumerateUserGroups: getgrgid(for gid: %u) failed (errno: %d)", (unsigned int)groupIds[i], errno);
status = errno ? errno : ENOENT;
break;
}
}
if (NULL != groupEntry)
{
(*groupList)[i].groupId = groupEntry->gr_gid;
(*groupList)[i].groupName = NULL;
(*groupList)[i].hasUsers = true;
if (0 < (groupNameLength = (groupEntry->gr_name ? strlen(groupEntry->gr_name) : 0)))
{
if (NULL != ((*groupList)[i].groupName = malloc(groupNameLength + 1)))
{
memset((*groupList)[i].groupName, 0, groupNameLength + 1);
memcpy((*groupList)[i].groupName, groupEntry->gr_name, groupNameLength);
OsConfigLogDebug(log, "EnumerateUserGroups: user %u ('%s', gid: %u) is in group %u ('%s')",
user->userId, IsSystemAccount(user) ? user->username : g_redacted, user->groupId,
(*groupList)[i].groupId, IsSystemGroup(&(*groupList)[i]) ? (*groupList)[i].groupName : g_redacted);
}
else
{
OsConfigLogError(log, "EnumerateUserGroups: out of memory");
status = ENOMEM;
break;
}
}
}
}
}
}
if (0 == *size)
{
FREE_MEMORY(*groupList);
}
if (status)
{
OsConfigCaptureReason(reason, "Failed to enumerate groups for users (%d). User database may be corrupt. Automatic remediation is not possible", status);
}
FREE_MEMORY(groupIds);
return status;
}