fba0ae0c02456f88bd0759032547e2b1188be542
[kai/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            = 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   handle timeouts of a dcerpc connect
740 */
741 static void dcerpc_connect_timeout_handler(struct event_context *ev, struct timed_event *te, 
742                                            struct timeval t, void *private)
743 {
744         struct composite_context *c = talloc_get_type(private, struct composite_context);
745         composite_error(c, NT_STATUS_IO_TIMEOUT);
746 }
747
748 /*
749   start a request to open a rpc connection to a rpc pipe, using
750   specified binding structure to determine the endpoint and options
751 */
752 struct composite_context* dcerpc_pipe_connect_b_send(TALLOC_CTX *parent_ctx,
753                                                      struct dcerpc_binding *binding,
754                                                      const struct dcerpc_interface_table *table,
755                                                      struct cli_credentials *credentials,
756                                                      struct event_context *ev)
757 {
758         struct composite_context *c;
759         struct pipe_connect_state *s;
760         struct event_context *new_ev = NULL;
761
762         if (ev == NULL) {
763                 new_ev = event_context_init(parent_ctx);
764                 if (new_ev == NULL) return NULL;
765                 ev = new_ev;
766         }
767
768         /* composite context allocation and setup */
769         c = composite_create(parent_ctx, ev);
770         if (c == NULL) {
771                 talloc_free(new_ev);
772                 return NULL;
773         }
774         talloc_steal(c, new_ev);
775
776         s = talloc_zero(c, struct pipe_connect_state);
777         if (composite_nomem(s, c)) return c;
778         c->private_data = s;
779
780         /* initialise dcerpc pipe structure */
781         s->pipe = dcerpc_pipe_init(c, ev);
782         if (composite_nomem(s->pipe, c)) return c;
783
784         /* store parameters in state structure */
785         s->binding      = binding;
786         s->table        = table;
787         s->credentials  = credentials;
788
789         event_add_timed(c->event_ctx, c,
790                         timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
791                         dcerpc_connect_timeout_handler, c);
792         
793         switch (s->binding->transport) {
794         case NCACN_NP:
795         case NCACN_IP_TCP:
796         case NCALRPC:
797                 if (!s->binding->endpoint) {
798                         struct composite_context *binding_req;
799                         binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table,
800                                                                   s->pipe->conn->event_ctx);
801                         composite_continue(c, binding_req, continue_map_binding, c);
802                         return c;
803                 }
804
805         default:
806                 break;
807         }
808
809         continue_connect(c, s);
810         return c;
811 }
812
813
814 /*
815   receive result of a request to open a rpc connection to a rpc pipe
816 */
817 NTSTATUS dcerpc_pipe_connect_b_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
818                                     struct dcerpc_pipe **p)
819 {
820         NTSTATUS status;
821         struct pipe_connect_state *s;
822         
823         status = composite_wait(c);
824         
825         s = talloc_get_type(c->private_data, struct pipe_connect_state);
826         talloc_steal(mem_ctx, s->pipe);
827         *p = s->pipe;
828
829         talloc_free(c);
830         return status;
831 }
832
833
834 /*
835   open a rpc connection to a rpc pipe, using the specified 
836   binding structure to determine the endpoint and options - sync version
837 */
838 NTSTATUS dcerpc_pipe_connect_b(TALLOC_CTX *parent_ctx,
839                                struct dcerpc_pipe **pp,
840                                struct dcerpc_binding *binding,
841                                const struct dcerpc_interface_table *table,
842                                struct cli_credentials *credentials,
843                                struct event_context *ev)
844 {
845         struct composite_context *c;
846         
847         c = dcerpc_pipe_connect_b_send(parent_ctx, binding, table,
848                                        credentials, ev);
849         return dcerpc_pipe_connect_b_recv(c, parent_ctx, pp);
850 }
851
852
853 struct pipe_conn_state {
854         struct dcerpc_pipe *pipe;
855 };
856
857
858 static void continue_pipe_connect_b(struct composite_context *ctx);
859
860
861 /*
862   Initiate rpc connection to a rpc pipe, using the specified string
863   binding to determine the endpoint and options.
864   The string is to be parsed to a binding structure first.
865 */
866 struct composite_context* dcerpc_pipe_connect_send(TALLOC_CTX *parent_ctx,
867                                                    struct dcerpc_pipe **pp,
868                                                    const char *binding,
869                                                    const struct dcerpc_interface_table *table,
870                                                    struct cli_credentials *credentials,
871                                                    struct event_context *ev)
872 {
873         struct composite_context *c;
874         struct pipe_conn_state *s;
875         struct dcerpc_binding *b;
876         struct composite_context *pipe_conn_req;
877         struct event_context *new_ev = NULL;
878
879         if (ev == NULL) {
880                 new_ev = event_context_init(parent_ctx);
881                 if (new_ev == NULL) return NULL;
882                 ev = new_ev;
883         }
884
885         /* composite context allocation and setup */
886         c = composite_create(parent_ctx, ev);
887         if (c == NULL) {
888                 talloc_free(new_ev);
889                 return NULL;
890         }
891         talloc_steal(c, new_ev);
892
893         s = talloc_zero(c, struct pipe_conn_state);
894         if (composite_nomem(s, c)) return c;
895         c->private_data = s;
896
897         /* parse binding string to the structure */
898         c->status = dcerpc_parse_binding(c, binding, &b);
899         if (!NT_STATUS_IS_OK(c->status)) {
900                 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding));
901                 composite_error(c, c->status);
902                 return c;
903         }
904
905         DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(c, b)));
906
907         /* 
908            start connecting to a rpc pipe after binding structure
909            is established
910          */
911         pipe_conn_req = dcerpc_pipe_connect_b_send(c, b, table,
912                                                    credentials, ev);
913         composite_continue(c, pipe_conn_req, continue_pipe_connect_b, c);
914         return c;
915 }
916
917
918 /*
919   Stage 2 of pipe_connect: Receive result of actual pipe connect request
920   and say if we're done ok
921 */
922 static void continue_pipe_connect_b(struct composite_context *ctx)
923 {
924         struct composite_context *c = talloc_get_type(ctx->async.private_data,
925                                                       struct composite_context);
926         struct pipe_conn_state *s = talloc_get_type(c->private_data,
927                                                     struct pipe_conn_state);
928
929         c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->pipe);
930         talloc_steal(s, s->pipe);
931         if (!composite_is_ok(c)) return;
932
933         composite_done(c);
934 }
935
936
937 /*
938   Receive result of pipe connect (using binding string) request
939   and return connected pipe structure.
940 */
941 NTSTATUS dcerpc_pipe_connect_recv(struct composite_context *c,
942                                   TALLOC_CTX *mem_ctx,
943                                   struct dcerpc_pipe **pp)
944 {
945         NTSTATUS status;
946         struct pipe_conn_state *s;
947
948         status = composite_wait(c);
949         s = talloc_get_type(c->private_data, struct pipe_conn_state);
950         *pp = talloc_steal(mem_ctx, s->pipe);
951
952         talloc_free(c);
953         return status;
954 }
955
956
957 /*
958   Open a rpc connection to a rpc pipe, using the specified string
959   binding to determine the endpoint and options - sync version
960 */
961 NTSTATUS dcerpc_pipe_connect(TALLOC_CTX *parent_ctx, 
962                              struct dcerpc_pipe **pp, 
963                              const char *binding,
964                              const struct dcerpc_interface_table *table,
965                              struct cli_credentials *credentials,
966                              struct event_context *ev)
967 {
968         struct composite_context *c;
969         c = dcerpc_pipe_connect_send(parent_ctx, pp, binding, table,
970                                      credentials, ev);
971         return dcerpc_pipe_connect_recv(c, parent_ctx, pp);
972 }
973
974
975 struct sec_conn_state {
976         struct dcerpc_pipe *pipe;
977         struct dcerpc_pipe *pipe2;
978         struct dcerpc_binding *binding;
979         struct smbcli_tree *tree;
980 };
981
982
983 static void continue_open_smb(struct composite_context *ctx);
984 static void continue_open_tcp(struct composite_context *ctx);
985 static void continue_open_pipe(struct composite_context *ctx);
986 static void continue_pipe_open(struct composite_context *c);
987
988
989 /*
990   Send request to create a secondary dcerpc connection from a primary
991   connection
992 */
993 struct composite_context* dcerpc_secondary_connection_send(struct dcerpc_pipe *p,
994                                                            struct dcerpc_binding *b)
995 {
996         struct composite_context *c;
997         struct sec_conn_state *s;
998         struct composite_context *pipe_smb_req;
999         struct composite_context *pipe_tcp_req;
1000         struct composite_context *pipe_ncalrpc_req;
1001         
1002         /* composite context allocation and setup */
1003         c = composite_create(p, p->conn->event_ctx);
1004         if (c == NULL) return NULL;
1005
1006         s = talloc_zero(c, struct sec_conn_state);
1007         if (composite_nomem(s, c)) return c;
1008         c->private_data = s;
1009
1010         s->pipe     = p;
1011         s->binding  = b;
1012
1013         /* initialise second dcerpc pipe based on primary pipe's event context */
1014         s->pipe2 = dcerpc_pipe_init(c, s->pipe->conn->event_ctx);
1015         if (composite_nomem(s->pipe2, c)) return c;
1016
1017         /* open second dcerpc pipe using the same transport as for primary pipe */
1018         switch (s->pipe->conn->transport.transport) {
1019         case NCACN_NP:
1020                 /* get smb tree of primary dcerpc pipe opened on smb */
1021                 s->tree = dcerpc_smb_tree(s->pipe->conn);
1022                 if (!s->tree) {
1023                         composite_error(c, NT_STATUS_INVALID_PARAMETER);
1024                         return c;
1025                 }
1026
1027                 pipe_smb_req = dcerpc_pipe_open_smb_send(s->pipe2->conn, s->tree,
1028                                                          s->binding->endpoint);
1029                 composite_continue(c, pipe_smb_req, continue_open_smb, c);
1030                 return c;
1031
1032         case NCACN_IP_TCP:
1033                 pipe_tcp_req = dcerpc_pipe_open_tcp_send(s->pipe2->conn,
1034                                                          s->binding->host,
1035                                                          atoi(s->binding->endpoint));
1036                 composite_continue(c, pipe_tcp_req, continue_open_tcp, c);
1037                 return c;
1038
1039         case NCALRPC:
1040                 pipe_ncalrpc_req = dcerpc_pipe_open_pipe_send(s->pipe2->conn,
1041                                                               s->binding->endpoint);
1042                 composite_continue(c, pipe_ncalrpc_req, continue_open_pipe, c);
1043                 return c;
1044
1045         default:
1046                 /* looks like a transport we don't support */
1047                 composite_error(c, NT_STATUS_NOT_SUPPORTED);
1048         }
1049
1050         return c;
1051 }
1052
1053
1054 /*
1055   Stage 2 of secondary_connection: Receive result of pipe open request on smb
1056 */
1057 static void continue_open_smb(struct composite_context *ctx)
1058 {
1059         struct composite_context *c = talloc_get_type(ctx->async.private_data,
1060                                                       struct composite_context);
1061         
1062         c->status = dcerpc_pipe_open_smb_recv(ctx);
1063         if (!composite_is_ok(c)) return;
1064
1065         continue_pipe_open(c);
1066 }
1067
1068
1069 /*
1070   Stage 2 of secondary_connection: Receive result of pipe open request on tcp/ip
1071 */
1072 static void continue_open_tcp(struct composite_context *ctx)
1073 {
1074         struct composite_context *c = talloc_get_type(ctx->async.private_data,
1075                                                       struct composite_context);
1076         
1077         c->status = dcerpc_pipe_open_tcp_recv(ctx);
1078         if (!composite_is_ok(c)) return;
1079
1080         continue_pipe_open(c);
1081 }
1082
1083
1084 /*
1085   Stage 2 of secondary_connection: Receive result of pipe open request on ncalrpc
1086 */
1087 static void continue_open_pipe(struct composite_context *ctx)
1088 {
1089         struct composite_context *c = talloc_get_type(ctx->async.private_data,
1090                                                       struct composite_context);
1091
1092         c->status = dcerpc_pipe_open_pipe_recv(ctx);
1093         if (!composite_is_ok(c)) return;
1094
1095         continue_pipe_open(c);
1096 }
1097
1098
1099 /*
1100   Stage 3 of secondary_connection: Get binding data and flags from primary pipe
1101   and say if we're done ok.
1102 */
1103 static void continue_pipe_open(struct composite_context *c)
1104 {
1105         struct sec_conn_state *s;
1106
1107         s = talloc_get_type(c->private_data, struct sec_conn_state);
1108
1109         s->pipe2->conn->flags = s->pipe->conn->flags;
1110         s->pipe2->binding     = s->binding;
1111         if (!talloc_reference(s->pipe2, s->binding)) {
1112                 composite_error(c, NT_STATUS_NO_MEMORY);
1113                 return;
1114         }
1115
1116         composite_done(c);
1117 }
1118
1119
1120 /*
1121   Receive result of secondary rpc connection request and return
1122   second dcerpc pipe.
1123 */
1124 NTSTATUS dcerpc_secondary_connection_recv(struct composite_context *c,
1125                                           struct dcerpc_pipe **p2)
1126 {
1127         NTSTATUS status = composite_wait(c);
1128         struct sec_conn_state *s;
1129
1130         s = talloc_get_type(c->private_data, struct sec_conn_state);
1131
1132         if (NT_STATUS_IS_OK(status)) {
1133                 *p2 = talloc_steal(s->pipe, s->pipe2);
1134         }
1135
1136         talloc_free(c);
1137         return status;
1138 }
1139
1140 /*
1141   Create a secondary dcerpc connection from a primary connection
1142   - sync version
1143
1144   If the primary is a SMB connection then the secondary connection
1145   will be on the same SMB connection, but using a new fnum
1146 */
1147 NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p,
1148                                      struct dcerpc_pipe **p2,
1149                                      struct dcerpc_binding *b)
1150 {
1151         struct composite_context *c;
1152         
1153         c = dcerpc_secondary_connection_send(p, b);
1154         return dcerpc_secondary_connection_recv(c, p2);
1155 }