s4: ran minimal_includes.pl on source4/winbind
[kai/samba.git] / source4 / winbind / wb_async_helpers.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Copyright (C) Volker Lendecke 2005
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 /*
20   a composite API for finding a DC and its name
21 */
22
23 #include "includes.h"
24 #include "libcli/composite/composite.h"
25 #include "winbind/wb_async_helpers.h"
26
27 #include "libcli/security/security.h"
28 #include "librpc/gen_ndr/ndr_lsa_c.h"
29 #include "librpc/gen_ndr/ndr_samr_c.h"
30
31
32 struct lsa_lookupsids_state {
33         struct composite_context *ctx;
34         int num_sids;
35         struct lsa_LookupSids r;
36         struct lsa_SidArray sids;
37         struct lsa_TransNameArray names;
38         struct lsa_RefDomainList *domains;
39         uint32_t count;
40         struct wb_sid_object **result;
41 };
42
43 static void lsa_lookupsids_recv_names(struct rpc_request *req);
44
45 struct composite_context *wb_lsa_lookupsids_send(TALLOC_CTX *mem_ctx,
46                                                  struct dcerpc_pipe *lsa_pipe,
47                                                  struct policy_handle *handle,
48                                                  int num_sids,
49                                                  const struct dom_sid **sids)
50 {
51         struct composite_context *result;
52         struct rpc_request *req;
53         struct lsa_lookupsids_state *state;
54         int i;
55
56         result = composite_create(mem_ctx, lsa_pipe->conn->event_ctx);
57         if (result == NULL) goto failed;
58
59         state = talloc(result, struct lsa_lookupsids_state);
60         if (state == NULL) goto failed;
61         result->private_data = state;
62         state->ctx = result;
63
64         state->sids.num_sids = num_sids;
65         state->sids.sids = talloc_array(state, struct lsa_SidPtr, num_sids);
66         if (state->sids.sids == NULL) goto failed;
67
68         for (i=0; i<num_sids; i++) {
69                 state->sids.sids[i].sid = dom_sid_dup(state->sids.sids,
70                                                       sids[i]);
71                 if (state->sids.sids[i].sid == NULL) goto failed;
72         }
73
74         state->domains = talloc(state, struct lsa_RefDomainList);
75         if (state->domains == NULL) goto failed;
76
77         state->count = 0;
78         state->num_sids = num_sids;
79         state->names.count = 0;
80         state->names.names = NULL;
81
82         state->r.in.handle = handle;
83         state->r.in.sids = &state->sids;
84         state->r.in.names = &state->names;
85         state->r.in.level = 1;
86         state->r.in.count = &state->count;
87         state->r.out.names = &state->names;
88         state->r.out.count = &state->count;
89         state->r.out.domains = &state->domains;
90
91         req = dcerpc_lsa_LookupSids_send(lsa_pipe, state, &state->r);
92         if (req == NULL) goto failed;
93
94         req->async.callback = lsa_lookupsids_recv_names;
95         req->async.private_data = state;
96         return result;
97
98  failed:
99         talloc_free(result);
100         return NULL;
101 }
102
103 static void lsa_lookupsids_recv_names(struct rpc_request *req)
104 {
105         struct lsa_lookupsids_state *state =
106                 talloc_get_type(req->async.private_data,
107                                 struct lsa_lookupsids_state);
108         int i;
109
110         state->ctx->status = dcerpc_ndr_request_recv(req);
111         if (!composite_is_ok(state->ctx)) return;
112         state->ctx->status = state->r.out.result;
113         if (!NT_STATUS_IS_OK(state->ctx->status) &&
114             !NT_STATUS_EQUAL(state->ctx->status, STATUS_SOME_UNMAPPED)) {
115                 composite_error(state->ctx, state->ctx->status);
116                 return;
117         }
118
119         state->result = talloc_array(state, struct wb_sid_object *,
120                                      state->num_sids);
121         if (composite_nomem(state->result, state->ctx)) return;
122
123         for (i=0; i<state->num_sids; i++) {
124                 struct lsa_TranslatedName *name =
125                         &state->r.out.names->names[i];
126                 struct lsa_DomainInfo *dom;
127                 struct lsa_RefDomainList *domains =
128                         state->domains;
129
130                 state->result[i] = talloc_zero(state->result,
131                                                struct wb_sid_object);
132                 if (composite_nomem(state->result[i], state->ctx)) return;
133
134                 state->result[i]->type = name->sid_type;
135                 if (state->result[i]->type == SID_NAME_UNKNOWN) {
136                         continue;
137                 }
138
139                 if (name->sid_index >= domains->count) {
140                         composite_error(state->ctx,
141                                         NT_STATUS_INVALID_PARAMETER);
142                         return;
143                 }
144
145                 dom = &domains->domains[name->sid_index];
146                 state->result[i]->domain = talloc_reference(state->result[i],
147                                                             dom->name.string);
148                 if ((name->sid_type == SID_NAME_DOMAIN) ||
149                     (name->name.string == NULL)) {
150                         state->result[i]->name =
151                                 talloc_strdup(state->result[i], "");
152                 } else {
153                         state->result[i]->name =
154                                 talloc_steal(state->result[i],
155                                              name->name.string);
156                 }
157
158                 if (composite_nomem(state->result[i]->name, state->ctx)) {
159                         return;
160                 }
161         }
162
163         composite_done(state->ctx);
164 }
165
166 NTSTATUS wb_lsa_lookupsids_recv(struct composite_context *c,
167                                 TALLOC_CTX *mem_ctx,
168                                 struct wb_sid_object ***names)
169 {
170         NTSTATUS status = composite_wait(c);
171         if (NT_STATUS_IS_OK(status)) {
172                 struct lsa_lookupsids_state *state =
173                         talloc_get_type(c->private_data,
174                                         struct lsa_lookupsids_state);
175                 *names = talloc_steal(mem_ctx, state->result);
176         }
177         talloc_free(c);
178         return status;
179 }
180
181
182 struct lsa_lookupnames_state {
183         struct composite_context *ctx;
184         uint32_t num_names;
185         struct lsa_LookupNames r;
186         struct lsa_TransSidArray sids;
187         struct lsa_RefDomainList *domains;
188         uint32_t count;
189         struct wb_sid_object **result;
190 };
191
192 static void lsa_lookupnames_recv_sids(struct rpc_request *req);
193
194 struct composite_context *wb_lsa_lookupnames_send(TALLOC_CTX *mem_ctx,
195                                                   struct dcerpc_pipe *lsa_pipe,
196                                                   struct policy_handle *handle,
197                                                   int num_names,
198                                                   const char **names)
199 {
200         struct composite_context *result;
201         struct rpc_request *req;
202         struct lsa_lookupnames_state *state;
203
204         struct lsa_String *lsa_names;
205         int i;
206
207         result = composite_create(mem_ctx, lsa_pipe->conn->event_ctx);
208         if (result == NULL) goto failed;
209
210         state = talloc(result, struct lsa_lookupnames_state);
211         if (state == NULL) goto failed;
212         result->private_data = state;
213         state->ctx = result;
214
215         state->sids.count = 0;
216         state->sids.sids = NULL;
217         state->num_names = num_names;
218         state->count = 0;
219
220         lsa_names = talloc_array(state, struct lsa_String, num_names);
221         if (lsa_names == NULL) goto failed;
222
223         for (i=0; i<num_names; i++) {
224                 lsa_names[i].string = names[i];
225         }
226
227         state->domains = talloc(state, struct lsa_RefDomainList);
228         if (state->domains == NULL) goto failed;
229
230         state->r.in.handle = handle;
231         state->r.in.num_names = num_names;
232         state->r.in.names = lsa_names;
233         state->r.in.sids = &state->sids;
234         state->r.in.level = 1;
235         state->r.in.count = &state->count;
236         state->r.out.count = &state->count;
237         state->r.out.sids = &state->sids;
238         state->r.out.domains = &state->domains;
239
240         req = dcerpc_lsa_LookupNames_send(lsa_pipe, state, &state->r);
241         if (req == NULL) goto failed;
242
243         req->async.callback = lsa_lookupnames_recv_sids;
244         req->async.private_data = state;
245         return result;
246
247  failed:
248         talloc_free(result);
249         return NULL;
250 }
251
252 static void lsa_lookupnames_recv_sids(struct rpc_request *req)
253 {
254         struct lsa_lookupnames_state *state =
255                 talloc_get_type(req->async.private_data,
256                                 struct lsa_lookupnames_state);
257         int i;
258
259         state->ctx->status = dcerpc_ndr_request_recv(req);
260         if (!composite_is_ok(state->ctx)) return;
261         state->ctx->status = state->r.out.result;
262         if (!NT_STATUS_IS_OK(state->ctx->status) &&
263             !NT_STATUS_EQUAL(state->ctx->status, STATUS_SOME_UNMAPPED)) {
264                 composite_error(state->ctx, state->ctx->status);
265                 return;
266         }
267
268         state->result = talloc_array(state, struct wb_sid_object *,
269                                      state->num_names);
270         if (composite_nomem(state->result, state->ctx)) return;
271
272         for (i=0; i<state->num_names; i++) {
273                 struct lsa_TranslatedSid *sid = &state->r.out.sids->sids[i];
274                 struct lsa_RefDomainList *domains = state->domains;
275                 struct lsa_DomainInfo *dom;
276
277                 state->result[i] = talloc_zero(state->result,
278                                                struct wb_sid_object);
279                 if (composite_nomem(state->result[i], state->ctx)) return;
280
281                 state->result[i]->type = sid->sid_type;
282                 if (state->result[i]->type == SID_NAME_UNKNOWN) {
283                         continue;
284                 }
285
286                 if (sid->sid_index >= domains->count) {
287                         composite_error(state->ctx,
288                                         NT_STATUS_INVALID_PARAMETER);
289                         return;
290                 }
291
292                 dom = &domains->domains[sid->sid_index];
293
294                 state->result[i]->sid = dom_sid_add_rid(state->result[i],
295                                                         dom->sid, sid->rid);
296         }
297
298         composite_done(state->ctx);
299 }
300
301 NTSTATUS wb_lsa_lookupnames_recv(struct composite_context *c,
302                                  TALLOC_CTX *mem_ctx,
303                                  struct wb_sid_object ***sids)
304 {
305         NTSTATUS status = composite_wait(c);
306         if (NT_STATUS_IS_OK(status)) {
307                 struct lsa_lookupnames_state *state =
308                         talloc_get_type(c->private_data,
309                                         struct lsa_lookupnames_state);
310                 *sids = talloc_steal(mem_ctx, state->result);
311         }
312         talloc_free(c);
313         return status;
314 }
315 struct samr_getuserdomgroups_state {
316         struct composite_context *ctx;
317         struct dcerpc_pipe *samr_pipe;
318
319         int num_rids;
320         uint32_t *rids;
321
322         struct samr_RidWithAttributeArray *rid_array;
323
324         struct policy_handle *user_handle;
325         struct samr_OpenUser o;
326         struct samr_GetGroupsForUser g;
327         struct samr_Close c;
328 };
329
330 static void samr_usergroups_recv_open(struct rpc_request *req);
331 static void samr_usergroups_recv_groups(struct rpc_request *req);
332 static void samr_usergroups_recv_close(struct rpc_request *req);
333
334 struct composite_context *wb_samr_userdomgroups_send(TALLOC_CTX *mem_ctx,
335                                                      struct dcerpc_pipe *samr_pipe,
336                                                      struct policy_handle *domain_handle,
337                                                      uint32_t rid)
338 {
339         struct composite_context *result;
340         struct rpc_request *req;
341         struct samr_getuserdomgroups_state *state;
342
343         result = composite_create(mem_ctx, samr_pipe->conn->event_ctx);
344         if (result == NULL) goto failed;
345
346         state = talloc(result, struct samr_getuserdomgroups_state);
347         if (state == NULL) goto failed;
348         result->private_data = state;
349         state->ctx = result;
350
351         state->samr_pipe = samr_pipe;
352
353         state->user_handle = talloc(state, struct policy_handle);
354         if (state->user_handle == NULL) goto failed;
355
356         state->o.in.domain_handle = domain_handle;
357         state->o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
358         state->o.in.rid = rid;
359         state->o.out.user_handle = state->user_handle;
360
361         req = dcerpc_samr_OpenUser_send(state->samr_pipe, state, &state->o);
362         if (req == NULL) goto failed;
363
364         req->async.callback = samr_usergroups_recv_open;
365         req->async.private_data = state;
366         return result;
367
368  failed:
369         talloc_free(result);
370         return NULL;
371 }
372                                               
373 static void samr_usergroups_recv_open(struct rpc_request *req)
374 {
375         struct samr_getuserdomgroups_state *state =
376                 talloc_get_type(req->async.private_data,
377                                 struct samr_getuserdomgroups_state);
378
379         state->ctx->status = dcerpc_ndr_request_recv(req);
380         if (!composite_is_ok(state->ctx)) return;
381         state->ctx->status = state->o.out.result;
382         if (!composite_is_ok(state->ctx)) return;
383
384         state->g.in.user_handle = state->user_handle;
385         state->g.out.rids = &state->rid_array;
386
387         req = dcerpc_samr_GetGroupsForUser_send(state->samr_pipe, state,
388                                                 &state->g);
389         composite_continue_rpc(state->ctx, req, samr_usergroups_recv_groups,
390                                state);
391 }
392
393 static void samr_usergroups_recv_groups(struct rpc_request *req)
394 {
395         struct samr_getuserdomgroups_state *state =
396                 talloc_get_type(req->async.private_data,
397                                 struct samr_getuserdomgroups_state);
398
399         state->ctx->status = dcerpc_ndr_request_recv(req);
400         if (!composite_is_ok(state->ctx)) return;
401         state->ctx->status = state->g.out.result;
402         if (!composite_is_ok(state->ctx)) return;
403
404         state->c.in.handle = state->user_handle;
405         state->c.out.handle = state->user_handle;
406
407         req = dcerpc_samr_Close_send(state->samr_pipe, state, &state->c);
408         composite_continue_rpc(state->ctx, req, samr_usergroups_recv_close,
409                                state);
410 }
411
412 static void samr_usergroups_recv_close(struct rpc_request *req)
413 {
414         struct samr_getuserdomgroups_state *state =
415                 talloc_get_type(req->async.private_data,
416                                 struct samr_getuserdomgroups_state);
417
418         state->ctx->status = dcerpc_ndr_request_recv(req);
419         if (!composite_is_ok(state->ctx)) return;
420         state->ctx->status = state->c.out.result;
421         if (!composite_is_ok(state->ctx)) return;
422
423         composite_done(state->ctx);
424 }
425
426 NTSTATUS wb_samr_userdomgroups_recv(struct composite_context *ctx,
427                                     TALLOC_CTX *mem_ctx,
428                                     int *num_rids, uint32_t **rids)
429 {
430         struct samr_getuserdomgroups_state *state =
431                 talloc_get_type(ctx->private_data,
432                                 struct samr_getuserdomgroups_state);
433
434         int i;
435         NTSTATUS status = composite_wait(ctx);
436         if (!NT_STATUS_IS_OK(status)) goto done;
437
438         *num_rids = state->rid_array->count;
439         *rids = talloc_array(mem_ctx, uint32_t, *num_rids);
440         if (*rids == NULL) {
441                 status = NT_STATUS_NO_MEMORY;
442                 goto done;
443         }
444
445         for (i=0; i<*num_rids; i++) {
446                 (*rids)[i] = state->rid_array->rids[i].rid;
447         }
448
449  done:
450         talloc_free(ctx);
451         return status;
452 }