user-util: Add helper functions for gid lists operations

This commit is contained in:
Dariusz Gadomski 2020-01-08 16:22:29 +01:00
parent 6a6078a585
commit 0c5d667932
2 changed files with 65 additions and 20 deletions

View file

@ -404,11 +404,16 @@ char* gid_to_name(gid_t gid) {
return ret;
}
static bool gid_list_has(const gid_t *list, size_t size, gid_t val) {
for (size_t i = 0; i < size; i++)
if (list[i] == val)
return true;
return false;
}
int in_gid(gid_t gid) {
_cleanup_free_ gid_t *allocated = NULL;
gid_t local[16], *p = local;
int ngroups = ELEMENTSOF(local);
unsigned attempt = 0;
_cleanup_free_ gid_t *gids = NULL;
int ngroups;
if (getgid() == gid)
return 1;
@ -419,6 +424,57 @@ int in_gid(gid_t gid) {
if (!gid_is_valid(gid))
return -EINVAL;
ngroups = getgroups_alloc(&gids);
if (ngroups < 0)
return ngroups;
return gid_list_has(gids, ngroups, gid);
}
int in_group(const char *name) {
int r;
gid_t gid;
r = get_group_creds(&name, &gid, 0);
if (r < 0)
return r;
return in_gid(gid);
}
int merge_gid_lists(const gid_t *list1, size_t size1, const gid_t *list2, size_t size2, gid_t **ret) {
size_t nresult = 0;
assert(ret);
if (size2 > INT_MAX - size1)
return -ENOBUFS;
gid_t *buf = new(gid_t, size1 + size2);
if (!buf)
return -ENOMEM;
/* Duplicates need to be skipped on merging, otherwise they'll be passed on and stored in the kernel. */
for (size_t i = 0; i < size1; i++)
if (!gid_list_has(buf, nresult, list1[i]))
buf[nresult++] = list1[i];
for (size_t i = 0; i < size2; i++)
if (!gid_list_has(buf, nresult, list2[i]))
buf[nresult++] = list2[i];
*ret = buf;
return (int)nresult;
}
int getgroups_alloc(gid_t** gids) {
gid_t *allocated;
_cleanup_free_ gid_t *p = NULL;
int ngroups = 8;
unsigned attempt = 0;
allocated = new(gid_t, ngroups);
if (!allocated)
return -ENOMEM;
p = allocated;
for (;;) {
ngroups = getgroups(ngroups, p);
if (ngroups >= 0)
@ -447,22 +503,8 @@ int in_gid(gid_t gid) {
p = allocated;
}
for (int i = 0; i < ngroups; i++)
if (p[i] == gid)
return true;
return false;
}
int in_group(const char *name) {
int r;
gid_t gid;
r = get_group_creds(&name, &gid, 0);
if (r < 0)
return r;
return in_gid(gid);
*gids = TAKE_PTR(p);
return ngroups;
}
int get_home_dir(char **_h) {

View file

@ -42,6 +42,9 @@ char* gid_to_name(gid_t gid);
int in_gid(gid_t gid);
int in_group(const char *name);
int merge_gid_lists(const gid_t *list1, size_t size1, const gid_t *list2, size_t size2, gid_t **result);
int getgroups_alloc(gid_t** gids);
int get_home_dir(char **ret);
int get_shell(char **_ret);