summaryrefslogtreecommitdiff
path: root/source3/nsswitch/wb_client.c
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2003-08-09 23:12:35 +0000
committerGerald Carter <jerry@samba.org>2003-08-09 23:12:35 +0000
commitc1bc3a7841890d8af470863e018721c035754999 (patch)
tree11bcaa505571c525e0d09c899fc5651cb372dac0 /source3/nsswitch/wb_client.c
parent722ce0eb955e0fd0d74593bada178f17263254bf (diff)
downloadsamba-c1bc3a7841890d8af470863e018721c035754999.tar.gz
samba-c1bc3a7841890d8af470863e018721c035754999.tar.bz2
samba-c1bc3a7841890d8af470863e018721c035754999.zip
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)
Diffstat (limited to 'source3/nsswitch/wb_client.c')
-rw-r--r--source3/nsswitch/wb_client.c74
1 files changed, 74 insertions, 0 deletions
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