diff options
Diffstat (limited to 'source/nsswitch/wb_client.c')
-rw-r--r-- | source/nsswitch/wb_client.c | 186 |
1 files changed, 176 insertions, 10 deletions
diff --git a/source/nsswitch/wb_client.c b/source/nsswitch/wb_client.c index 9ac1515d7d3..efeb26fe45f 100644 --- a/source/nsswitch/wb_client.c +++ b/source/nsswitch/wb_client.c @@ -25,15 +25,24 @@ #include "includes.h" #include "nsswitch/nss.h" -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -extern DOM_SID global_sid_NULL; /* NULL sid */ - NSS_STATUS winbindd_request(int req_type, struct winbindd_request *request, struct winbindd_response *response); +static BOOL parse_domain_user(const char *domuser, fstring domain, fstring user) +{ + char *p = strchr(domuser,*lp_winbind_separator()); + + if (!p) + return False; + + fstrcpy(user, p+1); + fstrcpy(domain, domuser); + domain[PTR_DIFF(p, domuser)] = 0; + strupper(domain); + return True; +} + /* Call winbindd to convert a name to a sid */ BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid, @@ -51,8 +60,13 @@ BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid, ZERO_STRUCT(request); ZERO_STRUCT(response); - fstrcpy(request.data.name.dom_name, dom_name); - fstrcpy(request.data.name.name, name); + if (dom_name == NULL) { + if (!parse_domain_user(name, request.data.name.dom_name, request.data.name.name)) + return False; + } else { + fstrcpy(request.data.name.dom_name, dom_name); + fstrcpy(request.data.name.name, name); + } if ((result = winbindd_request(WINBINDD_LOOKUPNAME, &request, &response)) == NSS_STATUS_SUCCESS) { @@ -65,7 +79,7 @@ BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid, /* Call winbindd to convert sid to name */ -BOOL winbind_lookup_sid(const DOM_SID *sid, +BOOL winbind_lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type) { @@ -102,7 +116,7 @@ BOOL winbind_lookup_sid(const DOM_SID *sid, /* Call winbindd to convert SID to uid */ -BOOL winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid) +BOOL winbind_sid_to_uid(uid_t *puid, DOM_SID *sid) { struct winbindd_request request; struct winbindd_response response; @@ -168,7 +182,7 @@ BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid) /* Call winbindd to convert SID to gid */ -BOOL winbind_sid_to_gid(gid_t *pgid, const DOM_SID *sid) +BOOL winbind_sid_to_gid(gid_t *pgid, DOM_SID *sid) { struct winbindd_request request; struct winbindd_response response; @@ -261,6 +275,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 @@ -302,3 +390,81 @@ int winbind_getgroups(const char *user, int size, gid_t *list) SAFE_FREE(groups); return result; } + +/* Utility function. Convert a uid_t to a name if possible. */ + +BOOL winbind_uidtoname(fstring name, uid_t uid) +{ + DOM_SID sid; + fstring dom_name; + fstring user_name; + enum SID_NAME_USE name_type; + + if (!winbind_uid_to_sid(&sid, uid)) + return False; + if (!winbind_lookup_sid(&sid, dom_name, user_name, &name_type)) + return False; + + if (name_type != SID_NAME_USER) + return False; + + slprintf(name, sizeof(fstring)-1, "%s%s%s", dom_name, + lp_winbind_separator(), user_name); + + return True; +} + +/* Utility function. Convert a gid_t to a name if possible. */ + +BOOL winbind_gidtoname(fstring name, gid_t gid) +{ + DOM_SID sid; + fstring dom_name; + fstring group_name; + enum SID_NAME_USE name_type; + + if (!winbind_gid_to_sid(&sid, gid)) + return False; + if (!winbind_lookup_sid(&sid, dom_name, group_name, &name_type)) + return False; + + if (name_type != SID_NAME_DOM_GRP) + return False; + + slprintf(name, sizeof(fstring)-1, "%s%s%s", dom_name, + lp_winbind_separator(), group_name); + + return True; +} + +/* Utility function. Convert a name to a uid_t if possible. */ + +BOOL winbind_nametouid(uid_t *puid, const char *name) +{ + DOM_SID sid; + enum SID_NAME_USE name_type; + + if (!winbind_lookup_name(NULL, name, &sid, &name_type)) + return False; + + if (name_type != SID_NAME_USER) + return False; + + return winbind_sid_to_uid(puid, &sid); +} + +/* Utility function. Convert a name to a gid_t if possible. */ + +BOOL winbind_nametogid(gid_t *pgid, const char *gname) +{ + DOM_SID g_sid; + enum SID_NAME_USE name_type; + + if (!winbind_lookup_name(NULL, gname, &g_sid, &name_type)) + return False; + + if (name_type != SID_NAME_DOM_GRP) + return False; + + return winbind_sid_to_gid(pgid, &g_sid); +} |