r26327: Explicit loadparm_context for RPC client functions.
[gd/samba-autobuild/.git] / source4 / librpc / rpc / dcerpc_connect.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    dcerpc connect functions
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Jelmer Vernooij 2004
8    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2007
9    Copyright (C) Rafal Szczesniak  2005
10    
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25
26 #include "includes.h"
27 #include "libcli/composite/composite.h"
28 #include "libcli/smb_composite/smb_composite.h"
29 #include "lib/events/events.h"
30 #include "libcli/smb2/smb2.h"
31 #include "libcli/smb2/smb2_calls.h"
32 #include "librpc/rpc/dcerpc.h"
33 #include "auth/credentials/credentials.h"
34 #include "param/param.h"
35
36
37 struct pipe_np_smb_state {
38         struct smb_composite_connect conn;
39         struct smbcli_tree *tree;
40         struct dcerpc_pipe_connect io;
41 };
42
43
44 /*
45   Stage 3 of ncacn_np_smb: Named pipe opened (or not)
46 */
47 static void continue_pipe_open_smb(struct composite_context *ctx)
48 {
49         struct composite_context *c = talloc_get_type(ctx->async.private_data,
50                                                       struct composite_context);
51
52         /* receive result of named pipe open request on smb */
53         c->status = dcerpc_pipe_open_smb_recv(ctx);
54         if (!composite_is_ok(c)) return;
55
56         composite_done(c);
57 }
58
59
60 /*
61   Stage 2 of ncacn_np_smb: Open a named pipe after successful smb connection
62 */
63 static void continue_smb_connect(struct composite_context *ctx)
64 {
65         struct composite_context *open_ctx;
66         struct composite_context *c = talloc_get_type(ctx->async.private_data,
67                                                       struct composite_context);
68         struct pipe_np_smb_state *s = talloc_get_type(c->private_data,
69                                                       struct pipe_np_smb_state);
70         
71         /* receive result of smb connect request */
72         c->status = smb_composite_connect_recv(ctx, c);
73         if (!composite_is_ok(c)) return;
74
75         /* prepare named pipe open parameters */
76         s->tree         = s->conn.out.tree;
77         s->io.pipe_name = s->io.binding->endpoint;
78
79         /* send named pipe open request */
80         open_ctx = dcerpc_pipe_open_smb_send(s->io.pipe, s->tree, s->io.pipe_name);
81         if (composite_nomem(open_ctx, c)) return;
82
83         composite_continue(c, open_ctx, continue_pipe_open_smb, c);
84 }
85
86
87 /*
88   Initiate async open of a rpc connection to a rpc pipe on SMB using
89   the binding structure to determine the endpoint and options
90 */
91 static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb_send(TALLOC_CTX *mem_ctx, 
92                                                                 struct dcerpc_pipe_connect *io)
93 {
94         struct composite_context *c;
95         struct pipe_np_smb_state *s;
96         struct composite_context *conn_req;
97         struct smb_composite_connect *conn;
98
99         /* composite context allocation and setup */
100         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
101         if (c == NULL) return NULL;
102
103         s = talloc_zero(c, struct pipe_np_smb_state);
104         if (composite_nomem(s, c)) return c;
105         c->private_data = s;
106
107         s->io  = *io;
108         conn   = &s->conn;
109
110         /* prepare smb connection parameters: we're connecting to IPC$ share on
111            remote rpc server */
112         conn->in.dest_host              = s->io.binding->host;
113         conn->in.port                   = 0;
114         if (s->io.binding->target_hostname == NULL)
115                 conn->in.called_name = "*SMBSERVER"; /* FIXME: This is invalid */
116         else
117                 conn->in.called_name            = s->io.binding->target_hostname;
118         conn->in.service                = "IPC$";
119         conn->in.service_type           = NULL;
120         conn->in.workgroup              = lp_workgroup(global_loadparm);
121
122         /*
123          * provide proper credentials - user supplied, but allow a
124          * fallback to anonymous if this is an schannel connection
125          * (might be NT4 not allowing machine logins at session
126          * setup).
127          */
128         s->conn.in.credentials = s->io.creds;
129         if (s->io.binding->flags & DCERPC_SCHANNEL) {
130                 conn->in.fallback_to_anonymous  = true;
131         } else {
132                 conn->in.fallback_to_anonymous  = false;
133         }
134
135         /* send smb connect request */
136         conn_req = smb_composite_connect_send(conn, s->io.pipe->conn, s->io.pipe->conn->event_ctx);
137         if (composite_nomem(conn_req, c)) return c;
138
139         composite_continue(c, conn_req, continue_smb_connect, c);
140         return c;
141 }
142
143
144 /*
145   Receive result of a rpc connection to a rpc pipe on SMB
146 */
147 static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb_recv(struct composite_context *c)
148 {
149         NTSTATUS status = composite_wait(c);
150
151         talloc_free(c);
152         return status;
153 }
154
155
156 struct pipe_np_smb2_state {
157         struct smb2_tree *tree;
158         struct dcerpc_pipe_connect io;
159 };
160
161
162 /*
163   Stage 3 of ncacn_np_smb: Named pipe opened (or not)
164 */
165 static void continue_pipe_open_smb2(struct composite_context *ctx)
166 {
167         struct composite_context *c = talloc_get_type(ctx->async.private_data,
168                                                       struct composite_context);
169
170         /* receive result of named pipe open request on smb2 */
171         c->status = dcerpc_pipe_open_smb2_recv(ctx);
172         if (!composite_is_ok(c)) return;
173
174         composite_done(c);
175 }
176
177
178 /*
179   Stage 2 of ncacn_np_smb2: Open a named pipe after successful smb2 connection
180 */
181 static void continue_smb2_connect(struct composite_context *ctx)
182 {
183         struct composite_context *open_req;
184         struct composite_context *c = talloc_get_type(ctx->async.private_data,
185                                                       struct composite_context);
186         struct pipe_np_smb2_state *s = talloc_get_type(c->private_data,
187                                                        struct pipe_np_smb2_state);
188
189         /* receive result of smb2 connect request */
190         c->status = smb2_connect_recv(ctx, c, &s->tree);
191         if (!composite_is_ok(c)) return;
192
193         /* prepare named pipe open parameters */
194         s->io.pipe_name = s->io.binding->endpoint;
195
196         /* send named pipe open request */
197         open_req = dcerpc_pipe_open_smb2_send(s->io.pipe, s->tree, s->io.pipe_name);
198         if (composite_nomem(open_req, c)) return;
199
200         composite_continue(c, open_req, continue_pipe_open_smb2, c);
201 }
202
203
204 /* 
205    Initiate async open of a rpc connection request on SMB2 using
206    the binding structure to determine the endpoint and options
207 */
208 static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send(
209                                         TALLOC_CTX *mem_ctx,
210                                         struct dcerpc_pipe_connect *io)
211 {
212         struct composite_context *c;
213         struct pipe_np_smb2_state *s;
214         struct composite_context *conn_req;
215
216         /* composite context allocation and setup */
217         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
218         if (c == NULL) return NULL;
219
220         s = talloc_zero(c, struct pipe_np_smb2_state);
221         if (composite_nomem(s, c)) return c;
222         c->private_data = s;
223
224         s->io = *io;
225
226         /*
227          * provide proper credentials - user supplied or anonymous in case this is
228          * schannel connection
229          */
230         if (s->io.binding->flags & DCERPC_SCHANNEL) {
231                 s->io.creds = cli_credentials_init(mem_ctx);
232                 if (composite_nomem(s->io.creds, c)) return c;
233
234                 cli_credentials_guess(s->io.creds, global_loadparm);
235         }
236
237         /* send smb2 connect request */
238         conn_req = smb2_connect_send(mem_ctx, s->io.binding->host, "IPC$", 
239                                      s->io.name_resolve_order,
240                                      s->io.creds,
241                                      c->event_ctx);
242         composite_continue(c, conn_req, continue_smb2_connect, c);
243         return c;
244 }
245
246
247 /*
248   Receive result of a rpc connection to a rpc pipe on SMB2
249 */
250 static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb2_recv(struct composite_context *c)
251 {
252         NTSTATUS status = composite_wait(c);
253         
254         talloc_free(c);
255         return status;
256 }
257
258
259 struct pipe_ip_tcp_state {
260         struct dcerpc_pipe_connect io;
261         const char *host;
262         const char *target_hostname;
263         uint32_t port;
264 };
265
266
267 /*
268   Stage 2 of ncacn_ip_tcp: rpc pipe opened (or not)
269 */
270 static void continue_pipe_open_ncacn_ip_tcp(struct composite_context *ctx)
271 {
272         struct composite_context *c = talloc_get_type(ctx->async.private_data,
273                                                       struct composite_context);
274
275         /* receive result of named pipe open request on tcp/ip */
276         c->status = dcerpc_pipe_open_tcp_recv(ctx);
277         if (!composite_is_ok(c)) return;
278
279         composite_done(c);
280 }
281
282
283 /*
284   Initiate async open of a rpc connection to a rpc pipe on TCP/IP using
285   the binding structure to determine the endpoint and options
286 */
287 static struct composite_context* dcerpc_pipe_connect_ncacn_ip_tcp_send(TALLOC_CTX *mem_ctx,
288                                                                        struct dcerpc_pipe_connect *io)
289 {
290         struct composite_context *c;
291         struct pipe_ip_tcp_state *s;
292         struct composite_context *pipe_req;
293
294         /* composite context allocation and setup */
295         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
296         if (c == NULL) return NULL;
297
298         s = talloc_zero(c, struct pipe_ip_tcp_state);
299         if (composite_nomem(s, c)) return c;
300         c->private_data = s;
301
302         /* store input parameters in state structure */
303         s->io               = *io;
304         s->host             = talloc_reference(c, io->binding->host);
305         s->target_hostname  = talloc_reference(c, io->binding->target_hostname);
306                              /* port number is a binding endpoint here */
307         s->port             = atoi(io->binding->endpoint);   
308
309         /* send pipe open request on tcp/ip */
310         pipe_req = dcerpc_pipe_open_tcp_send(s->io.pipe->conn, s->host, s->target_hostname, 
311                                              s->port);
312         composite_continue(c, pipe_req, continue_pipe_open_ncacn_ip_tcp, c);
313         return c;
314 }
315
316
317 /*
318   Receive result of a rpc connection to a rpc pipe on TCP/IP
319 */
320 static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp_recv(struct composite_context *c)
321 {
322         NTSTATUS status = composite_wait(c);
323         
324         talloc_free(c);
325         return status;
326 }
327
328
329 struct pipe_unix_state {
330         struct dcerpc_pipe_connect io;
331         const char *path;
332 };
333
334
335 /*
336   Stage 2 of ncacn_unix: rpc pipe opened (or not)
337 */
338 static void continue_pipe_open_ncacn_unix_stream(struct composite_context *ctx)
339 {
340         struct composite_context *c = talloc_get_type(ctx->async.private_data,
341                                                       struct composite_context);
342
343         /* receive result of pipe open request on unix socket */
344         c->status = dcerpc_pipe_open_unix_stream_recv(ctx);
345         if (!composite_is_ok(c)) return;
346
347         composite_done(c);
348 }
349
350
351 /*
352   Initiate async open of a rpc connection to a rpc pipe on unix socket using
353   the binding structure to determine the endpoint and options
354 */
355 static struct composite_context* dcerpc_pipe_connect_ncacn_unix_stream_send(TALLOC_CTX *mem_ctx,
356                                                                             struct dcerpc_pipe_connect *io)
357 {
358         struct composite_context *c;
359         struct pipe_unix_state *s;
360         struct composite_context *pipe_req;
361
362         /* composite context allocation and setup */
363         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
364         if (c == NULL) return NULL;
365
366         s = talloc_zero(c, struct pipe_unix_state);
367         if (composite_nomem(s, c)) return c;
368         c->private_data = s;
369
370         /* prepare pipe open parameters and store them in state structure
371            also, verify whether biding endpoint is not null */
372         s->io = *io;
373         
374         if (!io->binding->endpoint) {
375                 DEBUG(0, ("Path to unix socket not specified\n"));
376                 composite_error(c, NT_STATUS_INVALID_PARAMETER);
377                 return c;
378         }
379
380         s->path  = talloc_strdup(c, io->binding->endpoint);  /* path is a binding endpoint here */
381         if (composite_nomem(s->path, c)) return c;
382
383         /* send pipe open request on unix socket */
384         pipe_req = dcerpc_pipe_open_unix_stream_send(s->io.pipe->conn, s->path);
385         composite_continue(c, pipe_req, continue_pipe_open_ncacn_unix_stream, c);
386         return c;
387 }
388
389
390 /*
391   Receive result of a rpc connection to a pipe on unix socket
392 */
393 static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream_recv(struct composite_context *c)
394 {
395         NTSTATUS status = composite_wait(c);
396
397         talloc_free(c);
398         return status;
399 }
400
401
402 struct pipe_ncalrpc_state {
403         struct dcerpc_pipe_connect io;
404 };
405
406 static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c);
407
408 /*
409   Stage 2 of ncalrpc: rpc pipe opened (or not)
410 */
411 static void continue_pipe_open_ncalrpc(struct composite_context *ctx)
412 {
413         struct composite_context *c = talloc_get_type(ctx->async.private_data,
414                                                       struct composite_context);
415
416         /* receive result of pipe open request on ncalrpc */
417         c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx);
418         if (!composite_is_ok(c)) return;
419
420         composite_done(c);
421 }
422
423
424 /* 
425    Initiate async open of a rpc connection request on NCALRPC using
426    the binding structure to determine the endpoint and options
427 */
428 static struct composite_context* dcerpc_pipe_connect_ncalrpc_send(TALLOC_CTX *mem_ctx,
429                                                                   struct dcerpc_pipe_connect *io)
430 {
431         struct composite_context *c;
432         struct pipe_ncalrpc_state *s;
433         struct composite_context *pipe_req;
434
435         /* composite context allocation and setup */
436         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
437         if (c == NULL) return NULL;
438
439         s = talloc_zero(c, struct pipe_ncalrpc_state);
440         if (composite_nomem(s, c)) return c;
441         c->private_data = s;
442         
443         /* store input parameters in state structure */
444         s->io  = *io;
445
446         /* send pipe open request */
447         pipe_req = dcerpc_pipe_open_pipe_send(s->io.pipe->conn, lp_ncalrpc_dir(global_loadparm), 
448                                               s->io.binding->endpoint);
449         composite_continue(c, pipe_req, continue_pipe_open_ncalrpc, c);
450         return c;
451 }
452
453
454 /*
455   Receive result of a rpc connection to a rpc pipe on NCALRPC
456 */
457 static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c)
458 {
459         NTSTATUS status = composite_wait(c);
460         
461         talloc_free(c);
462         return status;
463 }
464
465
466 struct pipe_connect_state {
467         struct dcerpc_pipe *pipe;
468         struct dcerpc_binding *binding;
469         const struct ndr_interface_table *table;
470         struct cli_credentials *credentials;
471         struct loadparm_context *lp_ctx;
472 };
473
474
475 static void continue_map_binding(struct composite_context *ctx);
476 static void continue_connect(struct composite_context *c, struct pipe_connect_state *s);
477 static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx);
478 static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx);
479 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx);
480 static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx);
481 static void continue_pipe_connect_ncalrpc(struct composite_context *ctx);
482 static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s);
483 static void continue_pipe_auth(struct composite_context *ctx);
484
485
486 /*
487   Stage 2 of pipe_connect_b: Receive result of endpoint mapping
488 */
489 static void continue_map_binding(struct composite_context *ctx)
490 {
491         struct composite_context *c = talloc_get_type(ctx->async.private_data,
492                                                       struct composite_context);
493         struct pipe_connect_state *s = talloc_get_type(c->private_data,
494                                                        struct pipe_connect_state);
495         
496         c->status = dcerpc_epm_map_binding_recv(ctx);
497         if (!composite_is_ok(c)) return;
498
499         DEBUG(2,("Mapped to DCERPC endpoint %s\n", s->binding->endpoint));
500         
501         continue_connect(c, s);
502 }
503
504
505 /*
506   Stage 2 of pipe_connect_b: Continue connection after endpoint is known
507 */
508 static void continue_connect(struct composite_context *c, struct pipe_connect_state *s)
509 {
510         struct dcerpc_pipe_connect pc;
511
512         /* potential exits to another stage by sending an async request */
513         struct composite_context *ncacn_np_smb2_req;
514         struct composite_context *ncacn_np_smb_req;
515         struct composite_context *ncacn_ip_tcp_req;
516         struct composite_context *ncacn_unix_req;
517         struct composite_context *ncalrpc_req;
518
519         /* dcerpc pipe connect input parameters */
520         pc.pipe         = s->pipe;
521         pc.binding      = s->binding;
522         pc.interface    = s->table;
523         pc.creds        = s->credentials;
524         pc.name_resolve_order = lp_name_resolve_order(global_loadparm);
525
526         /* connect dcerpc pipe depending on required transport */
527         switch (s->binding->transport) {
528         case NCACN_NP:
529                 if (pc.binding->flags & DCERPC_SMB2) {
530                         /* new varient of SMB a.k.a. SMB2 */
531                         ncacn_np_smb2_req = dcerpc_pipe_connect_ncacn_np_smb2_send(c, &pc);
532                         composite_continue(c, ncacn_np_smb2_req, continue_pipe_connect_ncacn_np_smb2, c);
533                         return;
534
535                 } else {
536                         /* good old ordinary SMB */
537                         ncacn_np_smb_req = dcerpc_pipe_connect_ncacn_np_smb_send(c, &pc);
538                         composite_continue(c, ncacn_np_smb_req, continue_pipe_connect_ncacn_np_smb, c);
539                         return;
540                 }
541                 break;
542
543         case NCACN_IP_TCP:
544                 ncacn_ip_tcp_req = dcerpc_pipe_connect_ncacn_ip_tcp_send(c, &pc);
545                 composite_continue(c, ncacn_ip_tcp_req, continue_pipe_connect_ncacn_ip_tcp, c);
546                 return;
547
548         case NCACN_UNIX_STREAM:
549                 ncacn_unix_req = dcerpc_pipe_connect_ncacn_unix_stream_send(c, &pc);
550                 composite_continue(c, ncacn_unix_req, continue_pipe_connect_ncacn_unix, c);
551                 return;
552
553         case NCALRPC:
554                 ncalrpc_req = dcerpc_pipe_connect_ncalrpc_send(c, &pc);
555                 composite_continue(c, ncalrpc_req, continue_pipe_connect_ncalrpc, c);
556                 return;
557
558         default:
559                 /* looks like a transport we don't support now */
560                 composite_error(c, NT_STATUS_NOT_SUPPORTED);
561         }
562 }
563
564
565 /*
566   Stage 3 of pipe_connect_b: Receive result of pipe connect request on
567   named pipe on smb2
568 */
569 static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx)
570 {
571         struct composite_context *c = talloc_get_type(ctx->async.private_data,
572                                                       struct composite_context);
573         struct pipe_connect_state *s = talloc_get_type(c->private_data,
574                                                        struct pipe_connect_state);
575
576         c->status = dcerpc_pipe_connect_ncacn_np_smb2_recv(ctx);
577         if (!composite_is_ok(c)) return;
578
579         continue_pipe_connect(c, s);
580 }
581
582
583 /*
584   Stage 3 of pipe_connect_b: Receive result of pipe connect request on
585   named pipe on smb
586 */
587 static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx)
588 {
589         struct composite_context *c = talloc_get_type(ctx->async.private_data,
590                                                       struct composite_context);
591         struct pipe_connect_state *s = talloc_get_type(c->private_data,
592                                                        struct pipe_connect_state);
593
594         c->status = dcerpc_pipe_connect_ncacn_np_smb_recv(ctx);
595         if (!composite_is_ok(c)) return;
596         
597         continue_pipe_connect(c, s);
598 }
599
600
601 /*
602   Stage 3 of pipe_connect_b: Receive result of pipe connect request on tcp/ip
603 */
604 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx)
605 {
606         struct composite_context *c = talloc_get_type(ctx->async.private_data,
607                                                       struct composite_context);
608         struct pipe_connect_state *s = talloc_get_type(c->private_data,
609                                                        struct pipe_connect_state);
610
611         c->status = dcerpc_pipe_connect_ncacn_ip_tcp_recv(ctx);
612         if (!composite_is_ok(c)) return;
613
614         continue_pipe_connect(c, s);
615 }
616
617
618 /*
619   Stage 3 of pipe_connect_b: Receive result of pipe connect request on unix socket
620 */
621 static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx)
622 {
623         struct composite_context *c = talloc_get_type(ctx->async.private_data,
624                                                       struct composite_context);
625         struct pipe_connect_state *s = talloc_get_type(c->private_data,
626                                                        struct pipe_connect_state);
627         
628         c->status = dcerpc_pipe_connect_ncacn_unix_stream_recv(ctx);
629         if (!composite_is_ok(c)) return;
630         
631         continue_pipe_connect(c, s);
632 }
633
634
635 /*
636   Stage 3 of pipe_connect_b: Receive result of pipe connect request on local rpc
637 */
638 static void continue_pipe_connect_ncalrpc(struct composite_context *ctx)
639 {
640         struct composite_context *c = talloc_get_type(ctx->async.private_data,
641                                                       struct composite_context);
642         struct pipe_connect_state *s = talloc_get_type(c->private_data,
643                                                        struct pipe_connect_state);
644         
645         c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx);
646         if (!composite_is_ok(c)) return;
647
648         continue_pipe_connect(c, s);
649 }
650
651
652 /*
653   Stage 4 of pipe_connect_b: Start an authentication on connected dcerpc pipe
654   depending on credentials and binding flags passed.
655 */
656 static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s)
657 {
658         struct composite_context *auth_bind_req;
659
660         s->pipe->binding = s->binding;
661         if (!talloc_reference(s->pipe, s->binding)) {
662                 composite_error(c, NT_STATUS_NO_MEMORY);
663                 return;
664         }
665
666         auth_bind_req = dcerpc_pipe_auth_send(s->pipe, s->binding, s->table,
667                                               s->credentials, s->lp_ctx);
668         composite_continue(c, auth_bind_req, continue_pipe_auth, c);
669 }
670
671
672 /*
673   Stage 5 of pipe_connect_b: Receive result of pipe authentication request
674   and say if all went ok
675 */
676 static void continue_pipe_auth(struct composite_context *ctx)
677 {
678         struct composite_context *c = talloc_get_type(ctx->async.private_data,
679                                                       struct composite_context);
680         struct pipe_connect_state *s = talloc_get_type(c->private_data, struct pipe_connect_state);
681
682         c->status = dcerpc_pipe_auth_recv(ctx, s, &s->pipe);
683         if (!composite_is_ok(c)) return;
684
685         composite_done(c);
686 }
687
688
689 /*
690   handle timeouts of a dcerpc connect
691 */
692 static void dcerpc_connect_timeout_handler(struct event_context *ev, struct timed_event *te, 
693                                            struct timeval t, void *private)
694 {
695         struct composite_context *c = talloc_get_type(private, struct composite_context);
696         composite_error(c, NT_STATUS_IO_TIMEOUT);
697 }
698
699 /*
700   start a request to open a rpc connection to a rpc pipe, using
701   specified binding structure to determine the endpoint and options
702 */
703 struct composite_context* dcerpc_pipe_connect_b_send(TALLOC_CTX *parent_ctx,
704                                                      struct dcerpc_binding *binding,
705                                                      const struct ndr_interface_table *table,
706                                                      struct cli_credentials *credentials,
707                                                      struct event_context *ev,
708                                                      struct loadparm_context *lp_ctx)
709 {
710         struct composite_context *c;
711         struct pipe_connect_state *s;
712         struct event_context *new_ev = NULL;
713
714         if (ev == NULL) {
715                 new_ev = event_context_init(parent_ctx);
716                 if (new_ev == NULL) return NULL;
717                 ev = new_ev;
718         }
719
720         /* composite context allocation and setup */
721         c = composite_create(parent_ctx, ev);
722         if (c == NULL) {
723                 talloc_free(new_ev);
724                 return NULL;
725         }
726         talloc_steal(c, new_ev);
727
728         s = talloc_zero(c, struct pipe_connect_state);
729         if (composite_nomem(s, c)) return c;
730         c->private_data = s;
731
732         /* initialise dcerpc pipe structure */
733         s->pipe = dcerpc_pipe_init(c, ev);
734         if (composite_nomem(s->pipe, c)) return c;
735
736         /* store parameters in state structure */
737         s->binding      = binding;
738         s->table        = table;
739         s->credentials  = credentials;
740         s->lp_ctx       = lp_ctx;
741
742         event_add_timed(c->event_ctx, c,
743                         timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
744                         dcerpc_connect_timeout_handler, c);
745         
746         switch (s->binding->transport) {
747         case NCA_UNKNOWN: {
748                 struct composite_context *binding_req;
749                 binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table,
750                                                           s->pipe->conn->event_ctx,
751                                                           s->lp_ctx);
752                 composite_continue(c, binding_req, continue_map_binding, c);
753                 return c;
754                 }
755
756         case NCACN_NP:
757         case NCACN_IP_TCP:
758         case NCALRPC:
759                 if (!s->binding->endpoint) {
760                         struct composite_context *binding_req;
761                         binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table,
762                                                                   s->pipe->conn->event_ctx,
763                                                                   s->lp_ctx);
764                         composite_continue(c, binding_req, continue_map_binding, c);
765                         return c;
766                 }
767
768         default:
769                 break;
770         }
771
772         continue_connect(c, s);
773         return c;
774 }
775
776
777 /*
778   receive result of a request to open a rpc connection to a rpc pipe
779 */
780 NTSTATUS dcerpc_pipe_connect_b_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
781                                     struct dcerpc_pipe **p)
782 {
783         NTSTATUS status;
784         struct pipe_connect_state *s;
785         
786         status = composite_wait(c);
787         
788         if (NT_STATUS_IS_OK(status)) {
789                 s = talloc_get_type(c->private_data, struct pipe_connect_state);
790                 talloc_steal(mem_ctx, s->pipe);
791                 *p = s->pipe;
792         }
793         talloc_free(c);
794         return status;
795 }
796
797
798 /*
799   open a rpc connection to a rpc pipe, using the specified 
800   binding structure to determine the endpoint and options - sync version
801 */
802 NTSTATUS dcerpc_pipe_connect_b(TALLOC_CTX *parent_ctx,
803                                struct dcerpc_pipe **pp,
804                                struct dcerpc_binding *binding,
805                                const struct ndr_interface_table *table,
806                                struct cli_credentials *credentials,
807                                struct event_context *ev,
808                                struct loadparm_context *lp_ctx)
809 {
810         struct composite_context *c;
811         
812         c = dcerpc_pipe_connect_b_send(parent_ctx, binding, table,
813                                        credentials, ev, lp_ctx);
814         return dcerpc_pipe_connect_b_recv(c, parent_ctx, pp);
815 }
816
817
818 struct pipe_conn_state {
819         struct dcerpc_pipe *pipe;
820 };
821
822
823 static void continue_pipe_connect_b(struct composite_context *ctx);
824
825
826 /*
827   Initiate rpc connection to a rpc pipe, using the specified string
828   binding to determine the endpoint and options.
829   The string is to be parsed to a binding structure first.
830 */
831 struct composite_context* dcerpc_pipe_connect_send(TALLOC_CTX *parent_ctx,
832                                                    const char *binding,
833                                                    const struct ndr_interface_table *table,
834                                                    struct cli_credentials *credentials,
835                                                    struct event_context *ev, struct loadparm_context *lp_ctx)
836 {
837         struct composite_context *c;
838         struct pipe_conn_state *s;
839         struct dcerpc_binding *b;
840         struct composite_context *pipe_conn_req;
841         struct event_context *new_ev = NULL;
842
843         if (ev == NULL) {
844                 new_ev = event_context_init(parent_ctx);
845                 if (new_ev == NULL) return NULL;
846                 ev = new_ev;
847         }
848
849         /* composite context allocation and setup */
850         c = composite_create(parent_ctx, ev);
851         if (c == NULL) {
852                 talloc_free(new_ev);
853                 return NULL;
854         }
855         talloc_steal(c, new_ev);
856
857         s = talloc_zero(c, struct pipe_conn_state);
858         if (composite_nomem(s, c)) return c;
859         c->private_data = s;
860
861         /* parse binding string to the structure */
862         c->status = dcerpc_parse_binding(c, binding, &b);
863         if (!NT_STATUS_IS_OK(c->status)) {
864                 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding));
865                 composite_error(c, c->status);
866                 return c;
867         }
868
869         DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(c, b)));
870
871         /* 
872            start connecting to a rpc pipe after binding structure
873            is established
874          */
875         pipe_conn_req = dcerpc_pipe_connect_b_send(c, b, table,
876                                                    credentials, ev, lp_ctx);
877         composite_continue(c, pipe_conn_req, continue_pipe_connect_b, c);
878         return c;
879 }
880
881
882 /*
883   Stage 2 of pipe_connect: Receive result of actual pipe connect request
884   and say if we're done ok
885 */
886 static void continue_pipe_connect_b(struct composite_context *ctx)
887 {
888         struct composite_context *c = talloc_get_type(ctx->async.private_data,
889                                                       struct composite_context);
890         struct pipe_conn_state *s = talloc_get_type(c->private_data,
891                                                     struct pipe_conn_state);
892
893         c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->pipe);
894         talloc_steal(s, s->pipe);
895         if (!composite_is_ok(c)) return;
896
897         composite_done(c);
898 }
899
900
901 /*
902   Receive result of pipe connect (using binding string) request
903   and return connected pipe structure.
904 */
905 NTSTATUS dcerpc_pipe_connect_recv(struct composite_context *c,
906                                   TALLOC_CTX *mem_ctx,
907                                   struct dcerpc_pipe **pp)
908 {
909         NTSTATUS status;
910         struct pipe_conn_state *s;
911
912         status = composite_wait(c);
913         if (NT_STATUS_IS_OK(status)) {
914                 s = talloc_get_type(c->private_data, struct pipe_conn_state);
915                 *pp = talloc_steal(mem_ctx, s->pipe);
916         }
917         talloc_free(c);
918         return status;
919 }
920
921
922 /*
923   Open a rpc connection to a rpc pipe, using the specified string
924   binding to determine the endpoint and options - sync version
925 */
926 NTSTATUS dcerpc_pipe_connect(TALLOC_CTX *parent_ctx, 
927                              struct dcerpc_pipe **pp, 
928                              const char *binding,
929                              const struct ndr_interface_table *table,
930                              struct cli_credentials *credentials,
931                              struct event_context *ev,
932                              struct loadparm_context *lp_ctx)
933 {
934         struct composite_context *c;
935         c = dcerpc_pipe_connect_send(parent_ctx, binding, 
936                                      table, credentials, ev, lp_ctx);
937         return dcerpc_pipe_connect_recv(c, parent_ctx, pp);
938 }
939