2000-05-09 15:43:00 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2000-05-09 15:43:00 +04:00
Winbind daemon for ntdom nss module
2002-11-07 10:17:09 +03:00
Copyright ( C ) by Tim Potter 2000 - 2002
2002-07-15 14:35:28 +04:00
Copyright ( C ) Andrew Tridgell 2002
2003-04-14 07:53:58 +04:00
Copyright ( C ) Jelmer Vernooij 2003
2005-06-09 02:10:34 +04:00
Copyright ( C ) Volker Lendecke 2004
2007-04-21 01:09:44 +04:00
Copyright ( C ) James Peach 2007
2000-05-09 15:43:00 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
2003-11-12 04:51:10 +03:00
# include "includes.h"
2000-05-09 15:43:00 +04:00
# include "winbindd.h"
2007-04-21 01:09:44 +04:00
# include "smb_launchd.h"
2000-05-09 15:43:00 +04:00
2006-04-20 17:51:43 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_WINBIND
2002-07-15 14:35:28 +04:00
BOOL opt_nocache = False ;
2000-05-09 15:43:00 +04:00
2004-09-21 13:07:42 +04:00
extern BOOL override_logfile ;
2007-04-21 01:09:44 +04:00
static BOOL unlink_winbindd_socket = True ;
2004-09-21 13:07:42 +04:00
2007-01-17 15:59:14 +03:00
struct event_context * winbind_event_context ( void )
{
static struct event_context * ctx ;
if ( ! ctx & & ! ( ctx = event_context_init ( NULL ) ) ) {
2007-01-17 17:09:14 +03:00
smb_panic ( " Could not init winbind event context \n " ) ;
2007-01-17 15:59:14 +03:00
}
return ctx ;
}
2000-05-09 15:43:00 +04:00
/* Reload configuration */
2004-01-29 03:10:40 +03:00
static BOOL reload_services_file ( void )
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 ( ) ) ;
2001-11-19 05:49:53 +03:00
if ( file_exist ( fname , NULL ) & & ! strcsequal ( fname , dyn_CONFIGFILE ) ) {
pstrcpy ( dyn_CONFIGFILE , fname ) ;
2001-05-07 08:32:40 +04:00
}
}
2000-05-09 15:43:00 +04:00
reopen_logs ( ) ;
2006-01-29 01:53:04 +03:00
ret = lp_load ( dyn_CONFIGFILE , False , False , True , True ) ;
2000-05-09 15:43:00 +04:00
reopen_logs ( ) ;
load_interfaces ( ) ;
return ( ret ) ;
}
2003-07-15 21:21:21 +04:00
2001-11-23 14:18:20 +03:00
/**************************************************************************** **
Handle a fault . .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void fault_quit ( void )
{
dump_core ( ) ;
}
2001-11-14 09:18:13 +03:00
static void winbindd_status ( void )
2000-05-09 15:43:00 +04:00
{
2001-05-07 08:32:40 +04:00
struct winbindd_cli_state * tmp ;
2001-11-14 09:18:13 +03:00
DEBUG ( 0 , ( " winbindd status: \n " ) ) ;
2001-05-07 08:32:40 +04:00
/* Print client state information */
2002-11-02 04:36:42 +03:00
DEBUG ( 0 , ( " \t %d clients currently active \n " , winbindd_num_clients ( ) ) ) ;
2001-05-07 08:32:40 +04:00
2002-11-02 04:36:42 +03:00
if ( DEBUGLEVEL > = 2 & & winbindd_num_clients ( ) ) {
2001-05-07 08:32:40 +04:00
DEBUG ( 2 , ( " \t client list: \n " ) ) ;
2002-11-02 04:36:42 +03:00
for ( tmp = winbindd_client_list ( ) ; tmp ; tmp = tmp - > next ) {
2006-02-04 01:19:41 +03:00
DEBUGADD ( 2 , ( " \t \t pid %lu, sock %d \n " ,
2005-10-27 11:57:39 +04:00
( unsigned long ) tmp - > pid , tmp - > sock ) ) ;
2001-05-07 08:32:40 +04:00
}
}
}
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-11-15 06:23:15 +03:00
static void print_winbindd_status ( void )
2001-05-07 08:32:40 +04:00
{
2001-11-14 09:18:13 +03:00
winbindd_status ( ) ;
2000-05-09 15:43:00 +04:00
}
/* Flush client cache */
2001-11-15 06:23:15 +03:00
static void flush_caches ( void )
2000-05-09 15:43:00 +04:00
{
2003-06-21 08:05:01 +04:00
/* We need to invalidate cached user list entries on a SIGHUP
otherwise cached access denied errors due to restrict anonymous
hang around until the sequence number changes . */
wcache_invalidate_cache ( ) ;
2000-05-09 15:43:00 +04:00
}
/* Handle the signal by unlinking socket and exiting */
2001-11-15 00:49:30 +03:00
static void terminate ( void )
2000-05-09 15:43:00 +04:00
{
2001-05-07 08:32:40 +04:00
pstring path ;
2002-01-19 23:21:29 +03:00
2001-05-07 08:32:40 +04:00
/* Remove socket file */
2007-04-21 01:09:44 +04:00
if ( unlink_winbindd_socket ) {
pstr_sprintf ( path , " %s/%s " ,
WINBINDD_SOCKET_DIR , WINBINDD_SOCKET_NAME ) ;
unlink ( path ) ;
}
2005-06-09 02:10:34 +04:00
2007-02-20 22:57:14 +03:00
idmap_close ( ) ;
trustdom_cache_shutdown ( ) ;
2005-06-09 02:10:34 +04:00
#if 0
if ( interactive ) {
TALLOC_CTX * mem_ctx = talloc_init ( " end_description " ) ;
char * description = talloc_describe_all ( mem_ctx ) ;
DEBUG ( 3 , ( " tallocs left: \n %s \n " , description ) ) ;
talloc_destroy ( mem_ctx ) ;
}
# endif
2001-05-07 08:32:40 +04:00
exit ( 0 ) ;
}
2000-05-09 15:43:00 +04:00
2001-11-15 00:49:30 +03:00
static BOOL do_sigterm ;
static void termination_handler ( int signum )
{
do_sigterm = True ;
2005-06-09 19:20:11 +04:00
sys_select_signal ( signum ) ;
2001-11-15 00:49:30 +03:00
}
2002-01-10 09:20:03 +03:00
static BOOL do_sigusr2 ;
2000-05-09 15:43:00 +04:00
2002-01-10 09:20:03 +03:00
static void sigusr2_handler ( int signum )
2001-05-07 08:32:40 +04:00
{
2002-01-10 09:20:03 +03:00
do_sigusr2 = True ;
2005-06-09 19:20:11 +04:00
sys_select_signal ( SIGUSR2 ) ;
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
do_sighup = True ;
2005-06-09 19:20:11 +04:00
sys_select_signal ( SIGHUP ) ;
2000-05-09 15:43:00 +04:00
}
2005-06-09 02:10:34 +04:00
static BOOL do_sigchld ;
2004-07-21 08:24:30 +04:00
static void sigchld_handler ( int signum )
{
2005-06-09 02:10:34 +04:00
do_sigchld = True ;
2005-06-09 19:20:11 +04:00
sys_select_signal ( SIGCHLD ) ;
2004-07-21 08:24:30 +04:00
}
2003-07-15 21:21:21 +04:00
/* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
r21064: The core of this patch is
void message_register(int msg_type,
void (*fn)(int msg_type, struct process_id pid,
- void *buf, size_t len))
+ void *buf, size_t len,
+ void *private_data),
+ void *private_data)
{
struct dispatch_fns *dfn;
So this adds a (so far unused) private pointer that is passed from
message_register to the message handler. A prerequisite to implement a tiny
samba4-API compatible wrapper around our messaging system. That itself is
necessary for the Samba4 notify system.
Yes, I know, I could import the whole Samba4 messaging system, but I want to
do it step by step and I think getting notify in is more important in this
step.
Volker
(This used to be commit c8ae60ed65dcce9660ee39c75488f2838cf9a28b)
2007-01-31 01:22:06 +03:00
static void msg_reload_services ( int msg_type , struct process_id src ,
void * buf , size_t len , void * private_data )
2003-07-15 21:21:21 +04:00
{
/* Flush various caches */
flush_caches ( ) ;
2004-01-29 03:10:40 +03:00
reload_services_file ( ) ;
2003-07-15 21:21:21 +04:00
}
/* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
r21064: The core of this patch is
void message_register(int msg_type,
void (*fn)(int msg_type, struct process_id pid,
- void *buf, size_t len))
+ void *buf, size_t len,
+ void *private_data),
+ void *private_data)
{
struct dispatch_fns *dfn;
So this adds a (so far unused) private pointer that is passed from
message_register to the message handler. A prerequisite to implement a tiny
samba4-API compatible wrapper around our messaging system. That itself is
necessary for the Samba4 notify system.
Yes, I know, I could import the whole Samba4 messaging system, but I want to
do it step by step and I think getting notify in is more important in this
step.
Volker
(This used to be commit c8ae60ed65dcce9660ee39c75488f2838cf9a28b)
2007-01-31 01:22:06 +03:00
static void msg_shutdown ( int msg_type , struct process_id src ,
void * buf , size_t len , void * private_data )
2003-07-15 21:21:21 +04:00
{
2005-10-28 13:15:27 +04:00
do_sigterm = True ;
2003-07-15 21:21:21 +04:00
}
2005-06-20 17:42:29 +04:00
static struct winbindd_dispatch_table {
enum winbindd_cmd cmd ;
void ( * fn ) ( struct winbindd_cli_state * state ) ;
const char * winbindd_cmd_name ;
} dispatch_table [ ] = {
2001-05-07 08:32:40 +04:00
/* User functions */
2000-05-09 15:43:00 +04:00
2002-01-10 09:20:03 +03:00
{ WINBINDD_GETPWNAM , winbindd_getpwnam , " GETPWNAM " } ,
{ WINBINDD_GETPWUID , winbindd_getpwuid , " GETPWUID " } ,
2001-10-05 04:20:06 +04:00
2001-11-14 07:44:36 +03:00
{ WINBINDD_SETPWENT , winbindd_setpwent , " SETPWENT " } ,
{ WINBINDD_ENDPWENT , winbindd_endpwent , " ENDPWENT " } ,
{ WINBINDD_GETPWENT , winbindd_getpwent , " GETPWENT " } ,
2001-10-05 04:20:06 +04:00
2001-11-14 07:44:36 +03:00
{ WINBINDD_GETGROUPS , winbindd_getgroups , " GETGROUPS " } ,
2003-11-19 11:11:14 +03:00
{ WINBINDD_GETUSERSIDS , winbindd_getusersids , " GETUSERSIDS " } ,
2005-06-09 02:10:34 +04:00
{ WINBINDD_GETUSERDOMGROUPS , winbindd_getuserdomgroups ,
" GETUSERDOMGROUPS " } ,
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
2002-01-10 09:20:03 +03:00
{ WINBINDD_GETGRNAM , winbindd_getgrnam , " GETGRNAM " } ,
{ WINBINDD_GETGRGID , winbindd_getgrgid , " GETGRGID " } ,
2001-11-14 07:44:36 +03:00
{ WINBINDD_SETGRENT , winbindd_setgrent , " SETGRENT " } ,
{ WINBINDD_ENDGRENT , winbindd_endgrent , " ENDGRENT " } ,
{ WINBINDD_GETGRENT , winbindd_getgrent , " GETGRENT " } ,
2002-07-15 14:35:28 +04:00
{ WINBINDD_GETGRLST , winbindd_getgrent , " GETGRLST " } ,
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-11-14 07:44:36 +03:00
{ WINBINDD_PAM_AUTH , winbindd_pam_auth , " PAM_AUTH " } ,
2005-06-10 07:26:39 +04:00
{ WINBINDD_PAM_AUTH_CRAP , winbindd_pam_auth_crap , " AUTH_CRAP " } ,
2001-11-14 07:44:36 +03:00
{ WINBINDD_PAM_CHAUTHTOK , winbindd_pam_chauthtok , " CHAUTHTOK " } ,
2006-02-04 01:19:41 +03:00
{ WINBINDD_PAM_LOGOFF , winbindd_pam_logoff , " PAM_LOGOFF " } ,
2006-07-13 13:29:25 +04:00
{ WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP , winbindd_pam_chng_pswd_auth_crap , " CHNG_PSWD_AUTH_CRAP " } ,
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-11-15 22:40:00 +03:00
{ WINBINDD_LIST_USERS , winbindd_list_users , " LIST_USERS " } ,
{ WINBINDD_LIST_GROUPS , winbindd_list_groups , " LIST_GROUPS " } ,
2005-06-09 02:10:34 +04:00
{ WINBINDD_LIST_TRUSTDOM , winbindd_list_trusted_domains ,
" LIST_TRUSTDOM " } ,
2002-01-31 14:49:29 +03:00
{ WINBINDD_SHOW_SEQUENCE , winbindd_show_sequence , " SHOW_SEQUENCE " } ,
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-11-14 07:44:36 +03:00
{ WINBINDD_LOOKUPSID , winbindd_lookupsid , " LOOKUPSID " } ,
{ WINBINDD_LOOKUPNAME , winbindd_lookupname , " LOOKUPNAME " } ,
2006-07-11 22:01:26 +04:00
{ WINBINDD_LOOKUPRIDS , winbindd_lookuprids , " LOOKUPRIDS " } ,
2000-05-09 15:43:00 +04:00
2001-11-15 22:40:00 +03:00
/* Lookup related functions */
2000-05-09 15:43:00 +04:00
2001-11-14 07:44:36 +03:00
{ WINBINDD_SID_TO_UID , winbindd_sid_to_uid , " SID_TO_UID " } ,
{ WINBINDD_SID_TO_GID , winbindd_sid_to_gid , " SID_TO_GID " } ,
{ WINBINDD_UID_TO_SID , winbindd_uid_to_sid , " UID_TO_SID " } ,
2005-06-09 02:10:34 +04:00
{ WINBINDD_GID_TO_SID , winbindd_gid_to_sid , " GID_TO_SID " } ,
2007-04-20 02:26:09 +04:00
#if 0 /* DISABLED until we fix the interface in Samba 3.0.26 --jerry */
2006-12-12 17:52:13 +03:00
{ WINBINDD_SIDS_TO_XIDS , winbindd_sids_to_unixids , " SIDS_TO_XIDS " } ,
2007-04-20 02:26:09 +04:00
# endif /* end DISABLED */
2006-02-04 01:19:41 +03:00
{ WINBINDD_ALLOCATE_UID , winbindd_allocate_uid , " ALLOCATE_UID " } ,
2006-06-12 17:59:22 +04:00
{ WINBINDD_ALLOCATE_GID , winbindd_allocate_gid , " ALLOCATE_GID " } ,
2006-12-12 17:52:13 +03:00
{ WINBINDD_SET_MAPPING , winbindd_set_mapping , " SET_MAPPING " } ,
{ WINBINDD_SET_HWM , winbindd_set_hwm , " SET_HWMS " } ,
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
2006-12-12 17:52:13 +03:00
{ WINBINDD_DUMP_MAPS , winbindd_dump_maps , " DUMP_MAPS " } ,
2001-11-14 07:44:36 +03:00
{ WINBINDD_CHECK_MACHACC , winbindd_check_machine_acct , " CHECK_MACHACC " } ,
2002-01-10 13:23:54 +03:00
{ WINBINDD_PING , winbindd_ping , " PING " } ,
2002-01-10 14:28:14 +03:00
{ WINBINDD_INFO , winbindd_info , " INFO " } ,
2005-06-09 02:10:34 +04:00
{ WINBINDD_INTERFACE_VERSION , winbindd_interface_version ,
" INTERFACE_VERSION " } ,
2002-01-26 12:55:38 +03:00
{ WINBINDD_DOMAIN_NAME , winbindd_domain_name , " DOMAIN_NAME " } ,
2004-01-04 14:51:31 +03:00
{ WINBINDD_DOMAIN_INFO , winbindd_domain_info , " DOMAIN_INFO " } ,
2003-01-28 15:07:02 +03:00
{ WINBINDD_NETBIOS_NAME , winbindd_netbios_name , " NETBIOS_NAME " } ,
2005-06-09 02:10:34 +04:00
{ WINBINDD_PRIV_PIPE_DIR , winbindd_priv_pipe_dir ,
" WINBINDD_PRIV_PIPE_DIR " } ,
{ WINBINDD_GETDCNAME , winbindd_getdcname , " GETDCNAME " } ,
2000-05-09 15:43:00 +04:00
2006-08-19 05:04:54 +04:00
/* Credential cache access */
{ WINBINDD_CCACHE_NTLMAUTH , winbindd_ccache_ntlm_auth , " NTLMAUTH " } ,
2002-03-29 18:37:39 +03:00
/* WINS functions */
{ WINBINDD_WINS_BYNAME , winbindd_wins_byname , " WINS_BYNAME " } ,
{ WINBINDD_WINS_BYIP , winbindd_wins_byip , " WINS_BYIP " } ,
2003-07-09 20:44:47 +04:00
2001-05-07 08:32:40 +04:00
/* End of list */
2000-05-09 15:43:00 +04:00
2001-11-14 07:44:36 +03:00
{ WINBINDD_NUM_CMDS , NULL , " NONE " }
2001-05-07 08:32:40 +04:00
} ;
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
{
2005-06-09 02:10:34 +04:00
struct winbindd_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
2006-04-12 18:10:39 +04:00
SAFE_FREE ( state - > response . extra_data . 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
2005-06-09 02:10:34 +04:00
state - > response . result = WINBINDD_PENDING ;
2001-05-07 08:32:40 +04:00
state - > response . length = sizeof ( struct winbindd_response ) ;
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
state - > mem_ctx = talloc_init ( " winbind request " ) ;
if ( state - > mem_ctx = = NULL )
return ;
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 ) {
2005-06-09 02:10:34 +04:00
DEBUG ( 10 , ( " process_request: request fn %s \n " ,
table - > winbindd_cmd_name ) ) ;
2005-06-20 17:42:29 +04:00
table - > fn ( state ) ;
2001-05-07 08:32:40 +04:00
break ;
}
}
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
if ( ! table - > fn ) {
DEBUG ( 10 , ( " process_request: unknown request fn number %d \n " ,
( int ) state - > request . cmd ) ) ;
2005-06-20 17:42:29 +04:00
request_error ( state ) ;
2005-06-09 02:10:34 +04:00
}
}
/*
* A list of file descriptors being monitored by select in the main processing
* loop . fd_event - > handler is called whenever the socket is readable / writable .
*/
static struct fd_event * fd_events = NULL ;
void add_fd_event ( struct fd_event * ev )
{
struct fd_event * match ;
/* only add unique fd_event structs */
for ( match = fd_events ; match ; match = match - > next ) {
# ifdef DEVELOPER
SMB_ASSERT ( match ! = ev ) ;
# else
if ( match = = ev )
return ;
# endif
}
DLIST_ADD ( fd_events , ev ) ;
}
void remove_fd_event ( struct fd_event * ev )
{
DLIST_REMOVE ( fd_events , ev ) ;
}
/*
* Handler for fd_events to complete a read / write request , set up by
* setup_async_read / setup_async_write .
*/
static void rw_callback ( struct fd_event * event , int flags )
{
size_t todo ;
ssize_t done = 0 ;
todo = event - > length - event - > done ;
if ( event - > flags & EVENT_FD_WRITE ) {
SMB_ASSERT ( flags = = EVENT_FD_WRITE ) ;
done = sys_write ( event - > fd ,
& ( ( char * ) event - > data ) [ event - > done ] ,
todo ) ;
if ( done < = 0 ) {
event - > flags = 0 ;
2005-06-25 00:25:18 +04:00
event - > finished ( event - > private_data , False ) ;
2005-06-09 02:10:34 +04:00
return ;
}
}
if ( event - > flags & EVENT_FD_READ ) {
SMB_ASSERT ( flags = = EVENT_FD_READ ) ;
done = sys_read ( event - > fd , & ( ( char * ) event - > data ) [ event - > done ] ,
todo ) ;
2001-11-14 07:44:36 +03:00
2005-06-09 02:10:34 +04:00
if ( done < = 0 ) {
event - > flags = 0 ;
2005-06-25 00:25:18 +04:00
event - > finished ( event - > private_data , False ) ;
2005-06-09 02:10:34 +04:00
return ;
}
}
event - > done + = done ;
if ( event - > done = = event - > length ) {
event - > flags = 0 ;
2005-06-25 00:25:18 +04:00
event - > finished ( event - > private_data , True ) ;
2005-06-09 02:10:34 +04:00
}
}
/*
* Request an async read / write on a fd_event structure . ( * finished ) is called
* when the request is completed or an error had occurred .
*/
void setup_async_read ( struct fd_event * event , void * data , size_t length ,
2005-06-25 00:25:18 +04:00
void ( * finished ) ( void * private_data , BOOL success ) ,
void * private_data )
2005-06-09 02:10:34 +04:00
{
SMB_ASSERT ( event - > flags = = 0 ) ;
event - > data = data ;
event - > length = length ;
event - > done = 0 ;
event - > handler = rw_callback ;
event - > finished = finished ;
2005-06-25 00:25:18 +04:00
event - > private_data = private_data ;
2005-06-09 02:10:34 +04:00
event - > flags = EVENT_FD_READ ;
}
void setup_async_write ( struct fd_event * event , void * data , size_t length ,
2005-06-25 00:25:18 +04:00
void ( * finished ) ( void * private_data , BOOL success ) ,
void * private_data )
2005-06-09 02:10:34 +04:00
{
SMB_ASSERT ( event - > flags = = 0 ) ;
event - > data = data ;
event - > length = length ;
event - > done = 0 ;
event - > handler = rw_callback ;
event - > finished = finished ;
2005-06-25 00:25:18 +04:00
event - > private_data = private_data ;
2005-06-09 02:10:34 +04:00
event - > flags = EVENT_FD_WRITE ;
}
/*
* This is the main event loop of winbind requests . It goes through a
* state - machine of 3 read / write requests , 4 if you have extra data to send .
*
* An idle winbind client has a read request of 4 bytes outstanding ,
* finalizing function is request_len_recv , checking the length . request_recv
* then processes the packet . The processing function then at some point has
* to call request_finished which schedules sending the response .
*/
2005-06-25 00:25:18 +04:00
static void request_len_recv ( void * private_data , BOOL success ) ;
static void request_recv ( void * private_data , BOOL success ) ;
2005-09-30 21:13:37 +04:00
static void request_main_recv ( void * private_data , BOOL success ) ;
2005-06-20 17:42:29 +04:00
static void request_finished ( struct winbindd_cli_state * state ) ;
2005-06-25 00:25:18 +04:00
void request_finished_cont ( void * private_data , BOOL success ) ;
static void response_main_sent ( void * private_data , BOOL success ) ;
static void response_extra_sent ( void * private_data , BOOL success ) ;
2005-06-09 02:10:34 +04:00
2005-06-25 00:25:18 +04:00
static void response_extra_sent ( void * private_data , BOOL success )
2005-06-09 02:10:34 +04:00
{
struct winbindd_cli_state * state =
2005-06-25 00:25:18 +04:00
talloc_get_type_abort ( private_data , struct winbindd_cli_state ) ;
2005-06-09 02:10:34 +04:00
if ( state - > mem_ctx ! = NULL ) {
talloc_destroy ( state - > mem_ctx ) ;
state - > mem_ctx = NULL ;
}
if ( ! success ) {
state - > finished = True ;
return ;
}
2006-04-12 18:10:39 +04:00
SAFE_FREE ( state - > request . extra_data . data ) ;
SAFE_FREE ( state - > response . extra_data . data ) ;
2005-06-09 02:10:34 +04:00
setup_async_read ( & state - > fd_event , & state - > request , sizeof ( uint32 ) ,
request_len_recv , state ) ;
}
2005-06-25 00:25:18 +04:00
static void response_main_sent ( void * private_data , BOOL success )
2005-06-09 02:10:34 +04:00
{
struct winbindd_cli_state * state =
2005-06-25 00:25:18 +04:00
talloc_get_type_abort ( private_data , struct winbindd_cli_state ) ;
2005-06-09 02:10:34 +04:00
if ( ! success ) {
state - > finished = True ;
return ;
}
if ( state - > response . length = = sizeof ( state - > response ) ) {
if ( state - > mem_ctx ! = NULL ) {
talloc_destroy ( state - > mem_ctx ) ;
state - > mem_ctx = NULL ;
}
setup_async_read ( & state - > fd_event , & state - > request ,
sizeof ( uint32 ) , request_len_recv , state ) ;
return ;
}
2006-04-12 18:10:39 +04:00
setup_async_write ( & state - > fd_event , state - > response . extra_data . data ,
2005-06-09 02:10:34 +04:00
state - > response . length - sizeof ( state - > response ) ,
response_extra_sent , state ) ;
}
2005-06-20 17:42:29 +04:00
static void request_finished ( struct winbindd_cli_state * state )
2005-06-09 02:10:34 +04:00
{
setup_async_write ( & state - > fd_event , & state - > response ,
sizeof ( state - > response ) , response_main_sent , state ) ;
}
2005-06-20 17:42:29 +04:00
void request_error ( struct winbindd_cli_state * state )
{
SMB_ASSERT ( state - > response . result = = WINBINDD_PENDING ) ;
state - > response . result = WINBINDD_ERROR ;
request_finished ( state ) ;
}
void request_ok ( struct winbindd_cli_state * state )
{
SMB_ASSERT ( state - > response . result = = WINBINDD_PENDING ) ;
state - > response . result = WINBINDD_OK ;
request_finished ( state ) ;
}
2005-06-25 00:25:18 +04:00
void request_finished_cont ( void * private_data , BOOL success )
2005-06-09 02:10:34 +04:00
{
struct winbindd_cli_state * state =
2005-06-25 00:25:18 +04:00
talloc_get_type_abort ( private_data , struct winbindd_cli_state ) ;
2005-06-09 02:10:34 +04:00
2005-06-20 17:42:29 +04:00
if ( success )
request_ok ( state ) ;
else
request_error ( state ) ;
2005-06-09 02:10:34 +04:00
}
2005-09-30 21:13:37 +04:00
static void request_len_recv ( void * private_data , BOOL success )
2005-06-09 02:10:34 +04:00
{
struct winbindd_cli_state * state =
2005-06-25 00:25:18 +04:00
talloc_get_type_abort ( private_data , struct winbindd_cli_state ) ;
2005-06-09 02:10:34 +04:00
if ( ! success ) {
state - > finished = True ;
return ;
}
2005-09-30 21:13:37 +04:00
if ( * ( uint32 * ) ( & state - > request ) ! = sizeof ( state - > request ) ) {
DEBUG ( 0 , ( " request_len_recv: Invalid request size received: %d \n " ,
* ( uint32 * ) ( & state - > request ) ) ) ;
state - > finished = True ;
return ;
}
setup_async_read ( & state - > fd_event , ( uint32 * ) ( & state - > request ) + 1 ,
sizeof ( state - > request ) - sizeof ( uint32 ) ,
request_main_recv , state ) ;
2005-06-09 02:10:34 +04:00
}
2005-09-30 21:13:37 +04:00
static void request_main_recv ( void * private_data , BOOL success )
2005-06-09 02:10:34 +04:00
{
struct winbindd_cli_state * state =
2005-06-25 00:25:18 +04:00
talloc_get_type_abort ( private_data , struct winbindd_cli_state ) ;
2005-06-09 02:10:34 +04:00
if ( ! success ) {
state - > finished = True ;
return ;
}
2005-09-30 21:13:37 +04:00
if ( state - > request . extra_len = = 0 ) {
2006-04-12 18:10:39 +04:00
state - > request . extra_data . data = NULL ;
2005-09-30 21:13:37 +04:00
request_recv ( state , True ) ;
return ;
}
if ( ( ! state - > privileged ) & &
( state - > request . extra_len > WINBINDD_MAX_EXTRA_DATA ) ) {
DEBUG ( 3 , ( " Got request with %d bytes extra data on "
" unprivileged socket \n " , ( int ) state - > request . extra_len ) ) ;
2006-04-12 18:10:39 +04:00
state - > request . extra_data . data = NULL ;
2005-06-09 02:10:34 +04:00
state - > finished = True ;
return ;
}
2000-05-09 15:43:00 +04:00
2006-04-12 18:10:39 +04:00
state - > request . extra_data . data =
2005-09-30 21:13:37 +04:00
SMB_MALLOC_ARRAY ( char , state - > request . extra_len + 1 ) ;
2006-04-12 18:10:39 +04:00
if ( state - > request . extra_data . data = = NULL ) {
2005-09-30 21:13:37 +04:00
DEBUG ( 0 , ( " malloc failed \n " ) ) ;
state - > finished = True ;
return ;
}
/* Ensure null termination */
2006-04-12 18:10:39 +04:00
state - > request . extra_data . data [ state - > request . extra_len ] = ' \0 ' ;
2005-09-30 21:13:37 +04:00
2006-04-12 18:10:39 +04:00
setup_async_read ( & state - > fd_event , state - > request . extra_data . data ,
2005-09-30 21:13:37 +04:00
state - > request . extra_len , request_recv , state ) ;
}
static void request_recv ( void * private_data , BOOL success )
{
struct winbindd_cli_state * state =
talloc_get_type_abort ( private_data , struct winbindd_cli_state ) ;
if ( ! success ) {
state - > finished = True ;
return ;
}
process_request ( state ) ;
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
2003-04-07 11:32:51 +04:00
static void new_connection ( int listen_sock , BOOL privileged )
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 ) ;
2001-11-15 00:49:30 +03:00
do {
2002-11-02 04:36:42 +03:00
sock = accept ( listen_sock , ( struct sockaddr * ) & sunaddr , & len ) ;
2001-11-15 00:49:30 +03:00
} while ( sock = = - 1 & & errno = = EINTR ) ;
if ( sock = = - 1 )
2001-05-07 08:32:40 +04:00
return ;
DEBUG ( 6 , ( " accepted socket %d \n " , sock ) ) ;
/* Create new connection structure */
2007-02-08 03:28:25 +03:00
if ( ( state = TALLOC_ZERO_P ( NULL , struct winbindd_cli_state ) ) = = NULL ) {
close ( sock ) ;
2001-05-07 08:32:40 +04:00
return ;
2007-02-08 03:28:25 +03:00
}
2001-05-07 08:32:40 +04:00
state - > sock = sock ;
2003-02-28 03:25:55 +03:00
state - > last_access = time ( NULL ) ;
2003-04-07 11:32:51 +04:00
state - > privileged = privileged ;
2003-03-24 12:54:13 +03:00
2005-06-09 02:10:34 +04:00
state - > fd_event . fd = state - > sock ;
state - > fd_event . flags = 0 ;
add_fd_event ( & state - > fd_event ) ;
setup_async_read ( & state - > fd_event , & state - > request , sizeof ( uint32 ) ,
request_len_recv , state ) ;
2001-05-07 08:32:40 +04:00
/* Add to connection list */
2002-11-02 04:36:42 +03:00
winbindd_add_client ( state ) ;
2001-05-07 08:32:40 +04:00
}
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 */
2006-10-04 20:18:36 +04:00
if ( state = = NULL ) {
return ;
}
2001-05-07 08:32:40 +04:00
2006-10-04 20:18:36 +04:00
/* Close socket */
2001-05-07 08:32:40 +04:00
2006-10-04 20:18:36 +04:00
close ( state - > sock ) ;
2001-05-07 08:32:40 +04:00
2006-10-04 20:18:36 +04:00
/* Free any getent state */
2001-05-07 08:32:40 +04:00
2006-10-04 20:18:36 +04:00
free_getent_state ( state - > getpwent_state ) ;
free_getent_state ( state - > getgrent_state ) ;
2001-05-07 08:32:40 +04:00
2006-10-04 20:18:36 +04:00
/* We may have some extra data that was not freed if the client was
killed unexpectedly */
2001-05-07 08:32:40 +04:00
2006-10-04 20:18:36 +04:00
SAFE_FREE ( state - > response . extra_data . data ) ;
2005-06-09 02:10:34 +04:00
2006-10-04 20:18:36 +04:00
if ( state - > mem_ctx ! = NULL ) {
talloc_destroy ( state - > mem_ctx ) ;
state - > mem_ctx = NULL ;
}
2005-06-09 02:10:34 +04:00
2006-10-04 20:18:36 +04:00
remove_fd_event ( & state - > fd_event ) ;
2001-05-07 08:32:40 +04:00
2006-10-04 20:18:36 +04:00
/* Remove from list and free */
2001-05-07 08:32:40 +04:00
2006-10-04 20:18:36 +04:00
winbindd_remove_client ( state ) ;
TALLOC_FREE ( state ) ;
2001-05-07 08:32:40 +04:00
}
2000-05-09 15:43:00 +04:00
2003-02-28 03:25:55 +03:00
/* Shutdown client connection which has been idle for the longest time */
static BOOL remove_idle_client ( void )
{
struct winbindd_cli_state * state , * remove_state = NULL ;
time_t last_access = 0 ;
int nidle = 0 ;
for ( state = winbindd_client_list ( ) ; state ; state = state - > next ) {
2005-10-27 11:57:39 +04:00
if ( state - > response . result ! = WINBINDD_PENDING & &
2005-06-09 02:10:34 +04:00
! state - > getpwent_state & & ! state - > getgrent_state ) {
2003-02-28 03:25:55 +03:00
nidle + + ;
if ( ! last_access | | state - > last_access < last_access ) {
last_access = state - > last_access ;
remove_state = state ;
}
}
}
if ( remove_state ) {
DEBUG ( 5 , ( " Found %d idle client connections, shutting down sock %d, pid %u \n " ,
nidle , remove_state - > sock , ( unsigned int ) remove_state - > pid ) ) ;
remove_client ( remove_state ) ;
return True ;
}
return False ;
}
2007-04-21 01:09:44 +04:00
static BOOL winbindd_init_sockets ( int * public_sock , int * priv_sock ,
int * idle_timeout_sec )
{
struct smb_launch_info linfo ;
if ( smb_launchd_checkin_names ( & linfo , " WinbindPublicPipe " ,
" WinbindPrivilegedPipe " , NULL ) ) {
if ( linfo . num_sockets ! = 2 ) {
DEBUG ( 0 , ( " invalid launchd configuration, "
" expected 2 sockets but got %d \n " ,
linfo . num_sockets ) ) ;
return False ;
}
* public_sock = linfo . socket_list [ 0 ] ;
* priv_sock = linfo . socket_list [ 1 ] ;
* idle_timeout_sec = linfo . idle_timeout_secs ;
unlink_winbindd_socket = False ;
smb_launchd_checkout ( & linfo ) ;
return True ;
} else {
* public_sock = open_winbindd_socket ( ) ;
* priv_sock = open_winbindd_priv_socket ( ) ;
* idle_timeout_sec = - 1 ;
if ( * public_sock = = - 1 | | * priv_sock = = - 1 ) {
DEBUG ( 0 , ( " failed to open winbindd pipes: %s \n " ,
errno ? strerror ( errno ) : " unknown error " ) ) ;
return False ;
}
return True ;
}
}
2003-02-28 03:25:55 +03:00
/* Process incoming clients on listen_sock. We use a tricky non-blocking,
2001-05-07 08:32:40 +04:00
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
2007-04-21 01:09:44 +04:00
static int process_loop ( int listen_sock , int listen_priv_sock )
2001-05-07 08:32:40 +04:00
{
2005-06-09 02:10:34 +04:00
struct winbindd_cli_state * state ;
struct fd_event * ev ;
fd_set r_fds , w_fds ;
2007-04-21 01:09:44 +04:00
int maxfd , selret ;
2006-12-20 07:50:46 +03:00
struct timeval timeout , ev_timeout ;
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
/* We'll be doing this a lot */
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
/* Handle messages */
2002-03-27 01:33:06 +03:00
2005-06-09 02:10:34 +04:00
message_dispatch ( ) ;
2002-03-27 01:33:06 +03:00
2007-01-17 15:59:14 +03:00
run_events ( winbind_event_context ( ) , 0 , NULL , NULL ) ;
2006-12-20 07:50:46 +03:00
2005-06-09 02:10:34 +04:00
/* refresh the trusted domain cache */
2006-12-20 07:50:46 +03:00
2005-06-09 02:10:34 +04:00
rescan_trusted_domains ( ) ;
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
/* Free up temporary memory */
2000-05-09 15:43:00 +04:00
2006-02-20 20:59:58 +03:00
lp_TALLOC_FREE ( ) ;
main_loop_TALLOC_FREE ( ) ;
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
/* Initialise fd lists for select() */
2002-12-20 04:25:27 +03:00
2005-06-09 02:10:34 +04:00
maxfd = MAX ( listen_sock , listen_priv_sock ) ;
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
FD_ZERO ( & r_fds ) ;
FD_ZERO ( & w_fds ) ;
FD_SET ( listen_sock , & r_fds ) ;
FD_SET ( listen_priv_sock , & r_fds ) ;
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
timeout . tv_sec = WINBINDD_ESTABLISH_LOOP ;
timeout . tv_usec = 0 ;
2000-05-09 15:43:00 +04:00
2006-12-20 07:50:46 +03:00
/* Check for any event timeouts. */
2007-01-17 15:59:14 +03:00
if ( get_timed_events_timeout ( winbind_event_context ( ) , & ev_timeout ) ) {
2006-12-20 07:50:46 +03:00
timeout = timeval_min ( & timeout , & ev_timeout ) ;
}
2005-06-09 02:10:34 +04:00
/* Set up client readers and writers */
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
state = winbindd_client_list ( ) ;
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
while ( state ) {
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
struct winbindd_cli_state * next = state - > next ;
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
/* Dispose of client connection if it is marked as
finished */
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
if ( state - > finished )
remove_client ( state ) ;
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
state = next ;
}
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
for ( ev = fd_events ; ev ; ev = ev - > next ) {
if ( ev - > flags & EVENT_FD_READ ) {
FD_SET ( ev - > fd , & r_fds ) ;
maxfd = MAX ( ev - > fd , maxfd ) ;
}
if ( ev - > flags & EVENT_FD_WRITE ) {
FD_SET ( ev - > fd , & w_fds ) ;
maxfd = MAX ( ev - > fd , maxfd ) ;
2001-05-07 08:32:40 +04:00
}
2005-06-09 02:10:34 +04:00
}
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
/* Call select */
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
selret = sys_select ( maxfd + 1 , & r_fds , & w_fds , NULL , & timeout ) ;
2000-05-09 15:43:00 +04:00
2006-05-18 05:45:18 +04:00
if ( selret = = 0 ) {
2005-06-09 02:10:34 +04:00
goto no_fds_ready ;
2006-05-18 05:45:18 +04:00
}
2000-05-09 15:43:00 +04:00
2006-05-18 05:45:18 +04:00
if ( selret = = - 1 ) {
if ( errno = = EINTR ) {
goto no_fds_ready ;
}
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
/* Select error, something is badly wrong */
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
perror ( " select " ) ;
exit ( 1 ) ;
}
2000-05-09 15:43:00 +04:00
2006-05-18 05:45:18 +04:00
/* selret > 0 */
2005-06-09 02:10:34 +04:00
ev = fd_events ;
while ( ev ! = NULL ) {
struct fd_event * next = ev - > next ;
int flags = 0 ;
if ( FD_ISSET ( ev - > fd , & r_fds ) )
flags | = EVENT_FD_READ ;
if ( FD_ISSET ( ev - > fd , & w_fds ) )
flags | = EVENT_FD_WRITE ;
if ( flags )
ev - > handler ( ev , flags ) ;
ev = next ;
}
2002-07-15 14:35:28 +04:00
2005-06-09 02:10:34 +04:00
if ( FD_ISSET ( listen_sock , & r_fds ) ) {
while ( winbindd_num_clients ( ) >
WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1 ) {
DEBUG ( 5 , ( " winbindd: Exceeding %d client "
" connections, removing idle "
" connection. \n " ,
WINBINDD_MAX_SIMULTANEOUS_CLIENTS ) ) ;
if ( ! remove_idle_client ( ) ) {
DEBUG ( 0 , ( " winbindd: Exceeding %d "
" client connections, no idle "
" connection found \n " ,
WINBINDD_MAX_SIMULTANEOUS_CLIENTS ) ) ;
break ;
2003-03-24 12:54:13 +03:00
}
2005-06-09 02:10:34 +04:00
}
/* new, non-privileged connection */
new_connection ( listen_sock , False ) ;
}
2003-03-24 12:54:13 +03:00
2005-06-09 02:10:34 +04:00
if ( FD_ISSET ( listen_priv_sock , & r_fds ) ) {
while ( winbindd_num_clients ( ) >
WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1 ) {
DEBUG ( 5 , ( " winbindd: Exceeding %d client "
" connections, removing idle "
" connection. \n " ,
WINBINDD_MAX_SIMULTANEOUS_CLIENTS ) ) ;
if ( ! remove_idle_client ( ) ) {
DEBUG ( 0 , ( " winbindd: Exceeding %d "
" client connections, no idle "
" connection found \n " ,
WINBINDD_MAX_SIMULTANEOUS_CLIENTS ) ) ;
break ;
2001-05-07 08:32:40 +04:00
}
}
2005-06-09 02:10:34 +04:00
/* new, privileged connection */
new_connection ( listen_priv_sock , True ) ;
}
no_fds_ready :
2001-11-15 00:49:30 +03:00
2002-04-04 07:03:39 +04:00
#if 0
2005-06-09 02:10:34 +04:00
winbindd_check_cache_size ( time ( NULL ) ) ;
2002-04-04 07:03:39 +04:00
# endif
2005-06-09 02:10:34 +04:00
/* Check signal handling things */
2001-11-15 00:49:30 +03:00
2005-06-09 02:10:34 +04:00
if ( do_sigterm )
terminate ( ) ;
2001-11-15 00:49:30 +03:00
2005-06-09 02:10:34 +04:00
if ( do_sighup ) {
2001-11-15 00:49:30 +03:00
2005-06-09 02:10:34 +04:00
DEBUG ( 3 , ( " got SIGHUP \n " ) ) ;
2001-11-15 00:49:30 +03:00
r21064: The core of this patch is
void message_register(int msg_type,
void (*fn)(int msg_type, struct process_id pid,
- void *buf, size_t len))
+ void *buf, size_t len,
+ void *private_data),
+ void *private_data)
{
struct dispatch_fns *dfn;
So this adds a (so far unused) private pointer that is passed from
message_register to the message handler. A prerequisite to implement a tiny
samba4-API compatible wrapper around our messaging system. That itself is
necessary for the Samba4 notify system.
Yes, I know, I could import the whole Samba4 messaging system, but I want to
do it step by step and I think getting notify in is more important in this
step.
Volker
(This used to be commit c8ae60ed65dcce9660ee39c75488f2838cf9a28b)
2007-01-31 01:22:06 +03:00
msg_reload_services ( MSG_SMB_CONF_UPDATED , pid_to_procid ( 0 ) , NULL , 0 , NULL ) ;
2005-06-09 02:10:34 +04:00
do_sighup = False ;
}
if ( do_sigusr2 ) {
print_winbindd_status ( ) ;
do_sigusr2 = False ;
}
2001-11-15 00:49:30 +03:00
2005-06-09 02:10:34 +04:00
if ( do_sigchld ) {
pid_t pid ;
do_sigchld = False ;
while ( ( pid = sys_waitpid ( - 1 , NULL , WNOHANG ) ) > 0 ) {
winbind_child_died ( pid ) ;
2001-11-15 00:49:30 +03:00
}
2001-05-07 08:32:40 +04:00
}
2007-04-21 01:09:44 +04:00
return winbindd_num_clients ( ) ;
}
static void winbindd_process_loop ( enum smb_server_mode server_mode )
{
int idle_timeout_sec ;
struct timeval starttime ;
int listen_public , listen_priv ;
errno = 0 ;
if ( ! winbindd_init_sockets ( & listen_public , & listen_priv ,
& idle_timeout_sec ) ) {
terminate ( ) ;
}
starttime = timeval_current ( ) ;
if ( listen_public = = - 1 | | listen_priv = = - 1 ) {
DEBUG ( 0 , ( " failed to open winbindd pipes: %s \n " ,
errno ? strerror ( errno ) : " unknown error " ) ) ;
terminate ( ) ;
}
for ( ; ; ) {
int clients = process_loop ( listen_public , listen_priv ) ;
/* Don't bother figuring out the idle time if we won't be
* timing out anyway .
*/
if ( idle_timeout_sec < 0 ) {
continue ;
}
if ( clients = = 0 & & server_mode = = SERVER_MODE_FOREGROUND ) {
struct timeval now ;
now = timeval_current ( ) ;
if ( timeval_elapsed2 ( & starttime , & now ) >
( double ) idle_timeout_sec ) {
DEBUG ( 0 , ( " idle for %d secs, exitting \n " ,
idle_timeout_sec ) ) ;
terminate ( ) ;
}
} else {
starttime = timeval_current ( ) ;
}
}
2000-05-09 15:43:00 +04:00
}
/* Main function */
2006-11-30 02:20:22 +03:00
int main ( int argc , char * * argv , char * * envp )
2000-05-09 15:43:00 +04:00
{
2001-12-21 01:27:05 +03:00
pstring logfile ;
2007-04-20 22:34:33 +04:00
BOOL log_stdout = False ;
BOOL no_process_group = False ;
enum smb_server_mode server_mode = SERVER_MODE_DAEMON ;
2003-04-14 07:53:58 +04:00
struct poptOption long_options [ ] = {
POPT_AUTOHELP
{ " stdout " , ' S ' , POPT_ARG_VAL , & log_stdout , True , " Log to stdout " } ,
2007-04-20 22:34:33 +04:00
{ " foreground " , ' F ' , POPT_ARG_VAL , & server_mode , SERVER_MODE_FOREGROUND , " Daemon in foreground mode " } ,
2006-03-21 16:16:50 +03:00
{ " no-process-group " , 0 , POPT_ARG_VAL , & no_process_group , True , " Don't create a new process group " } ,
2007-04-20 22:34:33 +04:00
{ " interactive " , ' i ' , POPT_ARG_VAL , & server_mode , SERVER_MODE_INTERACTIVE , " Interactive mode " } ,
2004-03-16 21:54:09 +03:00
{ " no-caching " , ' n ' , POPT_ARG_VAL , & opt_nocache , True , " Disable caching " } ,
2003-04-14 07:53:58 +04:00
POPT_COMMON_SAMBA
POPT_TABLEEND
} ;
poptContext pc ;
2002-03-14 05:15:08 +03:00
int opt ;
2001-05-07 08:32:40 +04:00
2001-11-22 02:00:59 +03:00
/* glibc (?) likes to print "User defined signal 1" and exit if a
2002-03-27 01:33:06 +03:00
SIGUSR [ 12 ] is received before a handler is installed */
2001-11-15 06:23:15 +03:00
2002-03-27 01:33:06 +03:00
CatchSignal ( SIGUSR1 , SIG_IGN ) ;
2002-01-10 09:20:03 +03:00
CatchSignal ( SIGUSR2 , SIG_IGN ) ;
2001-11-15 06:23:15 +03:00
2001-11-23 14:18:20 +03:00
fault_setup ( ( void ( * ) ( void * ) ) fault_quit ) ;
2006-04-04 04:27:50 +04:00
dump_core_setup ( " winbindd " ) ;
2001-12-21 05:23:38 +03:00
2005-12-29 00:10:11 +03:00
load_case_tables ( ) ;
2001-11-15 00:49:30 +03:00
/* Initialise for running in non-root mode */
2001-10-05 04:20:06 +04:00
2001-07-08 22:25:19 +04:00
sec_init ( ) ;
2001-05-08 07:52:07 +04:00
2003-04-14 07:53:58 +04:00
set_remote_machine_name ( " winbindd " , False ) ;
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
2006-04-02 23:45:42 +04:00
if ( ! winbind_off ( ) ) {
2006-04-02 10:25:11 +04:00
DEBUG ( 0 , ( " Failed to disable recusive winbindd calls. Exiting. \n " ) ) ;
exit ( 1 ) ;
}
2001-05-07 08:32:40 +04:00
/* Initialise samba/rpc client stuff */
2003-04-14 07:53:58 +04:00
pc = poptGetContext ( " winbindd " , argc , ( const char * * ) argv , long_options ,
POPT_CONTEXT_KEEP_FIRST ) ;
2001-05-07 08:32:40 +04:00
2007-04-20 22:34:33 +04:00
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) { }
if ( server_mode = = SERVER_MODE_INTERACTIVE ) {
log_stdout = True ;
if ( DEBUGLEVEL > = 9 ) {
talloc_enable_leak_report ( ) ;
2000-05-09 15:43:00 +04:00
}
2001-05-07 08:32:40 +04:00
}
2000-05-09 15:43:00 +04:00
2007-04-20 22:34:33 +04:00
if ( log_stdout & & server_mode = = SERVER_MODE_DAEMON ) {
printf ( " Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i) \n " ) ;
2003-04-14 07:53:58 +04:00
poptPrintUsage ( pc , stderr , 0 ) ;
2003-01-03 20:39:30 +03:00
exit ( 1 ) ;
}
2004-09-21 13:07:42 +04:00
if ( ! override_logfile ) {
pstr_sprintf ( logfile , " %s/log.winbindd " , dyn_LOGFILEBASE ) ;
lp_set_logfile ( logfile ) ;
}
2003-01-03 20:39:30 +03:00
setup_logging ( " winbindd " , log_stdout ) ;
2001-05-07 08:32:40 +04:00
reopen_logs ( ) ;
2000-05-09 15:43:00 +04:00
2007-01-19 21:13:53 +03:00
DEBUG ( 1 , ( " winbindd version %s started. \n %s \n " ,
SAMBA_VERSION_STRING ,
COPYRIGHT_STARTUP_MESSAGE ) ) ;
2001-12-20 21:37:43 +03:00
2004-01-29 03:10:40 +03:00
if ( ! reload_services_file ( ) ) {
2001-12-20 21:37:43 +03:00
DEBUG ( 0 , ( " error opening config file \n " ) ) ;
exit ( 1 ) ;
}
2006-09-02 06:04:41 +04:00
if ( ! directory_exist ( lp_lockdir ( ) , NULL ) ) {
mkdir ( lp_lockdir ( ) , 0755 ) ;
}
2001-12-20 21:37:43 +03:00
/* Setup names. */
2002-01-22 03:35:05 +03:00
2002-11-13 02:20:50 +03:00
if ( ! init_names ( ) )
exit ( 1 ) ;
2000-05-09 15:43:00 +04:00
2003-05-06 06:32:47 +04:00
load_interfaces ( ) ;
if ( ! secrets_init ( ) ) {
DEBUG ( 0 , ( " Could not initialize domain trust account secrets. Giving up \n " ) ) ;
return False ;
}
/* Enable netbios namecache */
namecache_enable ( ) ;
/* Winbind daemon initialisation */
2007-03-01 06:16:38 +03:00
if ( ! NT_STATUS_IS_OK ( idmap_init_cache ( ) ) ) {
DEBUG ( 1 , ( " Could not init idmap cache! \n " ) ) ;
2004-06-29 19:46:43 +04:00
}
2003-05-06 06:32:47 +04:00
/* Unblock all signals we are interested in as they may have been
blocked by the parent process . */
BlockSignals ( False , SIGINT ) ;
BlockSignals ( False , SIGQUIT ) ;
BlockSignals ( False , SIGTERM ) ;
BlockSignals ( False , SIGUSR1 ) ;
BlockSignals ( False , SIGUSR2 ) ;
BlockSignals ( False , SIGHUP ) ;
2004-07-21 08:24:30 +04:00
BlockSignals ( False , SIGCHLD ) ;
2003-05-06 06:32:47 +04:00
/* Setup signal handlers */
CatchSignal ( SIGINT , termination_handler ) ; /* Exit on these sigs */
CatchSignal ( SIGQUIT , termination_handler ) ;
CatchSignal ( SIGTERM , termination_handler ) ;
2004-07-21 08:24:30 +04:00
CatchSignal ( SIGCHLD , sigchld_handler ) ;
2003-05-06 06:32:47 +04:00
CatchSignal ( SIGPIPE , SIG_IGN ) ; /* Ignore sigpipe */
CatchSignal ( SIGUSR2 , sigusr2_handler ) ; /* Debugging sigs */
CatchSignal ( SIGHUP , sighup_handler ) ;
2007-04-20 22:34:33 +04:00
if ( server_mode = = SERVER_MODE_DAEMON ) {
DEBUG ( 3 , ( " Becoming a daemon. \n " ) ) ;
become_daemon ( True , no_process_group ) ;
} else if ( server_mode = = SERVER_MODE_FOREGROUND ) {
become_daemon ( False , no_process_group ) ;
}
2000-05-09 15:43:00 +04:00
2003-04-14 07:53:58 +04:00
pidfile_create ( " winbindd " ) ;
2002-09-25 19:19:00 +04:00
2007-03-01 06:16:38 +03:00
#if 0 /* not finished yet */
2006-11-30 03:09:34 +03:00
/* Ensure all cache and idmap caches are consistent
before we startup . */
2006-11-30 02:20:22 +03:00
if ( winbindd_validate_cache ( ) ) {
/* We have a bad cache, but luckily we
just deleted it . Restart ourselves */
int i ;
/* Ensure we have no open low fd's. */
for ( i = 3 ; i < 100 ; i + + ) {
close ( i ) ;
}
return execve ( argv [ 0 ] , argv , envp ) ;
}
2007-03-01 06:16:38 +03:00
# endif
2006-11-30 02:20:22 +03:00
2001-12-30 04:46:38 +03:00
# if HAVE_SETPGID
/*
* If we ' re interactive we want to set our own process group for
* signal management .
*/
2007-04-20 22:34:33 +04:00
if ( server_mode = = SERVER_MODE_INTERACTIVE & & ! no_process_group ) {
2001-12-30 04:46:38 +03:00
setpgid ( ( pid_t ) 0 , ( pid_t ) 0 ) ;
2007-04-20 22:34:33 +04:00
}
2001-12-30 04:46:38 +03:00
# endif
2005-11-05 07:21:55 +03:00
TimeInit ( ) ;
2002-03-27 01:33:06 +03:00
/* Initialise messaging system */
if ( ! message_init ( ) ) {
2006-02-23 19:51:53 +03:00
DEBUG ( 0 , ( " unable to initialize messaging system \n " ) ) ;
2002-03-27 01:33:06 +03:00
exit ( 1 ) ;
}
2003-07-15 21:21:21 +04:00
2007-04-14 02:29:50 +04:00
/* Initialize cache (ensure version is correct). */
if ( ! initialize_winbindd_cache ( ) ) {
exit ( 1 ) ;
}
2003-07-15 21:21:21 +04:00
/* React on 'smbcontrol winbindd reload-config' in the same way
as to SIGHUP signal */
r21064: The core of this patch is
void message_register(int msg_type,
void (*fn)(int msg_type, struct process_id pid,
- void *buf, size_t len))
+ void *buf, size_t len,
+ void *private_data),
+ void *private_data)
{
struct dispatch_fns *dfn;
So this adds a (so far unused) private pointer that is passed from
message_register to the message handler. A prerequisite to implement a tiny
samba4-API compatible wrapper around our messaging system. That itself is
necessary for the Samba4 notify system.
Yes, I know, I could import the whole Samba4 messaging system, but I want to
do it step by step and I think getting notify in is more important in this
step.
Volker
(This used to be commit c8ae60ed65dcce9660ee39c75488f2838cf9a28b)
2007-01-31 01:22:06 +03:00
message_register ( MSG_SMB_CONF_UPDATED , msg_reload_services , NULL ) ;
message_register ( MSG_SHUTDOWN , msg_shutdown , NULL ) ;
2006-02-04 01:19:41 +03:00
/* Handle online/offline messages. */
r21064: The core of this patch is
void message_register(int msg_type,
void (*fn)(int msg_type, struct process_id pid,
- void *buf, size_t len))
+ void *buf, size_t len,
+ void *private_data),
+ void *private_data)
{
struct dispatch_fns *dfn;
So this adds a (so far unused) private pointer that is passed from
message_register to the message handler. A prerequisite to implement a tiny
samba4-API compatible wrapper around our messaging system. That itself is
necessary for the Samba4 notify system.
Yes, I know, I could import the whole Samba4 messaging system, but I want to
do it step by step and I think getting notify in is more important in this
step.
Volker
(This used to be commit c8ae60ed65dcce9660ee39c75488f2838cf9a28b)
2007-01-31 01:22:06 +03:00
message_register ( MSG_WINBIND_OFFLINE , winbind_msg_offline , NULL ) ;
message_register ( MSG_WINBIND_ONLINE , winbind_msg_online , NULL ) ;
message_register ( MSG_WINBIND_ONLINESTATUS , winbind_msg_onlinestatus ,
NULL ) ;
2006-02-04 01:19:41 +03:00
2003-04-14 07:53:58 +04:00
poptFreeContext ( pc ) ;
2002-03-27 01:33:06 +03:00
2005-11-10 23:28:23 +03:00
netsamlogon_cache_init ( ) ; /* Non-critical */
2006-03-16 18:21:41 +03:00
if ( ! init_domain_list ( ) ) {
2006-03-16 14:32:01 +03:00
DEBUG ( 0 , ( " unable to initalize domain list \n " ) ) ;
exit ( 1 ) ;
}
2004-01-08 11:19:18 +03:00
2005-06-09 02:10:34 +04:00
init_idmap_child ( ) ;
2006-09-20 04:15:50 +04:00
smb_nscd_flush_user_cache ( ) ;
smb_nscd_flush_group_cache ( ) ;
2006-03-16 16:37:23 +03:00
2001-05-07 08:32:40 +04:00
/* Loop waiting for requests */
2007-04-21 01:09:44 +04:00
winbindd_process_loop ( server_mode ) ;
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
}