r17856: The two new functions - libnet_LookupName and libnet_UserInfo.
[bbaumbach/samba-autobuild/.git] / source4 / libnet / libnet_domain.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Copyright (C) Rafal Szczesniak 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 /*
22   a composite function for domain handling on samr pipe
23 */
24
25 #include "includes.h"
26 #include "libcli/composite/composite.h"
27 #include "libnet/libnet.h"
28 #include "librpc/gen_ndr/ndr_samr_c.h"
29 #include "librpc/gen_ndr/ndr_lsa_c.h"
30
31 static void domain_open_handler(struct rpc_request*);
32
33 enum domain_open_stage { DOMOPEN_CONNECT, DOMOPEN_LOOKUP, DOMOPEN_OPEN,
34                          DOMOPEN_CLOSE_EXISTING, DOMOPEN_RPC_CONNECT };
35
36 struct domain_open_samr_state {
37         enum domain_open_stage    stage;
38         struct libnet_context     *ctx;
39         struct dcerpc_pipe        *pipe;
40         struct rpc_request        *req;
41         struct composite_context  *rpcconn_req;
42         struct samr_Connect       connect;
43         struct samr_LookupDomain  lookup;
44         struct samr_OpenDomain    open;
45         struct samr_Close         close;
46         struct libnet_RpcConnect  rpcconn;
47         struct lsa_String         domain_name;
48         uint32_t                  access_mask;
49         struct policy_handle      connect_handle;
50         struct policy_handle      domain_handle;
51 };
52
53
54 /**
55  * Stage 0.5 (optional): Connect to samr rpc pipe
56  */
57 static void domain_open_rpc_connect(struct composite_context *ctx)
58 {
59         struct composite_context *c;
60         struct domain_open_samr_state *s;
61
62         c = talloc_get_type(ctx->async.private_data, struct composite_context);
63         s = talloc_get_type(c->private_data, struct domain_open_samr_state);
64
65         c->status = libnet_RpcConnect_recv(ctx, s->ctx, c, &s->rpcconn);
66         if (!composite_is_ok(c)) return;
67
68         s->pipe = s->rpcconn.out.dcerpc_pipe;
69
70         /* preparing parameters for samr_Connect rpc call */
71         s->connect.in.system_name      = 0;
72         s->connect.in.access_mask      = s->access_mask;
73         s->connect.out.connect_handle  = &s->connect_handle;
74
75         /* send request */
76         s->req = dcerpc_samr_Connect_send(s->pipe, c, &s->connect);
77         if (composite_nomem(s->req, c)) return;
78
79         /* callback handler */
80         s->req->async.callback = domain_open_handler;
81         s->req->async.private  = c;
82         s->stage = DOMOPEN_CONNECT;
83 }
84
85
86 /**
87  * Stage 0.5 (optional): Close existing (in libnet context) domain
88  * handle
89  */
90 static NTSTATUS domain_open_close(struct composite_context *c,
91                                   struct domain_open_samr_state *s)
92 {
93         /* receive samr_Close reply */
94         c->status = dcerpc_ndr_request_recv(s->req);
95         NT_STATUS_NOT_OK_RETURN(c->status);
96
97         /* reset domain handle and associated data in libnet_context */
98         s->ctx->samr.name        = NULL;
99         s->ctx->samr.access_mask = 0;
100         ZERO_STRUCT(s->ctx->samr.handle);
101
102         /* preparing parameters for samr_Connect rpc call */
103         s->connect.in.system_name      = 0;
104         s->connect.in.access_mask      = s->access_mask;
105         s->connect.out.connect_handle  = &s->connect_handle;
106         
107         /* send request */
108         s->req = dcerpc_samr_Connect_send(s->pipe, c, &s->connect);
109         if (s->req == NULL) return NT_STATUS_NO_MEMORY;
110
111         /* callback handler */
112         s->req->async.callback = domain_open_handler;
113         s->req->async.private  = c;
114         s->stage = DOMOPEN_CONNECT;
115         
116         return NT_STATUS_OK;
117 }
118
119
120 /**
121  * Stage 1: Connect to SAM server.
122  */
123 static NTSTATUS domain_open_connect(struct composite_context *c,
124                                     struct domain_open_samr_state *s)
125 {
126         struct samr_LookupDomain *r = &s->lookup;
127
128         /* receive samr_Connect reply */
129         c->status = dcerpc_ndr_request_recv(s->req);
130         NT_STATUS_NOT_OK_RETURN(c->status);
131
132         /* prepare for samr_LookupDomain call */
133         r->in.connect_handle = &s->connect_handle;
134         r->in.domain_name    = &s->domain_name;
135
136         s->req = dcerpc_samr_LookupDomain_send(s->pipe, c, r);
137         if (s->req == NULL) goto failure;
138
139         s->req->async.callback = domain_open_handler;
140         s->req->async.private  = c;
141         s->stage = DOMOPEN_LOOKUP;
142
143         return NT_STATUS_OK;
144
145 failure:
146         return NT_STATUS_UNSUCCESSFUL;
147 }
148
149
150 /**
151  * Stage 2: Lookup domain by name.
152  */
153 static NTSTATUS domain_open_lookup(struct composite_context *c,
154                                    struct domain_open_samr_state *s)
155 {
156         struct samr_OpenDomain *r = &s->open;
157
158         /* receive samr_LookupDomain reply */
159         c->status = dcerpc_ndr_request_recv(s->req);
160         NT_STATUS_NOT_OK_RETURN(c->status);
161
162         /* prepare for samr_OpenDomain call */
163         r->in.connect_handle = &s->connect_handle;
164         r->in.access_mask    = SEC_FLAG_MAXIMUM_ALLOWED;
165         r->in.sid            = s->lookup.out.sid;
166         r->out.domain_handle = &s->domain_handle;
167
168         s->req = dcerpc_samr_OpenDomain_send(s->pipe, c, r);
169         if (s->req == NULL) goto failure;
170
171         s->req->async.callback = domain_open_handler;
172         s->req->async.private  = c;
173         s->stage = DOMOPEN_OPEN;
174
175         return NT_STATUS_OK;
176
177 failure:
178         return NT_STATUS_UNSUCCESSFUL;
179 }
180
181
182 /*
183  * Stage 3: Open domain.
184  */
185 static NTSTATUS domain_open_open(struct composite_context *c,
186                                  struct domain_open_samr_state *s)
187 {
188         /* receive samr_OpenDomain reply */
189         c->status = dcerpc_ndr_request_recv(s->req);
190         NT_STATUS_NOT_OK_RETURN(c->status);
191
192         c->state = COMPOSITE_STATE_DONE;
193         
194         return NT_STATUS_OK;
195 }
196
197
198 /**
199  * Event handler for asynchronous request. Handles transition through
200  * intermediate stages of the call.
201  *
202  * @param req rpc call context
203  */
204 static void domain_open_handler(struct rpc_request *req)
205 {
206         struct composite_context *c = req->async.private;
207         struct domain_open_samr_state *s = talloc_get_type(c->private_data,
208                                                            struct domain_open_samr_state);
209
210         /* Stages of the call */
211         switch (s->stage) {
212         case DOMOPEN_CONNECT:
213                 c->status = domain_open_connect(c, s);
214                 break;
215         case DOMOPEN_LOOKUP:
216                 c->status = domain_open_lookup(c, s);
217                 break;
218         case DOMOPEN_OPEN:
219                 c->status = domain_open_open(c, s);
220                 break;
221         case DOMOPEN_CLOSE_EXISTING:
222                 c->status = domain_open_close(c, s);
223                 break;
224         case DOMOPEN_RPC_CONNECT:
225                 /* this state shouldn't be handled here */
226                 c->status = NT_STATUS_UNSUCCESSFUL;
227                 break;
228         }
229
230         if (!NT_STATUS_IS_OK(c->status)) {
231                 c->state = COMPOSITE_STATE_ERROR;
232         }
233
234         if (c->state == COMPOSITE_STATE_DONE) {
235                 composite_done(c);
236         }
237 }
238
239
240 /**
241  * Sends asynchronous DomainOpen request
242  *
243  * @param ctx initialised libnet context
244  * @param io arguments and results of the call
245  * @param monitor pointer to monitor function that is passed monitor message
246  */
247
248 struct composite_context *libnet_DomainOpenSamr_send(struct libnet_context *ctx,
249                                                      struct libnet_DomainOpen *io,
250                                                      void (*monitor)(struct monitor_msg*))
251 {
252         struct composite_context *c;
253         struct domain_open_samr_state *s;
254
255         c = talloc_zero(ctx, struct composite_context);
256         if (c == NULL) return NULL;
257
258         s = talloc_zero(c, struct domain_open_samr_state);
259         if (composite_nomem(s, c)) return c;
260
261         c->state        = COMPOSITE_STATE_IN_PROGRESS;
262         c->private_data = s;
263         c->event_ctx    = ctx->event_ctx;
264
265         s->ctx                 = ctx;
266         s->pipe                = ctx->samr.pipe;
267         s->access_mask         = io->in.access_mask;
268         s->domain_name.string  = io->in.domain_name;
269
270         if (ctx->samr.pipe == NULL) {
271                 s->rpcconn.level           = LIBNET_RPC_CONNECT_DC;
272                 s->rpcconn.in.name         = io->in.domain_name;
273                 s->rpcconn.in.dcerpc_iface = &dcerpc_table_samr;
274
275                 s->rpcconn_req = libnet_RpcConnect_send(ctx, c, &s->rpcconn);
276                 if (composite_nomem(s->rpcconn_req, c)) return c;
277
278                 s->rpcconn_req->async.fn = domain_open_rpc_connect;
279                 s->rpcconn_req->async.private_data  = c;
280                 s->stage = DOMOPEN_RPC_CONNECT;
281
282                 return c;
283         }
284
285         /* libnet context's domain handle is not empty, so check out what
286            was opened first, before doing anything */
287         if (!policy_handle_empty(&ctx->samr.handle)) {
288                 if (strequal(ctx->samr.name, io->in.domain_name) &&
289                     ctx->samr.access_mask == io->in.access_mask) {
290
291                         /* this domain is already opened */
292                         composite_done(c);
293                         return c;
294
295                 } else {
296                         /* another domain or access rights have been
297                            requested - close the existing handle first */
298                         s->close.in.handle = &ctx->samr.handle;
299
300                         /* send request to close domain handle */
301                         s->req = dcerpc_samr_Close_send(s->pipe, c, &s->close);
302                         if (composite_nomem(s->req, c)) return c;
303
304                         /* callback handler */
305                         s->req->async.callback = domain_open_handler;
306                         s->req->async.private  = c;
307                         s->stage = DOMOPEN_CLOSE_EXISTING;
308
309                         return c;
310                 }
311         }
312
313         /* preparing parameters for samr_Connect rpc call */
314         s->connect.in.system_name      = 0;
315         s->connect.in.access_mask      = s->access_mask;
316         s->connect.out.connect_handle  = &s->connect_handle;
317         
318         /* send request */
319         s->req = dcerpc_samr_Connect_send(s->pipe, c, &s->connect);
320         if (composite_nomem(s->req, c)) return c;
321
322         /* callback handler */
323         s->req->async.callback = domain_open_handler;
324         s->req->async.private  = c;
325         s->stage = DOMOPEN_CONNECT;
326
327         return c;
328 }
329
330
331 /**
332  * Waits for and receives result of asynchronous DomainOpen call
333  * 
334  * @param c composite context returned by asynchronous DomainOpen call
335  * @param ctx initialised libnet context
336  * @param mem_ctx memory context of the call
337  * @param io pointer to results (and arguments) of the call
338  * @return nt status code of execution
339  */
340
341 NTSTATUS libnet_DomainOpenSamr_recv(struct composite_context *c, struct libnet_context *ctx,
342                                     TALLOC_CTX *mem_ctx, struct libnet_DomainOpen *io)
343 {
344         NTSTATUS status;
345         struct domain_open_samr_state *s;
346
347         /* wait for results of sending request */
348         status = composite_wait(c);
349         
350         if (NT_STATUS_IS_OK(status) && io) {
351                 s = talloc_get_type(c->private_data, struct domain_open_samr_state);
352                 io->out.domain_handle = s->domain_handle;
353
354                 /* store the resulting handle and related data for use by other
355                    libnet functions */
356                 ctx->samr.handle      = s->domain_handle;
357                 ctx->samr.name        = talloc_strdup(ctx, s->domain_name.string);
358                 ctx->samr.access_mask = s->access_mask;
359         }
360
361         talloc_free(c);
362         return status;
363 }
364
365
366 struct domain_open_lsa_state {
367         const char *name;
368         uint32_t access_mask;
369         struct libnet_context *ctx;
370         struct libnet_RpcConnect rpcconn;
371         struct lsa_OpenPolicy2   openpol;
372         struct policy_handle handle;
373         struct dcerpc_pipe *pipe;
374 };
375
376
377 static void continue_rpc_connect_lsa(struct composite_context *ctx);
378 static void continue_lsa_policy_open(struct rpc_request *req);
379
380
381 struct composite_context* libnet_DomainOpenLsa_send(struct libnet_context *ctx,
382                                                     struct libnet_DomainOpen *io,
383                                                     void (*monitor)(struct monitor_msg*))
384 {
385         struct composite_context *c;
386         struct domain_open_lsa_state *s;
387         struct composite_context *rpcconn_req;
388         struct rpc_request *openpol_req;
389         struct lsa_QosInfo *qos;
390
391         c = composite_create(ctx, ctx->event_ctx);
392         if (c == NULL) return c;
393
394         s = talloc_zero(c, struct domain_open_lsa_state);
395         if (composite_nomem(s, c)) return c;
396
397         c->private_data = s;
398
399         s->name = talloc_strdup(c, io->in.domain_name);
400         s->access_mask = io->in.access_mask;
401         s->ctx = ctx;
402
403         if (ctx->lsa.pipe == NULL) {
404                 s->rpcconn.level           = LIBNET_RPC_CONNECT_DC;
405                 s->rpcconn.in.name         = talloc_strdup(c, io->in.domain_name);
406                 s->rpcconn.in.dcerpc_iface = &dcerpc_table_lsarpc;
407                 
408                 rpcconn_req = libnet_RpcConnect_send(ctx, c, &s->rpcconn);
409                 if (composite_nomem(rpcconn_req, c)) return c;
410
411                 composite_continue(c, rpcconn_req, continue_rpc_connect_lsa, c);
412                 return c;
413         }
414
415         s->pipe = ctx->lsa.pipe;
416
417         s->openpol.in.system_name = s->name;
418         s->openpol.in.access_mask = s->access_mask;
419         s->openpol.in.attr        = talloc_zero(c, struct lsa_ObjectAttribute);
420
421         qos = talloc_zero(c, struct lsa_QosInfo);
422         qos->len                 = 0;
423         qos->impersonation_level = 2;
424         qos->context_mode        = 1;
425         qos->effective_only      = 0;
426
427         s->openpol.in.attr->sec_qos = qos;
428         s->openpol.out.handle       = &s->handle;
429
430         openpol_req = dcerpc_lsa_OpenPolicy2_send(s->pipe, c, &s->openpol);
431         if (composite_nomem(openpol_req, c)) return c;
432
433         composite_continue_rpc(c, openpol_req, continue_lsa_policy_open, c);
434         return c;
435 }
436
437
438 static void continue_rpc_connect_lsa(struct composite_context *ctx)
439 {
440         struct composite_context *c;
441         struct domain_open_lsa_state *s;
442         struct lsa_QosInfo *qos;
443         struct rpc_request *openpol_req;
444
445         c = talloc_get_type(ctx->async.private_data, struct composite_context);
446         s = talloc_get_type(c->private_data, struct domain_open_lsa_state);
447
448         c->status = libnet_RpcConnect_recv(ctx, s->ctx, c, &s->rpcconn);
449         if (!composite_is_ok(c)) return;
450
451         s->pipe = s->ctx->lsa.pipe;
452         
453         s->openpol.in.system_name = s->name;
454         s->openpol.in.access_mask = s->access_mask;
455         s->openpol.in.attr        = talloc_zero(c, struct lsa_ObjectAttribute);
456
457         qos = talloc_zero(c, struct lsa_QosInfo);
458         qos->len                 = 0;
459         qos->impersonation_level = 2;
460         qos->context_mode        = 1;
461         qos->effective_only      = 0;
462
463         s->openpol.in.attr->sec_qos = qos;
464         s->openpol.out.handle       = &s->handle;
465         
466         openpol_req = dcerpc_lsa_OpenPolicy2_send(s->pipe, c, &s->openpol);
467         if (composite_nomem(openpol_req, c)) return;
468
469         composite_continue_rpc(c, openpol_req, continue_lsa_policy_open, c);
470 }
471
472
473 static void continue_lsa_policy_open(struct rpc_request *req)
474 {
475         struct composite_context *c;
476         struct domain_open_lsa_state *s;
477
478         c = talloc_get_type(req->async.private, struct composite_context);
479         s = talloc_get_type(c->private_data, struct domain_open_lsa_state);
480
481         c->status = dcerpc_ndr_request_recv(req);
482         if (!composite_is_ok(c)) return;
483
484         composite_done(c);
485 }
486
487
488 NTSTATUS libnet_DomainOpenLsa_recv(struct composite_context *c, struct libnet_context *ctx,
489                                    TALLOC_CTX *mem_ctx, struct libnet_DomainOpen *io)
490 {
491         NTSTATUS status;
492         struct domain_open_lsa_state *s;
493
494         status = composite_wait(c);
495
496         if (NT_STATUS_IS_OK(status) && io) {
497                 s = talloc_get_type(c->private_data, struct domain_open_lsa_state);
498                 io->out.domain_handle = s->handle;
499
500                 ctx->lsa.handle      = s->handle;
501                 ctx->lsa.name        = talloc_strdup(ctx, s->name);
502                 ctx->lsa.access_mask = s->access_mask;
503
504         } else if (!NT_STATUS_IS_OK(status)) {
505                 io->out.error_string = talloc_asprintf(mem_ctx,
506                                                        "Failed to open domain: %s",
507                                                        nt_errstr(status));
508         }
509
510         talloc_free(c);
511         return status;
512 }
513
514
515 struct composite_context* libnet_DomainOpen_send(struct libnet_context *ctx,
516                                                  struct libnet_DomainOpen *io,
517                                                  void (*monitor)(struct monitor_msg*))
518 {
519         struct composite_context *c;
520
521         switch (io->in.type) {
522         case DOMAIN_LSA:
523                 c = libnet_DomainOpenLsa_send(ctx, io, monitor);
524                 break;
525
526         case DOMAIN_SAMR:
527         default:
528                 c = libnet_DomainOpenSamr_send(ctx, io, monitor);
529                 break;
530         }
531
532         return c;
533 }
534
535
536 NTSTATUS libnet_DomainOpen_recv(struct composite_context *c, struct libnet_context *ctx,
537                                 TALLOC_CTX *mem_ctx, struct libnet_DomainOpen *io)
538 {
539         NTSTATUS status;
540
541         switch (io->in.type) {
542         case DOMAIN_LSA:
543                 status = libnet_DomainOpenLsa_recv(c, ctx, mem_ctx, io);
544                 break;
545
546         case DOMAIN_SAMR:
547         default:
548                 status = libnet_DomainOpenSamr_recv(c, ctx, mem_ctx, io);
549                 break;
550         }
551         
552         return status;
553 }
554
555
556 /**
557  * Synchronous version of DomainOpen call
558  *
559  * @param ctx initialised libnet context
560  * @param mem_ctx memory context for the call
561  * @param io arguments and results of the call
562  * @return nt status code of execution
563  */
564
565 NTSTATUS libnet_DomainOpen(struct libnet_context *ctx,
566                            TALLOC_CTX *mem_ctx,
567                            struct libnet_DomainOpen *io)
568 {
569         struct composite_context *c = libnet_DomainOpen_send(ctx, io, NULL);
570         return libnet_DomainOpen_recv(c, ctx, mem_ctx, io);
571 }
572
573
574 struct domain_close_lsa_state {
575         struct dcerpc_pipe *pipe;
576         struct lsa_Close close;
577         struct policy_handle handle;
578
579         void (*monitor_fn)(struct monitor_msg*);
580 };
581
582
583 static void continue_lsa_close(struct rpc_request *req);
584
585
586 struct composite_context* libnet_DomainCloseLsa_send(struct libnet_context *ctx,
587                                                      struct libnet_DomainClose *io,
588                                                      void (*monitor)(struct monitor_msg*))
589 {
590         struct composite_context *c;
591         struct domain_close_lsa_state *s;
592         struct rpc_request *close_req;
593
594         c = composite_create(ctx, ctx->event_ctx);
595         if (c == NULL) return c;
596
597         s = talloc_zero(c, struct domain_close_lsa_state);
598         if (composite_nomem(s, c)) return c;
599
600         c->private_data = s;
601         s->monitor_fn   = monitor;
602
603         /* TODO: check if lsa pipe pointer is non-null */
604
605         if (!strequal(ctx->lsa.name, io->in.domain_name)) {
606                 composite_error(c, NT_STATUS_INVALID_PARAMETER);
607                 return c;
608         }
609
610         s->pipe = ctx->lsa.pipe;
611
612         s->close.in.handle  = &ctx->lsa.handle;
613         s->close.out.handle = &s->handle;
614
615         close_req = dcerpc_lsa_Close_send(s->pipe, c, &s->close);
616         if (composite_nomem(close_req, c)) return c;
617
618         composite_continue_rpc(c, close_req, continue_lsa_close, c);
619         return c;
620 }
621
622
623 static void continue_lsa_close(struct rpc_request *req)
624 {
625         struct composite_context *c;
626         struct domain_close_lsa_state *s;
627         
628         c = talloc_get_type(req->async.private, struct composite_context);
629         s = talloc_get_type(c->private_data, struct domain_close_lsa_state);
630
631         c->status = dcerpc_ndr_request_recv(req);
632         if (!composite_is_ok(c)) return;
633
634         composite_done(c);
635 }
636
637
638 NTSTATUS libnet_DomainCloseLsa_recv(struct composite_context *c, struct libnet_context *ctx,
639                                     TALLOC_CTX *mem_ctx, struct libnet_DomainClose *io)
640 {
641         NTSTATUS status;
642
643         status = composite_wait(c);
644
645         if (NT_STATUS_IS_OK(status) && io) {
646                 ctx->lsa.name = NULL;
647                 ZERO_STRUCT(ctx->lsa.handle);
648
649                 io->out.error_string = talloc_asprintf(mem_ctx, "Success");
650
651         } else if (!NT_STATUS_IS_OK(status)) {
652                 io->out.error_string = talloc_asprintf(mem_ctx, "Error: %s", nt_errstr(status));
653         }
654
655         talloc_free(c);
656         return status;
657 }
658
659
660 struct domain_close_samr_state {
661         struct samr_Close close;
662         
663         void (*monitor_fn)(struct monitor_msg*);
664 };
665
666
667 static void continue_samr_close(struct rpc_request *req);
668
669
670 struct composite_context* libnet_DomainCloseSamr_send(struct libnet_context *ctx,
671                                                       struct libnet_DomainClose *io,
672                                                       void (*monitor)(struct monitor_msg*))
673 {
674         struct composite_context *c;
675         struct domain_close_samr_state *s;
676         struct rpc_request *close_req;
677
678         c = composite_create(ctx, ctx->event_ctx);
679         if (c == NULL) return c;
680
681         s = talloc_zero(c, struct domain_close_samr_state);
682         if (composite_nomem(s, c)) return c;
683
684         c->private_data = s;
685         s->monitor_fn   = monitor;
686
687         /* TODO: check if samr pipe pointer is non-null */
688
689         if (!strequal(ctx->samr.name, io->in.domain_name)) {
690                 composite_error(c, NT_STATUS_INVALID_PARAMETER);
691                 return c;
692         }
693
694         s->close.in.handle = &ctx->samr.handle;
695
696         close_req = dcerpc_samr_Close_send(ctx->samr.pipe, ctx, &s->close);
697         if (composite_nomem(close_req, c)) return c;
698
699         composite_continue_rpc(c, close_req, continue_samr_close, c);
700         return c;
701 }
702
703
704 static void continue_samr_close(struct rpc_request *req)
705 {
706         struct composite_context *c;
707         struct domain_close_samr_state *s;
708
709         c = talloc_get_type(req->async.private, struct composite_context);
710         s = talloc_get_type(c->private_data, struct domain_close_samr_state);
711         
712         c->status = dcerpc_ndr_request_recv(req);
713         if (!composite_is_ok(c)) return;
714         
715         composite_done(c);
716 }
717
718
719 NTSTATUS libnet_DomainCloseSamr_recv(struct composite_context *c, struct libnet_context *ctx,
720                                      TALLOC_CTX *mem_ctx, struct libnet_DomainClose *io)
721 {
722         NTSTATUS status;
723
724         status = composite_wait(c);
725
726         if (NT_STATUS_IS_OK(status) && io) {
727                 ZERO_STRUCT(ctx->samr.handle);
728                 ctx->samr.name = NULL;
729                 io->out.error_string = talloc_asprintf(mem_ctx, "Success");
730
731         } else if (!NT_STATUS_IS_OK(status)) {
732                 io->out.error_string = talloc_asprintf(mem_ctx, "Error: %s", nt_errstr(status));
733         }
734
735         talloc_free(c);
736         return status;
737 }
738
739
740 struct composite_context* libnet_DomainClose_send(struct libnet_context *ctx,
741                                                   struct libnet_DomainClose *io,
742                                                   void (*monitor)(struct monitor_msg*))
743 {
744         struct composite_context *c;
745
746         switch (io->in.type) {
747         case DOMAIN_LSA:
748                 c = libnet_DomainCloseLsa_send(ctx, io, monitor);
749                 break;
750
751         case DOMAIN_SAMR:
752         default:
753                 c = libnet_DomainCloseSamr_send(ctx, io, monitor);
754                 break;
755         }
756         
757         return c;
758 }
759
760
761 NTSTATUS libnet_DomainClose_recv(struct composite_context *c, struct libnet_context *ctx,
762                                  TALLOC_CTX *mem_ctx, struct libnet_DomainClose *io)
763 {
764         NTSTATUS status;
765
766         switch (io->in.type) {
767         case DOMAIN_LSA:
768                 status = libnet_DomainCloseLsa_recv(c, ctx, mem_ctx, io);
769                 break;
770
771         case DOMAIN_SAMR:
772         default:
773                 status = libnet_DomainCloseSamr_recv(c, ctx, mem_ctx, io);
774                 break;
775         }
776         
777         return status;
778 }
779
780
781 NTSTATUS libnet_DomainClose(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
782                             struct libnet_DomainClose *io)
783 {
784         struct composite_context *c;
785         
786         c = libnet_DomainClose_send(ctx, io, NULL);
787         return libnet_DomainClose_recv(c, ctx, mem_ctx, io);
788 }