0001-01-01 02:30:17 +02:30
/*
* Unix SMB / CIFS implementation .
* SMB parameters and setup
* Copyright ( C ) Andrew Tridgell 1992 - 1998
* Copyright ( C ) Simo Sorce 2000 - 2002
* Copyright ( C ) Gerald Carter 2000
* Copyright ( C ) Jeremy Allison 2001
* Copyright ( C ) Andrew Bartlett 2002
*
* 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 2 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 , write to the Free Software Foundation , Inc . , 675
* Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
0001-01-01 02:30:17 +02:30
# include "tdbsam2.h"
# include "tdbsam2_parse_info.h"
0001-01-01 02:30:17 +02:30
static int tdbgumm_debug_level = DBGC_ALL ;
# undef DBGC_CLASS
# define DBGC_CLASS tdbgumm_debug_level
0001-01-01 02:30:17 +02:30
# define TDBSAM_VERSION 20021215
0001-01-01 02:30:17 +02:30
# define TDB_FILE_NAME "tdbsam2.tdb"
0001-01-01 02:30:17 +02:30
# define NAMEPREFIX "NAME_"
0001-01-01 02:30:17 +02:30
# define SIDPREFIX "SID_"
# define PRIVILEGEPREFIX "PRIV_"
# define TDB_FORMAT_STRING "ddB"
0001-01-01 02:30:17 +02:30
# define TALLOC_CHECK(ptr, err, label) do { if ((ptr) == NULL) { DEBUG(0, ("%s: Out of memory!\n", FUNCTION_MACRO)); err = NT_STATUS_NO_MEMORY; goto label; } } while(0)
# define SET_OR_FAIL(func, label) do { if (NT_STATUS_IS_ERR(func)) { DEBUG(0, ("%s: Setting gums object data failed!\n", FUNCTION_MACRO)); goto label; } } while(0)
0001-01-01 02:30:17 +02:30
struct tdbsam2_enum_objs {
uint32 type ;
fstring dom_sid ;
TDB_CONTEXT * db ;
TDB_DATA key ;
struct tdbsam2_enum_objs * next ;
} ;
0001-01-01 02:30:17 +02:30
union tdbsam2_data {
struct tdbsam2_domain_data * domain ;
struct tdbsam2_user_data * user ;
struct tdbsam2_group_data * group ;
} ;
struct tdbsam2_object {
uint32 type ;
0001-01-01 02:30:17 +02:30
uint32 version ;
0001-01-01 02:30:17 +02:30
union tdbsam2_data data ;
} ;
static TDB_CONTEXT * tdbsam2_db ;
0001-01-01 02:30:17 +02:30
struct tdbsam2_enum_objs * * teo_handlers ;
static NTSTATUS init_tdbsam2_object_from_buffer ( struct tdbsam2_object * object , TALLOC_CTX * mem_ctx , char * buffer , int size )
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL ;
int iret ;
char * obj_data ;
int data_size = 0 ;
int len ;
len = tdb_unpack ( buffer , size , TDB_FORMAT_STRING ,
& ( object - > version ) ,
& ( object - > type ) ,
& data_size , & obj_data ) ;
if ( len = = - 1 )
goto done ;
/* version is checked inside this function so that backward compatibility code can be
called eventually .
this way we can easily handle database format upgrades */
if ( object - > version ! = TDBSAM_VERSION ) {
DEBUG ( 3 , ( " init_tdbsam2_object_from_buffer: Error, db object has wrong tdbsam version! \n " ) ) ;
goto done ;
}
/* be sure the string is terminated before trying to parse it */
if ( obj_data [ data_size - 1 ] ! = ' \0 ' )
obj_data [ data_size - 1 ] = ' \0 ' ;
switch ( object - > type ) {
case GUMS_OBJ_DOMAIN :
object - > data . domain = ( struct tdbsam2_domain_data * ) talloc ( mem_ctx , sizeof ( struct tdbsam2_domain_data ) ) ;
TALLOC_CHECK ( object - > data . domain , ret , done ) ;
memset ( object - > data . domain , 0 , sizeof ( struct tdbsam2_domain_data ) ) ;
iret = gen_parse ( mem_ctx , pinfo_tdbsam2_domain_data , ( char * ) ( object - > data . domain ) , obj_data ) ;
break ;
case GUMS_OBJ_GROUP :
case GUMS_OBJ_ALIAS :
object - > data . group = ( struct tdbsam2_group_data * ) talloc ( mem_ctx , sizeof ( struct tdbsam2_group_data ) ) ;
TALLOC_CHECK ( object - > data . group , ret , done ) ;
memset ( object - > data . group , 0 , sizeof ( struct tdbsam2_group_data ) ) ;
iret = gen_parse ( mem_ctx , pinfo_tdbsam2_group_data , ( char * ) ( object - > data . group ) , obj_data ) ;
break ;
case GUMS_OBJ_NORMAL_USER :
object - > data . user = ( struct tdbsam2_user_data * ) talloc ( mem_ctx , sizeof ( struct tdbsam2_user_data ) ) ;
TALLOC_CHECK ( object - > data . user , ret , done ) ;
memset ( object - > data . user , 0 , sizeof ( struct tdbsam2_user_data ) ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
iret = gen_parse ( mem_ctx , pinfo_tdbsam2_user_data , ( char * ) ( object - > data . user ) , obj_data ) ;
break ;
default :
DEBUG ( 3 , ( " init_tdbsam2_object_from_buffer: Error, wrong object type number! \n " ) ) ;
goto done ;
}
if ( iret ! = 0 ) {
DEBUG ( 0 , ( " init_tdbsam2_object_from_buffer: Fatal Error! Unable to parse object! \n " ) ) ;
DEBUG ( 0 , ( " init_tdbsam2_object_from_buffer: DB Corrupted ? " ) ) ;
goto done ;
}
ret = NT_STATUS_OK ;
done :
SAFE_FREE ( obj_data ) ;
return ret ;
}
static NTSTATUS init_buffer_from_tdbsam2_object ( char * * buffer , size_t * len , TALLOC_CTX * mem_ctx , struct tdbsam2_object * object )
{
NTSTATUS ret ;
char * buf1 = NULL ;
size_t buflen ;
if ( ! buffer )
return NT_STATUS_INVALID_PARAMETER ;
switch ( object - > type ) {
case GUMS_OBJ_DOMAIN :
buf1 = gen_dump ( mem_ctx , pinfo_tdbsam2_domain_data , ( char * ) ( object - > data . domain ) , 0 ) ;
break ;
case GUMS_OBJ_GROUP :
case GUMS_OBJ_ALIAS :
buf1 = gen_dump ( mem_ctx , pinfo_tdbsam2_group_data , ( char * ) ( object - > data . group ) , 0 ) ;
break ;
case GUMS_OBJ_NORMAL_USER :
buf1 = gen_dump ( mem_ctx , pinfo_tdbsam2_user_data , ( char * ) ( object - > data . user ) , 0 ) ;
break ;
default :
DEBUG ( 3 , ( " init_buffer_from_tdbsam2_object: Error, wrong object type number! \n " ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
if ( buf1 = = NULL ) {
DEBUG ( 0 , ( " init_buffer_from_tdbsam2_object: Fatal Error! Unable to dump object! \n " ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
buflen = tdb_pack ( NULL , 0 , TDB_FORMAT_STRING ,
TDBSAM_VERSION ,
object - > type ,
strlen ( buf1 ) + 1 , buf1 ) ;
* buffer = talloc ( mem_ctx , buflen ) ;
TALLOC_CHECK ( * buffer , ret , done ) ;
* len = tdb_pack ( * buffer , buflen , TDB_FORMAT_STRING ,
TDBSAM_VERSION ,
object - > type ,
strlen ( buf1 ) + 1 , buf1 ) ;
if ( * len ! = buflen ) {
DEBUG ( 0 , ( " init_tdb_data_from_tdbsam2_object: somthing odd is going on here: bufflen (%d) != len (%d) in tdb_pack operations! \n " ,
buflen , * len ) ) ;
* buffer = NULL ;
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
ret = NT_STATUS_OK ;
done :
return ret ;
}
static NTSTATUS opentdb ( void )
{
if ( ! tdbsam2_db ) {
pstring tdbfile ;
get_private_directory ( tdbfile ) ;
pstrcat ( tdbfile , " / " ) ;
pstrcat ( tdbfile , TDB_FILE_NAME ) ;
tdbsam2_db = tdb_open_log ( tdbfile , 0 , TDB_DEFAULT , O_RDWR | O_CREAT , 0600 ) ;
if ( ! tdbsam2_db )
{
DEBUG ( 0 , ( " opentdb: Unable to open database (%s)! \n " , tdbfile ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
}
0001-01-01 02:30:17 +02:30
return NT_STATUS_OK ;
}
0001-01-01 02:30:17 +02:30
static NTSTATUS get_object_by_sid ( TALLOC_CTX * mem_ctx , struct tdbsam2_object * obj , const DOM_SID * sid )
{
NTSTATUS ret ;
TDB_DATA data , key ;
fstring keystr ;
if ( ! obj | | ! mem_ctx | | ! sid )
return NT_STATUS_INVALID_PARAMETER ;
if ( NT_STATUS_IS_ERR ( ret = opentdb ( ) ) ) {
return ret ;
}
slprintf ( keystr , sizeof ( keystr ) - 1 , " %s%s " , SIDPREFIX , sid_string_static ( sid ) ) ;
key . dptr = keystr ;
key . dsize = strlen ( keystr ) + 1 ;
data = tdb_fetch ( tdbsam2_db , key ) ;
if ( ! data . dptr ) {
DEBUG ( 5 , ( " get_object_by_sid: Error fetching database, domain entry not found! \n " ) ) ;
DEBUGADD ( 5 , ( " Error: %s \n " , tdb_errorstr ( tdbsam2_db ) ) ) ;
DEBUGADD ( 5 , ( " Key: %s \n " , keystr ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
if ( NT_STATUS_IS_ERR ( init_tdbsam2_object_from_buffer ( obj , mem_ctx , data . dptr , data . dsize ) ) ) {
SAFE_FREE ( data . dptr ) ;
DEBUG ( 0 , ( " get_object_by_sid: Error fetching database, malformed entry! \n " ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
SAFE_FREE ( data . dptr ) ;
0001-01-01 02:30:17 +02:30
return NT_STATUS_OK ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
static NTSTATUS get_object_by_name ( TALLOC_CTX * mem_ctx , struct tdbsam2_object * obj , const char * name )
{
0001-01-01 02:30:17 +02:30
NTSTATUS ret ;
TDB_DATA data , key ;
fstring keystr ;
fstring objname ;
0001-01-01 02:30:17 +02:30
DOM_SID sid ;
char * obj_sidstr ;
int obj_version , obj_type , obj_sidstr_len , len ;
0001-01-01 02:30:17 +02:30
if ( ! obj | | ! mem_ctx | | ! name )
return NT_STATUS_INVALID_PARAMETER ;
0001-01-01 02:30:17 +02:30
if ( NT_STATUS_IS_ERR ( ret = opentdb ( ) ) ) {
return ret ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
fstrcpy ( objname , name ) ;
strlower ( objname ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
slprintf ( keystr , sizeof ( keystr ) - 1 , " %s%s " , NAMEPREFIX , objname ) ;
0001-01-01 02:30:17 +02:30
key . dptr = keystr ;
key . dsize = strlen ( keystr ) + 1 ;
data = tdb_fetch ( tdbsam2_db , key ) ;
if ( ! data . dptr ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 5 , ( " get_object_by_name: Error fetching database, domain entry not found! \n " ) ) ;
0001-01-01 02:30:17 +02:30
DEBUGADD ( 5 , ( " Error: %s \n " , tdb_errorstr ( tdbsam2_db ) ) ) ;
DEBUGADD ( 5 , ( " Key: %s \n " , keystr ) ) ;
0001-01-01 02:30:17 +02:30
return NT_STATUS_UNSUCCESSFUL ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
len = tdb_unpack ( data . dptr , data . dsize , TDB_FORMAT_STRING ,
& obj_version ,
& obj_type ,
& obj_sidstr_len , & obj_sidstr ) ;
0001-01-01 02:30:17 +02:30
SAFE_FREE ( data . dptr ) ;
0001-01-01 02:30:17 +02:30
if ( len = = - 1 | | obj_version ! = TDBSAM_VERSION | | obj_sidstr_len < = 0 ) {
DEBUG ( 5 , ( " get_object_by_name: Error unpacking database object! \n " ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( ! string_to_sid ( & sid , obj_sidstr ) ) {
DEBUG ( 5 , ( " get_object_by_name: Error invalid sid string found in database object! \n " ) ) ;
SAFE_FREE ( obj_sidstr ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
SAFE_FREE ( obj_sidstr ) ;
return get_object_by_sid ( mem_ctx , obj , & sid ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
static NTSTATUS store_object ( TALLOC_CTX * mem_ctx , struct tdbsam2_object * object , BOOL new_obj )
{
0001-01-01 02:30:17 +02:30
NTSTATUS ret ;
0001-01-01 02:30:17 +02:30
TDB_DATA data , key , key2 ;
fstring keystr ;
fstring namestr ;
int flag , r ;
if ( NT_STATUS_IS_ERR ( ret = opentdb ( ) ) ) {
return ret ;
}
if ( new_obj ) {
flag = TDB_INSERT ;
} else {
flag = TDB_MODIFY ;
}
ret = init_buffer_from_tdbsam2_object ( & ( data . dptr ) , & ( data . dsize ) , mem_ctx , object ) ;
if ( NT_STATUS_IS_ERR ( ret ) )
return ret ;
switch ( object - > type ) {
case GUMS_OBJ_DOMAIN :
slprintf ( keystr , sizeof ( keystr ) - 1 , " %s%s " , SIDPREFIX , sid_string_static ( object - > data . domain - > dom_sid ) ) ;
slprintf ( namestr , sizeof ( namestr ) - 1 , " %s%s " , NAMEPREFIX , object - > data . domain - > name ) ;
break ;
case GUMS_OBJ_GROUP :
case GUMS_OBJ_ALIAS :
slprintf ( keystr , sizeof ( keystr ) - 1 , " %s%s " , SIDPREFIX , sid_string_static ( object - > data . group - > group_sid ) ) ;
slprintf ( namestr , sizeof ( namestr ) - 1 , " %s%s " , NAMEPREFIX , object - > data . group - > name ) ;
break ;
case GUMS_OBJ_NORMAL_USER :
slprintf ( keystr , sizeof ( keystr ) - 1 , " %s%s " , SIDPREFIX , sid_string_static ( object - > data . user - > user_sid ) ) ;
slprintf ( namestr , sizeof ( namestr ) - 1 , " %s%s " , NAMEPREFIX , object - > data . user - > name ) ;
break ;
default :
return NT_STATUS_UNSUCCESSFUL ;
}
key . dptr = keystr ;
key . dsize = strlen ( keystr ) + 1 ;
if ( ( r = tdb_store ( tdbsam2_db , key , data , flag ) ) ! = TDB_SUCCESS ) {
DEBUG ( 0 , ( " store_object: Unable to modify SAM! \n " ) ) ;
DEBUGADD ( 0 , ( " Error: %s " , tdb_errorstr ( tdbsam2_db ) ) ) ;
DEBUGADD ( 0 , ( " occured while storing the main record (%s) \n " , keystr ) ) ;
if ( r = = TDB_ERR_EXISTS ) return NT_STATUS_UNSUCCESSFUL ;
return NT_STATUS_INTERNAL_DB_ERROR ;
}
key2 . dptr = namestr ;
key2 . dsize = strlen ( namestr ) + 1 ;
if ( ( r = tdb_store ( tdbsam2_db , key2 , key , flag ) ) ! = TDB_SUCCESS ) {
DEBUG ( 0 , ( " store_object: Unable to modify SAM! \n " ) ) ;
DEBUGADD ( 0 , ( " Error: %s " , tdb_errorstr ( tdbsam2_db ) ) ) ;
DEBUGADD ( 0 , ( " occured while storing the main record (%s) \n " , keystr ) ) ;
if ( r = = TDB_ERR_EXISTS ) return NT_STATUS_UNSUCCESSFUL ;
return NT_STATUS_INTERNAL_DB_ERROR ;
}
/* TODO: update the general database counter */
/* TODO: update this entry counter too */
0001-01-01 02:30:17 +02:30
return NT_STATUS_OK ;
}
0001-01-01 02:30:17 +02:30
static NTSTATUS get_next_sid ( TALLOC_CTX * mem_ctx , DOM_SID * * sid )
{
0001-01-01 02:30:17 +02:30
NTSTATUS ret ;
0001-01-01 02:30:17 +02:30
struct tdbsam2_object obj ;
DOM_SID * dom_sid = get_global_sam_sid ( ) ;
uint32 new_rid ;
/* TODO: LOCK DOMAIN OBJECT */
ret = get_object_by_sid ( mem_ctx , & obj , dom_sid ) ;
if ( NT_STATUS_IS_ERR ( ret ) ) {
DEBUG ( 0 , ( " get_next_sid: unable to get root Domain object! \n " ) ) ;
ret = NT_STATUS_INTERNAL_DB_ERROR ;
goto error ;
}
new_rid = obj . data . domain - > next_rid ;
/* Increment the RID Counter */
obj . data . domain - > next_rid + + ;
/* Store back Domain object */
ret = store_object ( mem_ctx , & obj , False ) ;
if ( NT_STATUS_IS_ERR ( ret ) ) {
DEBUG ( 0 , ( " get_next_sid: unable to update root Domain object! \n " ) ) ;
ret = NT_STATUS_INTERNAL_DB_ERROR ;
goto error ;
}
/* TODO: UNLOCK DOMAIN OBJECT */
* sid = sid_dup_talloc ( mem_ctx , dom_sid ) ;
TALLOC_CHECK ( * sid , ret , error ) ;
if ( ! sid_append_rid ( * sid , new_rid ) ) {
DEBUG ( 0 , ( " get_next_sid: unable to build new SID !?! \n " ) ) ;
ret = NT_STATUS_UNSUCCESSFUL ;
goto error ;
}
0001-01-01 02:30:17 +02:30
return NT_STATUS_OK ;
0001-01-01 02:30:17 +02:30
error :
return ret ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static NTSTATUS user_data_to_gums_object ( GUMS_OBJECT * * object , struct tdbsam2_user_data * userdata )
{
0001-01-01 02:30:17 +02:30
NTSTATUS ret ;
if ( ! object | | ! userdata ) {
DEBUG ( 0 , ( " tdbsam2_user_data_to_gums_object: no NULL pointers are accepted here! \n " ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
/* userdata->xcounter */
/* userdata->sec_desc */
SET_OR_FAIL ( gums_set_object_sid ( * object , userdata - > user_sid ) , error ) ;
SET_OR_FAIL ( gums_set_object_name ( * object , userdata - > name ) , error ) ;
SET_OR_FAIL ( gums_set_user_pri_group ( * object , userdata - > group_sid ) , error ) ;
if ( userdata - > description )
SET_OR_FAIL ( gums_set_object_description ( * object , userdata - > description ) , error ) ;
if ( userdata - > full_name )
SET_OR_FAIL ( gums_set_user_fullname ( * object , userdata - > full_name ) , error ) ;
if ( userdata - > home_dir )
SET_OR_FAIL ( gums_set_user_homedir ( * object , userdata - > home_dir ) , error ) ;
if ( userdata - > dir_drive )
SET_OR_FAIL ( gums_set_user_dir_drive ( * object , userdata - > dir_drive ) , error ) ;
if ( userdata - > logon_script )
SET_OR_FAIL ( gums_set_user_logon_script ( * object , userdata - > logon_script ) , error ) ;
if ( userdata - > profile_path )
SET_OR_FAIL ( gums_set_user_profile_path ( * object , userdata - > profile_path ) , error ) ;
if ( userdata - > workstations )
SET_OR_FAIL ( gums_set_user_workstations ( * object , userdata - > workstations ) , error ) ;
if ( userdata - > unknown_str )
SET_OR_FAIL ( gums_set_user_unknown_str ( * object , userdata - > unknown_str ) , error ) ;
if ( userdata - > munged_dial )
SET_OR_FAIL ( gums_set_user_munged_dial ( * object , userdata - > munged_dial ) , error ) ;
SET_OR_FAIL ( gums_set_user_logon_divs ( * object , userdata - > logon_divs ) , error ) ;
SET_OR_FAIL ( gums_set_user_hours_len ( * object , userdata - > hours_len ) , error ) ;
if ( userdata - > hours )
SET_OR_FAIL ( gums_set_user_hours ( * object , userdata - > hours ) , error ) ;
SET_OR_FAIL ( gums_set_user_unknown_3 ( * object , userdata - > unknown_3 ) , error ) ;
SET_OR_FAIL ( gums_set_user_unknown_5 ( * object , userdata - > unknown_5 ) , error ) ;
SET_OR_FAIL ( gums_set_user_unknown_6 ( * object , userdata - > unknown_6 ) , error ) ;
0001-01-01 02:30:17 +02:30
SET_OR_FAIL ( gums_set_user_logon_time ( * object , * ( userdata - > logon_time ) ) , error ) ;
SET_OR_FAIL ( gums_set_user_logoff_time ( * object , * ( userdata - > logoff_time ) ) , error ) ;
SET_OR_FAIL ( gums_set_user_kickoff_time ( * object , * ( userdata - > kickoff_time ) ) , error ) ;
SET_OR_FAIL ( gums_set_user_pass_last_set_time ( * object , * ( userdata - > pass_last_set_time ) ) , error ) ;
SET_OR_FAIL ( gums_set_user_pass_can_change_time ( * object , * ( userdata - > pass_can_change_time ) ) , error ) ;
SET_OR_FAIL ( gums_set_user_pass_must_change_time ( * object , * ( userdata - > pass_must_change_time ) ) , error ) ;
0001-01-01 02:30:17 +02:30
ret = NT_STATUS_OK ;
return ret ;
error :
talloc_destroy ( ( * object ) - > mem_ctx ) ;
* object = NULL ;
return ret ;
}
0001-01-01 02:30:17 +02:30
static NTSTATUS group_data_to_gums_object ( GUMS_OBJECT * * object , struct tdbsam2_group_data * groupdata )
{
0001-01-01 02:30:17 +02:30
NTSTATUS ret ;
if ( ! object | | ! groupdata ) {
DEBUG ( 0 , ( " tdbsam2_group_data_to_gums_object: no NULL pointers are accepted here! \n " ) ) ;
0001-01-01 02:30:17 +02:30
return NT_STATUS_UNSUCCESSFUL ;
}
0001-01-01 02:30:17 +02:30
/* groupdata->xcounter */
/* groupdata->sec_desc */
SET_OR_FAIL ( gums_set_object_sid ( * object , groupdata - > group_sid ) , error ) ;
SET_OR_FAIL ( gums_set_object_name ( * object , groupdata - > name ) , error ) ;
if ( groupdata - > description )
SET_OR_FAIL ( gums_set_object_description ( * object , groupdata - > description ) , error ) ;
if ( groupdata - > count )
SET_OR_FAIL ( gums_set_group_members ( * object , groupdata - > count , groupdata - > members ) , error ) ;
ret = NT_STATUS_OK ;
return ret ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
error :
talloc_destroy ( ( * object ) - > mem_ctx ) ;
* object = NULL ;
return ret ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static NTSTATUS domain_data_to_gums_object ( GUMS_OBJECT * * object , struct tdbsam2_domain_data * domdata )
{
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
NTSTATUS ret ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( ! object | | ! * object | | ! domdata ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " tdbsam2_domain_data_to_gums_object: no NULL pointers are accepted here! \n " ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* domdata->xcounter */
/* domdata->sec_desc */
SET_OR_FAIL ( gums_set_object_sid ( * object , domdata - > dom_sid ) , error ) ;
SET_OR_FAIL ( gums_set_object_name ( * object , domdata - > name ) , error ) ;
if ( domdata - > description )
SET_OR_FAIL ( gums_set_object_description ( * object , domdata - > description ) , error ) ;
ret = NT_STATUS_OK ;
return ret ;
error :
talloc_destroy ( ( * object ) - > mem_ctx ) ;
* object = NULL ;
return ret ;
}
0001-01-01 02:30:17 +02:30
static NTSTATUS data_to_gums_object ( GUMS_OBJECT * * object , struct tdbsam2_object * data )
{
0001-01-01 02:30:17 +02:30
NTSTATUS ret ;
if ( ! object | | ! data ) {
DEBUG ( 0 , ( " tdbsam2_user_data_to_gums_object: no NULL structure pointers are accepted here! \n " ) ) ;
ret = NT_STATUS_INVALID_PARAMETER ;
goto done ;
}
ret = gums_create_object ( object , data - > type ) ;
if ( NT_STATUS_IS_ERR ( ret ) ) {
DEBUG ( 5 , ( " tdbsam2_user_data_to_gums_object: error creating gums object! \n " ) ) ;
goto done ;
}
switch ( data - > type ) {
case GUMS_OBJ_DOMAIN :
0001-01-01 02:30:17 +02:30
ret = domain_data_to_gums_object ( object , data - > data . domain ) ;
0001-01-01 02:30:17 +02:30
break ;
case GUMS_OBJ_NORMAL_USER :
0001-01-01 02:30:17 +02:30
ret = user_data_to_gums_object ( object , data - > data . user ) ;
0001-01-01 02:30:17 +02:30
break ;
case GUMS_OBJ_GROUP :
case GUMS_OBJ_ALIAS :
0001-01-01 02:30:17 +02:30
ret = group_data_to_gums_object ( object , data - > data . group ) ;
0001-01-01 02:30:17 +02:30
break ;
default :
ret = NT_STATUS_UNSUCCESSFUL ;
}
done :
return ret ;
}
0001-01-01 02:30:17 +02:30
/* GUMM object functions */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static NTSTATUS tdbsam2_get_domain_sid ( DOM_SID * sid , const char * name )
{
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
NTSTATUS ret ;
struct tdbsam2_object obj ;
TALLOC_CTX * mem_ctx ;
fstring domname ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( ! sid | | ! name )
return NT_STATUS_INVALID_PARAMETER ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
mem_ctx = talloc_init ( " tdbsam2_get_domain_sid " ) ;
if ( ! mem_ctx ) {
DEBUG ( 0 , ( " tdbsam2_new_object: Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
if ( NT_STATUS_IS_ERR ( ret = opentdb ( ) ) ) {
goto done ;
}
0001-01-01 02:30:17 +02:30
fstrcpy ( domname , name ) ;
strlower ( domname ) ;
0001-01-01 02:30:17 +02:30
ret = get_object_by_name ( mem_ctx , & obj , domname ) ;
if ( NT_STATUS_IS_ERR ( ret ) ) {
DEBUG ( 0 , ( " tdbsam2_get_domain_sid: Error fetching database! \n " ) ) ;
goto done ;
}
if ( obj . type ! = GUMS_OBJ_DOMAIN ) {
DEBUG ( 5 , ( " tdbsam2_get_domain_sid: Requested object is not a domain! \n " ) ) ;
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
sid_copy ( sid , obj . data . domain - > dom_sid ) ;
ret = NT_STATUS_OK ;
done :
talloc_destroy ( mem_ctx ) ;
return ret ;
}
static NTSTATUS tdbsam2_set_domain_sid ( const DOM_SID * sid , const char * name )
{
0001-01-01 02:30:17 +02:30
NTSTATUS ret ;
struct tdbsam2_object obj ;
TALLOC_CTX * mem_ctx ;
fstring domname ;
if ( ! sid | | ! name )
return NT_STATUS_INVALID_PARAMETER ;
0001-01-01 02:30:17 +02:30
mem_ctx = talloc_init ( " tdbsam2_set_domain_sid " ) ;
0001-01-01 02:30:17 +02:30
if ( ! mem_ctx ) {
DEBUG ( 0 , ( " tdbsam2_new_object: Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
if ( tdbsam2_db = = NULL ) {
0001-01-01 02:30:17 +02:30
if ( NT_STATUS_IS_ERR ( ret = opentdb ( ) ) ) {
0001-01-01 02:30:17 +02:30
goto done ;
}
}
0001-01-01 02:30:17 +02:30
fstrcpy ( domname , name ) ;
strlower ( domname ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* TODO: we need to lock this entry until updated! */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
ret = get_object_by_name ( mem_ctx , & obj , domname ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( NT_STATUS_IS_ERR ( ret ) ) {
DEBUG ( 0 , ( " tdbsam2_get_domain_sid: Error fetching database! \n " ) ) ;
0001-01-01 02:30:17 +02:30
goto done ;
}
if ( obj . type ! = GUMS_OBJ_DOMAIN ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 5 , ( " tdbsam2_get_domain_sid: Requested object is not a domain! \n " ) ) ;
0001-01-01 02:30:17 +02:30
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
0001-01-01 02:30:17 +02:30
sid_copy ( obj . data . domain - > dom_sid , sid ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
ret = store_object ( mem_ctx , & obj , False ) ;
0001-01-01 02:30:17 +02:30
done :
0001-01-01 02:30:17 +02:30
/* TODO: unlock here */
0001-01-01 02:30:17 +02:30
if ( mem_ctx ) talloc_destroy ( mem_ctx ) ;
return ret ;
}
0001-01-01 02:30:17 +02:30
/* TODO */
0001-01-01 02:30:17 +02:30
NTSTATUS ( * get_sequence_number ) ( void ) ;
0001-01-01 02:30:17 +02:30
extern DOM_SID global_sid_NULL ;
static NTSTATUS tdbsam2_new_object ( DOM_SID * sid , const char * name , const int obj_type )
{
0001-01-01 02:30:17 +02:30
NTSTATUS ret ;
struct tdbsam2_object obj ;
TALLOC_CTX * mem_ctx ;
0001-01-01 02:30:17 +02:30
NTTIME zero_time = { 0 , 0 } ;
const char * defpw = " NOPASSWORDXXXXXX " ;
uint8 defhours [ 21 ] = { 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 } ;
0001-01-01 02:30:17 +02:30
if ( ! sid | | ! name ) {
DEBUG ( 0 , ( " tdbsam2_new_object: no NULL pointers are accepted here! \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
mem_ctx = talloc_init ( " tdbsam2_new_object " ) ;
if ( ! mem_ctx ) {
DEBUG ( 0 , ( " tdbsam2_new_object: Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
0001-01-01 02:30:17 +02:30
obj . type = obj_type ;
obj . version = TDBSAM_VERSION ;
0001-01-01 02:30:17 +02:30
switch ( obj_type ) {
case GUMS_OBJ_NORMAL_USER :
obj . data . user = ( struct tdbsam2_user_data * ) talloc_zero ( mem_ctx , sizeof ( struct tdbsam2_user_data ) ) ;
TALLOC_CHECK ( obj . data . user , ret , done ) ;
0001-01-01 02:30:17 +02:30
get_next_sid ( mem_ctx , & ( obj . data . user - > user_sid ) ) ;
0001-01-01 02:30:17 +02:30
TALLOC_CHECK ( obj . data . user - > user_sid , ret , done ) ;
0001-01-01 02:30:17 +02:30
sid_copy ( sid , obj . data . user - > user_sid ) ;
0001-01-01 02:30:17 +02:30
obj . data . user - > name = talloc_strdup ( mem_ctx , name ) ;
TALLOC_CHECK ( obj . data . user , ret , done ) ;
0001-01-01 02:30:17 +02:30
obj . data . user - > xcounter = 1 ;
/*obj.data.user->sec_desc*/
obj . data . user - > description = " " ;
obj . data . user - > group_sid = & global_sid_NULL ;
obj . data . user - > logon_time = & zero_time ;
obj . data . user - > logoff_time = & zero_time ;
obj . data . user - > kickoff_time = & zero_time ;
obj . data . user - > pass_last_set_time = & zero_time ;
obj . data . user - > pass_can_change_time = & zero_time ;
obj . data . user - > pass_must_change_time = & zero_time ;
obj . data . user - > full_name = " " ;
obj . data . user - > home_dir = " " ;
obj . data . user - > dir_drive = " " ;
obj . data . user - > logon_script = " " ;
obj . data . user - > profile_path = " " ;
obj . data . user - > workstations = " " ;
obj . data . user - > unknown_str = " " ;
obj . data . user - > munged_dial = " " ;
obj . data . user - > lm_pw_ptr = defpw ;
obj . data . user - > nt_pw_ptr = defpw ;
obj . data . user - > logon_divs = 168 ;
obj . data . user - > hours_len = 21 ;
obj . data . user - > hours = & defhours ;
obj . data . user - > unknown_3 = 0x00ffffff ;
obj . data . user - > unknown_5 = 0x00020000 ;
obj . data . user - > unknown_6 = 0x000004ec ;
0001-01-01 02:30:17 +02:30
break ;
case GUMS_OBJ_GROUP :
case GUMS_OBJ_ALIAS :
obj . data . group = ( struct tdbsam2_group_data * ) talloc_zero ( mem_ctx , sizeof ( struct tdbsam2_group_data ) ) ;
TALLOC_CHECK ( obj . data . group , ret , done ) ;
0001-01-01 02:30:17 +02:30
get_next_sid ( mem_ctx , & ( obj . data . group - > group_sid ) ) ;
0001-01-01 02:30:17 +02:30
TALLOC_CHECK ( obj . data . group - > group_sid , ret , done ) ;
0001-01-01 02:30:17 +02:30
sid_copy ( sid , obj . data . group - > group_sid ) ;
0001-01-01 02:30:17 +02:30
obj . data . group - > name = talloc_strdup ( mem_ctx , name ) ;
TALLOC_CHECK ( obj . data . group , ret , done ) ;
0001-01-01 02:30:17 +02:30
obj . data . group - > xcounter = 1 ;
/*obj.data.group->sec_desc*/
obj . data . group - > description = " " ;
0001-01-01 02:30:17 +02:30
break ;
case GUMS_OBJ_DOMAIN :
0001-01-01 02:30:17 +02:30
/* FIXME: should we check against global_sam_sid to make it impossible
to store more than one domain ? */
obj . data . domain = ( struct tdbsam2_domain_data * ) talloc_zero ( mem_ctx , sizeof ( struct tdbsam2_domain_data ) ) ;
TALLOC_CHECK ( obj . data . domain , ret , done ) ;
obj . data . domain - > dom_sid = sid_dup_talloc ( mem_ctx , get_global_sam_sid ( ) ) ;
TALLOC_CHECK ( obj . data . domain - > dom_sid , ret , done ) ;
sid_copy ( sid , obj . data . domain - > dom_sid ) ;
obj . data . domain - > name = talloc_strdup ( mem_ctx , name ) ;
TALLOC_CHECK ( obj . data . domain , ret , done ) ;
obj . data . domain - > xcounter = 1 ;
/*obj.data.domain->sec_desc*/
obj . data . domain - > next_rid = 0x3e9 ;
obj . data . domain - > description = " " ;
ret = NT_STATUS_OK ;
break ;
0001-01-01 02:30:17 +02:30
default :
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
0001-01-01 02:30:17 +02:30
ret = store_object ( mem_ctx , & obj , True ) ;
0001-01-01 02:30:17 +02:30
done :
talloc_destroy ( mem_ctx ) ;
return ret ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
static NTSTATUS tdbsam2_delete_object ( const DOM_SID * sid )
{
0001-01-01 02:30:17 +02:30
NTSTATUS ret ;
struct tdbsam2_object obj ;
TALLOC_CTX * mem_ctx ;
TDB_DATA data , key ;
fstring keystr ;
if ( ! sid ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " tdbsam2_delete_object: no NULL pointers are accepted here! \n " ) ) ;
0001-01-01 02:30:17 +02:30
return NT_STATUS_INVALID_PARAMETER ;
}
mem_ctx = talloc_init ( " tdbsam2_delete_object " ) ;
if ( ! mem_ctx ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " tdbsam2_delete_object: Out of memory! \n " ) ) ;
0001-01-01 02:30:17 +02:30
return NT_STATUS_NO_MEMORY ;
}
if ( tdbsam2_db = = NULL ) {
0001-01-01 02:30:17 +02:30
if ( NT_STATUS_IS_ERR ( ret = opentdb ( ) ) ) {
0001-01-01 02:30:17 +02:30
goto done ;
}
}
0001-01-01 02:30:17 +02:30
slprintf ( keystr , sizeof ( keystr ) - 1 , " %s%s " , SIDPREFIX , sid_string_static ( sid ) ) ;
0001-01-01 02:30:17 +02:30
key . dptr = keystr ;
key . dsize = strlen ( keystr ) + 1 ;
data = tdb_fetch ( tdbsam2_db , key ) ;
if ( ! data . dptr ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 5 , ( " tdbsam2_delete_object: Error fetching database, SID entry not found! \n " ) ) ;
0001-01-01 02:30:17 +02:30
DEBUGADD ( 5 , ( " Error: %s \n " , tdb_errorstr ( tdbsam2_db ) ) ) ;
DEBUGADD ( 5 , ( " Key: %s \n " , keystr ) ) ;
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( tdb_delete ( tdbsam2_db , key ) ! = TDB_SUCCESS ) {
DEBUG ( 5 , ( " tdbsam2_delete_object: Error deleting object! \n " ) ) ;
DEBUGADD ( 5 , ( " Error: %s \n " , tdb_errorstr ( tdbsam2_db ) ) ) ;
DEBUGADD ( 5 , ( " Key: %s \n " , keystr ) ) ;
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( NT_STATUS_IS_ERR ( init_tdbsam2_object_from_buffer ( & obj , mem_ctx , data . dptr , data . dsize ) ) ) {
SAFE_FREE ( data . dptr ) ;
DEBUG ( 0 , ( " tdbsam2_delete_object: Error fetching database, malformed entry! \n " ) ) ;
0001-01-01 02:30:17 +02:30
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
0001-01-01 02:30:17 +02:30
switch ( obj . type ) {
case GUMS_OBJ_DOMAIN :
/* TODO: SHOULD WE ALLOW TO DELETE DOMAINS ? */
slprintf ( keystr , sizeof ( keystr ) - 1 , " %s%s " , NAMEPREFIX , obj . data . domain - > name ) ;
break ;
case GUMS_OBJ_GROUP :
case GUMS_OBJ_ALIAS :
slprintf ( keystr , sizeof ( keystr ) - 1 , " %s%s " , NAMEPREFIX , obj . data . group - > name ) ;
break ;
case GUMS_OBJ_NORMAL_USER :
slprintf ( keystr , sizeof ( keystr ) - 1 , " %s%s " , NAMEPREFIX , obj . data . user - > name ) ;
break ;
default :
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
key . dptr = keystr ;
key . dsize = strlen ( keystr ) + 1 ;
0001-01-01 02:30:17 +02:30
if ( tdb_delete ( tdbsam2_db , key ) ! = TDB_SUCCESS ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 5 , ( " tdbsam2_delete_object: Error deleting object! \n " ) ) ;
0001-01-01 02:30:17 +02:30
DEBUGADD ( 5 , ( " Error: %s \n " , tdb_errorstr ( tdbsam2_db ) ) ) ;
DEBUGADD ( 5 , ( " Key: %s \n " , keystr ) ) ;
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* TODO: update the general database counter */
done :
SAFE_FREE ( data . dptr ) ;
talloc_destroy ( mem_ctx ) ;
return ret ;
}
static NTSTATUS tdbsam2_get_object_from_sid ( GUMS_OBJECT * * object , const DOM_SID * sid , const int obj_type )
{
NTSTATUS ret ;
struct tdbsam2_object obj ;
TALLOC_CTX * mem_ctx ;
if ( ! object | | ! sid ) {
DEBUG ( 0 , ( " tdbsam2_get_object_from_sid: no NULL pointers are accepted here! \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
mem_ctx = talloc_init ( " tdbsam2_get_object_from_sid " ) ;
if ( ! mem_ctx ) {
DEBUG ( 0 , ( " tdbsam2_get_object_from_sid: Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
ret = get_object_by_sid ( mem_ctx , & obj , sid ) ;
if ( NT_STATUS_IS_ERR ( ret ) | | ( obj_type & & obj . type ! = obj_type ) ) {
DEBUG ( 0 , ( " tdbsam2_get_object_from_sid: error fetching object or wrong object type! \n " ) ) ;
goto done ;
}
ret = data_to_gums_object ( object , & obj ) ;
if ( NT_STATUS_IS_ERR ( ret ) ) {
DEBUG ( 0 , ( " tdbsam2_get_object_from_sid: error setting object data! \n " ) ) ;
goto done ;
}
done :
talloc_destroy ( mem_ctx ) ;
return ret ;
}
static NTSTATUS tdbsam2_get_object_from_name ( GUMS_OBJECT * * object , const char * name , const int obj_type )
{
NTSTATUS ret ;
struct tdbsam2_object obj ;
TALLOC_CTX * mem_ctx ;
if ( ! object | | ! name ) {
DEBUG ( 0 , ( " tdbsam2_get_object_from_sid: no NULL pointers are accepted here! \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
mem_ctx = talloc_init ( " tdbsam2_get_object_from_sid " ) ;
if ( ! mem_ctx ) {
DEBUG ( 0 , ( " tdbsam2_get_object_from_sid: Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
ret = get_object_by_name ( mem_ctx , & obj , name ) ;
if ( NT_STATUS_IS_ERR ( ret ) | | ( obj_type & & obj . type ! = obj_type ) ) {
DEBUG ( 0 , ( " tdbsam2_get_object_from_sid: error fetching object or wrong object type! \n " ) ) ;
goto done ;
}
ret = data_to_gums_object ( object , & obj ) ;
if ( NT_STATUS_IS_ERR ( ret ) ) {
DEBUG ( 0 , ( " tdbsam2_get_object_from_sid: error setting object data! \n " ) ) ;
goto done ;
}
done :
talloc_destroy ( mem_ctx ) ;
return ret ;
}
/* This function is used to get the list of all objects changed since base_time, it is
used to support PDC < - > BDC synchronization */
NTSTATUS ( * get_updated_objects ) ( GUMS_OBJECT * * objects , const NTTIME base_time ) ;
static NTSTATUS tdbsam2_enumerate_objects_start ( void * handle , const DOM_SID * sid , const int obj_type )
{
struct tdbsam2_enum_objs * teo , * t ;
pstring tdbfile ;
teo = ( struct tdbsam2_enum_objs * ) calloc ( 1 , sizeof ( struct tdbsam2_enum_objs ) ) ;
if ( ! teo ) {
DEBUG ( 0 , ( " tdbsam2_enumerate_objects_start: Out of Memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
teo - > type = obj_type ;
if ( sid ) {
sid_to_string ( teo - > dom_sid , sid ) ;
}
get_private_directory ( tdbfile ) ;
pstrcat ( tdbfile , " / " ) ;
pstrcat ( tdbfile , TDB_FILE_NAME ) ;
teo - > db = tdb_open_log ( tdbfile , 0 , TDB_DEFAULT , O_RDONLY , 0600 ) ;
if ( ! teo - > db )
{
DEBUG ( 0 , ( " tdbsam2_enumerate_objects_start: Unable to open database (%s)! \n " , tdbfile ) ) ;
SAFE_FREE ( teo ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
if ( ! teo_handlers ) {
* teo_handlers = teo ;
} else {
t = * teo_handlers ;
while ( t - > next ) {
t = t - > next ;
}
t - > next = teo ;
}
handle = teo ;
teo - > key = tdb_firstkey ( teo - > db ) ;
return NT_STATUS_OK ;
}
static NTSTATUS tdbsam2_enumerate_objects_get_next ( GUMS_OBJECT * * object , void * handle )
{
NTSTATUS ret ;
TALLOC_CTX * mem_ctx ;
TDB_DATA data ;
struct tdbsam2_enum_objs * teo ;
struct tdbsam2_object obj ;
const char * prefix = SIDPREFIX ;
const int preflen = strlen ( prefix ) ;
if ( ! object | | ! handle ) {
DEBUG ( 0 , ( " tdbsam2_get_object_from_sid: no NULL pointers are accepted here! \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
teo = ( struct tdbsam2_enum_objs * ) handle ;
mem_ctx = talloc_init ( " tdbsam2_enumerate_objects_get_next " ) ;
if ( ! mem_ctx ) {
DEBUG ( 0 , ( " tdbsam2_enumerate_objects_get_next: Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
while ( ( teo - > key . dsize ! = 0 ) ) {
int len , version , type , size ;
char * ptr ;
if ( strncmp ( teo - > key . dptr , prefix , preflen ) ) {
teo - > key = tdb_nextkey ( teo - > db , teo - > key ) ;
continue ;
}
if ( teo - > dom_sid ) {
if ( strncmp ( & ( teo - > key . dptr [ preflen ] ) , teo - > dom_sid , strlen ( teo - > dom_sid ) ) ) {
teo - > key = tdb_nextkey ( teo - > db , teo - > key ) ;
continue ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
data = tdb_fetch ( teo - > db , teo - > key ) ;
if ( ! data . dptr ) {
DEBUG ( 5 , ( " tdbsam2_enumerate_objects_get_next: Error fetching database, SID entry not found! \n " ) ) ;
DEBUGADD ( 5 , ( " Error: %s \n " , tdb_errorstr ( teo - > db ) ) ) ;
DEBUGADD ( 5 , ( " Key: %s \n " , teo - > key . dptr ) ) ;
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
len = tdb_unpack ( data . dptr , data . dsize , TDB_FORMAT_STRING ,
& version ,
& type ,
& size , & ptr ) ;
if ( len = = - 1 ) {
DEBUG ( 5 , ( " tdbsam2_enumerate_objects_get_next: Error unable to unpack data! \n " ) ) ;
0001-01-01 02:30:17 +02:30
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
0001-01-01 02:30:17 +02:30
}
SAFE_FREE ( ptr ) ;
if ( teo - > type & & type ! = teo - > type ) {
SAFE_FREE ( data . dptr ) ;
data . dsize = 0 ;
teo - > key = tdb_nextkey ( teo - > db , teo - > key ) ;
continue ;
}
break ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
if ( data . dsize ! = 0 ) {
if ( NT_STATUS_IS_ERR ( init_tdbsam2_object_from_buffer ( & obj , mem_ctx , data . dptr , data . dsize ) ) ) {
SAFE_FREE ( data . dptr ) ;
DEBUG ( 0 , ( " tdbsam2_enumerate_objects_get_next: Error fetching database, malformed entry! \n " ) ) ;
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
SAFE_FREE ( data . dptr ) ;
}
ret = data_to_gums_object ( object , & obj ) ;
0001-01-01 02:30:17 +02:30
done :
talloc_destroy ( mem_ctx ) ;
return ret ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
static NTSTATUS tdbsam2_enumerate_objects_stop ( void * handle )
{
struct tdbsam2_enum_objs * teo , * t , * p ;
teo = ( struct tdbsam2_enum_objs * ) handle ;
if ( * teo_handlers = = teo ) {
* teo_handlers = teo - > next ;
} else {
t = * teo_handlers ;
while ( t ! = teo ) {
p = t ;
t = t - > next ;
if ( t = = NULL ) {
DEBUG ( 0 , ( " tdbsam2_enumerate_objects_stop: Error, handle not found! \n " ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
}
p = t - > next ;
}
tdb_close ( teo - > db ) ;
SAFE_FREE ( teo ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
return NT_STATUS_OK ;
}
0001-01-01 02:30:17 +02:30
/* This function MUST be used ONLY by PDC<->BDC replication code or recovery tools.
Never use this function to update an object in the database , use set_object_values ( ) */
NTSTATUS ( * set_object ) ( const GUMS_OBJECT * object ) ;
/* set object values function */
NTSTATUS ( * set_object_values ) ( DOM_SID * sid , uint32 count , GUMS_DATA_SET * data_set ) ;
/* Group related functions */
NTSTATUS ( * add_memberss_to_group ) ( const DOM_SID * group , const DOM_SID * * members ) ;
NTSTATUS ( * delete_members_from_group ) ( const DOM_SID * group , const DOM_SID * * members ) ;
NTSTATUS ( * enumerate_group_members ) ( DOM_SID * * members , const DOM_SID * sid , const int type ) ;
NTSTATUS ( * get_sid_groups ) ( DOM_SID * * groups , const DOM_SID * sid ) ;
NTSTATUS ( * lock_sid ) ( const DOM_SID * sid ) ;
NTSTATUS ( * unlock_sid ) ( const DOM_SID * sid ) ;
/* privileges related functions */
NTSTATUS ( * add_members_to_privilege ) ( const LUID_ATTR * priv , const DOM_SID * * members ) ;
NTSTATUS ( * delete_members_from_privilege ) ( const LUID_ATTR * priv , const DOM_SID * * members ) ;
NTSTATUS ( * enumerate_privilege_members ) ( DOM_SID * * members , const LUID_ATTR * priv ) ;
NTSTATUS ( * get_sid_privileges ) ( DOM_SID * * privs , const DOM_SID * sid ) ;
/* warning!: set_privilege will overwrite a prior existing privilege if such exist */
NTSTATUS ( * set_privilege ) ( GUMS_PRIVILEGE * priv ) ;
0001-01-01 02:30:17 +02:30
int gumm_init ( GUMS_FUNCTIONS * * storage )
{
tdbsam2_db = NULL ;
teo_handlers = 0 ;
0001-01-01 02:30:17 +02:30
return 0 ;
}
0001-01-01 02:30:17 +02:30
#if 0
int main ( int argc , char * argv [ ] )
{
NTSTATUS ret ;
DOM_SID dsid ;
if ( argc < 2 ) {
printf ( " not enough arguments! \n " ) ;
exit ( 0 ) ;
}
if ( ! lp_load ( dyn_CONFIGFILE , True , False , False ) ) {
fprintf ( stderr , " Can't load %s - run testparm to debug it \n " , dyn_CONFIGFILE ) ;
exit ( 1 ) ;
}
ret = tdbsam2_new_object ( & dsid , " _domain_ " , GUMS_OBJ_DOMAIN ) ;
if ( NT_STATUS_IS_OK ( ret ) ) {
printf ( " _domain_ created, sid=%s \n " , sid_string_static ( & dsid ) ) ;
} else {
printf ( " _domain_ creation error n. 0x%08x \n " , ret . v ) ;
}
ret = tdbsam2_new_object ( & dsid , argv [ 1 ] , GUMS_OBJ_NORMAL_USER ) ;
if ( NT_STATUS_IS_OK ( ret ) ) {
printf ( " %s user created, sid=%s \n " , argv [ 1 ] , sid_string_static ( & dsid ) ) ;
} else {
printf ( " %s user creation error n. 0x%08x \n " , argv [ 1 ] , ret . v ) ;
}
exit ( 0 ) ;
}
# endif