summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/util.c22
-rw-r--r--source3/lib/util_smbd.c53
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;
}
+