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