2012-09-27 03:53:48 +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
2008-11-26 16:01:22 +03:00
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2000-05-09 15:43:00 +04:00
( at your option ) any later version .
2008-11-26 16:01:22 +03:00
2000-05-09 15:43:00 +04: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 16:01:22 +03:00
2000-05-09 15:43:00 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2000-05-09 15:43:00 +04:00
*/
2003-11-12 04:51:10 +03:00
# include "includes.h"
2010-08-05 12:49:53 +04:00
# include "popt_common.h"
2000-05-09 15:43:00 +04:00
# include "winbindd.h"
2010-08-18 14:42:49 +04:00
# include "nsswitch/winbind_client.h"
2011-02-17 02:43:05 +03:00
# include "nsswitch/wb_reqtrans.h"
2011-05-02 15:21:53 +04:00
# include "ntdomain.h"
2010-07-02 12:17:44 +04:00
# include "../librpc/gen_ndr/srv_lsa.h"
# include "../librpc/gen_ndr/srv_samr.h"
2010-08-05 04:25:37 +04:00
# include "secrets.h"
2013-12-17 23:06:14 +04:00
# include "rpc_client/cli_netlogon.h"
2010-08-18 20:13:42 +04:00
# include "idmap.h"
2011-01-31 19:25:55 +03:00
# include "lib/addrchange.h"
2011-03-25 04:28:05 +03:00
# include "auth.h"
2011-03-24 17:31:06 +03:00
# include "messages.h"
2012-07-20 03:36:18 +04:00
# include "../lib/util/pidfile.h"
2013-10-17 17:16:19 +04:00
# include "util_cluster.h"
2014-05-06 05:39:12 +04:00
# include "source4/lib/messaging/irpc.h"
# include "source4/lib/messaging/messaging.h"
# include "lib/param/param.h"
2015-06-25 08:59:20 +03:00
# include "lib/async_req/async_sock.h"
2016-11-29 18:41:27 +03:00
# include "libsmb/samlogon_cache.h"
2017-07-25 02:12:45 +03:00
# include "libcli/auth/netlogon_creds_cli.h"
2018-03-20 03:14:38 +03:00
# include "passdb.h"
2018-06-19 12:13:19 +03:00
# include "lib/util/tevent_req_profile.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
2015-07-06 21:29:17 +03:00
# define SCRUB_CLIENTS_INTERVAL 5
2010-08-23 03:53:40 +04:00
static bool client_is_idle ( struct winbindd_cli_state * state ) ;
2009-05-25 22:28:38 +04:00
static void remove_client ( struct winbindd_cli_state * state ) ;
2015-06-22 06:38:04 +03:00
static void winbindd_setup_max_fds ( void ) ;
2009-05-25 22:28:38 +04:00
2009-03-12 12:12:58 +03:00
static bool opt_nocache = False ;
2007-10-19 04:40:25 +04:00
static bool interactive = False ;
2000-05-09 15:43:00 +04:00
2007-10-19 04:40:25 +04:00
extern bool override_logfile ;
2004-09-21 13:07:42 +04:00
2014-05-06 05:39:12 +04:00
struct imessaging_context * winbind_imessaging_context ( void )
{
static struct imessaging_context * msg = NULL ;
2015-10-12 18:21:55 +03:00
struct messaging_context * msg_ctx ;
struct server_id myself ;
2014-05-06 05:39:12 +04:00
struct loadparm_context * lp_ctx ;
if ( msg ! = NULL ) {
return msg ;
}
2018-08-21 21:09:16 +03:00
msg_ctx = global_messaging_context ( ) ;
2015-10-12 18:21:55 +03:00
if ( msg_ctx = = NULL ) {
2018-08-21 21:09:16 +03:00
smb_panic ( " global_messaging_context failed \n " ) ;
2015-10-12 18:21:55 +03:00
}
myself = messaging_server_id ( msg_ctx ) ;
2014-05-06 05:39:12 +04:00
lp_ctx = loadparm_init_s3 ( NULL , loadparm_s3_helpers ( ) ) ;
if ( lp_ctx = = NULL ) {
smb_panic ( " Could not load smb.conf to init winbindd's imessaging context. \n " ) ;
}
/*
* Note we MUST use the NULL context here , not the autofree context ,
* to avoid side effects in forked children exiting .
*/
2018-08-21 21:06:16 +03:00
msg = imessaging_init ( NULL , lp_ctx , myself , global_event_context ( ) ) ;
2014-05-06 05:39:12 +04:00
talloc_unlink ( NULL , lp_ctx ) ;
if ( msg = = NULL ) {
smb_panic ( " Could not init winbindd's messaging context. \n " ) ;
}
return msg ;
}
2000-05-09 15:43:00 +04:00
/* Reload configuration */
2008-11-03 23:36:34 +03:00
static bool reload_services_file ( const char * lfile )
2000-05-09 15:43:00 +04:00
{
2007-10-19 04:40:25 +04:00
bool ret ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
if ( lp_loaded ( ) ) {
2014-01-15 08:29:57 +04:00
char * fname = lp_next_configfile ( talloc_tos ( ) ) ;
2001-05-07 08:32:40 +04:00
2008-10-17 14:48:19 +04:00
if ( file_exist ( fname ) & & ! strcsequal ( fname , get_dyn_CONFIGFILE ( ) ) ) {
2007-12-10 22:30:37 +03:00
set_dyn_CONFIGFILE ( fname ) ;
2001-05-07 08:32:40 +04:00
}
2012-06-01 02:06:58 +04:00
TALLOC_FREE ( fname ) ;
2001-05-07 08:32:40 +04:00
}
2008-07-18 07:10:18 +04:00
/* if this is a child, restore the logfile to the special
name - < domain > , idmap , etc . */
2008-11-03 23:36:34 +03:00
if ( lfile & & * lfile ) {
lp_set_logfile ( lfile ) ;
2008-07-18 07:10:18 +04:00
}
2000-05-09 15:43:00 +04:00
reopen_logs ( ) ;
2011-07-28 13:04:53 +04:00
ret = lp_load_global ( get_dyn_CONFIGFILE ( ) ) ;
2000-05-09 15:43:00 +04:00
reopen_logs ( ) ;
load_interfaces ( ) ;
2015-06-22 06:38:04 +03:00
winbindd_setup_max_fds ( ) ;
2000-05-09 15:43:00 +04:00
return ( ret ) ;
}
2003-07-15 21:21:21 +04:00
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 */
2008-11-26 16:01:22 +03:00
2002-11-02 04:36:42 +03:00
DEBUG ( 0 , ( " \t %d clients currently active \n " , winbindd_num_clients ( ) ) ) ;
2008-11-26 16:01:22 +03: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 ) {
2010-08-23 03:53:40 +04:00
DEBUGADD ( 2 , ( " \t \t pid %lu, sock %d (%s) \n " ,
( unsigned long ) tmp - > pid , tmp - > sock ,
client_is_idle ( tmp ) ? " idle " : " active " ) ) ;
2001-05-07 08:32:40 +04:00
}
}
}
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 . */
2008-01-07 12:59:14 +03:00
if ( ! wcache_invalidate_cache ( ) ) {
2007-11-26 13:44:30 +03:00
DEBUG ( 0 , ( " invalidating the cache failed; revalidate the cache \n " ) ) ;
2008-04-10 13:53:53 +04:00
if ( ! winbindd_cache_validate_and_initialize ( ) ) {
2007-11-26 13:44:30 +03:00
exit ( 1 ) ;
}
}
2000-05-09 15:43:00 +04:00
}
2010-02-09 11:35:40 +03:00
static void flush_caches_noinit ( void )
{
/*
* 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 .
* NB
* Skip uninitialized domains when flush cache .
* If domain is not initialized , it means it is never
* used or never become online . look , wcache_invalidate_cache ( )
* - > get_cache ( ) - > init_dc_connection ( ) . It causes a lot of traffic
* for unused domains and large traffic for primay domain ' s DC if there
* are many domains . .
*/
if ( ! wcache_invalidate_cache_noinit ( ) ) {
DEBUG ( 0 , ( " invalidating the cache failed; revalidate the cache \n " ) ) ;
if ( ! winbindd_cache_validate_and_initialize ( ) ) {
exit ( 1 ) ;
}
}
}
2000-05-09 15:43:00 +04:00
/* Handle the signal by unlinking socket and exiting */
2008-05-31 04:52:54 +04:00
static void terminate ( bool is_parent )
2000-05-09 15:43:00 +04:00
{
2008-05-31 04:52:54 +04:00
if ( is_parent ) {
/* When parent goes away we should
* remove the socket file . Not so
* when children terminate .
*/
char * path = NULL ;
2007-10-11 00:34:30 +04:00
2008-05-31 04:52:54 +04:00
if ( asprintf ( & path , " %s/%s " ,
2013-10-11 04:34:13 +04:00
lp_winbindd_socket_directory ( ) , WINBINDD_SOCKET_NAME ) > 0 ) {
2008-05-31 04:52:54 +04:00
unlink ( path ) ;
SAFE_FREE ( path ) ;
}
2007-11-21 04:18:16 +03:00
}
2005-06-09 02:10:34 +04:00
2007-02-20 22:57:14 +03:00
idmap_close ( ) ;
2008-11-26 16:01:22 +03:00
2009-07-13 19:04:29 +04:00
gencache_stabilize ( ) ;
2017-07-25 02:12:45 +03:00
netlogon_creds_cli_close_global_db ( ) ;
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
2009-06-18 13:45:57 +04:00
if ( is_parent ) {
2014-02-03 06:57:21 +04:00
pidfile_unlink ( lp_pid_directory ( ) , " winbindd " ) ;
2009-06-18 13:45:57 +04:00
}
2001-05-07 08:32:40 +04:00
exit ( 0 ) ;
}
2000-05-09 15:43:00 +04:00
2009-01-22 16:54:21 +03:00
static void winbindd_sig_term_handler ( struct tevent_context * ev ,
struct tevent_signal * se ,
int signum ,
int count ,
void * siginfo ,
void * private_data )
{
2018-02-09 17:33:39 +03:00
bool * p = talloc_get_type_abort ( private_data , bool ) ;
bool is_parent = * p ;
TALLOC_FREE ( p ) ;
2009-01-22 16:54:21 +03:00
DEBUG ( 0 , ( " Got sig[%d] terminate (is_parent=%d) \n " ,
2018-02-09 17:33:39 +03:00
signum , is_parent ) ) ;
terminate ( is_parent ) ;
2009-01-22 16:54:21 +03:00
}
2001-11-15 00:49:30 +03:00
2012-03-02 11:22:10 +04:00
/*
handle stdin becoming readable when we are in - - foreground mode
*/
static void winbindd_stdin_handler ( struct tevent_context * ev ,
struct tevent_fd * fde ,
uint16_t flags ,
void * private_data )
{
char c ;
if ( read ( 0 , & c , 1 ) ! = 1 ) {
bool * is_parent = talloc_get_type_abort ( private_data , bool ) ;
2012-09-27 03:53:48 +04:00
2012-03-02 11:22:10 +04:00
/* we have reached EOF on stdin, which means the
parent has exited . Shutdown the server */
DEBUG ( 0 , ( " EOF on stdin (is_parent=%d) \n " ,
( int ) * is_parent ) ) ;
terminate ( * is_parent ) ;
}
}
2009-01-22 16:54:21 +03:00
bool winbindd_setup_sig_term_handler ( bool parent )
2001-11-15 00:49:30 +03:00
{
2009-01-22 16:54:21 +03:00
struct tevent_signal * se ;
bool * is_parent ;
2018-08-21 21:06:16 +03:00
is_parent = talloc ( global_event_context ( ) , bool ) ;
2009-01-22 16:54:21 +03:00
if ( ! is_parent ) {
return false ;
}
* is_parent = parent ;
2018-08-21 21:06:16 +03:00
se = tevent_add_signal ( global_event_context ( ) ,
2009-01-22 16:54:21 +03:00
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 ;
}
2018-08-21 21:06:16 +03:00
se = tevent_add_signal ( global_event_context ( ) ,
2009-01-22 16:54:21 +03:00
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 ;
}
2018-08-21 21:06:16 +03:00
se = tevent_add_signal ( global_event_context ( ) ,
2009-01-22 16:54:21 +03:00
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-15 00:49:30 +03:00
}
2012-03-02 11:22:10 +04:00
bool winbindd_setup_stdin_handler ( bool parent , bool foreground )
{
bool * is_parent ;
if ( foreground ) {
2013-06-11 00:33:40 +04:00
struct stat st ;
2018-08-21 21:06:16 +03:00
is_parent = talloc ( global_event_context ( ) , bool ) ;
2012-03-02 11:22:10 +04:00
if ( ! is_parent ) {
return false ;
}
2012-09-27 03:53:48 +04:00
2012-03-02 11:22:10 +04:00
* is_parent = parent ;
/* if we are running in the foreground then look for
EOF on stdin , and exit if it happens . This allows
us to die if the parent process dies
2013-06-11 00:33:40 +04:00
Only do this on a pipe or socket , no other device .
2012-03-02 11:22:10 +04:00
*/
2013-06-11 00:33:40 +04:00
if ( fstat ( 0 , & st ) ! = 0 ) {
return false ;
}
if ( S_ISFIFO ( st . st_mode ) | | S_ISSOCK ( st . st_mode ) ) {
2018-08-21 21:06:16 +03:00
tevent_add_fd ( global_event_context ( ) ,
2013-06-11 00:33:40 +04:00
is_parent ,
0 ,
TEVENT_FD_READ ,
winbindd_stdin_handler ,
is_parent ) ;
}
2012-03-02 11:22:10 +04:00
}
2012-09-27 03:53:48 +04:00
2012-03-02 11:22:10 +04:00
return true ;
}
2009-01-22 16:54:21 +03: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 " ) ) ;
2010-02-09 11:35:40 +03:00
flush_caches_noinit ( ) ;
2009-01-22 16:54:21 +03:00
reload_services_file ( file ) ;
}
2000-05-09 15:43:00 +04:00
2009-01-22 16:54:21 +03:00
bool winbindd_setup_sig_hup_handler ( const char * lfile )
2001-05-07 08:32:40 +04:00
{
2009-01-22 16:54:21 +03:00
struct tevent_signal * se ;
char * file = NULL ;
if ( lfile ) {
2018-08-21 21:06:16 +03:00
file = talloc_strdup ( global_event_context ( ) ,
2009-01-22 16:54:21 +03:00
lfile ) ;
if ( ! file ) {
return false ;
}
}
2018-08-21 21:06:16 +03:00
se = tevent_add_signal ( global_event_context ( ) ,
global_event_context ( ) ,
2009-01-22 16:54:21 +03:00
SIGHUP , 0 ,
winbindd_sig_hup_handler ,
file ) ;
if ( ! se ) {
return false ;
}
return true ;
2000-05-09 15:43:00 +04:00
}
2009-01-22 16:54:21 +03: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 ;
2016-02-16 17:46:06 +03:00
while ( ( pid = waitpid ( - 1 , NULL , WNOHANG ) ) > 0 ) {
2009-01-22 16:54:21 +03:00
winbind_child_died ( pid ) ;
}
}
2000-05-09 15:43:00 +04:00
2009-01-22 16:54:21 +03:00
static bool winbindd_setup_sig_chld_handler ( void )
2000-05-09 15:43:00 +04:00
{
2009-01-22 16:54:21 +03:00
struct tevent_signal * se ;
2018-08-21 21:06:16 +03:00
se = tevent_add_signal ( global_event_context ( ) ,
global_event_context ( ) ,
2009-01-22 16:54:21 +03:00
SIGCHLD , 0 ,
winbindd_sig_chld_handler ,
NULL ) ;
if ( ! se ) {
return false ;
}
return true ;
2000-05-09 15:43:00 +04:00
}
2009-01-22 16:54:21 +03:00
static void winbindd_sig_usr2_handler ( struct tevent_context * ev ,
struct tevent_signal * se ,
int signum ,
int count ,
void * siginfo ,
void * private_data )
{
2010-08-23 03:53:39 +04:00
winbindd_status ( ) ;
2009-01-22 16:54:21 +03:00
}
2005-06-09 02:10:34 +04:00
2009-01-22 16:54:21 +03:00
static bool winbindd_setup_sig_usr2_handler ( void )
2004-07-21 08:24:30 +04:00
{
2009-01-22 16:54:21 +03:00
struct tevent_signal * se ;
2018-08-21 21:06:16 +03:00
se = tevent_add_signal ( global_event_context ( ) ,
global_event_context ( ) ,
2009-03-05 04:26:57 +03:00
SIGUSR2 , 0 ,
2009-01-22 16:54:21 +03:00
winbindd_sig_usr2_handler ,
NULL ) ;
if ( ! se ) {
return false ;
}
return true ;
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*/
2007-05-16 18:45:09 +04: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 21:21:21 +04:00
{
/* Flush various caches */
flush_caches ( ) ;
2008-07-18 07:10:18 +04:00
reload_services_file ( ( const char * ) private_data ) ;
2003-07-15 21:21:21 +04:00
}
/* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
2007-05-16 18:45:09 +04: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 21:21:21 +04:00
{
2009-01-22 16:54:21 +03:00
/* only the parent waits for this message */
DEBUG ( 0 , ( " Got shutdown message \n " ) ) ;
terminate ( true ) ;
2003-07-15 21:21:21 +04:00
}
2007-08-31 19:24:43 +04: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 )
{
2015-05-03 07:07:06 +03:00
uint8_t ret ;
2007-09-02 04:32:57 +04:00
pid_t child_pid ;
2011-04-29 14:53:13 +04:00
NTSTATUS status ;
2007-08-31 19:24:43 +04:00
DEBUG ( 10 , ( " winbindd_msg_validate_cache: got validate-cache "
" message. \n " ) ) ;
2007-09-02 04:32:57 +04: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 . . .
*/
2012-03-24 23:17:08 +04:00
child_pid = fork ( ) ;
2007-09-02 04:32:57 +04:00
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-24 03:22:43 +03:00
" pid %d. \n " , ( int ) child_pid ) ) ;
2007-09-02 04:32:57 +04:00
return ;
}
/* child */
2011-04-29 14:53:13 +04:00
status = winbindd_reinit_after_fork ( NULL , NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " winbindd_reinit_after_fork failed: %s \n " ,
nt_errstr ( status ) ) ) ;
2010-04-01 18:23:06 +04:00
_exit ( 0 ) ;
}
2007-09-02 04:32:57 +04:00
2010-04-08 14:45:54 +04:00
/* install default SIGCHLD handler: validation code uses fork/waitpid */
CatchSignal ( SIGCHLD , SIG_DFL ) ;
2017-12-20 19:42:45 +03:00
setproctitle ( " validate cache child " ) ;
2015-05-03 07:07:06 +03:00
ret = ( uint8_t ) winbindd_validate_cache_nobackup ( ) ;
2007-08-31 19:24:43 +04:00
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 04:32:57 +04:00
_exit ( 0 ) ;
2007-08-31 19:24:43 +04:00
}
2018-05-02 16:26:05 +03:00
static struct winbindd_bool_dispatch_table {
enum winbindd_cmd cmd ;
bool ( * fn ) ( struct winbindd_cli_state * state ) ;
const char * cmd_name ;
} bool_dispatch_table [ ] = {
2018-05-02 16:26:55 +03:00
{ WINBINDD_INTERFACE_VERSION ,
winbindd_interface_version ,
" INTERFACE_VERSION " } ,
2018-05-02 17:36:49 +03:00
{ WINBINDD_INFO ,
winbindd_info ,
" INFO " } ,
2018-05-02 17:38:14 +03:00
{ WINBINDD_PING ,
winbindd_ping ,
" PING " } ,
2018-05-02 17:39:20 +03:00
{ WINBINDD_DOMAIN_NAME ,
winbindd_domain_name ,
" DOMAIN_NAME " } ,
2018-05-02 19:25:00 +03:00
{ WINBINDD_NETBIOS_NAME ,
winbindd_netbios_name ,
" NETBIOS_NAME " } ,
2018-05-02 19:27:23 +03:00
{ WINBINDD_DC_INFO ,
winbindd_dc_info ,
" DC_INFO " } ,
2018-05-02 21:23:54 +03:00
{ WINBINDD_CCACHE_NTLMAUTH ,
winbindd_ccache_ntlm_auth ,
" NTLMAUTH " } ,
2018-05-02 21:26:19 +03:00
{ WINBINDD_CCACHE_SAVE ,
winbindd_ccache_save ,
" CCACHE_SAVE " } ,
2018-05-02 21:27:43 +03:00
{ WINBINDD_PRIV_PIPE_DIR ,
winbindd_priv_pipe_dir ,
" WINBINDD_PRIV_PIPE_DIR " } ,
2018-05-04 22:19:06 +03:00
{ WINBINDD_LIST_TRUSTDOM ,
winbindd_list_trusted_domains ,
" LIST_TRUSTDOM " } ,
2018-05-02 16:26:05 +03:00
} ;
2009-05-16 14:00:07 +04: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 14:46:55 +04:00
struct winbindd_cli_state * cli ,
2009-05-16 14:00:07 +04:00
struct winbindd_request * request ) ;
2009-07-31 18:16:24 +04:00
NTSTATUS ( * recv_req ) ( struct tevent_req * req ,
struct winbindd_response * presp ) ;
2009-05-16 14:00:07 +04:00
} ;
static struct winbindd_async_dispatch_table async_nonpriv_table [ ] = {
2009-08-04 14:57:13 +04:00
{ WINBINDD_LOOKUPSID , " LOOKUPSID " ,
winbindd_lookupsid_send , winbindd_lookupsid_recv } ,
2011-03-08 16:31:44 +03:00
{ WINBINDD_LOOKUPSIDS , " LOOKUPSIDS " ,
winbindd_lookupsids_send , winbindd_lookupsids_recv } ,
2009-08-04 15:29:03 +04:00
{ WINBINDD_LOOKUPNAME , " LOOKUPNAME " ,
winbindd_lookupname_send , winbindd_lookupname_recv } ,
2011-03-23 20:29:45 +03:00
{ WINBINDD_SIDS_TO_XIDS , " SIDS_TO_XIDS " ,
winbindd_sids_to_xids_send , winbindd_sids_to_xids_recv } ,
2015-08-14 18:15:33 +03:00
{ WINBINDD_XIDS_TO_SIDS , " XIDS_TO_SIDS " ,
winbindd_xids_to_sids_send , winbindd_xids_to_sids_recv } ,
2009-08-04 23:35:24 +04:00
{ WINBINDD_GETPWSID , " GETPWSID " ,
winbindd_getpwsid_send , winbindd_getpwsid_recv } ,
2009-08-04 23:37:54 +04:00
{ WINBINDD_GETPWNAM , " GETPWNAM " ,
winbindd_getpwnam_send , winbindd_getpwnam_recv } ,
2009-08-04 23:41:40 +04:00
{ WINBINDD_GETPWUID , " GETPWUID " ,
winbindd_getpwuid_send , winbindd_getpwuid_recv } ,
2009-08-04 23:58:45 +04:00
{ WINBINDD_GETSIDALIASES , " GETSIDALIASES " ,
winbindd_getsidaliases_send , winbindd_getsidaliases_recv } ,
2009-08-05 00:20:18 +04:00
{ WINBINDD_GETUSERDOMGROUPS , " GETUSERDOMGROUPS " ,
winbindd_getuserdomgroups_send , winbindd_getuserdomgroups_recv } ,
2009-08-05 00:26:07 +04:00
{ WINBINDD_GETGROUPS , " GETGROUPS " ,
winbindd_getgroups_send , winbindd_getgroups_recv } ,
2009-08-15 15:23:57 +04:00
{ WINBINDD_SHOW_SEQUENCE , " SHOW_SEQUENCE " ,
winbindd_show_sequence_send , winbindd_show_sequence_recv } ,
2009-08-16 14:13:00 +04:00
{ WINBINDD_GETGRGID , " GETGRGID " ,
winbindd_getgrgid_send , winbindd_getgrgid_recv } ,
2009-08-16 14:23:31 +04:00
{ WINBINDD_GETGRNAM , " GETGRNAM " ,
winbindd_getgrnam_send , winbindd_getgrnam_recv } ,
2009-08-27 16:55:41 +04:00
{ WINBINDD_GETUSERSIDS , " GETUSERSIDS " ,
winbindd_getusersids_send , winbindd_getusersids_recv } ,
2009-08-27 19:11:24 +04:00
{ WINBINDD_LOOKUPRIDS , " LOOKUPRIDS " ,
winbindd_lookuprids_send , winbindd_lookuprids_recv } ,
2009-08-18 01:13:48 +04: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-26 01:02:44 +04:00
{ WINBINDD_DSGETDCNAME , " DSGETDCNAME " ,
winbindd_dsgetdcname_send , winbindd_dsgetdcname_recv } ,
2009-08-26 14:27:32 +04:00
{ WINBINDD_GETDCNAME , " GETDCNAME " ,
winbindd_getdcname_send , winbindd_getdcname_recv } ,
2009-08-28 01:33:45 +04: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 18:05:02 +04:00
{ WINBINDD_LIST_USERS , " LIST_USERS " ,
winbindd_list_users_send , winbindd_list_users_recv } ,
2009-08-29 19:17:47 +04:00
{ WINBINDD_LIST_GROUPS , " LIST_GROUPS " ,
winbindd_list_groups_send , winbindd_list_groups_recv } ,
2009-09-06 11:32:34 +04:00
{ WINBINDD_CHECK_MACHACC , " CHECK_MACHACC " ,
winbindd_check_machine_acct_send , winbindd_check_machine_acct_recv } ,
2009-12-21 23:50:43 +03:00
{ WINBINDD_PING_DC , " PING_DC " ,
winbindd_ping_dc_send , winbindd_ping_dc_recv } ,
2010-03-29 19:52:38 +04:00
{ WINBINDD_PAM_AUTH , " PAM_AUTH " ,
winbindd_pam_auth_send , winbindd_pam_auth_recv } ,
2010-04-01 18:44:16 +04:00
{ WINBINDD_PAM_LOGOFF , " PAM_LOGOFF " ,
winbindd_pam_logoff_send , winbindd_pam_logoff_recv } ,
2010-04-01 14:35:14 +04:00
{ WINBINDD_PAM_CHAUTHTOK , " PAM_CHAUTHTOK " ,
winbindd_pam_chauthtok_send , winbindd_pam_chauthtok_recv } ,
2010-04-20 13:11:19 +04:00
{ WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP , " PAM_CHNG_PSWD_AUTH_CRAP " ,
winbindd_pam_chng_pswd_auth_crap_send ,
winbindd_pam_chng_pswd_auth_crap_recv } ,
2011-06-21 00:18:48 +04:00
{ WINBINDD_WINS_BYIP , " WINS_BYIP " ,
2011-06-05 13:30:43 +04:00
winbindd_wins_byip_send , winbindd_wins_byip_recv } ,
2011-06-15 01:51:10 +04:00
{ WINBINDD_WINS_BYNAME , " WINS_BYNAME " ,
winbindd_wins_byname_send , winbindd_wins_byname_recv } ,
2018-05-02 21:47:49 +03:00
{ WINBINDD_DOMAIN_INFO , " DOMAIN_INFO " ,
winbindd_domain_info_send , winbindd_domain_info_recv } ,
2009-05-16 14:00:34 +04:00
2009-05-16 14:00:07 +04:00
{ 0 , NULL , NULL , NULL }
} ;
2009-08-30 11:41:43 +04: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 11:46:34 +04:00
{ WINBINDD_ALLOCATE_GID , " ALLOCATE_GID " ,
winbindd_allocate_gid_send , winbindd_allocate_gid_recv } ,
2009-10-06 20:26:33 +04:00
{ WINBINDD_CHANGE_MACHACC , " CHANGE_MACHACC " ,
winbindd_change_machine_acct_send , winbindd_change_machine_acct_recv } ,
2010-03-31 01:02:36 +04:00
{ WINBINDD_PAM_AUTH_CRAP , " PAM_AUTH_CRAP " ,
winbindd_pam_auth_crap_send , winbindd_pam_auth_crap_recv } ,
2009-08-30 11:41:43 +04:00
{ 0 , NULL , NULL , NULL }
} ;
2018-05-03 16:12:55 +03:00
struct process_request_state {
struct winbindd_cli_state * cli_state ;
struct tevent_context * ev ;
} ;
static void process_request_done ( struct tevent_req * subreq ) ;
static void process_request_written ( struct tevent_req * subreq ) ;
2009-05-16 14:00:07 +04:00
2018-05-03 16:12:55 +03:00
static struct tevent_req * process_request_send (
TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct winbindd_cli_state * cli_state )
2000-05-09 15:43:00 +04:00
{
2018-05-03 16:12:55 +03:00
struct tevent_req * req , * subreq ;
struct process_request_state * state ;
2009-05-16 14:00:07 +04:00
struct winbindd_async_dispatch_table * atable ;
2018-05-03 16:12:55 +03:00
enum winbindd_cmd cmd = cli_state - > request - > cmd ;
2018-05-02 16:26:05 +03:00
size_t i ;
bool ok ;
2000-05-09 15:43:00 +04:00
2018-05-03 16:12:55 +03:00
req = tevent_req_create ( mem_ctx , & state ,
struct process_request_state ) ;
if ( req = = NULL ) {
return NULL ;
}
state - > cli_state = cli_state ;
state - > ev = ev ;
2018-06-19 12:13:19 +03:00
ok = tevent_req_set_profile ( req ) ;
if ( ! ok ) {
return tevent_req_post ( req , ev ) ;
}
2018-05-03 16:12:55 +03:00
SMB_ASSERT ( cli_state - > mem_ctx = = NULL ) ;
cli_state - > mem_ctx = talloc_named ( cli_state , 0 , " winbind request " ) ;
if ( tevent_req_nomem ( cli_state - > mem_ctx , req ) ) {
return tevent_req_post ( req , ev ) ;
}
cli_state - > response = talloc_zero (
cli_state - > mem_ctx ,
struct winbindd_response ) ;
if ( tevent_req_nomem ( cli_state - > response , req ) ) {
return tevent_req_post ( req , ev ) ;
}
cli_state - > response - > result = WINBINDD_PENDING ;
cli_state - > response - > length = sizeof ( struct winbindd_response ) ;
2005-06-09 02:10:34 +04:00
2007-06-05 03:51:19 +04:00
/* Remember who asked us. */
2018-05-03 16:12:55 +03:00
cli_state - > pid = cli_state - > request - > pid ;
2007-06-05 03:51:19 +04:00
2018-05-03 16:12:55 +03:00
cli_state - > cmd_name = " unknown request " ;
cli_state - > recv_fn = NULL ;
2010-03-05 13:16:12 +03:00
2018-05-03 16:12:55 +03:00
/* client is newest */
winbindd_promote_client ( cli_state ) ;
2000-05-09 15:43:00 +04:00
2009-05-16 14:00:07 +04:00
for ( atable = async_nonpriv_table ; atable - > send_req ; atable + = 1 ) {
2018-05-03 16:12:55 +03:00
if ( cmd = = atable - > cmd ) {
2009-05-16 14:00:07 +04:00
break ;
}
}
2018-05-03 16:12:55 +03:00
if ( ( atable - > send_req = = NULL ) & & cli_state - > privileged ) {
2009-08-30 11:41:43 +04:00
for ( atable = async_priv_table ; atable - > send_req ;
atable + = 1 ) {
2018-05-03 16:12:55 +03:00
if ( cmd = = atable - > cmd ) {
2009-08-30 11:41:43 +04:00
break ;
}
}
}
2009-05-16 14:00:07 +04:00
if ( atable - > send_req ! = NULL ) {
2018-05-03 16:12:55 +03:00
cli_state - > cmd_name = atable - > cmd_name ;
cli_state - > recv_fn = atable - > recv_req ;
2010-03-05 13:16:12 +03:00
DEBUG ( 10 , ( " process_request: Handling async request %d:%s \n " ,
2018-05-03 16:12:55 +03:00
( int ) cli_state - > pid , cli_state - > cmd_name ) ) ;
subreq = atable - > send_req (
state ,
state - > ev ,
cli_state ,
cli_state - > request ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
2009-05-16 14:00:07 +04:00
}
2018-05-03 16:12:55 +03:00
tevent_req_set_callback ( subreq , process_request_done , req ) ;
return req ;
2009-06-14 14:58:19 +04:00
}
2018-05-02 16:26:05 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( bool_dispatch_table ) ; i + + ) {
2018-05-03 16:12:55 +03:00
if ( cmd = = bool_dispatch_table [ i ] . cmd ) {
2001-05-07 08:32:40 +04:00
break ;
}
}
2000-05-09 15:43:00 +04:00
2018-05-03 16:12:55 +03:00
ok = false ;
2018-05-02 16:26:05 +03:00
2018-05-03 16:12:55 +03:00
if ( i < ARRAY_SIZE ( bool_dispatch_table ) ) {
DBG_DEBUG ( " process_request: request fn %s \n " ,
bool_dispatch_table [ i ] . cmd_name ) ;
ok = bool_dispatch_table [ i ] . fn ( cli_state ) ;
2005-06-09 02:10:34 +04:00
}
2018-05-03 16:12:55 +03:00
cli_state - > response - > result = ok ? WINBINDD_OK : WINBINDD_ERROR ;
2009-05-16 14:00:07 +04:00
2018-05-03 16:12:55 +03:00
TALLOC_FREE ( cli_state - > io_req ) ;
TALLOC_FREE ( cli_state - > request ) ;
2009-07-31 18:16:24 +04:00
2018-05-03 16:12:55 +03:00
subreq = wb_resp_write_send (
state ,
state - > ev ,
cli_state - > out_queue ,
cli_state - > sock ,
cli_state - > response ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , process_request_written , req ) ;
2010-03-05 13:16:12 +03:00
2018-05-03 16:12:55 +03:00
cli_state - > io_req = subreq ;
2010-03-05 13:16:12 +03:00
2018-05-03 16:12:55 +03:00
return req ;
2009-05-16 14:00:07 +04:00
}
2018-05-03 16:12:55 +03:00
static void process_request_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct process_request_state * state = tevent_req_data (
req , struct process_request_state ) ;
struct winbindd_cli_state * cli_state = state - > cli_state ;
NTSTATUS status ;
bool ok ;
2005-06-09 02:10:34 +04:00
2018-05-03 16:12:55 +03:00
status = cli_state - > recv_fn ( subreq , cli_state - > response ) ;
TALLOC_FREE ( subreq ) ;
2005-06-09 02:10:34 +04:00
2018-05-03 16:12:55 +03:00
DBG_DEBUG ( " [%d:%s]: %s \n " ,
( int ) cli_state - > pid ,
cli_state - > cmd_name ,
nt_errstr ( status ) ) ;
2005-06-09 02:10:34 +04:00
2018-05-03 16:12:55 +03:00
ok = NT_STATUS_IS_OK ( status ) ;
cli_state - > response - > result = ok ? WINBINDD_OK : WINBINDD_ERROR ;
2015-06-25 08:59:20 +03:00
2018-05-03 16:12:55 +03:00
TALLOC_FREE ( cli_state - > io_req ) ;
TALLOC_FREE ( cli_state - > request ) ;
2005-06-09 02:10:34 +04:00
2018-05-03 16:12:55 +03:00
subreq = wb_resp_write_send (
state ,
state - > ev ,
cli_state - > out_queue ,
cli_state - > sock ,
cli_state - > response ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
2005-06-09 02:10:34 +04:00
return ;
}
2018-05-03 16:12:55 +03:00
tevent_req_set_callback ( subreq , process_request_written , req ) ;
cli_state - > io_req = subreq ;
2005-06-09 02:10:34 +04:00
}
2018-05-03 16:12:55 +03:00
static void process_request_written ( struct tevent_req * subreq )
2005-06-09 02:10:34 +04:00
{
2018-05-03 16:12:55 +03:00
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct process_request_state * state = tevent_req_data (
req , struct process_request_state ) ;
struct winbindd_cli_state * cli_state = state - > cli_state ;
2009-05-09 22:04:27 +04:00
ssize_t ret ;
int err ;
2005-06-09 02:10:34 +04:00
2018-05-03 16:12:55 +03:00
cli_state - > io_req = NULL ;
2015-05-18 14:17:40 +03:00
2018-05-03 16:12:55 +03:00
ret = wb_resp_write_recv ( subreq , & err ) ;
TALLOC_FREE ( subreq ) ;
2009-05-09 22:04:27 +04:00
if ( ret = = - 1 ) {
2018-05-03 16:12:55 +03:00
tevent_req_nterror ( req , map_nt_error_from_unix ( err ) ) ;
2005-06-09 02:10:34 +04:00
return ;
}
2018-05-03 16:12:55 +03:00
DBG_DEBUG ( " [%d:%s]: delivered response to client \n " ,
( int ) cli_state - > pid , cli_state - > cmd_name ) ;
2010-03-05 13:16:12 +03:00
2018-05-03 16:12:55 +03:00
TALLOC_FREE ( cli_state - > mem_ctx ) ;
cli_state - > response = NULL ;
cli_state - > cmd_name = " no request " ;
cli_state - > recv_fn = NULL ;
2005-06-09 02:10:34 +04:00
2018-05-03 16:12:55 +03:00
tevent_req_done ( req ) ;
2005-06-09 02:10:34 +04:00
}
2018-06-19 12:13:19 +03:00
static NTSTATUS process_request_recv (
struct tevent_req * req ,
TALLOC_CTX * mem_ctx ,
struct tevent_req_profile * * profile )
2005-06-20 17:42:29 +04:00
{
2018-05-03 16:12:55 +03:00
NTSTATUS status ;
2005-06-20 17:42:29 +04:00
2018-05-03 16:12:55 +03:00
if ( tevent_req_is_nterror ( req , & status ) ) {
tevent_req_received ( req ) ;
return status ;
}
2018-06-19 12:13:19 +03:00
* profile = tevent_req_move_profile ( req , mem_ctx ) ;
2018-05-03 16:12:55 +03:00
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
2005-06-20 17:42:29 +04:00
}
2018-05-03 16:12:55 +03: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 .
*/
static void winbind_client_request_read ( struct tevent_req * req ) ;
static void winbind_client_activity ( struct tevent_req * req ) ;
static void winbind_client_processed ( struct tevent_req * req ) ;
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
2010-05-14 07:11:48 +04:00
static void new_connection ( int listen_sock , bool privileged )
2000-05-09 15:43:00 +04:00
{
2010-05-14 07:11:48 +04:00
struct sockaddr_un sunaddr ;
2001-05-07 08:32:40 +04:00
struct winbindd_cli_state * state ;
2009-05-09 22:04:27 +04:00
struct tevent_req * req ;
2010-05-14 07:11:48 +04:00
socklen_t len ;
int sock ;
/* Accept connection */
len = sizeof ( sunaddr ) ;
2011-03-03 17:31:04 +03:00
sock = accept ( listen_sock , ( struct sockaddr * ) ( void * ) & sunaddr , & len ) ;
2010-05-14 07:11:48 +04:00
2011-03-03 17:31:04 +03:00
if ( sock = = - 1 ) {
if ( errno ! = EINTR ) {
2012-12-12 15:55:45 +04:00
DEBUG ( 0 , ( " Failed to accept socket - %s \n " ,
2011-03-03 17:31:04 +03:00
strerror ( errno ) ) ) ;
}
2010-05-14 07:11:48 +04:00
return ;
2011-03-03 17:31:04 +03:00
}
2017-12-10 23:58:59 +03:00
smb_set_close_on_exec ( sock ) ;
2010-05-14 07:11:48 +04:00
DEBUG ( 6 , ( " accepted socket %d \n " , sock ) ) ;
2008-11-26 16:01:22 +03:00
2001-05-07 08:32:40 +04:00
/* Create new connection structure */
2008-11-26 16:01:22 +03:00
2011-06-07 05:44:43 +04:00
if ( ( state = talloc_zero ( NULL , struct winbindd_cli_state ) ) = = NULL ) {
2010-05-14 07:11:48 +04:00
close ( sock ) ;
2001-05-07 08:32:40 +04:00
return ;
2007-02-08 03:28:25 +03:00
}
2008-11-26 16:01:22 +03:00
2010-05-14 07:11:48 +04:00
state - > sock = sock ;
2003-02-28 03:25:55 +03:00
2009-05-09 22:04:27 +04:00
state - > out_queue = tevent_queue_create ( state , " winbind client reply " ) ;
if ( state - > out_queue = = NULL ) {
2010-05-14 07:11:48 +04:00
close ( sock ) ;
2009-05-09 22:04:27 +04:00
TALLOC_FREE ( state ) ;
return ;
}
2003-04-07 11:32:51 +04:00
state - > privileged = privileged ;
2003-03-24 12:54:13 +03:00
2018-08-21 21:06:16 +03:00
req = wb_req_read_send ( state , global_event_context ( ) , state - > sock ,
2009-05-09 22:04:27 +04:00
WINBINDD_MAX_EXTRA_DATA ) ;
if ( req = = NULL ) {
TALLOC_FREE ( state ) ;
2010-05-14 07:11:48 +04:00
close ( sock ) ;
2009-05-09 22:04:27 +04:00
return ;
}
tevent_req_set_callback ( req , winbind_client_request_read , state ) ;
2015-05-18 14:17:40 +03:00
state - > io_req = req ;
2005-06-09 02:10:34 +04:00
2001-05-07 08:32:40 +04:00
/* Add to connection list */
2008-11-26 16:01:22 +03:00
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
2009-05-09 22:04:27 +04: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 ;
2015-05-18 14:17:40 +03:00
state - > io_req = NULL ;
2009-05-09 22:04:27 +04:00
ret = wb_req_read_recv ( req , state , & state - > request , & err ) ;
2009-07-25 03:03:45 +04:00
TALLOC_FREE ( req ) ;
2009-05-09 22:04:27 +04:00
if ( ret = = - 1 ) {
2009-12-26 20:00:32 +03:00
if ( err = = EPIPE ) {
DEBUG ( 6 , ( " closing socket %d, client exited \n " ,
state - > sock ) ) ;
} else {
DEBUG ( 2 , ( " Could not read client request from fd %d: "
" %s \n " , state - > sock , strerror ( err ) ) ) ;
}
2009-09-21 04:42:35 +04:00
close ( state - > sock ) ;
state - > sock = - 1 ;
2009-05-25 22:28:38 +04:00
remove_client ( state ) ;
2009-05-09 22:04:27 +04:00
return ;
}
2015-06-25 08:59:20 +03:00
2018-08-21 21:06:16 +03:00
req = wait_for_read_send ( state , global_event_context ( ) , state - > sock ,
2015-06-25 10:12:37 +03:00
true ) ;
2015-06-25 08:59:20 +03:00
if ( req = = NULL ) {
DEBUG ( 0 , ( " winbind_client_request_read[%d:%s]: "
" wait_for_read_send failed - removing client \n " ,
( int ) state - > pid , state - > cmd_name ) ) ;
remove_client ( state ) ;
return ;
}
tevent_req_set_callback ( req , winbind_client_activity , state ) ;
state - > io_req = req ;
2018-08-21 21:06:16 +03:00
req = process_request_send ( state , global_event_context ( ) , state ) ;
2018-05-03 16:12:55 +03:00
if ( req = = NULL ) {
DBG_ERR ( " process_request_send failed \n " ) ;
remove_client ( state ) ;
return ;
}
tevent_req_set_callback ( req , winbind_client_processed , state ) ;
2009-05-09 22:04:27 +04:00
}
2015-06-25 08:59:20 +03:00
static void winbind_client_activity ( struct tevent_req * req )
{
struct winbindd_cli_state * state =
tevent_req_callback_data ( req , struct winbindd_cli_state ) ;
int err ;
2015-06-25 10:12:37 +03:00
bool has_data ;
2015-06-25 08:59:20 +03:00
2015-06-25 10:12:37 +03:00
has_data = wait_for_read_recv ( req , & err ) ;
if ( has_data ) {
DEBUG ( 0 , ( " winbind_client_activity[%d:%s]: "
" unexpected data from client - removing client \n " ,
( int ) state - > pid , state - > cmd_name ) ) ;
} else {
if ( err = = EPIPE ) {
DEBUG ( 6 , ( " winbind_client_activity[%d:%s]: "
" client has closed connection - removing "
" client \n " ,
( int ) state - > pid , state - > cmd_name ) ) ;
} else {
DEBUG ( 2 , ( " winbind_client_activity[%d:%s]: "
" client socket error (%s) - removing "
" client \n " ,
( int ) state - > pid , state - > cmd_name ,
strerror ( err ) ) ) ;
}
}
2015-06-25 08:59:20 +03:00
remove_client ( state ) ;
}
2018-05-03 16:12:55 +03:00
static void winbind_client_processed ( struct tevent_req * req )
{
struct winbindd_cli_state * cli_state = tevent_req_callback_data (
req , struct winbindd_cli_state ) ;
2018-06-19 12:13:19 +03:00
struct tevent_req_profile * profile = NULL ;
struct timeval start , stop , diff ;
int threshold ;
2018-05-03 16:12:55 +03:00
NTSTATUS status ;
2018-06-19 12:13:19 +03:00
status = process_request_recv ( req , cli_state , & profile ) ;
2018-05-03 16:12:55 +03:00
TALLOC_FREE ( req ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_DEBUG ( " process_request failed: %s \n " , nt_errstr ( status ) ) ;
remove_client ( cli_state ) ;
return ;
}
2018-06-19 12:13:19 +03:00
tevent_req_profile_get_start ( profile , NULL , & start ) ;
tevent_req_profile_get_stop ( profile , NULL , & stop ) ;
diff = tevent_timeval_until ( & start , & stop ) ;
threshold = lp_parm_int ( - 1 , " winbind " , " request profile threshold " , 60 ) ;
if ( diff . tv_sec > = threshold ) {
int depth ;
char * str ;
depth = lp_parm_int (
- 1 ,
" winbind " ,
" request profile depth " ,
INT_MAX ) ;
DBG_ERR ( " request took %u.%.6u seconds \n " ,
( unsigned ) diff . tv_sec , ( unsigned ) diff . tv_usec ) ;
str = tevent_req_profile_string ( profile , talloc_tos ( ) , 0 , depth ) ;
if ( str ! = NULL ) {
/* No "\n", already contained in "str" */
DEBUGADD ( 0 , ( " %s " , str ) ) ;
}
TALLOC_FREE ( str ) ;
}
TALLOC_FREE ( profile ) ;
2018-05-03 16:12:55 +03:00
req = wb_req_read_send (
cli_state ,
2018-08-21 21:06:16 +03:00
global_event_context ( ) ,
2018-05-03 16:12:55 +03:00
cli_state - > sock ,
WINBINDD_MAX_EXTRA_DATA ) ;
if ( req = = NULL ) {
remove_client ( cli_state ) ;
return ;
}
tevent_req_set_callback ( req , winbind_client_request_read , cli_state ) ;
cli_state - > io_req = req ;
}
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 */
2008-11-26 16:01:22 +03:00
2006-10-04 20:18:36 +04:00
if ( state = = NULL ) {
return ;
}
2008-10-27 16:28:44 +03:00
2015-05-18 14:17:40 +03:00
/*
* We need to remove a pending wb_req_read_ *
* or wb_resp_write_ * request before closing the
* socket .
*
* This is important as they might have used tevent_add_fd ( ) and we
* use the epoll * backend on linux . So we must remove the tevent_fd
* before closing the fd .
*
* Otherwise we might hit a race with close_conns_after_fork ( ) ( via
2018-05-03 12:47:44 +03:00
* winbindd_reinit_after_fork ( ) ) where a file descriptor
2015-05-18 14:17:40 +03:00
* is still open in a child , which means it ' s still active in
* the parents epoll queue , but the related tevent_fd is already
* already gone in the parent .
*
* See bug # 11141.
*/
TALLOC_FREE ( state - > io_req ) ;
2009-09-21 04:42:35 +04:00
if ( state - > sock ! = - 1 ) {
2018-05-03 12:48:45 +03:00
char c = 0 ;
int nwritten ;
2009-09-21 04:42:35 +04:00
/* tell client, we are closing ... */
nwritten = write ( state - > sock , & c , sizeof ( c ) ) ;
if ( nwritten = = - 1 ) {
2009-05-21 23:22:52 +04:00
DEBUG ( 2 , ( " final write to client failed: %s \n " ,
2009-09-21 04:42:35 +04:00
strerror ( errno ) ) ) ;
2009-05-21 23:22:52 +04:00
}
2008-10-27 16:28:44 +03:00
2009-09-21 04:42:35 +04:00
/* Close socket */
2008-11-26 16:01:22 +03:00
2009-09-21 04:42:35 +04:00
close ( state - > sock ) ;
state - > sock = - 1 ;
}
2008-11-26 16:01:22 +03:00
2008-07-24 16:46:43 +04:00
TALLOC_FREE ( state - > mem_ctx ) ;
2005-06-09 02:10:34 +04:00
2006-10-04 20:18:36 +04:00
/* Remove from list and free */
2008-11-26 16:01:22 +03: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
2010-08-23 03:53:40 +04:00
/* Is a client idle? */
static bool client_is_idle ( struct winbindd_cli_state * state ) {
2012-08-21 01:51:28 +04:00
return ( state - > request = = NULL & &
state - > response = = NULL & &
2010-08-23 03:53:40 +04:00
! state - > pwent_state & & ! state - > grent_state ) ;
}
2003-02-28 03:25:55 +03:00
/* Shutdown client connection which has been idle for the longest time */
2007-10-19 04:40:25 +04:00
static bool remove_idle_client ( void )
2003-02-28 03:25:55 +03:00
{
struct winbindd_cli_state * state , * remove_state = NULL ;
int nidle = 0 ;
for ( state = winbindd_client_list ( ) ; state ; state = state - > next ) {
2010-08-23 03:53:40 +04:00
if ( client_is_idle ( state ) ) {
2003-02-28 03:25:55 +03:00
nidle + + ;
2015-07-13 21:42:57 +03:00
/* list is sorted by access time */
remove_state = state ;
2003-02-28 03:25:55 +03:00
}
}
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 ;
}
2014-07-25 23:46:46 +04:00
/*
* Terminate all clients whose requests have taken longer than
* " winbind request timeout " seconds to process , or have been
* idle for more than " winbind request timeout " seconds .
*/
static void remove_timed_out_clients ( void )
{
2015-07-13 21:42:57 +03:00
struct winbindd_cli_state * state , * prev = NULL ;
2014-07-25 23:46:46 +04:00
time_t curr_time = time ( NULL ) ;
int timeout_val = lp_winbind_request_timeout ( ) ;
2015-07-13 21:42:57 +03:00
for ( state = winbindd_client_list_tail ( ) ; state ; state = prev ) {
2014-07-25 23:46:46 +04:00
time_t expiry_time ;
2015-07-13 21:42:57 +03:00
prev = winbindd_client_list_prev ( state ) ;
2014-07-25 23:46:46 +04:00
expiry_time = state - > last_access + timeout_val ;
2017-03-09 19:50:01 +03:00
if ( curr_time < = expiry_time ) {
2015-07-13 21:42:57 +03:00
/* list is sorted, previous clients in
list are newer */
break ;
2014-07-25 23:46:46 +04:00
}
2017-03-09 19:50:01 +03:00
if ( client_is_idle ( state ) ) {
DEBUG ( 5 , ( " Idle client timed out, "
" shutting down sock %d, pid %u \n " ,
state - > sock ,
( unsigned int ) state - > pid ) ) ;
} else {
DEBUG ( 5 , ( " Client request timed out, "
" shutting down sock %d, pid %u \n " ,
state - > sock ,
( unsigned int ) state - > pid ) ) ;
}
remove_client ( state ) ;
2014-07-25 23:46:46 +04:00
}
}
2015-07-06 21:29:17 +03:00
static void winbindd_scrub_clients_handler ( struct tevent_context * ev ,
struct tevent_timer * te ,
struct timeval current_time ,
void * private_data )
{
remove_timed_out_clients ( ) ;
if ( tevent_add_timer ( ev , ev ,
timeval_current_ofs ( SCRUB_CLIENTS_INTERVAL , 0 ) ,
winbindd_scrub_clients_handler , NULL ) = = NULL ) {
DEBUG ( 0 , ( " winbindd: failed to reschedule client scrubber \n " ) ) ;
exit ( 1 ) ;
}
}
2009-03-16 19:27:30 +03: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 ) ;
2010-09-15 03:43:39 +04:00
while ( winbindd_num_clients ( ) > lp_winbind_max_clients ( ) - 1 ) {
2009-03-16 19:27:30 +03:00
DEBUG ( 5 , ( " winbindd: Exceeding %d client "
" connections, removing idle "
2010-09-15 03:43:39 +04:00
" connection. \n " , lp_winbind_max_clients ( ) ) ) ;
2009-03-16 19:27:30 +03:00
if ( ! remove_idle_client ( ) ) {
DEBUG ( 0 , ( " winbindd: Exceeding %d "
" client connections, no idle "
" connection found \n " ,
2010-09-15 03:43:39 +04:00
lp_winbind_max_clients ( ) ) ) ;
2009-03-16 19:27:30 +03:00
break ;
}
}
2014-07-25 23:46:46 +04:00
remove_timed_out_clients ( ) ;
2009-03-16 19:27:30 +03:00
new_connection ( s - > fd , s - > privileged ) ;
}
2010-05-17 13:34:32 +04:00
/*
* Winbindd socket accessor functions
*/
char * get_winbind_priv_pipe_dir ( void )
{
2018-08-16 11:51:44 +03:00
return state_path ( talloc_tos ( ) , WINBINDD_PRIV_SOCKET_SUBDIR ) ;
2010-05-17 13:34:32 +04:00
}
2015-06-22 06:38:04 +03:00
static void winbindd_setup_max_fds ( void )
{
int num_fds = MAX_OPEN_FUDGEFACTOR ;
int actual_fds ;
num_fds + = lp_winbind_max_clients ( ) ;
/* Add some more to account for 2 sockets open
when the client transitions from unprivileged
to privileged socket
*/
num_fds + = lp_winbind_max_clients ( ) / 10 ;
/* Add one socket per child process
( yeah there are child processes other than the
domain children but only domain children can vary
with configuration
*/
num_fds + = lp_winbind_max_domain_connections ( ) *
( lp_allow_trusted_domains ( ) ? WINBIND_MAX_DOMAINS_HINT : 1 ) ;
actual_fds = set_maxfiles ( num_fds ) ;
if ( actual_fds < num_fds ) {
DEBUG ( 1 , ( " winbindd_setup_max_fds: Information only: "
" requested %d open files, %d are available. \n " ,
num_fds , actual_fds ) ) ;
}
}
2009-03-16 19:27:30 +03:00
static bool winbindd_setup_listeners ( void )
{
struct winbindd_listen_state * pub_state = NULL ;
struct winbindd_listen_state * priv_state = NULL ;
2009-05-25 22:31:59 +04:00
struct tevent_fd * fde ;
2011-08-29 11:49:22 +04:00
int rc ;
2014-11-02 22:21:36 +03:00
char * socket_path ;
2009-03-16 19:27:30 +03:00
2018-08-21 21:06:16 +03:00
pub_state = talloc ( global_event_context ( ) ,
2009-03-16 19:27:30 +03:00
struct winbindd_listen_state ) ;
if ( ! pub_state ) {
goto failed ;
}
pub_state - > privileged = false ;
2010-05-17 13:34:32 +04:00
pub_state - > fd = create_pipe_sock (
2013-10-11 04:34:13 +04:00
lp_winbindd_socket_directory ( ) , WINBINDD_SOCKET_NAME , 0755 ) ;
2009-03-16 19:27:30 +03:00
if ( pub_state - > fd = = - 1 ) {
goto failed ;
}
2011-08-29 11:49:22 +04:00
rc = listen ( pub_state - > fd , 5 ) ;
if ( rc < 0 ) {
goto failed ;
}
2009-03-16 19:27:30 +03:00
2018-08-21 21:06:16 +03:00
fde = tevent_add_fd ( global_event_context ( ) , pub_state , pub_state - > fd ,
2009-05-25 22:31:59 +04:00
TEVENT_FD_READ , winbindd_listen_fde_handler ,
pub_state ) ;
if ( fde = = NULL ) {
2009-03-16 19:27:30 +03:00
close ( pub_state - > fd ) ;
goto failed ;
}
2009-05-25 22:31:59 +04:00
tevent_fd_set_auto_close ( fde ) ;
2009-03-16 19:27:30 +03:00
2018-08-21 21:06:16 +03:00
priv_state = talloc ( global_event_context ( ) ,
2009-03-16 19:27:30 +03:00
struct winbindd_listen_state ) ;
if ( ! priv_state ) {
goto failed ;
}
2014-11-02 22:21:36 +03:00
socket_path = get_winbind_priv_pipe_dir ( ) ;
if ( socket_path = = NULL ) {
goto failed ;
}
2009-03-16 19:27:30 +03:00
priv_state - > privileged = true ;
2010-05-17 13:34:32 +04:00
priv_state - > fd = create_pipe_sock (
2014-11-02 22:21:36 +03:00
socket_path , WINBINDD_SOCKET_NAME , 0750 ) ;
TALLOC_FREE ( socket_path ) ;
2009-03-16 19:27:30 +03:00
if ( priv_state - > fd = = - 1 ) {
goto failed ;
}
2011-08-29 11:49:22 +04:00
rc = listen ( priv_state - > fd , 5 ) ;
if ( rc < 0 ) {
goto failed ;
}
2009-03-16 19:27:30 +03:00
2018-08-21 21:06:16 +03:00
fde = tevent_add_fd ( global_event_context ( ) , priv_state ,
2009-05-25 22:31:59 +04:00
priv_state - > fd , TEVENT_FD_READ ,
winbindd_listen_fde_handler , priv_state ) ;
if ( fde = = NULL ) {
2009-03-16 19:27:30 +03:00
close ( priv_state - > fd ) ;
goto failed ;
}
2009-05-25 22:31:59 +04:00
tevent_fd_set_auto_close ( fde ) ;
2009-03-16 19:27:30 +03:00
2018-08-21 21:06:16 +03:00
winbindd_scrub_clients_handler ( global_event_context ( ) , NULL ,
2015-07-06 21:29:17 +03:00
timeval_current ( ) , NULL ) ;
2009-03-16 19:27:30 +03:00
return true ;
failed :
TALLOC_FREE ( pub_state ) ;
TALLOC_FREE ( priv_state ) ;
return false ;
}
2009-03-12 12:12:58 +03:00
bool winbindd_use_idmap_cache ( void )
{
return ! opt_nocache ;
}
bool winbindd_use_cache ( void )
{
return ! opt_nocache ;
}
2012-10-19 20:09:21 +04:00
static void winbindd_register_handlers ( struct messaging_context * msg_ctx ,
bool foreground )
2010-05-11 15:37:30 +04:00
{
2017-11-29 18:02:28 +03:00
bool scan_trusts = true ;
2014-05-06 09:00:09 +04:00
NTSTATUS status ;
2010-05-11 15:37:30 +04:00
/* Setup signal handlers */
if ( ! winbindd_setup_sig_term_handler ( true ) )
exit ( 1 ) ;
2012-03-02 11:22:10 +04:00
if ( ! winbindd_setup_stdin_handler ( true , foreground ) )
exit ( 1 ) ;
2010-05-11 15:37:30 +04:00
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 */
/*
* Ensure all cache and idmap caches are consistent
* and initialized before we startup .
*/
if ( ! winbindd_cache_validate_and_initialize ( ) ) {
exit ( 1 ) ;
}
/* React on 'smbcontrol winbindd reload-config' in the same way
as to SIGHUP signal */
2012-10-19 20:09:21 +04:00
messaging_register ( msg_ctx , NULL ,
2010-05-11 15:37:30 +04:00
MSG_SMB_CONF_UPDATED , msg_reload_services ) ;
2012-10-19 20:09:21 +04:00
messaging_register ( msg_ctx , NULL ,
2010-05-11 15:37:30 +04:00
MSG_SHUTDOWN , msg_shutdown ) ;
/* Handle online/offline messages. */
2012-10-19 20:09:21 +04:00
messaging_register ( msg_ctx , NULL ,
2010-05-11 15:37:30 +04:00
MSG_WINBIND_OFFLINE , winbind_msg_offline ) ;
2012-10-19 20:09:21 +04:00
messaging_register ( msg_ctx , NULL ,
2010-05-11 15:37:30 +04:00
MSG_WINBIND_ONLINE , winbind_msg_online ) ;
2012-10-19 20:09:21 +04:00
messaging_register ( msg_ctx , NULL ,
2010-05-11 15:37:30 +04:00
MSG_WINBIND_ONLINESTATUS , winbind_msg_onlinestatus ) ;
2013-10-10 12:02:27 +04:00
/* Handle domain online/offline messages for domains */
2018-08-21 21:09:16 +03:00
messaging_register ( global_messaging_context ( ) , NULL ,
2013-10-10 12:02:27 +04:00
MSG_WINBIND_DOMAIN_OFFLINE , winbind_msg_domain_offline ) ;
2018-08-21 21:09:16 +03:00
messaging_register ( global_messaging_context ( ) , NULL ,
2013-10-10 12:02:27 +04:00
MSG_WINBIND_DOMAIN_ONLINE , winbind_msg_domain_online ) ;
2012-10-19 20:09:21 +04:00
messaging_register ( msg_ctx , NULL ,
2010-05-11 15:37:30 +04:00
MSG_WINBIND_VALIDATE_CACHE ,
winbind_msg_validate_cache ) ;
2012-10-19 20:09:21 +04:00
messaging_register ( msg_ctx , NULL ,
2010-05-11 15:37:30 +04:00
MSG_WINBIND_DUMP_DOMAIN_LIST ,
winbind_msg_dump_domain_list ) ;
2012-10-19 20:09:21 +04:00
messaging_register ( msg_ctx , NULL ,
2010-09-29 14:17:05 +04:00
MSG_WINBIND_IP_DROPPED ,
winbind_msg_ip_dropped_parent ) ;
2010-05-11 15:37:30 +04:00
/* Register handler for MSG_DEBUG. */
2012-10-19 20:09:21 +04:00
messaging_register ( msg_ctx , NULL ,
2010-05-11 15:37:30 +04:00
MSG_DEBUG ,
winbind_msg_debug ) ;
2018-02-28 18:08:44 +03:00
messaging_register ( msg_ctx , NULL ,
MSG_WINBIND_DISCONNECT_DC ,
winbind_disconnect_dc_parent ) ;
2010-05-11 15:37:30 +04:00
netsamlogon_cache_init ( ) ; /* Non-critical */
/* clear the cached list of trusted domains */
wcache_tdc_clear ( ) ;
if ( ! init_domain_list ( ) ) {
DEBUG ( 0 , ( " unable to initialize domain list \n " ) ) ;
exit ( 1 ) ;
}
init_idmap_child ( ) ;
init_locator_child ( ) ;
smb_nscd_flush_user_cache ( ) ;
smb_nscd_flush_group_cache ( ) ;
2017-11-29 18:02:28 +03:00
if ( ! lp_winbind_scan_trusted_domains ( ) ) {
scan_trusts = false ;
}
2017-11-29 18:02:28 +03:00
if ( ! lp_allow_trusted_domains ( ) ) {
scan_trusts = false ;
}
if ( IS_DC ) {
scan_trusts = false ;
}
if ( scan_trusts ) {
2018-08-21 21:06:16 +03:00
if ( tevent_add_timer ( global_event_context ( ) , NULL , timeval_zero ( ) ,
2011-04-07 00:52:42 +04:00
rescan_trusted_domains , NULL ) = = NULL ) {
DEBUG ( 0 , ( " Could not trigger rescan_trusted_domains() \n " ) ) ;
exit ( 1 ) ;
}
2010-05-11 15:37:30 +04:00
}
2014-05-08 06:46:06 +04:00
status = wb_irpc_register ( ) ;
2014-05-06 09:00:09 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-05-08 06:46:06 +04:00
DEBUG ( 0 , ( " Could not register IRPC handlers \n " ) ) ;
2014-05-06 09:00:09 +04:00
exit ( 1 ) ;
}
2010-05-11 15:37:30 +04:00
}
2011-01-31 19:25:55 +03:00
struct winbindd_addrchanged_state {
struct addrchange_context * ctx ;
struct tevent_context * ev ;
struct messaging_context * msg_ctx ;
} ;
static void winbindd_addr_changed ( struct tevent_req * req ) ;
static void winbindd_init_addrchange ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct messaging_context * msg_ctx )
{
struct winbindd_addrchanged_state * state ;
struct tevent_req * req ;
NTSTATUS status ;
state = talloc ( mem_ctx , struct winbindd_addrchanged_state ) ;
if ( state = = NULL ) {
DEBUG ( 10 , ( " talloc failed \n " ) ) ;
return ;
}
state - > ev = ev ;
state - > msg_ctx = msg_ctx ;
status = addrchange_context_create ( state , & state - > ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " addrchange_context_create failed: %s \n " ,
nt_errstr ( status ) ) ) ;
TALLOC_FREE ( state ) ;
return ;
}
req = addrchange_send ( state , ev , state - > ctx ) ;
if ( req = = NULL ) {
2011-02-04 14:29:42 +03:00
DEBUG ( 0 , ( " addrchange_send failed \n " ) ) ;
2011-01-31 19:25:55 +03:00
TALLOC_FREE ( state ) ;
2011-02-04 14:29:42 +03:00
return ;
2011-01-31 19:25:55 +03:00
}
tevent_req_set_callback ( req , winbindd_addr_changed , state ) ;
}
static void winbindd_addr_changed ( struct tevent_req * req )
{
struct winbindd_addrchanged_state * state = tevent_req_callback_data (
req , struct winbindd_addrchanged_state ) ;
enum addrchange_type type ;
struct sockaddr_storage addr ;
NTSTATUS status ;
status = addrchange_recv ( req , & type , & addr ) ;
TALLOC_FREE ( req ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " addrchange_recv failed: %s, stop listening \n " ,
nt_errstr ( status ) ) ) ;
TALLOC_FREE ( state ) ;
2011-02-04 14:29:42 +03:00
return ;
2011-01-31 19:25:55 +03:00
}
if ( type = = ADDRCHANGE_DEL ) {
char addrstr [ INET6_ADDRSTRLEN ] ;
DATA_BLOB blob ;
print_sockaddr ( addrstr , sizeof ( addrstr ) , & addr ) ;
DEBUG ( 3 , ( " winbindd: kernel (AF_NETLINK) dropped ip %s \n " ,
addrstr ) ) ;
blob = data_blob_const ( addrstr , strlen ( addrstr ) + 1 ) ;
status = messaging_send ( state - > msg_ctx ,
messaging_server_id ( state - > msg_ctx ) ,
MSG_WINBIND_IP_DROPPED , & blob ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-02-04 14:29:42 +03:00
DEBUG ( 10 , ( " messaging_send failed: %s - ignoring \n " ,
2011-01-31 19:25:55 +03:00
nt_errstr ( status ) ) ) ;
}
}
req = addrchange_send ( state , state - > ev , state - > ctx ) ;
if ( req = = NULL ) {
2011-02-04 14:29:42 +03:00
DEBUG ( 0 , ( " addrchange_send failed \n " ) ) ;
2011-01-31 19:25:55 +03:00
TALLOC_FREE ( state ) ;
2011-02-04 14:29:42 +03:00
return ;
2011-01-31 19:25:55 +03:00
}
tevent_req_set_callback ( req , winbindd_addr_changed , state ) ;
}
2000-05-09 15:43:00 +04:00
/* Main function */
2014-02-26 23:16:26 +04:00
int main ( int argc , const char * * argv )
2000-05-09 15:43:00 +04:00
{
2007-10-19 22:38:36 +04: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 07:53:58 +04:00
struct poptOption long_options [ ] = {
POPT_AUTOHELP
2007-10-19 22:38:36 +04: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-11 00:34:30 +04:00
{ " interactive " , ' i ' , POPT_ARG_NONE , NULL , ' i ' , " Interactive mode " } ,
2007-10-19 22:38:36 +04:00
{ " no-caching " , ' n ' , POPT_ARG_NONE , NULL , ' n ' , " 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 ;
2010-09-24 20:45:52 +04:00
TALLOC_CTX * frame ;
2010-07-04 18:28:13 +04:00
NTSTATUS status ;
2012-12-13 20:29:39 +04:00
bool ok ;
2001-05-07 08:32:40 +04:00
2017-12-20 19:42:45 +03:00
setproctitle_init ( argc , discard_const ( argv ) , environ ) ;
2010-09-24 20:45:52 +04:00
/*
* Do this before any other talloc operation
*/
talloc_enable_null_tracking ( ) ;
frame = talloc_stackframe ( ) ;
2013-06-18 04:25:41 +04:00
/*
* We want total control over the permissions on created files ,
* so set our umask to 0.
*/
umask ( 0 ) ;
2011-07-18 11:07:25 +04:00
setup_logging ( " winbindd " , DEBUG_DEFAULT_STDOUT ) ;
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
2011-03-22 06:05:23 +03:00
fault_setup ( ) ;
2012-07-18 09:37:23 +04:00
dump_core_setup ( " winbindd " , lp_logfile ( talloc_tos ( ) ) ) ;
2001-12-21 05:23:38 +03:00
2015-03-21 22:00:06 +03:00
smb_init_locale ( ) ;
2005-12-29 00:10:11 +03:00
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 */
2014-02-26 23:16:26 +04:00
pc = poptGetContext ( " winbindd " , argc , argv , long_options , 0 ) ;
2007-08-21 18:22:16 +04:00
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
switch ( opt ) {
2007-10-11 00:34:30 +04:00
/* Don't become a daemon */
2007-10-19 22:38:36 +04:00
case OPT_DAEMON :
2007-10-11 00:34:30 +04:00
is_daemon = True ;
break ;
case ' i ' :
interactive = True ;
log_stdout = True ;
Fork = False ;
break ;
2007-10-19 22:38:36 +04: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 18:22:16 +04:00
default :
2007-08-22 16:06:27 +04:00
d_fprintf ( stderr , " \n Invalid option %s: %s \n \n " ,
2007-08-21 18:22:16 +04:00
poptBadOption ( pc , 0 ) , poptStrerror ( opt ) ) ;
2007-08-22 16:06:27 +04:00
poptPrintUsage ( pc , stderr , 0 ) ;
2007-08-21 18:22:16 +04:00
exit ( 1 ) ;
}
}
2007-04-20 22:34:33 +04:00
2012-06-11 21:23:51 +04:00
/* We call dump_core_setup one more time because the command line can
* set the log file or the log - basename and this will influence where
* cores are stored . Without this call get_dyn_LOGFILEBASE will be
* the default value derived from build ' s prefix . For EOM this value
* is often not related to the path where winbindd is actually run
* in production .
*/
2012-07-18 09:37:23 +04:00
dump_core_setup ( " winbindd " , lp_logfile ( talloc_tos ( ) ) ) ;
2007-10-11 00:34:30 +04: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 08:32:40 +04:00
}
2000-05-09 15:43:00 +04:00
2007-10-11 00:34:30 +04: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 07:53:58 +04:00
poptPrintUsage ( pc , stderr , 0 ) ;
2003-01-03 20:39:30 +03:00
exit ( 1 ) ;
}
2007-08-22 16:06:27 +04:00
poptFreeContext ( pc ) ;
2004-09-21 13:07:42 +04:00
if ( ! override_logfile ) {
2008-11-03 23:36:34 +03:00
char * lfile = NULL ;
if ( asprintf ( & lfile , " %s/log.winbindd " ,
2007-12-10 22:30:37 +03:00
get_dyn_LOGFILEBASE ( ) ) > 0 ) {
2008-11-03 23:36:34 +03:00
lp_set_logfile ( lfile ) ;
SAFE_FREE ( lfile ) ;
2007-11-21 04:18:16 +03:00
}
2004-09-21 13:07:42 +04:00
}
2011-07-18 11:07:25 +04:00
2010-10-29 07:19:32 +04:00
if ( log_stdout ) {
setup_logging ( " winbindd " , DEBUG_STDOUT ) ;
} else {
setup_logging ( " winbindd " , DEBUG_FILE ) ;
}
2001-05-07 08:32:40 +04:00
reopen_logs ( ) ;
2000-05-09 15:43:00 +04:00
2009-01-16 00:27:52 +03:00
DEBUG ( 0 , ( " winbindd version %s started. \n " , samba_version_string ( ) ) ) ;
2007-10-30 17:44:27 +03:00
DEBUGADD ( 0 , ( " %s \n " , COPYRIGHT_STARTUP_MESSAGE ) ) ;
2001-12-20 21:37:43 +03:00
2008-04-15 12:57:16 +04:00
if ( ! lp_load_initial_only ( get_dyn_CONFIGFILE ( ) ) ) {
2011-03-23 03:22:15 +03:00
DEBUG ( 0 , ( " error opening config file '%s' \n " , get_dyn_CONFIGFILE ( ) ) ) ;
2008-04-15 12:57:16 +04:00
exit ( 1 ) ;
}
2012-06-11 21:23:51 +04:00
/* After parsing the configuration file we setup the core path one more time
* as the log file might have been set in the configuration and cores ' s
* path is by default basename ( lp_logfile ( ) ) .
*/
2012-07-18 09:37:23 +04:00
dump_core_setup ( " winbindd " , lp_logfile ( talloc_tos ( ) ) ) ;
2008-04-15 12:57:16 +04:00
2014-03-28 05:35:21 +04:00
if ( lp_server_role ( ) = = ROLE_ACTIVE_DIRECTORY_DC
& & ! lp_parm_bool ( - 1 , " server role check " , " inhibit " , false ) ) {
2012-08-22 15:01:16 +04:00
DEBUG ( 0 , ( " server role = 'active directory domain controller' not compatible with running the winbindd binary. \n " ) ) ;
DEBUGADD ( 0 , ( " You should start 'samba' instead, and it will control starting the internal AD DC winbindd implementation, which is not the same as this one \n " ) ) ;
exit ( 1 ) ;
}
2013-10-17 17:16:19 +04:00
if ( ! cluster_probe_ok ( ) ) {
exit ( 1 ) ;
2013-01-31 14:15:09 +04:00
}
2008-04-15 12:57:16 +04:00
/* Initialise messaging system */
2018-08-21 21:09:16 +03:00
if ( global_messaging_context ( ) = = NULL ) {
2008-04-15 12:57:16 +04:00
exit ( 1 ) ;
}
2008-07-18 07:10:18 +04:00
if ( ! reload_services_file ( NULL ) ) {
2001-12-20 21:37:43 +03:00
DEBUG ( 0 , ( " error opening config file \n " ) ) ;
exit ( 1 ) ;
}
2016-12-12 12:05:39 +03:00
{
size_t i ;
const char * idmap_backend ;
const char * invalid_backends [ ] = {
" ad " , " rfc2307 " , " rid " ,
} ;
idmap_backend = lp_idmap_default_backend ( ) ;
for ( i = 0 ; i < ARRAY_SIZE ( invalid_backends ) ; i + + ) {
ok = strequal ( idmap_backend , invalid_backends [ i ] ) ;
if ( ok ) {
DBG_ERR ( " FATAL: Invalid idmap backend %s "
" configured as the default backend! \n " ,
idmap_backend ) ;
exit ( 1 ) ;
}
}
}
2014-07-27 21:18:09 +04:00
ok = directory_create_or_exist ( lp_lock_directory ( ) , 0755 ) ;
2012-12-13 20:29:39 +04:00
if ( ! ok ) {
DEBUG ( 0 , ( " Failed to create directory %s for lock files - %s \n " ,
2014-02-03 06:46:08 +04:00
lp_lock_directory ( ) , strerror ( errno ) ) ) ;
2012-12-13 20:29:39 +04:00
exit ( 1 ) ;
2006-09-02 06:04:41 +04:00
}
2014-07-27 21:18:09 +04:00
ok = directory_create_or_exist ( lp_pid_directory ( ) , 0755 ) ;
2012-12-13 20:29:39 +04:00
if ( ! ok ) {
DEBUG ( 0 , ( " Failed to create directory %s for pid files - %s \n " ,
2014-02-03 06:57:21 +04:00
lp_pid_directory ( ) , strerror ( errno ) ) ) ;
2012-12-13 20:29:39 +04:00
exit ( 1 ) ;
2012-03-07 05:58:37 +04:00
}
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 ;
}
2013-12-17 23:06:14 +04:00
status = rpccli_pre_open_netlogon_creds ( ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " rpccli_pre_open_netlogon_creds() - %s \n " ,
nt_errstr ( status ) ) ) ;
exit ( 1 ) ;
}
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
2007-10-11 00:34:30 +04:00
if ( ! interactive )
2010-03-26 13:17:37 +03:00
become_daemon ( Fork , no_process_group , log_stdout ) ;
2000-05-09 15:43:00 +04:00
2014-02-03 06:57:21 +04:00
pidfile_create ( lp_pid_directory ( ) , " winbindd " ) ;
2002-09-25 19:19:00 +04: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-10-11 00:34:30 +04:00
if ( interactive & & ! no_process_group )
2001-12-30 04:46:38 +03:00
setpgid ( ( pid_t ) 0 , ( pid_t ) 0 ) ;
# endif
2005-11-05 07:21:55 +03:00
TimeInit ( ) ;
2010-05-13 11:07:15 +04: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 .
*/
2018-08-21 21:09:16 +03:00
status = reinit_after_fork ( global_messaging_context ( ) ,
2018-08-21 21:06:16 +03:00
global_event_context ( ) ,
2015-09-23 21:14:05 +03:00
false , NULL ) ;
2010-07-04 18:28:13 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-03-26 13:45:21 +04:00
exit_daemon ( " Winbindd reinit_after_fork() failed " , map_errno_from_nt_status ( status ) ) ;
2010-05-13 11:07:15 +04:00
}
2018-08-21 21:06:16 +03:00
initialize_password_db ( true , global_event_context ( ) ) ;
2010-05-13 11:07:15 +04:00
2012-03-15 19:29:27 +04:00
/*
* Do not initialize the parent - child - pipe before becoming
* a daemon : this is used to detect a died parent in the child
* process .
*/
status = init_before_fork ( ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-03-26 13:45:21 +04:00
exit_daemon ( nt_errstr ( status ) , map_errno_from_nt_status ( status ) ) ;
2012-03-15 19:29:27 +04:00
}
2018-08-21 21:09:16 +03:00
winbindd_register_handlers ( global_messaging_context ( ) , ! Fork ) ;
2006-03-16 16:37:23 +03:00
2018-08-21 21:09:16 +03:00
if ( ! messaging_parent_dgm_cleanup_init ( global_messaging_context ( ) ) ) {
2014-04-19 02:09:28 +04:00
exit ( 1 ) ;
}
2018-02-13 14:12:06 +03:00
status = init_system_session_info ( NULL ) ;
2011-02-19 22:05:07 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-03-26 13:45:21 +04:00
exit_daemon ( " Winbindd failed to setup system user info " , map_errno_from_nt_status ( status ) ) ;
2010-05-27 14:06:24 +04:00
}
2010-10-15 19:58:39 +04:00
rpc_lsarpc_init ( NULL ) ;
rpc_samr_init ( NULL ) ;
2018-08-21 21:06:16 +03:00
winbindd_init_addrchange ( NULL , global_event_context ( ) ,
2018-08-21 21:09:16 +03:00
global_messaging_context ( ) ) ;
2011-01-31 19:25:55 +03:00
2009-03-16 19:27:30 +03:00
/* setup listen sockets */
if ( ! winbindd_setup_listeners ( ) ) {
2014-03-26 13:45:21 +04:00
exit_daemon ( " Winbindd failed to setup listeners " , EPIPE ) ;
2009-03-16 19:27:30 +03:00
}
2007-10-11 00:34:30 +04:00
2014-05-06 05:39:12 +04:00
irpc_add_name ( winbind_imessaging_context ( ) , " winbind_server " ) ;
2007-11-16 01:19:52 +03:00
TALLOC_FREE ( frame ) ;
2014-03-25 14:53:04 +04:00
if ( ! interactive ) {
daemon_ready ( " winbindd " ) ;
}
2017-11-21 13:44:12 +03:00
gpupdate_init ( ) ;
2009-03-16 19:27:30 +03:00
/* Loop waiting for requests */
2007-10-11 00:34:30 +04:00
while ( 1 ) {
2007-11-16 01:19:52 +03:00
frame = talloc_stackframe ( ) ;
2009-03-16 18:14:20 +03:00
2018-08-21 21:06:16 +03:00
if ( tevent_loop_once ( global_event_context ( ) ) = = - 1 ) {
2009-05-26 00:40:09 +04:00
DEBUG ( 1 , ( " tevent_loop_once() failed: %s \n " ,
strerror ( errno ) ) ) ;
return 1 ;
}
2009-03-16 18:14:20 +03:00
2007-10-11 00:34:30 +04:00
TALLOC_FREE ( frame ) ;
}
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
}