2000-05-09 15:43:00 +04:00
/*
Unix SMB / Netbios implementation .
2001-12-10 02:59:42 +03:00
Winbind cache backend functions
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
Copyright ( C ) Andrew Tridgell 2001
2000-05-09 15:43:00 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 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 "winbindd.h"
2001-12-10 02:59:42 +03:00
struct winbind_cache {
struct winbindd_methods * backend ;
TDB_CONTEXT * tdb ;
2000-05-09 15:43:00 +04:00
} ;
2001-12-10 02:59:42 +03:00
struct cache_entry {
NTSTATUS status ;
uint32 sequence_number ;
uint8 * data ;
uint32 len , ofs ;
} ;
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
static struct winbind_cache * wcache ;
2001-10-14 12:26:45 +04:00
2001-12-10 03:39:01 +03:00
/* flush the cache */
2001-12-10 02:59:42 +03:00
void wcache_flush_cache ( void )
2000-05-09 15:43:00 +04:00
{
2001-12-10 02:59:42 +03:00
extern BOOL opt_nocache ;
2001-10-14 12:26:45 +04:00
2001-12-10 02:59:42 +03:00
if ( ! wcache ) return ;
if ( wcache - > tdb ) {
tdb_close ( wcache - > tdb ) ;
wcache - > tdb = NULL ;
2000-05-09 15:43:00 +04:00
}
2001-12-10 02:59:42 +03:00
if ( opt_nocache ) return ;
2000-05-09 15:43:00 +04:00
2001-12-10 08:20:55 +03:00
wcache - > tdb = tdb_open_log ( lock_path ( " winbindd_cache.tdb " ) , 5000 ,
2001-12-10 02:59:42 +03:00
TDB_NOLOCK , O_RDWR | O_CREAT | O_TRUNC , 0600 ) ;
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
if ( ! wcache - > tdb ) {
DEBUG ( 0 , ( " Failed to open winbindd_cache.tdb! \n " ) ) ;
}
2000-05-09 15:43:00 +04:00
}
2001-12-10 02:59:42 +03:00
/* get the winbind_cache structure */
static struct winbind_cache * get_cache ( struct winbindd_domain * domain )
2000-05-09 15:43:00 +04:00
{
2001-12-10 02:59:42 +03:00
extern struct winbindd_methods msrpc_methods ;
struct winbind_cache * ret = wcache ;
if ( ret ) return ret ;
ret = smb_xmalloc ( sizeof ( * ret ) ) ;
ZERO_STRUCTP ( ret ) ;
switch ( lp_security ( ) ) {
# ifdef HAVE_ADS
case SEC_ADS : {
extern struct winbindd_methods ads_methods ;
ret - > backend = & ads_methods ;
break ;
2000-05-09 15:43:00 +04:00
}
2001-12-10 02:59:42 +03:00
# endif
default :
ret - > backend = & msrpc_methods ;
}
wcache = ret ;
wcache_flush_cache ( ) ;
2001-10-14 12:26:45 +04:00
2001-12-10 02:59:42 +03:00
return ret ;
2000-05-09 15:43:00 +04:00
}
2001-12-10 02:59:42 +03:00
/*
free a centry structure
*/
static void centry_free ( struct cache_entry * centry )
2000-05-09 15:43:00 +04:00
{
2001-12-10 02:59:42 +03:00
if ( ! centry ) return ;
SAFE_FREE ( centry - > data ) ;
free ( centry ) ;
}
2001-05-07 08:32:40 +04:00
2001-12-10 02:59:42 +03:00
/*
pull a uint32 from a cache entry
*/
static uint32 centry_uint32 ( struct cache_entry * centry )
{
uint32 ret ;
if ( centry - > len - centry - > ofs < 4 ) {
DEBUG ( 0 , ( " centry corruption? needed 4 bytes, have %d \n " ,
centry - > len - centry - > ofs ) ) ;
smb_panic ( " centry_uint32 " ) ;
}
ret = IVAL ( centry - > data , centry - > ofs ) ;
centry - > ofs + = 4 ;
return ret ;
2000-05-09 15:43:00 +04:00
}
2001-12-10 08:20:55 +03:00
/*
pull a uint8 from a cache entry
*/
static uint8 centry_uint8 ( struct cache_entry * centry )
{
uint8 ret ;
if ( centry - > len - centry - > ofs < 1 ) {
DEBUG ( 0 , ( " centry corruption? needed 1 bytes, have %d \n " ,
centry - > len - centry - > ofs ) ) ;
smb_panic ( " centry_uint32 " ) ;
}
ret = CVAL ( centry - > data , centry - > ofs ) ;
centry - > ofs + = 1 ;
return ret ;
}
2001-12-10 02:59:42 +03:00
/* pull a string from a cache entry, using the supplied
talloc context
*/
static char * centry_string ( struct cache_entry * centry , TALLOC_CTX * mem_ctx )
2000-05-09 15:43:00 +04:00
{
2001-12-10 02:59:42 +03:00
uint32 len ;
char * ret ;
2001-12-10 08:20:55 +03:00
len = centry_uint8 ( centry ) ;
2001-12-10 03:07:51 +03:00
2001-12-10 08:20:55 +03:00
if ( len = = 0xFF ) {
2001-12-10 03:07:51 +03:00
/* a deliberate NULL string */
return NULL ;
}
2001-12-10 02:59:42 +03:00
if ( centry - > len - centry - > ofs < len ) {
DEBUG ( 0 , ( " centry corruption? needed %d bytes, have %d \n " ,
len , centry - > len - centry - > ofs ) ) ;
smb_panic ( " centry_string " ) ;
}
2001-05-07 08:32:40 +04:00
2001-12-10 02:59:42 +03:00
ret = talloc ( mem_ctx , len + 1 ) ;
if ( ! ret ) {
smb_panic ( " centry_string out of memory \n " ) ;
}
memcpy ( ret , centry - > data + centry - > ofs , len ) ;
ret [ len ] = 0 ;
centry - > ofs + = len ;
return ret ;
2000-05-09 15:43:00 +04:00
}
2001-12-10 02:59:42 +03:00
/* the server is considered down if it can't give us a sequence number */
static BOOL wcache_server_down ( struct winbindd_domain * domain )
2000-05-09 15:43:00 +04:00
{
2001-12-10 02:59:42 +03:00
if ( ! wcache - > tdb ) return False ;
return ( domain - > sequence_number = = DOM_SEQUENCE_NONE ) ;
}
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
/*
refresh the domain sequence number . If force is True
then always refresh it , no matter how recently we fetched it
*/
static void refresh_sequence_number ( struct winbindd_domain * domain , BOOL force )
{
NTSTATUS status ;
2001-10-14 12:26:45 +04:00
2001-12-10 02:59:42 +03:00
/* see if we have to refetch the domain sequence number */
if ( ! force & & ( time ( NULL ) - domain - > last_seq_check < lp_winbind_cache_time ( ) ) ) {
2001-11-21 11:36:43 +03:00
return ;
2001-12-10 02:59:42 +03:00
}
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
status = wcache - > backend - > sequence_number ( domain , & domain - > sequence_number ) ;
2001-05-07 08:32:40 +04:00
2001-12-10 02:59:42 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
domain - > sequence_number = DOM_SEQUENCE_NONE ;
}
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
domain - > last_seq_check = time ( NULL ) ;
2000-05-09 15:43:00 +04:00
}
2001-12-10 02:59:42 +03:00
/*
decide if a cache entry has expired
*/
static BOOL centry_expired ( struct winbindd_domain * domain , struct cache_entry * centry )
2000-05-09 15:43:00 +04:00
{
2001-12-10 02:59:42 +03:00
/* if the server is OK and our cache entry came from when it was down then
the entry is invalid */
if ( domain - > sequence_number ! = DOM_SEQUENCE_NONE & &
centry - > sequence_number = = DOM_SEQUENCE_NONE ) {
return True ;
}
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
/* if the server is down or the cache entry is not older than the
current sequence number then it is OK */
if ( wcache_server_down ( domain ) | |
centry - > sequence_number > = domain - > sequence_number ) {
return False ;
}
2001-05-07 08:32:40 +04:00
2001-12-10 02:59:42 +03:00
/* it's expired */
return True ;
2000-05-09 15:43:00 +04:00
}
2001-12-10 02:59:42 +03:00
/*
fetch an entry from the cache , with a varargs key . auto - fetch the sequence
number and return status
*/
static struct cache_entry * wcache_fetch ( struct winbind_cache * cache ,
struct winbindd_domain * domain ,
const char * format , . . . )
2000-05-09 15:43:00 +04:00
{
2001-12-10 02:59:42 +03:00
va_list ap ;
char * kstr ;
TDB_DATA data ;
struct cache_entry * centry ;
2001-12-10 08:20:55 +03:00
TDB_DATA key ;
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
refresh_sequence_number ( domain , False ) ;
2001-10-14 12:26:45 +04:00
2001-12-10 02:59:42 +03:00
va_start ( ap , format ) ;
smb_xvasprintf ( & kstr , format , ap ) ;
va_end ( ap ) ;
2001-12-10 08:20:55 +03:00
key . dptr = kstr ;
key . dsize = strlen ( kstr ) ;
data = tdb_fetch ( wcache - > tdb , key ) ;
2001-12-10 02:59:42 +03:00
free ( kstr ) ;
if ( ! data . dptr ) {
/* a cache miss */
return NULL ;
}
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
centry = smb_xmalloc ( sizeof ( * centry ) ) ;
centry - > data = data . dptr ;
centry - > len = data . dsize ;
centry - > ofs = 0 ;
2001-11-21 11:36:43 +03:00
2001-12-10 02:59:42 +03:00
if ( centry - > len < 8 ) {
/* huh? corrupt cache? */
centry_free ( centry ) ;
return NULL ;
}
centry - > status = NT_STATUS ( centry_uint32 ( centry ) ) ;
centry - > sequence_number = centry_uint32 ( centry ) ;
2001-11-21 11:36:43 +03:00
2001-12-10 02:59:42 +03:00
if ( centry_expired ( domain , centry ) ) {
centry_free ( centry ) ;
return NULL ;
}
2001-11-21 11:36:43 +03:00
2001-12-10 02:59:42 +03:00
return centry ;
2001-11-21 11:36:43 +03:00
}
2001-12-10 02:59:42 +03:00
/*
make sure we have at least len bytes available in a centry
*/
static void centry_expand ( struct cache_entry * centry , uint32 len )
2001-11-21 11:36:43 +03:00
{
2001-12-10 02:59:42 +03:00
uint8 * p ;
if ( centry - > len - centry - > ofs > = len ) return ;
centry - > len * = 2 ;
p = realloc ( centry - > data , centry - > len ) ;
if ( ! p ) {
DEBUG ( 0 , ( " out of memory: needed %d bytes in centry_expand \n " , centry - > len ) ) ;
smb_panic ( " out of memory in centry_expand " ) ;
}
centry - > data = p ;
2001-11-21 11:36:43 +03:00
}
2001-12-10 02:59:42 +03:00
/*
push a uint32 into a centry
*/
static void centry_put_uint32 ( struct cache_entry * centry , uint32 v )
2000-05-09 15:43:00 +04:00
{
2001-12-10 02:59:42 +03:00
centry_expand ( centry , 4 ) ;
SIVAL ( centry - > data , centry - > ofs , v ) ;
centry - > ofs + = 4 ;
2000-05-09 15:43:00 +04:00
}
2001-12-10 08:20:55 +03:00
/*
push a uint8 into a centry
*/
static void centry_put_uint8 ( struct cache_entry * centry , uint8 v )
{
centry_expand ( centry , 1 ) ;
SCVAL ( centry - > data , centry - > ofs , v ) ;
centry - > ofs + = 1 ;
}
2001-12-10 02:59:42 +03:00
/*
push a string into a centry
*/
static void centry_put_string ( struct cache_entry * centry , const char * s )
2000-05-09 15:43:00 +04:00
{
2001-12-10 03:07:51 +03:00
int len ;
if ( ! s ) {
/* null strings are marked as len 0xFFFF */
2001-12-10 08:20:55 +03:00
centry_put_uint8 ( centry , 0xFF ) ;
2001-12-10 03:07:51 +03:00
return ;
}
len = strlen ( s ) ;
2001-12-10 08:20:55 +03:00
/* can't handle more than 254 char strings. Truncating is probably best */
if ( len > 254 ) len = 254 ;
centry_put_uint8 ( centry , len ) ;
2001-12-10 02:59:42 +03:00
centry_expand ( centry , len ) ;
memcpy ( centry - > data + centry - > ofs , s , len ) ;
centry - > ofs + = len ;
2000-05-09 15:43:00 +04:00
}
2001-12-10 02:59:42 +03:00
/*
start a centry for output . When finished , call centry_end ( )
*/
struct cache_entry * centry_start ( struct winbindd_domain * domain , NTSTATUS status )
2000-05-09 15:43:00 +04:00
{
2001-12-10 02:59:42 +03:00
struct cache_entry * centry ;
2001-05-07 08:32:40 +04:00
2001-12-10 02:59:42 +03:00
if ( ! wcache - > tdb ) return NULL ;
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
centry = smb_xmalloc ( sizeof ( * centry ) ) ;
2001-05-07 08:32:40 +04:00
2001-12-10 02:59:42 +03:00
centry - > len = 8192 ; /* reasonable default */
centry - > data = smb_xmalloc ( centry - > len ) ;
centry - > ofs = 0 ;
centry - > sequence_number = domain - > sequence_number ;
centry_put_uint32 ( centry , NT_STATUS_V ( status ) ) ;
centry_put_uint32 ( centry , centry - > sequence_number ) ;
return centry ;
2000-05-09 15:43:00 +04:00
}
2001-12-10 02:59:42 +03:00
/*
finish a centry and write it to the tdb
*/
static void centry_end ( struct cache_entry * centry , const char * format , . . . )
2000-05-09 15:43:00 +04:00
{
2001-12-10 02:59:42 +03:00
va_list ap ;
char * kstr ;
2001-12-10 08:20:55 +03:00
TDB_DATA key , data ;
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
va_start ( ap , format ) ;
smb_xvasprintf ( & kstr , format , ap ) ;
va_end ( ap ) ;
2001-05-07 08:32:40 +04:00
2001-12-10 08:20:55 +03:00
key . dptr = kstr ;
key . dsize = strlen ( kstr ) ;
data . dptr = centry - > data ;
data . dsize = centry - > ofs ;
tdb_store ( wcache - > tdb , key , data , TDB_REPLACE ) ;
2001-12-10 02:59:42 +03:00
free ( kstr ) ;
2000-05-09 15:43:00 +04:00
}
2001-12-10 09:05:21 +03:00
/* form a name with the domain part stuck on the front */
static char * prepend_domain ( struct winbindd_domain * domain , const char * name )
{
static fstring s ;
snprintf ( s , sizeof ( s ) , " %s%s%s " , domain - > name , lp_winbind_separator ( ) , name ) ;
return s ;
}
/* form a sid from the domain plus rid */
static DOM_SID * form_sid ( struct winbindd_domain * domain , uint32 rid )
{
static DOM_SID sid ;
sid_copy ( & sid , & domain - > sid ) ;
sid_append_rid ( & sid , rid ) ;
return & sid ;
}
static void wcache_save_name_to_sid ( struct winbindd_domain * domain , NTSTATUS status ,
const char * name , DOM_SID * sid , enum SID_NAME_USE type )
{
struct cache_entry * centry ;
uint32 len ;
centry = centry_start ( domain , status ) ;
if ( ! centry ) return ;
len = sid_size ( sid ) ;
centry_expand ( centry , len ) ;
centry_put_uint32 ( centry , type ) ;
sid_linearize ( centry - > data + centry - > ofs , len , sid ) ;
centry - > ofs + = len ;
centry_end ( centry , " NS/%s/%s " , domain - > name , name ) ;
centry_free ( centry ) ;
}
static void wcache_save_sid_to_name ( struct winbindd_domain * domain , NTSTATUS status ,
DOM_SID * sid , const char * name , enum SID_NAME_USE type , uint32 rid )
{
struct cache_entry * centry ;
centry = centry_start ( domain , status ) ;
if ( ! centry ) return ;
if ( NT_STATUS_IS_OK ( status ) ) {
centry_put_uint32 ( centry , type ) ;
centry_put_string ( centry , name ) ;
}
centry_end ( centry , " SN/%s/%d " , domain - > name , rid ) ;
centry_free ( centry ) ;
}
static void wcache_save_user ( struct winbindd_domain * domain , NTSTATUS status , WINBIND_USERINFO * info )
{
struct cache_entry * centry ;
centry = centry_start ( domain , status ) ;
if ( ! centry ) return ;
centry_put_string ( centry , info - > acct_name ) ;
centry_put_string ( centry , info - > full_name ) ;
centry_put_uint32 ( centry , info - > user_rid ) ;
centry_put_uint32 ( centry , info - > group_rid ) ;
centry_end ( centry , " U/%s/%x " , domain - > name , info - > user_rid ) ;
centry_free ( centry ) ;
}
2001-12-10 02:59:42 +03:00
/* Query display info. This is the basic user list fn */
static NTSTATUS query_user_list ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2001-12-11 03:03:58 +03:00
uint32 * num_entries ,
2001-12-10 02:59:42 +03:00
WINBIND_USERINFO * * info )
2000-05-09 15:43:00 +04:00
{
2001-12-10 02:59:42 +03:00
struct winbind_cache * cache = get_cache ( domain ) ;
struct cache_entry * centry = NULL ;
NTSTATUS status ;
int i ;
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
if ( ! cache - > tdb ) goto do_query ;
2001-10-14 12:26:45 +04:00
2001-12-11 03:03:58 +03:00
centry = wcache_fetch ( cache , domain , " UL/%s " , domain - > name ) ;
2001-12-10 02:59:42 +03:00
if ( ! centry ) goto do_query ;
2001-10-14 12:26:45 +04:00
2001-12-10 02:59:42 +03:00
* num_entries = centry_uint32 ( centry ) ;
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
if ( * num_entries = = 0 ) goto do_cached ;
( * info ) = talloc ( mem_ctx , sizeof ( * * info ) * ( * num_entries ) ) ;
if ( ! ( * info ) ) smb_panic ( " query_user_list out of memory " ) ;
for ( i = 0 ; i < ( * num_entries ) ; i + + ) {
( * info ) [ i ] . acct_name = centry_string ( centry , mem_ctx ) ;
( * info ) [ i ] . full_name = centry_string ( centry , mem_ctx ) ;
( * info ) [ i ] . user_rid = centry_uint32 ( centry ) ;
( * info ) [ i ] . group_rid = centry_uint32 ( centry ) ;
}
2001-10-14 12:26:45 +04:00
2001-12-10 02:59:42 +03:00
do_cached :
status = centry - > status ;
centry_free ( centry ) ;
return status ;
2001-10-14 12:26:45 +04:00
2001-12-10 02:59:42 +03:00
do_query :
if ( wcache_server_down ( domain ) ) {
* num_entries = 0 ;
return NT_STATUS_SERVER_DISABLED ;
}
2000-05-09 15:43:00 +04:00
2001-12-11 03:03:58 +03:00
status = cache - > backend - > query_user_list ( domain , mem_ctx , num_entries , info ) ;
2001-12-10 02:59:42 +03:00
/* and save it */
2001-12-10 09:05:21 +03:00
refresh_sequence_number ( domain , True ) ;
2001-12-10 02:59:42 +03:00
centry = centry_start ( domain , status ) ;
if ( ! centry ) goto skip_save ;
centry_put_uint32 ( centry , * num_entries ) ;
for ( i = 0 ; i < ( * num_entries ) ; i + + ) {
centry_put_string ( centry , ( * info ) [ i ] . acct_name ) ;
centry_put_string ( centry , ( * info ) [ i ] . full_name ) ;
centry_put_uint32 ( centry , ( * info ) [ i ] . user_rid ) ;
centry_put_uint32 ( centry , ( * info ) [ i ] . group_rid ) ;
2001-12-10 09:05:21 +03:00
if ( cache - > backend - > consistent ) {
/* when the backend is consistent we can pre-prime some mappings */
wcache_save_name_to_sid ( domain , NT_STATUS_OK ,
prepend_domain ( domain , ( * info ) [ i ] . acct_name ) ,
form_sid ( domain , ( * info ) [ i ] . user_rid ) ,
SID_NAME_USER ) ;
wcache_save_sid_to_name ( domain , NT_STATUS_OK ,
form_sid ( domain , ( * info ) [ i ] . user_rid ) ,
prepend_domain ( domain , ( * info ) [ i ] . acct_name ) ,
SID_NAME_USER , ( * info ) [ i ] . user_rid ) ;
wcache_save_user ( domain , NT_STATUS_OK , & ( * info ) [ i ] ) ;
}
2001-12-10 02:59:42 +03:00
}
2001-12-11 03:03:58 +03:00
centry_end ( centry , " UL/%s " , domain - > name ) ;
2001-12-10 02:59:42 +03:00
centry_free ( centry ) ;
skip_save :
return status ;
2000-05-09 15:43:00 +04:00
}
2001-12-10 02:59:42 +03:00
/* list all domain groups */
static NTSTATUS enum_dom_groups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
uint32 * start_ndx , uint32 * num_entries ,
struct acct_info * * info )
2000-05-09 15:43:00 +04:00
{
2001-12-10 02:59:42 +03:00
struct winbind_cache * cache = get_cache ( domain ) ;
struct cache_entry * centry = NULL ;
NTSTATUS status ;
int i ;
2001-05-07 08:32:40 +04:00
2001-12-10 02:59:42 +03:00
if ( ! cache - > tdb ) goto do_query ;
2000-05-09 15:43:00 +04:00
2001-12-10 08:20:55 +03:00
centry = wcache_fetch ( cache , domain , " GL/%s/%d " , domain - > name , * start_ndx ) ;
2001-12-10 02:59:42 +03:00
if ( ! centry ) goto do_query ;
2001-05-07 08:32:40 +04:00
2001-12-10 02:59:42 +03:00
* num_entries = centry_uint32 ( centry ) ;
if ( * num_entries = = 0 ) goto do_cached ;
( * info ) = talloc ( mem_ctx , sizeof ( * * info ) * ( * num_entries ) ) ;
if ( ! ( * info ) ) smb_panic ( " enum_dom_groups out of memory " ) ;
for ( i = 0 ; i < ( * num_entries ) ; i + + ) {
fstrcpy ( ( * info ) [ i ] . acct_name , centry_string ( centry , mem_ctx ) ) ;
fstrcpy ( ( * info ) [ i ] . acct_desc , centry_string ( centry , mem_ctx ) ) ;
( * info ) [ i ] . rid = centry_uint32 ( centry ) ;
}
2001-05-07 08:32:40 +04:00
2001-12-10 02:59:42 +03:00
do_cached :
status = centry - > status ;
centry_free ( centry ) ;
return status ;
2001-05-07 08:32:40 +04:00
2001-12-10 02:59:42 +03:00
do_query :
if ( wcache_server_down ( domain ) ) {
* num_entries = 0 ;
return NT_STATUS_SERVER_DISABLED ;
}
2001-05-07 08:32:40 +04:00
2001-12-10 02:59:42 +03:00
status = cache - > backend - > enum_dom_groups ( domain , mem_ctx , start_ndx , num_entries , info ) ;
/* and save it */
2001-12-10 09:05:21 +03:00
refresh_sequence_number ( domain , True ) ;
2001-12-10 02:59:42 +03:00
centry = centry_start ( domain , status ) ;
if ( ! centry ) goto skip_save ;
centry_put_uint32 ( centry , * num_entries ) ;
for ( i = 0 ; i < ( * num_entries ) ; i + + ) {
centry_put_string ( centry , ( * info ) [ i ] . acct_name ) ;
centry_put_string ( centry , ( * info ) [ i ] . acct_desc ) ;
centry_put_uint32 ( centry , ( * info ) [ i ] . rid ) ;
}
2001-12-10 08:20:55 +03:00
centry_end ( centry , " GL/%s/%d " , domain - > name , * start_ndx ) ;
2001-12-10 02:59:42 +03:00
centry_free ( centry ) ;
skip_save :
return status ;
2000-05-09 15:43:00 +04:00
}
2001-10-14 12:26:45 +04:00
2001-12-10 02:59:42 +03:00
/* convert a single name to a sid in a domain */
static NTSTATUS name_to_sid ( struct winbindd_domain * domain ,
const char * name ,
DOM_SID * sid ,
enum SID_NAME_USE * type )
2001-11-21 11:36:43 +03:00
{
2001-12-10 02:59:42 +03:00
struct winbind_cache * cache = get_cache ( domain ) ;
struct cache_entry * centry = NULL ;
NTSTATUS status ;
2001-11-21 11:36:43 +03:00
2001-12-10 02:59:42 +03:00
if ( ! cache - > tdb ) goto do_query ;
2001-11-21 11:36:43 +03:00
2001-12-10 08:20:55 +03:00
centry = wcache_fetch ( cache , domain , " NS/%s/%s " , domain - > name , name ) ;
2001-12-10 02:59:42 +03:00
if ( ! centry ) goto do_query ;
* type = centry_uint32 ( centry ) ;
sid_parse ( centry - > data + centry - > ofs , centry - > len - centry - > ofs , sid ) ;
2001-11-21 11:36:43 +03:00
2001-12-10 02:59:42 +03:00
status = centry - > status ;
centry_free ( centry ) ;
return status ;
2001-11-21 11:36:43 +03:00
2001-12-10 02:59:42 +03:00
do_query :
if ( wcache_server_down ( domain ) ) {
return NT_STATUS_SERVER_DISABLED ;
}
status = cache - > backend - > name_to_sid ( domain , name , sid , type ) ;
/* and save it */
2001-12-10 09:05:21 +03:00
wcache_save_name_to_sid ( domain , status , name , sid , * type ) ;
2001-12-10 02:59:42 +03:00
return status ;
2001-11-21 11:36:43 +03:00
}
2001-12-10 08:20:55 +03:00
/* convert a sid to a user or group name. The sid is guaranteed to be in the domain
given */
2001-12-10 02:59:42 +03:00
static NTSTATUS sid_to_name ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
DOM_SID * sid ,
char * * name ,
enum SID_NAME_USE * type )
2001-11-21 11:36:43 +03:00
{
2001-12-10 02:59:42 +03:00
struct winbind_cache * cache = get_cache ( domain ) ;
struct cache_entry * centry = NULL ;
NTSTATUS status ;
2001-12-10 08:20:55 +03:00
uint32 rid = 0 ;
2001-11-21 11:36:43 +03:00
2001-12-10 08:20:55 +03:00
sid_peek_rid ( sid , & rid ) ;
2001-11-21 11:36:43 +03:00
2001-12-10 08:20:55 +03:00
if ( ! cache - > tdb ) goto do_query ;
2001-11-21 11:36:43 +03:00
2001-12-10 08:20:55 +03:00
centry = wcache_fetch ( cache , domain , " SN/%s/%d " , domain - > name , rid ) ;
2001-12-10 02:59:42 +03:00
if ( ! centry ) goto do_query ;
if ( NT_STATUS_IS_OK ( centry - > status ) ) {
* type = centry_uint32 ( centry ) ;
* name = centry_string ( centry , mem_ctx ) ;
}
status = centry - > status ;
centry_free ( centry ) ;
return status ;
do_query :
if ( wcache_server_down ( domain ) ) {
return NT_STATUS_SERVER_DISABLED ;
}
status = cache - > backend - > sid_to_name ( domain , mem_ctx , sid , name , type ) ;
/* and save it */
2001-12-10 09:05:21 +03:00
refresh_sequence_number ( domain , True ) ;
wcache_save_sid_to_name ( domain , status , sid , * name , * type , rid ) ;
2001-11-21 11:36:43 +03:00
2001-12-10 02:59:42 +03:00
return status ;
2001-11-21 11:36:43 +03:00
}
2001-10-14 12:26:45 +04:00
2001-12-10 02:59:42 +03:00
/* Lookup user information from a rid */
static NTSTATUS query_user ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
uint32 user_rid ,
WINBIND_USERINFO * info )
2000-05-09 15:43:00 +04:00
{
2001-12-10 02:59:42 +03:00
struct winbind_cache * cache = get_cache ( domain ) ;
struct cache_entry * centry = NULL ;
NTSTATUS status ;
if ( ! cache - > tdb ) goto do_query ;
2001-12-10 08:20:55 +03:00
centry = wcache_fetch ( cache , domain , " U/%s/%x " , domain - > name , user_rid ) ;
2001-12-10 02:59:42 +03:00
if ( ! centry ) goto do_query ;
info - > acct_name = centry_string ( centry , mem_ctx ) ;
info - > full_name = centry_string ( centry , mem_ctx ) ;
info - > user_rid = centry_uint32 ( centry ) ;
info - > group_rid = centry_uint32 ( centry ) ;
status = centry - > status ;
centry_free ( centry ) ;
return status ;
do_query :
if ( wcache_server_down ( domain ) ) {
return NT_STATUS_SERVER_DISABLED ;
}
status = cache - > backend - > query_user ( domain , mem_ctx , user_rid , info ) ;
/* and save it */
2001-12-10 09:05:21 +03:00
refresh_sequence_number ( domain , True ) ;
wcache_save_user ( domain , status , info ) ;
2001-12-10 02:59:42 +03:00
return status ;
2000-05-09 15:43:00 +04:00
}
2001-10-14 12:26:45 +04:00
2001-12-10 02:59:42 +03:00
/* Lookup groups a user is a member of. */
static NTSTATUS lookup_usergroups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
uint32 user_rid ,
uint32 * num_groups , uint32 * * user_gids )
2000-05-09 15:43:00 +04:00
{
2001-12-10 02:59:42 +03:00
struct winbind_cache * cache = get_cache ( domain ) ;
struct cache_entry * centry = NULL ;
NTSTATUS status ;
int i ;
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
if ( ! cache - > tdb ) goto do_query ;
2000-05-09 15:43:00 +04:00
2001-12-10 08:20:55 +03:00
centry = wcache_fetch ( cache , domain , " UG/%s/%x " , domain - > name , user_rid ) ;
2001-12-10 02:59:42 +03:00
if ( ! centry ) goto do_query ;
2001-10-14 12:26:45 +04:00
2001-12-10 02:59:42 +03:00
* num_groups = centry_uint32 ( centry ) ;
if ( * num_groups = = 0 ) goto do_cached ;
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
( * user_gids ) = talloc ( mem_ctx , sizeof ( * * user_gids ) * ( * num_groups ) ) ;
if ( ! ( * user_gids ) ) smb_panic ( " lookup_usergroups out of memory " ) ;
for ( i = 0 ; i < ( * num_groups ) ; i + + ) {
( * user_gids ) [ i ] = centry_uint32 ( centry ) ;
}
2001-10-14 12:26:45 +04:00
2001-12-10 02:59:42 +03:00
do_cached :
status = centry - > status ;
centry_free ( centry ) ;
return status ;
do_query :
if ( wcache_server_down ( domain ) ) {
( * num_groups ) = 0 ;
return NT_STATUS_SERVER_DISABLED ;
}
status = cache - > backend - > lookup_usergroups ( domain , mem_ctx , user_rid , num_groups , user_gids ) ;
/* and save it */
2001-12-10 09:05:21 +03:00
refresh_sequence_number ( domain , True ) ;
2001-12-10 02:59:42 +03:00
centry = centry_start ( domain , status ) ;
if ( ! centry ) goto skip_save ;
centry_put_uint32 ( centry , * num_groups ) ;
for ( i = 0 ; i < ( * num_groups ) ; i + + ) {
centry_put_uint32 ( centry , ( * user_gids ) [ i ] ) ;
}
2001-12-10 08:20:55 +03:00
centry_end ( centry , " UG/%s/%x " , domain - > name , user_rid ) ;
2001-12-10 02:59:42 +03:00
centry_free ( centry ) ;
skip_save :
return status ;
2000-05-09 15:43:00 +04:00
}
2001-12-10 02:59:42 +03:00
static NTSTATUS lookup_groupmem ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
uint32 group_rid , uint32 * num_names ,
uint32 * * rid_mem , char * * * names ,
uint32 * * name_types )
2000-05-09 15:43:00 +04:00
{
2001-12-10 02:59:42 +03:00
struct winbind_cache * cache = get_cache ( domain ) ;
struct cache_entry * centry = NULL ;
NTSTATUS status ;
int i ;
2001-05-07 08:32:40 +04:00
2001-12-10 02:59:42 +03:00
if ( ! cache - > tdb ) goto do_query ;
2000-05-09 15:43:00 +04:00
2001-12-10 08:20:55 +03:00
centry = wcache_fetch ( cache , domain , " GM/%s/%x " , domain - > name , group_rid ) ;
2001-12-10 02:59:42 +03:00
if ( ! centry ) goto do_query ;
2001-10-14 12:26:45 +04:00
2001-12-10 02:59:42 +03:00
* num_names = centry_uint32 ( centry ) ;
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
if ( * num_names = = 0 ) goto do_cached ;
2001-05-07 08:32:40 +04:00
2001-12-10 02:59:42 +03:00
( * rid_mem ) = talloc ( mem_ctx , sizeof ( * * rid_mem ) * ( * num_names ) ) ;
( * names ) = talloc ( mem_ctx , sizeof ( * * names ) * ( * num_names ) ) ;
( * name_types ) = talloc ( mem_ctx , sizeof ( * * name_types ) * ( * num_names ) ) ;
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
if ( ! ( * rid_mem ) | | ! ( * names ) | | ! ( * name_types ) ) {
smb_panic ( " lookup_groupmem out of memory " ) ;
}
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
for ( i = 0 ; i < ( * num_names ) ; i + + ) {
( * rid_mem ) [ i ] = centry_uint32 ( centry ) ;
( * names ) [ i ] = centry_string ( centry , mem_ctx ) ;
( * name_types ) [ i ] = centry_uint32 ( centry ) ;
}
2001-10-14 12:26:45 +04:00
2001-12-10 02:59:42 +03:00
do_cached :
status = centry - > status ;
centry_free ( centry ) ;
return status ;
2001-10-14 12:26:45 +04:00
2001-12-10 02:59:42 +03:00
do_query :
if ( wcache_server_down ( domain ) ) {
( * num_names ) = 0 ;
return NT_STATUS_SERVER_DISABLED ;
}
status = cache - > backend - > lookup_groupmem ( domain , mem_ctx , group_rid , num_names ,
rid_mem , names , name_types ) ;
/* and save it */
2001-12-10 09:05:21 +03:00
refresh_sequence_number ( domain , True ) ;
2001-12-10 02:59:42 +03:00
centry = centry_start ( domain , status ) ;
if ( ! centry ) goto skip_save ;
centry_put_uint32 ( centry , * num_names ) ;
for ( i = 0 ; i < ( * num_names ) ; i + + ) {
centry_put_uint32 ( centry , ( * rid_mem ) [ i ] ) ;
centry_put_string ( centry , ( * names ) [ i ] ) ;
centry_put_uint32 ( centry , ( * name_types ) [ i ] ) ;
}
2001-12-10 08:20:55 +03:00
centry_end ( centry , " GM/%s/%x " , domain - > name , group_rid ) ;
2001-12-10 02:59:42 +03:00
centry_free ( centry ) ;
skip_save :
return status ;
2000-05-09 15:43:00 +04:00
}
2001-12-10 02:59:42 +03:00
/* find the sequence number for a domain */
static NTSTATUS sequence_number ( struct winbindd_domain * domain , uint32 * seq )
2000-05-09 15:43:00 +04:00
{
2001-12-10 02:59:42 +03:00
refresh_sequence_number ( domain , False ) ;
2000-05-09 15:43:00 +04:00
2001-12-10 02:59:42 +03:00
* seq = domain - > sequence_number ;
2001-10-14 12:26:45 +04:00
2001-12-10 02:59:42 +03:00
return NT_STATUS_OK ;
2000-05-09 15:43:00 +04:00
}
2001-12-10 05:25:19 +03:00
/* enumerate trusted domains */
static NTSTATUS trusted_domains ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
uint32 * num_domains ,
char * * * names ,
DOM_SID * * dom_sids )
{
struct winbind_cache * cache = get_cache ( domain ) ;
2001-12-10 05:30:18 +03:00
/* we don't cache this call */
2001-12-10 05:25:19 +03:00
return cache - > backend - > trusted_domains ( domain , mem_ctx , num_domains ,
names , dom_sids ) ;
}
/* find the domain sid */
static NTSTATUS domain_sid ( struct winbindd_domain * domain , DOM_SID * sid )
{
struct winbind_cache * cache = get_cache ( domain ) ;
2001-12-10 05:30:18 +03:00
/* we don't cache this call */
2001-12-10 05:25:19 +03:00
return cache - > backend - > domain_sid ( domain , sid ) ;
}
2001-12-10 02:59:42 +03:00
/* the ADS backend methods are exposed via this structure */
struct winbindd_methods cache_methods = {
2001-12-10 09:05:21 +03:00
True ,
2001-12-10 02:59:42 +03:00
query_user_list ,
enum_dom_groups ,
name_to_sid ,
sid_to_name ,
query_user ,
lookup_usergroups ,
lookup_groupmem ,
2001-12-10 05:25:19 +03:00
sequence_number ,
trusted_domains ,
domain_sid
2001-12-10 02:59:42 +03:00
} ;
2001-05-07 08:32:40 +04:00
2001-10-14 12:26:45 +04:00