2008-03-21 18:26:50 +03:00
/*
* Unix SMB / CIFS implementation .
* libsmbconf - Samba configuration library , registry backend
* Copyright ( C ) Michael Adam 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"
# include "smbconf_private.h"
2008-04-08 19:46:36 +04:00
# define INCLUDES_VALNAME "includes"
2008-03-22 00:52:27 +03:00
struct reg_private_data {
NT_USER_TOKEN * token ;
2008-03-22 01:39:01 +03:00
bool open ; /* did _we_ open the registry? */
2008-03-22 00:52:27 +03:00
} ;
2008-03-21 18:26:50 +03:00
/**********************************************************************
*
* helper functions
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-03-22 00:55:20 +03:00
/**
* a convenience helper to cast the private data structure
*/
2008-03-22 00:52:27 +03:00
static struct reg_private_data * rpd ( struct smbconf_ctx * ctx )
{
return ( struct reg_private_data * ) ( ctx - > data ) ;
}
2008-04-09 00:51:02 +04:00
/*
* check whether a given value name is forbidden in registry ( smbconf )
*/
2008-04-09 00:57:48 +04:00
static bool smbconf_reg_valname_forbidden ( const char * valname )
2008-04-09 00:51:02 +04:00
{
/* hard code the list of forbidden names here for now */
const char * forbidden_valnames [ ] = {
" lock directory " ,
" lock dir " ,
" config backend " ,
NULL
} ;
const char * * forbidden = NULL ;
for ( forbidden = forbidden_valnames ; * forbidden ! = NULL ; forbidden + + ) {
if ( strwicmp ( valname , * forbidden ) = = 0 ) {
return true ;
}
}
return false ;
}
2008-04-09 02:05:45 +04:00
static bool smbconf_reg_valname_valid ( const char * valname )
{
return ( lp_parameter_is_valid ( valname ) & &
! smbconf_reg_valname_forbidden ( valname ) ) ;
}
2008-03-21 18:26:50 +03:00
/**
* Open a registry key specified by " path "
*/
static WERROR smbconf_reg_open_path ( TALLOC_CTX * mem_ctx ,
struct smbconf_ctx * ctx ,
const char * path ,
uint32 desired_access ,
struct registry_key * * key )
{
WERROR werr = WERR_OK ;
if ( ctx = = NULL ) {
DEBUG ( 1 , ( " Error: configuration is not open! \n " ) ) ;
werr = WERR_INVALID_PARAM ;
goto done ;
}
2008-03-22 00:52:27 +03:00
if ( rpd ( ctx ) - > token = = NULL ) {
2008-03-21 18:26:50 +03:00
DEBUG ( 1 , ( " Error: token missing from smbconf_ctx. "
" was smbconf_init() called? \n " ) ) ;
werr = WERR_INVALID_PARAM ;
goto done ;
}
2008-03-22 01:39:01 +03:00
werr = ctx - > ops - > open_conf ( ctx ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 1 , ( " Error opening the registry. \n " ) ) ;
goto done ;
}
2008-03-21 18:26:50 +03:00
if ( path = = NULL ) {
DEBUG ( 1 , ( " Error: NULL path string given \n " ) ) ;
werr = WERR_INVALID_PARAM ;
goto done ;
}
2008-03-22 00:52:27 +03:00
werr = reg_open_path ( mem_ctx , path , desired_access , rpd ( ctx ) - > token ,
key ) ;
2008-03-21 18:26:50 +03:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 1 , ( " Error opening registry path '%s': %s \n " ,
path , dos_errstr ( werr ) ) ) ;
}
done :
return werr ;
}
/**
2008-03-21 19:55:31 +03:00
* Open a subkey of the base key ( i . e a service )
2008-03-21 18:26:50 +03:00
*/
static WERROR smbconf_reg_open_service_key ( TALLOC_CTX * mem_ctx ,
struct smbconf_ctx * ctx ,
const char * servicename ,
uint32 desired_access ,
struct registry_key * * key )
{
WERROR werr = WERR_OK ;
char * path = NULL ;
if ( servicename = = NULL ) {
DEBUG ( 3 , ( " Error: NULL servicename given. \n " ) ) ;
werr = WERR_INVALID_PARAM ;
goto done ;
}
2008-03-21 19:55:31 +03:00
path = talloc_asprintf ( mem_ctx , " %s \\ %s " , ctx - > path , servicename ) ;
2008-03-21 18:26:50 +03:00
if ( path = = NULL ) {
werr = WERR_NOMEM ;
goto done ;
}
werr = smbconf_reg_open_path ( mem_ctx , ctx , path , desired_access , key ) ;
done :
TALLOC_FREE ( path ) ;
return werr ;
}
/**
2008-03-21 19:55:31 +03:00
* open the base key
2008-03-21 18:26:50 +03:00
*/
static WERROR smbconf_reg_open_base_key ( TALLOC_CTX * mem_ctx ,
struct smbconf_ctx * ctx ,
uint32 desired_access ,
struct registry_key * * key )
{
2008-03-21 19:55:31 +03:00
return smbconf_reg_open_path ( mem_ctx , ctx , ctx - > path , desired_access ,
2008-03-21 18:26:50 +03:00
key ) ;
}
/**
* check if a value exists in a given registry key
*/
static bool smbconf_value_exists ( struct registry_key * key , const char * param )
{
bool ret = false ;
WERROR werr = WERR_OK ;
TALLOC_CTX * ctx = talloc_stackframe ( ) ;
struct registry_value * value = NULL ;
werr = reg_queryvalue ( ctx , key , param , & value ) ;
if ( W_ERROR_IS_OK ( werr ) ) {
ret = true ;
}
TALLOC_FREE ( ctx ) ;
return ret ;
}
/**
2008-03-21 19:55:31 +03:00
* create a subkey of the base key ( i . e . a service . . . )
2008-03-21 18:26:50 +03:00
*/
static WERROR smbconf_reg_create_service_key ( TALLOC_CTX * mem_ctx ,
struct smbconf_ctx * ctx ,
const char * subkeyname ,
struct registry_key * * newkey )
{
WERROR werr = WERR_OK ;
struct registry_key * create_parent = NULL ;
TALLOC_CTX * create_ctx ;
enum winreg_CreateAction action = REG_ACTION_NONE ;
/* create a new talloc ctx for creation. it will hold
* the intermediate parent key ( SMBCONF ) for creation
* and will be destroyed when leaving this function . . . */
if ( ! ( create_ctx = talloc_stackframe ( ) ) ) {
werr = WERR_NOMEM ;
goto done ;
}
werr = smbconf_reg_open_base_key ( create_ctx , ctx , REG_KEY_WRITE ,
& create_parent ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
werr = reg_createkey ( mem_ctx , create_parent , subkeyname ,
REG_KEY_WRITE , newkey , & action ) ;
if ( W_ERROR_IS_OK ( werr ) & & ( action ! = REG_CREATED_NEW_KEY ) ) {
DEBUG ( 10 , ( " Key '%s' already exists. \n " , subkeyname ) ) ;
werr = WERR_ALREADY_EXISTS ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 5 , ( " Error creating key %s: %s \n " ,
subkeyname , dos_errstr ( werr ) ) ) ;
}
done :
TALLOC_FREE ( create_ctx ) ;
return werr ;
}
/**
* add a value to a key .
*/
static WERROR smbconf_reg_set_value ( struct registry_key * key ,
const char * valname ,
const char * valstr )
{
struct registry_value val ;
WERROR werr = WERR_OK ;
char * subkeyname ;
const char * canon_valname ;
const char * canon_valstr ;
if ( ! lp_canonicalize_parameter_with_value ( valname , valstr ,
& canon_valname ,
& canon_valstr ) )
{
if ( canon_valname = = NULL ) {
DEBUG ( 5 , ( " invalid parameter '%s' given \n " ,
valname ) ) ;
} else {
DEBUG ( 5 , ( " invalid value '%s' given for "
" parameter '%s' \n " , valstr , valname ) ) ;
}
werr = WERR_INVALID_PARAM ;
goto done ;
}
2008-04-09 00:57:48 +04:00
if ( smbconf_reg_valname_forbidden ( canon_valname ) ) {
2008-03-21 18:26:50 +03:00
DEBUG ( 5 , ( " Parameter '%s' not allowed in registry. \n " ,
canon_valname ) ) ;
werr = WERR_INVALID_PARAM ;
goto done ;
}
subkeyname = strrchr_m ( key - > key - > name , ' \\ ' ) ;
if ( ( subkeyname = = NULL ) | | ( * ( subkeyname + 1 ) = = ' \0 ' ) ) {
DEBUG ( 5 , ( " Invalid registry key '%s' given as "
" smbconf section. \n " , key - > key - > name ) ) ;
werr = WERR_INVALID_PARAM ;
goto done ;
}
subkeyname + + ;
if ( ! strequal ( subkeyname , GLOBAL_NAME ) & &
lp_parameter_is_global ( valname ) )
{
DEBUG ( 5 , ( " Global paramter '%s' not allowed in "
" service definition ('%s'). \n " , canon_valname ,
subkeyname ) ) ;
werr = WERR_INVALID_PARAM ;
goto done ;
}
2008-04-03 17:16:01 +04:00
ZERO_STRUCT ( val ) ;
val . type = REG_SZ ;
val . v . sz . str = CONST_DISCARD ( char * , canon_valstr ) ;
val . v . sz . len = strlen ( canon_valstr ) + 1 ;
2008-03-21 18:26:50 +03:00
werr = reg_setvalue ( key , canon_valname , & val ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 5 , ( " Error adding value '%s' to "
" key '%s': %s \n " ,
canon_valname , key - > key - > name , dos_errstr ( werr ) ) ) ;
}
done :
return werr ;
}
2008-04-08 19:46:36 +04:00
static WERROR smbconf_reg_set_multi_sz_value ( struct registry_key * key ,
const char * valname ,
const uint32_t num_strings ,
const char * * strings )
{
WERROR werr ;
struct registry_value * value ;
uint32_t count ;
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
if ( strings = = NULL ) {
werr = WERR_INVALID_PARAM ;
goto done ;
}
value = TALLOC_ZERO_P ( tmp_ctx , struct registry_value ) ;
value - > type = REG_MULTI_SZ ;
value - > v . multi_sz . num_strings = num_strings ;
value - > v . multi_sz . strings = TALLOC_ARRAY ( tmp_ctx , char * , num_strings ) ;
if ( value - > v . multi_sz . strings = = NULL ) {
werr = WERR_NOMEM ;
goto done ;
}
for ( count = 0 ; count < num_strings ; count + + ) {
value - > v . multi_sz . strings [ count ] =
talloc_strdup ( value - > v . multi_sz . strings ,
strings [ count ] ) ;
if ( value - > v . multi_sz . strings [ count ] = = NULL ) {
werr = WERR_NOMEM ;
goto done ;
}
}
werr = reg_setvalue ( key , valname , value ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 5 , ( " Error adding value '%s' to key '%s': %s \n " ,
valname , key - > key - > name , dos_errstr ( werr ) ) ) ;
}
done :
TALLOC_FREE ( tmp_ctx ) ;
return werr ;
}
2008-03-21 18:26:50 +03:00
/**
* format a registry_value into a string .
*
* This is intended to be used for smbconf registry values ,
* which are ar stored as REG_SZ values , so the incomplete
* handling should be ok .
*/
static char * smbconf_format_registry_value ( TALLOC_CTX * mem_ctx ,
struct registry_value * value )
{
char * result = NULL ;
/* alternatively, create a new talloc context? */
if ( mem_ctx = = NULL ) {
return result ;
}
switch ( value - > type ) {
case REG_DWORD :
result = talloc_asprintf ( mem_ctx , " %d " , value - > v . dword ) ;
break ;
case REG_SZ :
case REG_EXPAND_SZ :
result = talloc_asprintf ( mem_ctx , " %s " , value - > v . sz . str ) ;
break ;
case REG_MULTI_SZ : {
2008-04-07 17:29:11 +04:00
uint32 j ;
for ( j = 0 ; j < value - > v . multi_sz . num_strings ; j + + ) {
2008-04-09 00:23:57 +04:00
result = talloc_asprintf ( mem_ctx , " %s \" %s \" " ,
result ? result : " " ,
2008-03-21 18:26:50 +03:00
value - > v . multi_sz . strings [ j ] ) ;
if ( result = = NULL ) {
break ;
}
2008-04-07 17:29:11 +04:00
}
break ;
}
2008-03-21 18:26:50 +03:00
case REG_BINARY :
2008-04-07 17:29:11 +04:00
result = talloc_asprintf ( mem_ctx , " binary (%d bytes) " ,
2008-03-21 18:26:50 +03:00
( int ) value - > v . binary . length ) ;
2008-04-07 17:29:11 +04:00
break ;
default :
result = talloc_asprintf ( mem_ctx , " <unprintable> " ) ;
break ;
}
2008-03-21 18:26:50 +03:00
return result ;
}
2008-04-09 01:58:56 +04:00
static WERROR smbconf_reg_get_includes_internal ( TALLOC_CTX * mem_ctx ,
struct registry_key * key ,
uint32_t * num_includes ,
char * * * includes )
{
WERROR werr ;
uint32_t count ;
struct registry_value * value = NULL ;
char * * tmp_includes = NULL ;
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
if ( ! smbconf_value_exists ( key , INCLUDES_VALNAME ) ) {
/* no includes */
goto done ;
}
werr = reg_queryvalue ( tmp_ctx , key , INCLUDES_VALNAME , & value ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
if ( value - > type ! = REG_MULTI_SZ ) {
/* wront type -- ignore */
goto done ;
}
for ( count = 0 ; count < value - > v . multi_sz . num_strings ; count + + )
{
werr = smbconf_add_string_to_array ( tmp_ctx ,
& tmp_includes ,
count ,
value - > v . multi_sz . strings [ count ] ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
}
if ( count > 0 ) {
* includes = talloc_move ( mem_ctx , & tmp_includes ) ;
if ( * includes = = NULL ) {
werr = WERR_NOMEM ;
goto done ;
}
* num_includes = count ;
} else {
* num_includes = 0 ;
* includes = NULL ;
}
done :
TALLOC_FREE ( tmp_ctx ) ;
return werr ;
}
2008-03-21 18:26:50 +03:00
/**
* Get the values of a key as a list of value names
* and a list of value strings ( ordered )
*/
static WERROR smbconf_reg_get_values ( TALLOC_CTX * mem_ctx ,
struct registry_key * key ,
uint32_t * num_values ,
char * * * value_names ,
char * * * value_strings )
{
TALLOC_CTX * tmp_ctx = NULL ;
WERROR werr = WERR_OK ;
uint32_t count ;
struct registry_value * valvalue = NULL ;
char * valname = NULL ;
2008-04-09 02:05:45 +04:00
uint32_t tmp_num_values = 0 ;
2008-03-21 18:26:50 +03:00
char * * tmp_valnames = NULL ;
char * * tmp_valstrings = NULL ;
2008-04-09 02:47:27 +04:00
uint32_t num_includes = 0 ;
char * * includes = NULL ;
2008-03-21 18:26:50 +03:00
if ( ( num_values = = NULL ) | | ( value_names = = NULL ) | |
( value_strings = = NULL ) )
{
werr = WERR_INVALID_PARAM ;
goto done ;
}
tmp_ctx = talloc_stackframe ( ) ;
if ( tmp_ctx = = NULL ) {
werr = WERR_NOMEM ;
goto done ;
}
for ( count = 0 ;
2008-04-07 17:15:57 +04:00
werr = reg_enumvalue ( tmp_ctx , key , count , & valname , & valvalue ) ,
W_ERROR_IS_OK ( werr ) ;
2008-03-21 18:26:50 +03:00
count + + )
{
char * valstring ;
2008-04-09 02:05:45 +04:00
if ( ! smbconf_reg_valname_valid ( valname ) ) {
continue ;
}
2008-03-21 18:26:50 +03:00
werr = smbconf_add_string_to_array ( tmp_ctx ,
& tmp_valnames ,
2008-04-09 02:05:45 +04:00
tmp_num_values , valname ) ;
2008-03-21 18:26:50 +03:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
valstring = smbconf_format_registry_value ( tmp_ctx , valvalue ) ;
werr = smbconf_add_string_to_array ( tmp_ctx , & tmp_valstrings ,
2008-04-09 02:05:45 +04:00
tmp_num_values , valstring ) ;
2008-03-21 18:26:50 +03:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
2008-04-09 02:05:45 +04:00
tmp_num_values + + ;
2008-03-21 18:26:50 +03:00
}
if ( ! W_ERROR_EQUAL ( WERR_NO_MORE_ITEMS , werr ) ) {
goto done ;
}
2008-04-09 02:47:27 +04:00
/* now add the includes at the end */
werr = smbconf_reg_get_includes_internal ( tmp_ctx , key , & num_includes ,
& includes ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
for ( count = 0 ; count < num_includes ; count + + ) {
werr = smbconf_add_string_to_array ( tmp_ctx , & tmp_valnames ,
tmp_num_values , " include " ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
werr = smbconf_add_string_to_array ( tmp_ctx , & tmp_valstrings ,
tmp_num_values ,
includes [ count ] ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
tmp_num_values + + ;
}
2008-03-21 18:26:50 +03:00
2008-04-09 02:05:45 +04:00
* num_values = tmp_num_values ;
if ( tmp_num_values > 0 ) {
2008-03-21 18:26:50 +03:00
* value_names = talloc_move ( mem_ctx , & tmp_valnames ) ;
* value_strings = talloc_move ( mem_ctx , & tmp_valstrings ) ;
} else {
* value_names = NULL ;
* value_strings = NULL ;
}
done :
TALLOC_FREE ( tmp_ctx ) ;
return werr ;
}
/**********************************************************************
*
* smbconf operations : registry implementations
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* initialize the registry smbconf backend
*/
2008-03-21 19:55:31 +03:00
static WERROR smbconf_reg_init ( struct smbconf_ctx * ctx , const char * path )
2008-03-21 18:26:50 +03:00
{
WERROR werr = WERR_OK ;
2008-03-21 19:55:31 +03:00
if ( path = = NULL ) {
path = KEY_SMBCONF ;
}
ctx - > path = talloc_strdup ( ctx , path ) ;
if ( ctx - > path = = NULL ) {
werr = WERR_NOMEM ;
goto done ;
}
2008-03-22 00:52:27 +03:00
ctx - > data = TALLOC_ZERO_P ( ctx , struct reg_private_data ) ;
2008-03-21 18:26:50 +03:00
werr = ntstatus_to_werror ( registry_create_admin_token ( ctx ,
2008-03-22 00:52:27 +03:00
& ( rpd ( ctx ) - > token ) ) ) ;
2008-03-21 18:26:50 +03:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 1 , ( " Error creating admin token \n " ) ) ;
goto done ;
}
2008-03-22 01:39:01 +03:00
rpd ( ctx ) - > open = false ;
2008-03-21 18:26:50 +03:00
2008-03-22 00:52:27 +03:00
if ( ! registry_init_smbconf ( ) ) {
werr = WERR_REG_IO_FAILURE ;
goto done ;
}
2008-03-21 18:26:50 +03:00
done :
return werr ;
}
static int smbconf_reg_shutdown ( struct smbconf_ctx * ctx )
{
2008-03-22 01:39:01 +03:00
return ctx - > ops - > close_conf ( ctx ) ;
2008-03-21 18:26:50 +03:00
}
static WERROR smbconf_reg_open ( struct smbconf_ctx * ctx )
{
2008-03-22 01:39:01 +03:00
WERROR werr ;
if ( rpd ( ctx ) - > open ) {
return WERR_OK ;
}
werr = regdb_open ( ) ;
if ( W_ERROR_IS_OK ( werr ) ) {
rpd ( ctx ) - > open = true ;
}
return werr ;
2008-03-21 18:26:50 +03:00
}
static int smbconf_reg_close ( struct smbconf_ctx * ctx )
{
2008-03-22 01:39:01 +03:00
int ret ;
if ( ! rpd ( ctx ) - > open ) {
return 0 ;
}
ret = regdb_close ( ) ;
if ( ret = = 0 ) {
rpd ( ctx ) - > open = false ;
}
return ret ;
2008-03-21 18:26:50 +03:00
}
/**
* Get the change sequence number of the given service / parameter .
* service and parameter strings may be NULL .
*/
static void smbconf_reg_get_csn ( struct smbconf_ctx * ctx ,
struct smbconf_csn * csn ,
const char * service , const char * param )
{
if ( csn = = NULL ) {
return ;
}
2008-03-22 01:39:01 +03:00
if ( ! W_ERROR_IS_OK ( ctx - > ops - > open_conf ( ctx ) ) ) {
return ;
}
2008-03-21 18:26:50 +03:00
csn - > csn = ( uint64_t ) regdb_get_seqnum ( ) ;
}
/**
* Drop the whole configuration ( restarting empty ) - registry version
*/
static WERROR smbconf_reg_drop ( struct smbconf_ctx * ctx )
{
char * path , * p ;
WERROR werr = WERR_OK ;
struct registry_key * parent_key = NULL ;
struct registry_key * new_key = NULL ;
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
enum winreg_CreateAction action ;
2008-03-21 19:55:31 +03:00
path = talloc_strdup ( mem_ctx , ctx - > path ) ;
2008-03-21 18:26:50 +03:00
if ( path = = NULL ) {
werr = WERR_NOMEM ;
goto done ;
}
p = strrchr ( path , ' \\ ' ) ;
* p = ' \0 ' ;
werr = smbconf_reg_open_path ( mem_ctx , ctx , path , REG_KEY_WRITE ,
& parent_key ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
werr = reg_deletekey_recursive ( mem_ctx , parent_key , p + 1 ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
werr = reg_createkey ( mem_ctx , parent_key , p + 1 , REG_KEY_WRITE ,
& new_key , & action ) ;
done :
TALLOC_FREE ( mem_ctx ) ;
return werr ;
}
/**
* get the list of share names defined in the configuration .
* registry version .
*/
static WERROR smbconf_reg_get_share_names ( struct smbconf_ctx * ctx ,
TALLOC_CTX * mem_ctx ,
uint32_t * num_shares ,
char * * * share_names )
{
uint32_t count ;
uint32_t added_count = 0 ;
TALLOC_CTX * tmp_ctx = NULL ;
WERROR werr = WERR_OK ;
struct registry_key * key = NULL ;
char * subkey_name = NULL ;
char * * tmp_share_names = NULL ;
if ( ( num_shares = = NULL ) | | ( share_names = = NULL ) ) {
werr = WERR_INVALID_PARAM ;
goto done ;
}
tmp_ctx = talloc_stackframe ( ) ;
if ( tmp_ctx = = NULL ) {
werr = WERR_NOMEM ;
goto done ;
}
/* make sure "global" is always listed first */
if ( smbconf_share_exists ( ctx , GLOBAL_NAME ) ) {
werr = smbconf_add_string_to_array ( tmp_ctx , & tmp_share_names ,
0 , GLOBAL_NAME ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
added_count + + ;
}
werr = smbconf_reg_open_base_key ( tmp_ctx , ctx ,
SEC_RIGHTS_ENUM_SUBKEYS , & key ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
for ( count = 0 ;
2008-04-07 17:15:57 +04:00
werr = reg_enumkey ( tmp_ctx , key , count , & subkey_name , NULL ) ,
W_ERROR_IS_OK ( werr ) ;
2008-03-21 18:26:50 +03:00
count + + )
{
if ( strequal ( subkey_name , GLOBAL_NAME ) ) {
continue ;
}
werr = smbconf_add_string_to_array ( tmp_ctx ,
& tmp_share_names ,
added_count ,
subkey_name ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
added_count + + ;
}
if ( ! W_ERROR_EQUAL ( WERR_NO_MORE_ITEMS , werr ) ) {
goto done ;
}
werr = WERR_OK ;
* num_shares = added_count ;
if ( added_count > 0 ) {
* share_names = talloc_move ( mem_ctx , & tmp_share_names ) ;
} else {
* share_names = NULL ;
}
done :
TALLOC_FREE ( tmp_ctx ) ;
return werr ;
}
/**
* check if a share / service of a given name exists - registry version
*/
static bool smbconf_reg_share_exists ( struct smbconf_ctx * ctx ,
const char * servicename )
{
bool ret = false ;
WERROR werr = WERR_OK ;
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
struct registry_key * key = NULL ;
werr = smbconf_reg_open_service_key ( mem_ctx , ctx , servicename ,
REG_KEY_READ , & key ) ;
if ( W_ERROR_IS_OK ( werr ) ) {
ret = true ;
}
TALLOC_FREE ( mem_ctx ) ;
return ret ;
}
/**
* Add a service if it does not already exist - registry version
*/
static WERROR smbconf_reg_create_share ( struct smbconf_ctx * ctx ,
const char * servicename )
{
WERROR werr ;
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
struct registry_key * key = NULL ;
werr = smbconf_reg_create_service_key ( mem_ctx , ctx , servicename , & key ) ;
TALLOC_FREE ( mem_ctx ) ;
return werr ;
}
/**
* get a definition of a share ( service ) from configuration .
*/
static WERROR smbconf_reg_get_share ( struct smbconf_ctx * ctx ,
TALLOC_CTX * mem_ctx ,
const char * servicename ,
uint32_t * num_params ,
char * * * param_names , char * * * param_values )
{
WERROR werr = WERR_OK ;
struct registry_key * key = NULL ;
werr = smbconf_reg_open_service_key ( mem_ctx , ctx , servicename ,
REG_KEY_READ , & key ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
werr = smbconf_reg_get_values ( mem_ctx , key , num_params ,
param_names , param_values ) ;
done :
TALLOC_FREE ( key ) ;
return werr ;
}
/**
* delete a service from configuration
*/
static WERROR smbconf_reg_delete_share ( struct smbconf_ctx * ctx ,
const char * servicename )
{
WERROR werr = WERR_OK ;
struct registry_key * key = NULL ;
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
werr = smbconf_reg_open_base_key ( mem_ctx , ctx , REG_KEY_WRITE , & key ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
werr = reg_deletekey_recursive ( key , key , servicename ) ;
done :
TALLOC_FREE ( mem_ctx ) ;
return werr ;
}
/**
* set a configuration parameter to the value provided .
*/
static WERROR smbconf_reg_set_parameter ( struct smbconf_ctx * ctx ,
const char * service ,
const char * param ,
const char * valstr )
{
WERROR werr ;
struct registry_key * key = NULL ;
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
werr = smbconf_reg_open_service_key ( mem_ctx , ctx , service ,
REG_KEY_WRITE , & key ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
werr = smbconf_reg_set_value ( key , param , valstr ) ;
done :
TALLOC_FREE ( mem_ctx ) ;
return werr ;
}
/**
* get the value of a configuration parameter as a string
*/
static WERROR smbconf_reg_get_parameter ( struct smbconf_ctx * ctx ,
TALLOC_CTX * mem_ctx ,
const char * service ,
const char * param ,
char * * valstr )
{
WERROR werr = WERR_OK ;
struct registry_key * key = NULL ;
struct registry_value * value = NULL ;
werr = smbconf_reg_open_service_key ( mem_ctx , ctx , service ,
REG_KEY_READ , & key ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
if ( ! smbconf_value_exists ( key , param ) ) {
werr = WERR_INVALID_PARAM ;
goto done ;
}
werr = reg_queryvalue ( mem_ctx , key , param , & value ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
* valstr = smbconf_format_registry_value ( mem_ctx , value ) ;
if ( * valstr = = NULL ) {
werr = WERR_NOMEM ;
}
done :
TALLOC_FREE ( key ) ;
TALLOC_FREE ( value ) ;
return werr ;
}
/**
* delete a parameter from configuration
*/
static WERROR smbconf_reg_delete_parameter ( struct smbconf_ctx * ctx ,
const char * service ,
const char * param )
{
struct registry_key * key = NULL ;
WERROR werr = WERR_OK ;
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
werr = smbconf_reg_open_service_key ( mem_ctx , ctx , service ,
REG_KEY_ALL , & key ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
if ( ! smbconf_value_exists ( key , param ) ) {
werr = WERR_INVALID_PARAM ;
goto done ;
}
werr = reg_deletevalue ( key , param ) ;
done :
TALLOC_FREE ( mem_ctx ) ;
return werr ;
}
2008-04-08 03:56:32 +04:00
static WERROR smbconf_reg_get_includes ( struct smbconf_ctx * ctx ,
2008-04-08 12:16:03 +04:00
TALLOC_CTX * mem_ctx ,
2008-04-08 03:56:32 +04:00
const char * service ,
uint32_t * num_includes ,
char * * * includes )
{
2008-04-08 19:46:36 +04:00
WERROR werr ;
struct registry_key * key = NULL ;
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
werr = smbconf_reg_open_service_key ( tmp_ctx , ctx , service ,
REG_KEY_READ , & key ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
2008-04-09 01:58:56 +04:00
werr = smbconf_reg_get_includes_internal ( mem_ctx , key , num_includes ,
includes ) ;
2008-04-08 19:46:36 +04:00
done :
TALLOC_FREE ( tmp_ctx ) ;
return werr ;
2008-04-08 03:56:32 +04:00
}
static WERROR smbconf_reg_set_includes ( struct smbconf_ctx * ctx ,
const char * service ,
uint32_t num_includes ,
const char * * includes )
{
2008-04-08 19:46:36 +04:00
WERROR werr = WERR_OK ;
struct registry_key * key = NULL ;
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
werr = smbconf_reg_open_service_key ( tmp_ctx , ctx , service ,
REG_KEY_ALL , & key ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
werr = smbconf_reg_set_multi_sz_value ( key , INCLUDES_VALNAME ,
num_includes , includes ) ;
done :
TALLOC_FREE ( tmp_ctx ) ;
return werr ;
2008-04-08 03:56:32 +04:00
}
2008-03-21 18:26:50 +03:00
struct smbconf_ops smbconf_ops_reg = {
. init = smbconf_reg_init ,
. shutdown = smbconf_reg_shutdown ,
. open_conf = smbconf_reg_open ,
. close_conf = smbconf_reg_close ,
. get_csn = smbconf_reg_get_csn ,
. drop = smbconf_reg_drop ,
. get_share_names = smbconf_reg_get_share_names ,
. share_exists = smbconf_reg_share_exists ,
. create_share = smbconf_reg_create_share ,
. get_share = smbconf_reg_get_share ,
. delete_share = smbconf_reg_delete_share ,
. set_parameter = smbconf_reg_set_parameter ,
. get_parameter = smbconf_reg_get_parameter ,
2008-04-08 03:56:32 +04:00
. delete_parameter = smbconf_reg_delete_parameter ,
. get_includes = smbconf_reg_get_includes ,
. set_includes = smbconf_reg_set_includes ,
2008-03-21 18:26:50 +03:00
} ;
2008-03-21 18:35:52 +03:00
/**
* initialize the smbconf registry backend
* the only function that is exported from this module
*/
2008-03-21 19:55:31 +03:00
WERROR smbconf_init_reg ( TALLOC_CTX * mem_ctx , struct smbconf_ctx * * conf_ctx ,
const char * path )
2008-03-21 18:26:50 +03:00
{
2008-03-21 19:55:31 +03:00
return smbconf_init ( mem_ctx , conf_ctx , path , & smbconf_ops_reg ) ;
2008-03-21 18:26:50 +03:00
}