source: trunk/server/source4/winbind/wb_cmd_getgroups.c

Last change on this file was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

File size: 6.7 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 Backend for getgroups
5
6 Copyright (C) Matthieu Patou 2010
7
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.
12
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.
17
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/>.
20*/
21
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"
27
28struct 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;
35
36 gid_t *gids;
37};
38
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
44*/
45static void cmd_getgroups_recv_pwnam(struct composite_context *ctx);
46static void wb_getgroups_uid2sid_recv(struct composite_context *ctx);
47static void wb_getgroups_userdomsgroups_recv(struct composite_context *ctx);
48static void cmd_getgroups_recv_gid(struct composite_context *ctx);
49
50/*
51 Ask for the uid from the username
52*/
53struct composite_context *wb_cmd_getgroups_send(TALLOC_CTX *mem_ctx,
54 struct wbsrv_service *service,
55 const char* username)
56{
57 struct composite_context *ctx, *result;
58 struct cmd_getgroups_state *state;
59
60 DEBUG(5, ("wb_cmd_getgroups_send called\n"));
61
62 result = composite_create(mem_ctx, service->task->event_ctx);
63 if (!result) return NULL;
64
65 state = talloc(mem_ctx, struct cmd_getgroups_state);
66 if (composite_nomem(state, result)) return result;
67
68 state->ctx = result;
69 result->private_data = state;
70 state->service = service;
71 state->num_groups = 0;
72
73 state->username = talloc_strdup(state,username);
74 if (composite_nomem(state->username, result)) return result;
75
76 ctx = wb_cmd_getpwnam_send(state, service, username);
77 if (composite_nomem(ctx, result)) return result;
78
79 composite_continue(result, ctx, cmd_getgroups_recv_pwnam, state);
80 return result;
81}
82
83/*
84 Receive the uid and send request for SID
85*/
86static void cmd_getgroups_recv_pwnam(struct composite_context *ctx)
87{
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;
94
95 DEBUG(5, ("cmd_getgroups_recv_pwnam called\n"));
96
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;
103 }
104 DEBUG(6, ("cmd_getgroups_recv_pwnam uid %d\n",pw->pw_uid));
105
106 composite_continue(ctx, res, wb_getgroups_uid2sid_recv, state);
107 }
108}
109
110/*
111 Receive the SID and request groups through the userdomgroups helper
112*/
113static void wb_getgroups_uid2sid_recv(struct composite_context *ctx)
114{
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;
122
123 DEBUG(5, ("wb_getgroups_uid2sid_recv called\n"));
124
125 status = wb_uid2sid_recv(ctx, state, &sid);
126 if(NT_STATUS_IS_OK(status)) {
127 sid_str = dom_sid_string(state, sid);
128
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;
138 }
139
140 composite_continue(ctx, res, wb_getgroups_userdomsgroups_recv, state);
141 } else {
142 composite_error(state->ctx, NT_STATUS_UNSUCCESSFUL);
143 }
144 }
145}
146
147/*
148 Receive groups and search for uid for the first group
149*/
150static 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;
156
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;
160
161 DEBUG(5, ("wb_getgroups_userdomsgroups_recv %d groups\n",num_sids));
162
163 state->sids=sids;
164 state->num_groups=num_sids;
165 state->current_group=0;
166
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);
173 }
174}
175
176/*
177 Receive and uid the previous searched group and request the uid for the next one
178*/
179static void cmd_getgroups_recv_gid(struct composite_context *ctx)
180{
181 struct cmd_getgroups_state *state =
182 talloc_get_type(ctx->async.private_data,
183 struct cmd_getgroups_state);
184 gid_t gid;
185
186 DEBUG(5, ("cmd_getgroups_recv_gid called\n"));
187
188 state->ctx->status = wb_sid2gid_recv(ctx, &gid);
189 if(!composite_is_ok(state->ctx)) return;
190
191 state->gids[state->current_group] = gid;
192 DEBUG(5, ("cmd_getgroups_recv_gid group %d \n",state->current_group));
193
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);
200 }
201}
202
203/*
204 Return list of uids when finished
205*/
206NTSTATUS wb_cmd_getgroups_recv(struct composite_context *ctx,
207 TALLOC_CTX *mem_ctx, gid_t **groups,
208 uint32_t *num_groups)
209{
210 NTSTATUS status = composite_wait(ctx);
211
212 DEBUG(5, ("wb_cmd_getgroups_recv called\n"));
213
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;
220 }
221 talloc_free(ctx);
222 return status;
223}
Note: See TracBrowser for help on using the repository browser.