2017-03-31 21:43:17 +03:00
/*
2003-08-13 05:53:07 +04:00
Unix SMB / CIFS implementation .
2005-01-30 03:54:57 +03:00
2003-08-13 05:53:07 +04:00
Main SMB server routines
2005-01-30 03:54:57 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 2005
2003-08-13 05:53:07 +04:00
Copyright ( C ) Martin Pool 2002
Copyright ( C ) Jelmer Vernooij 2002
Copyright ( C ) James J Myers 2003 < myersjj @ samba . org >
2017-03-31 21:43:17 +03:00
2003-08-13 05:53:07 +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-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 05:53:07 +04:00
( at your option ) any later version .
2017-03-31 21:43:17 +03:00
2003-08-13 05:53:07 +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 .
2017-03-31 21:43:17 +03:00
2003-08-13 05:53:07 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 05:53:07 +04:00
*/
# include "includes.h"
2005-02-03 14:56:03 +03:00
# include "lib/events/events.h"
2005-01-18 13:10:35 +03:00
# include "version.h"
2021-01-14 11:50:10 +03:00
# include "lib/cmdline/cmdline.h"
2005-01-30 03:54:57 +03:00
# include "system/dir.h"
2005-02-10 08:09:35 +03:00
# include "system/filesys.h"
2005-12-31 01:46:16 +03:00
# include "auth/gensec/gensec.h"
2010-06-23 04:33:15 +04:00
# include "libcli/auth/schannel.h"
2020-11-20 17:27:17 +03:00
# include "samba/process_model.h"
2006-11-06 19:11:52 +03:00
# include "param/secrets.h"
2012-07-20 02:41:52 +04:00
# include "lib/util/pidfile.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2009-08-07 11:19:39 +04:00
# include "dsdb/samdb/samdb.h"
# include "auth/session.h"
2009-09-19 05:05:55 +04:00
# include "lib/messaging/irpc.h"
# include "librpc/gen_ndr/ndr_irpc.h"
# include "cluster/cluster.h"
2010-03-29 13:20:25 +04:00
# include "dynconfig/dynconfig.h"
2013-07-10 16:48:18 +04:00
# include "nsswitch/winbind_client.h"
2015-12-28 22:01:54 +03:00
# include "libds/common/roles.h"
2017-08-21 22:58:14 +03:00
# include "lib/util/tfork.h"
2018-05-01 06:48:38 +03:00
# include "dsdb/samdb/ldb_modules/util.h"
2019-01-17 18:27:10 +03:00
# include "lib/util/server_id.h"
2020-11-26 16:21:58 +03:00
# include "server_util.h"
2017-08-21 22:58:14 +03:00
# ifdef HAVE_PTHREAD
# include <pthread.h>
# endif
2003-08-13 05:53:07 +04:00
2017-03-31 21:54:45 +03:00
struct server_state {
struct tevent_context * event_ctx ;
const char * binary_name ;
} ;
2005-01-30 03:54:57 +03:00
/*
2005-07-10 12:06:28 +04:00
recursively delete a directory tree
2005-01-30 03:54:57 +03:00
*/
2005-07-10 12:06:28 +04:00
static void recursive_delete ( const char * path )
2003-08-13 05:53:07 +04:00
{
2005-01-30 03:54:57 +03:00
DIR * dir ;
struct dirent * de ;
2003-08-13 05:53:07 +04:00
2005-01-30 03:54:57 +03:00
dir = opendir ( path ) ;
if ( ! dir ) {
return ;
2003-08-13 05:53:07 +04:00
}
2005-01-30 03:54:57 +03:00
for ( de = readdir ( dir ) ; de ; de = readdir ( dir ) ) {
2005-07-10 12:06:28 +04:00
char * fname ;
struct stat st ;
2006-04-24 04:16:51 +04:00
if ( ISDOT ( de - > d_name ) | | ISDOTDOT ( de - > d_name ) ) {
2005-07-10 12:06:28 +04:00
continue ;
}
fname = talloc_asprintf ( path , " %s/%s " , path , de - > d_name ) ;
if ( stat ( fname , & st ) ! = 0 ) {
continue ;
}
if ( S_ISDIR ( st . st_mode ) ) {
recursive_delete ( fname ) ;
talloc_free ( fname ) ;
continue ;
}
if ( unlink ( fname ) ! = 0 ) {
2017-09-11 02:39:39 +03:00
DBG_ERR ( " Unabled to delete '%s' - %s \n " ,
fname , strerror ( errno ) ) ;
2005-07-10 12:06:28 +04:00
smb_panic ( " unable to cleanup tmp files " ) ;
2005-01-30 03:54:57 +03:00
}
2005-07-10 12:06:28 +04:00
talloc_free ( fname ) ;
2003-08-13 05:53:07 +04:00
}
2005-01-30 03:54:57 +03:00
closedir ( dir ) ;
2005-07-10 12:06:28 +04:00
}
/*
cleanup temporary files . This is the new alternative to
TDB_CLEAR_IF_FIRST . Unfortunately TDB_CLEAR_IF_FIRST is not
efficient on unix systems due to the lack of scaling of the byte
range locking system . So instead of putting the burden on tdb to
2017-03-31 21:43:17 +03:00
cleanup tmp files , this function deletes them .
2005-07-10 12:06:28 +04:00
*/
2007-12-03 00:32:11 +03:00
static void cleanup_tmp_files ( struct loadparm_context * lp_ctx )
2005-07-10 12:06:28 +04:00
{
char * path ;
TALLOC_CTX * mem_ctx = talloc_new ( NULL ) ;
2017-11-15 12:00:52 +03:00
if ( mem_ctx = = NULL ) {
exit_daemon ( " Failed to create memory context " ,
ENOMEM ) ;
}
2005-07-10 12:06:28 +04:00
2007-12-03 00:32:11 +03:00
path = smbd_tmp_path ( mem_ctx , lp_ctx , NULL ) ;
2017-11-15 12:00:52 +03:00
if ( path = = NULL ) {
exit_daemon ( " Failed to cleanup temporary files " ,
EINVAL ) ;
}
2005-01-30 03:54:57 +03:00
2005-07-10 12:06:28 +04:00
recursive_delete ( path ) ;
2005-01-30 03:54:57 +03:00
talloc_free ( mem_ctx ) ;
}
2003-08-13 05:53:07 +04:00
2006-03-08 15:31:57 +03:00
static void sig_hup ( int sig )
{
debug_schedule_reopen_logs ( ) ;
}
2006-09-11 08:47:56 +04:00
static void sig_term ( int sig )
{
2018-11-21 13:37:26 +03:00
# ifdef HAVE_GETPGRP
2017-03-31 22:38:14 +03:00
if ( getpgrp ( ) = = getpid ( ) ) {
/*
* We ' re the process group leader , send
* SIGTERM to our process group .
*/
2006-09-11 08:47:56 +04:00
kill ( - getpgrp ( ) , SIGTERM ) ;
}
# endif
2018-01-04 23:06:02 +03:00
_exit ( 127 ) ;
2006-09-11 08:47:56 +04:00
}
2017-03-31 22:38:14 +03:00
static void sigterm_signal_handler ( struct tevent_context * ev ,
struct tevent_signal * se ,
int signum , int count , void * siginfo ,
void * private_data )
{
struct server_state * state = talloc_get_type_abort (
private_data , struct server_state ) ;
2017-09-11 02:39:39 +03:00
DBG_DEBUG ( " Process %s got SIGTERM \n " , state - > binary_name ) ;
2017-04-03 21:04:31 +03:00
TALLOC_FREE ( state ) ;
2017-03-31 22:38:14 +03:00
sig_term ( SIGTERM ) ;
}
2020-11-20 17:21:03 +03:00
static void sighup_signal_handler ( struct tevent_context * ev ,
struct tevent_signal * se ,
int signum , int count , void * siginfo ,
void * private_data )
{
struct server_state * state = talloc_get_type_abort (
private_data , struct server_state ) ;
DBG_DEBUG ( " Process %s got SIGHUP \n " , state - > binary_name ) ;
reopen_logs_internal ( ) ;
}
2005-01-30 03:54:57 +03:00
/*
setup signal masks
*/
static void setup_signals ( void )
{
2003-08-13 05:53:07 +04:00
/* we are never interested in SIGPIPE */
2007-10-02 02:13:02 +04:00
BlockSignals ( true , SIGPIPE ) ;
2003-08-13 05:53:07 +04:00
# if defined(SIGFPE)
/* we are never interested in SIGFPE */
2007-10-02 02:13:02 +04:00
BlockSignals ( true , SIGFPE ) ;
2003-08-13 05:53:07 +04:00
# endif
2005-12-15 19:53:20 +03:00
/* We are no longer interested in USR1 */
2007-10-02 02:13:02 +04:00
BlockSignals ( true , SIGUSR1 ) ;
2005-12-15 19:53:20 +03:00
2003-08-13 05:53:07 +04:00
# if defined(SIGUSR2)
/* We are no longer interested in USR2 */
2007-10-02 02:13:02 +04:00
BlockSignals ( true , SIGUSR2 ) ;
2003-08-13 05:53:07 +04:00
# endif
/* POSIX demands that signals are inherited. If the invoking process has
2017-03-31 21:43:17 +03:00
* these signals masked , we will have problems ,
* as we won ' t receive them . */
2007-10-02 02:13:02 +04:00
BlockSignals ( false , SIGHUP ) ;
BlockSignals ( false , SIGTERM ) ;
2005-01-30 03:54:57 +03:00
2006-03-08 15:31:57 +03:00
CatchSignal ( SIGHUP , sig_hup ) ;
2006-09-11 08:47:56 +04:00
CatchSignal ( SIGTERM , sig_term ) ;
2005-12-15 19:53:20 +03:00
}
2005-01-30 03:54:57 +03:00
2005-05-17 10:20:54 +04:00
/*
handle io on stdin
*/
2017-03-31 21:43:17 +03:00
static void server_stdin_handler ( struct tevent_context * event_ctx ,
struct tevent_fd * fde ,
uint16_t flags ,
void * private_data )
2005-05-17 10:20:54 +04:00
{
2017-03-31 21:59:13 +03:00
struct server_state * state = talloc_get_type_abort (
private_data , struct server_state ) ;
2005-05-17 10:20:54 +04:00
uint8_t c ;
if ( read ( 0 , & c , 1 ) = = 0 ) {
2017-09-11 02:39:39 +03:00
DBG_ERR ( " %s: EOF on stdin - PID %d terminating \n " ,
state - > binary_name , ( int ) getpid ( ) ) ;
2018-11-21 13:37:26 +03:00
# ifdef HAVE_GETPGRP
2006-09-11 08:47:56 +04:00
if ( getpgrp ( ) = = getpid ( ) ) {
2017-09-11 02:39:39 +03:00
DBG_ERR ( " Sending SIGTERM from pid %d \n " ,
( int ) getpid ( ) ) ;
2006-09-11 08:47:56 +04:00
kill ( - getpgrp ( ) , SIGTERM ) ;
}
# endif
2017-04-03 21:04:31 +03:00
TALLOC_FREE ( state ) ;
2005-05-17 10:20:54 +04:00
exit ( 0 ) ;
}
}
2005-06-12 04:17:23 +04:00
/*
die if the user selected maximum runtime is exceeded
*/
2017-03-31 21:43:17 +03:00
_NORETURN_ static void max_runtime_handler ( struct tevent_context * ev ,
struct tevent_timer * te ,
2009-02-02 10:41:28 +03:00
struct timeval t , void * private_data )
2005-06-12 04:17:23 +04:00
{
2017-03-31 22:00:29 +03:00
struct server_state * state = talloc_get_type_abort (
private_data , struct server_state ) ;
2017-09-11 02:39:39 +03:00
DBG_ERR ( " %s: maximum runtime exceeded - "
2017-03-31 21:43:17 +03:00
" terminating PID %d at %llu, current ts: %llu \n " ,
2017-03-31 22:00:29 +03:00
state - > binary_name ,
2017-03-31 21:43:17 +03:00
( int ) getpid ( ) ,
( unsigned long long ) t . tv_sec ,
2017-09-11 02:39:39 +03:00
( unsigned long long ) time ( NULL ) ) ;
2017-04-03 21:04:31 +03:00
TALLOC_FREE ( state ) ;
2005-06-12 04:17:23 +04:00
exit ( 0 ) ;
}
2019-03-05 04:38:41 +03:00
/*
* When doing an in - place upgrade of Samba , the database format may have
* changed between versions . E . g . between 4.7 and 4.8 the DB changed from
* DN - based indexes to GUID - based indexes , so we have to re - index the DB after
* upgrading .
* This function handles migrating an older samba DB to a new Samba release .
* Note that we have to maintain DB compatibility between * all * older versions
* of Samba , not just the ones still under maintenance support .
2023-05-31 05:38:02 +03:00
*
* Finally , while the transaction is open , check if we support the set
* domain functional level , if the DC functional level on our object
* is correct and if not to update it ( except on the RODC )
2019-03-05 04:38:41 +03:00
*/
2023-05-31 05:38:02 +03:00
static int handle_inplace_db_upgrade_check_and_update_fl ( struct ldb_context * ldb_ctx ,
struct loadparm_context * lp_ctx )
2019-03-05 04:38:41 +03:00
{
int ret ;
/*
* The DSDB stack will handle reindexing the DB ( if needed ) upon the first
* DB write . Open and close a transaction on the DB now to trigger a
* reindex if required , rather than waiting for the first write .
* We do this here to guarantee that the DB will have been re - indexed by
* the time the main samba code runs .
* Refer to dsdb_schema_set_indices_and_attributes ( ) for the actual reindexing
* code , called from
* source4 / dsdb / samdb / ldb_modules / schema_load . c : schema_load_start_transaction ( )
*/
ret = ldb_transaction_start ( ldb_ctx ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
2023-05-31 05:38:02 +03:00
ret = dsdb_check_and_update_fl ( ldb_ctx , lp_ctx ) ;
if ( ret ! = LDB_SUCCESS ) {
ldb_transaction_cancel ( ldb_ctx ) ;
return ret ;
}
2019-03-05 04:38:41 +03:00
ret = ldb_transaction_commit ( ldb_ctx ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
return LDB_SUCCESS ;
}
2009-08-07 11:19:39 +04:00
/*
2009-10-23 07:30:00 +04:00
pre - open the key databases . This saves a lot of time in child
processes
2009-08-07 11:19:39 +04:00
*/
2018-05-01 06:48:38 +03:00
static int prime_ldb_databases ( struct tevent_context * event_ctx , bool * am_backup )
2009-08-07 11:19:39 +04:00
{
2018-05-01 06:48:38 +03:00
struct ldb_result * res = NULL ;
struct ldb_dn * samba_dsdb_dn = NULL ;
struct ldb_context * ldb_ctx = NULL ;
struct ldb_context * pdb = NULL ;
static const char * attrs [ ] = { " backupDate " , NULL } ;
2021-01-14 11:50:10 +03:00
struct loadparm_context * lp_ctx = samba_cmdline_get_lp_ctx ( ) ;
2018-05-01 06:48:38 +03:00
const char * msg = NULL ;
int ret ;
TALLOC_CTX * db_context = talloc_new ( event_ctx ) ;
if ( db_context = = NULL ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
* am_backup = false ;
/* note we deliberately leave these open, which allows them to be
2009-10-23 07:30:00 +04:00
* re - used in ldb_wrap_connect ( ) */
2018-05-01 06:48:38 +03:00
ldb_ctx = samdb_connect ( db_context ,
event_ctx ,
2021-01-14 11:50:10 +03:00
lp_ctx ,
system_session ( lp_ctx ) ,
2018-05-01 06:48:38 +03:00
NULL ,
0 ) ;
if ( ldb_ctx = = NULL ) {
talloc_free ( db_context ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
2019-03-05 04:38:41 +03:00
2023-05-31 05:38:02 +03:00
ret = handle_inplace_db_upgrade_check_and_update_fl ( ldb_ctx ,
lp_ctx ) ;
2019-03-05 04:38:41 +03:00
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( db_context ) ;
return ret ;
}
2021-01-14 11:50:10 +03:00
pdb = privilege_connect ( db_context , lp_ctx ) ;
2018-05-01 06:48:38 +03:00
if ( pdb = = NULL ) {
talloc_free ( db_context ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
/* check the root DB object to see if it's marked as a backup */
samba_dsdb_dn = ldb_dn_new ( db_context , ldb_ctx , " @SAMBA_DSDB " ) ;
if ( ! samba_dsdb_dn ) {
talloc_free ( db_context ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
ret = dsdb_search_dn ( ldb_ctx , db_context , & res , samba_dsdb_dn , attrs ,
DSDB_FLAG_AS_SYSTEM ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( db_context ) ;
return ret ;
}
2009-08-07 11:19:39 +04:00
2018-05-01 06:48:38 +03:00
if ( res - > count > 0 ) {
msg = ldb_msg_find_attr_as_string ( res - > msgs [ 0 ] , " backupDate " ,
NULL ) ;
if ( msg ! = NULL ) {
* am_backup = true ;
}
}
return LDB_SUCCESS ;
}
2009-09-19 05:05:55 +04:00
2019-01-17 18:27:10 +03:00
/*
called from ' smbcontrol samba shutdown '
*/
static void samba_parent_shutdown ( struct imessaging_context * msg ,
void * private_data ,
uint32_t msg_type ,
struct server_id src ,
2019-09-18 19:19:37 +03:00
size_t num_fds ,
int * fds ,
2019-01-17 18:27:10 +03:00
DATA_BLOB * data )
{
struct server_state * state =
talloc_get_type_abort ( private_data ,
struct server_state ) ;
struct server_id_buf src_buf ;
struct server_id dst = imessaging_get_server_id ( msg ) ;
struct server_id_buf dst_buf ;
2019-09-18 19:19:37 +03:00
if ( num_fds ! = 0 ) {
DBG_WARNING ( " Received %zu fds, ignoring message \n " , num_fds ) ;
return ;
}
2019-01-17 18:27:10 +03:00
DBG_ERR ( " samba_shutdown of %s %s: from %s \n " ,
state - > binary_name ,
server_id_str_buf ( dst , & dst_buf ) ,
server_id_str_buf ( src , & src_buf ) ) ;
TALLOC_FREE ( state ) ;
exit ( 0 ) ;
}
2009-09-19 05:05:55 +04:00
/*
called when a fatal condition occurs in a child task
*/
2017-03-31 21:43:17 +03:00
static NTSTATUS samba_terminate ( struct irpc_message * msg ,
2009-09-19 05:05:55 +04:00
struct samba_terminate * r )
{
2017-03-31 22:23:56 +03:00
struct server_state * state = talloc_get_type ( msg - > private_data ,
struct server_state ) ;
DBG_ERR ( " samba_terminate of %s %d: %s \n " ,
state - > binary_name , ( int ) getpid ( ) , r - > in . reason ) ;
2017-04-03 21:04:31 +03:00
TALLOC_FREE ( state ) ;
2009-09-19 05:05:55 +04:00
exit ( 1 ) ;
}
/*
setup messaging for the top level samba ( parent ) task
*/
2017-03-31 22:23:56 +03:00
static NTSTATUS setup_parent_messaging ( struct server_state * state ,
2009-09-19 05:05:55 +04:00
struct loadparm_context * lp_ctx )
{
2011-05-03 04:40:33 +04:00
struct imessaging_context * msg ;
2009-09-19 05:05:55 +04:00
NTSTATUS status ;
2019-05-22 13:57:53 +03:00
if ( state = = NULL ) {
return NT_STATUS_UNSUCCESSFUL ;
}
2017-04-03 21:04:31 +03:00
msg = imessaging_init ( state - > event_ctx ,
2011-10-13 13:01:56 +04:00
lp_ctx ,
2019-01-28 18:29:51 +03:00
cluster_id ( getpid ( ) , SAMBA_PARENT_TASKID ) ,
2017-03-31 22:23:56 +03:00
state - > event_ctx ) ;
2009-09-19 05:05:55 +04:00
NT_STATUS_HAVE_NO_MEMORY ( msg ) ;
2012-08-07 09:50:46 +04:00
status = irpc_add_name ( msg , " samba " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2009-09-19 05:05:55 +04:00
2019-01-17 18:27:10 +03:00
status = imessaging_register ( msg , state , MSG_SHUTDOWN ,
samba_parent_shutdown ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2009-09-19 05:05:55 +04:00
status = IRPC_REGISTER ( msg , irpc , SAMBA_TERMINATE ,
2017-03-31 22:23:56 +03:00
samba_terminate , state ) ;
2019-01-17 18:27:10 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2009-09-19 05:05:55 +04:00
2019-01-17 18:27:10 +03:00
return NT_STATUS_OK ;
2009-09-19 05:05:55 +04:00
}
2010-03-29 13:20:25 +04:00
/*
show build info
*/
static void show_build ( void )
{
# define CONFIG_OPTION(n) { #n, dyn_ ## n }
struct {
const char * name ;
const char * value ;
} config_options [ ] = {
CONFIG_OPTION ( BINDIR ) ,
CONFIG_OPTION ( SBINDIR ) ,
CONFIG_OPTION ( CONFIGFILE ) ,
CONFIG_OPTION ( NCALRPCDIR ) ,
CONFIG_OPTION ( LOGFILEBASE ) ,
CONFIG_OPTION ( LMHOSTSFILE ) ,
CONFIG_OPTION ( DATADIR ) ,
CONFIG_OPTION ( MODULESDIR ) ,
CONFIG_OPTION ( LOCKDIR ) ,
2011-07-12 15:04:08 +04:00
CONFIG_OPTION ( STATEDIR ) ,
CONFIG_OPTION ( CACHEDIR ) ,
2010-03-29 13:20:25 +04:00
CONFIG_OPTION ( PIDDIR ) ,
CONFIG_OPTION ( PRIVATE_DIR ) ,
2011-02-07 05:13:44 +03:00
CONFIG_OPTION ( CODEPAGEDIR ) ,
2010-03-29 13:20:25 +04:00
CONFIG_OPTION ( SETUPDIR ) ,
CONFIG_OPTION ( WINBINDD_SOCKET_DIR ) ,
CONFIG_OPTION ( NTP_SIGND_SOCKET_DIR ) ,
{ NULL , NULL }
} ;
int i ;
2010-10-14 05:42:40 +04:00
printf ( " Samba version: %s \n " , SAMBA_VERSION_STRING ) ;
2010-04-21 09:35:55 +04:00
printf ( " Build environment: \n " ) ;
2010-03-29 13:20:25 +04:00
printf ( " Paths: \n " ) ;
for ( i = 0 ; config_options [ i ] . name ; i + + ) {
2017-03-31 21:43:17 +03:00
printf ( " %s: %s \n " ,
config_options [ i ] . name ,
config_options [ i ] . value ) ;
2010-03-29 13:20:25 +04:00
}
exit ( 0 ) ;
}
2009-09-19 05:05:55 +04:00
2016-09-09 08:12:11 +03:00
static int event_ctx_destructor ( struct tevent_context * event_ctx )
{
2017-04-03 20:58:24 +03:00
imessaging_dgm_unref_ev ( event_ctx ) ;
2016-09-09 08:12:11 +03:00
return 0 ;
}
2017-08-21 22:58:14 +03:00
# ifdef HAVE_PTHREAD
static int to_children_fd = - 1 ;
static void atfork_prepare ( void ) {
}
static void atfork_parent ( void ) {
}
static void atfork_child ( void ) {
if ( to_children_fd ! = - 1 ) {
close ( to_children_fd ) ;
to_children_fd = - 1 ;
}
}
# endif
2005-01-30 03:54:57 +03:00
/*
main server .
*/
2021-01-14 11:36:47 +03:00
static int binary_smbd_main ( TALLOC_CTX * mem_ctx ,
const char * binary_name ,
int argc ,
const char * argv [ ] )
2005-01-30 03:54:57 +03:00
{
2021-09-03 15:04:22 +03:00
struct samba_cmdline_daemon_cfg * cmdline_daemon_cfg = NULL ;
2018-05-01 06:48:38 +03:00
bool db_is_backup = false ;
2005-01-30 03:54:57 +03:00
int opt ;
2018-05-01 06:48:38 +03:00
int ret ;
2005-01-30 03:54:57 +03:00
poptContext pc ;
2008-06-20 13:03:12 +04:00
uint16_t stdin_event_flags ;
2005-01-30 03:54:57 +03:00
NTSTATUS status ;
2019-01-31 02:08:00 +03:00
const char * model = " prefork " ;
2005-06-12 04:17:23 +04:00
int max_runtime = 0 ;
2013-06-11 00:33:40 +04:00
struct stat st ;
2006-04-03 18:02:53 +04:00
enum {
2021-09-03 15:04:22 +03:00
OPT_PROCESS_MODEL = 1000 ,
2017-08-21 06:12:04 +03:00
OPT_SHOW_BUILD ,
2006-04-03 18:02:53 +04:00
} ;
2005-01-30 03:54:57 +03:00
struct poptOption long_options [ ] = {
POPT_AUTOHELP
2018-12-13 13:49:35 +03:00
{
. longName = " model " ,
. shortName = ' M ' ,
. argInfo = POPT_ARG_STRING ,
. val = OPT_PROCESS_MODEL ,
. descrip = " Select process model " ,
. argDescrip = " MODEL " ,
} ,
{
. longName = " maximum-runtime " ,
. argInfo = POPT_ARG_INT ,
. arg = & max_runtime ,
. descrip = " set maximum runtime of the server process, "
" till autotermination " ,
. argDescrip = " seconds "
} ,
{
. longName = " show-build " ,
. shortName = ' b ' ,
. argInfo = POPT_ARG_NONE ,
. val = OPT_SHOW_BUILD ,
. descrip = " show build info " ,
} ,
2005-06-13 12:12:39 +04:00
POPT_COMMON_SAMBA
2021-09-03 15:04:22 +03:00
POPT_COMMON_DAEMON
2005-01-30 03:54:57 +03:00
POPT_COMMON_VERSION
2018-12-13 13:49:35 +03:00
POPT_TABLEEND
2005-01-30 03:54:57 +03:00
} ;
2017-03-31 21:54:45 +03:00
struct server_state * state = NULL ;
2017-03-31 22:38:14 +03:00
struct tevent_signal * se = NULL ;
2020-11-26 16:21:58 +03:00
struct samba_tevent_trace_state * samba_tevent_trace_state = NULL ;
2021-01-14 11:50:10 +03:00
struct loadparm_context * lp_ctx = NULL ;
bool ok ;
2005-12-15 21:08:25 +03:00
2017-09-06 07:04:50 +03:00
setproctitle ( " root process " ) ;
2021-01-14 11:50:10 +03:00
ok = samba_cmdline_init ( mem_ctx ,
SAMBA_CMDLINE_CONFIG_SERVER ,
true /* require_smbconf */ ) ;
if ( ! ok ) {
DBG_ERR ( " Failed to init cmdline parser! \n " ) ;
TALLOC_FREE ( mem_ctx ) ;
exit ( 1 ) ;
}
2021-09-03 15:04:22 +03:00
cmdline_daemon_cfg = samba_cmdline_get_daemon_cfg ( ) ;
2021-01-14 11:50:10 +03:00
pc = samba_popt_get_context ( binary_name ,
argc ,
argv ,
long_options ,
0 ) ;
if ( pc = = NULL ) {
DBG_ERR ( " Failed to setup popt context! \n " ) ;
TALLOC_FREE ( mem_ctx ) ;
exit ( 1 ) ;
}
2006-04-03 18:02:53 +04:00
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
switch ( opt ) {
case OPT_PROCESS_MODEL :
model = poptGetOptArg ( pc ) ;
break ;
2010-03-29 13:20:25 +04:00
case OPT_SHOW_BUILD :
show_build ( ) ;
break ;
2007-08-22 16:21:40 +04:00
default :
2007-12-12 00:23:06 +03:00
fprintf ( stderr , " \n Invalid option %s: %s \n \n " ,
2007-08-22 16:21:40 +04:00
poptBadOption ( pc , 0 ) , poptStrerror ( opt ) ) ;
poptPrintUsage ( pc , stderr , 0 ) ;
2010-02-13 20:03:08 +03:00
return 1 ;
2006-04-03 18:02:53 +04:00
}
}
2007-08-22 16:21:40 +04:00
2021-09-03 15:04:22 +03:00
if ( cmdline_daemon_cfg - > daemon & & cmdline_daemon_cfg - > interactive ) {
2007-12-12 00:23:06 +03:00
fprintf ( stderr , " \n ERROR: "
2017-03-31 21:43:17 +03:00
" Option -i|--interactive is "
" not allowed together with -D|--daemon \n \n " ) ;
2007-08-22 16:21:40 +04:00
poptPrintUsage ( pc , stderr , 0 ) ;
2010-02-13 20:03:08 +03:00
return 1 ;
2021-09-03 15:04:22 +03:00
} else if ( ! cmdline_daemon_cfg - > interactive & &
cmdline_daemon_cfg - > fork ) {
2007-08-22 16:21:40 +04:00
/* default is --daemon */
2021-09-03 15:04:22 +03:00
cmdline_daemon_cfg - > daemon = true ;
2007-08-22 16:21:40 +04:00
}
2005-01-30 03:54:57 +03:00
poptFreeContext ( pc ) ;
2021-01-14 11:50:10 +03:00
lp_ctx = samba_cmdline_get_lp_ctx ( ) ;
2015-02-11 18:31:26 +03:00
talloc_enable_null_tracking ( ) ;
2005-01-30 03:54:57 +03:00
setup_signals ( ) ;
2003-08-13 05:53:07 +04:00
/* we want total control over the permissions on created files,
so set our umask to 0 */
umask ( 0 ) ;
2023-12-14 13:35:19 +03:00
DBG_STARTUP_NOTICE ( " %s version %s started. \n %s \n " ,
binary_name ,
SAMBA_VERSION_STRING ,
SAMBA_COPYRIGHT_STRING ) ;
2017-03-31 21:43:17 +03:00
if ( sizeof ( uint16_t ) < 2 | |
sizeof ( uint32_t ) < 4 | |
sizeof ( uint64_t ) < 8 ) {
DEBUG ( 0 , ( " ERROR: Samba is not configured correctly "
" for the word size on your machine \n " ) ) ;
DEBUGADD ( 0 , ( " sizeof(uint16_t) = %u, sizeof(uint32_t) %u, "
" sizeof(uint64_t) = %u \n " ,
( unsigned int ) sizeof ( uint16_t ) ,
( unsigned int ) sizeof ( uint32_t ) ,
( unsigned int ) sizeof ( uint64_t ) ) ) ;
2010-02-13 20:03:08 +03:00
return 1 ;
2003-08-13 05:53:07 +04:00
}
2004-07-14 01:04:56 +04:00
2021-09-03 15:04:22 +03:00
if ( cmdline_daemon_cfg - > daemon ) {
2017-09-11 02:39:39 +03:00
DBG_NOTICE ( " Becoming a daemon. \n " ) ;
2021-09-03 15:04:22 +03:00
become_daemon ( cmdline_daemon_cfg - > fork ,
cmdline_daemon_cfg - > no_process_group ,
false ) ;
} else if ( ! cmdline_daemon_cfg - > interactive ) {
2020-10-24 16:52:43 +03:00
daemon_status ( " samba " , " Starting process... " ) ;
2003-08-13 05:53:07 +04:00
}
2017-03-31 21:54:45 +03:00
/* Create the memory context to hang everything off. */
2021-01-14 11:36:47 +03:00
state = talloc_zero ( mem_ctx , struct server_state ) ;
2017-03-31 21:54:45 +03:00
if ( state = = NULL ) {
exit_daemon ( " Samba cannot create server state " , ENOMEM ) ;
2019-05-22 13:57:53 +03:00
/*
* return is never reached but is here to satisfy static
* checkers
*/
return 1 ;
2017-03-31 21:54:45 +03:00
} ;
state - > binary_name = binary_name ;
2021-01-14 11:50:10 +03:00
cleanup_tmp_files ( lp_ctx ) ;
2005-01-30 03:54:57 +03:00
2021-01-14 11:50:10 +03:00
if ( ! directory_exist ( lpcfg_lock_directory ( lp_ctx ) ) ) {
mkdir ( lpcfg_lock_directory ( lp_ctx ) , 0755 ) ;
2003-08-13 05:53:07 +04:00
}
2021-01-14 11:50:10 +03:00
if ( ! directory_exist ( lpcfg_pid_directory ( lp_ctx ) ) ) {
mkdir ( lpcfg_pid_directory ( lp_ctx ) , 0755 ) ;
2018-04-18 12:44:33 +03:00
}
2021-01-14 11:50:10 +03:00
pidfile_create ( lpcfg_pid_directory ( lp_ctx ) , binary_name ) ;
2005-01-30 03:54:57 +03:00
2021-01-14 11:50:10 +03:00
if ( lpcfg_server_role ( lp_ctx ) = = ROLE_ACTIVE_DIRECTORY_DC ) {
2017-04-03 21:16:02 +03:00
if ( ! open_schannel_session_store ( state ,
2021-01-14 11:50:10 +03:00
lp_ctx ) ) {
2017-04-03 21:16:02 +03:00
TALLOC_FREE ( state ) ;
2017-03-31 21:43:17 +03:00
exit_daemon ( " Samba cannot open schannel store "
" for secured NETLOGON operations. " , EACCES ) ;
2019-05-22 13:57:53 +03:00
/*
* return is never reached but is here to satisfy static
* checkers
*/
return 1 ;
2010-06-23 04:33:15 +04:00
}
}
2013-07-10 16:48:18 +04:00
/* make sure we won't go through nss_winbind */
if ( ! winbind_off ( ) ) {
2017-04-03 21:16:02 +03:00
TALLOC_FREE ( state ) ;
2023-08-03 15:42:10 +03:00
exit_daemon ( " Samba failed to disable recursive "
2017-03-31 21:43:17 +03:00
" winbindd calls. " , EACCES ) ;
2019-05-22 13:57:53 +03:00
/*
* return is never reached but is here to satisfy static
* checkers
*/
return 1 ;
2013-07-10 16:48:18 +04:00
}
2011-06-06 08:58:28 +04:00
gensec_init ( ) ; /* FIXME: */
2004-04-19 15:21:50 +04:00
2021-01-14 11:50:10 +03:00
process_model_init ( lp_ctx ) ;
2005-12-27 00:58:31 +03:00
2021-08-27 14:06:00 +03:00
samba_service_init ( ) ;
2017-03-31 21:43:17 +03:00
2005-01-30 03:54:57 +03:00
/* the event context is the top level structure in smbd. Everything else
should hang off that */
2017-04-03 21:04:31 +03:00
state - > event_ctx = s4_event_context_init ( state ) ;
2005-01-14 04:32:56 +03:00
2017-03-31 21:54:45 +03:00
if ( state - > event_ctx = = NULL ) {
2017-04-03 21:16:02 +03:00
TALLOC_FREE ( state ) ;
2014-03-26 14:30:30 +04:00
exit_daemon ( " Initializing event context failed " , EACCES ) ;
2019-05-22 13:57:53 +03:00
/*
* return is never reached but is here to satisfy static
* checkers
*/
return 1 ;
2007-10-06 01:51:47 +04:00
}
2017-03-31 21:54:45 +03:00
talloc_set_destructor ( state - > event_ctx , event_ctx_destructor ) ;
2016-09-09 08:12:11 +03:00
2020-11-26 16:21:58 +03:00
samba_tevent_trace_state = create_samba_tevent_trace_state ( state ) ;
if ( samba_tevent_trace_state = = NULL ) {
exit_daemon ( " Samba failed to setup tevent tracing state " ,
ENOTTY ) ;
/*
* return is never reached but is here to satisfy static
* checkers
*/
return 1 ;
}
tevent_set_trace_callback ( state - > event_ctx ,
samba_tevent_trace_callback ,
samba_tevent_trace_state ) ;
2021-09-03 15:04:22 +03:00
if ( cmdline_daemon_cfg - > interactive ) {
2008-06-20 13:03:12 +04:00
/* terminate when stdin goes away */
2009-01-03 17:24:31 +03:00
stdin_event_flags = TEVENT_FD_READ ;
2008-06-20 13:03:12 +04:00
} else {
/* stay alive forever */
stdin_event_flags = 0 ;
2005-06-07 12:33:17 +04:00
}
2005-05-17 10:20:54 +04:00
2018-11-21 13:37:26 +03:00
# ifdef HAVE_SETPGID
2017-08-21 06:12:04 +03:00
/*
* If we ' re interactive we want to set our own process group for
* signal management , unless - - no - process - group specified .
*/
2021-09-03 15:04:22 +03:00
if ( cmdline_daemon_cfg - > interactive & &
! cmdline_daemon_cfg - > no_process_group )
{
2017-08-21 06:12:04 +03:00
setpgid ( ( pid_t ) 0 , ( pid_t ) 0 ) ;
2021-09-03 15:04:22 +03:00
}
2017-08-21 06:12:04 +03:00
# endif
2008-06-20 13:03:12 +04:00
/* catch EOF on stdin */
# ifdef SIGTTIN
signal ( SIGTTIN , SIG_IGN ) ;
# endif
2013-06-11 00:33:40 +04:00
if ( fstat ( 0 , & st ) ! = 0 ) {
2017-04-03 21:16:02 +03:00
TALLOC_FREE ( state ) ;
2017-03-31 21:43:17 +03:00
exit_daemon ( " Samba failed to set standard input handler " ,
ENOTTY ) ;
2019-05-22 13:57:53 +03:00
/*
* return is never reached but is here to satisfy static
* checkers
*/
return 1 ;
2013-06-11 00:33:40 +04:00
}
if ( S_ISFIFO ( st . st_mode ) | | S_ISSOCK ( st . st_mode ) ) {
2017-03-31 22:29:03 +03:00
struct tevent_fd * fde = tevent_add_fd ( state - > event_ctx ,
2017-03-31 21:54:45 +03:00
state - > event_ctx ,
2013-06-11 00:33:40 +04:00
0 ,
stdin_event_flags ,
server_stdin_handler ,
2017-03-31 21:59:13 +03:00
state ) ;
2017-03-31 22:29:03 +03:00
if ( fde = = NULL ) {
2017-04-03 21:16:02 +03:00
TALLOC_FREE ( state ) ;
2017-03-31 22:29:03 +03:00
exit_daemon ( " Initializing stdin failed " , ENOMEM ) ;
2019-05-22 13:57:53 +03:00
/*
* return is never reached but is here to
* satisfy static checkers
*/
return 1 ;
2017-03-31 22:29:03 +03:00
}
2013-06-11 00:33:40 +04:00
}
2005-06-12 04:17:23 +04:00
if ( max_runtime ) {
2017-03-31 22:29:03 +03:00
struct tevent_timer * te ;
2023-09-18 14:45:54 +03:00
DBG_NOTICE ( " %s PID %d was called with maxruntime %d - "
2017-03-31 21:43:17 +03:00
" current ts %llu \n " ,
binary_name , ( int ) getpid ( ) ,
2017-09-11 02:39:39 +03:00
max_runtime , ( unsigned long long ) time ( NULL ) ) ;
2017-03-31 22:29:03 +03:00
te = tevent_add_timer ( state - > event_ctx , state - > event_ctx ,
2009-01-03 17:24:31 +03:00
timeval_current_ofs ( max_runtime , 0 ) ,
max_runtime_handler ,
2017-03-31 22:00:29 +03:00
state ) ;
2017-03-31 22:29:03 +03:00
if ( te = = NULL ) {
2017-04-03 21:16:02 +03:00
TALLOC_FREE ( state ) ;
2017-03-31 22:29:03 +03:00
exit_daemon ( " Maxruntime handler failed " , ENOMEM ) ;
2019-05-22 13:57:53 +03:00
/*
* return is never reached but is here to
* satisfy static checkers
*/
return 1 ;
2021-03-07 12:11:09 +03:00
}
2005-06-12 04:17:23 +04:00
}
2017-03-31 22:38:14 +03:00
se = tevent_add_signal ( state - > event_ctx ,
state - > event_ctx ,
SIGTERM ,
0 ,
sigterm_signal_handler ,
state ) ;
if ( se = = NULL ) {
2017-04-03 21:16:02 +03:00
TALLOC_FREE ( state ) ;
2017-03-31 22:38:14 +03:00
exit_daemon ( " Initialize SIGTERM handler failed " , ENOMEM ) ;
2019-05-22 13:57:53 +03:00
/*
* return is never reached but is here to satisfy static
* checkers
*/
return 1 ;
2017-03-31 22:38:14 +03:00
}
2020-11-20 17:21:03 +03:00
se = tevent_add_signal ( state - > event_ctx ,
state - > event_ctx ,
SIGHUP ,
0 ,
sighup_signal_handler ,
state ) ;
if ( se = = NULL ) {
TALLOC_FREE ( state ) ;
exit_daemon ( " Initialize SIGHUP handler failed " , ENOMEM ) ;
/*
* return is never reached but is here to satisfy static
* checkers
*/
return 1 ;
}
2021-01-14 11:50:10 +03:00
if ( lpcfg_server_role ( lp_ctx ) ! = ROLE_ACTIVE_DIRECTORY_DC
& & ! lpcfg_parm_bool ( lp_ctx , NULL ,
2017-03-31 21:43:17 +03:00
" server role check " , " inhibit " , false )
2021-01-14 11:50:10 +03:00
& & ! str_list_check_ci ( lpcfg_server_services ( lp_ctx ) , " smb " )
& & ! str_list_check_ci ( lpcfg_dcerpc_endpoint_servers ( lp_ctx ) ,
2017-03-31 21:43:17 +03:00
" remote " )
2021-01-14 11:50:10 +03:00
& & ! str_list_check_ci ( lpcfg_dcerpc_endpoint_servers ( lp_ctx ) ,
2017-03-31 21:43:17 +03:00
" mapiproxy " ) ) {
DEBUG ( 0 , ( " At this time the 'samba' binary should only be used "
" for either: \n " ) ) ;
DEBUGADD ( 0 , ( " 'server role = active directory domain "
2022-08-17 01:12:28 +03:00
" controller' or the rpc proxy "
2017-03-31 21:43:17 +03:00
" with 'dcerpc endpoint servers = remote' \n " ) ) ;
DEBUGADD ( 0 , ( " You should start smbd/nmbd/winbindd instead for "
" domain member and standalone file server tasks \n " ) ) ;
exit_daemon ( " Samba detected misconfigured 'server role' "
" and exited. Check logs for details " , EINVAL ) ;
2012-08-22 15:01:16 +04:00
} ;
2018-05-01 06:48:38 +03:00
ret = prime_ldb_databases ( state - > event_ctx , & db_is_backup ) ;
if ( ret ! = LDB_SUCCESS ) {
TALLOC_FREE ( state ) ;
exit_daemon ( " Samba failed to prime database " , EINVAL ) ;
2019-05-22 13:57:53 +03:00
/*
* return is never reached but is here to satisfy static
* checkers
*/
return 1 ;
2018-05-01 06:48:38 +03:00
}
if ( db_is_backup ) {
TALLOC_FREE ( state ) ;
exit_daemon ( " Database is a backup. Please run samba-tool domain "
" backup restore " , EINVAL ) ;
2019-05-22 13:57:53 +03:00
/*
* return is never reached but is here to satisfy static
* checkers
*/
return 1 ;
2018-05-01 06:48:38 +03:00
}
2009-08-07 11:19:39 +04:00
2021-01-14 11:50:10 +03:00
status = setup_parent_messaging ( state , lp_ctx ) ;
2009-09-19 05:05:55 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2017-04-03 21:16:02 +03:00
TALLOC_FREE ( state ) ;
2017-03-31 21:43:17 +03:00
exit_daemon ( " Samba failed to setup parent messaging " ,
NT_STATUS_V ( status ) ) ;
2019-05-22 13:57:53 +03:00
/*
* return is never reached but is here to satisfy static
* checkers
*/
return 1 ;
2009-09-19 05:05:55 +04:00
}
2023-09-18 14:45:54 +03:00
DBG_NOTICE ( " %s: using '%s' process model \n " , binary_name , model ) ;
2009-09-21 00:17:35 +04:00
2017-08-21 22:58:14 +03:00
{
int child_pipe [ 2 ] ;
int rc ;
bool start_services = false ;
rc = pipe ( child_pipe ) ;
if ( rc < 0 ) {
TALLOC_FREE ( state ) ;
exit_daemon ( " Samba failed to open process control pipe " ,
errno ) ;
2019-05-22 13:57:53 +03:00
/*
* return is never reached but is here to satisfy static
* checkers
*/
return 1 ;
2017-08-21 22:58:14 +03:00
}
smb_set_close_on_exec ( child_pipe [ 0 ] ) ;
smb_set_close_on_exec ( child_pipe [ 1 ] ) ;
# ifdef HAVE_PTHREAD
to_children_fd = child_pipe [ 1 ] ;
pthread_atfork ( atfork_prepare , atfork_parent ,
atfork_child ) ;
start_services = true ;
# else
pid_t pid ;
struct tfork * t = NULL ;
t = tfork_create ( ) ;
if ( t = = NULL ) {
exit_daemon (
" Samba unable to fork master process " ,
0 ) ;
}
pid = tfork_child_pid ( t ) ;
if ( pid = = 0 ) {
start_services = false ;
} else {
/* In the child process */
start_services = true ;
close ( child_pipe [ 1 ] ) ;
}
# endif
if ( start_services ) {
status = server_service_startup (
2021-01-14 11:50:10 +03:00
state - > event_ctx , lp_ctx , model ,
lpcfg_server_services ( lp_ctx ) ,
2017-08-21 22:58:14 +03:00
child_pipe [ 0 ] ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( state ) ;
exit_daemon ( " Samba failed to start services " ,
NT_STATUS_V ( status ) ) ;
2019-05-22 13:57:53 +03:00
/*
* return is never reached but is here to
* satisfy static checkers
*/
return 1 ;
2017-08-21 22:58:14 +03:00
}
}
2004-07-14 01:04:56 +04:00
}
2003-08-13 05:53:07 +04:00
2021-09-03 15:04:22 +03:00
if ( ! cmdline_daemon_cfg - > interactive ) {
2014-03-25 14:53:04 +04:00
daemon_ready ( " samba " ) ;
}
2005-01-30 03:54:57 +03:00
/* wait for events - this is where smbd sits for most of its
life */
2017-03-31 21:54:45 +03:00
tevent_loop_wait ( state - > event_ctx ) ;
2005-01-14 04:32:56 +03:00
2017-03-31 21:54:45 +03:00
/* as everything hangs off this state->event context, freeing state
will initiate a clean shutdown of all services */
TALLOC_FREE ( state ) ;
2005-01-14 04:32:56 +03:00
return 0 ;
2004-07-14 01:04:56 +04:00
}
2009-09-21 00:17:35 +04:00
int main ( int argc , const char * argv [ ] )
2004-07-14 01:04:56 +04:00
{
2021-01-14 11:36:47 +03:00
TALLOC_CTX * mem_ctx = NULL ;
int rc ;
mem_ctx = talloc_init ( " samba/server.c#main " ) ;
if ( mem_ctx = = NULL ) {
exit ( ENOMEM ) ;
}
2017-09-14 00:36:21 +03:00
setproctitle_init ( argc , discard_const ( argv ) , environ ) ;
2021-01-14 11:36:47 +03:00
rc = binary_smbd_main ( mem_ctx , " samba " , argc , argv ) ;
TALLOC_FREE ( mem_ctx ) ;
return rc ;
2003-08-13 05:53:07 +04:00
}