From 3ba41cbd766a6f299b4d6454a2f5b4f55b36cee5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 3 May 2011 09:35:07 +1000 Subject: [PATCH] s3fs: added file_server directory this contains a file server backend that uses the smbd_base library from the s3 core code Pair-Programmed-With: Andrew Bartlett --- file_server/file_server.c | 364 +++++++++++++++++++++++++++++++ file_server/file_server.h | 25 +++ file_server/wscript_build | 12 + selftest/target/Samba4.pm | 9 +- source4/smb_server/service_smb.c | 1 + wscript_build | 1 + 6 files changed, 405 insertions(+), 7 deletions(-) create mode 100644 file_server/file_server.c create mode 100644 file_server/file_server.h create mode 100644 file_server/wscript_build diff --git a/file_server/file_server.c b/file_server/file_server.c new file mode 100644 index 0000000000..5dd26f7081 --- /dev/null +++ b/file_server/file_server.c @@ -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 . +*/ + +#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 index 0000000000..7da9437f57 --- /dev/null +++ b/file_server/file_server.h @@ -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 . +*/ + +/* + 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 index 0000000000..5a0c661ce5 --- /dev/null +++ b/file_server/wscript_build @@ -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 + ) diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 52c6d680d7..a8c02f284d 100644 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -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; } diff --git a/source4/smb_server/service_smb.c b/source4/smb_server/service_smb.c index cbbd2cd95e..c910b0fd65 100644 --- a/source4/smb_server/service_smb.c +++ b/source4/smb_server/service_smb.c @@ -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 diff --git a/wscript_build b/wscript_build index 5e0c05c216..ab6f9be40c 100644 --- a/wscript_build +++ b/wscript_build @@ -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') -- 2.34.1