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