r19266: Add a target_hostname element to the binding struct. This allows us
[bbaumbach/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
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 2 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, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26
27 #include "includes.h"
28 #include "libcli/composite/composite.h"
29 #include "libcli/smb_composite/smb_composite.h"
30 #include "lib/events/events.h"
31 #include "libcli/smb2/smb2.h"
32 #include "libcli/smb2/smb2_calls.h"
33 #include "librpc/rpc/dcerpc.h"
34 #include "auth/credentials/credentials.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->conn, 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 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         conn->in.called_name            = s->io.binding->target_hostname;
115         conn->in.service                = "IPC$";
116         conn->in.service_type           = NULL;
117         conn->in.workgroup              = lp_workgroup();
118
119         /*
120          * provide proper credentials - user supplied, but allow a
121          * fallback to anonymous if this is an schannel connection
122          * (might be NT4 not allowing machine logins at session
123          * setup).
124          */
125         s->conn.in.credentials = s->io.creds;
126         if (s->io.binding->flags & DCERPC_SCHANNEL) {
127                 conn->in.fallback_to_anonymous  = True;
128         } else {
129                 conn->in.fallback_to_anonymous  = False;
130         }
131
132         /* send smb connect request */
133         conn_req = smb_composite_connect_send(conn, s->io.pipe->conn, s->io.pipe->conn->event_ctx);
134         if (composite_nomem(conn_req, c)) return c;
135
136         composite_continue(c, conn_req, continue_smb_connect, c);
137         return c;
138 }
139
140
141 /*
142   Receive result of a rpc connection to a rpc pipe on SMB
143 */
144 NTSTATUS dcerpc_pipe_connect_ncacn_np_smb_recv(struct composite_context *c)
145 {
146         NTSTATUS status = composite_wait(c);
147
148         talloc_free(c);
149         return status;
150 }
151
152
153 /*
154   Sync version of a rpc connection to a rpc pipe on SMB
155 */
156 NTSTATUS dcerpc_pipe_connect_ncacn_np_smb(TALLOC_CTX *mem_ctx,
157                                           struct dcerpc_pipe_connect *io)
158 {
159         struct composite_context *c;
160         c = dcerpc_pipe_connect_ncacn_np_smb_send(mem_ctx, io);
161         return dcerpc_pipe_connect_ncacn_np_smb_recv(c);
162 }
163
164
165 struct pipe_np_smb2_state {
166         struct smb2_tree *tree;
167         struct dcerpc_pipe_connect io;
168 };
169
170
171 /*
172   Stage 3 of ncacn_np_smb: Named pipe opened (or not)
173 */
174 static void continue_pipe_open_smb2(struct composite_context *ctx)
175 {
176         struct composite_context *c = talloc_get_type(ctx->async.private_data,
177                                                       struct composite_context);
178
179         /* receive result of named pipe open request on smb2 */
180         c->status = dcerpc_pipe_open_smb2_recv(ctx);
181         if (!composite_is_ok(c)) return;
182
183         composite_done(c);
184 }
185
186
187 /*
188   Stage 2 of ncacn_np_smb2: Open a named pipe after successful smb2 connection
189 */
190 static void continue_smb2_connect(struct composite_context *ctx)
191 {
192         struct composite_context *open_req;
193         struct composite_context *c = talloc_get_type(ctx->async.private_data,
194                                                       struct composite_context);
195         struct pipe_np_smb2_state *s = talloc_get_type(c->private_data,
196                                                        struct pipe_np_smb2_state);
197
198         /* receive result of smb2 connect request */
199         c->status = smb2_connect_recv(ctx, c, &s->tree);
200         if (!composite_is_ok(c)) return;
201
202         /* prepare named pipe open parameters */
203         s->io.pipe_name = s->io.binding->endpoint;
204
205         /* send named pipe open request */
206         open_req = dcerpc_pipe_open_smb2_send(s->io.pipe->conn, s->tree, s->io.pipe_name);
207         if (composite_nomem(open_req, c)) return;
208
209         composite_continue(c, open_req, continue_pipe_open_smb2, c);
210 }
211
212
213 /* 
214    Initiate async open of a rpc connection request on SMB2 using
215    the binding structure to determine the endpoint and options
216 */
217 struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send(TALLOC_CTX *mem_ctx,
218                                                                  struct dcerpc_pipe_connect *io)
219 {
220         struct composite_context *c;
221         struct pipe_np_smb2_state *s;
222         struct composite_context *conn_req;
223
224         /* composite context allocation and setup */
225         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
226         if (c == NULL) return NULL;
227
228         s = talloc_zero(c, struct pipe_np_smb2_state);
229         if (composite_nomem(s, c)) return c;
230         c->private_data = s;
231
232         s->io = *io;
233
234         /*
235          * provide proper credentials - user supplied or anonymous in case this is
236          * schannel connection
237          */
238         if (s->io.binding->flags & DCERPC_SCHANNEL) {
239                 s->io.creds = cli_credentials_init(mem_ctx);
240                 if (composite_nomem(s->io.creds, c)) return c;
241
242                 cli_credentials_set_anonymous(s->io.creds);
243                 cli_credentials_guess(s->io.creds);
244         }
245
246         /* send smb2 connect request */
247         conn_req = smb2_connect_send(mem_ctx, s->io.binding->host, "IPC$", s->io.creds,
248                                      c->event_ctx);
249         composite_continue(c, conn_req, continue_smb2_connect, c);
250         return c;
251 }
252
253
254 /*
255   Receive result of a rpc connection to a rpc pipe on SMB2
256 */
257 NTSTATUS dcerpc_pipe_connect_ncacn_np_smb2_recv(struct composite_context *c)
258 {
259         NTSTATUS status = composite_wait(c);
260         
261         talloc_free(c);
262         return status;
263 }
264
265
266 /*
267   Sync version of a rpc connection to a rpc pipe on SMB2
268 */
269 NTSTATUS dcerpc_pipe_connect_ncacn_np_smb2(TALLOC_CTX *mem_ctx,
270                                            struct dcerpc_pipe_connect *io)
271 {
272         struct composite_context *c;
273         c = dcerpc_pipe_connect_ncacn_np_smb2_send(mem_ctx, io);
274         return dcerpc_pipe_connect_ncacn_np_smb2_recv(c);
275 }
276
277
278 struct pipe_ip_tcp_state {
279         struct dcerpc_pipe_connect io;
280         const char *host;
281         const char *target_hostname;
282         uint32_t port;
283 };
284
285
286 /*
287   Stage 2 of ncacn_ip_tcp: rpc pipe opened (or not)
288 */
289 static void continue_pipe_open_ncacn_ip_tcp(struct composite_context *ctx)
290 {
291         struct composite_context *c = talloc_get_type(ctx->async.private_data,
292                                                       struct composite_context);
293
294         /* receive result of named pipe open request on tcp/ip */
295         c->status = dcerpc_pipe_open_tcp_recv(ctx);
296         if (!composite_is_ok(c)) return;
297
298         composite_done(c);
299 }
300
301
302 /*
303   Initiate async open of a rpc connection to a rpc pipe on TCP/IP using
304   the binding structure to determine the endpoint and options
305 */
306 struct composite_context* dcerpc_pipe_connect_ncacn_ip_tcp_send(TALLOC_CTX *mem_ctx,
307                                                                 struct dcerpc_pipe_connect *io)
308 {
309         struct composite_context *c;
310         struct pipe_ip_tcp_state *s;
311         struct composite_context *pipe_req;
312
313         /* composite context allocation and setup */
314         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
315         if (c == NULL) return NULL;
316
317         s = talloc_zero(c, struct pipe_ip_tcp_state);
318         if (composite_nomem(s, c)) return c;
319         c->private_data = s;
320
321         /* store input parameters in state structure */
322         s->io               = *io;
323         s->host             = talloc_reference(c, io->binding->host);
324         s->target_hostname  = talloc_reference(c, io->binding->target_hostname);
325                              /* port number is a binding endpoint here */
326         s->port             = atoi(io->binding->endpoint);   
327
328         /* send pipe open request on tcp/ip */
329         pipe_req = dcerpc_pipe_open_tcp_send(s->io.pipe->conn, s->host, s->target_hostname, 
330                                              s->port);
331         composite_continue(c, pipe_req, continue_pipe_open_ncacn_ip_tcp, c);
332         return c;
333 }
334
335
336 /*
337   Receive result of a rpc connection to a rpc pipe on TCP/IP
338 */
339 NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp_recv(struct composite_context *c)
340 {
341         NTSTATUS status = composite_wait(c);
342         
343         talloc_free(c);
344         return status;
345 }
346
347
348 /*
349   Sync version of rpc connection to a rpc pipe on TCP/IP
350 */
351 NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(TALLOC_CTX *mem_ctx,
352                                           struct dcerpc_pipe_connect *io)
353 {
354         struct composite_context *c;
355         c = dcerpc_pipe_connect_ncacn_ip_tcp_send(mem_ctx, io);
356         return dcerpc_pipe_connect_ncacn_ip_tcp_recv(c);
357 }
358
359
360 struct pipe_unix_state {
361         struct dcerpc_pipe_connect io;
362         const char *path;
363 };
364
365
366 /*
367   Stage 2 of ncacn_unix: rpc pipe opened (or not)
368 */
369 static void continue_pipe_open_ncacn_unix_stream(struct composite_context *ctx)
370 {
371         struct composite_context *c = talloc_get_type(ctx->async.private_data,
372                                                       struct composite_context);
373
374         /* receive result of pipe open request on unix socket */
375         c->status = dcerpc_pipe_open_unix_stream_recv(ctx);
376         if (!composite_is_ok(c)) return;
377
378         composite_done(c);
379 }
380
381
382 /*
383   Initiate async open of a rpc connection to a rpc pipe on unix socket using
384   the binding structure to determine the endpoint and options
385 */
386 struct composite_context* dcerpc_pipe_connect_ncacn_unix_stream_send(TALLOC_CTX *mem_ctx,
387                                                                      struct dcerpc_pipe_connect *io)
388 {
389         struct composite_context *c;
390         struct pipe_unix_state *s;
391         struct composite_context *pipe_req;
392
393         /* composite context allocation and setup */
394         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
395         if (c == NULL) return NULL;
396
397         s = talloc_zero(c, struct pipe_unix_state);
398         if (composite_nomem(s, c)) return c;
399         c->private_data = s;
400
401         /* prepare pipe open parameters and store them in state structure
402            also, verify whether biding endpoint is not null */
403         s->io = *io;
404         
405         if (!io->binding->endpoint) {
406                 DEBUG(0, ("Path to unix socket not specified\n"));
407                 composite_error(c, NT_STATUS_INVALID_PARAMETER);
408                 return c;
409         }
410
411         s->path  = talloc_strdup(c, io->binding->endpoint);  /* path is a binding endpoint here */
412         if (composite_nomem(s->path, c)) return c;
413
414         /* send pipe open request on unix socket */
415         pipe_req = dcerpc_pipe_open_unix_stream_send(s->io.pipe->conn, s->path);
416         composite_continue(c, pipe_req, continue_pipe_open_ncacn_unix_stream, c);
417         return c;
418 }
419
420
421 /*
422   Receive result of a rpc connection to a pipe on unix socket
423 */
424 NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream_recv(struct composite_context *c)
425 {
426         NTSTATUS status = composite_wait(c);
427
428         talloc_free(c);
429         return status;
430 }
431
432
433 /*
434   Sync version of a rpc connection to a rpc pipe on unix socket
435 */
436 NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream(TALLOC_CTX *mem_ctx,
437                                                struct dcerpc_pipe_connect *io)
438 {
439         struct composite_context *c;
440         c = dcerpc_pipe_connect_ncacn_unix_stream_send(mem_ctx, io);
441         return dcerpc_pipe_connect_ncacn_unix_stream_recv(c);   
442 }
443
444
445 struct pipe_ncalrpc_state {
446         struct dcerpc_pipe_connect io;
447 };
448
449
450 /*
451   Stage 2 of ncalrpc: rpc pipe opened (or not)
452 */
453 static void continue_pipe_open_ncalrpc(struct composite_context *ctx)
454 {
455         struct composite_context *c = talloc_get_type(ctx->async.private_data,
456                                                       struct composite_context);
457
458         /* receive result of pipe open request on ncalrpc */
459         c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx);
460         if (!composite_is_ok(c)) return;
461
462         composite_done(c);
463 }
464
465
466 /* 
467    Initiate async open of a rpc connection request on NCALRPC using
468    the binding structure to determine the endpoint and options
469 */
470 struct composite_context* dcerpc_pipe_connect_ncalrpc_send(TALLOC_CTX *mem_ctx,
471                                                            struct dcerpc_pipe_connect *io)
472 {
473         struct composite_context *c;
474         struct pipe_ncalrpc_state *s;
475         struct composite_context *pipe_req;
476
477         /* composite context allocation and setup */
478         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
479         if (c == NULL) return NULL;
480
481         s = talloc_zero(c, struct pipe_ncalrpc_state);
482         if (composite_nomem(s, c)) return c;
483         c->private_data = s;
484         
485         /* store input parameters in state structure */
486         s->io  = *io;
487
488         /* send pipe open request */
489         pipe_req = dcerpc_pipe_open_pipe_send(s->io.pipe->conn, s->io.binding->endpoint);
490         composite_continue(c, pipe_req, continue_pipe_open_ncalrpc, c);
491         return c;
492 }
493
494
495 /*
496   Receive result of a rpc connection to a rpc pipe on NCALRPC
497 */
498 NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c)
499 {
500         NTSTATUS status = composite_wait(c);
501         
502         talloc_free(c);
503         return status;
504 }
505
506
507 /*
508   Sync version of a rpc connection to a rpc pipe on NCALRPC
509 */
510 NTSTATUS dcerpc_pipe_connect_ncalrpc(TALLOC_CTX *mem_ctx,
511                                      struct dcerpc_pipe_connect *io)
512 {
513         struct composite_context *c = dcerpc_pipe_connect_ncalrpc_send(mem_ctx, io);
514         return dcerpc_pipe_connect_ncalrpc_recv(c);
515 }
516
517
518 struct pipe_connect_state {
519         struct dcerpc_pipe *pipe;
520         struct dcerpc_binding *binding;
521         const struct dcerpc_interface_table *table;
522         struct cli_credentials *credentials;
523 };
524
525
526 static void continue_map_binding(struct composite_context *ctx);
527 static void continue_connect(struct composite_context *c, struct pipe_connect_state *s);
528 static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx);
529 static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx);
530 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx);
531 static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx);
532 static void continue_pipe_connect_ncalrpc(struct composite_context *ctx);
533 static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s);
534 static void continue_pipe_auth(struct composite_context *ctx);
535
536
537 /*
538   Stage 2 of pipe_connect_b: Receive result of endpoint mapping
539 */
540 static void continue_map_binding(struct composite_context *ctx)
541 {
542         struct composite_context *c = talloc_get_type(ctx->async.private_data,
543                                                       struct composite_context);
544         struct pipe_connect_state *s = talloc_get_type(c->private_data,
545                                                        struct pipe_connect_state);
546         
547         c->status = dcerpc_epm_map_binding_recv(ctx);
548         if (!composite_is_ok(c)) return;
549
550         DEBUG(2,("Mapped to DCERPC endpoint %s\n", s->binding->endpoint));
551         
552         continue_connect(c, s);
553 }
554
555
556 /*
557   Stage 2 of pipe_connect_b: Continue connection after endpoint is known
558 */
559 static void continue_connect(struct composite_context *c, struct pipe_connect_state *s)
560 {
561         struct dcerpc_pipe_connect pc;
562
563         /* potential exits to another stage by sending an async request */
564         struct composite_context *ncacn_np_smb2_req;
565         struct composite_context *ncacn_np_smb_req;
566         struct composite_context *ncacn_ip_tcp_req;
567         struct composite_context *ncacn_unix_req;
568         struct composite_context *ncalrpc_req;
569
570         /* dcerpc pipe connect input parameters */
571         pc.pipe         = s->pipe;
572         pc.binding      = s->binding;
573         pc.interface    = s->table;
574         pc.creds        = s->credentials;
575         
576         /* connect dcerpc pipe depending on required transport */
577         switch (s->binding->transport) {
578         case NCACN_NP:
579                 if (pc.binding->flags & DCERPC_SMB2) {
580                         /* new varient of SMB a.k.a. SMB2 */
581                         ncacn_np_smb2_req = dcerpc_pipe_connect_ncacn_np_smb2_send(c, &pc);
582                         composite_continue(c, ncacn_np_smb2_req, continue_pipe_connect_ncacn_np_smb2, c);
583                         return;
584
585                 } else {
586                         /* good old ordinary SMB */
587                         ncacn_np_smb_req = dcerpc_pipe_connect_ncacn_np_smb_send(c, &pc);
588                         composite_continue(c, ncacn_np_smb_req, continue_pipe_connect_ncacn_np_smb, c);
589                         return;
590                 }
591                 break;
592
593         case NCACN_IP_TCP:
594                 ncacn_ip_tcp_req = dcerpc_pipe_connect_ncacn_ip_tcp_send(c, &pc);
595                 composite_continue(c, ncacn_ip_tcp_req, continue_pipe_connect_ncacn_ip_tcp, c);
596                 return;
597
598         case NCACN_UNIX_STREAM:
599                 ncacn_unix_req = dcerpc_pipe_connect_ncacn_unix_stream_send(c, &pc);
600                 composite_continue(c, ncacn_unix_req, continue_pipe_connect_ncacn_unix, c);
601                 return;
602
603         case NCALRPC:
604                 ncalrpc_req = dcerpc_pipe_connect_ncalrpc_send(c, &pc);
605                 composite_continue(c, ncalrpc_req, continue_pipe_connect_ncalrpc, c);
606                 return;
607
608         default:
609                 /* looks like a transport we don't support now */
610                 composite_error(c, NT_STATUS_NOT_SUPPORTED);
611         }
612 }
613
614
615 /*
616   Stage 3 of pipe_connect_b: Receive result of pipe connect request on
617   named pipe on smb2
618 */
619 static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx)
620 {
621         struct composite_context *c = talloc_get_type(ctx->async.private_data,
622                                                       struct composite_context);
623         struct pipe_connect_state *s = talloc_get_type(c->private_data,
624                                                        struct pipe_connect_state);
625
626         c->status = dcerpc_pipe_connect_ncacn_np_smb2_recv(ctx);
627         if (!composite_is_ok(c)) return;
628
629         continue_pipe_connect(c, s);
630 }
631
632
633 /*
634   Stage 3 of pipe_connect_b: Receive result of pipe connect request on
635   named pipe on smb
636 */
637 static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx)
638 {
639         struct composite_context *c = talloc_get_type(ctx->async.private_data,
640                                                       struct composite_context);
641         struct pipe_connect_state *s = talloc_get_type(c->private_data,
642                                                        struct pipe_connect_state);
643
644         c->status = dcerpc_pipe_connect_ncacn_np_smb_recv(ctx);
645         if (!composite_is_ok(c)) return;
646         
647         continue_pipe_connect(c, s);
648 }
649
650
651 /*
652   Stage 3 of pipe_connect_b: Receive result of pipe connect request on tcp/ip
653 */
654 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx)
655 {
656         struct composite_context *c = talloc_get_type(ctx->async.private_data,
657                                                       struct composite_context);
658         struct pipe_connect_state *s = talloc_get_type(c->private_data,
659                                                        struct pipe_connect_state);
660
661         c->status = dcerpc_pipe_connect_ncacn_ip_tcp_recv(ctx);
662         if (!composite_is_ok(c)) return;
663
664         continue_pipe_connect(c, s);
665 }
666
667
668 /*
669   Stage 3 of pipe_connect_b: Receive result of pipe connect request on unix socket
670 */
671 static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx)
672 {
673         struct composite_context *c = talloc_get_type(ctx->async.private_data,
674                                                       struct composite_context);
675         struct pipe_connect_state *s = talloc_get_type(c->private_data,
676                                                        struct pipe_connect_state);
677         
678         c->status = dcerpc_pipe_connect_ncacn_unix_stream_recv(ctx);
679         if (!composite_is_ok(c)) return;
680         
681         continue_pipe_connect(c, s);
682 }
683
684
685 /*
686   Stage 3 of pipe_connect_b: Receive result of pipe connect request on local rpc
687 */
688 static void continue_pipe_connect_ncalrpc(struct composite_context *ctx)
689 {
690         struct composite_context *c = talloc_get_type(ctx->async.private_data,
691                                                       struct composite_context);
692         struct pipe_connect_state *s = talloc_get_type(c->private_data,
693                                                        struct pipe_connect_state);
694         
695         c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx);
696         if (!composite_is_ok(c)) return;
697
698         continue_pipe_connect(c, s);
699 }
700
701
702 /*
703   Stage 4 of pipe_connect_b: Start an authentication on connected dcerpc pipe
704   depending on credentials and binding flags passed.
705 */
706 static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s)
707 {
708         struct composite_context *auth_bind_req;
709
710         s->pipe->binding = s->binding;
711         if (!talloc_reference(s->pipe, s->binding)) {
712                 composite_error(c, NT_STATUS_NO_MEMORY);
713                 return;
714         }
715
716         auth_bind_req = dcerpc_pipe_auth_send(s->pipe, s->binding, s->table,
717                                               s->credentials);
718         composite_continue(c, auth_bind_req, continue_pipe_auth, c);
719 }
720
721
722 /*
723   Stage 5 of pipe_connect_b: Receive result of pipe authentication request
724   and say if all went ok
725 */
726 static void continue_pipe_auth(struct composite_context *ctx)
727 {
728         struct composite_context *c = talloc_get_type(ctx->async.private_data,
729                                                       struct composite_context);
730         struct pipe_connect_state *s = talloc_get_type(c->private_data, struct pipe_connect_state);
731
732         c->status = dcerpc_pipe_auth_recv(ctx, s, &s->pipe);
733         if (!composite_is_ok(c)) return;
734
735         composite_done(c);
736 }
737
738
739 /*
740   handle timeouts of a dcerpc connect
741 */
742 static void dcerpc_connect_timeout_handler(struct event_context *ev, struct timed_event *te, 
743                                            struct timeval t, void *private)
744 {
745         struct composite_context *c = talloc_get_type(private, struct composite_context);
746         composite_error(c, NT_STATUS_IO_TIMEOUT);
747 }
748
749 /*
750   start a request to open a rpc connection to a rpc pipe, using
751   specified binding structure to determine the endpoint and options
752 */
753 struct composite_context* dcerpc_pipe_connect_b_send(TALLOC_CTX *parent_ctx,
754                                                      struct dcerpc_binding *binding,
755                                                      const struct dcerpc_interface_table *table,
756                                                      struct cli_credentials *credentials,
757                                                      struct event_context *ev)
758 {
759         struct composite_context *c;
760         struct pipe_connect_state *s;
761         struct event_context *new_ev = NULL;
762
763         if (ev == NULL) {
764                 new_ev = event_context_init(parent_ctx);
765                 if (new_ev == NULL) return NULL;
766                 ev = new_ev;
767         }
768
769         /* composite context allocation and setup */
770         c = composite_create(parent_ctx, ev);
771         if (c == NULL) {
772                 talloc_free(new_ev);
773                 return NULL;
774         }
775         talloc_steal(c, new_ev);
776
777         s = talloc_zero(c, struct pipe_connect_state);
778         if (composite_nomem(s, c)) return c;
779         c->private_data = s;
780
781         /* initialise dcerpc pipe structure */
782         s->pipe = dcerpc_pipe_init(c, ev);
783         if (composite_nomem(s->pipe, c)) return c;
784
785         /* store parameters in state structure */
786         s->binding      = binding;
787         s->table        = table;
788         s->credentials  = credentials;
789
790         event_add_timed(c->event_ctx, c,
791                         timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
792                         dcerpc_connect_timeout_handler, c);
793         
794         switch (s->binding->transport) {
795         case NCACN_NP:
796         case NCACN_IP_TCP:
797         case NCALRPC:
798                 if (!s->binding->endpoint) {
799                         struct composite_context *binding_req;
800                         binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table,
801                                                                   s->pipe->conn->event_ctx);
802                         composite_continue(c, binding_req, continue_map_binding, c);
803                         return c;
804                 }
805
806         default:
807                 break;
808         }
809
810         continue_connect(c, s);
811         return c;
812 }
813
814
815 /*
816   receive result of a request to open a rpc connection to a rpc pipe
817 */
818 NTSTATUS dcerpc_pipe_connect_b_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
819                                     struct dcerpc_pipe **p)
820 {
821         NTSTATUS status;
822         struct pipe_connect_state *s;
823         
824         status = composite_wait(c);
825         
826         if (NT_STATUS_IS_OK(status)) {
827                 s = talloc_get_type(c->private_data, struct pipe_connect_state);
828                 talloc_steal(mem_ctx, s->pipe);
829                 *p = s->pipe;
830         }
831         talloc_free(c);
832         return status;
833 }
834
835
836 /*
837   open a rpc connection to a rpc pipe, using the specified 
838   binding structure to determine the endpoint and options - sync version
839 */
840 NTSTATUS dcerpc_pipe_connect_b(TALLOC_CTX *parent_ctx,
841                                struct dcerpc_pipe **pp,
842                                struct dcerpc_binding *binding,
843                                const struct dcerpc_interface_table *table,
844                                struct cli_credentials *credentials,
845                                struct event_context *ev)
846 {
847         struct composite_context *c;
848         
849         c = dcerpc_pipe_connect_b_send(parent_ctx, binding, table,
850                                        credentials, ev);
851         return dcerpc_pipe_connect_b_recv(c, parent_ctx, pp);
852 }
853
854
855 struct pipe_conn_state {
856         struct dcerpc_pipe *pipe;
857 };
858
859
860 static void continue_pipe_connect_b(struct composite_context *ctx);
861
862
863 /*
864   Initiate rpc connection to a rpc pipe, using the specified string
865   binding to determine the endpoint and options.
866   The string is to be parsed to a binding structure first.
867 */
868 struct composite_context* dcerpc_pipe_connect_send(TALLOC_CTX *parent_ctx,
869                                                    const char *binding,
870                                                    const struct dcerpc_interface_table *table,
871                                                    struct cli_credentials *credentials,
872                                                    struct event_context *ev)
873 {
874         struct composite_context *c;
875         struct pipe_conn_state *s;
876         struct dcerpc_binding *b;
877         struct composite_context *pipe_conn_req;
878         struct event_context *new_ev = NULL;
879
880         if (ev == NULL) {
881                 new_ev = event_context_init(parent_ctx);
882                 if (new_ev == NULL) return NULL;
883                 ev = new_ev;
884         }
885
886         /* composite context allocation and setup */
887         c = composite_create(parent_ctx, ev);
888         if (c == NULL) {
889                 talloc_free(new_ev);
890                 return NULL;
891         }
892         talloc_steal(c, new_ev);
893
894         s = talloc_zero(c, struct pipe_conn_state);
895         if (composite_nomem(s, c)) return c;
896         c->private_data = s;
897
898         /* parse binding string to the structure */
899         c->status = dcerpc_parse_binding(c, binding, &b);
900         if (!NT_STATUS_IS_OK(c->status)) {
901                 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding));
902                 composite_error(c, c->status);
903                 return c;
904         }
905
906         DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(c, b)));
907
908         /* 
909            start connecting to a rpc pipe after binding structure
910            is established
911          */
912         pipe_conn_req = dcerpc_pipe_connect_b_send(c, b, table,
913                                                    credentials, ev);
914         composite_continue(c, pipe_conn_req, continue_pipe_connect_b, c);
915         return c;
916 }
917
918
919 /*
920   Stage 2 of pipe_connect: Receive result of actual pipe connect request
921   and say if we're done ok
922 */
923 static void continue_pipe_connect_b(struct composite_context *ctx)
924 {
925         struct composite_context *c = talloc_get_type(ctx->async.private_data,
926                                                       struct composite_context);
927         struct pipe_conn_state *s = talloc_get_type(c->private_data,
928                                                     struct pipe_conn_state);
929
930         c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->pipe);
931         talloc_steal(s, s->pipe);
932         if (!composite_is_ok(c)) return;
933
934         composite_done(c);
935 }
936
937
938 /*
939   Receive result of pipe connect (using binding string) request
940   and return connected pipe structure.
941 */
942 NTSTATUS dcerpc_pipe_connect_recv(struct composite_context *c,
943                                   TALLOC_CTX *mem_ctx,
944                                   struct dcerpc_pipe **pp)
945 {
946         NTSTATUS status;
947         struct pipe_conn_state *s;
948
949         status = composite_wait(c);
950         s = talloc_get_type(c->private_data, struct pipe_conn_state);
951         *pp = talloc_steal(mem_ctx, s->pipe);
952
953         talloc_free(c);
954         return status;
955 }
956
957
958 /*
959   Open a rpc connection to a rpc pipe, using the specified string
960   binding to determine the endpoint and options - sync version
961 */
962 NTSTATUS dcerpc_pipe_connect(TALLOC_CTX *parent_ctx, 
963                              struct dcerpc_pipe **pp, 
964                              const char *binding,
965                              const struct dcerpc_interface_table *table,
966                              struct cli_credentials *credentials,
967                              struct event_context *ev)
968 {
969         struct composite_context *c;
970         c = dcerpc_pipe_connect_send(parent_ctx, binding, 
971                                      table,
972                                      credentials, ev);
973         return dcerpc_pipe_connect_recv(c, parent_ctx, pp);
974 }
975
976
977 struct sec_conn_state {
978         struct dcerpc_pipe *pipe;
979         struct dcerpc_pipe *pipe2;
980         struct dcerpc_binding *binding;
981         struct smbcli_tree *tree;
982 };
983
984
985 static void continue_open_smb(struct composite_context *ctx);
986 static void continue_open_tcp(struct composite_context *ctx);
987 static void continue_open_pipe(struct composite_context *ctx);
988 static void continue_pipe_open(struct composite_context *c);
989
990
991 /*
992   Send request to create a secondary dcerpc connection from a primary
993   connection
994 */
995 struct composite_context* dcerpc_secondary_connection_send(struct dcerpc_pipe *p,
996                                                            struct dcerpc_binding *b)
997 {
998         struct composite_context *c;
999         struct sec_conn_state *s;
1000         struct composite_context *pipe_smb_req;
1001         struct composite_context *pipe_tcp_req;
1002         struct composite_context *pipe_ncalrpc_req;
1003         
1004         /* composite context allocation and setup */
1005         c = composite_create(p, p->conn->event_ctx);
1006         if (c == NULL) return NULL;
1007
1008         s = talloc_zero(c, struct sec_conn_state);
1009         if (composite_nomem(s, c)) return c;
1010         c->private_data = s;
1011
1012         s->pipe     = p;
1013         s->binding  = b;
1014
1015         /* initialise second dcerpc pipe based on primary pipe's event context */
1016         s->pipe2 = dcerpc_pipe_init(c, s->pipe->conn->event_ctx);
1017         if (composite_nomem(s->pipe2, c)) return c;
1018
1019         /* open second dcerpc pipe using the same transport as for primary pipe */
1020         switch (s->pipe->conn->transport.transport) {
1021         case NCACN_NP:
1022                 /* get smb tree of primary dcerpc pipe opened on smb */
1023                 s->tree = dcerpc_smb_tree(s->pipe->conn);
1024                 if (!s->tree) {
1025                         composite_error(c, NT_STATUS_INVALID_PARAMETER);
1026                         return c;
1027                 }
1028
1029                 pipe_smb_req = dcerpc_pipe_open_smb_send(s->pipe2->conn, s->tree,
1030                                                          s->binding->endpoint);
1031                 composite_continue(c, pipe_smb_req, continue_open_smb, c);
1032                 return c;
1033
1034         case NCACN_IP_TCP:
1035                 pipe_tcp_req = dcerpc_pipe_open_tcp_send(s->pipe2->conn,
1036                                                          s->binding->host,
1037                                                          s->binding->target_hostname,
1038                                                          atoi(s->binding->endpoint));
1039                 composite_continue(c, pipe_tcp_req, continue_open_tcp, c);
1040                 return c;
1041
1042         case NCALRPC:
1043                 pipe_ncalrpc_req = dcerpc_pipe_open_pipe_send(s->pipe2->conn,
1044                                                               s->binding->endpoint);
1045                 composite_continue(c, pipe_ncalrpc_req, continue_open_pipe, c);
1046                 return c;
1047
1048         default:
1049                 /* looks like a transport we don't support */
1050                 composite_error(c, NT_STATUS_NOT_SUPPORTED);
1051         }
1052
1053         return c;
1054 }
1055
1056
1057 /*
1058   Stage 2 of secondary_connection: Receive result of pipe open request on smb
1059 */
1060 static void continue_open_smb(struct composite_context *ctx)
1061 {
1062         struct composite_context *c = talloc_get_type(ctx->async.private_data,
1063                                                       struct composite_context);
1064         
1065         c->status = dcerpc_pipe_open_smb_recv(ctx);
1066         if (!composite_is_ok(c)) return;
1067
1068         continue_pipe_open(c);
1069 }
1070
1071
1072 /*
1073   Stage 2 of secondary_connection: Receive result of pipe open request on tcp/ip
1074 */
1075 static void continue_open_tcp(struct composite_context *ctx)
1076 {
1077         struct composite_context *c = talloc_get_type(ctx->async.private_data,
1078                                                       struct composite_context);
1079         
1080         c->status = dcerpc_pipe_open_tcp_recv(ctx);
1081         if (!composite_is_ok(c)) return;
1082
1083         continue_pipe_open(c);
1084 }
1085
1086
1087 /*
1088   Stage 2 of secondary_connection: Receive result of pipe open request on ncalrpc
1089 */
1090 static void continue_open_pipe(struct composite_context *ctx)
1091 {
1092         struct composite_context *c = talloc_get_type(ctx->async.private_data,
1093                                                       struct composite_context);
1094
1095         c->status = dcerpc_pipe_open_pipe_recv(ctx);
1096         if (!composite_is_ok(c)) return;
1097
1098         continue_pipe_open(c);
1099 }
1100
1101
1102 /*
1103   Stage 3 of secondary_connection: Get binding data and flags from primary pipe
1104   and say if we're done ok.
1105 */
1106 static void continue_pipe_open(struct composite_context *c)
1107 {
1108         struct sec_conn_state *s;
1109
1110         s = talloc_get_type(c->private_data, struct sec_conn_state);
1111
1112         s->pipe2->conn->flags = s->pipe->conn->flags;
1113         s->pipe2->binding     = s->binding;
1114         if (!talloc_reference(s->pipe2, s->binding)) {
1115                 composite_error(c, NT_STATUS_NO_MEMORY);
1116                 return;
1117         }
1118
1119         composite_done(c);
1120 }
1121
1122
1123 /*
1124   Receive result of secondary rpc connection request and return
1125   second dcerpc pipe.
1126 */
1127 NTSTATUS dcerpc_secondary_connection_recv(struct composite_context *c,
1128                                           struct dcerpc_pipe **p2)
1129 {
1130         NTSTATUS status = composite_wait(c);
1131         struct sec_conn_state *s;
1132
1133         s = talloc_get_type(c->private_data, struct sec_conn_state);
1134
1135         if (NT_STATUS_IS_OK(status)) {
1136                 *p2 = talloc_steal(s->pipe, s->pipe2);
1137         }
1138
1139         talloc_free(c);
1140         return status;
1141 }
1142
1143 /*
1144   Create a secondary dcerpc connection from a primary connection
1145   - sync version
1146
1147   If the primary is a SMB connection then the secondary connection
1148   will be on the same SMB connection, but using a new fnum
1149 */
1150 NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p,
1151                                      struct dcerpc_pipe **p2,
1152                                      struct dcerpc_binding *b)
1153 {
1154         struct composite_context *c;
1155         
1156         c = dcerpc_secondary_connection_send(p, b);
1157         return dcerpc_secondary_connection_recv(c, p2);
1158 }