2008-02-29 19:06:22 +03:00
/*
* Unix SMB / CIFS implementation .
* Group Policy Support
2010-07-07 14:36:33 +04:00
* Copyright ( C ) Guenther Deschner 2007 - 2008 , 2010
2008-02-29 19:06:22 +03: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
* 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"
2009-04-21 01:38:11 +04:00
# include "../libgpo/gpo_ini.h"
2010-05-10 02:07:10 +04:00
# include "../libgpo/gpo.h"
# include "libgpo/gpo_proto.h"
2009-10-02 02:17:06 +04:00
# include "registry.h"
2010-07-07 14:36:33 +04:00
# include "../librpc/gen_ndr/ndr_preg.h"
2013-12-20 20:22:23 +04:00
# include "libgpo/gpext/gpext.h"
2008-02-29 19:06:22 +03:00
# define GP_EXT_NAME "registry"
/* more info can be found at:
* http : //msdn2.microsoft.com/en-us/library/aa374407.aspx */
# define GP_REGPOL_FILE "Registry.pol"
# define GP_REGPOL_FILE_SIGNATURE 0x67655250 /* 'PReg' */
# define GP_REGPOL_FILE_VERSION 1
static TALLOC_CTX * ctx = NULL ;
2017-05-04 16:07:14 +03:00
NTSTATUS gpext_registry_init ( TALLOC_CTX * mem_ctx ) ;
2008-02-29 19:06:22 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static bool reg_parse_value ( TALLOC_CTX * mem_ctx ,
2010-07-07 14:36:33 +04:00
const char * * value ,
2008-02-29 19:06:22 +03:00
enum gp_reg_action * action )
{
if ( ! * value ) {
* action = GP_REG_ACTION_ADD_KEY ;
return true ;
}
if ( strncmp ( * value , " ** " , 2 ) ! = 0 ) {
* action = GP_REG_ACTION_ADD_VALUE ;
return true ;
}
if ( strnequal ( * value , " **DelVals. " , 10 ) ) {
* action = GP_REG_ACTION_DEL_ALL_VALUES ;
return true ;
}
if ( strnequal ( * value , " **Del. " , 6 ) ) {
* value = talloc_strdup ( mem_ctx , * value + 6 ) ;
* action = GP_REG_ACTION_DEL_VALUE ;
return true ;
}
if ( strnequal ( * value , " **SecureKey " , 11 ) ) {
if ( strnequal ( * value , " **SecureKey=1 " , 13 ) ) {
* action = GP_REG_ACTION_SEC_KEY_SET ;
return true ;
}
/*************** not tested from here on ***************/
if ( strnequal ( * value , " **SecureKey=0 " , 13 ) ) {
smb_panic ( " not supported: **SecureKey=0 " ) ;
* action = GP_REG_ACTION_SEC_KEY_RESET ;
return true ;
}
DEBUG ( 0 , ( " unknown: SecureKey: %s \n " , * value ) ) ;
smb_panic ( " not supported SecureKey method " ) ;
return false ;
}
if ( strnequal ( * value , " **DeleteValues " , strlen ( " **DeleteValues " ) ) ) {
smb_panic ( " not supported: **DeleteValues " ) ;
* action = GP_REG_ACTION_DEL_VALUES ;
return false ;
}
if ( strnequal ( * value , " **DeleteKeys " , strlen ( " **DeleteKeys " ) ) ) {
smb_panic ( " not supported: **DeleteKeys " ) ;
* action = GP_REG_ACTION_DEL_KEYS ;
return false ;
}
DEBUG ( 0 , ( " unknown value: %s \n " , * value ) ) ;
smb_panic ( * value ) ;
return false ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static bool gp_reg_entry_from_file_entry ( TALLOC_CTX * mem_ctx ,
2010-07-07 14:36:33 +04:00
struct preg_entry * r ,
2008-02-29 19:06:22 +03:00
struct gp_registry_entry * * reg_entry )
{
struct registry_value * data = NULL ;
struct gp_registry_entry * entry = NULL ;
enum gp_reg_action action = GP_REG_ACTION_NONE ;
2018-08-21 22:38:01 +03:00
enum ndr_err_code ndr_err ;
2008-02-29 19:06:22 +03:00
ZERO_STRUCTP ( * reg_entry ) ;
2011-06-07 05:44:43 +04:00
data = talloc_zero ( mem_ctx , struct registry_value ) ;
2008-02-29 19:06:22 +03:00
if ( ! data )
return false ;
2010-07-07 14:36:33 +04:00
data - > type = r - > type ;
2018-04-16 05:53:18 +03:00
2018-08-21 22:38:01 +03:00
ndr_err = ndr_push_union_blob (
& data - > data ,
mem_ctx ,
& r - > data ,
r - > type ,
( ndr_push_flags_fn_t ) ndr_push_winreg_Data ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
DBG_WARNING ( " ndr_push_winreg_Data failed: %s \n " ,
ndr_errstr ( ndr_err ) ) ;
return false ;
}
2008-02-29 19:06:22 +03:00
2011-06-07 05:44:43 +04:00
entry = talloc_zero ( mem_ctx , struct gp_registry_entry ) ;
2008-02-29 19:06:22 +03:00
if ( ! entry )
return false ;
2010-07-07 14:36:33 +04:00
if ( ! reg_parse_value ( mem_ctx , & r - > valuename , & action ) )
return false ;
entry - > key = talloc_strdup ( entry , r - > keyname ) ;
entry - > value = talloc_strdup ( entry , r - > valuename ) ;
2008-02-29 19:06:22 +03:00
entry - > data = data ;
entry - > action = action ;
* reg_entry = entry ;
return true ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS reg_parse_registry ( TALLOC_CTX * mem_ctx ,
uint32_t flags ,
const char * filename ,
2010-07-07 14:36:33 +04:00
struct gp_registry_entry * * entries_p ,
size_t * num_entries_p )
2008-02-29 19:06:22 +03:00
{
2010-07-07 14:36:33 +04:00
DATA_BLOB blob ;
2008-02-29 19:06:22 +03:00
NTSTATUS status ;
2010-07-07 14:36:33 +04:00
enum ndr_err_code ndr_err ;
2008-02-29 19:06:22 +03:00
const char * real_filename = NULL ;
2010-07-07 14:36:33 +04:00
struct preg_file r ;
struct gp_registry_entry * entries = NULL ;
size_t num_entries = 0 ;
int i ;
2008-02-29 19:06:22 +03:00
status = gp_find_file ( mem_ctx ,
flags ,
filename ,
GP_REGPOL_FILE ,
& real_filename ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2010-07-07 14:36:33 +04:00
blob . data = ( uint8_t * ) file_load ( real_filename , & blob . length , 0 , NULL ) ;
if ( ! blob . data ) {
2008-02-29 19:06:22 +03:00
return NT_STATUS_CANNOT_LOAD_REGISTRY_FILE ;
}
2010-07-07 14:36:33 +04:00
ndr_err = ndr_pull_struct_blob ( & blob , mem_ctx , & r ,
( ndr_pull_flags_fn_t ) ndr_pull_preg_file ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
status = ndr_map_error2ntstatus ( ndr_err ) ;
2008-02-29 19:06:22 +03:00
goto out ;
}
2013-12-20 20:23:22 +04:00
if ( flags & GPO_INFO_FLAG_VERBOSE ) {
NDR_PRINT_DEBUG ( preg_file , & r ) ;
}
2010-07-07 14:36:33 +04:00
if ( ! strequal ( r . header . signature , " PReg " ) ) {
2008-02-29 19:06:22 +03:00
status = NT_STATUS_INVALID_PARAMETER ;
goto out ;
}
2010-07-07 14:36:33 +04:00
if ( r . header . version ! = GP_REGPOL_FILE_VERSION ) {
2008-02-29 19:06:22 +03:00
status = NT_STATUS_INVALID_PARAMETER ;
goto out ;
}
2010-07-07 14:36:33 +04:00
for ( i = 0 ; i < r . num_entries ; i + + ) {
struct gp_registry_entry * r_entry = NULL ;
if ( ! gp_reg_entry_from_file_entry ( mem_ctx ,
& r . entries [ i ] ,
& r_entry ) ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
if ( ! add_gp_registry_entry_to_array ( mem_ctx ,
r_entry ,
& entries ,
& num_entries ) ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
2008-02-29 19:06:22 +03:00
}
2010-07-07 14:36:33 +04:00
* entries_p = entries ;
* num_entries_p = num_entries ;
2008-02-29 19:06:22 +03:00
status = NT_STATUS_OK ;
out :
2010-07-07 14:36:33 +04:00
data_blob_free ( & blob ) ;
2008-02-29 19:06:22 +03:00
return status ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR reg_apply_registry ( TALLOC_CTX * mem_ctx ,
2010-08-26 14:04:11 +04:00
const struct security_token * token ,
2008-02-29 19:06:22 +03:00
struct registry_key * root_key ,
uint32_t flags ,
struct gp_registry_entry * entries ,
size_t num_entries )
{
struct gp_registry_context * reg_ctx = NULL ;
WERROR werr ;
size_t i ;
if ( num_entries = = 0 ) {
return WERR_OK ;
}
#if 0
if ( flags & GPO_LIST_FLAG_MACHINE ) {
werr = gp_init_reg_ctx ( mem_ctx , KEY_HKLM , REG_KEY_WRITE ,
get_system_token ( ) ,
& reg_ctx ) ;
} else {
werr = gp_init_reg_ctx ( mem_ctx , KEY_HKCU , REG_KEY_WRITE ,
token ,
& reg_ctx ) ;
}
W_ERROR_NOT_OK_RETURN ( werr ) ;
# endif
for ( i = 0 ; i < num_entries ; i + + ) {
/* FIXME: maybe we should check here if we attempt to go beyond
* the 4 allowed reg keys */
werr = reg_apply_registry_entry ( mem_ctx , root_key ,
reg_ctx ,
& ( entries ) [ i ] ,
token , flags ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 0 , ( " failed to apply registry: %s \n " ,
2008-11-01 19:19:26 +03:00
win_errstr ( werr ) ) ) ;
2008-02-29 19:06:22 +03:00
goto done ;
}
}
done :
gp_free_reg_ctx ( reg_ctx ) ;
return werr ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-12-13 18:52:31 +04:00
static NTSTATUS registry_process_group_policy ( TALLOC_CTX * mem_ctx ,
2008-02-29 19:06:22 +03:00
uint32_t flags ,
struct registry_key * root_key ,
2010-08-26 14:04:11 +04:00
const struct security_token * token ,
2013-12-20 01:23:44 +04:00
const struct GROUP_POLICY_OBJECT * deleted_gpo_list ,
const struct GROUP_POLICY_OBJECT * changed_gpo_list )
2008-02-29 19:06:22 +03:00
{
NTSTATUS status ;
WERROR werr ;
struct gp_registry_entry * entries = NULL ;
size_t num_entries = 0 ;
char * unix_path = NULL ;
2013-12-20 01:23:44 +04:00
const struct GROUP_POLICY_OBJECT * gpo ;
2018-08-16 11:51:44 +03:00
char * gpo_cache_path = cache_path ( talloc_tos ( ) , GPO_CACHE_DIR ) ;
2014-10-06 20:21:14 +04:00
if ( gpo_cache_path = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2008-02-29 19:06:22 +03:00
2013-12-18 22:33:28 +04:00
/* implementation of the policy callback function, see
* http : //msdn.microsoft.com/en-us/library/aa373494%28v=vs.85%29.aspx
* for details - gd */
2008-02-29 19:06:22 +03:00
2013-12-18 22:33:28 +04:00
/* for now do not process the list of deleted group policies
2008-02-29 19:06:22 +03:00
2013-12-18 22:33:28 +04:00
for ( gpo = deleted_gpo_list ; gpo ; gpo = gpo - > next ) {
2008-02-29 19:06:22 +03:00
}
2013-12-18 22:33:28 +04:00
*/
for ( gpo = changed_gpo_list ; gpo ; gpo = gpo - > next ) {
gpext_debug_header ( 0 , " registry_process_group_policy " , flags ,
2013-12-19 17:34:53 +04:00
gpo , GP_EXT_GUID_REGISTRY , NULL ) ;
2013-12-18 22:33:28 +04:00
2014-10-06 20:21:14 +04:00
status = gpo_get_unix_path ( mem_ctx , gpo_cache_path ,
2013-12-18 22:33:28 +04:00
gpo , & unix_path ) ;
2014-10-06 20:21:14 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto err_cache_path_free ;
}
2013-12-18 22:33:28 +04:00
status = reg_parse_registry ( mem_ctx ,
flags ,
unix_path ,
& entries ,
& num_entries ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " failed to parse registry: %s \n " ,
nt_errstr ( status ) ) ) ;
2014-10-06 20:21:14 +04:00
goto err_cache_path_free ;
2013-12-18 22:33:28 +04:00
}
dump_reg_entries ( flags , " READ " , entries , num_entries ) ;
2008-02-29 19:06:22 +03:00
2013-12-18 22:33:28 +04:00
werr = reg_apply_registry ( mem_ctx , token , root_key , flags ,
entries , num_entries ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 0 , ( " failed to apply registry: %s \n " ,
win_errstr ( werr ) ) ) ;
2014-10-06 20:21:14 +04:00
status = werror_to_ntstatus ( werr ) ;
goto err_cache_path_free ;
2013-12-18 22:33:28 +04:00
}
2008-02-29 19:06:22 +03:00
}
2014-10-06 20:21:14 +04:00
status = NT_STATUS_OK ;
2008-02-29 19:06:22 +03:00
2014-10-06 20:21:14 +04:00
err_cache_path_free :
talloc_free ( gpo_cache_path ) ;
2017-05-09 15:31:15 +03:00
talloc_free ( entries ) ;
2014-10-06 20:21:14 +04:00
return status ;
2008-02-29 19:06:22 +03:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS registry_get_reg_config ( TALLOC_CTX * mem_ctx ,
struct gp_extension_reg_info * * reg_info )
{
NTSTATUS status ;
struct gp_extension_reg_info * info = NULL ;
struct gp_extension_reg_table table [ ] = {
{ " ProcessGroupPolicy " , REG_SZ , " registry_process_group_policy " } ,
{ NULL , REG_NONE , NULL }
} ;
2011-06-07 05:44:43 +04:00
info = talloc_zero ( mem_ctx , struct gp_extension_reg_info ) ;
2008-02-29 19:06:22 +03:00
NT_STATUS_HAVE_NO_MEMORY ( info ) ;
2013-12-18 18:43:23 +04:00
status = gpext_info_add_entry ( mem_ctx , GP_EXT_NAME ,
GP_EXT_GUID_REGISTRY ,
table , info ) ;
2008-02-29 19:06:22 +03:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
* reg_info = info ;
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS registry_initialize ( TALLOC_CTX * mem_ctx )
{
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS registry_shutdown ( void )
{
NTSTATUS status ;
2013-12-18 18:43:23 +04:00
status = gpext_unregister_gp_extension ( GP_EXT_NAME ) ;
2008-02-29 19:06:22 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
return status ;
}
TALLOC_FREE ( ctx ) ;
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct gp_extension_methods registry_methods = {
. initialize = registry_initialize ,
. process_group_policy = registry_process_group_policy ,
. get_reg_config = registry_get_reg_config ,
. shutdown = registry_shutdown
} ;
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-04-24 14:25:41 +03:00
NTSTATUS gpext_registry_init ( TALLOC_CTX * mem_ctx )
2008-02-29 19:06:22 +03:00
{
NTSTATUS status ;
ctx = talloc_init ( " gpext_registry_init " ) ;
NT_STATUS_HAVE_NO_MEMORY ( ctx ) ;
2013-12-18 18:43:23 +04:00
status = gpext_register_gp_extension ( ctx , SMB_GPEXT_INTERFACE_VERSION ,
GP_EXT_NAME , GP_EXT_GUID_REGISTRY ,
& registry_methods ) ;
2008-02-29 19:06:22 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( ctx ) ;
}
return status ;
}