From b6153cb78bdc6dbf26b716793222983fd00545b8 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 14 Jun 2005 20:11:59 +0000 Subject: r7583: * more rearranging and renaming of functions * add access checks to _svcctl_XXX() calls based on the access granted on the handle (This used to be commit 82b76d4b34834b7f64389b85befe8bfcae04a404) --- source3/rpc_server/srv_svcctl_nt.c | 1078 +++++++++++++++++++----------------- 1 file changed, 570 insertions(+), 508 deletions(-) (limited to 'source3/rpc_server') diff --git a/source3/rpc_server/srv_svcctl_nt.c b/source3/rpc_server/srv_svcctl_nt.c index 53fddcf964..3367768f81 100644 --- a/source3/rpc_server/srv_svcctl_nt.c +++ b/source3/rpc_server/srv_svcctl_nt.c @@ -42,7 +42,6 @@ */ #define SCVCTL_DATABASE_VERSION_V1 1 -TALLOC_CTX *svcdb=NULL; static TDB_CONTEXT *service_tdb; /* used for services tdb file */ /* there are two types of services -- internal, and external. @@ -91,11 +90,12 @@ static const Internal_service_description ISD[] = { (d) check access control masks with se_access_check() ********************************************************************/ +#if 0 /********************************************************************* given a service nice name, find the underlying service name *********************************************************************/ -BOOL _svcctl_service_nicename_to_servicename(TDB_CONTEXT *stdb,pstring service_nicename, pstring servicename,int szsvcname) +static BOOL convert_service_displayname(TDB_CONTEXT *stdb,pstring service_nicename, pstring servicename,int szsvcname) { pstring keystring; TDB_DATA key_data; @@ -105,91 +105,30 @@ BOOL _svcctl_service_nicename_to_servicename(TDB_CONTEXT *stdb,pstring service_ pstr_sprintf(keystring,"SERVICE_NICENAME/%s", servicename); - DEBUG(5, ("_svcctl_service_nicename_to_servicename: Looking for service name [%s], key [%s]\n", + DEBUG(5, ("convert_service_displayname: Looking for service name [%s], key [%s]\n", service_nicename, keystring)); key_data = tdb_fetch_bystring(stdb,keystring); if (key_data.dsize == 0) { - DEBUG(5, ("_svcctl_service_nicename_to_servicename: [%s] Not found, tried key [%s]\n",service_nicename,keystring)); + DEBUG(5, ("convert_service_displayname: [%s] Not found, tried key [%s]\n",service_nicename,keystring)); return False; } strncpy(servicename,key_data.dptr,szsvcname); servicename[(key_data.dsize > szsvcname ? szsvcname : key_data.dsize)] = 0; - DEBUG(5, ("_svcctl_service_nicename_to_servicename: Found service name [%s], name is [%s]\n", + DEBUG(5, ("convert_service_displayname: Found service name [%s], name is [%s]\n", service_nicename,servicename)); return True; } - -/********************************************************************* -*********************************************************************/ - -static BOOL write_si_to_service_tdb(TDB_CONTEXT *stdb,char *service_name, Service_info *si) -{ - pstring keystring; - - /* Note -- when we write to the tdb, we "index" on the filename - field, not the nice name. when a service is "opened", it is - opened by the nice (SERVICENAME) name, not the file name. - So there needs to be a mapping from nice name back to the file name. */ - - if ((stdb == NULL) || (si == NULL) || (service_name==NULL) || (*service_name == 0)) - return False; - - - /* Store the nicename */ - - pstr_sprintf(keystring,"SERVICE_NICENAME/%s", si->servicename); - tdb_store_bystring(stdb,keystring,string_tdb_data(service_name),TDB_REPLACE); - - pstr_sprintf(keystring,"SERVICE/%s/TYPE", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->servicetype),TDB_REPLACE); - - pstr_sprintf(keystring,"SERVICE/%s/FILENAME", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->filename),TDB_REPLACE); - - pstr_sprintf(keystring,"SERVICE/%s/PROVIDES", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->provides),TDB_REPLACE); - - pstr_sprintf(keystring,"SERVICE/%s/SERVICENAME", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->servicename),TDB_REPLACE); - - pstr_sprintf(keystring,"SERVICE/%s/DEPENDENCIES", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->dependencies),TDB_REPLACE); - - pstr_sprintf(keystring,"SERVICE/%s/SHOULDSTART", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->shouldstart),TDB_REPLACE); - - pstr_sprintf(keystring,"SERVICE/%s/SHOULDSTOP", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->shouldstop),TDB_REPLACE); - - pstr_sprintf(keystring,"SERVICE/%s/REQUIREDSTART", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->requiredstart),TDB_REPLACE); - - pstr_sprintf(keystring,"SERVICE/%s/REQUIREDSTOP", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->requiredstop),TDB_REPLACE); - - pstr_sprintf(keystring,"SERVICE/%s/DESCRIPTION", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->description),TDB_REPLACE); - - pstr_sprintf(keystring,"SERVICE/%s/SHORTDESC", service_name); - tdb_lock_bystring(stdb, keystring, 0); - if (si->shortdescription && *si->shortdescription) - tdb_store_bystring(stdb,keystring,string_tdb_data(si->shortdescription),TDB_REPLACE); - else - tdb_store_bystring(stdb,keystring,string_tdb_data(si->description),TDB_REPLACE); - - return True; -} - +#endif /******************************************************************************* Get the INTERNAL services information for the given service name. *******************************************************************************/ -static BOOL _svcctl_get_internal_service_data(const Internal_service_description *isd, Service_info *si) +static BOOL get_internal_service_data(const Internal_service_description *isd, Service_info *si) { ZERO_STRUCTP( si ); #if 0 @@ -213,7 +152,7 @@ static BOOL _svcctl_get_internal_service_data(const Internal_service_description Get the names of the services/scripts to read from the smb.conf file. *******************************************************************************/ -static BOOL _svcctl_get_LSB_data(char *fname,Service_info *si ) +static BOOL get_LSB_data(char *fname,Service_info *si ) { pstring initdfile; char mybuffer[256]; @@ -351,184 +290,10 @@ static BOOL _svcctl_get_LSB_data(char *fname,Service_info *si ) return False; } -/**************************************************************************** - Create/Open the service control manager tdb. This code a clone of init_group_mapping. -****************************************************************************/ - -BOOL init_svcctl_db(void) -{ - const char *vstring = "INFO/version"; - uint32 vers_id; - char **svc_list; - char **svcname; - pstring keystring; - pstring external_service_list; - pstring internal_service_list; - Service_info si; - const Internal_service_description *isd_ptr; - /* svc_list = str_list_make( "etc/init.d/skeleton etc/init.d/syslog", NULL ); */ - svc_list=(char **)lp_enable_svcctl(); - - if (service_tdb) - return True; - - pstrcpy(external_service_list,""); - - service_tdb = tdb_open_log(lock_path("services.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600); - if (!service_tdb) { - DEBUG(0,("Failed to open service db\n")); - service_tdb = tdb_open_log(lock_path("services.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); - if (!service_tdb) return False; - DEBUG(0,("Created new services db\n")); - } - - if ((-1 == tdb_fetch_uint32(service_tdb, vstring,&vers_id)) || (vers_id != SERVICEDB_VERSION_V1)) { - /* wrong version of DB, or db was just created */ - tdb_traverse(service_tdb, tdb_traverse_delete_fn, NULL); - tdb_store_uint32(service_tdb, vstring, SERVICEDB_VERSION_V1); - } - tdb_unlock_bystring(service_tdb, vstring); - - DEBUG(0,("Initializing services db\n")); - - svcname = svc_list; - - /* Get the EXTERNAL services as mentioned by line in smb.conf */ - - while (*svcname) { - DEBUG(10,("Reading information on service %s\n",*svcname)); - if (_svcctl_get_LSB_data(*svcname,&si));{ - /* write the information to the TDB */ - write_si_to_service_tdb(service_tdb,*svcname,&si); - /* definitely not efficient to do it this way. */ - pstrcat(external_service_list,"\""); - pstrcat(external_service_list,*svcname); - pstrcat(external_service_list,"\" "); - } - svcname++; - } - pstrcpy(keystring,"EXTERNAL_SERVICES"); - tdb_lock_bystring(service_tdb, keystring, 0); - DEBUG(8,("Storing external service list [%s]\n",external_service_list)); - tdb_store_bystring(service_tdb,keystring,string_tdb_data(external_service_list),TDB_REPLACE); - tdb_unlock_bystring(service_tdb,keystring); - - /* Get the INTERNAL services */ - - pstrcpy(internal_service_list,""); - isd_ptr = ISD; - - while (isd_ptr && (isd_ptr->filename)) { - DEBUG(10,("Reading information on service %s\n",isd_ptr->filename)); - if (_svcctl_get_internal_service_data(isd_ptr,&si)){ - /* write the information to the TDB */ - write_si_to_service_tdb(service_tdb,(char *)isd_ptr->filename,&si); - /* definitely not efficient to do it this way. */ - pstrcat(internal_service_list,"\""); - pstrcat(internal_service_list,isd_ptr->filename); - pstrcat(internal_service_list,"\" "); - - } - isd_ptr++; - } - pstrcpy(keystring,"INTERNAL_SERVICES"); - tdb_lock_bystring(service_tdb, keystring, 0); - DEBUG(8,("Storing internal service list [%s]\n",internal_service_list)); - tdb_store_bystring(service_tdb,keystring,string_tdb_data(internal_service_list),TDB_REPLACE); - tdb_unlock_bystring(service_tdb,keystring); - - return True; -} - -/******************************************************************** -********************************************************************/ - -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) +static BOOL get_service_info(TDB_CONTEXT *stdb,char *service_name, Service_info *si) { pstring keystring; @@ -600,191 +365,73 @@ static BOOL read_service_tdb_to_si(TDB_CONTEXT *stdb,char *service_name, Service return True; } -/****************************************************************** - free() function for REGISTRY_KEY - *****************************************************************/ - -static void free_service_handle_info(void *ptr) -{ - SERVICE_INFO *info = (SERVICE_INFO*)ptr; - - SAFE_FREE(info->name); - SAFE_FREE(info); -} - -/****************************************************************** - Find a registry key handle and return a SERVICE_INFO - *****************************************************************/ +/********************************************************************* +*********************************************************************/ -static SERVICE_INFO *find_service_info_by_hnd(pipes_struct *p, POLICY_HND *hnd) +static BOOL store_service_info(TDB_CONTEXT *stdb,char *service_name, Service_info *si) { - SERVICE_INFO *service_info = NULL; + pstring keystring; - if( !find_policy_by_hnd( p, hnd, (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, - 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 */ - - if ( !service ) { - info->type = SVC_HANDLE_IS_SCM; - } else { - info->type = SVC_HANDLE_IS_SERVICE; - - if ( !(info->name = SMB_STRDUP( service )) ) { - free_service_handle_info( info ); - WERR_NOMEM; - } - -#if 0 - /* lookup the SERVICE_CONTROL_OPS */ - - for ( i=0; svcctl_ops[i].name; i++ ) { - ;; - } -#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 ) ) { - free_service_handle_info( info ); - return WERR_ACCESS_DENIED; - } - - return WERR_OK; -} - -/******************************************************************** -********************************************************************/ - -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; - - 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 ); -} + /* Note -- when we write to the tdb, we "index" on the filename + field, not the nice name. when a service is "opened", it is + opened by the nice (SERVICENAME) name, not the file name. + So there needs to be a mapping from nice name back to the file name. */ -/******************************************************************** -********************************************************************/ + if ((stdb == NULL) || (si == NULL) || (service_name==NULL) || (*service_name == 0)) + return False; -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)); - - if ( !service_tdb ) { - DEBUG(1, ("_svcctl_open_service: service database is not open\n!")); - return WERR_ACCESS_DENIED; - } - - /* 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, access_granted ); -} + /* Store the nicename */ -/******************************************************************** -********************************************************************/ + pstr_sprintf(keystring,"SERVICE_NICENAME/%s", si->servicename); + tdb_store_bystring(stdb,keystring,string_tdb_data(service_name),TDB_REPLACE); -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; -} + pstr_sprintf(keystring,"SERVICE/%s/TYPE", service_name); + tdb_store_bystring(stdb,keystring,string_tdb_data(si->servicetype),TDB_REPLACE); -/******************************************************************** -********************************************************************/ + pstr_sprintf(keystring,"SERVICE/%s/FILENAME", service_name); + tdb_store_bystring(stdb,keystring,string_tdb_data(si->filename),TDB_REPLACE); -WERROR _svcctl_get_display_name(pipes_struct *p, SVCCTL_Q_GET_DISPLAY_NAME *q_u, SVCCTL_R_GET_DISPLAY_NAME *r_u) -{ - fstring service; - fstring displayname; + pstr_sprintf(keystring,"SERVICE/%s/PROVIDES", service_name); + tdb_store_bystring(stdb,keystring,string_tdb_data(si->provides),TDB_REPLACE); - SERVICE_INFO *service_info; - POLICY_HND *handle; + pstr_sprintf(keystring,"SERVICE/%s/SERVICENAME", service_name); + tdb_store_bystring(stdb,keystring,string_tdb_data(si->servicename),TDB_REPLACE); - rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0); + pstr_sprintf(keystring,"SERVICE/%s/DEPENDENCIES", service_name); + tdb_store_bystring(stdb,keystring,string_tdb_data(si->dependencies),TDB_REPLACE); - handle = &(q_u->handle); + pstr_sprintf(keystring,"SERVICE/%s/SHOULDSTART", service_name); + tdb_store_bystring(stdb,keystring,string_tdb_data(si->shouldstart),TDB_REPLACE); - service_info = find_service_info_by_hnd(p, handle); + pstr_sprintf(keystring,"SERVICE/%s/SHOULDSTOP", service_name); + tdb_store_bystring(stdb,keystring,string_tdb_data(si->shouldstop),TDB_REPLACE); - if (!service_info) { - DEBUG(10, ("_svcctl_get_display_name : Can't find the service for the handle\n")); - return WERR_ACCESS_DENIED; - } + pstr_sprintf(keystring,"SERVICE/%s/REQUIREDSTART", service_name); + tdb_store_bystring(stdb,keystring,string_tdb_data(si->requiredstart),TDB_REPLACE); - DEBUG(10,("_svcctl_get_display_name: Found service [%s]\n", service_info->name )); + pstr_sprintf(keystring,"SERVICE/%s/REQUIREDSTOP", service_name); + tdb_store_bystring(stdb,keystring,string_tdb_data(si->requiredstop),TDB_REPLACE); - fstrcpy( displayname, "FIX ME!" ); + pstr_sprintf(keystring,"SERVICE/%s/DESCRIPTION", service_name); + tdb_store_bystring(stdb,keystring,string_tdb_data(si->description),TDB_REPLACE); - init_svcctl_r_get_display_name( r_u, displayname ); + pstr_sprintf(keystring,"SERVICE/%s/SHORTDESC", service_name); + tdb_lock_bystring(stdb, keystring, 0); + if (si->shortdescription && *si->shortdescription) + tdb_store_bystring(stdb,keystring,string_tdb_data(si->shortdescription),TDB_REPLACE); + else + tdb_store_bystring(stdb,keystring,string_tdb_data(si->description),TDB_REPLACE); - return WERR_OK; + return True; } /******************************************************************** + allocate an array of external services and return them. Null return + is okay, make sure &added is also zero! ********************************************************************/ -WERROR _svcctl_query_status(pipes_struct *p, SVCCTL_Q_QUERY_STATUS *q_u, SVCCTL_R_QUERY_STATUS *r_u) -{ - r_u->svc_status.type = 0x0020; - r_u->svc_status.state = 0x0004; - r_u->svc_status.controls_accepted = 0x0005; - - return WERR_OK; -} - -/* allocate an array of external services and return them. Null return is okay, make sure &added is also zero! */ - -int _svcctl_num_external_services(void) +static int num_external_services(void) { int num_services; char **svc_list; @@ -823,7 +470,7 @@ int _svcctl_num_external_services(void) number of services added. svc_ptr should have enough memory allocated to accommodate all of the services that exist. - Typically _svcctl_num_external_services is used to "size" the amount of + Typically num_external_services is used to "size" the amount of memory allocated, but does little/no work. enum_external_services() actually examines each of the specified @@ -835,7 +482,7 @@ int _svcctl_num_external_services(void) read for the service information. ********************************************************************/ -WERROR enum_external_services(TALLOC_CTX *tcx,ENUM_SERVICES_STATUS **svc_ptr, int existing_services,int *added) +static WERROR enum_external_services(TALLOC_CTX *tcx,ENUM_SERVICES_STATUS **svc_ptr, int existing_services,int *added) { /* *svc_ptr must have pre-allocated memory */ int num_services = 0; @@ -895,118 +542,475 @@ WERROR enum_external_services(TALLOC_CTX *tcx,ENUM_SERVICES_STATUS **svc_ptr, in } #endif - if (!svc_ptr || !(*svc_ptr)) - return WERR_NOMEM; - services = *svc_ptr; - if (existing_services > 0) { - i+=existing_services; + if (!svc_ptr || !(*svc_ptr)) + return WERR_NOMEM; + services = *svc_ptr; + if (existing_services > 0) { + i+=existing_services; + } + + svcname = svc_list; + DEBUG(8,("enum_external_services: enumerating %d external services starting at index %d\n", num_services,existing_services)); + + while (*svcname) { + DEBUG(10,("enum_external_services: Reading information on service %s, index %d\n",*svcname,i)); + /* get_LSB_data(*svcname,si); */ + if (!get_service_info(service_tdb,*svcname, si)) { + DEBUG(1,("enum_external_services: CAN'T FIND INFO FOR SERVICE %s in the services DB\n",*svcname)); + } + + if ((si->filename == NULL) || (*si->filename == 0)) { + init_unistr(&services[i].servicename, *svcname ); + } else { + init_unistr( &services[i].servicename, si->filename ); + /* init_unistr( &services[i].servicename, si->servicename ); */ + } + + if ((si->provides == NULL) || (*si->provides == 0)) { + init_unistr(&services[i].displayname, *svcname ); + } else { + init_unistr( &services[i].displayname, si->provides ); + } + + /* TODO - we could keep the following info in the DB, too... */ + + DEBUG(8,("enum_external_services: Service name [%s] displayname [%s]\n", + si->filename, si->provides)); + services[i].status.type = SVCCTL_WIN32_OWN_PROC; + services[i].status.win32_exit_code = 0x0; + services[i].status.service_exit_code = 0x0; + services[i].status.check_point = 0x0; + services[i].status.wait_hint = 0x0; + + /* TODO - do callout here to get the status */ + + memset(command, 0, sizeof(command)); + slprintf(command, sizeof(command)-1, "%s%s%s %s", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, *svcname, "status"); + + DEBUG(10, ("enum_external_services: status command is [%s]\n", command)); + + /* TODO - wrap in privilege check */ + + ret = smbrun(command, &fd); + DEBUGADD(10, ("returned [%d]\n", ret)); + close(fd); + if(ret != 0) + DEBUG(10, ("enum_external_services: Command returned [%d]\n", ret)); + services[i].status.state = SVCCTL_STOPPED; + if (ret == 0) { + services[i].status.state = SVCCTL_RUNNING; + services[i].status.controls_accepted = SVCCTL_CONTROL_SHUTDOWN | SVCCTL_CONTROL_STOP; + } else { + services[i].status.state = SVCCTL_STOPPED; + services[i].status.controls_accepted = 0; + } + svcname++; + i++; + } + + DEBUG(10,("enum_external_services: Read services %d\n",num_services)); + *added = num_services; + + return WERR_OK; +} + +int num_internal_services(void) +{ + int num_services; + char **svc_list; + pstring keystring, internal_services_string; + TDB_DATA key_data; + + if (!service_tdb) { + DEBUG(8,("enum_internal_services: service database is not open!!!\n")); + num_services = 0; + } else { + pstrcpy(keystring,"INTERNAL_SERVICES"); + tdb_lock_bystring(service_tdb, keystring, 0); + key_data = tdb_fetch_bystring(service_tdb, keystring); + + if ((key_data.dptr != NULL) && (key_data.dsize != 0)) { + strncpy(internal_services_string,key_data.dptr,key_data.dsize); + internal_services_string[key_data.dsize] = 0; + DEBUG(8,("enum_internal_services: services list is %s, size is %d\n",internal_services_string,key_data.dsize)); + } + tdb_unlock_bystring(service_tdb, keystring); + } + svc_list = str_list_make(internal_services_string,NULL); + + num_services = str_list_count( (const char **)svc_list); + + return num_services; +} + +/**************************************************************************** + Create/Open the service control manager tdb. This code a clone of init_group_mapping. +****************************************************************************/ + +BOOL init_svcctl_db(void) +{ + const char *vstring = "INFO/version"; + uint32 vers_id; + char **svc_list; + char **svcname; + pstring keystring; + pstring external_service_list; + pstring internal_service_list; + Service_info si; + const Internal_service_description *isd_ptr; + /* svc_list = str_list_make( "etc/init.d/skeleton etc/init.d/syslog", NULL ); */ + svc_list=(char **)lp_enable_svcctl(); + + if (service_tdb) + return True; + + pstrcpy(external_service_list,""); + + service_tdb = tdb_open_log(lock_path("services.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600); + if (!service_tdb) { + DEBUG(0,("Failed to open service db\n")); + service_tdb = tdb_open_log(lock_path("services.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); + if (!service_tdb) return False; + DEBUG(0,("Created new services db\n")); + } + + if ((-1 == tdb_fetch_uint32(service_tdb, vstring,&vers_id)) || (vers_id != SERVICEDB_VERSION_V1)) { + /* wrong version of DB, or db was just created */ + tdb_traverse(service_tdb, tdb_traverse_delete_fn, NULL); + tdb_store_uint32(service_tdb, vstring, SERVICEDB_VERSION_V1); + } + tdb_unlock_bystring(service_tdb, vstring); + + DEBUG(0,("Initializing services db\n")); + + svcname = svc_list; + + /* Get the EXTERNAL services as mentioned by line in smb.conf */ + + while (*svcname) { + DEBUG(10,("Reading information on service %s\n",*svcname)); + if (get_LSB_data(*svcname,&si));{ + /* write the information to the TDB */ + store_service_info(service_tdb,*svcname,&si); + /* definitely not efficient to do it this way. */ + pstrcat(external_service_list,"\""); + pstrcat(external_service_list,*svcname); + pstrcat(external_service_list,"\" "); + } + svcname++; + } + pstrcpy(keystring,"EXTERNAL_SERVICES"); + tdb_lock_bystring(service_tdb, keystring, 0); + DEBUG(8,("Storing external service list [%s]\n",external_service_list)); + tdb_store_bystring(service_tdb,keystring,string_tdb_data(external_service_list),TDB_REPLACE); + tdb_unlock_bystring(service_tdb,keystring); + + /* Get the INTERNAL services */ + + pstrcpy(internal_service_list,""); + isd_ptr = ISD; + + while (isd_ptr && (isd_ptr->filename)) { + DEBUG(10,("Reading information on service %s\n",isd_ptr->filename)); + if (get_internal_service_data(isd_ptr,&si)){ + /* write the information to the TDB */ + store_service_info(service_tdb,(char *)isd_ptr->filename,&si); + /* definitely not efficient to do it this way. */ + pstrcat(internal_service_list,"\""); + pstrcat(internal_service_list,isd_ptr->filename); + pstrcat(internal_service_list,"\" "); + + } + isd_ptr++; + } + pstrcpy(keystring,"INTERNAL_SERVICES"); + tdb_lock_bystring(service_tdb, keystring, 0); + DEBUG(8,("Storing internal service list [%s]\n",internal_service_list)); + tdb_store_bystring(service_tdb,keystring,string_tdb_data(internal_service_list),TDB_REPLACE); + tdb_unlock_bystring(service_tdb,keystring); + + return True; +} + +/******************************************************************** +********************************************************************/ + +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; +} + +/****************************************************************** + free() function for REGISTRY_KEY + *****************************************************************/ + +static void free_service_handle_info(void *ptr) +{ + SERVICE_INFO *info = (SERVICE_INFO*)ptr; + + SAFE_FREE(info->name); + SAFE_FREE(info); +} + +/****************************************************************** + 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 **)&service_info) ) { + DEBUG(2,("find_service_info_by_hnd: handle not found")); + return NULL; } - svcname = svc_list; - DEBUG(8,("enum_external_services: enumerating %d external services starting at index %d\n", num_services,existing_services)); + return service_info; +} - while (*svcname) { - DEBUG(10,("enum_external_services: Reading information on service %s, index %d\n",*svcname,i)); - /* _svcctl_get_LSB_data(*svcname,si); */ - if (!read_service_tdb_to_si(service_tdb,*svcname, si)) { - DEBUG(1,("enum_external_services: CAN'T FIND INFO FOR SERVICE %s in the services DB\n",*svcname)); - } +/****************************************************************** + *****************************************************************/ + +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; - if ((si->filename == NULL) || (*si->filename == 0)) { - init_unistr(&services[i].servicename, *svcname ); - } else { - init_unistr( &services[i].servicename, si->filename ); - /* init_unistr( &services[i].servicename, si->servicename ); */ + ZERO_STRUCTP( info ); + + /* the Service Manager has a NULL name */ + + if ( !service ) { + info->type = SVC_HANDLE_IS_SCM; + } else { + info->type = SVC_HANDLE_IS_SERVICE; + + if ( !(info->name = SMB_STRDUP( service )) ) { + free_service_handle_info( info ); + WERR_NOMEM; } + +#if 0 + /* lookup the SERVICE_CONTROL_OPS */ - if ((si->provides == NULL) || (*si->provides == 0)) { - init_unistr(&services[i].displayname, *svcname ); - } else { - init_unistr( &services[i].displayname, si->provides ); + for ( i=0; svcctl_ops[i].name; i++ ) { + ;; } +#endif + } - /* TODO - we could keep the following info in the DB, too... */ + 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 ) ) { + free_service_handle_info( info ); + return WERR_ACCESS_DENIED; + } + + return WERR_OK; +} - DEBUG(8,("enum_external_services: Service name [%s] displayname [%s]\n", - si->filename, si->provides)); - services[i].status.type = SVCCTL_WIN32_OWN_PROC; - services[i].status.win32_exit_code = 0x0; - services[i].status.service_exit_code = 0x0; - services[i].status.check_point = 0x0; - services[i].status.wait_hint = 0x0; +/******************************************************************** +********************************************************************/ - /* TODO - do callout here to get the status */ +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; + + 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 ); +} - memset(command, 0, sizeof(command)); - slprintf(command, sizeof(command)-1, "%s%s%s %s", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, *svcname, "status"); +/******************************************************************** +********************************************************************/ - DEBUG(10, ("enum_external_services: status command is [%s]\n", command)); +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; + SERVICE_INFO *scm_info; - /* TODO - wrap in privilege check */ + 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)); - ret = smbrun(command, &fd); - DEBUGADD(10, ("returned [%d]\n", ret)); - close(fd); - if(ret != 0) - DEBUG(10, ("enum_external_services: Command returned [%d]\n", ret)); - services[i].status.state = SVCCTL_STOPPED; - if (ret == 0) { - services[i].status.state = SVCCTL_RUNNING; - services[i].status.controls_accepted = SVCCTL_CONTROL_SHUTDOWN | SVCCTL_CONTROL_STOP; - } else { - services[i].status.state = SVCCTL_STOPPED; - services[i].status.controls_accepted = 0; - } - svcname++; - i++; - } + + /* based on my tests you can open a service if you have a valid scm handle */ + + if ( !(scm_info = find_service_info_by_hnd( p, &q_u->handle )) ) + return WERR_BADFID; + + /* 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 ( ! get_service_info(service_tdb, service, info) ) { + return WERR_NO_SUCH_SERVICE; +#endif + + return create_open_service_handle( p, &r_u->handle, service, access_granted ); +} - DEBUG(10,("enum_external_services: Read services %d\n",num_services)); - *added = num_services; +/******************************************************************** +********************************************************************/ - return WERR_OK; +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; } -int _svcctl_num_internal_services(void) +/******************************************************************** +********************************************************************/ + +WERROR _svcctl_get_display_name(pipes_struct *p, SVCCTL_Q_GET_DISPLAY_NAME *q_u, SVCCTL_R_GET_DISPLAY_NAME *r_u) { - int num_services; - char **svc_list; - pstring keystring, internal_services_string; - TDB_DATA key_data; + fstring service; + fstring displayname; + 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); - if (!service_tdb) { - DEBUG(8,("_svcctl_enum_internal_services: service database is not open!!!\n")); - num_services = 0; - } else { - pstrcpy(keystring,"INTERNAL_SERVICES"); - tdb_lock_bystring(service_tdb, keystring, 0); - key_data = tdb_fetch_bystring(service_tdb, keystring); + /* need a tdb lookup here or something */ + + fstrcpy( displayname, "FIX ME!" ); - if ((key_data.dptr != NULL) && (key_data.dsize != 0)) { - strncpy(internal_services_string,key_data.dptr,key_data.dsize); - internal_services_string[key_data.dsize] = 0; - DEBUG(8,("_svcctl_enum_internal_services: services list is %s, size is %d\n",internal_services_string,key_data.dsize)); - } - tdb_unlock_bystring(service_tdb, keystring); - } - svc_list = str_list_make(internal_services_string,NULL); - - num_services = str_list_count( (const char **)svc_list); + init_svcctl_r_get_display_name( r_u, displayname ); - return num_services; + return WERR_OK; } -#if 0 +/******************************************************************** +********************************************************************/ -int _svcctl_num_internal_services(void) +WERROR _svcctl_query_status(pipes_struct *p, SVCCTL_Q_QUERY_STATUS *q_u, SVCCTL_R_QUERY_STATUS *r_u) { - return 2; + 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; + + r_u->svc_status.type = 0x0020; + r_u->svc_status.state = 0x0004; + r_u->svc_status.controls_accepted = 0x0005; + + return WERR_OK; } -#endif -/* TODO - for internal services, do similar to external services, except we have to call the right status routine... */ -WERROR _svcctl_enum_internal_services(TALLOC_CTX *tcx,ENUM_SERVICES_STATUS **svc_ptr, int existing_services, int *added) +/********************************************************************* + TODO - for internal services, do similar to external services, except + we have to call the right status routine... +**********************************************************************/ + +static WERROR enum_internal_services(TALLOC_CTX *tcx,ENUM_SERVICES_STATUS **svc_ptr, int existing_services, int *added) { int num_services = 2; int i = 0; @@ -1020,7 +1024,7 @@ WERROR _svcctl_enum_internal_services(TALLOC_CTX *tcx,ENUM_SERVICES_STATUS **svc #if 0 /* *svc_ptr has the pointer to the array if there is one already. NULL if not. */ if ((existing_services>0) && svc_ptr && *svc_ptr) { /* reallocate vs. allocate */ - DEBUG(8,("_svcctl_enum_internal_services: REALLOCing %d services\n", num_services)); + DEBUG(8,("enum_internal_services: REALLOCing %d services\n", num_services)); services = TALLOC_REALLOC_ARRAY(tcx,*svc_ptr,ENUM_SERVICES_STATUS,existing_services+num_services); if (!rsvcs) return WERR_NOMEM; @@ -1034,7 +1038,7 @@ WERROR _svcctl_enum_internal_services(TALLOC_CTX *tcx,ENUM_SERVICES_STATUS **svc if (existing_services > 0) { i += existing_services; } - DEBUG(8,("_svcctl_enum_internal_services: Creating %d services, starting index %d\n", num_services,existing_services)); + DEBUG(8,("enum_internal_services: Creating %d services, starting index %d\n", num_services,existing_services)); init_unistr( &services[i].servicename, "Spooler" ); init_unistr( &services[i].displayname, "Print Spooler" ); @@ -1071,29 +1075,27 @@ WERROR _svcctl_enum_internal_services(TALLOC_CTX *tcx,ENUM_SERVICES_STATUS **svc return WERR_OK; } -WERROR _init_svcdb(void) -{ - if (svcdb) { - talloc_destroy(svcdb); - } - svcdb = talloc_init("services DB"); - - return WERR_OK; -} - /******************************************************************** ********************************************************************/ 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_int_services = 0; uint32 num_ext_services = 0; int i = 0; size_t buffer_size; WERROR result = WERR_OK; - WERROR ext_result = WERR_OK; + WERROR ext_result = WERR_OK; + SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); + + /* 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; /* num_services = str_list_count( lp_enable_svcctl() ); */ @@ -1103,14 +1105,14 @@ WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STAT num_int_services = 0; - num_int_services = _svcctl_num_internal_services(); + num_int_services = num_internal_services(); - num_ext_services = _svcctl_num_external_services(); + num_ext_services = num_external_services(); if ( !(services = TALLOC_ARRAY(p->mem_ctx, ENUM_SERVICES_STATUS, num_int_services+num_ext_services )) ) return WERR_NOMEM; - result = _svcctl_enum_internal_services(p->mem_ctx, &services, 0, &num_int_services); + result = enum_internal_services(p->mem_ctx, &services, 0, &num_int_services); if (W_ERROR_IS_OK(result)) { DEBUG(8,("_svcctl_enum_services_status: Got %d internal services\n", num_int_services)); @@ -1163,7 +1165,17 @@ WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STAT WERROR _svcctl_start_service(pipes_struct *p, SVCCTL_Q_START_SERVICE *q_u, SVCCTL_R_START_SERVICE *r_u) { - return WERR_ACCESS_DENIED; + 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_START) ) + return WERR_ACCESS_DENIED; + + return WERR_OK; } /******************************************************************** @@ -1171,6 +1183,20 @@ WERROR _svcctl_start_service(pipes_struct *p, SVCCTL_Q_START_SERVICE *q_u, SVCCT WERROR _svcctl_control_service(pipes_struct *p, SVCCTL_Q_CONTROL_SERVICE *q_u, SVCCTL_R_CONTROL_SERVICE *r_u) { + SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); + + /* perform access checks */ + /* we only support stop so don't get complicated */ + + if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) ) + return WERR_BADFID; + + if ( q_u->control != SVCCTL_CONTROL_STOP ) + return WERR_ACCESS_DENIED; + + if ( !(info->access_granted & SC_RIGHT_SVC_STOP) ) + return WERR_ACCESS_DENIED; + #if 0 SERVICE_INFO *service_info; POLICY_HND *handle; @@ -1244,7 +1270,16 @@ WERROR _svcctl_control_service(pipes_struct *p, SVCCTL_Q_CONTROL_SERVICE *q_u, S WERROR _svcctl_enum_dependent_services( pipes_struct *p, SVCCTL_Q_ENUM_DEPENDENT_SERVICES *q_u, SVCCTL_R_ENUM_DEPENDENT_SERVICES *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_ENUMERATE_DEPENDENTS) ) + return WERR_ACCESS_DENIED; + /* we have to set the outgoing buffer size to the same as the incoming buffer size (even in the case of failure */ @@ -1267,6 +1302,15 @@ WERROR _svcctl_query_service_status_ex( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_ POLICY_HND *handle; SERVICE_INFO *service_info; pstring command; + 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; /* we have to set the outgoing buffer size to the same as the incoming buffer size (even in the case of failure */ @@ -1343,6 +1387,15 @@ WERROR _svcctl_query_service_config( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CON POLICY_HND *handle; SERVICE_INFO *service_info; uint32 needed_size; + 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_CONFIG) ) + return WERR_ACCESS_DENIED; /* we have to set the outgoing buffer size to the same as the incoming buffer size (even in the case of failure */ @@ -1442,6 +1495,15 @@ WERROR _svcctl_query_service_config2( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CO POLICY_HND *handle; SERVICE_INFO *service_info; uint32 level; + 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_CONFIG) ) + return WERR_ACCESS_DENIED; /* we have to set the outgoing buffer size to the same as the incoming buffer size (even in the case of failure */ -- cgit