2008-02-18 11:48:51 +01:00
/*
2005-03-23 23:26:33 +00:00
* Unix SMB / CIFS implementation .
* RPC Pipe client / server routines
2005-09-30 17:13:37 +00:00
*
2005-06-14 15:40:51 +00:00
* Copyright ( C ) Marcin Krzysztof Porwit 2005.
2008-02-18 11:48:51 +01:00
*
2005-09-30 17:13:37 +00:00
* Largely Rewritten ( Again ) by :
* Copyright ( C ) Gerald ( Jerry ) Carter 2005.
2009-01-08 13:06:38 +01:00
* Copyright ( C ) Guenther Deschner 2008 , 2009.
2008-02-18 11:48:51 +01:00
*
2005-03-23 23:26:33 +00: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-09 19:25:36 +00:00
* the Free Software Foundation ; either version 3 of the License , or
2005-03-23 23:26:33 +00:00
* ( at your option ) any later version .
2008-02-18 11:48:51 +01:00
*
2005-03-23 23:26:33 +00:00
* 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 .
2008-02-18 11:48:51 +01:00
*
2005-03-23 23:26:33 +00:00
* You should have received a copy of the GNU General Public License
2007-07-10 05:23:25 +00:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2005-03-23 23:26:33 +00:00
*/
# include "includes.h"
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_RPC_SRV
2005-09-30 17:13:37 +00:00
struct service_control_op {
2005-06-15 00:54:43 +00:00
const char * name ;
SERVICE_CONTROL_OPS * ops ;
2005-06-14 03:17:31 +00:00
} ;
2005-10-06 17:48:03 +00:00
# define SVCCTL_NUM_INTERNAL_SERVICES 4
/* handle external services */
2005-09-30 17:13:37 +00:00
extern SERVICE_CONTROL_OPS rcinit_svc_ops ;
2005-10-06 17:48:03 +00:00
/* builtin services (see service_db.c and services/svc_*.c */
extern SERVICE_CONTROL_OPS spoolss_svc_ops ;
2005-09-30 17:13:37 +00:00
extern SERVICE_CONTROL_OPS netlogon_svc_ops ;
extern SERVICE_CONTROL_OPS winreg_svc_ops ;
2005-10-06 17:48:03 +00:00
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 4
2005-03-23 23:26:33 +00:00
2005-09-30 17:13:37 +00:00
struct service_control_op * svcctl_ops ;
2007-10-05 21:41:17 +00:00
static const struct generic_mapping scm_generic_map =
2005-09-30 17:13:37 +00:00
{ SC_MANAGER_READ_ACCESS , SC_MANAGER_WRITE_ACCESS , SC_MANAGER_EXECUTE_ACCESS , SC_MANAGER_ALL_ACCESS } ;
2007-10-05 21:41:17 +00:00
static const struct generic_mapping svc_generic_map =
2005-09-30 17:13:37 +00:00
{ SERVICE_READ_ACCESS , SERVICE_WRITE_ACCESS , SERVICE_EXECUTE_ACCESS , SERVICE_ALL_ACCESS } ;
2005-06-14 20:11:59 +00:00
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-18 17:40:25 -07:00
bool init_service_op_table ( void )
2005-09-30 17:13:37 +00:00
{
const char * * service_list = lp_svcctl_list ( ) ;
2008-10-12 00:56:56 +02:00
int num_services = SVCCTL_NUM_INTERNAL_SERVICES + str_list_length ( service_list ) ;
2005-09-30 17:13:37 +00:00
int i ;
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
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 */
2008-02-18 11:48:51 +01:00
2006-02-08 15:09:09 +00:00
for ( i = 0 ; service_list & & service_list [ i ] ; i + + ) {
2005-09-30 17:13:37 +00:00
svcctl_ops [ i ] . name = talloc_strdup ( svcctl_ops , service_list [ i ] ) ;
svcctl_ops [ i ] . ops = & rcinit_svc_ops ;
}
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
/* add builtin services */
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
svcctl_ops [ i ] . name = talloc_strdup ( svcctl_ops , " Spooler " ) ;
svcctl_ops [ i ] . ops = & spoolss_svc_ops ;
i + + ;
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
svcctl_ops [ i ] . name = talloc_strdup ( svcctl_ops , " NETLOGON " ) ;
svcctl_ops [ i ] . ops = & netlogon_svc_ops ;
i + + ;
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
svcctl_ops [ i ] . name = talloc_strdup ( svcctl_ops , " RemoteRegistry " ) ;
svcctl_ops [ i ] . ops = & winreg_svc_ops ;
i + + ;
2008-02-18 11:48:51 +01:00
2005-10-06 17:48:03 +00:00
svcctl_ops [ i ] . name = talloc_strdup ( svcctl_ops , " WINS " ) ;
svcctl_ops [ i ] . ops = & wins_svc_ops ;
i + + ;
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
/* NULL terminate the array */
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
svcctl_ops [ i ] . name = NULL ;
svcctl_ops [ i ] . ops = NULL ;
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
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 ;
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-02-18 11:48:51 +01:00
static NTSTATUS svcctl_access_check ( SEC_DESC * sec_desc , NT_USER_TOKEN * token ,
2005-06-14 20:11:59 +00:00
uint32 access_desired , uint32 * access_granted )
{
2005-09-16 14:47:21 +00:00
if ( geteuid ( ) = = sec_initial_uid ( ) ) {
2005-09-30 17:13:37 +00:00
DEBUG ( 5 , ( " svcctl_access_check: using root's token \n " ) ) ;
token = get_root_nt_token ( ) ;
2005-09-16 14:47:21 +00:00
}
2008-02-18 11:48:51 +01:00
2008-10-31 10:51:45 -07:00
return se_access_check ( sec_desc , token , access_desired , access_granted ) ;
2005-06-14 20:11:59 +00:00
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static SEC_DESC * construct_scm_sd ( TALLOC_CTX * ctx )
{
2008-02-18 11:48:51 +01:00
SEC_ACE ace [ 2 ] ;
2005-06-14 20:11:59 +00:00
size_t i = 0 ;
SEC_DESC * sd ;
2009-02-23 15:44:34 -08:00
SEC_ACL * theacl ;
2005-09-30 17:13:37 +00:00
size_t sd_size ;
2005-06-14 20:11:59 +00:00
/* basic access for Everyone */
2008-02-18 11:48:51 +01:00
2008-10-09 09:49:03 -07:00
init_sec_ace ( & ace [ i + + ] , & global_sid_World ,
SEC_ACE_TYPE_ACCESS_ALLOWED , SC_MANAGER_READ_ACCESS , 0 ) ;
2008-02-18 11:48:51 +01:00
2005-06-14 20:11:59 +00:00
/* Full Access 'BUILTIN\Administrators' */
2008-02-18 11:48:51 +01:00
2008-10-09 09:49:03 -07:00
init_sec_ace ( & ace [ i + + ] , & global_sid_Builtin_Administrators ,
SEC_ACE_TYPE_ACCESS_ALLOWED , SC_MANAGER_ALL_ACCESS , 0 ) ;
2008-02-18 11:48:51 +01:00
2005-06-14 20:11:59 +00:00
/* create the security descriptor */
2008-02-18 11:48:51 +01:00
2009-02-23 15:44:34 -08:00
if ( ! ( theacl = make_sec_acl ( ctx , NT4_ACL_REVISION , i , ace ) ) )
2005-06-14 20:11:59 +00:00
return NULL ;
2007-12-20 22:27:01 +01:00
if ( ! ( sd = make_sec_desc ( ctx , SECURITY_DESCRIPTOR_REVISION_1 ,
SEC_DESC_SELF_RELATIVE , NULL , NULL , NULL ,
2009-02-23 15:44:34 -08:00
theacl , & sd_size ) ) )
2005-06-14 20:11:59 +00:00
return NULL ;
return sd ;
}
/******************************************************************
Find a registry key handle and return a SERVICE_INFO
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-18 22:49:41 +01:00
static SERVICE_INFO * find_service_info_by_hnd ( pipes_struct * p , struct policy_handle * hnd )
2005-06-14 20:11:59 +00:00
{
SERVICE_INFO * service_info = NULL ;
2005-12-03 06:46:46 +00:00
if ( ! find_policy_by_hnd ( p , hnd , ( void * * ) ( void * ) & service_info ) ) {
2008-03-06 23:23:08 +01:00
DEBUG ( 2 , ( " find_service_info_by_hnd: handle not found \n " ) ) ;
2005-06-14 20:11:59 +00:00
return NULL ;
2005-06-14 03:17:31 +00:00
}
2005-06-14 20:11:59 +00:00
return service_info ;
}
2005-06-14 03:17:31 +00:00
2005-06-14 20:11:59 +00:00
/******************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-02-18 11:48:51 +01:00
2009-03-18 22:49:41 +01:00
static WERROR create_open_service_handle ( pipes_struct * p , struct policy_handle * handle , uint32 type ,
2005-06-14 20:11:59 +00:00
const char * service , uint32 access_granted )
{
SERVICE_INFO * info = NULL ;
2005-06-15 16:32:12 +00:00
WERROR result = WERR_OK ;
2005-09-30 17:13:37 +00:00
struct service_control_op * s_op ;
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
if ( ! ( info = TALLOC_ZERO_P ( NULL , SERVICE_INFO ) ) )
2005-06-14 20:11:59 +00:00
return WERR_NOMEM ;
2005-06-14 03:17:31 +00:00
2005-06-14 20:11:59 +00:00
/* the Service Manager has a NULL name */
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
info - > type = SVC_HANDLE_IS_SCM ;
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
switch ( type ) {
case SVC_HANDLE_IS_SCM :
2005-06-14 20:11:59 +00:00
info - > type = SVC_HANDLE_IS_SCM ;
2005-09-30 17:13:37 +00:00
break ;
2005-06-15 00:54:43 +00:00
2005-09-30 17:13:37 +00:00
case SVC_HANDLE_IS_DBLOCK :
info - > type = SVC_HANDLE_IS_DBLOCK ;
break ;
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
case SVC_HANDLE_IS_SERVICE :
2005-06-14 20:11:59 +00:00
info - > type = SVC_HANDLE_IS_SERVICE ;
2008-02-18 11:48:51 +01:00
2005-06-14 20:11:59 +00:00
/* lookup the SERVICE_CONTROL_OPS */
2005-06-14 03:17:31 +00:00
2005-09-30 17:13:37 +00:00
if ( ! ( s_op = find_service_by_name ( service ) ) ) {
2005-06-15 16:32:12 +00:00
result = WERR_NO_SUCH_SERVICE ;
goto done ;
}
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
info - > ops = s_op - > ops ;
2005-06-15 16:32:12 +00:00
2005-09-30 17:13:37 +00:00
if ( ! ( info - > name = talloc_strdup ( info , s_op - > name ) ) ) {
2005-06-15 16:32:12 +00:00
result = WERR_NOMEM ;
goto done ;
2005-06-14 03:17:31 +00:00
}
2005-09-30 17:13:37 +00:00
break ;
default :
result = WERR_NO_SUCH_SERVICE ;
goto done ;
2005-06-14 20:11:59 +00:00
}
2005-06-14 03:17:31 +00:00
2008-02-18 11:48:51 +01:00
info - > access_granted = access_granted ;
2005-06-14 20:11:59 +00:00
/* store the SERVICE_INFO and create an open handle */
2008-02-18 11:48:51 +01:00
2009-01-07 18:44:52 +01:00
if ( ! create_policy_hnd ( p , handle , info ) ) {
2005-06-15 16:32:12 +00:00
result = WERR_ACCESS_DENIED ;
goto done ;
2005-06-14 20:11:59 +00:00
}
2008-02-18 11:48:51 +01:00
2005-06-15 16:32:12 +00:00
done :
if ( ! W_ERROR_IS_OK ( result ) )
2009-01-07 18:44:52 +01:00
TALLOC_FREE ( info ) ;
2005-06-15 16:32:12 +00:00
return result ;
2005-06-14 20:11:59 +00:00
}
2005-06-14 03:17:31 +00:00
2005-06-14 20:11:59 +00:00
/********************************************************************
2009-01-08 13:06:38 +01:00
_svcctl_OpenSCManagerW
2005-06-14 20:11:59 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-06-14 03:17:31 +00:00
2008-02-18 11:55:31 +01:00
WERROR _svcctl_OpenSCManagerW ( pipes_struct * p ,
struct svcctl_OpenSCManagerW * r )
2005-06-14 20:11:59 +00:00
{
SEC_DESC * sec_desc ;
uint32 access_granted = 0 ;
NTSTATUS status ;
2008-02-18 11:48:51 +01:00
2005-06-14 20:11:59 +00:00
/* perform access checks */
2008-02-18 11:48:51 +01:00
2005-06-14 20:11:59 +00:00
if ( ! ( sec_desc = construct_scm_sd ( p - > mem_ctx ) ) )
return WERR_NOMEM ;
2008-02-18 11:48:51 +01:00
2008-02-18 11:55:31 +01:00
se_map_generic ( & r - > in . access_mask , & scm_generic_map ) ;
2008-11-23 23:48:17 +01:00
status = svcctl_access_check ( sec_desc , p - > server_info - > ptok ,
r - > in . access_mask , & access_granted ) ;
2005-06-14 20:11:59 +00:00
if ( ! NT_STATUS_IS_OK ( status ) )
return ntstatus_to_werror ( status ) ;
2008-02-18 11:48:51 +01:00
2008-02-18 11:55:31 +01:00
return create_open_service_handle ( p , r - > out . handle , SVC_HANDLE_IS_SCM , NULL , access_granted ) ;
2005-06-14 20:11:59 +00:00
}
2005-06-14 03:17:31 +00:00
2005-06-14 20:11:59 +00:00
/********************************************************************
2008-02-18 12:55:35 +01:00
_svcctl_OpenServiceW
2005-06-14 20:11:59 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-06-14 03:17:31 +00:00
2008-02-18 12:55:35 +01:00
WERROR _svcctl_OpenServiceW ( pipes_struct * p ,
struct svcctl_OpenServiceW * r )
2005-06-14 20:11:59 +00:00
{
SEC_DESC * sec_desc ;
uint32 access_granted = 0 ;
NTSTATUS status ;
2008-02-18 12:55:35 +01:00
const char * service = NULL ;
service = r - > in . ServiceName ;
if ( ! service ) {
2007-11-27 11:22:58 -08:00
return WERR_NOMEM ;
}
2008-02-18 12:55:35 +01:00
DEBUG ( 5 , ( " _svcctl_OpenServiceW: Attempting to open Service [%s], \n " , service ) ) ;
2005-06-14 03:17:31 +00:00
2005-06-14 20:11:59 +00:00
/* based on my tests you can open a service if you have a valid scm handle */
2007-11-27 11:22:58 -08:00
2008-02-18 12:55:35 +01:00
if ( ! find_service_info_by_hnd ( p , r - > in . scmanager_handle ) )
2005-06-14 20:11:59 +00:00
return WERR_BADFID ;
2007-11-27 11:22:58 -08:00
2008-02-18 11:48:51 +01:00
/* perform access checks. Use the root token in order to ensure that we
2006-11-18 17:07:15 +00:00
retrieve the security descriptor */
2007-11-27 11:22:58 -08:00
2005-09-30 17:13:37 +00:00
if ( ! ( sec_desc = svcctl_get_secdesc ( p - > mem_ctx , service , get_root_nt_token ( ) ) ) )
2005-06-14 20:11:59 +00:00
return WERR_NOMEM ;
2007-11-27 11:22:58 -08:00
2008-02-18 12:55:35 +01:00
se_map_generic ( & r - > in . access_mask , & svc_generic_map ) ;
2008-11-23 23:48:17 +01:00
status = svcctl_access_check ( sec_desc , p - > server_info - > ptok ,
r - > in . access_mask , & access_granted ) ;
2005-06-14 20:11:59 +00:00
if ( ! NT_STATUS_IS_OK ( status ) )
return ntstatus_to_werror ( status ) ;
2007-11-27 11:22:58 -08:00
2008-02-18 12:55:35 +01:00
return create_open_service_handle ( p , r - > out . handle , SVC_HANDLE_IS_SERVICE , service , access_granted ) ;
2005-06-14 20:11:59 +00:00
}
2005-06-14 03:17:31 +00:00
2005-06-14 20:11:59 +00:00
/********************************************************************
2009-01-08 13:06:38 +01:00
_svcctl_CloseServiceHandle
2005-06-14 20:11:59 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-06-14 03:17:31 +00:00
2009-01-08 13:06:38 +01:00
WERROR _svcctl_CloseServiceHandle ( pipes_struct * p ,
struct svcctl_CloseServiceHandle * r )
2005-06-14 20:11:59 +00:00
{
2007-05-31 17:24:30 +00:00
if ( ! close_policy_hnd ( p , r - > in . handle ) )
return WERR_BADFID ;
2008-03-27 22:55:20 +01:00
ZERO_STRUCTP ( r - > out . handle ) ;
2008-02-18 11:48:51 +01:00
return WERR_OK ;
2005-06-14 03:17:31 +00:00
}
2005-06-14 20:11:59 +00:00
/********************************************************************
2008-02-18 13:43:12 +01:00
_svcctl_GetServiceDisplayNameW
2005-06-14 20:11:59 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-02-18 13:43:12 +01:00
WERROR _svcctl_GetServiceDisplayNameW ( pipes_struct * p ,
struct svcctl_GetServiceDisplayNameW * r )
2005-06-14 03:17:31 +00:00
{
2008-02-18 13:43:12 +01:00
const char * service ;
2005-09-30 17:13:37 +00:00
const char * display_name ;
2008-02-18 13:43:12 +01:00
SERVICE_INFO * info = find_service_info_by_hnd ( p , r - > in . handle ) ;
2008-02-18 11:48:51 +01:00
2005-06-14 20:11:59 +00:00
/* can only use an SCM handle here */
2008-02-18 11:48:51 +01:00
2005-06-14 20:11:59 +00:00
if ( ! info | | ( info - > type ! = SVC_HANDLE_IS_SCM ) )
return WERR_BADFID ;
2008-02-18 11:48:51 +01:00
2008-02-18 13:43:12 +01:00
service = r - > in . service_name ;
2008-02-18 11:48:51 +01:00
2008-11-23 23:48:17 +01:00
display_name = svcctl_lookup_dispname ( p - > mem_ctx , service ,
p - > server_info - > ptok ) ;
2008-02-18 13:43:12 +01:00
if ( ! display_name ) {
display_name = " " ;
}
* r - > out . display_name = display_name ;
* r - > out . display_name_length = strlen ( display_name ) ;
2005-06-14 03:17:31 +00:00
2005-06-14 20:11:59 +00:00
return WERR_OK ;
2005-06-14 03:17:31 +00:00
}
2005-06-14 20:11:59 +00:00
/********************************************************************
2008-02-19 02:41:05 +01:00
_svcctl_QueryServiceStatus
2005-06-14 20:11:59 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-06-14 03:17:31 +00:00
2008-02-19 02:41:05 +01:00
WERROR _svcctl_QueryServiceStatus ( pipes_struct * p ,
struct svcctl_QueryServiceStatus * r )
2005-06-14 03:17:31 +00:00
{
2008-02-19 02:41:05 +01:00
SERVICE_INFO * info = find_service_info_by_hnd ( p , r - > in . handle ) ;
2008-02-18 11:48:51 +01:00
2005-06-14 20:11:59 +00:00
/* perform access checks */
if ( ! info | | ( info - > type ! = SVC_HANDLE_IS_SERVICE ) )
return WERR_BADFID ;
2008-02-18 11:48:51 +01:00
2005-06-14 20:11:59 +00:00
if ( ! ( info - > access_granted & SC_RIGHT_SVC_QUERY_STATUS ) )
return WERR_ACCESS_DENIED ;
2008-02-18 11:48:51 +01:00
2005-06-15 15:18:18 +00:00
/* try the service specific status call */
2008-02-19 02:41:05 +01:00
return info - > ops - > service_status ( info - > name , r - > out . service_status ) ;
2005-06-14 03:17:31 +00:00
}
2005-09-30 17:13:37 +00:00
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-06-14 03:17:31 +00:00
2009-01-09 16:19:37 +01:00
static int enumerate_status ( TALLOC_CTX * ctx , struct ENUM_SERVICE_STATUSW * * status , NT_USER_TOKEN * token )
2005-06-14 03:17:31 +00:00
{
2005-09-30 17:13:37 +00:00
int num_services = 0 ;
int i ;
2009-01-09 16:19:37 +01:00
struct ENUM_SERVICE_STATUSW * st ;
2005-09-30 17:13:37 +00:00
const char * display_name ;
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
/* just count */
while ( svcctl_ops [ num_services ] . name )
num_services + + ;
2009-01-09 16:19:37 +01:00
if ( ! ( st = TALLOC_ARRAY ( ctx , struct ENUM_SERVICE_STATUSW , num_services ) ) ) {
2005-09-30 17:13:37 +00:00
DEBUG ( 0 , ( " enumerate_status: talloc() failed! \n " ) ) ;
return - 1 ;
2005-06-14 03:17:31 +00:00
}
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
for ( i = 0 ; i < num_services ; i + + ) {
2009-01-09 16:19:37 +01:00
st [ i ] . service_name = talloc_strdup ( st , svcctl_ops [ i ] . name ) ;
2008-02-18 11:48:51 +01:00
2007-12-17 18:00:43 -08:00
display_name = svcctl_lookup_dispname ( ctx , svcctl_ops [ i ] . name , token ) ;
2009-01-09 16:19:37 +01:00
st [ i ] . display_name = talloc_strdup ( st , display_name ? display_name : " " ) ;
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
svcctl_ops [ i ] . ops - > service_status ( svcctl_ops [ i ] . name , & st [ i ] . status ) ;
}
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
* status = st ;
2005-06-14 03:17:31 +00:00
2005-09-30 17:13:37 +00:00
return num_services ;
2005-06-14 03:17:31 +00:00
}
/********************************************************************
2009-01-09 16:19:37 +01:00
_svcctl_EnumServicesStatusW
2005-06-14 03:17:31 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-01-09 16:19:37 +01:00
WERROR _svcctl_EnumServicesStatusW ( pipes_struct * p ,
struct svcctl_EnumServicesStatusW * r )
2005-06-14 03:17:31 +00:00
{
2009-01-09 16:19:37 +01:00
struct ENUM_SERVICE_STATUSW * services = NULL ;
2006-03-14 20:32:27 +00:00
int num_services ;
2005-06-14 03:17:31 +00:00
int i = 0 ;
2005-08-02 20:33:50 +00:00
size_t buffer_size = 0 ;
2005-06-14 03:17:31 +00:00
WERROR result = WERR_OK ;
2009-01-09 16:19:37 +01:00
SERVICE_INFO * info = find_service_info_by_hnd ( p , r - > in . handle ) ;
2008-11-23 23:48:17 +01:00
NT_USER_TOKEN * token = p - > server_info - > ptok ;
2009-01-09 16:19:37 +01:00
DATA_BLOB blob = data_blob_null ;
2008-02-18 11:48:51 +01:00
2005-06-14 20:11:59 +00:00
/* perform access checks */
if ( ! info | | ( info - > type ! = SVC_HANDLE_IS_SCM ) )
return WERR_BADFID ;
2008-02-18 11:48:51 +01:00
2006-03-13 18:59:31 +00:00
if ( ! ( info - > access_granted & SC_RIGHT_MGR_ENUMERATE_SERVICE ) ) {
2005-06-14 20:11:59 +00:00
return WERR_ACCESS_DENIED ;
2006-03-13 18:59:31 +00:00
}
2005-06-14 03:17:31 +00:00
2006-03-13 18:59:31 +00:00
num_services = enumerate_status ( p - > mem_ctx , & services , token ) ;
2006-03-14 20:32:27 +00:00
if ( num_services = = - 1 ) {
2005-08-02 20:33:50 +00:00
return WERR_NOMEM ;
2006-03-13 18:59:31 +00:00
}
2005-06-14 03:17:31 +00:00
2005-09-30 17:13:37 +00:00
for ( i = 0 ; i < num_services ; i + + ) {
2009-01-09 16:19:37 +01:00
buffer_size + = ndr_size_ENUM_SERVICE_STATUSW ( & services [ i ] , NULL , 0 ) ;
2005-06-14 03:17:31 +00:00
}
2005-03-23 23:26:33 +00:00
buffer_size + = buffer_size % 4 ;
2005-06-14 03:17:31 +00:00
2009-01-09 16:19:37 +01:00
if ( buffer_size > r - > in . buf_size ) {
2005-09-30 17:13:37 +00:00
num_services = 0 ;
2005-03-23 23:26:33 +00:00
result = WERR_MORE_DATA ;
}
if ( W_ERROR_IS_OK ( result ) ) {
2005-06-14 03:17:31 +00:00
2009-01-09 16:19:37 +01:00
enum ndr_err_code ndr_err ;
struct ndr_push * ndr ;
2005-03-23 23:26:33 +00:00
2009-01-09 16:19:37 +01:00
ndr = ndr_push_init_ctx ( p - > mem_ctx , NULL ) ;
if ( ndr = = NULL ) {
return WERR_INVALID_PARAM ;
}
2005-03-23 23:26:33 +00:00
2009-01-09 16:19:37 +01:00
ndr_err = ndr_push_ENUM_SERVICE_STATUSW_array (
ndr , num_services , services ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
return ntstatus_to_werror ( ndr_map_error2ntstatus ( ndr_err ) ) ;
}
blob = ndr_push_blob ( ndr ) ;
}
r - > out . service = blob . data ;
* r - > out . bytes_needed = ( buffer_size > r - > in . buf_size ) ? buffer_size : r - > in . buf_size ;
* r - > out . services_returned = ( uint32 ) num_services ;
* r - > out . resume_handle = 0x0 ;
2005-03-23 23:26:33 +00:00
return result ;
}
/********************************************************************
2008-02-19 02:28:46 +01:00
_svcctl_StartServiceW
2005-03-23 23:26:33 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-02-19 02:28:46 +01:00
WERROR _svcctl_StartServiceW ( pipes_struct * p ,
struct svcctl_StartServiceW * r )
2005-03-23 23:26:33 +00:00
{
2008-02-19 02:28:46 +01:00
SERVICE_INFO * info = find_service_info_by_hnd ( p , r - > in . handle ) ;
2008-02-18 11:48:51 +01:00
2005-06-14 20:11:59 +00:00
/* perform access checks */
if ( ! info | | ( info - > type ! = SVC_HANDLE_IS_SERVICE ) )
return WERR_BADFID ;
2008-02-18 11:48:51 +01:00
2005-06-14 20:11:59 +00:00
if ( ! ( info - > access_granted & SC_RIGHT_SVC_START ) )
return WERR_ACCESS_DENIED ;
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
return info - > ops - > start_service ( info - > name ) ;
2005-03-23 23:26:33 +00:00
}
/********************************************************************
2008-02-19 02:35:03 +01:00
_svcctl_ControlService
2005-03-23 23:26:33 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-02-19 02:35:03 +01:00
WERROR _svcctl_ControlService ( pipes_struct * p ,
struct svcctl_ControlService * r )
2005-03-23 23:26:33 +00:00
{
2008-02-19 02:35:03 +01:00
SERVICE_INFO * info = find_service_info_by_hnd ( p , r - > in . handle ) ;
2008-02-18 11:48:51 +01:00
2005-06-14 20:11:59 +00:00
/* perform access checks */
2008-02-18 11:48:51 +01:00
2005-06-14 20:11:59 +00:00
if ( ! info | | ( info - > type ! = SVC_HANDLE_IS_SERVICE ) )
2008-02-18 11:48:51 +01:00
return WERR_BADFID ;
2008-02-19 02:35:03 +01:00
switch ( r - > in . control ) {
2005-09-30 17:13:37 +00:00
case SVCCTL_CONTROL_STOP :
if ( ! ( info - > access_granted & SC_RIGHT_SVC_STOP ) )
return WERR_ACCESS_DENIED ;
2008-02-18 11:48:51 +01:00
2008-02-19 02:35:03 +01:00
return info - > ops - > stop_service ( info - > name ,
r - > out . service_status ) ;
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
case SVCCTL_CONTROL_INTERROGATE :
if ( ! ( info - > access_granted & SC_RIGHT_SVC_QUERY_STATUS ) )
return WERR_ACCESS_DENIED ;
2008-02-18 11:48:51 +01:00
2008-02-19 02:35:03 +01:00
return info - > ops - > service_status ( info - > name ,
r - > out . service_status ) ;
2008-11-17 10:21:29 -08:00
default :
return WERR_ACCESS_DENIED ;
2005-09-30 17:13:37 +00:00
}
2005-03-23 23:26:33 +00:00
}
/********************************************************************
2008-03-20 01:38:23 +01:00
_svcctl_EnumDependentServicesW
2005-03-23 23:26:33 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-03-20 01:38:23 +01:00
WERROR _svcctl_EnumDependentServicesW ( pipes_struct * p ,
struct svcctl_EnumDependentServicesW * r )
2005-03-23 23:26:33 +00:00
{
2008-03-20 01:38:23 +01:00
SERVICE_INFO * info = find_service_info_by_hnd ( p , r - > in . service ) ;
2008-02-18 11:48:51 +01:00
2005-06-14 20:11:59 +00:00
/* perform access checks */
if ( ! info | | ( info - > type ! = SVC_HANDLE_IS_SERVICE ) )
2008-02-18 11:48:51 +01:00
return WERR_BADFID ;
2005-06-14 20:11:59 +00:00
if ( ! ( info - > access_granted & SC_RIGHT_SVC_ENUMERATE_DEPENDENTS ) )
return WERR_ACCESS_DENIED ;
2008-02-18 11:48:51 +01:00
/* we have to set the outgoing buffer size to the same as the
2005-03-23 23:26:33 +00:00
incoming buffer size ( even in the case of failure */
2008-03-20 01:38:23 +01:00
/* this is done in the autogenerated server already - gd */
2005-03-23 23:26:33 +00:00
2008-03-20 01:38:23 +01:00
* r - > out . bytes_needed = r - > in . buf_size ;
2008-02-18 11:48:51 +01:00
2005-03-23 23:26:33 +00:00
/* no dependent services...basically a stub function */
2008-03-20 01:38:23 +01:00
* r - > out . services_returned = 0 ;
2005-03-23 23:26:33 +00:00
return WERR_OK ;
}
/********************************************************************
2009-01-06 18:59:44 +01:00
_svcctl_QueryServiceStatusEx
2005-03-23 23:26:33 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-01-06 18:59:44 +01:00
WERROR _svcctl_QueryServiceStatusEx ( pipes_struct * p ,
struct svcctl_QueryServiceStatusEx * r )
2005-03-23 23:26:33 +00:00
{
2009-01-06 18:59:44 +01:00
SERVICE_INFO * info = find_service_info_by_hnd ( p , r - > in . handle ) ;
2005-09-30 17:13:37 +00:00
uint32 buffer_size ;
2008-02-18 11:48:51 +01:00
2005-06-14 20:11:59 +00:00
/* perform access checks */
if ( ! info | | ( info - > type ! = SVC_HANDLE_IS_SERVICE ) )
2008-02-18 11:48:51 +01:00
return WERR_BADFID ;
2005-06-14 20:11:59 +00:00
if ( ! ( info - > access_granted & SC_RIGHT_SVC_QUERY_STATUS ) )
return WERR_ACCESS_DENIED ;
2005-06-14 03:17:31 +00:00
2008-02-18 11:48:51 +01:00
/* we have to set the outgoing buffer size to the same as the
2005-09-30 17:13:37 +00:00
incoming buffer size ( even in the case of failure ) */
2009-01-06 18:59:44 +01:00
* r - > out . bytes_needed = r - > in . buf_size ;
2008-02-18 11:48:51 +01:00
2009-01-06 18:59:44 +01:00
switch ( r - > in . info_level ) {
2005-09-30 17:13:37 +00:00
case SVC_STATUS_PROCESS_INFO :
{
2009-01-06 19:00:05 +01:00
struct SERVICE_STATUS_PROCESS svc_stat_proc ;
2009-01-06 18:59:44 +01:00
enum ndr_err_code ndr_err ;
DATA_BLOB blob ;
2005-06-14 03:17:31 +00:00
2005-09-30 17:13:37 +00:00
/* Get the status of the service.. */
info - > ops - > service_status ( info - > name , & svc_stat_proc . status ) ;
svc_stat_proc . process_id = sys_getpid ( ) ;
svc_stat_proc . service_flags = 0x0 ;
2005-06-14 03:17:31 +00:00
2009-01-06 18:59:44 +01:00
ndr_err = ndr_push_struct_blob ( & blob , p - > mem_ctx , NULL ,
& svc_stat_proc ,
( ndr_push_flags_fn_t ) ndr_push_SERVICE_STATUS_PROCESS ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
return WERR_INVALID_PARAM ;
}
r - > out . buffer = blob . data ;
2009-01-06 19:00:05 +01:00
buffer_size = sizeof ( struct SERVICE_STATUS_PROCESS ) ;
2005-09-30 17:13:37 +00:00
break ;
}
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
default :
2008-02-18 11:48:51 +01:00
return WERR_UNKNOWN_LEVEL ;
2005-06-14 03:17:31 +00:00
}
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
buffer_size + = buffer_size % 4 ;
2009-01-06 18:59:44 +01:00
* r - > out . bytes_needed = ( buffer_size > r - > in . buf_size ) ? buffer_size : r - > in . buf_size ;
2005-06-14 03:17:31 +00:00
2009-01-07 12:38:23 +01:00
if ( buffer_size > r - > in . buf_size ) {
return WERR_INSUFFICIENT_BUFFER ;
}
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
return WERR_OK ;
}
2005-06-14 03:17:31 +00:00
2005-09-30 17:13:37 +00:00
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-06-14 03:17:31 +00:00
2008-10-16 02:00:22 +02:00
static WERROR fill_svc_config ( TALLOC_CTX * ctx , const char * name ,
struct QUERY_SERVICE_CONFIG * config ,
NT_USER_TOKEN * token )
2005-09-30 17:13:37 +00:00
{
REGVAL_CTR * values ;
REGISTRY_VALUE * val ;
2005-06-14 03:17:31 +00:00
2005-09-30 17:13:37 +00:00
/* retrieve the registry values for this service */
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
if ( ! ( values = svcctl_fetch_regvalues ( name , token ) ) )
return WERR_REG_CORRUPT ;
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
/* now fill in the individual values */
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
if ( ( val = regval_ctr_getvalue ( values , " DisplayName " ) ) ! = NULL )
2008-10-16 02:00:22 +02:00
config - > displayname = regval_sz ( val ) ;
2005-09-30 17:13:37 +00:00
else
2008-10-16 02:00:22 +02:00
config - > displayname = name ;
2005-06-14 03:17:31 +00:00
2005-09-30 17:13:37 +00:00
if ( ( val = regval_ctr_getvalue ( values , " ObjectName " ) ) ! = NULL ) {
2008-10-16 02:00:22 +02:00
config - > startname = regval_sz ( val ) ;
2005-09-30 17:13:37 +00:00
}
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
if ( ( val = regval_ctr_getvalue ( values , " ImagePath " ) ) ! = NULL ) {
2008-10-16 02:00:22 +02:00
config - > executablepath = regval_sz ( val ) ;
2005-09-30 17:13:37 +00:00
}
2005-06-14 03:17:31 +00:00
2005-09-30 17:13:37 +00:00
/* a few hard coded values */
/* loadordergroup and dependencies are empty */
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
config - > tag_id = 0x00000000 ; /* unassigned loadorder group */
2009-01-08 13:05:29 +01:00
config - > service_type = SERVICE_TYPE_WIN32_OWN_PROCESS ;
2005-09-30 17:13:37 +00:00
config - > error_control = SVCCTL_SVC_ERROR_NORMAL ;
2005-06-14 03:17:31 +00:00
2008-02-18 11:48:51 +01:00
/* set the start type. NetLogon and WINS are disabled to prevent
2005-12-11 04:21:34 +00:00
the client from showing the " Start " button ( if of course the services
are not running */
2007-10-10 15:34:30 -05:00
if ( strequal ( name , " NETLOGON " ) & & ( lp_servicenumber ( name ) = = - 1 ) )
2005-12-11 04:21:34 +00:00
config - > start_type = SVCCTL_DISABLED ;
else if ( strequal ( name , " WINS " ) & & ( ! lp_wins_support ( ) ) )
config - > start_type = SVCCTL_DISABLED ;
else
config - > start_type = SVCCTL_DEMAND_START ;
2008-02-18 11:48:51 +01:00
2005-12-11 04:21:34 +00:00
2005-09-30 17:13:37 +00:00
TALLOC_FREE ( values ) ;
2005-06-14 03:17:31 +00:00
return WERR_OK ;
}
/********************************************************************
2008-10-16 02:00:22 +02:00
_svcctl_QueryServiceConfigW
2005-06-14 03:17:31 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-16 02:00:22 +02:00
WERROR _svcctl_QueryServiceConfigW ( pipes_struct * p ,
struct svcctl_QueryServiceConfigW * r )
2005-06-14 03:17:31 +00:00
{
2008-10-16 02:00:22 +02:00
SERVICE_INFO * info = find_service_info_by_hnd ( p , r - > in . handle ) ;
2005-09-30 17:13:37 +00:00
uint32 buffer_size ;
WERROR wresult ;
2008-02-18 11:48:51 +01:00
2005-06-14 20:11:59 +00:00
/* perform access checks */
if ( ! info | | ( info - > type ! = SVC_HANDLE_IS_SERVICE ) )
2008-02-18 11:48:51 +01:00
return WERR_BADFID ;
2005-06-14 20:11:59 +00:00
if ( ! ( info - > access_granted & SC_RIGHT_SVC_QUERY_CONFIG ) )
return WERR_ACCESS_DENIED ;
2005-06-14 03:17:31 +00:00
2008-02-18 11:48:51 +01:00
/* we have to set the outgoing buffer size to the same as the
2005-03-23 23:26:33 +00:00
incoming buffer size ( even in the case of failure */
2008-10-16 02:00:22 +02:00
* r - > out . bytes_needed = r - > in . buf_size ;
2008-02-18 11:48:51 +01:00
2008-11-23 23:48:17 +01:00
wresult = fill_svc_config ( p - > mem_ctx , info - > name , r - > out . query ,
p - > server_info - > ptok ) ;
2005-09-30 17:13:37 +00:00
if ( ! W_ERROR_IS_OK ( wresult ) )
return wresult ;
2008-02-18 11:48:51 +01:00
2009-01-01 04:45:33 +01:00
buffer_size = ndr_size_QUERY_SERVICE_CONFIG ( r - > out . query , NULL , 0 ) ;
2008-10-16 02:00:22 +02:00
* r - > out . bytes_needed = ( buffer_size > r - > in . buf_size ) ? buffer_size : r - > in . buf_size ;
2005-06-14 03:17:31 +00:00
2008-10-16 02:00:22 +02:00
if ( buffer_size > r - > in . buf_size ) {
2008-11-13 19:42:13 +01:00
ZERO_STRUCTP ( r - > out . query ) ;
2005-09-30 17:13:37 +00:00
return WERR_INSUFFICIENT_BUFFER ;
2005-06-14 03:17:31 +00:00
}
2008-02-18 11:48:51 +01:00
2005-06-14 03:17:31 +00:00
return WERR_OK ;
2005-03-23 23:26:33 +00:00
}
2005-06-14 03:17:31 +00:00
/********************************************************************
2009-01-07 15:05:01 +01:00
_svcctl_QueryServiceConfig2W
2005-06-14 03:17:31 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-01-07 15:05:01 +01:00
WERROR _svcctl_QueryServiceConfig2W ( pipes_struct * p ,
struct svcctl_QueryServiceConfig2W * r )
2005-06-14 03:17:31 +00:00
{
2009-01-07 15:05:01 +01:00
SERVICE_INFO * info = find_service_info_by_hnd ( p , r - > in . handle ) ;
2005-09-30 17:13:37 +00:00
uint32 buffer_size ;
2007-12-17 18:00:43 -08:00
2005-06-14 20:11:59 +00:00
/* perform access checks */
if ( ! info | | ( info - > type ! = SVC_HANDLE_IS_SERVICE ) )
2007-12-17 18:00:43 -08:00
return WERR_BADFID ;
2005-06-14 20:11:59 +00:00
if ( ! ( info - > access_granted & SC_RIGHT_SVC_QUERY_CONFIG ) )
return WERR_ACCESS_DENIED ;
2007-12-17 18:00:43 -08:00
/* we have to set the outgoing buffer size to the same as the
2005-06-14 03:17:31 +00:00
incoming buffer size ( even in the case of failure */
2009-01-07 15:05:01 +01:00
* r - > out . bytes_needed = r - > in . buf_size ;
2005-06-14 03:17:31 +00:00
2009-01-07 15:05:01 +01:00
switch ( r - > in . info_level ) {
2005-09-30 17:13:37 +00:00
case SERVICE_CONFIG_DESCRIPTION :
{
2009-01-07 15:05:01 +01:00
struct SERVICE_DESCRIPTION desc_buf ;
2005-09-30 17:13:37 +00:00
const char * description ;
2009-01-07 15:05:01 +01:00
enum ndr_err_code ndr_err ;
DATA_BLOB blob ;
2007-12-17 18:00:43 -08:00
2008-11-23 23:48:17 +01:00
description = svcctl_lookup_description (
p - > mem_ctx , info - > name , p - > server_info - > ptok ) ;
2007-12-17 18:00:43 -08:00
2009-01-07 15:05:01 +01:00
desc_buf . description = description ;
ndr_err = ndr_push_struct_blob ( & blob , p - > mem_ctx , NULL ,
& desc_buf ,
( ndr_push_flags_fn_t ) ndr_push_SERVICE_DESCRIPTION ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
return WERR_INVALID_PARAM ;
}
2005-06-14 03:17:31 +00:00
2009-01-07 15:05:01 +01:00
buffer_size = ndr_size_SERVICE_DESCRIPTION ( & desc_buf , NULL , 0 ) ;
r - > out . buffer = blob . data ;
2005-06-14 03:17:31 +00:00
2005-09-30 17:13:37 +00:00
break ;
2005-06-14 03:17:31 +00:00
}
2005-09-30 17:13:37 +00:00
break ;
case SERVICE_CONFIG_FAILURE_ACTIONS :
{
2009-01-07 15:05:01 +01:00
struct SERVICE_FAILURE_ACTIONS actions ;
enum ndr_err_code ndr_err ;
DATA_BLOB blob ;
2005-09-30 17:13:37 +00:00
/* nothing to say...just service the request */
2009-01-07 15:05:01 +01:00
ZERO_STRUCT ( actions ) ;
ndr_err = ndr_push_struct_blob ( & blob , p - > mem_ctx , NULL ,
& actions ,
( ndr_push_flags_fn_t ) ndr_push_SERVICE_FAILURE_ACTIONS ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
return WERR_INVALID_PARAM ;
}
buffer_size = ndr_size_SERVICE_FAILURE_ACTIONS ( & actions , NULL , 0 ) ;
r - > out . buffer = blob . data ;
2005-09-30 17:13:37 +00:00
break ;
2005-06-14 03:17:31 +00:00
}
2005-09-30 17:13:37 +00:00
break ;
default :
return WERR_UNKNOWN_LEVEL ;
}
2007-12-17 18:00:43 -08:00
2005-09-30 17:13:37 +00:00
buffer_size + = buffer_size % 4 ;
2009-01-07 15:05:01 +01:00
* r - > out . bytes_needed = ( buffer_size > r - > in . buf_size ) ? buffer_size : r - > in . buf_size ;
2005-06-14 03:17:31 +00:00
2009-01-07 15:05:01 +01:00
if ( buffer_size > r - > in . buf_size )
2005-09-30 17:13:37 +00:00
return WERR_INSUFFICIENT_BUFFER ;
2005-06-14 03:17:31 +00:00
2005-09-30 17:13:37 +00:00
return WERR_OK ;
}
/********************************************************************
2008-02-19 02:47:05 +01:00
_svcctl_LockServiceDatabase
2005-09-30 17:13:37 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-02-19 02:47:05 +01:00
WERROR _svcctl_LockServiceDatabase ( pipes_struct * p ,
struct svcctl_LockServiceDatabase * r )
2005-09-30 17:13:37 +00:00
{
2008-02-19 02:47:05 +01:00
SERVICE_INFO * info = find_service_info_by_hnd ( p , r - > in . handle ) ;
2008-02-18 11:48:51 +01:00
2005-09-30 17:13:37 +00:00
/* perform access checks */
if ( ! info | | ( info - > type ! = SVC_HANDLE_IS_SCM ) )
2008-02-18 11:48:51 +01:00
return WERR_BADFID ;
2005-09-30 17:13:37 +00:00
if ( ! ( info - > access_granted & SC_RIGHT_MGR_LOCK ) )
return WERR_ACCESS_DENIED ;
/* Just open a handle. Doesn't actually lock anything */
2008-02-18 11:48:51 +01:00
2008-02-19 02:47:05 +01:00
return create_open_service_handle ( p , r - > out . lock , SVC_HANDLE_IS_DBLOCK , NULL , 0 ) ;
2005-09-30 17:13:37 +00:00
}
/********************************************************************
2008-02-19 02:50:01 +01:00
_svcctl_UnlockServiceDatabase
2005-09-30 17:13:37 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-02-19 02:50:01 +01:00
WERROR _svcctl_UnlockServiceDatabase ( pipes_struct * p ,
struct svcctl_UnlockServiceDatabase * r )
2005-09-30 17:13:37 +00:00
{
2008-02-19 02:50:01 +01:00
SERVICE_INFO * info = find_service_info_by_hnd ( p , r - > in . lock ) ;
2005-09-30 17:13:37 +00:00
if ( ! info | | ( info - > type ! = SVC_HANDLE_IS_DBLOCK ) )
2008-02-18 11:48:51 +01:00
return WERR_BADFID ;
2008-02-19 02:50:01 +01:00
return close_policy_hnd ( p , r - > out . lock ) ? WERR_OK : WERR_BADFID ;
2005-06-14 03:17:31 +00:00
}
2006-01-13 20:24:50 +00:00
/********************************************************************
2008-02-28 00:05:23 +01:00
_svcctl_QueryServiceObjectSecurity
2006-01-13 20:24:50 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-02-28 00:05:23 +01:00
WERROR _svcctl_QueryServiceObjectSecurity ( pipes_struct * p ,
struct svcctl_QueryServiceObjectSecurity * r )
2006-01-13 20:24:50 +00:00
{
2008-02-28 00:05:23 +01:00
SERVICE_INFO * info = find_service_info_by_hnd ( p , r - > in . handle ) ;
2006-01-13 20:24:50 +00:00
SEC_DESC * sec_desc ;
2008-02-28 00:05:23 +01:00
NTSTATUS status ;
uint8_t * buffer = NULL ;
size_t len = 0 ;
2006-01-13 20:24:50 +00:00
/* only support the SCM and individual services */
if ( ! info | | ! ( info - > type & ( SVC_HANDLE_IS_SERVICE | SVC_HANDLE_IS_SCM ) ) )
2008-02-18 11:48:51 +01:00
return WERR_BADFID ;
2006-01-13 20:24:50 +00:00
/* check access reights (according to MSDN) */
if ( ! ( info - > access_granted & STD_RIGHT_READ_CONTROL_ACCESS ) )
return WERR_ACCESS_DENIED ;
/* TODO: handle something besides DACL_SECURITY_INFORMATION */
2008-02-28 00:05:23 +01:00
if ( ( r - > in . security_flags & DACL_SECURITY_INFORMATION ) ! = DACL_SECURITY_INFORMATION )
2006-01-13 20:24:50 +00:00
return WERR_INVALID_PARAM ;
/* lookup the security descriptor and marshall it up for a reply */
if ( ! ( sec_desc = svcctl_get_secdesc ( p - > mem_ctx , info - > name , get_root_nt_token ( ) ) ) )
return WERR_NOMEM ;
2009-01-01 04:45:33 +01:00
* r - > out . needed = ndr_size_security_descriptor ( sec_desc , NULL , 0 ) ;
2006-01-13 20:24:50 +00:00
2008-02-28 00:05:23 +01:00
if ( * r - > out . needed > r - > in . buffer_size ) {
ZERO_STRUCTP ( & r - > out . buffer ) ;
2006-01-13 20:24:50 +00:00
return WERR_INSUFFICIENT_BUFFER ;
}
2008-02-28 00:05:23 +01:00
status = marshall_sec_desc ( p - > mem_ctx , sec_desc , & buffer , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ntstatus_to_werror ( status ) ;
}
2006-01-13 20:24:50 +00:00
2008-02-28 00:05:23 +01:00
* r - > out . needed = len ;
r - > out . buffer = buffer ;
2008-02-18 11:48:51 +01:00
2006-01-13 20:24:50 +00:00
return WERR_OK ;
}
/********************************************************************
2008-02-28 00:33:06 +01:00
_svcctl_SetServiceObjectSecurity
2006-01-13 20:24:50 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-02-28 00:33:06 +01:00
WERROR _svcctl_SetServiceObjectSecurity ( pipes_struct * p ,
struct svcctl_SetServiceObjectSecurity * r )
2006-01-13 20:24:50 +00:00
{
2008-02-28 00:33:06 +01:00
SERVICE_INFO * info = find_service_info_by_hnd ( p , r - > in . handle ) ;
2006-01-13 20:24:50 +00:00
SEC_DESC * sec_desc = NULL ;
uint32 required_access ;
2008-02-28 00:33:06 +01:00
NTSTATUS status ;
2006-01-13 20:24:50 +00:00
if ( ! info | | ! ( info - > type & ( SVC_HANDLE_IS_SERVICE | SVC_HANDLE_IS_SCM ) ) )
return WERR_BADFID ;
2006-01-13 20:26:59 +00:00
/* can't set the security de4scriptor on the ServiceControlManager */
if ( info - > type = = SVC_HANDLE_IS_SCM )
2008-02-18 11:48:51 +01:00
return WERR_ACCESS_DENIED ;
2006-01-13 20:26:59 +00:00
2006-01-13 20:24:50 +00:00
/* check the access on the open handle */
2008-02-18 11:48:51 +01:00
2008-02-28 00:33:06 +01:00
switch ( r - > in . security_flags ) {
2006-01-13 20:24:50 +00:00
case DACL_SECURITY_INFORMATION :
required_access = STD_RIGHT_WRITE_DAC_ACCESS ;
break ;
2008-02-18 11:48:51 +01:00
2006-01-13 20:24:50 +00:00
case OWNER_SECURITY_INFORMATION :
case GROUP_SECURITY_INFORMATION :
required_access = STD_RIGHT_WRITE_OWNER_ACCESS ;
break ;
2008-02-18 11:48:51 +01:00
2006-01-13 20:24:50 +00:00
case SACL_SECURITY_INFORMATION :
return WERR_INVALID_PARAM ;
default :
return WERR_INVALID_PARAM ;
}
2008-02-18 11:48:51 +01:00
2006-01-13 20:24:50 +00:00
if ( ! ( info - > access_granted & required_access ) )
return WERR_ACCESS_DENIED ;
2008-02-18 11:48:51 +01:00
2006-01-13 20:24:50 +00:00
/* read the security descfriptor */
2008-02-18 11:48:51 +01:00
2008-02-28 00:33:06 +01:00
status = unmarshall_sec_desc ( p - > mem_ctx ,
r - > in . buffer , r - > in . buffer_size ,
& sec_desc ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ntstatus_to_werror ( status ) ;
}
2008-02-18 11:48:51 +01:00
2006-01-13 20:24:50 +00:00
/* store the new SD */
2008-11-23 23:48:17 +01:00
if ( ! svcctl_set_secdesc ( p - > mem_ctx , info - > name , sec_desc ,
p - > server_info - > ptok ) )
2006-01-13 20:24:50 +00:00
return WERR_ACCESS_DENIED ;
return WERR_OK ;
}
2007-05-31 17:24:30 +00:00
WERROR _svcctl_DeleteService ( pipes_struct * p , struct svcctl_DeleteService * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_SetServiceStatus ( pipes_struct * p , struct svcctl_SetServiceStatus * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_NotifyBootConfigStatus ( pipes_struct * p , struct svcctl_NotifyBootConfigStatus * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_SCSetServiceBitsW ( pipes_struct * p , struct svcctl_SCSetServiceBitsW * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_ChangeServiceConfigW ( pipes_struct * p , struct svcctl_ChangeServiceConfigW * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_CreateServiceW ( pipes_struct * p , struct svcctl_CreateServiceW * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_QueryServiceLockStatusW ( pipes_struct * p , struct svcctl_QueryServiceLockStatusW * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_GetServiceKeyNameW ( pipes_struct * p , struct svcctl_GetServiceKeyNameW * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_SCSetServiceBitsA ( pipes_struct * p , struct svcctl_SCSetServiceBitsA * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_ChangeServiceConfigA ( pipes_struct * p , struct svcctl_ChangeServiceConfigA * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_CreateServiceA ( pipes_struct * p , struct svcctl_CreateServiceA * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_EnumDependentServicesA ( pipes_struct * p , struct svcctl_EnumDependentServicesA * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_EnumServicesStatusA ( pipes_struct * p , struct svcctl_EnumServicesStatusA * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_OpenSCManagerA ( pipes_struct * p , struct svcctl_OpenSCManagerA * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_OpenServiceA ( pipes_struct * p , struct svcctl_OpenServiceA * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_QueryServiceConfigA ( pipes_struct * p , struct svcctl_QueryServiceConfigA * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_QueryServiceLockStatusA ( pipes_struct * p , struct svcctl_QueryServiceLockStatusA * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_StartServiceA ( pipes_struct * p , struct svcctl_StartServiceA * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_GetServiceDisplayNameA ( pipes_struct * p , struct svcctl_GetServiceDisplayNameA * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_GetServiceKeyNameA ( pipes_struct * p , struct svcctl_GetServiceKeyNameA * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_GetCurrentGroupeStateW ( pipes_struct * p , struct svcctl_GetCurrentGroupeStateW * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_EnumServiceGroupW ( pipes_struct * p , struct svcctl_EnumServiceGroupW * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_ChangeServiceConfig2A ( pipes_struct * p , struct svcctl_ChangeServiceConfig2A * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_ChangeServiceConfig2W ( pipes_struct * p , struct svcctl_ChangeServiceConfig2W * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_QueryServiceConfig2A ( pipes_struct * p , struct svcctl_QueryServiceConfig2A * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _EnumServicesStatusExA ( pipes_struct * p , struct EnumServicesStatusExA * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _EnumServicesStatusExW ( pipes_struct * p , struct EnumServicesStatusExW * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}
WERROR _svcctl_SCSendTSMessage ( pipes_struct * p , struct svcctl_SCSendTSMessage * r )
{
p - > rng_fault_state = True ;
2008-02-18 11:48:51 +01:00
return WERR_NOT_SUPPORTED ;
2007-05-31 17:24:30 +00:00
}