summaryrefslogtreecommitdiffstats
path: root/source/nsswitch/wb_client.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/nsswitch/wb_client.c')
-rw-r--r--source/nsswitch/wb_client.c186
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);
+}