2010-06-04 00:04:08 +04:00
/*
* Unix SMB / CIFS implementation .
* RPC Pipe client / server routines
* Copyright ( C ) Andrew Tridgell 1992 - 1998 ,
* Largely re - written : 2005
* Copyright ( C ) Jeremy Allison 1998 - 2005
2010-07-07 23:24:00 +04:00
* Copyright ( C ) Simo Sorce 2010
2011-07-18 16:26:31 +04:00
* Copyright ( C ) Andrew Bartlett 2011
2010-06-04 00:04:08 +04:00
*
* 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
* the Free Software Foundation ; either version 3 of the License , or
* ( 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
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
2011-02-28 12:19:44 +03:00
# include "rpc_client/cli_pipe.h"
2010-08-18 20:26:17 +04:00
# include "rpc_dce.h"
2010-07-07 23:24:00 +04:00
# include "../libcli/named_pipe_auth/npa_tstream.h"
# include "rpc_server/rpc_ncacn_np.h"
# include "librpc/gen_ndr/netlogon.h"
2011-02-09 06:22:16 +03:00
# include "librpc/gen_ndr/auth.h"
# include "../auth/auth_sam_reply.h"
2018-08-30 17:33:25 +03:00
# include "../auth/auth_util.h"
2011-03-24 14:08:15 +03:00
# include "auth.h"
2011-07-21 19:02:59 +04:00
# include "rpc_server/rpc_pipes.h"
2011-04-28 19:26:40 +04:00
# include "../lib/tsocket/tsocket.h"
2011-04-28 19:38:09 +04:00
# include "../lib/util/tevent_ntstatus.h"
2011-08-10 23:34:37 +04:00
# include "rpc_server/rpc_config.h"
2013-09-18 12:59:14 +04:00
# include "librpc/ndr/ndr_table.h"
2013-09-25 13:35:41 +04:00
# include "rpc_server/rpc_server.h"
2021-04-02 13:20:38 +03:00
# include "librpc/rpc/dcerpc_util.h"
2010-06-04 00:04:08 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_RPC_SRV
2019-02-18 23:04:00 +03:00
struct np_proxy_state {
uint16_t file_type ;
uint16_t device_state ;
uint64_t allocation_size ;
struct tstream_context * npipe ;
struct tevent_queue * read_queue ;
struct tevent_queue * write_queue ;
} ;
static struct np_proxy_state * make_external_rpc_pipe_p ( TALLOC_CTX * mem_ctx ,
const char * pipe_name ,
const struct tsocket_address * remote_address ,
const struct tsocket_address * local_address ,
const struct auth_session_info * session_info ) ;
2013-09-24 13:27:35 +04:00
static struct npa_state * npa_state_init ( TALLOC_CTX * mem_ctx )
{
struct npa_state * npa ;
npa = talloc_zero ( mem_ctx , struct npa_state ) ;
if ( npa = = NULL ) {
return NULL ;
}
npa - > read_queue = tevent_queue_create ( npa , " npa_cli_read " ) ;
if ( npa - > read_queue = = NULL ) {
DEBUG ( 0 , ( " tevent_queue_create failed \n " ) ) ;
goto fail ;
}
npa - > write_queue = tevent_queue_create ( npa , " npa_cli_write " ) ;
if ( npa - > write_queue = = NULL ) {
DEBUG ( 0 , ( " tevent_queue_create failed \n " ) ) ;
goto fail ;
}
return npa ;
fail :
talloc_free ( npa ) ;
return NULL ;
}
2018-04-11 11:42:21 +03:00
NTSTATUS make_internal_rpc_pipe_socketpair (
TALLOC_CTX * mem_ctx ,
struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2019-02-27 23:36:22 +03:00
struct dcesrv_context * dce_ctx ,
struct dcesrv_endpoint * endpoint ,
2018-04-11 11:42:21 +03:00
const struct tsocket_address * remote_address ,
const struct tsocket_address * local_address ,
const struct auth_session_info * session_info ,
struct npa_state * * pnpa )
2013-09-25 13:35:41 +04:00
{
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
2019-02-18 21:38:08 +03:00
struct dcerpc_ncacn_conn * ncacn_conn = NULL ;
2019-12-05 13:45:54 +03:00
struct dcesrv_connection * dcesrv_conn = NULL ;
2013-09-25 13:35:41 +04:00
struct npa_state * npa ;
NTSTATUS status ;
int rc ;
2019-02-27 23:36:22 +03:00
enum dcerpc_transport_t transport = dcerpc_binding_get_transport (
endpoint - > ep_description ) ;
const char * pipe_name = dcerpc_binding_get_string_option (
endpoint - > ep_description , " endpoint " ) ;
2013-09-25 13:35:41 +04:00
DEBUG ( 4 , ( " Create of internal pipe %s requested \n " , pipe_name ) ) ;
npa = npa_state_init ( tmp_ctx ) ;
if ( npa = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
npa - > file_type = FILE_TYPE_MESSAGE_MODE_PIPE ;
npa - > device_state = 0xff | 0x0400 | 0x0100 ;
npa - > allocation_size = 4096 ;
2019-02-18 21:38:08 +03:00
status = dcerpc_ncacn_conn_init ( npa ,
ev_ctx ,
msg_ctx ,
2019-02-28 01:44:16 +03:00
dce_ctx ,
endpoint ,
2019-02-18 21:38:08 +03:00
NULL , /* termination fn */
NULL , /* termination data */
& ncacn_conn ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2013-09-25 13:35:41 +04:00
goto out ;
}
2019-02-18 21:38:08 +03:00
npa - > private_data = ( void * ) ncacn_conn ;
2013-09-25 13:35:41 +04:00
rc = tstream_npa_socketpair ( npa - > file_type ,
npa ,
& npa - > stream ,
2019-02-18 21:38:08 +03:00
ncacn_conn ,
& ncacn_conn - > tstream ) ;
2013-09-25 13:35:41 +04:00
if ( rc = = - 1 ) {
status = map_nt_error_from_unix ( errno ) ;
goto out ;
}
2019-02-18 21:38:08 +03:00
ncacn_conn - > remote_client_addr = tsocket_address_copy ( remote_address ,
ncacn_conn ) ;
if ( ncacn_conn - > remote_client_addr = = NULL ) {
2013-09-25 13:35:41 +04:00
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
2019-02-18 21:38:08 +03:00
ncacn_conn - > remote_client_name = tsocket_address_inet_addr_string (
ncacn_conn - > remote_client_addr , ncacn_conn ) ;
if ( ncacn_conn - > remote_client_name = = NULL ) {
2013-09-25 13:35:41 +04:00
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
2019-02-18 21:38:08 +03:00
ncacn_conn - > local_server_addr = tsocket_address_copy ( local_address ,
ncacn_conn ) ;
if ( ncacn_conn - > local_server_addr = = NULL ) {
2018-04-11 11:42:21 +03:00
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
2019-02-18 21:38:08 +03:00
ncacn_conn - > local_server_name = tsocket_address_inet_addr_string (
ncacn_conn - > local_server_addr , ncacn_conn ) ;
if ( ncacn_conn - > local_server_name = = NULL ) {
2018-04-11 11:42:21 +03:00
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
2019-02-18 21:38:08 +03:00
ncacn_conn - > session_info = copy_session_info ( ncacn_conn , session_info ) ;
if ( ncacn_conn - > session_info = = NULL ) {
2013-09-25 13:35:41 +04:00
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
2021-01-11 23:35:26 +03:00
rc = make_base_pipes_struct ( ncacn_conn ,
ncacn_conn - > msg_ctx ,
pipe_name ,
transport ,
ncacn_conn - > remote_client_addr ,
ncacn_conn - > local_server_addr ,
& ncacn_conn - > p ) ;
if ( rc ! = 0 ) {
status = map_nt_error_from_unix ( rc ) ;
2013-09-25 13:35:41 +04:00
goto out ;
}
2019-12-05 13:45:54 +03:00
/*
* This fills in dcesrv_conn - > endpoint with the endpoint
* associated with the socket . From this point on we know
* which ( group of ) services we are handling , but not the
* specific interface .
*/
status = dcesrv_endpoint_connect ( ncacn_conn - > dce_ctx ,
ncacn_conn ,
ncacn_conn - > endpoint ,
ncacn_conn - > session_info ,
ncacn_conn - > ev_ctx ,
DCESRV_CALL_STATE_FLAG_MAY_ASYNC ,
& dcesrv_conn ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " Failed to connect to endpoint: %s \n " ,
nt_errstr ( status ) ) ;
goto out ;
}
dcesrv_conn - > transport . private_data = ncacn_conn ;
dcesrv_conn - > transport . report_output_data =
dcesrv_sock_report_output_data ;
dcesrv_conn - > transport . terminate_connection =
dcesrv_transport_terminate_connection ;
dcesrv_conn - > send_queue = tevent_queue_create ( dcesrv_conn ,
" dcesrv send queue " ) ;
if ( dcesrv_conn - > send_queue = = NULL ) {
2013-09-25 13:35:41 +04:00
status = NT_STATUS_NO_MEMORY ;
2019-12-05 13:45:54 +03:00
DBG_ERR ( " Failed to create send queue: %s \n " ,
nt_errstr ( status ) ) ;
2013-09-25 13:35:41 +04:00
goto out ;
}
2019-12-05 13:45:54 +03:00
dcesrv_conn - > stream = talloc_move ( dcesrv_conn , & ncacn_conn - > tstream ) ;
dcesrv_conn - > local_address = ncacn_conn - > local_server_addr ;
dcesrv_conn - > remote_address = ncacn_conn - > remote_client_addr ;
status = dcesrv_connection_loop_start ( dcesrv_conn ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " Failed to start dcesrv_connection loop: %s \n " ,
nt_errstr ( status ) ) ;
2013-09-25 13:35:41 +04:00
goto out ;
}
2019-03-20 16:15:10 +03:00
* pnpa = talloc_move ( mem_ctx , & npa ) ;
2013-09-25 13:35:41 +04:00
status = NT_STATUS_OK ;
out :
talloc_free ( tmp_ctx ) ;
return status ;
}
2019-11-18 16:01:52 +03:00
static NTSTATUS make_internal_ncacn_conn ( TALLOC_CTX * mem_ctx ,
const struct ndr_interface_table * table ,
2019-02-13 12:48:54 +03:00
const struct tsocket_address * remote_address ,
const struct tsocket_address * local_address ,
const struct auth_session_info * session_info ,
struct messaging_context * msg_ctx ,
2019-11-18 16:01:52 +03:00
struct dcerpc_ncacn_conn * * _out )
2010-06-04 00:04:08 +04:00
{
2019-11-18 16:01:52 +03:00
struct dcerpc_ncacn_conn * ncacn_conn = NULL ;
const char * pipe_name = NULL ;
NTSTATUS status ;
2011-07-21 19:02:59 +04:00
int ret ;
2010-06-04 00:04:08 +04:00
2019-11-18 16:01:52 +03:00
pipe_name = dcerpc_default_transport_endpoint ( mem_ctx ,
NCACN_NP ,
table ) ;
DBG_INFO ( " Create pipe requested %s \n " , pipe_name ) ;
ncacn_conn = talloc_zero ( mem_ctx , struct dcerpc_ncacn_conn ) ;
if ( ncacn_conn = = NULL ) {
return NT_STATUS_NO_MEMORY ;
2013-09-18 12:59:14 +04:00
}
2019-11-18 16:01:52 +03:00
ncacn_conn - > msg_ctx = msg_ctx ;
2010-06-04 00:04:08 +04:00
2019-11-18 16:01:52 +03:00
if ( remote_address ! = NULL ) {
ncacn_conn - > remote_client_addr =
tsocket_address_copy ( remote_address , ncacn_conn ) ;
if ( ncacn_conn - > remote_client_addr = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
}
if ( local_address ! = NULL ) {
ncacn_conn - > local_server_addr =
tsocket_address_copy ( local_address , ncacn_conn ) ;
if ( ncacn_conn - > local_server_addr = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
}
2010-06-04 00:04:08 +04:00
2019-11-18 16:01:52 +03:00
ncacn_conn - > session_info = copy_session_info ( ncacn_conn , session_info ) ;
if ( ncacn_conn - > session_info = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
ret = make_base_pipes_struct ( ncacn_conn ,
msg_ctx ,
pipe_name ,
NCALRPC ,
ncacn_conn - > remote_client_addr ,
ncacn_conn - > local_server_addr ,
& ncacn_conn - > p ) ;
2011-07-21 19:02:59 +04:00
if ( ret ) {
2019-02-13 12:48:54 +03:00
DBG_ERR ( " No memory for pipes_struct! \n " ) ;
2019-11-18 16:01:52 +03:00
status = NT_STATUS_NO_MEMORY ;
goto fail ;
2010-06-04 00:04:08 +04:00
}
2011-07-21 19:02:59 +04:00
DEBUG ( 4 , ( " Created internal pipe %s \n " , pipe_name ) ) ;
2010-06-04 00:04:08 +04:00
2019-11-18 16:01:52 +03:00
* _out = ncacn_conn ;
2019-02-13 12:48:54 +03:00
return NT_STATUS_OK ;
2019-11-18 16:01:52 +03:00
fail :
talloc_free ( ncacn_conn ) ;
return status ;
2010-06-04 00:04:08 +04:00
}
2019-11-18 16:01:52 +03:00
static NTSTATUS find_ncalrpc_default_endpoint ( struct dcesrv_context * dce_ctx ,
2021-08-23 15:27:49 +03:00
const struct ndr_interface_table * ndr_table ,
struct dcesrv_endpoint * * ep )
2019-11-18 16:01:52 +03:00
{
TALLOC_CTX * tmp_ctx = NULL ;
struct dcerpc_binding * binding = NULL ;
const char * ep_description = NULL ;
NTSTATUS status ;
tmp_ctx = talloc_new ( dce_ctx ) ;
if ( tmp_ctx = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2021-08-23 15:27:49 +03:00
if ( rpc_service_mode ( ndr_table - > name ) = = RPC_SERVICE_MODE_EXTERNAL ) {
ep_description = talloc_asprintf ( tmp_ctx , " ncalrpc:[%s] " ,
talloc_strdup_upper ( tmp_ctx , ndr_table - > name ) ) ;
if ( ep_description = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
status = dcerpc_parse_binding ( tmp_ctx , ep_description , & binding ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
}
status = dcesrv_find_endpoint ( dce_ctx , binding , ep ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
goto out ;
}
}
2019-11-18 16:01:52 +03:00
/*
* Some services use a rpcint binding handle in their initialization ,
* before the server is fully initialized . Search the NCALRPC endpoint
* with and without endpoint
*/
status = dcerpc_parse_binding ( tmp_ctx , " ncalrpc: " , & binding ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
}
status = dcesrv_find_endpoint ( dce_ctx , binding , ep ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
goto out ;
}
if ( lp_server_role ( ) = = ROLE_ACTIVE_DIRECTORY_DC ) {
ep_description = " ncalrpc:[SMBD] " ;
} else {
ep_description = " ncalrpc:[DEFAULT] " ;
}
status = dcerpc_parse_binding ( tmp_ctx , ep_description , & binding ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
}
status = dcesrv_find_endpoint ( dce_ctx , binding , ep ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
}
out :
talloc_free ( tmp_ctx ) ;
return status ;
}
static NTSTATUS make_internal_dcesrv_connection ( TALLOC_CTX * mem_ctx ,
2019-05-28 13:05:45 +03:00
const struct ndr_interface_table * ndr_table ,
2019-11-18 16:01:52 +03:00
struct dcerpc_ncacn_conn * ncacn_conn ,
struct dcesrv_connection * * _out )
2010-08-07 16:37:21 +04:00
{
2019-11-18 16:01:52 +03:00
struct dcesrv_connection * conn = NULL ;
struct dcesrv_connection_context * context = NULL ;
struct dcesrv_endpoint * endpoint = NULL ;
2019-05-28 13:05:45 +03:00
NTSTATUS status ;
2010-08-07 16:37:21 +04:00
2019-11-18 16:01:52 +03:00
conn = talloc_zero ( mem_ctx , struct dcesrv_connection ) ;
if ( conn = = NULL ) {
return NT_STATUS_NO_MEMORY ;
2010-08-07 16:37:21 +04:00
}
2019-11-18 16:01:52 +03:00
conn - > dce_ctx = global_dcesrv_context ( ) ;
conn - > preferred_transfer = & ndr_transfer_syntax_ndr ;
conn - > transport . private_data = ncacn_conn ;
2010-08-07 16:37:21 +04:00
2021-08-23 15:27:49 +03:00
status = find_ncalrpc_default_endpoint ( conn - > dce_ctx , ndr_table , & endpoint ) ;
2019-11-18 16:01:52 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
conn - > endpoint = endpoint ;
conn - > default_auth_state = talloc_zero ( conn , struct dcesrv_auth ) ;
if ( conn - > default_auth_state = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
conn - > default_auth_state - > session_info = ncacn_conn - > session_info ;
conn - > default_auth_state - > auth_finished = true ;
context = talloc_zero ( conn , struct dcesrv_connection_context ) ;
if ( context = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
context - > conn = conn ;
context - > context_id = 0 ;
context - > transfer_syntax = * ( conn - > preferred_transfer ) ;
2021-01-27 15:51:33 +03:00
context - > iface = find_interface_by_syntax_id (
conn - > endpoint , & ndr_table - > syntax_id ) ;
2019-11-18 16:01:52 +03:00
if ( context - > iface = = NULL ) {
status = NT_STATUS_RPC_INTERFACE_NOT_FOUND ;
goto fail ;
}
DLIST_ADD ( conn - > contexts , context ) ;
* _out = conn ;
return NT_STATUS_OK ;
fail :
talloc_free ( conn ) ;
return status ;
}
2010-08-07 16:37:21 +04:00
struct rpcint_bh_state {
2019-11-18 16:01:52 +03:00
struct dcesrv_connection * conn ;
2010-08-07 16:37:21 +04:00
} ;
static bool rpcint_bh_is_connected ( struct dcerpc_binding_handle * h )
{
struct rpcint_bh_state * hs = dcerpc_binding_handle_data ( h ,
struct rpcint_bh_state ) ;
2019-11-18 16:01:52 +03:00
if ( hs - > conn = = NULL ) {
2010-08-07 16:37:21 +04:00
return false ;
}
return true ;
}
2010-09-03 22:05:39 +04:00
static uint32_t rpcint_bh_set_timeout ( struct dcerpc_binding_handle * h ,
uint32_t timeout )
{
/* TODO: implement timeouts */
return UINT32_MAX ;
}
2010-08-07 16:37:21 +04:00
struct rpcint_bh_raw_call_state {
2019-11-18 16:01:52 +03:00
struct dcesrv_call_state * call ;
2010-08-07 16:37:21 +04:00
} ;
static struct tevent_req * rpcint_bh_raw_call_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct dcerpc_binding_handle * h ,
const struct GUID * object ,
uint32_t opnum ,
uint32_t in_flags ,
const uint8_t * in_data ,
size_t in_length )
{
struct rpcint_bh_state * hs =
dcerpc_binding_handle_data ( h ,
struct rpcint_bh_state ) ;
struct tevent_req * req ;
struct rpcint_bh_raw_call_state * state ;
2019-11-18 16:01:52 +03:00
struct dcesrv_context * dce_ctx = global_dcesrv_context ( ) ;
2010-08-07 16:37:21 +04:00
bool ok ;
NTSTATUS status ;
req = tevent_req_create ( mem_ctx , & state ,
struct rpcint_bh_raw_call_state ) ;
if ( req = = NULL ) {
return NULL ;
}
ok = rpcint_bh_is_connected ( h ) ;
if ( ! ok ) {
2011-09-14 19:57:37 +04:00
tevent_req_nterror ( req , NT_STATUS_CONNECTION_DISCONNECTED ) ;
2010-08-07 16:37:21 +04:00
return tevent_req_post ( req , ev ) ;
}
2021-03-23 19:06:15 +03:00
state - > call = talloc_zero ( state , struct dcesrv_call_state ) ;
2019-11-18 16:01:52 +03:00
if ( tevent_req_nomem ( state - > call , req ) ) {
return tevent_req_post ( req , ev ) ;
}
state - > call - > event_ctx = ev ;
state - > call - > conn = hs - > conn ;
state - > call - > context = hs - > conn - > contexts ;
state - > call - > auth_state = hs - > conn - > default_auth_state ;
if ( hs - > conn - > assoc_group = = NULL ) {
ZERO_STRUCT ( state - > call - > pkt ) ;
state - > call - > pkt . u . bind . assoc_group_id = 0 ;
2021-02-02 17:07:35 +03:00
status = dce_ctx - > callbacks - > assoc_group . find (
2021-01-29 20:16:08 +03:00
state - > call ,
2021-02-02 17:07:35 +03:00
dce_ctx - > callbacks - > assoc_group . private_data ) ;
2019-11-18 16:01:52 +03:00
if ( tevent_req_nterror ( req , status ) ) {
return tevent_req_post ( req , ev ) ;
}
}
ZERO_STRUCT ( state - > call - > pkt ) ;
state - > call - > pkt . u . request . opnum = opnum ;
state - > call - > pkt . u . request . context_id = 0 ;
state - > call - > pkt . u . request . stub_and_verifier . data = discard_const_p ( uint8_t , in_data ) ;
state - > call - > pkt . u . request . stub_and_verifier . length = in_length ;
2010-08-07 16:37:21 +04:00
/* TODO: allow async */
2020-10-23 12:42:14 +03:00
status = dcesrv_call_dispatch_local ( state - > call ) ;
2010-08-07 16:37:21 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
tevent_req_nterror ( req , status ) ;
return tevent_req_post ( req , ev ) ;
}
tevent_req_done ( req ) ;
return tevent_req_post ( req , ev ) ;
}
static NTSTATUS rpcint_bh_raw_call_recv ( struct tevent_req * req ,
TALLOC_CTX * mem_ctx ,
uint8_t * * out_data ,
size_t * out_length ,
uint32_t * out_flags )
{
struct rpcint_bh_raw_call_state * state =
tevent_req_data ( req ,
struct rpcint_bh_raw_call_state ) ;
2019-11-18 16:01:52 +03:00
struct data_blob_list_item * rep = NULL ;
2010-08-07 16:37:21 +04:00
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
tevent_req_received ( req ) ;
return status ;
}
2019-11-18 16:01:52 +03:00
rep = state - > call - > replies ;
DLIST_REMOVE ( state - > call - > replies , rep ) ;
* out_data = talloc_steal ( mem_ctx , rep - > blob . data ) ;
* out_length = rep - > blob . length ;
2010-08-07 16:37:21 +04:00
* out_flags = 0 ;
2019-11-18 16:01:52 +03:00
talloc_free ( rep ) ;
2010-08-07 16:37:21 +04:00
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
}
struct rpcint_bh_disconnect_state {
uint8_t _dummy ;
} ;
static struct tevent_req * rpcint_bh_disconnect_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct dcerpc_binding_handle * h )
{
struct rpcint_bh_state * hs = dcerpc_binding_handle_data ( h ,
struct rpcint_bh_state ) ;
struct tevent_req * req ;
struct rpcint_bh_disconnect_state * state ;
bool ok ;
req = tevent_req_create ( mem_ctx , & state ,
struct rpcint_bh_disconnect_state ) ;
if ( req = = NULL ) {
return NULL ;
}
ok = rpcint_bh_is_connected ( h ) ;
if ( ! ok ) {
2011-09-14 19:57:37 +04:00
tevent_req_nterror ( req , NT_STATUS_CONNECTION_DISCONNECTED ) ;
2010-08-07 16:37:21 +04:00
return tevent_req_post ( req , ev ) ;
}
/*
* TODO : do a real async disconnect . . .
*
2019-11-18 16:01:52 +03:00
* For now the caller needs to free dcesrv_connection
2010-08-07 16:37:21 +04:00
*/
2019-11-18 16:01:52 +03:00
hs - > conn = NULL ;
2010-08-07 16:37:21 +04:00
tevent_req_done ( req ) ;
return tevent_req_post ( req , ev ) ;
}
static NTSTATUS rpcint_bh_disconnect_recv ( struct tevent_req * req )
{
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
tevent_req_received ( req ) ;
return status ;
}
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
}
static bool rpcint_bh_ref_alloc ( struct dcerpc_binding_handle * h )
{
return true ;
}
static void rpcint_bh_do_ndr_print ( struct dcerpc_binding_handle * h ,
int ndr_flags ,
const void * _struct_ptr ,
const struct ndr_interface_call * call )
{
void * struct_ptr = discard_const ( _struct_ptr ) ;
2010-10-01 21:48:11 +04:00
if ( DEBUGLEVEL < 11 ) {
2010-08-07 16:37:21 +04:00
return ;
}
if ( ndr_flags & NDR_IN ) {
ndr_print_function_debug ( call - > ndr_print ,
call - > name ,
ndr_flags ,
struct_ptr ) ;
}
if ( ndr_flags & NDR_OUT ) {
ndr_print_function_debug ( call - > ndr_print ,
call - > name ,
ndr_flags ,
struct_ptr ) ;
}
}
static const struct dcerpc_binding_handle_ops rpcint_bh_ops = {
. name = " rpcint " ,
. is_connected = rpcint_bh_is_connected ,
2010-09-03 22:05:39 +04:00
. set_timeout = rpcint_bh_set_timeout ,
2010-08-07 16:37:21 +04:00
. raw_call_send = rpcint_bh_raw_call_send ,
. raw_call_recv = rpcint_bh_raw_call_recv ,
. disconnect_send = rpcint_bh_disconnect_send ,
. disconnect_recv = rpcint_bh_disconnect_recv ,
. ref_alloc = rpcint_bh_ref_alloc ,
. do_ndr_print = rpcint_bh_do_ndr_print ,
} ;
2010-09-03 21:28:00 +04:00
static NTSTATUS rpcint_binding_handle_ex ( TALLOC_CTX * mem_ctx ,
const struct ndr_syntax_id * abstract_syntax ,
const struct ndr_interface_table * ndr_table ,
2011-06-07 19:21:28 +04:00
const struct tsocket_address * remote_address ,
2017-02-24 03:29:12 +03:00
const struct tsocket_address * local_address ,
2011-07-18 07:06:47 +04:00
const struct auth_session_info * session_info ,
2010-09-03 21:28:00 +04:00
struct messaging_context * msg_ctx ,
struct dcerpc_binding_handle * * binding_handle )
2010-08-07 16:37:21 +04:00
{
struct dcerpc_binding_handle * h ;
struct rpcint_bh_state * hs ;
2019-11-18 16:01:52 +03:00
struct dcerpc_ncacn_conn * ncacn_conn = NULL ;
2019-02-13 12:48:54 +03:00
NTSTATUS status ;
2010-08-07 16:37:21 +04:00
2010-09-03 21:28:00 +04:00
h = dcerpc_binding_handle_create ( mem_ctx ,
2010-08-07 16:37:21 +04:00
& rpcint_bh_ops ,
NULL ,
2010-09-03 21:28:00 +04:00
ndr_table ,
2010-08-07 16:37:21 +04:00
& hs ,
struct rpcint_bh_state ,
__location__ ) ;
if ( h = = NULL ) {
2010-09-03 21:28:00 +04:00
return NT_STATUS_NO_MEMORY ;
}
2019-02-13 12:48:54 +03:00
2019-11-18 16:01:52 +03:00
status = make_internal_ncacn_conn ( hs ,
ndr_table ,
2019-02-13 12:48:54 +03:00
remote_address ,
local_address ,
session_info ,
msg_ctx ,
2019-11-18 16:01:52 +03:00
& ncacn_conn ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( h ) ;
return status ;
}
status = make_internal_dcesrv_connection ( ncacn_conn ,
ndr_table ,
ncacn_conn ,
& hs - > conn ) ;
2019-02-13 12:48:54 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-09-03 21:28:00 +04:00
TALLOC_FREE ( h ) ;
2019-02-13 12:48:54 +03:00
return status ;
2010-08-07 16:37:21 +04:00
}
2010-09-03 21:28:00 +04:00
* binding_handle = h ;
return NT_STATUS_OK ;
}
/**
* @ brief Create a new DCERPC Binding Handle which uses a local dispatch function .
*
* @ param [ in ] mem_ctx The memory context to use .
*
* @ param [ in ] ndr_table Normally the ndr_table_ < name > .
*
2011-06-07 19:21:28 +04:00
* @ param [ in ] remote_address The info about the connected client .
2010-09-03 21:28:00 +04:00
*
* @ param [ in ] serversupplied_info The server supplied authentication function .
*
* @ param [ in ] msg_ctx The messaging context that can be used by the server
*
* @ param [ out ] binding_handle A pointer to store the connected
* dcerpc_binding_handle
*
* @ return NT_STATUS_OK on success , a corresponding NT status if an
2017-02-17 22:46:28 +03:00
* error occurred .
2010-09-03 21:28:00 +04:00
*
* @ code
* struct dcerpc_binding_handle * winreg_binding ;
* NTSTATUS status ;
*
* status = rpcint_binding_handle ( tmp_ctx ,
* & ndr_table_winreg ,
2011-06-07 19:21:28 +04:00
* p - > remote_address ,
2011-02-21 12:25:52 +03:00
* p - > session_info ,
2010-09-03 21:28:00 +04:00
* p - > msg_ctx
* & winreg_binding ) ;
* @ endcode
*/
NTSTATUS rpcint_binding_handle ( TALLOC_CTX * mem_ctx ,
const struct ndr_interface_table * ndr_table ,
2011-06-07 19:21:28 +04:00
const struct tsocket_address * remote_address ,
2017-02-24 03:29:12 +03:00
const struct tsocket_address * local_address ,
2011-07-18 07:06:47 +04:00
const struct auth_session_info * session_info ,
2010-09-03 21:28:00 +04:00
struct messaging_context * msg_ctx ,
struct dcerpc_binding_handle * * binding_handle )
{
2011-06-07 19:21:28 +04:00
return rpcint_binding_handle_ex ( mem_ctx , NULL , ndr_table , remote_address ,
2017-02-24 03:29:12 +03:00
local_address , session_info ,
msg_ctx , binding_handle ) ;
2010-08-07 16:37:21 +04:00
}
2010-06-04 00:04:08 +04:00
/**
2011-03-29 14:51:45 +04:00
* @ internal
*
* @ brief Create a new RPC client context which uses a local transport .
*
* This creates a local transport . It is a shortcut to directly call the server
2011-05-12 00:38:46 +04:00
* functions and avoid marshalling .
* NOTE : this function should be used only by rpc_pipe_open_interface ( )
2010-06-04 00:04:08 +04:00
*
* @ param [ in ] mem_ctx The memory context to use .
*
2016-09-24 03:08:47 +03:00
* @ param [ in ] ndr_table the ndr_table_ < name > structure .
2010-06-04 00:04:08 +04:00
*
* @ param [ in ] serversupplied_info The server supplied authentication function .
*
2011-06-07 19:21:28 +04:00
* @ param [ in ] remote_address The client address information .
2011-03-29 14:51:45 +04:00
*
* @ param [ in ] msg_ctx The messaging context to use .
*
2010-06-04 00:04:08 +04:00
* @ param [ out ] presult A pointer to store the connected rpc client pipe .
*
* @ return NT_STATUS_OK on success , a corresponding NT status if an
2017-02-17 22:46:28 +03:00
* error occurred .
2010-06-04 00:04:08 +04:00
*/
2011-08-12 13:19:09 +04:00
NTSTATUS rpc_pipe_open_internal ( TALLOC_CTX * mem_ctx ,
2016-09-24 03:08:47 +03:00
const struct ndr_interface_table * ndr_table ,
2011-07-18 07:06:47 +04:00
const struct auth_session_info * session_info ,
2011-06-07 19:21:28 +04:00
const struct tsocket_address * remote_address ,
2017-02-24 03:29:12 +03:00
const struct tsocket_address * local_address ,
2010-08-08 11:22:05 +04:00
struct messaging_context * msg_ctx ,
2010-06-04 00:04:08 +04:00
struct rpc_pipe_client * * presult )
{
struct rpc_pipe_client * result ;
2010-09-03 21:28:00 +04:00
NTSTATUS status ;
2010-06-04 00:04:08 +04:00
2011-06-07 05:44:43 +04:00
result = talloc_zero ( mem_ctx , struct rpc_pipe_client ) ;
2010-06-04 00:04:08 +04:00
if ( result = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2016-09-24 03:08:47 +03:00
result - > abstract_syntax = ndr_table - > syntax_id ;
2012-03-18 19:46:57 +04:00
result - > transfer_syntax = ndr_transfer_syntax_ndr ;
2010-06-04 00:04:08 +04:00
2011-06-07 19:21:28 +04:00
if ( remote_address = = NULL ) {
struct tsocket_address * local ;
int rc ;
rc = tsocket_address_inet_from_strings ( mem_ctx ,
" ip " ,
2018-03-17 21:50:49 +03:00
" 127.0.0.1 " ,
2011-06-07 19:21:28 +04:00
0 ,
& local ) ;
if ( rc < 0 ) {
TALLOC_FREE ( result ) ;
return NT_STATUS_NO_MEMORY ;
}
remote_address = local ;
2010-08-16 13:01:26 +04:00
}
2010-06-04 00:04:08 +04:00
result - > max_xmit_frag = - 1 ;
2016-09-24 03:08:47 +03:00
status = rpcint_binding_handle ( result ,
ndr_table ,
remote_address ,
2017-02-24 03:29:12 +03:00
local_address ,
2016-09-24 03:08:47 +03:00
session_info ,
msg_ctx ,
& result - > binding_handle ) ;
2010-09-03 21:28:00 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-08-07 16:37:21 +04:00
TALLOC_FREE ( result ) ;
2010-09-03 21:28:00 +04:00
return status ;
2010-08-07 16:37:21 +04:00
}
2010-06-04 00:04:08 +04:00
* presult = result ;
return NT_STATUS_OK ;
}
2010-07-07 23:24:00 +04:00
/****************************************************************************
* External pipes functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-09-24 13:28:29 +04:00
NTSTATUS make_external_rpc_pipe ( TALLOC_CTX * mem_ctx ,
const char * pipe_name ,
2017-03-17 00:29:02 +03:00
const struct tsocket_address * remote_client_address ,
const struct tsocket_address * local_server_address ,
2013-09-24 13:28:29 +04:00
const struct auth_session_info * session_info ,
struct npa_state * * pnpa )
{
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
struct auth_session_info_transport * session_info_t ;
struct tevent_context * ev_ctx ;
struct tevent_req * subreq ;
const char * socket_np_dir ;
const char * socket_dir ;
struct npa_state * npa ;
int sys_errno ;
NTSTATUS status ;
int rc = - 1 ;
bool ok ;
npa = npa_state_init ( tmp_ctx ) ;
if ( npa = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
socket_dir = lp_parm_const_string ( GLOBAL_SECTION_SNUM ,
" external_rpc_pipe " ,
" socket_dir " ,
lp_ncalrpc_dir ( ) ) ;
if ( socket_dir = = NULL ) {
DEBUG ( 0 , ( " external_rpc_pipe: socket_dir not set \n " ) ) ;
status = NT_STATUS_PIPE_NOT_AVAILABLE ;
goto out ;
}
socket_np_dir = talloc_asprintf ( tmp_ctx , " %s/np " , socket_dir ) ;
if ( socket_np_dir = = NULL ) {
DEBUG ( 0 , ( " talloc_asprintf failed \n " ) ) ;
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
session_info_t = talloc_zero ( tmp_ctx ,
struct auth_session_info_transport ) ;
if ( session_info_t = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
session_info_t - > session_info = copy_session_info ( session_info_t ,
session_info ) ;
if ( session_info_t - > session_info = = NULL ) {
DEBUG ( 0 , ( " copy_session_info failed \n " ) ) ;
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
2016-09-24 05:11:17 +03:00
ev_ctx = samba_tevent_context_init ( tmp_ctx ) ;
2013-09-24 13:28:29 +04:00
if ( ev_ctx = = NULL ) {
2016-09-24 05:11:17 +03:00
DEBUG ( 0 , ( " samba_tevent_context_init failed \n " ) ) ;
2013-09-24 13:28:29 +04:00
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
become_root ( ) ;
subreq = tstream_npa_connect_send ( tmp_ctx ,
ev_ctx ,
socket_np_dir ,
pipe_name ,
2017-03-17 00:29:02 +03:00
remote_client_address ,
2013-09-24 13:28:29 +04:00
NULL , /* client_name */
2017-03-17 00:29:02 +03:00
local_server_address ,
2013-09-24 13:28:29 +04:00
NULL , /* server_name */
session_info_t ) ;
if ( subreq = = NULL ) {
unbecome_root ( ) ;
DEBUG ( 0 , ( " tstream_npa_connect_send to %s for pipe %s and "
" user %s \\ %s failed \n " ,
socket_np_dir , pipe_name , session_info_t - > session_info - > info - > domain_name ,
session_info_t - > session_info - > info - > account_name ) ) ;
status = NT_STATUS_OBJECT_NAME_NOT_FOUND ;
goto out ;
}
ok = tevent_req_poll ( subreq , ev_ctx ) ;
unbecome_root ( ) ;
if ( ! ok ) {
DEBUG ( 0 , ( " tevent_req_poll to %s for pipe %s and user %s \\ %s "
" failed for tstream_npa_connect: %s \n " ,
socket_np_dir ,
pipe_name ,
session_info_t - > session_info - > info - > domain_name ,
session_info_t - > session_info - > info - > account_name ,
strerror ( errno ) ) ) ;
status = NT_STATUS_OBJECT_NAME_NOT_FOUND ;
goto out ;
}
rc = tstream_npa_connect_recv ( subreq ,
& sys_errno ,
npa ,
& npa - > stream ,
& npa - > file_type ,
& npa - > device_state ,
& npa - > allocation_size ) ;
talloc_free ( subreq ) ;
if ( rc ! = 0 ) {
int l = 1 ;
if ( errno = = ENOENT ) {
l = 2 ;
}
DEBUG ( l , ( " tstream_npa_connect_recv to %s for pipe %s and "
" user %s \\ %s failed: %s \n " ,
socket_np_dir ,
pipe_name ,
session_info_t - > session_info - > info - > domain_name ,
session_info_t - > session_info - > info - > account_name ,
strerror ( sys_errno ) ) ) ;
status = NT_STATUS_OBJECT_NAME_NOT_FOUND ;
goto out ;
}
* pnpa = talloc_steal ( mem_ctx , npa ) ;
status = NT_STATUS_OK ;
out :
talloc_free ( tmp_ctx ) ;
return status ;
}
2010-07-07 23:24:00 +04:00
2019-02-18 23:04:00 +03:00
static struct np_proxy_state * make_external_rpc_pipe_p ( TALLOC_CTX * mem_ctx ,
2010-07-07 23:24:00 +04:00
const char * pipe_name ,
2019-02-18 23:04:00 +03:00
const struct tsocket_address * remote_address ,
const struct tsocket_address * local_address ,
2011-07-18 07:06:47 +04:00
const struct auth_session_info * session_info )
2010-07-07 23:24:00 +04:00
{
struct np_proxy_state * result ;
char * socket_np_dir ;
const char * socket_dir ;
struct tevent_context * ev ;
struct tevent_req * subreq ;
2011-02-21 12:25:52 +03:00
struct auth_session_info_transport * session_info_t ;
2010-07-07 23:24:00 +04:00
bool ok ;
int ret ;
int sys_errno ;
result = talloc ( mem_ctx , struct np_proxy_state ) ;
if ( result = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
return NULL ;
}
2011-02-07 12:29:55 +03:00
result - > read_queue = tevent_queue_create ( result , " np_read " ) ;
if ( result - > read_queue = = NULL ) {
DEBUG ( 0 , ( " tevent_queue_create failed \n " ) ) ;
goto fail ;
}
result - > write_queue = tevent_queue_create ( result , " np_write " ) ;
if ( result - > write_queue = = NULL ) {
DEBUG ( 0 , ( " tevent_queue_create failed \n " ) ) ;
goto fail ;
}
2016-09-24 05:11:17 +03:00
ev = samba_tevent_context_init ( talloc_tos ( ) ) ;
2010-07-07 23:24:00 +04:00
if ( ev = = NULL ) {
2016-09-24 05:11:17 +03:00
DEBUG ( 0 , ( " samba_tevent_context_init failed \n " ) ) ;
2010-07-07 23:24:00 +04:00
goto fail ;
}
socket_dir = lp_parm_const_string (
GLOBAL_SECTION_SNUM , " external_rpc_pipe " , " socket_dir " ,
lp_ncalrpc_dir ( ) ) ;
if ( socket_dir = = NULL ) {
2013-08-12 19:56:53 +04:00
DEBUG ( 0 , ( " external_rpc_pipe:socket_dir not set \n " ) ) ;
2010-07-07 23:24:00 +04:00
goto fail ;
}
socket_np_dir = talloc_asprintf ( talloc_tos ( ) , " %s/np " , socket_dir ) ;
if ( socket_np_dir = = NULL ) {
DEBUG ( 0 , ( " talloc_asprintf failed \n " ) ) ;
goto fail ;
}
2011-04-05 10:15:27 +04:00
session_info_t = talloc_zero ( talloc_tos ( ) , struct auth_session_info_transport ) ;
2011-07-18 07:10:30 +04:00
if ( session_info_t = = NULL ) {
2011-04-05 10:15:27 +04:00
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
goto fail ;
}
2011-07-21 19:58:41 +04:00
session_info_t - > session_info = copy_session_info ( session_info_t ,
session_info ) ;
if ( session_info_t - > session_info = = NULL ) {
DEBUG ( 0 , ( " copy_session_info failed \n " ) ) ;
goto fail ;
}
2011-04-05 10:15:27 +04:00
2010-07-07 23:24:00 +04:00
become_root ( ) ;
subreq = tstream_npa_connect_send ( talloc_tos ( ) , ev ,
socket_np_dir ,
pipe_name ,
2019-02-18 23:04:00 +03:00
remote_address ,
2010-07-07 23:24:00 +04:00
NULL , /* client_name */
2019-02-18 23:04:00 +03:00
local_address ,
2010-07-07 23:24:00 +04:00
NULL , /* server_name */
2011-02-21 12:25:52 +03:00
session_info_t ) ;
2010-07-07 23:24:00 +04:00
if ( subreq = = NULL ) {
unbecome_root ( ) ;
DEBUG ( 0 , ( " tstream_npa_connect_send to %s for pipe %s and "
" user %s \\ %s failed \n " ,
2011-04-05 10:15:27 +04:00
socket_np_dir , pipe_name , session_info_t - > session_info - > info - > domain_name ,
session_info_t - > session_info - > info - > account_name ) ) ;
2010-07-07 23:24:00 +04:00
goto fail ;
}
ok = tevent_req_poll ( subreq , ev ) ;
unbecome_root ( ) ;
if ( ! ok ) {
DEBUG ( 0 , ( " tevent_req_poll to %s for pipe %s and user %s \\ %s "
" failed for tstream_npa_connect: %s \n " ,
2011-04-05 10:15:27 +04:00
socket_np_dir , pipe_name , session_info_t - > session_info - > info - > domain_name ,
session_info_t - > session_info - > info - > account_name ,
2010-07-07 23:24:00 +04:00
strerror ( errno ) ) ) ;
goto fail ;
}
ret = tstream_npa_connect_recv ( subreq , & sys_errno ,
result ,
& result - > npipe ,
& result - > file_type ,
& result - > device_state ,
& result - > allocation_size ) ;
TALLOC_FREE ( subreq ) ;
if ( ret ! = 0 ) {
2012-10-20 13:08:19 +04:00
int l = 1 ;
2021-02-09 20:36:56 +03:00
if ( sys_errno = = ENOENT ) {
2012-10-20 13:08:19 +04:00
l = 2 ;
}
DEBUG ( l , ( " tstream_npa_connect_recv to %s for pipe %s and "
2010-07-07 23:24:00 +04:00
" user %s \\ %s failed: %s \n " ,
2011-04-05 10:15:27 +04:00
socket_np_dir , pipe_name , session_info_t - > session_info - > info - > domain_name ,
session_info_t - > session_info - > info - > account_name ,
2010-07-07 23:24:00 +04:00
strerror ( sys_errno ) ) ) ;
goto fail ;
}
return result ;
fail :
TALLOC_FREE ( result ) ;
return NULL ;
}
static NTSTATUS rpc_pipe_open_external ( TALLOC_CTX * mem_ctx ,
2017-03-17 00:26:03 +03:00
const char * pipe_name ,
const struct ndr_interface_table * table ,
const struct auth_session_info * session_info ,
const struct tsocket_address * remote_client_address ,
const struct tsocket_address * local_server_address ,
struct rpc_pipe_client * * _result )
2010-07-07 23:24:00 +04:00
{
struct rpc_pipe_client * result = NULL ;
struct np_proxy_state * proxy_state = NULL ;
struct pipe_auth_data * auth ;
2017-03-17 00:26:03 +03:00
struct tsocket_address * remote_client_addr ;
struct tsocket_address * local_server_addr ;
2010-07-07 23:24:00 +04:00
NTSTATUS status ;
int ret ;
2017-03-17 00:26:03 +03:00
if ( local_server_address = = NULL ) {
/* this is an internal connection, fake up ip addresses */
ret = tsocket_address_inet_from_strings ( talloc_tos ( ) , " ip " ,
NULL , 0 , & local_server_addr ) ;
if ( ret ) {
return NT_STATUS_NO_MEMORY ;
}
local_server_address = local_server_addr ;
2010-07-07 23:24:00 +04:00
}
2017-03-17 00:26:03 +03:00
if ( remote_client_address = = NULL ) {
/* this is an internal connection, fake up ip addresses */
ret = tsocket_address_inet_from_strings ( talloc_tos ( ) , " ip " ,
NULL , 0 , & remote_client_addr ) ;
if ( ret ) {
return NT_STATUS_NO_MEMORY ;
}
remote_client_address = remote_client_addr ;
2010-07-07 23:24:00 +04:00
}
proxy_state = make_external_rpc_pipe_p ( mem_ctx , pipe_name ,
2017-03-17 00:26:03 +03:00
remote_client_address ,
2017-03-17 00:29:02 +03:00
local_server_address ,
2017-03-17 00:26:03 +03:00
session_info ) ;
2010-07-07 23:24:00 +04:00
if ( ! proxy_state ) {
2014-04-29 01:08:25 +04:00
DEBUG ( 1 , ( " Unable to make proxy_state for connection to %s. \n " , pipe_name ) ) ;
2010-07-07 23:24:00 +04:00
return NT_STATUS_UNSUCCESSFUL ;
}
result = talloc_zero ( mem_ctx , struct rpc_pipe_client ) ;
if ( result = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
2013-08-27 15:23:04 +04:00
result - > abstract_syntax = table - > syntax_id ;
2012-03-18 19:46:57 +04:00
result - > transfer_syntax = ndr_transfer_syntax_ndr ;
2010-07-07 23:24:00 +04:00
result - > desthost = get_myname ( result ) ;
result - > srv_name_slash = talloc_asprintf_strupper_m (
result , " \\ \\ %s " , result - > desthost ) ;
if ( ( result - > desthost = = NULL ) | | ( result - > srv_name_slash = = NULL ) ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
result - > max_xmit_frag = RPC_MAX_PDU_FRAG_LEN ;
status = rpc_transport_tstream_init ( result ,
2010-06-23 02:01:45 +04:00
& proxy_state - > npipe ,
2010-07-07 23:24:00 +04:00
& result - > transport ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2013-08-27 15:23:04 +04:00
result - > binding_handle = rpccli_bh_create ( result , NULL , table ) ;
2011-02-09 08:56:25 +03:00
if ( result - > binding_handle = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
DEBUG ( 0 , ( " Failed to create binding handle. \n " ) ) ;
goto done ;
}
2010-07-07 23:24:00 +04:00
result - > auth = talloc_zero ( result , struct pipe_auth_data ) ;
if ( ! result - > auth ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
result - > auth - > auth_type = DCERPC_AUTH_TYPE_NONE ;
result - > auth - > auth_level = DCERPC_AUTH_LEVEL_NONE ;
2015-07-08 01:01:37 +03:00
result - > auth - > auth_context_id = 0 ;
2010-07-07 23:24:00 +04:00
status = rpccli_anon_bind_data ( result , & auth ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to initialize anonymous bind. \n " ) ) ;
goto done ;
}
status = rpc_pipe_bind ( result , auth ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-02-09 08:56:25 +03:00
DEBUG ( 0 , ( " Failed to bind external pipe. \n " ) ) ;
2010-07-07 23:24:00 +04:00
goto done ;
}
2011-02-09 08:56:25 +03:00
2010-07-07 23:24:00 +04:00
done :
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( result ) ;
}
TALLOC_FREE ( proxy_state ) ;
* _result = result ;
return status ;
}
/**
2011-05-12 00:38:46 +04:00
* @ brief Create a new RPC client context which uses a local dispatch function
* or a remote transport , depending on rpc_server configuration for the
* specific service .
*
* @ param [ in ] mem_ctx The memory context to use .
*
* @ param [ in ] abstract_syntax Normally the syntax_id of the autogenerated
* ndr_table_ < name > .
*
* @ param [ in ] serversupplied_info The server supplied authentication function .
2010-07-07 23:24:00 +04:00
*
2011-06-07 19:21:28 +04:00
* @ param [ in ] remote_address The client address information .
2011-05-12 00:38:46 +04:00
*
* @ param [ in ] msg_ctx The messaging context to use .
2010-07-07 23:24:00 +04:00
*
2011-05-12 00:38:46 +04:00
* @ param [ out ] presult A pointer to store the connected rpc client pipe .
*
* @ return NT_STATUS_OK on success , a corresponding NT status if an
2017-02-17 22:46:28 +03:00
* error occurred .
2011-05-12 00:38:46 +04:00
*
* @ code
* struct rpc_pipe_client * winreg_pipe ;
* NTSTATUS status ;
*
* status = rpc_pipe_open_interface ( tmp_ctx ,
* & ndr_table_winreg . syntax_id ,
* p - > session_info ,
2011-06-07 19:21:28 +04:00
* remote_address ,
2011-05-12 00:38:46 +04:00
* & winreg_pipe ) ;
* @ endcode
2010-07-07 23:24:00 +04:00
*/
NTSTATUS rpc_pipe_open_interface ( TALLOC_CTX * mem_ctx ,
2013-05-17 18:44:05 +04:00
const struct ndr_interface_table * table ,
2011-07-18 07:06:47 +04:00
const struct auth_session_info * session_info ,
2011-06-07 19:21:28 +04:00
const struct tsocket_address * remote_address ,
2017-02-24 03:29:12 +03:00
const struct tsocket_address * local_address ,
2010-07-07 23:24:00 +04:00
struct messaging_context * msg_ctx ,
struct rpc_pipe_client * * cli_pipe )
{
2010-09-15 13:38:53 +04:00
struct rpc_pipe_client * cli = NULL ;
2011-08-10 23:34:37 +04:00
enum rpc_service_mode_e pipe_mode ;
2010-07-07 23:24:00 +04:00
const char * pipe_name ;
NTSTATUS status ;
2010-09-15 13:38:53 +04:00
TALLOC_CTX * tmp_ctx ;
2010-07-07 23:24:00 +04:00
2012-12-17 20:46:34 +04:00
if ( cli_pipe ! = NULL ) {
if ( rpccli_is_connected ( * cli_pipe ) ) {
return NT_STATUS_OK ;
} else {
TALLOC_FREE ( * cli_pipe ) ;
}
2010-07-07 23:24:00 +04:00
}
2010-09-15 13:38:53 +04:00
tmp_ctx = talloc_stackframe ( ) ;
if ( tmp_ctx = = NULL ) {
2010-07-07 23:24:00 +04:00
return NT_STATUS_NO_MEMORY ;
}
2013-09-18 12:59:14 +04:00
pipe_name = dcerpc_default_transport_endpoint ( mem_ctx , NCACN_NP , table ) ;
2010-09-15 13:38:53 +04:00
if ( pipe_name = = NULL ) {
2014-04-29 01:08:25 +04:00
DEBUG ( 1 , ( " Unable to find pipe name to forward %s to. \n " , table - > name ) ) ;
2010-09-15 13:38:53 +04:00
status = NT_STATUS_INVALID_PARAMETER ;
goto done ;
2010-07-07 23:24:00 +04:00
}
2010-09-16 12:49:39 +04:00
while ( pipe_name [ 0 ] = = ' \\ ' ) {
pipe_name + + ;
}
DEBUG ( 5 , ( " Connecting to %s pipe. \n " , pipe_name ) ) ;
2010-07-07 23:24:00 +04:00
2011-08-10 23:34:37 +04:00
pipe_mode = rpc_service_mode ( pipe_name ) ;
2010-09-16 12:49:39 +04:00
2011-08-10 23:34:37 +04:00
switch ( pipe_mode ) {
case RPC_SERVICE_MODE_EMBEDDED :
2010-09-15 13:38:53 +04:00
status = rpc_pipe_open_internal ( tmp_ctx ,
2016-09-24 03:08:47 +03:00
table , session_info ,
2017-02-24 03:29:12 +03:00
remote_address , local_address ,
msg_ctx ,
2010-09-15 13:38:53 +04:00
& cli ) ;
2010-07-07 23:24:00 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2011-08-10 23:34:37 +04:00
break ;
case RPC_SERVICE_MODE_EXTERNAL :
2010-07-07 23:24:00 +04:00
/* It would be nice to just use rpc_pipe_open_ncalrpc() but
* for now we need to use the special proxy setup to connect
* to spoolssd . */
2010-09-15 13:38:53 +04:00
status = rpc_pipe_open_external ( tmp_ctx ,
2013-08-27 15:23:04 +04:00
pipe_name , table ,
2011-02-21 12:25:52 +03:00
session_info ,
2017-03-17 00:26:03 +03:00
remote_address , local_address ,
2010-09-15 13:38:53 +04:00
& cli ) ;
2010-07-07 23:24:00 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2011-08-10 23:34:37 +04:00
break ;
case RPC_SERVICE_MODE_DISABLED :
2011-03-29 12:58:05 +04:00
status = NT_STATUS_NOT_IMPLEMENTED ;
2011-08-10 23:34:37 +04:00
DEBUG ( 0 , ( " Service pipe %s is disabled in config file: %s " ,
pipe_name , nt_errstr ( status ) ) ) ;
2011-03-29 12:58:05 +04:00
goto done ;
}
2010-07-07 23:24:00 +04:00
status = NT_STATUS_OK ;
done :
2012-12-17 20:46:34 +04:00
if ( NT_STATUS_IS_OK ( status ) & & cli_pipe ! = NULL ) {
2010-09-15 13:38:53 +04:00
* cli_pipe = talloc_move ( mem_ctx , & cli ) ;
2010-07-07 23:24:00 +04:00
}
2010-09-15 13:38:53 +04:00
TALLOC_FREE ( tmp_ctx ) ;
2010-07-07 23:24:00 +04:00
return status ;
}