1996-05-04 11:50:46 +04:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
Main SMB server routines
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
1996-05-04 11:50:46 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
# include "trans2.h"
pstring servicesf = CONFIGFILE ;
extern pstring debugf ;
1998-04-25 05:12:08 +04:00
extern fstring global_myworkgroup ;
1998-04-30 02:27:26 +04:00
extern pstring global_myname ;
1996-05-04 11:50:46 +04:00
1996-12-10 21:00:22 +03:00
int am_parent = 1 ;
1996-05-04 11:50:46 +04:00
/* the last message the was processed */
int last_message = - 1 ;
/* a useful macro to debug the last message processed */
# define LAST_MESSAGE() smb_fn_name(last_message)
extern pstring scope ;
extern int DEBUGLEVEL ;
extern pstring user_socket_options ;
1998-07-29 07:08:05 +04:00
# ifdef WITH_DFS
1998-03-04 04:50:47 +03:00
extern int dcelogin_atmost_once ;
1998-07-29 07:08:05 +04:00
# endif /* WITH_DFS */
1998-03-04 04:50:47 +03:00
1997-09-30 06:38:19 +04:00
1996-05-04 11:50:46 +04:00
extern fstring remote_machine ;
1997-10-25 14:58:18 +04:00
extern pstring OriginalDir ;
1996-05-04 11:50:46 +04:00
extern pstring myhostname ;
1996-12-10 21:00:22 +03:00
/****************************************************************************
when exiting , take the whole family
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-09-05 09:07:05 +04:00
static void * dflt_sig ( void )
1996-12-10 21:00:22 +03:00
{
1998-08-17 18:11:44 +04:00
exit_server ( " caught signal " ) ;
return NULL ;
1996-12-10 21:00:22 +03:00
}
1998-08-17 18:11:44 +04:00
1996-12-10 21:00:22 +03:00
/****************************************************************************
Send a SIGTERM to our process group .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-09-05 09:07:05 +04:00
static void killkids ( void )
1996-12-10 21:00:22 +03:00
{
1998-08-17 18:11:44 +04:00
if ( am_parent ) kill ( 0 , SIGTERM ) ;
1996-12-10 21:00:22 +03:00
}
1996-05-04 11:50:46 +04:00
1997-09-23 23:19:06 +04:00
1997-09-30 06:38:19 +04:00
/****************************************************************************
1998-08-17 17:11:34 +04:00
open the socket communication
1997-09-30 06:38:19 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-17 18:11:44 +04:00
static BOOL open_sockets_inetd ( void )
1997-09-30 06:38:19 +04:00
{
1998-08-17 18:11:44 +04:00
extern int Client ;
/* Started from inetd. fd 0 is the socket. */
/* We will abort gracefully when the client or remote system
goes away */
Client = dup ( 0 ) ;
/* close our standard file descriptors */
close_low_fds ( ) ;
set_socket_options ( Client , " SO_KEEPALIVE " ) ;
set_socket_options ( Client , user_socket_options ) ;
return True ;
}
1997-10-02 03:32:22 +04:00
1997-09-25 04:25:44 +04:00
1998-08-17 18:11:44 +04:00
/****************************************************************************
open the socket communication
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL open_sockets ( BOOL is_daemon , int port )
{
extern int Client ;
int num_interfaces = iface_count ( ) ;
int fd_listenset [ FD_SETSIZE ] ;
fd_set listen_set ;
int s ;
int i ;
if ( ! is_daemon ) {
return open_sockets_inetd ( ) ;
}
1998-08-17 17:11:34 +04:00
# ifdef HAVE_ATEXIT
1998-08-17 18:11:44 +04:00
{
static int atexit_set ;
if ( atexit_set = = 0 ) {
atexit_set = 1 ;
atexit ( killkids ) ;
}
}
1998-08-17 17:11:34 +04:00
# endif
1997-10-02 07:26:07 +04:00
1998-08-17 18:11:44 +04:00
/* Stop zombies */
CatchChild ( ) ;
FD_ZERO ( & listen_set ) ;
if ( lp_interfaces ( ) & & lp_bind_interfaces_only ( ) ) {
/* We have been given an interfaces line, and been
told to only bind to those interfaces . Create a
socket per interface and bind to only these .
*/
if ( num_interfaces > FD_SETSIZE ) {
DEBUG ( 0 , ( " open_sockets: Too many interfaces specified to bind to. Number was %d \
max can be % d \ n " ,
num_interfaces , FD_SETSIZE ) ) ;
return False ;
}
/* Now open a listen socket for each of the
interfaces . */
for ( i = 0 ; i < num_interfaces ; i + + ) {
struct in_addr * ifip = iface_n_ip ( i ) ;
if ( ifip = = NULL ) {
DEBUG ( 0 , ( " open_sockets: interface %d has NULL IP address ! \n " , i ) ) ;
continue ;
}
s = fd_listenset [ i ] = open_socket_in ( SOCK_STREAM , port , 0 , ifip - > s_addr ) ;
if ( s = = - 1 )
return False ;
/* ready to listen */
if ( listen ( s , 5 ) = = - 1 ) {
DEBUG ( 0 , ( " listen: %s \n " , strerror ( errno ) ) ) ;
close ( s ) ;
return False ;
}
FD_SET ( s , & listen_set ) ;
}
} else {
/* Just bind to 0.0.0.0 - accept connections
from anywhere . */
num_interfaces = 1 ;
/* open an incoming socket */
s = open_socket_in ( SOCK_STREAM , port , 0 ,
interpret_addr ( lp_socket_address ( ) ) ) ;
if ( s = = - 1 )
return ( False ) ;
/* ready to listen */
if ( listen ( s , 5 ) = = - 1 ) {
DEBUG ( 0 , ( " open_sockets: listen: %s \n " ,
strerror ( errno ) ) ) ;
close ( s ) ;
return False ;
}
fd_listenset [ 0 ] = s ;
FD_SET ( s , & listen_set ) ;
}
/* now accept incoming connections - forking a new process
for each incoming connection */
DEBUG ( 2 , ( " waiting for a connection \n " ) ) ;
while ( 1 ) {
fd_set lfds ;
int num ;
memcpy ( ( char * ) & lfds , ( char * ) & listen_set ,
sizeof ( listen_set ) ) ;
1998-08-29 01:46:29 +04:00
num = sys_select ( 256 , & lfds , NULL ) ;
1998-08-17 18:11:44 +04:00
if ( num = = - 1 & & errno = = EINTR )
continue ;
/* Find the sockets that are read-ready -
accept on these . */
for ( ; num > 0 ; num - - ) {
struct sockaddr addr ;
int in_addrlen = sizeof ( addr ) ;
s = - 1 ;
for ( i = 0 ; i < num_interfaces ; i + + ) {
if ( FD_ISSET ( fd_listenset [ i ] , & lfds ) ) {
s = fd_listenset [ i ] ;
/* Clear this so we don't look
at it again . */
FD_CLR ( fd_listenset [ i ] , & lfds ) ;
break ;
}
}
Client = accept ( s , & addr , & in_addrlen ) ;
if ( Client = = - 1 & & errno = = EINTR )
continue ;
if ( Client = = - 1 ) {
DEBUG ( 0 , ( " open_sockets: accept: %s \n " ,
strerror ( errno ) ) ) ;
continue ;
}
if ( Client ! = - 1 & & fork ( ) = = 0 ) {
/* Child code ... */
/* close the listening socket(s) */
for ( i = 0 ; i < num_interfaces ; i + + )
close ( fd_listenset [ i ] ) ;
/* close our standard file
descriptors */
close_low_fds ( ) ;
am_parent = 0 ;
set_socket_options ( Client , " SO_KEEPALIVE " ) ;
set_socket_options ( Client , user_socket_options ) ;
/* Reset global variables in util.c so
that client substitutions will be
done correctly in the process . */
reset_globals_after_fork ( ) ;
1998-09-26 03:40:49 +04:00
/*
* Ensure this child has kernel oplock
* capabilities , but not it ' s children .
*/
set_process_capability ( KERNEL_OPLOCK_CAPABILITY , True ) ;
set_inherited_process_capability ( KERNEL_OPLOCK_CAPABILITY , False ) ;
1998-08-17 18:11:44 +04:00
return True ;
}
/* The parent doesn't need this socket */
close ( Client ) ;
/* Force parent to check log size after
* spawning child . Fix from
* klausr @ ITAP . Physik . Uni - Stuttgart . De . The
* parent smbd will log to logserver . smb . It
* writes only two messages for each child
* started / finished . But each child writes ,
* say , 50 messages also in logserver . smb ,
* begining with the debug_count of the
* parent , before the child opens its own log
* file logserver . client . In a worst case
* scenario the size of logserver . smb would be
* checked after about 50 * 50 = 2500 messages
* ( ca . 100 kb ) .
* */
force_check_log_size ( ) ;
1998-08-17 17:11:34 +04:00
1998-08-17 18:11:44 +04:00
} /* end for num */
} /* end while 1 */
1998-08-28 00:38:53 +04:00
/* NOTREACHED return True; */
1997-11-19 02:30:49 +03:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
reload the services file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL reload_services ( BOOL test )
{
1998-08-14 21:38:29 +04:00
BOOL ret ;
if ( lp_loaded ( ) ) {
pstring fname ;
pstrcpy ( fname , lp_configfile ( ) ) ;
1998-08-17 17:11:34 +04:00
if ( file_exist ( fname , NULL ) & & ! strcsequal ( fname , servicesf ) ) {
pstrcpy ( servicesf , fname ) ;
test = False ;
1998-08-14 21:38:29 +04:00
}
}
1996-05-04 11:50:46 +04:00
1998-08-17 17:11:34 +04:00
reopen_logs ( ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 17:11:34 +04:00
if ( test & & ! lp_file_list_changed ( ) )
return ( True ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 17:11:34 +04:00
lp_killunused ( conn_snum_used ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 17:11:34 +04:00
ret = lp_load ( servicesf , False , False , True ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 17:11:34 +04:00
load_printers ( ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 17:11:34 +04:00
/* perhaps the config filename is now set */
if ( ! test )
reload_services ( True ) ;
1997-10-08 04:21:39 +04:00
1998-08-17 17:11:34 +04:00
reopen_logs ( ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 17:11:34 +04:00
load_interfaces ( ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
{
extern int Client ;
1998-08-17 17:11:34 +04:00
if ( Client ! = - 1 ) {
set_socket_options ( Client , " SO_KEEPALIVE " ) ;
set_socket_options ( Client , user_socket_options ) ;
}
1998-08-14 21:38:29 +04:00
}
1998-01-31 17:31:08 +03:00
1998-08-17 17:11:34 +04:00
reset_mangled_cache ( ) ;
1998-01-31 17:31:08 +03:00
1998-08-17 17:11:34 +04:00
/* this forces service parameters to be flushed */
become_service ( NULL , True ) ;
1998-01-31 17:31:08 +03:00
1998-08-17 17:11:34 +04:00
return ( ret ) ;
1998-01-31 17:31:08 +03:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
1998-08-17 17:11:34 +04:00
this prevents zombie child processes
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-17 17:11:34 +04:00
BOOL reload_after_sighup = False ;
1996-05-04 11:50:46 +04:00
1998-08-17 17:11:34 +04:00
static void sig_hup ( int sig )
{
1998-08-17 18:11:44 +04:00
BlockSignals ( True , SIGHUP ) ;
DEBUG ( 0 , ( " Got SIGHUP \n " ) ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
/*
* Fix from < branko . cibej @ hermes . si > here .
* We used to reload in the signal handler - this
* is a * BIG * no - no .
*/
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
reload_after_sighup = True ;
BlockSignals ( False , SIGHUP ) ;
1996-05-04 11:50:46 +04:00
}
# if DUMP_CORE
/*******************************************************************
prepare to dump a core file - carefully !
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL dump_core ( void )
{
1998-08-17 18:11:44 +04:00
char * p ;
pstring dname ;
pstrcpy ( dname , debugf ) ;
if ( ( p = strrchr ( dname , ' / ' ) ) ) * p = 0 ;
pstrcat ( dname , " /corefiles " ) ;
mkdir ( dname , 0700 ) ;
sys_chown ( dname , getuid ( ) , getgid ( ) ) ;
chmod ( dname , 0700 ) ;
if ( chdir ( dname ) ) return ( False ) ;
umask ( ~ ( 0700 ) ) ;
1996-05-04 11:50:46 +04:00
1998-07-29 07:08:05 +04:00
# ifdef HAVE_GETRLIMIT
1996-05-04 11:50:46 +04:00
# ifdef RLIMIT_CORE
1998-08-17 18:11:44 +04:00
{
struct rlimit rlp ;
getrlimit ( RLIMIT_CORE , & rlp ) ;
rlp . rlim_cur = MAX ( 4 * 1024 * 1024 , rlp . rlim_cur ) ;
setrlimit ( RLIMIT_CORE , & rlp ) ;
getrlimit ( RLIMIT_CORE , & rlp ) ;
DEBUG ( 3 , ( " Core limits now %d %d \n " ,
( int ) rlp . rlim_cur , ( int ) rlp . rlim_max ) ) ;
}
1996-05-04 11:50:46 +04:00
# endif
# endif
1998-08-17 18:11:44 +04:00
DEBUG ( 0 , ( " Dumping core in %s \n " , dname ) ) ;
abort ( ) ;
return ( True ) ;
1996-05-04 11:50:46 +04:00
}
# endif
1998-08-17 18:11:44 +04:00
1996-05-04 11:50:46 +04:00
/****************************************************************************
exit the server
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void exit_server ( char * reason )
{
1998-08-17 18:11:44 +04:00
static int firsttime = 1 ;
extern char * last_inbuf ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
if ( ! firsttime ) exit ( 0 ) ;
firsttime = 0 ;
1998-08-17 10:13:32 +04:00
1998-08-17 18:11:44 +04:00
unbecome_user ( ) ;
DEBUG ( 2 , ( " Closing connections \n " ) ) ;
conn_close_all ( ) ;
1998-08-17 10:13:32 +04:00
1998-07-29 07:08:05 +04:00
# ifdef WITH_DFS
1998-08-17 18:11:44 +04:00
if ( dcelogin_atmost_once ) {
dfs_unlogin ( ) ;
}
1996-05-04 11:50:46 +04:00
# endif
1998-08-17 18:11:44 +04:00
if ( ! reason ) {
int oldlevel = DEBUGLEVEL ;
DEBUGLEVEL = 10 ;
DEBUG ( 0 , ( " Last message was %s \n " , smb_fn_name ( last_message ) ) ) ;
if ( last_inbuf )
show_msg ( last_inbuf ) ;
DEBUGLEVEL = oldlevel ;
DEBUG ( 0 , ( " =============================================================== \n " ) ) ;
1996-05-04 11:50:46 +04:00
# if DUMP_CORE
1998-08-17 18:11:44 +04:00
if ( dump_core ( ) ) return ;
1996-05-04 11:50:46 +04:00
# endif
1998-08-17 18:11:44 +04:00
}
1997-01-09 21:02:17 +03:00
1998-08-17 18:11:44 +04:00
locking_end ( ) ;
1997-01-09 21:02:17 +03:00
1998-08-17 18:11:44 +04:00
DEBUG ( 3 , ( " Server exit (%s) \n " , ( reason ? reason : " " ) ) ) ;
exit ( 0 ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
initialise connect , service and file structs
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_structs ( void )
{
1998-08-17 18:11:44 +04:00
get_myname ( myhostname , NULL ) ;
/*
* Set the machine NETBIOS name if not already
* set from the config file .
*/
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
if ( ! * global_myname ) {
char * p ;
fstrcpy ( global_myname , myhostname ) ;
p = strchr ( global_myname , ' . ' ) ;
if ( p )
* p = 0 ;
}
1998-04-30 02:27:26 +04:00
1998-08-17 18:11:44 +04:00
strupper ( global_myname ) ;
1998-04-30 02:27:26 +04:00
1998-08-17 18:11:44 +04:00
conn_init ( ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
file_init ( ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
/* for RPC pipes */
init_rpc_pipe_hnd ( ) ;
1997-10-30 20:08:42 +03:00
1998-08-17 18:11:44 +04:00
/* for LSA handles */
init_lsa_policy_hnd ( ) ;
following a cvs error, i am rewriting this monster-commit. with bad grace.
Modified Files:
---------------
Makefile:
adding extra files
ipc.c :
send_trans_reply() - alignment issue. this makes the alignment
the same as that in NT. this should be looked at by people who
understand the SMB stuff better than i.
api_fd_commands[] - added samr and wkssvc pipes.
loadparm.c :
lp_domain_controller() changed to mean "samba is a domain controller".
it's a "yes/no" parameter, now. no, it isn't used _anywhere_.
namedbwork.c nameelect.c :
if "domain controller = yes" then add SV_TYPE_DOMAIN_CTRL to the
host _and_ workgroup announcements. yes, you must do both: nt does.
namelogon.c :
important NETLOGON bug in SAMLOGON request parsing, which may be
the source of some people's problems with logging on to the Samba PDC.
password.c :
get_smbpwnam() renamed to get_smbpwd_entry().
pipes.c :
added samr and wkssvc pipes.
proto.h :
usual. can we actually _remove_ proto.h from the cvs tree, and
have it as one of the Makefile dependencies, or something?
reply.c :
get_smbpwnam() renamed to get_smbpwd_entry() - also changed response
error code when logging in from a WORKSTATION$ account. yes, paul
is right: we need to know when to return the right error code, and why.
server.c :
added call to reset_chain_pnum().
#ifdef NTDOMAIN added call to init_lsa_policy_hnd() #endif. jeremy,
you'd be proud: i did a compile without NTDOMAIN, and caught a link
error for this function.
smb.h :
defines and structures for samr and wkssvc pipes.
smbpass.c :
modified get_smbpwnam() to get_smbpwd_entry() and it now takes
two arguments. one for the name; if this is null, it looks up
by smb_userid instead.
oh, by the way, smb_userids are actually domain relative ids
(RIDs). concatenate a RID with the domain SID, and you have
an internet globally unique way of identifying a user.
we're using RIDs in the wrong way....
added mod_smbpwnam() function. this was based on code in smbpasswd.c
rpc_pipes/lsaparse.c :
added enum trusted domain parsing. this is incomplete: i need
a packet trace to write it properly.
rpc_pipes/pipe_hnd.c :
added reset_chain_pnum() function.
rpc_pipes/pipenetlog.c :
get_smbpwnam() function renamed to get_smbpwd_entry().
arcfour() issues.
removed capability of get_md4pw() function to automatically add
workstation accounts. this should either be done using
smbpasswd -add MACHINE$, or by using \PIPE\samr.
rpc_pipes/pipe_util.c :
create_pol_hnd() - creates a unique LSA Policy Handle. overkill
function: uses a 64 bit sequence number; current unix time and
the smbd pid.
rpc_pipes/smbparse.c :
arcfour() issues.
smb_io_unistr2() should advance by uni_str_len not uni_max_len.
smb_io_smb_hdr_rb() - request bind uses uint16 for the context
id, and uint8 for the num_syntaxes. oops, i put these both as
uint32s.
Added Files:
------------
rpc_pipes/lsa_hnd.c :
on the samr pipe, allocate and associate an LSA Policy Handle
with a SID. you receive queries with the LSA Policy Handle,
and have to turn this back into a SID in order to answer the
query...
rpc_pipes/pipesamr.c rpc_pipes/samrparse.c
\PIPE\samr processing. samr i presume is the SAM Replication pipe.
rpc_pipes/pipewkssvc.c rpc_pipes/wksparse.c
\PIPE\wkssvc processing. the Workstation Service pipe?
holy cow.
(This used to be commit 1bd084b3e690eb26a1006d616075e53d711ecd2f)
1997-11-07 02:03:58 +03:00
1998-08-17 18:11:44 +04:00
init_dptrs ( ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
usage on the program
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-06-04 10:42:03 +04:00
static void usage ( char * pname )
1996-05-04 11:50:46 +04:00
{
1998-08-17 18:11:44 +04:00
DEBUG ( 0 , ( " Incorrect program usage - are you sure the command line is correct? \n " ) ) ;
1998-08-21 21:21:55 +04:00
printf ( " Usage: %s [-D] [-p port] [-d debuglevel] " , pname ) ;
printf ( " [-l log basename] [-s services file] \n " ) ;
1998-08-17 18:11:44 +04:00
printf ( " Version %s \n " , VERSION ) ;
printf ( " \t -D become a daemon \n " ) ;
printf ( " \t -p port listen on the specified port \n " ) ;
printf ( " \t -d debuglevel set the debuglevel \n " ) ;
printf ( " \t -l log basename. Basename for log/debug files \n " ) ;
printf ( " \t -s services file. Filename of services file \n " ) ;
printf ( " \t -P passive only \n " ) ;
1998-08-21 21:21:55 +04:00
printf ( " \t -a append to log file (default) \n " ) ;
printf ( " \t -o overwrite log file, don't append \n " ) ;
1998-10-28 20:51:49 +03:00
printf ( " \t -i scope NetBIOS scope to use (default none) \n " ) ;
1998-08-17 18:11:44 +04:00
printf ( " \n " ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
main program
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-06-04 10:42:03 +04:00
int main ( int argc , char * argv [ ] )
1996-05-04 11:50:46 +04:00
{
1998-08-17 18:11:44 +04:00
extern BOOL append_log ;
/* shall I run as a daemon */
BOOL is_daemon = False ;
int port = SMB_PORT ;
int opt ;
extern char * optarg ;
1998-07-29 07:08:05 +04:00
# ifdef HAVE_SET_AUTH_PARAMETERS
1998-08-17 18:11:44 +04:00
set_auth_parameters ( argc , argv ) ;
1996-05-04 11:50:46 +04:00
# endif
1998-07-29 07:08:05 +04:00
# ifdef HAVE_SETLUID
1998-08-17 18:11:44 +04:00
/* needed for SecureWare on SCO */
setluid ( 0 ) ;
1996-05-04 11:50:46 +04:00
# endif
1998-08-17 18:11:44 +04:00
append_log = True ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
TimeInit ( ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
pstrcpy ( debugf , SMBLOGFILE ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
pstrcpy ( remote_machine , " smb " ) ;
1998-02-12 17:57:55 +03:00
1998-08-17 18:11:44 +04:00
setup_logging ( argv [ 0 ] , False ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
charset_initialise ( ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
/* make absolutely sure we run as root - to handle cases where people
are crazy enough to have it setuid */
1998-07-29 07:08:05 +04:00
# ifdef HAVE_SETRESUID
1998-08-17 18:11:44 +04:00
setresuid ( 0 , 0 , 0 ) ;
1996-05-04 11:50:46 +04:00
# else
1998-08-17 18:11:44 +04:00
setuid ( 0 ) ;
seteuid ( 0 ) ;
setuid ( 0 ) ;
seteuid ( 0 ) ;
1996-05-04 11:50:46 +04:00
# endif
1998-08-17 18:11:44 +04:00
fault_setup ( ( void ( * ) ( void * ) ) exit_server ) ;
CatchSignal ( SIGTERM , SIGNAL_CAST dflt_sig ) ;
1998-09-02 09:00:47 +04:00
/* we are never interested in SIGPIPE */
BlockSignals ( True , SIGPIPE ) ;
1998-08-17 18:11:44 +04:00
/* we want total control over the permissions on created files,
so set our umask to 0 */
umask ( 0 ) ;
GetWd ( OriginalDir ) ;
init_uid ( ) ;
/* this is for people who can't start the program correctly */
while ( argc > 1 & & ( * argv [ 1 ] ! = ' - ' ) ) {
argv + + ;
argc - - ;
1996-05-04 11:50:46 +04:00
}
1998-08-21 21:21:55 +04:00
while ( EOF ! = ( opt = getopt ( argc , argv , " O:i:l:s:d:Dp:h?Paof: " ) ) )
1998-08-17 18:11:44 +04:00
switch ( opt ) {
case ' O ' :
pstrcpy ( user_socket_options , optarg ) ;
break ;
case ' i ' :
pstrcpy ( scope , optarg ) ;
break ;
case ' P ' :
{
extern BOOL passive ;
passive = True ;
}
break ;
case ' s ' :
pstrcpy ( servicesf , optarg ) ;
break ;
case ' l ' :
pstrcpy ( debugf , optarg ) ;
break ;
case ' a ' :
1998-08-21 21:21:55 +04:00
append_log = True ;
break ;
case ' o ' :
append_log = False ;
1998-08-17 18:11:44 +04:00
break ;
case ' D ' :
is_daemon = True ;
break ;
case ' d ' :
if ( * optarg = = ' A ' )
DEBUGLEVEL = 10000 ;
else
DEBUGLEVEL = atoi ( optarg ) ;
break ;
case ' p ' :
port = atoi ( optarg ) ;
break ;
case ' h ' :
1998-08-21 21:21:55 +04:00
case ' ? ' :
1998-08-17 18:11:44 +04:00
usage ( argv [ 0 ] ) ;
exit ( 0 ) ;
break ;
default :
usage ( argv [ 0 ] ) ;
exit ( 1 ) ;
}
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
reopen_logs ( ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
DEBUG ( 1 , ( " smbd version %s started. \n " , VERSION ) ) ;
1998-09-09 20:37:54 +04:00
DEBUGADD ( 1 , ( " Copyright Andrew Tridgell 1992-1998 \n " ) ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
DEBUG ( 2 , ( " uid=%d gid=%d euid=%d egid=%d \n " ,
( int ) getuid ( ) , ( int ) getgid ( ) , ( int ) geteuid ( ) , ( int ) getegid ( ) ) ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
if ( sizeof ( uint16 ) < 2 | | sizeof ( uint32 ) < 4 ) {
DEBUG ( 0 , ( " ERROR: Samba is not configured correctly for the word size on your machine \n " ) ) ;
exit ( 1 ) ;
}
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
if ( ! reload_services ( False ) )
return ( - 1 ) ;
1996-05-04 11:50:46 +04:00
1998-09-30 05:05:51 +04:00
init_structs ( ) ;
1998-07-29 07:08:05 +04:00
# ifdef WITH_SSL
1998-08-17 18:11:44 +04:00
{
extern BOOL sslEnabled ;
sslEnabled = lp_ssl_enabled ( ) ;
if ( sslEnabled )
sslutil_init ( True ) ;
}
1998-07-29 07:08:05 +04:00
# endif /* WITH_SSL */
1998-06-16 05:35:52 +04:00
1998-08-17 18:11:44 +04:00
codepage_initialise ( lp_client_code_page ( ) ) ;
1997-06-11 05:03:06 +04:00
1998-10-22 20:55:03 +04:00
fstrcpy ( global_myworkgroup , lp_workgroup ( ) ) ;
1997-05-20 04:32:51 +04:00
1998-10-22 02:36:26 +04:00
if ( ! pdb_generate_sam_sid ( ) ) {
DEBUG ( 0 , ( " ERROR: Samba cannot create a SAM SID. \n " ) ) ;
1998-08-17 18:11:44 +04:00
exit ( 1 ) ;
}
1997-12-24 12:30:56 +03:00
1998-08-17 18:11:44 +04:00
CatchSignal ( SIGHUP , SIGNAL_CAST sig_hup ) ;
/* Setup the signals that allow the debug log level
to by dynamically changed . */
1997-12-24 12:30:56 +03:00
1998-08-17 18:11:44 +04:00
/* If we are using the malloc debug code we can't use
SIGUSR1 and SIGUSR2 to do debug level changes . */
1998-01-23 08:22:19 +03:00
# ifndef MEM_MAN
1997-12-24 12:30:56 +03:00
# if defined(SIGUSR1)
1998-08-17 18:11:44 +04:00
CatchSignal ( SIGUSR1 , SIGNAL_CAST sig_usr1 ) ;
1997-12-24 12:30:56 +03:00
# endif /* SIGUSR1 */
# if defined(SIGUSR2)
1998-08-17 18:11:44 +04:00
CatchSignal ( SIGUSR2 , SIGNAL_CAST sig_usr2 ) ;
1997-12-24 12:30:56 +03:00
# endif /* SIGUSR2 */
1998-01-23 08:22:19 +03:00
# endif /* MEM_MAN */
1997-12-24 12:30:56 +03:00
1998-08-17 18:11:44 +04:00
DEBUG ( 3 , ( " loaded services \n " ) ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
if ( ! is_daemon & & ! is_a_socket ( 0 ) ) {
DEBUG ( 0 , ( " standard input is not a socket, assuming -D option \n " ) ) ;
is_daemon = True ;
}
1997-11-11 03:48:42 +03:00
1998-08-17 18:11:44 +04:00
if ( is_daemon ) {
DEBUG ( 3 , ( " Becoming a daemon. \n " ) ) ;
become_daemon ( ) ;
}
1996-12-10 21:00:22 +03:00
1998-09-26 03:40:49 +04:00
check_kernel_oplocks ( ) ;
1998-08-17 18:11:44 +04:00
if ( ! directory_exist ( lp_lockdir ( ) , NULL ) ) {
mkdir ( lp_lockdir ( ) , 0755 ) ;
}
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
if ( is_daemon ) {
pidfile_create ( " smbd " ) ;
}
1996-08-15 19:11:34 +04:00
1998-08-17 18:11:44 +04:00
if ( ! open_sockets ( is_daemon , port ) )
exit ( 1 ) ;
1998-05-19 03:57:28 +04:00
1998-08-17 18:11:44 +04:00
if ( ! locking_init ( 0 ) )
exit ( 1 ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
if ( ! initialize_password_db ( ) )
exit ( 1 ) ;
1996-05-05 07:04:19 +04:00
1998-08-17 18:11:44 +04:00
/* possibly reload the services file. */
reload_services ( True ) ;
if ( * lp_rootdir ( ) ) {
if ( sys_chroot ( lp_rootdir ( ) ) = = 0 )
DEBUG ( 2 , ( " Changed root to %s \n " , lp_rootdir ( ) ) ) ;
}
1997-09-23 23:19:06 +04:00
1998-08-17 18:11:44 +04:00
/* Setup the oplock IPC socket. */
if ( ! open_oplock_ipc ( ) )
exit ( 1 ) ;
1996-05-05 07:04:19 +04:00
1998-08-17 18:11:44 +04:00
smbd_process ( ) ;
close_sockets ( ) ;
exit_server ( " normal exit " ) ;
return ( 0 ) ;
1996-05-04 11:50:46 +04:00
}