2008-01-17 01:18:07 +03:00
/*
2007-04-09 14:38:55 +04:00
* Unix SMB / CIFS implementation .
* Virtual Windows Registry Layer
* Copyright ( C ) Gerald Carter 2002 - 2005
2008-01-17 01:18:07 +03:00
* Copyright ( C ) Michael Adam 2006 - 2008
2007-04-09 14:38:55 +04: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 23:25:36 +04:00
* the Free Software Foundation ; either version 3 of the License , or
2007-04-09 14:38:55 +04:00
* ( at your option ) any later version .
2008-01-17 01:18:07 +03:00
*
2007-04-09 14:38:55 +04:00
* 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 .
2008-01-17 01:18:07 +03:00
*
2007-04-09 14:38:55 +04:00
* You should have received a copy of the GNU General Public License
2007-07-10 09:23:25 +04:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2007-04-09 14:38:55 +04:00
*/
2008-01-17 01:18:07 +03:00
/*
* Implementation of registry frontend view functions .
2007-04-09 14:38:55 +04:00
* Functions moved from reg_frontend . c to minimize linker deps .
*/
# include "includes.h"
2011-10-07 21:00:29 +04:00
# include "system/passwd.h" /* uid_wrapper */
2009-10-02 02:17:06 +04:00
# include "registry.h"
2010-05-25 00:49:42 +04:00
# include "reg_dispatcher.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2007-04-09 14:38:55 +04:00
2007-09-29 03:05:52 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_REGISTRY
2007-04-09 14:38:55 +04:00
2007-10-06 01:41:17 +04:00
static const struct generic_mapping reg_generic_map =
2007-04-09 14:38:55 +04:00
{ REG_KEY_READ , REG_KEY_WRITE , REG_KEY_EXECUTE , REG_KEY_ALL } ;
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-05-18 12:29:34 +04:00
static WERROR construct_registry_sd ( TALLOC_CTX * ctx , struct security_descriptor * * psd )
2007-04-09 14:38:55 +04:00
{
2010-05-18 05:25:38 +04:00
struct security_ace ace [ 3 ] ;
2007-04-09 14:38:55 +04:00
size_t i = 0 ;
2010-05-18 12:29:34 +04:00
struct security_descriptor * sd ;
2010-05-18 05:30:40 +04:00
struct security_acl * theacl ;
2007-04-09 14:38:55 +04:00
size_t sd_size ;
/* basic access for Everyone */
2008-01-17 01:18:07 +03:00
2008-02-18 16:44:51 +03:00
init_sec_ace ( & ace [ i + + ] , & global_sid_World , SEC_ACE_TYPE_ACCESS_ALLOWED ,
2008-10-09 20:49:03 +04:00
REG_KEY_READ , 0 ) ;
2008-01-17 01:18:07 +03:00
2007-04-09 14:38:55 +04:00
/* Full Access 'BUILTIN\Administrators' */
2008-01-17 01:18:07 +03:00
2008-02-18 16:44:51 +03:00
init_sec_ace ( & ace [ i + + ] , & global_sid_Builtin_Administrators ,
2008-10-09 20:49:03 +04:00
SEC_ACE_TYPE_ACCESS_ALLOWED , REG_KEY_ALL , 0 ) ;
2007-09-27 01:46:43 +04:00
/* Full Access 'NT Authority\System' */
2008-02-18 16:44:51 +03:00
init_sec_ace ( & ace [ i + + ] , & global_sid_System , SEC_ACE_TYPE_ACCESS_ALLOWED ,
2008-10-09 20:49:03 +04:00
REG_KEY_ALL , 0 ) ;
2007-09-27 01:46:43 +04:00
2007-04-09 14:38:55 +04:00
/* create the security descriptor */
2008-01-17 01:18:07 +03:00
2009-02-24 02:03:29 +03:00
theacl = make_sec_acl ( ctx , NT4_ACL_REVISION , i , ace ) ;
if ( theacl = = NULL ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2008-02-18 16:44:51 +03:00
}
2007-04-09 14:38:55 +04:00
2010-05-18 14:52:18 +04:00
sd = make_sec_desc ( ctx , SD_REVISION , SEC_DESC_SELF_RELATIVE ,
2008-02-18 18:03:16 +03:00
& global_sid_Builtin_Administrators ,
2009-02-24 02:03:29 +03:00
& global_sid_System , NULL , theacl ,
2008-02-18 16:44:51 +03:00
& sd_size ) ;
if ( sd = = NULL ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2008-02-18 16:44:51 +03:00
}
2007-04-09 14:38:55 +04:00
2008-02-18 16:55:48 +03:00
* psd = sd ;
return WERR_OK ;
2007-04-09 14:38:55 +04:00
}
/***********************************************************************
High level wrapper function for storing registry subkeys
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-17 01:18:07 +03:00
2009-03-24 01:02:57 +03:00
bool store_reg_keys ( struct registry_key_handle * key ,
struct regsubkey_ctr * subkeys )
2007-04-09 14:38:55 +04:00
{
2008-04-13 02:54:44 +04:00
if ( key - > ops & & key - > ops - > store_subkeys )
return key - > ops - > store_subkeys ( key - > name , subkeys ) ;
2007-04-09 14:38:55 +04:00
2008-01-17 01:19:38 +03:00
return false ;
2007-04-09 14:38:55 +04:00
}
/***********************************************************************
High level wrapper function for storing registry values
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-17 01:18:07 +03:00
2009-03-24 01:02:57 +03:00
bool store_reg_values ( struct registry_key_handle * key , struct regval_ctr * val )
2007-04-09 14:38:55 +04:00
{
2008-04-13 02:54:44 +04:00
if ( key - > ops & & key - > ops - > store_values )
return key - > ops - > store_values ( key - > name , val ) ;
2007-04-09 14:38:55 +04:00
2008-01-17 01:19:38 +03:00
return false ;
2007-04-09 14:38:55 +04:00
}
2009-03-24 01:02:57 +03:00
WERROR create_reg_subkey ( struct registry_key_handle * key , const char * subkey )
2009-02-25 23:59:54 +03:00
{
if ( key - > ops & & key - > ops - > create_subkey ) {
return key - > ops - > create_subkey ( key - > name , subkey ) ;
}
return WERR_NOT_SUPPORTED ;
}
2011-08-01 17:27:46 +04:00
WERROR delete_reg_subkey ( struct registry_key_handle * key , const char * subkey , bool lazy )
2009-02-26 04:54:50 +03:00
{
if ( key - > ops & & key - > ops - > delete_subkey ) {
2011-08-01 17:27:46 +04:00
return key - > ops - > delete_subkey ( key - > name , subkey , lazy ) ;
2009-02-26 04:54:50 +03:00
}
return WERR_NOT_SUPPORTED ;
}
2007-04-09 14:38:55 +04:00
/***********************************************************************
High level wrapper function for enumerating registry subkeys
Initialize the TALLOC_CTX if necessary
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-24 01:02:57 +03:00
int fetch_reg_keys ( struct registry_key_handle * key ,
struct regsubkey_ctr * subkey_ctr )
2007-04-09 14:38:55 +04:00
{
int result = - 1 ;
2008-01-17 01:18:07 +03:00
2008-04-13 02:54:44 +04:00
if ( key - > ops & & key - > ops - > fetch_subkeys )
result = key - > ops - > fetch_subkeys ( key - > name , subkey_ctr ) ;
2007-04-09 14:38:55 +04:00
return result ;
}
/***********************************************************************
High level wrapper function for enumerating registry values
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-24 01:02:57 +03:00
int fetch_reg_values ( struct registry_key_handle * key , struct regval_ctr * val )
2007-04-09 14:38:55 +04:00
{
int result = - 1 ;
2008-01-17 01:18:07 +03:00
2008-01-18 19:57:32 +03:00
DEBUG ( 10 , ( " fetch_reg_values called for key '%s' (ops %p) \n " , key - > name ,
2008-04-13 02:54:44 +04:00
( key - > ops ) ? ( void * ) key - > ops : NULL ) ) ;
2008-01-18 19:57:32 +03:00
2008-04-13 02:54:44 +04:00
if ( key - > ops & & key - > ops - > fetch_values )
result = key - > ops - > fetch_values ( key - > name , val ) ;
2008-01-17 01:18:07 +03:00
2007-04-09 14:38:55 +04:00
return result ;
}
/***********************************************************************
2008-01-17 01:18:07 +03:00
High level access check for passing the required access mask to the
2007-04-09 14:38:55 +04:00
underlying registry backend
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-04-14 17:50:28 +03:00
bool regkey_access_check ( struct registry_key_handle * key , uint32_t requested ,
uint32_t * granted ,
2010-08-26 14:04:11 +04:00
const struct security_token * token )
2007-04-09 14:38:55 +04:00
{
2010-05-18 12:29:34 +04:00
struct security_descriptor * sec_desc ;
2007-04-09 14:38:55 +04:00
NTSTATUS status ;
WERROR err ;
2010-03-16 15:53:54 +03:00
/* root free-pass, like we have on all other pipes like samr, lsa, etc. */
2013-11-06 20:43:19 +04:00
if ( root_mode ( ) ) {
2010-03-16 15:53:54 +03:00
* granted = REG_KEY_ALL ;
return true ;
}
2007-04-09 14:38:55 +04:00
/* use the default security check if the backend has not defined its
* own */
2008-04-13 02:54:44 +04:00
if ( key - > ops & & key - > ops - > reg_access_check ) {
return key - > ops - > reg_access_check ( key - > name , requested ,
granted , token ) ;
2007-04-09 14:38:55 +04:00
}
2009-02-27 13:18:35 +03:00
err = regkey_get_secdesc ( talloc_tos ( ) , key , & sec_desc ) ;
2007-04-09 14:38:55 +04:00
if ( ! W_ERROR_IS_OK ( err ) ) {
2008-01-17 01:19:38 +03:00
return false ;
2007-04-09 14:38:55 +04:00
}
se_map_generic ( & requested , & reg_generic_map ) ;
2008-10-31 20:51:45 +03:00
status = se_access_check ( sec_desc , token , requested , granted ) ;
2009-02-27 13:18:35 +03:00
TALLOC_FREE ( sec_desc ) ;
2008-10-31 20:51:45 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-17 01:19:38 +03:00
return false ;
2007-04-09 14:38:55 +04:00
}
return NT_STATUS_IS_OK ( status ) ;
}
2009-03-24 01:02:57 +03:00
WERROR regkey_get_secdesc ( TALLOC_CTX * mem_ctx , struct registry_key_handle * key ,
2007-04-09 14:38:55 +04:00
struct security_descriptor * * psecdesc )
{
struct security_descriptor * secdesc ;
2008-02-18 16:55:48 +03:00
WERROR werr ;
2007-04-09 14:38:55 +04:00
2008-04-13 02:54:44 +04:00
if ( key - > ops & & key - > ops - > get_secdesc ) {
werr = key - > ops - > get_secdesc ( mem_ctx , key - > name , psecdesc ) ;
2008-02-18 16:55:48 +03:00
if ( W_ERROR_IS_OK ( werr ) ) {
2007-04-09 14:38:55 +04:00
return WERR_OK ;
}
}
2008-02-18 16:55:48 +03:00
werr = construct_registry_sd ( mem_ctx , & secdesc ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
2007-04-09 14:38:55 +04:00
}
* psecdesc = secdesc ;
return WERR_OK ;
}
2007-11-06 02:50:47 +03:00
2009-03-24 01:02:57 +03:00
WERROR regkey_set_secdesc ( struct registry_key_handle * key ,
2007-11-06 02:50:47 +03:00
struct security_descriptor * psecdesc )
{
2008-04-13 02:54:44 +04:00
if ( key - > ops & & key - > ops - > set_secdesc ) {
return key - > ops - > set_secdesc ( key - > name , psecdesc ) ;
2007-11-06 02:50:47 +03:00
}
return WERR_ACCESS_DENIED ;
}
2008-01-14 20:31:11 +03:00
/**
* Check whether the in - memory version of the subkyes of a
* registry key needs update from disk .
*/
2009-03-24 01:02:57 +03:00
bool reg_subkeys_need_update ( struct registry_key_handle * key ,
struct regsubkey_ctr * subkeys )
2008-01-14 20:31:11 +03:00
{
2008-04-13 02:54:44 +04:00
if ( key - > ops & & key - > ops - > subkeys_need_update )
2008-01-14 20:31:11 +03:00
{
2008-04-13 02:54:44 +04:00
return key - > ops - > subkeys_need_update ( subkeys ) ;
2008-01-14 20:31:11 +03:00
}
2012-05-07 16:08:13 +04:00
return true ;
2008-01-14 20:31:11 +03:00
}
/**
* Check whether the in - memory version of the values of a
* registry key needs update from disk .
*/
2009-03-24 01:02:57 +03:00
bool reg_values_need_update ( struct registry_key_handle * key ,
struct regval_ctr * values )
2008-01-14 20:31:11 +03:00
{
2008-04-13 02:54:44 +04:00
if ( key - > ops & & key - > ops - > values_need_update )
2008-01-14 20:31:11 +03:00
{
2008-04-13 02:54:44 +04:00
return key - > ops - > values_need_update ( values ) ;
2008-01-14 20:31:11 +03:00
}
2012-05-07 16:09:28 +04:00
return true ;
2008-01-14 20:31:11 +03:00
}