s3fs: added file_server directory
authorAndrew Tridgell <tridge@samba.org>
Mon, 2 May 2011 23:35:07 +0000 (09:35 +1000)
committerAndrew Tridgell <tridge@samba.org>
Thu, 9 Feb 2012 04:41:48 +0000 (15:41 +1100)
this contains a file server backend that uses the smbd_base library
from the s3 core code

Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>

file_server/file_server.c [new file with mode: 0644]
file_server/file_server.h [new file with mode: 0644]
file_server/wscript_build [new file with mode: 0644]
selftest/target/Samba4.pm
source4/smb_server/service_smb.c
wscript_build

diff --git a/file_server/file_server.c b/file_server/file_server.c
new file mode 100644 (file)
index 0000000..5dd26f7
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   run s3 file server within Samba4
+
+   Copyright (C) Andrew Tridgell       2011
+
+   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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "source3/include/includes.h"
+
+/* we use the full source3/source4 prefixes as this code mixes the two
+   sets of header pathsx */
+#include "source3/smbd/globals.h"
+#include "source3/smbd/proto.h"
+#include "source3/include/memcache.h"
+#include "source3/include/passdb.h"
+#include "source3/include/secrets.h"
+#include "source3/locking/proto.h"
+#include "source3/include/messages.h"
+#include "source3/include/serverid.h"
+#include "source3/printing/printer_list.h"
+#include "source3/registry/reg_init_full.h"
+#include "source3/include/printing.h"
+#include "source3/include/auth.h"
+#include "rpc_server/rpc_service_setup.h"
+#include "source4/smbd/service_stream.h"
+#include "lib/param/param.h"
+#include "source4/lib/socket/socket.h"
+#include "source4/smbd/service.h"
+#include "source4/smbd/process_model.h"
+#include "source4/lib/socket/netif.h"
+#include "libcli/auth/schannel.h"
+#include "file_server/file_server.h"
+
+
+/*
+  this runs through the initialisation that the samba3 file server
+  normally does. It is derived from main() in source3/smbd/server.c
+ */
+static int s3fs_server_init(struct loadparm_context *lp_ctx)
+{
+       uint64_t unique_id;
+       NTSTATUS status;
+       struct tevent_context *ev_ctx;
+       struct messaging_context *msg_ctx;
+
+       /* create a stackframe for the file server child */
+       talloc_stackframe();
+
+       smbd_init_globals();
+
+       TimeInit();
+
+       set_remote_machine_name("smbd", False);
+
+       /* get initial effective uid and gid */
+       sec_init();
+
+       lp_set_cmdline("config file", lpcfg_configfile(lp_ctx));
+       lp_set_cmdline("auth methods", "guest samba4");
+       lp_set_cmdline("passdb backend", "samba4");
+        lp_set_cmdline("rpc_server:lsarpc", "external");
+       lp_set_cmdline("rpc_server:netlogon", "external");
+       lp_set_cmdline("rpc_server:samr", "external");
+
+       if (!lp_load_initial_only(lpcfg_configfile(lp_ctx))) {
+               DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
+               return -1;
+       }
+
+       /* Init the security context and global current_user */
+       init_sec_ctx();
+
+       /*
+        * Initialize the event context. The event context needs to be
+        * initialized before the messaging context, cause the messaging
+        * context holds an event context.
+        * FIXME: This should be s3_tevent_context_init()
+        */
+       ev_ctx = server_event_context();
+       if (ev_ctx == NULL) {
+               DEBUG(0, ("Failed to get server event context"));
+               return -1;
+       }
+
+       /*
+        * Init the messaging context
+        * FIXME: This should only call messaging_init()
+        */
+       msg_ctx = server_messaging_context();
+       if (msg_ctx == NULL) {
+               DEBUG(0, ("Failed to get server messaging context"));
+               return -1;
+       }
+
+       /*
+        * Reloading of the printers will not work here as we don't have a
+        * server info and rpc services set up. It will be called later.
+        */
+       if (!reload_services(NULL, -1, False)) {
+               DEBUG(0, ("Failed to reload smb.conf"));
+               return -1;
+       }
+
+       /* ...NOTE... Log files are working from this point! */
+
+        generate_random_buffer((uint8_t *)&unique_id, sizeof(unique_id));
+        set_my_unique_id(unique_id);
+
+       status = reinit_after_fork(msg_ctx,
+                                  ev_ctx,
+                                  procid_self(), false);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("reinit_after_fork() failed\n"));
+               return -1;
+       }
+
+       smbd_server_conn->msg_ctx = msg_ctx;
+
+       smbd_setup_sig_term_handler();
+       smbd_setup_sig_hup_handler(ev_ctx,
+                                  msg_ctx);
+
+       /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */
+
+       if (smbd_memcache() == NULL) {
+               DEBUG(0, ("Failed to init smbd memcache"));
+               return -1;
+       }
+
+       memcache_set_global(smbd_memcache());
+
+       /* Initialise the password backed before the global_sam_sid
+          to ensure that we fetch from ldap before we make a domain sid up */
+
+       if(!initialize_password_db(false, ev_ctx)) {
+               DEBUG(0, ("Failed to init passdb backends"));
+               return -1;
+       }
+
+       if (!secrets_init()) {
+               DEBUG(0, ("ERROR: smbd can not open secrets.tdb\n"));
+               return -1;
+       }
+
+       if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) {
+               if (!open_schannel_session_store(NULL, lp_ctx)) {
+                       DEBUG(0,("ERROR: Samba cannot open schannel store for secured NETLOGON operations.\n"));
+                       return -1;
+               }
+       }
+
+       if(!get_global_sam_sid()) {
+               DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n"));
+               return -1;
+       }
+
+       if (!sessionid_init()) {
+               DEBUG(0, ("Failed to init sessionid database"));
+               return -1;
+       }
+
+       if (!connections_init(True)) {
+               DEBUG(0, ("Failed to init connections database"));
+               return -1;
+       }
+
+       if (!locking_init()) {
+               DEBUG(0, ("Failed to init locking database"));
+               return -1;
+       }
+       if (!messaging_tdb_parent_init(ev_ctx)) {
+               DEBUG(0, ("Failed to init messaging tdb as parent task"));
+               return -1;
+       }
+
+       if (!notify_internal_parent_init(ev_ctx)) {
+               DEBUG(0, ("Failed to init notify db as parent task"));
+               return -1;
+       }
+
+       if (!serverid_parent_init(ev_ctx)) {
+               return -1;
+       }
+
+       if (!W_ERROR_IS_OK(registry_init_full())) {
+               DEBUG(0, ("Failed to init registry"));
+               return -1;
+       }
+
+       /* 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"));
+               return -1;
+       }
+
+       status = init_system_info();
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(1, ("ERROR: failed to setup system user info: %s.\n",
+                         nt_errstr(status)));
+               return -1;
+       }
+
+       if (!init_guest_info()) {
+               DEBUG(0,("ERROR: failed to setup guest info.\n"));
+               return -1;
+       }
+
+       if (!file_init(smbd_server_conn)) {
+               DEBUG(0, ("ERROR: file_init failed\n"));
+               return -1;
+       }
+
+       if (!dcesrv_ep_setup(ev_ctx, msg_ctx)) {
+               DEBUG(0, ("Failed to init dcerpc endpoints"));
+               return -1;
+       }
+
+       init_names();
+
+
+       return 0;
+}
+
+/*
+  initialise a server_context from a open socket and register a event handler
+  for reading from that socket
+*/
+static void s3fs_smb_accept(struct stream_connection *conn)
+{
+       if (lpcfg_parm_bool(conn->lp_ctx, NULL, "s3fs", "gdb", false)) {
+               samba_start_debugger();
+               sleep(2);
+       }
+       DEBUG(0,(__location__ ": new s3fs smbd connection\n"));
+
+       if (s3fs_server_init(conn->lp_ctx) != 0) {
+               DEBUG(0,("Failed to initialise s3fs backend\n"));
+               exit(1);
+       }
+
+       smbd_server_conn->sock = socket_get_fd(conn->socket);
+
+       if (!serverid_register(procid_self(),
+                              FLAG_MSG_GENERAL|FLAG_MSG_SMBD
+                              |FLAG_MSG_DBWRAP
+                              |FLAG_MSG_PRINT_GENERAL)) {
+               exit_server_cleanly("Could not register myself in "
+                                   "serverid.tdb");
+       }
+
+       smbd_process(server_event_context(), smbd_server_conn);
+       exit(1);
+}
+
+static const struct stream_server_ops s3fs_smb_stream_ops = {
+       .name                   = "s3fs",
+       .accept_connection      = s3fs_smb_accept,
+};
+
+/*
+  setup a listening socket on all the SMB ports for a particular address
+*/
+static NTSTATUS s3fs_add_socket(struct task_server *task,
+                                 struct tevent_context *event_context,
+                                 struct loadparm_context *lp_ctx,
+                                 const struct model_ops *model_ops,
+                                 const char *address)
+{
+       const char **ports = lpcfg_smb_ports(lp_ctx);
+       int i;
+       NTSTATUS status;
+
+       for (i=0;ports[i];i++) {
+               uint16_t port = atoi(ports[i]);
+               if (port == 0) continue;
+               status = stream_setup_socket(task, event_context, lp_ctx,
+                                            model_ops, &s3fs_smb_stream_ops,
+                                            "ip", address, &port,
+                                            lpcfg_socket_options(lp_ctx),
+                                            NULL);
+               NT_STATUS_NOT_OK_RETURN(status);
+       }
+
+       return NT_STATUS_OK;
+}
+
+/*
+  open the s3 smb server sockets
+*/
+static void s3fs_task_init(struct task_server *task)
+{
+       NTSTATUS status;
+       const struct model_ops *model_ops;
+
+       model_ops = process_model_startup("standard");
+
+       if (model_ops == NULL) {
+               goto failed;
+       }
+
+       task_server_set_title(task, "task[s3fs_parent]");
+
+       if (lpcfg_interfaces(task->lp_ctx) && lpcfg_bind_interfaces_only(task->lp_ctx)) {
+               int num_interfaces;
+               int i;
+               struct interface *ifaces;
+
+               load_interface_list(task, task->lp_ctx, &ifaces);
+
+               num_interfaces = iface_list_count(ifaces);
+
+               /* 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.
+               */
+               for(i = 0; i < num_interfaces; i++) {
+                       const char *address = iface_list_n_ip(ifaces, i);
+                       status = s3fs_add_socket(task, task->event_ctx, task->lp_ctx, model_ops, address);
+                       if (!NT_STATUS_IS_OK(status)) goto failed;
+               }
+       } else {
+               const char **wcard;
+               int i;
+               wcard = iface_list_wildcard(task, task->lp_ctx);
+               if (wcard == NULL) {
+                       DEBUG(0,("No wildcard addresses available\n"));
+                       goto failed;
+               }
+               for (i=0; wcard[i]; i++) {
+                       status = s3fs_add_socket(task, task->event_ctx, task->lp_ctx, model_ops, wcard[i]);
+                       if (!NT_STATUS_IS_OK(status)) goto failed;
+               }
+               talloc_free(wcard);
+       }
+
+       return;
+failed:
+       task_server_terminate(task, "Failed to startup s3fs smb task", true);
+}
+
+/* called at smbd startup - register ourselves as a server service */
+NTSTATUS server_service_s3fs_init(void);
+
+NTSTATUS server_service_s3fs_init(void)
+{
+       return register_server_service("s3fs", s3fs_task_init);
+}
diff --git a/file_server/file_server.h b/file_server/file_server.h
new file mode 100644 (file)
index 0000000..7da9437
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   run s3 file server within Samba4
+
+   Copyright (C) Andrew Tridgell       2011
+
+   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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+  open the s3 smb server sockets
+*/
+void s3_smbd_task_init(struct task_server *task);
diff --git a/file_server/wscript_build b/file_server/wscript_build
new file mode 100644 (file)
index 0000000..5a0c661
--- /dev/null
@@ -0,0 +1,12 @@
+#!/usr/bin/env python
+
+import samba3
+
+bld.SAMBA_MODULE('service_s3fs',
+                 source='file_server.c',
+                 autoproto='file_server_proto.h',
+                 subsystem='service',
+                 init_function='server_service_s3fs_init',
+                 deps='netif samba-hostconfig smbd_base service talloc',
+                 internal_module=False
+                 )
index 52c6d680d739de07301c8071984be4553e4a3e00..a8c02f284d7ec5cf0b19781ef130b7947761d8e6 100644 (file)
@@ -1287,7 +1287,7 @@ sub provision_plugin_s4_dc($$)
        my ($self, $prefix) = @_;
 
        my $extra_smbconf_options = "
-server services = -smb
+server services = +s3fs -smb
 dcerpc endpoint servers = -unixinfo -rpcecho -spoolss -winreg -wkssvc -srvsvc
 ";
 
@@ -1664,12 +1664,7 @@ sub setup_plugin_s4_dc($$)
 
                $self->wait_for_start($env);
 
-               my $s3_part_env = $self->{target3}->setup_plugin_s4_dc($path, $env, 30);
-               if (not defined($s3_part_env)) {
-                   return undef;
-               }
-
-               $self->{vars}->{plugin_s4_dc} = $s3_part_env;
+               $self->{vars}->{plugin_s4_dc} = $env;
        }
        return $env;
 }
index cbbd2cd95e2db409d263c82d3f91ebd022aef1a3..c910b0fd650afe9e34b8c0d148ad5ee04d9b2596 100644 (file)
@@ -33,6 +33,7 @@
 #include "param/share.h"
 #include "dsdb/samdb/samdb.h"
 #include "param/param.h"
+#include "file_server/file_server.h"
 
 /*
   open the smb server sockets
index 5e0c05c216d06add0495e09a3a4d17760d309741..ab6f9be40cbdd61b205ed1b31c9d740f8f920fff 100644 (file)
@@ -119,6 +119,7 @@ bld.RECURSE('lib')
 bld.RECURSE('libds/common')
 bld.RECURSE('source3')
 bld.RECURSE('dfs_server')
+bld.RECURSE('file_server')
 
 bld.RECURSE('testsuite/headers')
 bld.RECURSE('testsuite/libsmbclient/src')