svn commit: samba r17459 - in branches/SAMBA_3_0/source/nsswitch: .

idra at samba.org idra at samba.org
Tue Aug 8 15:33:10 GMT 2006


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 <Keith.Reynolds at centrify.com> */
+
+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);
 }
 
 /*



More information about the samba-cvs mailing list