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
pstring servicesf = CONFIGFILE ;
2000-05-09 15:43:00 +04:00
/* List of all connected clients */
2001-05-07 08:32:40 +04:00
struct winbindd_cli_state * client_list ;
static int num_clients ;
2000-05-09 15:43:00 +04:00
/* Reload configuration */
2001-05-07 08:32:40 +04:00
static BOOL reload_services_file ( BOOL test )
2000-05-09 15:43:00 +04:00
{
BOOL ret ;
2001-05-07 08:32:40 +04:00
if ( lp_loaded ( ) ) {
pstring fname ;
pstrcpy ( fname , lp_configfile ( ) ) ;
if ( file_exist ( fname , NULL ) & & ! strcsequal ( fname , servicesf ) ) {
pstrcpy ( servicesf , fname ) ;
test = False ;
}
}
2000-05-09 15:43:00 +04:00
reopen_logs ( ) ;
ret = lp_load ( servicesf , False , False , True ) ;
reopen_logs ( ) ;
load_interfaces ( ) ;
return ( ret ) ;
}
2001-09-10 15:34:32 +04:00
static void winbindd_dump_status ( void )
2000-05-09 15:43:00 +04:00
{
2001-05-07 08:32:40 +04:00
struct winbindd_cli_state * tmp ;
DEBUG ( 0 , ( " Global status for winbindd: \n " ) ) ;
/* Print client state information */
DEBUG ( 0 , ( " \t %d clients currently active \n " , num_clients ) ) ;
if ( DEBUGLEVEL > = 2 ) {
DEBUG ( 2 , ( " \t client list: \n " ) ) ;
for ( tmp = client_list ; tmp ; tmp = tmp - > next ) {
DEBUG ( 2 , ( " \t \t pid %d, sock %d, rbl %d, wbl %d \n " ,
tmp - > pid , tmp - > sock , tmp - > read_buf_len ,
tmp - > write_buf_len ) ) ;
}
}
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Print winbindd status to log file */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
static void do_print_winbindd_status ( void )
{
winbindd_dump_status ( ) ;
winbindd_idmap_dump_status ( ) ;
winbindd_cache_dump_status ( ) ;
2000-05-09 15:43:00 +04:00
}
/* Flush client cache */
static void do_flush_caches ( void )
{
2001-05-07 08:32:40 +04:00
/* Clear cached user and group enumation info */
winbindd_flush_cache ( ) ;
2000-05-09 15:43:00 +04:00
}
/* Handle the signal by unlinking socket and exiting */
static void termination_handler ( int signum )
{
2001-05-07 08:32:40 +04:00
pstring path ;
/* Remove socket file */
snprintf ( path , sizeof ( path ) , " %s/%s " ,
WINBINDD_SOCKET_DIR , WINBINDD_SOCKET_NAME ) ;
unlink ( path ) ;
exit ( 0 ) ;
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
static BOOL print_winbindd_status ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
static void sigusr1_handler ( int signum )
{
BlockSignals ( True , SIGUSR1 ) ;
print_winbindd_status = True ;
BlockSignals ( False , SIGUSR1 ) ;
2000-05-09 15:43:00 +04:00
}
2001-05-07 08:32:40 +04:00
static BOOL do_sighup ;
2000-05-09 15:43:00 +04:00
static void sighup_handler ( int signum )
{
2001-05-07 08:32:40 +04:00
BlockSignals ( True , SIGHUP ) ;
do_sighup = True ;
BlockSignals ( False , SIGHUP ) ;
2000-05-09 15:43:00 +04:00
}
/* Create winbindd socket */
static int create_sock ( void )
{
2001-10-05 04:20:06 +04:00
struct sockaddr_un sunaddr ;
struct stat st ;
int sock ;
mode_t old_umask ;
pstring path ;
/* Create the socket directory or reuse the existing one */
if ( lstat ( WINBINDD_SOCKET_DIR , & st ) = = - 1 ) {
if ( errno = = ENOENT ) {
/* Create directory */
if ( mkdir ( WINBINDD_SOCKET_DIR , 0755 ) = = - 1 ) {
DEBUG ( 0 , ( " error creating socket directory "
" %s: %s \n " , WINBINDD_SOCKET_DIR ,
strerror ( errno ) ) ) ;
return - 1 ;
}
} else {
DEBUG ( 0 , ( " lstat failed on socket directory %s: %s \n " ,
WINBINDD_SOCKET_DIR , strerror ( errno ) ) ) ;
return - 1 ;
}
2000-05-09 15:43:00 +04:00
} else {
2001-10-05 04:20:06 +04:00
/* Check ownership and permission on existing directory */
if ( ! S_ISDIR ( st . st_mode ) ) {
DEBUG ( 0 , ( " socket directory %s isn't a directory \n " ,
WINBINDD_SOCKET_DIR ) ) ;
return - 1 ;
}
if ( ( st . st_uid ! = sec_initial_uid ( ) ) | |
( ( st . st_mode & 0777 ) ! = 0755 ) ) {
DEBUG ( 0 , ( " invalid permissions on socket directory "
" %s \n " , WINBINDD_SOCKET_DIR ) ) ;
return - 1 ;
}
2000-05-09 15:43:00 +04:00
}
2001-10-05 04:20:06 +04:00
/* Create the socket file */
old_umask = umask ( 0 ) ;
sock = socket ( AF_UNIX , SOCK_STREAM , 0 ) ;
if ( sock = = - 1 ) {
perror ( " socket " ) ;
return - 1 ;
2000-05-09 15:43:00 +04:00
}
2001-10-05 04:20:06 +04:00
snprintf ( path , sizeof ( path ) , " %s/%s " ,
WINBINDD_SOCKET_DIR , WINBINDD_SOCKET_NAME ) ;
unlink ( path ) ;
memset ( & sunaddr , 0 , sizeof ( sunaddr ) ) ;
sunaddr . sun_family = AF_UNIX ;
safe_strcpy ( sunaddr . sun_path , path , sizeof ( sunaddr . sun_path ) - 1 ) ;
if ( bind ( sock , ( struct sockaddr * ) & sunaddr , sizeof ( sunaddr ) ) = = - 1 ) {
DEBUG ( 0 , ( " bind failed on winbind socket %s: %s \n " ,
path ,
strerror ( errno ) ) ) ;
close ( sock ) ;
return - 1 ;
2000-05-09 15:43:00 +04:00
}
2001-10-05 04:20:06 +04:00
if ( listen ( sock , 5 ) = = - 1 ) {
DEBUG ( 0 , ( " listen failed on winbind socket %s: %s \n " ,
path ,
strerror ( errno ) ) ) ;
close ( sock ) ;
return - 1 ;
}
umask ( old_umask ) ;
/* Success! */
return sock ;
2000-05-09 15:43:00 +04:00
}
2001-05-07 08:32:40 +04:00
struct dispatch_table {
enum winbindd_cmd cmd ;
enum winbindd_result ( * fn ) ( struct winbindd_cli_state * state ) ;
} ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
static struct dispatch_table dispatch_table [ ] = {
/* User functions */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
{ WINBINDD_GETPWNAM_FROM_USER , winbindd_getpwnam_from_user } ,
{ WINBINDD_GETPWNAM_FROM_UID , winbindd_getpwnam_from_uid } ,
2001-10-05 04:20:06 +04:00
#if 0
2001-05-07 08:32:40 +04:00
{ WINBINDD_SETPWENT , winbindd_setpwent } ,
{ WINBINDD_ENDPWENT , winbindd_endpwent } ,
{ WINBINDD_GETPWENT , winbindd_getpwent } ,
2001-10-05 04:20:06 +04:00
2001-05-07 08:32:40 +04:00
{ WINBINDD_GETGROUPS , winbindd_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 , winbindd_getgrnam_from_group } ,
{ WINBINDD_GETGRNAM_FROM_GID , winbindd_getgrnam_from_gid } ,
{ WINBINDD_SETGRENT , winbindd_setgrent } ,
{ WINBINDD_ENDGRENT , winbindd_endgrent } ,
{ WINBINDD_GETGRENT , winbindd_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 , winbindd_pam_auth } ,
2001-08-22 06:48:16 +04:00
{ WINBINDD_PAM_AUTH_CRAP , winbindd_pam_auth_crap } ,
2001-05-07 08:32:40 +04:00
{ WINBINDD_PAM_CHAUTHTOK , winbindd_pam_chauthtok } ,
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Enumeration functions */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
{ WINBINDD_LIST_USERS , winbindd_list_users } ,
{ WINBINDD_LIST_GROUPS , winbindd_list_groups } ,
{ WINBINDD_LIST_TRUSTDOM , winbindd_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 , winbindd_lookupsid } ,
{ WINBINDD_LOOKUPNAME , winbindd_lookupname } ,
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 , winbindd_sid_to_uid } ,
{ WINBINDD_SID_TO_GID , winbindd_sid_to_gid } ,
{ WINBINDD_GID_TO_SID , winbindd_gid_to_sid } ,
{ WINBINDD_UID_TO_SID , winbindd_uid_to_sid } ,
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Miscellaneous */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
{ WINBINDD_CHECK_MACHACC , winbindd_check_machine_acct } ,
2000-05-09 15:43:00 +04:00
2001-10-05 04:20:06 +04:00
# endif
2001-05-07 08:32:40 +04:00
/* End of list */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
{ WINBINDD_NUM_CMDS , NULL }
} ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
static void process_request ( struct winbindd_cli_state * state )
2000-05-09 15:43:00 +04:00
{
2001-05-07 08:32:40 +04:00
struct dispatch_table * table = dispatch_table ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Free response data - we may be interrupted and receive another
command before being able to send this data off . */
2000-05-09 15:43:00 +04:00
2001-09-17 08:52:45 +04:00
SAFE_FREE ( state - > response . extra_data ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
ZERO_STRUCT ( state - > response ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
state - > response . result = WINBINDD_ERROR ;
state - > response . length = sizeof ( struct winbindd_response ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Process command */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
for ( table = dispatch_table ; table - > fn ; table + + ) {
if ( state - > request . cmd = = table - > cmd ) {
state - > response . result = table - > fn ( state ) ;
break ;
}
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* In case extra data pointer is NULL */
2000-05-09 15:43:00 +04:00
2001-10-05 04:20:06 +04:00
if ( ! state - > response . extra_data )
2001-05-07 08:32:40 +04:00
state - > response . length = sizeof ( struct winbindd_response ) ;
2000-05-09 15:43:00 +04:00
}
2001-05-07 08:32:40 +04:00
/* Process a new connection by adding it to the client connection list */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
static void new_connection ( int accept_sock )
2000-05-09 15:43:00 +04:00
{
2001-05-07 08:32:40 +04:00
struct sockaddr_un sunaddr ;
struct winbindd_cli_state * state ;
2001-06-25 06:53:13 +04:00
socklen_t len ;
int sock ;
2001-05-07 08:32:40 +04:00
/* Accept connection */
len = sizeof ( sunaddr ) ;
if ( ( sock = accept ( accept_sock , ( struct sockaddr * ) & sunaddr , & len ) )
2001-10-05 04:20:06 +04:00
= = - 1 )
2001-05-07 08:32:40 +04:00
return ;
DEBUG ( 6 , ( " accepted socket %d \n " , sock ) ) ;
/* Create new connection structure */
2001-10-05 04:20:06 +04:00
if ( ( state = ( struct winbindd_cli_state * )
malloc ( sizeof ( * state ) ) ) = = NULL )
2001-05-07 08:32:40 +04:00
return ;
ZERO_STRUCTP ( state ) ;
state - > sock = sock ;
/* Add to connection list */
DLIST_ADD ( client_list , state ) ;
num_clients + + ;
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Remove a client connection from client connection list */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
static void remove_client ( struct winbindd_cli_state * state )
{
/* It's a dead client - hold a funeral */
if ( state ! = NULL ) {
/* Close socket */
close ( state - > sock ) ;
/* Free any getent state */
free_getent_state ( state - > getpwent_state ) ;
free_getent_state ( state - > getgrent_state ) ;
/* We may have some extra data that was not freed if the
client was killed unexpectedly */
2001-09-17 08:52:45 +04:00
SAFE_FREE ( state - > response . extra_data ) ;
2001-05-07 08:32:40 +04:00
/* Remove from list and free */
DLIST_REMOVE ( client_list , state ) ;
2001-09-17 08:52:45 +04:00
SAFE_FREE ( state ) ;
2001-05-07 08:32:40 +04:00
num_clients - - ;
}
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Process a complete received packet from a client */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
static void process_packet ( struct winbindd_cli_state * state )
{
/* Process request */
state - > pid = state - > request . pid ;
process_request ( state ) ;
/* Update client state */
state - > read_buf_len = 0 ;
state - > write_buf_len = sizeof ( struct winbindd_response ) ;
2000-05-09 15:43:00 +04:00
}
/* Read some data from a client connection */
static void client_read ( struct winbindd_cli_state * state )
{
2001-05-07 08:32:40 +04:00
int n ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Read data */
n = read ( state - > sock , state - > read_buf_len + ( char * ) & state - > request ,
sizeof ( state - > request ) - state - > read_buf_len ) ;
/* Read failed, kill client */
if ( n = = - 1 | | n = = 0 ) {
DEBUG ( 5 , ( " read failed on sock %d, pid %d: %s \n " ,
state - > sock , state - > pid ,
( n = = - 1 ) ? strerror ( errno ) : " EOF " ) ) ;
state - > finished = True ;
return ;
}
/* Update client state */
state - > read_buf_len + = n ;
2000-05-09 15:43:00 +04:00
}
/* Write some data to a client connection */
static void client_write ( struct winbindd_cli_state * state )
{
2001-05-07 08:32:40 +04:00
char * data ;
int num_written ;
/* Write some data */
if ( ! state - > write_extra_data ) {
/* Write response structure */
data = ( char * ) & state - > response + sizeof ( state - > response ) -
state - > write_buf_len ;
} else {
/* Write extra data */
data = ( char * ) state - > response . extra_data +
state - > response . length -
sizeof ( struct winbindd_response ) -
state - > write_buf_len ;
}
num_written = write ( state - > sock , data , state - > write_buf_len ) ;
/* Write failed, kill cilent */
if ( num_written = = - 1 | | num_written = = 0 ) {
DEBUG ( 3 , ( " write failed on sock %d, pid %d: %s \n " ,
state - > sock , state - > pid ,
( num_written = = - 1 ) ? strerror ( errno ) : " EOF " ) ) ;
state - > finished = True ;
2001-09-17 08:52:45 +04:00
SAFE_FREE ( state - > response . extra_data ) ;
2001-05-07 08:32:40 +04:00
return ;
}
/* Update client state */
state - > write_buf_len - = num_written ;
/* Have we written all data? */
if ( state - > write_buf_len = = 0 ) {
/* Take care of extra data */
if ( state - > write_extra_data ) {
2001-09-17 08:52:45 +04:00
SAFE_FREE ( state - > response . extra_data ) ;
2001-05-07 08:32:40 +04:00
state - > write_extra_data = False ;
} else if ( state - > response . length >
sizeof ( struct winbindd_response ) ) {
/* Start writing extra data */
state - > write_buf_len =
state - > response . length -
sizeof ( struct winbindd_response ) ;
state - > write_extra_data = True ;
}
}
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Process incoming clients on accept_sock. We use a tricky non-blocking,
non - forking , non - threaded model which allows us to handle many
simultaneous connections while remaining impervious to many denial of
service attacks . */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
static void process_loop ( int accept_sock )
{
/* We'll be doing this a lot */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
while ( 1 ) {
struct winbindd_cli_state * state ;
fd_set r_fds , w_fds ;
int maxfd = accept_sock , selret ;
struct timeval timeout ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Free up temporary memory */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
lp_talloc_free ( ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Initialise fd lists for select() */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
FD_ZERO ( & r_fds ) ;
FD_ZERO ( & w_fds ) ;
FD_SET ( accept_sock , & r_fds ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
timeout . tv_sec = WINBINDD_ESTABLISH_LOOP ;
timeout . tv_usec = 0 ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Set up client readers and writers */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
state = client_list ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
while ( state ) {
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Dispose of client connection if it is marked as
finished */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
if ( state - > finished ) {
struct winbindd_cli_state * next = state - > next ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
remove_client ( state ) ;
state = next ;
continue ;
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Select requires we know the highest fd used */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
if ( state - > sock > maxfd ) maxfd = state - > sock ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Add fd for reading */
2000-05-09 15:43:00 +04:00
2001-10-05 04:20:06 +04:00
if ( state - > read_buf_len ! = sizeof ( state - > request ) )
2001-05-07 08:32:40 +04:00
FD_SET ( state - > sock , & r_fds ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Add fd for writing */
2000-05-09 15:43:00 +04:00
2001-10-05 04:20:06 +04:00
if ( state - > write_buf_len )
2001-05-07 08:32:40 +04:00
FD_SET ( state - > sock , & w_fds ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
state = state - > next ;
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Check signal handling things */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
if ( do_sighup ) {
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Flush winbindd cache */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
do_flush_caches ( ) ;
reload_services_file ( True ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
do_sighup = False ;
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
if ( print_winbindd_status ) {
do_print_winbindd_status ( ) ;
print_winbindd_status = False ;
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Call select */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
selret = select ( maxfd + 1 , & r_fds , & w_fds , NULL , & timeout ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
if ( selret = = 0 ) continue ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
if ( ( selret = = - 1 & & errno ! = EINTR ) | | selret = = 0 ) {
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Select error, something is badly wrong */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
perror ( " select " ) ;
exit ( 1 ) ;
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Create a new connection if accept_sock readable */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
if ( selret > 0 ) {
2000-05-09 15:43:00 +04:00
2001-10-05 04:20:06 +04:00
if ( FD_ISSET ( accept_sock , & r_fds ) )
2001-05-07 08:32:40 +04:00
new_connection ( accept_sock ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Process activity on client connections */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
for ( state = client_list ; state ; state = state - > next ) {
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Data available for reading */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
if ( FD_ISSET ( state - > sock , & r_fds ) ) {
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Read data */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
client_read ( state ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* A request packet might be
complete */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
if ( state - > read_buf_len = =
sizeof ( state - > request ) ) {
process_packet ( state ) ;
}
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Data available for writing */
2000-05-09 15:43:00 +04:00
2001-10-05 04:20:06 +04:00
if ( FD_ISSET ( state - > sock , & w_fds ) )
2001-05-07 08:32:40 +04:00
client_write ( state ) ;
}
}
}
2000-05-09 15:43:00 +04:00
}
/* Main function */
struct winbindd_state server_state ; /* Server state information */
int main ( int argc , char * * argv )
{
2001-05-07 08:32:40 +04:00
extern pstring global_myname ;
extern pstring debugf ;
int accept_sock ;
BOOL interactive = False ;
int opt , new_debuglevel = - 1 ;
2001-10-05 04:20:06 +04:00
/* Initialise for running in non-root mode */
2001-07-08 22:25:19 +04:00
sec_init ( ) ;
2001-05-08 07:52:07 +04:00
2001-05-07 08:32:40 +04:00
/* Set environment variable so we don't recursively call ourselves.
This may also be useful interactively . */
2001-10-05 04:20:06 +04:00
2001-05-07 08:32:40 +04:00
SETENV ( WINBINDD_DONT_ENV , " 1 " , 1 ) ;
/* Initialise samba/rpc client stuff */
while ( ( opt = getopt ( argc , argv , " id:s: " ) ) ! = EOF ) {
switch ( opt ) {
/* Don't become a daemon */
2000-05-09 15:43:00 +04:00
case ' i ' :
interactive = True ;
break ;
2001-05-07 08:32:40 +04:00
/* Run with specified debug level */
case ' d ' :
new_debuglevel = atoi ( optarg ) ;
break ;
/* Load a different smb.conf file */
case ' s ' :
pstrcpy ( servicesf , optarg ) ;
break ;
2000-05-09 15:43:00 +04:00
default :
2001-05-07 08:32:40 +04:00
printf ( " Unknown option %c \n " , ( char ) opt ) ;
2000-05-09 15:43:00 +04:00
exit ( 1 ) ;
}
2001-05-07 08:32:40 +04:00
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
snprintf ( debugf , sizeof ( debugf ) , " %s/log.winbindd " , LOGFILEBASE ) ;
setup_logging ( " winbindd " , interactive ) ;
reopen_logs ( ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
if ( ! * global_myname ) {
char * p ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
fstrcpy ( global_myname , myhostname ( ) ) ;
2001-07-19 01:50:20 +04:00
p = strchr ( global_myname , ' . ' ) ;
2001-10-05 04:20:06 +04:00
if ( p )
2001-05-07 08:32:40 +04:00
* p = 0 ;
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
TimeInit ( ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
if ( ! reload_services_file ( False ) ) {
DEBUG ( 0 , ( " error opening config file \n " ) ) ;
exit ( 1 ) ;
}
2000-05-09 15:43:00 +04:00
2001-10-05 04:20:06 +04:00
if ( new_debuglevel ! = - 1 )
2001-05-07 08:32:40 +04:00
DEBUGLEVEL = new_debuglevel ;
2000-05-09 15:43:00 +04:00
2001-10-05 04:20:06 +04:00
if ( ! interactive )
2001-05-07 08:32:40 +04:00
become_daemon ( ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
load_interfaces ( ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
secrets_init ( ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
ZERO_STRUCT ( server_state ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Winbind daemon initialisation */
2000-05-09 15:43:00 +04:00
2001-10-05 04:20:06 +04:00
if ( ! winbindd_param_init ( ) )
2001-05-07 08:32:40 +04:00
return 1 ;
2000-05-09 15:43:00 +04:00
2001-10-05 04:20:06 +04:00
if ( ! winbindd_idmap_init ( ) )
2001-05-07 08:32:40 +04:00
return 1 ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
winbindd_cache_init ( ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Unblock all signals we are interested in as they may have been
blocked by the parent process . */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
BlockSignals ( False , SIGINT ) ;
BlockSignals ( False , SIGQUIT ) ;
BlockSignals ( False , SIGTERM ) ;
BlockSignals ( False , SIGUSR1 ) ;
BlockSignals ( False , SIGHUP ) ;
/* Setup signal handlers */
CatchSignal ( SIGINT , termination_handler ) ; /* Exit on these sigs */
CatchSignal ( SIGQUIT , termination_handler ) ;
CatchSignal ( SIGTERM , termination_handler ) ;
CatchSignal ( SIGPIPE , SIG_IGN ) ; /* Ignore sigpipe */
CatchSignal ( SIGUSR1 , sigusr1_handler ) ; /* Debugging sigs */
CatchSignal ( SIGHUP , sighup_handler ) ;
/* Create UNIX domain socket */
if ( ( accept_sock = create_sock ( ) ) = = - 1 ) {
DEBUG ( 0 , ( " failed to create socket \n " ) ) ;
return 1 ;
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Loop waiting for requests */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
process_loop ( accept_sock ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
return 0 ;
2000-05-09 15:43:00 +04:00
}