diff options
Diffstat (limited to 'source/smbd/server.c')
-rw-r--r-- | source/smbd/server.c | 394 |
1 files changed, 147 insertions, 247 deletions
diff --git a/source/smbd/server.c b/source/smbd/server.c index 39d5e3bcd3f..14105342755 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -1,8 +1,8 @@ /* - Unix SMB/CIFS implementation. + Unix SMB/Netbios implementation. + Version 1.9. Main SMB server routines - Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Martin Pool 2002 + Copyright (C) Andrew Tridgell 1992-1998 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 @@ -21,6 +21,7 @@ #include "includes.h" +pstring servicesf = CONFIGFILE; extern fstring global_myworkgroup; extern pstring global_myname; @@ -33,13 +34,13 @@ int last_message = -1; #define LAST_MESSAGE() smb_fn_name(last_message) extern pstring user_socket_options; -extern SIG_ATOMIC_T got_sig_term; -extern SIG_ATOMIC_T reload_after_sighup; #ifdef WITH_DFS extern int dcelogin_atmost_once; #endif /* WITH_DFS */ +extern fstring remote_machine; + /* really we should have a top level context structure that has the client file descriptor as an element. That would require a major rewrite :( @@ -53,7 +54,7 @@ int smbd_server_fd(void) return server_fd; } -static void smbd_set_server_fd(int fd) +void smbd_set_server_fd(int fd) { server_fd = fd; client_setfd(fd); @@ -63,6 +64,8 @@ static void smbd_set_server_fd(int fd) Terminate signal. ****************************************************************************/ +SIG_ATOMIC_T got_sig_term; + static void sig_term(void) { got_sig_term = 1; @@ -73,6 +76,8 @@ static void sig_term(void) Catch a sighup. ****************************************************************************/ +SIG_ATOMIC_T reload_after_sighup; + static void sig_hup(int sig) { reload_after_sighup = 1; @@ -85,36 +90,8 @@ static void sig_hup(int sig) static void killkids(void) { - if(am_parent) kill(0,SIGTERM); -} - -/**************************************************************************** - Process a sam sync message - not sure whether to do this here or - somewhere else. -****************************************************************************/ - -static void msg_sam_sync(int UNUSED(msg_type), pid_t UNUSED(pid), - void *UNUSED(buf), size_t UNUSED(len)) -{ - DEBUG(10, ("** sam sync message received, ignoring\n")); -} - -/**************************************************************************** - Process a sam sync replicate message - not sure whether to do this here or - somewhere else. -****************************************************************************/ - -static void msg_sam_repl(int msg_type, pid_t pid, void *buf, size_t len) -{ - uint32 low_serial; - - if (len != sizeof(uint32)) - return; - - low_serial = *((uint32 *)buf); - - DEBUG(3, ("received sam replication message, serial = 0x%04x\n", - low_serial)); + if(am_parent) + kill(0,SIGTERM); } /**************************************************************************** @@ -129,33 +106,25 @@ static BOOL open_sockets_inetd(void) smbd_set_server_fd(dup(0)); /* close our standard file descriptors */ - close_low_fds(False); /* Don't close stderr */ + close_low_fds(); set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); - set_socket_options(smbd_server_fd(), user_socket_options); + set_socket_options(smbd_server_fd(),user_socket_options); return True; } -static void msg_exit_server(int msg_type, pid_t src, void *buf, size_t len) -{ - exit_server("Got a SHUTDOWN message"); -} - - /**************************************************************************** Open the socket communication. ****************************************************************************/ -static BOOL open_sockets_smbd(BOOL is_daemon,const char *smb_ports) +static BOOL open_sockets(BOOL is_daemon,BOOL interactive, int port) { int num_interfaces = iface_count(); - int num_sockets = 0; int fd_listenset[FD_SETSIZE]; fd_set listen_set; int s; int i; - char *ports; if (!is_daemon) { return open_sockets_inetd(); @@ -174,112 +143,73 @@ static BOOL open_sockets_smbd(BOOL is_daemon,const char *smb_ports) /* Stop zombies */ CatchChild(); - + + FD_ZERO(&listen_set); - /* use a reasonable default set of ports - listing on 445 and 139 */ - if (!smb_ports) { - ports = lp_smb_ports(); - if (!ports || !*ports) { - ports = SMB_PORTS; - } - ports = strdup(ports); - } else { - ports = strdup(smb_ports); - } - - if (lp_interfaces() && lp_bind_interfaces_only()) { + 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); - fstring tok; - char *ptr; - + if(ifip == NULL) { - DEBUG(0,("open_sockets_smbd: interface %d has NULL IP address !\n", i)); + 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, True); + if(s == -1) + return False; - for (ptr=ports; next_token(&ptr, tok, NULL, sizeof(tok)); ) { - unsigned port = atoi(tok); - if (port == 0) continue; - s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); - if(s == -1) - return False; - - /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,user_socket_options); - - if (listen(s, 5) == -1) { - DEBUG(0,("listen: %s\n",strerror(errno))); - close(s); - return False; - } - FD_SET(s,&listen_set); + /* ready to listen */ + set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,user_socket_options); - num_sockets++; - if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); - return False; - } + 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. */ - - fstring tok; - char *ptr; - num_interfaces = 1; - for (ptr=ports; next_token(&ptr, tok, NULL, sizeof(tok)); ) { - unsigned port = atoi(tok); - if (port == 0) continue; - /* open an incoming socket */ - s = open_socket_in(SOCK_STREAM, port, 0, - interpret_addr(lp_socket_address()),True); - if (s == -1) - return(False); + /* open an incoming socket */ + s = open_socket_in(SOCK_STREAM, port, 0, + interpret_addr(lp_socket_address()),True); + if (s == -1) + return(False); - /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,user_socket_options); - - if (listen(s, 5) == -1) { - DEBUG(0,("open_sockets_smbd: listen: %s\n", - strerror(errno))); - close(s); - return False; - } - - fd_listenset[num_sockets] = s; - FD_SET(s,&listen_set); - - num_sockets++; - - if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); - return False; - } + /* ready to listen */ + set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,user_socket_options); + + 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); } - SAFE_FREE(ports); - - /* Listen to messages */ - - message_register(MSG_SMB_SAM_SYNC, msg_sam_sync); - message_register(MSG_SMB_SAM_REPL, msg_sam_repl); - message_register(MSG_SHUTDOWN, msg_exit_server); - /* now accept incoming connections - forking a new process for each incoming connection */ DEBUG(2,("waiting for a connection\n")); @@ -305,10 +235,11 @@ static BOOL open_sockets_smbd(BOOL is_daemon,const char *smb_ports) /* check for sighup processing */ if (reload_after_sighup) { + DEBUG(0,("Got SIGHUP\n")); change_to_root_user(); DEBUG(1,("Reloading services after SIGHUP\n")); reload_services(False); - reload_after_sighup = 0; + reload_after_sighup = False; } continue; @@ -324,7 +255,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon,const char *smb_ports) socklen_t in_addrlen = sizeof(addr); s = -1; - for(i = 0; i < num_sockets; i++) { + 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 @@ -340,30 +271,29 @@ static BOOL open_sockets_smbd(BOOL is_daemon,const char *smb_ports) continue; if (smbd_server_fd() == -1) { - DEBUG(0,("open_sockets_smbd: accept: %s\n", + DEBUG(0,("open_sockets: accept: %s\n", strerror(errno))); continue; } - + + if (smbd_server_fd() != -1 && interactive) + return True; + if (smbd_server_fd() != -1 && sys_fork()==0) { /* Child code ... */ /* close the listening socket(s) */ - for(i = 0; i < num_sockets; i++) + for(i = 0; i < num_interfaces; i++) close(fd_listenset[i]); /* close our standard file descriptors */ - close_low_fds(False); + close_low_fds(); am_parent = 0; set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); set_socket_options(smbd_server_fd(),user_socket_options); - /* this is needed so that we get decent entries - in smbstatus for port 445 connects */ - set_remote_machine_name(get_socket_addr(smbd_server_fd())); - /* Reset global variables in util.c so that client substitutions will be done correctly in the process. */ @@ -411,7 +341,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon,const char *smb_ports) /**************************************************************************** Reload the services file. -**************************************************************************/ + **************************************************************************/ BOOL reload_services(BOOL test) { @@ -420,9 +350,8 @@ BOOL reload_services(BOOL test) if (lp_loaded()) { pstring fname; pstrcpy(fname,lp_configfile()); - if (file_exist(fname, NULL) && - !strcsequal(fname, dyn_CONFIGFILE)) { - pstrcpy(dyn_CONFIGFILE, fname); + if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) { + pstrcpy(servicesf,fname); test = False; } } @@ -434,7 +363,7 @@ BOOL reload_services(BOOL test) lp_killunused(conn_snum_used); - ret = lp_load(dyn_CONFIGFILE, False, False, True); + ret = lp_load(servicesf,False,False,True); load_printers(); @@ -449,7 +378,7 @@ BOOL reload_services(BOOL test) { if (smbd_server_fd() != -1) { set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); - set_socket_options(smbd_server_fd(), user_socket_options); + set_socket_options(smbd_server_fd(),user_socket_options); } } @@ -464,15 +393,15 @@ BOOL reload_services(BOOL test) #if DUMP_CORE /******************************************************************* -prepare to dump a core file - carefully! + Prepare to dump a core file - carefully ! ********************************************************************/ + static BOOL dump_core(void) { char *p; pstring dname; - pstrcpy(dname,lp_logfile()); - if ((p=strrchr_m(dname,'/'))) *p=0; + if ((p=strrchr(dname,'/'))) *p=0; pstrcat(dname,"/corefiles"); mkdir(dname,0700); sys_chown(dname,getuid(),getgid()); @@ -495,7 +424,7 @@ static BOOL dump_core(void) #endif - DEBUG(0,("Dumping core in %s\n", dname)); + DEBUG(0,("Dumping core in %s\n",dname)); abort(); return(True); } @@ -523,27 +452,21 @@ void exit_server(char *reason) { static int firsttime=1; extern char *last_inbuf; - extern struct auth_context *negprot_global_auth_context; - if (!firsttime) - exit(0); + + if (!firsttime) exit(0); firsttime = 0; change_to_root_user(); DEBUG(2,("Closing connections\n")); - if (negprot_global_auth_context) { - (negprot_global_auth_context->free)(&negprot_global_auth_context); - } - conn_close_all(); invalidate_all_vuids(); - print_notify_send_messages(); - /* delete our entry in the connections database. */ - yield_connection(NULL,""); + if (lp_status(-1)) + yield_connection(NULL,""); respond_to_all_remaining_local_messages(); decrement_smbd_process_count(); @@ -568,7 +491,6 @@ void exit_server(char *reason) } locking_end(); - printing_end(); DEBUG(3,("Server exit (%s)\n", (reason ? reason : ""))); exit(0); @@ -587,13 +509,13 @@ static void init_structs(void ) if (!*global_myname) { char *p; - pstrcpy( global_myname, myhostname() ); - p = strchr_m(global_myname, '.' ); + fstrcpy( global_myname, myhostname() ); + p = strchr( global_myname, '.' ); if (p) *p = 0; } - strupper(global_myname); + strupper( global_myname ); conn_init(); @@ -605,7 +527,6 @@ static void init_structs(void ) init_dptrs(); secrets_init(); - } /**************************************************************************** @@ -615,22 +536,21 @@ static void init_structs(void ) static void usage(char *pname) { - d_printf("Usage: %s [-DaioPh?Vb] [-d debuglevel] [-l log basename] [-p port]\n", pname); - d_printf(" [-O socket options] [-s services file]\n"); - d_printf("\t-D Become a daemon (default)\n"); - d_printf("\t-a Append to log file (default)\n"); - d_printf("\t-i Run interactive (not a daemon)\n" ); - d_printf("\t-o Overwrite log file, don't append\n"); - d_printf("\t-h Print usage\n"); - d_printf("\t-? Print usage\n"); - d_printf("\t-V Print version\n"); - d_printf("\t-b Print build options\n"); - d_printf("\t-d debuglevel Set the debuglevel\n"); - d_printf("\t-l log basename. Basename for log/debug files\n"); - d_printf("\t-p port Listen on the specified port\n"); - d_printf("\t-O socket options Socket options\n"); - d_printf("\t-s services file. Filename of services file\n"); - d_printf("\n"); + printf("Usage: %s [-DaioPh?V] [-d debuglevel] [-l log basename] [-p port]\n", pname); + printf(" [-O socket options] [-s services file]\n"); + printf("\t-D Become a daemon (default)\n"); + printf("\t-a Append to log file (default)\n"); + printf("\t-i Run interactive (not a daemon)\n"); + printf("\t-o Overwrite log file, don't append\n"); + printf("\t-h Print usage\n"); + printf("\t-? Print usage\n"); + printf("\t-V Print version\n"); + printf("\t-d debuglevel Set the debuglevel\n"); + printf("\t-l log basename. Basename for log/debug files\n"); + printf("\t-p port Listen on the specified port\n"); + printf("\t-O socket options Socket options\n"); + printf("\t-s services file. Filename of services file\n"); + printf("\n"); } /**************************************************************************** @@ -641,15 +561,15 @@ static void usage(char *pname) { extern BOOL append_log; extern BOOL AllowDebugChange; - extern char *optarg; /* shall I run as a daemon */ BOOL is_daemon = False; BOOL interactive = False; BOOL specified_logfile = False; - char *ports = NULL; + int port = SMB_PORT; int opt; + extern char *optarg; pstring logfile; - + #ifdef HAVE_SET_AUTH_PARAMETERS set_auth_parameters(argc,argv); #endif @@ -660,19 +580,19 @@ static void usage(char *pname) argc--; } - while ( EOF != (opt = getopt(argc, argv, "O:l:s:d:Dp:h?bVaiof:")) ) + while ( EOF != (opt = getopt(argc, argv, "O:l:s:d:Dip:h?Vaof:")) ) switch (opt) { case 'O': pstrcpy(user_socket_options,optarg); break; case 's': - pstrcpy(dyn_CONFIGFILE,optarg); + pstrcpy(servicesf,optarg); break; case 'l': specified_logfile = True; - pstr_sprintf(logfile, "%s/log.smbd", optarg); + slprintf(logfile, sizeof(logfile)-1, "%s/log.smbd", optarg); lp_set_logfile(logfile); break; @@ -680,10 +600,6 @@ static void usage(char *pname) append_log = True; break; - case 'i': - interactive = True; - break; - case 'o': append_log = False; break; @@ -692,6 +608,10 @@ static void usage(char *pname) is_daemon = True; break; + case 'i': + interactive = True; + break; + case 'd': if (*optarg == 'A') DEBUGLEVEL = 10000; @@ -701,7 +621,7 @@ static void usage(char *pname) break; case 'p': - ports = optarg; + port = atoi(optarg); break; case 'h': @@ -711,11 +631,7 @@ static void usage(char *pname) break; case 'V': - d_printf("Version %s\n",VERSION); - exit(0); - break; - case 'b': - build_options(True); /* Display output to screen as well as debug */ + printf("Version %s\n",VERSION); exit(0); break; default: @@ -731,19 +647,21 @@ static void usage(char *pname) sec_init(); - load_case_tables(); - append_log = True; + TimeInit(); + if(!specified_logfile) { - pstr_sprintf(logfile, "%s/log.smbd", dyn_LOGFILEBASE); + slprintf(logfile, sizeof(logfile)-1, "%s/log.smbd", LOGFILEBASE); lp_set_logfile(logfile); } - set_remote_machine_name("smbd"); + pstrcpy(remote_machine, "smbd"); setup_logging(argv[0],interactive); + charset_initialise(); + /* we want to re-seed early to prevent time delays causing client problems at a later date. (tridge) */ generate_random_buffer(NULL, 0, False); @@ -757,7 +675,7 @@ static void usage(char *pname) fault_setup((void (*)(void *))exit_server); CatchSignal(SIGTERM , SIGNAL_CAST sig_term); CatchSignal(SIGHUP,SIGNAL_CAST sig_hup); - + /* we are never interested in SIGPIPE */ BlockSignals(True,SIGPIPE); @@ -782,6 +700,7 @@ static void usage(char *pname) umask(0); init_sec_ctx(); + init_conn_ctx(); reopen_logs(); @@ -791,9 +710,6 @@ static void usage(char *pname) DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); - /* Output the build options to the debug log */ - build_options(False); - 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); @@ -807,13 +723,24 @@ static void usage(char *pname) return(-1); init_structs(); - + #ifdef WITH_PROFILE if (!profile_setup(False)) { - DEBUG(0,("ERROR: failed to setup profiling\n")); + DEBUG(0,("ERROR: failed to setup profiling shared memory\n")); return -1; } -#endif +#endif /* WITH_PROFILE */ + +#ifdef WITH_SSL + { + extern BOOL sslEnabled; + sslEnabled = lp_ssl_enabled(); + if(sslEnabled) + sslutil_init(True); + } +#endif /* WITH_SSL */ + + codepage_initialise(lp_client_code_page()); fstrcpy(global_myworkgroup, lp_workgroup()); @@ -845,39 +772,35 @@ static void usage(char *pname) setpgid( (pid_t)0, (pid_t)0); #endif - if (!directory_exist(lp_lockdir(), NULL)) { + if (!directory_exist(lp_lockdir(), NULL)) mkdir(lp_lockdir(), 0755); - } - if (is_daemon) { + if (is_daemon) pidfile_create("smbd"); - } - if (!message_init()) { + if (!message_init()) exit(1); - } - register_msg_pool_usage(); - register_dmalloc_msgs(); /* Setup the main smbd so that we can get messages. */ - claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD); + if (lp_status(-1)) + claim_connection(NULL,"",0,True); + + /* Attempt to migrate from an old 2.0.x machine account file. */ + if (!migrate_from_old_password_file(global_myworkgroup)) + DEBUG(0,("Failed to migrate from old MAC file.\n")); - /* - DO NOT ENABLE THIS TILL YOU COPE WITH KILLING THESE TASKS AND INETD - THIS *killed* LOTS OF BUILD FARM MACHINES. IT CREATED HUNDREDS OF - smbd PROCESSES THAT NEVER DIE - start_background_queue(); - */ + if(!pdb_generate_sam_sid()) { + DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); + exit(1); + } - if (!open_sockets_smbd(is_daemon,ports)) + if (!open_sockets(is_daemon,interactive,port)) exit(1); /* - * everything after this point is run after the fork() + * Everything after this point is run after the fork(). */ - namecache_enable(); - if (!locking_init(0)) exit(1); @@ -887,27 +810,12 @@ static void usage(char *pname) if (!share_info_db_init()) exit(1); - if (!init_registry()) - exit(1); - if(!initialize_password_db(False)) exit(1); - uni_group_cache_init(); /* Non-critical */ - /* possibly reload the services file. */ reload_services(True); - if(!get_global_sam_sid()) { - DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); - exit(1); - } - - if (!init_account_policy()) { - DEBUG(0,("Could not open account policy tdb.\n")); - exit(1); - } - if (*lp_rootdir()) { if (sys_chroot(lp_rootdir()) == 0) DEBUG(2,("Changed root to %s\n", lp_rootdir())); @@ -916,21 +824,13 @@ static void usage(char *pname) /* Setup oplocks */ if (!init_oplocks()) exit(1); - + /* Setup change notify */ if (!init_change_notify()) exit(1); - /* re-initialise the timezone */ - TimeInit(); - - /* register our message handlers */ - message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis); - talloc_init_named("dummy!"); - smbd_process(); - uni_group_cache_shutdown(); exit_server("normal exit"); return(0); } |