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-11-02 05:57:18 +03:00
# include "librpc/gen_ndr/ndr_netlogon.h"
2004-11-16 12:00:52 +03:00
# include "lib/ldb/include/ldb.h"
2005-01-12 05:40:25 +03:00
# include "system/time.h"
2005-02-10 08:09:35 +03:00
# include "system/filesys.h"
2005-02-10 10:22:25 +03:00
# include "db_wrap.h"
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
*/
2005-02-27 14:35:47 +03:00
struct ldb_context * samdb_connect ( TALLOC_CTX * mem_ctx )
2004-05-03 18:58:08 +04:00
{
2004-10-16 17:47:00 +04:00
return ldb_wrap_connect ( mem_ctx , lp_sam_url ( ) , 0 , NULL ) ;
2004-05-06 16:42:42 +04:00
}
2004-05-06 13:55:05 +04:00
2004-05-03 18:58:08 +04:00
/*
2004-06-27 15:06:10 +04:00
search the sam for the specified attributes - varargs variant
2004-05-03 18:58:08 +04:00
*/
2005-02-27 14:35:47 +03:00
int samdb_search ( struct ldb_context * sam_ldb ,
2004-05-06 16:42:42 +04:00
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-26 12:02:20 +04:00
const char * format , . . . ) _PRINTF_ATTRIBUTE ( 6 , 7 )
2004-05-03 18:58:08 +04:00
{
va_list ap ;
int count ;
va_start ( ap , format ) ;
2005-02-27 14:35:47 +03:00
count = gendb_search_v ( sam_ldb , 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
2004-12-30 20:01:49 +03:00
/*
search the sam for the specified attributes in a specific domain , filter on
objectSid being in domain_sid .
*/
2005-02-27 14:35:47 +03:00
int samdb_search_domain ( struct ldb_context * sam_ldb ,
2004-12-30 20:01:49 +03:00
TALLOC_CTX * mem_ctx ,
const char * basedn ,
struct ldb_message * * * res ,
const char * const * attrs ,
const struct dom_sid * domain_sid ,
const char * format , . . . ) _PRINTF_ATTRIBUTE ( 7 , 8 )
{
va_list ap ;
int i , count ;
va_start ( ap , format ) ;
2005-02-27 14:35:47 +03:00
count = gendb_search_v ( sam_ldb , mem_ctx , basedn , res , attrs ,
2004-12-30 20:01:49 +03:00
format , ap ) ;
va_end ( ap ) ;
i = 0 ;
while ( i < count ) {
struct dom_sid * entry_sid ;
entry_sid = samdb_result_dom_sid ( mem_ctx , ( * res ) [ i ] ,
" objectSid " ) ;
if ( ( entry_sid = = NULL ) | |
( ! dom_sid_in_domain ( domain_sid , entry_sid ) ) ) {
/* Delete that entry from the result set */
( * res ) [ i ] = ( * res ) [ count - 1 ] ;
count - = 1 ;
continue ;
}
i + = 1 ;
}
return count ;
}
2004-05-04 11:53:06 +04:00
/*
free up a search result
*/
2005-02-27 14:35:47 +03:00
int samdb_search_free ( struct ldb_context * sam_ldb ,
2004-05-06 16:42:42 +04:00
TALLOC_CTX * mem_ctx , struct ldb_message * * res )
2004-05-04 11:53:06 +04:00
{
2005-02-27 14:35:47 +03:00
return ldb_search_free ( sam_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
*/
2005-02-27 14:35:47 +03:00
const char * samdb_search_string_v ( struct ldb_context * sam_ldb ,
2004-05-08 04:02:31 +04:00
TALLOC_CTX * mem_ctx ,
const char * basedn ,
const char * attr_name ,
2004-08-25 11:15:21 +04:00
const char * format , va_list ap ) _PRINTF_ATTRIBUTE ( 5 , 0 )
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 ;
2005-02-27 14:35:47 +03:00
count = gendb_search_v ( sam_ldb , mem_ctx , basedn , & res , attrs , format , ap ) ;
2004-05-08 04:02:31 +04:00
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 ) {
2005-02-27 14:35:47 +03:00
samdb_search_free ( sam_ldb , 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
*/
2005-02-27 14:35:47 +03:00
const char * samdb_search_string ( struct ldb_context * sam_ldb ,
2004-05-08 04:02:31 +04:00
TALLOC_CTX * mem_ctx ,
const char * basedn ,
const char * attr_name ,
2004-05-26 12:02:20 +04:00
const char * format , . . . ) _PRINTF_ATTRIBUTE ( 5 , 6 )
2004-05-08 04:02:31 +04:00
{
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 ) ;
2005-02-27 14:35:47 +03:00
str = samdb_search_string_v ( sam_ldb , mem_ctx , basedn , attr_name , format , ap ) ;
2004-05-08 04:02:31 +04:00
va_end ( ap ) ;
2004-05-03 18:58:08 +04:00
return str ;
}
2004-05-27 08:13:58 +04:00
/*
return the count of the number of records in the sam matching the query
*/
2005-02-27 14:35:47 +03:00
int samdb_search_count ( struct ldb_context * sam_ldb ,
2004-05-27 08:13:58 +04:00
TALLOC_CTX * mem_ctx ,
const char * basedn ,
const char * format , . . . ) _PRINTF_ATTRIBUTE ( 4 , 5 )
{
va_list ap ;
struct ldb_message * * res ;
const char * const attrs [ ] = { NULL } ;
int ret ;
va_start ( ap , format ) ;
2005-02-27 14:35:47 +03:00
ret = gendb_search_v ( sam_ldb , mem_ctx , basedn , & res , attrs , format , ap ) ;
2004-05-27 08:13:58 +04:00
va_end ( ap ) ;
return ret ;
}
2004-05-09 16:32:25 +04:00
/*
search the sam for a single integer attribute in exactly 1 record
*/
2005-02-27 14:35:47 +03:00
uint_t samdb_search_uint ( struct ldb_context * sam_ldb ,
2004-05-09 16:32:25 +04:00
TALLOC_CTX * mem_ctx ,
uint_t default_value ,
const char * basedn ,
const char * attr_name ,
2004-05-26 12:02:20 +04:00
const char * format , . . . ) _PRINTF_ATTRIBUTE ( 6 , 7 )
2004-05-09 16:32:25 +04:00
{
va_list ap ;
int count ;
struct ldb_message * * res ;
const char * const attrs [ 2 ] = { attr_name , NULL } ;
va_start ( ap , format ) ;
2005-02-27 14:35:47 +03:00
count = gendb_search_v ( sam_ldb , mem_ctx , basedn , & res , attrs , format , ap ) ;
2004-05-09 16:32:25 +04:00
va_end ( ap ) ;
if ( count ! = 1 ) {
return default_value ;
}
return samdb_result_uint ( res [ 0 ] , attr_name , default_value ) ;
}
2004-05-25 17:57:39 +04:00
/*
search the sam for a single signed 64 bit integer attribute in exactly 1 record
*/
2005-02-27 14:35:47 +03:00
int64_t samdb_search_int64 ( struct ldb_context * sam_ldb ,
2004-05-25 17:57:39 +04:00
TALLOC_CTX * mem_ctx ,
int64_t default_value ,
const char * basedn ,
const char * attr_name ,
2004-05-26 12:02:20 +04:00
const char * format , . . . ) _PRINTF_ATTRIBUTE ( 6 , 7 )
2004-05-25 17:57:39 +04:00
{
va_list ap ;
int count ;
struct ldb_message * * res ;
const char * const attrs [ 2 ] = { attr_name , NULL } ;
va_start ( ap , format ) ;
2005-02-27 14:35:47 +03:00
count = gendb_search_v ( sam_ldb , mem_ctx , basedn , & res , attrs , format , ap ) ;
2004-05-25 17:57:39 +04:00
va_end ( ap ) ;
if ( count ! = 1 ) {
return default_value ;
}
return samdb_result_int64 ( res [ 0 ] , attr_name , default_value ) ;
}
2004-05-03 18:58:08 +04:00
/*
search the sam for multipe records each giving a single string attribute
return the number of matches , or - 1 on error
*/
2005-02-27 14:35:47 +03:00
int samdb_search_string_multiple ( struct ldb_context * sam_ldb ,
2004-05-06 16:42:42 +04:00
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 ,
2004-05-26 12:02:20 +04:00
const char * format , . . . ) _PRINTF_ATTRIBUTE ( 6 , 7 )
2004-05-03 18:58:08 +04:00
{
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 ) ;
2005-02-27 14:35:47 +03:00
count = gendb_search_v ( sam_ldb , 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 ) ) ;
2005-02-27 14:35:47 +03:00
samdb_search_free ( sam_ldb , mem_ctx , res ) ;
2004-05-03 18:58:08 +04:00
return - 1 ;
}
}
2005-01-27 10:08:20 +03:00
* strs = talloc_array ( mem_ctx , const char * , count + 1 ) ;
2004-05-03 18:58:08 +04:00
if ( ! * strs ) {
2005-02-27 14:35:47 +03:00
samdb_search_free ( sam_ldb , 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
2004-05-25 17:57:39 +04:00
/*
pull a ( signed ) int64 from a result set .
*/
int64_t samdb_result_int64 ( struct ldb_message * msg , const char * attr , int64_t default_value )
{
return ldb_msg_find_int64 ( 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 .
*/
2004-05-25 20:24:13 +04:00
uint32_t samdb_result_rid_from_sid ( TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
const char * attr , uint32_t default_value )
2004-05-08 18:42:45 +04:00
{
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-20 17:29:38 +04:00
/*
pull a dom_sid structure from a objectSid in a result set .
*/
struct dom_sid * samdb_result_dom_sid ( TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
const char * attr )
{
const char * sidstr = ldb_msg_find_string ( msg , attr , NULL ) ;
if ( ! sidstr ) return NULL ;
return dom_sid_parse_talloc ( mem_ctx , sidstr ) ;
}
2004-05-27 10:27:21 +04:00
/*
pull a guid structure from a objectGUID in a result set .
*/
struct GUID samdb_result_guid ( struct ldb_message * msg , const char * attr )
{
NTSTATUS status ;
struct GUID guid ;
const char * guidstr = ldb_msg_find_string ( msg , attr , NULL ) ;
ZERO_STRUCT ( guid ) ;
if ( ! guidstr ) return guid ;
status = GUID_from_string ( guidstr , & guid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ZERO_STRUCT ( guid ) ;
return guid ;
}
return guid ;
}
2004-05-20 17:29:38 +04:00
/*
pull a sid prefix from a objectSid in a result set .
this is used to find the domain sid for a user
*/
const char * samdb_result_sid_prefix ( TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
const char * attr )
{
struct dom_sid * sid = samdb_result_dom_sid ( mem_ctx , msg , attr ) ;
if ( ! sid | | sid - > num_auths < 1 ) return NULL ;
sid - > num_auths - - ;
return dom_sid_string ( mem_ctx , sid ) ;
}
2004-05-08 18:42:45 +04:00
/*
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
/*
2004-05-25 17:57:39 +04:00
pull a uint64_t from a result set .
2004-05-09 13:39:47 +04:00
*/
2004-05-25 17:57:39 +04:00
uint64_t samdb_result_uint64 ( struct ldb_message * msg , const char * attr , uint64_t default_value )
2004-05-09 13:39:47 +04:00
{
2004-05-25 17:57:39 +04:00
return ldb_msg_find_uint64 ( msg , attr , default_value ) ;
2004-05-09 13:39:47 +04:00
}
/*
2004-06-05 07:22:10 +04:00
construct the allow_password_change field from the PwdLastSet attribute and the
2004-05-09 13:39:47 +04:00
domain password settings
*/
2005-02-27 14:35:47 +03:00
NTTIME samdb_result_allow_password_change ( struct ldb_context * sam_ldb ,
2005-01-11 16:55:45 +03:00
TALLOC_CTX * mem_ctx ,
2004-06-05 07:22:10 +04:00
const char * domain_dn ,
struct ldb_message * msg ,
const char * attr )
2004-05-09 13:39:47 +04:00
{
2004-05-25 17:57:39 +04:00
uint64_t attr_time = samdb_result_uint64 ( msg , attr , 0 ) ;
int64_t minPwdAge ;
if ( attr_time = = 0 ) {
return 0 ;
2004-05-09 13:39:47 +04:00
}
2004-05-25 17:57:39 +04:00
2005-02-27 14:35:47 +03:00
minPwdAge = samdb_search_int64 ( sam_ldb , mem_ctx , 0 , NULL ,
2004-06-05 07:22:10 +04:00
" minPwdAge " , " dn=%s " , domain_dn ) ;
2004-05-25 17:57:39 +04:00
/* yes, this is a -= not a += as minPwdAge is stored as the negative
of the number of 100 - nano - seconds */
attr_time - = minPwdAge ;
return attr_time ;
2004-05-09 13:39:47 +04:00
}
/*
2004-06-05 07:22:10 +04:00
construct the force_password_change field from the PwdLastSet attribute and the
2004-05-09 13:39:47 +04:00
domain password settings
*/
2005-02-27 14:35:47 +03:00
NTTIME samdb_result_force_password_change ( struct ldb_context * sam_ldb ,
2005-01-11 16:55:45 +03:00
TALLOC_CTX * mem_ctx ,
2004-06-05 07:22:10 +04:00
const char * domain_dn ,
struct ldb_message * msg ,
const char * attr )
2004-05-09 13:39:47 +04:00
{
2004-05-25 17:57:39 +04:00
uint64_t attr_time = samdb_result_uint64 ( msg , attr , 0 ) ;
int64_t maxPwdAge ;
if ( attr_time = = 0 ) {
return 0 ;
2004-05-09 13:39:47 +04:00
}
2004-05-25 17:57:39 +04:00
2005-02-27 14:35:47 +03:00
maxPwdAge = samdb_search_int64 ( sam_ldb , mem_ctx , 0 , NULL , " maxPwdAge " , " dn=%s " , domain_dn ) ;
2004-05-25 17:57:39 +04:00
if ( maxPwdAge = = 0 ) {
2004-05-26 12:02:20 +04:00
return 0 ;
2004-05-25 17:57:39 +04:00
} else {
attr_time - = maxPwdAge ;
}
return attr_time ;
2004-05-09 13:39:47 +04:00
}
2004-05-10 15:23:50 +04:00
/*
2004-06-04 15:58:46 +04:00
pull a samr_Password structutre from a result set .
2004-05-10 15:23:50 +04:00
*/
2004-06-04 15:58:46 +04:00
struct samr_Password samdb_result_hash ( struct ldb_message * msg , const char * attr )
2004-05-10 15:23:50 +04:00
{
2004-06-04 15:58:46 +04:00
struct samr_Password hash ;
2004-05-10 15:23:50 +04:00
const struct ldb_val * val = ldb_msg_find_ldb_val ( msg , attr ) ;
ZERO_STRUCT ( hash ) ;
if ( val ) {
2004-09-11 19:04:40 +04:00
memcpy ( hash . hash , val - > data , MIN ( val - > length , sizeof ( hash . hash ) ) ) ;
2004-05-10 15:23:50 +04:00
}
return hash ;
}
/*
2004-06-04 15:58:46 +04:00
pull an array of samr_Password structutres from a result set .
2004-05-10 15:23:50 +04:00
*/
uint_t samdb_result_hashes ( TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
2004-06-04 15:58:46 +04:00
const char * attr , struct samr_Password * * hashes )
2004-05-10 15:23:50 +04:00
{
uint_t count = 0 ;
const struct ldb_val * val = ldb_msg_find_ldb_val ( msg , attr ) ;
int i ;
* hashes = NULL ;
if ( ! val ) {
return 0 ;
}
count = val - > length / 16 ;
if ( count = = 0 ) {
return 0 ;
}
2005-01-27 10:08:20 +03:00
* hashes = talloc_array ( mem_ctx , struct samr_Password , count ) ;
2004-05-10 15:23:50 +04:00
if ( ! * hashes ) {
return 0 ;
}
for ( i = 0 ; i < count ; i + + ) {
memcpy ( ( * hashes ) [ i ] . hash , ( i * 16 ) + ( char * ) val - > data , 16 ) ;
}
return count ;
}
2004-05-15 11:51:38 +04:00
NTSTATUS samdb_result_passwords ( TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
2004-06-04 15:58:46 +04:00
struct samr_Password * * lm_pwd , struct samr_Password * * nt_pwd )
2004-05-15 11:51:38 +04:00
{
const char * unicodePwd = samdb_result_string ( msg , " unicodePwd " , NULL ) ;
2004-06-04 15:58:46 +04:00
struct samr_Password * lmPwdHash , * ntPwdHash ;
2004-05-15 11:51:38 +04:00
if ( unicodePwd ) {
if ( nt_pwd ) {
2005-01-27 10:08:20 +03:00
ntPwdHash = talloc ( mem_ctx , struct samr_Password ) ;
2004-05-15 11:51:38 +04:00
if ( ! ntPwdHash ) {
return NT_STATUS_NO_MEMORY ;
}
E_md4hash ( unicodePwd , ntPwdHash - > hash ) ;
2004-06-04 15:58:46 +04:00
* nt_pwd = ntPwdHash ;
2004-05-15 11:51:38 +04:00
}
if ( lm_pwd ) {
BOOL lm_hash_ok ;
2005-01-27 10:08:20 +03:00
lmPwdHash = talloc ( mem_ctx , struct samr_Password ) ;
2004-05-15 11:51:38 +04:00
if ( ! lmPwdHash ) {
return NT_STATUS_NO_MEMORY ;
}
/* compute the new nt and lm hashes */
lm_hash_ok = E_deshash ( unicodePwd , lmPwdHash - > hash ) ;
if ( lm_hash_ok ) {
2004-06-04 15:58:46 +04:00
* lm_pwd = lmPwdHash ;
2004-05-15 11:51:38 +04:00
} else {
* lm_pwd = NULL ;
}
}
} else {
if ( nt_pwd ) {
int num_nt ;
num_nt = samdb_result_hashes ( mem_ctx , msg , " ntPwdHash " , & ntPwdHash ) ;
if ( num_nt = = 0 ) {
2004-05-25 18:21:09 +04:00
* nt_pwd = NULL ;
2004-05-15 11:51:38 +04:00
} else if ( num_nt > 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else {
2004-06-04 15:58:46 +04:00
* nt_pwd = & ntPwdHash [ 0 ] ;
2004-05-15 11:51:38 +04:00
}
}
if ( lm_pwd ) {
int num_lm ;
num_lm = samdb_result_hashes ( mem_ctx , msg , " lmPwdHash " , & lmPwdHash ) ;
if ( num_lm = = 0 ) {
* lm_pwd = NULL ;
} else if ( num_lm > 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else {
2004-06-04 15:58:46 +04:00
* lm_pwd = & lmPwdHash [ 0 ] ;
2004-05-15 11:51:38 +04:00
}
}
}
return NT_STATUS_OK ;
}
2004-05-10 15:23:50 +04:00
2004-05-09 13:39:47 +04:00
/*
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 ) ;
2005-02-10 08:09:35 +03:00
hours . bits = talloc_array ( mem_ctx , uint8_t , units_per_week ) ;
2005-01-05 18:24:20 +03:00
if ( ! hours . bits ) {
2004-05-09 13:39:47 +04:00
return hours ;
}
hours . units_per_week = units_per_week ;
2005-01-05 18:24:20 +03:00
memset ( hours . bits , 0xFF , units_per_week ) ;
2004-05-09 13:39:47 +04:00
if ( val ) {
2005-01-05 18:24:20 +03:00
memcpy ( hours . bits , val - > data , MIN ( val - > length , units_per_week ) ) ;
2004-05-09 13:39:47 +04:00
}
return hours ;
}
/*
pull a set of account_flags from a result set .
*/
2004-05-25 21:24:24 +04:00
uint16_t samdb_result_acct_flags ( struct ldb_message * msg , const char * attr )
2004-05-09 13:39:47 +04:00
{
uint_t userAccountControl = ldb_msg_find_uint ( msg , attr , 0 ) ;
2004-05-15 11:51:38 +04:00
return samdb_uf2acb ( userAccountControl ) ;
2004-05-09 13:39:47 +04:00
}
2004-05-08 04:02:31 +04:00
/*
copy from a template record to a message
*/
2005-02-27 14:35:47 +03:00
int samdb_copy_template ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx ,
2004-05-08 04:02:31 +04:00
struct ldb_message * msg , const char * expression )
{
struct ldb_message * * res , * t ;
int ret , i , j ;
/* pull the template record */
2005-02-27 14:35:47 +03:00
ret = samdb_search ( sam_ldb , mem_ctx , NULL , & res , NULL , " %s " , expression ) ;
2004-05-08 04:02:31 +04:00
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 & &
2004-05-10 16:05:54 +04:00
( strcasecmp ( ( char * ) el - > values [ j ] . data , " Template " ) = = 0 | |
strcasecmp ( ( char * ) el - > values [ j ] . data , " userTemplate " ) = = 0 | |
2004-12-23 01:19:54 +03:00
strcasecmp ( ( char * ) el - > values [ j ] . data , " groupTemplate " ) = = 0 | |
2004-12-28 01:20:17 +03:00
strcasecmp ( ( char * ) el - > values [ j ] . data , " foreignSecurityTemplate " ) = = 0 | |
2005-01-12 05:40:25 +03:00
strcasecmp ( ( char * ) el - > values [ j ] . data , " aliasTemplate " ) = = 0 | |
strcasecmp ( ( char * ) el - > values [ j ] . data , " trustedDomainTemplate " ) = = 0 | |
strcasecmp ( ( char * ) el - > values [ j ] . data , " secretTemplate " ) = = 0 ) ) {
2004-05-09 15:21:46 +04:00
continue ;
}
2005-02-27 14:35:47 +03:00
samdb_msg_add_string ( sam_ldb , mem_ctx , msg , el - > name ,
2004-05-08 04:02:31 +04:00
( char * ) el - > values [ j ] . data ) ;
}
}
return 0 ;
}
/*
allocate a new id , attempting to do it atomically
return 0 on failure , the id on success
*/
2005-02-27 14:35:47 +03:00
static NTSTATUS _samdb_allocate_next_id ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , const char * dn ,
2004-05-25 20:24:13 +04:00
const char * attr , uint32_t * id )
2004-05-08 04:02:31 +04:00
{
struct ldb_message msg ;
int ret ;
const char * str ;
struct ldb_val vals [ 2 ] ;
struct ldb_message_element els [ 2 ] ;
2005-02-27 14:35:47 +03:00
str = samdb_search_string ( sam_ldb , mem_ctx , NULL , attr , " dn=%s " , dn ) ;
2004-05-08 04:02:31 +04:00
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 ) ;
2005-02-27 14:35:47 +03:00
ret = ldb_modify ( sam_ldb , & msg ) ;
2004-05-08 04:02:31 +04:00
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
*/
2005-02-27 14:35:47 +03:00
NTSTATUS samdb_allocate_next_id ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , const char * dn , const char * attr ,
2004-05-25 20:24:13 +04:00
uint32_t * id )
2004-05-08 04:02:31 +04:00
{
int tries = 10 ;
NTSTATUS status ;
/* we need to try multiple times to cope with two account
creations at the same time */
while ( tries - - ) {
2005-02-27 14:35:47 +03:00
status = _samdb_allocate_next_id ( sam_ldb , mem_ctx , dn , attr , id ) ;
2004-05-08 04:02:31 +04:00
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
*/
2005-02-27 14:35:47 +03:00
int samdb_msg_add_string ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
2004-05-08 04:02:31 +04:00
const char * attr_name , const char * str )
{
char * s = talloc_strdup ( mem_ctx , str ) ;
char * a = talloc_strdup ( mem_ctx , attr_name ) ;
if ( s = = NULL | | a = = NULL ) {
return - 1 ;
}
2005-02-27 14:35:47 +03:00
return ldb_msg_add_string ( sam_ldb , msg , a , s ) ;
2004-05-08 04:02:31 +04:00
}
2004-05-10 16:05:54 +04:00
/*
add a delete element operation to a message
*/
2005-02-27 14:35:47 +03:00
int samdb_msg_add_delete ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
2004-05-10 16:05:54 +04:00
const char * attr_name )
{
char * a = talloc_strdup ( mem_ctx , attr_name ) ;
if ( a = = NULL ) {
return - 1 ;
}
2004-05-22 04:53:57 +04:00
/* we use an empty replace rather than a delete, as it allows for
samdb_replace ( ) to be used everywhere */
2005-02-27 14:35:47 +03:00
return ldb_msg_add_empty ( sam_ldb , msg , a , LDB_FLAG_MOD_REPLACE ) ;
2004-05-10 16:05:54 +04:00
}
2004-12-26 21:02:18 +03:00
/*
add a add attribute value to a message
*/
2005-02-27 14:35:47 +03:00
int samdb_msg_add_addval ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
2004-12-26 21:02:18 +03:00
const char * attr_name , const char * value )
{
struct ldb_message_element * el ;
char * a , * v ;
int ret ;
a = talloc_strdup ( mem_ctx , attr_name ) ;
if ( a = = NULL )
return - 1 ;
v = talloc_strdup ( mem_ctx , value ) ;
if ( v = = NULL )
return - 1 ;
2005-02-27 14:35:47 +03:00
ret = ldb_msg_add_string ( sam_ldb , msg , a , v ) ;
2004-12-26 21:02:18 +03:00
if ( ret ! = 0 )
return ret ;
el = ldb_msg_find_element ( msg , a ) ;
if ( el = = NULL )
return - 1 ;
el - > flags = LDB_FLAG_MOD_ADD ;
return 0 ;
}
/*
add a delete attribute value to a message
*/
2005-02-27 14:35:47 +03:00
int samdb_msg_add_delval ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
2004-12-26 21:02:18 +03:00
const char * attr_name , const char * value )
{
struct ldb_message_element * el ;
char * a , * v ;
int ret ;
a = talloc_strdup ( mem_ctx , attr_name ) ;
if ( a = = NULL )
return - 1 ;
v = talloc_strdup ( mem_ctx , value ) ;
if ( v = = NULL )
return - 1 ;
2005-02-27 14:35:47 +03:00
ret = ldb_msg_add_string ( sam_ldb , msg , a , v ) ;
2004-12-26 21:02:18 +03:00
if ( ret ! = 0 )
return ret ;
el = ldb_msg_find_element ( msg , a ) ;
if ( el = = NULL )
return - 1 ;
el - > flags = LDB_FLAG_MOD_DELETE ;
return 0 ;
}
2004-05-08 18:42:45 +04:00
/*
add a uint_t element to a message
*/
2005-02-27 14:35:47 +03:00
int samdb_msg_add_uint ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
2004-05-08 18:42:45 +04:00
const char * attr_name , uint_t v )
{
const char * s = talloc_asprintf ( mem_ctx , " %u " , v ) ;
2005-02-27 14:35:47 +03:00
return samdb_msg_add_string ( sam_ldb , mem_ctx , msg , attr_name , s ) ;
2004-05-08 18:42:45 +04:00
}
2004-05-10 15:23:50 +04:00
/*
2004-05-25 17:57:39 +04:00
add a ( signed ) int64_t element to a message
*/
2005-02-27 14:35:47 +03:00
int samdb_msg_add_int64 ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
2004-05-25 17:57:39 +04:00
const char * attr_name , int64_t v )
{
const char * s = talloc_asprintf ( mem_ctx , " %lld " , v ) ;
2005-02-27 14:35:47 +03:00
return samdb_msg_add_string ( sam_ldb , mem_ctx , msg , attr_name , s ) ;
2004-05-25 17:57:39 +04:00
}
/*
add a uint64_t element to a message
2004-05-10 15:23:50 +04:00
*/
2005-02-27 14:35:47 +03:00
int samdb_msg_add_uint64 ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
2004-05-25 17:57:39 +04:00
const char * attr_name , uint64_t v )
2004-05-10 15:23:50 +04:00
{
2004-05-25 17:57:39 +04:00
const char * s = talloc_asprintf ( mem_ctx , " %llu " , v ) ;
2005-02-27 14:35:47 +03:00
return samdb_msg_add_string ( sam_ldb , mem_ctx , msg , attr_name , s ) ;
2004-05-10 15:23:50 +04:00
}
/*
2004-06-04 15:58:46 +04:00
add a samr_Password element to a message
2004-05-10 15:23:50 +04:00
*/
2005-02-27 14:35:47 +03:00
int samdb_msg_add_hash ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
2005-01-10 20:28:36 +03:00
const char * attr_name , struct samr_Password * hash )
2004-05-10 15:23:50 +04:00
{
struct ldb_val val ;
2005-01-10 20:28:36 +03:00
val . data = talloc_memdup ( mem_ctx , hash - > hash , 16 ) ;
2004-05-10 15:23:50 +04:00
if ( ! val . data ) {
return - 1 ;
}
2005-01-06 06:06:58 +03:00
val . length = 16 ;
2005-02-27 14:35:47 +03:00
return ldb_msg_add_value ( sam_ldb , msg , attr_name , & val ) ;
2004-05-10 15:23:50 +04:00
}
/*
2004-06-04 15:58:46 +04:00
add a samr_Password array to a message
2004-05-10 15:23:50 +04:00
*/
2005-02-27 14:35:47 +03:00
int samdb_msg_add_hashes ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
2004-06-04 15:58:46 +04:00
const char * attr_name , struct samr_Password * hashes , uint_t count )
2004-05-10 15:23:50 +04:00
{
struct ldb_val val ;
int i ;
2005-01-07 07:39:16 +03:00
val . data = talloc_array_size ( mem_ctx , 16 , count ) ;
2004-05-10 15:23:50 +04:00
val . length = count * 16 ;
if ( ! val . data ) {
return - 1 ;
}
for ( i = 0 ; i < count ; i + + ) {
memcpy ( i * 16 + ( char * ) val . data , hashes [ i ] . hash , 16 ) ;
}
2005-02-27 14:35:47 +03:00
return ldb_msg_add_value ( sam_ldb , msg , attr_name , & val ) ;
2004-05-10 15:23:50 +04:00
}
2004-05-09 13:39:47 +04:00
/*
add a acct_flags element to a message
*/
2005-02-27 14:35:47 +03:00
int samdb_msg_add_acct_flags ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
2004-05-25 20:24:13 +04:00
const char * attr_name , uint32_t v )
2004-05-09 13:39:47 +04:00
{
2005-02-27 14:35:47 +03:00
return samdb_msg_add_uint ( sam_ldb , mem_ctx , msg , attr_name , samdb_acb2uf ( v ) ) ;
2004-05-09 13:39:47 +04:00
}
/*
add a logon_hours element to a message
*/
2005-02-27 14:35:47 +03:00
int samdb_msg_add_logon_hours ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
2004-11-02 05:57:18 +03:00
const char * attr_name , struct samr_LogonHours * hours )
2004-05-09 13:39:47 +04:00
{
struct ldb_val val ;
2004-11-02 05:57:18 +03:00
val . length = hours - > units_per_week / 8 ;
2005-01-05 18:24:20 +03:00
val . data = hours - > bits ;
2005-02-27 14:35:47 +03:00
return ldb_msg_add_value ( sam_ldb , msg , attr_name , & val ) ;
2004-05-09 13:39:47 +04:00
}
2005-01-11 16:55:45 +03:00
/*
add a general value element to a message
*/
2005-02-27 14:35:47 +03:00
int samdb_msg_add_value ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
2005-01-11 16:55:45 +03:00
const char * attr_name , const struct ldb_val * val )
{
2005-02-27 14:35:47 +03:00
return ldb_msg_add_value ( sam_ldb , msg , attr_name , val ) ;
2005-01-11 16:55:45 +03:00
}
2005-01-16 04:21:58 +03:00
/*
sets a general value element to a message
*/
2005-02-27 14:35:47 +03:00
int samdb_msg_set_value ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
2005-01-16 04:21:58 +03:00
const char * attr_name , const struct ldb_val * val )
{
struct ldb_message_element * el ;
el = ldb_msg_find_element ( msg , attr_name ) ;
if ( el ) {
el - > num_values = 0 ;
}
2005-02-27 14:35:47 +03:00
return ldb_msg_add_value ( sam_ldb , msg , attr_name , val ) ;
2005-01-16 04:21:58 +03:00
}
2004-05-08 04:02:31 +04:00
/*
set a string element in a message
*/
2005-02-27 14:35:47 +03:00
int samdb_msg_set_string ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
2004-05-08 04:02:31 +04:00
const char * attr_name , const char * str )
{
struct ldb_message_element * el ;
el = ldb_msg_find_element ( msg , attr_name ) ;
if ( el ) {
el - > num_values = 0 ;
}
2005-02-27 14:35:47 +03:00
return samdb_msg_add_string ( sam_ldb , mem_ctx , msg , attr_name , str ) ;
2004-05-08 04:02:31 +04:00
}
/*
set a ldaptime element in a message
*/
2005-02-27 14:35:47 +03:00
int samdb_msg_set_ldaptime ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg ,
2004-05-08 04:02:31 +04:00
const char * attr_name , time_t t )
{
char * str = ldap_timestring ( mem_ctx , t ) ;
if ( ! str ) {
return - 1 ;
}
2005-02-27 14:35:47 +03:00
return samdb_msg_set_string ( sam_ldb , mem_ctx , msg , attr_name , str ) ;
2004-05-08 04:02:31 +04:00
}
/*
add a record
*/
2005-02-27 14:35:47 +03:00
int samdb_add ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg )
2004-05-08 04:02:31 +04:00
{
2005-01-12 05:40:25 +03:00
struct GUID guid ;
const char * guidstr ;
time_t now = time ( NULL ) ;
/* a new GUID */
guid = GUID_random ( ) ;
guidstr = GUID_string ( mem_ctx , & guid ) ;
if ( ! guidstr ) {
return - 1 ;
}
2005-02-27 14:35:47 +03:00
samdb_msg_add_string ( sam_ldb , mem_ctx , msg , " objectGUID " , guidstr ) ;
samdb_msg_set_ldaptime ( sam_ldb , mem_ctx , msg , " whenCreated " , now ) ;
samdb_msg_set_ldaptime ( sam_ldb , mem_ctx , msg , " whenChanged " , now ) ;
return ldb_add ( sam_ldb , msg ) ;
2004-05-08 04:02:31 +04:00
}
/*
delete a record
*/
2005-02-27 14:35:47 +03:00
int samdb_delete ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , const char * dn )
2004-05-08 04:02:31 +04:00
{
2005-02-27 14:35:47 +03:00
return ldb_delete ( sam_ldb , dn ) ;
2004-05-08 04:02:31 +04:00
}
2004-05-08 18:42:45 +04:00
/*
modify a record
*/
2005-02-27 14:35:47 +03:00
int samdb_modify ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg )
2004-05-08 18:42:45 +04:00
{
2005-01-12 05:40:25 +03:00
time_t now = time ( NULL ) ;
2005-02-27 14:35:47 +03:00
samdb_msg_set_ldaptime ( sam_ldb , mem_ctx , msg , " whenChanged " , now ) ;
return ldb_modify ( sam_ldb , msg ) ;
2004-05-08 18:42:45 +04:00
}
2004-05-10 15:23:50 +04:00
2004-05-22 04:53:57 +04:00
/*
replace elements in a record
*/
2005-02-27 14:35:47 +03:00
int samdb_replace ( struct ldb_context * sam_ldb , TALLOC_CTX * mem_ctx , struct ldb_message * msg )
2004-05-22 04:53:57 +04:00
{
int i ;
/* mark all the message elements as LDB_FLAG_MOD_REPLACE */
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
msg - > elements [ i ] . flags = LDB_FLAG_MOD_REPLACE ;
}
/* modify the samdb record */
2005-02-27 14:35:47 +03:00
return samdb_modify ( sam_ldb , mem_ctx , msg ) ;
2004-05-22 04:53:57 +04:00
}
2004-05-28 17:23:30 +04:00
/*
return a default security descriptor
*/
struct security_descriptor * samdb_default_security_descriptor ( TALLOC_CTX * mem_ctx )
{
struct security_descriptor * sd ;
2004-11-17 17:35:29 +03:00
sd = security_descriptor_initialise ( mem_ctx ) ;
2004-05-28 17:23:30 +04:00
return sd ;
}