2004-05-03 18:58:08 +04:00
/*
Unix SMB / CIFS implementation .
interface functions for the sam database
Copyright ( C ) Andrew Tridgell 2004
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"
2004-05-06 16:42:42 +04:00
struct samdb_context {
struct ldb_context * ldb ;
} ;
2004-05-03 18:58:08 +04:00
2004-05-06 13:55:05 +04:00
/*
this is used to catch debug messages from ldb
*/
void samdb_debug ( void * context , enum ldb_debug_level level , const char * fmt , va_list ap )
{
char * s = NULL ;
if ( DEBUGLEVEL < 4 & & level > LDB_DEBUG_WARNING ) {
return ;
}
vasprintf ( & s , fmt , ap ) ;
if ( ! s ) return ;
DEBUG ( level , ( " samdb: %s \n " , s ) ) ;
free ( s ) ;
}
2004-05-03 18:58:08 +04:00
/*
connect to the SAM database
2004-05-06 16:42:42 +04:00
return an opaque context pointer on success , or NULL on failure
2004-05-03 18:58:08 +04:00
*/
2004-05-06 16:42:42 +04:00
void * samdb_connect ( void )
2004-05-03 18:58:08 +04:00
{
2004-05-06 16:42:42 +04:00
struct samdb_context * ctx ;
/*
the way that unix fcntl locking works forces us to have a
static ldb handle here rather than a much more sensible
approach of having the ldb handle as part of the
samr_Connect ( ) pipe state . Otherwise we would try to open
the ldb more than once , and tdb would rightly refuse the
second open due to the broken nature of unix locking .
*/
static struct ldb_context * static_sam_db ;
if ( static_sam_db = = NULL ) {
static_sam_db = ldb_connect ( lp_sam_url ( ) , 0 , NULL ) ;
if ( static_sam_db = = NULL ) {
return NULL ;
}
2004-05-03 18:58:08 +04:00
}
2004-05-06 16:42:42 +04:00
ldb_set_debug ( static_sam_db , samdb_debug , NULL ) ;
ctx = malloc_p ( struct samdb_context ) ;
if ( ! ctx ) {
errno = ENOMEM ;
return NULL ;
2004-05-03 18:58:08 +04:00
}
2004-05-06 16:42:42 +04:00
ctx - > ldb = static_sam_db ;
return ctx ;
}
2004-05-06 13:55:05 +04:00
2004-05-06 16:42:42 +04:00
/* close a connection to the sam */
void samdb_close ( void * ctx )
{
struct samdb_context * sam_ctx = ctx ;
/* we don't actually close due to broken posix locking semantics */
sam_ctx - > ldb = NULL ;
free ( sam_ctx ) ;
2004-05-03 18:58:08 +04:00
}
2004-05-06 11:32:51 +04:00
/*
a alloc function for ldb
*/
static void * samdb_alloc ( void * context , void * ptr , size_t size )
{
return talloc_realloc ( ( TALLOC_CTX * ) context , ptr , size ) ;
}
2004-05-03 18:58:08 +04:00
/*
search the sam for the specified attributes - va_list varient
*/
2004-05-06 16:42:42 +04:00
int samdb_search_v ( void * ctx ,
TALLOC_CTX * mem_ctx ,
2004-05-08 04:02:31 +04:00
const char * basedn ,
2004-05-06 11:32:51 +04:00
struct ldb_message * * * res ,
2004-05-08 04:02:31 +04:00
const char * const * attrs ,
2004-05-03 18:58:08 +04:00
const char * format ,
va_list ap )
{
2004-05-06 16:42:42 +04:00
struct samdb_context * sam_ctx = ctx ;
2004-05-03 18:58:08 +04:00
char * expr = NULL ;
int count ;
vasprintf ( & expr , format , ap ) ;
if ( expr = = NULL ) {
return - 1 ;
}
2004-05-06 16:42:42 +04:00
ldb_set_alloc ( sam_ctx - > ldb , samdb_alloc , mem_ctx ) ;
2004-05-06 11:32:51 +04:00
2004-05-08 04:02:31 +04:00
count = ldb_search ( sam_ctx - > ldb , basedn , LDB_SCOPE_SUBTREE , expr , attrs , res ) ;
2004-05-03 18:58:08 +04:00
2004-05-09 04:42:35 +04:00
DEBUG ( 4 , ( " samdb_search_v: %s %s -> %d \n " , basedn ? basedn : " NULL " , expr , count ) ) ;
2004-05-03 18:58:08 +04:00
free ( expr ) ;
return count ;
}
/*
search the sam for the specified attributes - varargs varient
*/
2004-05-06 16:42:42 +04:00
int samdb_search ( void * ctx ,
TALLOC_CTX * mem_ctx ,
2004-05-08 04:02:31 +04:00
const char * basedn ,
2004-05-06 11:32:51 +04:00
struct ldb_message * * * res ,
2004-05-08 04:02:31 +04:00
const char * const * attrs ,
2004-05-03 18:58:08 +04:00
const char * format , . . . )
{
va_list ap ;
int count ;
va_start ( ap , format ) ;
2004-05-08 04:02:31 +04:00
count = samdb_search_v ( ctx , mem_ctx , basedn , res , attrs , format , ap ) ;
2004-05-03 18:58:08 +04:00
va_end ( ap ) ;
return count ;
}
2004-05-04 11:53:06 +04:00
/*
free up a search result
*/
2004-05-06 16:42:42 +04:00
int samdb_search_free ( void * ctx ,
TALLOC_CTX * mem_ctx , struct ldb_message * * res )
2004-05-04 11:53:06 +04:00
{
2004-05-06 16:42:42 +04:00
struct samdb_context * sam_ctx = ctx ;
ldb_set_alloc ( sam_ctx - > ldb , samdb_alloc , mem_ctx ) ;
return ldb_search_free ( sam_ctx - > ldb , res ) ;
2004-05-04 11:53:06 +04:00
}
2004-05-03 18:58:08 +04:00
/*
search the sam for a single string attribute in exactly 1 record
*/
2004-05-08 04:02:31 +04:00
const char * samdb_search_string_v ( void * ctx ,
TALLOC_CTX * mem_ctx ,
const char * basedn ,
const char * attr_name ,
const char * format , va_list ap )
2004-05-03 18:58:08 +04:00
{
int count ;
2004-05-08 04:02:31 +04:00
const char * const attrs [ 2 ] = { attr_name , NULL } ;
2004-05-03 18:58:08 +04:00
struct ldb_message * * res = NULL ;
2004-05-08 04:02:31 +04:00
count = samdb_search_v ( ctx , mem_ctx , basedn , & res , attrs , format , ap ) ;
if ( count > 1 ) {
DEBUG ( 1 , ( " samdb: search for %s %s not single valued (count=%d) \n " ,
attr_name , format , count ) ) ;
2004-05-03 18:58:08 +04:00
}
2004-05-08 04:02:31 +04:00
if ( count ! = 1 ) {
2004-05-06 16:42:42 +04:00
samdb_search_free ( ctx , mem_ctx , res ) ;
2004-05-03 18:58:08 +04:00
return NULL ;
}
2004-05-08 04:02:31 +04:00
return samdb_result_string ( res [ 0 ] , attr_name , NULL ) ;
}
/*
search the sam for a single string attribute in exactly 1 record
*/
const char * samdb_search_string ( void * ctx ,
TALLOC_CTX * mem_ctx ,
const char * basedn ,
const char * attr_name ,
const char * format , . . . )
{
va_list ap ;
const char * str ;
2004-05-03 18:58:08 +04:00
2004-05-08 04:02:31 +04:00
va_start ( ap , format ) ;
str = samdb_search_string_v ( ctx , mem_ctx , basedn , attr_name , format , ap ) ;
va_end ( ap ) ;
2004-05-03 18:58:08 +04:00
return str ;
}
/*
search the sam for multipe records each giving a single string attribute
return the number of matches , or - 1 on error
*/
2004-05-06 16:42:42 +04:00
int samdb_search_string_multiple ( void * ctx ,
TALLOC_CTX * mem_ctx ,
2004-05-08 04:02:31 +04:00
const char * basedn ,
const char * * * strs ,
2004-05-03 18:58:08 +04:00
const char * attr_name ,
const char * format , . . . )
{
va_list ap ;
int count , i ;
2004-05-08 04:02:31 +04:00
const char * const attrs [ 2 ] = { attr_name , NULL } ;
2004-05-03 18:58:08 +04:00
struct ldb_message * * res = NULL ;
va_start ( ap , format ) ;
2004-05-08 04:02:31 +04:00
count = samdb_search_v ( ctx , mem_ctx , basedn , & res , attrs , format , ap ) ;
2004-05-03 18:58:08 +04:00
va_end ( ap ) ;
if ( count < = 0 ) {
return count ;
}
/* make sure its single valued */
for ( i = 0 ; i < count ; i + + ) {
2004-05-08 04:02:31 +04:00
if ( res [ i ] - > num_elements ! = 1 ) {
2004-05-03 18:58:08 +04:00
DEBUG ( 1 , ( " samdb: search for %s %s not single valued \n " ,
attr_name , format ) ) ;
2004-05-06 16:42:42 +04:00
samdb_search_free ( ctx , mem_ctx , res ) ;
2004-05-03 18:58:08 +04:00
return - 1 ;
}
}
2004-05-08 04:02:31 +04:00
* strs = talloc_array_p ( mem_ctx , const char * , count + 1 ) ;
2004-05-03 18:58:08 +04:00
if ( ! * strs ) {
2004-05-06 16:42:42 +04:00
samdb_search_free ( ctx , mem_ctx , res ) ;
2004-05-03 18:58:08 +04:00
return - 1 ;
}
for ( i = 0 ; i < count ; i + + ) {
2004-05-08 04:02:31 +04:00
( * strs ) [ i ] = samdb_result_string ( res [ i ] , attr_name , NULL ) ;
2004-05-03 18:58:08 +04:00
}
( * strs ) [ count ] = NULL ;
return count ;
}
2004-05-04 11:53:06 +04:00
/*
pull a uint from a result set .
*/
uint_t samdb_result_uint ( struct ldb_message * msg , const char * attr , uint_t default_value )
{
return ldb_msg_find_uint ( msg , attr , default_value ) ;
}
2004-05-08 04:02:31 +04:00
/*
pull a string from a result set .
*/
2004-05-08 18:42:45 +04:00
const char * samdb_result_string ( struct ldb_message * msg , const char * attr ,
const char * default_value )
2004-05-08 04:02:31 +04:00
{
return ldb_msg_find_string ( msg , attr , default_value ) ;
}
2004-05-08 18:42:45 +04:00
/*
pull a rid from a objectSid in a result set .
*/
uint32 samdb_result_rid_from_sid ( TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
const char * attr , uint32 default_value )
{
struct dom_sid * sid ;
const char * sidstr = ldb_msg_find_string ( msg , attr , NULL ) ;
if ( ! sidstr ) return default_value ;
sid = dom_sid_parse_talloc ( mem_ctx , sidstr ) ;
if ( ! sid ) return default_value ;
return sid - > sub_auths [ sid - > num_auths - 1 ] ;
}
/*
2004-05-09 13:39:47 +04:00
pull a NTTIME in a result set .
2004-05-08 18:42:45 +04:00
*/
2004-05-09 13:39:47 +04:00
NTTIME samdb_result_nttime ( struct ldb_message * msg , const char * attr , const char * default_value )
2004-05-08 18:42:45 +04:00
{
const char * str = ldb_msg_find_string ( msg , attr , default_value ) ;
return nttime_from_string ( str ) ;
}
2004-05-09 13:39:47 +04:00
/*
pull a double ( really a large integer ) from a result set .
*/
double samdb_result_double ( struct ldb_message * msg , const char * attr , double default_value )
{
return ldb_msg_find_double ( msg , attr , default_value ) ;
}
/*
construct the allow_pwd_change field from the PwdLastSet attribute and the
domain password settings
*/
NTTIME samdb_result_allow_pwd_change ( void * ctx , TALLOC_CTX * mem_ctx ,
const char * domain_dn , struct ldb_message * msg , const char * attr )
{
double attr_time = samdb_result_double ( msg , attr , 0 ) ;
if ( attr_time > 0 ) {
const char * minPwdAge = samdb_search_string ( ctx , mem_ctx , NULL , " minPwdAge " ,
" dn=%s " , domain_dn ) ;
if ( minPwdAge ) {
/* yes, this is a -= not a += as minPwdAge is stored as the negative
of the number of 100 - nano - seconds */
attr_time - = strtod ( minPwdAge , NULL ) ;
}
}
return nttime_from_double_nt ( attr_time ) ;
}
/*
construct the force_pwd_change field from the PwdLastSet attribute and the
domain password settings
*/
NTTIME samdb_result_force_pwd_change ( void * ctx , TALLOC_CTX * mem_ctx ,
const char * domain_dn , struct ldb_message * msg , const char * attr )
{
double attr_time = samdb_result_double ( msg , attr , 0 ) ;
if ( attr_time > 0 ) {
const char * maxPwdAge = samdb_search_string ( ctx , mem_ctx , NULL , " maxPwdAge " ,
" dn=%s " , domain_dn ) ;
if ( ! maxPwdAge | | strcmp ( maxPwdAge , " 0 " ) = = 0 ) {
attr_time = 0 ;
} else {
attr_time - = strtod ( maxPwdAge , NULL ) ;
}
}
return nttime_from_double_nt ( attr_time ) ;
}
/*
pull a samr_LogonHours structutre from a result set .
*/
struct samr_LogonHours samdb_result_logon_hours ( TALLOC_CTX * mem_ctx , struct ldb_message * msg , const char * attr )
{
struct samr_LogonHours hours ;
const int units_per_week = 168 ;
const struct ldb_val * val = ldb_msg_find_ldb_val ( msg , attr ) ;
ZERO_STRUCT ( hours ) ;
hours . bitmap = talloc_array_p ( mem_ctx , uint8 , units_per_week ) ;
if ( ! hours . bitmap ) {
return hours ;
}
hours . units_per_week = units_per_week ;
memset ( hours . bitmap , 0xFF , units_per_week ) ;
if ( val ) {
memcpy ( hours . bitmap , val - > data , MIN ( val - > length , units_per_week ) ) ;
}
return hours ;
}
/* mapping between ADS userAccountControl and SAMR acct_flags */
static const struct {
uint32 uf , acb ;
} acct_flags_map [ ] = {
{ UF_ACCOUNTDISABLE , ACB_DISABLED } ,
{ UF_HOMEDIR_REQUIRED , ACB_HOMDIRREQ } ,
{ UF_PASSWD_NOTREQD , ACB_PWNOTREQ } ,
{ UF_TEMP_DUPLICATE_ACCOUNT , ACB_TEMPDUP } ,
{ UF_NORMAL_ACCOUNT , ACB_NORMAL } ,
{ UF_MNS_LOGON_ACCOUNT , ACB_MNS } ,
{ UF_INTERDOMAIN_TRUST_ACCOUNT , ACB_DOMTRUST } ,
{ UF_WORKSTATION_TRUST_ACCOUNT , ACB_WSTRUST } ,
{ UF_SERVER_TRUST_ACCOUNT , ACB_SVRTRUST } ,
{ UF_DONT_EXPIRE_PASSWD , ACB_PWNOEXP } ,
{ UF_LOCKOUT , ACB_AUTOLOCK }
} ;
/*
pull a set of account_flags from a result set .
*/
uint32 samdb_result_acct_flags ( struct ldb_message * msg , const char * attr )
{
uint_t userAccountControl = ldb_msg_find_uint ( msg , attr , 0 ) ;
uint32 i , ret = 0 ;
for ( i = 0 ; i < ARRAY_SIZE ( acct_flags_map ) ; i + + ) {
if ( acct_flags_map [ i ] . uf & userAccountControl ) {
ret | = acct_flags_map [ i ] . acb ;
}
}
return ret ;
}
2004-05-08 04:02:31 +04:00
/*
copy from a template record to a message
*/
int samdb_copy_template ( void * ctx , TALLOC_CTX * mem_ctx ,
struct ldb_message * msg , const char * expression )
{
struct ldb_message * * res , * t ;
int ret , i , j ;
/* pull the template record */
ret = samdb_search ( ctx , mem_ctx , NULL , & res , NULL , expression ) ;
if ( ret ! = 1 ) {
DEBUG ( 1 , ( " samdb: ERROR: template '%s' matched %d records \n " ,
expression , ret ) ) ;
return - 1 ;
}
t = res [ 0 ] ;
for ( i = 0 ; i < t - > num_elements ; i + + ) {
struct ldb_message_element * el = & t - > elements [ i ] ;
/* some elements should not be copied from the template */
if ( strcasecmp ( el - > name , " cn " ) = = 0 | |
strcasecmp ( el - > name , " name " ) = = 0 | |
strcasecmp ( el - > name , " sAMAccountName " ) = = 0 ) {
continue ;
}
for ( j = 0 ; j < el - > num_values ; j + + ) {
if ( strcasecmp ( el - > name , " objectClass " ) = = 0 & &
strcasecmp ( ( char * ) el - > values [ j ] . data , " userTemplate " ) = = 0 ) {
continue ;
}
samdb_msg_add_string ( ctx , mem_ctx , msg , el - > name ,
( char * ) el - > values [ j ] . data ) ;
}
}
return 0 ;
}
/*
allocate a new id , attempting to do it atomically
return 0 on failure , the id on success
*/
static NTSTATUS _samdb_allocate_next_id ( void * ctx , TALLOC_CTX * mem_ctx , const char * dn ,
const char * attr , uint32 * id )
{
struct samdb_context * sam_ctx = ctx ;
struct ldb_message msg ;
int ret ;
const char * str ;
struct ldb_val vals [ 2 ] ;
struct ldb_message_element els [ 2 ] ;
str = samdb_search_string ( ctx , mem_ctx , NULL , attr , " dn=%s " , dn ) ;
if ( ! str ) {
DEBUG ( 1 , ( " id not found at %s %s \n " , dn , attr ) ) ;
return NT_STATUS_OBJECT_NAME_INVALID ;
}
* id = strtol ( str , NULL , 0 ) ;
if ( ( * id ) + 1 = = 0 ) {
/* out of IDs ! */
return NT_STATUS_INSUFFICIENT_RESOURCES ;
}
/* we do a delete and add as a single operation. That prevents
a race */
ZERO_STRUCT ( msg ) ;
msg . dn = talloc_strdup ( mem_ctx , dn ) ;
if ( ! msg . dn ) {
return NT_STATUS_NO_MEMORY ;
}
msg . num_elements = 2 ;
msg . elements = els ;
els [ 0 ] . num_values = 1 ;
els [ 0 ] . values = & vals [ 0 ] ;
els [ 0 ] . flags = LDB_FLAG_MOD_DELETE ;
els [ 0 ] . name = talloc_strdup ( mem_ctx , attr ) ;
if ( ! els [ 0 ] . name ) {
return NT_STATUS_NO_MEMORY ;
}
els [ 1 ] . num_values = 1 ;
els [ 1 ] . values = & vals [ 1 ] ;
els [ 1 ] . flags = LDB_FLAG_MOD_ADD ;
els [ 1 ] . name = els [ 0 ] . name ;
vals [ 0 ] . data = talloc_asprintf ( mem_ctx , " %u " , * id ) ;
if ( ! vals [ 0 ] . data ) {
return NT_STATUS_NO_MEMORY ;
}
vals [ 0 ] . length = strlen ( vals [ 0 ] . data ) ;
vals [ 1 ] . data = talloc_asprintf ( mem_ctx , " %u " , ( * id ) + 1 ) ;
if ( ! vals [ 1 ] . data ) {
return NT_STATUS_NO_MEMORY ;
}
vals [ 1 ] . length = strlen ( vals [ 1 ] . data ) ;
ret = ldb_modify ( sam_ctx - > ldb , & msg ) ;
if ( ret ! = 0 ) {
return NT_STATUS_UNEXPECTED_IO_ERROR ;
}
( * id ) + + ;
return NT_STATUS_OK ;
}
/*
allocate a new id , attempting to do it atomically
return 0 on failure , the id on success
*/
NTSTATUS samdb_allocate_next_id ( void * ctx , TALLOC_CTX * mem_ctx , const char * dn , const char * attr ,
uint32 * id )
{
int tries = 10 ;
NTSTATUS status ;
/* we need to try multiple times to cope with two account
creations at the same time */
while ( tries - - ) {
status = _samdb_allocate_next_id ( ctx , mem_ctx , dn , attr , id ) ;
if ( ! NT_STATUS_EQUAL ( NT_STATUS_UNEXPECTED_IO_ERROR , status ) ) {
break ;
}
}
if ( NT_STATUS_EQUAL ( NT_STATUS_UNEXPECTED_IO_ERROR , status ) ) {
DEBUG ( 1 , ( " Failed to increment id %s at %s \n " , attr , dn ) ) ;
}
return status ;
}
/*
add a string element to a message
*/
int samdb_msg_add_string ( void * ctx , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
const char * attr_name , const char * str )
{
struct samdb_context * sam_ctx = ctx ;
char * s = talloc_strdup ( mem_ctx , str ) ;
char * a = talloc_strdup ( mem_ctx , attr_name ) ;
if ( s = = NULL | | a = = NULL ) {
return - 1 ;
}
ldb_set_alloc ( sam_ctx - > ldb , samdb_alloc , mem_ctx ) ;
return ldb_msg_add_string ( sam_ctx - > ldb , msg , a , s ) ;
}
2004-05-08 18:42:45 +04:00
/*
add a uint_t element to a message
*/
int samdb_msg_add_uint ( void * ctx , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
const char * attr_name , uint_t v )
{
const char * s = talloc_asprintf ( mem_ctx , " %u " , v ) ;
return samdb_msg_add_string ( ctx , mem_ctx , msg , attr_name , s ) ;
}
2004-05-09 13:39:47 +04:00
/*
add a acct_flags element to a message
*/
int samdb_msg_add_acct_flags ( void * ctx , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
const char * attr_name , uint32 v )
{
uint_t i , flags = 0 ;
for ( i = 0 ; i < ARRAY_SIZE ( acct_flags_map ) ; i + + ) {
if ( acct_flags_map [ i ] . acb & v ) {
flags | = acct_flags_map [ i ] . uf ;
}
}
return samdb_msg_add_uint ( ctx , mem_ctx , msg , attr_name , flags ) ;
}
/*
add a logon_hours element to a message
*/
int samdb_msg_add_logon_hours ( void * ctx , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
const char * attr_name , struct samr_LogonHours hours )
{
struct samdb_context * sam_ctx = ctx ;
struct ldb_val val ;
val . length = hours . units_per_week / 8 ;
val . data = hours . bitmap ;
ldb_set_alloc ( sam_ctx - > ldb , samdb_alloc , mem_ctx ) ;
return ldb_msg_add_value ( sam_ctx - > ldb , msg , attr_name , & val ) ;
}
2004-05-08 04:02:31 +04:00
/*
set a string element in a message
*/
int samdb_msg_set_string ( void * ctx , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
const char * attr_name , const char * str )
{
struct samdb_context * sam_ctx = ctx ;
struct ldb_message_element * el ;
ldb_set_alloc ( sam_ctx - > ldb , samdb_alloc , mem_ctx ) ;
el = ldb_msg_find_element ( msg , attr_name ) ;
if ( el ) {
el - > num_values = 0 ;
}
return samdb_msg_add_string ( ctx , mem_ctx , msg , attr_name , str ) ;
}
/*
set a ldaptime element in a message
*/
int samdb_msg_set_ldaptime ( void * ctx , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
const char * attr_name , time_t t )
{
char * str = ldap_timestring ( mem_ctx , t ) ;
if ( ! str ) {
return - 1 ;
}
return samdb_msg_set_string ( ctx , mem_ctx , msg , attr_name , str ) ;
}
/*
add a record
*/
int samdb_add ( void * ctx , TALLOC_CTX * mem_ctx , struct ldb_message * msg )
{
struct samdb_context * sam_ctx = ctx ;
ldb_set_alloc ( sam_ctx - > ldb , samdb_alloc , mem_ctx ) ;
return ldb_add ( sam_ctx - > ldb , msg ) ;
}
/*
delete a record
*/
int samdb_delete ( void * ctx , TALLOC_CTX * mem_ctx , const char * dn )
{
struct samdb_context * sam_ctx = ctx ;
ldb_set_alloc ( sam_ctx - > ldb , samdb_alloc , mem_ctx ) ;
return ldb_delete ( sam_ctx - > ldb , dn ) ;
}
2004-05-08 18:42:45 +04:00
/*
modify a record
*/
int samdb_modify ( void * ctx , TALLOC_CTX * mem_ctx , struct ldb_message * msg )
{
struct samdb_context * sam_ctx = ctx ;
ldb_set_alloc ( sam_ctx - > ldb , samdb_alloc , mem_ctx ) ;
return ldb_modify ( sam_ctx - > ldb , msg ) ;
}