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/>.
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
;
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;
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
);
100 conn
= t
->session
->transport
->conn
;
101 session
= t
->session
->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
,
108 DCERPC_REQUEST_TIMEOUT
* 1000,
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
;
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
;
139 /* prepare smb connection parameters: we're connecting to IPC$ share on
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;
168 conn
->in
.fallback_to_anonymous
= false;
171 /* send smb connect request */
172 conn_req
= smb_composite_connect_send(conn
, s
->io
.conn
,
175 if (composite_nomem(conn_req
, c
)) return c
;
177 composite_continue(c
, conn_req
, continue_smb_connect
, 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
);
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;
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
);
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
);
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
);
243 conn
= t
->session
->transport
->conn
;
244 session
= t
->session
->smbXcli
;
247 /* send named pipe open request */
248 open_req
= dcerpc_pipe_open_smb_send(s
->io
.conn
,
250 DCERPC_REQUEST_TIMEOUT
* 1000,
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(
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
;
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
;
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
,
301 lpcfg_parm_string_list(mem_ctx
, lp_ctx
, NULL
, "smb2", "ports", NULL
),
305 0, /* previous_session_id */
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
);
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
);
327 struct pipe_ip_tcp_state
{
328 struct dcerpc_pipe_connect io
;
329 const char *localaddr
;
331 const char *target_hostname
;
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
,
355 if (!composite_is_ok(c
)) return;
357 c
->status
= dcerpc_binding_set_string_option(s
->io
.binding
,
360 if (!composite_is_ok(c
)) return;
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
;
386 /* store input parameters in state structure */
388 s
->localaddr
= dcerpc_binding_get_string_option(io
->binding
,
390 s
->host
= dcerpc_binding_get_string_option(io
->binding
, "host");
391 s
->target_hostname
= dcerpc_binding_get_string_option(io
->binding
,
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
);
400 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
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
);
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
);
424 struct pipe_unix_state
{
425 struct dcerpc_pipe_connect io
;
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;
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
;
465 /* prepare pipe open parameters and store them in state structure
466 also, verify whether biding endpoint is not null */
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
);
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
);
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
);
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;
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
;
536 /* store input parameters in state structure */
539 endpoint
= dcerpc_binding_get_string_option(io
->binding
, "endpoint");
540 if (endpoint
== NULL
) {
541 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
545 /* send pipe open request */
546 pipe_req
= dcerpc_pipe_open_pipe_send(s
->io
.conn
,
549 composite_continue(c
, pipe_req
, continue_pipe_open_ncalrpc
, 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
);
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
;
623 /* dcerpc pipe connect input parameters */
625 pc
.conn
= s
->pipe
->conn
;
626 pc
.binding
= s
->binding
;
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 */
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
);
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
);
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
);
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
);
663 pc
.ncalrpc
.dir
= lpcfg_ncalrpc_dir(s
->lp_ctx
);
664 c
->status
= dcerpc_binding_set_string_option(s
->binding
, "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
);
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
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
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
)) {
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;
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
);
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
);
839 s
= talloc_zero(c
, struct pipe_connect_state
);
840 if (composite_nomem(s
, c
)) return c
;
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
;
854 s
->credentials
= credentials
;
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
);
870 endpoint
= dcerpc_binding_get_string_option(s
->binding
, "endpoint");
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
,
882 composite_continue(c
, binding_req
, continue_map_binding
, c
);
886 continue_connect(c
, s
);
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
)
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
);
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
,
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
);
962 s
= talloc_zero(c
, struct pipe_conn_state
);
963 if (composite_nomem(s
, c
)) return c
;
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
);
974 DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(c
, b
)));
977 start connecting to a rpc pipe after binding structure
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
);
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;
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
)
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
);
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
);