[PATCH 2/5] s4:winbind Implement logic for getgroups to work

Matthieu Patou mat at matws.net
Wed Mar 3 17:05:06 MST 2010


This function is called by the system everytime we do a id user or when we do wbinfo -r
---
 source4/winbind/config.mk          |    1 +
 source4/winbind/wb_cmd_getgroups.c |  187 ++++++++++++++++++++++++++++++++++++
 source4/winbind/wb_samba3_cmd.c    |   74 +++++++++++----
 3 files changed, 245 insertions(+), 17 deletions(-)
 create mode 100644 source4/winbind/wb_cmd_getgroups.c

diff --git a/source4/winbind/config.mk b/source4/winbind/config.mk
index 45164d3..0bee89c 100644
--- a/source4/winbind/config.mk
+++ b/source4/winbind/config.mk
@@ -52,6 +52,7 @@ WINBIND_OBJ_FILES = $(addprefix $(winbindsrcdir)/, \
 		wb_cmd_getpwent.o \
 		wb_cmd_getgrent.o \
 		wb_cmd_setgrent.o \
+		wb_cmd_getgroups.o \
 		wb_pam_auth.o \
 		wb_sam_logon.o)
 
diff --git a/source4/winbind/wb_cmd_getgroups.c b/source4/winbind/wb_cmd_getgroups.c
new file mode 100644
index 0000000..2610262
--- /dev/null
+++ b/source4/winbind/wb_cmd_getgroups.c
@@ -0,0 +1,187 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Backend for getgroups
+
+   Copyright (C) Matthieu Patou 2010
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "libcli/composite/composite.h"
+#include "winbind/wb_server.h"
+#include "smbd/service_task.h"
+#include "libcli/security/dom_sid.h"
+
+struct cmd_getgroups_state {
+	struct composite_context *ctx;
+	struct wbsrv_service *service;
+	char* username;
+	uint32_t num_groups;
+	uint32_t current_group;
+	struct dom_sid **sids;
+
+	gid_t *gids;
+};
+
+static void cmd_getgroups_recv_pwnam(struct composite_context *ctx);
+static void wb_getgroups_uid2sid_recv(struct composite_context *ctx);
+static void wb_getgroups_userdomsgroups_recv(struct composite_context *ctx);
+static void cmd_getgroups_recv_gid(struct composite_context *ctx);
+
+struct composite_context *wb_cmd_getgroups_send(TALLOC_CTX *mem_ctx,
+						 struct wbsrv_service *service,
+						 const char* username)
+{
+	struct composite_context *ctx, *result;
+	struct cmd_getgroups_state *state;
+
+	DEBUG(5, ("wb_cmd_getgroups_send called\n"));
+
+	result = composite_create(mem_ctx, service->task->event_ctx);
+	if (!result) return NULL;
+
+	state = talloc(mem_ctx, struct cmd_getgroups_state);
+	if (composite_nomem(state, result)) return result;
+
+	state->ctx = result;
+	result->private_data = state;
+	state->service = service;
+	state->num_groups = 0;
+
+	state->username = talloc_strdup(state,username);
+	if (composite_nomem(ctx, result)) return result;
+
+	ctx = wb_cmd_getpwnam_send(state, service, username);
+	if (composite_nomem(ctx, result)) return result;
+
+	composite_continue(result, ctx, cmd_getgroups_recv_pwnam, state);
+	return result;
+}
+
+static void cmd_getgroups_recv_pwnam(struct composite_context *ctx)
+{
+	struct composite_context *res;
+        struct cmd_getgroups_state *state =
+		talloc_get_type(ctx->async.private_data,
+				struct cmd_getgroups_state);
+	struct winbindd_pw *pw;
+	struct wbsrv_service *service = state->service;
+
+	DEBUG(5, ("cmd_getgroups_recv_pwnam called\n"));
+
+	state->ctx->status = wb_cmd_getpwnam_recv(ctx, state, &pw);
+	if (composite_is_ok(state->ctx)) { 
+		res = wb_uid2sid_send(state, service, pw->pw_uid);
+		NT_STATUS_HAVE_NO_MEMORY(res);
+		DEBUG(6, ("cmd_getgroups_recv_pwnam uid %d\n",pw->pw_uid));
+
+		composite_continue(ctx, res, wb_getgroups_uid2sid_recv, state);
+	}
+}
+
+static void wb_getgroups_uid2sid_recv(struct composite_context *ctx)
+{
+	struct composite_context *res;
+        struct cmd_getgroups_state *state =
+		talloc_get_type(ctx->async.private_data,
+				struct cmd_getgroups_state);
+	NTSTATUS status;
+	struct dom_sid *sid;
+	char *sid_str;
+
+	DEBUG(5, ("wb_getgroups_uid2sid_recv called\n"));
+
+	status = wb_uid2sid_recv(ctx, state, &sid);
+	if(NT_STATUS_IS_OK(status)) {
+		sid_str = dom_sid_string(state, sid);
+
+		/* If the conversion failed, bail out with a failure. */
+		if (sid_str != NULL) {
+			DEBUG(7, ("wb_getgroups_uid2sid_recv SID = %s\n",sid_str));
+			/* Ok got the SID now get the groups */
+			res = wb_cmd_userdomgroups_send(state, state->service, sid);
+			NT_STATUS_HAVE_NO_MEMORY(res);
+
+			composite_continue(ctx, res, wb_getgroups_userdomsgroups_recv, state);
+		} else {
+			composite_error(state->ctx, NT_STATUS_UNSUCCESSFUL);
+		}
+	}
+}
+
+static void wb_getgroups_userdomsgroups_recv(struct composite_context *ctx) {
+        struct cmd_getgroups_state *state =
+		talloc_get_type(ctx->async.private_data,
+				struct cmd_getgroups_state);
+	int num_sids;
+	struct dom_sid **sids;
+
+	DEBUG(5, ("wb_getgroups_userdomsgroups_recv called\n"));
+	state->ctx->status = wb_cmd_userdomgroups_recv(ctx,state,&num_sids,&sids);
+	if (!composite_is_ok(state->ctx)) return;
+	DEBUG(5, ("wb_getgroups_userdomsgroups_recv %d groups\n",num_sids));
+	state->sids=sids;
+	state->num_groups=num_sids;
+	state->current_group=0;
+	if(num_sids > 0) {
+		state->gids = talloc_array(state, struct gid_t *, state->num_groups);
+		ctx = wb_sid2gid_send(state, state->service, state->sids[state->current_group]);
+		composite_continue(state->ctx, ctx, cmd_getgroups_recv_gid, state);
+	} else {
+		composite_done(state->ctx);
+	}
+}
+
+static void cmd_getgroups_recv_gid(struct composite_context *ctx)
+{
+        struct cmd_getgroups_state *state =
+		talloc_get_type(ctx->async.private_data,
+				struct cmd_getgroups_state);
+	gid_t gid;
+	char* sid_str;
+
+	DEBUG(5, ("cmd_getgroups_recv_gid called\n"));
+
+	state->ctx->status = wb_sid2gid_recv(ctx, &gid);
+	if(!composite_is_ok(state->ctx)) return;
+	state->gids[state->current_group] = gid; 
+	DEBUG(5, ("cmd_getgroups_recv_gid group %d \n",state->current_group));
+
+	state->current_group++;
+	if(state->current_group < state->num_groups ) {
+		ctx = wb_sid2gid_send(state, state->service, state->sids[state->current_group]);
+		composite_continue(state->ctx, ctx, cmd_getgroups_recv_gid, state);
+	} else {
+		composite_done(state->ctx);
+	}
+}
+
+NTSTATUS wb_cmd_getgroups_recv(struct composite_context *ctx,TALLOC_CTX *mem_ctx,gid_t **groups,uint32_t *num_groups)
+{
+	NTSTATUS status = composite_wait(ctx);
+
+	DEBUG(5, ("wb_cmd_getgroups_recv called\n"));
+
+	if (NT_STATUS_IS_OK(status)) {
+		struct cmd_getgroups_state *state =
+			talloc_get_type(ctx->private_data,
+					struct cmd_getgroups_state);
+		*groups = talloc_steal(mem_ctx, state->gids);
+		*num_groups = state->num_groups;
+	}
+	talloc_free(ctx);
+	return status;
+}
diff --git a/source4/winbind/wb_samba3_cmd.c b/source4/winbind/wb_samba3_cmd.c
index 2c846c4..99980d2 100644
--- a/source4/winbind/wb_samba3_cmd.c
+++ b/source4/winbind/wb_samba3_cmd.c
@@ -1183,31 +1183,51 @@ static void getgrgid_recv(struct composite_context *ctx)
 	wbsrv_samba3_async_epilogue(status, s3call);
 }
 
+static void getgroups_recv(struct composite_context *ctx);
+
 NTSTATUS wbsrv_samba3_getgroups(struct wbsrv_samba3_call *s3call)
 {
+	struct composite_context *ctx;
+	struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
+
 	DEBUG(5, ("wbsrv_samba3_getgroups called\n"));
-	s3call->response.result = WINBINDD_ERROR;
+	/* S3 code do the same so why not ... */
+	s3call->request.data.username[sizeof(s3call->request.data.username)-1]='\0';
+	ctx = wb_cmd_getgroups_send(s3call, service, s3call->request.data.username);
+	NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+	ctx->async.fn = getgroups_recv;
+	ctx->async.private_data = s3call;
+	s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
 	return NT_STATUS_OK;
 }
 
-static void setgrent_recv(struct composite_context *ctx)
+static void getgroups_recv(struct composite_context *ctx)
 {
 	struct wbsrv_samba3_call *s3call =
 		talloc_get_type(ctx->async.private_data,
 				struct wbsrv_samba3_call);
+	gid_t *gids;
+	uint32_t num_groups;
 	NTSTATUS status;
-	struct wbsrv_grent *grent;
+	DEBUG(5, ("getgroups_recv called\n"));
 
-	DEBUG(5, ("setpwent_recv called\n"));
-
-	status = wb_cmd_setgrent_recv(ctx, s3call->wbconn, &grent);
+	status = wb_cmd_getgroups_recv(ctx, s3call, &gids, &num_groups);
 	if (NT_STATUS_IS_OK(status)) {
-		s3call->wbconn->protocol_private_data = grent;
+		uint32_t extra_len = sizeof(gid_t) * num_groups;
+
+		s3call->response.data.num_entries = num_groups;
+		s3call->response.extra_data.data = gids;
+		s3call->response.length += extra_len;
+	} else {
+		s3call->response.result = WINBINDD_ERROR;
 	}
 
 	wbsrv_samba3_async_epilogue(status, s3call);
 }
 
+static void setgrent_recv(struct composite_context *ctx);
+
 NTSTATUS wbsrv_samba3_setgrent(struct wbsrv_samba3_call *s3call)
 {
 	struct composite_context *ctx;
@@ -1224,29 +1244,26 @@ NTSTATUS wbsrv_samba3_setgrent(struct wbsrv_samba3_call *s3call)
 	return NT_STATUS_OK;
 }
 
-static void getgrent_recv(struct composite_context *ctx)
+static void setgrent_recv(struct composite_context *ctx)
 {
 	struct wbsrv_samba3_call *s3call =
 		talloc_get_type(ctx->async.private_data,
 				struct wbsrv_samba3_call);
 	NTSTATUS status;
-	struct winbindd_gr *gr;
-	uint32_t num_groups;
+	struct wbsrv_grent *grent;
 
-	DEBUG(5, ("getgrent_recv called\n"));
+	DEBUG(5, ("setpwent_recv called\n"));
 
-	status = wb_cmd_getgrent_recv(ctx, s3call, &gr, &num_groups);
+	status = wb_cmd_setgrent_recv(ctx, s3call->wbconn, &grent);
 	if (NT_STATUS_IS_OK(status)) {
-		uint32_t extra_len = sizeof(struct winbindd_gr) * num_groups;
-
-		s3call->response.data.num_entries = num_groups;
-		s3call->response.extra_data.data = gr;
-		s3call->response.length += extra_len;
+		s3call->wbconn->protocol_private_data = grent;
 	}
 
 	wbsrv_samba3_async_epilogue(status, s3call);
 }
 
+static void getgrent_recv(struct composite_context *ctx);
+
 NTSTATUS wbsrv_samba3_getgrent(struct wbsrv_samba3_call *s3call)
 {
 	struct composite_context *ctx;
@@ -1271,6 +1288,29 @@ NTSTATUS wbsrv_samba3_getgrent(struct wbsrv_samba3_call *s3call)
 	return NT_STATUS_OK;
 }
 
+static void getgrent_recv(struct composite_context *ctx)
+{
+	struct wbsrv_samba3_call *s3call =
+		talloc_get_type(ctx->async.private_data,
+				struct wbsrv_samba3_call);
+	NTSTATUS status;
+	struct winbindd_gr *gr;
+	uint32_t num_groups;
+
+	DEBUG(5, ("getgrent_recv called\n"));
+
+	status = wb_cmd_getgrent_recv(ctx, s3call, &gr, &num_groups);
+	if (NT_STATUS_IS_OK(status)) {
+		uint32_t extra_len = sizeof(struct winbindd_gr) * num_groups;
+
+		s3call->response.data.num_entries = num_groups;
+		s3call->response.extra_data.data = gr;
+		s3call->response.length += extra_len;
+	}
+
+	wbsrv_samba3_async_epilogue(status, s3call);
+}
+
 NTSTATUS wbsrv_samba3_endgrent(struct wbsrv_samba3_call *s3call)
 {
 	DEBUG(5, ("wbsrv_samba3_endgrent called\n"));
-- 
1.6.3.3


--------------040801000300030600080808
Content-Type: text/x-patch;
 name="0003-s4-winbind-Fix-a-misplaced-returned-info.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="0003-s4-winbind-Fix-a-misplaced-returned-info.patch"



More information about the samba-technical mailing list