⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 srv_svcctl_nt.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  *  Unix SMB/CIFS implementation. *  RPC Pipe client / server routines * *  Copyright (C) Marcin Krzysztof Porwit           2005. *  *  Largely Rewritten (Again) by: *  Copyright (C) Gerald (Jerry) Carter             2005. *   *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 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, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "includes.h"#undef DBGC_CLASS#define DBGC_CLASS DBGC_RPC_SRVstruct service_control_op {	const char *name;	SERVICE_CONTROL_OPS *ops;};#define SVCCTL_NUM_INTERNAL_SERVICES	4/* handle external services */extern SERVICE_CONTROL_OPS rcinit_svc_ops;/* builtin services (see service_db.c and services/svc_*.c */extern SERVICE_CONTROL_OPS spoolss_svc_ops;extern SERVICE_CONTROL_OPS netlogon_svc_ops;extern SERVICE_CONTROL_OPS winreg_svc_ops;extern SERVICE_CONTROL_OPS wins_svc_ops;/* make sure this number patches the number of builtin   SERVICE_CONTROL_OPS structure listed above */#define SVCCTL_NUM_INTERNAL_SERVICES	4struct service_control_op *svcctl_ops;static struct generic_mapping scm_generic_map =	{ SC_MANAGER_READ_ACCESS, SC_MANAGER_WRITE_ACCESS, SC_MANAGER_EXECUTE_ACCESS, SC_MANAGER_ALL_ACCESS };static struct generic_mapping svc_generic_map =	{ SERVICE_READ_ACCESS, SERVICE_WRITE_ACCESS, SERVICE_EXECUTE_ACCESS, SERVICE_ALL_ACCESS };/****************************************************************************************************************************************/BOOL init_service_op_table( void ){	const char **service_list = lp_svcctl_list();	int num_services = SVCCTL_NUM_INTERNAL_SERVICES + str_list_count( service_list );	int i;		if ( !(svcctl_ops = TALLOC_ARRAY( NULL, struct service_control_op, num_services+1)) ) {		DEBUG(0,("init_service_op_table: talloc() failed!\n"));		return False;	}	/* services listed in smb.conf get the rc.init interface */		for ( i=0; service_list && service_list[i]; i++ ) {		svcctl_ops[i].name = talloc_strdup( svcctl_ops, service_list[i] );		svcctl_ops[i].ops  = &rcinit_svc_ops;	}		/* add builtin services */		svcctl_ops[i].name = talloc_strdup( svcctl_ops, "Spooler" );	svcctl_ops[i].ops  = &spoolss_svc_ops;	i++;		svcctl_ops[i].name = talloc_strdup( svcctl_ops, "NETLOGON" );	svcctl_ops[i].ops  = &netlogon_svc_ops;	i++;		svcctl_ops[i].name = talloc_strdup( svcctl_ops, "RemoteRegistry" );	svcctl_ops[i].ops  = &winreg_svc_ops;	i++;		svcctl_ops[i].name = talloc_strdup( svcctl_ops, "WINS" );	svcctl_ops[i].ops  = &wins_svc_ops;	i++;		/* NULL terminate the array */		svcctl_ops[i].name = NULL;	svcctl_ops[i].ops  = NULL;		return True;}/****************************************************************************************************************************************/static struct service_control_op* find_service_by_name( const char *name ){	int i;	for ( i=0; svcctl_ops[i].name; i++ ) {		if ( strequal( name, svcctl_ops[i].name ) )			return &svcctl_ops[i];	}	return NULL;}/****************************************************************************************************************************************/static NTSTATUS svcctl_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token,                                      uint32 access_desired, uint32 *access_granted ){	NTSTATUS result;	if ( geteuid() == sec_initial_uid() ) {		DEBUG(5,("svcctl_access_check: using root's token\n"));		token = get_root_nt_token();	}		se_access_check( sec_desc, token, access_desired, access_granted, &result );	return result;}/****************************************************************************************************************************************/static SEC_DESC* construct_scm_sd( TALLOC_CTX *ctx ){	SEC_ACE ace[2];		SEC_ACCESS mask;	size_t i = 0;	SEC_DESC *sd;	SEC_ACL *acl;	size_t sd_size;	/* basic access for Everyone */		init_sec_access(&mask, SC_MANAGER_READ_ACCESS );	init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);		/* Full Access 'BUILTIN\Administrators' */		init_sec_access(&mask,SC_MANAGER_ALL_ACCESS );	init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);			/* create the security descriptor */		if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )		return NULL;	if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) )		return NULL;	return sd;}/****************************************************************** free() function for REGISTRY_KEY *****************************************************************/ static void free_service_handle_info(void *ptr){	TALLOC_FREE( ptr );}/****************************************************************** Find a registry key handle and return a SERVICE_INFO *****************************************************************/static SERVICE_INFO *find_service_info_by_hnd(pipes_struct *p, POLICY_HND *hnd){	SERVICE_INFO *service_info = NULL;	if( !find_policy_by_hnd( p, hnd, (void **)(void *)&service_info) ) {		DEBUG(2,("find_service_info_by_hnd: handle not found"));		return NULL;	}	return service_info;}/****************************************************************** *****************************************************************/ static WERROR create_open_service_handle( pipes_struct *p, POLICY_HND *handle, uint32 type,                                          const char *service, uint32 access_granted ){	SERVICE_INFO *info = NULL;	WERROR result = WERR_OK;	struct service_control_op *s_op;		if ( !(info = TALLOC_ZERO_P( NULL, SERVICE_INFO )) )		return WERR_NOMEM;	/* the Service Manager has a NULL name */		info->type = SVC_HANDLE_IS_SCM;		switch ( type ) {	case SVC_HANDLE_IS_SCM:		info->type = SVC_HANDLE_IS_SCM;		break;	case SVC_HANDLE_IS_DBLOCK:		info->type = SVC_HANDLE_IS_DBLOCK;		break;			case SVC_HANDLE_IS_SERVICE:		info->type = SVC_HANDLE_IS_SERVICE;				/* lookup the SERVICE_CONTROL_OPS */		if ( !(s_op = find_service_by_name( service )) ) {			result = WERR_NO_SUCH_SERVICE;			goto done;		}				info->ops = s_op->ops;		if ( !(info->name  = talloc_strdup( info, s_op->name )) ) {			result = WERR_NOMEM;			goto done;		}		break;	default:		result = WERR_NO_SUCH_SERVICE;		goto done;	}	info->access_granted = access_granted;			/* store the SERVICE_INFO and create an open handle */		if ( !create_policy_hnd( p, handle, free_service_handle_info, info ) ) {		result = WERR_ACCESS_DENIED;		goto done;	}		done:	if ( !W_ERROR_IS_OK(result) )		free_service_handle_info( info );	return result;}/****************************************************************************************************************************************/WERROR _svcctl_open_scmanager(pipes_struct *p, SVCCTL_Q_OPEN_SCMANAGER *q_u, SVCCTL_R_OPEN_SCMANAGER *r_u){	SEC_DESC *sec_desc;	uint32 access_granted = 0;	NTSTATUS status;		/* perform access checks */		if ( !(sec_desc = construct_scm_sd( p->mem_ctx )) )		return WERR_NOMEM;			se_map_generic( &q_u->access, &scm_generic_map );	status = svcctl_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );	if ( !NT_STATUS_IS_OK(status) )		return ntstatus_to_werror( status );			return create_open_service_handle( p, &r_u->handle, SVC_HANDLE_IS_SCM, NULL, access_granted );}/****************************************************************************************************************************************/WERROR _svcctl_open_service(pipes_struct *p, SVCCTL_Q_OPEN_SERVICE *q_u, SVCCTL_R_OPEN_SERVICE *r_u){	SEC_DESC *sec_desc;	uint32 access_granted = 0;	NTSTATUS status;	pstring service;	rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0);	  	DEBUG(5, ("_svcctl_open_service: Attempting to open Service [%s], \n", service));		/* based on my tests you can open a service if you have a valid scm handle */		if ( !find_service_info_by_hnd( p, &q_u->handle ) )		return WERR_BADFID;				/* perform access checks.  Use the root token in order to ensure that we 	   retreive the security descriptor */		if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, service, get_root_nt_token() )) )		return WERR_NOMEM;			se_map_generic( &q_u->access, &svc_generic_map );	status = svcctl_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );	if ( !NT_STATUS_IS_OK(status) )		return ntstatus_to_werror( status );		return create_open_service_handle( p, &r_u->handle, SVC_HANDLE_IS_SERVICE, service, access_granted );}/****************************************************************************************************************************************/WERROR _svcctl_close_service(pipes_struct *p, SVCCTL_Q_CLOSE_SERVICE *q_u, SVCCTL_R_CLOSE_SERVICE *r_u){	return close_policy_hnd( p, &q_u->handle ) ? WERR_OK : WERR_BADFID;}/****************************************************************************************************************************************/WERROR _svcctl_get_display_name(pipes_struct *p, SVCCTL_Q_GET_DISPLAY_NAME *q_u, SVCCTL_R_GET_DISPLAY_NAME *r_u){	fstring service;	const char *display_name;	SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );		/* can only use an SCM handle here */		if ( !info || (info->type != SVC_HANDLE_IS_SCM) )		return WERR_BADFID;			rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0);		display_name = svcctl_lookup_dispname( service, p->pipe_user.nt_user_token );	init_svcctl_r_get_display_name( r_u, display_name );	return WERR_OK;}/****************************************************************************************************************************************/WERROR _svcctl_query_status(pipes_struct *p, SVCCTL_Q_QUERY_STATUS *q_u, SVCCTL_R_QUERY_STATUS *r_u){	SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );		/* perform access checks */	if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )		return WERR_BADFID;			if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )		return WERR_ACCESS_DENIED;			/* try the service specific status call */	return info->ops->service_status( info->name, &r_u->svc_status );}/****************************************************************************************************************************************/static int enumerate_status( TALLOC_CTX *ctx, ENUM_SERVICES_STATUS **status, NT_USER_TOKEN *token ){	int num_services = 0;	int i;	ENUM_SERVICES_STATUS *st;	const char *display_name;		/* just count */	while ( svcctl_ops[num_services].name )		num_services++;	if ( !(st = TALLOC_ARRAY( ctx, ENUM_SERVICES_STATUS, num_services )) ) {		DEBUG(0,("enumerate_status: talloc() failed!\n"));		return -1;	}		for ( i=0; i<num_services; i++ ) {		init_unistr( &st[i].servicename, svcctl_ops[i].name );				display_name = svcctl_lookup_dispname( svcctl_ops[i].name, token );		init_unistr( &st[i].displayname, display_name );				svcctl_ops[i].ops->service_status( svcctl_ops[i].name, &st[i].status );	}		*status = st;	return num_services;}/****************************************************************************************************************************************/WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STATUS *q_u, SVCCTL_R_ENUM_SERVICES_STATUS *r_u){	ENUM_SERVICES_STATUS *services = NULL;	uint32 num_services;	int i = 0;	size_t buffer_size = 0;	WERROR result = WERR_OK;	SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );	NT_USER_TOKEN *token = p->pipe_user.nt_user_token;		/* perform access checks */	if ( !info || (info->type != SVC_HANDLE_IS_SCM) )		return WERR_BADFID;			if ( !(info->access_granted & SC_RIGHT_MGR_ENUMERATE_SERVICE) )		return WERR_ACCESS_DENIED;	if ( (num_services = enumerate_status( p->mem_ctx, &services, token )) == -1 )		return WERR_NOMEM;        for ( i=0; i<num_services; i++ ) {		buffer_size += svcctl_sizeof_enum_services_status(&services[i]);	}	buffer_size += buffer_size % 4;	if (buffer_size > q_u->buffer_size ) {		num_services = 0;		result = WERR_MORE_DATA;	}	rpcbuf_init(&r_u->buffer, q_u->buffer_size, p->mem_ctx);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -