2011-01-31 18:40:33 +03:00
/*
* Unix SMB / CIFS implementation .
*
* SVC winreg glue
*
* Copyright ( c ) 2005 Marcin Krzysztof Porwit
* Copyright ( c ) 2005 Gerald ( Jerry ) Carter
* Copyright ( c ) 2011 Andreas Schneider < asn @ samba . org >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "services/services.h"
# include "services/svc_winreg_glue.h"
# include "rpc_client/cli_winreg_int.h"
# include "rpc_client/cli_winreg.h"
# include "../librpc/gen_ndr/ndr_winreg_c.h"
# include "../libcli/security/security.h"
# define TOP_LEVEL_SERVICES_KEY "SYSTEM\\CurrentControlSet\\Services"
struct security_descriptor * svcctl_gen_service_sd ( TALLOC_CTX * mem_ctx )
{
struct security_descriptor * sd = NULL ;
struct security_acl * theacl = NULL ;
struct security_ace ace [ 4 ] ;
size_t sd_size ;
size_t i = 0 ;
/* Basic access for everyone */
init_sec_ace ( & ace [ i + + ] , & global_sid_World ,
SEC_ACE_TYPE_ACCESS_ALLOWED , SERVICE_READ_ACCESS , 0 ) ;
init_sec_ace ( & ace [ i + + ] , & global_sid_Builtin_Power_Users ,
SEC_ACE_TYPE_ACCESS_ALLOWED , SERVICE_EXECUTE_ACCESS , 0 ) ;
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 ) ;
/* Create the security descriptor */
theacl = make_sec_acl ( mem_ctx ,
NT4_ACL_REVISION ,
i ,
ace ) ;
if ( theacl = = NULL ) {
return NULL ;
}
sd = make_sec_desc ( mem_ctx ,
SECURITY_DESCRIPTOR_REVISION_1 ,
SEC_DESC_SELF_RELATIVE ,
NULL ,
NULL ,
NULL ,
theacl ,
& sd_size ) ;
if ( sd = = NULL ) {
return NULL ;
}
return sd ;
}
struct security_descriptor * svcctl_get_secdesc ( TALLOC_CTX * mem_ctx ,
struct messaging_context * msg_ctx ,
2011-07-18 07:06:47 +04:00
const struct auth_session_info * session_info ,
2011-01-31 18:40:33 +03:00
const char * name )
{
struct dcerpc_binding_handle * h = NULL ;
uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED ;
struct policy_handle hive_hnd , key_hnd ;
struct security_descriptor * sd = NULL ;
char * key = NULL ;
NTSTATUS status ;
WERROR result = WERR_OK ;
key = talloc_asprintf ( mem_ctx ,
" %s \\ %s \\ Security " ,
TOP_LEVEL_SERVICES_KEY , name ) ;
if ( key = = NULL ) {
return NULL ;
}
status = dcerpc_winreg_int_hklm_openkey ( mem_ctx ,
2011-02-21 12:25:52 +03:00
session_info ,
2011-01-31 18:40:33 +03:00
msg_ctx ,
& h ,
key ,
false ,
access_mask ,
& hive_hnd ,
& key_hnd ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-02-01 13:49:33 +03:00
DEBUG ( 2 , ( " svcctl_set_secdesc: Could not open %s - %s \n " ,
2011-01-31 18:40:33 +03:00
key , nt_errstr ( status ) ) ) ;
return NULL ;
}
if ( ! W_ERROR_IS_OK ( result ) ) {
2011-02-01 13:49:33 +03:00
DEBUG ( 2 , ( " svcctl_set_secdesc: Could not open %s - %s \n " ,
2011-01-31 18:40:33 +03:00
key , win_errstr ( result ) ) ) ;
return NULL ;
}
status = dcerpc_winreg_query_sd ( mem_ctx ,
h ,
& key_hnd ,
" Security " ,
& sd ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-02-01 13:49:33 +03:00
DEBUG ( 2 , ( " svcctl_get_secdesc: error getting value 'Security': "
2011-01-31 18:40:33 +03:00
" %s \n " , nt_errstr ( status ) ) ) ;
return NULL ;
}
if ( W_ERROR_EQUAL ( result , WERR_BADFILE ) ) {
goto fallback_to_default_sd ;
} else if ( ! W_ERROR_IS_OK ( result ) ) {
2011-02-01 13:49:33 +03:00
DEBUG ( 2 , ( " svcctl_get_secdesc: error getting value 'Security': "
2011-01-31 18:40:33 +03:00
" %s \n " , win_errstr ( result ) ) ) ;
return NULL ;
}
goto done ;
fallback_to_default_sd :
DEBUG ( 6 , ( " svcctl_get_secdesc: constructing default secdesc for "
" service [%s] \n " , name ) ) ;
sd = svcctl_gen_service_sd ( mem_ctx ) ;
done :
return sd ;
}
bool svcctl_set_secdesc ( struct messaging_context * msg_ctx ,
2011-07-18 07:06:47 +04:00
const struct auth_session_info * session_info ,
2011-01-31 18:40:33 +03:00
const char * name ,
struct security_descriptor * sd )
{
struct dcerpc_binding_handle * h = NULL ;
uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED ;
2011-03-26 15:33:40 +03:00
struct policy_handle hive_hnd ;
struct policy_handle key_hnd = { 0 , } ;
2011-01-31 18:40:33 +03:00
char * key = NULL ;
bool ok = false ;
TALLOC_CTX * tmp_ctx ;
NTSTATUS status ;
WERROR result = WERR_OK ;
tmp_ctx = talloc_stackframe ( ) ;
if ( tmp_ctx = = NULL ) {
return false ;
}
key = talloc_asprintf ( tmp_ctx , " %s \\ %s " , TOP_LEVEL_SERVICES_KEY , name ) ;
if ( key = = NULL ) {
goto done ;
}
status = dcerpc_winreg_int_hklm_openkey ( tmp_ctx ,
2011-02-21 12:25:52 +03:00
session_info ,
2011-01-31 18:40:33 +03:00
msg_ctx ,
& h ,
key ,
false ,
access_mask ,
& hive_hnd ,
& key_hnd ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " svcctl_set_secdesc: Could not open %s - %s \n " ,
key , nt_errstr ( status ) ) ) ;
goto done ;
}
if ( ! W_ERROR_IS_OK ( result ) ) {
DEBUG ( 0 , ( " svcctl_set_secdesc: Could not open %s - %s \n " ,
key , win_errstr ( result ) ) ) ;
goto done ;
}
if ( is_valid_policy_hnd ( & key_hnd ) ) {
dcerpc_winreg_CloseKey ( h , tmp_ctx , & key_hnd , & result ) ;
}
{
enum winreg_CreateAction action = REG_ACTION_NONE ;
2011-03-15 12:54:59 +03:00
struct winreg_String wkey = { 0 , } ;
2011-01-31 18:40:33 +03:00
struct winreg_String wkeyclass ;
wkey . name = talloc_asprintf ( tmp_ctx , " %s \\ Security " , key ) ;
if ( wkey . name = = NULL ) {
result = WERR_NOMEM ;
goto done ;
}
ZERO_STRUCT ( wkeyclass ) ;
wkeyclass . name = " " ;
status = dcerpc_winreg_CreateKey ( h ,
tmp_ctx ,
& hive_hnd ,
wkey ,
wkeyclass ,
0 ,
access_mask ,
NULL ,
& key_hnd ,
& action ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-02-01 13:49:33 +03:00
DEBUG ( 2 , ( " svcctl_set_secdesc: Could not create key %s: %s \n " ,
2011-01-31 18:40:33 +03:00
wkey . name , nt_errstr ( status ) ) ) ;
goto done ;
}
if ( ! W_ERROR_IS_OK ( result ) ) {
2011-02-01 13:49:33 +03:00
DEBUG ( 2 , ( " svcctl_set_secdesc: Could not create key %s: %s \n " ,
2011-01-31 18:40:33 +03:00
wkey . name , win_errstr ( result ) ) ) ;
goto done ;
}
status = dcerpc_winreg_set_sd ( tmp_ctx ,
h ,
& key_hnd ,
" Security " ,
sd ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
if ( ! W_ERROR_IS_OK ( result ) ) {
goto done ;
}
}
ok = true ;
done :
if ( is_valid_policy_hnd ( & key_hnd ) ) {
dcerpc_winreg_CloseKey ( h , tmp_ctx , & key_hnd , & result ) ;
}
talloc_free ( tmp_ctx ) ;
return ok ;
}
const char * svcctl_get_string_value ( TALLOC_CTX * mem_ctx ,
struct messaging_context * msg_ctx ,
2011-07-18 07:06:47 +04:00
const struct auth_session_info * session_info ,
2011-01-31 18:40:33 +03:00
const char * key_name ,
const char * value_name )
{
struct dcerpc_binding_handle * h = NULL ;
uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED ;
struct policy_handle hive_hnd , key_hnd ;
const char * data = NULL ;
char * path = NULL ;
TALLOC_CTX * tmp_ctx ;
NTSTATUS status ;
WERROR result = WERR_OK ;
tmp_ctx = talloc_stackframe ( ) ;
if ( tmp_ctx = = NULL ) {
return NULL ;
}
path = talloc_asprintf ( tmp_ctx , " %s \\ %s " ,
TOP_LEVEL_SERVICES_KEY , key_name ) ;
if ( path = = NULL ) {
goto done ;
}
status = dcerpc_winreg_int_hklm_openkey ( tmp_ctx ,
2011-02-21 12:25:52 +03:00
session_info ,
2011-01-31 18:40:33 +03:00
msg_ctx ,
& h ,
path ,
false ,
access_mask ,
& hive_hnd ,
& key_hnd ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-02-01 13:49:33 +03:00
DEBUG ( 2 , ( " svcctl_get_string_value: Could not open %s - %s \n " ,
2011-01-31 18:40:33 +03:00
path , nt_errstr ( status ) ) ) ;
goto done ;
}
if ( ! W_ERROR_IS_OK ( result ) ) {
2011-02-01 13:49:33 +03:00
DEBUG ( 2 , ( " svcctl_get_string_value: Could not open %s - %s \n " ,
2011-01-31 18:40:33 +03:00
path , win_errstr ( result ) ) ) ;
goto done ;
}
status = dcerpc_winreg_query_sz ( mem_ctx ,
h ,
& key_hnd ,
value_name ,
& data ,
& result ) ;
done :
talloc_free ( tmp_ctx ) ;
return data ;
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
const char * svcctl_lookup_dispname ( TALLOC_CTX * mem_ctx ,
struct messaging_context * msg_ctx ,
2011-07-18 07:06:47 +04:00
const struct auth_session_info * session_info ,
2011-01-31 18:40:33 +03:00
const char * name )
{
const char * display_name = NULL ;
display_name = svcctl_get_string_value ( mem_ctx ,
msg_ctx ,
2011-02-21 12:25:52 +03:00
session_info ,
2011-01-31 18:40:33 +03:00
name ,
" DisplayName " ) ;
if ( display_name = = NULL ) {
display_name = talloc_strdup ( mem_ctx , name ) ;
}
return display_name ;
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
const char * svcctl_lookup_description ( TALLOC_CTX * mem_ctx ,
struct messaging_context * msg_ctx ,
2011-07-18 07:06:47 +04:00
const struct auth_session_info * session_info ,
2011-01-31 18:40:33 +03:00
const char * name )
{
const char * description = NULL ;
description = svcctl_get_string_value ( mem_ctx ,
msg_ctx ,
2011-02-21 12:25:52 +03:00
session_info ,
2011-01-31 18:40:33 +03:00
name ,
" Description " ) ;
if ( description = = NULL ) {
description = talloc_strdup ( mem_ctx , " Unix Service " ) ;
}
return description ;
}
/* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */