r10691: This gets half-way to wbinfo -n. It acquires an lsa pipe, and does a
[amitay/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 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
245         state->p = dcerpc_pipe_init(state, ev);
246         if (state->p == NULL) goto failed;
247
248         ctx = dcerpc_pipe_open_smb_send(state->p->conn, state->io->in.tree,
249                                         "\\netlogon");
250         if (ctx == NULL) goto failed;
251
252         ctx->async.fn = get_schannel_creds_recv_pipe;
253         ctx->async.private_data = state;
254         state->ctx = result;
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
479         state->finddcs = talloc(state, struct wb_finddcs);
480         if (state->finddcs == NULL) goto failed;
481
482         state->finddcs->in.msg_ctx = io->in.msg_ctx;
483         state->finddcs->in.domain = lp_workgroup();
484
485         ctx = wb_finddcs_send(state->finddcs, io->in.event_ctx);
486         if (ctx == NULL) goto failed;
487
488         ctx->async.fn = get_lsa_pipe_recv_dcs;
489         ctx->async.private_data = state;
490         state->ctx = result;
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         state->io->out.domain_sid =
733                 talloc_steal(mem_ctx, state->queryinfo.out.info->domain.sid);
734         state->io->out.pipe =
735                 talloc_steal(mem_ctx, state->lsa_pipe);
736         talloc_free(c);
737         return status;
738 }
739
740 NTSTATUS wb_get_lsa_pipe(struct wb_get_lsa_pipe *io,
741                          TALLOC_CTX *mem_ctx)
742 {
743         struct composite_context *c = wb_get_lsa_pipe_send(io);
744         return wb_get_lsa_pipe_recv(c, mem_ctx);
745 }