2004-10-24 19:48:19 +04:00
/*
Unix SMB / CIFS implementation .
2007-09-03 17:13:25 +04:00
smbd - specific dcerpc server code
2004-10-24 19:48:19 +04:00
2007-09-03 17:13:25 +04:00
Copyright ( C ) Andrew Tridgell 2003 - 2005
Copyright ( C ) Stefan ( metze ) Metzmacher 2004 - 2005
Copyright ( C ) Jelmer Vernooij < jelmer @ samba . org > 2004 , 2007
2004-10-24 19:48:19 +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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2004-10-24 19:48:19 +04: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/>.
2004-10-24 19:48:19 +04:00
*/
# include "includes.h"
2007-09-03 17:13:25 +04:00
# include "librpc/gen_ndr/ndr_dcerpc.h"
# include "auth/auth.h"
2008-10-11 23:31:42 +04:00
# include "../lib/util/dlinklist.h"
2004-11-02 10:42:47 +03:00
# include "rpc_server/dcerpc_server.h"
2008-11-23 13:24:29 +03:00
# include "rpc_server/dcerpc_server_proto.h"
2019-10-03 17:59:49 +03:00
# include "librpc/rpc/dcerpc.h"
2007-09-03 17:13:25 +04:00
# include "system/filesys.h"
2005-07-19 13:44:11 +04:00
# include "lib/messaging/irpc.h"
2006-03-07 14:07:23 +03:00
# include "system/network.h"
2006-08-17 17:37:04 +04:00
# include "lib/socket/netif.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2009-04-07 20:35:30 +04:00
# include "../lib/tsocket/tsocket.h"
# include "librpc/rpc/dcerpc_proto.h"
# include "../lib/util/tevent_ntstatus.h"
# include "libcli/raw/smb.h"
2020-11-20 17:27:17 +03:00
# include "samba/process_model.h"
2004-10-24 19:48:19 +04:00
2022-01-22 03:08:26 +03:00
static void skip_become_root ( void )
{
}
static void skip_unbecome_root ( void )
{
}
2021-03-13 18:33:21 +03:00
static struct dcesrv_context_callbacks srv_callbacks = {
2019-01-24 22:03:44 +03:00
. log . successful_authz = log_successful_dcesrv_authz_event ,
2019-01-24 22:34:03 +03:00
. auth . gensec_prepare = dcesrv_gensec_prepare ,
2022-01-22 03:08:26 +03:00
. auth . become_root = skip_become_root ,
. auth . unbecome_root = skip_unbecome_root ,
2022-03-31 13:29:14 +03:00
. assoc_group . find = dcesrv_assoc_group_find_s4 ,
2019-01-24 22:03:44 +03:00
} ;
2018-08-29 06:07:32 +03:00
/*
* Need to run the majority of the RPC endpoints in a single process to allow
* for shared handles , and the sharing of ldb contexts .
*
* However other endpoints are capable of being run in multiple processes
* e . g . NETLOGON .
*
* To support this the process model is manipulated to force those end points
* not supporting multiple processes into the single process model . The code
* responsible for this is in dcesrv_init_endpoints
*
*/
2017-04-20 22:24:43 +03:00
NTSTATUS server_service_rpc_init ( TALLOC_CTX * ) ;
2007-09-03 17:13:25 +04:00
/*
2018-08-29 06:07:32 +03:00
* Initialise the rpc endpoints .
*/
static NTSTATUS dcesrv_init_endpoints ( struct task_server * task ,
struct dcesrv_context * dce_ctx ,
bool use_single_process )
{
struct dcesrv_endpoint * e ;
const struct model_ops * model_ops = NULL ;
/*
* For those RPC services that run with shared context we need to
* ensure that they don ' t fork a new process on accept ( standard_model ) .
* And as there is only one process handling these requests we need
* to handle accept errors in a similar manner to the single process
* model .
*
* To do this we override the process model operations with the single
* process operations . This is not the most elegant solution , but it is
* the least ugly , and is confined to the next block of code .
*/
2021-01-20 16:53:56 +03:00
if ( use_single_process ) {
2018-08-29 06:07:32 +03:00
model_ops = process_model_startup ( " single " ) ;
if ( model_ops = = NULL ) {
2023-07-31 07:39:38 +03:00
DBG_ERR ( " Unable to load single process model \n " ) ;
2018-08-29 06:07:32 +03:00
return NT_STATUS_INTERNAL_ERROR ;
}
} else {
model_ops = task - > model_ops ;
}
for ( e = dce_ctx - > endpoint_list ; e ; e = e - > next ) {
enum dcerpc_transport_t transport =
dcerpc_binding_get_transport ( e - > ep_description ) ;
if ( transport = = NCACN_HTTP ) {
/*
* We don ' t support ncacn_http yet
*/
continue ;
}
if ( e - > use_single_process = = use_single_process ) {
NTSTATUS status ;
status = dcesrv_add_ep ( dce_ctx ,
task - > lp_ctx ,
e ,
task - > event_ctx ,
model_ops ,
task - > process_context ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
}
}
return NT_STATUS_OK ;
}
2019-01-24 22:03:44 +03:00
2018-08-29 06:07:32 +03:00
/*
* Initialise the RPC service .
* And those end points that can be serviced by multiple processes .
* The endpoints that need to be run in a single process are setup in the
* post_fork hook .
2007-09-03 17:13:25 +04:00
*/
2018-08-23 00:35:52 +03:00
static NTSTATUS dcesrv_task_init ( struct task_server * task )
2007-09-03 17:13:25 +04:00
{
2018-08-23 00:35:52 +03:00
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
2007-09-03 17:13:25 +04:00
struct dcesrv_context * dce_ctx ;
2019-02-05 20:54:02 +03:00
const char * * ep_servers = NULL ;
2008-12-09 11:22:31 +03:00
dcerpc_server_init ( task - > lp_ctx ) ;
2007-09-03 17:13:25 +04:00
task_server_set_title ( task , " task[dcesrv] " ) ;
status = dcesrv_init_context ( task - > event_ctx ,
2007-12-04 22:05:00 +03:00
task - > lp_ctx ,
2019-01-24 22:03:44 +03:00
& srv_callbacks ,
2007-09-03 17:13:25 +04:00
& dce_ctx ) ;
2018-08-29 06:07:32 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2007-09-03 17:13:25 +04:00
2019-02-05 20:54:02 +03:00
ep_servers = lpcfg_dcerpc_endpoint_servers ( task - > lp_ctx ) ;
status = dcesrv_init_ep_servers ( dce_ctx , ep_servers ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2007-09-03 17:13:25 +04:00
/* Make sure the directory for NCALRPC exists */
2010-07-16 08:32:42 +04:00
if ( ! directory_exist ( lpcfg_ncalrpc_dir ( task - > lp_ctx ) ) ) {
2023-10-06 01:10:25 +03:00
int ret ;
ret = mkdir ( lpcfg_ncalrpc_dir ( task - > lp_ctx ) , 0755 ) ;
if ( ret = = - 1 & & errno ! = EEXIST ) {
return map_nt_error_from_unix_common ( errno ) ;
}
2007-09-03 17:13:25 +04:00
}
2018-08-29 06:07:32 +03:00
status = dcesrv_init_endpoints ( task , dce_ctx , false ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2007-09-03 17:13:25 +04:00
2018-08-29 06:07:32 +03:00
task - > private_data = dce_ctx ;
return NT_STATUS_OK ;
}
2016-10-18 00:36:51 +03:00
2018-08-29 06:07:32 +03:00
/*
* Initialise the endpoints that need to run in a single process fork .
* The endpoint registration is only done for the first process instance .
*
*/
static void dcesrv_post_fork ( struct task_server * task ,
struct process_details * pd )
{
2016-10-18 00:36:51 +03:00
2018-08-29 06:07:32 +03:00
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
struct dcesrv_context * dce_ctx ;
2016-10-18 00:36:51 +03:00
2018-08-29 06:07:32 +03:00
if ( task - > private_data = = NULL ) {
task_server_terminate ( task , " dcerpc: No dcesrv_context " , true ) ;
return ;
}
dce_ctx =
talloc_get_type_abort ( task - > private_data , struct dcesrv_context ) ;
2014-09-21 10:38:10 +04:00
2018-08-29 06:07:32 +03:00
/*
* Ensure the single process endpoints are only available to the
* first instance .
*/
if ( pd - > instances = = 0 ) {
status = dcesrv_init_endpoints ( task , dce_ctx , true ) ;
2016-12-14 01:58:48 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2018-08-29 06:07:32 +03:00
task_server_terminate (
task ,
" dcerpc: Failed to initialise end points " ,
true ) ;
return ;
2016-12-14 01:58:48 +03:00
}
2007-09-03 17:13:25 +04:00
}
2013-05-27 14:10:57 +04:00
irpc_add_name ( task - > msg_ctx , " rpc_server " ) ;
2007-09-03 17:13:25 +04:00
}
2017-04-20 22:24:43 +03:00
NTSTATUS server_service_rpc_init ( TALLOC_CTX * ctx )
2007-09-03 17:13:25 +04:00
{
2018-08-23 00:29:56 +03:00
static const struct service_details details = {
2018-08-29 06:07:32 +03:00
. inhibit_fork_on_accept = false ,
. inhibit_pre_fork = false ,
. task_init = dcesrv_task_init ,
. post_fork = dcesrv_post_fork } ;
2018-08-23 00:35:52 +03:00
return register_server_service ( ctx , " rpc " , & details ) ;
2007-09-03 17:13:25 +04:00
}