diff options
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/util.c | 22 | ||||
-rw-r--r-- | source3/lib/util_smbd.c | 53 |
2 files changed, 63 insertions, 12 deletions
diff --git a/source3/lib/util.c b/source3/lib/util.c index 5e88bd896f..89cf1bfa02 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -289,6 +289,28 @@ BOOL in_group(gid_t group, gid_t current_gid, int ngroups, const gid_t *groups) } /**************************************************************************** + Add a gid to an array of gids if it's not already there. +****************************************************************************/ + +void add_gid_to_array_unique(gid_t gid, gid_t **gids, int *num) +{ + int i; + + for (i=0; i<*num; i++) { + if ((*gids)[i] == gid) + return; + } + + *gids = Realloc(*gids, (*num+1) * sizeof(gid_t)); + + if (*gids == NULL) + return; + + (*gids)[*num] = gid; + *num += 1; +} + +/**************************************************************************** Like atoi but gets the value up to the separator character. ****************************************************************************/ diff --git a/source3/lib/util_smbd.c b/source3/lib/util_smbd.c index 071f20b416..36c3104e55 100644 --- a/source3/lib/util_smbd.c +++ b/source3/lib/util_smbd.c @@ -37,29 +37,58 @@ NOTE! uses become_root() to gain correct priviages on systems that lack a native getgroups() call (uses initgroups and getgroups) */ -int getgroups_user(const char *user, gid_t **groups) +BOOL getgroups_user(const char *user, gid_t **ret_groups, int *ngroups) { struct passwd *pwd; int ngrp, max_grp; + gid_t *temp_groups; + gid_t *groups; + int i; pwd = getpwnam_alloc(user); - if (!pwd) return -1; + if (!pwd) return False; max_grp = groups_max(); - (*groups) = (gid_t *)malloc(sizeof(gid_t) * max_grp); - if (! *groups) { + temp_groups = (gid_t *)malloc(sizeof(gid_t) * max_grp); + if (! temp_groups) { passwd_free(&pwd); - errno = ENOMEM; - return -1; + return False; } - ngrp = sys_getgrouplist(user, pwd->pw_gid, *groups, &max_grp); - if (ngrp <= 0) { - passwd_free(&pwd); - free(*groups); - return ngrp; + if (sys_getgrouplist(user, pwd->pw_gid, temp_groups, &max_grp) == -1) { + + gid_t *groups_tmp; + + groups_tmp = Realloc(temp_groups, sizeof(gid_t) * max_grp); + + if (!groups_tmp) { + SAFE_FREE(temp_groups); + return False; + } + temp_groups = groups_tmp; + + if (sys_getgrouplist(user, pwd->pw_gid, temp_groups, &max_grp) == -1) { + DEBUG(0, ("get_user_groups: failed to get the unix group list\n")); + passwd_free(&pwd); + SAFE_FREE(temp_groups); + return False; + } } + + ngrp = 0; + groups = NULL; + + /* Add in primary group first */ + add_gid_to_array_unique(pwd->pw_gid, &groups, &ngrp); passwd_free(&pwd); - return ngrp; + + for (i=0; i<max_grp; i++) + add_gid_to_array_unique(temp_groups[i], &groups, &ngrp); + + *ngroups = ngrp; + *ret_groups = groups; + SAFE_FREE(temp_groups); + return True; } + |