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-05-07 08:32:40 +04:00
/* Debug connection state */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
void debug_conn_state ( void )
2000-05-09 15:43:00 +04:00
{
2001-05-07 08:32:40 +04:00
struct winbindd_domain * domain ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
DEBUG ( 3 , ( " server: dc=%s, pwdb_init=%d, lsa_hnd=%d \n " ,
server_state . controller ,
server_state . pwdb_initialised ,
server_state . lsa_handle_open ) ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
for ( domain = domain_list ; domain ; domain = domain - > next ) {
DEBUG ( 3 , ( " %s: dc=%s, got_sid=%d, sam_hnd=%d sam_dom_hnd=%d \n " ,
domain - > name , domain - > controller ,
domain - > got_domain_info , domain - > sam_handle_open ,
domain - > sam_dom_handle_open ) ) ;
}
2000-05-09 15:43:00 +04:00
}
2001-05-07 08:32:40 +04:00
/* Add a trusted domain to our list of domains */
2000-05-09 15:43:00 +04:00
static struct winbindd_domain * add_trusted_domain ( char * domain_name )
{
2001-05-07 08:32:40 +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 trusted list \n " ,
domain_name ) ) ;
return tmp ;
}
}
2000-05-09 15:43:00 +04:00
DEBUG ( 1 , ( " adding trusted domain %s \n " , domain_name ) ) ;
/* Create new domain entry */
if ( ( domain = ( struct winbindd_domain * ) malloc ( sizeof ( * domain ) ) ) = = NULL ) {
return NULL ;
}
/* Fill in fields */
ZERO_STRUCTP ( domain ) ;
if ( domain_name ) {
fstrcpy ( domain - > name , domain_name ) ;
}
/* Link to domain list */
DLIST_ADD ( domain_list , domain ) ;
return domain ;
}
/* Look up global info for the winbind daemon */
2001-05-07 08:32:40 +04:00
2000-05-09 15:43:00 +04:00
static BOOL get_trusted_domains ( void )
{
uint32 enum_ctx = 0 ;
uint32 num_doms = 0 ;
char * * domains = NULL ;
2001-05-07 08:32:40 +04:00
DOM_SID * sids = NULL ;
2000-05-09 15:43:00 +04:00
BOOL result ;
int i ;
DEBUG ( 1 , ( " getting trusted domain list \n " ) ) ;
/* Add our workgroup - keep handle to look up trusted domains */
if ( ! add_trusted_domain ( lp_workgroup ( ) ) ) {
2000-07-10 09:40:43 +04:00
DEBUG ( 0 , ( " could not add record for domain %s \n " ,
lp_workgroup ( ) ) ) ;
2000-05-09 15:43:00 +04:00
return False ;
}
/* Enumerate list of trusted domains */
2001-05-07 10:04:22 +04:00
result = wb_lsa_enum_trust_dom ( & server_state . lsa_handle , & enum_ctx ,
& num_doms , & domains , & sids ) ;
2000-05-09 15:43:00 +04:00
if ( ! result | | ! domains ) return False ;
/* Add each domain to the trusted domain list */
for ( i = 0 ; i < num_doms ; i + + ) {
if ( ! add_trusted_domain ( domains [ i ] ) ) {
2000-07-10 09:40:43 +04:00
DEBUG ( 0 , ( " could not add record for domain %s \n " ,
domains [ i ] ) ) ;
2000-05-09 15:43:00 +04:00
result = False ;
}
}
return True ;
}
2001-05-07 08:32:40 +04:00
/* Open sam and sam domain handles */
2000-05-09 15:43:00 +04:00
static BOOL open_sam_handles ( struct winbindd_domain * domain )
{
2001-05-07 08:32:40 +04:00
/* Get domain info (sid and controller name) */
2000-05-09 15:43:00 +04:00
if ( ! domain - > got_domain_info ) {
domain - > got_domain_info = get_domain_info ( domain ) ;
if ( ! domain - > got_domain_info ) return False ;
}
2001-05-07 08:32:40 +04:00
/* Shut down existing sam handles */
2000-07-10 09:40:43 +04:00
2001-05-07 08:32:40 +04:00
if ( domain - > sam_dom_handle_open ) {
2001-05-07 10:04:22 +04:00
wb_samr_close ( & domain - > sam_dom_handle ) ;
2001-05-07 08:32:40 +04:00
domain - > sam_dom_handle_open = False ;
2000-05-10 17:21:32 +04:00
}
2001-05-07 08:32:40 +04:00
if ( domain - > sam_handle_open ) {
2001-05-07 10:04:22 +04:00
wb_samr_close ( & domain - > sam_handle ) ;
2001-05-07 08:32:40 +04:00
domain - > sam_handle_open = False ;
}
2000-07-10 09:40:43 +04:00
2001-05-07 08:32:40 +04:00
/* Open sam handle */
2000-07-10 09:40:43 +04:00
2001-05-07 08:32:40 +04:00
domain - > sam_handle_open =
2001-05-07 10:04:22 +04:00
wb_samr_connect ( domain - > controller ,
SEC_RIGHTS_MAXIMUM_ALLOWED ,
& domain - > sam_handle ) ;
2000-07-10 09:40:43 +04:00
2001-05-07 08:32:40 +04:00
if ( ! domain - > sam_handle_open ) return False ;
/* Open sam domain handle */
domain - > sam_dom_handle_open =
2001-05-07 10:04:22 +04:00
wb_samr_open_domain ( & domain - > sam_handle ,
SEC_RIGHTS_MAXIMUM_ALLOWED ,
& domain - > sid ,
& domain - > sam_dom_handle ) ;
2001-05-07 08:32:40 +04:00
if ( ! domain - > sam_dom_handle_open ) return False ;
return True ;
}
static BOOL rpc_hnd_ok ( CLI_POLICY_HND * hnd )
{
return hnd - > cli - > fd ! = - 1 ;
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Return true if the SAM domain handles are open and responding. */
2000-07-10 09:40:43 +04:00
2001-05-07 08:32:40 +04:00
BOOL domain_handles_open ( struct winbindd_domain * domain )
{
time_t t ;
BOOL result ;
2000-07-10 09:40:43 +04:00
2001-05-07 08:32:40 +04:00
/* Check we haven't checked too recently */
2000-07-10 09:40:43 +04:00
2001-05-07 08:32:40 +04:00
t = time ( NULL ) ;
if ( ( t - domain - > last_check ) < WINBINDD_ESTABLISH_LOOP ) {
return domain - > sam_handle_open & &
domain - > sam_dom_handle_open ;
2000-05-09 15:43:00 +04:00
}
2001-05-07 08:32:40 +04:00
DEBUG ( 3 , ( " checking domain handles for domain %s \n " , domain - > name ) ) ;
debug_conn_state ( ) ;
domain - > last_check = t ;
/* Open sam handles if they are marked as closed */
if ( ! domain - > sam_handle_open | | ! domain - > sam_dom_handle_open ) {
reopen :
DEBUG ( 3 , ( " opening sam handles \n " ) ) ;
return open_sam_handles ( domain ) ;
}
/* Check sam handles are ok - the domain controller may have failed
and we need to move to a BDC . */
if ( ! rpc_hnd_ok ( & domain - > sam_handle ) | |
! rpc_hnd_ok ( & domain - > sam_dom_handle ) ) {
/* We want to close the current connection but attempt
to open a new set , possibly to a new dc . If this
doesn ' t work then return False as we have no dc
to talk to . */
DEBUG ( 3 , ( " sam handles not responding \n " ) ) ;
winbindd_kill_connections ( domain ) ;
goto reopen ;
}
result = domain - > sam_handle_open & & domain - > sam_dom_handle_open ;
return result ;
2000-05-09 15:43:00 +04:00
}
2001-05-07 08:32:40 +04:00
/* Shut down connections to all domain controllers */
2000-07-10 09:40:43 +04:00
2001-05-07 08:32:40 +04:00
void winbindd_kill_connections ( struct winbindd_domain * domain )
2000-05-09 15:43:00 +04:00
{
2001-05-07 08:32:40 +04:00
BOOL is_server = False ;
struct winbindd_domain * server_domain ;
/* Find pointer to domain of pdc */
server_domain = find_domain_from_name ( lp_workgroup ( ) ) ;
if ( ! server_domain ) return ;
/* If NULL passed, use pdc */
if ( ! domain ) {
domain = server_domain ;
}
if ( domain = = server_domain | |
strequal ( domain - > name , lp_workgroup ( ) ) ) {
is_server = True ;
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Log a level 0 message - this is probably a domain controller
failure */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
DEBUG ( 0 , ( " killing connections to domain %s with controller %s \n " ,
domain - > name , domain - > controller ) ) ;
2000-07-10 09:40:43 +04:00
2001-05-07 08:32:40 +04:00
debug_conn_state ( ) ;
if ( is_server ) {
server_state . pwdb_initialised = False ;
server_state . lsa_handle_open = False ;
2001-05-07 10:04:22 +04:00
wb_lsa_close ( & server_state . lsa_handle ) ;
2001-05-07 08:32:40 +04:00
}
/* Close domain sam handles but don't free them as this
severely traumatises the getent state . The connections
will be reopened later . */
if ( domain - > sam_dom_handle_open ) {
2001-05-07 10:04:22 +04:00
wb_samr_close ( & domain - > sam_dom_handle ) ;
2001-05-07 08:32:40 +04:00
domain - > sam_dom_handle_open = False ;
}
if ( domain - > sam_handle_open ) {
2001-05-07 10:04:22 +04:00
wb_samr_close ( & domain - > sam_handle ) ;
2001-05-07 08:32:40 +04:00
domain - > sam_handle_open = False ;
}
/* Re-lookup domain info which includes domain controller name */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
domain - > got_domain_info = False ;
}
/* Kill connections to all servers */
void winbindd_kill_all_connections ( void )
{
struct winbindd_domain * domain ;
/* Iterate over domain list */
2000-07-10 09:40:43 +04:00
domain = domain_list ;
2001-05-07 08:32:40 +04:00
while ( domain ) {
2000-07-10 09:40:43 +04:00
struct winbindd_domain * next ;
2001-05-07 08:32:40 +04:00
/* Kill conections */
2000-07-10 09:40:43 +04:00
2001-05-07 08:32:40 +04:00
winbindd_kill_connections ( domain ) ;
2000-07-10 09:40:43 +04:00
2001-05-07 08:32:40 +04:00
/* Remove domain from list */
2000-07-10 09:40:43 +04:00
next = domain - > next ;
2000-05-09 15:43:00 +04:00
DLIST_REMOVE ( domain_list , domain ) ;
free ( domain ) ;
2000-07-10 09:40:43 +04:00
domain = next ;
}
2001-05-07 08:32:40 +04:00
}
2000-07-10 09:40:43 +04:00
2001-05-07 08:32:40 +04:00
static BOOL get_any_dc_name ( char * domain , fstring srv_name )
{
struct in_addr * ip_list , dc_ip ;
extern pstring global_myname ;
int count , i ;
2000-07-10 09:40:43 +04:00
2001-05-07 08:32:40 +04:00
/* Lookup domain controller name */
2001-05-09 09:06:35 +04:00
if ( ! get_dc_list ( False , domain , & ip_list , & count ) )
2001-05-07 08:32:40 +04:00
return False ;
/* Firstly choose a PDC/BDC who has the same network address as any
of our interfaces . */
for ( i = 0 ; i < count ; i + + ) {
if ( ! is_local_net ( ip_list [ i ] ) )
goto got_ip ;
2000-05-09 15:43:00 +04:00
}
2001-05-07 08:32:40 +04:00
i = ( sys_random ( ) % count ) ;
got_ip :
dc_ip = ip_list [ i ] ;
free ( ip_list ) ;
2001-05-09 09:06:35 +04:00
if ( ! lookup_pdc_name ( global_myname , domain , & dc_ip , srv_name ) )
2001-05-07 08:32:40 +04:00
return False ;
return True ;
2000-05-09 15:43:00 +04:00
}
2001-05-07 08:32:40 +04:00
/* Attempt to connect to all domain controllers we know about */
2000-07-10 09:40:43 +04:00
2001-05-07 08:32:40 +04:00
void establish_connections ( BOOL force_reestablish )
2000-05-09 15:43:00 +04:00
{
static time_t lastt ;
time_t t ;
2001-05-07 08:32:40 +04:00
/* Check we haven't checked too recently */
2000-05-09 15:43:00 +04:00
t = time ( NULL ) ;
2001-05-07 08:32:40 +04:00
if ( ( t - lastt < WINBINDD_ESTABLISH_LOOP ) & & ! force_reestablish ) {
return ;
}
2000-05-09 15:43:00 +04:00
lastt = t ;
2001-05-07 08:32:40 +04:00
DEBUG ( 3 , ( " establishing connections \n " ) ) ;
debug_conn_state ( ) ;
/* Maybe the connection died - if so then close up and restart */
2000-05-09 15:43:00 +04:00
if ( server_state . pwdb_initialised & &
server_state . lsa_handle_open & &
! rpc_hnd_ok ( & server_state . lsa_handle ) ) {
2001-05-07 08:32:40 +04:00
winbindd_kill_connections ( NULL ) ;
2000-05-09 15:43:00 +04:00
}
if ( ! server_state . pwdb_initialised ) {
2001-05-07 08:32:40 +04:00
/* Lookup domain controller name */
if ( ! get_any_dc_name ( lp_workgroup ( ) ,
server_state . controller ) ) {
2001-05-08 07:52:07 +04:00
DEBUG ( 3 , ( " could not find any domain controllers "
" for domain %s \n " , lp_workgroup ( ) ) ) ;
2001-05-07 08:32:40 +04:00
return ;
2000-05-09 15:43:00 +04:00
}
2001-05-07 08:32:40 +04:00
/* Initialise password database and sids */
// server_state.pwdb_initialised = pwdb_initialise(False);
server_state . pwdb_initialised = True ;
2001-05-08 07:52:07 +04:00
if ( ! server_state . pwdb_initialised ) {
DEBUG ( 3 , ( " could not initialise pwdb \n " ) ) ;
2001-05-07 08:32:40 +04:00
return ;
2001-05-08 07:52:07 +04:00
}
2000-05-09 15:43:00 +04:00
}
/* Open lsa handle if it isn't already open */
2001-05-07 08:32:40 +04:00
2000-05-09 15:43:00 +04:00
if ( ! server_state . lsa_handle_open ) {
2001-05-07 08:32:40 +04:00
2000-05-09 15:43:00 +04:00
server_state . lsa_handle_open =
2001-05-07 10:04:22 +04:00
wb_lsa_open_policy ( server_state . controller ,
False , SEC_RIGHTS_MAXIMUM_ALLOWED ,
& server_state . lsa_handle ) ;
2001-05-07 08:32:40 +04:00
2001-05-08 07:52:07 +04:00
if ( ! server_state . lsa_handle_open ) {
DEBUG ( 0 , ( " error opening lsa handle on dc %s \n " ,
server_state . controller ) ) ;
return ;
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Now we can talk to the server we can get some info */
2000-05-09 15:43:00 +04:00
get_trusted_domains ( ) ;
}
2001-05-07 08:32:40 +04:00
debug_conn_state ( ) ;
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 )
{
fstring level5_dom ;
BOOL res ;
uint32 enum_ctx = 0 ;
uint32 num_doms = 0 ;
char * * domains = NULL ;
2001-05-07 08:32:40 +04:00
DOM_SID * sids = NULL ;
2000-05-09 15:43:00 +04:00
if ( domain = = NULL ) {
return False ;
}
DEBUG ( 1 , ( " looking up sid for domain %s \n " , domain_name ) ) ;
/* Get controller name for domain */
2001-05-07 08:32:40 +04:00
if ( ! get_any_dc_name ( domain_name , domain - > controller ) ) {
DEBUG ( 0 , ( " Could not resolve domain controller for domain %s \n " ,
domain_name ) ) ;
2000-05-09 15:43:00 +04:00
return False ;
}
2001-05-09 09:06:35 +04:00
/* Do a level 5 query info policy if we are looking up our own SID */
if ( strequal ( domain_name , lp_workgroup ( ) ) ) {
2001-05-07 10:04:22 +04:00
return wb_lsa_query_info_pol ( & server_state . lsa_handle , 0x05 ,
level5_dom , & domain - > sid ) ;
2000-05-09 15:43:00 +04:00
}
/* Use lsaenumdomains to get sid for this domain */
2001-05-07 10:04:22 +04:00
res = wb_lsa_enum_trust_dom ( & server_state . lsa_handle , & enum_ctx ,
& num_doms , & domains , & sids ) ;
2000-05-09 15:43:00 +04:00
/* Look for domain name */
2001-05-09 09:06:35 +04:00
if ( res & & domains & & sids ) {
2000-05-09 15:43:00 +04:00
int found = False ;
int i ;
for ( i = 0 ; i < num_doms ; i + + ) {
if ( strequal ( domain_name , domains [ i ] ) ) {
2001-05-07 08:32:40 +04:00
sid_copy ( & domain - > sid , & sids [ i ] ) ;
2000-05-09 15:43:00 +04:00
found = True ;
break ;
}
}
res = found ;
}
return res ;
}
/* Lookup domain controller and sid for a domain */
BOOL get_domain_info ( struct winbindd_domain * domain )
{
fstring sid_str ;
DEBUG ( 1 , ( " Getting domain info for domain %s \n " , domain - > name ) ) ;
/* Lookup domain sid */
2001-05-07 08:32:40 +04:00
2000-05-09 15:43:00 +04:00
if ( ! lookup_domain_sid ( domain - > name , domain ) ) {
DEBUG ( 0 , ( " could not find sid for domain %s \n " , domain - > name ) ) ;
2001-05-07 08:32:40 +04:00
/* Could be a DC failure - shut down connections to this domain */
winbindd_kill_connections ( domain ) ;
2000-05-09 15:43:00 +04:00
return False ;
}
/* Lookup OK */
domain - > got_domain_info = 1 ;
sid_to_string ( sid_str , & domain - > sid ) ;
DEBUG ( 1 , ( " found sid %s for domain %s \n " , sid_str , domain - > name ) ) ;
return True ;
}
/* 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 )
{
int num_sids = 0 , num_names = 1 ;
DOM_SID * sids = NULL ;
uint32 * types = NULL ;
BOOL res ;
/* Don't bother with machine accounts */
if ( name [ strlen ( name ) - 1 ] = = ' $ ' ) {
return False ;
}
/* Lookup name */
2001-05-07 10:04:22 +04:00
res = wb_lsa_lookup_names ( & server_state . lsa_handle , num_names ,
( char * * ) & name , & sids , & types , & num_sids ) ;
2000-05-09 15:43:00 +04:00
/* Return rid and type if lookup successful */
if ( res ) {
/* Return sid */
if ( ( sid ! = NULL ) & & ( sids ! = NULL ) ) {
sid_copy ( sid , & sids [ 0 ] ) ;
}
/* Return name type */
if ( ( type ! = NULL ) & & ( types ! = NULL ) ) {
* type = types [ 0 ] ;
}
}
/* Free memory */
if ( types ! = NULL ) free ( types ) ;
if ( sids ! = NULL ) free ( sids ) ;
return res ;
}
/* 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 )
{
int num_sids = 1 , num_names = 0 ;
uint32 * types = NULL ;
char * * names ;
BOOL res ;
/* Lookup name */
2001-05-07 08:32:40 +04:00
2001-05-07 10:04:22 +04:00
res = wb_lsa_lookup_sids ( & server_state . lsa_handle , num_sids , sid ,
& names , & types , & num_names ) ;
2000-05-09 15:43:00 +04:00
/* Return name and type if successful */
if ( res ) {
/* Return name */
if ( ( names ! = NULL ) & & ( name ! = NULL ) ) {
fstrcpy ( name , names [ 0 ] ) ;
}
/* Return name type */
if ( ( type ! = NULL ) & & ( types ! = NULL ) ) {
* type = types [ 0 ] ;
}
}
/* Free memory */
safe_free ( types ) ;
free_char_array ( num_names , names ) ;
return res ;
}
/* Lookup user information from a rid */
BOOL winbindd_lookup_userinfo ( struct winbindd_domain * domain ,
2001-05-14 07:58:49 +04:00
uint32 user_rid , SAM_USERINFO_CTR * * user_info )
2000-05-09 15:43:00 +04:00
{
2001-05-07 10:04:22 +04:00
return wb_get_samr_query_userinfo ( & domain - > sam_dom_handle , 0x15 ,
user_rid , user_info ) ;
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 )
{
POLICY_HND user_pol ;
BOOL result ;
2001-05-07 10:04:22 +04:00
if ( ! wb_samr_open_user ( & domain - > sam_dom_handle ,
SEC_RIGHTS_MAXIMUM_ALLOWED ,
user_rid , & user_pol ) ) {
2001-05-07 08:32:40 +04:00
return False ;
}
if ( cli_samr_query_usergroups ( domain - > sam_dom_handle . cli ,
domain - > sam_dom_handle . mem_ctx ,
& user_pol , num_groups , user_groups )
! = NT_STATUS_NOPROBLEMO ) {
result = False ;
goto done ;
}
result = True ;
done :
cli_samr_close ( domain - > sam_dom_handle . cli ,
domain - > sam_dom_handle . mem_ctx , & user_pol ) ;
return True ;
}
2000-05-09 15:43:00 +04:00
/* Lookup group information from a rid */
BOOL winbindd_lookup_groupinfo ( struct winbindd_domain * domain ,
uint32 group_rid , GROUP_INFO_CTR * info )
{
2001-05-07 10:04:22 +04:00
return wb_get_samr_query_groupinfo ( & domain - > sam_dom_handle , 1 ,
group_rid , info ) ;
2000-05-09 15:43:00 +04:00
}
/* Lookup group membership given a rid */
BOOL winbindd_lookup_groupmem ( struct winbindd_domain * domain ,
uint32 group_rid , uint32 * num_names ,
uint32 * * rid_mem , char * * * names ,
enum SID_NAME_USE * * name_types )
{
2001-05-07 10:04:22 +04:00
return wb_sam_query_groupmem ( & domain - > sam_dom_handle , group_rid ,
num_names , rid_mem , names , name_types ) ;
2000-05-09 15:43:00 +04:00
}
2001-05-07 08:32:40 +04:00
/* Globals for domain list stuff */
struct winbindd_domain * domain_list = NULL ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* 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 )
2000-05-09 15:43:00 +04:00
{
2001-05-07 08:32:40 +04:00
struct winbindd_domain * tmp ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Search through list */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
for ( tmp = domain_list ; tmp ! = NULL ; tmp = tmp - > next ) {
if ( strcmp ( domain_name , tmp - > name ) = = 0 ) {
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
if ( ! tmp - > got_domain_info ) {
get_domain_info ( tmp ) ;
}
return tmp - > got_domain_info ? tmp : NULL ;
}
}
/* Not found */
return NULL ;
}
2000-05-09 15:43:00 +04:00
/* Given a domain name, return the struct winbindd domain info for it */
2001-05-07 08:32:40 +04:00
struct winbindd_domain * find_domain_from_sid ( DOM_SID * sid )
2000-05-09 15:43:00 +04:00
{
struct winbindd_domain * tmp ;
/* Search through list */
for ( tmp = domain_list ; tmp ! = NULL ; tmp = tmp - > next ) {
2001-05-07 08:32:40 +04:00
if ( sid_equal ( sid , & tmp - > sid ) ) {
2000-05-09 15:43:00 +04:00
if ( ! tmp - > got_domain_info ) return NULL ;
return tmp ;
}
}
/* Not found */
return NULL ;
}
/* 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 */
safe_free ( state - > sam_entries ) ;
DLIST_REMOVE ( state , state ) ;
next = temp - > next ;
free ( temp ) ;
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 ) & &
parse_id_list ( lp_winbind_gid ( ) , False ) ) ) {
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 ;
}
/* Convert a enum winbindd_cmd to a string */
2001-05-07 08:32:40 +04:00
struct cmdstr_table {
enum winbindd_cmd cmd ;
char * desc ;
} ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
static struct cmdstr_table cmdstr_table [ ] = {
/* User functions */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
{ WINBINDD_GETPWNAM_FROM_USER , " getpwnam from user " } ,
{ WINBINDD_GETPWNAM_FROM_UID , " getpwnam from uid " } ,
{ WINBINDD_SETPWENT , " setpwent " } ,
{ WINBINDD_ENDPWENT , " endpwent " } ,
{ WINBINDD_GETPWENT , " getpwent " } ,
{ WINBINDD_GETGROUPS , " getgroups " } ,
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Group functions */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
{ WINBINDD_GETGRNAM_FROM_GROUP , " getgrnam from group " } ,
{ WINBINDD_GETGRNAM_FROM_GID , " getgrnam from gid " } ,
{ WINBINDD_SETGRENT , " setgrent " } ,
{ WINBINDD_ENDGRENT , " endgrent " } ,
{ WINBINDD_GETGRENT , " getgrent " } ,
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* PAM auth functions */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
{ WINBINDD_PAM_AUTH , " pam auth " } ,
{ WINBINDD_PAM_CHAUTHTOK , " pam chauthtok " } ,
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* List things */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
{ WINBINDD_LIST_USERS , " list users " } ,
{ WINBINDD_LIST_GROUPS , " list groups " } ,
{ WINBINDD_LIST_TRUSTDOM , " list trusted domains " } ,
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* SID related functions */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
{ WINBINDD_LOOKUPSID , " lookup sid " } ,
{ WINBINDD_LOOKUPNAME , " lookup name " } ,
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* S*RS related functions */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
{ WINBINDD_SID_TO_UID , " sid to uid " } ,
{ WINBINDD_SID_TO_GID , " sid to gid " } ,
{ WINBINDD_GID_TO_SID , " gid to sid " } ,
{ WINBINDD_UID_TO_SID , " uid to sid " } ,
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Miscellaneous other stuff */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
{ WINBINDD_CHECK_MACHACC , " check machine acct pw " } ,
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* End of list */
{ WINBINDD_NUM_CMDS , NULL }
} ;
char * winbindd_cmd_to_string ( enum winbindd_cmd cmd )
2000-05-09 15:43:00 +04:00
{
2001-05-07 08:32:40 +04:00
struct cmdstr_table * table = cmdstr_table ;
char * result = NULL ;
for ( table = cmdstr_table ; table - > desc ; table + + ) {
if ( cmd = = table - > cmd ) {
result = table - > desc ;
break ;
}
2000-05-09 15:43:00 +04:00
}
2001-05-07 08:32:40 +04:00
if ( result = = NULL ) {
result = " invalid command " ;
}
return result ;
} ;
2000-05-09 15:43:00 +04:00
/* find the sequence number for a domain */
2001-05-07 08:32:40 +04:00
2000-05-09 15:43:00 +04:00
uint32 domain_sequence_number ( char * domain_name )
{
struct winbindd_domain * domain ;
SAM_UNK_CTR ctr ;
domain = find_domain_from_name ( domain_name ) ;
if ( ! domain ) return DOM_SEQUENCE_NONE ;
2001-05-07 10:04:22 +04:00
if ( ! wb_samr_query_dom_info ( & domain - > sam_dom_handle , 2 , & ctr ) ) {
2001-05-07 08:32:40 +04:00
/* If this fails, something bad has gone wrong */
winbindd_kill_connections ( domain ) ;
2000-05-09 15:43:00 +04:00
DEBUG ( 2 , ( " domain sequence query failed \n " ) ) ;
return DOM_SEQUENCE_NONE ;
}
DEBUG ( 4 , ( " got domain sequence number for %s of %u \n " ,
domain_name , ( unsigned ) ctr . info . inf2 . seq_num ) ) ;
return ctr . info . inf2 . seq_num ;
}
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 . */
uint32 winbindd_query_dispinfo ( struct winbindd_domain * domain ,
uint32 * start_ndx , uint16 info_level ,
uint32 * num_entries , SAM_DISPINFO_CTR * ctr )
{
uint32 status ;
2001-05-07 10:04:22 +04:00
status = wb_samr_query_dispinfo ( & domain - > sam_dom_handle , start_ndx ,
info_level , num_entries , ctr ) ;
2001-05-07 08:32:40 +04:00
return status ;
}
/* 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 ) ) ) {
if ( strequal ( name , domain ) ) {
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 ( ) ;
if ( ! sep ) sep = " \\ " ;
p = strchr ( domuser , * sep ) ;
if ( ! p ) p = strchr ( domuser , ' \\ ' ) ;
if ( ! p ) {
fstrcpy ( domain , " " ) ;
fstrcpy ( user , domuser ) ;
return ;
}
fstrcpy ( user , p + 1 ) ;
fstrcpy ( domain , domuser ) ;
domain [ PTR_DIFF ( p , domuser ) ] = 0 ;
strupper ( domain ) ;
}