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