2005-12-06 11:56:13 +03:00
/*
Unix SMB / CIFS implementation .
dcerpc connect functions
Copyright ( C ) Andrew Tridgell 2003
Copyright ( C ) Jelmer Vernooij 2004
2007-07-16 15:27:29 +04:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2005 - 2007
2005-12-06 11:56:13 +03:00
Copyright ( C ) Rafal Szczesniak 2005
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-12-06 11:56:13 +03:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-12-06 11:56:13 +03:00
*/
2024-09-19 00:35:20 +03:00
# define SOURCE4_LIBRPC_INTERNALS 1
2005-12-06 11:56:13 +03:00
# include "includes.h"
# include "libcli/composite/composite.h"
# include "libcli/smb_composite/smb_composite.h"
2006-05-04 14:03:41 +04:00
# include "lib/events/events.h"
2005-12-28 18:38:36 +03:00
# include "libcli/smb2/smb2.h"
2006-01-03 20:27:33 +03:00
# include "libcli/smb2/smb2_calls.h"
2013-09-19 20:16:16 +04:00
# include "libcli/smb/smbXcli_base.h"
2006-03-18 18:42:57 +03:00
# include "librpc/rpc/dcerpc.h"
2008-04-02 06:53:27 +04:00
# include "librpc/rpc/dcerpc_proto.h"
2006-05-04 21:39:35 +04:00
# include "auth/credentials/credentials.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2007-12-10 20:41:19 +03:00
# include "libcli/resolve/resolve.h"
2019-04-02 19:34:24 +03:00
# include "libcli/http/http.h"
2018-07-18 17:55:33 +03:00
# include "lib/util/util_net.h"
2005-12-06 11:56:13 +03:00
2020-08-07 23:27:39 +03:00
# undef strcasecmp
2013-12-04 17:28:11 +04:00
struct dcerpc_pipe_connect {
2014-02-12 13:48:52 +04:00
struct dcecli_connection * conn ;
2014-02-13 19:28:54 +04:00
struct dcerpc_binding * binding ;
2013-12-04 17:28:11 +04:00
const struct ndr_interface_table * interface ;
struct cli_credentials * creds ;
struct resolve_context * resolve_ctx ;
2014-02-13 12:42:10 +04:00
struct {
const char * dir ;
} ncalrpc ;
2014-01-15 15:56:36 +04:00
struct {
struct smbXcli_conn * conn ;
struct smbXcli_session * session ;
struct smbXcli_tcon * tcon ;
const char * pipe_name ;
} smb ;
2013-12-04 17:28:11 +04:00
} ;
2005-12-06 11:56:13 +03:00
struct pipe_np_smb_state {
struct smb_composite_connect conn ;
struct dcerpc_pipe_connect io ;
} ;
2005-12-06 22:44:49 +03:00
/*
2005-12-10 13:10:44 +03:00
Stage 3 of ncacn_np_smb : Named pipe opened ( or not )
2005-12-06 22:44:49 +03:00
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_open_smb ( struct composite_context * ctx )
2005-12-06 11:56:13 +03:00
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
2005-12-10 13:10:44 +03:00
/* receive result of named pipe open request on smb */
2005-12-06 11:56:13 +03:00
c - > status = dcerpc_pipe_open_smb_recv ( ctx ) ;
2006-03-10 23:08:15 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2005-12-06 11:56:13 +03:00
composite_done ( c ) ;
}
2014-01-15 16:03:27 +04:00
static void continue_smb_open ( struct composite_context * c ) ;
2018-07-18 17:55:33 +03:00
static void continue_smb2_connect ( struct tevent_req * subreq ) ;
static void continue_smbXcli_connect ( struct tevent_req * subreq ) ;
2006-05-04 21:39:35 +04:00
2005-12-06 22:44:49 +03:00
/*
Stage 2 of ncacn_np_smb : Open a named pipe after successful smb connection
*/
2006-03-10 02:21:49 +03:00
static void continue_smb_connect ( struct composite_context * ctx )
2005-12-06 11:56:13 +03:00
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
struct pipe_np_smb_state * s = talloc_get_type ( c - > private_data ,
struct pipe_np_smb_state ) ;
2013-09-19 20:16:16 +04:00
struct smbcli_tree * t ;
2005-12-06 22:44:49 +03:00
/* receive result of smb connect request */
2014-02-12 13:48:52 +04:00
c - > status = smb_composite_connect_recv ( ctx , s - > io . conn ) ;
2006-03-10 23:08:15 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2005-12-06 11:56:13 +03:00
2013-09-19 20:16:16 +04:00
t = s - > conn . out . tree ;
2014-01-15 15:56:36 +04:00
/* prepare named pipe open parameters */
s - > io . smb . conn = t - > session - > transport - > conn ;
s - > io . smb . session = t - > session - > smbXcli ;
s - > io . smb . tcon = t - > smbXcli ;
smb1cli_tcon_set_id ( s - > io . smb . tcon , t - > tid ) ;
s - > io . smb . pipe_name = dcerpc_binding_get_string_option ( s - > io . binding ,
" endpoint " ) ;
2013-09-19 20:16:16 +04:00
2014-01-15 16:03:27 +04:00
continue_smb_open ( c ) ;
}
static void continue_smb_open ( struct composite_context * c )
{
struct pipe_np_smb_state * s = talloc_get_type ( c - > private_data ,
struct pipe_np_smb_state ) ;
struct composite_context * open_ctx ;
2005-12-06 22:44:49 +03:00
/* send named pipe open request */
2014-02-12 13:48:52 +04:00
open_ctx = dcerpc_pipe_open_smb_send ( s - > io . conn ,
2014-01-15 15:56:36 +04:00
s - > io . smb . conn ,
s - > io . smb . session ,
s - > io . smb . tcon ,
2014-01-15 16:17:42 +04:00
DCERPC_REQUEST_TIMEOUT * 1000 ,
2014-01-15 15:56:36 +04:00
s - > io . smb . pipe_name ) ;
2006-03-10 02:21:49 +03:00
if ( composite_nomem ( open_ctx , c ) ) return ;
2005-12-06 11:56:13 +03:00
composite_continue ( c , open_ctx , continue_pipe_open_smb , c ) ;
}
2005-12-06 22:44:49 +03:00
/*
Initiate async open of a rpc connection to a rpc pipe on SMB using
the binding structure to determine the endpoint and options
*/
2008-01-03 00:00:58 +03:00
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 )
2005-12-06 11:56:13 +03:00
{
struct composite_context * c ;
struct pipe_np_smb_state * s ;
2018-07-18 17:55:33 +03:00
struct tevent_req * subreq = NULL ;
2005-12-06 11:56:13 +03:00
struct smb_composite_connect * conn ;
2014-02-04 13:02:28 +04:00
uint32_t flags ;
2018-07-18 17:55:33 +03:00
const char * target_hostname = NULL ;
const char * dest_address = NULL ;
const char * calling_name = NULL ;
2005-12-06 11:56:13 +03:00
2005-12-06 22:44:49 +03:00
/* composite context allocation and setup */
2014-02-12 13:48:52 +04:00
c = composite_create ( mem_ctx , io - > conn - > event_ctx ) ;
2005-12-06 11:56:13 +03:00
if ( c = = NULL ) return NULL ;
2005-12-06 14:52:16 +03:00
s = talloc_zero ( c , struct pipe_np_smb_state ) ;
2006-03-10 02:21:49 +03:00
if ( composite_nomem ( s , c ) ) return c ;
2005-12-06 20:42:04 +03:00
c - > private_data = s ;
2005-12-06 11:56:13 +03:00
s - > io = * io ;
conn = & s - > conn ;
2014-01-15 16:06:20 +04:00
if ( smbXcli_conn_is_connected ( s - > io . smb . conn ) ) {
continue_smb_open ( c ) ;
return c ;
}
2018-07-18 17:55:33 +03:00
if ( s - > io . creds = = NULL ) {
composite_error ( c , NT_STATUS_INVALID_PARAMETER_MIX ) ;
return c ;
}
2005-12-06 22:44:49 +03:00
/* prepare smb connection parameters: we're connecting to IPC$ share on
remote rpc server */
2018-07-18 17:55:33 +03:00
target_hostname = dcerpc_binding_get_string_option ( s - > io . binding , " target_hostname " ) ;
2014-02-04 13:03:09 +04:00
conn - > in . dest_host = dcerpc_binding_get_string_option ( s - > io . binding , " host " ) ;
conn - > in . dest_ports = lpcfg_smb_ports ( lp_ctx ) ;
2018-07-18 17:55:33 +03:00
conn - > in . called_name = target_hostname ;
2014-02-04 13:03:09 +04:00
if ( conn - > in . called_name = = NULL ) {
conn - > in . called_name = " *SMBSERVER " ;
}
2010-07-16 08:32:42 +04:00
conn - > in . socket_options = lpcfg_socket_options ( lp_ctx ) ;
2005-12-06 11:56:13 +03:00
conn - > in . service = " IPC$ " ;
conn - > in . service_type = NULL ;
2010-07-16 08:32:42 +04:00
conn - > in . workgroup = lpcfg_workgroup ( lp_ctx ) ;
conn - > in . gensec_settings = lpcfg_gensec_settings ( conn , lp_ctx ) ;
2008-10-24 15:13:27 +04:00
2010-07-16 08:32:42 +04:00
lpcfg_smbcli_options ( lp_ctx , & conn - > in . options ) ;
lpcfg_smbcli_session_options ( lp_ctx , & conn - > in . session_options ) ;
2008-01-03 03:39:15 +03:00
2005-12-06 22:44:49 +03:00
/*
2006-01-12 12:33:49 +03:00
* provide proper credentials - user supplied , but allow a
* fallback to anonymous if this is an schannel connection
* ( might be NT4 not allowing machine logins at session
2009-06-18 06:33:46 +04:00
* setup ) or if asked to do so by the caller ( perhaps a SAMR password change ? )
2005-12-06 22:44:49 +03:00
*/
2006-01-12 12:33:49 +03:00
s - > conn . in . credentials = s - > io . creds ;
2014-02-04 13:02:28 +04:00
flags = dcerpc_binding_get_flags ( s - > io . binding ) ;
if ( flags & ( DCERPC_SCHANNEL | DCERPC_ANON_FALLBACK ) ) {
2007-09-25 20:05:08 +04:00
conn - > in . fallback_to_anonymous = true ;
2005-12-06 11:56:13 +03:00
} else {
2007-09-25 20:05:08 +04:00
conn - > in . fallback_to_anonymous = false ;
2005-12-06 11:56:13 +03:00
}
2018-07-18 17:55:33 +03:00
conn - > in . options . min_protocol = lpcfg_client_ipc_min_protocol ( lp_ctx ) ;
conn - > in . options . max_protocol = lpcfg_client_ipc_max_protocol ( lp_ctx ) ;
if ( ( flags & DCERPC_SMB1 ) & & ( flags & DCERPC_SMB2 ) ) {
/* auto */
} else if ( flags & DCERPC_SMB2 ) {
if ( conn - > in . options . min_protocol < PROTOCOL_SMB2_02 ) {
conn - > in . options . min_protocol = PROTOCOL_SMB2_02 ;
}
if ( conn - > in . options . max_protocol < PROTOCOL_SMB2_02 ) {
conn - > in . options . max_protocol = PROTOCOL_LATEST ;
}
} else if ( flags & DCERPC_SMB1 ) {
conn - > in . options . min_protocol = PROTOCOL_NT1 ;
conn - > in . options . max_protocol = PROTOCOL_NT1 ;
} else {
/* auto */
}
2014-03-28 16:44:29 +04:00
conn - > in . options . signing = lpcfg_client_ipc_signing ( lp_ctx ) ;
2018-07-18 17:55:33 +03:00
if ( s - > conn . in . credentials ! = NULL ) {
calling_name = cli_credentials_get_workstation ( s - > conn . in . credentials ) ;
}
if ( calling_name = = NULL ) {
calling_name = " SMBCLIENT " ;
}
if ( target_hostname = = NULL ) {
target_hostname = conn - > in . dest_host ;
}
2019-07-24 08:50:35 +03:00
if ( conn - > in . dest_host ! = NULL & & is_ipaddress ( conn - > in . dest_host ) ) {
2018-07-18 17:55:33 +03:00
dest_address = conn - > in . dest_host ;
}
subreq = smb_connect_nego_send ( s ,
c - > event_ctx ,
s - > io . resolve_ctx ,
& conn - > in . options ,
conn - > in . socket_options ,
conn - > in . dest_host ,
dest_address ,
conn - > in . dest_ports ,
target_hostname ,
conn - > in . called_name ,
calling_name ) ;
if ( composite_nomem ( subreq , c ) ) return c ;
tevent_req_set_callback ( subreq ,
continue_smbXcli_connect ,
c ) ;
2005-12-06 11:56:13 +03:00
2005-12-06 14:11:11 +03:00
return c ;
2005-12-06 11:56:13 +03:00
}
2018-07-18 17:55:33 +03:00
static void continue_smbXcli_connect ( struct tevent_req * subreq )
{
struct composite_context * c =
tevent_req_callback_data ( subreq ,
struct composite_context ) ;
struct pipe_np_smb_state * s =
talloc_get_type_abort ( c - > private_data ,
struct pipe_np_smb_state ) ;
struct smb_composite_connect * conn = & s - > conn ;
struct composite_context * creq = NULL ;
enum protocol_types protocol ;
c - > status = smb_connect_nego_recv ( subreq , s ,
& conn - > in . existing_conn ) ;
TALLOC_FREE ( subreq ) ;
if ( ! composite_is_ok ( c ) ) return ;
protocol = smbXcli_conn_protocol ( conn - > in . existing_conn ) ;
if ( protocol > = PROTOCOL_SMB2_02 ) {
/*
* continue with smb2 session setup / tree connect
* on the established connection .
*/
subreq = smb2_connect_send ( s , c - > event_ctx ,
conn - > in . dest_host ,
conn - > in . dest_ports ,
conn - > in . service ,
s - > io . resolve_ctx ,
conn - > in . credentials ,
conn - > in . fallback_to_anonymous ,
& conn - > in . existing_conn ,
0 , /* previous_session_id */
& conn - > in . options ,
conn - > in . socket_options ,
conn - > in . gensec_settings ) ;
if ( composite_nomem ( subreq , c ) ) return ;
tevent_req_set_callback ( subreq , continue_smb2_connect , c ) ;
return ;
}
/*
* continue with smb1 session setup / tree connect
* on the established connection .
*/
creq = smb_composite_connect_send ( conn , s - > io . conn ,
s - > io . resolve_ctx ,
c - > event_ctx ) ;
if ( composite_nomem ( creq , c ) ) return ;
composite_continue ( c , creq , continue_smb_connect , c ) ;
return ;
}
2005-12-06 11:56:13 +03:00
2005-12-06 22:44:49 +03:00
/*
Receive result of a rpc connection to a rpc pipe on SMB
*/
2006-10-24 11:56:59 +04:00
static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb_recv ( struct composite_context * c )
2005-12-06 11:56:13 +03:00
{
NTSTATUS status = composite_wait ( c ) ;
talloc_free ( c ) ;
return status ;
}
2005-12-10 13:10:44 +03:00
/*
Stage 2 of ncacn_np_smb2 : Open a named pipe after successful smb2 connection
*/
2011-04-27 10:57:41 +04:00
static void continue_smb2_connect ( struct tevent_req * subreq )
2005-12-09 03:04:38 +03:00
{
2011-04-27 10:57:41 +04:00
struct composite_context * c =
tevent_req_callback_data ( subreq ,
struct composite_context ) ;
2014-01-15 15:58:52 +04:00
struct pipe_np_smb_state * s = talloc_get_type ( c - > private_data ,
struct pipe_np_smb_state ) ;
2013-09-19 20:43:06 +04:00
struct smb2_tree * t ;
2005-12-09 03:04:38 +03:00
2005-12-10 13:10:44 +03:00
/* receive result of smb2 connect request */
2014-02-12 13:48:52 +04:00
c - > status = smb2_connect_recv ( subreq , s - > io . conn , & t ) ;
2011-04-27 10:57:41 +04:00
TALLOC_FREE ( subreq ) ;
2006-03-10 23:08:15 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2005-12-10 13:10:44 +03:00
2014-01-15 15:56:36 +04:00
s - > io . smb . conn = t - > session - > transport - > conn ;
s - > io . smb . session = t - > session - > smbXcli ;
s - > io . smb . tcon = t - > smbXcli ;
s - > io . smb . pipe_name = dcerpc_binding_get_string_option ( s - > io . binding ,
" endpoint " ) ;
2013-09-19 20:43:06 +04:00
2014-01-15 16:03:27 +04:00
continue_smb_open ( c ) ;
2005-12-09 03:04:38 +03:00
}
2006-02-19 19:58:48 +03:00
struct pipe_ip_tcp_state {
struct dcerpc_pipe_connect io ;
2010-08-27 16:04:07 +04:00
const char * localaddr ;
2006-02-19 19:58:48 +03:00
const char * host ;
2006-10-13 17:01:48 +04:00
const char * target_hostname ;
2006-02-19 19:58:48 +03:00
uint32_t port ;
} ;
2006-02-20 20:30:15 +03:00
/*
Stage 2 of ncacn_ip_tcp : rpc pipe opened ( or not )
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_open_ncacn_ip_tcp ( struct composite_context * ctx )
2006-02-19 19:58:48 +03:00
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
2014-02-13 19:28:54 +04:00
struct pipe_ip_tcp_state * s = talloc_get_type ( c - > private_data ,
struct pipe_ip_tcp_state ) ;
char * localaddr = NULL ;
char * remoteaddr = NULL ;
2006-02-19 19:58:48 +03:00
2006-02-20 20:30:15 +03:00
/* receive result of named pipe open request on tcp/ip */
2014-02-13 19:28:54 +04:00
c - > status = dcerpc_pipe_open_tcp_recv ( ctx , s , & localaddr , & remoteaddr ) ;
if ( ! composite_is_ok ( c ) ) return ;
c - > status = dcerpc_binding_set_string_option ( s - > io . binding ,
" localaddress " ,
localaddr ) ;
if ( ! composite_is_ok ( c ) ) return ;
c - > status = dcerpc_binding_set_string_option ( s - > io . binding ,
" host " ,
remoteaddr ) ;
2006-03-10 23:08:15 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2006-02-19 19:58:48 +03:00
composite_done ( c ) ;
}
2006-02-20 20:30:15 +03:00
/*
Initiate async open of a rpc connection to a rpc pipe on TCP / IP using
the binding structure to determine the endpoint and options
*/
2006-10-24 11:56:59 +04:00
static struct composite_context * dcerpc_pipe_connect_ncacn_ip_tcp_send ( TALLOC_CTX * mem_ctx ,
struct dcerpc_pipe_connect * io )
2006-02-19 19:58:48 +03:00
{
struct composite_context * c ;
struct pipe_ip_tcp_state * s ;
struct composite_context * pipe_req ;
2014-02-04 14:30:38 +04:00
const char * endpoint ;
2006-02-19 19:58:48 +03:00
/* composite context allocation and setup */
2014-02-12 13:48:52 +04:00
c = composite_create ( mem_ctx , io - > conn - > event_ctx ) ;
2006-02-19 19:58:48 +03:00
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct pipe_ip_tcp_state ) ;
2006-03-10 02:21:49 +03:00
if ( composite_nomem ( s , c ) ) return c ;
2006-02-19 19:58:48 +03:00
c - > private_data = s ;
2006-02-20 20:30:15 +03:00
/* store input parameters in state structure */
2014-02-04 13:03:09 +04:00
s - > io = * io ;
2014-01-16 18:39:55 +04:00
s - > localaddr = dcerpc_binding_get_string_option ( io - > binding ,
" localaddress " ) ;
2014-02-04 13:03:09 +04:00
s - > host = dcerpc_binding_get_string_option ( io - > binding , " host " ) ;
s - > target_hostname = dcerpc_binding_get_string_option ( io - > binding ,
" target_hostname " ) ;
2014-02-04 14:30:38 +04:00
endpoint = dcerpc_binding_get_string_option ( io - > binding , " endpoint " ) ;
/* port number is a binding endpoint here */
if ( endpoint ! = NULL ) {
s - > port = atoi ( endpoint ) ;
}
if ( s - > port = = 0 ) {
composite_error ( c , NT_STATUS_INVALID_PARAMETER_MIX ) ;
return c ;
}
2006-02-19 19:58:48 +03:00
2006-02-20 20:30:15 +03:00
/* send pipe open request on tcp/ip */
2014-02-12 13:48:52 +04:00
pipe_req = dcerpc_pipe_open_tcp_send ( s - > io . conn , s - > localaddr , s - > host , s - > target_hostname ,
2007-12-10 20:41:19 +03:00
s - > port , io - > resolve_ctx ) ;
2006-02-19 19:58:48 +03:00
composite_continue ( c , pipe_req , continue_pipe_open_ncacn_ip_tcp , c ) ;
return c ;
}
2006-02-20 20:30:15 +03:00
/*
Receive result of a rpc connection to a rpc pipe on TCP / IP
*/
2006-10-24 11:56:59 +04:00
static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp_recv ( struct composite_context * c )
2006-02-19 19:58:48 +03:00
{
NTSTATUS status = composite_wait ( c ) ;
talloc_free ( c ) ;
return status ;
}
2014-09-16 19:01:02 +04:00
struct pipe_http_state {
struct dcerpc_pipe_connect io ;
const char * localaddr ;
2017-07-21 00:05:53 +03:00
const char * target_hostname ;
2014-09-16 19:01:02 +04:00
const char * rpc_server ;
uint32_t rpc_server_port ;
char * rpc_proxy ;
uint32_t rpc_proxy_port ;
char * http_proxy ;
uint32_t http_proxy_port ;
bool use_tls ;
bool use_proxy ;
2017-07-20 14:05:39 +03:00
enum http_auth_method http_auth ;
2014-09-16 19:01:02 +04:00
struct loadparm_context * lp_ctx ;
} ;
/*
Stage 2 of ncacn_http : rpc pipe opened ( or not )
*/
static void continue_pipe_open_ncacn_http ( struct tevent_req * subreq )
{
struct composite_context * c = NULL ;
struct pipe_http_state * s = NULL ;
struct tstream_context * stream = NULL ;
struct tevent_queue * queue = NULL ;
c = tevent_req_callback_data ( subreq , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct pipe_http_state ) ;
/* receive result of RoH connect request */
c - > status = dcerpc_pipe_open_roh_recv ( subreq , s - > io . conn ,
& stream , & queue ) ;
TALLOC_FREE ( subreq ) ;
if ( ! composite_is_ok ( c ) ) return ;
s - > io . conn - > transport . transport = NCACN_HTTP ;
s - > io . conn - > transport . stream = stream ;
s - > io . conn - > transport . write_queue = queue ;
s - > io . conn - > transport . pending_reads = 0 ;
2017-07-21 00:05:53 +03:00
s - > io . conn - > server_name = strupper_talloc ( s - > io . conn ,
s - > target_hostname ) ;
2014-09-16 19:01:02 +04:00
composite_done ( c ) ;
}
/*
Initiate async open of a rpc connection to a rpc pipe using HTTP transport ,
and using the binding structure to determine the endpoint and options
*/
static struct composite_context * dcerpc_pipe_connect_ncacn_http_send (
TALLOC_CTX * mem_ctx , struct dcerpc_pipe_connect * io ,
struct loadparm_context * lp_ctx )
{
struct composite_context * c ;
struct pipe_http_state * s ;
struct tevent_req * subreq ;
const char * endpoint ;
const char * use_proxy ;
char * proxy ;
char * port ;
const char * opt ;
/* composite context allocation and setup */
c = composite_create ( mem_ctx , io - > conn - > event_ctx ) ;
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct pipe_http_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
/* store input parameters in state structure */
s - > lp_ctx = lp_ctx ;
s - > io = * io ;
s - > localaddr = dcerpc_binding_get_string_option ( io - > binding ,
" localaddress " ) ;
/* RPC server and port (the endpoint) */
s - > rpc_server = dcerpc_binding_get_string_option ( io - > binding , " host " ) ;
2017-07-21 00:05:53 +03:00
s - > target_hostname = dcerpc_binding_get_string_option ( io - > binding ,
" target_hostname " ) ;
2014-09-16 19:01:02 +04:00
endpoint = dcerpc_binding_get_string_option ( io - > binding , " endpoint " ) ;
if ( endpoint = = NULL ) {
composite_error ( c , NT_STATUS_INVALID_PARAMETER_MIX ) ;
return c ;
}
s - > rpc_server_port = atoi ( endpoint ) ;
if ( s - > rpc_server_port = = 0 ) {
composite_error ( c , NT_STATUS_INVALID_PARAMETER_MIX ) ;
return c ;
}
/* Use TLS */
opt = dcerpc_binding_get_string_option ( io - > binding , " HttpUseTls " ) ;
if ( opt ) {
if ( strcasecmp ( opt , " true " ) = = 0 ) {
s - > use_tls = true ;
} else if ( strcasecmp ( opt , " false " ) = = 0 ) {
s - > use_tls = false ;
} else {
composite_error ( c , NT_STATUS_INVALID_PARAMETER_MIX ) ;
return c ;
}
} else {
s - > use_tls = true ;
}
/* RPC Proxy */
proxy = port = talloc_strdup ( s , dcerpc_binding_get_string_option (
io - > binding , " RpcProxy " ) ) ;
s - > rpc_proxy = strsep ( & port , " : " ) ;
if ( proxy & & port ) {
s - > rpc_proxy_port = atoi ( port ) ;
} else {
s - > rpc_proxy_port = s - > use_tls ? 443 : 80 ;
}
if ( s - > rpc_proxy = = NULL ) {
s - > rpc_proxy = talloc_strdup ( s , s - > rpc_server ) ;
if ( composite_nomem ( s - > rpc_proxy , c ) ) return c ;
}
/* HTTP Proxy */
proxy = port = talloc_strdup ( s , dcerpc_binding_get_string_option (
io - > binding , " HttpProxy " ) ) ;
s - > http_proxy = strsep ( & port , " : " ) ;
if ( proxy & & port ) {
s - > http_proxy_port = atoi ( port ) ;
} else {
s - > http_proxy_port = s - > use_tls ? 443 : 80 ;
}
/* Use local proxy */
use_proxy = dcerpc_binding_get_string_option ( io - > binding ,
" HttpConnectOption " ) ;
if ( use_proxy & & strcasecmp ( use_proxy , " UseHttpProxy " ) ) {
s - > use_proxy = true ;
}
/* If use local proxy set, the http proxy should be provided */
if ( s - > use_proxy & & ! s - > http_proxy ) {
composite_error ( c , NT_STATUS_INVALID_PARAMETER_MIX ) ;
return c ;
}
/* Check which HTTP authentication method to use */
opt = dcerpc_binding_get_string_option ( io - > binding , " HttpAuthOption " ) ;
if ( opt ) {
if ( strcasecmp ( opt , " basic " ) = = 0 ) {
2017-07-20 14:05:39 +03:00
s - > http_auth = HTTP_AUTH_BASIC ;
2014-09-16 19:01:02 +04:00
} else if ( strcasecmp ( opt , " ntlm " ) = = 0 ) {
2017-07-20 14:05:39 +03:00
s - > http_auth = HTTP_AUTH_NTLM ;
2017-07-20 14:06:58 +03:00
} else if ( strcasecmp ( opt , " negotiate " ) = = 0 ) {
s - > http_auth = HTTP_AUTH_NEGOTIATE ;
2014-09-16 19:01:02 +04:00
} else {
composite_error ( c , NT_STATUS_INVALID_PARAMETER_MIX ) ;
return c ;
}
} else {
2017-07-20 14:05:39 +03:00
s - > http_auth = HTTP_AUTH_NTLM ;
2014-09-16 19:01:02 +04:00
}
subreq = dcerpc_pipe_open_roh_send ( s - > io . conn , s - > localaddr ,
s - > rpc_server , s - > rpc_server_port ,
s - > rpc_proxy , s - > rpc_proxy_port ,
s - > http_proxy , s - > http_proxy_port ,
s - > use_tls , s - > use_proxy ,
s - > io . creds , io - > resolve_ctx ,
2017-07-20 14:05:39 +03:00
s - > lp_ctx , s - > http_auth ) ;
2014-09-16 19:01:02 +04:00
if ( composite_nomem ( subreq , c ) ) return c ;
tevent_req_set_callback ( subreq , continue_pipe_open_ncacn_http , c ) ;
return c ;
}
static NTSTATUS dcerpc_pipe_connect_ncacn_http_recv ( struct composite_context * c )
{
return composite_wait_free ( c ) ;
}
2006-02-19 19:58:48 +03:00
struct pipe_unix_state {
struct dcerpc_pipe_connect io ;
const char * path ;
} ;
2006-02-20 20:30:15 +03:00
/*
Stage 2 of ncacn_unix : rpc pipe opened ( or not )
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_open_ncacn_unix_stream ( struct composite_context * ctx )
2006-02-19 19:58:48 +03:00
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
2006-02-20 20:30:15 +03:00
/* receive result of pipe open request on unix socket */
2006-02-19 19:58:48 +03:00
c - > status = dcerpc_pipe_open_unix_stream_recv ( ctx ) ;
2006-03-10 23:08:15 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2006-02-19 19:58:48 +03:00
composite_done ( c ) ;
}
2006-02-20 20:30:15 +03:00
/*
Initiate async open of a rpc connection to a rpc pipe on unix socket using
the binding structure to determine the endpoint and options
*/
2006-10-24 11:56:59 +04:00
static struct composite_context * dcerpc_pipe_connect_ncacn_unix_stream_send ( TALLOC_CTX * mem_ctx ,
struct dcerpc_pipe_connect * io )
2006-02-19 19:58:48 +03:00
{
struct composite_context * c ;
struct pipe_unix_state * s ;
struct composite_context * pipe_req ;
/* composite context allocation and setup */
2014-02-12 13:48:52 +04:00
c = composite_create ( mem_ctx , io - > conn - > event_ctx ) ;
2006-02-19 19:58:48 +03:00
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct pipe_unix_state ) ;
2006-03-10 02:21:49 +03:00
if ( composite_nomem ( s , c ) ) return c ;
2006-02-19 19:58:48 +03:00
c - > private_data = s ;
2006-02-20 20:30:15 +03:00
/* prepare pipe open parameters and store them in state structure
also , verify whether biding endpoint is not null */
s - > io = * io ;
2014-02-04 14:30:38 +04:00
s - > path = dcerpc_binding_get_string_option ( io - > binding , " endpoint " ) ;
if ( s - > path = = NULL ) {
composite_error ( c , NT_STATUS_INVALID_PARAMETER_MIX ) ;
2006-03-10 02:21:49 +03:00
return c ;
2006-02-19 19:58:48 +03:00
}
2006-02-20 20:30:15 +03:00
/* send pipe open request on unix socket */
2014-02-12 13:48:52 +04:00
pipe_req = dcerpc_pipe_open_unix_stream_send ( s - > io . conn , s - > path ) ;
2006-02-19 19:58:48 +03:00
composite_continue ( c , pipe_req , continue_pipe_open_ncacn_unix_stream , c ) ;
return c ;
}
2006-02-20 20:30:15 +03:00
/*
Receive result of a rpc connection to a pipe on unix socket
*/
2006-10-24 11:56:59 +04:00
static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream_recv ( struct composite_context * c )
2006-02-19 19:58:48 +03:00
{
NTSTATUS status = composite_wait ( c ) ;
talloc_free ( c ) ;
return status ;
}
struct pipe_ncalrpc_state {
struct dcerpc_pipe_connect io ;
} ;
2006-10-24 11:56:59 +04:00
static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv ( struct composite_context * c ) ;
2006-02-19 19:58:48 +03:00
2006-02-20 20:30:15 +03:00
/*
Stage 2 of ncalrpc : rpc pipe opened ( or not )
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_open_ncalrpc ( struct composite_context * ctx )
2006-02-19 19:58:48 +03:00
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
2006-02-20 20:30:15 +03:00
/* receive result of pipe open request on ncalrpc */
2006-02-19 19:58:48 +03:00
c - > status = dcerpc_pipe_connect_ncalrpc_recv ( ctx ) ;
2006-03-10 23:08:15 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2006-02-19 19:58:48 +03:00
composite_done ( c ) ;
}
2006-02-20 20:30:15 +03:00
/*
Initiate async open of a rpc connection request on NCALRPC using
the binding structure to determine the endpoint and options
*/
2006-10-24 11:56:59 +04:00
static struct composite_context * dcerpc_pipe_connect_ncalrpc_send ( TALLOC_CTX * mem_ctx ,
2014-02-13 12:42:10 +04:00
struct dcerpc_pipe_connect * io )
2006-02-19 19:58:48 +03:00
{
struct composite_context * c ;
struct pipe_ncalrpc_state * s ;
struct composite_context * pipe_req ;
2014-02-04 14:30:38 +04:00
const char * endpoint ;
2006-02-19 19:58:48 +03:00
/* composite context allocation and setup */
2014-02-12 13:48:52 +04:00
c = composite_create ( mem_ctx , io - > conn - > event_ctx ) ;
2006-02-19 19:58:48 +03:00
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct pipe_ncalrpc_state ) ;
2006-03-10 02:21:49 +03:00
if ( composite_nomem ( s , c ) ) return c ;
2006-02-19 19:58:48 +03:00
c - > private_data = s ;
2006-02-20 20:30:15 +03:00
/* store input parameters in state structure */
2006-02-19 19:58:48 +03:00
s - > io = * io ;
2014-02-04 14:30:38 +04:00
endpoint = dcerpc_binding_get_string_option ( io - > binding , " endpoint " ) ;
if ( endpoint = = NULL ) {
composite_error ( c , NT_STATUS_INVALID_PARAMETER_MIX ) ;
return c ;
}
2006-02-20 20:30:15 +03:00
/* send pipe open request */
2014-02-12 13:48:52 +04:00
pipe_req = dcerpc_pipe_open_pipe_send ( s - > io . conn ,
2014-02-13 12:42:10 +04:00
s - > io . ncalrpc . dir ,
2014-02-04 14:30:38 +04:00
endpoint ) ;
2006-02-19 19:58:48 +03:00
composite_continue ( c , pipe_req , continue_pipe_open_ncalrpc , c ) ;
return c ;
}
2006-02-20 20:30:15 +03:00
/*
Receive result of a rpc connection to a rpc pipe on NCALRPC
*/
2006-10-24 11:56:59 +04:00
static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv ( struct composite_context * c )
2006-02-19 19:58:48 +03:00
{
NTSTATUS status = composite_wait ( c ) ;
talloc_free ( c ) ;
return status ;
}
2006-03-10 02:21:49 +03:00
struct pipe_connect_state {
struct dcerpc_pipe * pipe ;
struct dcerpc_binding * binding ;
2007-08-20 00:46:45 +04:00
const struct ndr_interface_table * table ;
2006-03-10 02:21:49 +03:00
struct cli_credentials * credentials ;
2007-12-07 04:37:04 +03:00
struct loadparm_context * lp_ctx ;
2006-03-10 02:21:49 +03:00
} ;
static void continue_map_binding ( struct composite_context * ctx ) ;
static void continue_connect ( struct composite_context * c , struct pipe_connect_state * s ) ;
static void continue_pipe_connect_ncacn_np_smb ( struct composite_context * ctx ) ;
static void continue_pipe_connect_ncacn_ip_tcp ( struct composite_context * ctx ) ;
2014-09-16 19:01:02 +04:00
static void continue_pipe_connect_ncacn_http ( struct composite_context * ctx ) ;
2006-03-10 02:21:49 +03:00
static void continue_pipe_connect_ncacn_unix ( struct composite_context * ctx ) ;
static void continue_pipe_connect_ncalrpc ( struct composite_context * ctx ) ;
static void continue_pipe_connect ( struct composite_context * c , struct pipe_connect_state * s ) ;
static void continue_pipe_auth ( struct composite_context * ctx ) ;
2006-03-10 19:36:35 +03:00
/*
Stage 2 of pipe_connect_b : Receive result of endpoint mapping
*/
2006-03-10 02:21:49 +03:00
static void continue_map_binding ( struct composite_context * ctx )
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
struct pipe_connect_state * s = talloc_get_type ( c - > private_data ,
struct pipe_connect_state ) ;
2014-02-04 14:30:38 +04:00
const char * endpoint ;
2006-03-10 02:21:49 +03:00
c - > status = dcerpc_epm_map_binding_recv ( ctx ) ;
2006-03-10 23:08:15 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2006-03-10 02:21:49 +03:00
2014-02-04 14:30:38 +04:00
endpoint = dcerpc_binding_get_string_option ( s - > binding , " endpoint " ) ;
DEBUG ( 4 , ( " Mapped to DCERPC endpoint %s \n " , endpoint ) ) ;
2006-03-10 02:21:49 +03:00
continue_connect ( c , s ) ;
}
2006-03-10 19:36:35 +03:00
/*
Stage 2 of pipe_connect_b : Continue connection after endpoint is known
*/
2006-03-10 02:21:49 +03:00
static void continue_connect ( struct composite_context * c , struct pipe_connect_state * s )
{
struct dcerpc_pipe_connect pc ;
/* potential exits to another stage by sending an async request */
struct composite_context * ncacn_np_smb_req ;
struct composite_context * ncacn_ip_tcp_req ;
2014-09-16 19:01:02 +04:00
struct composite_context * ncacn_http_req ;
2006-03-10 02:21:49 +03:00
struct composite_context * ncacn_unix_req ;
struct composite_context * ncalrpc_req ;
2014-01-31 01:00:44 +04:00
enum dcerpc_transport_t transport ;
2006-03-10 02:21:49 +03:00
/* dcerpc pipe connect input parameters */
2014-02-13 12:42:10 +04:00
ZERO_STRUCT ( pc ) ;
2014-02-12 13:48:52 +04:00
pc . conn = s - > pipe - > conn ;
2006-03-10 02:21:49 +03:00
pc . binding = s - > binding ;
pc . interface = s - > table ;
pc . creds = s - > credentials ;
2010-07-16 08:32:42 +04:00
pc . resolve_ctx = lpcfg_resolve_context ( s - > lp_ctx ) ;
2006-10-24 11:56:59 +04:00
2014-01-31 01:00:44 +04:00
transport = dcerpc_binding_get_transport ( s - > binding ) ;
2014-03-28 16:44:29 +04:00
2006-03-10 19:36:35 +03:00
/* connect dcerpc pipe depending on required transport */
2014-01-31 01:00:44 +04:00
switch ( transport ) {
2006-03-10 02:21:49 +03:00
case NCACN_NP :
2018-07-18 17:55:33 +03:00
/*
* SMB1 / 2 / 3. . .
*/
ncacn_np_smb_req = dcerpc_pipe_connect_ncacn_np_smb_send ( c , & pc , s - > lp_ctx ) ;
composite_continue ( c , ncacn_np_smb_req , continue_pipe_connect_ncacn_np_smb , c ) ;
return ;
2006-03-10 02:21:49 +03:00
case NCACN_IP_TCP :
ncacn_ip_tcp_req = dcerpc_pipe_connect_ncacn_ip_tcp_send ( c , & pc ) ;
composite_continue ( c , ncacn_ip_tcp_req , continue_pipe_connect_ncacn_ip_tcp , c ) ;
return ;
2014-09-16 19:01:02 +04:00
case NCACN_HTTP :
ncacn_http_req = dcerpc_pipe_connect_ncacn_http_send ( c , & pc , s - > lp_ctx ) ;
composite_continue ( c , ncacn_http_req , continue_pipe_connect_ncacn_http , c ) ;
return ;
2006-03-10 02:21:49 +03:00
case NCACN_UNIX_STREAM :
ncacn_unix_req = dcerpc_pipe_connect_ncacn_unix_stream_send ( c , & pc ) ;
composite_continue ( c , ncacn_unix_req , continue_pipe_connect_ncacn_unix , c ) ;
return ;
case NCALRPC :
2014-02-13 12:42:10 +04:00
pc . ncalrpc . dir = lpcfg_ncalrpc_dir ( s - > lp_ctx ) ;
c - > status = dcerpc_binding_set_string_option ( s - > binding , " ncalrpc_dir " ,
pc . ncalrpc . dir ) ;
if ( ! composite_is_ok ( c ) ) return ;
ncalrpc_req = dcerpc_pipe_connect_ncalrpc_send ( c , & pc ) ;
2006-03-10 02:21:49 +03:00
composite_continue ( c , ncalrpc_req , continue_pipe_connect_ncalrpc , c ) ;
return ;
default :
2006-03-10 19:36:35 +03:00
/* looks like a transport we don't support now */
2006-03-10 02:21:49 +03:00
composite_error ( c , NT_STATUS_NOT_SUPPORTED ) ;
}
}
2006-03-10 19:36:35 +03:00
/*
Stage 3 of pipe_connect_b : Receive result of pipe connect request on
named pipe on smb
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_connect_ncacn_np_smb ( struct composite_context * ctx )
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
struct pipe_connect_state * s = talloc_get_type ( c - > private_data ,
struct pipe_connect_state ) ;
c - > status = dcerpc_pipe_connect_ncacn_np_smb_recv ( ctx ) ;
if ( ! composite_is_ok ( c ) ) return ;
continue_pipe_connect ( c , s ) ;
}
2006-03-10 19:36:35 +03:00
/*
Stage 3 of pipe_connect_b : Receive result of pipe connect request on tcp / ip
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_connect_ncacn_ip_tcp ( struct composite_context * ctx )
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
struct pipe_connect_state * s = talloc_get_type ( c - > private_data ,
struct pipe_connect_state ) ;
c - > status = dcerpc_pipe_connect_ncacn_ip_tcp_recv ( ctx ) ;
if ( ! composite_is_ok ( c ) ) return ;
continue_pipe_connect ( c , s ) ;
}
2014-09-16 19:01:02 +04:00
/*
Stage 3 of pipe_connect_b : Receive result of pipe connect request on http
*/
static void continue_pipe_connect_ncacn_http ( struct composite_context * ctx )
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
struct pipe_connect_state * s = talloc_get_type ( c - > private_data ,
struct pipe_connect_state ) ;
c - > status = dcerpc_pipe_connect_ncacn_http_recv ( ctx ) ;
if ( ! composite_is_ok ( c ) ) return ;
continue_pipe_connect ( c , s ) ;
}
2006-03-10 19:36:35 +03:00
/*
Stage 3 of pipe_connect_b : Receive result of pipe connect request on unix socket
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_connect_ncacn_unix ( struct composite_context * ctx )
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
struct pipe_connect_state * s = talloc_get_type ( c - > private_data ,
struct pipe_connect_state ) ;
c - > status = dcerpc_pipe_connect_ncacn_unix_stream_recv ( ctx ) ;
if ( ! composite_is_ok ( c ) ) return ;
continue_pipe_connect ( c , s ) ;
}
2006-03-10 19:36:35 +03:00
/*
Stage 3 of pipe_connect_b : Receive result of pipe connect request on local rpc
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_connect_ncalrpc ( struct composite_context * ctx )
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
struct pipe_connect_state * s = talloc_get_type ( c - > private_data ,
struct pipe_connect_state ) ;
c - > status = dcerpc_pipe_connect_ncalrpc_recv ( ctx ) ;
if ( ! composite_is_ok ( c ) ) return ;
continue_pipe_connect ( c , s ) ;
}
2006-03-10 19:36:35 +03:00
/*
Stage 4 of pipe_connect_b : Start an authentication on connected dcerpc pipe
depending on credentials and binding flags passed .
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_connect ( struct composite_context * c , struct pipe_connect_state * s )
{
struct composite_context * auth_bind_req ;
2013-09-19 20:23:37 +04:00
s - > pipe - > binding = dcerpc_binding_dup ( s - > pipe , s - > binding ) ;
if ( composite_nomem ( s - > pipe - > binding , c ) ) {
2006-03-10 02:21:49 +03:00
return ;
}
auth_bind_req = dcerpc_pipe_auth_send ( s - > pipe , s - > binding , s - > table ,
2007-12-07 04:37:04 +03:00
s - > credentials , s - > lp_ctx ) ;
2006-03-10 02:21:49 +03:00
composite_continue ( c , auth_bind_req , continue_pipe_auth , c ) ;
}
2006-03-10 19:36:35 +03:00
/*
Stage 5 of pipe_connect_b : Receive result of pipe authentication request
and say if all went ok
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_auth ( struct composite_context * ctx )
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
2006-05-04 14:03:41 +04:00
struct pipe_connect_state * s = talloc_get_type ( c - > private_data , struct pipe_connect_state ) ;
2006-03-10 02:21:49 +03:00
2006-05-07 23:55:14 +04:00
c - > status = dcerpc_pipe_auth_recv ( ctx , s , & s - > pipe ) ;
2006-03-10 02:21:49 +03:00
if ( ! composite_is_ok ( c ) ) return ;
composite_done ( c ) ;
}
2006-09-01 14:33:55 +04:00
/*
handle timeouts of a dcerpc connect
*/
2008-12-29 22:24:57 +03:00
static void dcerpc_connect_timeout_handler ( struct tevent_context * ev , struct tevent_timer * te ,
2009-02-02 10:27:33 +03:00
struct timeval t , void * private_data )
2006-09-01 14:33:55 +04:00
{
2012-07-29 14:37:39 +04:00
struct composite_context * c = talloc_get_type_abort ( private_data ,
2012-07-09 08:37:28 +04:00
struct composite_context ) ;
2017-05-29 10:32:12 +03:00
struct pipe_connect_state * s = talloc_get_type_abort ( c - > private_data , struct pipe_connect_state ) ;
if ( ! s - > pipe - > inhibit_timeout_processing ) {
composite_error ( c , NT_STATUS_IO_TIMEOUT ) ;
} else {
s - > pipe - > timed_out = true ;
}
2006-09-01 14:33:55 +04:00
}
2006-03-10 19:36:35 +03:00
/*
start a request to open a rpc connection to a rpc pipe , using
specified binding structure to determine the endpoint and options
*/
2008-04-02 06:53:27 +04:00
_PUBLIC_ struct composite_context * dcerpc_pipe_connect_b_send ( TALLOC_CTX * parent_ctx ,
2014-02-12 15:11:51 +04:00
const struct dcerpc_binding * binding ,
2007-08-20 00:46:45 +04:00
const struct ndr_interface_table * table ,
2006-03-10 02:21:49 +03:00
struct cli_credentials * credentials ,
2008-12-29 22:24:57 +03:00
struct tevent_context * ev ,
2007-12-07 04:37:04 +03:00
struct loadparm_context * lp_ctx )
2006-03-10 02:21:49 +03:00
{
struct composite_context * c ;
struct pipe_connect_state * s ;
2014-01-31 01:00:44 +04:00
enum dcerpc_transport_t transport ;
const char * endpoint = NULL ;
2014-09-21 11:20:26 +04:00
struct cli_credentials * epm_creds = NULL ;
2006-07-30 22:24:07 +04:00
2006-03-10 02:21:49 +03:00
/* composite context allocation and setup */
2006-07-30 22:24:07 +04:00
c = composite_create ( parent_ctx , ev ) ;
if ( c = = NULL ) {
return NULL ;
}
2006-03-10 02:21:49 +03:00
s = talloc_zero ( c , struct pipe_connect_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
/* initialise dcerpc pipe structure */
2010-05-09 19:20:01 +04:00
s - > pipe = dcerpc_pipe_init ( c , ev ) ;
2006-03-10 02:21:49 +03:00
if ( composite_nomem ( s - > pipe , c ) ) return c ;
2022-03-20 10:43:34 +03:00
if ( DEBUGLEVEL > = 10 ) {
2014-02-03 06:46:08 +04:00
s - > pipe - > conn - > packet_log_dir = lpcfg_lock_directory ( lp_ctx ) ;
2022-03-20 10:43:34 +03:00
}
2008-11-02 02:26:04 +03:00
2006-03-10 19:36:35 +03:00
/* store parameters in state structure */
2014-02-12 15:11:51 +04:00
s - > binding = dcerpc_binding_dup ( s , binding ) ;
if ( composite_nomem ( s - > binding , c ) ) return c ;
2006-03-10 02:21:49 +03:00
s - > table = table ;
s - > credentials = credentials ;
2007-12-07 04:37:04 +03:00
s - > lp_ctx = lp_ctx ;
2006-09-01 14:33:55 +04:00
2017-05-29 10:32:12 +03:00
s - > pipe - > timed_out = false ;
s - > pipe - > inhibit_timeout_processing = false ;
2012-07-29 14:37:39 +04:00
tevent_add_timer ( c - > event_ctx , c ,
2012-07-09 08:37:28 +04:00
timeval_current_ofs ( DCERPC_REQUEST_TIMEOUT , 0 ) ,
2012-07-29 14:37:39 +04:00
dcerpc_connect_timeout_handler , c ) ;
2007-08-29 06:01:56 +04:00
2014-01-31 01:00:44 +04:00
transport = dcerpc_binding_get_transport ( s - > binding ) ;
switch ( transport ) {
2006-03-10 02:21:49 +03:00
case NCACN_NP :
case NCACN_IP_TCP :
case NCALRPC :
2014-01-31 01:00:44 +04:00
endpoint = dcerpc_binding_get_string_option ( s - > binding , " endpoint " ) ;
2014-09-21 11:20:26 +04:00
/* anonymous credentials for rpc connection used to get endpoint mapping */
epm_creds = cli_credentials_init_anon ( s ) ;
if ( composite_nomem ( epm_creds , c ) ) return c ;
break ;
case NCACN_HTTP :
endpoint = dcerpc_binding_get_string_option ( s - > binding , " endpoint " ) ;
epm_creds = credentials ;
2014-01-31 01:00:44 +04:00
break ;
2006-03-10 02:21:49 +03:00
default :
2019-07-10 07:24:46 +03:00
DBG_INFO ( " Unknown transport; continuing with anon, no endpoint. \n " ) ;
epm_creds = cli_credentials_init_anon ( s ) ;
if ( composite_nomem ( epm_creds , c ) ) {
return c ;
}
2006-03-10 02:21:49 +03:00
break ;
}
2014-01-31 01:00:44 +04:00
if ( endpoint = = NULL ) {
struct composite_context * binding_req ;
binding_req = dcerpc_epm_map_binding_send ( c , s - > binding , s - > table ,
2014-09-21 11:20:26 +04:00
epm_creds ,
2014-01-31 01:00:44 +04:00
s - > pipe - > conn - > event_ctx ,
s - > lp_ctx ) ;
composite_continue ( c , binding_req , continue_map_binding , c ) ;
return c ;
}
2006-03-10 02:21:49 +03:00
continue_connect ( c , s ) ;
return c ;
}
2006-03-10 19:36:35 +03:00
/*
receive result of a request to open a rpc connection to a rpc pipe
*/
2008-04-02 06:53:27 +04:00
_PUBLIC_ NTSTATUS dcerpc_pipe_connect_b_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx ,
2006-03-10 02:21:49 +03:00
struct dcerpc_pipe * * p )
{
NTSTATUS status ;
struct pipe_connect_state * s ;
status = composite_wait ( c ) ;
2006-10-13 17:01:48 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
s = talloc_get_type ( c - > private_data , struct pipe_connect_state ) ;
talloc_steal ( mem_ctx , s - > pipe ) ;
* p = s - > pipe ;
}
2006-03-10 02:21:49 +03:00
talloc_free ( c ) ;
return status ;
}
/*
open a rpc connection to a rpc pipe , using the specified
binding structure to determine the endpoint and options - sync version
*/
2008-04-02 06:53:27 +04:00
_PUBLIC_ NTSTATUS dcerpc_pipe_connect_b ( TALLOC_CTX * parent_ctx ,
2006-03-10 02:21:49 +03:00
struct dcerpc_pipe * * pp ,
2014-02-12 15:11:51 +04:00
const struct dcerpc_binding * binding ,
2007-08-20 00:46:45 +04:00
const struct ndr_interface_table * table ,
2006-03-10 02:21:49 +03:00
struct cli_credentials * credentials ,
2008-12-29 22:24:57 +03:00
struct tevent_context * ev ,
2007-12-07 04:37:04 +03:00
struct loadparm_context * lp_ctx )
2006-03-10 02:21:49 +03:00
{
struct composite_context * c ;
2006-05-04 14:03:41 +04:00
c = dcerpc_pipe_connect_b_send ( parent_ctx , binding , table ,
2007-12-07 04:37:04 +03:00
credentials , ev , lp_ctx ) ;
2006-03-10 02:21:49 +03:00
return dcerpc_pipe_connect_b_recv ( c , parent_ctx , pp ) ;
}
struct pipe_conn_state {
struct dcerpc_pipe * pipe ;
} ;
static void continue_pipe_connect_b ( struct composite_context * ctx ) ;
2006-03-10 19:36:35 +03:00
/*
Initiate rpc connection to a rpc pipe , using the specified string
binding to determine the endpoint and options .
The string is to be parsed to a binding structure first .
*/
2008-04-02 06:53:27 +04:00
_PUBLIC_ struct composite_context * dcerpc_pipe_connect_send ( TALLOC_CTX * parent_ctx ,
2006-03-10 02:21:49 +03:00
const char * binding ,
2007-08-20 00:46:45 +04:00
const struct ndr_interface_table * table ,
2006-03-10 02:21:49 +03:00
struct cli_credentials * credentials ,
2008-12-29 22:24:57 +03:00
struct tevent_context * ev , struct loadparm_context * lp_ctx )
2006-03-10 02:21:49 +03:00
{
struct composite_context * c ;
struct pipe_conn_state * s ;
struct dcerpc_binding * b ;
struct composite_context * pipe_conn_req ;
2006-03-10 19:36:35 +03:00
/* composite context allocation and setup */
2006-07-30 22:24:07 +04:00
c = composite_create ( parent_ctx , ev ) ;
if ( c = = NULL ) {
return NULL ;
}
2006-03-10 02:21:49 +03:00
s = talloc_zero ( c , struct pipe_conn_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
2006-03-10 19:36:35 +03:00
/* parse binding string to the structure */
2006-07-30 22:24:07 +04:00
c - > status = dcerpc_parse_binding ( c , binding , & b ) ;
if ( ! NT_STATUS_IS_OK ( c - > status ) ) {
2006-03-10 02:21:49 +03:00
DEBUG ( 0 , ( " Failed to parse dcerpc binding '%s' \n " , binding ) ) ;
2006-07-30 22:24:07 +04:00
composite_error ( c , c - > status ) ;
2006-03-10 02:21:49 +03:00
return c ;
}
DEBUG ( 3 , ( " Using binding %s \n " , dcerpc_binding_string ( c , b ) ) ) ;
2006-03-10 19:36:35 +03:00
/*
start connecting to a rpc pipe after binding structure
is established
*/
2006-05-04 14:03:41 +04:00
pipe_conn_req = dcerpc_pipe_connect_b_send ( c , b , table ,
2007-12-07 04:37:04 +03:00
credentials , ev , lp_ctx ) ;
2006-03-10 02:21:49 +03:00
composite_continue ( c , pipe_conn_req , continue_pipe_connect_b , c ) ;
return c ;
}
2006-03-10 19:36:35 +03:00
/*
Stage 2 of pipe_connect : Receive result of actual pipe connect request
and say if we ' re done ok
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_connect_b ( struct composite_context * ctx )
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
struct pipe_conn_state * s = talloc_get_type ( c - > private_data ,
struct pipe_conn_state ) ;
c - > status = dcerpc_pipe_connect_b_recv ( ctx , c , & s - > pipe ) ;
2006-05-04 14:03:41 +04:00
talloc_steal ( s , s - > pipe ) ;
2006-03-10 02:21:49 +03:00
if ( ! composite_is_ok ( c ) ) return ;
composite_done ( c ) ;
}
2006-03-10 19:36:35 +03:00
/*
Receive result of pipe connect ( using binding string ) request
and return connected pipe structure .
*/
2006-03-10 02:21:49 +03:00
NTSTATUS dcerpc_pipe_connect_recv ( struct composite_context * c ,
TALLOC_CTX * mem_ctx ,
struct dcerpc_pipe * * pp )
{
NTSTATUS status ;
struct pipe_conn_state * s ;
status = composite_wait ( c ) ;
2007-04-25 16:36:12 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
s = talloc_get_type ( c - > private_data , struct pipe_conn_state ) ;
* pp = talloc_steal ( mem_ctx , s - > pipe ) ;
}
2006-03-10 02:21:49 +03:00
talloc_free ( c ) ;
return status ;
}
/*
2006-03-10 19:36:35 +03:00
Open a rpc connection to a rpc pipe , using the specified string
2006-03-10 02:21:49 +03:00
binding to determine the endpoint and options - sync version
*/
2008-04-02 06:53:27 +04:00
_PUBLIC_ NTSTATUS dcerpc_pipe_connect ( TALLOC_CTX * parent_ctx ,
2006-03-10 02:21:49 +03:00
struct dcerpc_pipe * * pp ,
const char * binding ,
2007-08-20 00:46:45 +04:00
const struct ndr_interface_table * table ,
2006-03-10 02:21:49 +03:00
struct cli_credentials * credentials ,
2008-12-29 22:24:57 +03:00
struct tevent_context * ev ,
2007-12-07 04:37:04 +03:00
struct loadparm_context * lp_ctx )
2006-03-10 02:21:49 +03:00
{
struct composite_context * c ;
2006-10-13 17:01:48 +04:00
c = dcerpc_pipe_connect_send ( parent_ctx , binding ,
2007-12-07 04:37:04 +03:00
table , credentials , ev , lp_ctx ) ;
2006-03-10 02:21:49 +03:00
return dcerpc_pipe_connect_recv ( c , parent_ctx , pp ) ;
}