From c1bc3a7841890d8af470863e018721c035754999 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Sat, 9 Aug 2003 23:12:35 +0000 Subject: fix for BUG #267 (problem with supplementary groups). Use winbindd to get the group list if possible since we already know it from netsamlogon_cache.tdb. More effecient than letting libc call getgrent() to get seconary groups. Tested by Ken Cross. (This used to be commit 3c537c906f29a08e75895c8c8e3ed5c5abaaa940) --- source3/nsswitch/wb_client.c | 74 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) (limited to 'source3/nsswitch') diff --git a/source3/nsswitch/wb_client.c b/source3/nsswitch/wb_client.c index 7c5a8dd054..0c6644e9d0 100644 --- a/source3/nsswitch/wb_client.c +++ b/source3/nsswitch/wb_client.c @@ -264,6 +264,80 @@ static int wb_getgroups(const char *user, gid_t **groups) return -1; } +/* Call winbindd to initialise group membership. This is necessary for + some systems (i.e RH5.2) that do not have an initgroups function as part + of the nss extension. In RH5.2 this is implemented using getgrent() + which can be amazingly inefficient as well as having problems with + username case. */ + +int winbind_initgroups(char *user, gid_t gid) +{ + gid_t *tgr, *groups = NULL; + int result; + + /* Call normal initgroups if we are a local user */ + + if (!strchr(user, *lp_winbind_separator())) { + return initgroups(user, gid); + } + + result = wb_getgroups(user, &groups); + + DEBUG(10,("winbind_getgroups: %s: result = %s\n", user, + result == -1 ? "FAIL" : "SUCCESS")); + + if (result != -1) { + int ngroups = result, i; + BOOL is_member = False; + + /* Check to see if the passed gid is already in the list */ + + for (i = 0; i < ngroups; i++) { + if (groups[i] == gid) { + is_member = True; + } + } + + /* Add group to list if necessary */ + + if (!is_member) { + tgr = (gid_t *)Realloc(groups, sizeof(gid_t) * ngroups + 1); + + if (!tgr) { + errno = ENOMEM; + result = -1; + goto done; + } + else groups = tgr; + + groups[ngroups] = gid; + ngroups++; + } + + /* Set the groups */ + + if (sys_setgroups(ngroups, groups) == -1) { + errno = EPERM; + result = -1; + goto done; + } + + } else { + + /* The call failed. Set errno to something so we don't get + a bogus value from the last failed system call. */ + + errno = EIO; + } + + /* Free response data if necessary */ + + done: + SAFE_FREE(groups); + + return result; +} + /* Return a list of groups the user is a member of. This function is useful for large systems where inverting the group database would be too time consuming. If size is zero, list is not modified and the total -- cgit