2010-06-18 11:00:38 -04:00
/*
Unix SMB / Netbios implementation .
Generic infrstructure for RPC Daemons
Copyright ( C ) Simo Sorce 2010
2011-07-18 22:26:31 +10:00
Copyright ( C ) Andrew Bartlett 2011
2011-07-21 13:13:35 +02:00
Copyright ( C ) Andreas Schneider 2011
2010-06-18 11:00:38 -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"
2019-01-25 09:50:15 +01:00
# include "librpc/rpc/dcesrv_core.h"
2011-07-21 11:02:59 -04:00
# include "rpc_server/rpc_pipes.h"
2010-06-18 11:00:38 -04:00
# include "rpc_server/rpc_server.h"
2011-08-10 16:33:22 -04:00
# include "rpc_server/rpc_config.h"
2010-06-18 10:40:19 -04:00
# include "rpc_dce.h"
# include "librpc/gen_ndr/netlogon.h"
2011-02-09 14:22:16 +11:00
# include "librpc/gen_ndr/auth.h"
2010-06-18 10:55:44 -04:00
# include "lib/tsocket/tsocket.h"
2010-06-18 10:56:58 -04:00
# include "libcli/named_pipe_auth/npa_tstream.h"
2011-02-09 14:22:16 +11:00
# include "../auth/auth_sam_reply.h"
2011-03-24 12:08:15 +01:00
# include "auth.h"
2011-04-29 16:40:24 +02:00
# include "rpc_server/rpc_ncacn_np.h"
2011-04-29 23:32:28 +02:00
# include "rpc_server/srv_pipe_hnd.h"
2023-01-05 10:04:23 +01:00
# include "lib/util/idtree_random.h"
2010-06-18 10:40:19 -04:00
2019-02-05 19:27:58 +01:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_RPC_SRV
2010-06-18 10:55:44 -04:00
/* Start listening on the appropriate unix socket and setup all is needed to
* dispatch requests to the pipes rpc implementation */
2010-06-18 11:00:38 -04:00
2011-02-15 12:57:26 +01:00
struct dcerpc_ncacn_listen_state {
2010-06-18 11:00:38 -04:00
int fd ;
2011-02-14 10:29:14 +01:00
struct tevent_context * ev_ctx ;
struct messaging_context * msg_ctx ;
2019-02-27 17:52:21 +01:00
struct dcesrv_context * dce_ctx ;
struct dcesrv_endpoint * endpoint ;
2019-02-18 18:48:57 +01:00
dcerpc_ncacn_termination_fn termination_fn ;
void * termination_data ;
2010-06-18 11:00:38 -04:00
} ;
2019-02-27 21:03:30 +01:00
static void ncacn_terminate_connection ( struct dcerpc_ncacn_conn * conn ,
const char * reason ) ;
2021-01-29 18:16:08 +01:00
NTSTATUS dcesrv_auth_gensec_prepare (
TALLOC_CTX * mem_ctx ,
struct dcesrv_call_state * call ,
struct gensec_security * * out ,
void * private_data )
2019-01-25 09:50:15 +01:00
{
struct gensec_security * gensec = NULL ;
NTSTATUS status ;
if ( out = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
}
status = auth_generic_prepare ( mem_ctx ,
call - > conn - > remote_address ,
call - > conn - > local_address ,
" DCE/RPC " ,
& gensec ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " Failed to prepare gensec: %s \n " , nt_errstr ( status ) ) ;
return status ;
}
* out = gensec ;
return NT_STATUS_OK ;
}
2021-01-29 18:16:08 +01:00
void dcesrv_log_successful_authz (
struct dcesrv_call_state * call ,
void * private_data )
2019-01-25 09:50:15 +01:00
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
struct auth4_context * auth4_context = NULL ;
struct dcesrv_auth * auth = call - > auth_state ;
enum dcerpc_transport_t transport = dcerpc_binding_get_transport (
call - > conn - > endpoint - > ep_description ) ;
const char * auth_type = derpc_transport_string_by_transport ( transport ) ;
const char * transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE ;
NTSTATUS status ;
if ( frame = = NULL ) {
2023-08-07 16:48:06 +12:00
DBG_ERR ( " No memory \n " ) ;
2019-01-25 09:50:15 +01:00
return ;
}
if ( transport = = NCACN_NP ) {
transport_protection = AUTHZ_TRANSPORT_PROTECTION_SMB ;
}
become_root ( ) ;
status = make_auth4_context ( frame , & auth4_context ) ;
unbecome_root ( ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " Unable to make auth context for authz log. \n " ) ;
TALLOC_FREE ( frame ) ;
return ;
}
/*
* 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 ( auth4_context - > msg_ctx ,
auth4_context - > lp_ctx ,
call - > conn - > remote_address ,
call - > conn - > local_address ,
" DCE/RPC " ,
auth_type ,
transport_protection ,
2023-06-15 17:07:05 +12:00
auth - > session_info ,
NULL /* client_audit_info */ ,
NULL /* server_audit_info */ ) ;
2019-01-25 09:50:15 +01:00
auth - > auth_audited = true ;
TALLOC_FREE ( frame ) ;
}
2020-06-26 17:20:32 +02: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 ) {
DBG_ERR ( " Failed to remove assoc_group 0x%08x \n " ,
assoc_group - > id ) ;
}
return 0 ;
}
static NTSTATUS dcesrv_assoc_group_new ( struct dcesrv_call_state * call )
2019-10-04 14:05:53 +02:00
{
struct dcesrv_connection * conn = call - > conn ;
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 = NULL ;
2020-06-26 17:20:32 +02:00
int id ;
2019-10-04 14:05:53 +02:00
assoc_group = talloc_zero ( conn , struct dcesrv_assoc_group ) ;
if ( assoc_group = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2020-06-26 17:20:32 +02:00
id = idr_get_new_random ( dce_ctx - > assoc_groups_idr ,
assoc_group ,
2023-01-04 11:43:59 +01:00
1 ,
2020-06-26 17:20:32 +02:00
UINT16_MAX ) ;
if ( id = = - 1 ) {
TALLOC_FREE ( assoc_group ) ;
DBG_ERR ( " Out of association groups! \n " ) ;
return NT_STATUS_RPC_OUT_OF_RESOURCES ;
}
2019-10-04 14:05:53 +02:00
assoc_group - > transport = transport ;
2020-06-26 17:20:32 +02:00
assoc_group - > id = id ;
2019-10-04 14:05:53 +02:00
assoc_group - > dce_ctx = dce_ctx ;
call - > conn - > assoc_group = assoc_group ;
2020-06-26 17:20:32 +02:00
talloc_set_destructor ( assoc_group , dcesrv_assoc_group_destructor ) ;
2019-10-04 14:05:53 +02:00
return NT_STATUS_OK ;
}
2020-06-18 18:40:16 +02:00
static NTSTATUS dcesrv_assoc_group_reference ( struct dcesrv_call_state * call ,
uint32_t assoc_group_id )
{
struct dcesrv_connection * conn = call - > conn ;
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 = NULL ;
void * id_ptr = NULL ;
/* find an association group given a assoc_group_id */
id_ptr = idr_find ( conn - > dce_ctx - > assoc_groups_idr , assoc_group_id ) ;
if ( id_ptr = = NULL ) {
/*
* FIXME If the association group is not found it has
* been created in other process ( preforking daemons ) .
* Until this is properly fixed we just create a new
* association group in this process
*/
DBG_NOTICE ( " Failed to find assoc_group 0x%08x in this "
" server process, creating a new one \n " ,
assoc_group_id ) ;
2020-06-26 17:20:32 +02:00
return dcesrv_assoc_group_new ( call ) ;
2020-06-18 18:40:16 +02:00
}
assoc_group = talloc_get_type_abort ( id_ptr , struct dcesrv_assoc_group ) ;
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 16:48:06 +12:00
" is not available on transport %s \n " ,
2020-06-18 18:40:16 +02:00
assoc_group_id , at , ct ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
conn - > assoc_group = talloc_reference ( conn , assoc_group ) ;
return NT_STATUS_OK ;
}
2021-01-29 18:16:08 +01:00
NTSTATUS dcesrv_assoc_group_find (
struct dcesrv_call_state * call ,
void * private_data )
2019-01-25 09:50:15 +01:00
{
2019-10-04 14:05:53 +02:00
uint32_t assoc_group_id = call - > pkt . u . bind . assoc_group_id ;
2020-06-18 18:40:16 +02:00
if ( assoc_group_id ! = 0 ) {
return dcesrv_assoc_group_reference ( call , assoc_group_id ) ;
2019-10-04 14:05:53 +02:00
}
2020-06-18 18:40:16 +02:00
/* If not requested by client create a new association group */
2020-06-26 17:20:32 +02:00
return dcesrv_assoc_group_new ( call ) ;
2019-01-25 09:50:15 +01:00
}
2019-12-05 11:45:54 +01:00
void dcesrv_transport_terminate_connection ( struct dcesrv_connection * dce_conn ,
const char * reason )
{
struct dcerpc_ncacn_conn * ncacn_conn = talloc_get_type_abort (
dce_conn - > transport . private_data ,
struct dcerpc_ncacn_conn ) ;
ncacn_terminate_connection ( ncacn_conn , reason ) ;
}
2019-02-27 21:03:30 +01:00
static void ncacn_terminate_connection ( struct dcerpc_ncacn_conn * conn ,
const char * reason )
{
if ( reason = = NULL ) {
reason = " Unknown reason " ;
}
DBG_NOTICE ( " Terminating connection - '%s' \n " , reason ) ;
talloc_free ( conn ) ;
}
2019-02-27 21:36:22 +01:00
NTSTATUS dcesrv_endpoint_by_ncacn_np_name ( struct dcesrv_context * dce_ctx ,
const char * pipe_name ,
struct dcesrv_endpoint * * out )
{
struct dcesrv_endpoint * e = NULL ;
for ( e = dce_ctx - > endpoint_list ; e ; e = e - > next ) {
enum dcerpc_transport_t transport =
dcerpc_binding_get_transport ( e - > ep_description ) ;
const char * endpoint = NULL ;
if ( transport ! = NCACN_NP ) {
continue ;
}
endpoint = dcerpc_binding_get_string_option ( e - > ep_description ,
" endpoint " ) ;
if ( endpoint = = NULL ) {
continue ;
}
if ( strncmp ( endpoint , " \\ pipe \\ " , 6 ) = = 0 ) {
endpoint + = 6 ;
}
if ( strequal ( endpoint , pipe_name ) ) {
* out = e ;
return NT_STATUS_OK ;
}
}
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
2019-02-27 23:28:25 +01:00
struct pipes_struct * dcesrv_get_pipes_struct ( struct dcesrv_connection * conn )
{
struct dcerpc_ncacn_conn * ncacn_conn = talloc_get_type_abort (
conn - > transport . private_data ,
struct dcerpc_ncacn_conn ) ;
2021-10-06 12:20:17 +02:00
return & ncacn_conn - > p ;
2019-02-27 23:28:25 +01:00
}
2011-02-14 10:29:14 +01:00
/* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */