s4:librpc/rpc: use DCERPC_REQUEST_TIMEOUT for smb opens
[Samba/wip.git] / source4 / librpc / rpc / dcerpc_connect.c
blobd9daa7dee251dd2a78d8c2ab30ac975d0156dd2a
1 /*
2 Unix SMB/CIFS implementation.
4 dcerpc connect functions
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
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.
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.
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/>.
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"
39 struct dcerpc_pipe_connect {
40 struct dcecli_connection *conn;
41 struct dcerpc_binding *binding;
42 const char *pipe_name;
43 const struct ndr_interface_table *interface;
44 struct cli_credentials *creds;
45 struct resolve_context *resolve_ctx;
46 struct {
47 const char *dir;
48 } ncalrpc;
51 struct pipe_np_smb_state {
52 struct smb_composite_connect conn;
53 struct dcerpc_pipe_connect io;
58 Stage 3 of ncacn_np_smb: Named pipe opened (or not)
60 static void continue_pipe_open_smb(struct composite_context *ctx)
62 struct composite_context *c = talloc_get_type(ctx->async.private_data,
63 struct composite_context);
65 /* receive result of named pipe open request on smb */
66 c->status = dcerpc_pipe_open_smb_recv(ctx);
67 if (!composite_is_ok(c)) return;
69 composite_done(c);
74 Stage 2 of ncacn_np_smb: Open a named pipe after successful smb connection
76 static void continue_smb_connect(struct composite_context *ctx)
78 struct composite_context *open_ctx;
79 struct composite_context *c = talloc_get_type(ctx->async.private_data,
80 struct composite_context);
81 struct pipe_np_smb_state *s = talloc_get_type(c->private_data,
82 struct pipe_np_smb_state);
83 struct smbcli_tree *t;
84 struct smbXcli_conn *conn;
85 struct smbXcli_session *session;
86 struct smbXcli_tcon *tcon;
88 /* receive result of smb connect request */
89 c->status = smb_composite_connect_recv(ctx, s->io.conn);
90 if (!composite_is_ok(c)) return;
92 /* prepare named pipe open parameters */
93 s->io.pipe_name = dcerpc_binding_get_string_option(s->io.binding, "endpoint");
94 if (s->io.pipe_name == NULL) {
95 composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
96 return;
99 t = s->conn.out.tree;
100 conn = t->session->transport->conn;
101 session = t->session->smbXcli;
102 tcon = t->smbXcli;
103 smb1cli_tcon_set_id(tcon, t->tid);
105 /* send named pipe open request */
106 open_ctx = dcerpc_pipe_open_smb_send(s->io.conn,
107 conn, session, tcon,
108 DCERPC_REQUEST_TIMEOUT * 1000,
109 s->io.pipe_name);
110 if (composite_nomem(open_ctx, c)) return;
112 composite_continue(c, open_ctx, continue_pipe_open_smb, c);
117 Initiate async open of a rpc connection to a rpc pipe on SMB using
118 the binding structure to determine the endpoint and options
120 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)
122 struct composite_context *c;
123 struct pipe_np_smb_state *s;
124 struct composite_context *conn_req;
125 struct smb_composite_connect *conn;
126 uint32_t flags;
128 /* composite context allocation and setup */
129 c = composite_create(mem_ctx, io->conn->event_ctx);
130 if (c == NULL) return NULL;
132 s = talloc_zero(c, struct pipe_np_smb_state);
133 if (composite_nomem(s, c)) return c;
134 c->private_data = s;
136 s->io = *io;
137 conn = &s->conn;
139 /* prepare smb connection parameters: we're connecting to IPC$ share on
140 remote rpc server */
141 conn->in.dest_host = dcerpc_binding_get_string_option(s->io.binding, "host");
142 conn->in.dest_ports = lpcfg_smb_ports(lp_ctx);
143 conn->in.called_name =
144 dcerpc_binding_get_string_option(s->io.binding, "target_hostname");
145 if (conn->in.called_name == NULL) {
146 conn->in.called_name = "*SMBSERVER";
148 conn->in.socket_options = lpcfg_socket_options(lp_ctx);
149 conn->in.service = "IPC$";
150 conn->in.service_type = NULL;
151 conn->in.workgroup = lpcfg_workgroup(lp_ctx);
152 conn->in.gensec_settings = lpcfg_gensec_settings(conn, lp_ctx);
154 lpcfg_smbcli_options(lp_ctx, &conn->in.options);
155 lpcfg_smbcli_session_options(lp_ctx, &conn->in.session_options);
158 * provide proper credentials - user supplied, but allow a
159 * fallback to anonymous if this is an schannel connection
160 * (might be NT4 not allowing machine logins at session
161 * setup) or if asked to do so by the caller (perhaps a SAMR password change?)
163 s->conn.in.credentials = s->io.creds;
164 flags = dcerpc_binding_get_flags(s->io.binding);
165 if (flags & (DCERPC_SCHANNEL|DCERPC_ANON_FALLBACK)) {
166 conn->in.fallback_to_anonymous = true;
167 } else {
168 conn->in.fallback_to_anonymous = false;
171 /* send smb connect request */
172 conn_req = smb_composite_connect_send(conn, s->io.conn,
173 s->io.resolve_ctx,
174 c->event_ctx);
175 if (composite_nomem(conn_req, c)) return c;
177 composite_continue(c, conn_req, continue_smb_connect, c);
178 return c;
183 Receive result of a rpc connection to a rpc pipe on SMB
185 static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb_recv(struct composite_context *c)
187 NTSTATUS status = composite_wait(c);
189 talloc_free(c);
190 return status;
194 struct pipe_np_smb2_state {
195 struct dcerpc_pipe_connect io;
200 Stage 3 of ncacn_np_smb: Named pipe opened (or not)
202 static void continue_pipe_open_smb2(struct composite_context *ctx)
204 struct composite_context *c = talloc_get_type(ctx->async.private_data,
205 struct composite_context);
207 /* receive result of named pipe open request on smb2 */
208 c->status = dcerpc_pipe_open_smb_recv(ctx);
209 if (!composite_is_ok(c)) return;
211 composite_done(c);
216 Stage 2 of ncacn_np_smb2: Open a named pipe after successful smb2 connection
218 static void continue_smb2_connect(struct tevent_req *subreq)
220 struct composite_context *open_req;
221 struct composite_context *c =
222 tevent_req_callback_data(subreq,
223 struct composite_context);
224 struct pipe_np_smb2_state *s = talloc_get_type(c->private_data,
225 struct pipe_np_smb2_state);
226 struct smb2_tree *t;
227 struct smbXcli_conn *conn;
228 struct smbXcli_session *session;
229 struct smbXcli_tcon *tcon;
231 /* receive result of smb2 connect request */
232 c->status = smb2_connect_recv(subreq, s->io.conn, &t);
233 TALLOC_FREE(subreq);
234 if (!composite_is_ok(c)) return;
236 /* prepare named pipe open parameters */
237 s->io.pipe_name = dcerpc_binding_get_string_option(s->io.binding, "endpoint");
238 if (s->io.pipe_name == NULL) {
239 composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
240 return;
243 conn = t->session->transport->conn;
244 session = t->session->smbXcli;
245 tcon = t->smbXcli;
247 /* send named pipe open request */
248 open_req = dcerpc_pipe_open_smb_send(s->io.conn,
249 conn, session, tcon,
250 DCERPC_REQUEST_TIMEOUT * 1000,
251 s->io.pipe_name);
252 if (composite_nomem(open_req, c)) return;
254 composite_continue(c, open_req, continue_pipe_open_smb2, c);
259 Initiate async open of a rpc connection request on SMB2 using
260 the binding structure to determine the endpoint and options
262 static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send(
263 TALLOC_CTX *mem_ctx,
264 struct dcerpc_pipe_connect *io,
265 struct loadparm_context *lp_ctx)
267 struct composite_context *c;
268 struct pipe_np_smb2_state *s;
269 struct tevent_req *subreq;
270 struct smbcli_options options;
271 const char *host;
272 uint32_t flags;
274 /* composite context allocation and setup */
275 c = composite_create(mem_ctx, io->conn->event_ctx);
276 if (c == NULL) return NULL;
278 s = talloc_zero(c, struct pipe_np_smb2_state);
279 if (composite_nomem(s, c)) return c;
280 c->private_data = s;
282 s->io = *io;
284 host = dcerpc_binding_get_string_option(s->io.binding, "host");
285 flags = dcerpc_binding_get_flags(s->io.binding);
288 * provide proper credentials - user supplied or anonymous in case this is
289 * schannel connection
291 if (flags & DCERPC_SCHANNEL) {
292 s->io.creds = cli_credentials_init_anon(mem_ctx);
293 if (composite_nomem(s->io.creds, c)) return c;
296 lpcfg_smbcli_options(lp_ctx, &options);
298 /* send smb2 connect request */
299 subreq = smb2_connect_send(s, c->event_ctx,
300 host,
301 lpcfg_parm_string_list(mem_ctx, lp_ctx, NULL, "smb2", "ports", NULL),
302 "IPC$",
303 s->io.resolve_ctx,
304 s->io.creds,
305 0, /* previous_session_id */
306 &options,
307 lpcfg_socket_options(lp_ctx),
308 lpcfg_gensec_settings(mem_ctx, lp_ctx));
309 if (composite_nomem(subreq, c)) return c;
310 tevent_req_set_callback(subreq, continue_smb2_connect, c);
311 return c;
316 Receive result of a rpc connection to a rpc pipe on SMB2
318 static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb2_recv(struct composite_context *c)
320 NTSTATUS status = composite_wait(c);
322 talloc_free(c);
323 return status;
327 struct pipe_ip_tcp_state {
328 struct dcerpc_pipe_connect io;
329 const char *localaddr;
330 const char *host;
331 const char *target_hostname;
332 uint32_t port;
337 Stage 2 of ncacn_ip_tcp: rpc pipe opened (or not)
339 static void continue_pipe_open_ncacn_ip_tcp(struct composite_context *ctx)
341 struct composite_context *c = talloc_get_type(ctx->async.private_data,
342 struct composite_context);
343 struct pipe_ip_tcp_state *s = talloc_get_type(c->private_data,
344 struct pipe_ip_tcp_state);
345 char *localaddr = NULL;
346 char *remoteaddr = NULL;
348 /* receive result of named pipe open request on tcp/ip */
349 c->status = dcerpc_pipe_open_tcp_recv(ctx, s, &localaddr, &remoteaddr);
350 if (!composite_is_ok(c)) return;
352 c->status = dcerpc_binding_set_string_option(s->io.binding,
353 "localaddress",
354 localaddr);
355 if (!composite_is_ok(c)) return;
357 c->status = dcerpc_binding_set_string_option(s->io.binding,
358 "host",
359 remoteaddr);
360 if (!composite_is_ok(c)) return;
362 composite_done(c);
367 Initiate async open of a rpc connection to a rpc pipe on TCP/IP using
368 the binding structure to determine the endpoint and options
370 static struct composite_context* dcerpc_pipe_connect_ncacn_ip_tcp_send(TALLOC_CTX *mem_ctx,
371 struct dcerpc_pipe_connect *io)
373 struct composite_context *c;
374 struct pipe_ip_tcp_state *s;
375 struct composite_context *pipe_req;
376 const char *endpoint;
378 /* composite context allocation and setup */
379 c = composite_create(mem_ctx, io->conn->event_ctx);
380 if (c == NULL) return NULL;
382 s = talloc_zero(c, struct pipe_ip_tcp_state);
383 if (composite_nomem(s, c)) return c;
384 c->private_data = s;
386 /* store input parameters in state structure */
387 s->io = *io;
388 s->localaddr = dcerpc_binding_get_string_option(io->binding,
389 "localaddress");
390 s->host = dcerpc_binding_get_string_option(io->binding, "host");
391 s->target_hostname = dcerpc_binding_get_string_option(io->binding,
392 "target_hostname");
393 endpoint = dcerpc_binding_get_string_option(io->binding, "endpoint");
394 /* port number is a binding endpoint here */
395 if (endpoint != NULL) {
396 s->port = atoi(endpoint);
399 if (s->port == 0) {
400 composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
401 return c;
404 /* send pipe open request on tcp/ip */
405 pipe_req = dcerpc_pipe_open_tcp_send(s->io.conn, s->localaddr, s->host, s->target_hostname,
406 s->port, io->resolve_ctx);
407 composite_continue(c, pipe_req, continue_pipe_open_ncacn_ip_tcp, c);
408 return c;
413 Receive result of a rpc connection to a rpc pipe on TCP/IP
415 static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp_recv(struct composite_context *c)
417 NTSTATUS status = composite_wait(c);
419 talloc_free(c);
420 return status;
424 struct pipe_unix_state {
425 struct dcerpc_pipe_connect io;
426 const char *path;
431 Stage 2 of ncacn_unix: rpc pipe opened (or not)
433 static void continue_pipe_open_ncacn_unix_stream(struct composite_context *ctx)
435 struct composite_context *c = talloc_get_type(ctx->async.private_data,
436 struct composite_context);
438 /* receive result of pipe open request on unix socket */
439 c->status = dcerpc_pipe_open_unix_stream_recv(ctx);
440 if (!composite_is_ok(c)) return;
442 composite_done(c);
447 Initiate async open of a rpc connection to a rpc pipe on unix socket using
448 the binding structure to determine the endpoint and options
450 static struct composite_context* dcerpc_pipe_connect_ncacn_unix_stream_send(TALLOC_CTX *mem_ctx,
451 struct dcerpc_pipe_connect *io)
453 struct composite_context *c;
454 struct pipe_unix_state *s;
455 struct composite_context *pipe_req;
457 /* composite context allocation and setup */
458 c = composite_create(mem_ctx, io->conn->event_ctx);
459 if (c == NULL) return NULL;
461 s = talloc_zero(c, struct pipe_unix_state);
462 if (composite_nomem(s, c)) return c;
463 c->private_data = s;
465 /* prepare pipe open parameters and store them in state structure
466 also, verify whether biding endpoint is not null */
467 s->io = *io;
469 s->path = dcerpc_binding_get_string_option(io->binding, "endpoint");
470 if (s->path == NULL) {
471 composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
472 return c;
475 /* send pipe open request on unix socket */
476 pipe_req = dcerpc_pipe_open_unix_stream_send(s->io.conn, s->path);
477 composite_continue(c, pipe_req, continue_pipe_open_ncacn_unix_stream, c);
478 return c;
483 Receive result of a rpc connection to a pipe on unix socket
485 static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream_recv(struct composite_context *c)
487 NTSTATUS status = composite_wait(c);
489 talloc_free(c);
490 return status;
494 struct pipe_ncalrpc_state {
495 struct dcerpc_pipe_connect io;
498 static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c);
501 Stage 2 of ncalrpc: rpc pipe opened (or not)
503 static void continue_pipe_open_ncalrpc(struct composite_context *ctx)
505 struct composite_context *c = talloc_get_type(ctx->async.private_data,
506 struct composite_context);
508 /* receive result of pipe open request on ncalrpc */
509 c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx);
510 if (!composite_is_ok(c)) return;
512 composite_done(c);
517 Initiate async open of a rpc connection request on NCALRPC using
518 the binding structure to determine the endpoint and options
520 static struct composite_context* dcerpc_pipe_connect_ncalrpc_send(TALLOC_CTX *mem_ctx,
521 struct dcerpc_pipe_connect *io)
523 struct composite_context *c;
524 struct pipe_ncalrpc_state *s;
525 struct composite_context *pipe_req;
526 const char *endpoint;
528 /* composite context allocation and setup */
529 c = composite_create(mem_ctx, io->conn->event_ctx);
530 if (c == NULL) return NULL;
532 s = talloc_zero(c, struct pipe_ncalrpc_state);
533 if (composite_nomem(s, c)) return c;
534 c->private_data = s;
536 /* store input parameters in state structure */
537 s->io = *io;
539 endpoint = dcerpc_binding_get_string_option(io->binding, "endpoint");
540 if (endpoint == NULL) {
541 composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
542 return c;
545 /* send pipe open request */
546 pipe_req = dcerpc_pipe_open_pipe_send(s->io.conn,
547 s->io.ncalrpc.dir,
548 endpoint);
549 composite_continue(c, pipe_req, continue_pipe_open_ncalrpc, c);
550 return c;
555 Receive result of a rpc connection to a rpc pipe on NCALRPC
557 static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c)
559 NTSTATUS status = composite_wait(c);
561 talloc_free(c);
562 return status;
566 struct pipe_connect_state {
567 struct dcerpc_pipe *pipe;
568 struct dcerpc_binding *binding;
569 const struct ndr_interface_table *table;
570 struct cli_credentials *credentials;
571 struct loadparm_context *lp_ctx;
575 static void continue_map_binding(struct composite_context *ctx);
576 static void continue_connect(struct composite_context *c, struct pipe_connect_state *s);
577 static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx);
578 static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx);
579 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx);
580 static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx);
581 static void continue_pipe_connect_ncalrpc(struct composite_context *ctx);
582 static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s);
583 static void continue_pipe_auth(struct composite_context *ctx);
587 Stage 2 of pipe_connect_b: Receive result of endpoint mapping
589 static void continue_map_binding(struct composite_context *ctx)
591 struct composite_context *c = talloc_get_type(ctx->async.private_data,
592 struct composite_context);
593 struct pipe_connect_state *s = talloc_get_type(c->private_data,
594 struct pipe_connect_state);
595 const char *endpoint;
597 c->status = dcerpc_epm_map_binding_recv(ctx);
598 if (!composite_is_ok(c)) return;
600 endpoint = dcerpc_binding_get_string_option(s->binding, "endpoint");
601 DEBUG(4,("Mapped to DCERPC endpoint %s\n", endpoint));
603 continue_connect(c, s);
608 Stage 2 of pipe_connect_b: Continue connection after endpoint is known
610 static void continue_connect(struct composite_context *c, struct pipe_connect_state *s)
612 struct dcerpc_pipe_connect pc;
614 /* potential exits to another stage by sending an async request */
615 struct composite_context *ncacn_np_smb2_req;
616 struct composite_context *ncacn_np_smb_req;
617 struct composite_context *ncacn_ip_tcp_req;
618 struct composite_context *ncacn_unix_req;
619 struct composite_context *ncalrpc_req;
620 enum dcerpc_transport_t transport;
621 uint32_t flags;
623 /* dcerpc pipe connect input parameters */
624 ZERO_STRUCT(pc);
625 pc.conn = s->pipe->conn;
626 pc.binding = s->binding;
627 pc.pipe_name = NULL;
628 pc.interface = s->table;
629 pc.creds = s->credentials;
630 pc.resolve_ctx = lpcfg_resolve_context(s->lp_ctx);
632 transport = dcerpc_binding_get_transport(s->binding);
633 flags = dcerpc_binding_get_flags(s->binding);
635 /* connect dcerpc pipe depending on required transport */
636 switch (transport) {
637 case NCACN_NP:
638 if (flags & DCERPC_SMB2) {
639 /* new varient of SMB a.k.a. SMB2 */
640 ncacn_np_smb2_req = dcerpc_pipe_connect_ncacn_np_smb2_send(c, &pc, s->lp_ctx);
641 composite_continue(c, ncacn_np_smb2_req, continue_pipe_connect_ncacn_np_smb2, c);
642 return;
644 } else {
645 /* good old ordinary SMB */
646 ncacn_np_smb_req = dcerpc_pipe_connect_ncacn_np_smb_send(c, &pc, s->lp_ctx);
647 composite_continue(c, ncacn_np_smb_req, continue_pipe_connect_ncacn_np_smb, c);
648 return;
650 break;
652 case NCACN_IP_TCP:
653 ncacn_ip_tcp_req = dcerpc_pipe_connect_ncacn_ip_tcp_send(c, &pc);
654 composite_continue(c, ncacn_ip_tcp_req, continue_pipe_connect_ncacn_ip_tcp, c);
655 return;
657 case NCACN_UNIX_STREAM:
658 ncacn_unix_req = dcerpc_pipe_connect_ncacn_unix_stream_send(c, &pc);
659 composite_continue(c, ncacn_unix_req, continue_pipe_connect_ncacn_unix, c);
660 return;
662 case NCALRPC:
663 pc.ncalrpc.dir = lpcfg_ncalrpc_dir(s->lp_ctx);
664 c->status = dcerpc_binding_set_string_option(s->binding, "ncalrpc_dir",
665 pc.ncalrpc.dir);
666 if (!composite_is_ok(c)) return;
667 ncalrpc_req = dcerpc_pipe_connect_ncalrpc_send(c, &pc);
668 composite_continue(c, ncalrpc_req, continue_pipe_connect_ncalrpc, c);
669 return;
671 default:
672 /* looks like a transport we don't support now */
673 composite_error(c, NT_STATUS_NOT_SUPPORTED);
679 Stage 3 of pipe_connect_b: Receive result of pipe connect request on
680 named pipe on smb2
682 static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx)
684 struct composite_context *c = talloc_get_type(ctx->async.private_data,
685 struct composite_context);
686 struct pipe_connect_state *s = talloc_get_type(c->private_data,
687 struct pipe_connect_state);
689 c->status = dcerpc_pipe_connect_ncacn_np_smb2_recv(ctx);
690 if (!composite_is_ok(c)) return;
692 continue_pipe_connect(c, s);
697 Stage 3 of pipe_connect_b: Receive result of pipe connect request on
698 named pipe on smb
700 static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx)
702 struct composite_context *c = talloc_get_type(ctx->async.private_data,
703 struct composite_context);
704 struct pipe_connect_state *s = talloc_get_type(c->private_data,
705 struct pipe_connect_state);
707 c->status = dcerpc_pipe_connect_ncacn_np_smb_recv(ctx);
708 if (!composite_is_ok(c)) return;
710 continue_pipe_connect(c, s);
715 Stage 3 of pipe_connect_b: Receive result of pipe connect request on tcp/ip
717 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx)
719 struct composite_context *c = talloc_get_type(ctx->async.private_data,
720 struct composite_context);
721 struct pipe_connect_state *s = talloc_get_type(c->private_data,
722 struct pipe_connect_state);
724 c->status = dcerpc_pipe_connect_ncacn_ip_tcp_recv(ctx);
725 if (!composite_is_ok(c)) return;
727 continue_pipe_connect(c, s);
732 Stage 3 of pipe_connect_b: Receive result of pipe connect request on unix socket
734 static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx)
736 struct composite_context *c = talloc_get_type(ctx->async.private_data,
737 struct composite_context);
738 struct pipe_connect_state *s = talloc_get_type(c->private_data,
739 struct pipe_connect_state);
741 c->status = dcerpc_pipe_connect_ncacn_unix_stream_recv(ctx);
742 if (!composite_is_ok(c)) return;
744 continue_pipe_connect(c, s);
749 Stage 3 of pipe_connect_b: Receive result of pipe connect request on local rpc
751 static void continue_pipe_connect_ncalrpc(struct composite_context *ctx)
753 struct composite_context *c = talloc_get_type(ctx->async.private_data,
754 struct composite_context);
755 struct pipe_connect_state *s = talloc_get_type(c->private_data,
756 struct pipe_connect_state);
758 c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx);
759 if (!composite_is_ok(c)) return;
761 continue_pipe_connect(c, s);
766 Stage 4 of pipe_connect_b: Start an authentication on connected dcerpc pipe
767 depending on credentials and binding flags passed.
769 static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s)
771 struct composite_context *auth_bind_req;
773 s->pipe->binding = dcerpc_binding_dup(s->pipe, s->binding);
774 if (composite_nomem(s->pipe->binding, c)) {
775 return;
778 auth_bind_req = dcerpc_pipe_auth_send(s->pipe, s->binding, s->table,
779 s->credentials, s->lp_ctx);
780 composite_continue(c, auth_bind_req, continue_pipe_auth, c);
785 Stage 5 of pipe_connect_b: Receive result of pipe authentication request
786 and say if all went ok
788 static void continue_pipe_auth(struct composite_context *ctx)
790 struct composite_context *c = talloc_get_type(ctx->async.private_data,
791 struct composite_context);
792 struct pipe_connect_state *s = talloc_get_type(c->private_data, struct pipe_connect_state);
794 c->status = dcerpc_pipe_auth_recv(ctx, s, &s->pipe);
795 if (!composite_is_ok(c)) return;
797 composite_done(c);
802 handle timeouts of a dcerpc connect
804 static void dcerpc_connect_timeout_handler(struct tevent_context *ev, struct tevent_timer *te,
805 struct timeval t, void *private_data)
807 struct composite_context *c = talloc_get_type_abort(private_data,
808 struct composite_context);
809 struct pipe_connect_state *s = talloc_get_type_abort(c->private_data, struct pipe_connect_state);
810 if (!s->pipe->inhibit_timeout_processing) {
811 composite_error(c, NT_STATUS_IO_TIMEOUT);
812 } else {
813 s->pipe->timed_out = true;
818 start a request to open a rpc connection to a rpc pipe, using
819 specified binding structure to determine the endpoint and options
821 _PUBLIC_ struct composite_context* dcerpc_pipe_connect_b_send(TALLOC_CTX *parent_ctx,
822 const struct dcerpc_binding *binding,
823 const struct ndr_interface_table *table,
824 struct cli_credentials *credentials,
825 struct tevent_context *ev,
826 struct loadparm_context *lp_ctx)
828 struct composite_context *c;
829 struct pipe_connect_state *s;
830 enum dcerpc_transport_t transport;
831 const char *endpoint = NULL;
833 /* composite context allocation and setup */
834 c = composite_create(parent_ctx, ev);
835 if (c == NULL) {
836 return NULL;
839 s = talloc_zero(c, struct pipe_connect_state);
840 if (composite_nomem(s, c)) return c;
841 c->private_data = s;
843 /* initialise dcerpc pipe structure */
844 s->pipe = dcerpc_pipe_init(c, ev);
845 if (composite_nomem(s->pipe, c)) return c;
847 if (DEBUGLEVEL >= 10)
848 s->pipe->conn->packet_log_dir = lpcfg_lock_directory(lp_ctx);
850 /* store parameters in state structure */
851 s->binding = dcerpc_binding_dup(s, binding);
852 if (composite_nomem(s->binding, c)) return c;
853 s->table = table;
854 s->credentials = credentials;
855 s->lp_ctx = lp_ctx;
857 s->pipe->timed_out = false;
858 s->pipe->inhibit_timeout_processing = false;
860 tevent_add_timer(c->event_ctx, c,
861 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
862 dcerpc_connect_timeout_handler, c);
864 transport = dcerpc_binding_get_transport(s->binding);
866 switch (transport) {
867 case NCACN_NP:
868 case NCACN_IP_TCP:
869 case NCALRPC:
870 endpoint = dcerpc_binding_get_string_option(s->binding, "endpoint");
871 break;
872 default:
873 break;
876 if (endpoint == NULL) {
877 struct composite_context *binding_req;
879 binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table,
880 s->pipe->conn->event_ctx,
881 s->lp_ctx);
882 composite_continue(c, binding_req, continue_map_binding, c);
883 return c;
886 continue_connect(c, s);
887 return c;
892 receive result of a request to open a rpc connection to a rpc pipe
894 _PUBLIC_ NTSTATUS dcerpc_pipe_connect_b_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
895 struct dcerpc_pipe **p)
897 NTSTATUS status;
898 struct pipe_connect_state *s;
900 status = composite_wait(c);
902 if (NT_STATUS_IS_OK(status)) {
903 s = talloc_get_type(c->private_data, struct pipe_connect_state);
904 talloc_steal(mem_ctx, s->pipe);
905 *p = s->pipe;
907 talloc_free(c);
908 return status;
913 open a rpc connection to a rpc pipe, using the specified
914 binding structure to determine the endpoint and options - sync version
916 _PUBLIC_ NTSTATUS dcerpc_pipe_connect_b(TALLOC_CTX *parent_ctx,
917 struct dcerpc_pipe **pp,
918 const struct dcerpc_binding *binding,
919 const struct ndr_interface_table *table,
920 struct cli_credentials *credentials,
921 struct tevent_context *ev,
922 struct loadparm_context *lp_ctx)
924 struct composite_context *c;
926 c = dcerpc_pipe_connect_b_send(parent_ctx, binding, table,
927 credentials, ev, lp_ctx);
928 return dcerpc_pipe_connect_b_recv(c, parent_ctx, pp);
932 struct pipe_conn_state {
933 struct dcerpc_pipe *pipe;
937 static void continue_pipe_connect_b(struct composite_context *ctx);
941 Initiate rpc connection to a rpc pipe, using the specified string
942 binding to determine the endpoint and options.
943 The string is to be parsed to a binding structure first.
945 _PUBLIC_ struct composite_context* dcerpc_pipe_connect_send(TALLOC_CTX *parent_ctx,
946 const char *binding,
947 const struct ndr_interface_table *table,
948 struct cli_credentials *credentials,
949 struct tevent_context *ev, struct loadparm_context *lp_ctx)
951 struct composite_context *c;
952 struct pipe_conn_state *s;
953 struct dcerpc_binding *b;
954 struct composite_context *pipe_conn_req;
956 /* composite context allocation and setup */
957 c = composite_create(parent_ctx, ev);
958 if (c == NULL) {
959 return NULL;
962 s = talloc_zero(c, struct pipe_conn_state);
963 if (composite_nomem(s, c)) return c;
964 c->private_data = s;
966 /* parse binding string to the structure */
967 c->status = dcerpc_parse_binding(c, binding, &b);
968 if (!NT_STATUS_IS_OK(c->status)) {
969 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding));
970 composite_error(c, c->status);
971 return c;
974 DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(c, b)));
977 start connecting to a rpc pipe after binding structure
978 is established
980 pipe_conn_req = dcerpc_pipe_connect_b_send(c, b, table,
981 credentials, ev, lp_ctx);
982 composite_continue(c, pipe_conn_req, continue_pipe_connect_b, c);
983 return c;
988 Stage 2 of pipe_connect: Receive result of actual pipe connect request
989 and say if we're done ok
991 static void continue_pipe_connect_b(struct composite_context *ctx)
993 struct composite_context *c = talloc_get_type(ctx->async.private_data,
994 struct composite_context);
995 struct pipe_conn_state *s = talloc_get_type(c->private_data,
996 struct pipe_conn_state);
998 c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->pipe);
999 talloc_steal(s, s->pipe);
1000 if (!composite_is_ok(c)) return;
1002 composite_done(c);
1007 Receive result of pipe connect (using binding string) request
1008 and return connected pipe structure.
1010 NTSTATUS dcerpc_pipe_connect_recv(struct composite_context *c,
1011 TALLOC_CTX *mem_ctx,
1012 struct dcerpc_pipe **pp)
1014 NTSTATUS status;
1015 struct pipe_conn_state *s;
1017 status = composite_wait(c);
1018 if (NT_STATUS_IS_OK(status)) {
1019 s = talloc_get_type(c->private_data, struct pipe_conn_state);
1020 *pp = talloc_steal(mem_ctx, s->pipe);
1022 talloc_free(c);
1023 return status;
1028 Open a rpc connection to a rpc pipe, using the specified string
1029 binding to determine the endpoint and options - sync version
1031 _PUBLIC_ NTSTATUS dcerpc_pipe_connect(TALLOC_CTX *parent_ctx,
1032 struct dcerpc_pipe **pp,
1033 const char *binding,
1034 const struct ndr_interface_table *table,
1035 struct cli_credentials *credentials,
1036 struct tevent_context *ev,
1037 struct loadparm_context *lp_ctx)
1039 struct composite_context *c;
1040 c = dcerpc_pipe_connect_send(parent_ctx, binding,
1041 table, credentials, ev, lp_ctx);
1042 return dcerpc_pipe_connect_recv(c, parent_ctx, pp);