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"
43 struct dcerpc_pipe_connect
{
44 struct dcecli_connection
*conn
;
45 struct dcerpc_binding
*binding
;
46 const struct ndr_interface_table
*interface
;
47 struct cli_credentials
*creds
;
48 struct resolve_context
*resolve_ctx
;
53 struct smbXcli_conn
*conn
;
54 struct smbXcli_session
*session
;
55 struct smbXcli_tcon
*tcon
;
56 const char *pipe_name
;
60 struct pipe_np_smb_state
{
61 struct smb_composite_connect conn
;
62 struct dcerpc_pipe_connect io
;
67 Stage 3 of ncacn_np_smb: Named pipe opened (or not)
69 static void continue_pipe_open_smb(struct composite_context
*ctx
)
71 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
72 struct composite_context
);
74 /* receive result of named pipe open request on smb */
75 c
->status
= dcerpc_pipe_open_smb_recv(ctx
);
76 if (!composite_is_ok(c
)) return;
81 static void continue_smb_open(struct composite_context
*c
);
82 static void continue_smb2_connect(struct tevent_req
*subreq
);
83 static void continue_smbXcli_connect(struct tevent_req
*subreq
);
86 Stage 2 of ncacn_np_smb: Open a named pipe after successful smb connection
88 static void continue_smb_connect(struct composite_context
*ctx
)
90 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
91 struct composite_context
);
92 struct pipe_np_smb_state
*s
= talloc_get_type(c
->private_data
,
93 struct pipe_np_smb_state
);
94 struct smbcli_tree
*t
;
96 /* receive result of smb connect request */
97 c
->status
= smb_composite_connect_recv(ctx
, s
->io
.conn
);
98 if (!composite_is_ok(c
)) return;
100 t
= s
->conn
.out
.tree
;
102 /* prepare named pipe open parameters */
103 s
->io
.smb
.conn
= t
->session
->transport
->conn
;
104 s
->io
.smb
.session
= t
->session
->smbXcli
;
105 s
->io
.smb
.tcon
= t
->smbXcli
;
106 smb1cli_tcon_set_id(s
->io
.smb
.tcon
, t
->tid
);
107 s
->io
.smb
.pipe_name
= dcerpc_binding_get_string_option(s
->io
.binding
,
110 continue_smb_open(c
);
113 static void continue_smb_open(struct composite_context
*c
)
115 struct pipe_np_smb_state
*s
= talloc_get_type(c
->private_data
,
116 struct pipe_np_smb_state
);
117 struct composite_context
*open_ctx
;
119 /* send named pipe open request */
120 open_ctx
= dcerpc_pipe_open_smb_send(s
->io
.conn
,
124 DCERPC_REQUEST_TIMEOUT
* 1000,
125 s
->io
.smb
.pipe_name
);
126 if (composite_nomem(open_ctx
, c
)) return;
128 composite_continue(c
, open_ctx
, continue_pipe_open_smb
, c
);
133 Initiate async open of a rpc connection to a rpc pipe on SMB using
134 the binding structure to determine the endpoint and options
136 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
)
138 struct composite_context
*c
;
139 struct pipe_np_smb_state
*s
;
140 struct tevent_req
*subreq
= NULL
;
141 struct smb_composite_connect
*conn
;
143 const char *target_hostname
= NULL
;
144 const char *dest_address
= NULL
;
145 const char *calling_name
= NULL
;
147 /* composite context allocation and setup */
148 c
= composite_create(mem_ctx
, io
->conn
->event_ctx
);
149 if (c
== NULL
) return NULL
;
151 s
= talloc_zero(c
, struct pipe_np_smb_state
);
152 if (composite_nomem(s
, c
)) return c
;
158 if (smbXcli_conn_is_connected(s
->io
.smb
.conn
)) {
159 continue_smb_open(c
);
163 if (s
->io
.creds
== NULL
) {
164 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
168 /* prepare smb connection parameters: we're connecting to IPC$ share on
170 target_hostname
= dcerpc_binding_get_string_option(s
->io
.binding
, "target_hostname");
171 conn
->in
.dest_host
= dcerpc_binding_get_string_option(s
->io
.binding
, "host");
172 conn
->in
.dest_ports
= lpcfg_smb_ports(lp_ctx
);
173 conn
->in
.called_name
= target_hostname
;
174 if (conn
->in
.called_name
== NULL
) {
175 conn
->in
.called_name
= "*SMBSERVER";
177 conn
->in
.socket_options
= lpcfg_socket_options(lp_ctx
);
178 conn
->in
.service
= "IPC$";
179 conn
->in
.service_type
= NULL
;
180 conn
->in
.workgroup
= lpcfg_workgroup(lp_ctx
);
181 conn
->in
.gensec_settings
= lpcfg_gensec_settings(conn
, lp_ctx
);
183 lpcfg_smbcli_options(lp_ctx
, &conn
->in
.options
);
184 lpcfg_smbcli_session_options(lp_ctx
, &conn
->in
.session_options
);
187 * provide proper credentials - user supplied, but allow a
188 * fallback to anonymous if this is an schannel connection
189 * (might be NT4 not allowing machine logins at session
190 * setup) or if asked to do so by the caller (perhaps a SAMR password change?)
192 s
->conn
.in
.credentials
= s
->io
.creds
;
193 flags
= dcerpc_binding_get_flags(s
->io
.binding
);
194 if (flags
& (DCERPC_SCHANNEL
|DCERPC_ANON_FALLBACK
)) {
195 conn
->in
.fallback_to_anonymous
= true;
197 conn
->in
.fallback_to_anonymous
= false;
200 conn
->in
.options
.min_protocol
= lpcfg_client_ipc_min_protocol(lp_ctx
);
201 conn
->in
.options
.max_protocol
= lpcfg_client_ipc_max_protocol(lp_ctx
);
202 if ((flags
& DCERPC_SMB1
) && (flags
& DCERPC_SMB2
)) {
204 } else if (flags
& DCERPC_SMB2
) {
205 if (conn
->in
.options
.min_protocol
< PROTOCOL_SMB2_02
) {
206 conn
->in
.options
.min_protocol
= PROTOCOL_SMB2_02
;
208 if (conn
->in
.options
.max_protocol
< PROTOCOL_SMB2_02
) {
209 conn
->in
.options
.max_protocol
= PROTOCOL_LATEST
;
211 } else if (flags
& DCERPC_SMB1
) {
212 conn
->in
.options
.min_protocol
= PROTOCOL_NT1
;
213 conn
->in
.options
.max_protocol
= PROTOCOL_NT1
;
218 conn
->in
.options
.signing
= lpcfg_client_ipc_signing(lp_ctx
);
220 if (s
->conn
.in
.credentials
!= NULL
) {
221 calling_name
= cli_credentials_get_workstation(s
->conn
.in
.credentials
);
223 if (calling_name
== NULL
) {
224 calling_name
= "SMBCLIENT";
227 if (target_hostname
== NULL
) {
228 target_hostname
= conn
->in
.dest_host
;
231 if (conn
->in
.dest_host
!= NULL
&& is_ipaddress(conn
->in
.dest_host
)) {
232 dest_address
= conn
->in
.dest_host
;
235 subreq
= smb_connect_nego_send(s
,
239 conn
->in
.socket_options
,
244 conn
->in
.called_name
,
246 if (composite_nomem(subreq
, c
)) return c
;
247 tevent_req_set_callback(subreq
,
248 continue_smbXcli_connect
,
254 static void continue_smbXcli_connect(struct tevent_req
*subreq
)
256 struct composite_context
*c
=
257 tevent_req_callback_data(subreq
,
258 struct composite_context
);
259 struct pipe_np_smb_state
*s
=
260 talloc_get_type_abort(c
->private_data
,
261 struct pipe_np_smb_state
);
262 struct smb_composite_connect
*conn
= &s
->conn
;
263 struct composite_context
*creq
= NULL
;
264 enum protocol_types protocol
;
266 c
->status
= smb_connect_nego_recv(subreq
, s
,
267 &conn
->in
.existing_conn
);
269 if (!composite_is_ok(c
)) return;
271 protocol
= smbXcli_conn_protocol(conn
->in
.existing_conn
);
272 if (protocol
>= PROTOCOL_SMB2_02
) {
274 * continue with smb2 session setup/tree connect
275 * on the established connection.
277 subreq
= smb2_connect_send(s
, c
->event_ctx
,
282 conn
->in
.credentials
,
283 conn
->in
.fallback_to_anonymous
,
284 &conn
->in
.existing_conn
,
285 0, /* previous_session_id */
287 conn
->in
.socket_options
,
288 conn
->in
.gensec_settings
);
289 if (composite_nomem(subreq
, c
)) return;
290 tevent_req_set_callback(subreq
, continue_smb2_connect
, c
);
295 * continue with smb1 session setup/tree connect
296 * on the established connection.
298 creq
= smb_composite_connect_send(conn
, s
->io
.conn
,
301 if (composite_nomem(creq
, c
)) return;
303 composite_continue(c
, creq
, continue_smb_connect
, c
);
309 Receive result of a rpc connection to a rpc pipe on SMB
311 static NTSTATUS
dcerpc_pipe_connect_ncacn_np_smb_recv(struct composite_context
*c
)
313 NTSTATUS status
= composite_wait(c
);
320 Stage 2 of ncacn_np_smb2: Open a named pipe after successful smb2 connection
322 static void continue_smb2_connect(struct tevent_req
*subreq
)
324 struct composite_context
*c
=
325 tevent_req_callback_data(subreq
,
326 struct composite_context
);
327 struct pipe_np_smb_state
*s
= talloc_get_type(c
->private_data
,
328 struct pipe_np_smb_state
);
331 /* receive result of smb2 connect request */
332 c
->status
= smb2_connect_recv(subreq
, s
->io
.conn
, &t
);
334 if (!composite_is_ok(c
)) return;
336 s
->io
.smb
.conn
= t
->session
->transport
->conn
;
337 s
->io
.smb
.session
= t
->session
->smbXcli
;
338 s
->io
.smb
.tcon
= t
->smbXcli
;
339 s
->io
.smb
.pipe_name
= dcerpc_binding_get_string_option(s
->io
.binding
,
342 continue_smb_open(c
);
346 struct pipe_ip_tcp_state
{
347 struct dcerpc_pipe_connect io
;
348 const char *localaddr
;
350 const char *target_hostname
;
356 Stage 2 of ncacn_ip_tcp: rpc pipe opened (or not)
358 static void continue_pipe_open_ncacn_ip_tcp(struct composite_context
*ctx
)
360 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
361 struct composite_context
);
362 struct pipe_ip_tcp_state
*s
= talloc_get_type(c
->private_data
,
363 struct pipe_ip_tcp_state
);
364 char *localaddr
= NULL
;
365 char *remoteaddr
= NULL
;
367 /* receive result of named pipe open request on tcp/ip */
368 c
->status
= dcerpc_pipe_open_tcp_recv(ctx
, s
, &localaddr
, &remoteaddr
);
369 if (!composite_is_ok(c
)) return;
371 c
->status
= dcerpc_binding_set_string_option(s
->io
.binding
,
374 if (!composite_is_ok(c
)) return;
376 c
->status
= dcerpc_binding_set_string_option(s
->io
.binding
,
379 if (!composite_is_ok(c
)) return;
386 Initiate async open of a rpc connection to a rpc pipe on TCP/IP using
387 the binding structure to determine the endpoint and options
389 static struct composite_context
* dcerpc_pipe_connect_ncacn_ip_tcp_send(TALLOC_CTX
*mem_ctx
,
390 struct dcerpc_pipe_connect
*io
)
392 struct composite_context
*c
;
393 struct pipe_ip_tcp_state
*s
;
394 struct composite_context
*pipe_req
;
395 const char *endpoint
;
397 /* composite context allocation and setup */
398 c
= composite_create(mem_ctx
, io
->conn
->event_ctx
);
399 if (c
== NULL
) return NULL
;
401 s
= talloc_zero(c
, struct pipe_ip_tcp_state
);
402 if (composite_nomem(s
, c
)) return c
;
405 /* store input parameters in state structure */
407 s
->localaddr
= dcerpc_binding_get_string_option(io
->binding
,
409 s
->host
= dcerpc_binding_get_string_option(io
->binding
, "host");
410 s
->target_hostname
= dcerpc_binding_get_string_option(io
->binding
,
412 endpoint
= dcerpc_binding_get_string_option(io
->binding
, "endpoint");
413 /* port number is a binding endpoint here */
414 if (endpoint
!= NULL
) {
415 s
->port
= atoi(endpoint
);
419 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
423 /* send pipe open request on tcp/ip */
424 pipe_req
= dcerpc_pipe_open_tcp_send(s
->io
.conn
, s
->localaddr
, s
->host
, s
->target_hostname
,
425 s
->port
, io
->resolve_ctx
);
426 composite_continue(c
, pipe_req
, continue_pipe_open_ncacn_ip_tcp
, c
);
432 Receive result of a rpc connection to a rpc pipe on TCP/IP
434 static NTSTATUS
dcerpc_pipe_connect_ncacn_ip_tcp_recv(struct composite_context
*c
)
436 NTSTATUS status
= composite_wait(c
);
443 struct pipe_http_state
{
444 struct dcerpc_pipe_connect io
;
445 const char *localaddr
;
446 const char *target_hostname
;
447 const char *rpc_server
;
448 uint32_t rpc_server_port
;
450 uint32_t rpc_proxy_port
;
452 uint32_t http_proxy_port
;
455 enum http_auth_method http_auth
;
456 struct loadparm_context
*lp_ctx
;
460 Stage 2 of ncacn_http: rpc pipe opened (or not)
462 static void continue_pipe_open_ncacn_http(struct tevent_req
*subreq
)
464 struct composite_context
*c
= NULL
;
465 struct pipe_http_state
*s
= NULL
;
466 struct tstream_context
*stream
= NULL
;
467 struct tevent_queue
*queue
= NULL
;
469 c
= tevent_req_callback_data(subreq
, struct composite_context
);
470 s
= talloc_get_type(c
->private_data
, struct pipe_http_state
);
472 /* receive result of RoH connect request */
473 c
->status
= dcerpc_pipe_open_roh_recv(subreq
, s
->io
.conn
,
476 if (!composite_is_ok(c
)) return;
478 s
->io
.conn
->transport
.transport
= NCACN_HTTP
;
479 s
->io
.conn
->transport
.stream
= stream
;
480 s
->io
.conn
->transport
.write_queue
= queue
;
481 s
->io
.conn
->transport
.pending_reads
= 0;
482 s
->io
.conn
->server_name
= strupper_talloc(s
->io
.conn
,
489 Initiate async open of a rpc connection to a rpc pipe using HTTP transport,
490 and using the binding structure to determine the endpoint and options
492 static struct composite_context
* dcerpc_pipe_connect_ncacn_http_send(
493 TALLOC_CTX
*mem_ctx
, struct dcerpc_pipe_connect
*io
,
494 struct loadparm_context
*lp_ctx
)
496 struct composite_context
*c
;
497 struct pipe_http_state
*s
;
498 struct tevent_req
*subreq
;
499 const char *endpoint
;
500 const char *use_proxy
;
505 /* composite context allocation and setup */
506 c
= composite_create(mem_ctx
, io
->conn
->event_ctx
);
507 if (c
== NULL
) return NULL
;
509 s
= talloc_zero(c
, struct pipe_http_state
);
510 if (composite_nomem(s
, c
)) return c
;
513 /* store input parameters in state structure */
516 s
->localaddr
= dcerpc_binding_get_string_option(io
->binding
,
518 /* RPC server and port (the endpoint) */
519 s
->rpc_server
= dcerpc_binding_get_string_option(io
->binding
, "host");
520 s
->target_hostname
= dcerpc_binding_get_string_option(io
->binding
,
522 endpoint
= dcerpc_binding_get_string_option(io
->binding
, "endpoint");
523 if (endpoint
== NULL
) {
524 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
527 s
->rpc_server_port
= atoi(endpoint
);
528 if (s
->rpc_server_port
== 0) {
529 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
534 opt
= dcerpc_binding_get_string_option(io
->binding
, "HttpUseTls");
536 if (strcasecmp(opt
, "true") == 0) {
538 } else if (strcasecmp(opt
, "false") == 0) {
541 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
549 proxy
= port
= talloc_strdup(s
, dcerpc_binding_get_string_option(
550 io
->binding
, "RpcProxy"));
551 s
->rpc_proxy
= strsep(&port
, ":");
553 s
->rpc_proxy_port
= atoi(port
);
555 s
->rpc_proxy_port
= s
->use_tls
? 443 : 80;
557 if (s
->rpc_proxy
== NULL
) {
558 s
->rpc_proxy
= talloc_strdup(s
, s
->rpc_server
);
559 if (composite_nomem(s
->rpc_proxy
, c
)) return c
;
563 proxy
= port
= talloc_strdup(s
, dcerpc_binding_get_string_option(
564 io
->binding
, "HttpProxy"));
565 s
->http_proxy
= strsep(&port
, ":");
567 s
->http_proxy_port
= atoi(port
);
569 s
->http_proxy_port
= s
->use_tls
? 443 : 80;
572 /* Use local proxy */
573 use_proxy
= dcerpc_binding_get_string_option(io
->binding
,
574 "HttpConnectOption");
575 if (use_proxy
&& strcasecmp(use_proxy
, "UseHttpProxy")) {
579 /* If use local proxy set, the http proxy should be provided */
580 if (s
->use_proxy
&& !s
->http_proxy
) {
581 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
585 /* Check which HTTP authentication method to use */
586 opt
= dcerpc_binding_get_string_option(io
->binding
, "HttpAuthOption");
588 if (strcasecmp(opt
, "basic") == 0) {
589 s
->http_auth
= HTTP_AUTH_BASIC
;
590 } else if (strcasecmp(opt
, "ntlm") == 0) {
591 s
->http_auth
= HTTP_AUTH_NTLM
;
592 } else if (strcasecmp(opt
, "negotiate") == 0) {
593 s
->http_auth
= HTTP_AUTH_NEGOTIATE
;
595 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
599 s
->http_auth
= HTTP_AUTH_NTLM
;
602 subreq
= dcerpc_pipe_open_roh_send(s
->io
.conn
, s
->localaddr
,
603 s
->rpc_server
, s
->rpc_server_port
,
604 s
->rpc_proxy
, s
->rpc_proxy_port
,
605 s
->http_proxy
, s
->http_proxy_port
,
606 s
->use_tls
, s
->use_proxy
,
607 s
->io
.creds
, io
->resolve_ctx
,
608 s
->lp_ctx
, s
->http_auth
);
609 if (composite_nomem(subreq
, c
)) return c
;
611 tevent_req_set_callback(subreq
, continue_pipe_open_ncacn_http
, c
);
615 static NTSTATUS
dcerpc_pipe_connect_ncacn_http_recv(struct composite_context
*c
)
617 return composite_wait_free(c
);
621 struct pipe_unix_state
{
622 struct dcerpc_pipe_connect io
;
628 Stage 2 of ncacn_unix: rpc pipe opened (or not)
630 static void continue_pipe_open_ncacn_unix_stream(struct composite_context
*ctx
)
632 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
633 struct composite_context
);
635 /* receive result of pipe open request on unix socket */
636 c
->status
= dcerpc_pipe_open_unix_stream_recv(ctx
);
637 if (!composite_is_ok(c
)) return;
644 Initiate async open of a rpc connection to a rpc pipe on unix socket using
645 the binding structure to determine the endpoint and options
647 static struct composite_context
* dcerpc_pipe_connect_ncacn_unix_stream_send(TALLOC_CTX
*mem_ctx
,
648 struct dcerpc_pipe_connect
*io
)
650 struct composite_context
*c
;
651 struct pipe_unix_state
*s
;
652 struct composite_context
*pipe_req
;
654 /* composite context allocation and setup */
655 c
= composite_create(mem_ctx
, io
->conn
->event_ctx
);
656 if (c
== NULL
) return NULL
;
658 s
= talloc_zero(c
, struct pipe_unix_state
);
659 if (composite_nomem(s
, c
)) return c
;
662 /* prepare pipe open parameters and store them in state structure
663 also, verify whether biding endpoint is not null */
666 s
->path
= dcerpc_binding_get_string_option(io
->binding
, "endpoint");
667 if (s
->path
== NULL
) {
668 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
672 /* send pipe open request on unix socket */
673 pipe_req
= dcerpc_pipe_open_unix_stream_send(s
->io
.conn
, s
->path
);
674 composite_continue(c
, pipe_req
, continue_pipe_open_ncacn_unix_stream
, c
);
680 Receive result of a rpc connection to a pipe on unix socket
682 static NTSTATUS
dcerpc_pipe_connect_ncacn_unix_stream_recv(struct composite_context
*c
)
684 NTSTATUS status
= composite_wait(c
);
691 struct pipe_ncalrpc_state
{
692 struct dcerpc_pipe_connect io
;
695 static NTSTATUS
dcerpc_pipe_connect_ncalrpc_recv(struct composite_context
*c
);
698 Stage 2 of ncalrpc: rpc pipe opened (or not)
700 static void continue_pipe_open_ncalrpc(struct composite_context
*ctx
)
702 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
703 struct composite_context
);
705 /* receive result of pipe open request on ncalrpc */
706 c
->status
= dcerpc_pipe_connect_ncalrpc_recv(ctx
);
707 if (!composite_is_ok(c
)) return;
714 Initiate async open of a rpc connection request on NCALRPC using
715 the binding structure to determine the endpoint and options
717 static struct composite_context
* dcerpc_pipe_connect_ncalrpc_send(TALLOC_CTX
*mem_ctx
,
718 struct dcerpc_pipe_connect
*io
)
720 struct composite_context
*c
;
721 struct pipe_ncalrpc_state
*s
;
722 struct composite_context
*pipe_req
;
723 const char *endpoint
;
725 /* composite context allocation and setup */
726 c
= composite_create(mem_ctx
, io
->conn
->event_ctx
);
727 if (c
== NULL
) return NULL
;
729 s
= talloc_zero(c
, struct pipe_ncalrpc_state
);
730 if (composite_nomem(s
, c
)) return c
;
733 /* store input parameters in state structure */
736 endpoint
= dcerpc_binding_get_string_option(io
->binding
, "endpoint");
737 if (endpoint
== NULL
) {
738 composite_error(c
, NT_STATUS_INVALID_PARAMETER_MIX
);
742 /* send pipe open request */
743 pipe_req
= dcerpc_pipe_open_pipe_send(s
->io
.conn
,
746 composite_continue(c
, pipe_req
, continue_pipe_open_ncalrpc
, c
);
752 Receive result of a rpc connection to a rpc pipe on NCALRPC
754 static NTSTATUS
dcerpc_pipe_connect_ncalrpc_recv(struct composite_context
*c
)
756 NTSTATUS status
= composite_wait(c
);
763 struct pipe_connect_state
{
764 struct dcerpc_pipe
*pipe
;
765 struct dcerpc_binding
*binding
;
766 const struct ndr_interface_table
*table
;
767 struct cli_credentials
*credentials
;
768 struct loadparm_context
*lp_ctx
;
772 static void continue_map_binding(struct composite_context
*ctx
);
773 static void continue_connect(struct composite_context
*c
, struct pipe_connect_state
*s
);
774 static void continue_pipe_connect_ncacn_np_smb(struct composite_context
*ctx
);
775 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context
*ctx
);
776 static void continue_pipe_connect_ncacn_http(struct composite_context
*ctx
);
777 static void continue_pipe_connect_ncacn_unix(struct composite_context
*ctx
);
778 static void continue_pipe_connect_ncalrpc(struct composite_context
*ctx
);
779 static void continue_pipe_connect(struct composite_context
*c
, struct pipe_connect_state
*s
);
780 static void continue_pipe_auth(struct composite_context
*ctx
);
784 Stage 2 of pipe_connect_b: Receive result of endpoint mapping
786 static void continue_map_binding(struct composite_context
*ctx
)
788 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
789 struct composite_context
);
790 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
791 struct pipe_connect_state
);
792 const char *endpoint
;
794 c
->status
= dcerpc_epm_map_binding_recv(ctx
);
795 if (!composite_is_ok(c
)) return;
797 endpoint
= dcerpc_binding_get_string_option(s
->binding
, "endpoint");
798 DEBUG(4,("Mapped to DCERPC endpoint %s\n", endpoint
));
800 continue_connect(c
, s
);
805 Stage 2 of pipe_connect_b: Continue connection after endpoint is known
807 static void continue_connect(struct composite_context
*c
, struct pipe_connect_state
*s
)
809 struct dcerpc_pipe_connect pc
;
811 /* potential exits to another stage by sending an async request */
812 struct composite_context
*ncacn_np_smb_req
;
813 struct composite_context
*ncacn_ip_tcp_req
;
814 struct composite_context
*ncacn_http_req
;
815 struct composite_context
*ncacn_unix_req
;
816 struct composite_context
*ncalrpc_req
;
817 enum dcerpc_transport_t transport
;
819 /* dcerpc pipe connect input parameters */
821 pc
.conn
= s
->pipe
->conn
;
822 pc
.binding
= s
->binding
;
823 pc
.interface
= s
->table
;
824 pc
.creds
= s
->credentials
;
825 pc
.resolve_ctx
= lpcfg_resolve_context(s
->lp_ctx
);
827 transport
= dcerpc_binding_get_transport(s
->binding
);
829 /* connect dcerpc pipe depending on required transport */
835 ncacn_np_smb_req
= dcerpc_pipe_connect_ncacn_np_smb_send(c
, &pc
, s
->lp_ctx
);
836 composite_continue(c
, ncacn_np_smb_req
, continue_pipe_connect_ncacn_np_smb
, c
);
840 ncacn_ip_tcp_req
= dcerpc_pipe_connect_ncacn_ip_tcp_send(c
, &pc
);
841 composite_continue(c
, ncacn_ip_tcp_req
, continue_pipe_connect_ncacn_ip_tcp
, c
);
845 ncacn_http_req
= dcerpc_pipe_connect_ncacn_http_send(c
, &pc
, s
->lp_ctx
);
846 composite_continue(c
, ncacn_http_req
, continue_pipe_connect_ncacn_http
, c
);
849 case NCACN_UNIX_STREAM
:
850 ncacn_unix_req
= dcerpc_pipe_connect_ncacn_unix_stream_send(c
, &pc
);
851 composite_continue(c
, ncacn_unix_req
, continue_pipe_connect_ncacn_unix
, c
);
855 pc
.ncalrpc
.dir
= lpcfg_ncalrpc_dir(s
->lp_ctx
);
856 c
->status
= dcerpc_binding_set_string_option(s
->binding
, "ncalrpc_dir",
858 if (!composite_is_ok(c
)) return;
859 ncalrpc_req
= dcerpc_pipe_connect_ncalrpc_send(c
, &pc
);
860 composite_continue(c
, ncalrpc_req
, continue_pipe_connect_ncalrpc
, c
);
864 /* looks like a transport we don't support now */
865 composite_error(c
, NT_STATUS_NOT_SUPPORTED
);
871 Stage 3 of pipe_connect_b: Receive result of pipe connect request on
874 static void continue_pipe_connect_ncacn_np_smb(struct composite_context
*ctx
)
876 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
877 struct composite_context
);
878 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
879 struct pipe_connect_state
);
881 c
->status
= dcerpc_pipe_connect_ncacn_np_smb_recv(ctx
);
882 if (!composite_is_ok(c
)) return;
884 continue_pipe_connect(c
, s
);
889 Stage 3 of pipe_connect_b: Receive result of pipe connect request on tcp/ip
891 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context
*ctx
)
893 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
894 struct composite_context
);
895 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
896 struct pipe_connect_state
);
898 c
->status
= dcerpc_pipe_connect_ncacn_ip_tcp_recv(ctx
);
899 if (!composite_is_ok(c
)) return;
901 continue_pipe_connect(c
, s
);
906 Stage 3 of pipe_connect_b: Receive result of pipe connect request on http
908 static void continue_pipe_connect_ncacn_http(struct composite_context
*ctx
)
910 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
911 struct composite_context
);
912 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
913 struct pipe_connect_state
);
915 c
->status
= dcerpc_pipe_connect_ncacn_http_recv(ctx
);
916 if (!composite_is_ok(c
)) return;
918 continue_pipe_connect(c
, s
);
923 Stage 3 of pipe_connect_b: Receive result of pipe connect request on unix socket
925 static void continue_pipe_connect_ncacn_unix(struct composite_context
*ctx
)
927 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
928 struct composite_context
);
929 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
930 struct pipe_connect_state
);
932 c
->status
= dcerpc_pipe_connect_ncacn_unix_stream_recv(ctx
);
933 if (!composite_is_ok(c
)) return;
935 continue_pipe_connect(c
, s
);
940 Stage 3 of pipe_connect_b: Receive result of pipe connect request on local rpc
942 static void continue_pipe_connect_ncalrpc(struct composite_context
*ctx
)
944 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
945 struct composite_context
);
946 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
947 struct pipe_connect_state
);
949 c
->status
= dcerpc_pipe_connect_ncalrpc_recv(ctx
);
950 if (!composite_is_ok(c
)) return;
952 continue_pipe_connect(c
, s
);
957 Stage 4 of pipe_connect_b: Start an authentication on connected dcerpc pipe
958 depending on credentials and binding flags passed.
960 static void continue_pipe_connect(struct composite_context
*c
, struct pipe_connect_state
*s
)
962 struct composite_context
*auth_bind_req
;
964 s
->pipe
->binding
= dcerpc_binding_dup(s
->pipe
, s
->binding
);
965 if (composite_nomem(s
->pipe
->binding
, c
)) {
969 auth_bind_req
= dcerpc_pipe_auth_send(s
->pipe
, s
->binding
, s
->table
,
970 s
->credentials
, s
->lp_ctx
);
971 composite_continue(c
, auth_bind_req
, continue_pipe_auth
, c
);
976 Stage 5 of pipe_connect_b: Receive result of pipe authentication request
977 and say if all went ok
979 static void continue_pipe_auth(struct composite_context
*ctx
)
981 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
982 struct composite_context
);
983 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
, struct pipe_connect_state
);
985 c
->status
= dcerpc_pipe_auth_recv(ctx
, s
, &s
->pipe
);
986 if (!composite_is_ok(c
)) return;
993 handle timeouts of a dcerpc connect
995 static void dcerpc_connect_timeout_handler(struct tevent_context
*ev
, struct tevent_timer
*te
,
996 struct timeval t
, void *private_data
)
998 struct composite_context
*c
= talloc_get_type_abort(private_data
,
999 struct composite_context
);
1000 struct pipe_connect_state
*s
= talloc_get_type_abort(c
->private_data
, struct pipe_connect_state
);
1001 if (!s
->pipe
->inhibit_timeout_processing
) {
1002 composite_error(c
, NT_STATUS_IO_TIMEOUT
);
1004 s
->pipe
->timed_out
= true;
1009 start a request to open a rpc connection to a rpc pipe, using
1010 specified binding structure to determine the endpoint and options
1012 _PUBLIC_
struct composite_context
* dcerpc_pipe_connect_b_send(TALLOC_CTX
*parent_ctx
,
1013 const struct dcerpc_binding
*binding
,
1014 const struct ndr_interface_table
*table
,
1015 struct cli_credentials
*credentials
,
1016 struct tevent_context
*ev
,
1017 struct loadparm_context
*lp_ctx
)
1019 struct composite_context
*c
;
1020 struct pipe_connect_state
*s
;
1021 enum dcerpc_transport_t transport
;
1022 const char *endpoint
= NULL
;
1023 struct cli_credentials
*epm_creds
= NULL
;
1025 /* composite context allocation and setup */
1026 c
= composite_create(parent_ctx
, ev
);
1031 s
= talloc_zero(c
, struct pipe_connect_state
);
1032 if (composite_nomem(s
, c
)) return c
;
1033 c
->private_data
= s
;
1035 /* initialise dcerpc pipe structure */
1036 s
->pipe
= dcerpc_pipe_init(c
, ev
);
1037 if (composite_nomem(s
->pipe
, c
)) return c
;
1039 if (DEBUGLEVEL
>= 10)
1040 s
->pipe
->conn
->packet_log_dir
= lpcfg_lock_directory(lp_ctx
);
1042 /* store parameters in state structure */
1043 s
->binding
= dcerpc_binding_dup(s
, binding
);
1044 if (composite_nomem(s
->binding
, c
)) return c
;
1046 s
->credentials
= credentials
;
1049 s
->pipe
->timed_out
= false;
1050 s
->pipe
->inhibit_timeout_processing
= false;
1052 tevent_add_timer(c
->event_ctx
, c
,
1053 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT
, 0),
1054 dcerpc_connect_timeout_handler
, c
);
1056 transport
= dcerpc_binding_get_transport(s
->binding
);
1058 switch (transport
) {
1062 endpoint
= dcerpc_binding_get_string_option(s
->binding
, "endpoint");
1064 /* anonymous credentials for rpc connection used to get endpoint mapping */
1065 epm_creds
= cli_credentials_init_anon(s
);
1066 if (composite_nomem(epm_creds
, c
)) return c
;
1070 endpoint
= dcerpc_binding_get_string_option(s
->binding
, "endpoint");
1071 epm_creds
= credentials
;
1074 DBG_INFO("Unknown transport; continuing with anon, no endpoint.\n");
1075 epm_creds
= cli_credentials_init_anon(s
);
1076 if (composite_nomem(epm_creds
, c
)){
1082 if (endpoint
== NULL
) {
1083 struct composite_context
*binding_req
;
1085 binding_req
= dcerpc_epm_map_binding_send(c
, s
->binding
, s
->table
,
1087 s
->pipe
->conn
->event_ctx
,
1089 composite_continue(c
, binding_req
, continue_map_binding
, c
);
1093 continue_connect(c
, s
);
1099 receive result of a request to open a rpc connection to a rpc pipe
1101 _PUBLIC_ NTSTATUS
dcerpc_pipe_connect_b_recv(struct composite_context
*c
, TALLOC_CTX
*mem_ctx
,
1102 struct dcerpc_pipe
**p
)
1105 struct pipe_connect_state
*s
;
1107 status
= composite_wait(c
);
1109 if (NT_STATUS_IS_OK(status
)) {
1110 s
= talloc_get_type(c
->private_data
, struct pipe_connect_state
);
1111 talloc_steal(mem_ctx
, s
->pipe
);
1120 open a rpc connection to a rpc pipe, using the specified
1121 binding structure to determine the endpoint and options - sync version
1123 _PUBLIC_ NTSTATUS
dcerpc_pipe_connect_b(TALLOC_CTX
*parent_ctx
,
1124 struct dcerpc_pipe
**pp
,
1125 const struct dcerpc_binding
*binding
,
1126 const struct ndr_interface_table
*table
,
1127 struct cli_credentials
*credentials
,
1128 struct tevent_context
*ev
,
1129 struct loadparm_context
*lp_ctx
)
1131 struct composite_context
*c
;
1133 c
= dcerpc_pipe_connect_b_send(parent_ctx
, binding
, table
,
1134 credentials
, ev
, lp_ctx
);
1135 return dcerpc_pipe_connect_b_recv(c
, parent_ctx
, pp
);
1139 struct pipe_conn_state
{
1140 struct dcerpc_pipe
*pipe
;
1144 static void continue_pipe_connect_b(struct composite_context
*ctx
);
1148 Initiate rpc connection to a rpc pipe, using the specified string
1149 binding to determine the endpoint and options.
1150 The string is to be parsed to a binding structure first.
1152 _PUBLIC_
struct composite_context
* dcerpc_pipe_connect_send(TALLOC_CTX
*parent_ctx
,
1153 const char *binding
,
1154 const struct ndr_interface_table
*table
,
1155 struct cli_credentials
*credentials
,
1156 struct tevent_context
*ev
, struct loadparm_context
*lp_ctx
)
1158 struct composite_context
*c
;
1159 struct pipe_conn_state
*s
;
1160 struct dcerpc_binding
*b
;
1161 struct composite_context
*pipe_conn_req
;
1163 /* composite context allocation and setup */
1164 c
= composite_create(parent_ctx
, ev
);
1169 s
= talloc_zero(c
, struct pipe_conn_state
);
1170 if (composite_nomem(s
, c
)) return c
;
1171 c
->private_data
= s
;
1173 /* parse binding string to the structure */
1174 c
->status
= dcerpc_parse_binding(c
, binding
, &b
);
1175 if (!NT_STATUS_IS_OK(c
->status
)) {
1176 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding
));
1177 composite_error(c
, c
->status
);
1181 DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(c
, b
)));
1184 start connecting to a rpc pipe after binding structure
1187 pipe_conn_req
= dcerpc_pipe_connect_b_send(c
, b
, table
,
1188 credentials
, ev
, lp_ctx
);
1189 composite_continue(c
, pipe_conn_req
, continue_pipe_connect_b
, c
);
1195 Stage 2 of pipe_connect: Receive result of actual pipe connect request
1196 and say if we're done ok
1198 static void continue_pipe_connect_b(struct composite_context
*ctx
)
1200 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
1201 struct composite_context
);
1202 struct pipe_conn_state
*s
= talloc_get_type(c
->private_data
,
1203 struct pipe_conn_state
);
1205 c
->status
= dcerpc_pipe_connect_b_recv(ctx
, c
, &s
->pipe
);
1206 talloc_steal(s
, s
->pipe
);
1207 if (!composite_is_ok(c
)) return;
1214 Receive result of pipe connect (using binding string) request
1215 and return connected pipe structure.
1217 NTSTATUS
dcerpc_pipe_connect_recv(struct composite_context
*c
,
1218 TALLOC_CTX
*mem_ctx
,
1219 struct dcerpc_pipe
**pp
)
1222 struct pipe_conn_state
*s
;
1224 status
= composite_wait(c
);
1225 if (NT_STATUS_IS_OK(status
)) {
1226 s
= talloc_get_type(c
->private_data
, struct pipe_conn_state
);
1227 *pp
= talloc_steal(mem_ctx
, s
->pipe
);
1235 Open a rpc connection to a rpc pipe, using the specified string
1236 binding to determine the endpoint and options - sync version
1238 _PUBLIC_ NTSTATUS
dcerpc_pipe_connect(TALLOC_CTX
*parent_ctx
,
1239 struct dcerpc_pipe
**pp
,
1240 const char *binding
,
1241 const struct ndr_interface_table
*table
,
1242 struct cli_credentials
*credentials
,
1243 struct tevent_context
*ev
,
1244 struct loadparm_context
*lp_ctx
)
1246 struct composite_context
*c
;
1247 c
= dcerpc_pipe_connect_send(parent_ctx
, binding
,
1248 table
, credentials
, ev
, lp_ctx
);
1249 return dcerpc_pipe_connect_recv(c
, parent_ctx
, pp
);