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