diff options
Diffstat (limited to 'source4/smb_server')
-rw-r--r-- | source4/smb_server/config.mk | 8 | ||||
-rw-r--r-- | source4/smb_server/smb/sesssetup.c | 19 | ||||
-rw-r--r-- | source4/smb_server/smb/signing.c | 33 | ||||
-rw-r--r-- | source4/smb_server/smb_samba3.c | 174 |
4 files changed, 193 insertions, 41 deletions
diff --git a/source4/smb_server/config.mk b/source4/smb_server/config.mk index e11968a100..d1ec6d49e8 100644 --- a/source4/smb_server/config.mk +++ b/source4/smb_server/config.mk @@ -9,6 +9,14 @@ SERVICE_SMB_OBJ_FILES = $(smb_serversrcdir)/smb_server.o $(eval $(call proto_header_template,$(smb_serversrcdir)/service_smb_proto.h,$(SERVICE_SMB_OBJ_FILES:.o=.c))) +# samba3 SMB server subsystem +# +[MODULE::SERVICE_SAMBA3_SMB] +INIT_FUNCTION = server_service_samba3_smb_init +SUBSYSTEM = smbd + +SERVICE_SAMBA3_SMB_OBJ_FILES = $(smb_serversrcdir)/smb_samba3.o + ####################### # Start SUBSYSTEM SMB [SUBSYSTEM::SMB_SERVER] diff --git a/source4/smb_server/smb/sesssetup.c b/source4/smb_server/smb/sesssetup.c index f45cbf1756..a12bbd5cec 100644 --- a/source4/smb_server/smb/sesssetup.c +++ b/source4/smb_server/smb/sesssetup.c @@ -193,16 +193,6 @@ static void sesssetup_nt1_send(struct auth_check_password_request *areq, goto done; } - /* Force check of the request packet, now we know the session key */ - smbsrv_signing_check_incoming(req); -/* TODO: why don't we check the result here? */ - - /* Unfortunetly win2k3 as a client doesn't sign the request - * packet here, so we have to force signing to start again */ - - smbsrv_signing_restart(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2, - session_info->server_info->authenticated); - done: status = NT_STATUS_OK; failed: @@ -321,13 +311,8 @@ static void sesssetup_spnego_send(struct gensec_update_request *greq, void *priv if (!NT_STATUS_IS_OK(status)) goto failed; skey_status = gensec_session_key(smb_sess->gensec_ctx, &session_key); - if (NT_STATUS_IS_OK(skey_status) && - smbsrv_setup_signing(req->smb_conn, &session_key, NULL)) { - /* Force check of the request packet, now we know the session key */ - smbsrv_signing_check_incoming(req); - - smbsrv_signing_restart(req->smb_conn, &session_key, NULL, - session_info->server_info->authenticated); + if (NT_STATUS_IS_OK(skey_status)) { + smbsrv_setup_signing(req->smb_conn, &session_key, NULL); } /* Ensure this is marked as a 'real' vuid, not one diff --git a/source4/smb_server/smb/signing.c b/source4/smb_server/smb/signing.c index ee4531c8f6..0b5cf56fdb 100644 --- a/source4/smb_server/smb/signing.c +++ b/source4/smb_server/smb/signing.c @@ -75,30 +75,6 @@ bool smbsrv_setup_signing(struct smbsrv_connection *smb_conn, &smb_conn->signing, session_key, response); } -void smbsrv_signing_restart(struct smbsrv_connection *smb_conn, - DATA_BLOB *session_key, - DATA_BLOB *response, - bool authenticated_session) -{ - if (!smb_conn->signing.seen_valid) { - DEBUG(5, ("Client did not send a valid signature on " - "SPNEGO session setup - ignored, expect good next time\n")); - /* force things back on (most clients do not sign this packet)... */ - smbsrv_setup_signing(smb_conn, session_key, response); - smb_conn->signing.next_seq_num = 2; - - /* If mandetory_signing is set, and this was an authenticated logon, then force on */ - if (smb_conn->signing.mandatory_signing && authenticated_session) { - DEBUG(5, ("Configured for mandatory signing, 'good packet seen' forced on\n")); - /* if this is mandatory, then - * pretend we have seen a - * valid packet, so we don't - * turn it off */ - smb_conn->signing.seen_valid = true; - } - } -} - bool smbsrv_init_signing(struct smbsrv_connection *smb_conn) { smb_conn->signing.mac_key = data_blob(NULL, 0); @@ -118,10 +94,19 @@ bool smbsrv_init_signing(struct smbsrv_connection *smb_conn) smb_conn->signing.mandatory_signing = true; break; case SMB_SIGNING_AUTO: + /* If we are a domain controller, SMB signing is + * really important, as it can prevent a number of + * attacks on communications between us and the + * clients */ + if (lp_server_role(smb_conn->lp_ctx) == ROLE_DOMAIN_CONTROLLER) { smb_conn->signing.allow_smb_signing = true; smb_conn->signing.mandatory_signing = true; } else { + /* However, it really sucks (no sendfile, CPU + * overhead) performance-wise when used on a + * file server, so disable it by default (auto + * is the default) on non-DCs */ smb_conn->signing.allow_smb_signing = false; } break; diff --git a/source4/smb_server/smb_samba3.c b/source4/smb_server/smb_samba3.c new file mode 100644 index 0000000000..7b3229892f --- /dev/null +++ b/source4/smb_server/smb_samba3.c @@ -0,0 +1,174 @@ +/* + Unix SMB/CIFS implementation. + + process incoming connections and fork a samba3 in inetd mode + + Copyright (C) Stefan Metzmacher 2008 + + 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 "includes.h" +#include "smbd/service_task.h" +#include "smbd/service_stream.h" +#include "smbd/service.h" +#include "lib/messaging/irpc.h" +#include "lib/stream/packet.h" +#include "lib/socket/socket.h" +#include "libcli/smb2/smb2.h" +#include "smb_server/smb2/smb2_server.h" +#include "system/network.h" +#include "lib/socket/netif.h" +#include "param/share.h" +#include "dsdb/samdb/samdb.h" +#include "param/param.h" +#include "dynconfig/dynconfig.h" +#include "smbd/process_model.h" + +/* + initialise a server_context from a open socket and register a event handler + for reading from that socket +*/ +static void samba3_smb_accept(struct stream_connection *conn) +{ + int i; + int fd = socket_get_fd(conn->socket); + const char *prog; + char *argv[2]; + char *reason; + + close(0); + close(1); + dup2(fd, 0); + dup2(fd, 1); + for (i=2;i<256;i++) { + close(i); + } + + prog = lp_parm_string(conn->lp_ctx, NULL, "samba3", "smbd"); + + if (prog == NULL) { + argv[0] = talloc_asprintf(conn, "%s/%s", dyn_BINDIR, "smbd3"); + } + else { + argv[0] = talloc_strdup(conn, prog); + } + + if (argv[0] == NULL) { + stream_terminate_connection(conn, "out of memory"); + return; + } + argv[1] = NULL; + + execve(argv[0], argv, environ); + + /* + * Should never get here + */ + reason = talloc_asprintf(conn, "Could not execute %s", argv[0]); + if (reason == NULL) { + stream_terminate_connection(conn, "out of memory"); + return; + } + stream_terminate_connection(conn, reason); + talloc_free(reason); +} + +static const struct stream_server_ops samba3_smb_stream_ops = { + .name = "samba3", + .accept_connection = samba3_smb_accept, +}; + +/* + setup a listening socket on all the SMB ports for a particular address +*/ +static NTSTATUS samba3_add_socket(struct event_context *event_context, + struct loadparm_context *lp_ctx, + const struct model_ops *model_ops, + const char *address) +{ + const char **ports = lp_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(event_context, lp_ctx, + model_ops, &samba3_smb_stream_ops, + "ip", address, &port, + lp_socket_options(lp_ctx), + NULL); + NT_STATUS_NOT_OK_RETURN(status); + } + + return NT_STATUS_OK; +} + + +/* + open the smb server sockets +*/ +static void samba3_smb_task_init(struct task_server *task) +{ + NTSTATUS status; + const struct model_ops *model_ops; + + model_ops = process_model_startup(task->event_ctx, "standard"); + + if (model_ops == NULL) { + goto failed; + } + + task_server_set_title(task, "task[samba3_smb]"); + + if (lp_interfaces(task->lp_ctx) + && lp_bind_interfaces_only(task->lp_ctx)) { + int num_interfaces; + int i; + struct interface *ifaces; + + load_interfaces(task, lp_interfaces(task->lp_ctx), &ifaces); + + num_interfaces = iface_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_n_ip(ifaces, i); + status = samba3_add_socket(task->event_ctx, + task->lp_ctx, + model_ops, address); + if (!NT_STATUS_IS_OK(status)) goto failed; + } + } else { + /* Just bind to lp_socket_address() (usually 0.0.0.0) */ + status = samba3_add_socket(task->event_ctx, task->lp_ctx, + model_ops, + lp_socket_address(task->lp_ctx)); + if (!NT_STATUS_IS_OK(status)) goto failed; + } + + return; +failed: + task_server_terminate(task, "Failed to startup samba3 smb task"); +} + +/* called at smbd startup - register ourselves as a server service */ +NTSTATUS server_service_samba3_smb_init(void) +{ + return register_server_service("samba3_smb", samba3_smb_task_init); +} |