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