lib: Remove messages_local
[obnox/samba/samba-obnox.git] / source3 / smbd / server.c
index d53b19a57f30f8ac86ea2d318ff165dd950489af..df565cf0aea7bfdc541ab12ed52acc3e4fdf73b0 100644 (file)
@@ -31,6 +31,7 @@
 #include "secrets.h"
 #include "memcache.h"
 #include "ctdbd_conn.h"
+#include "util_cluster.h"
 #include "printing/queue_process.h"
 #include "rpc_server/rpc_service_setup.h"
 #include "rpc_server/rpc_config.h"
@@ -44,6 +45,8 @@
 #include "lib/background.h"
 #include "lib/conn_tdb.h"
 #include "../lib/util/pidfile.h"
+#include "lib/smbd_shim.h"
+#include "scavenger.h"
 
 struct smbd_open_socket;
 struct smbd_child_pid;
@@ -61,7 +64,7 @@ struct smbd_parent_context {
        struct smbd_child_pid *children;
        size_t num_children;
 
-       struct timed_event *cleanup_te;
+       struct tevent_timer *cleanup_te;
 };
 
 struct smbd_open_socket {
@@ -79,7 +82,7 @@ struct smbd_child_pid {
 extern void start_epmd(struct tevent_context *ev_ctx,
                       struct messaging_context *msg_ctx);
 
-extern void start_lsasd(struct event_context *ev_ctx,
+extern void start_lsasd(struct tevent_context *ev_ctx,
                        struct messaging_context *msg_ctx);
 
 #ifdef WITH_DFS
@@ -281,7 +284,7 @@ static bool smbd_parent_notify_init(TALLOC_CTX *mem_ctx,
 
        state = talloc(mem_ctx, struct smbd_parent_notify_state);
        if (state == NULL) {
-               return NULL;
+               return false;
        }
        state->msg = msg;
        state->ev = ev;
@@ -367,6 +370,17 @@ static void smb_parent_force_tdis(struct messaging_context *ctx,
        messaging_send_to_children(ctx, msg_type, msg_data);
 }
 
+static void smb_parent_kill_client_by_ip(struct messaging_context *ctx,
+                                        void *data,
+                                        uint32_t msg_type,
+                                        struct server_id srv_id,
+                                        DATA_BLOB* msg_data)
+{
+       if (am_parent) {
+               messaging_send_to_children(ctx, msg_type, msg_data);
+       }
+}
+
 static void add_child_pid(struct smbd_parent_context *parent,
                          pid_t pid)
 {
@@ -382,6 +396,20 @@ static void add_child_pid(struct smbd_parent_context *parent,
        parent->num_children += 1;
 }
 
+static void smb_tell_num_children(struct messaging_context *ctx, void *data,
+                                 uint32_t msg_type, struct server_id srv_id,
+                                 DATA_BLOB *msg_data)
+{
+       uint8_t buf[sizeof(uint32_t)];
+
+       if (am_parent) {
+               SIVAL(buf, 0, am_parent->num_children);
+               messaging_send_buf(ctx, srv_id, MSG_SMB_NUM_CHILDREN,
+                                  buf, sizeof(buf));
+       }
+}
+
+
 /*
   at most every smbd:cleanuptime seconds (default 20), we scan the BRL
   and locking database for entries to cleanup. As a side effect this
@@ -393,8 +421,8 @@ static void add_child_pid(struct smbd_parent_context *parent,
   network outage).  
 */
 
-static void cleanup_timeout_fn(struct event_context *event_ctx,
-                               struct timed_event *te,
+static void cleanup_timeout_fn(struct tevent_context *event_ctx,
+                               struct tevent_timer *te,
                                struct timeval now,
                                void *private_data)
 {
@@ -437,6 +465,8 @@ static void remove_child_pid(struct smbd_parent_context *parent,
        }
 
        if (unclean_shutdown) {
+               NTSTATUS status;
+
                /* a child terminated uncleanly so tickle all
                   processes to see if they can grab any of the
                   pending locks
@@ -453,6 +483,10 @@ static void remove_child_pid(struct smbd_parent_context *parent,
                                                parent);
                        DEBUG(1,("Scheduled cleanup of brl and lock database after unclean shutdown\n"));
                }
+
+               status = messaging_dgm_cleanup(parent->msg_ctx, pid);
+               DEBUG(10, ("%s: messaging_dgm_cleanup returned %s\n",
+                          __func__, nt_errstr(status)));
        }
 
        if (!serverid_deregister(child_id)) {
@@ -550,7 +584,7 @@ static void smbd_accept_connection(struct tevent_context *ev,
                return;
 
        if (fd == -1) {
-               DEBUG(0,("open_sockets_smbd: accept: %s\n",
+               DEBUG(0,("accept: %s\n",
                         strerror(errno)));
                return;
        }
@@ -661,7 +695,6 @@ static void smbd_accept_connection(struct tevent_context *ev,
 
 static bool smbd_open_one_socket(struct smbd_parent_context *parent,
                                 struct tevent_context *ev_ctx,
-                                struct messaging_context *msg_ctx,
                                 const struct sockaddr_storage *ifss,
                                 uint16_t port)
 {
@@ -752,6 +785,15 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent,
                ports = (const char **)str_list_make_v3(talloc_tos(), smb_ports, NULL);
        }
 
+       for (j = 0; ports && ports[j]; j++) {
+               unsigned port = atoi(ports[j]);
+
+               if (port == 0 || port > 0xffff) {
+                       exit_server_cleanly("Invalid port in the config or on "
+                                           "the commandline specified!");
+               }
+       }
+
        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
@@ -772,9 +814,6 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent,
 
                        for (j = 0; ports && ports[j]; j++) {
                                unsigned port = atoi(ports[j]);
-                               if (port == 0 || port > 0xffff) {
-                                       continue;
-                               }
 
                                /* Keep the first port for mDNS service
                                 * registration.
@@ -785,7 +824,6 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent,
 
                                if (!smbd_open_one_socket(parent,
                                                          ev_ctx,
-                                                         msg_ctx,
                                                          ifss,
                                                          port)) {
                                        return false;
@@ -810,11 +848,7 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent,
                     next_token_talloc(talloc_tos(), &sock_ptr, &sock_tok, " \t,"); ) {
                        for (j = 0; ports && ports[j]; j++) {
                                struct sockaddr_storage ss;
-
                                unsigned port = atoi(ports[j]);
-                               if (port == 0 || port > 0xffff) {
-                                       continue;
-                               }
 
                                /* Keep the first port for mDNS service
                                 * registration.
@@ -831,7 +865,6 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent,
 
                                if (!smbd_open_one_socket(parent,
                                                          ev_ctx,
-                                                         msg_ctx,
                                                          &ss,
                                                          port)) {
                                        return false;
@@ -875,17 +908,19 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent,
                           brl_revalidate);
        messaging_register(msg_ctx, NULL, MSG_SMB_FORCE_TDIS,
                           smb_parent_force_tdis);
+       messaging_register(msg_ctx, NULL, MSG_SMB_KILL_CLIENT_IP,
+                          smb_parent_kill_client_by_ip);
+       messaging_register(msg_ctx, NULL, MSG_SMB_TELL_NUM_CHILDREN,
+                          smb_tell_num_children);
 
        messaging_register(msg_ctx, NULL,
                           ID_CACHE_DELETE, smbd_parent_id_cache_delete);
        messaging_register(msg_ctx, NULL,
                           ID_CACHE_KILL, smbd_parent_id_cache_kill);
 
-#ifdef CLUSTER_SUPPORT
        if (lp_clustering()) {
                ctdbd_register_reconfigure(messaging_ctdbd_connection());
        }
-#endif
 
 #ifdef DEVELOPER
        messaging_register(msg_ctx, NULL, MSG_SMB_INJECT_FAULT,
@@ -1040,7 +1075,6 @@ extern void build_options(bool screen);
        {"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"},
        {"profiling-level", 'P', POPT_ARG_STRING, &profile_level, 0, "Set profiling level","PROFILE_LEVEL"},
        POPT_COMMON_SAMBA
-       POPT_COMMON_DYNCONFIG
        POPT_TABLEEND
        };
        struct smbd_parent_context *parent = NULL;
@@ -1051,6 +1085,23 @@ extern void build_options(bool screen);
        struct server_id server_id;
        struct tevent_signal *se;
        char *np_dir = NULL;
+       static const struct smbd_shim smbd_shim_fns =
+       {
+               .cancel_pending_lock_requests_by_fid = smbd_cancel_pending_lock_requests_by_fid,
+               .send_stat_cache_delete_message = smbd_send_stat_cache_delete_message,
+               .change_to_root_user = smbd_change_to_root_user,
+               .become_authenticated_pipe_user = smbd_become_authenticated_pipe_user,
+               .unbecome_authenticated_pipe_user = smbd_unbecome_authenticated_pipe_user,
+
+               .contend_level2_oplocks_begin = smbd_contend_level2_oplocks_begin,
+               .contend_level2_oplocks_end = smbd_contend_level2_oplocks_end,
+
+               .become_root = smbd_become_root,
+               .unbecome_root = smbd_unbecome_root,
+
+               .exit_server = smbd_exit_server,
+               .exit_server_cleanly = smbd_exit_server_cleanly,
+       };
 
        /*
         * Do this before any other talloc operation
@@ -1062,6 +1113,8 @@ extern void build_options(bool screen);
 
        load_case_tables();
 
+       set_smbd_shim(&smbd_shim_fns);
+
        smbd_init_globals();
 
        TimeInit();
@@ -1196,6 +1249,10 @@ extern void build_options(bool screen);
                exit(1);
        }
 
+       if (!cluster_probe_ok()) {
+               exit(1);
+       }
+
        /* Init the security context and global current_user */
        init_sec_ctx();
 
@@ -1256,8 +1313,10 @@ extern void build_options(bool screen);
 #endif
 
        if (!is_daemon && !is_a_socket(0)) {
-               if (!interactive)
-                       DEBUG(0,("standard input is not a socket, assuming -D option\n"));
+               if (!interactive) {
+                       DEBUG(3, ("Standard input is not a socket, "
+                                 "assuming -D option\n"));
+               }
 
                /*
                 * Setting is_daemon here prevents us from eventually calling
@@ -1268,7 +1327,7 @@ extern void build_options(bool screen);
        }
 
        if (is_daemon && !interactive) {
-               DEBUG( 3, ( "Becoming a daemon.\n" ) );
+               DEBUG(3, ("Becoming a daemon.\n"));
                become_daemon(Fork, no_process_group, log_stdout);
        }
 
@@ -1283,21 +1342,20 @@ extern void build_options(bool screen);
                setpgid( (pid_t)0, (pid_t)0);
 #endif
 
-       if (!directory_exist(lp_lockdir()))
-               mkdir(lp_lockdir(), 0755);
+       if (!directory_exist(lp_lock_directory()))
+               mkdir(lp_lock_directory(), 0755);
 
-       if (!directory_exist(lp_piddir()))
-               mkdir(lp_piddir(), 0755);
+       if (!directory_exist(lp_pid_directory()))
+               mkdir(lp_pid_directory(), 0755);
 
        if (is_daemon)
-               pidfile_create(lp_piddir(), "smbd");
+               pidfile_create(lp_pid_directory(), "smbd");
 
        status = reinit_after_fork(msg_ctx,
                                   ev_ctx,
                                   false);
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0,("reinit_after_fork() failed\n"));
-               exit(1);
+               exit_daemon("reinit_after_fork() failed", map_errno_from_nt_status(status));
        }
 
        if (!interactive) {
@@ -1308,8 +1366,7 @@ extern void build_options(bool screen);
                 */
                status = init_before_fork();
                if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0, ("init_before_fork failed: %s\n", nt_errstr(status)));
-                       exit(1);
+                       exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
                }
        }
 
@@ -1342,7 +1399,7 @@ extern void build_options(bool screen);
        /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */
 
        if (smbd_memcache() == NULL) {
-               exit(1);
+               exit_daemon("no memcache available", EACCES);
        }
 
        memcache_set_global(smbd_memcache());
@@ -1354,71 +1411,61 @@ extern void build_options(bool screen);
                exit(1);
 
        if (!secrets_init()) {
-               DEBUG(0, ("ERROR: smbd can not open secrets.tdb\n"));
-               exit(1);
+               exit_daemon("smbd can not open secrets.tdb", EACCES);
        }
 
        if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) {
                struct loadparm_context *lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
                if (!open_schannel_session_store(NULL, lp_ctx)) {
-                       DEBUG(0,("ERROR: Samba cannot open schannel store for secured NETLOGON operations.\n"));
-                       exit(1);
+                       exit_daemon("ERROR: Samba cannot open schannel store for secured NETLOGON operations.", EACCES);
                }
                TALLOC_FREE(lp_ctx);
        }
 
        if(!get_global_sam_sid()) {
-               DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n"));
-               exit(1);
+               exit_daemon("Samba cannot create a SAM SID", EACCES);
        }
 
        server_id = messaging_server_id(msg_ctx);
        status = smbXsrv_version_global_init(&server_id);
        if (!NT_STATUS_IS_OK(status)) {
-               exit(1);
+               exit_daemon("Samba cannot init server context", EACCES);
        }
 
-       if (!sessionid_init()) {
-               exit(1);
-       }
        status = smbXsrv_session_global_init();
        if (!NT_STATUS_IS_OK(status)) {
-               exit(1);
+               exit_daemon("Samba cannot init session context", EACCES);
        }
 
-       if (!connections_init(true)) {
-               exit(1);
-       }
        status = smbXsrv_tcon_global_init();
        if (!NT_STATUS_IS_OK(status)) {
-               exit(1);
+               exit_daemon("Samba cannot init tcon context", EACCES);
        }
 
        if (!locking_init())
-               exit(1);
+               exit_daemon("Samba cannot init locking", EACCES);
 
-       if (!messaging_tdb_parent_init(ev_ctx)) {
-               exit(1);
+       if (!smbd_parent_notify_init(NULL, msg_ctx, ev_ctx)) {
+               exit_daemon("Samba cannot init notification", EACCES);
        }
 
-       if (!smbd_parent_notify_init(NULL, msg_ctx, ev_ctx)) {
-               exit(1);
+       if (!smbd_scavenger_init(NULL, msg_ctx, ev_ctx)) {
+               exit_daemon("Samba cannot init scavenging", EACCES);
        }
 
        if (!serverid_parent_init(ev_ctx)) {
-               exit(1);
+               exit_daemon("Samba cannot init server id", EACCES);
        }
 
        if (!W_ERROR_IS_OK(registry_init_full()))
-               exit(1);
+               exit_daemon("Samba cannot init registry", EACCES);
 
        /* Open the share_info.tdb here, so we don't have to open
           after the fork on every single connection.  This is a small
           performance improvment and reduces the total number of system
           fds used. */
        if (!share_info_db_init()) {
-               DEBUG(0,("ERROR: failed to load share info db.\n"));
-               exit(1);
+               exit_daemon("ERROR: failed to load share info db.", EACCES);
        }
 
        status = init_system_session_info();
@@ -1439,7 +1486,7 @@ extern void build_options(bool screen);
        }
        status = smbXsrv_open_global_init();
        if (!NT_STATUS_IS_OK(status)) {
-               exit(1);
+               exit_daemon("Samba cannot init global open", map_errno_from_nt_status(status));
        }
 
        /* This MUST be done before start_epmd() because otherwise
@@ -1457,7 +1504,7 @@ extern void build_options(bool screen);
                return -1;
        }
 
-       if (!directory_create_or_exist(np_dir, geteuid(), 0700)) {
+       if (!directory_create_or_exist_strict(np_dir, geteuid(), 0700)) {
                DEBUG(0, ("Failed to create pipe directory %s - %s\n",
                          np_dir, strerror(errno)));
                return -1;
@@ -1469,6 +1516,14 @@ extern void build_options(bool screen);
                }
        }
 
+       if (!dcesrv_ep_setup(ev_ctx, msg_ctx)) {
+               exit_daemon("Samba cannot setup ep pipe", EACCES);
+       }
+
+       if (is_daemon && !interactive) {
+               daemon_ready("smbd");
+       }
+
        /* only start other daemons if we are running as a daemon
         * -- bad things will happen if smbd is launched via inetd
         *  and we fork a copy of ourselves here */
@@ -1483,7 +1538,7 @@ extern void build_options(bool screen);
                        bool bgq = lp_parm_bool(-1, "smbd", "backgroundqueue", true);
 
                        if (!printing_subsystem_init(ev_ctx, msg_ctx, true, bgq)) {
-                               exit(1);
+                               exit_daemon("Samba failed to init printing subsystem", EACCES);
                        }
                }
        } else if (!lp__disable_spoolss() &&
@@ -1493,10 +1548,6 @@ extern void build_options(bool screen);
                }
        }
 
-       if (!dcesrv_ep_setup(ev_ctx, msg_ctx)) {
-               exit(1);
-       }
-
        if (!is_daemon) {
                int sock;
 
@@ -1529,7 +1580,10 @@ extern void build_options(bool screen);
 
        /* do a printer update now that all messaging has been set up,
         * before we allow clients to start connecting */
-       printing_subsystem_update(ev_ctx, msg_ctx, false);
+       if (!lp__disable_spoolss() &&
+           (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) {
+               printing_subsystem_update(ev_ctx, msg_ctx, false);
+       }
 
        TALLOC_FREE(frame);
        /* make sure we always have a valid stackframe */
@@ -1539,8 +1593,20 @@ extern void build_options(bool screen);
                /* 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
+                  Only do this on a pipe or socket, no other device.
                */
-               tevent_add_fd(ev_ctx, parent, 0, TEVENT_FD_READ, smbd_stdin_handler, NULL);
+               struct stat st;
+               if (fstat(0, &st) != 0) {
+                       return false;
+               }
+               if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
+                       tevent_add_fd(ev_ctx,
+                                       parent,
+                                       0,
+                                       TEVENT_FD_READ,
+                                       smbd_stdin_handler,
+                                       NULL);
+               }
        }
 
        smbd_parent_loop(ev_ctx, parent);