r10825: Complete wbinfo -n
[ira/wip.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 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20 /*
21   a composite API for finding a DC and its name
22 */
23
24 #include "includes.h"
25 #include "libcli/composite/composite.h"
26 #include "libcli/smb_composite/smb_composite.h"
27 #include "winbind/wb_async_helpers.h"
28
29 #include "librpc/gen_ndr/nbt.h"
30 #include "librpc/gen_ndr/samr.h"
31 #include "lib/messaging/irpc.h"
32 #include "librpc/gen_ndr/irpc.h"
33 #include "librpc/gen_ndr/ndr_irpc.h"
34 #include "libcli/raw/libcliraw.h"
35 #include "librpc/gen_ndr/ndr_netlogon.h"
36 #include "librpc/gen_ndr/ndr_lsa.h"
37 #include "libcli/auth/credentials.h"
38
39 struct finddcs_state {
40         struct wb_finddcs *io;
41         struct composite_context *creq;
42
43         struct nbtd_getdcname *r;
44         struct irpc_request *ireq;
45 };
46
47 static void finddcs_getdc(struct irpc_request *ireq)
48 {
49         struct composite_context *c = talloc_get_type(ireq->async.private,
50                                                       struct composite_context);
51         struct finddcs_state *state = talloc_get_type(c->private_data,
52                                                       struct finddcs_state);
53
54         c->status = irpc_call_recv(ireq);
55         if (!NT_STATUS_IS_OK(c->status)) {
56                 goto done;
57         }
58
59         state->io->out.dcs[0].name = talloc_steal(state->io->out.dcs,
60                                                   state->r->out.dcname);
61
62         c->status = NT_STATUS_OK;
63         c->state = COMPOSITE_STATE_DONE;
64
65  done:
66         if (!NT_STATUS_IS_OK(c->status)) {
67                 c->state = COMPOSITE_STATE_ERROR;
68         }
69                 
70         if (c->state >= COMPOSITE_STATE_DONE &&
71             c->async.fn) {
72                 c->async.fn(c);
73         }
74         talloc_free(ireq);
75 }
76
77 /*
78   called when name resolution is finished
79 */
80 static void finddcs_resolve(struct composite_context *res_ctx)
81 {
82         struct composite_context *c = talloc_get_type(res_ctx->async.private_data,
83                                                       struct composite_context);
84         struct finddcs_state *state = talloc_get_type(c->private_data,
85                                                       struct finddcs_state);
86         uint32_t *nbt_servers;
87
88         state->io->out.num_dcs = 1;
89         state->io->out.dcs = talloc_array(state, struct nbt_dc_name,
90                                           state->io->out.num_dcs);
91         if (state->io->out.dcs == NULL) {
92                 c->status = NT_STATUS_NO_MEMORY;
93                 goto done;
94         }
95
96         c->status = resolve_name_recv(res_ctx, state->io->out.dcs,
97                                       &state->io->out.dcs[0].address);
98         if (!NT_STATUS_IS_OK(c->status)) {
99                 goto done;
100         }
101
102         nbt_servers = irpc_servers_byname(state->io->in.msg_ctx, "nbt_server");
103         if ((nbt_servers == NULL) || (nbt_servers[0] == 0)) {
104                 c->status = NT_STATUS_NO_LOGON_SERVERS;
105                 goto done;
106         }
107
108         state->r = talloc(state, struct nbtd_getdcname);
109         if (state->r == NULL) {
110                 c->status = NT_STATUS_NO_MEMORY;
111                 goto done;
112         }
113
114         state->r->in.domainname = talloc_strdup(state->r, lp_workgroup());
115         state->r->in.ip_address = state->io->out.dcs[0].address;
116         state->r->in.my_computername = lp_netbios_name();
117         state->r->in.my_accountname = talloc_asprintf(state->r, "%s$",
118                                                       lp_netbios_name());
119         state->r->in.account_control = ACB_WSTRUST;
120         state->r->in.domain_sid = secrets_get_domain_sid(state->r,
121                                                          lp_workgroup());
122
123         if ((state->r->in.domainname == NULL) ||
124             (state->r->in.my_accountname == NULL)) {
125                 DEBUG(0, ("talloc failed\n"));
126                 c->status = NT_STATUS_NO_MEMORY;
127                 goto done;
128         }
129         if (state->r->in.domain_sid == NULL) {
130                 c->status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
131                 goto done;
132         }
133
134         state->ireq = irpc_call_send(state->io->in.msg_ctx, nbt_servers[0],
135                                      &dcerpc_table_irpc, DCERPC_NBTD_GETDCNAME,
136                                      state->r, state);
137         
138         if (state->ireq == NULL) {
139                 c->status = NT_STATUS_NO_MEMORY;
140                 goto done;
141         }
142
143         c->status = NT_STATUS_OK;
144         state->ireq->async.fn = finddcs_getdc;
145         state->ireq->async.private = c;
146
147  done:
148         if (!NT_STATUS_IS_OK(c->status)) {
149                 c->state = COMPOSITE_STATE_ERROR;
150         }
151                 
152         if (c->state >= COMPOSITE_STATE_DONE &&
153             c->async.fn) {
154                 c->async.fn(c);
155         }
156 }
157
158 struct composite_context *wb_finddcs_send(struct wb_finddcs *io,
159                                           struct event_context *event_ctx)
160 {
161         struct composite_context *c;
162         struct finddcs_state *state;
163         struct nbt_name name;
164
165         c = talloc_zero(NULL, struct composite_context);
166         if (c == NULL) goto failed;
167         c->state = COMPOSITE_STATE_IN_PROGRESS;
168         c->event_ctx = event_ctx;
169
170         state = talloc(c, struct finddcs_state);
171         if (state == NULL) goto failed;
172         state->io = io;
173
174         make_nbt_name(&name, io->in.domain, 0x1c);
175         state->creq = resolve_name_send(&name, c->event_ctx,
176                                         lp_name_resolve_order());
177
178         if (state->creq == NULL) goto failed;
179         state->creq->async.private_data = c;
180         state->creq->async.fn = finddcs_resolve;
181         c->private_data = state;
182
183         return c;
184 failed:
185         talloc_free(c);
186         return NULL;
187 }
188
189 NTSTATUS wb_finddcs_recv(struct composite_context *c, TALLOC_CTX *mem_ctx)
190 {
191         NTSTATUS status;
192
193         status = composite_wait(c);
194
195         if (NT_STATUS_IS_OK(status)) {
196                 struct finddcs_state *state = talloc_get_type(c->private_data,
197                                                               struct finddcs_state);
198                 talloc_steal(mem_ctx, state->io->out.dcs);
199         }
200
201         talloc_free(c);
202         return status;
203 }
204
205 NTSTATUS wb_finddcs(struct wb_finddcs *io, TALLOC_CTX *mem_ctx,
206                     struct event_context *ev)
207 {
208         struct composite_context *c = wb_finddcs_send(io, ev);
209         return wb_finddcs_recv(c, mem_ctx);
210 }
211
212 struct get_schannel_creds_state {
213         struct composite_context *ctx;
214         struct dcerpc_pipe *p;
215         struct wb_get_schannel_creds *io;
216         struct netr_ServerReqChallenge *r;
217
218         struct creds_CredentialState *creds_state;
219         struct netr_Credential netr_cred;
220         uint32_t negotiate_flags;
221         struct netr_ServerAuthenticate2 *a;
222 };
223
224 static void get_schannel_creds_recv_auth(struct rpc_request *req);
225 static void get_schannel_creds_recv_chal(struct rpc_request *req);
226 static void get_schannel_creds_recv_pipe(struct composite_context *ctx);
227
228 struct composite_context *wb_get_schannel_creds_send(struct wb_get_schannel_creds *io,
229                                                      struct event_context *ev)
230 {
231         struct composite_context *result, *ctx;
232         struct get_schannel_creds_state *state;
233
234         result = talloc_zero(NULL, struct composite_context);
235         if (result == NULL) goto failed;
236         result->state = COMPOSITE_STATE_IN_PROGRESS;
237         result->event_ctx = ev;
238
239         state = talloc(result, struct get_schannel_creds_state);
240         if (state == NULL) goto failed;
241         result->private_data = state;
242
243         state->io = io;
244         state->ctx = result;
245
246         state->p = dcerpc_pipe_init(state, ev);
247         if (state->p == NULL) goto failed;
248
249         ctx = dcerpc_pipe_open_smb_send(state->p->conn, state->io->in.tree,
250                                         "\\netlogon");
251         if (ctx == NULL) goto failed;
252
253         ctx->async.fn = get_schannel_creds_recv_pipe;
254         ctx->async.private_data = state;
255         return result;
256
257  failed:
258         talloc_free(result);
259         return NULL;
260 }
261
262 static void get_schannel_creds_recv_pipe(struct composite_context *ctx)
263 {
264         struct get_schannel_creds_state *state =
265                 talloc_get_type(ctx->async.private_data,
266                                 struct get_schannel_creds_state);
267         struct rpc_request *req;
268
269         state->ctx->status = dcerpc_pipe_open_smb_recv(ctx);
270         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
271
272         state->ctx->status = dcerpc_bind_auth_none(state->p,
273                                                    DCERPC_NETLOGON_UUID,
274                                                    DCERPC_NETLOGON_VERSION);
275         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
276
277         state->r = talloc(state, struct netr_ServerReqChallenge);
278         if (state->r == NULL) {
279                 state->ctx->status = NT_STATUS_NO_MEMORY;
280                 goto done;
281         }
282
283         state->r->in.computer_name =
284                 cli_credentials_get_workstation(state->io->in.creds);
285         state->r->in.server_name =
286                 talloc_asprintf(state->r, "\\\\%s",
287                                 dcerpc_server_name(state->p));
288         state->r->in.credentials = talloc(state->r, struct netr_Credential);
289         state->r->out.credentials = talloc(state->r, struct netr_Credential);
290
291         if ((state->r->in.server_name == NULL) ||
292             (state->r->in.credentials == NULL) ||
293             (state->r->out.credentials == NULL)) {
294                 state->ctx->status = NT_STATUS_NO_MEMORY;
295                 goto done;
296         }
297         generate_random_buffer(state->r->in.credentials->data,
298                                sizeof(state->r->in.credentials->data));
299
300         req = dcerpc_netr_ServerReqChallenge_send(state->p, state, state->r);
301         if (req == NULL) {
302                 state->ctx->status = NT_STATUS_NO_MEMORY;
303                 goto done;
304         }
305
306         req->async.callback = get_schannel_creds_recv_chal;
307         req->async.private = state;
308         return;
309
310  done:
311         if (!NT_STATUS_IS_OK(state->ctx->status)) {
312                 state->ctx->state = COMPOSITE_STATE_ERROR;
313         }
314         if ((state->ctx->state >= COMPOSITE_STATE_DONE) &&
315             (state->ctx->async.fn != NULL)) {
316                 state->ctx->async.fn(state->ctx);
317         }
318 }
319
320 static void get_schannel_creds_recv_chal(struct rpc_request *req)
321 {
322         struct get_schannel_creds_state *state =
323                 talloc_get_type(req->async.private,
324                                 struct get_schannel_creds_state);
325         const struct samr_Password *mach_pwd;
326
327         state->ctx->status = dcerpc_ndr_request_recv(req);
328         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
329         state->ctx->status = state->r->out.result;
330         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
331
332         state->creds_state = talloc(state, struct creds_CredentialState);
333         mach_pwd = cli_credentials_get_nt_hash(state->io->in.creds, state);
334         if ((state->creds_state == NULL) || (mach_pwd == NULL)) {
335                 state->ctx->status = NT_STATUS_NO_MEMORY;
336                 goto done;
337         }
338
339         state->negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS;
340
341         creds_client_init(state->creds_state, state->r->in.credentials,
342                           state->r->out.credentials, mach_pwd,
343                           &state->netr_cred, state->negotiate_flags);
344
345         state->a = talloc(state, struct netr_ServerAuthenticate2);
346         if (state->a == NULL) {
347                 state->ctx->status = NT_STATUS_NO_MEMORY;
348                 goto done;
349         }
350
351         state->a->in.server_name =
352                 talloc_reference(state->a, state->r->in.server_name);
353         state->a->in.account_name =
354                 cli_credentials_get_username(state->io->in.creds);
355         state->a->in.secure_channel_type =
356                 cli_credentials_get_secure_channel_type(state->io->in.creds);
357         state->a->in.computer_name =
358                 cli_credentials_get_workstation(state->io->in.creds);
359         state->a->in.negotiate_flags = &state->negotiate_flags;
360         state->a->out.negotiate_flags = &state->negotiate_flags;
361         state->a->in.credentials = &state->netr_cred;
362         state->a->out.credentials = &state->netr_cred;
363
364         req = dcerpc_netr_ServerAuthenticate2_send(state->p, state, state->a);
365         if (req == NULL) {
366                 state->ctx->status = NT_STATUS_NO_MEMORY;
367                 goto done;
368         }
369
370         req->async.callback = get_schannel_creds_recv_auth;
371         req->async.private = state;
372         return;
373
374         state->io->out.netlogon = state->p;
375         state->ctx->state = COMPOSITE_STATE_DONE;
376
377  done:
378         if (!NT_STATUS_IS_OK(state->ctx->status)) {
379                 state->ctx->state = COMPOSITE_STATE_ERROR;
380         }
381         if ((state->ctx->state >= COMPOSITE_STATE_DONE) &&
382             (state->ctx->async.fn != NULL)) {
383                 state->ctx->async.fn(state->ctx);
384         }
385 }
386
387 static void get_schannel_creds_recv_auth(struct rpc_request *req)
388 {
389         struct get_schannel_creds_state *state =
390                 talloc_get_type(req->async.private,
391                                 struct get_schannel_creds_state);
392
393         state->ctx->status = dcerpc_ndr_request_recv(req);
394         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
395         state->ctx->status = state->a->out.result;
396         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
397
398         if (!creds_client_check(state->creds_state,
399                                 state->a->out.credentials)) {
400                 DEBUG(5, ("Server got us invalid creds\n"));
401                 state->ctx->status = NT_STATUS_UNSUCCESSFUL;
402                 goto done;
403         }
404
405         cli_credentials_set_netlogon_creds(state->io->in.creds,
406                                            state->creds_state);
407
408         state->ctx->state = COMPOSITE_STATE_DONE;
409
410  done:
411         if (!NT_STATUS_IS_OK(state->ctx->status)) {
412                 state->ctx->state = COMPOSITE_STATE_ERROR;
413         }
414         if ((state->ctx->state >= COMPOSITE_STATE_DONE) &&
415             (state->ctx->async.fn != NULL)) {
416                 state->ctx->async.fn(state->ctx);
417         }
418 }
419
420 NTSTATUS wb_get_schannel_creds_recv(struct composite_context *c,
421                                     TALLOC_CTX *mem_ctx)
422 {
423         NTSTATUS status = composite_wait(c);
424         struct get_schannel_creds_state *state =
425                 talloc_get_type(c->private_data,
426                                 struct get_schannel_creds_state);
427         state->io->out.netlogon = talloc_steal(mem_ctx, state->p);
428         talloc_free(c);
429         return status;
430 }
431
432 NTSTATUS wb_get_schannel_creds(struct wb_get_schannel_creds *io,
433                                TALLOC_CTX *mem_ctx,
434                                struct event_context *ev)
435 {
436         struct composite_context *c = wb_get_schannel_creds_send(io, ev);
437         return wb_get_schannel_creds_recv(c, mem_ctx);
438 }
439
440 struct get_lsa_pipe_state {
441         struct composite_context *ctx;
442         struct wb_get_lsa_pipe *io;
443         struct wb_finddcs *finddcs;
444         struct smb_composite_connect *conn;
445         struct dcerpc_pipe *lsa_pipe;
446
447         struct lsa_ObjectAttribute objectattr;
448         struct lsa_OpenPolicy2 openpolicy;
449         struct policy_handle policy_handle;
450
451         struct lsa_QueryInfoPolicy queryinfo;
452
453         struct lsa_Close close;
454 };
455
456 static void get_lsa_pipe_recv_dcs(struct composite_context *ctx);
457 static void get_lsa_pipe_recv_tree(struct composite_context *ctx);
458 static void get_lsa_pipe_recv_pipe(struct composite_context *ctx);
459 static void get_lsa_pipe_recv_openpol(struct rpc_request *req);
460 static void get_lsa_pipe_recv_queryinfo(struct rpc_request *req);
461 static void get_lsa_pipe_recv_close(struct rpc_request *req);
462
463 struct composite_context *wb_get_lsa_pipe_send(struct wb_get_lsa_pipe *io)
464 {
465         struct composite_context *result, *ctx;
466         struct get_lsa_pipe_state *state;
467
468         result = talloc_zero(NULL, struct composite_context);
469         if (result == NULL) goto failed;
470         result->state = COMPOSITE_STATE_IN_PROGRESS;
471         result->event_ctx = io->in.event_ctx;
472
473         state = talloc(result, struct get_lsa_pipe_state);
474         if (state == NULL) goto failed;
475         result->private_data = state;
476
477         state->io = io;
478         state->ctx = result;
479
480         state->finddcs = talloc(state, struct wb_finddcs);
481         if (state->finddcs == NULL) goto failed;
482
483         state->finddcs->in.msg_ctx = io->in.msg_ctx;
484         state->finddcs->in.domain = lp_workgroup();
485
486         ctx = wb_finddcs_send(state->finddcs, io->in.event_ctx);
487         if (ctx == NULL) goto failed;
488
489         ctx->async.fn = get_lsa_pipe_recv_dcs;
490         ctx->async.private_data = state;
491         return result;
492
493  failed:
494         talloc_free(result);
495         return NULL;
496 }
497
498 static void get_lsa_pipe_recv_dcs(struct composite_context *ctx)
499 {
500         struct get_lsa_pipe_state *state =
501                 talloc_get_type(ctx->async.private_data,
502                                 struct get_lsa_pipe_state);
503
504         state->ctx->status = wb_finddcs_recv(ctx, state);
505         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
506
507         state->conn = talloc(state, struct smb_composite_connect);
508         if (state->conn == NULL) {
509                 state->ctx->status = NT_STATUS_NO_MEMORY;
510                 goto done;
511         }
512
513         state->conn->in.dest_host = state->finddcs->out.dcs[0].address;
514         state->conn->in.port = 0;
515         state->conn->in.called_name = state->finddcs->out.dcs[0].name;
516         state->conn->in.service = "IPC$";
517         state->conn->in.service_type = "IPC";
518         state->conn->in.workgroup = lp_workgroup();
519
520         state->conn->in.credentials = cli_credentials_init(state->conn);
521         if (state->conn->in.credentials == NULL) {
522                 state->ctx->status = NT_STATUS_NO_MEMORY;
523                 goto done;
524         }
525         cli_credentials_set_conf(state->conn->in.credentials);
526         cli_credentials_set_anonymous(state->conn->in.credentials);
527
528         ctx = smb_composite_connect_send(state->conn, state, 
529                                          state->ctx->event_ctx);
530         if (ctx == NULL) {
531                 state->ctx->status = NT_STATUS_NO_MEMORY;
532                 goto done;
533         }
534
535         ctx->async.fn = get_lsa_pipe_recv_tree;
536         ctx->async.private_data = state;
537         return;
538
539  done:
540         if (!NT_STATUS_IS_OK(state->ctx->status)) {
541                 state->ctx->state = COMPOSITE_STATE_ERROR;
542         }
543         if ((state->ctx->state >= COMPOSITE_STATE_DONE) &&
544             (state->ctx->async.fn != NULL)) {
545                 state->ctx->async.fn(state->ctx);
546         }
547 }
548
549 static void get_lsa_pipe_recv_tree(struct composite_context *ctx)
550 {
551         struct get_lsa_pipe_state *state =
552                 talloc_get_type(ctx->async.private_data,
553                                 struct get_lsa_pipe_state);
554
555         state->ctx->status = smb_composite_connect_recv(ctx, state);
556         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
557
558         state->lsa_pipe = dcerpc_pipe_init(state, state->ctx->event_ctx);
559         if (state->lsa_pipe == NULL) {
560                 state->ctx->status = NT_STATUS_NO_MEMORY;
561                 goto done;
562         }
563
564         ctx = dcerpc_pipe_open_smb_send(state->lsa_pipe->conn,
565                                         state->conn->out.tree, "\\lsarpc");
566         if (ctx == NULL) {
567                 state->ctx->status = NT_STATUS_NO_MEMORY;
568                 goto done;
569         }
570
571         ctx->async.fn = get_lsa_pipe_recv_pipe;
572         ctx->async.private_data = state;
573         return;
574
575  done:
576         if (!NT_STATUS_IS_OK(state->ctx->status)) {
577                 state->ctx->state = COMPOSITE_STATE_ERROR;
578         }
579         if ((state->ctx->state >= COMPOSITE_STATE_DONE) &&
580             (state->ctx->async.fn != NULL)) {
581                 state->ctx->async.fn(state->ctx);
582         }
583 }
584
585 static void get_lsa_pipe_recv_pipe(struct composite_context *ctx)
586 {
587         struct get_lsa_pipe_state *state =
588                 talloc_get_type(ctx->async.private_data,
589                                 struct get_lsa_pipe_state);
590         struct rpc_request *req;
591
592         state->ctx->status = dcerpc_pipe_open_smb_recv(ctx);
593         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
594
595         talloc_unlink(state, state->conn->out.tree); /* The pipe owns it now */
596         state->conn->out.tree = NULL;
597
598         state->ctx->status = dcerpc_bind_auth_none(state->lsa_pipe,
599                                                    DCERPC_LSARPC_UUID,
600                                                    DCERPC_LSARPC_VERSION);
601         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
602
603         ZERO_STRUCT(state->openpolicy);
604         state->openpolicy.in.system_name =
605                 talloc_asprintf(state, "\\\\%s",
606                                 dcerpc_server_name(state->lsa_pipe));
607         ZERO_STRUCT(state->objectattr);
608         state->openpolicy.in.attr = &state->objectattr;
609         state->openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
610         state->openpolicy.out.handle = &state->policy_handle;
611
612         req = dcerpc_lsa_OpenPolicy2_send(state->lsa_pipe, state,
613                                           &state->openpolicy);
614         if (req == NULL) {
615                 state->ctx->status = NT_STATUS_NO_MEMORY;
616                 goto done;
617         }
618
619         req->async.callback = get_lsa_pipe_recv_openpol;
620         req->async.private = state;
621         return;
622
623  done:
624         if (!NT_STATUS_IS_OK(state->ctx->status)) {
625                 state->ctx->state = COMPOSITE_STATE_ERROR;
626         }
627         if ((state->ctx->state >= COMPOSITE_STATE_DONE) &&
628             (state->ctx->async.fn != NULL)) {
629                 state->ctx->async.fn(state->ctx);
630         }
631 }
632
633 static void get_lsa_pipe_recv_openpol(struct rpc_request *req)
634 {
635         struct get_lsa_pipe_state *state =
636                 talloc_get_type(req->async.private, struct get_lsa_pipe_state);
637
638         state->ctx->status = dcerpc_ndr_request_recv(req);
639         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
640         state->ctx->status = state->openpolicy.out.result;
641         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
642
643         ZERO_STRUCT(state->queryinfo);
644         state->queryinfo.in.handle = &state->policy_handle;
645         state->queryinfo.in.level = LSA_POLICY_INFO_ACCOUNT_DOMAIN;
646
647         req = dcerpc_lsa_QueryInfoPolicy_send(state->lsa_pipe, state,
648                                               &state->queryinfo);
649         if (req == NULL) {
650                 state->ctx->status = NT_STATUS_NO_MEMORY;
651                 goto done;
652         }
653
654         req->async.callback = get_lsa_pipe_recv_queryinfo;
655         req->async.private = state;
656         return;
657
658  done:
659         if (!NT_STATUS_IS_OK(state->ctx->status)) {
660                 state->ctx->state = COMPOSITE_STATE_ERROR;
661         }
662         if ((state->ctx->state >= COMPOSITE_STATE_DONE) &&
663             (state->ctx->async.fn != NULL)) {
664                 state->ctx->async.fn(state->ctx);
665         }
666 }
667
668 static void get_lsa_pipe_recv_queryinfo(struct rpc_request *req)
669 {
670         struct get_lsa_pipe_state *state =
671                 talloc_get_type(req->async.private, struct get_lsa_pipe_state);
672
673         state->ctx->status = dcerpc_ndr_request_recv(req);
674         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
675         state->ctx->status = state->queryinfo.out.result;
676         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
677
678         ZERO_STRUCT(state->close);
679         state->close.in.handle = &state->policy_handle;
680         state->close.out.handle = &state->policy_handle;
681
682         req = dcerpc_lsa_Close_send(state->lsa_pipe, state,
683                                     &state->close);
684         if (req == NULL) {
685                 state->ctx->status = NT_STATUS_NO_MEMORY;
686                 goto done;
687         }
688
689         req->async.callback = get_lsa_pipe_recv_close;
690         req->async.private = state;
691         return;
692
693  done:
694         if (!NT_STATUS_IS_OK(state->ctx->status)) {
695                 state->ctx->state = COMPOSITE_STATE_ERROR;
696         }
697         if ((state->ctx->state >= COMPOSITE_STATE_DONE) &&
698             (state->ctx->async.fn != NULL)) {
699                 state->ctx->async.fn(state->ctx);
700         }
701 }
702
703 static void get_lsa_pipe_recv_close(struct rpc_request *req)
704 {
705         struct get_lsa_pipe_state *state =
706                 talloc_get_type(req->async.private, struct get_lsa_pipe_state);
707
708         state->ctx->status = dcerpc_ndr_request_recv(req);
709         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
710         state->ctx->status = state->close.out.result;
711         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
712
713         state->ctx->state = COMPOSITE_STATE_DONE;
714
715  done:
716         if (!NT_STATUS_IS_OK(state->ctx->status)) {
717                 state->ctx->state = COMPOSITE_STATE_ERROR;
718         }
719         if ((state->ctx->state >= COMPOSITE_STATE_DONE) &&
720             (state->ctx->async.fn != NULL)) {
721                 state->ctx->async.fn(state->ctx);
722         }
723 }
724
725 NTSTATUS wb_get_lsa_pipe_recv(struct composite_context *c,
726                               TALLOC_CTX *mem_ctx)
727 {
728         NTSTATUS status = composite_wait(c);
729         struct get_lsa_pipe_state *state =
730                 talloc_get_type(c->private_data,
731                                 struct get_lsa_pipe_state);
732         if (NT_STATUS_IS_OK(status)) {
733                 state->io->out.domain_sid =
734                         talloc_steal(mem_ctx,
735                                      state->queryinfo.out.info->domain.sid);
736                 state->io->out.pipe =
737                         talloc_steal(mem_ctx,
738                                      state->lsa_pipe);
739         }
740         talloc_free(c);
741         return status;
742 }
743
744 NTSTATUS wb_get_lsa_pipe(struct wb_get_lsa_pipe *io,
745                          TALLOC_CTX *mem_ctx)
746 {
747         struct composite_context *c = wb_get_lsa_pipe_send(io);
748         return wb_get_lsa_pipe_recv(c, mem_ctx);
749 }
750
751 struct lsa_lookupnames_state {
752         struct composite_context *ctx;
753         uint32_t num_names;
754         struct lsa_LookupNames r;
755         struct lsa_TransSidArray sids;
756         uint32_t count;
757         struct wb_sid_object **result;
758 };
759
760 static void lsa_lookupnames_recv_sids(struct rpc_request *req);
761
762 struct composite_context *wb_lsa_lookupnames_send(struct dcerpc_pipe *lsa_pipe,
763                                                   struct policy_handle *handle,
764                                                   int num_names,
765                                                   const char **names)
766 {
767         struct composite_context *result;
768         struct rpc_request *req;
769         struct lsa_lookupnames_state *state;
770
771         struct lsa_String *lsa_names;
772         int i;
773
774         result = talloc_zero(NULL, struct composite_context);
775         if (result == NULL) goto failed;
776         result->state = COMPOSITE_STATE_IN_PROGRESS;
777         result->event_ctx = lsa_pipe->conn->event_ctx;
778
779         state = talloc(result, struct lsa_lookupnames_state);
780         if (state == NULL) goto failed;
781         result->private_data = state;
782
783         state->sids.count = 0;
784         state->sids.sids = NULL;
785         state->num_names = num_names;
786         state->count = 0;
787
788         lsa_names = talloc_array(state, struct lsa_String, num_names);
789         if (lsa_names == NULL) goto failed;
790
791         for (i=0; i<num_names; i++) {
792                 lsa_names[i].string = names[i];
793         }
794
795         state->r.in.handle = handle;
796         state->r.in.num_names = num_names;
797         state->r.in.names = lsa_names;
798         state->r.in.sids = &state->sids;
799         state->r.in.level = 1;
800         state->r.in.count = &state->count;
801         state->r.out.count = &state->count;
802         state->r.out.sids = &state->sids;
803
804         req = dcerpc_lsa_LookupNames_send(lsa_pipe, state, &state->r);
805         if (req == NULL) goto failed;
806
807         req->async.callback = lsa_lookupnames_recv_sids;
808         req->async.private = state;
809         state->ctx = result;
810         return result;
811
812  failed:
813         talloc_free(result);
814         return NULL;
815 }
816
817 static void lsa_lookupnames_recv_sids(struct rpc_request *req)
818 {
819         struct lsa_lookupnames_state *state =
820                 talloc_get_type(req->async.private,
821                                 struct lsa_lookupnames_state);
822         int i;
823
824         state->ctx->status = dcerpc_ndr_request_recv(req);
825         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
826         state->ctx->status = state->r.out.result;
827         if (!NT_STATUS_IS_OK(state->ctx->status) &&
828             !NT_STATUS_EQUAL(state->ctx->status, STATUS_SOME_UNMAPPED)) {
829                 goto done;
830         }
831
832         state->result = talloc_array(state, struct wb_sid_object *,
833                                      state->num_names);
834         if (state->result == NULL) {
835                 state->ctx->status = NT_STATUS_NO_MEMORY;
836                 goto done;
837         }
838
839         for (i=0; i<state->num_names; i++) {
840                 struct lsa_TranslatedSid *sid = &state->r.out.sids->sids[i];
841                 struct lsa_TrustInformation *dom;
842
843                 state->result[i] = talloc_zero(state->result,
844                                                struct wb_sid_object);
845                 if (state->result[i] == NULL) {
846                         state->ctx->status = NT_STATUS_NO_MEMORY;
847                         goto done;
848                 }
849
850                 state->result[i]->type = sid->sid_type;
851                 if (state->result[i]->type == SID_NAME_UNKNOWN) {
852                         continue;
853                 }
854
855                 if (sid->sid_index >= state->r.out.domains->count) {
856                         state->ctx->status = NT_STATUS_INVALID_PARAMETER;
857                         goto done;
858                 }
859
860                 dom = &state->r.out.domains->domains[sid->sid_index];
861
862                 state->result[i]->sid = dom_sid_add_rid(state->result[i],
863                                                         dom->sid, sid->rid);
864         }
865
866         state->ctx->state = COMPOSITE_STATE_DONE;
867
868  done:
869         if (!NT_STATUS_IS_OK(state->ctx->status)) {
870                 state->ctx->state = COMPOSITE_STATE_ERROR;
871         }
872         if ((state->ctx->state >= COMPOSITE_STATE_DONE) &&
873             (state->ctx->async.fn != NULL)) {
874                 state->ctx->async.fn(state->ctx);
875         }
876 }
877
878 NTSTATUS wb_lsa_lookupnames_recv(struct composite_context *c,
879                                  TALLOC_CTX *mem_ctx,
880                                  struct wb_sid_object ***sids)
881 {
882         NTSTATUS status = composite_wait(c);
883         if (NT_STATUS_IS_OK(status)) {
884                 struct lsa_lookupnames_state *state =
885                         talloc_get_type(c->private_data,
886                                         struct lsa_lookupnames_state);
887                 *sids = talloc_steal(mem_ctx, state->result);
888         }
889         talloc_free(c);
890         return status;
891 }
892
893 NTSTATUS wb_lsa_lookupnames(struct dcerpc_pipe *lsa_pipe, 
894                             struct policy_handle *handle,
895                             int num_names, const char **names,
896                             TALLOC_CTX *mem_ctx,
897                             struct wb_sid_object ***sids)
898 {
899         struct composite_context *c =
900                 wb_lsa_lookupnames_send(lsa_pipe, handle, num_names, names);
901         return wb_lsa_lookupnames_recv(c, mem_ctx, sids);
902 }
903
904 struct lsa_lookupname_state {
905         struct composite_context *ctx;
906         struct dcerpc_pipe *lsa_pipe;
907         const char *name;
908         struct wb_sid_object *sid;
909
910         struct lsa_ObjectAttribute objectattr;
911         struct lsa_OpenPolicy2 openpolicy;
912         struct policy_handle policy_handle;
913         struct lsa_Close close;
914 };
915
916 static void lsa_lookupname_recv_open(struct rpc_request *req);
917 static void lsa_lookupname_recv_sids(struct composite_context *ctx);
918
919 struct composite_context *wb_lsa_lookupname_send(struct dcerpc_pipe *lsa_pipe,
920                                                  const char *name)
921 {
922         struct composite_context *result;
923         struct rpc_request *req;
924         struct lsa_lookupname_state *state;
925
926         result = talloc_zero(NULL, struct composite_context);
927         if (result == NULL) goto failed;
928         result->state = COMPOSITE_STATE_IN_PROGRESS;
929         result->event_ctx = lsa_pipe->conn->event_ctx;
930
931         state = talloc(result, struct lsa_lookupname_state);
932         if (state == NULL) goto failed;
933         result->private_data = state;
934
935         state->lsa_pipe = lsa_pipe;
936         state->name = talloc_strdup(state, name);
937         if (state->name == NULL) goto failed;
938         state->ctx = result;
939
940         ZERO_STRUCT(state->openpolicy);
941         state->openpolicy.in.system_name =
942                 talloc_asprintf(state, "\\\\%s",
943                                 dcerpc_server_name(state->lsa_pipe));
944         ZERO_STRUCT(state->objectattr);
945         state->openpolicy.in.attr = &state->objectattr;
946         state->openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
947         state->openpolicy.out.handle = &state->policy_handle;
948
949         req = dcerpc_lsa_OpenPolicy2_send(state->lsa_pipe, state,
950                                           &state->openpolicy);
951         if (req == NULL) goto failed;
952
953         req->async.callback = lsa_lookupname_recv_open;
954         req->async.private = state;
955         return result;
956
957  failed:
958         talloc_free(result);
959         return NULL;
960 }
961
962 static void lsa_lookupname_recv_open(struct rpc_request *req)
963 {
964         struct lsa_lookupname_state *state =
965                 talloc_get_type(req->async.private,
966                                 struct lsa_lookupname_state);
967         struct composite_context *ctx;
968
969         state->ctx->status = dcerpc_ndr_request_recv(req);
970         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
971         state->ctx->status = state->openpolicy.out.result;
972         if (!NT_STATUS_IS_OK(state->ctx->status)) goto done;
973
974         ctx = wb_lsa_lookupnames_send(state->lsa_pipe, &state->policy_handle,
975                                       1, &state->name);
976         if (ctx == NULL) {
977                 state->ctx->status = NT_STATUS_NO_MEMORY;
978                 goto done;
979         }
980
981         ctx->async.fn = lsa_lookupname_recv_sids;
982         ctx->async.private_data = state;
983         return;
984
985  done:
986         if (!NT_STATUS_IS_OK(state->ctx->status)) {
987                 state->ctx->state = COMPOSITE_STATE_ERROR;
988         }
989         if ((state->ctx->state >= COMPOSITE_STATE_DONE) &&
990             (state->ctx->async.fn != NULL)) {
991                 state->ctx->async.fn(state->ctx);
992         }
993 }
994
995 static void lsa_lookupname_recv_sids(struct composite_context *ctx)
996 {
997         struct lsa_lookupname_state *state =
998                 talloc_get_type(ctx->async.private_data,
999                                 struct lsa_lookupname_state);
1000         struct rpc_request *req;
1001         struct wb_sid_object **sids;
1002
1003         state->ctx->status = wb_lsa_lookupnames_recv(ctx, state, &sids);
1004
1005         if (NT_STATUS_IS_OK(state->ctx->status)) {
1006                 state->sid = NULL;
1007                 if (sids != NULL) {
1008                         state->sid = sids[0];
1009                 }
1010         }
1011
1012         ZERO_STRUCT(state->close);
1013         state->close.in.handle = &state->policy_handle;
1014         state->close.out.handle = &state->policy_handle;
1015
1016         req = dcerpc_lsa_Close_send(state->lsa_pipe, state,
1017                                     &state->close);
1018         if (req != NULL) {
1019                 req->async.callback =
1020                         (void(*)(struct rpc_request *))talloc_free;
1021         }
1022
1023         state->ctx->state = COMPOSITE_STATE_DONE;
1024
1025         if (!NT_STATUS_IS_OK(state->ctx->status)) {
1026                 state->ctx->state = COMPOSITE_STATE_ERROR;
1027         }
1028         if ((state->ctx->state >= COMPOSITE_STATE_DONE) &&
1029             (state->ctx->async.fn != NULL)) {
1030                 state->ctx->async.fn(state->ctx);
1031         }
1032 }
1033
1034 NTSTATUS wb_lsa_lookupname_recv(struct composite_context *c,
1035                                 TALLOC_CTX *mem_ctx,
1036                                 struct wb_sid_object **sid)
1037 {
1038         NTSTATUS status = composite_wait(c);
1039         if (NT_STATUS_IS_OK(status)) {
1040                 struct lsa_lookupname_state *state =
1041                         talloc_get_type(c->private_data,
1042                                         struct lsa_lookupname_state);
1043                 *sid = talloc_steal(mem_ctx, state->sid);
1044         }
1045         talloc_free(c);
1046         return status;
1047 }
1048
1049 NTSTATUS wb_lsa_lookupname(struct dcerpc_pipe *lsa_pipe, const char *name,
1050                            TALLOC_CTX *mem_ctx, struct wb_sid_object **sid)
1051 {
1052         struct composite_context *c =
1053                 wb_lsa_lookupname_send(lsa_pipe, name);
1054         return wb_lsa_lookupname_recv(c, mem_ctx, sid);
1055 }
1056