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