2000-05-09 15:43:00 +04:00
/*
Unix SMB / Netbios implementation .
Version 2.0
Winbind daemon for ntdom nss module
Copyright ( C ) Tim Potter 2000
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-05-07 08:32:40 +04:00
# include "sids.h"
2000-05-09 15:43:00 +04:00
2001-11-21 12:59:15 +03:00
/* Globals for domain list stuff */
struct winbindd_domain * domain_list = NULL ;
/* Given a domain name, return the struct winbindd domain info for it
if it is actually working . */
struct winbindd_domain * find_domain_from_name ( char * domain_name )
{
struct winbindd_domain * tmp ;
if ( domain_list = = NULL )
get_domain_info ( ) ;
/* Search through list */
for ( tmp = domain_list ; tmp ! = NULL ; tmp = tmp - > next ) {
if ( strcmp ( domain_name , tmp - > name ) = = 0 )
return tmp ;
}
/* Not found */
return NULL ;
}
/* Given a domain name, return the struct winbindd domain info for it */
struct winbindd_domain * find_domain_from_sid ( DOM_SID * sid )
{
struct winbindd_domain * tmp ;
if ( domain_list = = NULL )
get_domain_info ( ) ;
/* Search through list */
for ( tmp = domain_list ; tmp ! = NULL ; tmp = tmp - > next ) {
if ( sid_equal ( sid , & tmp - > sid ) )
return tmp ;
}
/* Not found */
return NULL ;
}
2001-05-07 08:32:40 +04:00
/* Add a trusted domain to our list of domains */
2001-10-08 04:34:14 +04:00
static struct winbindd_domain * add_trusted_domain ( char * domain_name ,
DOM_SID * domain_sid )
2000-05-09 15:43:00 +04:00
{
2001-10-11 03:08:13 +04:00
struct winbindd_domain * domain , * tmp ;
for ( tmp = domain_list ; tmp ! = NULL ; tmp = tmp - > next ) {
if ( strcmp ( domain_name , tmp - > name ) = = 0 ) {
DEBUG ( 3 , ( " domain %s already in domain list \n " ,
domain_name ) ) ;
return tmp ;
}
}
DEBUG ( 1 , ( " adding domain %s \n " , domain_name ) ) ;
/* Create new domain entry */
if ( ( domain = ( struct winbindd_domain * )
malloc ( sizeof ( * domain ) ) ) = = NULL )
return NULL ;
2000-05-09 15:43:00 +04:00
2001-10-11 03:08:13 +04:00
/* Fill in fields */
ZERO_STRUCTP ( domain ) ;
fstrcpy ( domain - > name , domain_name ) ;
sid_copy ( & domain - > sid , domain_sid ) ;
/* Link to domain list */
DLIST_ADD ( domain_list , domain ) ;
return domain ;
2000-05-09 15:43:00 +04:00
}
/* Look up global info for the winbind daemon */
2001-05-07 08:32:40 +04:00
2001-10-08 04:34:14 +04:00
BOOL get_domain_info ( void )
2000-05-09 15:43:00 +04:00
{
2001-10-12 12:28:08 +04:00
uint32 enum_ctx = 0 , num_doms = 0 ;
2000-05-09 15:43:00 +04:00
char * * domains = NULL ;
2001-10-08 04:34:14 +04:00
DOM_SID * sids = NULL , domain_sid ;
2001-11-22 02:00:59 +03:00
NTSTATUS result ;
CLI_POLICY_HND * hnd ;
2000-05-09 15:43:00 +04:00
int i ;
2001-11-22 02:00:59 +03:00
fstring level5_dom ;
BOOL rv = False ;
TALLOC_CTX * mem_ctx ;
2000-05-09 15:43:00 +04:00
DEBUG ( 1 , ( " getting trusted domain list \n " ) ) ;
2001-11-22 02:00:59 +03:00
if ( ! ( mem_ctx = talloc_init ( ) ) )
return False ;
2001-10-12 12:28:08 +04:00
2000-05-09 15:43:00 +04:00
/* Add our workgroup - keep handle to look up trusted domains */
2001-10-08 04:34:14 +04:00
2001-11-22 02:00:59 +03:00
if ( ! ( hnd = cm_get_lsa_handle ( lp_workgroup ( ) ) ) )
goto done ;
2001-10-08 04:34:14 +04:00
2001-11-22 02:00:59 +03:00
result = cli_lsa_query_info_policy ( hnd - > cli , mem_ctx ,
& hnd - > pol , 0x05 , level5_dom , & domain_sid ) ;
2001-10-08 04:34:14 +04:00
2001-11-22 02:00:59 +03:00
if ( ! NT_STATUS_IS_OK ( result ) )
goto done ;
2001-10-08 04:34:14 +04:00
add_trusted_domain ( lp_workgroup ( ) , & domain_sid ) ;
2000-05-09 15:43:00 +04:00
/* Enumerate list of trusted domains */
2001-10-08 04:34:14 +04:00
2001-11-22 02:00:59 +03:00
if ( ! ( hnd = cm_get_lsa_handle ( lp_workgroup ( ) ) ) )
goto done ;
2001-10-08 04:34:14 +04:00
2001-11-22 02:00:59 +03:00
result = cli_lsa_enum_trust_dom ( hnd - > cli , mem_ctx ,
& hnd - > pol , & enum_ctx , & num_doms , & domains , & sids ) ;
2000-05-09 15:43:00 +04:00
2001-11-22 02:00:59 +03:00
if ( ! NT_STATUS_IS_OK ( result ) )
goto done ;
2000-05-09 15:43:00 +04:00
2001-11-22 02:00:59 +03:00
/* Add each domain to the trusted domain list */
2001-10-08 04:34:14 +04:00
for ( i = 0 ; i < num_doms ; i + + )
add_trusted_domain ( domains [ i ] , & sids [ i ] ) ;
2001-10-12 12:28:08 +04:00
2001-11-22 02:00:59 +03:00
rv = True ;
2001-10-12 12:28:08 +04:00
done :
2001-11-22 02:00:59 +03:00
talloc_destroy ( mem_ctx ) ;
return rv ;
2000-05-09 15:43:00 +04:00
}
2001-11-15 06:34:27 +03:00
/* Free global domain info */
void free_domain_info ( void )
{
struct winbindd_domain * domain ;
/* Free list of domains */
if ( domain_list ) {
struct winbindd_domain * next_domain ;
domain = domain_list ;
while ( domain ) {
next_domain = domain - > next ;
free ( domain ) ;
domain = next_domain ;
}
}
}
2000-05-09 15:43:00 +04:00
/* Connect to a domain controller using get_any_dc_name() to discover
the domain name and sid */
2001-05-07 08:32:40 +04:00
2000-05-09 15:43:00 +04:00
BOOL lookup_domain_sid ( char * domain_name , struct winbindd_domain * domain )
{
2001-10-05 04:20:06 +04:00
fstring level5_dom ;
2001-10-12 12:28:08 +04:00
uint32 enum_ctx = 0 , num_doms = 0 ;
2001-10-05 04:20:06 +04:00
char * * domains = NULL ;
DOM_SID * sids = NULL ;
CLI_POLICY_HND * hnd ;
NTSTATUS result ;
2001-10-12 12:28:08 +04:00
BOOL rv = False ;
2001-10-19 05:46:43 +04:00
TALLOC_CTX * mem_ctx ;
2001-10-05 04:20:06 +04:00
DEBUG ( 1 , ( " looking up sid for domain %s \n " , domain_name ) ) ;
2001-10-12 12:28:08 +04:00
if ( ! ( mem_ctx = talloc_init ( ) ) )
return False ;
2001-10-05 04:20:06 +04:00
if ( ! ( hnd = cm_get_lsa_handle ( domain_name ) ) )
2001-10-12 12:28:08 +04:00
goto done ;
2001-10-05 04:20:06 +04:00
/* Do a level 5 query info policy if we are looking up the SID for
our own domain . */
if ( strequal ( domain_name , lp_workgroup ( ) ) ) {
2001-10-12 12:28:08 +04:00
result = cli_lsa_query_info_policy ( hnd - > cli , mem_ctx ,
2001-10-05 04:20:06 +04:00
& hnd - > pol , 0x05 , level5_dom ,
& domain - > sid ) ;
2001-10-12 12:28:08 +04:00
rv = NT_STATUS_IS_OK ( result ) ;
goto done ;
2001-10-05 04:20:06 +04:00
}
/* Use lsaenumdomains to get sid for this domain */
2001-10-12 12:28:08 +04:00
result = cli_lsa_enum_trust_dom ( hnd - > cli , mem_ctx , & hnd - > pol ,
2001-10-05 04:20:06 +04:00
& enum_ctx , & num_doms , & domains , & sids ) ;
/* Look for domain name */
if ( NT_STATUS_IS_OK ( result ) & & domains & & sids ) {
2001-10-12 12:28:08 +04:00
BOOL found = False ;
2001-10-05 04:20:06 +04:00
int i ;
for ( i = 0 ; i < num_doms ; i + + ) {
if ( strequal ( domain_name , domains [ i ] ) ) {
sid_copy ( & domain - > sid , & sids [ i ] ) ;
found = True ;
2001-10-12 12:28:08 +04:00
break ;
2001-10-05 04:20:06 +04:00
}
}
2001-10-12 12:28:08 +04:00
rv = found ;
goto done ;
2001-10-05 04:20:06 +04:00
}
2001-10-12 12:28:08 +04:00
rv = False ; /* An error occured with a trusted domain */
done :
2001-10-19 05:46:43 +04:00
talloc_destroy ( mem_ctx ) ;
2001-10-12 12:28:08 +04:00
return rv ;
2000-05-09 15:43:00 +04:00
}
2001-11-21 12:59:15 +03:00
/* Store a SID in a domain indexed by name in the cache. */
static void store_sid_by_name_in_cache ( fstring name , DOM_SID * sid , enum SID_NAME_USE type )
{
fstring domain_str ;
char * p ;
struct winbindd_sid sid_val ;
struct winbindd_domain * domain ;
/* Get name from domain. */
fstrcpy ( domain_str , name ) ;
p = strchr ( domain_str , ' \\ ' ) ;
if ( p )
* p = ' \0 ' ;
if ( ( domain = find_domain_from_name ( domain_str ) ) = = NULL )
return ;
sid_to_string ( sid_val . sid , sid ) ;
sid_val . type = ( int ) type ;
winbindd_store_sid_cache_entry ( domain , name , & sid_val ) ;
}
/* Lookup a SID in a domain indexed by name in the cache. */
static BOOL winbindd_lookup_sid_by_name_in_cache ( fstring name , DOM_SID * sid , enum SID_NAME_USE * type )
{
fstring domain_str ;
char * p ;
struct winbindd_sid sid_ret ;
struct winbindd_domain * domain ;
/* Get name from domain. */
fstrcpy ( domain_str , name ) ;
p = strchr ( domain_str , ' \\ ' ) ;
if ( p )
* p = ' \0 ' ;
if ( ( domain = find_domain_from_name ( domain_str ) ) = = NULL )
return False ;
2001-11-22 10:32:48 +03:00
if ( ! winbindd_fetch_sid_cache_entry ( domain , name , & sid_ret ) )
2001-11-21 12:59:15 +03:00
return False ;
string_to_sid ( sid , sid_ret . sid ) ;
* type = ( enum SID_NAME_USE ) sid_ret . type ;
2001-11-22 10:32:48 +03:00
DEBUG ( 10 , ( " winbindd_lookup_sid_by_name_in_cache: Cache hit for name %s. SID = %s \n " ,
name , sid_ret . sid ) ) ;
2001-11-21 12:59:15 +03:00
return True ;
}
2000-05-09 15:43:00 +04:00
/* Lookup a sid in a domain from a name */
2001-05-07 08:32:40 +04:00
BOOL winbindd_lookup_sid_by_name ( char * name , DOM_SID * sid ,
2000-05-09 15:43:00 +04:00
enum SID_NAME_USE * type )
{
2001-11-21 12:59:15 +03:00
int num_sids = 0 , num_names = 1 ;
DOM_SID * sids = NULL ;
uint32 * types = NULL ;
CLI_POLICY_HND * hnd ;
NTSTATUS result ;
TALLOC_CTX * mem_ctx ;
BOOL rv = False ;
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
/* Don't bother with machine accounts */
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
if ( name [ strlen ( name ) - 1 ] = = ' $ ' )
return False ;
2001-10-12 12:28:08 +04:00
2001-11-21 12:59:15 +03:00
/* First check cache. */
if ( winbindd_lookup_sid_by_name_in_cache ( name , sid , type ) ) {
if ( * type = = SID_NAME_USE_NONE )
return False ; /* Negative cache hit. */
return True ;
}
/* Lookup name */
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
if ( ! ( mem_ctx = talloc_init ( ) ) )
return False ;
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
if ( ! ( hnd = cm_get_lsa_handle ( lp_workgroup ( ) ) ) )
goto done ;
2001-10-12 12:28:08 +04:00
2001-11-21 12:59:15 +03:00
result = cli_lsa_lookup_names ( hnd - > cli , mem_ctx , & hnd - > pol ,
num_names , ( char * * ) & name , & sids ,
& types , & num_sids ) ;
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
/* Return rid and type if lookup successful */
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
if ( NT_STATUS_IS_OK ( result ) ) {
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
/* Return sid */
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
if ( ( sid ! = NULL ) & & ( sids ! = NULL ) )
sid_copy ( sid , & sids [ 0 ] ) ;
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
/* Return name type */
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
if ( ( type ! = NULL ) & & ( types ! = NULL ) )
* type = types [ 0 ] ;
store_sid_by_name_in_cache ( name , & sids [ 0 ] , types [ 0 ] ) ;
}
/* JRA. Here's where we add the -ve cache store with a name type of SID_NAME_USE_NONE. */
/* We need to know the error returns that W2K gives on "no such user". */
2001-10-12 12:28:08 +04:00
2001-11-21 12:59:15 +03:00
rv = NT_STATUS_IS_OK ( result ) ;
2001-10-12 12:28:08 +04:00
done :
2001-11-21 12:59:15 +03:00
talloc_destroy ( mem_ctx ) ;
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
return rv ;
}
/* Store a name in a domain indexed by SID in the cache. */
static void store_name_by_sid_in_cache ( DOM_SID * sid , fstring name , enum SID_NAME_USE type )
{
fstring sid_str ;
uint32 rid ;
DOM_SID domain_sid ;
struct winbindd_name name_val ;
struct winbindd_domain * domain ;
/* Split sid into domain sid and user rid */
sid_copy ( & domain_sid , sid ) ;
sid_split_rid ( & domain_sid , & rid ) ;
if ( ( domain = find_domain_from_sid ( & domain_sid ) ) = = NULL )
return ;
sid_to_string ( sid_str , sid ) ;
fstrcpy ( name_val . name , name ) ;
name_val . type = ( int ) type ;
winbindd_store_name_cache_entry ( domain , sid_str , & name_val ) ;
}
/* Lookup a name in a domain indexed by SID in the cache. */
static BOOL winbindd_lookup_name_by_sid_in_cache ( DOM_SID * sid , fstring name , enum SID_NAME_USE * type )
{
fstring sid_str ;
uint32 rid ;
DOM_SID domain_sid ;
struct winbindd_name name_ret ;
struct winbindd_domain * domain ;
/* Split sid into domain sid and user rid */
sid_copy ( & domain_sid , sid ) ;
sid_split_rid ( & domain_sid , & rid ) ;
if ( ( domain = find_domain_from_sid ( & domain_sid ) ) = = NULL )
return False ;
sid_to_string ( sid_str , sid ) ;
2001-11-22 10:32:48 +03:00
if ( ! winbindd_fetch_name_cache_entry ( domain , sid_str , & name_ret ) )
2001-11-21 12:59:15 +03:00
return False ;
fstrcpy ( name , name_ret . name ) ;
* type = ( enum SID_NAME_USE ) name_ret . type ;
2001-11-22 10:32:48 +03:00
DEBUG ( 10 , ( " winbindd_lookup_name_by_sid_in_cache: Cache hit for SID = %s, name %s \n " ,
sid_str , name ) ) ;
2001-11-21 12:59:15 +03:00
return True ;
2000-05-09 15:43:00 +04:00
}
/* Lookup a name in a domain from a sid */
2001-05-07 08:32:40 +04:00
BOOL winbindd_lookup_name_by_sid ( DOM_SID * sid , fstring name ,
2000-05-09 15:43:00 +04:00
enum SID_NAME_USE * type )
{
2001-11-21 12:59:15 +03:00
int num_sids = 1 , num_names = 0 ;
uint32 * types = NULL ;
char * * names ;
CLI_POLICY_HND * hnd ;
NTSTATUS result ;
TALLOC_CTX * mem_ctx ;
BOOL rv = False ;
2001-10-12 12:28:08 +04:00
2001-11-21 12:59:15 +03:00
/* First check cache. */
if ( winbindd_lookup_name_by_sid_in_cache ( sid , name , type ) ) {
if ( * type = = SID_NAME_USE_NONE )
return False ; /* Negative cache hit. */
return True ;
}
/* Lookup name */
if ( ! ( mem_ctx = talloc_init ( ) ) )
return False ;
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
if ( ! ( hnd = cm_get_lsa_handle ( lp_workgroup ( ) ) ) )
goto done ;
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
result = cli_lsa_lookup_sids ( hnd - > cli , mem_ctx , & hnd - > pol ,
num_sids , sid , & names , & types ,
& num_names ) ;
2000-05-09 15:43:00 +04:00
2001-11-21 12:59:15 +03:00
/* Return name and type if successful */
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
if ( NT_STATUS_IS_OK ( result ) ) {
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
/* Return name */
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
if ( ( names ! = NULL ) & & ( name ! = NULL ) )
fstrcpy ( name , names [ 0 ] ) ;
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
/* Return name type */
2001-10-05 04:20:06 +04:00
2001-11-21 12:59:15 +03:00
if ( ( type ! = NULL ) & & ( types ! = NULL ) )
* type = types [ 0 ] ;
store_name_by_sid_in_cache ( sid , names [ 0 ] , types [ 0 ] ) ;
}
/* JRA. Here's where we add the -ve cache store with a name type of SID_NAME_USE_NONE. */
/* We need to know the error returns that W2K gives on "no such user". */
2001-10-12 12:28:08 +04:00
2001-11-21 12:59:15 +03:00
rv = NT_STATUS_IS_OK ( result ) ;
2001-10-05 04:20:06 +04:00
2001-10-12 12:28:08 +04:00
done :
2001-11-21 12:59:15 +03:00
talloc_destroy ( mem_ctx ) ;
return rv ;
2000-05-09 15:43:00 +04:00
}
/* Lookup user information from a rid */
2001-10-29 07:50:17 +03:00
BOOL winbindd_lookup_userinfo ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx , uint32 user_rid ,
2001-10-08 04:34:14 +04:00
SAM_USERINFO_CTR * * user_info )
2000-05-09 15:43:00 +04:00
{
2001-10-08 04:34:14 +04:00
CLI_POLICY_HND * hnd ;
uint16 info_level = 0x15 ;
2001-10-19 05:46:43 +04:00
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
2001-11-15 09:55:56 +03:00
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED ;
POLICY_HND dom_pol , user_pol ;
BOOL got_dom_pol = False , got_user_pol = False ;
2001-10-19 05:46:43 +04:00
2001-11-15 09:55:56 +03:00
/* Get sam handle */
if ( ! ( hnd = cm_get_sam_handle ( domain - > name ) ) )
goto done ;
/* Get domain handle */
result = cli_samr_open_domain ( hnd - > cli , mem_ctx , & hnd - > pol ,
des_access , & domain - > sid , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) )
goto done ;
got_dom_pol = True ;
/* Get user handle */
result = cli_samr_open_user ( hnd - > cli , mem_ctx , & dom_pol ,
des_access , user_rid , & user_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) )
2001-10-19 05:46:43 +04:00
goto done ;
2001-10-08 04:34:14 +04:00
2001-11-15 09:55:56 +03:00
/* Get user info */
result = cli_samr_query_userinfo ( hnd - > cli , mem_ctx , & user_pol ,
2001-10-19 05:46:43 +04:00
info_level , user_info ) ;
2001-11-15 09:55:56 +03:00
cli_samr_close ( hnd - > cli , mem_ctx , & user_pol ) ;
2001-10-19 05:46:43 +04:00
done :
2001-11-15 09:55:56 +03:00
/* Clean up policy handles */
if ( got_user_pol )
cli_samr_close ( hnd - > cli , mem_ctx , & user_pol ) ;
if ( got_dom_pol )
cli_samr_close ( hnd - > cli , mem_ctx , & dom_pol ) ;
2001-10-08 04:34:14 +04:00
return NT_STATUS_IS_OK ( result ) ;
2000-05-09 15:43:00 +04:00
}
2001-05-07 08:32:40 +04:00
/* Lookup groups a user is a member of. I wish Unix had a call like this! */
BOOL winbindd_lookup_usergroups ( struct winbindd_domain * domain ,
uint32 user_rid , uint32 * num_groups ,
DOM_GID * * user_groups )
{
2001-10-19 05:46:43 +04:00
TALLOC_CTX * mem_ctx ;
2001-10-10 02:55:00 +04:00
CLI_POLICY_HND * hnd ;
2001-10-19 05:46:43 +04:00
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
2001-11-15 09:55:56 +03:00
POLICY_HND dom_pol , user_pol ;
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED ;
BOOL got_dom_pol = False , got_user_pol = False ;
2001-10-19 05:46:43 +04:00
if ( ! ( mem_ctx = talloc_init ( ) ) )
return False ;
2001-05-07 08:32:40 +04:00
2001-11-15 09:55:56 +03:00
/* Get sam handle */
if ( ! ( hnd = cm_get_sam_handle ( domain - > name ) ) )
goto done ;
/* Get domain handle */
result = cli_samr_open_domain ( hnd - > cli , mem_ctx , & hnd - > pol ,
des_access , & domain - > sid , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) )
goto done ;
got_dom_pol = True ;
/* Get user handle */
result = cli_samr_open_user ( hnd - > cli , mem_ctx , & dom_pol ,
des_access , user_rid , & user_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) )
2001-10-19 05:46:43 +04:00
goto done ;
2001-11-15 09:55:56 +03:00
got_user_pol = True ;
/* Query user rids */
2001-11-19 08:23:59 +03:00
result = cli_samr_query_usergroups ( hnd - > cli , mem_ctx , & user_pol ,
2001-10-19 05:46:43 +04:00
num_groups , user_groups ) ;
2001-05-07 08:32:40 +04:00
2001-10-19 05:46:43 +04:00
done :
2001-11-15 09:55:56 +03:00
/* Clean up policy handles */
if ( got_user_pol )
cli_samr_close ( hnd - > cli , mem_ctx , & user_pol ) ;
if ( got_dom_pol )
cli_samr_close ( hnd - > cli , mem_ctx , & dom_pol ) ;
2001-10-19 05:46:43 +04:00
talloc_destroy ( mem_ctx ) ;
2001-05-07 08:32:40 +04:00
2001-10-10 02:55:00 +04:00
return NT_STATUS_IS_OK ( result ) ;
2001-05-07 08:32:40 +04:00
}
2001-10-10 02:55:00 +04:00
/* Lookup group membership given a rid. */
2000-05-09 15:43:00 +04:00
BOOL winbindd_lookup_groupmem ( struct winbindd_domain * domain ,
2001-10-19 05:46:43 +04:00
TALLOC_CTX * mem_ctx ,
2000-05-09 15:43:00 +04:00
uint32 group_rid , uint32 * num_names ,
uint32 * * rid_mem , char * * * names ,
2001-09-05 12:11:17 +04:00
uint32 * * name_types )
2000-05-09 15:43:00 +04:00
{
2001-11-15 09:55:56 +03:00
CLI_POLICY_HND * hnd ;
2001-10-19 05:46:43 +04:00
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
2001-10-10 02:55:00 +04:00
uint32 i , total_names = 0 ;
2001-11-15 09:55:56 +03:00
POLICY_HND dom_pol , group_pol ;
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED ;
BOOL got_dom_pol = False , got_group_pol = False ;
2000-05-09 15:43:00 +04:00
2001-11-15 09:55:56 +03:00
/* Get sam handle */
if ( ! ( hnd = cm_get_sam_handle ( domain - > name ) ) )
goto done ;
/* Get domain handle */
2001-10-31 09:20:58 +03:00
2001-11-15 09:55:56 +03:00
result = cli_samr_open_domain ( hnd - > cli , mem_ctx , & hnd - > pol ,
des_access , & domain - > sid , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) )
goto done ;
got_dom_pol = True ;
/* Get group handle */
result = cli_samr_open_group ( hnd - > cli , mem_ctx , & dom_pol ,
des_access , group_rid , & group_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) )
2001-10-19 05:46:43 +04:00
goto done ;
2001-10-10 02:55:00 +04:00
2001-11-15 09:55:56 +03:00
got_group_pol = True ;
2001-10-10 02:55:00 +04:00
2001-11-15 09:55:56 +03:00
/* Step #1: Get a list of user rids that are the members of the
group . */
result = cli_samr_query_groupmem ( hnd - > cli , mem_ctx ,
& group_pol , num_names , rid_mem ,
2001-10-10 02:55:00 +04:00
name_types ) ;
if ( ! NT_STATUS_IS_OK ( result ) )
2001-10-19 05:46:43 +04:00
goto done ;
2001-10-10 02:55:00 +04:00
2001-10-31 09:20:58 +03:00
/* Step #2: Convert list of rids into list of usernames. Do this
in bunches of ~ 1000 to avoid crashing NT4 . It looks like there
is a buffer overflow or something like that lurking around
somewhere . */
2001-10-10 02:55:00 +04:00
# define MAX_LOOKUP_RIDS 900
2001-10-19 05:46:43 +04:00
* names = talloc ( mem_ctx , * num_names * sizeof ( char * ) ) ;
* name_types = talloc ( mem_ctx , * num_names * sizeof ( uint32 ) ) ;
2001-10-10 02:55:00 +04:00
for ( i = 0 ; i < * num_names ; i + = MAX_LOOKUP_RIDS ) {
int num_lookup_rids = MIN ( * num_names - i , MAX_LOOKUP_RIDS ) ;
uint32 tmp_num_names = 0 ;
char * * tmp_names = NULL ;
uint32 * tmp_types = NULL ;
/* Lookup a chunk of rids */
2001-11-15 09:55:56 +03:00
result = cli_samr_lookup_rids ( hnd - > cli , mem_ctx ,
& dom_pol , 1000 , /* flags */
2001-10-10 02:55:00 +04:00
num_lookup_rids ,
& ( * rid_mem ) [ i ] ,
& tmp_num_names ,
& tmp_names , & tmp_types ) ;
if ( ! NT_STATUS_IS_OK ( result ) )
2001-10-19 05:46:43 +04:00
goto done ;
2001-10-10 02:55:00 +04:00
/* Copy result into array. The talloc system will take
care of freeing the temporary arrays later on . */
memcpy ( & ( * names ) [ i ] , tmp_names , sizeof ( char * ) *
tmp_num_names ) ;
memcpy ( & ( * name_types ) [ i ] , tmp_types , sizeof ( uint32 ) *
tmp_num_names ) ;
total_names + = tmp_num_names ;
}
* num_names = total_names ;
2001-10-19 05:46:43 +04:00
done :
2001-11-15 09:55:56 +03:00
if ( got_group_pol )
cli_samr_close ( hnd - > cli , mem_ctx , & group_pol ) ;
if ( got_dom_pol )
cli_samr_close ( hnd - > cli , mem_ctx , & dom_pol ) ;
2001-10-10 02:55:00 +04:00
return NT_STATUS_IS_OK ( result ) ;
}
2001-10-05 04:20:06 +04:00
2000-05-09 15:43:00 +04:00
/* Free state information held for {set,get,end}{pw,gr}ent() functions */
void free_getent_state ( struct getent_state * state )
{
struct getent_state * temp ;
/* Iterate over state list */
temp = state ;
while ( temp ! = NULL ) {
struct getent_state * next ;
/* Free sam entries then list entry */
2001-09-17 08:52:45 +04:00
SAFE_FREE ( state - > sam_entries ) ;
2000-05-09 15:43:00 +04:00
DLIST_REMOVE ( state , state ) ;
next = temp - > next ;
2001-09-17 08:52:45 +04:00
SAFE_FREE ( temp ) ;
2000-05-09 15:43:00 +04:00
temp = next ;
}
}
/* Parse list of arguments to winbind uid or winbind gid parameters */
static BOOL parse_id_list ( char * paramstr , BOOL is_user )
{
uid_t id_low , id_high = 0 ;
2000-05-10 14:41:59 +04:00
/* Give a nicer error message if no parameters specified */
if ( strequal ( paramstr , " " ) ) {
2001-05-07 08:32:40 +04:00
DEBUG ( 0 , ( " winbind %s parameter missing \n " , is_user ? " uid " : " gid " ) ) ;
2000-05-10 14:41:59 +04:00
return False ;
}
2000-05-09 15:43:00 +04:00
/* Parse entry */
if ( sscanf ( paramstr , " %u-%u " , & id_low , & id_high ) ! = 2 ) {
2001-05-07 08:32:40 +04:00
DEBUG ( 0 , ( " winbind %s parameter invalid \n " ,
2000-05-09 15:43:00 +04:00
is_user ? " uid " : " gid " ) ) ;
return False ;
}
/* Store id info */
if ( is_user ) {
server_state . uid_low = id_low ;
server_state . uid_high = id_high ;
} else {
server_state . gid_low = id_low ;
server_state . gid_high = id_high ;
}
return True ;
}
/* Initialise trusted domain info */
BOOL winbindd_param_init ( void )
{
/* Parse winbind uid and winbind_gid parameters */
if ( ! ( parse_id_list ( lp_winbind_uid ( ) , True ) & &
2001-10-14 12:31:54 +04:00
parse_id_list ( lp_winbind_gid ( ) , False ) ) )
2000-05-09 15:43:00 +04:00
return False ;
/* Check for reversed uid and gid ranges */
if ( server_state . uid_low > server_state . uid_high ) {
DEBUG ( 0 , ( " uid range invalid \n " ) ) ;
return False ;
}
if ( server_state . gid_low > server_state . gid_high ) {
2001-05-07 08:32:40 +04:00
DEBUG ( 0 , ( " gid range invalid \n " ) ) ;
2000-05-09 15:43:00 +04:00
return False ;
}
return True ;
}
2001-05-07 08:32:40 +04:00
/* Query display info for a domain. This returns enough information plus a
bit extra to give an overview of domain users for the User Manager
application . */
2001-09-04 11:13:01 +04:00
NTSTATUS winbindd_query_dispinfo ( struct winbindd_domain * domain ,
2001-10-19 05:46:43 +04:00
TALLOC_CTX * mem_ctx ,
2001-09-04 11:13:01 +04:00
uint32 * start_ndx , uint16 info_level ,
uint32 * num_entries , SAM_DISPINFO_CTR * ctr )
2001-05-07 08:32:40 +04:00
{
2001-10-08 04:34:14 +04:00
CLI_POLICY_HND * hnd ;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
2001-11-15 09:55:56 +03:00
POLICY_HND dom_pol ;
BOOL got_dom_pol = False ;
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED ;
/* Get sam handle */
2001-10-08 04:34:14 +04:00
2001-11-15 09:55:56 +03:00
if ( ! ( hnd = cm_get_sam_handle ( domain - > name ) ) )
2001-10-19 05:46:43 +04:00
goto done ;
2001-10-08 04:34:14 +04:00
2001-11-15 09:55:56 +03:00
/* Get domain handle */
result = cli_samr_open_domain ( hnd - > cli , mem_ctx , & hnd - > pol ,
des_access , & domain - > sid , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) )
goto done ;
got_dom_pol = True ;
/* Query display info */
2001-10-19 05:46:43 +04:00
result = cli_samr_query_dispinfo ( hnd - > cli , mem_ctx ,
2001-11-15 09:55:56 +03:00
& dom_pol , start_ndx , info_level ,
2001-10-08 04:34:14 +04:00
num_entries , 0xffff , ctr ) ;
2001-10-19 05:46:43 +04:00
done :
2001-11-15 09:55:56 +03:00
if ( got_dom_pol )
cli_samr_close ( hnd - > cli , mem_ctx , & dom_pol ) ;
2001-10-19 05:46:43 +04:00
return result ;
2001-05-07 08:32:40 +04:00
}
/* Check if a domain is present in a comma-separated list of domains */
BOOL check_domain_env ( char * domain_env , char * domain )
{
fstring name ;
char * tmp = domain_env ;
while ( next_token ( & tmp , name , " , " , sizeof ( fstring ) ) ) {
2001-10-14 12:31:54 +04:00
if ( strequal ( name , domain ) )
2001-05-07 08:32:40 +04:00
return True ;
}
return False ;
}
/* Parse a string of the form DOMAIN/user into a domain and a user */
void parse_domain_user ( char * domuser , fstring domain , fstring user )
{
char * p ;
char * sep = lp_winbind_separator ( ) ;
2001-10-14 12:31:54 +04:00
if ( ! sep )
sep = " \\ " ;
2001-07-19 01:50:20 +04:00
p = strchr ( domuser , * sep ) ;
2001-10-14 12:31:54 +04:00
if ( ! p )
p = strchr ( domuser , ' \\ ' ) ;
2001-05-07 08:32:40 +04:00
if ( ! p ) {
fstrcpy ( domain , " " ) ;
fstrcpy ( user , domuser ) ;
return ;
}
fstrcpy ( user , p + 1 ) ;
fstrcpy ( domain , domuser ) ;
domain [ PTR_DIFF ( p , domuser ) ] = 0 ;
strupper ( domain ) ;
}