diff options
-rw-r--r-- | source3/include/rpc_secdes.h | 34 | ||||
-rw-r--r-- | source3/rpc_server/srv_svcctl_nt.c | 126 |
2 files changed, 139 insertions, 21 deletions
diff --git a/source3/include/rpc_secdes.h b/source3/include/rpc_secdes.h index 9eb4c9a41e..fe95706d03 100644 --- a/source3/include/rpc_secdes.h +++ b/source3/include/rpc_secdes.h @@ -475,15 +475,20 @@ typedef struct standard_mapping { #define SC_RIGHT_MGR_QUERY_LOCK_STATUS 0x0010 #define SC_RIGHT_MGR_MODIFY_BOOT_CONFIG 0x0020 +#define SC_MANAGER_READ_ACCESS \ + ( STANDARD_RIGHTS_READ_ACCESS | \ + SC_RIGHT_MGR_CONNECT | \ + SC_RIGHT_MGR_ENUMERATE_SERVICE | \ + SC_RIGHT_MGR_QUERY_LOCK_STATUS ) + #define SC_MANAGER_ALL_ACCESS \ ( STANDARD_RIGHTS_REQUIRED_ACCESS | \ - SC_RIGHT_MGR_CONNECT | \ + SC_MANAGER_READ_ACCESS | \ SC_RIGHT_MGR_CREATE_SERVICE | \ - SC_RIGHT_MGR_ENUMERATE_SERVICE | \ SC_RIGHT_MGR_LOCK | \ - SC_RIGHT_MGR_QUERY_LOCK_STATUS | \ SC_RIGHT_MGR_MODIFY_BOOT_CONFIG ) + /* Service Object Bits */ #define SC_RIGHT_SVC_QUERY_CONFIG 0x0001 @@ -496,17 +501,26 @@ typedef struct standard_mapping { #define SC_RIGHT_SVC_INTERROGATE 0x0080 #define SC_RIGHT_SVC_USER_DEFINED_CONTROL 0x0100 -#define SERVICE_ALL_ACCESS \ - ( STANDARD_RIGHTS_REQUIRED_ACCESS | \ +#define SERVICE_READ_ACCESS \ + ( STANDARD_RIGHTS_READ_ACCESS | \ + SC_RIGHT_SVC_ENUMERATE_DEPENDENTS | \ + SC_RIGHT_SVC_INTERROGATE | \ SC_RIGHT_SVC_QUERY_CONFIG | \ - SC_RIGHT_SVC_CHANGE_CONFIG | \ SC_RIGHT_SVC_QUERY_STATUS | \ - SC_RIGHT_SVC_ENUMERATE_DEPENDENTS | \ + SC_RIGHT_SVC_USER_DEFINED_CONTROL ) + +#define SERVICE_EXECUTE_ACCESS \ + ( SERVICE_READ_ACCESS | \ SC_RIGHT_SVC_START | \ SC_RIGHT_SVC_STOP | \ - SC_RIGHT_SVC_PAUSE_CONTINUE | \ - SC_RIGHT_SVC_INTERROGATE | \ - SC_RIGHT_SVC_USER_DEFINED_CONTROL ) + SC_RIGHT_SVC_PAUSE_CONTINUE ) + +#define SERVICE_ALL_ACCESS \ + ( STANDARD_RIGHTS_REQUIRED_ACCESS | \ + SERVICE_READ_ACCESS | \ + SERVICE_EXECUTE_ACCESS ) + + /* * Access Bits for registry ACLS diff --git a/source3/rpc_server/srv_svcctl_nt.c b/source3/rpc_server/srv_svcctl_nt.c index 707fd8bdd5..53fddcf964 100644 --- a/source3/rpc_server/srv_svcctl_nt.c +++ b/source3/rpc_server/srv_svcctl_nt.c @@ -443,6 +443,91 @@ BOOL init_svcctl_db(void) /******************************************************************** ********************************************************************/ +static NTSTATUS svcctl_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token, + uint32 access_desired, uint32 *access_granted ) +{ + NTSTATUS result; + + /* maybe add privilege checks in here later */ + + 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; + uint32 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; +} + +/******************************************************************** +********************************************************************/ + +static SEC_DESC* construct_service_sd( TALLOC_CTX *ctx ) +{ + SEC_ACE ace[4]; + SEC_ACCESS mask; + size_t i = 0; + SEC_DESC *sd; + SEC_ACL *acl; + uint32 sd_size; + + /* basic access for Everyone */ + + init_sec_access(&mask, SERVICE_READ_ACCESS ); + init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + init_sec_access(&mask,SERVICE_EXECUTE_ACCESS ); + init_sec_ace(&ace[i++], &global_sid_Builtin_Power_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + init_sec_access(&mask,SERVICE_ALL_ACCESS ); + init_sec_ace(&ace[i++], &global_sid_Builtin_Server_Operators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + 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; +} + + +/******************************************************************** +********************************************************************/ + static BOOL read_service_tdb_to_si(TDB_CONTEXT *stdb,char *service_name, Service_info *si) { @@ -546,12 +631,15 @@ static SERVICE_INFO *find_service_info_by_hnd(pipes_struct *p, POLICY_HND *hnd) /****************************************************************** *****************************************************************/ -WERROR create_open_service_handle( pipes_struct *p, POLICY_HND *handle, const char *service ) +static WERROR create_open_service_handle( pipes_struct *p, POLICY_HND *handle, + const char *service, uint32 access_granted ) { SERVICE_INFO *info = NULL; if ( !(info = SMB_MALLOC_P( SERVICE_INFO )) ) return WERR_NOMEM; + + ZERO_STRUCTP( info ); /* the Service Manager has a NULL name */ @@ -574,6 +662,8 @@ WERROR create_open_service_handle( pipes_struct *p, POLICY_HND *handle, const ch #endif } + 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 ) ) { @@ -589,13 +679,20 @@ WERROR create_open_service_handle( pipes_struct *p, POLICY_HND *handle, const ch WERROR _svcctl_open_scmanager(pipes_struct *p, SVCCTL_Q_OPEN_SCMANAGER *q_u, SVCCTL_R_OPEN_SCMANAGER *r_u) { - /* perform access checks */ + SEC_DESC *sec_desc; + uint32 access_granted = 0; + NTSTATUS status; - - /* open the handle and return */ + /* perform access checks */ - return create_open_service_handle( p, &r_u->handle, NULL ); - + if ( !(sec_desc = construct_scm_sd( p->mem_ctx )) ) + return WERR_NOMEM; + + 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, NULL, access_granted ); } /******************************************************************** @@ -603,6 +700,9 @@ WERROR _svcctl_open_scmanager(pipes_struct *p, SVCCTL_Q_OPEN_SCMANAGER *q_u, SVC 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); @@ -614,17 +714,21 @@ WERROR _svcctl_open_service(pipes_struct *p, SVCCTL_Q_OPEN_SERVICE *q_u, SVCCTL_ return WERR_ACCESS_DENIED; } - /* check the access granted on the SCM handle */ - - /* check the access requested on this service */ + /* perform access checks */ - + if ( !(sec_desc = construct_service_sd( p->mem_ctx )) ) + return WERR_NOMEM; + + 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 ); + #if 0 /* FIXME!!! */ if ( ! read_service_tdb_to_si(service_tdb,service, info) ) { return WERR_NO_SUCH_SERVICE; #endif - return create_open_service_handle( p, &r_u->handle, service ); + return create_open_service_handle( p, &r_u->handle, service, access_granted ); } /******************************************************************** |