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"
38 #include "libcli/http/http.h"
39 #include "lib/util/util_net.h"
41 struct dcerpc_pipe_connect
{
42 struct dcecli_connection
*conn
;
43 struct dcerpc_binding
*binding
;
44 const struct ndr_interface_table
*interface
;
45 struct cli_credentials
*creds
;
46 struct resolve_context
*resolve_ctx
;
51 struct smbXcli_conn
*conn
;
52 struct smbXcli_session
*session
;
53 struct smbXcli_tcon
*tcon
;
54 const char *pipe_name
;
58 struct pipe_np_smb_state
{
59 struct smb_composite_connect conn
;
60 struct dcerpc_pipe_connect io
;
65 Stage 3 of ncacn_np_smb: Named pipe opened (or not)
67 static void continue_pipe_open_smb(struct composite_context
*ctx
)
69 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
70 struct composite_context
);
72 /* receive result of named pipe open request on smb */
73 c
->status
= dcerpc_pipe_open_smb_recv(ctx
);
74 if (!composite_is_ok(c
)) return;
79 static void continue_smb_open(struct composite_context
*c
);
80 static void continue_smb2_connect(struct tevent_req
*subreq
);
81 static void continue_smbXcli_connect(struct tevent_req
*subreq
);
84 Stage 2 of ncacn_np_smb: Open a named pipe after successful smb connection
86 static void continue_smb_connect(struct composite_context
*ctx
)
88 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
89 struct composite_context
);
90 struct pipe_np_smb_state
*s
= talloc_get_type(c
->private_data
,
91 struct pipe_np_smb_state
);
92 struct smbcli_tree
*t
;
94 /* receive result of smb connect request */
95 c
->status
= smb_composite_connect_recv(ctx
, s
->io
.conn
);
96 if (!composite_is_ok(c
)) return;
100 /* prepare named pipe open parameters */
101 s
->io
.smb
.conn
= t
->session
->transport
->conn
;
102 s
->io
.smb
.session
= t
->session
->smbXcli
;
103 s
->io
.smb
.tcon
= t
->smbXcli
;
104 smb1cli_tcon_set_id(s
->io
.smb
.tcon
, t
->tid
);
105 s
->io
.smb
.pipe_name
= dcerpc_binding_get_string_option(s
->io
.binding
,
108 continue_smb_open(c
);
111 static void continue_smb_open(struct composite_context
*c
)
113 struct pipe_np_smb_state
*s
= talloc_get_type(c
->private_data
,
114 struct pipe_np_smb_state
);
115 struct composite_context
*open_ctx
;
117 /* send named pipe open request */
118 open_ctx
= dcerpc_pipe_open_smb_send(s
->io
.conn
,
122 DCERPC_REQUEST_TIMEOUT
* 1000,
123 s
->io
.smb
.pipe_name
);
124 if (composite_nomem(open_ctx
, c
)) return;
126 composite_continue(c
, open_ctx
, continue_pipe_open_smb
, c
);
131 Initiate async open of a rpc connection to a rpc pipe on SMB using
132 the binding structure to determine the endpoint and options
134 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
)
136 struct composite_context
*c
;
137 struct pipe_np_smb_state
*s
;
138 struct tevent_req
*subreq
= NULL
;
139 struct smb_composite_connect
*conn
;
141 const char *target_hostname
= NULL
;
142 const char *dest_address
= NULL
;
143 const char *calling_name
= NULL
;
145 /* composite context allocation and setup */
146 c
= composite_create(mem_ctx
, io
->conn
->event_ctx
);
147 if (c
== NULL
) return NULL
;
149 s
= talloc_zero(c
, struct pipe_np_smb_state
);
150 if (composite_nomem(s
, c
)) return c
;
156 if (smbXcli_conn_is_connected(s
->io
.smb
.conn
)) {
157 continue_smb_open(c
);
161 if (s
->io
.creds
== NULL
) {
162 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
166 /* prepare smb connection parameters: we're connecting to IPC$ share on
168 target_hostname
= dcerpc_binding_get_string_option(s
->io
.binding
, "target_hostname");
169 conn
->in
.dest_host
= dcerpc_binding_get_string_option(s
->io
.binding
, "host");
170 conn
->in
.dest_ports
= lpcfg_smb_ports(lp_ctx
);
171 conn
->in
.called_name
= target_hostname
;
172 if (conn
->in
.called_name
== NULL
) {
173 conn
->in
.called_name
= "*SMBSERVER";
175 conn
->in
.socket_options
= lpcfg_socket_options(lp_ctx
);
176 conn
->in
.service
= "IPC$";
177 conn
->in
.service_type
= NULL
;
178 conn
->in
.workgroup
= lpcfg_workgroup(lp_ctx
);
179 conn
->in
.gensec_settings
= lpcfg_gensec_settings(conn
, lp_ctx
);
181 lpcfg_smbcli_options(lp_ctx
, &conn
->in
.options
);
182 lpcfg_smbcli_session_options(lp_ctx
, &conn
->in
.session_options
);
185 * provide proper credentials - user supplied, but allow a
186 * fallback to anonymous if this is an schannel connection
187 * (might be NT4 not allowing machine logins at session
188 * setup) or if asked to do so by the caller (perhaps a SAMR password change?)
190 s
->conn
.in
.credentials
= s
->io
.creds
;
191 flags
= dcerpc_binding_get_flags(s
->io
.binding
);
192 if (flags
& (DCERPC_SCHANNEL
|DCERPC_ANON_FALLBACK
)) {
193 conn
->in
.fallback_to_anonymous
= true;
195 conn
->in
.fallback_to_anonymous
= false;
198 conn
->in
.options
.min_protocol
= lpcfg_client_ipc_min_protocol(lp_ctx
);
199 conn
->in
.options
.max_protocol
= lpcfg_client_ipc_max_protocol(lp_ctx
);
200 if ((flags
& DCERPC_SMB1
) && (flags
& DCERPC_SMB2
)) {
202 } else if (flags
& DCERPC_SMB2
) {
203 if (conn
->in
.options
.min_protocol
< PROTOCOL_SMB2_02
) {
204 conn
->in
.options
.min_protocol
= PROTOCOL_SMB2_02
;
206 if (conn
->in
.options
.max_protocol
< PROTOCOL_SMB2_02
) {
207 conn
->in
.options
.max_protocol
= PROTOCOL_LATEST
;
209 } else if (flags
& DCERPC_SMB1
) {
210 conn
->in
.options
.min_protocol
= PROTOCOL_NT1
;
211 conn
->in
.options
.max_protocol
= PROTOCOL_NT1
;
216 conn
->in
.options
.signing
= lpcfg_client_ipc_signing(lp_ctx
);
218 if (s
->conn
.in
.credentials
!= NULL
) {
219 calling_name
= cli_credentials_get_workstation(s
->conn
.in
.credentials
);
221 if (calling_name
== NULL
) {
222 calling_name
= "SMBCLIENT";
225 if (target_hostname
== NULL
) {
226 target_hostname
= conn
->in
.dest_host
;
229 if (conn
->in
.dest_host
!= NULL
&& is_ipaddress(conn
->in
.dest_host
)) {
230 dest_address
= conn
->in
.dest_host
;
233 subreq
= smb_connect_nego_send(s
,
237 conn
->in
.socket_options
,
242 conn
->in
.called_name
,
244 if (composite_nomem(subreq
, c
)) return c
;
245 tevent_req_set_callback(subreq
,
246 continue_smbXcli_connect
,
252 static void continue_smbXcli_connect(struct tevent_req
*subreq
)
254 struct composite_context
*c
=
255 tevent_req_callback_data(subreq
,
256 struct composite_context
);
257 struct pipe_np_smb_state
*s
=
258 talloc_get_type_abort(c
->private_data
,
259 struct pipe_np_smb_state
);
260 struct smb_composite_connect
*conn
= &s
->conn
;
261 struct composite_context
*creq
= NULL
;
262 enum protocol_types protocol
;
264 c
->status
= smb_connect_nego_recv(subreq
, s
,
265 &conn
->in
.existing_conn
);
267 if (!composite_is_ok(c
)) return;
269 protocol
= smbXcli_conn_protocol(conn
->in
.existing_conn
);
270 if (protocol
>= PROTOCOL_SMB2_02
) {
272 * continue with smb2 session setup/tree connect
273 * on the established connection.
275 subreq
= smb2_connect_send(s
, c
->event_ctx
,
280 conn
->in
.credentials
,
281 conn
->in
.fallback_to_anonymous
,
282 &conn
->in
.existing_conn
,
283 0, /* previous_session_id */
285 conn
->in
.socket_options
,
286 conn
->in
.gensec_settings
);
287 if (composite_nomem(subreq
, c
)) return;
288 tevent_req_set_callback(subreq
, continue_smb2_connect
, c
);
293 * continue with smb1 session setup/tree connect
294 * on the established connection.
296 creq
= smb_composite_connect_send(conn
, s
->io
.conn
,
299 if (composite_nomem(creq
, c
)) return;
301 composite_continue(c
, creq
, continue_smb_connect
, c
);
307 Receive result of a rpc connection to a rpc pipe on SMB
309 static NTSTATUS
dcerpc_pipe_connect_ncacn_np_smb_recv(struct composite_context
*c
)
311 NTSTATUS status
= composite_wait(c
);
318 Stage 2 of ncacn_np_smb2: Open a named pipe after successful smb2 connection
320 static void continue_smb2_connect(struct tevent_req
*subreq
)
322 struct composite_context
*c
=
323 tevent_req_callback_data(subreq
,
324 struct composite_context
);
325 struct pipe_np_smb_state
*s
= talloc_get_type(c
->private_data
,
326 struct pipe_np_smb_state
);
329 /* receive result of smb2 connect request */
330 c
->status
= smb2_connect_recv(subreq
, s
->io
.conn
, &t
);
332 if (!composite_is_ok(c
)) return;
334 s
->io
.smb
.conn
= t
->session
->transport
->conn
;
335 s
->io
.smb
.session
= t
->session
->smbXcli
;
336 s
->io
.smb
.tcon
= t
->smbXcli
;
337 s
->io
.smb
.pipe_name
= dcerpc_binding_get_string_option(s
->io
.binding
,
340 continue_smb_open(c
);
344 struct pipe_ip_tcp_state
{
345 struct dcerpc_pipe_connect io
;
346 const char *localaddr
;
348 const char *target_hostname
;
354 Stage 2 of ncacn_ip_tcp: rpc pipe opened (or not)
356 static void continue_pipe_open_ncacn_ip_tcp(struct composite_context
*ctx
)
358 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
359 struct composite_context
);
360 struct pipe_ip_tcp_state
*s
= talloc_get_type(c
->private_data
,
361 struct pipe_ip_tcp_state
);
362 char *localaddr
= NULL
;
363 char *remoteaddr
= NULL
;
365 /* receive result of named pipe open request on tcp/ip */
366 c
->status
= dcerpc_pipe_open_tcp_recv(ctx
, s
, &localaddr
, &remoteaddr
);
367 if (!composite_is_ok(c
)) return;
369 c
->status
= dcerpc_binding_set_string_option(s
->io
.binding
,
372 if (!composite_is_ok(c
)) return;
374 c
->status
= dcerpc_binding_set_string_option(s
->io
.binding
,
377 if (!composite_is_ok(c
)) return;
384 Initiate async open of a rpc connection to a rpc pipe on TCP/IP using
385 the binding structure to determine the endpoint and options
387 static struct composite_context
* dcerpc_pipe_connect_ncacn_ip_tcp_send(TALLOC_CTX
*mem_ctx
,
388 struct dcerpc_pipe_connect
*io
)
390 struct composite_context
*c
;
391 struct pipe_ip_tcp_state
*s
;
392 struct composite_context
*pipe_req
;
393 const char *endpoint
;
395 /* composite context allocation and setup */
396 c
= composite_create(mem_ctx
, io
->conn
->event_ctx
);
397 if (c
== NULL
) return NULL
;
399 s
= talloc_zero(c
, struct pipe_ip_tcp_state
);
400 if (composite_nomem(s
, c
)) return c
;
403 /* store input parameters in state structure */
405 s
->localaddr
= dcerpc_binding_get_string_option(io
->binding
,
407 s
->host
= dcerpc_binding_get_string_option(io
->binding
, "host");
408 s
->target_hostname
= dcerpc_binding_get_string_option(io
->binding
,
410 endpoint
= dcerpc_binding_get_string_option(io
->binding
, "endpoint");
411 /* port number is a binding endpoint here */
412 if (endpoint
!= NULL
) {
413 s
->port
= atoi(endpoint
);
417 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
421 /* send pipe open request on tcp/ip */
422 pipe_req
= dcerpc_pipe_open_tcp_send(s
->io
.conn
, s
->localaddr
, s
->host
, s
->target_hostname
,
423 s
->port
, io
->resolve_ctx
);
424 composite_continue(c
, pipe_req
, continue_pipe_open_ncacn_ip_tcp
, c
);
430 Receive result of a rpc connection to a rpc pipe on TCP/IP
432 static NTSTATUS
dcerpc_pipe_connect_ncacn_ip_tcp_recv(struct composite_context
*c
)
434 NTSTATUS status
= composite_wait(c
);
441 struct pipe_http_state
{
442 struct dcerpc_pipe_connect io
;
443 const char *localaddr
;
444 const char *target_hostname
;
445 const char *rpc_server
;
446 uint32_t rpc_server_port
;
448 uint32_t rpc_proxy_port
;
450 uint32_t http_proxy_port
;
453 enum http_auth_method http_auth
;
454 struct loadparm_context
*lp_ctx
;
458 Stage 2 of ncacn_http: rpc pipe opened (or not)
460 static void continue_pipe_open_ncacn_http(struct tevent_req
*subreq
)
462 struct composite_context
*c
= NULL
;
463 struct pipe_http_state
*s
= NULL
;
464 struct tstream_context
*stream
= NULL
;
465 struct tevent_queue
*queue
= NULL
;
467 c
= tevent_req_callback_data(subreq
, struct composite_context
);
468 s
= talloc_get_type(c
->private_data
, struct pipe_http_state
);
470 /* receive result of RoH connect request */
471 c
->status
= dcerpc_pipe_open_roh_recv(subreq
, s
->io
.conn
,
474 if (!composite_is_ok(c
)) return;
476 s
->io
.conn
->transport
.transport
= NCACN_HTTP
;
477 s
->io
.conn
->transport
.stream
= stream
;
478 s
->io
.conn
->transport
.write_queue
= queue
;
479 s
->io
.conn
->transport
.pending_reads
= 0;
480 s
->io
.conn
->server_name
= strupper_talloc(s
->io
.conn
,
487 Initiate async open of a rpc connection to a rpc pipe using HTTP transport,
488 and using the binding structure to determine the endpoint and options
490 static struct composite_context
* dcerpc_pipe_connect_ncacn_http_send(
491 TALLOC_CTX
*mem_ctx
, struct dcerpc_pipe_connect
*io
,
492 struct loadparm_context
*lp_ctx
)
494 struct composite_context
*c
;
495 struct pipe_http_state
*s
;
496 struct tevent_req
*subreq
;
497 const char *endpoint
;
498 const char *use_proxy
;
503 /* composite context allocation and setup */
504 c
= composite_create(mem_ctx
, io
->conn
->event_ctx
);
505 if (c
== NULL
) return NULL
;
507 s
= talloc_zero(c
, struct pipe_http_state
);
508 if (composite_nomem(s
, c
)) return c
;
511 /* store input parameters in state structure */
514 s
->localaddr
= dcerpc_binding_get_string_option(io
->binding
,
516 /* RPC server and port (the endpoint) */
517 s
->rpc_server
= dcerpc_binding_get_string_option(io
->binding
, "host");
518 s
->target_hostname
= dcerpc_binding_get_string_option(io
->binding
,
520 endpoint
= dcerpc_binding_get_string_option(io
->binding
, "endpoint");
521 if (endpoint
== NULL
) {
522 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
525 s
->rpc_server_port
= atoi(endpoint
);
526 if (s
->rpc_server_port
== 0) {
527 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
532 opt
= dcerpc_binding_get_string_option(io
->binding
, "HttpUseTls");
534 if (strcasecmp(opt
, "true") == 0) {
536 } else if (strcasecmp(opt
, "false") == 0) {
539 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
547 proxy
= port
= talloc_strdup(s
, dcerpc_binding_get_string_option(
548 io
->binding
, "RpcProxy"));
549 s
->rpc_proxy
= strsep(&port
, ":");
551 s
->rpc_proxy_port
= atoi(port
);
553 s
->rpc_proxy_port
= s
->use_tls
? 443 : 80;
555 if (s
->rpc_proxy
== NULL
) {
556 s
->rpc_proxy
= talloc_strdup(s
, s
->rpc_server
);
557 if (composite_nomem(s
->rpc_proxy
, c
)) return c
;
561 proxy
= port
= talloc_strdup(s
, dcerpc_binding_get_string_option(
562 io
->binding
, "HttpProxy"));
563 s
->http_proxy
= strsep(&port
, ":");
565 s
->http_proxy_port
= atoi(port
);
567 s
->http_proxy_port
= s
->use_tls
? 443 : 80;
570 /* Use local proxy */
571 use_proxy
= dcerpc_binding_get_string_option(io
->binding
,
572 "HttpConnectOption");
573 if (use_proxy
&& strcasecmp(use_proxy
, "UseHttpProxy")) {
577 /* If use local proxy set, the http proxy should be provided */
578 if (s
->use_proxy
&& !s
->http_proxy
) {
579 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
583 /* Check which HTTP authentication method to use */
584 opt
= dcerpc_binding_get_string_option(io
->binding
, "HttpAuthOption");
586 if (strcasecmp(opt
, "basic") == 0) {
587 s
->http_auth
= HTTP_AUTH_BASIC
;
588 } else if (strcasecmp(opt
, "ntlm") == 0) {
589 s
->http_auth
= HTTP_AUTH_NTLM
;
590 } else if (strcasecmp(opt
, "negotiate") == 0) {
591 s
->http_auth
= HTTP_AUTH_NEGOTIATE
;
593 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
597 s
->http_auth
= HTTP_AUTH_NTLM
;
600 subreq
= dcerpc_pipe_open_roh_send(s
->io
.conn
, s
->localaddr
,
601 s
->rpc_server
, s
->rpc_server_port
,
602 s
->rpc_proxy
, s
->rpc_proxy_port
,
603 s
->http_proxy
, s
->http_proxy_port
,
604 s
->use_tls
, s
->use_proxy
,
605 s
->io
.creds
, io
->resolve_ctx
,
606 s
->lp_ctx
, s
->http_auth
);
607 if (composite_nomem(subreq
, c
)) return c
;
609 tevent_req_set_callback(subreq
, continue_pipe_open_ncacn_http
, c
);
613 static NTSTATUS
dcerpc_pipe_connect_ncacn_http_recv(struct composite_context
*c
)
615 return composite_wait_free(c
);
619 struct pipe_unix_state
{
620 struct dcerpc_pipe_connect io
;
626 Stage 2 of ncacn_unix: rpc pipe opened (or not)
628 static void continue_pipe_open_ncacn_unix_stream(struct composite_context
*ctx
)
630 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
631 struct composite_context
);
633 /* receive result of pipe open request on unix socket */
634 c
->status
= dcerpc_pipe_open_unix_stream_recv(ctx
);
635 if (!composite_is_ok(c
)) return;
642 Initiate async open of a rpc connection to a rpc pipe on unix socket using
643 the binding structure to determine the endpoint and options
645 static struct composite_context
* dcerpc_pipe_connect_ncacn_unix_stream_send(TALLOC_CTX
*mem_ctx
,
646 struct dcerpc_pipe_connect
*io
)
648 struct composite_context
*c
;
649 struct pipe_unix_state
*s
;
650 struct composite_context
*pipe_req
;
652 /* composite context allocation and setup */
653 c
= composite_create(mem_ctx
, io
->conn
->event_ctx
);
654 if (c
== NULL
) return NULL
;
656 s
= talloc_zero(c
, struct pipe_unix_state
);
657 if (composite_nomem(s
, c
)) return c
;
660 /* prepare pipe open parameters and store them in state structure
661 also, verify whether biding endpoint is not null */
664 s
->path
= dcerpc_binding_get_string_option(io
->binding
, "endpoint");
665 if (s
->path
== NULL
) {
666 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
670 /* send pipe open request on unix socket */
671 pipe_req
= dcerpc_pipe_open_unix_stream_send(s
->io
.conn
, s
->path
);
672 composite_continue(c
, pipe_req
, continue_pipe_open_ncacn_unix_stream
, c
);
678 Receive result of a rpc connection to a pipe on unix socket
680 static NTSTATUS
dcerpc_pipe_connect_ncacn_unix_stream_recv(struct composite_context
*c
)
682 NTSTATUS status
= composite_wait(c
);
689 struct pipe_ncalrpc_state
{
690 struct dcerpc_pipe_connect io
;
693 static NTSTATUS
dcerpc_pipe_connect_ncalrpc_recv(struct composite_context
*c
);
696 Stage 2 of ncalrpc: rpc pipe opened (or not)
698 static void continue_pipe_open_ncalrpc(struct composite_context
*ctx
)
700 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
701 struct composite_context
);
703 /* receive result of pipe open request on ncalrpc */
704 c
->status
= dcerpc_pipe_connect_ncalrpc_recv(ctx
);
705 if (!composite_is_ok(c
)) return;
712 Initiate async open of a rpc connection request on NCALRPC using
713 the binding structure to determine the endpoint and options
715 static struct composite_context
* dcerpc_pipe_connect_ncalrpc_send(TALLOC_CTX
*mem_ctx
,
716 struct dcerpc_pipe_connect
*io
)
718 struct composite_context
*c
;
719 struct pipe_ncalrpc_state
*s
;
720 struct composite_context
*pipe_req
;
721 const char *endpoint
;
723 /* composite context allocation and setup */
724 c
= composite_create(mem_ctx
, io
->conn
->event_ctx
);
725 if (c
== NULL
) return NULL
;
727 s
= talloc_zero(c
, struct pipe_ncalrpc_state
);
728 if (composite_nomem(s
, c
)) return c
;
731 /* store input parameters in state structure */
734 endpoint
= dcerpc_binding_get_string_option(io
->binding
, "endpoint");
735 if (endpoint
== NULL
) {
736 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
740 /* send pipe open request */
741 pipe_req
= dcerpc_pipe_open_pipe_send(s
->io
.conn
,
744 composite_continue(c
, pipe_req
, continue_pipe_open_ncalrpc
, c
);
750 Receive result of a rpc connection to a rpc pipe on NCALRPC
752 static NTSTATUS
dcerpc_pipe_connect_ncalrpc_recv(struct composite_context
*c
)
754 NTSTATUS status
= composite_wait(c
);
761 struct pipe_connect_state
{
762 struct dcerpc_pipe
*pipe
;
763 struct dcerpc_binding
*binding
;
764 const struct ndr_interface_table
*table
;
765 struct cli_credentials
*credentials
;
766 struct loadparm_context
*lp_ctx
;
770 static void continue_map_binding(struct composite_context
*ctx
);
771 static void continue_connect(struct composite_context
*c
, struct pipe_connect_state
*s
);
772 static void continue_pipe_connect_ncacn_np_smb(struct composite_context
*ctx
);
773 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context
*ctx
);
774 static void continue_pipe_connect_ncacn_http(struct composite_context
*ctx
);
775 static void continue_pipe_connect_ncacn_unix(struct composite_context
*ctx
);
776 static void continue_pipe_connect_ncalrpc(struct composite_context
*ctx
);
777 static void continue_pipe_connect(struct composite_context
*c
, struct pipe_connect_state
*s
);
778 static void continue_pipe_auth(struct composite_context
*ctx
);
782 Stage 2 of pipe_connect_b: Receive result of endpoint mapping
784 static void continue_map_binding(struct composite_context
*ctx
)
786 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
787 struct composite_context
);
788 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
789 struct pipe_connect_state
);
790 const char *endpoint
;
792 c
->status
= dcerpc_epm_map_binding_recv(ctx
);
793 if (!composite_is_ok(c
)) return;
795 endpoint
= dcerpc_binding_get_string_option(s
->binding
, "endpoint");
796 DEBUG(4,("Mapped to DCERPC endpoint %s\n", endpoint
));
798 continue_connect(c
, s
);
803 Stage 2 of pipe_connect_b: Continue connection after endpoint is known
805 static void continue_connect(struct composite_context
*c
, struct pipe_connect_state
*s
)
807 struct dcerpc_pipe_connect pc
;
809 /* potential exits to another stage by sending an async request */
810 struct composite_context
*ncacn_np_smb_req
;
811 struct composite_context
*ncacn_ip_tcp_req
;
812 struct composite_context
*ncacn_http_req
;
813 struct composite_context
*ncacn_unix_req
;
814 struct composite_context
*ncalrpc_req
;
815 enum dcerpc_transport_t transport
;
817 /* dcerpc pipe connect input parameters */
819 pc
.conn
= s
->pipe
->conn
;
820 pc
.binding
= s
->binding
;
821 pc
.interface
= s
->table
;
822 pc
.creds
= s
->credentials
;
823 pc
.resolve_ctx
= lpcfg_resolve_context(s
->lp_ctx
);
825 transport
= dcerpc_binding_get_transport(s
->binding
);
827 /* connect dcerpc pipe depending on required transport */
833 ncacn_np_smb_req
= dcerpc_pipe_connect_ncacn_np_smb_send(c
, &pc
, s
->lp_ctx
);
834 composite_continue(c
, ncacn_np_smb_req
, continue_pipe_connect_ncacn_np_smb
, c
);
838 ncacn_ip_tcp_req
= dcerpc_pipe_connect_ncacn_ip_tcp_send(c
, &pc
);
839 composite_continue(c
, ncacn_ip_tcp_req
, continue_pipe_connect_ncacn_ip_tcp
, c
);
843 ncacn_http_req
= dcerpc_pipe_connect_ncacn_http_send(c
, &pc
, s
->lp_ctx
);
844 composite_continue(c
, ncacn_http_req
, continue_pipe_connect_ncacn_http
, c
);
847 case NCACN_UNIX_STREAM
:
848 ncacn_unix_req
= dcerpc_pipe_connect_ncacn_unix_stream_send(c
, &pc
);
849 composite_continue(c
, ncacn_unix_req
, continue_pipe_connect_ncacn_unix
, c
);
853 pc
.ncalrpc
.dir
= lpcfg_ncalrpc_dir(s
->lp_ctx
);
854 c
->status
= dcerpc_binding_set_string_option(s
->binding
, "ncalrpc_dir",
856 if (!composite_is_ok(c
)) return;
857 ncalrpc_req
= dcerpc_pipe_connect_ncalrpc_send(c
, &pc
);
858 composite_continue(c
, ncalrpc_req
, continue_pipe_connect_ncalrpc
, c
);
862 /* looks like a transport we don't support now */
863 composite_error(c
, NT_STATUS_NOT_SUPPORTED
);
869 Stage 3 of pipe_connect_b: Receive result of pipe connect request on
872 static void continue_pipe_connect_ncacn_np_smb(struct composite_context
*ctx
)
874 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
875 struct composite_context
);
876 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
877 struct pipe_connect_state
);
879 c
->status
= dcerpc_pipe_connect_ncacn_np_smb_recv(ctx
);
880 if (!composite_is_ok(c
)) return;
882 continue_pipe_connect(c
, s
);
887 Stage 3 of pipe_connect_b: Receive result of pipe connect request on tcp/ip
889 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context
*ctx
)
891 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
892 struct composite_context
);
893 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
894 struct pipe_connect_state
);
896 c
->status
= dcerpc_pipe_connect_ncacn_ip_tcp_recv(ctx
);
897 if (!composite_is_ok(c
)) return;
899 continue_pipe_connect(c
, s
);
904 Stage 3 of pipe_connect_b: Receive result of pipe connect request on http
906 static void continue_pipe_connect_ncacn_http(struct composite_context
*ctx
)
908 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
909 struct composite_context
);
910 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
911 struct pipe_connect_state
);
913 c
->status
= dcerpc_pipe_connect_ncacn_http_recv(ctx
);
914 if (!composite_is_ok(c
)) return;
916 continue_pipe_connect(c
, s
);
921 Stage 3 of pipe_connect_b: Receive result of pipe connect request on unix socket
923 static void continue_pipe_connect_ncacn_unix(struct composite_context
*ctx
)
925 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
926 struct composite_context
);
927 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
928 struct pipe_connect_state
);
930 c
->status
= dcerpc_pipe_connect_ncacn_unix_stream_recv(ctx
);
931 if (!composite_is_ok(c
)) return;
933 continue_pipe_connect(c
, s
);
938 Stage 3 of pipe_connect_b: Receive result of pipe connect request on local rpc
940 static void continue_pipe_connect_ncalrpc(struct composite_context
*ctx
)
942 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
943 struct composite_context
);
944 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
945 struct pipe_connect_state
);
947 c
->status
= dcerpc_pipe_connect_ncalrpc_recv(ctx
);
948 if (!composite_is_ok(c
)) return;
950 continue_pipe_connect(c
, s
);
955 Stage 4 of pipe_connect_b: Start an authentication on connected dcerpc pipe
956 depending on credentials and binding flags passed.
958 static void continue_pipe_connect(struct composite_context
*c
, struct pipe_connect_state
*s
)
960 struct composite_context
*auth_bind_req
;
962 s
->pipe
->binding
= dcerpc_binding_dup(s
->pipe
, s
->binding
);
963 if (composite_nomem(s
->pipe
->binding
, c
)) {
967 auth_bind_req
= dcerpc_pipe_auth_send(s
->pipe
, s
->binding
, s
->table
,
968 s
->credentials
, s
->lp_ctx
);
969 composite_continue(c
, auth_bind_req
, continue_pipe_auth
, c
);
974 Stage 5 of pipe_connect_b: Receive result of pipe authentication request
975 and say if all went ok
977 static void continue_pipe_auth(struct composite_context
*ctx
)
979 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
980 struct composite_context
);
981 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
, struct pipe_connect_state
);
983 c
->status
= dcerpc_pipe_auth_recv(ctx
, s
, &s
->pipe
);
984 if (!composite_is_ok(c
)) return;
991 handle timeouts of a dcerpc connect
993 static void dcerpc_connect_timeout_handler(struct tevent_context
*ev
, struct tevent_timer
*te
,
994 struct timeval t
, void *private_data
)
996 struct composite_context
*c
= talloc_get_type_abort(private_data
,
997 struct composite_context
);
998 struct pipe_connect_state
*s
= talloc_get_type_abort(c
->private_data
, struct pipe_connect_state
);
999 if (!s
->pipe
->inhibit_timeout_processing
) {
1000 composite_error(c
, NT_STATUS_IO_TIMEOUT
);
1002 s
->pipe
->timed_out
= true;
1007 start a request to open a rpc connection to a rpc pipe, using
1008 specified binding structure to determine the endpoint and options
1010 _PUBLIC_
struct composite_context
* dcerpc_pipe_connect_b_send(TALLOC_CTX
*parent_ctx
,
1011 const struct dcerpc_binding
*binding
,
1012 const struct ndr_interface_table
*table
,
1013 struct cli_credentials
*credentials
,
1014 struct tevent_context
*ev
,
1015 struct loadparm_context
*lp_ctx
)
1017 struct composite_context
*c
;
1018 struct pipe_connect_state
*s
;
1019 enum dcerpc_transport_t transport
;
1020 const char *endpoint
= NULL
;
1021 struct cli_credentials
*epm_creds
= NULL
;
1023 /* composite context allocation and setup */
1024 c
= composite_create(parent_ctx
, ev
);
1029 s
= talloc_zero(c
, struct pipe_connect_state
);
1030 if (composite_nomem(s
, c
)) return c
;
1031 c
->private_data
= s
;
1033 /* initialise dcerpc pipe structure */
1034 s
->pipe
= dcerpc_pipe_init(c
, ev
);
1035 if (composite_nomem(s
->pipe
, c
)) return c
;
1037 if (DEBUGLEVEL
>= 10)
1038 s
->pipe
->conn
->packet_log_dir
= lpcfg_lock_directory(lp_ctx
);
1040 /* store parameters in state structure */
1041 s
->binding
= dcerpc_binding_dup(s
, binding
);
1042 if (composite_nomem(s
->binding
, c
)) return c
;
1044 s
->credentials
= credentials
;
1047 s
->pipe
->timed_out
= false;
1048 s
->pipe
->inhibit_timeout_processing
= false;
1050 tevent_add_timer(c
->event_ctx
, c
,
1051 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT
, 0),
1052 dcerpc_connect_timeout_handler
, c
);
1054 transport
= dcerpc_binding_get_transport(s
->binding
);
1056 switch (transport
) {
1060 endpoint
= dcerpc_binding_get_string_option(s
->binding
, "endpoint");
1062 /* anonymous credentials for rpc connection used to get endpoint mapping */
1063 epm_creds
= cli_credentials_init_anon(s
);
1064 if (composite_nomem(epm_creds
, c
)) return c
;
1068 endpoint
= dcerpc_binding_get_string_option(s
->binding
, "endpoint");
1069 epm_creds
= credentials
;
1072 DBG_INFO("Unknown transport; continuing with anon, no endpoint.\n");
1073 epm_creds
= cli_credentials_init_anon(s
);
1074 if (composite_nomem(epm_creds
, c
)){
1080 if (endpoint
== NULL
) {
1081 struct composite_context
*binding_req
;
1083 binding_req
= dcerpc_epm_map_binding_send(c
, s
->binding
, s
->table
,
1085 s
->pipe
->conn
->event_ctx
,
1087 composite_continue(c
, binding_req
, continue_map_binding
, c
);
1091 continue_connect(c
, s
);
1097 receive result of a request to open a rpc connection to a rpc pipe
1099 _PUBLIC_ NTSTATUS
dcerpc_pipe_connect_b_recv(struct composite_context
*c
, TALLOC_CTX
*mem_ctx
,
1100 struct dcerpc_pipe
**p
)
1103 struct pipe_connect_state
*s
;
1105 status
= composite_wait(c
);
1107 if (NT_STATUS_IS_OK(status
)) {
1108 s
= talloc_get_type(c
->private_data
, struct pipe_connect_state
);
1109 talloc_steal(mem_ctx
, s
->pipe
);
1118 open a rpc connection to a rpc pipe, using the specified
1119 binding structure to determine the endpoint and options - sync version
1121 _PUBLIC_ NTSTATUS
dcerpc_pipe_connect_b(TALLOC_CTX
*parent_ctx
,
1122 struct dcerpc_pipe
**pp
,
1123 const struct dcerpc_binding
*binding
,
1124 const struct ndr_interface_table
*table
,
1125 struct cli_credentials
*credentials
,
1126 struct tevent_context
*ev
,
1127 struct loadparm_context
*lp_ctx
)
1129 struct composite_context
*c
;
1131 c
= dcerpc_pipe_connect_b_send(parent_ctx
, binding
, table
,
1132 credentials
, ev
, lp_ctx
);
1133 return dcerpc_pipe_connect_b_recv(c
, parent_ctx
, pp
);
1137 struct pipe_conn_state
{
1138 struct dcerpc_pipe
*pipe
;
1142 static void continue_pipe_connect_b(struct composite_context
*ctx
);
1146 Initiate rpc connection to a rpc pipe, using the specified string
1147 binding to determine the endpoint and options.
1148 The string is to be parsed to a binding structure first.
1150 _PUBLIC_
struct composite_context
* dcerpc_pipe_connect_send(TALLOC_CTX
*parent_ctx
,
1151 const char *binding
,
1152 const struct ndr_interface_table
*table
,
1153 struct cli_credentials
*credentials
,
1154 struct tevent_context
*ev
, struct loadparm_context
*lp_ctx
)
1156 struct composite_context
*c
;
1157 struct pipe_conn_state
*s
;
1158 struct dcerpc_binding
*b
;
1159 struct composite_context
*pipe_conn_req
;
1161 /* composite context allocation and setup */
1162 c
= composite_create(parent_ctx
, ev
);
1167 s
= talloc_zero(c
, struct pipe_conn_state
);
1168 if (composite_nomem(s
, c
)) return c
;
1169 c
->private_data
= s
;
1171 /* parse binding string to the structure */
1172 c
->status
= dcerpc_parse_binding(c
, binding
, &b
);
1173 if (!NT_STATUS_IS_OK(c
->status
)) {
1174 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding
));
1175 composite_error(c
, c
->status
);
1179 DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(c
, b
)));
1182 start connecting to a rpc pipe after binding structure
1185 pipe_conn_req
= dcerpc_pipe_connect_b_send(c
, b
, table
,
1186 credentials
, ev
, lp_ctx
);
1187 composite_continue(c
, pipe_conn_req
, continue_pipe_connect_b
, c
);
1193 Stage 2 of pipe_connect: Receive result of actual pipe connect request
1194 and say if we're done ok
1196 static void continue_pipe_connect_b(struct composite_context
*ctx
)
1198 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
1199 struct composite_context
);
1200 struct pipe_conn_state
*s
= talloc_get_type(c
->private_data
,
1201 struct pipe_conn_state
);
1203 c
->status
= dcerpc_pipe_connect_b_recv(ctx
, c
, &s
->pipe
);
1204 talloc_steal(s
, s
->pipe
);
1205 if (!composite_is_ok(c
)) return;
1212 Receive result of pipe connect (using binding string) request
1213 and return connected pipe structure.
1215 NTSTATUS
dcerpc_pipe_connect_recv(struct composite_context
*c
,
1216 TALLOC_CTX
*mem_ctx
,
1217 struct dcerpc_pipe
**pp
)
1220 struct pipe_conn_state
*s
;
1222 status
= composite_wait(c
);
1223 if (NT_STATUS_IS_OK(status
)) {
1224 s
= talloc_get_type(c
->private_data
, struct pipe_conn_state
);
1225 *pp
= talloc_steal(mem_ctx
, s
->pipe
);
1233 Open a rpc connection to a rpc pipe, using the specified string
1234 binding to determine the endpoint and options - sync version
1236 _PUBLIC_ NTSTATUS
dcerpc_pipe_connect(TALLOC_CTX
*parent_ctx
,
1237 struct dcerpc_pipe
**pp
,
1238 const char *binding
,
1239 const struct ndr_interface_table
*table
,
1240 struct cli_credentials
*credentials
,
1241 struct tevent_context
*ev
,
1242 struct loadparm_context
*lp_ctx
)
1244 struct composite_context
*c
;
1245 c
= dcerpc_pipe_connect_send(parent_ctx
, binding
,
1246 table
, credentials
, ev
, lp_ctx
);
1247 return dcerpc_pipe_connect_recv(c
, parent_ctx
, pp
);