s4:torture/smb2: add smb2.notify.session-reconnect test
[Samba.git] / source4 / winbind / wb_cmd_getgroups.c
blob29c5205369a7bfd5938a3e87d0bf98f6c833f689
1 /*
2 Unix SMB/CIFS implementation.
4 Backend for getgroups
6 Copyright (C) Matthieu Patou 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "libcli/composite/composite.h"
24 #include "winbind/wb_server.h"
25 #include "smbd/service_task.h"
26 #include "libcli/security/security.h"
28 struct cmd_getgroups_state {
29 struct composite_context *ctx;
30 struct wbsrv_service *service;
31 char* username;
32 uint32_t num_groups;
33 uint32_t current_group;
34 struct dom_sid **sids;
36 gid_t *gids;
39 /* The idea is to get the groups for a user
40 We receive one user from this we search for his uid
41 From the uid we search for his SID
42 From the SID we search for the list of groups
43 And with the list of groups we search for each group its gid
45 static void cmd_getgroups_recv_pwnam(struct composite_context *ctx);
46 static void wb_getgroups_uid2sid_recv(struct composite_context *ctx);
47 static void wb_getgroups_userdomsgroups_recv(struct composite_context *ctx);
48 static void cmd_getgroups_recv_gid(struct composite_context *ctx);
51 Ask for the uid from the username
53 struct composite_context *wb_cmd_getgroups_send(TALLOC_CTX *mem_ctx,
54 struct wbsrv_service *service,
55 const char* username)
57 struct composite_context *ctx, *result;
58 struct cmd_getgroups_state *state;
60 DEBUG(5, ("wb_cmd_getgroups_send called\n"));
62 result = composite_create(mem_ctx, service->task->event_ctx);
63 if (!result) return NULL;
65 state = talloc(mem_ctx, struct cmd_getgroups_state);
66 if (composite_nomem(state, result)) return result;
68 state->ctx = result;
69 result->private_data = state;
70 state->service = service;
71 state->num_groups = 0;
73 state->username = talloc_strdup(state,username);
74 if (composite_nomem(state->username, result)) return result;
76 ctx = wb_cmd_getpwnam_send(state, service, username);
77 if (composite_nomem(ctx, result)) return result;
79 composite_continue(result, ctx, cmd_getgroups_recv_pwnam, state);
80 return result;
84 Receive the uid and send request for SID
86 static void cmd_getgroups_recv_pwnam(struct composite_context *ctx)
88 struct composite_context *res;
89 struct cmd_getgroups_state *state =
90 talloc_get_type(ctx->async.private_data,
91 struct cmd_getgroups_state);
92 struct winbindd_pw *pw;
93 struct wbsrv_service *service = state->service;
95 DEBUG(5, ("cmd_getgroups_recv_pwnam called\n"));
97 state->ctx->status = wb_cmd_getpwnam_recv(ctx, state, &pw);
98 if (composite_is_ok(state->ctx)) {
99 res = wb_uid2sid_send(state, service, pw->pw_uid);
100 if (res == NULL) {
101 composite_error(state->ctx, NT_STATUS_NO_MEMORY);
102 return;
104 DEBUG(6, ("cmd_getgroups_recv_pwnam uid %d\n",pw->pw_uid));
106 composite_continue(ctx, res, wb_getgroups_uid2sid_recv, state);
111 Receive the SID and request groups through the userdomgroups helper
113 static void wb_getgroups_uid2sid_recv(struct composite_context *ctx)
115 struct composite_context *res;
116 struct cmd_getgroups_state *state =
117 talloc_get_type(ctx->async.private_data,
118 struct cmd_getgroups_state);
119 NTSTATUS status;
120 struct dom_sid *sid;
121 char *sid_str;
123 DEBUG(5, ("wb_getgroups_uid2sid_recv called\n"));
125 status = wb_uid2sid_recv(ctx, state, &sid);
126 if(NT_STATUS_IS_OK(status)) {
127 sid_str = dom_sid_string(state, sid);
129 /* If the conversion failed, bail out with a failure. */
130 if (sid_str != NULL) {
131 DEBUG(7, ("wb_getgroups_uid2sid_recv SID = %s\n",sid_str));
132 /* Ok got the SID now get the groups */
133 res = wb_cmd_userdomgroups_send(state, state->service, sid);
134 if (res == NULL) {
135 composite_error(state->ctx,
136 NT_STATUS_NO_MEMORY);
137 return;
140 composite_continue(ctx, res, wb_getgroups_userdomsgroups_recv, state);
141 } else {
142 composite_error(state->ctx, NT_STATUS_UNSUCCESSFUL);
148 Receive groups and search for uid for the first group
150 static void wb_getgroups_userdomsgroups_recv(struct composite_context *ctx) {
151 struct cmd_getgroups_state *state =
152 talloc_get_type(ctx->async.private_data,
153 struct cmd_getgroups_state);
154 uint32_t num_sids;
155 struct dom_sid **sids;
157 DEBUG(5, ("wb_getgroups_userdomsgroups_recv called\n"));
158 state->ctx->status = wb_cmd_userdomgroups_recv(ctx,state,&num_sids,&sids);
159 if (!composite_is_ok(state->ctx)) return;
161 DEBUG(5, ("wb_getgroups_userdomsgroups_recv %d groups\n",num_sids));
163 state->sids=sids;
164 state->num_groups=num_sids;
165 state->current_group=0;
167 if(num_sids > 0) {
168 state->gids = talloc_array(state, gid_t, state->num_groups);
169 ctx = wb_sid2gid_send(state, state->service, state->sids[state->current_group]);
170 composite_continue(state->ctx, ctx, cmd_getgroups_recv_gid, state);
171 } else {
172 composite_done(state->ctx);
177 Receive and uid the previous searched group and request the uid for the next one
179 static void cmd_getgroups_recv_gid(struct composite_context *ctx)
181 struct cmd_getgroups_state *state =
182 talloc_get_type(ctx->async.private_data,
183 struct cmd_getgroups_state);
184 gid_t gid;
186 DEBUG(5, ("cmd_getgroups_recv_gid called\n"));
188 state->ctx->status = wb_sid2gid_recv(ctx, &gid);
189 if(!composite_is_ok(state->ctx)) return;
191 state->gids[state->current_group] = gid;
192 DEBUG(5, ("cmd_getgroups_recv_gid group %d \n",state->current_group));
194 state->current_group++;
195 if(state->current_group < state->num_groups ) {
196 ctx = wb_sid2gid_send(state, state->service, state->sids[state->current_group]);
197 composite_continue(state->ctx, ctx, cmd_getgroups_recv_gid, state);
198 } else {
199 composite_done(state->ctx);
204 Return list of uids when finished
206 NTSTATUS wb_cmd_getgroups_recv(struct composite_context *ctx,
207 TALLOC_CTX *mem_ctx, gid_t **groups,
208 uint32_t *num_groups)
210 NTSTATUS status = composite_wait(ctx);
212 DEBUG(5, ("wb_cmd_getgroups_recv called\n"));
214 if (NT_STATUS_IS_OK(status)) {
215 struct cmd_getgroups_state *state =
216 talloc_get_type(ctx->private_data,
217 struct cmd_getgroups_state);
218 *groups = talloc_steal(mem_ctx, state->gids);
219 *num_groups = state->num_groups;
221 talloc_free(ctx);
222 return status;