s4:libcli: add fallback_to_anonymous to smb2_connect_send()
[npower/samba.git] / source4 / librpc / rpc / dcerpc_connect.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    dcerpc connect functions
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Jelmer Vernooij 2004
8    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2007
9    Copyright (C) Rafal Szczesniak  2005
10    
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25
26 #include "includes.h"
27 #include "libcli/composite/composite.h"
28 #include "libcli/smb_composite/smb_composite.h"
29 #include "lib/events/events.h"
30 #include "libcli/smb2/smb2.h"
31 #include "libcli/smb2/smb2_calls.h"
32 #include "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 #include "lib/http/http.h"
39
40 struct dcerpc_pipe_connect {
41         struct dcecli_connection *conn;
42         struct dcerpc_binding *binding;
43         const struct ndr_interface_table *interface;
44         struct cli_credentials *creds;
45         struct resolve_context *resolve_ctx;
46         struct {
47                 const char *dir;
48         } ncalrpc;
49         struct {
50                 struct smbXcli_conn *conn;
51                 struct smbXcli_session *session;
52                 struct smbXcli_tcon *tcon;
53                 const char *pipe_name;
54         } smb;
55 };
56
57 struct pipe_np_smb_state {
58         struct smb_composite_connect conn;
59         struct dcerpc_pipe_connect io;
60 };
61
62
63 /*
64   Stage 3 of ncacn_np_smb: Named pipe opened (or not)
65 */
66 static void continue_pipe_open_smb(struct composite_context *ctx)
67 {
68         struct composite_context *c = talloc_get_type(ctx->async.private_data,
69                                                       struct composite_context);
70
71         /* receive result of named pipe open request on smb */
72         c->status = dcerpc_pipe_open_smb_recv(ctx);
73         if (!composite_is_ok(c)) return;
74
75         composite_done(c);
76 }
77
78 static void continue_smb_open(struct composite_context *c);
79
80 /*
81   Stage 2 of ncacn_np_smb: Open a named pipe after successful smb connection
82 */
83 static void continue_smb_connect(struct composite_context *ctx)
84 {
85         struct composite_context *c = talloc_get_type(ctx->async.private_data,
86                                                       struct composite_context);
87         struct pipe_np_smb_state *s = talloc_get_type(c->private_data,
88                                                       struct pipe_np_smb_state);
89         struct smbcli_tree *t;
90
91         /* receive result of smb connect request */
92         c->status = smb_composite_connect_recv(ctx, s->io.conn);
93         if (!composite_is_ok(c)) return;
94
95         t = s->conn.out.tree;
96
97         /* prepare named pipe open parameters */
98         s->io.smb.conn = t->session->transport->conn;
99         s->io.smb.session = t->session->smbXcli;
100         s->io.smb.tcon = t->smbXcli;
101         smb1cli_tcon_set_id(s->io.smb.tcon, t->tid);
102         s->io.smb.pipe_name = dcerpc_binding_get_string_option(s->io.binding,
103                                                                "endpoint");
104
105         continue_smb_open(c);
106 }
107
108 static void continue_smb_open(struct composite_context *c)
109 {
110         struct pipe_np_smb_state *s = talloc_get_type(c->private_data,
111                                                       struct pipe_np_smb_state);
112         struct composite_context *open_ctx;
113
114         /* send named pipe open request */
115         open_ctx = dcerpc_pipe_open_smb_send(s->io.conn,
116                                              s->io.smb.conn,
117                                              s->io.smb.session,
118                                              s->io.smb.tcon,
119                                              DCERPC_REQUEST_TIMEOUT * 1000,
120                                              s->io.smb.pipe_name);
121         if (composite_nomem(open_ctx, c)) return;
122
123         composite_continue(c, open_ctx, continue_pipe_open_smb, c);
124 }
125
126
127 /*
128   Initiate async open of a rpc connection to a rpc pipe on SMB using
129   the binding structure to determine the endpoint and options
130 */
131 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)
132 {
133         struct composite_context *c;
134         struct pipe_np_smb_state *s;
135         struct composite_context *conn_req;
136         struct smb_composite_connect *conn;
137         uint32_t flags;
138
139         /* composite context allocation and setup */
140         c = composite_create(mem_ctx, io->conn->event_ctx);
141         if (c == NULL) return NULL;
142
143         s = talloc_zero(c, struct pipe_np_smb_state);
144         if (composite_nomem(s, c)) return c;
145         c->private_data = s;
146
147         s->io  = *io;
148         conn   = &s->conn;
149
150         if (smbXcli_conn_is_connected(s->io.smb.conn)) {
151                 continue_smb_open(c);
152                 return c;
153         }
154
155         /* prepare smb connection parameters: we're connecting to IPC$ share on
156            remote rpc server */
157         conn->in.dest_host = dcerpc_binding_get_string_option(s->io.binding, "host");
158         conn->in.dest_ports = lpcfg_smb_ports(lp_ctx);
159         conn->in.called_name =
160                 dcerpc_binding_get_string_option(s->io.binding, "target_hostname");
161         if (conn->in.called_name == NULL) {
162                 conn->in.called_name = "*SMBSERVER";
163         }
164         conn->in.socket_options         = lpcfg_socket_options(lp_ctx);
165         conn->in.service                = "IPC$";
166         conn->in.service_type           = NULL;
167         conn->in.workgroup              = lpcfg_workgroup(lp_ctx);
168         conn->in.gensec_settings = lpcfg_gensec_settings(conn, lp_ctx);
169
170         lpcfg_smbcli_options(lp_ctx, &conn->in.options);
171         lpcfg_smbcli_session_options(lp_ctx, &conn->in.session_options);
172
173         /*
174          * provide proper credentials - user supplied, but allow a
175          * fallback to anonymous if this is an schannel connection
176          * (might be NT4 not allowing machine logins at session
177          * setup) or if asked to do so by the caller (perhaps a SAMR password change?)
178          */
179         s->conn.in.credentials = s->io.creds;
180         flags = dcerpc_binding_get_flags(s->io.binding);
181         if (flags & (DCERPC_SCHANNEL|DCERPC_ANON_FALLBACK)) {
182                 conn->in.fallback_to_anonymous  = true;
183         } else {
184                 conn->in.fallback_to_anonymous  = false;
185         }
186
187         conn->in.options.min_protocol = PROTOCOL_NT1;
188         conn->in.options.max_protocol = PROTOCOL_NT1;
189
190         conn->in.options.signing = lpcfg_client_ipc_signing(lp_ctx);
191
192         /* send smb connect request */
193         conn_req = smb_composite_connect_send(conn, s->io.conn,
194                                               s->io.resolve_ctx,
195                                               c->event_ctx);
196         if (composite_nomem(conn_req, c)) return c;
197
198         composite_continue(c, conn_req, continue_smb_connect, c);
199         return c;
200 }
201
202
203 /*
204   Receive result of a rpc connection to a rpc pipe on SMB
205 */
206 static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb_recv(struct composite_context *c)
207 {
208         NTSTATUS status = composite_wait(c);
209
210         talloc_free(c);
211         return status;
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 *c =
220                 tevent_req_callback_data(subreq,
221                 struct composite_context);
222         struct pipe_np_smb_state *s = talloc_get_type(c->private_data,
223                                                       struct pipe_np_smb_state);
224         struct smb2_tree *t;
225
226         /* receive result of smb2 connect request */
227         c->status = smb2_connect_recv(subreq, s->io.conn, &t);
228         TALLOC_FREE(subreq);
229         if (!composite_is_ok(c)) return;
230
231         s->io.smb.conn = t->session->transport->conn;
232         s->io.smb.session = t->session->smbXcli;
233         s->io.smb.tcon = t->smbXcli;
234         s->io.smb.pipe_name = dcerpc_binding_get_string_option(s->io.binding,
235                                                                "endpoint");
236
237         continue_smb_open(c);
238 }
239
240
241 /* 
242    Initiate async open of a rpc connection request on SMB2 using
243    the binding structure to determine the endpoint and options
244 */
245 static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send(
246                                         TALLOC_CTX *mem_ctx,
247                                         struct dcerpc_pipe_connect *io,
248                                         struct loadparm_context *lp_ctx)
249 {
250         struct composite_context *c;
251         struct pipe_np_smb_state *s;
252         struct tevent_req *subreq;
253         struct smbcli_options options;
254         const char *host;
255         uint32_t flags;
256
257         /* composite context allocation and setup */
258         c = composite_create(mem_ctx, io->conn->event_ctx);
259         if (c == NULL) return NULL;
260
261         s = talloc_zero(c, struct pipe_np_smb_state);
262         if (composite_nomem(s, c)) return c;
263         c->private_data = s;
264
265         s->io = *io;
266
267         if (smbXcli_conn_is_connected(s->io.smb.conn)) {
268                 continue_smb_open(c);
269                 return c;
270         }
271
272         host = dcerpc_binding_get_string_option(s->io.binding, "host");
273         flags = dcerpc_binding_get_flags(s->io.binding);
274
275         /*
276          * provide proper credentials - user supplied or anonymous in case this is
277          * schannel connection
278          */
279         if (flags & DCERPC_SCHANNEL) {
280                 s->io.creds = cli_credentials_init_anon(mem_ctx);
281                 if (composite_nomem(s->io.creds, c)) return c;
282         }
283
284         lpcfg_smbcli_options(lp_ctx, &options);
285
286         options.min_protocol = lpcfg_client_ipc_min_protocol(lp_ctx);
287         if (options.min_protocol < PROTOCOL_SMB2_02) {
288                 options.min_protocol = PROTOCOL_SMB2_02;
289         }
290         options.max_protocol = lpcfg_client_ipc_max_protocol(lp_ctx);
291         if (options.max_protocol < PROTOCOL_SMB2_02) {
292                 options.max_protocol = PROTOCOL_SMB2_02;
293         }
294
295         options.signing = lpcfg_client_ipc_signing(lp_ctx);
296
297         /* send smb2 connect request */
298         subreq = smb2_connect_send(s, c->event_ctx,
299                         host,
300                         lpcfg_parm_string_list(mem_ctx, lp_ctx, NULL, "smb2", "ports", NULL),
301                         "IPC$",
302                         s->io.resolve_ctx,
303                         s->io.creds,
304                         false, /* fallback_to_anonymous */
305                         NULL, /* existing_conn */
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         struct pipe_ip_tcp_state *s = talloc_get_type(c->private_data,
345                                                       struct pipe_ip_tcp_state);
346         char *localaddr = NULL;
347         char *remoteaddr = NULL;
348
349         /* receive result of named pipe open request on tcp/ip */
350         c->status = dcerpc_pipe_open_tcp_recv(ctx, s, &localaddr, &remoteaddr);
351         if (!composite_is_ok(c)) return;
352
353         c->status = dcerpc_binding_set_string_option(s->io.binding,
354                                                      "localaddress",
355                                                      localaddr);
356         if (!composite_is_ok(c)) return;
357
358         c->status = dcerpc_binding_set_string_option(s->io.binding,
359                                                      "host",
360                                                      remoteaddr);
361         if (!composite_is_ok(c)) return;
362
363         composite_done(c);
364 }
365
366
367 /*
368   Initiate async open of a rpc connection to a rpc pipe on TCP/IP using
369   the binding structure to determine the endpoint and options
370 */
371 static struct composite_context* dcerpc_pipe_connect_ncacn_ip_tcp_send(TALLOC_CTX *mem_ctx,
372                                                                        struct dcerpc_pipe_connect *io)
373 {
374         struct composite_context *c;
375         struct pipe_ip_tcp_state *s;
376         struct composite_context *pipe_req;
377         const char *endpoint;
378
379         /* composite context allocation and setup */
380         c = composite_create(mem_ctx, io->conn->event_ctx);
381         if (c == NULL) return NULL;
382
383         s = talloc_zero(c, struct pipe_ip_tcp_state);
384         if (composite_nomem(s, c)) return c;
385         c->private_data = s;
386
387         /* store input parameters in state structure */
388         s->io = *io;
389         s->localaddr = dcerpc_binding_get_string_option(io->binding,
390                                                         "localaddress");
391         s->host = dcerpc_binding_get_string_option(io->binding, "host");
392         s->target_hostname = dcerpc_binding_get_string_option(io->binding,
393                                                               "target_hostname");
394         endpoint = dcerpc_binding_get_string_option(io->binding, "endpoint");
395         /* port number is a binding endpoint here */
396         if (endpoint != NULL) {
397                 s->port = atoi(endpoint);
398         }
399
400         if (s->port == 0) {
401                 composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
402                 return c;
403         }
404
405         /* send pipe open request on tcp/ip */
406         pipe_req = dcerpc_pipe_open_tcp_send(s->io.conn, s->localaddr, s->host, s->target_hostname,
407                                              s->port, io->resolve_ctx);
408         composite_continue(c, pipe_req, continue_pipe_open_ncacn_ip_tcp, c);
409         return c;
410 }
411
412
413 /*
414   Receive result of a rpc connection to a rpc pipe on TCP/IP
415 */
416 static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp_recv(struct composite_context *c)
417 {
418         NTSTATUS status = composite_wait(c);
419         
420         talloc_free(c);
421         return status;
422 }
423
424
425 struct pipe_http_state {
426         struct dcerpc_pipe_connect io;
427         const char *localaddr;
428         const char *target_hostname;
429         const char *rpc_server;
430         uint32_t rpc_server_port;
431         char *rpc_proxy;
432         uint32_t rpc_proxy_port;
433         char *http_proxy;
434         uint32_t http_proxy_port;
435         bool use_tls;
436         bool use_proxy;
437         enum http_auth_method http_auth;
438         struct loadparm_context *lp_ctx;
439 };
440
441 /*
442   Stage 2 of ncacn_http: rpc pipe opened (or not)
443  */
444 static void continue_pipe_open_ncacn_http(struct tevent_req *subreq)
445 {
446         struct composite_context *c = NULL;
447         struct pipe_http_state *s = NULL;
448         struct tstream_context *stream = NULL;
449         struct tevent_queue *queue = NULL;
450
451         c = tevent_req_callback_data(subreq, struct composite_context);
452         s = talloc_get_type(c->private_data, struct pipe_http_state);
453
454         /* receive result of RoH connect request */
455         c->status = dcerpc_pipe_open_roh_recv(subreq, s->io.conn,
456                                               &stream, &queue);
457         TALLOC_FREE(subreq);
458         if (!composite_is_ok(c)) return;
459
460         s->io.conn->transport.transport = NCACN_HTTP;
461         s->io.conn->transport.stream = stream;
462         s->io.conn->transport.write_queue = queue;
463         s->io.conn->transport.pending_reads = 0;
464         s->io.conn->server_name = strupper_talloc(s->io.conn,
465                                                   s->target_hostname);
466
467         composite_done(c);
468 }
469
470 /*
471   Initiate async open of a rpc connection to a rpc pipe using HTTP transport,
472   and using the binding structure to determine the endpoint and options
473 */
474 static struct composite_context* dcerpc_pipe_connect_ncacn_http_send(
475                 TALLOC_CTX *mem_ctx, struct dcerpc_pipe_connect *io,
476                 struct loadparm_context *lp_ctx)
477 {
478         struct composite_context *c;
479         struct pipe_http_state *s;
480         struct tevent_req *subreq;
481         const char *endpoint;
482         const char *use_proxy;
483         char *proxy;
484         char *port;
485         const char *opt;
486
487         /* composite context allocation and setup */
488         c = composite_create(mem_ctx, io->conn->event_ctx);
489         if (c == NULL) return NULL;
490
491         s = talloc_zero(c, struct pipe_http_state);
492         if (composite_nomem(s, c)) return c;
493         c->private_data = s;
494
495         /* store input parameters in state structure */
496         s->lp_ctx       = lp_ctx;
497         s->io           = *io;
498         s->localaddr    = dcerpc_binding_get_string_option(io->binding,
499                                                         "localaddress");
500         /* RPC server and port (the endpoint) */
501         s->rpc_server = dcerpc_binding_get_string_option(io->binding, "host");
502         s->target_hostname = dcerpc_binding_get_string_option(io->binding,
503                                                               "target_hostname");
504         endpoint = dcerpc_binding_get_string_option(io->binding, "endpoint");
505         if (endpoint == NULL) {
506                 composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
507                 return c;
508         }
509         s->rpc_server_port = atoi(endpoint);
510         if (s->rpc_server_port == 0) {
511                 composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
512                 return c;
513         }
514
515         /* Use TLS */
516         opt = dcerpc_binding_get_string_option(io->binding, "HttpUseTls");
517         if (opt) {
518                 if (strcasecmp(opt, "true") == 0) {
519                         s->use_tls = true;
520                 } else if (strcasecmp(opt, "false") == 0) {
521                         s->use_tls = false;
522                 } else {
523                         composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
524                         return c;
525                 }
526         } else {
527                 s->use_tls = true;
528         }
529
530         /* RPC Proxy */
531         proxy = port = talloc_strdup(s, dcerpc_binding_get_string_option(
532                         io->binding, "RpcProxy"));
533         s->rpc_proxy  = strsep(&port, ":");
534         if (proxy && port) {
535                 s->rpc_proxy_port = atoi(port);
536         } else {
537                 s->rpc_proxy_port = s->use_tls ? 443 : 80;
538         }
539         if (s->rpc_proxy == NULL) {
540                 s->rpc_proxy = talloc_strdup(s, s->rpc_server);
541                 if (composite_nomem(s->rpc_proxy, c)) return c;
542         }
543
544         /* HTTP Proxy */
545         proxy = port = talloc_strdup(s, dcerpc_binding_get_string_option(
546                         io->binding, "HttpProxy"));
547         s->http_proxy = strsep(&port, ":");
548         if (proxy && port) {
549                 s->http_proxy_port = atoi(port);
550         } else {
551                 s->http_proxy_port = s->use_tls ? 443 : 80;
552         }
553
554         /* Use local proxy */
555         use_proxy = dcerpc_binding_get_string_option(io->binding,
556                                                  "HttpConnectOption");
557         if (use_proxy && strcasecmp(use_proxy, "UseHttpProxy")) {
558                 s->use_proxy = true;
559         }
560
561         /* If use local proxy set, the http proxy should be provided */
562         if (s->use_proxy && !s->http_proxy) {
563                 composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
564                 return c;
565         }
566
567         /* Check which HTTP authentication method to use */
568         opt = dcerpc_binding_get_string_option(io->binding, "HttpAuthOption");
569         if (opt) {
570                 if (strcasecmp(opt, "basic") == 0) {
571                         s->http_auth = HTTP_AUTH_BASIC;
572                 } else if (strcasecmp(opt, "ntlm") == 0) {
573                         s->http_auth = HTTP_AUTH_NTLM;
574                 } else if (strcasecmp(opt, "negotiate") == 0) {
575                         s->http_auth = HTTP_AUTH_NEGOTIATE;
576                 } else {
577                         composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
578                         return c;
579                 }
580         } else {
581                 s->http_auth = HTTP_AUTH_NTLM;
582         }
583
584         subreq = dcerpc_pipe_open_roh_send(s->io.conn, s->localaddr,
585                                            s->rpc_server, s->rpc_server_port,
586                                            s->rpc_proxy, s->rpc_proxy_port,
587                                            s->http_proxy, s->http_proxy_port,
588                                            s->use_tls, s->use_proxy,
589                                            s->io.creds, io->resolve_ctx,
590                                            s->lp_ctx, s->http_auth);
591         if (composite_nomem(subreq, c)) return c;
592
593         tevent_req_set_callback(subreq, continue_pipe_open_ncacn_http, c);
594         return c;
595 }
596
597 static NTSTATUS dcerpc_pipe_connect_ncacn_http_recv(struct composite_context *c)
598 {
599         return composite_wait_free(c);
600 }
601
602
603 struct pipe_unix_state {
604         struct dcerpc_pipe_connect io;
605         const char *path;
606 };
607
608
609 /*
610   Stage 2 of ncacn_unix: rpc pipe opened (or not)
611 */
612 static void continue_pipe_open_ncacn_unix_stream(struct composite_context *ctx)
613 {
614         struct composite_context *c = talloc_get_type(ctx->async.private_data,
615                                                       struct composite_context);
616
617         /* receive result of pipe open request on unix socket */
618         c->status = dcerpc_pipe_open_unix_stream_recv(ctx);
619         if (!composite_is_ok(c)) return;
620
621         composite_done(c);
622 }
623
624
625 /*
626   Initiate async open of a rpc connection to a rpc pipe on unix socket using
627   the binding structure to determine the endpoint and options
628 */
629 static struct composite_context* dcerpc_pipe_connect_ncacn_unix_stream_send(TALLOC_CTX *mem_ctx,
630                                                                             struct dcerpc_pipe_connect *io)
631 {
632         struct composite_context *c;
633         struct pipe_unix_state *s;
634         struct composite_context *pipe_req;
635
636         /* composite context allocation and setup */
637         c = composite_create(mem_ctx, io->conn->event_ctx);
638         if (c == NULL) return NULL;
639
640         s = talloc_zero(c, struct pipe_unix_state);
641         if (composite_nomem(s, c)) return c;
642         c->private_data = s;
643
644         /* prepare pipe open parameters and store them in state structure
645            also, verify whether biding endpoint is not null */
646         s->io = *io;
647
648         s->path = dcerpc_binding_get_string_option(io->binding, "endpoint");
649         if (s->path == NULL) {
650                 composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
651                 return c;
652         }
653
654         /* send pipe open request on unix socket */
655         pipe_req = dcerpc_pipe_open_unix_stream_send(s->io.conn, s->path);
656         composite_continue(c, pipe_req, continue_pipe_open_ncacn_unix_stream, c);
657         return c;
658 }
659
660
661 /*
662   Receive result of a rpc connection to a pipe on unix socket
663 */
664 static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream_recv(struct composite_context *c)
665 {
666         NTSTATUS status = composite_wait(c);
667
668         talloc_free(c);
669         return status;
670 }
671
672
673 struct pipe_ncalrpc_state {
674         struct dcerpc_pipe_connect io;
675 };
676
677 static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c);
678
679 /*
680   Stage 2 of ncalrpc: rpc pipe opened (or not)
681 */
682 static void continue_pipe_open_ncalrpc(struct composite_context *ctx)
683 {
684         struct composite_context *c = talloc_get_type(ctx->async.private_data,
685                                                       struct composite_context);
686
687         /* receive result of pipe open request on ncalrpc */
688         c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx);
689         if (!composite_is_ok(c)) return;
690
691         composite_done(c);
692 }
693
694
695 /* 
696    Initiate async open of a rpc connection request on NCALRPC using
697    the binding structure to determine the endpoint and options
698 */
699 static struct composite_context* dcerpc_pipe_connect_ncalrpc_send(TALLOC_CTX *mem_ctx,
700                                                                   struct dcerpc_pipe_connect *io)
701 {
702         struct composite_context *c;
703         struct pipe_ncalrpc_state *s;
704         struct composite_context *pipe_req;
705         const char *endpoint;
706
707         /* composite context allocation and setup */
708         c = composite_create(mem_ctx, io->conn->event_ctx);
709         if (c == NULL) return NULL;
710
711         s = talloc_zero(c, struct pipe_ncalrpc_state);
712         if (composite_nomem(s, c)) return c;
713         c->private_data = s;
714         
715         /* store input parameters in state structure */
716         s->io  = *io;
717
718         endpoint = dcerpc_binding_get_string_option(io->binding, "endpoint");
719         if (endpoint == NULL) {
720                 composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
721                 return c;
722         }
723
724         /* send pipe open request */
725         pipe_req = dcerpc_pipe_open_pipe_send(s->io.conn,
726                                               s->io.ncalrpc.dir,
727                                               endpoint);
728         composite_continue(c, pipe_req, continue_pipe_open_ncalrpc, c);
729         return c;
730 }
731
732
733 /*
734   Receive result of a rpc connection to a rpc pipe on NCALRPC
735 */
736 static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c)
737 {
738         NTSTATUS status = composite_wait(c);
739         
740         talloc_free(c);
741         return status;
742 }
743
744
745 struct pipe_connect_state {
746         struct dcerpc_pipe *pipe;
747         struct dcerpc_binding *binding;
748         const struct ndr_interface_table *table;
749         struct cli_credentials *credentials;
750         struct loadparm_context *lp_ctx;
751 };
752
753
754 static void continue_map_binding(struct composite_context *ctx);
755 static void continue_connect(struct composite_context *c, struct pipe_connect_state *s);
756 static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx);
757 static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx);
758 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx);
759 static void continue_pipe_connect_ncacn_http(struct composite_context *ctx);
760 static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx);
761 static void continue_pipe_connect_ncalrpc(struct composite_context *ctx);
762 static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s);
763 static void continue_pipe_auth(struct composite_context *ctx);
764
765
766 /*
767   Stage 2 of pipe_connect_b: Receive result of endpoint mapping
768 */
769 static void continue_map_binding(struct composite_context *ctx)
770 {
771         struct composite_context *c = talloc_get_type(ctx->async.private_data,
772                                                       struct composite_context);
773         struct pipe_connect_state *s = talloc_get_type(c->private_data,
774                                                        struct pipe_connect_state);
775         const char *endpoint;
776
777         c->status = dcerpc_epm_map_binding_recv(ctx);
778         if (!composite_is_ok(c)) return;
779
780         endpoint = dcerpc_binding_get_string_option(s->binding, "endpoint");
781         DEBUG(4,("Mapped to DCERPC endpoint %s\n", endpoint));
782
783         continue_connect(c, s);
784 }
785
786
787 /*
788   Stage 2 of pipe_connect_b: Continue connection after endpoint is known
789 */
790 static void continue_connect(struct composite_context *c, struct pipe_connect_state *s)
791 {
792         struct dcerpc_pipe_connect pc;
793
794         /* potential exits to another stage by sending an async request */
795         struct composite_context *ncacn_np_smb2_req;
796         struct composite_context *ncacn_np_smb_req;
797         struct composite_context *ncacn_ip_tcp_req;
798         struct composite_context *ncacn_http_req;
799         struct composite_context *ncacn_unix_req;
800         struct composite_context *ncalrpc_req;
801         enum dcerpc_transport_t transport;
802         enum protocol_types min_ipc_protocol;
803         uint32_t flags;
804
805         /* dcerpc pipe connect input parameters */
806         ZERO_STRUCT(pc);
807         pc.conn         = s->pipe->conn;
808         pc.binding      = s->binding;
809         pc.interface    = s->table;
810         pc.creds        = s->credentials;
811         pc.resolve_ctx  = lpcfg_resolve_context(s->lp_ctx);
812
813         transport = dcerpc_binding_get_transport(s->binding);
814         flags = dcerpc_binding_get_flags(s->binding);
815
816         min_ipc_protocol = lpcfg_client_ipc_min_protocol(s->lp_ctx);
817         if (min_ipc_protocol >= PROTOCOL_SMB2_02) {
818                 flags |= DCERPC_SMB2;
819         }
820
821         /* connect dcerpc pipe depending on required transport */
822         switch (transport) {
823         case NCACN_NP:
824                 if (flags & DCERPC_SMB2) {
825                         /* new varient of SMB a.k.a. SMB2 */
826                         ncacn_np_smb2_req = dcerpc_pipe_connect_ncacn_np_smb2_send(c, &pc, s->lp_ctx);
827                         composite_continue(c, ncacn_np_smb2_req, continue_pipe_connect_ncacn_np_smb2, c);
828                         return;
829
830                 } else {
831                         /* good old ordinary SMB */
832                         ncacn_np_smb_req = dcerpc_pipe_connect_ncacn_np_smb_send(c, &pc, s->lp_ctx);
833                         composite_continue(c, ncacn_np_smb_req, continue_pipe_connect_ncacn_np_smb, c);
834                         return;
835                 }
836                 break;
837
838         case NCACN_IP_TCP:
839                 ncacn_ip_tcp_req = dcerpc_pipe_connect_ncacn_ip_tcp_send(c, &pc);
840                 composite_continue(c, ncacn_ip_tcp_req, continue_pipe_connect_ncacn_ip_tcp, c);
841                 return;
842
843         case NCACN_HTTP:
844                 ncacn_http_req = dcerpc_pipe_connect_ncacn_http_send(c, &pc, s->lp_ctx);
845                 composite_continue(c, ncacn_http_req, continue_pipe_connect_ncacn_http, c);
846                 return;
847
848         case NCACN_UNIX_STREAM:
849                 ncacn_unix_req = dcerpc_pipe_connect_ncacn_unix_stream_send(c, &pc);
850                 composite_continue(c, ncacn_unix_req, continue_pipe_connect_ncacn_unix, c);
851                 return;
852
853         case NCALRPC:
854                 pc.ncalrpc.dir = lpcfg_ncalrpc_dir(s->lp_ctx);
855                 c->status = dcerpc_binding_set_string_option(s->binding, "ncalrpc_dir",
856                                                              pc.ncalrpc.dir);
857                 if (!composite_is_ok(c)) return;
858                 ncalrpc_req = dcerpc_pipe_connect_ncalrpc_send(c, &pc);
859                 composite_continue(c, ncalrpc_req, continue_pipe_connect_ncalrpc, c);
860                 return;
861
862         default:
863                 /* looks like a transport we don't support now */
864                 composite_error(c, NT_STATUS_NOT_SUPPORTED);
865         }
866 }
867
868
869 /*
870   Stage 3 of pipe_connect_b: Receive result of pipe connect request on
871   named pipe on smb2
872 */
873 static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx)
874 {
875         struct composite_context *c = talloc_get_type(ctx->async.private_data,
876                                                       struct composite_context);
877         struct pipe_connect_state *s = talloc_get_type(c->private_data,
878                                                        struct pipe_connect_state);
879
880         c->status = dcerpc_pipe_connect_ncacn_np_smb2_recv(ctx);
881         if (!composite_is_ok(c)) return;
882
883         continue_pipe_connect(c, s);
884 }
885
886
887 /*
888   Stage 3 of pipe_connect_b: Receive result of pipe connect request on
889   named pipe on smb
890 */
891 static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx)
892 {
893         struct composite_context *c = talloc_get_type(ctx->async.private_data,
894                                                       struct composite_context);
895         struct pipe_connect_state *s = talloc_get_type(c->private_data,
896                                                        struct pipe_connect_state);
897
898         c->status = dcerpc_pipe_connect_ncacn_np_smb_recv(ctx);
899         if (!composite_is_ok(c)) return;
900         
901         continue_pipe_connect(c, s);
902 }
903
904
905 /*
906   Stage 3 of pipe_connect_b: Receive result of pipe connect request on tcp/ip
907 */
908 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx)
909 {
910         struct composite_context *c = talloc_get_type(ctx->async.private_data,
911                                                       struct composite_context);
912         struct pipe_connect_state *s = talloc_get_type(c->private_data,
913                                                        struct pipe_connect_state);
914
915         c->status = dcerpc_pipe_connect_ncacn_ip_tcp_recv(ctx);
916         if (!composite_is_ok(c)) return;
917
918         continue_pipe_connect(c, s);
919 }
920
921
922 /*
923   Stage 3 of pipe_connect_b: Receive result of pipe connect request on http
924 */
925 static void continue_pipe_connect_ncacn_http(struct composite_context *ctx)
926 {
927         struct composite_context *c = talloc_get_type(ctx->async.private_data,
928                                                       struct composite_context);
929         struct pipe_connect_state *s = talloc_get_type(c->private_data,
930                                                        struct pipe_connect_state);
931
932         c->status = dcerpc_pipe_connect_ncacn_http_recv(ctx);
933         if (!composite_is_ok(c)) return;
934
935         continue_pipe_connect(c, s);
936 }
937
938
939 /*
940   Stage 3 of pipe_connect_b: Receive result of pipe connect request on unix socket
941 */
942 static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx)
943 {
944         struct composite_context *c = talloc_get_type(ctx->async.private_data,
945                                                       struct composite_context);
946         struct pipe_connect_state *s = talloc_get_type(c->private_data,
947                                                        struct pipe_connect_state);
948         
949         c->status = dcerpc_pipe_connect_ncacn_unix_stream_recv(ctx);
950         if (!composite_is_ok(c)) return;
951         
952         continue_pipe_connect(c, s);
953 }
954
955
956 /*
957   Stage 3 of pipe_connect_b: Receive result of pipe connect request on local rpc
958 */
959 static void continue_pipe_connect_ncalrpc(struct composite_context *ctx)
960 {
961         struct composite_context *c = talloc_get_type(ctx->async.private_data,
962                                                       struct composite_context);
963         struct pipe_connect_state *s = talloc_get_type(c->private_data,
964                                                        struct pipe_connect_state);
965         
966         c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx);
967         if (!composite_is_ok(c)) return;
968
969         continue_pipe_connect(c, s);
970 }
971
972
973 /*
974   Stage 4 of pipe_connect_b: Start an authentication on connected dcerpc pipe
975   depending on credentials and binding flags passed.
976 */
977 static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s)
978 {
979         struct composite_context *auth_bind_req;
980
981         s->pipe->binding = dcerpc_binding_dup(s->pipe, s->binding);
982         if (composite_nomem(s->pipe->binding, c)) {
983                 return;
984         }
985
986         auth_bind_req = dcerpc_pipe_auth_send(s->pipe, s->binding, s->table,
987                                               s->credentials, s->lp_ctx);
988         composite_continue(c, auth_bind_req, continue_pipe_auth, c);
989 }
990
991
992 /*
993   Stage 5 of pipe_connect_b: Receive result of pipe authentication request
994   and say if all went ok
995 */
996 static void continue_pipe_auth(struct composite_context *ctx)
997 {
998         struct composite_context *c = talloc_get_type(ctx->async.private_data,
999                                                       struct composite_context);
1000         struct pipe_connect_state *s = talloc_get_type(c->private_data, struct pipe_connect_state);
1001
1002         c->status = dcerpc_pipe_auth_recv(ctx, s, &s->pipe);
1003         if (!composite_is_ok(c)) return;
1004
1005         composite_done(c);
1006 }
1007
1008
1009 /*
1010   handle timeouts of a dcerpc connect
1011 */
1012 static void dcerpc_connect_timeout_handler(struct tevent_context *ev, struct tevent_timer *te, 
1013                                            struct timeval t, void *private_data)
1014 {
1015         struct composite_context *c = talloc_get_type_abort(private_data,
1016                                                       struct composite_context);
1017         struct pipe_connect_state *s = talloc_get_type_abort(c->private_data, struct pipe_connect_state);
1018         if (!s->pipe->inhibit_timeout_processing) {
1019                 composite_error(c, NT_STATUS_IO_TIMEOUT);
1020         } else {
1021                 s->pipe->timed_out = true;
1022         }
1023 }
1024
1025 /*
1026   start a request to open a rpc connection to a rpc pipe, using
1027   specified binding structure to determine the endpoint and options
1028 */
1029 _PUBLIC_ struct composite_context* dcerpc_pipe_connect_b_send(TALLOC_CTX *parent_ctx,
1030                                                      const struct dcerpc_binding *binding,
1031                                                      const struct ndr_interface_table *table,
1032                                                      struct cli_credentials *credentials,
1033                                                      struct tevent_context *ev,
1034                                                      struct loadparm_context *lp_ctx)
1035 {
1036         struct composite_context *c;
1037         struct pipe_connect_state *s;
1038         enum dcerpc_transport_t transport;
1039         const char *endpoint = NULL;
1040         struct cli_credentials *epm_creds = NULL;
1041
1042         /* composite context allocation and setup */
1043         c = composite_create(parent_ctx, ev);
1044         if (c == NULL) {
1045                 return NULL;
1046         }
1047
1048         s = talloc_zero(c, struct pipe_connect_state);
1049         if (composite_nomem(s, c)) return c;
1050         c->private_data = s;
1051
1052         /* initialise dcerpc pipe structure */
1053         s->pipe = dcerpc_pipe_init(c, ev);
1054         if (composite_nomem(s->pipe, c)) return c;
1055
1056         if (DEBUGLEVEL >= 10)
1057                 s->pipe->conn->packet_log_dir = lpcfg_lock_directory(lp_ctx);
1058
1059         /* store parameters in state structure */
1060         s->binding      = dcerpc_binding_dup(s, binding);
1061         if (composite_nomem(s->binding, c)) return c;
1062         s->table        = table;
1063         s->credentials  = credentials;
1064         s->lp_ctx       = lp_ctx;
1065
1066         s->pipe->timed_out = false;
1067         s->pipe->inhibit_timeout_processing = false;
1068
1069         tevent_add_timer(c->event_ctx, c,
1070                          timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
1071                          dcerpc_connect_timeout_handler, c);
1072
1073         transport = dcerpc_binding_get_transport(s->binding);
1074
1075         switch (transport) {
1076         case NCACN_NP:
1077         case NCACN_IP_TCP:
1078         case NCALRPC:
1079                 endpoint = dcerpc_binding_get_string_option(s->binding, "endpoint");
1080
1081                 /* anonymous credentials for rpc connection used to get endpoint mapping */
1082                 epm_creds = cli_credentials_init_anon(s);
1083                 if (composite_nomem(epm_creds, c)) return c;
1084
1085                 break;
1086         case NCACN_HTTP:
1087                 endpoint = dcerpc_binding_get_string_option(s->binding, "endpoint");
1088                 epm_creds = credentials;
1089                 break;
1090         default:
1091                 break;
1092         }
1093
1094         if (endpoint == NULL) {
1095                 struct composite_context *binding_req;
1096
1097                 binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table,
1098                                                           epm_creds,
1099                                                           s->pipe->conn->event_ctx,
1100                                                           s->lp_ctx);
1101                 composite_continue(c, binding_req, continue_map_binding, c);
1102                 return c;
1103         }
1104
1105         continue_connect(c, s);
1106         return c;
1107 }
1108
1109
1110 /*
1111   receive result of a request to open a rpc connection to a rpc pipe
1112 */
1113 _PUBLIC_ NTSTATUS dcerpc_pipe_connect_b_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
1114                                     struct dcerpc_pipe **p)
1115 {
1116         NTSTATUS status;
1117         struct pipe_connect_state *s;
1118         
1119         status = composite_wait(c);
1120         
1121         if (NT_STATUS_IS_OK(status)) {
1122                 s = talloc_get_type(c->private_data, struct pipe_connect_state);
1123                 talloc_steal(mem_ctx, s->pipe);
1124                 *p = s->pipe;
1125         }
1126         talloc_free(c);
1127         return status;
1128 }
1129
1130
1131 /*
1132   open a rpc connection to a rpc pipe, using the specified 
1133   binding structure to determine the endpoint and options - sync version
1134 */
1135 _PUBLIC_ NTSTATUS dcerpc_pipe_connect_b(TALLOC_CTX *parent_ctx,
1136                                struct dcerpc_pipe **pp,
1137                                const struct dcerpc_binding *binding,
1138                                const struct ndr_interface_table *table,
1139                                struct cli_credentials *credentials,
1140                                struct tevent_context *ev,
1141                                struct loadparm_context *lp_ctx)
1142 {
1143         struct composite_context *c;
1144         
1145         c = dcerpc_pipe_connect_b_send(parent_ctx, binding, table,
1146                                        credentials, ev, lp_ctx);
1147         return dcerpc_pipe_connect_b_recv(c, parent_ctx, pp);
1148 }
1149
1150
1151 struct pipe_conn_state {
1152         struct dcerpc_pipe *pipe;
1153 };
1154
1155
1156 static void continue_pipe_connect_b(struct composite_context *ctx);
1157
1158
1159 /*
1160   Initiate rpc connection to a rpc pipe, using the specified string
1161   binding to determine the endpoint and options.
1162   The string is to be parsed to a binding structure first.
1163 */
1164 _PUBLIC_ struct composite_context* dcerpc_pipe_connect_send(TALLOC_CTX *parent_ctx,
1165                                                    const char *binding,
1166                                                    const struct ndr_interface_table *table,
1167                                                    struct cli_credentials *credentials,
1168                                                    struct tevent_context *ev, struct loadparm_context *lp_ctx)
1169 {
1170         struct composite_context *c;
1171         struct pipe_conn_state *s;
1172         struct dcerpc_binding *b;
1173         struct composite_context *pipe_conn_req;
1174
1175         /* composite context allocation and setup */
1176         c = composite_create(parent_ctx, ev);
1177         if (c == NULL) {
1178                 return NULL;
1179         }
1180
1181         s = talloc_zero(c, struct pipe_conn_state);
1182         if (composite_nomem(s, c)) return c;
1183         c->private_data = s;
1184
1185         /* parse binding string to the structure */
1186         c->status = dcerpc_parse_binding(c, binding, &b);
1187         if (!NT_STATUS_IS_OK(c->status)) {
1188                 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding));
1189                 composite_error(c, c->status);
1190                 return c;
1191         }
1192
1193         DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(c, b)));
1194
1195         /* 
1196            start connecting to a rpc pipe after binding structure
1197            is established
1198          */
1199         pipe_conn_req = dcerpc_pipe_connect_b_send(c, b, table,
1200                                                    credentials, ev, lp_ctx);
1201         composite_continue(c, pipe_conn_req, continue_pipe_connect_b, c);
1202         return c;
1203 }
1204
1205
1206 /*
1207   Stage 2 of pipe_connect: Receive result of actual pipe connect request
1208   and say if we're done ok
1209 */
1210 static void continue_pipe_connect_b(struct composite_context *ctx)
1211 {
1212         struct composite_context *c = talloc_get_type(ctx->async.private_data,
1213                                                       struct composite_context);
1214         struct pipe_conn_state *s = talloc_get_type(c->private_data,
1215                                                     struct pipe_conn_state);
1216
1217         c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->pipe);
1218         talloc_steal(s, s->pipe);
1219         if (!composite_is_ok(c)) return;
1220
1221         composite_done(c);
1222 }
1223
1224
1225 /*
1226   Receive result of pipe connect (using binding string) request
1227   and return connected pipe structure.
1228 */
1229 NTSTATUS dcerpc_pipe_connect_recv(struct composite_context *c,
1230                                   TALLOC_CTX *mem_ctx,
1231                                   struct dcerpc_pipe **pp)
1232 {
1233         NTSTATUS status;
1234         struct pipe_conn_state *s;
1235
1236         status = composite_wait(c);
1237         if (NT_STATUS_IS_OK(status)) {
1238                 s = talloc_get_type(c->private_data, struct pipe_conn_state);
1239                 *pp = talloc_steal(mem_ctx, s->pipe);
1240         }
1241         talloc_free(c);
1242         return status;
1243 }
1244
1245
1246 /*
1247   Open a rpc connection to a rpc pipe, using the specified string
1248   binding to determine the endpoint and options - sync version
1249 */
1250 _PUBLIC_ NTSTATUS dcerpc_pipe_connect(TALLOC_CTX *parent_ctx, 
1251                              struct dcerpc_pipe **pp, 
1252                              const char *binding,
1253                              const struct ndr_interface_table *table,
1254                              struct cli_credentials *credentials,
1255                              struct tevent_context *ev,
1256                              struct loadparm_context *lp_ctx)
1257 {
1258         struct composite_context *c;
1259         c = dcerpc_pipe_connect_send(parent_ctx, binding, 
1260                                      table, credentials, ev, lp_ctx);
1261         return dcerpc_pipe_connect_recv(c, parent_ctx, pp);
1262 }
1263