2005-06-15 00:54:43 +00:00
/*
* Unix SMB / CIFS implementation .
* Service Control API Implementation
2005-09-30 17:13:37 +00:00
*
2005-06-15 00:54:43 +00:00
* Copyright ( C ) Marcin Krzysztof Porwit 2005.
2005-09-30 17:13:37 +00:00
* Largely Rewritten by :
* Copyright ( C ) Gerald ( Jerry ) Carter 2005.
2005-06-15 00:54:43 +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-06-15 00:54:43 +00:00
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2007-07-10 05:23:25 +00:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2005-06-15 00:54:43 +00:00
*/
# include "includes.h"
2010-05-20 13:39:46 +02:00
# include "services/services.h"
2009-10-02 00:17:06 +02:00
# include "registry.h"
2010-09-21 08:11:18 +02:00
# include "registry/reg_api.h"
2010-09-20 02:43:33 +02:00
# include "registry/reg_api_util.h"
2010-10-12 15:27:50 +11:00
# include "../libcli/security/security.h"
2005-06-15 00:54:43 +00:00
2005-10-06 17:48:03 +00:00
struct rcinit_file_information {
char * description ;
} ;
struct service_display_info {
const char * servicename ;
const char * daemon ;
const char * dispname ;
const char * description ;
} ;
2007-11-20 17:57:47 -08:00
struct service_display_info builtin_svcs [ ] = {
2005-11-21 13:00:36 +00:00
{ " Spooler " , " smbd " , " Print Spooler " , " Internal service for spooling files to print devices " } ,
2005-12-16 01:41:25 +00:00
{ " NETLOGON " , " smbd " , " Net Logon " , " File service providing access to policy and profile data (not remotely manageable) " } ,
2005-11-21 13:00:36 +00:00
{ " RemoteRegistry " , " smbd " , " Remote Registry Service " , " Internal service providing remote access to "
" the Samba registry " } ,
{ " WINS " , " nmbd " , " Windows Internet Name Service (WINS) " , " Internal service providing a "
2005-12-16 01:41:25 +00:00
" NetBIOS point-to-point name server (not remotely manageable) " } ,
2005-10-06 17:48:03 +00:00
{ NULL , NULL , NULL , NULL }
} ;
2007-11-20 17:57:47 -08:00
struct service_display_info common_unix_svcs [ ] = {
2005-11-21 13:00:36 +00:00
{ " cups " , NULL , " Common Unix Printing System " , " Provides unified printing support for all operating systems " } ,
{ " postfix " , NULL , " Internet Mail Service " , " Provides support for sending and receiving electonic mail " } ,
{ " sendmail " , NULL , " Internet Mail Service " , " Provides support for sending and receiving electonic mail " } ,
{ " portmap " , NULL , " TCP Port to RPC PortMapper " , NULL } ,
{ " xinetd " , NULL , " Internet Meta-Daemon " , NULL } ,
{ " inet " , NULL , " Internet Meta-Daemon " , NULL } ,
{ " xntpd " , NULL , " Network Time Service " , NULL } ,
{ " ntpd " , NULL , " Network Time Service " , NULL } ,
{ " lpd " , NULL , " BSD Print Spooler " , NULL } ,
{ " nfsserver " , NULL , " Network File Service " , NULL } ,
{ " cron " , NULL , " Scheduling Service " , NULL } ,
{ " at " , NULL , " Scheduling Service " , NULL } ,
{ " nscd " , NULL , " Name Service Cache Daemon " , NULL } ,
{ " slapd " , NULL , " LDAP Directory Service " , NULL } ,
{ " ldap " , NULL , " LDAP DIrectory Service " , NULL } ,
{ " ypbind " , NULL , " NIS Directory Service " , NULL } ,
{ " courier-imap " , NULL , " IMAP4 Mail Service " , NULL } ,
{ " courier-pop3 " , NULL , " POP3 Mail Service " , NULL } ,
{ " named " , NULL , " Domain Name Service " , NULL } ,
{ " bind " , NULL , " Domain Name Service " , NULL } ,
{ " httpd " , NULL , " HTTP Server " , NULL } ,
{ " apache " , NULL , " HTTP Server " , " Provides s highly scalable and flexible web server "
" capable of implementing various protocols incluing "
" but not limited to HTTP " } ,
{ " autofs " , NULL , " Automounter " , NULL } ,
{ " squid " , NULL , " Web Cache Proxy " , NULL } ,
2005-11-08 16:33:45 +00:00
{ " perfcountd " , NULL , " Performance Monitoring Daemon " , NULL } ,
2005-11-21 13:00:36 +00:00
{ " pgsql " , NULL , " PgSQL Database Server " , " Provides service for SQL database from Postgresql.org " } ,
{ " arpwatch " , NULL , " ARP Tables watcher " , " Provides service for monitoring ARP tables for changes " } ,
{ " dhcpd " , NULL , " DHCP Server " , " Provides service for dynamic host configuration and IP assignment " } ,
{ " nwserv " , NULL , " NetWare Server Emulator " , " Provides service for emulating Novell NetWare 3.12 server " } ,
{ " proftpd " , NULL , " Professional FTP Server " , " Provides high configurable service for FTP connection and "
" file transferring " } ,
{ " ssh2 " , NULL , " SSH Secure Shell " , " Provides service for secure connection for remote administration " } ,
{ " sshd " , NULL , " SSH Secure Shell " , " Provides service for secure connection for remote administration " } ,
2005-10-06 17:48:03 +00:00
{ NULL , NULL , NULL , NULL }
} ;
2010-09-21 03:11:43 +02:00
static WERROR svcctl_set_secdesc_internal ( struct registry_key * key ,
struct security_descriptor * sec_desc ) ;
2005-10-06 17:48:03 +00:00
2005-09-30 17:13:37 +00:00
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-06-15 00:54:43 +00:00
2010-05-18 10:29:34 +02:00
static struct security_descriptor * construct_service_sd ( TALLOC_CTX * ctx )
2005-06-15 00:54:43 +00:00
{
2010-05-18 03:25:38 +02:00
struct security_ace ace [ 4 ] ;
2005-09-30 17:13:37 +00:00
size_t i = 0 ;
2010-05-18 10:29:34 +02:00
struct security_descriptor * sd = NULL ;
2010-05-18 03:30:40 +02:00
struct security_acl * theacl = NULL ;
2005-09-30 17:13:37 +00:00
size_t sd_size ;
2007-11-20 17:57:47 -08:00
2005-09-30 17:13:37 +00:00
/* basic access for Everyone */
2007-11-20 17:57:47 -08:00
2008-10-09 09:49:03 -07:00
init_sec_ace ( & ace [ i + + ] , & global_sid_World ,
SEC_ACE_TYPE_ACCESS_ALLOWED , SERVICE_READ_ACCESS , 0 ) ;
2007-11-20 17:57:47 -08:00
2008-10-09 09:49:03 -07:00
init_sec_ace ( & ace [ i + + ] , & global_sid_Builtin_Power_Users ,
SEC_ACE_TYPE_ACCESS_ALLOWED , SERVICE_EXECUTE_ACCESS , 0 ) ;
2007-11-20 17:57:47 -08:00
2008-10-09 09:49:03 -07:00
init_sec_ace ( & ace [ i + + ] , & global_sid_Builtin_Server_Operators ,
SEC_ACE_TYPE_ACCESS_ALLOWED , SERVICE_ALL_ACCESS , 0 ) ;
init_sec_ace ( & ace [ i + + ] , & global_sid_Builtin_Administrators ,
SEC_ACE_TYPE_ACCESS_ALLOWED , SERVICE_ALL_ACCESS , 0 ) ;
2007-11-20 17:57:47 -08:00
2005-09-30 17:13:37 +00:00
/* create the security descriptor */
2007-11-20 17:57:47 -08:00
2010-09-20 00:40:44 +02:00
theacl = make_sec_acl ( ctx , NT4_ACL_REVISION , i , ace ) ;
if ( theacl = = NULL ) {
2005-09-30 17:13:37 +00:00
return NULL ;
2010-09-20 00:40:44 +02:00
}
2005-06-15 00:54:43 +00:00
2010-09-20 00:40:44 +02:00
sd = make_sec_desc ( ctx , SECURITY_DESCRIPTOR_REVISION_1 ,
SEC_DESC_SELF_RELATIVE , NULL , NULL , NULL ,
theacl , & sd_size ) ;
if ( sd = = NULL ) {
2005-09-30 17:13:37 +00:00
return NULL ;
2010-09-20 00:40:44 +02:00
}
2005-06-15 00:54:43 +00:00
2005-09-30 17:13:37 +00:00
return sd ;
}
2005-06-15 00:54:43 +00:00
/********************************************************************
2005-09-30 17:13:37 +00:00
This is where we do the dirty work of filling in things like the
Display name , Description , etc . . .
2005-06-15 00:54:43 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-09-21 07:40:36 +02:00
static char * get_common_service_dispname ( TALLOC_CTX * mem_ctx ,
const char * servicename )
2005-10-06 17:48:03 +00:00
{
int i ;
2007-11-20 17:57:47 -08:00
2005-10-06 17:48:03 +00:00
for ( i = 0 ; common_unix_svcs [ i ] . servicename ; i + + ) {
2007-11-20 17:57:47 -08:00
if ( strequal ( servicename , common_unix_svcs [ i ] . servicename ) ) {
2007-12-17 18:00:43 -08:00
char * dispname ;
2010-09-21 07:40:36 +02:00
dispname = talloc_asprintf ( mem_ctx , " %s (%s) " ,
common_unix_svcs [ i ] . dispname ,
common_unix_svcs [ i ] . servicename ) ;
if ( dispname = = NULL ) {
2007-12-17 18:00:43 -08:00
return NULL ;
}
2005-10-06 17:48:03 +00:00
return dispname ;
}
2007-11-20 17:57:47 -08:00
}
2010-09-21 07:40:36 +02:00
return talloc_strdup ( mem_ctx , servicename ) ;
2005-10-06 17:48:03 +00:00
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-20 17:57:47 -08:00
static char * cleanup_string ( const char * string )
2005-10-06 17:48:03 +00:00
{
2007-11-20 17:57:47 -08:00
char * clean = NULL ;
2005-10-06 17:48:03 +00:00
char * begin , * end ;
2007-11-20 17:57:47 -08:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2005-10-06 17:48:03 +00:00
2007-11-20 17:57:47 -08:00
clean = talloc_strdup ( ctx , string ) ;
if ( ! clean ) {
return NULL ;
}
2005-10-06 17:48:03 +00:00
begin = clean ;
2007-11-20 17:57:47 -08:00
2005-10-06 17:48:03 +00:00
/* trim any beginning whilespace */
2007-11-20 17:57:47 -08:00
while ( isspace ( * begin ) ) {
2005-10-06 17:48:03 +00:00
begin + + ;
2007-11-20 17:57:47 -08:00
}
2005-10-06 17:48:03 +00:00
2007-11-20 17:57:47 -08:00
if ( * begin = = ' \0 ' ) {
2005-10-06 17:48:03 +00:00
return NULL ;
2007-11-20 17:57:47 -08:00
}
2005-10-06 17:48:03 +00:00
/* trim any trailing whitespace or carriage returns.
Start at the end and move backwards */
2007-11-20 17:57:47 -08:00
2005-10-06 17:48:03 +00:00
end = begin + strlen ( begin ) - 1 ;
2007-11-20 17:57:47 -08:00
2005-10-06 17:48:03 +00:00
while ( isspace ( * end ) | | * end = = ' \n ' | | * end = = ' \r ' ) {
* end = ' \0 ' ;
end - - ;
}
2007-11-20 17:57:47 -08:00
return begin ;
2005-10-06 17:48:03 +00:00
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-18 17:40:25 -07:00
static bool read_init_file ( const char * servicename , struct rcinit_file_information * * service_info )
2005-10-06 17:48:03 +00:00
{
2008-09-17 12:02:13 -07:00
struct rcinit_file_information * info = NULL ;
2007-11-20 17:57:47 -08:00
char * filepath = NULL ;
char str [ 1024 ] ;
2008-09-17 12:02:13 -07:00
XFILE * f = NULL ;
char * p = NULL ;
2007-11-20 17:57:47 -08:00
2010-09-20 00:46:59 +02:00
info = TALLOC_ZERO_P ( NULL , struct rcinit_file_information ) ;
if ( info = = NULL ) {
2005-10-06 17:48:03 +00:00
return False ;
2010-09-20 00:46:59 +02:00
}
2007-11-20 17:57:47 -08:00
2005-10-06 17:48:03 +00:00
/* attempt the file open */
2007-11-20 17:57:47 -08:00
2008-08-15 00:50:56 +02:00
filepath = talloc_asprintf ( info , " %s/%s/%s " , get_dyn_MODULESDIR ( ) ,
2007-11-20 17:57:47 -08:00
SVCCTL_SCRIPT_DIR , servicename ) ;
if ( ! filepath ) {
TALLOC_FREE ( info ) ;
return false ;
}
2010-09-20 00:46:59 +02:00
f = x_fopen ( filepath , O_RDONLY , 0 ) ;
if ( f = = NULL ) {
2005-10-06 17:48:03 +00:00
DEBUG ( 0 , ( " read_init_file: failed to open [%s] \n " , filepath ) ) ;
TALLOC_FREE ( info ) ;
2007-11-20 17:57:47 -08:00
return false ;
2005-10-06 17:48:03 +00:00
}
2007-11-20 17:57:47 -08:00
2005-10-13 13:20:26 +00:00
while ( ( x_fgets ( str , sizeof ( str ) - 1 , f ) ) ! = NULL ) {
2007-11-20 17:57:47 -08:00
/* ignore everything that is not a full line
2005-10-06 17:48:03 +00:00
comment starting with a ' # ' */
2007-11-20 17:57:47 -08:00
2005-10-06 17:48:03 +00:00
if ( str [ 0 ] ! = ' # ' )
continue ;
2007-11-20 17:57:47 -08:00
2005-10-06 17:48:03 +00:00
/* Look for a line like '^#.*Description:' */
2007-11-20 17:57:47 -08:00
2010-09-20 00:46:59 +02:00
p = strstr ( str , " Description: " ) ;
if ( p ! = NULL ) {
2005-10-06 17:48:03 +00:00
char * desc ;
p + = strlen ( " Description: " ) + 1 ;
2007-11-20 17:57:47 -08:00
if ( ! p )
2005-10-06 17:48:03 +00:00
break ;
2007-11-20 17:57:47 -08:00
2010-09-20 00:46:59 +02:00
desc = cleanup_string ( p ) ;
if ( desc ! = NULL )
2005-10-06 17:48:03 +00:00
info - > description = talloc_strdup ( info , desc ) ;
}
}
2007-11-20 17:57:47 -08:00
2005-10-06 17:48:03 +00:00
x_fclose ( f ) ;
2007-11-20 17:57:47 -08:00
2005-10-06 17:48:03 +00:00
if ( ! info - > description )
info - > description = talloc_strdup ( info , " External Unix Service " ) ;
2007-11-20 17:57:47 -08:00
2005-10-06 17:48:03 +00:00
* service_info = info ;
2007-11-20 17:57:47 -08:00
TALLOC_FREE ( filepath ) ;
2005-10-06 17:48:03 +00:00
return True ;
}
/********************************************************************
This is where we do the dirty work of filling in things like the
Display name , Description , etc . . .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-09-21 06:48:19 +02:00
static WERROR svcctl_setvalue ( struct registry_key * key ,
const char * name ,
struct registry_value * value )
{
WERROR wresult ;
wresult = reg_setvalue ( key , name , value ) ;
if ( ! W_ERROR_IS_OK ( wresult ) ) {
DEBUG ( 0 , ( " reg_setvalue failed for %s in key %s: %s \n " ,
name , key - > key - > name , win_errstr ( wresult ) ) ) ;
}
return wresult ;
}
static WERROR svcctl_setvalue_dword ( struct registry_key * key ,
const char * name ,
uint32_t dword )
{
struct registry_value value ;
value . type = REG_DWORD ;
value . data . length = sizeof ( uint32_t ) ;
value . data . data = ( uint8_t * ) & dword ;
return svcctl_setvalue ( key , name , & value ) ;
}
static WERROR svcctl_setvalue_sz ( struct registry_key * key ,
const char * name ,
const char * sz )
{
struct registry_value value ;
WERROR wresult ;
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
if ( ! push_reg_sz ( mem_ctx , & value . data , sz ) ) {
DEBUG ( 0 , ( " push_reg_sz failed \n " ) ) ;
wresult = WERR_NOMEM ;
goto done ;
}
value . type = REG_SZ ;
wresult = svcctl_setvalue ( key , name , & value ) ;
done :
talloc_free ( mem_ctx ) ;
return wresult ;
}
static void fill_service_values ( struct registry_key * key )
2005-06-15 00:54:43 +00:00
{
2009-09-24 15:01:32 +02:00
char * dname , * ipath , * description ;
2005-10-06 17:48:03 +00:00
int i ;
2010-09-21 06:48:19 +02:00
WERROR wresult ;
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
char * name = NULL ;
name = strrchr ( key - > key - > name , ' \\ ' ) ;
if ( name = = NULL ) {
name = key - > key - > name ;
} else {
name + + ;
}
2007-11-20 17:57:47 -08:00
2005-09-30 17:13:37 +00:00
/* These values are hardcoded in all QueryServiceConfig() replies.
I ' m just storing them here for cosmetic purposes */
2007-11-20 17:57:47 -08:00
2010-09-21 06:48:19 +02:00
wresult = svcctl_setvalue_dword ( key , " Start " , SVCCTL_AUTO_START ) ;
if ( ! W_ERROR_IS_OK ( wresult ) ) {
goto done ;
}
2007-11-20 17:57:47 -08:00
2010-09-21 06:48:19 +02:00
wresult = svcctl_setvalue_dword ( key , " Type " , SERVICE_TYPE_WIN32_OWN_PROCESS ) ;
if ( ! W_ERROR_IS_OK ( wresult ) ) {
goto done ;
}
2005-06-15 00:54:43 +00:00
2010-09-21 06:48:19 +02:00
wresult = svcctl_setvalue_dword ( key , " ErrorControl " , SVCCTL_SVC_ERROR_NORMAL ) ;
if ( ! W_ERROR_IS_OK ( wresult ) ) {
goto done ;
}
2007-11-20 17:57:47 -08:00
2005-09-30 17:13:37 +00:00
/* everything runs as LocalSystem */
2007-11-20 17:57:47 -08:00
2010-09-21 06:48:19 +02:00
wresult = svcctl_setvalue_sz ( key , " ObjectName " , " LocalSystem " ) ;
if ( ! W_ERROR_IS_OK ( wresult ) ) {
goto done ;
}
2007-11-20 17:57:47 -08:00
2005-09-30 17:13:37 +00:00
/* special considerations for internal services and the DisplayName value */
2007-11-20 17:57:47 -08:00
2005-10-06 17:48:03 +00:00
for ( i = 0 ; builtin_svcs [ i ] . servicename ; i + + ) {
if ( strequal ( name , builtin_svcs [ i ] . servicename ) ) {
2010-09-21 06:48:19 +02:00
ipath = talloc_asprintf ( mem_ctx , " %s/%s/%s " ,
get_dyn_MODULESDIR ( ) ,
SVCCTL_SCRIPT_DIR ,
builtin_svcs [ i ] . daemon ) ;
description = talloc_strdup ( mem_ctx , builtin_svcs [ i ] . description ) ;
dname = talloc_strdup ( mem_ctx , builtin_svcs [ i ] . dispname ) ;
2005-10-06 17:48:03 +00:00
break ;
}
2007-11-20 17:57:47 -08:00
}
2005-10-06 17:48:03 +00:00
/* default to an external service if we haven't found a match */
2007-11-20 17:57:47 -08:00
2005-10-06 17:48:03 +00:00
if ( builtin_svcs [ i ] . servicename = = NULL ) {
2007-12-17 18:00:43 -08:00
char * dispname = NULL ;
2005-10-06 17:48:03 +00:00
struct rcinit_file_information * init_info = NULL ;
2010-09-21 06:48:19 +02:00
ipath = talloc_asprintf ( mem_ctx , " %s/%s/%s " ,
2009-09-24 15:01:32 +02:00
get_dyn_MODULESDIR ( ) , SVCCTL_SCRIPT_DIR ,
name ) ;
2007-11-20 17:57:47 -08:00
2005-10-06 17:48:03 +00:00
/* lookup common unix display names */
2010-09-21 07:40:36 +02:00
dispname = get_common_service_dispname ( mem_ctx , name ) ;
2010-09-21 06:48:19 +02:00
dname = talloc_strdup ( mem_ctx , dispname ? dispname : " " ) ;
2005-10-06 17:48:03 +00:00
2007-11-20 17:57:47 -08:00
/* get info from init file itself */
2005-10-06 17:48:03 +00:00
if ( read_init_file ( name , & init_info ) ) {
2010-09-21 06:48:19 +02:00
description = talloc_strdup ( mem_ctx , init_info - > description ) ;
2005-10-06 17:48:03 +00:00
TALLOC_FREE ( init_info ) ;
}
else {
2010-09-21 06:48:19 +02:00
description = talloc_strdup ( mem_ctx , " External Unix Service " ) ;
2005-10-06 17:48:03 +00:00
}
2005-09-30 17:13:37 +00:00
}
2007-11-20 17:57:47 -08:00
2005-10-06 17:48:03 +00:00
/* add the new values */
2007-11-20 17:57:47 -08:00
2010-09-21 06:48:19 +02:00
wresult = svcctl_setvalue_sz ( key , " DisplayName " , dname ) ;
if ( ! W_ERROR_IS_OK ( wresult ) ) {
goto done ;
}
2009-09-24 15:01:32 +02:00
2010-09-21 06:48:19 +02:00
wresult = svcctl_setvalue_sz ( key , " ImagePath " , ipath ) ;
if ( ! W_ERROR_IS_OK ( wresult ) ) {
goto done ;
}
2007-11-20 17:57:47 -08:00
2010-09-21 06:48:19 +02:00
wresult = svcctl_setvalue_sz ( key , " Description " , description ) ;
done :
talloc_free ( mem_ctx ) ;
2005-09-30 17:13:37 +00:00
return ;
2005-06-15 00:54:43 +00:00
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-09-21 06:48:19 +02:00
static void add_new_svc_name ( struct registry_key * key_parent ,
const char * name )
2005-06-15 00:54:43 +00:00
{
2010-09-21 06:48:19 +02:00
struct registry_key * key_service = NULL , * key_secdesc = NULL ;
2005-09-30 17:13:37 +00:00
WERROR wresult ;
2010-05-18 10:29:34 +02:00
struct security_descriptor * sd = NULL ;
2010-09-21 06:48:19 +02:00
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
enum winreg_CreateAction action = REG_ACTION_NONE ;
2005-09-30 17:13:37 +00:00
2010-09-21 06:48:19 +02:00
wresult = reg_createkey ( mem_ctx , key_parent , name , REG_KEY_ALL ,
& key_service , & action ) ;
2005-09-30 17:13:37 +00:00
2009-02-24 23:23:04 +01:00
if ( ! W_ERROR_IS_OK ( wresult ) ) {
2010-09-21 06:48:19 +02:00
DEBUG ( 0 , ( " add_new_svc_name: reg_createkey failed for %s \\ %s: "
" %s \n " , key_parent - > key - > name , name ,
win_errstr ( wresult ) ) ) ;
goto done ;
2005-06-15 00:54:43 +00:00
}
2007-11-20 17:57:47 -08:00
2005-09-30 17:13:37 +00:00
/* now for the service values */
2007-11-20 17:57:47 -08:00
2010-09-21 06:48:19 +02:00
fill_service_values ( key_service ) ;
2005-09-30 17:13:37 +00:00
/* now add the security descriptor */
2005-06-15 00:54:43 +00:00
2010-09-21 06:48:19 +02:00
sd = construct_service_sd ( key_secdesc ) ;
if ( sd = = NULL ) {
DEBUG ( 0 , ( " add_new_svc_name: Failed to create default "
" sec_desc! \n " ) ) ;
goto done ;
2005-09-30 17:13:37 +00:00
}
2007-11-20 17:57:47 -08:00
2010-09-21 06:48:19 +02:00
wresult = svcctl_set_secdesc_internal ( key_service , sd ) ;
2005-06-15 00:54:43 +00:00
2010-09-21 06:48:19 +02:00
done :
talloc_free ( mem_ctx ) ;
2005-09-30 17:13:37 +00:00
return ;
2005-06-15 00:54:43 +00:00
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 17:13:37 +00:00
void svcctl_init_keys ( void )
2005-06-15 00:54:43 +00:00
{
2005-09-30 17:13:37 +00:00
const char * * service_list = lp_svcctl_list ( ) ;
int i ;
2010-09-21 06:48:19 +02:00
struct registry_key * key = NULL ;
struct registry_key * subkey = NULL ;
2005-09-30 17:13:37 +00:00
WERROR wresult ;
2010-09-21 06:48:19 +02:00
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
2007-11-20 17:57:47 -08:00
2005-09-30 17:13:37 +00:00
/* bad mojo here if the lookup failed. Should not happen */
2007-11-20 17:57:47 -08:00
2010-09-21 06:48:19 +02:00
wresult = reg_open_path ( mem_ctx , KEY_SERVICES , REG_KEY_ALL , get_root_nt_token ( ) , & key ) ;
2005-06-15 00:54:43 +00:00
2005-09-30 17:13:37 +00:00
if ( ! W_ERROR_IS_OK ( wresult ) ) {
2007-11-20 17:57:47 -08:00
DEBUG ( 0 , ( " svcctl_init_keys: key lookup failed! (%s) \n " ,
2008-11-01 17:19:26 +01:00
win_errstr ( wresult ) ) ) ;
2010-09-21 06:48:19 +02:00
goto done ;
2005-09-30 17:13:37 +00:00
}
2007-11-20 17:57:47 -08:00
2008-02-18 16:58:24 +01:00
/* the builtin services exist */
2007-11-20 17:57:47 -08:00
2005-10-06 17:48:03 +00:00
for ( i = 0 ; builtin_svcs [ i ] . servicename ; i + + )
2010-09-21 06:48:19 +02:00
add_new_svc_name ( key , builtin_svcs [ i ] . servicename ) ;
2007-11-20 17:57:47 -08:00
2006-02-08 15:09:09 +00:00
for ( i = 0 ; service_list & & service_list [ i ] ; i + + ) {
2007-11-20 17:57:47 -08:00
2005-09-30 17:13:37 +00:00
/* only add new services */
2010-09-21 06:48:19 +02:00
wresult = reg_openkey ( mem_ctx , key , service_list [ i ] , REG_KEY_ALL , & subkey ) ;
if ( W_ERROR_IS_OK ( wresult ) ) {
2005-09-30 17:13:37 +00:00
continue ;
2010-09-21 06:48:19 +02:00
}
2005-06-15 00:54:43 +00:00
2005-09-30 17:13:37 +00:00
/* Add the new service key and initialize the appropriate values */
2005-06-15 00:54:43 +00:00
2010-09-21 06:48:19 +02:00
add_new_svc_name ( key , service_list [ i ] ) ;
2005-06-15 00:54:43 +00:00
}
2005-09-30 17:13:37 +00:00
/* initialize the control hooks */
2005-06-15 00:54:43 +00:00
2005-09-30 17:13:37 +00:00
init_service_op_table ( ) ;
2005-06-15 00:54:43 +00:00
2010-09-21 06:48:19 +02:00
done :
talloc_free ( mem_ctx ) ;
2005-09-30 17:13:37 +00:00
return ;
2005-06-15 00:54:43 +00:00
}
/********************************************************************
2005-09-30 17:13:37 +00:00
This is where we do the dirty work of filling in things like the
2007-11-20 17:57:47 -08:00
Display name , Description , etc . . . Always return a default secdesc
2005-09-30 17:13:37 +00:00
in case of any failure .
2005-06-15 00:54:43 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-08-26 22:08:22 +10:00
struct security_descriptor * svcctl_get_secdesc ( TALLOC_CTX * ctx , const char * name , struct security_token * token )
2005-06-15 00:54:43 +00:00
{
2010-09-20 04:41:59 +02:00
struct registry_key * key = NULL ;
struct registry_value * value ;
2010-05-18 10:29:34 +02:00
struct security_descriptor * ret_sd = NULL ;
2007-11-20 17:57:47 -08:00
char * path = NULL ;
2005-09-30 17:13:37 +00:00
WERROR wresult ;
2007-10-07 12:56:43 +00:00
NTSTATUS status ;
2010-09-20 04:12:42 +02:00
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
2007-11-20 17:57:47 -08:00
2010-09-20 04:12:42 +02:00
path = talloc_asprintf ( mem_ctx , " %s \\ %s \\ %s " , KEY_SERVICES , name ,
" Security " ) ;
if ( path = = NULL ) {
goto done ;
2007-11-20 17:57:47 -08:00
}
2010-09-20 04:12:42 +02:00
2010-09-20 04:41:59 +02:00
wresult = reg_open_path ( mem_ctx , path , REG_KEY_ALL , token , & key ) ;
2005-09-30 17:13:37 +00:00
if ( ! W_ERROR_IS_OK ( wresult ) ) {
2007-11-20 17:57:47 -08:00
DEBUG ( 0 , ( " svcctl_get_secdesc: key lookup failed! [%s] (%s) \n " ,
2008-11-01 17:19:26 +01:00
path , win_errstr ( wresult ) ) ) ;
2008-02-18 17:38:19 +01:00
goto done ;
2005-09-30 17:13:37 +00:00
}
2005-06-15 00:54:43 +00:00
2010-09-20 04:41:59 +02:00
wresult = reg_queryvalue ( mem_ctx , key , " Security " , & value ) ;
if ( W_ERROR_EQUAL ( wresult , WERR_BADFILE ) ) {
2008-02-18 17:38:19 +01:00
goto fallback_to_default_sd ;
2010-09-20 04:41:59 +02:00
} else if ( ! W_ERROR_IS_OK ( wresult ) ) {
DEBUG ( 0 , ( " svcctl_get_secdesc: error getting value 'Security': "
" %s \n " , win_errstr ( wresult ) ) ) ;
goto done ;
2005-09-30 17:13:37 +00:00
}
2005-06-15 00:54:43 +00:00
2010-09-20 04:41:59 +02:00
status = unmarshall_sec_desc ( ctx , value - > data . data ,
value - > data . length , & ret_sd ) ;
2007-10-07 12:56:43 +00:00
2008-02-18 17:38:19 +01:00
if ( NT_STATUS_IS_OK ( status ) ) {
goto done ;
2005-09-30 17:13:37 +00:00
}
2005-06-15 00:54:43 +00:00
2008-02-18 17:38:19 +01:00
fallback_to_default_sd :
DEBUG ( 6 , ( " svcctl_get_secdesc: constructing default secdesc for "
" service [%s] \n " , name ) ) ;
ret_sd = construct_service_sd ( ctx ) ;
done :
2010-09-20 04:12:42 +02:00
talloc_free ( mem_ctx ) ;
2005-09-30 17:13:37 +00:00
return ret_sd ;
}
2005-06-15 00:54:43 +00:00
2006-01-13 20:24:50 +00:00
/********************************************************************
Wrapper to make storing a Service sd easier
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-09-21 03:11:43 +02:00
static WERROR svcctl_set_secdesc_internal ( struct registry_key * key ,
struct security_descriptor * sec_desc )
2006-01-13 20:24:50 +00:00
{
2010-09-21 03:00:29 +02:00
struct registry_key * key_security = NULL ;
2006-01-13 20:24:50 +00:00
WERROR wresult ;
2010-09-20 02:43:33 +02:00
struct registry_value value ;
2009-02-05 02:54:05 +01:00
NTSTATUS status ;
2010-09-21 03:00:29 +02:00
enum winreg_CreateAction action = REG_ACTION_NONE ;
2010-09-21 03:11:43 +02:00
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
2006-01-13 20:24:50 +00:00
2010-09-21 03:00:29 +02:00
wresult = reg_createkey ( mem_ctx , key , " Security " , REG_KEY_ALL , & key_security , & action ) ;
if ( ! W_ERROR_IS_OK ( wresult ) ) {
DEBUG ( 0 , ( " svcctl_set_secdesc: reg_createkey failed: "
" [%s \\ Security] (%s) \n " , key - > key - > name ,
win_errstr ( wresult ) ) ) ;
goto done ;
}
2010-09-20 03:34:49 +02:00
status = marshall_sec_desc ( mem_ctx , sec_desc , & value . data . data ,
& value . data . length ) ;
2009-02-05 02:54:05 +01:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-09-21 03:11:43 +02:00
DEBUG ( 0 , ( " svcctl_set_secdesc: marshall_sec_desc() failed: %s \n " ,
nt_errstr ( status ) ) ) ;
wresult = ntstatus_to_werror ( status ) ;
2010-09-20 03:34:49 +02:00
goto done ;
2008-03-14 14:26:28 -08:00
}
2007-11-20 17:57:47 -08:00
2010-09-20 02:43:33 +02:00
value . type = REG_BINARY ;
2010-09-21 03:00:29 +02:00
wresult = reg_setvalue ( key_security , " Security " , & value ) ;
2010-09-20 02:43:33 +02:00
if ( ! W_ERROR_IS_OK ( wresult ) ) {
DEBUG ( 0 , ( " svcctl_set_secdesc: reg_setvalue failed: %s \n " ,
win_errstr ( wresult ) ) ) ;
2010-09-21 03:11:43 +02:00
}
done :
talloc_free ( mem_ctx ) ;
return wresult ;
}
bool svcctl_set_secdesc ( const char * name , struct security_descriptor * sec_desc ,
struct security_token * token )
{
struct registry_key * key = NULL ;
WERROR wresult ;
char * path = NULL ;
bool ret = false ;
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
path = talloc_asprintf ( mem_ctx , " %s \\ %s " , KEY_SERVICES , name ) ;
if ( path = = NULL ) {
2010-09-20 03:34:49 +02:00
goto done ;
2010-09-20 02:43:33 +02:00
}
2007-11-20 17:57:47 -08:00
2010-09-21 03:11:43 +02:00
wresult = reg_open_path ( mem_ctx , path , REG_KEY_ALL , token , & key ) ;
if ( ! W_ERROR_IS_OK ( wresult ) ) {
DEBUG ( 0 , ( " svcctl_set_secdesc: key lookup failed! [%s] (%s) \n " ,
path , win_errstr ( wresult ) ) ) ;
goto done ;
}
wresult = svcctl_set_secdesc_internal ( key , sec_desc ) ;
ret = W_ERROR_IS_OK ( wresult ) ;
2006-01-13 20:24:50 +00:00
2010-09-20 03:34:49 +02:00
done :
talloc_free ( mem_ctx ) ;
2006-01-13 20:24:50 +00:00
return ret ;
}
2010-09-20 10:27:56 +02:00
const char * svcctl_get_string_value ( TALLOC_CTX * ctx , const char * key_name ,
const char * value_name ,
struct security_token * token )
2005-09-30 17:13:37 +00:00
{
2010-09-20 08:06:30 +02:00
const char * result = NULL ;
2010-09-20 08:11:07 +02:00
struct registry_key * key = NULL ;
struct registry_value * value = NULL ;
2007-11-20 17:57:47 -08:00
char * path = NULL ;
2005-09-30 17:13:37 +00:00
WERROR wresult ;
2010-09-20 04:58:27 +02:00
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
2007-11-20 17:57:47 -08:00
2010-09-20 08:06:30 +02:00
path = talloc_asprintf ( mem_ctx , " %s \\ %s " , KEY_SERVICES , key_name ) ;
2010-09-20 04:58:27 +02:00
if ( path = = NULL ) {
goto done ;
2007-11-20 17:57:47 -08:00
}
2010-09-20 08:11:07 +02:00
wresult = reg_open_path ( mem_ctx , path , REG_KEY_READ , token , & key ) ;
if ( ! W_ERROR_IS_OK ( wresult ) ) {
2010-09-20 08:06:30 +02:00
DEBUG ( 0 , ( " svcctl_get_string_value: key lookup failed! "
" [%s] (%s) \n " , path , win_errstr ( wresult ) ) ) ;
goto done ;
2005-09-30 17:13:37 +00:00
}
2005-06-15 00:54:43 +00:00
2010-09-20 08:06:30 +02:00
wresult = reg_queryvalue ( mem_ctx , key , value_name , & value ) ;
2010-05-24 14:03:46 +02:00
if ( ! W_ERROR_IS_OK ( wresult ) ) {
2010-09-20 08:06:30 +02:00
DEBUG ( 0 , ( " svcctl_get_string_value: error getting value "
" '%s': %s \n " , value_name , win_errstr ( wresult ) ) ) ;
goto done ;
2005-09-30 17:13:37 +00:00
}
2005-06-15 00:54:43 +00:00
2010-09-20 08:11:07 +02:00
if ( value - > type ! = REG_SZ ) {
2010-09-20 08:06:30 +02:00
goto done ;
2010-09-20 08:11:07 +02:00
}
2005-10-06 17:48:03 +00:00
2010-09-20 08:06:30 +02:00
pull_reg_sz ( ctx , & value - > data , & result ) ;
2005-06-15 00:54:43 +00:00
2010-09-20 04:58:27 +02:00
goto done ;
2005-10-06 17:48:03 +00:00
2010-09-20 04:58:27 +02:00
done :
talloc_free ( mem_ctx ) ;
2010-09-20 08:06:30 +02:00
return result ;
2005-06-15 00:54:43 +00:00
}
2005-09-30 17:13:37 +00:00
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-06-15 00:54:43 +00:00
2010-09-20 08:06:30 +02:00
const char * svcctl_lookup_dispname ( TALLOC_CTX * ctx , const char * name , struct security_token * token )
2005-06-15 00:54:43 +00:00
{
2010-09-20 08:06:30 +02:00
const char * display_name = NULL ;
2007-11-20 17:57:47 -08:00
2010-09-20 08:06:30 +02:00
display_name = svcctl_get_string_value ( ctx , name , " DisplayName " , token ) ;
2010-09-20 06:03:58 +02:00
2010-09-20 08:06:30 +02:00
if ( display_name = = NULL ) {
display_name = talloc_strdup ( ctx , name ) ;
2005-06-15 00:54:43 +00:00
}
2010-09-20 08:06:30 +02:00
return display_name ;
}
2005-06-15 00:54:43 +00:00
2010-09-20 08:06:30 +02:00
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-09-30 20:00:52 +02:00
2010-09-20 08:06:30 +02:00
const char * svcctl_lookup_description ( TALLOC_CTX * ctx , const char * name , struct security_token * token )
{
const char * description = NULL ;
2010-09-20 06:19:57 +02:00
2010-09-20 08:06:30 +02:00
description = svcctl_get_string_value ( ctx , name , " Description " , token ) ;
2010-09-20 06:19:57 +02:00
2010-09-20 08:06:30 +02:00
if ( description = = NULL ) {
description = talloc_strdup ( ctx , " Unix Service " ) ;
}
2009-09-30 20:00:52 +02:00
2005-09-30 17:13:37 +00:00
return description ;
}