Search code examples
cmacosdarwinusergroups

getgroups() on macOS is not returning all the supplementary groups, but instead just the primary group


'id' command does give me all the supplementary groups, but the following code is just returning the primary groups for which the use belongs:

gid_size = getgroups(0, NULL); //1 is getting returned here
grouplist = malloc(gid_size * sizeof(gid_t));
getgroups(gid_size, grouplist); //Even with gid_size>1, only primary groups is returned.

My question is, whether there's any other alternative way to get all the supplementary groups on macOS.


Solution

  • You should be able to get up to 16 more groups by invoking initgroups() first, but even this is not ideal.

    From the initgroups(3) man page:

    Processes should not use the group ID numbers from getgroups(2) to determine a user's group membership. The list obtained from getgroups() may only be a partial list of a user's group membership. Membership checks should use the mbr_gid_to_uuid(3), mbr_uid_to_uuid(3), and mbr_check_membership(3) functions.

    So if you're trying to check if the user is a member of a specific group, the mbr_*() functions are the way to go.

    Note that the source code of the id command is available and based on a very quick inspection it looks like it uses the undocumented getgrouplist_2().

    It looks like this is a variant of the getgrouplist() function, but without the 16-group limitation.

    I don't think this function is declared in any public headers, id.c uses the prototype

    int32_t getgrouplist_2(const char *, gid_t, gid_t **);