Remove another use of global_loadparm.
[npower/samba.git] / source4 / librpc / rpc / dcerpc_connect.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    dcerpc connect functions
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Jelmer Vernooij 2004
8    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2007
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 3 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, see <http://www.gnu.org/licenses/>.
23 */
24
25
26 #include "includes.h"
27 #include "libcli/composite/composite.h"
28 #include "libcli/smb_composite/smb_composite.h"
29 #include "lib/events/events.h"
30 #include "libcli/smb2/smb2.h"
31 #include "libcli/smb2/smb2_calls.h"
32 #include "librpc/rpc/dcerpc.h"
33 #include "librpc/rpc/dcerpc_proto.h"
34 #include "auth/credentials/credentials.h"
35 #include "param/param.h"
36 #include "libcli/resolve/resolve.h"
37
38
39 struct pipe_np_smb_state {
40         struct smb_composite_connect conn;
41         struct smbcli_tree *tree;
42         struct dcerpc_pipe_connect io;
43 };
44
45
46 /*
47   Stage 3 of ncacn_np_smb: Named pipe opened (or not)
48 */
49 static void continue_pipe_open_smb(struct composite_context *ctx)
50 {
51         struct composite_context *c = talloc_get_type(ctx->async.private_data,
52                                                       struct composite_context);
53
54         /* receive result of named pipe open request on smb */
55         c->status = dcerpc_pipe_open_smb_recv(ctx);
56         if (!composite_is_ok(c)) return;
57
58         composite_done(c);
59 }
60
61
62 /*
63   Stage 2 of ncacn_np_smb: Open a named pipe after successful smb connection
64 */
65 static void continue_smb_connect(struct composite_context *ctx)
66 {
67         struct composite_context *open_ctx;
68         struct composite_context *c = talloc_get_type(ctx->async.private_data,
69                                                       struct composite_context);
70         struct pipe_np_smb_state *s = talloc_get_type(c->private_data,
71                                                       struct pipe_np_smb_state);
72         
73         /* receive result of smb connect request */
74         c->status = smb_composite_connect_recv(ctx, c);
75         if (!composite_is_ok(c)) return;
76
77         /* prepare named pipe open parameters */
78         s->tree         = s->conn.out.tree;
79         s->io.pipe_name = s->io.binding->endpoint;
80
81         /* send named pipe open request */
82         open_ctx = dcerpc_pipe_open_smb_send(s->io.pipe, s->tree, s->io.pipe_name);
83         if (composite_nomem(open_ctx, c)) return;
84
85         composite_continue(c, open_ctx, continue_pipe_open_smb, c);
86 }
87
88
89 /*
90   Initiate async open of a rpc connection to a rpc pipe on SMB using
91   the binding structure to determine the endpoint and options
92 */
93 static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb_send(TALLOC_CTX *mem_ctx, struct dcerpc_pipe_connect *io, struct loadparm_context *lp_ctx)
94 {
95         struct composite_context *c;
96         struct pipe_np_smb_state *s;
97         struct composite_context *conn_req;
98         struct smb_composite_connect *conn;
99
100         /* composite context allocation and setup */
101         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
102         if (c == NULL) return NULL;
103
104         s = talloc_zero(c, struct pipe_np_smb_state);
105         if (composite_nomem(s, c)) return c;
106         c->private_data = s;
107
108         s->io  = *io;
109         conn   = &s->conn;
110
111         /* prepare smb connection parameters: we're connecting to IPC$ share on
112            remote rpc server */
113         conn->in.dest_host              = s->io.binding->host;
114         conn->in.dest_ports                  = lp_smb_ports(lp_ctx);
115         if (s->io.binding->target_hostname == NULL)
116                 conn->in.called_name = "*SMBSERVER"; /* FIXME: This is invalid */
117         else
118                 conn->in.called_name            = s->io.binding->target_hostname;
119         conn->in.service                = "IPC$";
120         conn->in.service_type           = NULL;
121         conn->in.workgroup              = lp_workgroup(lp_ctx);
122
123         conn->in.iconv_convenience = lp_iconv_convenience(lp_ctx);
124
125         lp_smbcli_options(lp_ctx, &conn->in.options);
126         lp_smbcli_session_options(lp_ctx, &conn->in.session_options);
127
128         /*
129          * provide proper credentials - user supplied, but allow a
130          * fallback to anonymous if this is an schannel connection
131          * (might be NT4 not allowing machine logins at session
132          * setup).
133          */
134         s->conn.in.credentials = s->io.creds;
135         if (s->io.binding->flags & DCERPC_SCHANNEL) {
136                 conn->in.fallback_to_anonymous  = true;
137         } else {
138                 conn->in.fallback_to_anonymous  = false;
139         }
140
141         /* send smb connect request */
142         conn_req = smb_composite_connect_send(conn, s->io.pipe->conn, 
143                                               s->io.resolve_ctx,
144                                               s->io.pipe->conn->event_ctx);
145         if (composite_nomem(conn_req, c)) return c;
146
147         composite_continue(c, conn_req, continue_smb_connect, c);
148         return c;
149 }
150
151
152 /*
153   Receive result of a rpc connection to a rpc pipe on SMB
154 */
155 static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb_recv(struct composite_context *c)
156 {
157         NTSTATUS status = composite_wait(c);
158
159         talloc_free(c);
160         return status;
161 }
162
163
164 struct pipe_np_smb2_state {
165         struct smb2_tree *tree;
166         struct dcerpc_pipe_connect io;
167 };
168
169
170 /*
171   Stage 3 of ncacn_np_smb: Named pipe opened (or not)
172 */
173 static void continue_pipe_open_smb2(struct composite_context *ctx)
174 {
175         struct composite_context *c = talloc_get_type(ctx->async.private_data,
176                                                       struct composite_context);
177
178         /* receive result of named pipe open request on smb2 */
179         c->status = dcerpc_pipe_open_smb2_recv(ctx);
180         if (!composite_is_ok(c)) return;
181
182         composite_done(c);
183 }
184
185
186 /*
187   Stage 2 of ncacn_np_smb2: Open a named pipe after successful smb2 connection
188 */
189 static void continue_smb2_connect(struct composite_context *ctx)
190 {
191         struct composite_context *open_req;
192         struct composite_context *c = talloc_get_type(ctx->async.private_data,
193                                                       struct composite_context);
194         struct pipe_np_smb2_state *s = talloc_get_type(c->private_data,
195                                                        struct pipe_np_smb2_state);
196
197         /* receive result of smb2 connect request */
198         c->status = smb2_connect_recv(ctx, c, &s->tree);
199         if (!composite_is_ok(c)) return;
200
201         /* prepare named pipe open parameters */
202         s->io.pipe_name = s->io.binding->endpoint;
203
204         /* send named pipe open request */
205         open_req = dcerpc_pipe_open_smb2_send(s->io.pipe, s->tree, s->io.pipe_name);
206         if (composite_nomem(open_req, c)) return;
207
208         composite_continue(c, open_req, continue_pipe_open_smb2, c);
209 }
210
211
212 /* 
213    Initiate async open of a rpc connection request on SMB2 using
214    the binding structure to determine the endpoint and options
215 */
216 static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send(
217                                         TALLOC_CTX *mem_ctx,
218                                         struct dcerpc_pipe_connect *io,
219                                         struct loadparm_context *lp_ctx)
220 {
221         struct composite_context *c;
222         struct pipe_np_smb2_state *s;
223         struct composite_context *conn_req;
224         struct smbcli_options options;
225
226         /* composite context allocation and setup */
227         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
228         if (c == NULL) return NULL;
229
230         s = talloc_zero(c, struct pipe_np_smb2_state);
231         if (composite_nomem(s, c)) return c;
232         c->private_data = s;
233
234         s->io = *io;
235
236         /*
237          * provide proper credentials - user supplied or anonymous in case this is
238          * schannel connection
239          */
240         if (s->io.binding->flags & DCERPC_SCHANNEL) {
241                 s->io.creds = cli_credentials_init(mem_ctx);
242                 if (composite_nomem(s->io.creds, c)) return c;
243
244                 cli_credentials_guess(s->io.creds, lp_ctx);
245         }
246
247         lp_smbcli_options(lp_ctx, &options);
248
249         /* send smb2 connect request */
250         conn_req = smb2_connect_send(mem_ctx, s->io.binding->host, 
251                         lp_parm_string_list(mem_ctx, lp_ctx, NULL, "smb2", "ports", NULL),
252                                         "IPC$", 
253                                      s->io.resolve_ctx,
254                                      s->io.creds,
255                                      c->event_ctx,
256                                      &options);
257         composite_continue(c, conn_req, continue_smb2_connect, c);
258         return c;
259 }
260
261
262 /*
263   Receive result of a rpc connection to a rpc pipe on SMB2
264 */
265 static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb2_recv(struct composite_context *c)
266 {
267         NTSTATUS status = composite_wait(c);
268         
269         talloc_free(c);
270         return status;
271 }
272
273
274 struct pipe_ip_tcp_state {
275         struct dcerpc_pipe_connect io;
276         const char *host;
277         const char *target_hostname;
278         uint32_t port;
279 };
280
281
282 /*
283   Stage 2 of ncacn_ip_tcp: rpc pipe opened (or not)
284 */
285 static void continue_pipe_open_ncacn_ip_tcp(struct composite_context *ctx)
286 {
287         struct composite_context *c = talloc_get_type(ctx->async.private_data,
288                                                       struct composite_context);
289
290         /* receive result of named pipe open request on tcp/ip */
291         c->status = dcerpc_pipe_open_tcp_recv(ctx);
292         if (!composite_is_ok(c)) return;
293
294         composite_done(c);
295 }
296
297
298 /*
299   Initiate async open of a rpc connection to a rpc pipe on TCP/IP using
300   the binding structure to determine the endpoint and options
301 */
302 static struct composite_context* dcerpc_pipe_connect_ncacn_ip_tcp_send(TALLOC_CTX *mem_ctx,
303                                                                        struct dcerpc_pipe_connect *io)
304 {
305         struct composite_context *c;
306         struct pipe_ip_tcp_state *s;
307         struct composite_context *pipe_req;
308
309         /* composite context allocation and setup */
310         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
311         if (c == NULL) return NULL;
312
313         s = talloc_zero(c, struct pipe_ip_tcp_state);
314         if (composite_nomem(s, c)) return c;
315         c->private_data = s;
316
317         /* store input parameters in state structure */
318         s->io               = *io;
319         s->host             = talloc_reference(c, io->binding->host);
320         s->target_hostname  = talloc_reference(c, io->binding->target_hostname);
321                              /* port number is a binding endpoint here */
322         s->port             = atoi(io->binding->endpoint);   
323
324         /* send pipe open request on tcp/ip */
325         pipe_req = dcerpc_pipe_open_tcp_send(s->io.pipe->conn, s->host, s->target_hostname, 
326                                              s->port, io->resolve_ctx);
327         composite_continue(c, pipe_req, continue_pipe_open_ncacn_ip_tcp, c);
328         return c;
329 }
330
331
332 /*
333   Receive result of a rpc connection to a rpc pipe on TCP/IP
334 */
335 static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp_recv(struct composite_context *c)
336 {
337         NTSTATUS status = composite_wait(c);
338         
339         talloc_free(c);
340         return status;
341 }
342
343
344 struct pipe_unix_state {
345         struct dcerpc_pipe_connect io;
346         const char *path;
347 };
348
349
350 /*
351   Stage 2 of ncacn_unix: rpc pipe opened (or not)
352 */
353 static void continue_pipe_open_ncacn_unix_stream(struct composite_context *ctx)
354 {
355         struct composite_context *c = talloc_get_type(ctx->async.private_data,
356                                                       struct composite_context);
357
358         /* receive result of pipe open request on unix socket */
359         c->status = dcerpc_pipe_open_unix_stream_recv(ctx);
360         if (!composite_is_ok(c)) return;
361
362         composite_done(c);
363 }
364
365
366 /*
367   Initiate async open of a rpc connection to a rpc pipe on unix socket using
368   the binding structure to determine the endpoint and options
369 */
370 static struct composite_context* dcerpc_pipe_connect_ncacn_unix_stream_send(TALLOC_CTX *mem_ctx,
371                                                                             struct dcerpc_pipe_connect *io)
372 {
373         struct composite_context *c;
374         struct pipe_unix_state *s;
375         struct composite_context *pipe_req;
376
377         /* composite context allocation and setup */
378         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
379         if (c == NULL) return NULL;
380
381         s = talloc_zero(c, struct pipe_unix_state);
382         if (composite_nomem(s, c)) return c;
383         c->private_data = s;
384
385         /* prepare pipe open parameters and store them in state structure
386            also, verify whether biding endpoint is not null */
387         s->io = *io;
388         
389         if (!io->binding->endpoint) {
390                 DEBUG(0, ("Path to unix socket not specified\n"));
391                 composite_error(c, NT_STATUS_INVALID_PARAMETER);
392                 return c;
393         }
394
395         s->path  = talloc_strdup(c, io->binding->endpoint);  /* path is a binding endpoint here */
396         if (composite_nomem(s->path, c)) return c;
397
398         /* send pipe open request on unix socket */
399         pipe_req = dcerpc_pipe_open_unix_stream_send(s->io.pipe->conn, s->path);
400         composite_continue(c, pipe_req, continue_pipe_open_ncacn_unix_stream, c);
401         return c;
402 }
403
404
405 /*
406   Receive result of a rpc connection to a pipe on unix socket
407 */
408 static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream_recv(struct composite_context *c)
409 {
410         NTSTATUS status = composite_wait(c);
411
412         talloc_free(c);
413         return status;
414 }
415
416
417 struct pipe_ncalrpc_state {
418         struct dcerpc_pipe_connect io;
419 };
420
421 static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c);
422
423 /*
424   Stage 2 of ncalrpc: rpc pipe opened (or not)
425 */
426 static void continue_pipe_open_ncalrpc(struct composite_context *ctx)
427 {
428         struct composite_context *c = talloc_get_type(ctx->async.private_data,
429                                                       struct composite_context);
430
431         /* receive result of pipe open request on ncalrpc */
432         c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx);
433         if (!composite_is_ok(c)) return;
434
435         composite_done(c);
436 }
437
438
439 /* 
440    Initiate async open of a rpc connection request on NCALRPC using
441    the binding structure to determine the endpoint and options
442 */
443 static struct composite_context* dcerpc_pipe_connect_ncalrpc_send(TALLOC_CTX *mem_ctx,
444                                                                   struct dcerpc_pipe_connect *io, struct loadparm_context *lp_ctx)
445 {
446         struct composite_context *c;
447         struct pipe_ncalrpc_state *s;
448         struct composite_context *pipe_req;
449
450         /* composite context allocation and setup */
451         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
452         if (c == NULL) return NULL;
453
454         s = talloc_zero(c, struct pipe_ncalrpc_state);
455         if (composite_nomem(s, c)) return c;
456         c->private_data = s;
457         
458         /* store input parameters in state structure */
459         s->io  = *io;
460
461         /* send pipe open request */
462         pipe_req = dcerpc_pipe_open_pipe_send(s->io.pipe->conn, lp_ncalrpc_dir(lp_ctx), 
463                                               s->io.binding->endpoint);
464         composite_continue(c, pipe_req, continue_pipe_open_ncalrpc, c);
465         return c;
466 }
467
468
469 /*
470   Receive result of a rpc connection to a rpc pipe on NCALRPC
471 */
472 static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c)
473 {
474         NTSTATUS status = composite_wait(c);
475         
476         talloc_free(c);
477         return status;
478 }
479
480
481 struct pipe_connect_state {
482         struct dcerpc_pipe *pipe;
483         struct dcerpc_binding *binding;
484         const struct ndr_interface_table *table;
485         struct cli_credentials *credentials;
486         struct loadparm_context *lp_ctx;
487 };
488
489
490 static void continue_map_binding(struct composite_context *ctx);
491 static void continue_connect(struct composite_context *c, struct pipe_connect_state *s);
492 static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx);
493 static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx);
494 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx);
495 static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx);
496 static void continue_pipe_connect_ncalrpc(struct composite_context *ctx);
497 static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s);
498 static void continue_pipe_auth(struct composite_context *ctx);
499
500
501 /*
502   Stage 2 of pipe_connect_b: Receive result of endpoint mapping
503 */
504 static void continue_map_binding(struct composite_context *ctx)
505 {
506         struct composite_context *c = talloc_get_type(ctx->async.private_data,
507                                                       struct composite_context);
508         struct pipe_connect_state *s = talloc_get_type(c->private_data,
509                                                        struct pipe_connect_state);
510         
511         c->status = dcerpc_epm_map_binding_recv(ctx);
512         if (!composite_is_ok(c)) return;
513
514         DEBUG(2,("Mapped to DCERPC endpoint %s\n", s->binding->endpoint));
515         
516         continue_connect(c, s);
517 }
518
519
520 /*
521   Stage 2 of pipe_connect_b: Continue connection after endpoint is known
522 */
523 static void continue_connect(struct composite_context *c, struct pipe_connect_state *s)
524 {
525         struct dcerpc_pipe_connect pc;
526
527         /* potential exits to another stage by sending an async request */
528         struct composite_context *ncacn_np_smb2_req;
529         struct composite_context *ncacn_np_smb_req;
530         struct composite_context *ncacn_ip_tcp_req;
531         struct composite_context *ncacn_unix_req;
532         struct composite_context *ncalrpc_req;
533
534         /* dcerpc pipe connect input parameters */
535         pc.pipe         = s->pipe;
536         pc.binding      = s->binding;
537         pc.interface    = s->table;
538         pc.creds        = s->credentials;
539         pc.resolve_ctx  = lp_resolve_context(s->lp_ctx);
540
541         /* connect dcerpc pipe depending on required transport */
542         switch (s->binding->transport) {
543         case NCACN_NP:
544                 if (pc.binding->flags & DCERPC_SMB2) {
545                         /* new varient of SMB a.k.a. SMB2 */
546                         ncacn_np_smb2_req = dcerpc_pipe_connect_ncacn_np_smb2_send(c, &pc, s->lp_ctx);
547                         composite_continue(c, ncacn_np_smb2_req, continue_pipe_connect_ncacn_np_smb2, c);
548                         return;
549
550                 } else {
551                         /* good old ordinary SMB */
552                         ncacn_np_smb_req = dcerpc_pipe_connect_ncacn_np_smb_send(c, &pc, s->lp_ctx);
553                         composite_continue(c, ncacn_np_smb_req, continue_pipe_connect_ncacn_np_smb, c);
554                         return;
555                 }
556                 break;
557
558         case NCACN_IP_TCP:
559                 ncacn_ip_tcp_req = dcerpc_pipe_connect_ncacn_ip_tcp_send(c, &pc);
560                 composite_continue(c, ncacn_ip_tcp_req, continue_pipe_connect_ncacn_ip_tcp, c);
561                 return;
562
563         case NCACN_UNIX_STREAM:
564                 ncacn_unix_req = dcerpc_pipe_connect_ncacn_unix_stream_send(c, &pc);
565                 composite_continue(c, ncacn_unix_req, continue_pipe_connect_ncacn_unix, c);
566                 return;
567
568         case NCALRPC:
569                 ncalrpc_req = dcerpc_pipe_connect_ncalrpc_send(c, &pc, s->lp_ctx);
570                 composite_continue(c, ncalrpc_req, continue_pipe_connect_ncalrpc, c);
571                 return;
572
573         default:
574                 /* looks like a transport we don't support now */
575                 composite_error(c, NT_STATUS_NOT_SUPPORTED);
576         }
577 }
578
579
580 /*
581   Stage 3 of pipe_connect_b: Receive result of pipe connect request on
582   named pipe on smb2
583 */
584 static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx)
585 {
586         struct composite_context *c = talloc_get_type(ctx->async.private_data,
587                                                       struct composite_context);
588         struct pipe_connect_state *s = talloc_get_type(c->private_data,
589                                                        struct pipe_connect_state);
590
591         c->status = dcerpc_pipe_connect_ncacn_np_smb2_recv(ctx);
592         if (!composite_is_ok(c)) return;
593
594         continue_pipe_connect(c, s);
595 }
596
597
598 /*
599   Stage 3 of pipe_connect_b: Receive result of pipe connect request on
600   named pipe on smb
601 */
602 static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx)
603 {
604         struct composite_context *c = talloc_get_type(ctx->async.private_data,
605                                                       struct composite_context);
606         struct pipe_connect_state *s = talloc_get_type(c->private_data,
607                                                        struct pipe_connect_state);
608
609         c->status = dcerpc_pipe_connect_ncacn_np_smb_recv(ctx);
610         if (!composite_is_ok(c)) return;
611         
612         continue_pipe_connect(c, s);
613 }
614
615
616 /*
617   Stage 3 of pipe_connect_b: Receive result of pipe connect request on tcp/ip
618 */
619 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx)
620 {
621         struct composite_context *c = talloc_get_type(ctx->async.private_data,
622                                                       struct composite_context);
623         struct pipe_connect_state *s = talloc_get_type(c->private_data,
624                                                        struct pipe_connect_state);
625
626         c->status = dcerpc_pipe_connect_ncacn_ip_tcp_recv(ctx);
627         if (!composite_is_ok(c)) return;
628
629         continue_pipe_connect(c, s);
630 }
631
632
633 /*
634   Stage 3 of pipe_connect_b: Receive result of pipe connect request on unix socket
635 */
636 static void continue_pipe_connect_ncacn_unix(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_unix_stream_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 local rpc
652 */
653 static void continue_pipe_connect_ncalrpc(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_ncalrpc_recv(ctx);
661         if (!composite_is_ok(c)) return;
662
663         continue_pipe_connect(c, s);
664 }
665
666
667 /*
668   Stage 4 of pipe_connect_b: Start an authentication on connected dcerpc pipe
669   depending on credentials and binding flags passed.
670 */
671 static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s)
672 {
673         struct composite_context *auth_bind_req;
674
675         s->pipe->binding = s->binding;
676         if (!talloc_reference(s->pipe, s->binding)) {
677                 composite_error(c, NT_STATUS_NO_MEMORY);
678                 return;
679         }
680
681         auth_bind_req = dcerpc_pipe_auth_send(s->pipe, s->binding, s->table,
682                                               s->credentials, s->lp_ctx);
683         composite_continue(c, auth_bind_req, continue_pipe_auth, c);
684 }
685
686
687 /*
688   Stage 5 of pipe_connect_b: Receive result of pipe authentication request
689   and say if all went ok
690 */
691 static void continue_pipe_auth(struct composite_context *ctx)
692 {
693         struct composite_context *c = talloc_get_type(ctx->async.private_data,
694                                                       struct composite_context);
695         struct pipe_connect_state *s = talloc_get_type(c->private_data, struct pipe_connect_state);
696
697         c->status = dcerpc_pipe_auth_recv(ctx, s, &s->pipe);
698         if (!composite_is_ok(c)) return;
699
700         composite_done(c);
701 }
702
703
704 /*
705   handle timeouts of a dcerpc connect
706 */
707 static void dcerpc_connect_timeout_handler(struct event_context *ev, struct timed_event *te, 
708                                            struct timeval t, void *private)
709 {
710         struct composite_context *c = talloc_get_type(private, struct composite_context);
711         composite_error(c, NT_STATUS_IO_TIMEOUT);
712 }
713
714 /*
715   start a request to open a rpc connection to a rpc pipe, using
716   specified binding structure to determine the endpoint and options
717 */
718 _PUBLIC_ struct composite_context* dcerpc_pipe_connect_b_send(TALLOC_CTX *parent_ctx,
719                                                      struct dcerpc_binding *binding,
720                                                      const struct ndr_interface_table *table,
721                                                      struct cli_credentials *credentials,
722                                                      struct event_context *ev,
723                                                      struct loadparm_context *lp_ctx)
724 {
725         struct composite_context *c;
726         struct pipe_connect_state *s;
727         struct event_context *new_ev = NULL;
728
729         /* composite context allocation and setup */
730         c = composite_create(parent_ctx, ev);
731         if (c == NULL) {
732                 talloc_free(new_ev);
733                 return NULL;
734         }
735         talloc_steal(c, new_ev);
736
737         s = talloc_zero(c, struct pipe_connect_state);
738         if (composite_nomem(s, c)) return c;
739         c->private_data = s;
740
741         /* initialise dcerpc pipe structure */
742         s->pipe = dcerpc_pipe_init(c, ev, lp_iconv_convenience(lp_ctx));
743         if (composite_nomem(s->pipe, c)) return c;
744
745         /* store parameters in state structure */
746         s->binding      = binding;
747         s->table        = table;
748         s->credentials  = credentials;
749         s->lp_ctx       = lp_ctx;
750
751         event_add_timed(c->event_ctx, c,
752                         timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
753                         dcerpc_connect_timeout_handler, c);
754         
755         switch (s->binding->transport) {
756         case NCA_UNKNOWN: {
757                 struct composite_context *binding_req;
758                 binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table,
759                                                           s->pipe->conn->event_ctx,
760                                                           s->lp_ctx);
761                 composite_continue(c, binding_req, continue_map_binding, c);
762                 return c;
763                 }
764
765         case NCACN_NP:
766         case NCACN_IP_TCP:
767         case NCALRPC:
768                 if (!s->binding->endpoint) {
769                         struct composite_context *binding_req;
770                         binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table,
771                                                                   s->pipe->conn->event_ctx,
772                                                                   s->lp_ctx);
773                         composite_continue(c, binding_req, continue_map_binding, c);
774                         return c;
775                 }
776
777         default:
778                 break;
779         }
780
781         continue_connect(c, s);
782         return c;
783 }
784
785
786 /*
787   receive result of a request to open a rpc connection to a rpc pipe
788 */
789 _PUBLIC_ NTSTATUS dcerpc_pipe_connect_b_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
790                                     struct dcerpc_pipe **p)
791 {
792         NTSTATUS status;
793         struct pipe_connect_state *s;
794         
795         status = composite_wait(c);
796         
797         if (NT_STATUS_IS_OK(status)) {
798                 s = talloc_get_type(c->private_data, struct pipe_connect_state);
799                 talloc_steal(mem_ctx, s->pipe);
800                 *p = s->pipe;
801         }
802         talloc_free(c);
803         return status;
804 }
805
806
807 /*
808   open a rpc connection to a rpc pipe, using the specified 
809   binding structure to determine the endpoint and options - sync version
810 */
811 _PUBLIC_ NTSTATUS dcerpc_pipe_connect_b(TALLOC_CTX *parent_ctx,
812                                struct dcerpc_pipe **pp,
813                                struct dcerpc_binding *binding,
814                                const struct ndr_interface_table *table,
815                                struct cli_credentials *credentials,
816                                struct event_context *ev,
817                                struct loadparm_context *lp_ctx)
818 {
819         struct composite_context *c;
820         
821         c = dcerpc_pipe_connect_b_send(parent_ctx, binding, table,
822                                        credentials, ev, lp_ctx);
823         return dcerpc_pipe_connect_b_recv(c, parent_ctx, pp);
824 }
825
826
827 struct pipe_conn_state {
828         struct dcerpc_pipe *pipe;
829 };
830
831
832 static void continue_pipe_connect_b(struct composite_context *ctx);
833
834
835 /*
836   Initiate rpc connection to a rpc pipe, using the specified string
837   binding to determine the endpoint and options.
838   The string is to be parsed to a binding structure first.
839 */
840 _PUBLIC_ struct composite_context* dcerpc_pipe_connect_send(TALLOC_CTX *parent_ctx,
841                                                    const char *binding,
842                                                    const struct ndr_interface_table *table,
843                                                    struct cli_credentials *credentials,
844                                                    struct event_context *ev, struct loadparm_context *lp_ctx)
845 {
846         struct composite_context *c;
847         struct pipe_conn_state *s;
848         struct dcerpc_binding *b;
849         struct composite_context *pipe_conn_req;
850
851         /* composite context allocation and setup */
852         c = composite_create(parent_ctx, ev);
853         if (c == NULL) {
854                 return NULL;
855         }
856
857         s = talloc_zero(c, struct pipe_conn_state);
858         if (composite_nomem(s, c)) return c;
859         c->private_data = s;
860
861         /* parse binding string to the structure */
862         c->status = dcerpc_parse_binding(c, binding, &b);
863         if (!NT_STATUS_IS_OK(c->status)) {
864                 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding));
865                 composite_error(c, c->status);
866                 return c;
867         }
868
869         DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(c, b)));
870
871         /* 
872            start connecting to a rpc pipe after binding structure
873            is established
874          */
875         pipe_conn_req = dcerpc_pipe_connect_b_send(c, b, table,
876                                                    credentials, ev, lp_ctx);
877         composite_continue(c, pipe_conn_req, continue_pipe_connect_b, c);
878         return c;
879 }
880
881
882 /*
883   Stage 2 of pipe_connect: Receive result of actual pipe connect request
884   and say if we're done ok
885 */
886 static void continue_pipe_connect_b(struct composite_context *ctx)
887 {
888         struct composite_context *c = talloc_get_type(ctx->async.private_data,
889                                                       struct composite_context);
890         struct pipe_conn_state *s = talloc_get_type(c->private_data,
891                                                     struct pipe_conn_state);
892
893         c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->pipe);
894         talloc_steal(s, s->pipe);
895         if (!composite_is_ok(c)) return;
896
897         composite_done(c);
898 }
899
900
901 /*
902   Receive result of pipe connect (using binding string) request
903   and return connected pipe structure.
904 */
905 NTSTATUS dcerpc_pipe_connect_recv(struct composite_context *c,
906                                   TALLOC_CTX *mem_ctx,
907                                   struct dcerpc_pipe **pp)
908 {
909         NTSTATUS status;
910         struct pipe_conn_state *s;
911
912         status = composite_wait(c);
913         if (NT_STATUS_IS_OK(status)) {
914                 s = talloc_get_type(c->private_data, struct pipe_conn_state);
915                 *pp = talloc_steal(mem_ctx, s->pipe);
916         }
917         talloc_free(c);
918         return status;
919 }
920
921
922 /*
923   Open a rpc connection to a rpc pipe, using the specified string
924   binding to determine the endpoint and options - sync version
925 */
926 _PUBLIC_ NTSTATUS dcerpc_pipe_connect(TALLOC_CTX *parent_ctx, 
927                              struct dcerpc_pipe **pp, 
928                              const char *binding,
929                              const struct ndr_interface_table *table,
930                              struct cli_credentials *credentials,
931                              struct event_context *ev,
932                              struct loadparm_context *lp_ctx)
933 {
934         struct composite_context *c;
935         c = dcerpc_pipe_connect_send(parent_ctx, binding, 
936                                      table, credentials, ev, lp_ctx);
937         return dcerpc_pipe_connect_recv(c, parent_ctx, pp);
938 }
939