diff --git a/src/native/util/os_darwin.cpp b/src/native/util/os_darwin.cpp index fc6207dcf2..0bc801856a 100644 --- a/src/native/util/os_darwin.cpp +++ b/src/native/util/os_darwin.cpp @@ -42,6 +42,54 @@ const uid_t ThreadScope::orig_uid = getuid(); const gid_t ThreadScope::orig_gid = getgid(); const std::vector ThreadScope::orig_groups = get_process_groups(); +static int +get_supplemental_groups_by_uid(uid_t uid, std::vector& groups) +{ + // getpwuid will only indicate if an error happened by setting errno. set it to 0, so will know if there is a change + errno = 0; + struct passwd* pw = getpwuid(uid); + if (pw == NULL) { + if (errno == 0) { + LOG("get_supplemental_groups_by_uid: no record for uid " << uid); + } else { + LOG("WARNING: get_supplemental_groups_by_uid: getpwuid failed: " << strerror(errno)); + } + return -1; + } + int ngroups = NGROUPS_MAX; + groups.resize(ngroups); + if (getgrouplist(pw->pw_name, pw->pw_gid, &groups[0], &ngroups) < 0) { + LOG("get_supplemental_groups_by_uid: getgrouplist failed: ngroups too small " << ngroups); + return -1; + } + groups.resize(ngroups); + return 0; +} + +/** + * set supplemental groups of the thread according to the following: + * 1. if groups were defined in the account configuration, set the groups list to the one defined + * 2. try to get the list of groups corresponding to the user in the system recods, and set it to it + * 3. if supplemental groups were not defined for the account and getting it from system record failed (either because record doesn't exist ot because of an error) + * keep it as an empty set + */ +static void +set_supplemental_groups(uid_t uid, std::vector& groups) { + //first check if groups were defined in the account configuration + if (groups.empty()) { + if (get_supplemental_groups_by_uid(uid, groups) < 0) { + //aready unset by _mac_thread_setugid + return; + } + } + /*accourding to BSD Manual https://man.freebsd.org/cgi/man.cgi?query=setgroups + which darwin is occasionally compliant to setgroups changes the effective gid according to + the first element on the list. add the effective gid as the first element to prevent issues*/ + _groups.push_back(_gid); + std::swap(_groups.front(), _groups.back()); + MUST_SYS(setgroups(_groups.size(), &_groups[0])); +} + /** * set the effective uid/gid/supplemental_groups of the current thread using pthread_getugid_np and setgroups diff --git a/src/test/system_tests/test_utils.js b/src/test/system_tests/test_utils.js index 4a42118b63..09f927c1ce 100644 --- a/src/test/system_tests/test_utils.js +++ b/src/test/system_tests/test_utils.js @@ -343,7 +343,15 @@ async function delete_fs_user_by_platform(name) { */ async function create_fs_group_by_platform(group_name, gid, user_name) { if (process.platform === 'darwin') { - //TODO not implemented + const create_group_cmd = `sudo dscl . create /Groups/${group_name} UserShell /bin/bash`; + const create_group_realname_cmd = `sudo dscl . create /Groups/${group_name} RealName ${group_name}`; + const create_group_gid_cmd = `sudo dscl . create /Groups/${group_name} gid ${gid}`; + const add_user_to_group_cmd = `sudo dscl . append /Groups/${group_name} GroupMembership ${user_name}`; + await os_utils.exec(create_group_cmd, { return_stdout: true }); + await os_utils.exec(create_group_realname_cmd, { return_stdout: true }); + await os_utils.exec(create_group_gid_cmd, { return_stdout: true }); + await os_utils.exec(add_user_to_group_cmd, { return_stdout: true }); + } else { const create_group_cmd = `groupadd -g ${gid} ${group_name}`; await os_utils.exec(create_group_cmd, { return_stdout: true }); @@ -361,7 +369,10 @@ async function create_fs_group_by_platform(group_name, gid, user_name) { */ async function delete_fs_group_by_platform(group_name, force = false) { if (process.platform === 'darwin') { - //TODO not implemented + const delete_group_cmd = `sudo dscl . -delete /Groups/${group_name}`; + const delete_group_home_cmd = `sudo rm -rf /Groups/${group_name}`; + await os_utils.exec(delete_group_cmd, { return_stdout: true }); + await os_utils.exec(delete_group_home_cmd, { return_stdout: true }); } else { const flags = force ? '-f' : ''; const delete_group_cmd = `groupdel ${flags} ${group_name}`;