2000-05-09 11:43:00 +00:00
/*
2002-01-30 06:08:46 +00:00
Unix SMB / CIFS implementation .
2000-05-09 11:43:00 +00:00
Winbind daemon for ntdom nss module
2002-11-07 07:17:09 +00:00
Copyright ( C ) by Tim Potter 2000 - 2002
2002-07-15 10:35:28 +00:00
Copyright ( C ) Andrew Tridgell 2002
2003-04-14 03:53:58 +00:00
Copyright ( C ) Jelmer Vernooij 2003
2005-06-08 22:10:34 +00:00
Copyright ( C ) Volker Lendecke 2004
2008-11-26 14:01:22 +01:00
2000-05-09 11:43:00 +00: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
2007-07-09 19:25:36 +00:00
the Free Software Foundation ; either version 3 of the License , or
2000-05-09 11:43:00 +00:00
( at your option ) any later version .
2008-11-26 14:01:22 +01:00
2000-05-09 11:43:00 +00:00
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 .
2008-11-26 14:01:22 +01:00
2000-05-09 11:43:00 +00:00
You should have received a copy of the GNU General Public License
2007-07-10 00:52:41 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2000-05-09 11:43:00 +00:00
*/
2003-11-12 01:51:10 +00:00
# include "includes.h"
2000-05-09 11:43:00 +00:00
# include "winbindd.h"
2009-05-09 20:04:27 +02:00
# include "../../nsswitch/libwbclient/wbc_async.h"
2000-05-09 11:43:00 +00:00
2006-04-20 13:51:43 +00:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_WINBIND
2009-05-25 20:28:38 +02:00
static void remove_client ( struct winbindd_cli_state * state ) ;
2009-03-12 10:12:58 +01:00
static bool opt_nocache = False ;
2007-10-18 17:40:25 -07:00
static bool interactive = False ;
2000-05-09 11:43:00 +00:00
2007-10-18 17:40:25 -07:00
extern bool override_logfile ;
2004-09-21 09:07:42 +00:00
2007-01-17 12:59:14 +00:00
struct event_context * winbind_event_context ( void )
{
static struct event_context * ctx ;
if ( ! ctx & & ! ( ctx = event_context_init ( NULL ) ) ) {
2007-06-15 21:58:49 +00:00
smb_panic ( " Could not init winbind event context " ) ;
2007-01-17 12:59:14 +00:00
}
return ctx ;
}
2007-05-15 10:50:44 +00:00
struct messaging_context * winbind_messaging_context ( void )
{
static struct messaging_context * ctx ;
2008-06-24 12:30:38 +02:00
if ( ctx = = NULL ) {
ctx = messaging_init ( NULL , server_id_self ( ) ,
winbind_event_context ( ) ) ;
}
if ( ctx = = NULL ) {
2008-06-24 12:29:05 +02:00
DEBUG ( 0 , ( " Could not init winbind messaging context. \n " ) ) ;
2007-05-15 10:50:44 +00:00
}
return ctx ;
}
2000-05-09 11:43:00 +00:00
/* Reload configuration */
2008-11-03 12:36:34 -08:00
static bool reload_services_file ( const char * lfile )
2000-05-09 11:43:00 +00:00
{
2007-10-18 17:40:25 -07:00
bool ret ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
if ( lp_loaded ( ) ) {
2007-11-20 17:18:16 -08:00
const char * fname = lp_configfile ( ) ;
2001-05-07 04:32:40 +00:00
2008-10-17 12:48:19 +02:00
if ( file_exist ( fname ) & & ! strcsequal ( fname , get_dyn_CONFIGFILE ( ) ) ) {
2007-12-10 11:30:37 -08:00
set_dyn_CONFIGFILE ( fname ) ;
2001-05-07 04:32:40 +00:00
}
}
2008-07-17 20:10:18 -07:00
/* if this is a child, restore the logfile to the special
name - < domain > , idmap , etc . */
2008-11-03 12:36:34 -08:00
if ( lfile & & * lfile ) {
lp_set_logfile ( lfile ) ;
2008-07-17 20:10:18 -07:00
}
2000-05-09 11:43:00 +00:00
reopen_logs ( ) ;
2007-12-10 11:30:37 -08:00
ret = lp_load ( get_dyn_CONFIGFILE ( ) , False , False , True , True ) ;
2000-05-09 11:43:00 +00:00
reopen_logs ( ) ;
load_interfaces ( ) ;
return ( ret ) ;
}
2003-07-15 17:21:21 +00:00
2001-11-23 11:18:20 +00:00
/**************************************************************************** **
Handle a fault . .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void fault_quit ( void )
{
dump_core ( ) ;
}
2001-11-14 06:18:13 +00:00
static void winbindd_status ( void )
2000-05-09 11:43:00 +00:00
{
2001-05-07 04:32:40 +00:00
struct winbindd_cli_state * tmp ;
2001-11-14 06:18:13 +00:00
DEBUG ( 0 , ( " winbindd status: \n " ) ) ;
2001-05-07 04:32:40 +00:00
/* Print client state information */
2008-11-26 14:01:22 +01:00
2002-11-02 01:36:42 +00:00
DEBUG ( 0 , ( " \t %d clients currently active \n " , winbindd_num_clients ( ) ) ) ;
2008-11-26 14:01:22 +01:00
2002-11-02 01:36:42 +00:00
if ( DEBUGLEVEL > = 2 & & winbindd_num_clients ( ) ) {
2001-05-07 04:32:40 +00:00
DEBUG ( 2 , ( " \t client list: \n " ) ) ;
2002-11-02 01:36:42 +00:00
for ( tmp = winbindd_client_list ( ) ; tmp ; tmp = tmp - > next ) {
2006-02-03 22:19:41 +00:00
DEBUGADD ( 2 , ( " \t \t pid %lu, sock %d \n " ,
2005-10-27 07:57:39 +00:00
( unsigned long ) tmp - > pid , tmp - > sock ) ) ;
2001-05-07 04:32:40 +00:00
}
}
}
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* Print winbindd status to log file */
2000-05-09 11:43:00 +00:00
2001-11-15 03:23:15 +00:00
static void print_winbindd_status ( void )
2001-05-07 04:32:40 +00:00
{
2001-11-14 06:18:13 +00:00
winbindd_status ( ) ;
2000-05-09 11:43:00 +00:00
}
/* Flush client cache */
2001-11-15 03:23:15 +00:00
static void flush_caches ( void )
2000-05-09 11:43:00 +00:00
{
2003-06-21 04:05:01 +00: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 . */
2008-01-07 10:59:14 +01:00
if ( ! wcache_invalidate_cache ( ) ) {
2007-11-26 11:44:30 +01:00
DEBUG ( 0 , ( " invalidating the cache failed; revalidate the cache \n " ) ) ;
2008-04-10 11:53:53 +02:00
if ( ! winbindd_cache_validate_and_initialize ( ) ) {
2007-11-26 11:44:30 +01:00
exit ( 1 ) ;
}
}
2000-05-09 11:43:00 +00:00
}
/* Handle the signal by unlinking socket and exiting */
2008-05-30 17:52:54 -07:00
static void terminate ( bool is_parent )
2000-05-09 11:43:00 +00:00
{
2008-05-30 17:52:54 -07:00
if ( is_parent ) {
/* When parent goes away we should
* remove the socket file . Not so
* when children terminate .
*/
char * path = NULL ;
2007-10-10 15:34:30 -05:00
2008-05-30 17:52:54 -07:00
if ( asprintf ( & path , " %s/%s " ,
2007-11-20 17:18:16 -08:00
get_winbind_pipe_dir ( ) , WINBINDD_SOCKET_NAME ) > 0 ) {
2008-05-30 17:52:54 -07:00
unlink ( path ) ;
SAFE_FREE ( path ) ;
}
2007-11-20 17:18:16 -08:00
}
2005-06-08 22:10:34 +00:00
2007-02-20 19:57:14 +00:00
idmap_close ( ) ;
2008-11-26 14:01:22 +01:00
2007-02-20 19:57:14 +00:00
trustdom_cache_shutdown ( ) ;
2009-07-13 17:04:29 +02:00
gencache_stabilize ( ) ;
2005-06-08 22:10:34 +00: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
2009-06-18 11:45:57 +02:00
if ( is_parent ) {
pidfile_unlink ( ) ;
}
2001-05-07 04:32:40 +00:00
exit ( 0 ) ;
}
2000-05-09 11:43:00 +00:00
2009-01-22 14:54:21 +01:00
static void winbindd_sig_term_handler ( struct tevent_context * ev ,
struct tevent_signal * se ,
int signum ,
int count ,
void * siginfo ,
void * private_data )
{
bool * is_parent = talloc_get_type_abort ( private_data , bool ) ;
DEBUG ( 0 , ( " Got sig[%d] terminate (is_parent=%d) \n " ,
signum , ( int ) * is_parent ) ) ;
terminate ( * is_parent ) ;
}
2001-11-14 21:49:30 +00:00
2009-01-22 14:54:21 +01:00
bool winbindd_setup_sig_term_handler ( bool parent )
2001-11-14 21:49:30 +00:00
{
2009-01-22 14:54:21 +01:00
struct tevent_signal * se ;
bool * is_parent ;
is_parent = talloc ( winbind_event_context ( ) , bool ) ;
if ( ! is_parent ) {
return false ;
}
* is_parent = parent ;
se = tevent_add_signal ( winbind_event_context ( ) ,
is_parent ,
SIGTERM , 0 ,
winbindd_sig_term_handler ,
is_parent ) ;
if ( ! se ) {
DEBUG ( 0 , ( " failed to setup SIGTERM handler " ) ) ;
talloc_free ( is_parent ) ;
return false ;
}
se = tevent_add_signal ( winbind_event_context ( ) ,
is_parent ,
SIGINT , 0 ,
winbindd_sig_term_handler ,
is_parent ) ;
if ( ! se ) {
DEBUG ( 0 , ( " failed to setup SIGINT handler " ) ) ;
talloc_free ( is_parent ) ;
return false ;
}
se = tevent_add_signal ( winbind_event_context ( ) ,
is_parent ,
SIGQUIT , 0 ,
winbindd_sig_term_handler ,
is_parent ) ;
if ( ! se ) {
DEBUG ( 0 , ( " failed to setup SIGINT handler " ) ) ;
talloc_free ( is_parent ) ;
return false ;
}
return true ;
2001-11-14 21:49:30 +00:00
}
2009-01-22 14:54:21 +01:00
static void winbindd_sig_hup_handler ( struct tevent_context * ev ,
struct tevent_signal * se ,
int signum ,
int count ,
void * siginfo ,
void * private_data )
{
const char * file = ( const char * ) private_data ;
DEBUG ( 1 , ( " Reloading services after SIGHUP \n " ) ) ;
flush_caches ( ) ;
reload_services_file ( file ) ;
}
2000-05-09 11:43:00 +00:00
2009-01-22 14:54:21 +01:00
bool winbindd_setup_sig_hup_handler ( const char * lfile )
2001-05-07 04:32:40 +00:00
{
2009-01-22 14:54:21 +01:00
struct tevent_signal * se ;
char * file = NULL ;
if ( lfile ) {
file = talloc_strdup ( winbind_event_context ( ) ,
lfile ) ;
if ( ! file ) {
return false ;
}
}
se = tevent_add_signal ( winbind_event_context ( ) ,
winbind_event_context ( ) ,
SIGHUP , 0 ,
winbindd_sig_hup_handler ,
file ) ;
if ( ! se ) {
return false ;
}
return true ;
2000-05-09 11:43:00 +00:00
}
2009-01-22 14:54:21 +01:00
static void winbindd_sig_chld_handler ( struct tevent_context * ev ,
struct tevent_signal * se ,
int signum ,
int count ,
void * siginfo ,
void * private_data )
{
pid_t pid ;
while ( ( pid = sys_waitpid ( - 1 , NULL , WNOHANG ) ) > 0 ) {
winbind_child_died ( pid ) ;
}
}
2000-05-09 11:43:00 +00:00
2009-01-22 14:54:21 +01:00
static bool winbindd_setup_sig_chld_handler ( void )
2000-05-09 11:43:00 +00:00
{
2009-01-22 14:54:21 +01:00
struct tevent_signal * se ;
se = tevent_add_signal ( winbind_event_context ( ) ,
winbind_event_context ( ) ,
SIGCHLD , 0 ,
winbindd_sig_chld_handler ,
NULL ) ;
if ( ! se ) {
return false ;
}
return true ;
2000-05-09 11:43:00 +00:00
}
2009-01-22 14:54:21 +01:00
static void winbindd_sig_usr2_handler ( struct tevent_context * ev ,
struct tevent_signal * se ,
int signum ,
int count ,
void * siginfo ,
void * private_data )
{
print_winbindd_status ( ) ;
}
2005-06-08 22:10:34 +00:00
2009-01-22 14:54:21 +01:00
static bool winbindd_setup_sig_usr2_handler ( void )
2004-07-21 04:24:30 +00:00
{
2009-01-22 14:54:21 +01:00
struct tevent_signal * se ;
se = tevent_add_signal ( winbind_event_context ( ) ,
winbind_event_context ( ) ,
2009-03-04 17:26:57 -08:00
SIGUSR2 , 0 ,
2009-01-22 14:54:21 +01:00
winbindd_sig_usr2_handler ,
NULL ) ;
if ( ! se ) {
return false ;
}
return true ;
2004-07-21 04:24:30 +00:00
}
2003-07-15 17:21:21 +00:00
/* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
2007-05-16 14:45:09 +00:00
static void msg_reload_services ( struct messaging_context * msg ,
void * private_data ,
uint32_t msg_type ,
struct server_id server_id ,
DATA_BLOB * data )
2003-07-15 17:21:21 +00:00
{
/* Flush various caches */
flush_caches ( ) ;
2008-07-17 20:10:18 -07:00
reload_services_file ( ( const char * ) private_data ) ;
2003-07-15 17:21:21 +00:00
}
/* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
2007-05-16 14:45:09 +00:00
static void msg_shutdown ( struct messaging_context * msg ,
void * private_data ,
uint32_t msg_type ,
struct server_id server_id ,
DATA_BLOB * data )
2003-07-15 17:21:21 +00:00
{
2009-01-22 14:54:21 +01:00
/* only the parent waits for this message */
DEBUG ( 0 , ( " Got shutdown message \n " ) ) ;
terminate ( true ) ;
2003-07-15 17:21:21 +00:00
}
2007-08-31 15:24:43 +00:00
static void winbind_msg_validate_cache ( struct messaging_context * msg_ctx ,
void * private_data ,
uint32_t msg_type ,
struct server_id server_id ,
DATA_BLOB * data )
{
uint8 ret ;
2007-09-02 00:32:57 +00:00
pid_t child_pid ;
struct sigaction act ;
struct sigaction oldact ;
2007-08-31 15:24:43 +00:00
DEBUG ( 10 , ( " winbindd_msg_validate_cache: got validate-cache "
" message. \n " ) ) ;
2007-09-02 00:32:57 +00:00
/*
* call the validation code from a child :
* so we don ' t block the main winbindd and the validation
* code can safely use fork / waitpid . . .
*/
CatchChild ( ) ;
child_pid = sys_fork ( ) ;
if ( child_pid = = - 1 ) {
DEBUG ( 1 , ( " winbind_msg_validate_cache: Could not fork: %s \n " ,
strerror ( errno ) ) ) ;
return ;
}
if ( child_pid ! = 0 ) {
/* parent */
DEBUG ( 5 , ( " winbind_msg_validate_cache: child created with "
2009-02-23 16:22:43 -08:00
" pid %d. \n " , ( int ) child_pid ) ) ;
2007-09-02 00:32:57 +00:00
return ;
}
/* child */
/* install default SIGCHLD handler: validation code uses fork/waitpid */
ZERO_STRUCT ( act ) ;
act . sa_handler = SIG_DFL ;
# ifdef SA_RESTART
/* We *want* SIGALRM to interrupt a system call. */
act . sa_flags = SA_RESTART ;
# endif
sigemptyset ( & act . sa_mask ) ;
sigaddset ( & act . sa_mask , SIGCHLD ) ;
sigaction ( SIGCHLD , & act , & oldact ) ;
2007-08-31 15:24:43 +00:00
ret = ( uint8 ) winbindd_validate_cache_nobackup ( ) ;
DEBUG ( 10 , ( " winbindd_msg_validata_cache: got return value %d \n " , ret ) ) ;
messaging_send_buf ( msg_ctx , server_id , MSG_WINBIND_VALIDATE_CACHE , & ret ,
( size_t ) 1 ) ;
2007-09-02 00:32:57 +00:00
_exit ( 0 ) ;
2007-08-31 15:24:43 +00:00
}
2005-06-20 13:42:29 +00:00
static struct winbindd_dispatch_table {
enum winbindd_cmd cmd ;
void ( * fn ) ( struct winbindd_cli_state * state ) ;
const char * winbindd_cmd_name ;
} dispatch_table [ ] = {
2008-11-26 14:01:22 +01:00
2001-05-07 04:32:40 +00:00
/* PAM auth functions */
2000-05-09 11:43:00 +00:00
2001-11-14 04:44:36 +00:00
{ WINBINDD_PAM_AUTH , winbindd_pam_auth , " PAM_AUTH " } ,
2005-06-10 03:26:39 +00:00
{ WINBINDD_PAM_AUTH_CRAP , winbindd_pam_auth_crap , " AUTH_CRAP " } ,
2001-11-14 04:44:36 +00:00
{ WINBINDD_PAM_CHAUTHTOK , winbindd_pam_chauthtok , " CHAUTHTOK " } ,
2006-02-03 22:19:41 +00:00
{ WINBINDD_PAM_LOGOFF , winbindd_pam_logoff , " PAM_LOGOFF " } ,
2006-07-13 09:29:25 +00:00
{ WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP , winbindd_pam_chng_pswd_auth_crap , " CHNG_PSWD_AUTH_CRAP " } ,
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* Enumeration functions */
2000-05-09 11:43:00 +00:00
2005-06-08 22:10:34 +00:00
{ WINBINDD_LIST_TRUSTDOM , winbindd_list_trusted_domains ,
" LIST_TRUSTDOM " } ,
2000-05-09 11:43:00 +00:00
2001-11-15 19:40:00 +00:00
/* Lookup related functions */
2000-05-09 11:43:00 +00:00
2008-10-27 23:37:55 -07:00
{ WINBINDD_REMOVE_MAPPING , winbindd_remove_mapping , " REMOVE_MAPPING " } ,
2006-12-12 14:52:13 +00:00
{ WINBINDD_SET_HWM , winbindd_set_hwm , " SET_HWMS " } ,
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* Miscellaneous */
2000-05-09 11:43:00 +00:00
2002-01-10 11:28:14 +00:00
{ WINBINDD_INFO , winbindd_info , " INFO " } ,
2005-06-08 22:10:34 +00:00
{ WINBINDD_INTERFACE_VERSION , winbindd_interface_version ,
" INTERFACE_VERSION " } ,
2002-01-26 09:55:38 +00:00
{ WINBINDD_DOMAIN_NAME , winbindd_domain_name , " DOMAIN_NAME " } ,
2004-01-04 11:51:31 +00:00
{ WINBINDD_DOMAIN_INFO , winbindd_domain_info , " DOMAIN_INFO " } ,
2003-01-28 12:07:02 +00:00
{ WINBINDD_NETBIOS_NAME , winbindd_netbios_name , " NETBIOS_NAME " } ,
2005-06-08 22:10:34 +00:00
{ WINBINDD_PRIV_PIPE_DIR , winbindd_priv_pipe_dir ,
" WINBINDD_PRIV_PIPE_DIR " } ,
2000-05-09 11:43:00 +00:00
2006-08-19 01:04:54 +00:00
/* Credential cache access */
{ WINBINDD_CCACHE_NTLMAUTH , winbindd_ccache_ntlm_auth , " NTLMAUTH " } ,
2002-03-29 15:37:39 +00:00
/* WINS functions */
{ WINBINDD_WINS_BYNAME , winbindd_wins_byname , " WINS_BYNAME " } ,
{ WINBINDD_WINS_BYIP , winbindd_wins_byip , " WINS_BYIP " } ,
2008-10-27 23:36:36 -07:00
2001-05-07 04:32:40 +00:00
/* End of list */
2000-05-09 11:43:00 +00:00
2001-11-14 04:44:36 +00:00
{ WINBINDD_NUM_CMDS , NULL , " NONE " }
2001-05-07 04:32:40 +00:00
} ;
2000-05-09 11:43:00 +00:00
2009-05-16 12:00:07 +02:00
struct winbindd_async_dispatch_table {
enum winbindd_cmd cmd ;
const char * cmd_name ;
struct tevent_req * ( * send_req ) ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
2009-08-16 12:46:55 +02:00
struct winbindd_cli_state * cli ,
2009-05-16 12:00:07 +02:00
struct winbindd_request * request ) ;
2009-07-31 16:16:24 +02:00
NTSTATUS ( * recv_req ) ( struct tevent_req * req ,
struct winbindd_response * presp ) ;
2009-05-16 12:00:07 +02:00
} ;
static struct winbindd_async_dispatch_table async_nonpriv_table [ ] = {
2009-05-16 12:00:34 +02:00
{ WINBINDD_PING , " PING " ,
wb_ping_send , wb_ping_recv } ,
2009-08-04 06:57:13 -04:00
{ WINBINDD_LOOKUPSID , " LOOKUPSID " ,
winbindd_lookupsid_send , winbindd_lookupsid_recv } ,
2009-08-04 07:29:03 -04:00
{ WINBINDD_LOOKUPNAME , " LOOKUPNAME " ,
winbindd_lookupname_send , winbindd_lookupname_recv } ,
2009-08-04 13:33:56 -04:00
{ WINBINDD_SID_TO_UID , " SID_TO_UID " ,
winbindd_sid_to_uid_send , winbindd_sid_to_uid_recv } ,
2009-08-04 13:42:22 -04:00
{ WINBINDD_SID_TO_GID , " SID_TO_GID " ,
winbindd_sid_to_gid_send , winbindd_sid_to_gid_recv } ,
2009-08-04 14:07:44 -04:00
{ WINBINDD_UID_TO_SID , " UID_TO_SID " ,
winbindd_uid_to_sid_send , winbindd_uid_to_sid_recv } ,
2009-08-04 14:22:17 -04:00
{ WINBINDD_GID_TO_SID , " GID_TO_SID " ,
winbindd_gid_to_sid_send , winbindd_gid_to_sid_recv } ,
2009-08-04 15:35:24 -04:00
{ WINBINDD_GETPWSID , " GETPWSID " ,
winbindd_getpwsid_send , winbindd_getpwsid_recv } ,
2009-08-04 15:37:54 -04:00
{ WINBINDD_GETPWNAM , " GETPWNAM " ,
winbindd_getpwnam_send , winbindd_getpwnam_recv } ,
2009-08-04 15:41:40 -04:00
{ WINBINDD_GETPWUID , " GETPWUID " ,
winbindd_getpwuid_send , winbindd_getpwuid_recv } ,
2009-08-04 15:58:45 -04:00
{ WINBINDD_GETSIDALIASES , " GETSIDALIASES " ,
winbindd_getsidaliases_send , winbindd_getsidaliases_recv } ,
2009-08-04 16:20:18 -04:00
{ WINBINDD_GETUSERDOMGROUPS , " GETUSERDOMGROUPS " ,
winbindd_getuserdomgroups_send , winbindd_getuserdomgroups_recv } ,
2009-08-04 16:26:07 -04:00
{ WINBINDD_GETGROUPS , " GETGROUPS " ,
winbindd_getgroups_send , winbindd_getgroups_recv } ,
2009-08-15 13:23:57 +02:00
{ WINBINDD_SHOW_SEQUENCE , " SHOW_SEQUENCE " ,
winbindd_show_sequence_send , winbindd_show_sequence_recv } ,
2009-08-16 12:13:00 +02:00
{ WINBINDD_GETGRGID , " GETGRGID " ,
winbindd_getgrgid_send , winbindd_getgrgid_recv } ,
2009-08-16 12:23:31 +02:00
{ WINBINDD_GETGRNAM , " GETGRNAM " ,
winbindd_getgrnam_send , winbindd_getgrnam_recv } ,
2009-08-27 14:55:41 +02:00
{ WINBINDD_GETUSERSIDS , " GETUSERSIDS " ,
winbindd_getusersids_send , winbindd_getusersids_recv } ,
2009-08-27 17:11:24 +02:00
{ WINBINDD_LOOKUPRIDS , " LOOKUPRIDS " ,
winbindd_lookuprids_send , winbindd_lookuprids_recv } ,
2009-08-17 23:13:48 +02:00
{ WINBINDD_SETPWENT , " SETPWENT " ,
winbindd_setpwent_send , winbindd_setpwent_recv } ,
{ WINBINDD_GETPWENT , " GETPWENT " ,
winbindd_getpwent_send , winbindd_getpwent_recv } ,
{ WINBINDD_ENDPWENT , " ENDPWENT " ,
winbindd_endpwent_send , winbindd_endpwent_recv } ,
2009-08-25 23:02:44 +02:00
{ WINBINDD_DSGETDCNAME , " DSGETDCNAME " ,
winbindd_dsgetdcname_send , winbindd_dsgetdcname_recv } ,
2009-08-26 12:27:32 +02:00
{ WINBINDD_GETDCNAME , " GETDCNAME " ,
winbindd_getdcname_send , winbindd_getdcname_recv } ,
2009-08-27 23:33:45 +02:00
{ WINBINDD_SETGRENT , " SETGRENT " ,
winbindd_setgrent_send , winbindd_setgrent_recv } ,
{ WINBINDD_GETGRENT , " GETGRENT " ,
winbindd_getgrent_send , winbindd_getgrent_recv } ,
{ WINBINDD_ENDGRENT , " ENDGRENT " ,
winbindd_endgrent_send , winbindd_endgrent_recv } ,
2009-08-29 16:05:02 +02:00
{ WINBINDD_LIST_USERS , " LIST_USERS " ,
winbindd_list_users_send , winbindd_list_users_recv } ,
2009-08-29 17:17:47 +02:00
{ WINBINDD_LIST_GROUPS , " LIST_GROUPS " ,
winbindd_list_groups_send , winbindd_list_groups_recv } ,
2009-09-06 09:32:34 +02:00
{ WINBINDD_CHECK_MACHACC , " CHECK_MACHACC " ,
winbindd_check_machine_acct_send , winbindd_check_machine_acct_recv } ,
2009-05-16 12:00:34 +02:00
2009-05-16 12:00:07 +02:00
{ 0 , NULL , NULL , NULL }
} ;
2009-08-30 09:41:43 +02:00
static struct winbindd_async_dispatch_table async_priv_table [ ] = {
{ WINBINDD_ALLOCATE_UID , " ALLOCATE_UID " ,
winbindd_allocate_uid_send , winbindd_allocate_uid_recv } ,
2009-08-30 09:46:34 +02:00
{ WINBINDD_ALLOCATE_GID , " ALLOCATE_GID " ,
winbindd_allocate_gid_send , winbindd_allocate_gid_recv } ,
2009-09-06 14:47:06 +02:00
{ WINBINDD_SET_MAPPING , " SET_MAPPING " ,
winbindd_set_mapping_send , winbindd_set_mapping_recv } ,
2009-08-30 09:41:43 +02:00
{ 0 , NULL , NULL , NULL }
} ;
2009-05-16 12:00:07 +02:00
static void wb_request_done ( struct tevent_req * req ) ;
2001-05-07 04:32:40 +00:00
static void process_request ( struct winbindd_cli_state * state )
2000-05-09 11:43:00 +00:00
{
2005-06-08 22:10:34 +00:00
struct winbindd_dispatch_table * table = dispatch_table ;
2009-05-16 12:00:07 +02:00
struct winbindd_async_dispatch_table * atable ;
2000-05-09 11:43:00 +00:00
2005-06-08 22:10:34 +00:00
state - > mem_ctx = talloc_init ( " winbind request " ) ;
if ( state - > mem_ctx = = NULL )
return ;
2007-06-04 23:51:19 +00:00
/* Remember who asked us. */
2009-05-07 22:46:27 +02:00
state - > pid = state - > request - > pid ;
2007-06-04 23:51:19 +00:00
2001-05-07 04:32:40 +00:00
/* Process command */
2000-05-09 11:43:00 +00:00
2009-05-16 12:00:07 +02:00
for ( atable = async_nonpriv_table ; atable - > send_req ; atable + = 1 ) {
if ( state - > request - > cmd = = atable - > cmd ) {
break ;
}
}
2009-08-30 09:41:43 +02:00
if ( ( atable - > send_req = = NULL ) & & state - > privileged ) {
for ( atable = async_priv_table ; atable - > send_req ;
atable + = 1 ) {
if ( state - > request - > cmd = = atable - > cmd ) {
break ;
}
}
}
2009-05-16 12:00:07 +02:00
if ( atable - > send_req ! = NULL ) {
struct tevent_req * req ;
DEBUG ( 10 , ( " process_request: Handling async request %s \n " ,
atable - > cmd_name ) ) ;
req = atable - > send_req ( state - > mem_ctx , winbind_event_context ( ) ,
2009-08-16 12:46:55 +02:00
state , state - > request ) ;
2009-05-16 12:00:07 +02:00
if ( req = = NULL ) {
DEBUG ( 0 , ( " process_request: atable->send failed for "
" %s \n " , atable - > cmd_name ) ) ;
request_error ( state ) ;
return ;
}
tevent_req_set_callback ( req , wb_request_done , state ) ;
state - > recv_fn = atable - > recv_req ;
return ;
}
2009-06-14 12:58:19 +02:00
state - > response = talloc_zero ( state - > mem_ctx ,
struct winbindd_response ) ;
if ( state - > response = = NULL ) {
DEBUG ( 10 , ( " talloc failed \n " ) ) ;
remove_client ( state ) ;
return ;
}
state - > response - > result = WINBINDD_PENDING ;
state - > response - > length = sizeof ( struct winbindd_response ) ;
2001-05-07 04:32:40 +00:00
for ( table = dispatch_table ; table - > fn ; table + + ) {
2009-05-07 22:46:27 +02:00
if ( state - > request - > cmd = = table - > cmd ) {
2005-06-08 22:10:34 +00:00
DEBUG ( 10 , ( " process_request: request fn %s \n " ,
table - > winbindd_cmd_name ) ) ;
2005-06-20 13:42:29 +00:00
table - > fn ( state ) ;
2001-05-07 04:32:40 +00:00
break ;
}
}
2000-05-09 11:43:00 +00:00
2005-06-08 22:10:34 +00:00
if ( ! table - > fn ) {
DEBUG ( 10 , ( " process_request: unknown request fn number %d \n " ,
2009-05-07 22:46:27 +02:00
( int ) state - > request - > cmd ) ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
2005-06-08 22:10:34 +00:00
}
}
2009-05-16 12:00:07 +02:00
static void wb_request_done ( struct tevent_req * req )
{
struct winbindd_cli_state * state = tevent_req_callback_data (
req , struct winbindd_cli_state ) ;
NTSTATUS status ;
2009-07-31 16:16:24 +02:00
state - > response = talloc_zero ( state , struct winbindd_response ) ;
if ( state - > response = = NULL ) {
remove_client ( state ) ;
return ;
}
state - > response - > result = WINBINDD_PENDING ;
state - > response - > length = sizeof ( struct winbindd_response ) ;
status = state - > recv_fn ( req , state - > response ) ;
2009-05-16 12:00:07 +02:00
TALLOC_FREE ( req ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " returning %s \n " , nt_errstr ( status ) ) ) ;
request_error ( state ) ;
2009-07-31 16:16:24 +02:00
return ;
2009-05-16 12:00:07 +02:00
}
request_ok ( state ) ;
}
2005-06-08 22:10:34 +00:00
/*
* 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-20 13:42:29 +00:00
static void request_finished ( struct winbindd_cli_state * state ) ;
2005-06-08 22:10:34 +00:00
2009-05-09 20:04:27 +02:00
static void winbind_client_request_read ( struct tevent_req * req ) ;
static void winbind_client_response_written ( struct tevent_req * req ) ;
static void request_finished ( struct winbindd_cli_state * state )
2005-06-08 22:10:34 +00:00
{
2009-05-09 20:04:27 +02:00
struct tevent_req * req ;
2005-06-08 22:10:34 +00:00
2009-05-09 20:04:27 +02:00
TALLOC_FREE ( state - > request ) ;
2005-06-08 22:10:34 +00:00
2009-05-09 20:04:27 +02:00
req = wb_resp_write_send ( state , winbind_event_context ( ) ,
state - > out_queue , state - > sock ,
2009-06-14 12:41:46 +02:00
state - > response ) ;
2009-05-09 20:04:27 +02:00
if ( req = = NULL ) {
2009-05-25 20:28:38 +02:00
remove_client ( state ) ;
2005-06-08 22:10:34 +00:00
return ;
}
2009-05-09 20:04:27 +02:00
tevent_req_set_callback ( req , winbind_client_response_written , state ) ;
2005-06-08 22:10:34 +00:00
}
2009-05-09 20:04:27 +02:00
static void winbind_client_response_written ( struct tevent_req * req )
2005-06-08 22:10:34 +00:00
{
2009-05-09 20:04:27 +02:00
struct winbindd_cli_state * state = tevent_req_callback_data (
req , struct winbindd_cli_state ) ;
ssize_t ret ;
int err ;
2005-06-08 22:10:34 +00:00
2009-05-09 20:04:27 +02:00
ret = wb_resp_write_recv ( req , & err ) ;
TALLOC_FREE ( req ) ;
if ( ret = = - 1 ) {
DEBUG ( 2 , ( " Could not write response to client: %s \n " ,
strerror ( err ) ) ) ;
2009-05-25 20:28:38 +02:00
remove_client ( state ) ;
2005-06-08 22:10:34 +00:00
return ;
}
2009-05-09 20:04:27 +02:00
TALLOC_FREE ( state - > mem_ctx ) ;
2009-07-26 20:20:50 +02:00
state - > response = NULL ;
2005-06-08 22:10:34 +00:00
2009-05-09 20:04:27 +02:00
req = wb_req_read_send ( state , winbind_event_context ( ) , state - > sock ,
WINBINDD_MAX_EXTRA_DATA ) ;
if ( req = = NULL ) {
2009-05-25 20:28:38 +02:00
remove_client ( state ) ;
2005-06-08 22:10:34 +00:00
return ;
}
2009-05-09 20:04:27 +02:00
tevent_req_set_callback ( req , winbind_client_request_read , state ) ;
2005-06-08 22:10:34 +00:00
}
2005-06-20 13:42:29 +00:00
void request_error ( struct winbindd_cli_state * state )
{
2009-06-14 12:41:46 +02:00
SMB_ASSERT ( state - > response - > result = = WINBINDD_PENDING ) ;
state - > response - > result = WINBINDD_ERROR ;
2005-06-20 13:42:29 +00:00
request_finished ( state ) ;
}
void request_ok ( struct winbindd_cli_state * state )
{
2009-06-14 12:41:46 +02:00
SMB_ASSERT ( state - > response - > result = = WINBINDD_PENDING ) ;
state - > response - > result = WINBINDD_OK ;
2005-06-20 13:42:29 +00:00
request_finished ( state ) ;
}
2001-05-07 04:32:40 +00:00
/* Process a new connection by adding it to the client connection list */
2000-05-09 11:43:00 +00:00
2007-10-18 17:40:25 -07:00
static void new_connection ( int listen_sock , bool privileged )
2000-05-09 11:43:00 +00:00
{
2001-05-07 04:32:40 +00:00
struct sockaddr_un sunaddr ;
struct winbindd_cli_state * state ;
2009-05-09 20:04:27 +02:00
struct tevent_req * req ;
2001-06-25 02:53:13 +00:00
socklen_t len ;
int sock ;
2008-11-26 14:01:22 +01:00
2001-05-07 04:32:40 +00:00
/* Accept connection */
2008-11-26 14:01:22 +01:00
2001-05-07 04:32:40 +00:00
len = sizeof ( sunaddr ) ;
2001-11-14 21:49:30 +00:00
do {
2009-05-07 23:07:55 +02:00
sock = accept ( listen_sock , ( struct sockaddr * ) ( void * ) & sunaddr ,
& len ) ;
2001-11-14 21:49:30 +00:00
} while ( sock = = - 1 & & errno = = EINTR ) ;
if ( sock = = - 1 )
2001-05-07 04:32:40 +00:00
return ;
2008-11-26 14:01:22 +01:00
2001-05-07 04:32:40 +00:00
DEBUG ( 6 , ( " accepted socket %d \n " , sock ) ) ;
2008-11-26 14:01:22 +01:00
2001-05-07 04:32:40 +00:00
/* Create new connection structure */
2008-11-26 14:01:22 +01:00
2007-02-08 00:28:25 +00:00
if ( ( state = TALLOC_ZERO_P ( NULL , struct winbindd_cli_state ) ) = = NULL ) {
close ( sock ) ;
2001-05-07 04:32:40 +00:00
return ;
2007-02-08 00:28:25 +00:00
}
2008-11-26 14:01:22 +01:00
2001-05-07 04:32:40 +00:00
state - > sock = sock ;
2003-02-28 00:25:55 +00:00
2009-05-09 20:04:27 +02:00
state - > out_queue = tevent_queue_create ( state , " winbind client reply " ) ;
if ( state - > out_queue = = NULL ) {
close ( sock ) ;
TALLOC_FREE ( state ) ;
return ;
}
2003-02-28 00:25:55 +00:00
state - > last_access = time ( NULL ) ;
2003-04-07 07:32:51 +00:00
state - > privileged = privileged ;
2003-03-24 09:54:13 +00:00
2009-05-09 20:04:27 +02:00
req = wb_req_read_send ( state , winbind_event_context ( ) , state - > sock ,
WINBINDD_MAX_EXTRA_DATA ) ;
if ( req = = NULL ) {
TALLOC_FREE ( state ) ;
close ( sock ) ;
return ;
}
tevent_req_set_callback ( req , winbind_client_request_read , state ) ;
2005-06-08 22:10:34 +00:00
2001-05-07 04:32:40 +00:00
/* Add to connection list */
2008-11-26 14:01:22 +01:00
2002-11-02 01:36:42 +00:00
winbindd_add_client ( state ) ;
2001-05-07 04:32:40 +00:00
}
2000-05-09 11:43:00 +00:00
2009-05-09 20:04:27 +02:00
static void winbind_client_request_read ( struct tevent_req * req )
{
struct winbindd_cli_state * state = tevent_req_callback_data (
req , struct winbindd_cli_state ) ;
ssize_t ret ;
int err ;
ret = wb_req_read_recv ( req , state , & state - > request , & err ) ;
2009-07-24 19:03:45 -04:00
TALLOC_FREE ( req ) ;
2009-05-09 20:04:27 +02:00
if ( ret = = - 1 ) {
DEBUG ( 2 , ( " Could not read client request: %s \n " ,
strerror ( err ) ) ) ;
2009-05-25 20:28:38 +02:00
remove_client ( state ) ;
2009-05-09 20:04:27 +02:00
return ;
}
process_request ( state ) ;
}
2001-05-07 04:32:40 +00:00
/* Remove a client connection from client connection list */
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
static void remove_client ( struct winbindd_cli_state * state )
{
2008-10-27 14:28:44 +01:00
char c = 0 ;
2008-11-28 19:53:59 +01:00
int nwritten ;
2008-10-27 14:28:44 +01:00
2001-05-07 04:32:40 +00:00
/* It's a dead client - hold a funeral */
2008-11-26 14:01:22 +01:00
2006-10-04 16:18:36 +00:00
if ( state = = NULL ) {
return ;
}
2008-10-27 14:28:44 +01:00
/* tell client, we are closing ... */
2008-11-28 19:53:59 +01:00
nwritten = write ( state - > sock , & c , sizeof ( c ) ) ;
if ( nwritten = = - 1 ) {
2009-05-22 03:22:52 +08:00
/*
* ignore EPIPE error here , because the other end might
* have already closed the socket .
*/
if ( errno ! = EPIPE ) {
DEBUG ( 2 , ( " final write to client failed: %s \n " ,
strerror ( errno ) ) ) ;
}
2008-11-28 19:53:59 +01:00
}
2008-10-27 14:28:44 +01:00
2006-10-04 16:18:36 +00:00
/* Close socket */
2008-11-26 14:01:22 +01:00
2006-10-04 16:18:36 +00:00
close ( state - > sock ) ;
2008-11-26 14:01:22 +01:00
2006-10-04 16:18:36 +00:00
/* Free any getent state */
2008-11-26 14:01:22 +01:00
2006-10-04 16:18:36 +00:00
free_getent_state ( state - > getgrent_state ) ;
2008-11-26 14:01:22 +01:00
2008-07-24 14:46:43 +02:00
TALLOC_FREE ( state - > mem_ctx ) ;
2005-06-08 22:10:34 +00:00
2006-10-04 16:18:36 +00:00
/* Remove from list and free */
2008-11-26 14:01:22 +01:00
2006-10-04 16:18:36 +00:00
winbindd_remove_client ( state ) ;
TALLOC_FREE ( state ) ;
2001-05-07 04:32:40 +00:00
}
2000-05-09 11:43:00 +00:00
2003-02-28 00:25:55 +00:00
/* Shutdown client connection which has been idle for the longest time */
2007-10-18 17:40:25 -07:00
static bool remove_idle_client ( void )
2003-02-28 00:25:55 +00:00
{
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 ) {
2009-07-26 20:20:50 +02:00
if ( state - > response = = NULL & &
2009-08-17 23:13:48 +02:00
! state - > pwent_state & & ! state - > getgrent_state ) {
2003-02-28 00:25:55 +00: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 ;
}
2009-03-16 17:27:30 +01:00
struct winbindd_listen_state {
bool privileged ;
int fd ;
} ;
static void winbindd_listen_fde_handler ( struct tevent_context * ev ,
struct tevent_fd * fde ,
uint16_t flags ,
void * private_data )
{
struct winbindd_listen_state * s = talloc_get_type_abort ( private_data ,
struct winbindd_listen_state ) ;
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 ;
}
}
new_connection ( s - > fd , s - > privileged ) ;
}
static bool winbindd_setup_listeners ( void )
{
struct winbindd_listen_state * pub_state = NULL ;
struct winbindd_listen_state * priv_state = NULL ;
2009-05-25 20:31:59 +02:00
struct tevent_fd * fde ;
2009-03-16 17:27:30 +01:00
pub_state = talloc ( winbind_event_context ( ) ,
struct winbindd_listen_state ) ;
if ( ! pub_state ) {
goto failed ;
}
pub_state - > privileged = false ;
pub_state - > fd = open_winbindd_socket ( ) ;
if ( pub_state - > fd = = - 1 ) {
goto failed ;
}
2009-05-25 20:31:59 +02:00
fde = tevent_add_fd ( winbind_event_context ( ) , pub_state , pub_state - > fd ,
TEVENT_FD_READ , winbindd_listen_fde_handler ,
pub_state ) ;
if ( fde = = NULL ) {
2009-03-16 17:27:30 +01:00
close ( pub_state - > fd ) ;
goto failed ;
}
2009-05-25 20:31:59 +02:00
tevent_fd_set_auto_close ( fde ) ;
2009-03-16 17:27:30 +01:00
priv_state = talloc ( winbind_event_context ( ) ,
struct winbindd_listen_state ) ;
if ( ! priv_state ) {
goto failed ;
}
priv_state - > privileged = true ;
priv_state - > fd = open_winbindd_priv_socket ( ) ;
if ( priv_state - > fd = = - 1 ) {
goto failed ;
}
2009-05-25 20:31:59 +02:00
fde = tevent_add_fd ( winbind_event_context ( ) , priv_state ,
priv_state - > fd , TEVENT_FD_READ ,
winbindd_listen_fde_handler , priv_state ) ;
if ( fde = = NULL ) {
2009-03-16 17:27:30 +01:00
close ( priv_state - > fd ) ;
goto failed ;
}
2009-05-25 20:31:59 +02:00
tevent_fd_set_auto_close ( fde ) ;
2009-03-16 17:27:30 +01:00
return true ;
failed :
TALLOC_FREE ( pub_state ) ;
TALLOC_FREE ( priv_state ) ;
return false ;
}
2009-03-12 10:12:58 +01:00
bool winbindd_use_idmap_cache ( void )
{
return ! opt_nocache ;
}
bool winbindd_use_cache ( void )
{
return ! opt_nocache ;
}
2000-05-09 11:43:00 +00:00
/* Main function */
2006-11-29 23:20:22 +00:00
int main ( int argc , char * * argv , char * * envp )
2000-05-09 11:43:00 +00:00
{
2007-10-19 11:38:36 -07:00
static bool is_daemon = False ;
static bool Fork = True ;
static bool log_stdout = False ;
static bool no_process_group = False ;
enum {
OPT_DAEMON = 1000 ,
OPT_FORK ,
OPT_NO_PROCESS_GROUP ,
OPT_LOG_STDOUT
} ;
2003-04-14 03:53:58 +00:00
struct poptOption long_options [ ] = {
POPT_AUTOHELP
2007-10-19 11:38:36 -07:00
{ " stdout " , ' S ' , POPT_ARG_NONE , NULL , OPT_LOG_STDOUT , " Log to stdout " } ,
{ " foreground " , ' F ' , POPT_ARG_NONE , NULL , OPT_FORK , " Daemon in foreground mode " } ,
{ " no-process-group " , 0 , POPT_ARG_NONE , NULL , OPT_NO_PROCESS_GROUP , " Don't create a new process group " } ,
{ " daemon " , ' D ' , POPT_ARG_NONE , NULL , OPT_DAEMON , " Become a daemon (default) " } ,
2007-10-10 15:34:30 -05:00
{ " interactive " , ' i ' , POPT_ARG_NONE , NULL , ' i ' , " Interactive mode " } ,
2007-10-19 11:38:36 -07:00
{ " no-caching " , ' n ' , POPT_ARG_NONE , NULL , ' n ' , " Disable caching " } ,
2003-04-14 03:53:58 +00:00
POPT_COMMON_SAMBA
POPT_TABLEEND
} ;
poptContext pc ;
2002-03-14 02:15:08 +00:00
int opt ;
2007-11-15 14:19:52 -08:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2009-05-25 22:34:48 +02:00
struct tevent_timer * te ;
2001-05-07 04:32:40 +00:00
2001-11-21 23:00:59 +00:00
/* glibc (?) likes to print "User defined signal 1" and exit if a
2002-03-26 22:33:06 +00:00
SIGUSR [ 12 ] is received before a handler is installed */
2001-11-15 03:23:15 +00:00
2002-03-26 22:33:06 +00:00
CatchSignal ( SIGUSR1 , SIG_IGN ) ;
2002-01-10 06:20:03 +00:00
CatchSignal ( SIGUSR2 , SIG_IGN ) ;
2001-11-15 03:23:15 +00:00
2001-11-23 11:18:20 +00:00
fault_setup ( ( void ( * ) ( void * ) ) fault_quit ) ;
2006-04-04 00:27:50 +00:00
dump_core_setup ( " winbindd " ) ;
2001-12-21 02:23:38 +00:00
2005-12-28 21:10:11 +00:00
load_case_tables ( ) ;
2001-11-14 21:49:30 +00:00
/* Initialise for running in non-root mode */
2001-10-05 00:20:06 +00:00
2001-07-08 18:25:19 +00:00
sec_init ( ) ;
2001-05-08 03:52:07 +00:00
2003-04-14 03:53:58 +00:00
set_remote_machine_name ( " winbindd " , False ) ;
2001-05-07 04:32:40 +00:00
/* Set environment variable so we don't recursively call ourselves.
This may also be useful interactively . */
2001-10-05 00:20:06 +00:00
2006-04-02 19:45:42 +00:00
if ( ! winbind_off ( ) ) {
2006-04-02 06:25:11 +00:00
DEBUG ( 0 , ( " Failed to disable recusive winbindd calls. Exiting. \n " ) ) ;
exit ( 1 ) ;
}
2001-05-07 04:32:40 +00:00
/* Initialise samba/rpc client stuff */
2007-08-21 14:22:16 +00:00
pc = poptGetContext ( " winbindd " , argc , ( const char * * ) argv , long_options , 0 ) ;
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
switch ( opt ) {
2007-10-10 15:34:30 -05:00
/* Don't become a daemon */
2007-10-19 11:38:36 -07:00
case OPT_DAEMON :
2007-10-10 15:34:30 -05:00
is_daemon = True ;
break ;
case ' i ' :
interactive = True ;
log_stdout = True ;
Fork = False ;
break ;
2007-10-19 11:38:36 -07:00
case OPT_FORK :
Fork = false ;
break ;
case OPT_NO_PROCESS_GROUP :
no_process_group = true ;
break ;
case OPT_LOG_STDOUT :
log_stdout = true ;
break ;
case ' n ' :
opt_nocache = true ;
break ;
2007-08-21 14:22:16 +00:00
default :
2007-08-22 12:06:27 +00:00
d_fprintf ( stderr , " \n Invalid option %s: %s \n \n " ,
2007-08-21 14:22:16 +00:00
poptBadOption ( pc , 0 ) , poptStrerror ( opt ) ) ;
2007-08-22 12:06:27 +00:00
poptPrintUsage ( pc , stderr , 0 ) ;
2007-08-21 14:22:16 +00:00
exit ( 1 ) ;
}
}
2007-04-20 18:34:33 +00:00
2007-10-10 15:34:30 -05:00
if ( is_daemon & & interactive ) {
d_fprintf ( stderr , " \n ERROR: "
" Option -i|--interactive is not allowed together with -D|--daemon \n \n " ) ;
poptPrintUsage ( pc , stderr , 0 ) ;
exit ( 1 ) ;
2001-05-07 04:32:40 +00:00
}
2000-05-09 11:43:00 +00:00
2007-10-10 15:34:30 -05:00
if ( log_stdout & & Fork ) {
d_fprintf ( stderr , " \n ERROR: "
" Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i) \n \n " ) ;
2003-04-14 03:53:58 +00:00
poptPrintUsage ( pc , stderr , 0 ) ;
2003-01-03 17:39:30 +00:00
exit ( 1 ) ;
}
2007-08-22 12:06:27 +00:00
poptFreeContext ( pc ) ;
2004-09-21 09:07:42 +00:00
if ( ! override_logfile ) {
2008-11-03 12:36:34 -08:00
char * lfile = NULL ;
if ( asprintf ( & lfile , " %s/log.winbindd " ,
2007-12-10 11:30:37 -08:00
get_dyn_LOGFILEBASE ( ) ) > 0 ) {
2008-11-03 12:36:34 -08:00
lp_set_logfile ( lfile ) ;
SAFE_FREE ( lfile ) ;
2007-11-20 17:18:16 -08:00
}
2004-09-21 09:07:42 +00:00
}
2003-01-03 17:39:30 +00:00
setup_logging ( " winbindd " , log_stdout ) ;
2001-05-07 04:32:40 +00:00
reopen_logs ( ) ;
2000-05-09 11:43:00 +00:00
2009-01-15 22:27:52 +01:00
DEBUG ( 0 , ( " winbindd version %s started. \n " , samba_version_string ( ) ) ) ;
2007-10-30 15:44:27 +01:00
DEBUGADD ( 0 , ( " %s \n " , COPYRIGHT_STARTUP_MESSAGE ) ) ;
2001-12-20 18:37:43 +00:00
2008-04-15 10:57:16 +02:00
if ( ! lp_load_initial_only ( get_dyn_CONFIGFILE ( ) ) ) {
DEBUG ( 0 , ( " error opening config file \n " ) ) ;
exit ( 1 ) ;
}
/* Initialise messaging system */
if ( winbind_messaging_context ( ) = = NULL ) {
exit ( 1 ) ;
}
2008-07-17 20:10:18 -07:00
if ( ! reload_services_file ( NULL ) ) {
2001-12-20 18:37:43 +00:00
DEBUG ( 0 , ( " error opening config file \n " ) ) ;
exit ( 1 ) ;
}
2008-10-17 12:48:19 +02:00
if ( ! directory_exist ( lp_lockdir ( ) ) ) {
2006-09-02 02:04:41 +00:00
mkdir ( lp_lockdir ( ) , 0755 ) ;
}
2001-12-20 18:37:43 +00:00
/* Setup names. */
2002-01-22 00:35:05 +00:00
2002-11-12 23:20:50 +00:00
if ( ! init_names ( ) )
exit ( 1 ) ;
2000-05-09 11:43:00 +00:00
2003-05-06 02:32:47 +00: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 ( ) ;
/* 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 04:24:30 +00:00
BlockSignals ( False , SIGCHLD ) ;
2003-05-06 02:32:47 +00:00
2007-10-10 15:34:30 -05:00
if ( ! interactive )
become_daemon ( Fork , no_process_group ) ;
2000-05-09 11:43:00 +00:00
2003-04-14 03:53:58 +00:00
pidfile_create ( " winbindd " ) ;
2002-09-25 15:19:00 +00:00
2001-12-30 01:46:38 +00:00
# if HAVE_SETPGID
/*
* If we ' re interactive we want to set our own process group for
* signal management .
*/
2007-10-10 15:34:30 -05:00
if ( interactive & & ! no_process_group )
2001-12-30 01:46:38 +00:00
setpgid ( ( pid_t ) 0 , ( pid_t ) 0 ) ;
# endif
2005-11-05 04:21:55 +00:00
TimeInit ( ) ;
2009-01-06 17:34:06 -08:00
/* Don't use winbindd_reinit_after_fork here as
* we ' re just starting up and haven ' t created any
* winbindd - specific resources we must free yet . JRA .
*/
2009-05-05 21:18:50 +00:00
if ( ! NT_STATUS_IS_OK ( reinit_after_fork ( winbind_messaging_context ( ) ,
winbind_event_context ( ) ,
false ) ) ) {
2008-04-15 10:57:16 +02:00
DEBUG ( 0 , ( " reinit_after_fork() failed \n " ) ) ;
2002-03-26 22:33:06 +00:00
exit ( 1 ) ;
}
2007-11-23 10:54:48 +01:00
2009-01-22 14:54:21 +01:00
/* Setup signal handlers */
if ( ! winbindd_setup_sig_term_handler ( true ) )
exit ( 1 ) ;
if ( ! winbindd_setup_sig_hup_handler ( NULL ) )
exit ( 1 ) ;
if ( ! winbindd_setup_sig_chld_handler ( ) )
exit ( 1 ) ;
if ( ! winbindd_setup_sig_usr2_handler ( ) )
exit ( 1 ) ;
CatchSignal ( SIGPIPE , SIG_IGN ) ; /* Ignore sigpipe */
2007-11-23 10:54:48 +01:00
/*
* Ensure all cache and idmap caches are consistent
2008-04-10 11:53:53 +02:00
* and initialized before we startup .
2007-11-23 10:54:48 +01:00
*/
2008-04-10 11:53:53 +02:00
if ( ! winbindd_cache_validate_and_initialize ( ) ) {
2007-04-13 22:29:50 +00:00
exit ( 1 ) ;
}
2008-04-01 14:01:28 +02:00
/* get broadcast messages */
claim_connection ( NULL , " " , FLAG_MSG_GENERAL | FLAG_MSG_DBWRAP ) ;
2003-07-15 17:21:21 +00:00
/* React on 'smbcontrol winbindd reload-config' in the same way
as to SIGHUP signal */
2007-05-16 14:45:09 +00:00
messaging_register ( winbind_messaging_context ( ) , NULL ,
MSG_SMB_CONF_UPDATED , msg_reload_services ) ;
messaging_register ( winbind_messaging_context ( ) , NULL ,
MSG_SHUTDOWN , msg_shutdown ) ;
2006-02-03 22:19:41 +00:00
/* Handle online/offline messages. */
2007-05-16 14:45:09 +00:00
messaging_register ( winbind_messaging_context ( ) , NULL ,
MSG_WINBIND_OFFLINE , winbind_msg_offline ) ;
messaging_register ( winbind_messaging_context ( ) , NULL ,
MSG_WINBIND_ONLINE , winbind_msg_online ) ;
messaging_register ( winbind_messaging_context ( ) , NULL ,
MSG_WINBIND_ONLINESTATUS , winbind_msg_onlinestatus ) ;
2006-02-03 22:19:41 +00:00
2007-06-21 13:05:56 +00:00
messaging_register ( winbind_messaging_context ( ) , NULL ,
MSG_DUMP_EVENT_LIST , winbind_msg_dump_event_list ) ;
2007-08-31 15:24:43 +00:00
messaging_register ( winbind_messaging_context ( ) , NULL ,
MSG_WINBIND_VALIDATE_CACHE ,
winbind_msg_validate_cache ) ;
2008-01-24 16:19:58 +01:00
messaging_register ( winbind_messaging_context ( ) , NULL ,
MSG_WINBIND_DUMP_DOMAIN_LIST ,
winbind_msg_dump_domain_list ) ;
2008-07-01 11:37:13 -07:00
/* Register handler for MSG_DEBUG. */
messaging_register ( winbind_messaging_context ( ) , NULL ,
MSG_DEBUG ,
winbind_msg_debug ) ;
2008-11-26 14:01:22 +01:00
2005-11-10 20:28:23 +00:00
netsamlogon_cache_init ( ) ; /* Non-critical */
2008-11-26 14:01:22 +01:00
2007-05-06 19:17:30 +00:00
/* clear the cached list of trusted domains */
wcache_tdc_clear ( ) ;
2008-11-26 14:01:22 +01:00
2006-03-16 15:21:41 +00:00
if ( ! init_domain_list ( ) ) {
2008-03-25 21:35:41 +01:00
DEBUG ( 0 , ( " unable to initialize domain list \n " ) ) ;
2006-03-16 11:32:01 +00:00
exit ( 1 ) ;
}
2004-01-08 08:19:18 +00:00
2005-06-08 22:10:34 +00:00
init_idmap_child ( ) ;
2007-08-29 12:43:23 +00:00
init_locator_child ( ) ;
2005-06-08 22:10:34 +00:00
2006-09-20 00:15:50 +00:00
smb_nscd_flush_user_cache ( ) ;
smb_nscd_flush_group_cache ( ) ;
2006-03-16 13:37:23 +00:00
2009-03-16 17:27:30 +01:00
/* setup listen sockets */
if ( ! winbindd_setup_listeners ( ) ) {
DEBUG ( 0 , ( " winbindd_setup_listeners() failed \n " ) ) ;
exit ( 1 ) ;
}
2007-10-10 15:34:30 -05:00
2009-05-25 22:34:48 +02:00
te = tevent_add_timer ( winbind_event_context ( ) , NULL , timeval_zero ( ) ,
rescan_trusted_domains , NULL ) ;
if ( te = = NULL ) {
DEBUG ( 0 , ( " Could not trigger rescan_trusted_domains() \n " ) ) ;
exit ( 1 ) ;
}
2007-11-15 14:19:52 -08:00
TALLOC_FREE ( frame ) ;
2009-03-16 17:27:30 +01:00
/* Loop waiting for requests */
2007-10-10 15:34:30 -05:00
while ( 1 ) {
2007-11-15 14:19:52 -08:00
frame = talloc_stackframe ( ) ;
2009-03-16 16:14:20 +01:00
2009-05-25 22:40:09 +02:00
if ( tevent_loop_once ( winbind_event_context ( ) ) = = - 1 ) {
DEBUG ( 1 , ( " tevent_loop_once() failed: %s \n " ,
strerror ( errno ) ) ) ;
return 1 ;
}
2009-03-16 16:14:20 +01:00
2007-10-10 15:34:30 -05:00
TALLOC_FREE ( frame ) ;
}
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
return 0 ;
2000-05-09 11:43:00 +00:00
}