2001-10-05 04:20:06 +04:00
/*
Unix SMB / Netbios implementation .
Version 3.0
Winbind daemon connection manager
Copyright ( C ) Tim Potter 2001
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
2001-11-28 02:48:44 +03:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
2001-10-05 04:20:06 +04:00
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 .
*/
/*
We need to manage connections to domain controllers without having to
mess up the main winbindd code with other issues . The aim of the
connection manager is to :
- make connections to domain controllers and cache them
- re - establish connections when networks or servers go down
- centralise the policy on connection timeouts , domain controller
2001-11-28 02:48:44 +03:00
selection etc
2001-10-05 04:20:06 +04:00
- manage re - entrancy for when winbindd becomes able to handle
2001-11-28 02:48:44 +03:00
multiple outstanding rpc requests
2001-10-05 04:20:06 +04:00
Why not have connection management as part of the rpc layer like tng ?
Good question . This code may morph into libsmb / rpc_cache . c or something
2001-11-28 02:48:44 +03:00
like that but at the moment it ' s simply staying as part of winbind . I
2001-10-05 04:20:06 +04:00
think the TNG architecture of forcing every user of the rpc layer to use
2001-11-28 02:48:44 +03:00
the connection caching system is a bad idea . It should be an optional
2001-11-15 09:55:56 +03:00
method of using the routines .
2001-10-05 04:20:06 +04:00
The TNG design is quite good but I disagree with some aspects of the
implementation . - tpot
*/
/*
TODO :
- I ' m pretty annoyed by all the make_nmb_name ( ) stuff . It should be
moved down into another function .
- There needs to be a utility function in libsmb / namequery . c that does
2001-10-08 04:34:14 +04:00
cm_get_dc_name ( )
- Take care when destroying cli_structs as they can be shared between
various sam handles .
2001-10-05 04:20:06 +04:00
*/
# include "winbindd.h"
2001-11-28 02:48:44 +03:00
/* Global list of connections. Initially a DLIST but can become a hash
2001-11-14 09:18:13 +03:00
table or whatever later . */
2001-10-05 04:20:06 +04:00
struct winbindd_cm_conn {
2001-11-15 22:40:00 +03:00
struct winbindd_cm_conn * prev , * next ;
fstring domain ;
fstring controller ;
fstring pipe_name ;
struct cli_state * cli ;
POLICY_HND pol ;
2001-10-05 04:20:06 +04:00
} ;
2001-12-01 15:31:43 +03:00
static struct winbindd_cm_conn * cm_conns = NULL ;
2001-10-05 04:20:06 +04:00
2001-11-15 06:33:12 +03:00
/* Get a domain controller name. Cache positive and negative lookups so we
don ' t go to the network too often when something is badly broken . */
2001-10-05 04:20:06 +04:00
2001-11-15 06:33:12 +03:00
# define GET_DC_NAME_CACHE_TIMEOUT 30 /* Seconds between dc lookups */
struct get_dc_name_cache {
2001-11-15 22:40:00 +03:00
fstring domain_name ;
fstring srv_name ;
time_t lookup_time ;
struct get_dc_name_cache * prev , * next ;
2001-11-15 06:33:12 +03:00
} ;
static BOOL cm_get_dc_name ( char * domain , fstring srv_name )
2001-10-05 04:20:06 +04:00
{
2001-11-15 22:40:00 +03:00
static struct get_dc_name_cache * get_dc_name_cache ;
struct get_dc_name_cache * dcc ;
2001-10-05 04:20:06 +04:00
struct in_addr * ip_list , dc_ip ;
int count , i ;
2001-11-15 22:40:00 +03:00
/* Check the cache for previous lookups */
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
for ( dcc = get_dc_name_cache ; dcc ; dcc = dcc - > next ) {
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
if ( ! strequal ( domain , dcc - > domain_name ) )
continue ; /* Not our domain */
2001-11-15 06:33:12 +03:00
2001-11-28 02:48:44 +03:00
if ( ( time ( NULL ) - dcc - > lookup_time ) >
GET_DC_NAME_CACHE_TIMEOUT ) {
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
/* Cache entry has expired, delete it */
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
DEBUG ( 10 , ( " get_dc_name_cache entry expired for %s \n " , domain ) ) ;
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
DLIST_REMOVE ( get_dc_name_cache , dcc ) ;
SAFE_FREE ( dcc ) ;
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
break ;
}
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
/* Return a positive or negative lookup for this domain */
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
if ( dcc - > srv_name [ 0 ] ) {
2001-11-28 02:48:44 +03:00
DEBUG ( 10 , ( " returning positive get_dc_name_cache entry for %s \n " , domain ) ) ;
2001-11-15 22:40:00 +03:00
fstrcpy ( srv_name , dcc - > srv_name ) ;
return True ;
} else {
2001-11-28 02:48:44 +03:00
DEBUG ( 10 , ( " returning negative get_dc_name_cache entry for %s \n " , domain ) ) ;
2001-11-15 22:40:00 +03:00
return False ;
}
}
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
/* Add cache entry for this lookup. */
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
DEBUG ( 10 , ( " Creating get_dc_name_cache entry for %s \n " , domain ) ) ;
2001-11-15 06:33:12 +03:00
2001-11-28 02:48:44 +03:00
if ( ! ( dcc = ( struct get_dc_name_cache * )
malloc ( sizeof ( struct get_dc_name_cache ) ) ) )
2001-11-15 22:40:00 +03:00
return False ;
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
ZERO_STRUCTP ( dcc ) ;
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
fstrcpy ( dcc - > domain_name , domain ) ;
dcc - > lookup_time = time ( NULL ) ;
DLIST_ADD ( get_dc_name_cache , dcc ) ;
2001-11-15 06:33:12 +03:00
2001-10-05 04:20:06 +04:00
/* Lookup domain controller name */
2001-11-29 08:50:32 +03:00
if ( ! get_dc_list ( False , domain , & ip_list , & count ) ) {
DEBUG ( 3 , ( " Could not look up dc's for domain %s \n " , domain ) ) ;
2001-10-05 04:20:06 +04:00
return False ;
2001-11-29 08:50:32 +03:00
}
2001-10-05 04:20:06 +04:00
/* Firstly choose a PDC/BDC who has the same network address as any
of our interfaces . */
for ( i = 0 ; i < count ; i + + ) {
2001-10-29 18:00:45 +03:00
if ( is_local_net ( ip_list [ i ] ) )
2001-10-05 04:20:06 +04:00
goto got_ip ;
}
2001-11-26 12:28:27 +03:00
2001-11-29 08:50:32 +03:00
if ( count = = 0 ) {
DEBUG ( 3 , ( " No domain controllers for domain %s \n " , domain ) ) ;
return False ;
}
2001-10-05 04:20:06 +04:00
i = ( sys_random ( ) % count ) ;
got_ip :
dc_ip = ip_list [ i ] ;
SAFE_FREE ( ip_list ) ;
2001-11-29 08:50:32 +03:00
/* We really should be doing a GETDC call here rather than a node
status lookup . */
if ( ! name_status_find ( domain , 0x1c , 0x20 , dc_ip , srv_name ) ) {
DEBUG ( 3 , ( " Error looking up DC name for %s in domain %s \n " , inet_ntoa ( dc_ip ) , domain ) ) ;
2001-10-05 04:20:06 +04:00
return False ;
2001-11-29 08:50:32 +03:00
}
2001-10-05 04:20:06 +04:00
2001-11-15 22:40:00 +03:00
/* We have a name so make the cache entry positive now */
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
fstrcpy ( dcc - > srv_name , srv_name ) ;
2001-11-15 06:33:12 +03:00
2001-10-05 04:20:06 +04:00
return True ;
}
2001-12-11 08:19:15 +03:00
/* Choose between anonymous or authenticated connections. We need to use
an authenticated connection if DCs have the RestrictAnonymous registry
entry set > 0 , or the " Additional restrictions for anonymous
connections " set in the win2k Local Security Policy. */
void cm_init_creds ( struct ntuser_creds * creds )
{
char * username , * password ;
ZERO_STRUCTP ( creds ) ;
creds - > pwd . null_pwd = True ; /* anonymoose */
username = secrets_fetch ( SECRETS_AUTH_USER , NULL ) ;
password = secrets_fetch ( SECRETS_AUTH_PASSWORD , NULL ) ;
if ( username & & * username ) {
pwd_set_cleartext ( & creds - > pwd , password ) ;
fstrcpy ( creds - > user_name , username ) ;
fstrcpy ( creds - > domain , lp_workgroup ( ) ) ;
DEBUG ( 3 , ( " IPC$ connections done %s \\ %s \n " , creds - > domain ,
creds - > user_name ) ) ;
} else
DEBUG ( 3 , ( " IPC$ connections done anonymously \n " ) ) ;
}
2001-11-15 06:33:12 +03:00
/* Open a new smb pipe connection to a DC on a given domain. Cache
negative creation attempts so we don ' t try and connect to broken
machines too often . */
# define OPEN_CONNECTION_CACHE_TIMEOUT 30 /* Seconds between attempts */
struct open_connection_cache {
2001-11-15 22:40:00 +03:00
fstring domain_name ;
fstring controller ;
time_t lookup_time ;
struct open_connection_cache * prev , * next ;
2001-11-15 06:33:12 +03:00
} ;
2001-10-05 04:20:06 +04:00
static BOOL cm_open_connection ( char * domain , char * pipe_name ,
2001-11-28 02:48:44 +03:00
struct winbindd_cm_conn * new_conn )
2001-10-05 04:20:06 +04:00
{
2001-11-15 22:40:00 +03:00
static struct open_connection_cache * open_connection_cache ;
struct open_connection_cache * occ ;
2001-10-05 04:20:06 +04:00
struct nmb_name calling , called ;
2001-11-15 22:40:00 +03:00
extern pstring global_myname ;
fstring dest_host ;
struct in_addr dest_ip ;
BOOL result = False ;
struct ntuser_creds creds ;
fstrcpy ( new_conn - > domain , domain ) ;
fstrcpy ( new_conn - > pipe_name , pipe_name ) ;
2001-11-28 02:48:44 +03:00
2001-11-15 22:40:00 +03:00
/* Look for a domain controller for this domain. Negative results
are cached so don ' t bother applying the caching for this
function just yet . */
2001-10-05 04:20:06 +04:00
2001-11-15 22:40:00 +03:00
if ( ! cm_get_dc_name ( domain , new_conn - > controller ) )
goto done ;
2001-10-05 04:20:06 +04:00
2001-11-15 22:40:00 +03:00
/* Return false if we have tried to look up this domain and netbios
name before and failed . */
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
for ( occ = open_connection_cache ; occ ; occ = occ - > next ) {
2001-11-28 02:48:44 +03:00
2001-11-15 22:40:00 +03:00
if ( ! ( strequal ( domain , occ - > domain_name ) & &
2001-11-28 02:48:44 +03:00
strequal ( new_conn - > controller , occ - > controller ) ) )
2001-11-15 22:40:00 +03:00
continue ; /* Not our domain */
2001-11-15 06:33:12 +03:00
2001-11-28 02:48:44 +03:00
if ( ( time ( NULL ) - occ - > lookup_time ) >
OPEN_CONNECTION_CACHE_TIMEOUT ) {
2001-11-15 22:40:00 +03:00
/* Cache entry has expired, delete it */
2001-11-15 06:33:12 +03:00
2001-11-28 02:48:44 +03:00
DEBUG ( 10 , ( " cm_open_connection cache entry expired for %s, %s \n " , domain , new_conn - > controller ) ) ;
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
DLIST_REMOVE ( open_connection_cache , occ ) ;
free ( occ ) ;
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
break ;
}
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
/* The timeout hasn't expired yet so return false */
2001-11-15 06:33:12 +03:00
2001-11-28 02:48:44 +03:00
DEBUG ( 10 , ( " returning negative open_connection_cache entry for %s, %s \n " , domain , new_conn - > controller ) ) ;
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
goto done ;
}
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
/* Initialise SMB connection */
2001-10-05 04:20:06 +04:00
2001-11-15 22:40:00 +03:00
if ( ! ( new_conn - > cli = cli_initialise ( NULL ) ) )
goto done ;
2001-10-05 04:20:06 +04:00
if ( ! resolve_srv_name ( new_conn - > controller , dest_host , & dest_ip ) )
goto done ;
2001-11-15 22:40:00 +03:00
make_nmb_name ( & called , dns_to_netbios_name ( new_conn - > controller ) , 0x20 ) ;
2001-10-05 04:20:06 +04:00
make_nmb_name ( & calling , dns_to_netbios_name ( global_myname ) , 0 ) ;
2001-12-11 08:19:15 +03:00
cm_init_creds ( & creds ) ;
2001-10-05 04:20:06 +04:00
2001-10-08 04:34:14 +04:00
cli_init_creds ( new_conn - > cli , & creds ) ;
2001-10-05 04:20:06 +04:00
2001-10-08 04:34:14 +04:00
if ( ! cli_establish_connection ( new_conn - > cli , new_conn - > controller ,
2001-11-28 02:48:44 +03:00
& dest_ip , & calling , & called , " IPC$ " ,
" IPC " , False , True ) )
2001-10-05 04:20:06 +04:00
goto done ;
2001-10-08 04:34:14 +04:00
if ( ! cli_nt_session_open ( new_conn - > cli , pipe_name ) )
2001-10-05 04:20:06 +04:00
goto done ;
2001-11-28 02:48:44 +03:00
result = True ;
2001-10-05 04:20:06 +04:00
done :
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
/* Create negative lookup cache entry for this domain and controller */
2001-11-15 06:33:12 +03:00
2001-11-15 22:40:00 +03:00
if ( ! result ) {
if ( ! ( occ = ( struct open_connection_cache * )
2001-11-28 02:48:44 +03:00
malloc ( sizeof ( struct open_connection_cache ) ) ) )
2001-11-15 22:40:00 +03:00
return False ;
2001-11-15 06:33:12 +03:00
2001-11-28 02:48:44 +03:00
ZERO_STRUCTP ( occ ) ;
2001-11-15 06:33:12 +03:00
2001-11-28 02:48:44 +03:00
fstrcpy ( occ - > domain_name , domain ) ;
fstrcpy ( occ - > controller , new_conn - > controller ) ;
occ - > lookup_time = time ( NULL ) ;
DLIST_ADD ( open_connection_cache , occ ) ;
2001-11-15 22:40:00 +03:00
}
2001-10-05 04:20:06 +04:00
2001-11-15 22:40:00 +03:00
if ( ! result & & new_conn - > cli )
cli_shutdown ( new_conn - > cli ) ;
return result ;
2001-10-05 04:20:06 +04:00
}
2001-10-27 08:48:22 +04:00
/* Return true if a connection is still alive */
static BOOL connection_ok ( struct winbindd_cm_conn * conn )
{
2001-11-15 22:40:00 +03:00
if ( ! conn - > cli - > initialised )
return False ;
2001-10-27 08:48:22 +04:00
2001-11-15 22:40:00 +03:00
if ( conn - > cli - > fd = = - 1 )
return False ;
2001-10-27 08:48:22 +04:00
2001-11-15 22:40:00 +03:00
return True ;
2001-10-27 08:48:22 +04:00
}
2001-10-05 04:20:06 +04:00
/* Return a LSA policy handle on a domain */
CLI_POLICY_HND * cm_get_lsa_handle ( char * domain )
{
2001-11-15 22:40:00 +03:00
struct winbindd_cm_conn * conn ;
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED ;
NTSTATUS result ;
static CLI_POLICY_HND hnd ;
2001-10-05 04:20:06 +04:00
2001-11-15 22:40:00 +03:00
/* Look for existing connections */
2001-10-05 04:20:06 +04:00
2001-11-15 22:40:00 +03:00
for ( conn = cm_conns ; conn ; conn = conn - > next ) {
2001-11-28 02:48:44 +03:00
if ( strequal ( conn - > domain , domain ) & &
strequal ( conn - > pipe_name , PIPE_LSARPC ) ) {
2001-10-27 08:48:22 +04:00
2001-11-15 22:40:00 +03:00
if ( ! connection_ok ( conn ) ) {
DLIST_REMOVE ( cm_conns , conn ) ;
return NULL ;
}
2001-10-27 08:48:22 +04:00
2001-11-15 22:40:00 +03:00
goto ok ;
}
}
2001-10-05 04:20:06 +04:00
2001-11-15 22:40:00 +03:00
/* Create a new one */
2001-10-05 04:20:06 +04:00
2001-11-15 22:40:00 +03:00
if ( ! ( conn = ( struct winbindd_cm_conn * ) malloc ( sizeof ( struct winbindd_cm_conn ) ) ) )
return NULL ;
2001-10-05 04:20:06 +04:00
2001-11-15 22:40:00 +03:00
ZERO_STRUCTP ( conn ) ;
2001-10-08 04:34:14 +04:00
2001-11-15 22:40:00 +03:00
if ( ! cm_open_connection ( domain , PIPE_LSARPC , conn ) ) {
DEBUG ( 3 , ( " Could not connect to a dc for domain %s \n " , domain ) ) ;
return NULL ;
}
2001-10-05 04:20:06 +04:00
2001-11-28 02:48:44 +03:00
result = cli_lsa_open_policy ( conn - > cli , conn - > cli - > mem_ctx , False ,
des_access , & conn - > pol ) ;
2001-10-05 04:20:06 +04:00
2001-11-15 22:40:00 +03:00
if ( ! NT_STATUS_IS_OK ( result ) )
return NULL ;
2001-10-05 04:20:06 +04:00
2001-11-15 22:40:00 +03:00
/* Add to list */
2001-10-05 04:20:06 +04:00
2001-11-15 22:40:00 +03:00
DLIST_ADD ( cm_conns , conn ) ;
2001-10-05 04:20:06 +04:00
ok :
2001-11-15 22:40:00 +03:00
hnd . pol = conn - > pol ;
hnd . cli = conn - > cli ;
2001-10-05 04:20:06 +04:00
2001-11-15 22:40:00 +03:00
return & hnd ;
2001-10-05 04:20:06 +04:00
}
/* Return a SAM policy handle on a domain */
CLI_POLICY_HND * cm_get_sam_handle ( char * domain )
{
2001-11-15 22:40:00 +03:00
struct winbindd_cm_conn * conn ;
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED ;
NTSTATUS result ;
static CLI_POLICY_HND hnd ;
2001-10-08 04:34:14 +04:00
2001-11-15 22:40:00 +03:00
/* Look for existing connections */
2001-10-08 04:34:14 +04:00
2001-11-15 22:40:00 +03:00
for ( conn = cm_conns ; conn ; conn = conn - > next ) {
if ( strequal ( conn - > domain , domain ) & & strequal ( conn - > pipe_name , PIPE_SAMR ) ) {
2001-10-27 08:48:22 +04:00
2001-11-15 22:40:00 +03:00
if ( ! connection_ok ( conn ) ) {
DLIST_REMOVE ( cm_conns , conn ) ;
return NULL ;
}
2001-10-27 08:48:22 +04:00
2001-11-15 22:40:00 +03:00
goto ok ;
}
}
2001-10-08 04:34:14 +04:00
2001-11-15 22:40:00 +03:00
/* Create a new one */
2001-10-08 04:34:14 +04:00
2001-11-28 02:48:44 +03:00
if ( ! ( conn = ( struct winbindd_cm_conn * )
malloc ( sizeof ( struct winbindd_cm_conn ) ) ) )
2001-11-15 22:40:00 +03:00
return NULL ;
2001-10-08 04:34:14 +04:00
2001-11-15 22:40:00 +03:00
ZERO_STRUCTP ( conn ) ;
2001-10-08 04:34:14 +04:00
2001-11-15 22:40:00 +03:00
if ( ! cm_open_connection ( domain , PIPE_SAMR , conn ) ) {
DEBUG ( 3 , ( " Could not connect to a dc for domain %s \n " , domain ) ) ;
return NULL ;
}
2001-10-08 04:34:14 +04:00
2001-11-28 02:48:44 +03:00
result = cli_samr_connect ( conn - > cli , conn - > cli - > mem_ctx ,
des_access , & conn - > pol ) ;
2001-10-08 04:34:14 +04:00
2001-11-15 22:40:00 +03:00
if ( ! NT_STATUS_IS_OK ( result ) )
return NULL ;
2001-10-08 04:34:14 +04:00
2001-11-15 22:40:00 +03:00
/* Add to list */
2001-10-08 04:34:14 +04:00
2001-11-15 22:40:00 +03:00
DLIST_ADD ( cm_conns , conn ) ;
2001-10-08 04:34:14 +04:00
ok :
2001-11-15 22:40:00 +03:00
hnd . pol = conn - > pol ;
hnd . cli = conn - > cli ;
2001-10-08 04:34:14 +04:00
2001-11-28 02:48:44 +03:00
return & hnd ;
2001-10-05 04:20:06 +04:00
}
2001-11-15 09:55:56 +03:00
#if 0
2001-10-05 04:20:06 +04:00
/* Return a SAM domain policy handle on a domain */
2001-10-08 04:34:14 +04:00
CLI_POLICY_HND * cm_get_sam_dom_handle ( char * domain , DOM_SID * domain_sid )
2001-10-05 04:20:06 +04:00
{
2001-11-28 02:48:44 +03:00
struct winbindd_cm_conn * conn , * basic_conn = NULL ;
static CLI_POLICY_HND hnd ;
NTSTATUS result ;
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED ;
2001-10-08 04:34:14 +04:00
2001-11-28 02:48:44 +03:00
/* Look for existing connections */
2001-10-08 04:34:14 +04:00
2001-11-28 02:48:44 +03:00
for ( conn = cm_conns ; conn ; conn = conn - > next ) {
if ( strequal ( conn - > domain , domain ) & &
strequal ( conn - > pipe_name , PIPE_SAMR ) & &
conn - > pipe_data . samr . pipe_type = = SAM_PIPE_DOM ) {
2001-10-27 08:48:22 +04:00
2001-11-28 02:48:44 +03:00
if ( ! connection_ok ( conn ) ) {
DLIST_REMOVE ( cm_conns , conn ) ;
return NULL ;
}
2001-10-27 08:48:22 +04:00
2001-11-28 02:48:44 +03:00
goto ok ;
}
}
2001-10-08 04:34:14 +04:00
2001-11-28 02:48:44 +03:00
/* Create a basic handle to open a domain handle from */
2001-10-08 04:34:14 +04:00
2001-11-28 02:48:44 +03:00
if ( ! cm_get_sam_handle ( domain ) )
return False ;
2001-10-08 04:34:14 +04:00
2001-11-28 02:48:44 +03:00
for ( conn = cm_conns ; conn ; conn = conn - > next ) {
if ( strequal ( conn - > domain , domain ) & &
strequal ( conn - > pipe_name , PIPE_SAMR ) & &
conn - > pipe_data . samr . pipe_type = = SAM_PIPE_BASIC )
basic_conn = conn ;
}
if ( ! ( conn = ( struct winbindd_cm_conn * )
malloc ( sizeof ( struct winbindd_cm_conn ) ) ) )
return NULL ;
ZERO_STRUCTP ( conn ) ;
2001-10-08 04:34:14 +04:00
2001-11-28 02:48:44 +03:00
fstrcpy ( conn - > domain , basic_conn - > domain ) ;
fstrcpy ( conn - > controller , basic_conn - > controller ) ;
fstrcpy ( conn - > pipe_name , basic_conn - > pipe_name ) ;
2001-10-08 04:34:14 +04:00
2001-11-28 02:48:44 +03:00
conn - > pipe_data . samr . pipe_type = SAM_PIPE_DOM ;
conn - > cli = basic_conn - > cli ;
2001-10-08 04:34:14 +04:00
2001-11-28 02:48:44 +03:00
result = cli_samr_open_domain ( conn - > cli , conn - > cli - > mem_ctx ,
& basic_conn - > pol , des_access ,
domain_sid , & conn - > pol ) ;
2001-10-08 04:34:14 +04:00
2001-11-28 02:48:44 +03:00
if ( ! NT_STATUS_IS_OK ( result ) )
return NULL ;
2001-10-08 04:34:14 +04:00
2001-11-28 02:48:44 +03:00
/* Add to list */
2001-10-08 04:34:14 +04:00
2001-11-28 02:48:44 +03:00
DLIST_ADD ( cm_conns , conn ) ;
2001-10-08 04:34:14 +04:00
ok :
2001-11-28 02:48:44 +03:00
hnd . pol = conn - > pol ;
hnd . cli = conn - > cli ;
2001-10-08 04:34:14 +04:00
2001-11-28 02:48:44 +03:00
return & hnd ;
2001-10-05 04:20:06 +04:00
}
/* Return a SAM policy handle on a domain user */
2001-10-08 04:34:14 +04:00
CLI_POLICY_HND * cm_get_sam_user_handle ( char * domain , DOM_SID * domain_sid ,
2001-11-28 02:48:44 +03:00
uint32 user_rid )
2001-10-05 04:20:06 +04:00
{
2001-11-28 02:48:44 +03:00
struct winbindd_cm_conn * conn , * basic_conn = NULL ;
static CLI_POLICY_HND hnd ;
NTSTATUS result ;
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED ;
/* Look for existing connections */
for ( conn = cm_conns ; conn ; conn = conn - > next ) {
if ( strequal ( conn - > domain , domain ) & &
strequal ( conn - > pipe_name , PIPE_SAMR ) & &
conn - > pipe_data . samr . pipe_type = = SAM_PIPE_USER & &
conn - > pipe_data . samr . rid = = user_rid ) {
if ( ! connection_ok ( conn ) ) {
DLIST_REMOVE ( cm_conns , conn ) ;
return NULL ;
}
goto ok ;
}
}
/* Create a domain handle to open a user handle from */
if ( ! cm_get_sam_dom_handle ( domain , domain_sid ) )
return NULL ;
for ( conn = cm_conns ; conn ; conn = conn - > next ) {
if ( strequal ( conn - > domain , domain ) & &
strequal ( conn - > pipe_name , PIPE_SAMR ) & &
conn - > pipe_data . samr . pipe_type = = SAM_PIPE_DOM )
basic_conn = conn ;
}
if ( ! basic_conn ) {
DEBUG ( 0 , ( " No domain sam handle was created! \n " ) ) ;
return NULL ;
}
if ( ! ( conn = ( struct winbindd_cm_conn * )
malloc ( sizeof ( struct winbindd_cm_conn ) ) ) )
return NULL ;
ZERO_STRUCTP ( conn ) ;
fstrcpy ( conn - > domain , basic_conn - > domain ) ;
fstrcpy ( conn - > controller , basic_conn - > controller ) ;
fstrcpy ( conn - > pipe_name , basic_conn - > pipe_name ) ;
conn - > pipe_data . samr . pipe_type = SAM_PIPE_USER ;
conn - > cli = basic_conn - > cli ;
conn - > pipe_data . samr . rid = user_rid ;
result = cli_samr_open_user ( conn - > cli , conn - > cli - > mem_ctx ,
& basic_conn - > pol , des_access , user_rid ,
& conn - > pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) )
return NULL ;
/* Add to list */
DLIST_ADD ( cm_conns , conn ) ;
2001-10-08 04:34:14 +04:00
ok :
2001-11-28 02:48:44 +03:00
hnd . pol = conn - > pol ;
hnd . cli = conn - > cli ;
2001-10-08 04:34:14 +04:00
2001-11-28 02:48:44 +03:00
return & hnd ;
2001-10-05 04:20:06 +04:00
}
/* Return a SAM policy handle on a domain group */
2001-10-10 02:55:00 +04:00
CLI_POLICY_HND * cm_get_sam_group_handle ( char * domain , DOM_SID * domain_sid ,
2001-11-28 02:48:44 +03:00
uint32 group_rid )
2001-10-05 04:20:06 +04:00
{
2001-11-28 02:48:44 +03:00
struct winbindd_cm_conn * conn , * basic_conn = NULL ;
static CLI_POLICY_HND hnd ;
NTSTATUS result ;
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED ;
/* Look for existing connections */
for ( conn = cm_conns ; conn ; conn = conn - > next ) {
if ( strequal ( conn - > domain , domain ) & &
strequal ( conn - > pipe_name , PIPE_SAMR ) & &
conn - > pipe_data . samr . pipe_type = = SAM_PIPE_GROUP & &
conn - > pipe_data . samr . rid = = group_rid ) {
if ( ! connection_ok ( conn ) ) {
DLIST_REMOVE ( cm_conns , conn ) ;
return NULL ;
}
goto ok ;
}
}
/* Create a domain handle to open a user handle from */
if ( ! cm_get_sam_dom_handle ( domain , domain_sid ) )
return NULL ;
for ( conn = cm_conns ; conn ; conn = conn - > next ) {
if ( strequal ( conn - > domain , domain ) & &
strequal ( conn - > pipe_name , PIPE_SAMR ) & &
conn - > pipe_data . samr . pipe_type = = SAM_PIPE_DOM )
basic_conn = conn ;
}
if ( ! basic_conn ) {
DEBUG ( 0 , ( " No domain sam handle was created! \n " ) ) ;
return NULL ;
}
if ( ! ( conn = ( struct winbindd_cm_conn * )
malloc ( sizeof ( struct winbindd_cm_conn ) ) ) )
return NULL ;
ZERO_STRUCTP ( conn ) ;
fstrcpy ( conn - > domain , basic_conn - > domain ) ;
fstrcpy ( conn - > controller , basic_conn - > controller ) ;
fstrcpy ( conn - > pipe_name , basic_conn - > pipe_name ) ;
conn - > pipe_data . samr . pipe_type = SAM_PIPE_GROUP ;
conn - > cli = basic_conn - > cli ;
conn - > pipe_data . samr . rid = group_rid ;
result = cli_samr_open_group ( conn - > cli , conn - > cli - > mem_ctx ,
& basic_conn - > pol , des_access , group_rid ,
& conn - > pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) )
return NULL ;
/* Add to list */
DLIST_ADD ( cm_conns , conn ) ;
2001-10-10 02:55:00 +04:00
ok :
2001-11-28 02:48:44 +03:00
hnd . pol = conn - > pol ;
hnd . cli = conn - > cli ;
2001-10-10 02:55:00 +04:00
2001-11-28 02:48:44 +03:00
return & hnd ;
2001-10-05 04:20:06 +04:00
}
2001-11-05 03:21:17 +03:00
2001-11-15 09:55:56 +03:00
# endif
/* Get a handle on a netlogon pipe. This is a bit of a hack to re-use the
netlogon pipe as no handle is returned . */
2001-11-05 03:21:17 +03:00
2001-11-23 03:14:04 +03:00
NTSTATUS cm_get_netlogon_cli ( char * domain , unsigned char * trust_passwd ,
2001-11-28 02:48:44 +03:00
struct cli_state * * cli )
2001-11-05 03:21:17 +03:00
{
2001-11-15 22:40:00 +03:00
struct winbindd_cm_conn conn ;
2001-11-23 03:14:04 +03:00
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
2001-11-05 03:21:17 +03:00
2001-11-15 22:40:00 +03:00
/* Open an initial conection */
2001-11-05 03:21:17 +03:00
2001-11-15 22:40:00 +03:00
ZERO_STRUCT ( conn ) ;
2001-11-05 03:21:17 +03:00
2001-11-15 22:40:00 +03:00
if ( ! cm_open_connection ( domain , PIPE_NETLOGON , & conn ) ) {
DEBUG ( 3 , ( " Could not open a connection to %s \n " , domain ) ) ;
2001-11-28 02:48:44 +03:00
return result ;
2001-11-15 22:40:00 +03:00
}
2001-11-05 03:21:17 +03:00
2001-11-15 22:40:00 +03:00
result = cli_nt_setup_creds ( conn . cli , trust_passwd ) ;
2001-11-05 03:21:17 +03:00
2001-11-15 22:40:00 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
DEBUG ( 0 , ( " error connecting to domain password server: %s \n " ,
get_nt_error_msg ( result ) ) ) ;
cli_shutdown ( conn . cli ) ;
2001-11-28 02:48:44 +03:00
return result ;
2001-11-15 22:40:00 +03:00
}
2001-11-05 03:21:17 +03:00
2001-11-28 02:48:44 +03:00
if ( cli )
* cli = conn . cli ;
2001-11-05 03:21:17 +03:00
2001-11-28 02:48:44 +03:00
return result ;
2001-11-05 03:21:17 +03:00
}
2001-11-14 09:18:13 +03:00
/* Dump the current connection status */
static void dump_conn_list ( void )
{
2001-11-15 22:40:00 +03:00
struct winbindd_cm_conn * con ;
2001-11-14 09:18:13 +03:00
2001-11-28 02:48:44 +03:00
DEBUG ( 0 , ( " \t Domain Controller Pipe \n " ) ) ;
2001-11-14 09:18:13 +03:00
2001-11-15 22:40:00 +03:00
for ( con = cm_conns ; con ; con = con - > next ) {
char * msg ;
2001-11-14 09:18:13 +03:00
2001-11-15 22:40:00 +03:00
/* Display pipe info */
2001-11-28 02:48:44 +03:00
2001-11-15 22:40:00 +03:00
asprintf ( & msg , " \t %-15s %-15s %-16s " , con - > domain , con - > controller , con - > pipe_name ) ;
2001-11-28 02:48:44 +03:00
2001-11-15 22:40:00 +03:00
DEBUG ( 0 , ( " %s \n " , msg ) ) ;
free ( msg ) ;
}
2001-11-14 09:18:13 +03:00
}
void winbindd_cm_status ( void )
{
2001-11-15 22:40:00 +03:00
/* List open connections */
2001-11-14 09:18:13 +03:00
2001-11-15 22:40:00 +03:00
DEBUG ( 0 , ( " winbindd connection manager status: \n " ) ) ;
2001-11-14 09:18:13 +03:00
2001-11-15 22:40:00 +03:00
if ( cm_conns )
dump_conn_list ( ) ;
else
DEBUG ( 0 , ( " \t No active connections \n " ) ) ;
2001-11-14 09:18:13 +03:00
}