2008-02-29 18:03:23 +03:00
/*
* Unix SMB / CIFS implementation .
* Group Policy Support
* Copyright ( C ) Guenther Deschner 2007 - 2008
*
* 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"
2010-05-10 02:07:10 +04:00
# include "../libgpo/gpo.h"
2009-03-01 04:13:21 +03:00
# include "../libgpo/gpext/gpext.h"
# include "librpc/gen_ndr/ndr_misc.h"
# include "lib/util/dlinklist.h"
2011-02-26 02:28:15 +03:00
# include "../libcli/registry/util_reg.h"
2010-05-10 02:07:10 +04:00
# include "libgpo/gpo_proto.h"
2009-10-02 02:17:06 +04:00
# include "registry.h"
2010-09-21 10:11:18 +04:00
# include "registry/reg_api.h"
2017-06-22 17:10:52 +03:00
# include "lib/util/util_paths.h"
2020-08-07 21:17:34 +03:00
# include "lib/util/string_wrappers.h"
2008-02-29 18:03:23 +03:00
static struct gp_extension * extensions = NULL ;
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-12-18 18:43:23 +04:00
struct gp_extension * gpext_get_gp_extension_list ( void )
2008-02-29 18:03:23 +03:00
{
return extensions ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct gp_extension_reg_table gpext_reg_vals [ ] = {
2018-12-13 13:07:24 +03:00
{
. val = " DllName " ,
. type = REG_EXPAND_SZ ,
} ,
{
. val = " ProcessGroupPolicy " ,
. type = REG_SZ ,
} ,
{
. val = " NoMachinePolicy " ,
. type = REG_DWORD ,
} ,
{
. val = " NoUserPolicy " ,
. type = REG_DWORD ,
} ,
{
. val = " NoSlowLink " ,
. type = REG_DWORD ,
} ,
{
. val = " NoBackgroundPolicy " ,
. type = REG_DWORD ,
} ,
{
. val = " NoGPOListChanges " ,
. type = REG_DWORD ,
} ,
{
. val = " PerUserLocalSettings " ,
. type = REG_DWORD ,
} ,
{
. val = " RequiresSuccessfulRegistry " ,
. type = REG_DWORD ,
} ,
{
. val = " EnableAsynchronousProcessing " ,
. type = REG_DWORD ,
} ,
{
. val = " ExtensionDebugLevel " ,
. type = REG_DWORD ,
} ,
2008-02-29 18:03:23 +03:00
/* new */
2018-12-13 13:07:24 +03:00
{
. val = " GenerateGroupPolicy " , /* not supported on w2k */
. type = REG_SZ ,
} ,
{
. val = " NotifyLinkTransition " ,
. type = REG_DWORD ,
} ,
{
. val = " ProcessGroupPolicyEx " , /* not supported on w2k */
. type = REG_SZ ,
} ,
{
. val = " ExtensionEventSource " , /* not supported on w2k */
. type = REG_MULTI_SZ ,
} ,
{
. val = " MaxNoGPOListChangesInterval " ,
. type = REG_DWORD ,
} ,
{ . type = REG_NONE }
2008-02-29 18:03:23 +03:00
} ;
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct gp_extension * get_extension_by_name ( struct gp_extension * be ,
const char * name )
{
struct gp_extension * b ;
for ( b = be ; b ; b = b - > next ) {
if ( strequal ( b - > name , name ) ) {
return b ;
}
}
return NULL ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct gp_extension_methods * get_methods_by_name ( struct gp_extension * be ,
const char * name )
{
struct gp_extension * b ;
for ( b = be ; b ; b = b - > next ) {
if ( strequal ( b - > name , name ) ) {
return b - > methods ;
}
}
return NULL ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-12-18 18:43:23 +04:00
NTSTATUS gpext_unregister_gp_extension ( const char * name )
2008-02-29 18:03:23 +03:00
{
struct gp_extension * ext ;
ext = get_extension_by_name ( extensions , name ) ;
if ( ! ext ) {
return NT_STATUS_OK ;
}
DLIST_REMOVE ( extensions , ext ) ;
2009-03-01 04:13:21 +03:00
talloc_free ( ext ) ;
2008-02-29 18:03:23 +03:00
DEBUG ( 2 , ( " Successfully removed GP extension '%s' \n " , name ) ) ;
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-12-18 18:43:23 +04:00
NTSTATUS gpext_register_gp_extension ( TALLOC_CTX * gpext_ctx ,
int version ,
const char * name ,
const char * guid ,
struct gp_extension_methods * methods )
2008-02-29 18:03:23 +03:00
{
struct gp_extension_methods * test ;
struct gp_extension * entry ;
NTSTATUS status ;
if ( ! gpext_ctx ) {
return NT_STATUS_INTERNAL_DB_ERROR ;
}
if ( ( version ! = SMB_GPEXT_INTERFACE_VERSION ) ) {
DEBUG ( 0 , ( " Failed to register gp extension. \n "
" The module was compiled against "
" SMB_GPEXT_INTERFACE_VERSION %d, \n "
" current SMB_GPEXT_INTERFACE_VERSION is %d. \n "
" Please recompile against the current "
" version of samba! \n " ,
version , SMB_GPEXT_INTERFACE_VERSION ) ) ;
return NT_STATUS_OBJECT_TYPE_MISMATCH ;
}
if ( ! guid | | ! name | | ! name [ 0 ] | | ! methods ) {
DEBUG ( 0 , ( " Called with NULL pointer or empty name! \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
test = get_methods_by_name ( extensions , name ) ;
if ( test ) {
DEBUG ( 0 , ( " GP extension module %s already registered! \n " ,
name ) ) ;
return NT_STATUS_OBJECT_NAME_COLLISION ;
}
2009-03-01 04:13:21 +03:00
entry = talloc_zero ( gpext_ctx , struct gp_extension ) ;
2008-02-29 18:03:23 +03:00
NT_STATUS_HAVE_NO_MEMORY ( entry ) ;
entry - > name = talloc_strdup ( gpext_ctx , name ) ;
NT_STATUS_HAVE_NO_MEMORY ( entry - > name ) ;
2009-03-01 04:13:21 +03:00
entry - > guid = talloc_zero ( gpext_ctx , struct GUID ) ;
2008-02-29 18:03:23 +03:00
NT_STATUS_HAVE_NO_MEMORY ( entry - > guid ) ;
status = GUID_from_string ( guid , entry - > guid ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
entry - > methods = methods ;
DLIST_ADD ( extensions , entry ) ;
DEBUG ( 2 , ( " Successfully added GP extension '%s' %s \n " ,
name , GUID_string2 ( gpext_ctx , entry - > guid ) ) ) ;
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS gp_extension_init_module ( TALLOC_CTX * mem_ctx ,
const char * name ,
struct gp_extension * * gpext )
{
NTSTATUS status ;
struct gp_extension * ext = NULL ;
2009-03-01 04:13:21 +03:00
ext = talloc_zero ( mem_ctx , struct gp_extension ) ;
2008-02-29 18:03:23 +03:00
NT_STATUS_HAVE_NO_MEMORY ( gpext ) ;
ext - > methods = get_methods_by_name ( extensions , name ) ;
if ( ! ext - > methods ) {
status = smb_probe_module ( SAMBA_SUBSYSTEM_GPEXT ,
name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
ext - > methods = get_methods_by_name ( extensions , name ) ;
if ( ! ext - > methods ) {
return NT_STATUS_DLL_INIT_FAILED ;
}
}
* gpext = ext ;
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static bool add_gp_extension_reg_entry_to_array ( TALLOC_CTX * mem_ctx ,
struct gp_extension_reg_entry * entry ,
struct gp_extension_reg_entry * * entries ,
size_t * num )
{
2009-03-01 04:13:21 +03:00
* entries = talloc_realloc ( mem_ctx , * entries ,
2008-02-29 18:03:23 +03:00
struct gp_extension_reg_entry ,
( * num ) + 1 ) ;
if ( * entries = = NULL ) {
* num = 0 ;
return false ;
}
( * entries ) [ * num ] . value = entry - > value ;
( * entries ) [ * num ] . data = entry - > data ;
* num + = 1 ;
return true ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static bool add_gp_extension_reg_info_entry_to_array ( TALLOC_CTX * mem_ctx ,
struct gp_extension_reg_info_entry * entry ,
struct gp_extension_reg_info_entry * * entries ,
size_t * num )
{
2009-03-01 04:13:21 +03:00
* entries = talloc_realloc ( mem_ctx , * entries ,
2008-02-29 18:03:23 +03:00
struct gp_extension_reg_info_entry ,
( * num ) + 1 ) ;
if ( * entries = = NULL ) {
* num = 0 ;
return false ;
}
( * entries ) [ * num ] . guid = entry - > guid ;
( * entries ) [ * num ] . num_entries = entry - > num_entries ;
( * entries ) [ * num ] . entries = entry - > entries ;
* num + = 1 ;
return true ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS gp_ext_info_add_reg ( TALLOC_CTX * mem_ctx ,
struct gp_extension_reg_info_entry * entry ,
const char * value ,
enum winreg_Type type ,
const char * data_s )
{
struct gp_extension_reg_entry * reg_entry = NULL ;
struct registry_value * data = NULL ;
2009-03-01 04:13:21 +03:00
reg_entry = talloc_zero ( mem_ctx , struct gp_extension_reg_entry ) ;
2008-02-29 18:03:23 +03:00
NT_STATUS_HAVE_NO_MEMORY ( reg_entry ) ;
2009-03-01 04:13:21 +03:00
data = talloc_zero ( mem_ctx , struct registry_value ) ;
2008-02-29 18:03:23 +03:00
NT_STATUS_HAVE_NO_MEMORY ( data ) ;
data - > type = type ;
switch ( type ) {
case REG_SZ :
case REG_EXPAND_SZ :
2010-06-29 18:13:15 +04:00
if ( ! push_reg_sz ( mem_ctx , & data - > data , data_s ) ) {
return NT_STATUS_NO_MEMORY ;
}
2008-02-29 18:03:23 +03:00
break ;
2010-06-29 18:13:15 +04:00
case REG_DWORD : {
uint32_t v = atoi ( data_s ) ;
data - > data = data_blob_talloc ( mem_ctx , NULL , 4 ) ;
SIVAL ( data - > data . data , 0 , v ) ;
2008-02-29 18:03:23 +03:00
break ;
2010-06-29 18:13:15 +04:00
}
2008-02-29 18:03:23 +03:00
default :
return NT_STATUS_NOT_SUPPORTED ;
}
reg_entry - > value = value ;
reg_entry - > data = data ;
if ( ! add_gp_extension_reg_entry_to_array ( mem_ctx , reg_entry ,
& entry - > entries ,
& entry - > num_entries ) ) {
return NT_STATUS_NO_MEMORY ;
}
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS gp_ext_info_add_reg_table ( TALLOC_CTX * mem_ctx ,
const char * module ,
struct gp_extension_reg_info_entry * entry ,
struct gp_extension_reg_table * table )
{
NTSTATUS status ;
const char * module_name = NULL ;
int i ;
module_name = talloc_asprintf ( mem_ctx , " %s.%s " , module , shlib_ext ( ) ) ;
NT_STATUS_HAVE_NO_MEMORY ( module_name ) ;
status = gp_ext_info_add_reg ( mem_ctx , entry ,
" DllName " , REG_EXPAND_SZ , module_name ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
for ( i = 0 ; table [ i ] . val ; i + + ) {
status = gp_ext_info_add_reg ( mem_ctx , entry ,
table [ i ] . val ,
table [ i ] . type ,
table [ i ] . data ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
}
return status ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-12-18 18:43:23 +04:00
NTSTATUS gpext_info_add_entry ( TALLOC_CTX * mem_ctx ,
const char * module ,
const char * ext_guid ,
struct gp_extension_reg_table * table ,
struct gp_extension_reg_info * info )
2008-02-29 18:03:23 +03:00
{
NTSTATUS status ;
struct gp_extension_reg_info_entry * entry = NULL ;
2011-06-07 05:44:43 +04:00
entry = talloc_zero ( mem_ctx , struct gp_extension_reg_info_entry ) ;
2008-02-29 18:03:23 +03:00
NT_STATUS_HAVE_NO_MEMORY ( entry ) ;
status = GUID_from_string ( ext_guid , & entry - > guid ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
status = gp_ext_info_add_reg_table ( mem_ctx , module , entry , table ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
if ( ! add_gp_extension_reg_info_entry_to_array ( mem_ctx , entry ,
& info - > entries ,
& info - > num_entries ) ) {
return NT_STATUS_NO_MEMORY ;
}
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static bool gp_extension_reg_info_verify_entry ( struct gp_extension_reg_entry * entry )
{
int i ;
for ( i = 0 ; gpext_reg_vals [ i ] . val ; i + + ) {
if ( ( strequal ( entry - > value , gpext_reg_vals [ i ] . val ) ) & &
( entry - > data - > type = = gpext_reg_vals [ i ] . type ) ) {
return true ;
}
}
return false ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static bool gp_extension_reg_info_verify ( struct gp_extension_reg_info_entry * entry )
{
int i ;
for ( i = 0 ; i < entry - > num_entries ; i + + ) {
if ( ! gp_extension_reg_info_verify_entry ( & entry - > entries [ i ] ) ) {
return false ;
}
}
return true ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR gp_extension_store_reg_vals ( TALLOC_CTX * mem_ctx ,
struct registry_key * key ,
struct gp_extension_reg_info_entry * entry )
{
WERROR werr = WERR_OK ;
size_t i ;
for ( i = 0 ; i < entry - > num_entries ; i + + ) {
werr = reg_setvalue ( key ,
entry - > entries [ i ] . value ,
entry - > entries [ i ] . data ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
}
return werr ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR gp_extension_store_reg_entry ( TALLOC_CTX * mem_ctx ,
struct gp_registry_context * reg_ctx ,
struct gp_extension_reg_info_entry * entry )
{
WERROR werr ;
struct registry_key * key = NULL ;
const char * subkeyname = NULL ;
if ( ! gp_extension_reg_info_verify ( entry ) ) {
2015-12-03 17:24:23 +03:00
return WERR_INVALID_PARAMETER ;
2008-02-29 18:03:23 +03:00
}
subkeyname = GUID_string2 ( mem_ctx , & entry - > guid ) ;
W_ERROR_HAVE_NO_MEMORY ( subkeyname ) ;
2012-08-09 02:35:28 +04:00
if ( ! strupper_m ( discard_const_p ( char , subkeyname ) ) ) {
2015-12-03 17:24:23 +03:00
return WERR_INVALID_PARAMETER ;
2012-08-09 02:35:28 +04:00
}
2008-02-29 18:03:23 +03:00
werr = gp_store_reg_subkey ( mem_ctx ,
subkeyname ,
reg_ctx - > curr_key ,
& key ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
werr = gp_extension_store_reg_vals ( mem_ctx ,
key ,
entry ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
return werr ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR gp_extension_store_reg ( TALLOC_CTX * mem_ctx ,
struct gp_registry_context * reg_ctx ,
struct gp_extension_reg_info * info )
{
WERROR werr = WERR_OK ;
int i ;
if ( ! info ) {
return WERR_OK ;
}
for ( i = 0 ; i < info - > num_entries ; i + + ) {
werr = gp_extension_store_reg_entry ( mem_ctx ,
reg_ctx ,
& info - > entries [ i ] ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
}
return werr ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS gp_glob_ext_list ( TALLOC_CTX * mem_ctx ,
const char * * * ext_list ,
size_t * ext_list_len )
{
2012-03-28 06:22:03 +04:00
DIR * dir = NULL ;
2012-03-28 06:18:14 +04:00
struct dirent * dirent = NULL ;
2008-02-29 18:03:23 +03:00
2012-03-28 06:01:19 +04:00
dir = opendir ( modules_path ( talloc_tos ( ) ,
2011-06-06 08:37:06 +04:00
SAMBA_SUBSYSTEM_GPEXT ) ) ;
2008-02-29 18:03:23 +03:00
if ( ! dir ) {
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2008-02-29 18:03:23 +03:00
}
2012-03-28 06:03:00 +04:00
while ( ( dirent = readdir ( dir ) ) ) {
2008-02-29 18:03:23 +03:00
fstring name ; /* forgive me... */
char * p ;
if ( ( strequal ( dirent - > d_name , " . " ) ) | |
( strequal ( dirent - > d_name , " .. " ) ) ) {
continue ;
}
p = strrchr ( dirent - > d_name , ' . ' ) ;
if ( ! p ) {
2012-03-28 06:08:27 +04:00
closedir ( dir ) ;
2008-02-29 18:03:23 +03:00
return NT_STATUS_NO_MEMORY ;
}
if ( ! strcsequal ( p + 1 , shlib_ext ( ) ) ) {
DEBUG ( 10 , ( " gp_glob_ext_list: not a *.so file: %s \n " ,
dirent - > d_name ) ) ;
continue ;
}
fstrcpy ( name , dirent - > d_name ) ;
name [ PTR_DIFF ( p , dirent - > d_name ) ] = 0 ;
if ( ! add_string_to_array ( mem_ctx , name , ext_list ,
2014-11-14 16:12:26 +03:00
ext_list_len ) ) {
2012-03-28 06:08:27 +04:00
closedir ( dir ) ;
2008-02-29 18:03:23 +03:00
return NT_STATUS_NO_MEMORY ;
}
}
2012-03-28 06:08:27 +04:00
closedir ( dir ) ;
2008-02-29 18:03:23 +03:00
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-12-18 18:43:23 +04:00
NTSTATUS gpext_shutdown_gp_extensions ( void )
2008-02-29 18:03:23 +03:00
{
struct gp_extension * ext = NULL ;
for ( ext = extensions ; ext ; ext = ext - > next ) {
if ( ext - > methods & & ext - > methods - > shutdown ) {
ext - > methods - > shutdown ( ) ;
}
}
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-12-18 18:43:23 +04:00
NTSTATUS gpext_init_gp_extensions ( TALLOC_CTX * mem_ctx )
2008-02-29 18:03:23 +03:00
{
NTSTATUS status ;
WERROR werr ;
int i = 0 ;
const char * * ext_array = NULL ;
size_t ext_array_len = 0 ;
struct gp_extension * gpext = NULL ;
struct gp_registry_context * reg_ctx = NULL ;
2013-12-18 18:43:23 +04:00
if ( gpext_get_gp_extension_list ( ) ) {
2008-02-29 18:03:23 +03:00
return NT_STATUS_OK ;
}
status = gp_glob_ext_list ( mem_ctx , & ext_array , & ext_array_len ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
for ( i = 0 ; i < ext_array_len ; i + + ) {
struct gp_extension_reg_info * info = NULL ;
status = gp_extension_init_module ( mem_ctx , ext_array [ i ] ,
& gpext ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
}
if ( gpext - > methods - > get_reg_config ) {
status = gpext - > methods - > initialize ( mem_ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
gpext - > methods - > shutdown ( ) ;
goto out ;
}
status = gpext - > methods - > get_reg_config ( mem_ctx ,
& info ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
gpext - > methods - > shutdown ( ) ;
goto out ;
}
if ( ! reg_ctx ) {
2010-08-26 16:08:22 +04:00
struct security_token * token ;
2008-02-29 18:03:23 +03:00
token = registry_create_system_token ( mem_ctx ) ;
NT_STATUS_HAVE_NO_MEMORY ( token ) ;
werr = gp_init_reg_ctx ( mem_ctx ,
KEY_WINLOGON_GPEXT_PATH ,
REG_KEY_WRITE ,
token ,
& reg_ctx ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
status = werror_to_ntstatus ( werr ) ;
gpext - > methods - > shutdown ( ) ;
goto out ;
}
}
werr = gp_extension_store_reg ( mem_ctx , reg_ctx , info ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 1 , ( " gp_extension_store_reg failed: %s \n " ,
2008-11-01 19:19:26 +03:00
win_errstr ( werr ) ) ) ;
2008-02-29 18:03:23 +03:00
TALLOC_FREE ( info ) ;
gpext - > methods - > shutdown ( ) ;
status = werror_to_ntstatus ( werr ) ;
goto out ;
}
TALLOC_FREE ( info ) ;
}
}
out :
TALLOC_FREE ( reg_ctx ) ;
return status ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-12-18 18:43:23 +04:00
NTSTATUS gpext_free_gp_extensions ( void )
2008-02-29 18:03:23 +03:00
{
struct gp_extension * ext , * ext_next = NULL ;
for ( ext = extensions ; ext ; ext = ext_next ) {
ext_next = ext - > next ;
DLIST_REMOVE ( extensions , ext ) ;
TALLOC_FREE ( ext ) ;
}
extensions = NULL ;
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-12-18 18:24:17 +04:00
void gpext_debug_header ( int lvl ,
2008-02-29 18:03:23 +03:00
const char * name ,
uint32_t flags ,
2013-12-20 01:23:44 +04:00
const struct GROUP_POLICY_OBJECT * gpo ,
2008-02-29 18:03:23 +03:00
const char * extension_guid ,
const char * snapin_guid )
{
char * flags_str = NULL ;
DEBUG ( lvl , ( " %s \n " , name ) ) ;
DEBUGADD ( lvl , ( " \t gpo: %s (%s) \n " , gpo - > name ,
gpo - > display_name ) ) ;
DEBUGADD ( lvl , ( " \t cse extension: %s (%s) \n " , extension_guid ,
cse_gpo_guid_string_to_name ( extension_guid ) ) ) ;
DEBUGADD ( lvl , ( " \t gplink: %s \n " , gpo - > link ) ) ;
DEBUGADD ( lvl , ( " \t snapin: %s (%s) \n " , snapin_guid ,
cse_snapin_gpo_guid_string_to_name ( snapin_guid ) ) ) ;
2009-03-15 22:34:59 +03:00
flags_str = gpo_flag_str ( NULL , flags ) ;
2008-02-29 18:03:23 +03:00
DEBUGADD ( lvl , ( " \t flags: 0x%08x %s \n " , flags , flags_str ) ) ;
2009-03-15 22:34:59 +03:00
TALLOC_FREE ( flags_str ) ;
2008-02-29 18:03:23 +03:00
}
2013-12-18 18:43:23 +04:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-12-18 22:59:09 +04:00
static NTSTATUS gpext_check_gpo_for_gpext_presence ( TALLOC_CTX * mem_ctx ,
uint32_t flags ,
const struct GROUP_POLICY_OBJECT * gpo ,
const struct GUID * guid ,
bool * gpext_guid_present )
{
struct GP_EXT * gp_ext = NULL ;
int i ;
bool ok ;
* gpext_guid_present = false ;
if ( gpo - > link_type = = GP_LINK_LOCAL ) {
return NT_STATUS_OK ;
}
ok = gpo_get_gp_ext_from_gpo ( mem_ctx , flags , gpo , & gp_ext ) ;
if ( ! ok ) {
return NT_STATUS_INVALID_PARAMETER ;
}
if ( gp_ext = = NULL ) {
return NT_STATUS_OK ;
}
for ( i = 0 ; i < gp_ext - > num_exts ; i + + ) {
struct GUID guid2 ;
NTSTATUS status ;
status = GUID_from_string ( gp_ext - > extensions_guid [ i ] , & guid2 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( GUID_equal ( guid , & guid2 ) ) {
* gpext_guid_present = true ;
return NT_STATUS_OK ;
}
}
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-12-13 18:54:10 +04:00
NTSTATUS gpext_process_extension ( TALLOC_CTX * mem_ctx ,
2008-02-29 18:03:23 +03:00
uint32_t flags ,
2010-08-26 16:08:22 +04:00
const struct security_token * token ,
2008-02-29 18:03:23 +03:00
struct registry_key * root_key ,
2013-12-18 22:33:28 +04:00
const struct GROUP_POLICY_OBJECT * deleted_gpo_list ,
const struct GROUP_POLICY_OBJECT * changed_gpo_list ,
2013-12-19 20:25:37 +04:00
const char * extension_guid_filter )
2008-02-29 18:03:23 +03:00
{
NTSTATUS status ;
struct gp_extension * ext = NULL ;
2013-12-18 22:33:28 +04:00
const struct GROUP_POLICY_OBJECT * gpo ;
2013-12-19 20:25:37 +04:00
struct GUID extension_guid_filter_guid ;
2008-02-29 18:03:23 +03:00
2013-12-18 18:43:23 +04:00
status = gpext_init_gp_extensions ( mem_ctx ) ;
2008-02-29 18:03:23 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2013-12-18 18:43:23 +04:00
DEBUG ( 1 , ( " gpext_init_gp_extensions failed: %s \n " ,
2008-02-29 18:03:23 +03:00
nt_errstr ( status ) ) ) ;
return status ;
}
2013-12-19 20:25:37 +04:00
if ( extension_guid_filter ) {
status = GUID_from_string ( extension_guid_filter ,
& extension_guid_filter_guid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
}
2008-02-29 18:03:23 +03:00
for ( ext = extensions ; ext ; ext = ext - > next ) {
2013-12-18 22:33:28 +04:00
struct GROUP_POLICY_OBJECT * deleted_gpo_list_filtered = NULL ;
struct GROUP_POLICY_OBJECT * changed_gpo_list_filtered = NULL ;
2013-12-19 20:25:37 +04:00
if ( extension_guid_filter ) {
if ( ! GUID_equal ( & extension_guid_filter_guid , ext - > guid ) ) {
continue ;
}
}
2013-12-18 22:33:28 +04:00
for ( gpo = deleted_gpo_list ; gpo ; gpo = gpo - > next ) {
bool is_present = false ;
status = gpext_check_gpo_for_gpext_presence ( mem_ctx ,
flags ,
gpo ,
ext - > guid ,
& is_present ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( is_present ) {
struct GROUP_POLICY_OBJECT * new_gpo ;
status = gpo_copy ( mem_ctx , gpo , & new_gpo ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
DLIST_ADD ( deleted_gpo_list_filtered , new_gpo ) ;
}
2008-02-29 18:03:23 +03:00
}
2013-12-18 22:33:28 +04:00
for ( gpo = changed_gpo_list ; gpo ; gpo = gpo - > next ) {
2008-02-29 18:03:23 +03:00
2013-12-18 22:33:28 +04:00
bool is_present = false ;
2008-02-29 18:03:23 +03:00
2013-12-18 22:33:28 +04:00
status = gpext_check_gpo_for_gpext_presence ( mem_ctx ,
flags ,
gpo ,
ext - > guid ,
& is_present ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2008-02-29 18:03:23 +03:00
2013-12-18 22:33:28 +04:00
if ( is_present ) {
struct GROUP_POLICY_OBJECT * new_gpo ;
2008-02-29 18:03:23 +03:00
2013-12-18 22:33:28 +04:00
status = gpo_copy ( mem_ctx , gpo , & new_gpo ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
DLIST_ADD ( changed_gpo_list_filtered , new_gpo ) ;
}
}
status = ext - > methods - > initialize ( mem_ctx ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
status = ext - > methods - > process_group_policy ( mem_ctx ,
flags ,
root_key ,
token ,
deleted_gpo_list_filtered ,
2013-12-19 17:34:53 +04:00
changed_gpo_list_filtered ) ;
2013-12-18 22:33:28 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
ext - > methods - > shutdown ( ) ;
}
2008-02-29 18:03:23 +03:00
}
2013-12-18 22:33:28 +04:00
return status ;
2008-02-29 18:03:23 +03:00
}