2007-10-06 04:17:44 +04:00
/*
2007-08-26 19:16:40 +04:00
Unix SMB / CIFS implementation .
Registry interface
2008-09-13 14:10:00 +04:00
Copyright ( C ) 2004 - 2007 , Jelmer Vernooij , jelmer @ samba . org
Copyright ( C ) 2008 Matthias Dieter Wallnöfer , mwallnoefer @ yahoo . de
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +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
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +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 .
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +04:00
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 "registry.h"
# include "lib/ldb/include/ldb.h"
# include "lib/ldb/include/ldb_errors.h"
2007-11-16 22:12:00 +03:00
# include "ldb_wrap.h"
2007-08-26 19:16:40 +04:00
# include "librpc/gen_ndr/winreg.h"
2007-10-01 22:52:55 +04:00
# include "param/param.h"
2007-08-26 19:16:40 +04:00
static struct hive_operations reg_backend_ldb ;
2007-10-06 04:17:44 +04:00
struct ldb_key_data
2007-08-26 19:16:40 +04:00
{
struct hive_key key ;
struct ldb_context * ldb ;
struct ldb_dn * dn ;
struct ldb_message * * subkeys , * * values ;
int subkey_count , value_count ;
} ;
2008-02-21 19:54:24 +03:00
static void reg_ldb_unpack_value ( TALLOC_CTX * mem_ctx ,
struct smb_iconv_convenience * iconv_convenience ,
struct ldb_message * msg ,
2007-10-06 04:17:44 +04:00
const char * * name , uint32_t * type ,
DATA_BLOB * data )
2007-08-26 19:16:40 +04:00
{
const struct ldb_val * val ;
2008-01-07 23:11:29 +03:00
uint32_t value_type ;
2007-08-26 19:16:40 +04:00
if ( name ! = NULL )
2007-10-06 04:17:44 +04:00
* name = talloc_strdup ( mem_ctx ,
ldb_msg_find_attr_as_string ( msg , " value " ,
NULL ) ) ;
2007-08-26 19:16:40 +04:00
2008-01-07 23:11:29 +03:00
value_type = ldb_msg_find_attr_as_uint ( msg , " type " , 0 ) ;
2008-09-15 20:21:45 +04:00
* type = value_type ;
2008-09-15 19:21:35 +04:00
val = ldb_msg_find_ldb_val ( msg , " data " ) ;
2007-08-26 19:16:40 +04:00
2008-09-15 19:21:35 +04:00
switch ( value_type )
{
case REG_SZ :
case REG_EXPAND_SZ :
2008-09-18 18:51:48 +04:00
if ( val ! = NULL )
2008-10-24 16:26:46 +04:00
data - > length = convert_string_talloc_convenience ( mem_ctx , iconv_convenience , CH_UTF8 , CH_UTF16 ,
2007-10-06 04:17:44 +04:00
val - > data , val - > length ,
( void * * ) & data - > data ) ;
2008-09-18 18:51:48 +04:00
else {
data - > data = NULL ;
data - > length = 0 ;
}
2008-09-15 19:21:35 +04:00
break ;
case REG_BINARY :
2008-09-18 18:51:48 +04:00
if ( val ! = NULL )
2008-10-21 16:57:41 +04:00
* data = data_blob_talloc ( mem_ctx , val - > data , val - > length ) ;
2008-09-15 19:21:35 +04:00
else {
data - > data = NULL ;
data - > length = 0 ;
2008-09-09 19:49:41 +04:00
}
2008-09-15 19:21:35 +04:00
break ;
case REG_DWORD : {
uint32_t tmp = strtoul ( ( char * ) val - > data , NULL , 0 ) ;
* data = data_blob_talloc ( mem_ctx , & tmp , 4 ) ;
}
break ;
default :
2008-10-21 16:57:41 +04:00
* data = data_blob_talloc ( mem_ctx , val - > data , val - > length ) ;
2008-09-15 19:21:35 +04:00
break ;
2007-08-26 19:16:40 +04:00
}
}
2007-10-06 04:17:44 +04:00
static struct ldb_message * reg_ldb_pack_value ( struct ldb_context * ctx ,
TALLOC_CTX * mem_ctx ,
const char * name ,
uint32_t type , DATA_BLOB data )
2007-08-26 19:16:40 +04:00
{
struct ldb_val val ;
struct ldb_message * msg = talloc_zero ( mem_ctx , struct ldb_message ) ;
char * type_s ;
ldb_msg_add_string ( msg , " value " , talloc_strdup ( mem_ctx , name ) ) ;
switch ( type ) {
case REG_SZ :
case REG_EXPAND_SZ :
2008-09-18 18:51:48 +04:00
if ( data . data [ 0 ] ! = ' \0 ' ) {
2008-10-24 16:26:46 +04:00
val . length = convert_string_talloc ( mem_ctx , CH_UTF16 , CH_UTF8 ,
2007-10-06 04:17:44 +04:00
( void * ) data . data ,
data . length ,
( void * * ) & val . data ) ;
2008-09-18 18:51:48 +04:00
ldb_msg_add_value ( msg , " data " , & val , NULL ) ;
} else {
ldb_msg_add_empty ( msg , " data " , LDB_FLAG_MOD_DELETE , NULL ) ;
}
2007-08-26 19:16:40 +04:00
break ;
2008-09-09 19:49:41 +04:00
case REG_BINARY :
2008-09-19 14:39:53 +04:00
if ( data . length > 0 )
ldb_msg_add_value ( msg , " data " , & data , NULL ) ;
else
ldb_msg_add_empty ( msg , " data " , LDB_FLAG_MOD_DELETE , NULL ) ;
2008-09-09 19:49:41 +04:00
break ;
2007-08-26 19:16:40 +04:00
case REG_DWORD :
2007-10-06 04:17:44 +04:00
ldb_msg_add_string ( msg , " data " ,
talloc_asprintf ( mem_ctx , " 0x%x " ,
IVAL ( data . data , 0 ) ) ) ;
2007-08-26 19:16:40 +04:00
break ;
default :
ldb_msg_add_value ( msg , " data " , & data , NULL ) ;
}
type_s = talloc_asprintf ( mem_ctx , " %u " , type ) ;
2007-10-06 04:17:44 +04:00
ldb_msg_add_string ( msg , " type " , type_s ) ;
2007-08-26 19:16:40 +04:00
return msg ;
}
2008-01-18 03:50:33 +03:00
static char * reg_ldb_escape ( TALLOC_CTX * mem_ctx , const char * value )
{
struct ldb_val val ;
val . data = discard_const_p ( uint8_t , value ) ;
val . length = strlen ( value ) ;
return ldb_dn_escape_value ( mem_ctx , val ) ;
}
2007-08-26 19:16:40 +04:00
static int reg_close_ldb_key ( struct ldb_key_data * key )
{
if ( key - > subkeys ! = NULL ) {
2007-10-06 04:17:44 +04:00
talloc_free ( key - > subkeys ) ;
2007-08-26 19:16:40 +04:00
key - > subkeys = NULL ;
}
if ( key - > values ! = NULL ) {
2007-10-06 04:17:44 +04:00
talloc_free ( key - > values ) ;
2007-08-26 19:16:40 +04:00
key - > values = NULL ;
}
return 0 ;
}
2007-10-06 04:17:44 +04:00
static struct ldb_dn * reg_path_to_ldb ( TALLOC_CTX * mem_ctx ,
const struct hive_key * from ,
const char * path , const char * add )
2007-08-26 19:16:40 +04:00
{
TALLOC_CTX * local_ctx ;
struct ldb_dn * ret ;
char * mypath = talloc_strdup ( mem_ctx , path ) ;
char * begin ;
struct ldb_key_data * kd = talloc_get_type ( from , struct ldb_key_data ) ;
struct ldb_context * ldb = kd - > ldb ;
local_ctx = talloc_new ( mem_ctx ) ;
if ( add ) {
ret = ldb_dn_new ( mem_ctx , ldb , add ) ;
} else {
ret = ldb_dn_new ( mem_ctx , ldb , NULL ) ;
}
if ( ! ldb_dn_validate ( ret ) ) {
talloc_free ( ret ) ;
talloc_free ( local_ctx ) ;
return NULL ;
}
while ( mypath ) {
char * keyname ;
begin = strrchr ( mypath , ' \\ ' ) ;
if ( begin ) keyname = begin + 1 ;
else keyname = mypath ;
if ( strlen ( keyname ) ) {
2008-01-18 04:51:51 +03:00
if ( ! ldb_dn_add_base_fmt ( ret , " key=%s " ,
reg_ldb_escape ( local_ctx ,
keyname ) ) )
{
talloc_free ( local_ctx ) ;
return NULL ;
}
2007-08-26 19:16:40 +04:00
}
if ( begin ) {
* begin = ' \0 ' ;
} else {
break ;
}
}
ldb_dn_add_base ( ret , kd - > dn ) ;
talloc_free ( local_ctx ) ;
return ret ;
}
static WERROR cache_subkeys ( struct ldb_key_data * kd )
{
struct ldb_context * c = kd - > ldb ;
struct ldb_result * res ;
int ret ;
2008-09-23 22:30:06 +04:00
ret = ldb_search ( c , c , & res , kd - > dn , LDB_SCOPE_ONELEVEL , NULL , " (key=*) " ) ;
2007-08-26 19:16:40 +04:00
if ( ret ! = LDB_SUCCESS ) {
2007-10-06 04:17:44 +04:00
DEBUG ( 0 , ( " Error getting subkeys for '%s': %s \n " ,
ldb_dn_get_linearized ( kd - > dn ) , ldb_errstring ( c ) ) ) ;
2007-08-26 19:16:40 +04:00
return WERR_FOOBAR ;
}
kd - > subkey_count = res - > count ;
kd - > subkeys = talloc_steal ( kd , res - > msgs ) ;
talloc_free ( res ) ;
return WERR_OK ;
}
static WERROR cache_values ( struct ldb_key_data * kd )
{
struct ldb_context * c = kd - > ldb ;
struct ldb_result * res ;
int ret ;
2008-09-23 22:30:06 +04:00
ret = ldb_search ( c , c , & res , kd - > dn , LDB_SCOPE_ONELEVEL ,
NULL , " (value=*) " ) ;
2007-08-26 19:16:40 +04:00
if ( ret ! = LDB_SUCCESS ) {
2007-10-06 04:17:44 +04:00
DEBUG ( 0 , ( " Error getting values for '%s': %s \n " ,
ldb_dn_get_linearized ( kd - > dn ) , ldb_errstring ( c ) ) ) ;
2007-08-26 19:16:40 +04:00
return WERR_FOOBAR ;
}
2008-09-14 05:51:35 +04:00
2007-08-26 19:16:40 +04:00
kd - > value_count = res - > count ;
kd - > values = talloc_steal ( kd , res - > msgs ) ;
talloc_free ( res ) ;
2008-09-14 05:51:35 +04:00
2007-08-26 19:16:40 +04:00
return WERR_OK ;
}
2007-10-06 04:17:44 +04:00
static WERROR ldb_get_subkey_by_id ( TALLOC_CTX * mem_ctx ,
const struct hive_key * k , uint32_t idx ,
const char * * name ,
const char * * classname ,
NTTIME * last_mod_time )
2007-08-26 19:16:40 +04:00
{
struct ldb_message_element * el ;
struct ldb_key_data * kd = talloc_get_type ( k , struct ldb_key_data ) ;
2008-09-13 15:32:39 +04:00
/* Initialization */
if ( name ! = NULL )
* name = NULL ;
if ( classname ! = NULL )
* classname = NULL ; /* TODO: Store properly */
if ( last_mod_time ! = NULL )
* last_mod_time = 0 ; /* TODO: we need to add this to the
ldb backend properly */
2007-08-26 19:16:40 +04:00
/* Do a search if necessary */
if ( kd - > subkeys = = NULL ) {
W_ERROR_NOT_OK_RETURN ( cache_subkeys ( kd ) ) ;
2007-10-06 04:17:44 +04:00
}
2007-08-26 19:16:40 +04:00
2007-10-06 04:17:44 +04:00
if ( idx > = kd - > subkey_count )
2007-08-26 19:16:40 +04:00
return WERR_NO_MORE_ITEMS ;
el = ldb_msg_find_element ( kd - > subkeys [ idx ] , " key " ) ;
SMB_ASSERT ( el ! = NULL ) ;
SMB_ASSERT ( el - > num_values ! = 0 ) ;
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +04:00
if ( name ! = NULL )
* name = talloc_strdup ( mem_ctx , ( char * ) el - > values [ 0 ] . data ) ;
return WERR_OK ;
}
2008-09-09 19:49:41 +04:00
static WERROR ldb_get_default_value ( TALLOC_CTX * mem_ctx , struct hive_key * k ,
2008-09-15 21:21:38 +04:00
const char * * name , uint32_t * data_type ,
2008-09-09 19:49:41 +04:00
DATA_BLOB * data )
{
struct ldb_key_data * kd = talloc_get_type ( k , struct ldb_key_data ) ;
struct ldb_context * c = kd - > ldb ;
const char * attrs [ ] = { " data " , " type " , NULL } ;
struct ldb_result * res ;
int ret ;
2008-10-21 17:47:34 +04:00
ret = ldb_search ( c , mem_ctx , & res , kd - > dn , LDB_SCOPE_BASE , attrs , " %s " , " " ) ;
2008-09-09 19:49:41 +04:00
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( " Error getting default value for '%s': %s \n " ,
ldb_dn_get_linearized ( kd - > dn ) , ldb_errstring ( c ) ) ) ;
return WERR_FOOBAR ;
}
if ( res - > count = = 0 | | res - > msgs [ 0 ] - > num_elements = = 0 )
return WERR_BADFILE ;
reg_ldb_unpack_value ( mem_ctx , lp_iconv_convenience ( global_loadparm ) ,
res - > msgs [ 0 ] , name , data_type , data ) ;
talloc_free ( res ) ;
return WERR_OK ;
}
2007-12-14 12:38:26 +03:00
static WERROR ldb_get_value_by_id ( TALLOC_CTX * mem_ctx , struct hive_key * k ,
2007-10-06 04:17:44 +04:00
int idx , const char * * name ,
uint32_t * data_type , DATA_BLOB * data )
2007-08-26 19:16:40 +04:00
{
struct ldb_key_data * kd = talloc_get_type ( k , struct ldb_key_data ) ;
2008-09-13 14:10:00 +04:00
/* if default value exists, give it back */
2008-09-14 05:51:35 +04:00
if ( W_ERROR_IS_OK ( ldb_get_default_value ( mem_ctx , k , name , data_type ,
data ) ) ) {
2008-09-13 14:10:00 +04:00
if ( idx = = 0 )
return WERR_OK ;
else
- - idx ;
2008-09-14 05:51:35 +04:00
}
2007-08-26 19:16:40 +04:00
2008-09-13 14:10:00 +04:00
/* Do the search if necessary */
if ( kd - > values = = NULL ) {
W_ERROR_NOT_OK_RETURN ( cache_values ( kd ) ) ;
}
2007-08-26 19:16:40 +04:00
2008-09-13 14:10:00 +04:00
if ( idx > = kd - > value_count )
return WERR_NO_MORE_ITEMS ;
2008-09-09 19:49:41 +04:00
2008-09-13 14:10:00 +04:00
reg_ldb_unpack_value ( mem_ctx , lp_iconv_convenience ( global_loadparm ) ,
2008-09-09 19:49:41 +04:00
kd - > values [ idx ] , name , data_type , data ) ;
2007-08-26 19:16:40 +04:00
return WERR_OK ;
}
2007-10-06 04:17:44 +04:00
static WERROR ldb_get_value ( TALLOC_CTX * mem_ctx , struct hive_key * k ,
const char * name , uint32_t * data_type ,
DATA_BLOB * data )
2007-08-26 19:16:40 +04:00
{
struct ldb_key_data * kd = talloc_get_type ( k , struct ldb_key_data ) ;
struct ldb_context * c = kd - > ldb ;
struct ldb_result * res ;
int ret ;
2008-09-09 19:49:41 +04:00
char * query ;
2007-08-26 19:16:40 +04:00
2008-09-09 19:49:41 +04:00
if ( strlen ( name ) = = 0 ) {
/* default value */
return ldb_get_default_value ( mem_ctx , k , NULL , data_type , data ) ;
} else {
/* normal value */
query = talloc_asprintf ( mem_ctx , " (value=%s) " , name ) ;
2008-10-21 17:47:34 +04:00
ret = ldb_search ( c , mem_ctx , & res , kd - > dn , LDB_SCOPE_ONELEVEL , NULL , " %s " , query ) ;
2008-09-09 19:49:41 +04:00
talloc_free ( query ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( " Error getting values for '%s': %s \n " ,
ldb_dn_get_linearized ( kd - > dn ) , ldb_errstring ( c ) ) ) ;
return WERR_FOOBAR ;
}
2007-08-26 19:16:40 +04:00
2008-09-09 19:49:41 +04:00
if ( res - > count = = 0 )
return WERR_BADFILE ;
2007-08-26 19:16:40 +04:00
2008-09-09 19:49:41 +04:00
reg_ldb_unpack_value ( mem_ctx , lp_iconv_convenience ( global_loadparm ) ,
res - > msgs [ 0 ] , NULL , data_type , data ) ;
2007-08-26 19:16:40 +04:00
2008-09-09 19:49:41 +04:00
talloc_free ( res ) ;
}
2007-08-26 19:16:40 +04:00
return WERR_OK ;
}
2007-10-06 04:17:44 +04:00
static WERROR ldb_open_key ( TALLOC_CTX * mem_ctx , const struct hive_key * h ,
const char * name , struct hive_key * * key )
2007-08-26 19:16:40 +04:00
{
struct ldb_result * res ;
struct ldb_dn * ldap_path ;
int ret ;
struct ldb_key_data * newkd ;
struct ldb_key_data * kd = talloc_get_type ( h , struct ldb_key_data ) ;
struct ldb_context * c = kd - > ldb ;
ldap_path = reg_path_to_ldb ( mem_ctx , h , name , NULL ) ;
2008-09-23 22:30:06 +04:00
ret = ldb_search ( c , mem_ctx , & res , ldap_path , LDB_SCOPE_BASE , NULL , " (key=*) " ) ;
2007-08-26 19:16:40 +04:00
if ( ret ! = LDB_SUCCESS ) {
2007-10-06 04:17:44 +04:00
DEBUG ( 3 , ( " Error opening key '%s': %s \n " ,
ldb_dn_get_linearized ( ldap_path ) , ldb_errstring ( c ) ) ) ;
2007-08-26 19:16:40 +04:00
return WERR_FOOBAR ;
} else if ( res - > count = = 0 ) {
2007-10-06 04:17:44 +04:00
DEBUG ( 3 , ( " Key '%s' not found \n " ,
ldb_dn_get_linearized ( ldap_path ) ) ) ;
2007-08-26 19:16:40 +04:00
talloc_free ( res ) ;
2008-01-18 05:37:06 +03:00
return WERR_BADFILE ;
2007-08-26 19:16:40 +04:00
}
newkd = talloc_zero ( mem_ctx , struct ldb_key_data ) ;
newkd - > key . ops = & reg_backend_ldb ;
newkd - > ldb = talloc_reference ( newkd , kd - > ldb ) ;
2007-10-06 04:17:44 +04:00
newkd - > dn = ldb_dn_copy ( mem_ctx , res - > msgs [ 0 ] - > dn ) ;
2007-08-26 19:16:40 +04:00
* key = ( struct hive_key * ) newkd ;
return WERR_OK ;
}
2007-10-06 04:17:44 +04:00
WERROR reg_open_ldb_file ( TALLOC_CTX * parent_ctx , const char * location ,
2007-10-01 22:52:55 +04:00
struct auth_session_info * session_info ,
struct cli_credentials * credentials ,
2008-04-17 14:23:44 +04:00
struct event_context * ev_ctx ,
2007-12-14 02:27:31 +03:00
struct loadparm_context * lp_ctx ,
2007-10-01 22:52:55 +04:00
struct hive_key * * k )
2007-08-26 19:16:40 +04:00
{
struct ldb_key_data * kd ;
struct ldb_context * wrap ;
2008-01-08 08:41:55 +03:00
struct ldb_message * attrs_msg ;
2007-08-26 19:16:40 +04:00
2007-10-06 04:17:44 +04:00
if ( location = = NULL )
2007-08-26 19:16:40 +04:00
return WERR_INVALID_PARAM ;
2008-04-17 14:23:44 +04:00
wrap = ldb_wrap_connect ( parent_ctx , ev_ctx , lp_ctx ,
2007-10-01 22:52:55 +04:00
location , session_info , credentials , 0 , NULL ) ;
2007-08-26 19:16:40 +04:00
if ( wrap = = NULL ) {
DEBUG ( 1 , ( __FILE__ " : unable to connect \n " ) ) ;
return WERR_FOOBAR ;
}
2008-01-08 08:41:55 +03:00
attrs_msg = ldb_msg_new ( wrap ) ;
W_ERROR_HAVE_NO_MEMORY ( attrs_msg ) ;
attrs_msg - > dn = ldb_dn_new ( attrs_msg , wrap , " @ATTRIBUTES " ) ;
W_ERROR_HAVE_NO_MEMORY ( attrs_msg - > dn ) ;
ldb_msg_add_string ( attrs_msg , " key " , " CASE_INSENSITIVE " ) ;
ldb_msg_add_string ( attrs_msg , " value " , " CASE_INSENSITIVE " ) ;
ldb_add ( wrap , attrs_msg ) ;
2007-08-26 19:16:40 +04:00
ldb_set_debug_stderr ( wrap ) ;
kd = talloc_zero ( parent_ctx , struct ldb_key_data ) ;
kd - > key . ops = & reg_backend_ldb ;
kd - > ldb = talloc_reference ( kd , wrap ) ;
talloc_set_destructor ( kd , reg_close_ldb_key ) ;
kd - > dn = ldb_dn_new ( kd , wrap , " hive=NONE " ) ;
* k = ( struct hive_key * ) kd ;
return WERR_OK ;
}
2007-10-06 04:17:44 +04:00
static WERROR ldb_add_key ( TALLOC_CTX * mem_ctx , const struct hive_key * parent ,
const char * name , const char * classname ,
struct security_descriptor * sd ,
struct hive_key * * newkey )
2007-08-26 19:16:40 +04:00
{
2008-02-09 19:18:51 +03:00
struct ldb_key_data * parentkd = discard_const_p ( struct ldb_key_data , parent ) ;
2007-08-26 19:16:40 +04:00
struct ldb_message * msg ;
struct ldb_key_data * newkd ;
int ret ;
msg = ldb_msg_new ( mem_ctx ) ;
msg - > dn = reg_path_to_ldb ( msg , parent , name , NULL ) ;
ldb_msg_add_string ( msg , " key " , talloc_strdup ( mem_ctx , name ) ) ;
if ( classname ! = NULL )
2007-10-06 04:17:44 +04:00
ldb_msg_add_string ( msg , " classname " ,
talloc_strdup ( mem_ctx , classname ) ) ;
2007-08-26 19:16:40 +04:00
ret = ldb_add ( parentkd - > ldb , msg ) ;
2008-01-18 04:45:00 +03:00
if ( ret = = LDB_ERR_ENTRY_ALREADY_EXISTS ) {
return WERR_ALREADY_EXISTS ;
}
2008-01-18 03:48:48 +03:00
if ( ret ! = LDB_SUCCESS ) {
2008-01-18 04:45:00 +03:00
DEBUG ( 1 , ( " ldb_add: %s \n " , ldb_errstring ( parentkd - > ldb ) ) ) ;
2007-08-26 19:16:40 +04:00
return WERR_FOOBAR ;
2007-10-06 04:17:44 +04:00
}
2007-08-26 19:16:40 +04:00
DEBUG ( 2 , ( " key added: %s \n " , ldb_dn_get_linearized ( msg - > dn ) ) ) ;
newkd = talloc_zero ( mem_ctx , struct ldb_key_data ) ;
newkd - > ldb = talloc_reference ( newkd , parentkd - > ldb ) ;
newkd - > key . ops = & reg_backend_ldb ;
newkd - > dn = talloc_steal ( newkd , msg - > dn ) ;
* newkey = ( struct hive_key * ) newkd ;
2008-01-18 05:37:06 +03:00
/* reset cache */
talloc_free ( parentkd - > subkeys ) ;
parentkd - > subkeys = NULL ;
2007-08-26 19:16:40 +04:00
return WERR_OK ;
}
static WERROR ldb_del_value ( struct hive_key * key , const char * child )
{
int ret ;
struct ldb_key_data * kd = talloc_get_type ( key , struct ldb_key_data ) ;
2008-09-09 19:49:41 +04:00
TALLOC_CTX * mem_ctx ;
struct ldb_message * msg ;
2007-08-26 19:16:40 +04:00
struct ldb_dn * childdn ;
2008-09-09 19:49:41 +04:00
if ( strlen ( child ) = = 0 ) {
/* default value */
mem_ctx = talloc_init ( " ldb_del_value " ) ;
msg = talloc_zero ( mem_ctx , struct ldb_message ) ;
msg - > dn = ldb_dn_copy ( msg , kd - > dn ) ;
ldb_msg_add_empty ( msg , " data " , LDB_FLAG_MOD_DELETE , NULL ) ;
ldb_msg_add_empty ( msg , " type " , LDB_FLAG_MOD_DELETE , NULL ) ;
ret = ldb_modify ( kd - > ldb , msg ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 1 , ( " ldb_del_value: %s \n " , ldb_errstring ( kd - > ldb ) ) ) ;
talloc_free ( mem_ctx ) ;
return WERR_FOOBAR ;
}
talloc_free ( mem_ctx ) ;
} else {
/* normal value */
childdn = ldb_dn_copy ( kd - > ldb , kd - > dn ) ;
if ( ! ldb_dn_add_child_fmt ( childdn , " value=%s " ,
2008-01-18 03:50:33 +03:00
reg_ldb_escape ( childdn , child ) ) )
2008-09-09 19:49:41 +04:00
{
talloc_free ( childdn ) ;
return WERR_FOOBAR ;
}
2007-08-26 19:16:40 +04:00
2008-09-09 19:49:41 +04:00
ret = ldb_delete ( kd - > ldb , childdn ) ;
2007-08-26 19:16:40 +04:00
2008-09-09 19:49:41 +04:00
talloc_free ( childdn ) ;
2007-08-26 19:16:40 +04:00
2008-09-09 19:49:41 +04:00
if ( ret = = LDB_ERR_NO_SUCH_OBJECT ) {
return WERR_BADFILE ;
} else if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 1 , ( " ldb_del_value: %s \n " , ldb_errstring ( kd - > ldb ) ) ) ;
return WERR_FOOBAR ;
}
}
2008-01-18 05:37:06 +03:00
2008-09-12 18:31:57 +04:00
/* reset cache */
talloc_free ( kd - > values ) ;
kd - > values = NULL ;
2007-08-26 19:16:40 +04:00
return WERR_OK ;
}
2008-02-17 00:08:28 +03:00
static WERROR ldb_del_key ( const struct hive_key * key , const char * name )
{
int i , ret ;
struct ldb_key_data * parentkd = talloc_get_type ( key , struct ldb_key_data ) ;
struct ldb_dn * ldap_path ;
TALLOC_CTX * mem_ctx = talloc_init ( " ldb_del_key " ) ;
struct ldb_context * c = parentkd - > ldb ;
struct ldb_result * res_keys ;
struct ldb_result * res_vals ;
WERROR werr ;
struct hive_key * hk ;
/* Verify key exists by opening it */
werr = ldb_open_key ( mem_ctx , key , name , & hk ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
talloc_free ( mem_ctx ) ;
return werr ;
}
ldap_path = reg_path_to_ldb ( mem_ctx , key , name , NULL ) ;
if ( ! ldap_path ) {
talloc_free ( mem_ctx ) ;
return WERR_FOOBAR ;
}
/* Search for subkeys */
2008-09-23 22:30:06 +04:00
ret = ldb_search ( c , mem_ctx , & res_keys , ldap_path , LDB_SCOPE_ONELEVEL ,
NULL , " (key=*) " ) ;
2008-02-17 00:08:28 +03:00
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( " Error getting subkeys for '%s': %s \n " ,
ldb_dn_get_linearized ( ldap_path ) , ldb_errstring ( c ) ) ) ;
talloc_free ( mem_ctx ) ;
return WERR_FOOBAR ;
}
/* Search for values */
2008-09-23 22:30:06 +04:00
ret = ldb_search ( c , mem_ctx , & res_vals , ldap_path , LDB_SCOPE_ONELEVEL ,
NULL , " (value=*) " ) ;
2008-02-17 00:08:28 +03:00
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( " Error getting values for '%s': %s \n " ,
ldb_dn_get_linearized ( ldap_path ) , ldb_errstring ( c ) ) ) ;
talloc_free ( mem_ctx ) ;
return WERR_FOOBAR ;
}
/* Start an explicit transaction */
ret = ldb_transaction_start ( c ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( " ldb_transaction_start: %s \n " , ldb_errstring ( c ) ) ) ;
talloc_free ( mem_ctx ) ;
return WERR_FOOBAR ;
}
if ( res_keys - > count | | res_vals - > count )
{
/* Delete any subkeys */
for ( i = 0 ; i < res_keys - > count ; i + + )
{
werr = ldb_del_key ( hk , ldb_msg_find_attr_as_string (
res_keys - > msgs [ i ] ,
" key " , NULL ) ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
ret = ldb_transaction_cancel ( c ) ;
talloc_free ( mem_ctx ) ;
return werr ;
}
}
/* Delete any values */
for ( i = 0 ; i < res_vals - > count ; i + + )
{
werr = ldb_del_value ( hk , ldb_msg_find_attr_as_string (
res_vals - > msgs [ i ] ,
" value " , NULL ) ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
ret = ldb_transaction_cancel ( c ) ;
talloc_free ( mem_ctx ) ;
return werr ;
}
}
}
/* Delete the key itself */
ret = ldb_delete ( c , ldap_path ) ;
if ( ret ! = LDB_SUCCESS )
{
DEBUG ( 1 , ( " ldb_del_key: %s \n " , ldb_errstring ( c ) ) ) ;
ret = ldb_transaction_cancel ( c ) ;
talloc_free ( mem_ctx ) ;
return WERR_FOOBAR ;
}
/* Commit the transaction */
ret = ldb_transaction_commit ( c ) ;
if ( ret ! = LDB_SUCCESS )
{
DEBUG ( 0 , ( " ldb_transaction_commit: %s \n " , ldb_errstring ( c ) ) ) ;
ret = ldb_transaction_cancel ( c ) ;
talloc_free ( mem_ctx ) ;
return WERR_FOOBAR ;
}
talloc_free ( mem_ctx ) ;
/* reset cache */
talloc_free ( parentkd - > subkeys ) ;
parentkd - > subkeys = NULL ;
return WERR_OK ;
}
2007-10-06 04:17:44 +04:00
static WERROR ldb_set_value ( struct hive_key * parent ,
const char * name , uint32_t type ,
const DATA_BLOB data )
2007-08-26 19:16:40 +04:00
{
struct ldb_message * msg ;
struct ldb_key_data * kd = talloc_get_type ( parent , struct ldb_key_data ) ;
int ret ;
TALLOC_CTX * mem_ctx = talloc_init ( " ldb_set_value " ) ;
msg = reg_ldb_pack_value ( kd - > ldb , mem_ctx , name , type , data ) ;
msg - > dn = ldb_dn_copy ( msg , kd - > dn ) ;
2008-09-09 19:49:41 +04:00
if ( strlen ( name ) > 0 ) {
/* For a default value, we add/overwrite the attributes to/of the hive.
For a normal value , we create new childs . */
if ( ! ldb_dn_add_child_fmt ( msg - > dn , " value=%s " ,
2008-01-18 03:50:33 +03:00
reg_ldb_escape ( mem_ctx , name ) ) )
2008-09-09 19:49:41 +04:00
{
talloc_free ( mem_ctx ) ;
return WERR_FOOBAR ;
}
2008-01-18 03:50:33 +03:00
}
2007-08-26 19:16:40 +04:00
ret = ldb_add ( kd - > ldb , msg ) ;
2008-01-18 03:47:10 +03:00
if ( ret = = LDB_ERR_ENTRY_ALREADY_EXISTS ) {
int i ;
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
2008-09-18 18:51:48 +04:00
if ( msg - > elements [ i ] . flags ! = LDB_FLAG_MOD_DELETE )
msg - > elements [ i ] . flags = LDB_FLAG_MOD_REPLACE ;
2007-08-26 19:16:40 +04:00
}
2008-01-18 03:47:10 +03:00
ret = ldb_modify ( kd - > ldb , msg ) ;
}
if ( ret ! = LDB_SUCCESS ) {
2008-09-09 19:49:41 +04:00
DEBUG ( 1 , ( " ldb_set_value: %s \n " , ldb_errstring ( kd - > ldb ) ) ) ;
2008-01-18 03:47:10 +03:00
talloc_free ( mem_ctx ) ;
return WERR_FOOBAR ;
2007-08-26 19:16:40 +04:00
}
2007-10-06 04:17:44 +04:00
2008-01-18 05:37:06 +03:00
/* reset cache */
talloc_free ( kd - > values ) ;
kd - > values = NULL ;
2007-08-26 19:16:40 +04:00
talloc_free ( mem_ctx ) ;
return WERR_OK ;
}
2007-10-06 04:17:44 +04:00
static WERROR ldb_get_key_info ( TALLOC_CTX * mem_ctx ,
const struct hive_key * key ,
const char * * classname ,
uint32_t * num_subkeys ,
uint32_t * num_values ,
2008-01-07 23:11:29 +03:00
NTTIME * last_change_time ,
uint32_t * max_subkeynamelen ,
uint32_t * max_valnamelen ,
uint32_t * max_valbufsize )
2007-08-26 19:16:40 +04:00
{
struct ldb_key_data * kd = talloc_get_type ( key , struct ldb_key_data ) ;
2008-09-13 15:32:39 +04:00
/* Initialization */
if ( classname ! = NULL )
* classname = NULL ;
if ( num_subkeys ! = NULL )
* num_subkeys = 0 ;
if ( num_values ! = NULL )
* num_values = 0 ;
if ( last_change_time ! = NULL )
* last_change_time = 0 ;
if ( max_subkeynamelen ! = NULL )
* max_subkeynamelen = 0 ;
if ( max_valnamelen ! = NULL )
* max_valnamelen = 0 ;
if ( max_valbufsize ! = NULL )
* max_valbufsize = 0 ;
2008-01-18 05:37:06 +03:00
if ( kd - > subkeys = = NULL ) {
W_ERROR_NOT_OK_RETURN ( cache_subkeys ( kd ) ) ;
}
if ( kd - > values = = NULL ) {
W_ERROR_NOT_OK_RETURN ( cache_values ( kd ) ) ;
}
2007-08-26 19:16:40 +04:00
if ( num_subkeys ! = NULL ) {
* num_subkeys = kd - > subkey_count ;
}
if ( num_values ! = NULL ) {
* num_values = kd - > value_count ;
}
2008-01-07 23:11:29 +03:00
if ( max_subkeynamelen ! = NULL ) {
int i ;
struct ldb_message_element * el ;
* max_subkeynamelen = 0 ;
for ( i = 0 ; i < kd - > subkey_count ; i + + ) {
el = ldb_msg_find_element ( kd - > subkeys [ i ] , " key " ) ;
* max_subkeynamelen = MAX ( * max_subkeynamelen , el - > values [ 0 ] . length ) ;
}
}
if ( max_valnamelen ! = NULL | | max_valbufsize ! = NULL ) {
int i ;
struct ldb_message_element * el ;
W_ERROR_NOT_OK_RETURN ( cache_values ( kd ) ) ;
if ( max_valbufsize ! = NULL )
* max_valbufsize = 0 ;
if ( max_valnamelen ! = NULL )
* max_valnamelen = 0 ;
for ( i = 0 ; i < kd - > value_count ; i + + ) {
if ( max_valnamelen ! = NULL ) {
el = ldb_msg_find_element ( kd - > values [ i ] , " value " ) ;
* max_valnamelen = MAX ( * max_valnamelen , el - > values [ 0 ] . length ) ;
}
if ( max_valbufsize ! = NULL ) {
2008-09-15 21:21:38 +04:00
uint32_t data_type ;
2008-01-07 23:11:29 +03:00
DATA_BLOB data ;
2008-02-21 19:54:24 +03:00
reg_ldb_unpack_value ( mem_ctx ,
lp_iconv_convenience ( global_loadparm ) ,
kd - > values [ i ] , NULL ,
2008-09-15 21:21:38 +04:00
& data_type , & data ) ;
2008-01-07 23:11:29 +03:00
* max_valbufsize = MAX ( * max_valbufsize , data . length ) ;
talloc_free ( data . data ) ;
}
}
}
2007-08-26 19:16:40 +04:00
return WERR_OK ;
}
static struct hive_operations reg_backend_ldb = {
. name = " ldb " ,
. add_key = ldb_add_key ,
. del_key = ldb_del_key ,
. get_key_by_name = ldb_open_key ,
. enum_value = ldb_get_value_by_id ,
. enum_key = ldb_get_subkey_by_id ,
. set_value = ldb_set_value ,
. get_value_by_name = ldb_get_value ,
. delete_value = ldb_del_value ,
. get_key_info = ldb_get_key_info ,
} ;