Author: idra
Date: 2006-08-08 15:33:09 +0000 (Tue, 08 Aug 2006)
New Revision: 17459

WebSVN: 
http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=17459

Log:

As by Jerry's word commit this without his review.

This patch add some missing async functions to
solve UID/GID -> SID requests not just out of the cache,
but down the remote idmap if necessary.

This patch solves the problem of servers not showing users/groups names
for allocated UID/GIDs when joined to a group of servers that share a
prepopulated idmap backend.

Also correctly resolve UID/GIDs to SIDs when looking ACLs from the
windows security tab on teh same situation.

Simo.


Modified:
   branches/SAMBA_3_0/source/nsswitch/winbindd_async.c
   branches/SAMBA_3_0/source/nsswitch/winbindd_dual.c
   branches/SAMBA_3_0/source/nsswitch/winbindd_group.c
   branches/SAMBA_3_0/source/nsswitch/winbindd_nss.h
   branches/SAMBA_3_0/source/nsswitch/winbindd_sid.c
   branches/SAMBA_3_0/source/nsswitch/winbindd_user.c


Changeset:
Modified: branches/SAMBA_3_0/source/nsswitch/winbindd_async.c
===================================================================
--- branches/SAMBA_3_0/source/nsswitch/winbindd_async.c 2006-08-08 15:32:15 UTC 
(rev 17458)
+++ branches/SAMBA_3_0/source/nsswitch/winbindd_async.c 2006-08-08 15:33:09 UTC 
(rev 17459)
@@ -1524,3 +1524,113 @@
        do_async_domain(mem_ctx, domain, &request, query_user_recv,
                        (void *)cont, private_data);
 }
+
+/* The following uid2sid/gid2sid functions has been contributed by
+ * Keith Reynolds <[EMAIL PROTECTED]> */
+
+static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success,
+                                 struct winbindd_response *response,
+                                 void *c, void *private_data)
+{
+       void (*cont)(void *priv, BOOL succ, const char *sid) = c;
+
+       if (!success) {
+               DEBUG(5, ("Could not trigger uid2sid\n"));
+               cont(private_data, False, NULL);
+               return;
+       }
+
+       if (response->result != WINBINDD_OK) {
+               DEBUG(5, ("uid2sid returned an error\n"));
+               cont(private_data, False, NULL);
+               return;
+       }
+
+       cont(private_data, True, response->data.sid.sid);
+}
+
+void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid,
+                           void (*cont)(void *private_data, BOOL success, 
const char *sid),
+                           void *private_data)
+{
+       struct winbindd_request request;
+
+       ZERO_STRUCT(request);
+       request.cmd = WINBINDD_DUAL_UID2SID;
+       request.data.uid = uid;
+       do_async(mem_ctx, idmap_child(), &request, winbindd_uid2sid_recv, cont, 
private_data);
+}
+
+enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain,
+                                          struct winbindd_cli_state *state)
+{
+       DOM_SID sid;
+       NTSTATUS result;
+
+       DEBUG(3,("[%5lu]: uid to sid %lu\n",
+                (unsigned long)state->pid,
+                (unsigned long) state->request.data.uid));
+
+       /* Find sid for this uid and return it, possibly ask the slow remote 
idmap */
+       result = idmap_uid_to_sid(&sid, state->request.data.uid, 
IDMAP_FLAG_NONE);
+
+       if (NT_STATUS_IS_OK(result)) {
+               sid_to_string(state->response.data.sid.sid, &sid);
+               state->response.data.sid.type = SID_NAME_USER;
+               return WINBINDD_OK;
+       }
+
+       return WINBINDD_ERROR;
+}
+
+static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success,
+                                 struct winbindd_response *response,
+                                 void *c, void *private_data)
+{
+       void (*cont)(void *priv, BOOL succ, const char *sid) = c;
+
+       if (!success) {
+               DEBUG(5, ("Could not trigger gid2sid\n"));
+               cont(private_data, False, NULL);
+               return;
+       }
+
+       cont(private_data, True, response->data.sid.sid);
+}
+
+void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid,
+                           void (*cont)(void *private_data, BOOL success, 
const char *sid),
+                           void *private_data)
+{
+       struct winbindd_request request;
+
+       ZERO_STRUCT(request);
+       request.cmd = WINBINDD_DUAL_GID2SID;
+       request.data.gid = gid;
+       do_async(mem_ctx, idmap_child(), &request, winbindd_gid2sid_recv, cont, 
private_data);
+}
+
+enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain,
+                                          struct winbindd_cli_state *state)
+{
+       DOM_SID sid;
+       NTSTATUS result;
+
+       DEBUG(3,("[%5lu]: gid %lu to sid\n",
+               (unsigned long)state->pid,
+               (unsigned long) state->request.data.gid));
+
+       /* Find sid for this gid and return it, possibly ask the slow remote 
idmap */
+       result = idmap_gid_to_sid(&sid, state->request.data.gid, 
IDMAP_FLAG_NONE);
+
+       if (NT_STATUS_IS_OK(result)) {
+               sid_to_string(state->response.data.sid.sid, &sid);
+               DEBUG(10, ("[%5lu]: retrieved sid: %s\n",
+                          (unsigned long)state->pid,
+                          state->response.data.sid.sid));
+               state->response.data.sid.type = SID_NAME_DOM_GRP;
+               return WINBINDD_OK;
+       }
+
+       return WINBINDD_ERROR;
+}

Modified: branches/SAMBA_3_0/source/nsswitch/winbindd_dual.c
===================================================================
--- branches/SAMBA_3_0/source/nsswitch/winbindd_dual.c  2006-08-08 15:32:15 UTC 
(rev 17458)
+++ branches/SAMBA_3_0/source/nsswitch/winbindd_dual.c  2006-08-08 15:33:09 UTC 
(rev 17459)
@@ -357,6 +357,8 @@
        { WINBINDD_CHECK_MACHACC,        winbindd_dual_check_machine_acct,    
"CHECK_MACHACC" },
        { WINBINDD_DUAL_SID2UID,         winbindd_dual_sid2uid,               
"DUAL_SID2UID" },
        { WINBINDD_DUAL_SID2GID,         winbindd_dual_sid2gid,               
"DUAL_SID2GID" },
+       { WINBINDD_DUAL_UID2SID,         winbindd_dual_uid2sid,               
"DUAL_UID2SID" },
+       { WINBINDD_DUAL_GID2SID,         winbindd_dual_gid2sid,               
"DUAL_GID2SID" },
        { WINBINDD_DUAL_UID2NAME,        winbindd_dual_uid2name,              
"DUAL_UID2NAME" },
        { WINBINDD_DUAL_NAME2UID,        winbindd_dual_name2uid,              
"DUAL_NAME2UID" },
        { WINBINDD_DUAL_GID2NAME,        winbindd_dual_gid2name,              
"DUAL_GID2NAME" },

Modified: branches/SAMBA_3_0/source/nsswitch/winbindd_group.c
===================================================================
--- branches/SAMBA_3_0/source/nsswitch/winbindd_group.c 2006-08-08 15:32:15 UTC 
(rev 17458)
+++ branches/SAMBA_3_0/source/nsswitch/winbindd_group.c 2006-08-08 15:33:09 UTC 
(rev 17459)
@@ -329,54 +329,16 @@
        request_ok(state);
 }
 
-/* Return a group structure from a gid number */
-
-void winbindd_getgrgid(struct winbindd_cli_state *state)
+static void getgrgid_got_sid(struct winbindd_cli_state *state, DOM_SID 
group_sid)
 {
        struct winbindd_domain *domain;
-       DOM_SID group_sid;
        enum SID_NAME_USE name_type;
        fstring dom_name;
        fstring group_name;
        size_t gr_mem_len;
        size_t num_gr_mem;
        char *gr_mem;
-       NTSTATUS status;
 
-       DEBUG(3, ("[%5lu]: getgrgid %lu\n", (unsigned long)state->pid, 
-                 (unsigned long)state->request.data.gid));
-
-       /* Bug out if the gid isn't in the winbind range */
-
-       if ((state->request.data.gid < server_state.gid_low) ||
-           (state->request.data.gid > server_state.gid_high)) {
-               request_error(state);
-               return;
-       }
-
-       /* Get sid from gid */
-
-       status = idmap_gid_to_sid(&group_sid, state->request.data.gid, 0);
-       if (NT_STATUS_IS_OK(status)) {
-               /* This is a remote one */
-               goto got_sid;
-       }
-
-       /* Ok, this might be "ours", i.e. an alias */
-
-       if (pdb_gid_to_sid(state->request.data.gid, &group_sid) &&
-           lookup_sid(state->mem_ctx, &group_sid, NULL, NULL, &name_type) &&
-           (name_type == SID_NAME_ALIAS)) {
-               /* Hey, got an alias */
-               goto got_sid;
-       }
-
-       DEBUG(1, ("could not convert gid %lu to sid\n", 
-                 (unsigned long)state->request.data.gid));
-       request_error(state);
-       return;
-
- got_sid:
        /* Get name from sid */
 
        if (!winbindd_lookup_name_by_sid(state->mem_ctx, &group_sid, dom_name,
@@ -423,9 +385,73 @@
 
        state->response.length += gr_mem_len;
        state->response.extra_data.data = gr_mem;
+
        request_ok(state);
 }
 
+static void getgrgid_recv(void *private_data, BOOL success, const char *sid)
+{
+       struct winbindd_cli_state *state = talloc_get_type_abort(private_data, 
struct winbindd_cli_state);
+       enum SID_NAME_USE name_type;
+       DOM_SID group_sid;
+
+       if (success) {
+               DEBUG(10,("getgrgid_recv: gid %lu has sid %s\n",
+                         (unsigned long)(state->request.data.gid), sid));
+
+               string_to_sid(&group_sid, sid);
+               getgrgid_got_sid(state, group_sid);
+               return;
+       }
+
+       /* Ok, this might be "ours", i.e. an alias */
+       if (pdb_gid_to_sid(state->request.data.gid, &group_sid) &&
+           lookup_sid(state->mem_ctx, &group_sid, NULL, NULL, &name_type) &&
+           (name_type == SID_NAME_ALIAS)) {
+               /* Hey, got an alias */
+               DEBUG(10,("getgrgid_recv: we have an alias with gid %lu and sid 
%s\n",
+                         (unsigned long)(state->request.data.gid), sid));
+               getgrgid_got_sid(state, group_sid);
+               return;
+       }
+
+       DEBUG(1, ("could not convert gid %lu to sid\n", 
+                 (unsigned long)state->request.data.gid));
+       request_error(state);
+}
+
+/* Return a group structure from a gid number */
+void winbindd_getgrgid(struct winbindd_cli_state *state)
+{
+       DOM_SID group_sid;
+       NTSTATUS status;
+
+       DEBUG(3, ("[%5lu]: getgrgid %lu\n", (unsigned long)state->pid, 
+                 (unsigned long)state->request.data.gid));
+
+       /* Bug out if the gid isn't in the winbind range */
+
+       if ((state->request.data.gid < server_state.gid_low) ||
+           (state->request.data.gid > server_state.gid_high)) {
+               request_error(state);
+               return;
+       }
+
+       /* Get sid from gid */
+
+       status = idmap_gid_to_sid(&group_sid, state->request.data.gid, 
IDMAP_FLAG_NONE);
+       if (NT_STATUS_IS_OK(status)) {
+               /* This is a remote one */
+               getgrgid_got_sid(state, group_sid);
+               return;
+       }
+
+       DEBUG(10,("winbindd_getgrgid: gid %lu not found in cache, try with the 
async interface\n",
+                 (unsigned long)state->request.data.gid));
+
+       winbindd_gid2sid_async(state->mem_ctx, state->request.data.gid, 
getgrgid_recv, state);
+}
+
 /*
  * set/get/endgrent functions
  */

Modified: branches/SAMBA_3_0/source/nsswitch/winbindd_nss.h
===================================================================
--- branches/SAMBA_3_0/source/nsswitch/winbindd_nss.h   2006-08-08 15:32:15 UTC 
(rev 17458)
+++ branches/SAMBA_3_0/source/nsswitch/winbindd_nss.h   2006-08-08 15:33:09 UTC 
(rev 17459)
@@ -140,6 +140,8 @@
         * between parent and children */
        WINBINDD_DUAL_SID2UID,
        WINBINDD_DUAL_SID2GID,
+       WINBINDD_DUAL_UID2SID,
+       WINBINDD_DUAL_GID2SID,
        WINBINDD_DUAL_IDMAPSET,
 
        /* Wrapper around possibly blocking unix nss calls */

Modified: branches/SAMBA_3_0/source/nsswitch/winbindd_sid.c
===================================================================
--- branches/SAMBA_3_0/source/nsswitch/winbindd_sid.c   2006-08-08 15:32:15 UTC 
(rev 17458)
+++ branches/SAMBA_3_0/source/nsswitch/winbindd_sid.c   2006-08-08 15:33:09 UTC 
(rev 17459)
@@ -297,11 +297,12 @@
                                    enum SID_NAME_USE type);
 static void uid2sid_idmap_set_mapping_recv(void *private_data, BOOL success);
 
+static void uid2sid_recv(void *private_data, BOOL success, const char *sid);
+
 void winbindd_uid_to_sid(struct winbindd_cli_state *state)
 {
        DOM_SID sid;
        NTSTATUS status;
-       struct uid2sid_state *uid2sid_state;
 
        DEBUG(3, ("[%5lu]: uid to sid %lu\n", (unsigned long)state->pid, 
                  (unsigned long)state->request.data.uid));
@@ -322,6 +323,25 @@
                return;
        }
 
+       winbindd_uid2sid_async(state->mem_ctx, state->request.data.uid, 
uid2sid_recv, state);
+}
+
+static void uid2sid_recv(void *private_data, BOOL success, const char *sid)
+{
+       struct winbindd_cli_state *state = private_data;
+       struct uid2sid_state *uid2sid_state;
+
+       if (success) {
+               DEBUG(10,("uid2sid: uid %lu has sid %s\n",
+                         (unsigned long)(state->request.data.uid), sid));
+               fstrcpy(state->response.data.sid.sid, sid);
+               state->response.data.sid.type = SID_NAME_USER;
+               request_ok(state);
+               return;
+       }
+
+       /* preexisitng mapping not found go on */
+
        if (is_in_uid_range(state->request.data.uid)) {
                /* This is winbind's, so we should better have succeeded
                 * above. */
@@ -337,9 +357,6 @@
                return;
        }
 
-       /* The only chance that this is correct is that winbind trusted
-        * domains only = yes, and the user exists in nss and the domain. */
-
        uid2sid_state = TALLOC_ZERO_P(state->mem_ctx, struct uid2sid_state);
        if (uid2sid_state == NULL) {
                DEBUG(0, ("talloc failed\n"));
@@ -424,6 +441,8 @@
                                    enum SID_NAME_USE type);
 static void gid2sid_idmap_set_mapping_recv(void *private_data, BOOL success);
 
+static void gid2sid_recv(void *private_data, BOOL success, const char *sid);
+
 void winbindd_gid_to_sid(struct winbindd_cli_state *state)
 {
        DOM_SID sid;
@@ -449,6 +468,25 @@
                return;
        }
 
+       winbindd_gid2sid_async(state->mem_ctx, state->request.data.gid, 
gid2sid_recv, state);
+}
+
+static void gid2sid_recv(void *private_data, BOOL success, const char *sid)
+{
+       struct winbindd_cli_state *state = private_data;
+       struct gid2sid_state *gid2sid_state;
+
+       if (success) {
+               DEBUG(10,("gid2sid: gid %lu has sid %s\n",
+                         (unsigned long)(state->request.data.gid), sid));
+               fstrcpy(state->response.data.sid.sid, sid);
+               state->response.data.sid.type = SID_NAME_DOM_GRP;
+               request_ok(state);
+               return;
+       }
+
+       /* preexisitng mapping not found go on */
+
        if (is_in_gid_range(state->request.data.gid)) {
                /* This is winbind's, so we should better have succeeded
                 * above. */

Modified: branches/SAMBA_3_0/source/nsswitch/winbindd_user.c
===================================================================
--- branches/SAMBA_3_0/source/nsswitch/winbindd_user.c  2006-08-08 15:32:15 UTC 
(rev 17458)
+++ branches/SAMBA_3_0/source/nsswitch/winbindd_user.c  2006-08-08 15:33:09 UTC 
(rev 17459)
@@ -380,15 +380,32 @@
        winbindd_getpwsid(state, sid);
 }
 
+static void getpwuid_recv(void *private_data, BOOL success, const char *sid)
+{
+       struct winbindd_cli_state *state = private_data;
+       DOM_SID user_sid;
+
+       if (!success) {
+               DEBUG(10,("uid2sid_recv: uid [%lu] to sid mapping failed\n.",
+                         (unsigned long)(state->request.data.uid)));
+               request_error(state);
+               return;
+       }
+       
+       DEBUG(10,("uid2sid_recv: uid %lu has sid %s\n",
+                 (unsigned long)(state->request.data.uid), sid));
+
+       string_to_sid(&user_sid, sid);
+       winbindd_getpwsid(state, &user_sid);
+}
+
 /* Return a password structure given a uid number */
-
 void winbindd_getpwuid(struct winbindd_cli_state *state)
 {
        DOM_SID user_sid;
        NTSTATUS status;
        
        /* Bug out if the uid isn't in the winbind range */
-
        if ((state->request.data.uid < server_state.uid_low ) ||
            (state->request.data.uid > server_state.uid_high)) {
                request_error(state);
@@ -401,14 +418,15 @@
        status = idmap_uid_to_sid(&user_sid, state->request.data.uid,
                                  IDMAP_FLAG_QUERY_ONLY | 
IDMAP_FLAG_CACHE_ONLY);
 
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(5, ("Could not find SID for uid %lu\n",
-                         (unsigned long)state->request.data.uid));
-               request_error(state);
+       if (NT_STATUS_IS_OK(status)) {
+               winbindd_getpwsid(state, &user_sid);
                return;
        }
 
-       winbindd_getpwsid(state, &user_sid);
+       DEBUG(10,("Could not find SID for uid %lu in the cache. Querying idmap 
backend\n",
+                 (unsigned long)state->request.data.uid));
+
+       winbindd_uid2sid_async(state->mem_ctx, state->request.data.uid, 
getpwuid_recv, state);
 }
 
 /*

Reply via email to