2003-12-11 01:21:04 +03:00
/*
Unix SMB / CIFS implementation .
server side dcerpc core code
2005-01-11 19:53:02 +03:00
Copyright ( C ) Andrew Tridgell 2003 - 2005
Copyright ( C ) Stefan ( metze ) Metzmacher 2004 - 2005
2003-12-11 01:21:04 +03: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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-12-11 01:21:04 +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/>.
2003-12-11 01:21:04 +03:00
*/
# include "includes.h"
2004-11-02 05:57:18 +03:00
# include "auth/auth.h"
2006-11-07 03:48:36 +03:00
# include "auth/gensec/gensec.h"
2019-01-24 22:34:03 +03:00
# include "auth/credentials/credentials.h"
2004-11-02 10:42:47 +03:00
# include "rpc_server/dcerpc_server.h"
2008-04-02 06:53:27 +04:00
# include "rpc_server/dcerpc_server_proto.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2020-11-20 17:27:17 +03:00
# include "samba/service_stream.h"
2019-10-01 00:35:55 +03:00
# include "lib/tsocket/tsocket.h"
2010-10-11 02:49:13 +04:00
# include "lib/socket/socket.h"
2020-11-20 17:27:17 +03:00
# include "samba/process_model.h"
2011-12-03 10:03:35 +04:00
# include "lib/util/samba_modules.h"
2019-10-01 00:35:55 +03:00
# include "lib/util/tevent_ntstatus.h"
2023-01-05 12:04:23 +03:00
# include "lib/util/idtree_random.h"
2003-12-11 01:21:04 +03:00
2009-09-22 08:36:54 +04:00
/*
take a reference to an existing association group
*/
2018-12-12 15:49:35 +03:00
static struct dcesrv_assoc_group * dcesrv_assoc_group_reference ( struct dcesrv_connection * conn ,
2009-09-22 08:36:54 +04:00
uint32_t id )
{
2018-12-12 15:49:35 +03:00
const struct dcesrv_endpoint * endpoint = conn - > endpoint ;
enum dcerpc_transport_t transport =
dcerpc_binding_get_transport ( endpoint - > ep_description ) ;
2009-09-22 08:36:54 +04:00
struct dcesrv_assoc_group * assoc_group ;
2019-10-03 18:26:54 +03:00
void * id_ptr = NULL ;
2009-09-22 08:36:54 +04:00
2019-10-03 18:26:54 +03:00
/* find an association group given a assoc_group_id */
id_ptr = idr_find ( conn - > dce_ctx - > assoc_groups_idr , id ) ;
if ( id_ptr = = NULL ) {
2018-12-12 15:49:35 +03:00
DBG_NOTICE ( " Failed to find assoc_group 0x%08x \n " , id ) ;
return NULL ;
}
2019-10-03 18:26:54 +03:00
assoc_group = talloc_get_type_abort ( id_ptr , struct dcesrv_assoc_group ) ;
2018-12-12 15:49:35 +03:00
if ( assoc_group - > transport ! = transport ) {
const char * at =
derpc_transport_string_by_transport (
assoc_group - > transport ) ;
const char * ct =
derpc_transport_string_by_transport (
transport ) ;
DBG_NOTICE ( " assoc_group 0x%08x (transport %s) "
2023-08-07 07:54:15 +03:00
" is not available on transport %s \n " ,
2018-12-12 15:49:35 +03:00
id , at , ct ) ;
2009-09-22 08:36:54 +04:00
return NULL ;
}
2018-12-12 15:49:35 +03:00
2019-10-03 20:38:31 +03:00
return talloc_reference ( conn , assoc_group ) ;
2003-12-11 01:21:04 +03:00
}
2019-10-03 20:38:31 +03:00
static int dcesrv_assoc_group_destructor ( struct dcesrv_assoc_group * assoc_group )
{
int ret ;
ret = idr_remove ( assoc_group - > dce_ctx - > assoc_groups_idr , assoc_group - > id ) ;
if ( ret ! = 0 ) {
DEBUG ( 0 , ( __location__ " : Failed to remove assoc_group 0x%08x \n " ,
assoc_group - > id ) ) ;
}
2023-10-12 13:49:42 +03:00
SMB_ASSERT ( assoc_group - > dce_ctx - > assoc_groups_num > 0 ) ;
assoc_group - > dce_ctx - > assoc_groups_num - = 1 ;
2019-10-03 20:38:31 +03:00
return 0 ;
}
2003-12-11 01:21:04 +03:00
2003-12-13 05:20:40 +03:00
/*
2019-10-03 20:38:31 +03:00
allocate a new association group
*/
static struct dcesrv_assoc_group * dcesrv_assoc_group_new ( struct dcesrv_connection * conn )
2003-12-13 05:20:40 +03:00
{
2019-10-03 20:38:31 +03:00
struct dcesrv_context * dce_ctx = conn - > dce_ctx ;
const struct dcesrv_endpoint * endpoint = conn - > endpoint ;
enum dcerpc_transport_t transport =
dcerpc_binding_get_transport ( endpoint - > ep_description ) ;
struct dcesrv_assoc_group * assoc_group ;
int id ;
2003-12-13 05:20:40 +03:00
2019-10-03 20:38:31 +03:00
assoc_group = talloc_zero ( conn , struct dcesrv_assoc_group ) ;
if ( assoc_group = = NULL ) {
return NULL ;
This patch adds a better dcerpc server infastructure.
1.) We now register endpoint servers add startup via register_backend()
and later use the smb.conf 'dcerpc endpoint servers' parameter to setup the dcesrv_context
2.) each endpoint server can register at context creation time as much interfaces as it wants
(multiple interfaces on one endpoint are supported!)
(NOTE: there's a difference between 'endpoint server' and 'endpoint'!
for details look at rpc_server/dcesrv_server.h)
3.) one endpoint can have a security descriptor registered to it self
this will be checked in the future when a client wants to connect
to an smb pipe endpoint.
4.) we now have a 'remote' endpoint server, which works like the ntvfs_cifs module
it takes this options in the [globals] section:
dcerpc remote:interfaces = srvsvc, winreg, w32time, epmapper
dcerpc remote:binding = ...
dcerpc remote:user = ...
dcerpc remote:password = ...
5.) we currently have tree endpoint servers: epmapper, rpcecho and remote
the default for the 'dcerpc endpiont servers = epmapper, rpcecho'
for testing you can also do
dcerpc endpoint servers = rpcecho, remote, epmapper
dcerpc remote:interfaces = srvsvc, samr, netlogon
6,) please notice the the epmapper now only returns NO_ENTRIES
(but I think we'll find a solution for this too:-)
7.) also there're some other stuff left, but step by step :-)
This patch also includes updates for the
register_subsystem() , ntvfs_init(), and some other funtions
to check for duplicate subsystem registration
metze
(hmmm, my first large commit...I hope it works as supposed :-)
(This used to be commit 917e45dafd5be4c2cd90ff425b8d6f8403122349)
2004-01-09 01:55:27 +03:00
}
2023-01-04 13:43:59 +03:00
id = idr_get_new_random (
dce_ctx - > assoc_groups_idr , assoc_group , 1 , UINT16_MAX ) ;
2019-10-03 20:38:31 +03:00
if ( id = = - 1 ) {
talloc_free ( assoc_group ) ;
DEBUG ( 0 , ( __location__ " : Out of association groups! \n " ) ) ;
return NULL ;
}
This patch adds a better dcerpc server infastructure.
1.) We now register endpoint servers add startup via register_backend()
and later use the smb.conf 'dcerpc endpoint servers' parameter to setup the dcesrv_context
2.) each endpoint server can register at context creation time as much interfaces as it wants
(multiple interfaces on one endpoint are supported!)
(NOTE: there's a difference between 'endpoint server' and 'endpoint'!
for details look at rpc_server/dcesrv_server.h)
3.) one endpoint can have a security descriptor registered to it self
this will be checked in the future when a client wants to connect
to an smb pipe endpoint.
4.) we now have a 'remote' endpoint server, which works like the ntvfs_cifs module
it takes this options in the [globals] section:
dcerpc remote:interfaces = srvsvc, winreg, w32time, epmapper
dcerpc remote:binding = ...
dcerpc remote:user = ...
dcerpc remote:password = ...
5.) we currently have tree endpoint servers: epmapper, rpcecho and remote
the default for the 'dcerpc endpiont servers = epmapper, rpcecho'
for testing you can also do
dcerpc endpoint servers = rpcecho, remote, epmapper
dcerpc remote:interfaces = srvsvc, samr, netlogon
6,) please notice the the epmapper now only returns NO_ENTRIES
(but I think we'll find a solution for this too:-)
7.) also there're some other stuff left, but step by step :-)
This patch also includes updates for the
register_subsystem() , ntvfs_init(), and some other funtions
to check for duplicate subsystem registration
metze
(hmmm, my first large commit...I hope it works as supposed :-)
(This used to be commit 917e45dafd5be4c2cd90ff425b8d6f8403122349)
2004-01-09 01:55:27 +03:00
2019-10-03 20:38:31 +03:00
assoc_group - > transport = transport ;
assoc_group - > id = id ;
assoc_group - > dce_ctx = dce_ctx ;
This patch adds a better dcerpc server infastructure.
1.) We now register endpoint servers add startup via register_backend()
and later use the smb.conf 'dcerpc endpoint servers' parameter to setup the dcesrv_context
2.) each endpoint server can register at context creation time as much interfaces as it wants
(multiple interfaces on one endpoint are supported!)
(NOTE: there's a difference between 'endpoint server' and 'endpoint'!
for details look at rpc_server/dcesrv_server.h)
3.) one endpoint can have a security descriptor registered to it self
this will be checked in the future when a client wants to connect
to an smb pipe endpoint.
4.) we now have a 'remote' endpoint server, which works like the ntvfs_cifs module
it takes this options in the [globals] section:
dcerpc remote:interfaces = srvsvc, winreg, w32time, epmapper
dcerpc remote:binding = ...
dcerpc remote:user = ...
dcerpc remote:password = ...
5.) we currently have tree endpoint servers: epmapper, rpcecho and remote
the default for the 'dcerpc endpiont servers = epmapper, rpcecho'
for testing you can also do
dcerpc endpoint servers = rpcecho, remote, epmapper
dcerpc remote:interfaces = srvsvc, samr, netlogon
6,) please notice the the epmapper now only returns NO_ENTRIES
(but I think we'll find a solution for this too:-)
7.) also there're some other stuff left, but step by step :-)
This patch also includes updates for the
register_subsystem() , ntvfs_init(), and some other funtions
to check for duplicate subsystem registration
metze
(hmmm, my first large commit...I hope it works as supposed :-)
(This used to be commit 917e45dafd5be4c2cd90ff425b8d6f8403122349)
2004-01-09 01:55:27 +03:00
2019-10-03 20:38:31 +03:00
talloc_set_destructor ( assoc_group , dcesrv_assoc_group_destructor ) ;
2003-12-13 05:20:40 +03:00
2023-10-12 13:49:42 +03:00
SMB_ASSERT ( dce_ctx - > assoc_groups_num < UINT16_MAX ) ;
dce_ctx - > assoc_groups_num + = 1 ;
2019-10-03 20:38:31 +03:00
return assoc_group ;
This patch adds a better dcerpc server infastructure.
1.) We now register endpoint servers add startup via register_backend()
and later use the smb.conf 'dcerpc endpoint servers' parameter to setup the dcesrv_context
2.) each endpoint server can register at context creation time as much interfaces as it wants
(multiple interfaces on one endpoint are supported!)
(NOTE: there's a difference between 'endpoint server' and 'endpoint'!
for details look at rpc_server/dcesrv_server.h)
3.) one endpoint can have a security descriptor registered to it self
this will be checked in the future when a client wants to connect
to an smb pipe endpoint.
4.) we now have a 'remote' endpoint server, which works like the ntvfs_cifs module
it takes this options in the [globals] section:
dcerpc remote:interfaces = srvsvc, winreg, w32time, epmapper
dcerpc remote:binding = ...
dcerpc remote:user = ...
dcerpc remote:password = ...
5.) we currently have tree endpoint servers: epmapper, rpcecho and remote
the default for the 'dcerpc endpiont servers = epmapper, rpcecho'
for testing you can also do
dcerpc endpoint servers = rpcecho, remote, epmapper
dcerpc remote:interfaces = srvsvc, samr, netlogon
6,) please notice the the epmapper now only returns NO_ENTRIES
(but I think we'll find a solution for this too:-)
7.) also there're some other stuff left, but step by step :-)
This patch also includes updates for the
register_subsystem() , ntvfs_init(), and some other funtions
to check for duplicate subsystem registration
metze
(hmmm, my first large commit...I hope it works as supposed :-)
(This used to be commit 917e45dafd5be4c2cd90ff425b8d6f8403122349)
2004-01-09 01:55:27 +03:00
}
2003-12-13 05:20:40 +03:00
2022-03-31 13:29:14 +03:00
NTSTATUS dcesrv_assoc_group_find_s4 (
2021-01-29 20:16:08 +03:00
struct dcesrv_call_state * call ,
void * private_data )
2003-12-14 16:22:12 +03:00
{
2019-10-03 20:38:31 +03:00
/*
if provided , check the assoc_group is valid
*/
if ( call - > pkt . u . bind . assoc_group_id ! = 0 ) {
call - > conn - > assoc_group =
dcesrv_assoc_group_reference ( call - > conn ,
call - > pkt . u . bind . assoc_group_id ) ;
} else {
call - > conn - > assoc_group = dcesrv_assoc_group_new ( call - > conn ) ;
}
This patch adds a better dcerpc server infastructure.
1.) We now register endpoint servers add startup via register_backend()
and later use the smb.conf 'dcerpc endpoint servers' parameter to setup the dcesrv_context
2.) each endpoint server can register at context creation time as much interfaces as it wants
(multiple interfaces on one endpoint are supported!)
(NOTE: there's a difference between 'endpoint server' and 'endpoint'!
for details look at rpc_server/dcesrv_server.h)
3.) one endpoint can have a security descriptor registered to it self
this will be checked in the future when a client wants to connect
to an smb pipe endpoint.
4.) we now have a 'remote' endpoint server, which works like the ntvfs_cifs module
it takes this options in the [globals] section:
dcerpc remote:interfaces = srvsvc, winreg, w32time, epmapper
dcerpc remote:binding = ...
dcerpc remote:user = ...
dcerpc remote:password = ...
5.) we currently have tree endpoint servers: epmapper, rpcecho and remote
the default for the 'dcerpc endpiont servers = epmapper, rpcecho'
for testing you can also do
dcerpc endpoint servers = rpcecho, remote, epmapper
dcerpc remote:interfaces = srvsvc, samr, netlogon
6,) please notice the the epmapper now only returns NO_ENTRIES
(but I think we'll find a solution for this too:-)
7.) also there're some other stuff left, but step by step :-)
This patch also includes updates for the
register_subsystem() , ntvfs_init(), and some other funtions
to check for duplicate subsystem registration
metze
(hmmm, my first large commit...I hope it works as supposed :-)
(This used to be commit 917e45dafd5be4c2cd90ff425b8d6f8403122349)
2004-01-09 01:55:27 +03:00
2019-10-03 20:38:31 +03:00
/*
* The NETLOGON server does not use handles and so
* there is no need to support association groups , but
* we need to give back a number regardless .
*
* We have to do this when it is not run as a single process ,
* because then it can ' t see the other valid association
2023-08-09 07:04:03 +03:00
* groups . We handle this generically for all endpoints not
2019-10-03 20:38:31 +03:00
* running in single process mode .
*
* We know which endpoint we are on even before checking the
* iface UUID , so for simplicity we enforce the same policy
* for all interfaces on the endpoint .
*
* This means that where NETLOGON
2021-01-13 18:03:08 +03:00
* shares an endpoint ( such as ncalrpc or if ' lsa over
2019-10-03 20:38:31 +03:00
* netlogon ' is set ) we will still check association groups .
*
*/
if ( call - > conn - > assoc_group = = NULL & &
! call - > conn - > endpoint - > use_single_process ) {
call - > conn - > assoc_group
= dcesrv_assoc_group_new ( call - > conn ) ;
}
if ( call - > conn - > assoc_group = = NULL ) {
/* TODO Return correct status */
return NT_STATUS_UNSUCCESSFUL ;
2003-12-14 16:22:12 +03:00
}
2019-10-03 20:38:31 +03:00
return NT_STATUS_OK ;
2003-12-14 16:22:12 +03:00
}
2008-12-09 11:22:31 +03:00
void dcerpc_server_init ( struct loadparm_context * lp_ctx )
{
static bool initialized ;
2017-04-20 22:24:43 +03:00
# define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
2010-11-01 07:38:37 +03:00
STATIC_dcerpc_server_MODULES_PROTO ;
2011-12-03 10:03:35 +04:00
init_module_fn static_init [ ] = { STATIC_dcerpc_server_MODULES } ;
init_module_fn * shared_init ;
2008-12-09 11:22:31 +03:00
if ( initialized ) {
return ;
}
initialized = true ;
2011-12-03 10:03:35 +04:00
shared_init = load_samba_modules ( NULL , " dcerpc_server " ) ;
2008-12-09 11:22:31 +03:00
2017-04-20 22:24:43 +03:00
run_init_functions ( NULL , static_init ) ;
run_init_functions ( NULL , shared_init ) ;
2008-12-09 11:22:31 +03:00
talloc_free ( shared_init ) ;
}
2010-10-11 02:49:13 +04:00
struct dcesrv_socket_context {
const struct dcesrv_endpoint * endpoint ;
struct dcesrv_context * dcesrv_ctx ;
} ;
static void dcesrv_sock_accept ( struct stream_connection * srv_conn )
{
NTSTATUS status ;
struct dcesrv_socket_context * dcesrv_sock =
talloc_get_type ( srv_conn - > private_data , struct dcesrv_socket_context ) ;
2014-01-30 22:01:34 +04:00
enum dcerpc_transport_t transport =
dcerpc_binding_get_transport ( dcesrv_sock - > endpoint - > ep_description ) ;
2010-10-11 02:49:13 +04:00
struct dcesrv_connection * dcesrv_conn = NULL ;
int ret ;
struct loadparm_context * lp_ctx = dcesrv_sock - > dcesrv_ctx - > lp_ctx ;
2013-07-09 18:38:59 +04:00
dcesrv_cleanup_broken_connections ( dcesrv_sock - > dcesrv_ctx ) ;
2010-10-11 02:49:13 +04:00
if ( ! srv_conn - > session_info ) {
status = auth_anonymous_session_info ( srv_conn ,
lp_ctx ,
& srv_conn - > session_info ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " dcesrv_sock_accept: auth_anonymous_session_info failed: %s \n " ,
nt_errstr ( status ) ) ) ;
stream_terminate_connection ( srv_conn , nt_errstr ( status ) ) ;
return ;
}
}
2016-12-13 23:38:28 +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 .
*/
2010-10-11 02:49:13 +04:00
status = dcesrv_endpoint_connect ( dcesrv_sock - > dcesrv_ctx ,
srv_conn ,
dcesrv_sock - > endpoint ,
srv_conn - > session_info ,
srv_conn - > event . ctx ,
DCESRV_CALL_STATE_FLAG_MAY_ASYNC ,
& dcesrv_conn ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s \n " ,
nt_errstr ( status ) ) ) ;
stream_terminate_connection ( srv_conn , nt_errstr ( status ) ) ;
return ;
}
dcesrv_conn - > transport . private_data = srv_conn ;
dcesrv_conn - > transport . report_output_data = dcesrv_sock_report_output_data ;
2022-03-31 13:32:08 +03:00
dcesrv_conn - > transport . terminate_connection = dcesrv_transport_terminate_connection_s4 ;
2010-10-11 02:49:13 +04:00
TALLOC_FREE ( srv_conn - > event . fde ) ;
dcesrv_conn - > send_queue = tevent_queue_create ( dcesrv_conn , " dcesrv send queue " ) ;
if ( ! dcesrv_conn - > send_queue ) {
status = NT_STATUS_NO_MEMORY ;
DEBUG ( 0 , ( " dcesrv_sock_accept: tevent_queue_create(%s) \n " ,
nt_errstr ( status ) ) ) ;
stream_terminate_connection ( srv_conn , nt_errstr ( status ) ) ;
return ;
}
2014-01-30 22:01:34 +04:00
if ( transport = = NCACN_NP ) {
2010-10-11 02:49:13 +04:00
dcesrv_conn - > stream = talloc_move ( dcesrv_conn ,
& srv_conn - > tstream ) ;
} else {
ret = tstream_bsd_existing_socket ( dcesrv_conn ,
socket_get_fd ( srv_conn - > socket ) ,
& dcesrv_conn - > stream ) ;
if ( ret = = - 1 ) {
2011-06-20 08:55:32 +04:00
status = map_nt_error_from_unix_common ( errno ) ;
2010-10-11 02:49:13 +04:00
DEBUG ( 0 , ( " dcesrv_sock_accept: "
" failed to setup tstream: %s \n " ,
nt_errstr ( status ) ) ) ;
stream_terminate_connection ( srv_conn , nt_errstr ( status ) ) ;
return ;
}
socket_set_flags ( srv_conn - > socket , SOCKET_FLAG_NOCLOSE ) ;
2023-01-12 12:48:22 +03:00
/* as server we want to fail early */
tstream_bsd_fail_readv_first_error ( dcesrv_conn - > stream , true ) ;
2010-10-11 02:49:13 +04:00
}
dcesrv_conn - > local_address = srv_conn - > local_address ;
dcesrv_conn - > remote_address = srv_conn - > remote_address ;
2015-01-22 14:24:31 +03:00
if ( transport = = NCALRPC ) {
uid_t uid ;
gid_t gid ;
2016-06-07 11:01:32 +03:00
int sock_fd ;
2015-01-22 14:24:31 +03:00
2016-06-07 11:01:32 +03:00
sock_fd = socket_get_fd ( srv_conn - > socket ) ;
if ( sock_fd = = - 1 ) {
stream_terminate_connection (
srv_conn , " socket_get_fd failed \n " ) ;
return ;
}
ret = getpeereid ( sock_fd , & uid , & gid ) ;
2015-01-22 14:24:31 +03:00
if ( ret = = - 1 ) {
status = map_nt_error_from_unix_common ( errno ) ;
DEBUG ( 0 , ( " dcesrv_sock_accept: "
" getpeereid() failed for NCALRPC: %s \n " ,
nt_errstr ( status ) ) ) ;
stream_terminate_connection ( srv_conn , nt_errstr ( status ) ) ;
return ;
}
if ( uid = = dcesrv_conn - > dce_ctx - > initial_euid ) {
struct tsocket_address * r = NULL ;
ret = tsocket_address_unix_from_path ( dcesrv_conn ,
2017-07-24 02:00:45 +03:00
AS_SYSTEM_MAGIC_PATH_TOKEN ,
2015-01-22 14:24:31 +03:00
& r ) ;
if ( ret = = - 1 ) {
status = map_nt_error_from_unix_common ( errno ) ;
DEBUG ( 0 , ( " dcesrv_sock_accept: "
" tsocket_address_unix_from_path() failed for NCALRPC: %s \n " ,
nt_errstr ( status ) ) ) ;
stream_terminate_connection ( srv_conn , nt_errstr ( status ) ) ;
return ;
}
dcesrv_conn - > remote_address = r ;
}
}
2010-10-11 02:49:13 +04:00
srv_conn - > private_data = dcesrv_conn ;
2019-01-24 17:59:04 +03:00
status = dcesrv_connection_loop_start ( dcesrv_conn ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-10-11 02:49:13 +04:00
DEBUG ( 0 , ( " dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s) \n " ,
nt_errstr ( status ) ) ) ;
stream_terminate_connection ( srv_conn , nt_errstr ( status ) ) ;
return ;
}
return ;
}
static void dcesrv_sock_recv ( struct stream_connection * conn , uint16_t flags )
{
struct dcesrv_connection * dce_conn = talloc_get_type ( conn - > private_data ,
struct dcesrv_connection ) ;
dcesrv_terminate_connection ( dce_conn , " dcesrv_sock_recv triggered " ) ;
}
static void dcesrv_sock_send ( struct stream_connection * conn , uint16_t flags )
{
struct dcesrv_connection * dce_conn = talloc_get_type ( conn - > private_data ,
struct dcesrv_connection ) ;
dcesrv_terminate_connection ( dce_conn , " dcesrv_sock_send triggered " ) ;
}
static const struct stream_server_ops dcesrv_stream_ops = {
. name = " rpc " ,
. accept_connection = dcesrv_sock_accept ,
. recv_handler = dcesrv_sock_recv ,
. send_handler = dcesrv_sock_send ,
} ;
static NTSTATUS dcesrv_add_ep_unix ( struct dcesrv_context * dce_ctx ,
struct loadparm_context * lp_ctx ,
struct dcesrv_endpoint * e ,
2017-09-14 22:09:23 +03:00
struct tevent_context * event_ctx ,
const struct model_ops * model_ops ,
void * process_context )
2010-10-11 02:49:13 +04:00
{
struct dcesrv_socket_context * dcesrv_sock ;
uint16_t port = 1 ;
NTSTATUS status ;
2014-02-04 14:32:03 +04:00
const char * endpoint ;
2010-10-11 02:49:13 +04:00
2015-06-26 09:10:46 +03:00
dcesrv_sock = talloc_zero ( event_ctx , struct dcesrv_socket_context ) ;
2010-10-11 02:49:13 +04:00
NT_STATUS_HAVE_NO_MEMORY ( dcesrv_sock ) ;
/* remember the endpoint of this socket */
dcesrv_sock - > endpoint = e ;
dcesrv_sock - > dcesrv_ctx = talloc_reference ( dcesrv_sock , dce_ctx ) ;
2014-02-04 14:32:03 +04:00
endpoint = dcerpc_binding_get_string_option ( e - > ep_description , " endpoint " ) ;
2010-11-15 02:12:22 +03:00
status = stream_setup_socket ( dcesrv_sock , event_ctx , lp_ctx ,
2010-10-11 02:49:13 +04:00
model_ops , & dcesrv_stream_ops ,
2014-02-04 14:32:03 +04:00
" unix " , endpoint , & port ,
2010-10-11 02:49:13 +04:00
lpcfg_socket_options ( lp_ctx ) ,
2017-09-14 22:09:23 +03:00
dcesrv_sock , process_context ) ;
2010-10-11 02:49:13 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " service_setup_stream_socket(path=%s) failed - %s \n " ,
2014-02-04 14:32:03 +04:00
endpoint , nt_errstr ( status ) ) ) ;
2010-10-11 02:49:13 +04:00
}
return status ;
}
static NTSTATUS dcesrv_add_ep_ncalrpc ( struct dcesrv_context * dce_ctx ,
struct loadparm_context * lp_ctx ,
struct dcesrv_endpoint * e ,
2017-09-14 22:09:23 +03:00
struct tevent_context * event_ctx ,
const struct model_ops * model_ops ,
void * process_context )
2010-10-11 02:49:13 +04:00
{
struct dcesrv_socket_context * dcesrv_sock ;
uint16_t port = 1 ;
char * full_path ;
NTSTATUS status ;
2014-02-04 14:32:03 +04:00
const char * endpoint ;
endpoint = dcerpc_binding_get_string_option ( e - > ep_description , " endpoint " ) ;
2010-10-11 02:49:13 +04:00
2014-02-04 14:32:03 +04:00
if ( endpoint = = NULL ) {
/*
* No identifier specified : use DEFAULT .
*
* TODO : DO NOT hardcode this value anywhere else . Rather , specify
* no endpoint and let the epmapper worry about it .
*/
endpoint = " DEFAULT " ;
status = dcerpc_binding_set_string_option ( e - > ep_description ,
" endpoint " ,
endpoint ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " dcerpc_binding_set_string_option() failed - %s \n " ,
nt_errstr ( status ) ) ) ;
return status ;
}
2010-10-11 02:49:13 +04:00
}
full_path = talloc_asprintf ( dce_ctx , " %s/%s " , lpcfg_ncalrpc_dir ( lp_ctx ) ,
2014-02-04 14:32:03 +04:00
endpoint ) ;
2010-10-11 02:49:13 +04:00
2015-06-26 09:10:46 +03:00
dcesrv_sock = talloc_zero ( event_ctx , struct dcesrv_socket_context ) ;
2010-10-11 02:49:13 +04:00
NT_STATUS_HAVE_NO_MEMORY ( dcesrv_sock ) ;
/* remember the endpoint of this socket */
dcesrv_sock - > endpoint = e ;
dcesrv_sock - > dcesrv_ctx = talloc_reference ( dcesrv_sock , dce_ctx ) ;
2010-11-15 02:12:22 +03:00
status = stream_setup_socket ( dcesrv_sock , event_ctx , lp_ctx ,
2010-10-11 02:49:13 +04:00
model_ops , & dcesrv_stream_ops ,
" unix " , full_path , & port ,
lpcfg_socket_options ( lp_ctx ) ,
2017-09-14 22:09:23 +03:00
dcesrv_sock , process_context ) ;
2010-10-11 02:49:13 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " service_setup_stream_socket(identifier=%s,path=%s) failed - %s \n " ,
2014-02-04 14:32:03 +04:00
endpoint , full_path , nt_errstr ( status ) ) ) ;
2010-10-11 02:49:13 +04:00
}
return status ;
}
static NTSTATUS dcesrv_add_ep_np ( struct dcesrv_context * dce_ctx ,
struct loadparm_context * lp_ctx ,
struct dcesrv_endpoint * e ,
2017-09-14 22:09:23 +03:00
struct tevent_context * event_ctx ,
const struct model_ops * model_ops ,
void * process_context )
2010-10-11 02:49:13 +04:00
{
struct dcesrv_socket_context * dcesrv_sock ;
NTSTATUS status ;
2014-02-04 14:32:03 +04:00
const char * endpoint ;
endpoint = dcerpc_binding_get_string_option ( e - > ep_description , " endpoint " ) ;
if ( endpoint = = NULL ) {
2010-10-11 02:49:13 +04:00
DEBUG ( 0 , ( " Endpoint mandatory for named pipes \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
2015-06-26 09:10:46 +03:00
dcesrv_sock = talloc_zero ( event_ctx , struct dcesrv_socket_context ) ;
2010-10-11 02:49:13 +04:00
NT_STATUS_HAVE_NO_MEMORY ( dcesrv_sock ) ;
/* remember the endpoint of this socket */
dcesrv_sock - > endpoint = e ;
dcesrv_sock - > dcesrv_ctx = talloc_reference ( dcesrv_sock , dce_ctx ) ;
2010-11-15 02:12:22 +03:00
status = tstream_setup_named_pipe ( dce_ctx , event_ctx , lp_ctx ,
2010-10-11 02:49:13 +04:00
model_ops , & dcesrv_stream_ops ,
2014-02-04 14:32:03 +04:00
endpoint ,
2017-09-14 22:09:23 +03:00
dcesrv_sock , process_context ) ;
2010-10-11 02:49:13 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " stream_setup_named_pipe(pipe=%s) failed - %s \n " ,
2014-02-04 14:32:03 +04:00
endpoint , nt_errstr ( status ) ) ) ;
2010-10-11 02:49:13 +04:00
return status ;
}
return NT_STATUS_OK ;
}
/*
add a socket address to the list of events , one event per dcerpc endpoint
*/
2017-09-14 22:09:23 +03:00
static NTSTATUS add_socket_rpc_tcp_iface ( struct dcesrv_context * dce_ctx ,
struct dcesrv_endpoint * e ,
struct tevent_context * event_ctx ,
const struct model_ops * model_ops ,
const char * address ,
void * process_context )
2010-10-11 02:49:13 +04:00
{
struct dcesrv_socket_context * dcesrv_sock ;
uint16_t port = 0 ;
NTSTATUS status ;
2014-02-04 14:32:03 +04:00
const char * endpoint ;
char port_str [ 6 ] ;
endpoint = dcerpc_binding_get_string_option ( e - > ep_description , " endpoint " ) ;
if ( endpoint ! = NULL ) {
port = atoi ( endpoint ) ;
2010-10-11 02:49:13 +04:00
}
2015-06-26 09:10:46 +03:00
dcesrv_sock = talloc_zero ( event_ctx , struct dcesrv_socket_context ) ;
2010-10-11 02:49:13 +04:00
NT_STATUS_HAVE_NO_MEMORY ( dcesrv_sock ) ;
/* remember the endpoint of this socket */
dcesrv_sock - > endpoint = e ;
dcesrv_sock - > dcesrv_ctx = talloc_reference ( dcesrv_sock , dce_ctx ) ;
2010-11-15 02:12:22 +03:00
status = stream_setup_socket ( dcesrv_sock , event_ctx , dce_ctx - > lp_ctx ,
2010-10-11 02:49:13 +04:00
model_ops , & dcesrv_stream_ops ,
2011-05-12 14:36:33 +04:00
" ip " , address , & port ,
2010-10-11 02:49:13 +04:00
lpcfg_socket_options ( dce_ctx - > lp_ctx ) ,
2017-09-14 22:09:23 +03:00
dcesrv_sock , process_context ) ;
2010-10-11 02:49:13 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2016-10-18 00:36:51 +03:00
struct dcesrv_if_list * iface ;
DEBUG ( 0 , ( " service_setup_stream_socket(address=%s,port=%u) for " ,
address , port ) ) ;
for ( iface = e - > interface_list ; iface ; iface = iface - > next ) {
2019-10-01 17:48:01 +03:00
DEBUGADD ( 0 , ( " %s " , iface - > iface - > name ) ) ;
2016-10-18 00:36:51 +03:00
}
2019-03-29 18:36:03 +03:00
DEBUGADD ( 0 , ( " failed - %s \n " ,
2016-10-18 00:36:51 +03:00
nt_errstr ( status ) ) ) ;
2014-02-04 14:32:03 +04:00
return status ;
2010-10-11 02:49:13 +04:00
}
2014-02-04 14:32:03 +04:00
snprintf ( port_str , sizeof ( port_str ) , " %u " , port ) ;
status = dcerpc_binding_set_string_option ( e - > ep_description ,
" endpoint " , port_str ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " dcerpc_binding_set_string_option(endpoint, %s) failed - %s \n " ,
port_str , nt_errstr ( status ) ) ) ;
return status ;
2016-10-19 02:45:05 +03:00
} else {
struct dcesrv_if_list * iface ;
DEBUG ( 4 , ( " Successfully listening on ncacn_ip_tcp endpoint [%s]:[%s] for " ,
address , port_str ) ) ;
for ( iface = e - > interface_list ; iface ; iface = iface - > next ) {
2019-10-01 17:48:01 +03:00
DEBUGADD ( 4 , ( " %s " , iface - > iface - > name ) ) ;
2016-10-19 02:45:05 +03:00
}
DEBUGADD ( 4 , ( " \n " ) ) ;
2010-10-11 02:49:13 +04:00
}
2014-02-04 14:32:03 +04:00
return NT_STATUS_OK ;
2010-10-11 02:49:13 +04:00
}
# include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
static NTSTATUS dcesrv_add_ep_tcp ( struct dcesrv_context * dce_ctx ,
struct loadparm_context * lp_ctx ,
struct dcesrv_endpoint * e ,
2017-09-14 22:09:23 +03:00
struct tevent_context * event_ctx ,
const struct model_ops * model_ops ,
void * process_context )
2010-10-11 02:49:13 +04:00
{
NTSTATUS status ;
/* Add TCP/IP sockets */
if ( lpcfg_interfaces ( lp_ctx ) & & lpcfg_bind_interfaces_only ( lp_ctx ) ) {
int num_interfaces ;
int i ;
struct interface * ifaces ;
2011-06-02 09:40:28 +04:00
load_interface_list ( dce_ctx , lp_ctx , & ifaces ) ;
2010-10-11 02:49:13 +04:00
2011-05-02 09:57:19 +04:00
num_interfaces = iface_list_count ( ifaces ) ;
2010-10-11 02:49:13 +04:00
for ( i = 0 ; i < num_interfaces ; i + + ) {
2011-05-02 09:57:19 +04:00
const char * address = iface_list_n_ip ( ifaces , i ) ;
2017-09-14 22:09:23 +03:00
status = add_socket_rpc_tcp_iface ( dce_ctx , e , event_ctx ,
model_ops , address ,
process_context ) ;
2010-10-11 02:49:13 +04:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
}
} else {
2014-02-27 13:28:23 +04:00
char * * wcard ;
2017-12-07 19:48:00 +03:00
size_t i ;
size_t num_binds = 0 ;
2014-02-27 13:28:23 +04:00
wcard = iface_list_wildcard ( dce_ctx ) ;
2011-05-12 14:35:02 +04:00
NT_STATUS_HAVE_NO_MEMORY ( wcard ) ;
for ( i = 0 ; wcard [ i ] ; i + + ) {
2017-09-14 22:09:23 +03:00
status = add_socket_rpc_tcp_iface ( dce_ctx , e , event_ctx ,
model_ops , wcard [ i ] ,
process_context ) ;
2014-06-05 23:32:30 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
num_binds + + ;
}
2011-05-12 14:35:02 +04:00
}
talloc_free ( wcard ) ;
2014-06-05 23:32:30 +04:00
if ( num_binds = = 0 ) {
return NT_STATUS_INVALID_PARAMETER_MIX ;
}
2010-10-11 02:49:13 +04:00
}
return NT_STATUS_OK ;
}
NTSTATUS dcesrv_add_ep ( struct dcesrv_context * dce_ctx ,
struct loadparm_context * lp_ctx ,
struct dcesrv_endpoint * e ,
struct tevent_context * event_ctx ,
2017-09-14 22:09:23 +03:00
const struct model_ops * model_ops ,
void * process_context )
2010-10-11 02:49:13 +04:00
{
2014-01-30 22:01:34 +04:00
enum dcerpc_transport_t transport =
dcerpc_binding_get_transport ( e - > ep_description ) ;
switch ( transport ) {
2010-10-11 02:49:13 +04:00
case NCACN_UNIX_STREAM :
2017-09-14 22:09:23 +03:00
return dcesrv_add_ep_unix ( dce_ctx , lp_ctx , e , event_ctx ,
model_ops , process_context ) ;
2010-10-11 02:49:13 +04:00
case NCALRPC :
2017-09-14 22:09:23 +03:00
return dcesrv_add_ep_ncalrpc ( dce_ctx , lp_ctx , e , event_ctx ,
model_ops , process_context ) ;
2010-10-11 02:49:13 +04:00
case NCACN_IP_TCP :
2017-09-14 22:09:23 +03:00
return dcesrv_add_ep_tcp ( dce_ctx , lp_ctx , e , event_ctx ,
model_ops , process_context ) ;
2010-10-11 02:49:13 +04:00
case NCACN_NP :
2017-09-14 22:09:23 +03:00
return dcesrv_add_ep_np ( dce_ctx , lp_ctx , e , event_ctx ,
model_ops , process_context ) ;
2010-10-11 02:49:13 +04:00
default :
return NT_STATUS_NOT_SUPPORTED ;
}
}
2011-02-25 05:13:01 +03:00
2019-01-23 22:37:21 +03:00
_PUBLIC_ struct imessaging_context * dcesrv_imessaging_context (
struct dcesrv_connection * conn )
{
struct stream_connection * srv_conn =
talloc_get_type_abort ( conn - > transport . private_data ,
struct stream_connection ) ;
return srv_conn - > msg_ctx ;
}
2019-01-23 22:41:54 +03:00
_PUBLIC_ struct server_id dcesrv_server_id ( struct dcesrv_connection * conn )
{
struct stream_connection * srv_conn =
talloc_get_type_abort ( conn - > transport . private_data ,
struct stream_connection ) ;
return srv_conn - > server_id ;
}
2019-01-24 22:03:44 +03:00
2021-01-29 20:16:08 +03:00
void log_successful_dcesrv_authz_event (
struct dcesrv_call_state * call ,
void * private_data )
2019-01-24 22:03:44 +03:00
{
struct dcesrv_auth * auth = call - > auth_state ;
enum dcerpc_transport_t transport =
dcerpc_binding_get_transport ( call - > conn - > endpoint - > ep_description ) ;
struct imessaging_context * imsg_ctx =
dcesrv_imessaging_context ( call - > conn ) ;
const char * auth_type = derpc_transport_string_by_transport ( transport ) ;
const char * transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE ;
if ( transport = = NCACN_NP ) {
transport_protection = AUTHZ_TRANSPORT_PROTECTION_SMB ;
}
/*
* Log the authorization to this RPC interface . This
* covered ncacn_np pass - through auth , and anonymous
* DCE / RPC ( eg epmapper , netlogon etc )
*/
log_successful_authz_event ( imsg_ctx ,
call - > conn - > dce_ctx - > lp_ctx ,
call - > conn - > remote_address ,
call - > conn - > local_address ,
" DCE/RPC " ,
auth_type ,
transport_protection ,
2023-06-15 08:07:05 +03:00
auth - > session_info ,
NULL /* client_audit_info */ ,
NULL /* server_audit_info */ ) ;
2019-01-24 22:03:44 +03:00
auth - > auth_audited = true ;
}
2019-01-24 22:34:03 +03:00
2021-01-29 20:16:08 +03:00
NTSTATUS dcesrv_gensec_prepare (
TALLOC_CTX * mem_ctx ,
struct dcesrv_call_state * call ,
struct gensec_security * * out ,
void * private_data )
2019-01-24 22:34:03 +03:00
{
struct cli_credentials * server_creds = NULL ;
struct imessaging_context * imsg_ctx =
dcesrv_imessaging_context ( call - > conn ) ;
2021-04-08 16:45:42 +03:00
bool ok ;
2019-01-24 22:34:03 +03:00
2020-09-04 13:21:36 +03:00
server_creds = cli_credentials_init_server ( call - > auth_state ,
call - > conn - > dce_ctx - > lp_ctx ) ;
if ( server_creds = = NULL ) {
2019-01-24 22:34:03 +03:00
DEBUG ( 1 , ( " Failed to init server credentials \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
2021-04-08 16:45:42 +03:00
/* This is required for ncalrpc_as_system. */
ok = cli_credentials_set_kerberos_state ( server_creds ,
CRED_USE_KERBEROS_DESIRED ,
CRED_SPECIFIED ) ;
if ( ! ok ) {
DBG_WARNING ( " Failed to set kerberos state \n " ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
2019-01-24 22:34:03 +03:00
return samba_server_gensec_start ( mem_ctx ,
call - > event_ctx ,
imsg_ctx ,
call - > conn - > dce_ctx - > lp_ctx ,
server_creds ,
NULL ,
out ) ;
}
2019-01-24 22:25:58 +03:00
2022-03-31 13:32:08 +03:00
void dcesrv_transport_terminate_connection_s4 ( struct dcesrv_connection * dce_conn ,
const char * reason )
2019-01-24 22:25:58 +03:00
{
struct stream_connection * srv_conn =
talloc_get_type_abort ( dce_conn - > transport . private_data ,
struct stream_connection ) ;
stream_terminate_connection ( srv_conn , reason ) ;
}