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