2008-02-29 17:46:14 +03:00
/*
* Unix SMB / CIFS implementation .
* Group Policy Object 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"
# 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"
2010-05-25 00:42:00 +04:00
# include "registry/reg_backend_db.h"
2010-09-20 04:42:10 +04:00
# include "registry/reg_api_util.h"
2010-09-21 10:37:14 +04:00
# include "registry/reg_init_basic.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2018-11-23 10:49:44 +03:00
# include "libcli/security/dom_sid.h"
2011-02-26 02:28:15 +03:00
# include "../libcli/registry/util_reg.h"
2008-02-29 17:46:14 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-08-26 14:04:11 +04:00
struct security_token * registry_create_system_token ( TALLOC_CTX * mem_ctx )
2008-02-29 17:46:14 +03:00
{
2010-08-26 14:04:11 +04:00
struct security_token * token = NULL ;
2008-02-29 17:46:14 +03:00
2011-06-07 05:44:43 +04:00
token = talloc_zero ( mem_ctx , struct security_token ) ;
2008-02-29 17:46:14 +03:00
if ( ! token ) {
DEBUG ( 1 , ( " talloc failed \n " ) ) ;
return NULL ;
}
2010-08-30 07:14:40 +04:00
token - > privilege_mask = SE_ALL_PRIVS ;
2008-02-29 17:46:14 +03:00
if ( ! NT_STATUS_IS_OK ( add_sid_to_array ( token , & global_sid_System ,
2010-08-31 03:32:52 +04:00
& token - > sids , & token - > num_sids ) ) ) {
2008-02-29 17:46:14 +03:00
DEBUG ( 1 , ( " Error adding nt-authority system sid to token \n " ) ) ;
return NULL ;
}
return token ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
WERROR gp_init_reg_ctx ( TALLOC_CTX * mem_ctx ,
const char * initial_path ,
uint32_t desired_access ,
2010-08-26 14:04:11 +04:00
const struct security_token * token ,
2008-02-29 17:46:14 +03:00
struct gp_registry_context * * reg_ctx )
{
struct gp_registry_context * tmp_ctx ;
WERROR werr ;
if ( ! reg_ctx ) {
2015-12-03 17:24:24 +03:00
return WERR_INVALID_PARAMETER ;
2008-02-29 17:46:14 +03:00
}
2008-04-13 17:12:04 +04:00
werr = registry_init_basic ( ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
2008-02-29 17:46:14 +03:00
}
2011-06-07 05:44:43 +04:00
tmp_ctx = talloc_zero ( mem_ctx , struct gp_registry_context ) ;
2008-02-29 17:46:14 +03:00
W_ERROR_HAVE_NO_MEMORY ( tmp_ctx ) ;
if ( token ) {
tmp_ctx - > token = token ;
} else {
tmp_ctx - > token = registry_create_system_token ( mem_ctx ) ;
}
if ( ! tmp_ctx - > token ) {
TALLOC_FREE ( tmp_ctx ) ;
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2008-02-29 17:46:14 +03:00
}
2008-03-22 04:45:04 +03:00
werr = regdb_open ( ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
2008-02-29 17:46:14 +03:00
if ( initial_path ) {
tmp_ctx - > path = talloc_strdup ( mem_ctx , initial_path ) ;
if ( ! tmp_ctx - > path ) {
TALLOC_FREE ( tmp_ctx ) ;
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2008-02-29 17:46:14 +03:00
}
werr = reg_open_path ( mem_ctx , tmp_ctx - > path , desired_access ,
tmp_ctx - > token , & tmp_ctx - > curr_key ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
TALLOC_FREE ( tmp_ctx ) ;
return werr ;
}
}
* reg_ctx = tmp_ctx ;
return WERR_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void gp_free_reg_ctx ( struct gp_registry_context * reg_ctx )
{
TALLOC_FREE ( reg_ctx ) ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
WERROR gp_store_reg_subkey ( TALLOC_CTX * mem_ctx ,
const char * subkeyname ,
struct registry_key * curr_key ,
struct registry_key * * new_key )
{
enum winreg_CreateAction action = REG_ACTION_NONE ;
WERROR werr ;
werr = reg_createkey ( mem_ctx , curr_key , subkeyname ,
REG_KEY_WRITE , new_key , & action ) ;
if ( W_ERROR_IS_OK ( werr ) & & ( action ! = REG_CREATED_NEW_KEY ) ) {
return WERR_OK ;
}
return werr ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
WERROR gp_read_reg_subkey ( TALLOC_CTX * mem_ctx ,
struct gp_registry_context * reg_ctx ,
const char * subkeyname ,
struct registry_key * * key )
{
const char * tmp = NULL ;
if ( ! reg_ctx | | ! subkeyname | | ! key ) {
2015-12-03 17:24:24 +03:00
return WERR_INVALID_PARAMETER ;
2008-02-29 17:46:14 +03:00
}
tmp = talloc_asprintf ( mem_ctx , " %s \\ %s " , reg_ctx - > path , subkeyname ) ;
W_ERROR_HAVE_NO_MEMORY ( tmp ) ;
return reg_open_path ( mem_ctx , tmp , REG_KEY_READ ,
reg_ctx - > token , key ) ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
WERROR gp_store_reg_val_sz ( TALLOC_CTX * mem_ctx ,
struct registry_key * key ,
const char * val_name ,
const char * val )
{
struct registry_value reg_val ;
reg_val . type = REG_SZ ;
2010-06-29 18:13:15 +04:00
if ( ! push_reg_sz ( mem_ctx , & reg_val . data , val ) ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2010-06-29 18:13:15 +04:00
}
2008-02-29 17:46:14 +03:00
return reg_setvalue ( key , val_name , & reg_val ) ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR gp_store_reg_val_dword ( TALLOC_CTX * mem_ctx ,
struct registry_key * key ,
const char * val_name ,
uint32_t val )
{
struct registry_value reg_val ;
reg_val . type = REG_DWORD ;
2010-06-29 18:13:15 +04:00
reg_val . data = data_blob_talloc ( mem_ctx , NULL , 4 ) ;
SIVAL ( reg_val . data . data , 0 , val ) ;
2008-02-29 17:46:14 +03:00
return reg_setvalue ( key , val_name , & reg_val ) ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
WERROR gp_read_reg_val_sz ( TALLOC_CTX * mem_ctx ,
struct registry_key * key ,
const char * val_name ,
const char * * val )
{
WERROR werr ;
struct registry_value * reg_val = NULL ;
werr = reg_queryvalue ( mem_ctx , key , val_name , & reg_val ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
if ( reg_val - > type ! = REG_SZ ) {
return WERR_INVALID_DATATYPE ;
}
2010-06-29 18:13:15 +04:00
if ( ! pull_reg_sz ( mem_ctx , & reg_val - > data , val ) ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2010-06-29 18:13:15 +04:00
}
2008-02-29 17:46:14 +03:00
return WERR_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR gp_read_reg_val_dword ( TALLOC_CTX * mem_ctx ,
struct registry_key * key ,
const char * val_name ,
uint32_t * val )
{
WERROR werr ;
struct registry_value * reg_val = NULL ;
werr = reg_queryvalue ( mem_ctx , key , val_name , & reg_val ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
if ( reg_val - > type ! = REG_DWORD ) {
return WERR_INVALID_DATATYPE ;
}
2010-06-29 18:13:15 +04:00
if ( reg_val - > data . length < 4 ) {
return WERR_INSUFFICIENT_BUFFER ;
}
* val = IVAL ( reg_val - > data . data , 0 ) ;
2008-02-29 17:46:14 +03:00
return WERR_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR gp_store_reg_gpovals ( TALLOC_CTX * mem_ctx ,
struct registry_key * key ,
struct GROUP_POLICY_OBJECT * gpo )
{
WERROR werr ;
if ( ! key | | ! gpo ) {
2015-12-03 17:24:24 +03:00
return WERR_INVALID_PARAMETER ;
2008-02-29 17:46:14 +03:00
}
werr = gp_store_reg_val_dword ( mem_ctx , key , " Version " ,
gpo - > version ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
werr = gp_store_reg_val_dword ( mem_ctx , key , " WQLFilterPass " ,
true ) ; /* fake */
W_ERROR_NOT_OK_RETURN ( werr ) ;
werr = gp_store_reg_val_dword ( mem_ctx , key , " AccessDenied " ,
false ) ; /* fake */
W_ERROR_NOT_OK_RETURN ( werr ) ;
werr = gp_store_reg_val_dword ( mem_ctx , key , " GPO-Disabled " ,
( gpo - > options & GPO_FLAG_DISABLE ) ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
werr = gp_store_reg_val_dword ( mem_ctx , key , " Options " ,
gpo - > options ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
werr = gp_store_reg_val_sz ( mem_ctx , key , " GPOID " ,
gpo - > name ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
werr = gp_store_reg_val_sz ( mem_ctx , key , " SOM " ,
2013-12-10 20:39:54 +04:00
gpo - > link ? gpo - > link : " " ) ;
2008-02-29 17:46:14 +03:00
W_ERROR_NOT_OK_RETURN ( werr ) ;
werr = gp_store_reg_val_sz ( mem_ctx , key , " DisplayName " ,
gpo - > display_name ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
werr = gp_store_reg_val_sz ( mem_ctx , key , " WQL-Id " ,
2013-12-10 20:39:54 +04:00
" " ) ;
2008-02-29 17:46:14 +03:00
W_ERROR_NOT_OK_RETURN ( werr ) ;
return werr ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static const char * gp_reg_groupmembership_path ( TALLOC_CTX * mem_ctx ,
2010-05-21 05:25:01 +04:00
const struct dom_sid * sid ,
2008-02-29 17:46:14 +03:00
uint32_t flags )
{
2018-11-23 10:49:44 +03:00
struct dom_sid_buf sidbuf ;
2008-02-29 17:46:14 +03:00
if ( flags & GPO_LIST_FLAG_MACHINE ) {
return " GroupMembership " ;
}
2018-11-23 10:49:44 +03:00
return talloc_asprintf (
mem_ctx ,
" %s \\ %s " ,
dom_sid_str_buf ( sid , & sidbuf ) ,
" GroupMembership " ) ;
2008-02-29 17:46:14 +03:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR gp_reg_del_groupmembership ( TALLOC_CTX * mem_ctx ,
struct registry_key * key ,
2010-08-26 14:04:11 +04:00
const struct security_token * token ,
2008-02-29 17:46:14 +03:00
uint32_t flags )
{
const char * path = NULL ;
2010-08-31 03:32:52 +04:00
path = gp_reg_groupmembership_path ( mem_ctx , & token - > sids [ 0 ] ,
2008-02-29 17:46:14 +03:00
flags ) ;
W_ERROR_HAVE_NO_MEMORY ( path ) ;
2010-09-22 08:21:38 +04:00
return reg_deletekey_recursive ( key , path ) ;
2008-02-29 17:46:14 +03:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR gp_reg_store_groupmembership ( TALLOC_CTX * mem_ctx ,
struct gp_registry_context * reg_ctx ,
2010-08-26 14:04:11 +04:00
const struct security_token * token ,
2008-02-29 17:46:14 +03:00
uint32_t flags )
{
struct registry_key * key = NULL ;
WERROR werr ;
2018-11-23 10:50:47 +03:00
uint32_t i = 0 ;
2008-02-29 17:46:14 +03:00
const char * valname = NULL ;
const char * path = NULL ;
int count = 0 ;
2010-08-31 03:32:52 +04:00
path = gp_reg_groupmembership_path ( mem_ctx , & token - > sids [ 0 ] ,
2008-02-29 17:46:14 +03:00
flags ) ;
W_ERROR_HAVE_NO_MEMORY ( path ) ;
gp_reg_del_groupmembership ( mem_ctx , reg_ctx - > curr_key , token , flags ) ;
werr = gp_store_reg_subkey ( mem_ctx , path ,
reg_ctx - > curr_key , & key ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
for ( i = 0 ; i < token - > num_sids ; i + + ) {
2018-12-10 14:34:13 +03:00
struct dom_sid_buf buf ;
2008-02-29 17:46:14 +03:00
valname = talloc_asprintf ( mem_ctx , " Group%d " , count + + ) ;
W_ERROR_HAVE_NO_MEMORY ( valname ) ;
2018-12-10 14:34:13 +03:00
werr = gp_store_reg_val_sz (
mem_ctx ,
key ,
valname ,
dom_sid_str_buf ( & token - > sids [ i ] , & buf ) ) ;
2008-02-29 17:46:14 +03:00
W_ERROR_NOT_OK_RETURN ( werr ) ;
}
werr = gp_store_reg_val_dword ( mem_ctx , key , " Count " , count ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
return WERR_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#if 0
/* not used yet */
static WERROR gp_reg_read_groupmembership ( TALLOC_CTX * mem_ctx ,
struct gp_registry_context * reg_ctx ,
2010-05-21 05:25:01 +04:00
const struct dom_sid * object_sid ,
2010-08-26 14:04:11 +04:00
struct security_token * * token ,
2008-02-29 17:46:14 +03:00
uint32_t flags )
{
struct registry_key * key = NULL ;
WERROR werr ;
int i = 0 ;
const char * valname = NULL ;
const char * val = NULL ;
const char * path = NULL ;
uint32_t count = 0 ;
int num_token_sids = 0 ;
2010-08-26 14:04:11 +04:00
struct security_token * tmp_token = NULL ;
2008-02-29 17:46:14 +03:00
2011-06-07 05:44:43 +04:00
tmp_token = talloc_zero ( mem_ctx , struct security_token ) ;
2008-02-29 17:46:14 +03:00
W_ERROR_HAVE_NO_MEMORY ( tmp_token ) ;
path = gp_reg_groupmembership_path ( mem_ctx , object_sid , flags ) ;
W_ERROR_HAVE_NO_MEMORY ( path ) ;
werr = gp_read_reg_subkey ( mem_ctx , reg_ctx , path , & key ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
werr = gp_read_reg_val_dword ( mem_ctx , key , " Count " , & count ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
for ( i = 0 ; i < count ; i + + ) {
valname = talloc_asprintf ( mem_ctx , " Group%d " , i ) ;
W_ERROR_HAVE_NO_MEMORY ( valname ) ;
werr = gp_read_reg_val_sz ( mem_ctx , key , valname , & val ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
2010-08-31 03:32:52 +04:00
if ( ! string_to_sid ( & tmp_token - > sids [ num_token_sids + + ] ,
2008-02-29 17:46:14 +03:00
val ) ) {
return WERR_INSUFFICIENT_BUFFER ;
}
}
tmp_token - > num_sids = num_token_sids ;
* token = tmp_token ;
return WERR_OK ;
}
# endif
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static const char * gp_req_state_path ( TALLOC_CTX * mem_ctx ,
2010-05-21 05:25:01 +04:00
const struct dom_sid * sid ,
2008-02-29 17:46:14 +03:00
uint32_t flags )
{
2018-11-23 10:49:44 +03:00
struct dom_sid_buf sidbuf ;
2008-02-29 17:46:14 +03:00
if ( flags & GPO_LIST_FLAG_MACHINE ) {
return GPO_REG_STATE_MACHINE ;
}
2018-11-23 10:49:44 +03:00
return talloc_asprintf (
mem_ctx ,
" %s \\ %s " ,
" State " ,
dom_sid_str_buf ( sid , & sidbuf ) ) ;
2008-02-29 17:46:14 +03:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR gp_del_reg_state ( TALLOC_CTX * mem_ctx ,
struct registry_key * key ,
const char * path )
{
2010-09-22 08:21:38 +04:00
return reg_deletesubkeys_recursive ( key , path ) ;
2008-02-29 17:46:14 +03:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
WERROR gp_reg_state_store ( TALLOC_CTX * mem_ctx ,
uint32_t flags ,
const char * dn ,
2010-08-26 14:04:11 +04:00
const struct security_token * token ,
2008-02-29 17:46:14 +03:00
struct GROUP_POLICY_OBJECT * gpo_list )
{
struct gp_registry_context * reg_ctx = NULL ;
2015-12-03 17:24:20 +03:00
WERROR werr = WERR_GEN_FAILURE ;
2008-02-29 17:46:14 +03:00
const char * subkeyname = NULL ;
struct GROUP_POLICY_OBJECT * gpo ;
int count = 0 ;
struct registry_key * key ;
werr = gp_init_reg_ctx ( mem_ctx , KEY_GROUP_POLICY , REG_KEY_WRITE ,
token , & reg_ctx ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
2008-03-22 04:22:54 +03:00
werr = gp_secure_key ( mem_ctx , flags , reg_ctx - > curr_key ,
2010-08-31 03:32:52 +04:00
& token - > sids [ 0 ] ) ;
2008-02-29 17:46:14 +03:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
2008-11-01 19:19:26 +03:00
DEBUG ( 0 , ( " failed to secure key: %s \n " , win_errstr ( werr ) ) ) ;
2008-02-29 17:46:14 +03:00
goto done ;
}
werr = gp_reg_store_groupmembership ( mem_ctx , reg_ctx , token , flags ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
2008-11-01 19:19:26 +03:00
DEBUG ( 0 , ( " failed to store group membership: %s \n " , win_errstr ( werr ) ) ) ;
2008-02-29 17:46:14 +03:00
goto done ;
}
2010-08-31 03:32:52 +04:00
subkeyname = gp_req_state_path ( mem_ctx , & token - > sids [ 0 ] , flags ) ;
2008-02-29 17:46:14 +03:00
if ( ! subkeyname ) {
2015-12-03 17:24:14 +03:00
werr = WERR_NOT_ENOUGH_MEMORY ;
2008-02-29 17:46:14 +03:00
goto done ;
}
werr = gp_del_reg_state ( mem_ctx , reg_ctx - > curr_key , subkeyname ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
2008-11-01 19:19:26 +03:00
DEBUG ( 0 , ( " failed to delete old state: %s \n " , win_errstr ( werr ) ) ) ;
2008-02-29 17:46:14 +03:00
/* goto done; */
}
werr = gp_store_reg_subkey ( mem_ctx , subkeyname ,
reg_ctx - > curr_key , & reg_ctx - > curr_key ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
werr = gp_store_reg_val_sz ( mem_ctx , reg_ctx - > curr_key ,
" Distinguished-Name " , dn ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
/* store link list */
werr = gp_store_reg_subkey ( mem_ctx , " GPLink-List " ,
reg_ctx - > curr_key , & key ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
/* store gpo list */
werr = gp_store_reg_subkey ( mem_ctx , " GPO-List " ,
reg_ctx - > curr_key , & reg_ctx - > curr_key ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
for ( gpo = gpo_list ; gpo ; gpo = gpo - > next ) {
subkeyname = talloc_asprintf ( mem_ctx , " %d " , count + + ) ;
if ( ! subkeyname ) {
2015-12-03 17:24:14 +03:00
werr = WERR_NOT_ENOUGH_MEMORY ;
2008-02-29 17:46:14 +03:00
goto done ;
}
werr = gp_store_reg_subkey ( mem_ctx , subkeyname ,
reg_ctx - > curr_key , & key ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
werr = gp_store_reg_gpovals ( mem_ctx , key , gpo ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 0 , ( " gp_reg_state_store: "
2013-12-10 20:39:54 +04:00
" gp_store_reg_gpovals failed for %s: %s \n " ,
2008-11-01 19:19:26 +03:00
gpo - > display_name , win_errstr ( werr ) ) ) ;
2008-02-29 17:46:14 +03:00
goto done ;
}
}
done :
gp_free_reg_ctx ( reg_ctx ) ;
return werr ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR gp_read_reg_gpovals ( TALLOC_CTX * mem_ctx ,
struct registry_key * key ,
struct GROUP_POLICY_OBJECT * gpo )
{
WERROR werr ;
if ( ! key | | ! gpo ) {
2015-12-03 17:24:24 +03:00
return WERR_INVALID_PARAMETER ;
2008-02-29 17:46:14 +03:00
}
werr = gp_read_reg_val_dword ( mem_ctx , key , " Version " ,
& gpo - > version ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
werr = gp_read_reg_val_dword ( mem_ctx , key , " Options " ,
& gpo - > options ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
werr = gp_read_reg_val_sz ( mem_ctx , key , " GPOID " ,
& gpo - > name ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
werr = gp_read_reg_val_sz ( mem_ctx , key , " SOM " ,
& gpo - > link ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
werr = gp_read_reg_val_sz ( mem_ctx , key , " DisplayName " ,
& gpo - > display_name ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
return werr ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR gp_read_reg_gpo ( TALLOC_CTX * mem_ctx ,
struct registry_key * key ,
struct GROUP_POLICY_OBJECT * * gpo_ret )
{
struct GROUP_POLICY_OBJECT * gpo = NULL ;
WERROR werr ;
if ( ! gpo_ret | | ! key ) {
2015-12-03 17:24:24 +03:00
return WERR_INVALID_PARAMETER ;
2008-02-29 17:46:14 +03:00
}
2011-06-07 05:44:43 +04:00
gpo = talloc_zero ( mem_ctx , struct GROUP_POLICY_OBJECT ) ;
2008-02-29 17:46:14 +03:00
W_ERROR_HAVE_NO_MEMORY ( gpo ) ;
werr = gp_read_reg_gpovals ( mem_ctx , key , gpo ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
* gpo_ret = gpo ;
return werr ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
WERROR gp_reg_state_read ( TALLOC_CTX * mem_ctx ,
uint32_t flags ,
2010-05-21 05:25:01 +04:00
const struct dom_sid * sid ,
2008-02-29 17:46:14 +03:00
struct GROUP_POLICY_OBJECT * * gpo_list )
{
struct gp_registry_context * reg_ctx = NULL ;
2015-12-03 17:24:20 +03:00
WERROR werr = WERR_GEN_FAILURE ;
2008-02-29 17:46:14 +03:00
const char * subkeyname = NULL ;
struct GROUP_POLICY_OBJECT * gpo = NULL ;
int count = 0 ;
struct registry_key * key = NULL ;
const char * path = NULL ;
const char * gp_state_path = NULL ;
if ( ! gpo_list ) {
2015-12-03 17:24:24 +03:00
return WERR_INVALID_PARAMETER ;
2008-02-29 17:46:14 +03:00
}
ZERO_STRUCTP ( gpo_list ) ;
gp_state_path = gp_req_state_path ( mem_ctx , sid , flags ) ;
if ( ! gp_state_path ) {
2015-12-03 17:24:14 +03:00
werr = WERR_NOT_ENOUGH_MEMORY ;
2008-02-29 17:46:14 +03:00
goto done ;
}
path = talloc_asprintf ( mem_ctx , " %s \\ %s \\ %s " ,
KEY_GROUP_POLICY ,
gp_state_path ,
" GPO-List " ) ;
if ( ! path ) {
2015-12-03 17:24:14 +03:00
werr = WERR_NOT_ENOUGH_MEMORY ;
2008-02-29 17:46:14 +03:00
goto done ;
}
werr = gp_init_reg_ctx ( mem_ctx , path , REG_KEY_READ , NULL , & reg_ctx ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
while ( 1 ) {
subkeyname = talloc_asprintf ( mem_ctx , " %d " , count + + ) ;
if ( ! subkeyname ) {
2015-12-03 17:24:14 +03:00
werr = WERR_NOT_ENOUGH_MEMORY ;
2008-02-29 17:46:14 +03:00
goto done ;
}
werr = gp_read_reg_subkey ( mem_ctx , reg_ctx , subkeyname , & key ) ;
2015-12-03 17:24:11 +03:00
if ( W_ERROR_EQUAL ( werr , WERR_FILE_NOT_FOUND ) ) {
2008-02-29 17:46:14 +03:00
werr = WERR_OK ;
break ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 0 , ( " gp_reg_state_read: "
" gp_read_reg_subkey gave: %s \n " ,
2008-11-01 19:19:26 +03:00
win_errstr ( werr ) ) ) ;
2008-02-29 17:46:14 +03:00
goto done ;
}
werr = gp_read_reg_gpo ( mem_ctx , key , & gpo ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
DLIST_ADD ( * gpo_list , gpo ) ;
}
done :
gp_free_reg_ctx ( reg_ctx ) ;
return werr ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR gp_reg_generate_sd ( TALLOC_CTX * mem_ctx ,
2010-05-21 05:25:01 +04:00
const struct dom_sid * sid ,
2008-02-29 17:46:14 +03:00
struct security_descriptor * * sd ,
size_t * sd_size )
{
2010-05-18 05:25:38 +04:00
struct security_ace ace [ 6 ] ;
2008-10-09 20:49:03 +04:00
uint32_t mask ;
2008-02-29 17:46:14 +03:00
2010-05-18 05:30:40 +04:00
struct security_acl * theacl = NULL ;
2008-02-29 17:46:14 +03:00
uint8_t inherit_flags ;
2008-10-09 20:49:03 +04:00
mask = REG_KEY_ALL ;
2008-02-29 17:46:14 +03:00
init_sec_ace ( & ace [ 0 ] ,
& global_sid_System ,
SEC_ACE_TYPE_ACCESS_ALLOWED ,
mask , 0 ) ;
2008-10-09 20:49:03 +04:00
mask = REG_KEY_ALL ;
2008-02-29 17:46:14 +03:00
init_sec_ace ( & ace [ 1 ] ,
& global_sid_Builtin_Administrators ,
SEC_ACE_TYPE_ACCESS_ALLOWED ,
mask , 0 ) ;
2008-10-09 20:49:03 +04:00
mask = REG_KEY_READ ;
2008-02-29 17:46:14 +03:00
init_sec_ace ( & ace [ 2 ] ,
sid ? sid : & global_sid_Authenticated_Users ,
SEC_ACE_TYPE_ACCESS_ALLOWED ,
mask , 0 ) ;
inherit_flags = SEC_ACE_FLAG_OBJECT_INHERIT |
SEC_ACE_FLAG_CONTAINER_INHERIT |
SEC_ACE_FLAG_INHERIT_ONLY ;
2008-10-09 20:49:03 +04:00
mask = REG_KEY_ALL ;
2008-02-29 17:46:14 +03:00
init_sec_ace ( & ace [ 3 ] ,
& global_sid_System ,
SEC_ACE_TYPE_ACCESS_ALLOWED ,
mask , inherit_flags ) ;
2008-10-09 20:49:03 +04:00
mask = REG_KEY_ALL ;
2008-02-29 17:46:14 +03:00
init_sec_ace ( & ace [ 4 ] ,
& global_sid_Builtin_Administrators ,
SEC_ACE_TYPE_ACCESS_ALLOWED ,
mask , inherit_flags ) ;
2008-10-09 20:49:03 +04:00
mask = REG_KEY_READ ;
2008-02-29 17:46:14 +03:00
init_sec_ace ( & ace [ 5 ] ,
sid ? sid : & global_sid_Authenticated_Users ,
SEC_ACE_TYPE_ACCESS_ALLOWED ,
mask , inherit_flags ) ;
2009-02-24 02:44:34 +03:00
theacl = make_sec_acl ( mem_ctx , NT4_ACL_REVISION , 6 , ace ) ;
W_ERROR_HAVE_NO_MEMORY ( theacl ) ;
2008-02-29 17:46:14 +03:00
2010-05-18 14:52:18 +04:00
* sd = make_sec_desc ( mem_ctx , SD_REVISION ,
2008-02-29 17:46:14 +03:00
SEC_DESC_SELF_RELATIVE |
SEC_DESC_DACL_AUTO_INHERITED | /* really ? */
SEC_DESC_DACL_AUTO_INHERIT_REQ , /* really ? */
NULL , NULL , NULL ,
2009-02-24 02:44:34 +03:00
theacl , sd_size ) ;
2008-02-29 17:46:14 +03:00
W_ERROR_HAVE_NO_MEMORY ( * sd ) ;
return WERR_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
WERROR gp_secure_key ( TALLOC_CTX * mem_ctx ,
uint32_t flags ,
2008-03-22 04:22:54 +03:00
struct registry_key * key ,
2010-05-21 05:25:01 +04:00
const struct dom_sid * sid )
2008-02-29 17:46:14 +03:00
{
struct security_descriptor * sd = NULL ;
size_t sd_size = 0 ;
2010-05-21 05:25:01 +04:00
const struct dom_sid * sd_sid = NULL ;
2008-02-29 17:46:14 +03:00
WERROR werr ;
if ( ! ( flags & GPO_LIST_FLAG_MACHINE ) ) {
sd_sid = sid ;
}
werr = gp_reg_generate_sd ( mem_ctx , sd_sid , & sd , & sd_size ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
2008-03-22 04:22:54 +03:00
return reg_setkeysecurity ( key , sd ) ;
2008-02-29 17:46:14 +03:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void dump_reg_val ( int lvl , const char * direction ,
const char * key , const char * subkey ,
struct registry_value * val )
{
int i = 0 ;
const char * type_str = NULL ;
if ( ! val ) {
DEBUG ( lvl , ( " no val! \n " ) ) ;
return ;
}
2010-04-27 18:38:40 +04:00
type_str = str_regtype ( val - > type ) ;
2008-02-29 17:46:14 +03:00
2008-04-17 16:04:18 +04:00
DEBUG ( lvl , ( " \t dump_reg_val: \t %s '%s' \n \t \t \t '%s' %s: " ,
2008-02-29 17:46:14 +03:00
direction , key , subkey , type_str ) ) ;
switch ( val - > type ) {
2010-06-29 18:13:15 +04:00
case REG_DWORD : {
uint32_t v ;
if ( val - > data . length < 4 ) {
break ;
}
v = IVAL ( val - > data . data , 0 ) ;
2008-04-13 19:32:07 +04:00
DEBUG ( lvl , ( " %d (0x%08x) \n " ,
2010-06-29 18:13:15 +04:00
( int ) v , v ) ) ;
2008-02-29 17:46:14 +03:00
break ;
2010-06-29 18:13:15 +04:00
}
case REG_QWORD : {
uint64_t v ;
if ( val - > data . length < 8 ) {
break ;
}
v = BVAL ( val - > data . data , 0 ) ;
2008-04-14 20:21:21 +04:00
DEBUG ( lvl , ( " %d (0x%016llx) \n " ,
2010-06-29 18:13:15 +04:00
( int ) v ,
( unsigned long long ) v ) ) ;
2008-02-29 17:46:14 +03:00
break ;
2010-06-29 18:13:15 +04:00
}
case REG_SZ : {
const char * s ;
if ( ! pull_reg_sz ( talloc_tos ( ) , & val - > data , & s ) ) {
break ;
}
2008-02-29 17:46:14 +03:00
DEBUG ( lvl , ( " %s (length: %d) \n " ,
2010-06-29 18:13:15 +04:00
s , ( int ) strlen_m ( s ) ) ) ;
2008-02-29 17:46:14 +03:00
break ;
2010-06-29 18:13:15 +04:00
}
case REG_MULTI_SZ : {
const char * * a ;
if ( ! pull_reg_multi_sz ( talloc_tos ( ) , & val - > data , & a ) ) {
break ;
}
for ( i = 0 ; a [ i ] ! = NULL ; i + + ) {
; ;
}
DEBUG ( lvl , ( " (num_strings: %d) \n " , i ) ) ;
for ( i = 0 ; a [ i ] ! = NULL ; i + + ) {
DEBUGADD ( lvl , ( " \t %s \n " , a [ i ] ) ) ;
2008-02-29 17:46:14 +03:00
}
break ;
2010-06-29 18:13:15 +04:00
}
2008-02-29 17:46:14 +03:00
case REG_NONE :
DEBUG ( lvl , ( " \n " ) ) ;
break ;
case REG_BINARY :
2010-06-29 18:13:15 +04:00
dump_data ( lvl , val - > data . data ,
val - > data . length ) ;
2008-02-29 17:46:14 +03:00
break ;
default :
DEBUG ( lvl , ( " unsupported type: %d \n " , val - > type ) ) ;
break ;
}
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void dump_reg_entry ( uint32_t flags ,
const char * dir ,
struct gp_registry_entry * entry )
{
if ( ! ( flags & GPO_INFO_FLAG_VERBOSE ) )
return ;
dump_reg_val ( 1 , dir ,
entry - > key ,
entry - > value ,
entry - > data ) ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void dump_reg_entries ( uint32_t flags ,
const char * dir ,
struct gp_registry_entry * entries ,
size_t num_entries )
{
size_t i ;
if ( ! ( flags & GPO_INFO_FLAG_VERBOSE ) )
return ;
for ( i = 0 ; i < num_entries ; i + + ) {
dump_reg_entry ( flags , dir , & entries [ i ] ) ;
}
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool add_gp_registry_entry_to_array ( TALLOC_CTX * mem_ctx ,
struct gp_registry_entry * entry ,
struct gp_registry_entry * * entries ,
size_t * num )
{
2011-06-07 05:10:15 +04:00
* entries = talloc_realloc ( mem_ctx , * entries ,
2008-02-29 17:46:14 +03:00
struct gp_registry_entry ,
( * num ) + 1 ) ;
if ( * entries = = NULL ) {
* num = 0 ;
return false ;
}
( * entries ) [ * num ] . action = entry - > action ;
( * entries ) [ * num ] . key = entry - > key ;
( * entries ) [ * num ] . value = entry - > value ;
( * entries ) [ * num ] . data = entry - > data ;
* num + = 1 ;
return true ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static const char * gp_reg_action_str ( enum gp_reg_action action )
{
switch ( action ) {
case GP_REG_ACTION_NONE :
return " GP_REG_ACTION_NONE " ;
case GP_REG_ACTION_ADD_VALUE :
return " GP_REG_ACTION_ADD_VALUE " ;
case GP_REG_ACTION_ADD_KEY :
return " GP_REG_ACTION_ADD_KEY " ;
case GP_REG_ACTION_DEL_VALUES :
return " GP_REG_ACTION_DEL_VALUES " ;
case GP_REG_ACTION_DEL_VALUE :
return " GP_REG_ACTION_DEL_VALUE " ;
case GP_REG_ACTION_DEL_ALL_VALUES :
return " GP_REG_ACTION_DEL_ALL_VALUES " ;
case GP_REG_ACTION_DEL_KEYS :
return " GP_REG_ACTION_DEL_KEYS " ;
case GP_REG_ACTION_SEC_KEY_SET :
return " GP_REG_ACTION_SEC_KEY_SET " ;
case GP_REG_ACTION_SEC_KEY_RESET :
return " GP_REG_ACTION_SEC_KEY_RESET " ;
default :
return " unknown " ;
}
2008-04-09 20:20:07 +04:00
}
2008-02-29 17:46:14 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
WERROR reg_apply_registry_entry ( TALLOC_CTX * mem_ctx ,
struct registry_key * root_key ,
struct gp_registry_context * reg_ctx ,
struct gp_registry_entry * entry ,
2010-08-26 14:04:11 +04:00
const struct security_token * token ,
2008-02-29 17:46:14 +03:00
uint32_t flags )
{
WERROR werr ;
struct registry_key * key = NULL ;
if ( flags & GPO_INFO_FLAG_VERBOSE ) {
printf ( " about to store key: [%s] \n " , entry - > key ) ;
printf ( " value: [%s] \n " , entry - > value ) ;
2010-04-27 18:38:40 +04:00
printf ( " data: [%s] \n " , str_regtype ( entry - > data - > type ) ) ;
2008-02-29 17:46:14 +03:00
printf ( " action: [%s] \n " , gp_reg_action_str ( entry - > action ) ) ;
}
werr = gp_store_reg_subkey ( mem_ctx , entry - > key ,
root_key , & key ) ;
/* reg_ctx->curr_key, &key); */
if ( ! W_ERROR_IS_OK ( werr ) ) {
2008-11-01 19:19:26 +03:00
DEBUG ( 0 , ( " gp_store_reg_subkey failed: %s \n " , win_errstr ( werr ) ) ) ;
2008-02-29 17:46:14 +03:00
return werr ;
}
switch ( entry - > action ) {
case GP_REG_ACTION_NONE :
case GP_REG_ACTION_ADD_KEY :
return WERR_OK ;
case GP_REG_ACTION_SEC_KEY_SET :
werr = gp_secure_key ( mem_ctx , flags ,
2008-03-22 04:22:54 +03:00
key ,
2010-08-31 03:32:52 +04:00
& token - > sids [ 0 ] ) ;
2008-02-29 17:46:14 +03:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 0 , ( " reg_apply_registry_entry: "
" gp_secure_key failed: %s \n " ,
2008-11-01 19:19:26 +03:00
win_errstr ( werr ) ) ) ;
2008-02-29 17:46:14 +03:00
return werr ;
}
break ;
case GP_REG_ACTION_ADD_VALUE :
werr = reg_setvalue ( key , entry - > value , entry - > data ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 0 , ( " reg_apply_registry_entry: "
" reg_setvalue failed: %s \n " ,
2008-11-01 19:19:26 +03:00
win_errstr ( werr ) ) ) ;
2008-02-29 17:46:14 +03:00
dump_reg_entry ( flags , " STORE " , entry ) ;
return werr ;
}
break ;
case GP_REG_ACTION_DEL_VALUE :
werr = reg_deletevalue ( key , entry - > value ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 0 , ( " reg_apply_registry_entry: "
" reg_deletevalue failed: %s \n " ,
2008-11-01 19:19:26 +03:00
win_errstr ( werr ) ) ) ;
2008-02-29 17:46:14 +03:00
dump_reg_entry ( flags , " STORE " , entry ) ;
return werr ;
}
break ;
case GP_REG_ACTION_DEL_ALL_VALUES :
werr = reg_deleteallvalues ( key ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 0 , ( " reg_apply_registry_entry: "
" reg_deleteallvalues failed: %s \n " ,
2008-11-01 19:19:26 +03:00
win_errstr ( werr ) ) ) ;
2008-02-29 17:46:14 +03:00
dump_reg_entry ( flags , " STORE " , entry ) ;
return werr ;
}
break ;
case GP_REG_ACTION_DEL_VALUES :
case GP_REG_ACTION_DEL_KEYS :
case GP_REG_ACTION_SEC_KEY_RESET :
DEBUG ( 0 , ( " reg_apply_registry_entry: "
" not yet supported: %s (%d) \n " ,
gp_reg_action_str ( entry - > action ) ,
entry - > action ) ) ;
return WERR_NOT_SUPPORTED ;
default :
DEBUG ( 0 , ( " invalid action: %d \n " , entry - > action ) ) ;
2015-12-03 17:24:24 +03:00
return WERR_INVALID_PARAMETER ;
2008-02-29 17:46:14 +03:00
}
return werr ;
}