r17990: added timeout checking on dcerpc connection establishment. This should
[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            = 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         DEBUG(0,("DCERPC CONNECT TIMEOUT\n"));
746         composite_error(c, NT_STATUS_IO_TIMEOUT);
747         composite_done(c);
748 }
749
750 /*
751   start a request to open a rpc connection to a rpc pipe, using
752   specified binding structure to determine the endpoint and options
753 */
754 struct composite_context* dcerpc_pipe_connect_b_send(TALLOC_CTX *parent_ctx,
755                                                      struct dcerpc_binding *binding,
756                                                      const struct dcerpc_interface_table *table,
757                                                      struct cli_credentials *credentials,
758                                                      struct event_context *ev)
759 {
760         struct composite_context *c;
761         struct pipe_connect_state *s;
762         struct event_context *new_ev = NULL;
763
764         if (ev == NULL) {
765                 new_ev = event_context_init(parent_ctx);
766                 if (new_ev == NULL) return NULL;
767                 ev = new_ev;
768         }
769
770         /* composite context allocation and setup */
771         c = composite_create(parent_ctx, ev);
772         if (c == NULL) {
773                 talloc_free(new_ev);
774                 return NULL;
775         }
776         talloc_steal(c, new_ev);
777
778         s = talloc_zero(c, struct pipe_connect_state);
779         if (composite_nomem(s, c)) return c;
780         c->private_data = s;
781
782         /* initialise dcerpc pipe structure */
783         s->pipe = dcerpc_pipe_init(c, ev);
784         if (composite_nomem(s->pipe, c)) return c;
785
786         /* store parameters in state structure */
787         s->binding      = binding;
788         s->table        = table;
789         s->credentials  = credentials;
790
791         event_add_timed(c->event_ctx, c,
792                         timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
793                         dcerpc_connect_timeout_handler, c);
794         
795         switch (s->binding->transport) {
796         case NCACN_NP:
797         case NCACN_IP_TCP:
798         case NCALRPC:
799                 if (!s->binding->endpoint) {
800                         struct composite_context *binding_req;
801                         binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table,
802                                                                   s->pipe->conn->event_ctx);
803                         composite_continue(c, binding_req, continue_map_binding, c);
804                         return c;
805                 }
806
807         default:
808                 break;
809         }
810
811         continue_connect(c, s);
812         return c;
813 }
814
815
816 /*
817   receive result of a request to open a rpc connection to a rpc pipe
818 */
819 NTSTATUS dcerpc_pipe_connect_b_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
820                                     struct dcerpc_pipe **p)
821 {
822         NTSTATUS status;
823         struct pipe_connect_state *s;
824         
825         status = composite_wait(c);
826         
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                                                    struct dcerpc_pipe **pp,
870                                                    const char *binding,
871                                                    const struct dcerpc_interface_table *table,
872                                                    struct cli_credentials *credentials,
873                                                    struct event_context *ev)
874 {
875         struct composite_context *c;
876         struct pipe_conn_state *s;
877         struct dcerpc_binding *b;
878         struct composite_context *pipe_conn_req;
879         struct event_context *new_ev = NULL;
880
881         if (ev == NULL) {
882                 new_ev = event_context_init(parent_ctx);
883                 if (new_ev == NULL) return NULL;
884                 ev = new_ev;
885         }
886
887         /* composite context allocation and setup */
888         c = composite_create(parent_ctx, ev);
889         if (c == NULL) {
890                 talloc_free(new_ev);
891                 return NULL;
892         }
893         talloc_steal(c, new_ev);
894
895         s = talloc_zero(c, struct pipe_conn_state);
896         if (composite_nomem(s, c)) return c;
897         c->private_data = s;
898
899         /* parse binding string to the structure */
900         c->status = dcerpc_parse_binding(c, binding, &b);
901         if (!NT_STATUS_IS_OK(c->status)) {
902                 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding));
903                 composite_error(c, c->status);
904                 return c;
905         }
906
907         DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(c, b)));
908
909         /* 
910            start connecting to a rpc pipe after binding structure
911            is established
912          */
913         pipe_conn_req = dcerpc_pipe_connect_b_send(c, b, table,
914                                                    credentials, ev);
915         composite_continue(c, pipe_conn_req, continue_pipe_connect_b, c);
916         return c;
917 }
918
919
920 /*
921   Stage 2 of pipe_connect: Receive result of actual pipe connect request
922   and say if we're done ok
923 */
924 static void continue_pipe_connect_b(struct composite_context *ctx)
925 {
926         struct composite_context *c = talloc_get_type(ctx->async.private_data,
927                                                       struct composite_context);
928         struct pipe_conn_state *s = talloc_get_type(c->private_data,
929                                                     struct pipe_conn_state);
930
931         c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->pipe);
932         talloc_steal(s, s->pipe);
933         if (!composite_is_ok(c)) return;
934
935         composite_done(c);
936 }
937
938
939 /*
940   Receive result of pipe connect (using binding string) request
941   and return connected pipe structure.
942 */
943 NTSTATUS dcerpc_pipe_connect_recv(struct composite_context *c,
944                                   TALLOC_CTX *mem_ctx,
945                                   struct dcerpc_pipe **pp)
946 {
947         NTSTATUS status;
948         struct pipe_conn_state *s;
949
950         status = composite_wait(c);
951         s = talloc_get_type(c->private_data, struct pipe_conn_state);
952         *pp = talloc_steal(mem_ctx, s->pipe);
953
954         talloc_free(c);
955         return status;
956 }
957
958
959 /*
960   Open a rpc connection to a rpc pipe, using the specified string
961   binding to determine the endpoint and options - sync version
962 */
963 NTSTATUS dcerpc_pipe_connect(TALLOC_CTX *parent_ctx, 
964                              struct dcerpc_pipe **pp, 
965                              const char *binding,
966                              const struct dcerpc_interface_table *table,
967                              struct cli_credentials *credentials,
968                              struct event_context *ev)
969 {
970         struct composite_context *c;
971         c = dcerpc_pipe_connect_send(parent_ctx, pp, binding, 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                                                          atoi(s->binding->endpoint));
1038                 composite_continue(c, pipe_tcp_req, continue_open_tcp, c);
1039                 return c;
1040
1041         case NCALRPC:
1042                 pipe_ncalrpc_req = dcerpc_pipe_open_pipe_send(s->pipe2->conn,
1043                                                               s->binding->endpoint);
1044                 composite_continue(c, pipe_ncalrpc_req, continue_open_pipe, c);
1045                 return c;
1046
1047         default:
1048                 /* looks like a transport we don't support */
1049                 composite_error(c, NT_STATUS_NOT_SUPPORTED);
1050         }
1051
1052         return c;
1053 }
1054
1055
1056 /*
1057   Stage 2 of secondary_connection: Receive result of pipe open request on smb
1058 */
1059 static void continue_open_smb(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_smb_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 tcp/ip
1073 */
1074 static void continue_open_tcp(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_tcp_recv(ctx);
1080         if (!composite_is_ok(c)) return;
1081
1082         continue_pipe_open(c);
1083 }
1084
1085
1086 /*
1087   Stage 2 of secondary_connection: Receive result of pipe open request on ncalrpc
1088 */
1089 static void continue_open_pipe(struct composite_context *ctx)
1090 {
1091         struct composite_context *c = talloc_get_type(ctx->async.private_data,
1092                                                       struct composite_context);
1093
1094         c->status = dcerpc_pipe_open_pipe_recv(ctx);
1095         if (!composite_is_ok(c)) return;
1096
1097         continue_pipe_open(c);
1098 }
1099
1100
1101 /*
1102   Stage 3 of secondary_connection: Get binding data and flags from primary pipe
1103   and say if we're done ok.
1104 */
1105 static void continue_pipe_open(struct composite_context *c)
1106 {
1107         struct sec_conn_state *s;
1108
1109         s = talloc_get_type(c->private_data, struct sec_conn_state);
1110
1111         s->pipe2->conn->flags = s->pipe->conn->flags;
1112         s->pipe2->binding     = s->binding;
1113         if (!talloc_reference(s->pipe2, s->binding)) {
1114                 composite_error(c, NT_STATUS_NO_MEMORY);
1115                 return;
1116         }
1117
1118         composite_done(c);
1119 }
1120
1121
1122 /*
1123   Receive result of secondary rpc connection request and return
1124   second dcerpc pipe.
1125 */
1126 NTSTATUS dcerpc_secondary_connection_recv(struct composite_context *c,
1127                                           struct dcerpc_pipe **p2)
1128 {
1129         NTSTATUS status = composite_wait(c);
1130         struct sec_conn_state *s;
1131
1132         s = talloc_get_type(c->private_data, struct sec_conn_state);
1133
1134         if (NT_STATUS_IS_OK(status)) {
1135                 *p2 = talloc_steal(s->pipe, s->pipe2);
1136         }
1137
1138         talloc_free(c);
1139         return status;
1140 }
1141
1142 /*
1143   Create a secondary dcerpc connection from a primary connection
1144   - sync version
1145
1146   If the primary is a SMB connection then the secondary connection
1147   will be on the same SMB connection, but using a new fnum
1148 */
1149 NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p,
1150                                      struct dcerpc_pipe **p2,
1151                                      struct dcerpc_binding *b)
1152 {
1153         struct composite_context *c;
1154         
1155         c = dcerpc_secondary_connection_send(p, b);
1156         return dcerpc_secondary_connection_recv(c, p2);
1157 }