summaryrefslogtreecommitdiff
path: root/source4/smb_server
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2008-10-21 14:51:13 +0200
committerJelmer Vernooij <jelmer@samba.org>2008-10-21 14:51:13 +0200
commit5209a846a9157e649fcdcb561f7eaf19c8c0e465 (patch)
treeb0a7e52b5646c8eec182dbc391e7934b6804488c /source4/smb_server
parent625359b2e266105022309df8985720108ecd6f67 (diff)
parent2ee8d29d22bcb1c350ab59d71b0aee548489bc9c (diff)
downloadsamba-5209a846a9157e649fcdcb561f7eaf19c8c0e465.tar.gz
samba-5209a846a9157e649fcdcb561f7eaf19c8c0e465.tar.bz2
samba-5209a846a9157e649fcdcb561f7eaf19c8c0e465.zip
Merge branch 'master' of ssh://git.samba.org/data/git/samba into regsrv
Conflicts: source4/lib/registry/ldb.c source4/rpc_server/winreg/rpc_winreg.c
Diffstat (limited to 'source4/smb_server')
-rw-r--r--source4/smb_server/blob.c30
-rw-r--r--source4/smb_server/config.mk10
-rw-r--r--source4/smb_server/handle.c2
-rw-r--r--source4/smb_server/session.c2
-rw-r--r--source4/smb_server/smb/request.c7
-rw-r--r--source4/smb_server/smb/sesssetup.c19
-rw-r--r--source4/smb_server/smb/signing.c33
-rw-r--r--source4/smb_server/smb/trans2.c2
-rw-r--r--source4/smb_server/smb2/fileinfo.c2
-rw-r--r--source4/smb_server/smb2/fileio.c6
-rw-r--r--source4/smb_server/smb2/keepalive.c9
-rw-r--r--source4/smb_server/smb2/negprot.c4
-rw-r--r--source4/smb_server/smb2/receive.c41
-rw-r--r--source4/smb_server/smb2/smb2_server.h3
-rw-r--r--source4/smb_server/smb_samba3.c176
-rw-r--r--source4/smb_server/smb_server.h4
-rw-r--r--source4/smb_server/tcon.c2
17 files changed, 292 insertions, 60 deletions
diff --git a/source4/smb_server/blob.c b/source4/smb_server/blob.c
index 368b81d18e..bd250361a4 100644
--- a/source4/smb_server/blob.c
+++ b/source4/smb_server/blob.c
@@ -19,7 +19,7 @@
*/
#include "includes.h"
-#include "lib/util/dlinklist.h"
+#include "../lib/util/dlinklist.h"
#include "smb_server/smb_server.h"
#include "librpc/gen_ndr/ndr_misc.h"
#include "ntvfs/ntvfs.h"
@@ -35,7 +35,7 @@
#define BLOB_CHECK_MIN_SIZE(blob, size) do { \
if ((blob)->length < (size)) { \
- return NT_STATUS_INFO_LENGTH_MISMATCH; \
+ return NT_STATUS_INVALID_PARAMETER; \
} \
} while (0)
@@ -530,13 +530,14 @@ NTSTATUS smbsrv_pull_passthru_sfileinfo(TALLOC_CTX *mem_ctx,
switch (level) {
case SMB_SFILEINFO_BASIC_INFORMATION:
- BLOB_CHECK_MIN_SIZE(blob, 36);
+ BLOB_CHECK_MIN_SIZE(blob, 40);
st->basic_info.in.create_time = pull_nttime(blob->data, 0);
st->basic_info.in.access_time = pull_nttime(blob->data, 8);
st->basic_info.in.write_time = pull_nttime(blob->data, 16);
st->basic_info.in.change_time = pull_nttime(blob->data, 24);
- st->basic_info.in.attrib = IVAL(blob->data, 32);
+ st->basic_info.in.attrib = IVAL(blob->data, 32);
+ st->basic_info.in.reserved = IVAL(blob->data, 36);
return NT_STATUS_OK;
@@ -581,6 +582,27 @@ NTSTATUS smbsrv_pull_passthru_sfileinfo(TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
+
+ case RAW_SFILEINFO_LINK_INFORMATION:
+ if (!bufinfo) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ BLOB_CHECK_MIN_SIZE(blob, 20);
+ st->link_information.in.overwrite = CVAL(blob->data, 0);
+ st->link_information.in.root_fid = IVAL(blob->data, 8);
+ len = IVAL(blob->data, 16);
+ ofs = 20;
+ str_blob = *blob;
+ str_blob.length = MIN(str_blob.length, ofs+len);
+ smbsrv_blob_pull_string(bufinfo, &str_blob, ofs,
+ &st->link_information.in.new_name,
+ STR_UNICODE);
+ if (st->link_information.in.new_name == NULL) {
+ return NT_STATUS_FOOBAR;
+ }
+
+ return NT_STATUS_OK;
+
case RAW_SFILEINFO_RENAME_INFORMATION_SMB2:
/* SMB2 uses a different format for rename information */
if (!bufinfo) {
diff --git a/source4/smb_server/config.mk b/source4/smb_server/config.mk
index e11968a100..6a1a50ffbf 100644
--- a/source4/smb_server/config.mk
+++ b/source4/smb_server/config.mk
@@ -2,13 +2,21 @@
#
[MODULE::SERVICE_SMB]
INIT_FUNCTION = server_service_smb_init
-SUBSYSTEM = smbd
+SUBSYSTEM = samba
PRIVATE_DEPENDENCIES = SMB_SERVER
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 = samba
+
+SERVICE_SAMBA3_SMB_OBJ_FILES = $(smb_serversrcdir)/smb_samba3.o
+
#######################
# Start SUBSYSTEM SMB
[SUBSYSTEM::SMB_SERVER]
diff --git a/source4/smb_server/handle.c b/source4/smb_server/handle.c
index 56f9c5825e..6ee4e163ad 100644
--- a/source4/smb_server/handle.c
+++ b/source4/smb_server/handle.c
@@ -18,7 +18,7 @@
*/
#include "includes.h"
-#include "lib/util/dlinklist.h"
+#include "../lib/util/dlinklist.h"
#include "smb_server/smb_server.h"
#include "ntvfs/ntvfs.h"
diff --git a/source4/smb_server/session.c b/source4/smb_server/session.c
index e7970eb7d5..0e626307d6 100644
--- a/source4/smb_server/session.c
+++ b/source4/smb_server/session.c
@@ -21,7 +21,7 @@
#include "includes.h"
#include "smb_server/smb_server.h"
-#include "lib/util/dlinklist.h"
+#include "../lib/util/dlinklist.h"
/*
diff --git a/source4/smb_server/smb/request.c b/source4/smb_server/smb/request.c
index c7fa2d7d8a..241c262857 100644
--- a/source4/smb_server/smb/request.c
+++ b/source4/smb_server/smb/request.c
@@ -135,7 +135,12 @@ void smbsrv_setup_reply(struct smbsrv_request *req, uint_t wct, size_t buflen)
flags2 = FLAGS2_LONG_PATH_COMPONENTS |
FLAGS2_EXTENDED_ATTRIBUTES |
FLAGS2_IS_LONG_NAME;
- flags2 |= (req->flags2 & (FLAGS2_UNICODE_STRINGS|FLAGS2_EXTENDED_SECURITY));
+#define _SMB_FLAGS2_ECHOED_FLAGS ( \
+ FLAGS2_UNICODE_STRINGS | \
+ FLAGS2_EXTENDED_SECURITY | \
+ FLAGS2_SMB_SECURITY_SIGNATURES \
+)
+ flags2 |= (req->flags2 & _SMB_FLAGS2_ECHOED_FLAGS);
if (req->smb_conn->negotiate.client_caps & CAP_STATUS32) {
flags2 |= FLAGS2_32_BIT_ERROR_CODES;
}
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/trans2.c b/source4/smb_server/smb/trans2.c
index 0e820cfe0e..40ffeeef48 100644
--- a/source4/smb_server/smb/trans2.c
+++ b/source4/smb_server/smb/trans2.c
@@ -21,7 +21,7 @@
*/
#include "includes.h"
-#include "lib/util/dlinklist.h"
+#include "../lib/util/dlinklist.h"
#include "smb_server/smb_server.h"
#include "librpc/gen_ndr/ndr_misc.h"
#include "ntvfs/ntvfs.h"
diff --git a/source4/smb_server/smb2/fileinfo.c b/source4/smb_server/smb2/fileinfo.c
index 6c4b8f33d5..82b006c4a1 100644
--- a/source4/smb_server/smb2/fileinfo.c
+++ b/source4/smb_server/smb2/fileinfo.c
@@ -369,7 +369,7 @@ void smb2srv_setinfo_recv(struct smb2srv_request *req)
SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_setinfo_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
info->in.level = SVAL(req->in.body, 0x02);
- SMB2SRV_CHECK(smb2_pull_s32o32_blob(&req->in, info, req->in.body+0x04, &info->in.blob));
+ SMB2SRV_CHECK(smb2_pull_s32o16_blob(&req->in, info, req->in.body+0x04, &info->in.blob));
info->in.flags = IVAL(req->in.body, 0x0C);
info->in.file.ntvfs = smb2srv_pull_handle(req, req->in.body, 0x10);
diff --git a/source4/smb_server/smb2/fileio.c b/source4/smb_server/smb2/fileio.c
index 2c322ea587..4f4402ba33 100644
--- a/source4/smb_server/smb2/fileio.c
+++ b/source4/smb_server/smb2/fileio.c
@@ -254,6 +254,12 @@ void smb2srv_read_recv(struct smb2srv_request *req)
union smb_read *io;
SMB2SRV_CHECK_BODY_SIZE(req, 0x30, true);
+
+ /* MS-SMB2 2.2.19 read must have a single byte of zero */
+ if (req->in.body_size - req->in.body_fixed < 1) {
+ smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
SMB2SRV_TALLOC_IO_PTR(io, union smb_read);
SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_read_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
diff --git a/source4/smb_server/smb2/keepalive.c b/source4/smb_server/smb2/keepalive.c
index f40bcc485c..ff47d594f0 100644
--- a/source4/smb_server/smb2/keepalive.c
+++ b/source4/smb_server/smb2/keepalive.c
@@ -54,8 +54,13 @@ void smb2srv_keepalive_recv(struct smb2srv_request *req)
{
uint16_t _pad;
- if (req->in.body_size < 0x04) {
- smb2srv_send_error(req, NT_STATUS_FOOBAR);
+ if (req->in.body_size != 0x04) {
+ smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+
+ if (SVAL(req->in.body, 0x00) != 0x04) {
+ smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER);
return;
}
diff --git a/source4/smb_server/smb2/negprot.c b/source4/smb_server/smb2/negprot.c
index d64b36d659..49a2d12ef4 100644
--- a/source4/smb_server/smb2/negprot.c
+++ b/source4/smb_server/smb2/negprot.c
@@ -192,7 +192,7 @@ void smb2srv_negprot_recv(struct smb2srv_request *req)
enum ndr_err_code ndr_err;
if (req->in.body_size < 0x26) {
- smb2srv_send_error(req, NT_STATUS_FOOBAR);
+ smbsrv_terminate_connection(req->smb_conn, "Bad body size in SMB2 negprot");
return;
}
@@ -209,7 +209,7 @@ void smb2srv_negprot_recv(struct smb2srv_request *req)
io->in.capabilities = IVAL(req->in.body, 0x08);
ndr_err = smbcli_pull_guid(req->in.body, 0xC, &io->in.client_guid);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- smbsrv_terminate_connection(req->smb_conn, nt_errstr(NT_STATUS_FOOBAR));
+ smbsrv_terminate_connection(req->smb_conn, "Bad GUID in SMB2 negprot");
talloc_free(req);
return;
}
diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c
index 1fe6f0b877..c3607f0a33 100644
--- a/source4/smb_server/smb2/receive.c
+++ b/source4/smb_server/smb2/receive.c
@@ -153,7 +153,7 @@ static void smb2srv_chain_reply(struct smb2srv_request *p_req)
chain_offset = p_req->chain_offset;
p_req->chain_offset = 0;
- if (p_req->in.size < (NBT_HDR_SIZE + chain_offset + SMB2_MIN_SIZE)) {
+ if (p_req->in.size < (NBT_HDR_SIZE + chain_offset + SMB2_MIN_SIZE_NO_BODY)) {
DEBUG(2,("Invalid SMB2 chained packet at offset 0x%X\n",
chain_offset));
smbsrv_terminate_connection(p_req->smb_conn, "Invalid SMB2 chained packet");
@@ -184,6 +184,19 @@ static void smb2srv_chain_reply(struct smb2srv_request *p_req)
req->in.body_size = req->in.size - (NBT_HDR_SIZE+ chain_offset + SMB2_HDR_BODY);
req->in.dynamic = NULL;
+ req->seqnum = BVAL(req->in.hdr, SMB2_HDR_MESSAGE_ID);
+
+ if (req->in.body_size < 2) {
+ /* error handling for this is different for negprot to
+ other packet types */
+ uint16_t opcode = SVAL(req->in.hdr, SMB2_HDR_OPCODE);
+ if (opcode == SMB2_OP_NEGPROT) {
+ smbsrv_terminate_connection(req->smb_conn, "Bad body size in SMB2 negprot");
+ } else {
+ smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER);
+ }
+ }
+
buffer_code = SVAL(req->in.body, 0);
req->in.body_fixed = (buffer_code & ~1);
dynamic_size = req->in.body_size - req->in.body_fixed;
@@ -290,6 +303,10 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req)
uint64_t uid;
uint32_t flags;
+ if (SVAL(req->in.hdr, SMB2_HDR_LENGTH) != SMB2_HDR_BODY) {
+ smbsrv_terminate_connection(req->smb_conn, "Invalid SMB2 header length");
+ return NT_STATUS_INVALID_PARAMETER;
+ }
opcode = SVAL(req->in.hdr, SMB2_HDR_OPCODE);
req->chain_offset = IVAL(req->in.hdr, SMB2_HDR_NEXT_COMMAND);
req->seqnum = BVAL(req->in.hdr, SMB2_HDR_MESSAGE_ID);
@@ -297,6 +314,13 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req)
uid = BVAL(req->in.hdr, SMB2_HDR_SESSION_ID);
flags = IVAL(req->in.hdr, SMB2_HDR_FLAGS);
+ if (req->smb_conn->highest_smb2_seqnum != 0 &&
+ req->seqnum <= req->smb_conn->highest_smb2_seqnum) {
+ smbsrv_terminate_connection(req->smb_conn, "Invalid SMB2 sequence number");
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ req->smb_conn->highest_smb2_seqnum = req->seqnum;
+
req->session = smbsrv_session_find(req->smb_conn, uid, req->request_time);
req->tcon = smbsrv_smb2_tcon_find(req->session, tid, req->request_time);
@@ -443,7 +467,7 @@ NTSTATUS smbsrv_recv_smb2_request(void *private, DATA_BLOB blob)
return NT_STATUS_OK;
}
- if (blob.length < (NBT_HDR_SIZE + SMB2_MIN_SIZE)) {
+ if (blob.length < (NBT_HDR_SIZE + SMB2_MIN_SIZE_NO_BODY)) {
DEBUG(2,("Invalid SMB2 packet length count %ld\n", (long)blob.length));
smbsrv_terminate_connection(smb_conn, "Invalid SMB2 packet");
return NT_STATUS_OK;
@@ -470,6 +494,19 @@ NTSTATUS smbsrv_recv_smb2_request(void *private, DATA_BLOB blob)
req->in.body_size = req->in.size - (SMB2_HDR_BODY+NBT_HDR_SIZE);
req->in.dynamic = NULL;
+ req->seqnum = BVAL(req->in.hdr, SMB2_HDR_MESSAGE_ID);
+
+ if (req->in.body_size < 2) {
+ /* error handling for this is different for negprot to
+ other packet types */
+ uint16_t opcode = SVAL(req->in.hdr, SMB2_HDR_OPCODE);
+ if (opcode == SMB2_OP_NEGPROT) {
+ smbsrv_terminate_connection(req->smb_conn, "Bad body size in SMB2 negprot");
+ } else {
+ smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER);
+ }
+ }
+
buffer_code = SVAL(req->in.body, 0);
req->in.body_fixed = (buffer_code & ~1);
dynamic_size = req->in.body_size - req->in.body_fixed;
diff --git a/source4/smb_server/smb2/smb2_server.h b/source4/smb_server/smb2/smb2_server.h
index d45e0861af..431add4ed9 100644
--- a/source4/smb_server/smb2/smb2_server.h
+++ b/source4/smb_server/smb2/smb2_server.h
@@ -75,7 +75,7 @@ struct smbsrv_request;
/* useful way of catching field size errors with file and line number */
#define SMB2SRV_CHECK_BODY_SIZE(req, size, dynamic) do { \
size_t is_size = req->in.body_size; \
- uint16_t field_size = SVAL(req->in.body, 0); \
+ uint16_t field_size; \
uint16_t want_size = ((dynamic)?(size)+1:(size)); \
if (is_size < (size)) { \
DEBUG(0,("%s: buffer too small 0x%x. Expected 0x%x\n", \
@@ -83,6 +83,7 @@ struct smbsrv_request;
smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER); \
return; \
}\
+ field_size = SVAL(req->in.body, 0); \
if (field_size != want_size) { \
DEBUG(0,("%s: unexpected fixed body size 0x%x. Expected 0x%x\n", \
__location__, (unsigned)field_size, (unsigned)want_size)); \
diff --git a/source4/smb_server/smb_samba3.c b/source4/smb_server/smb_samba3.c
new file mode 100644
index 0000000000..ea589a0579
--- /dev/null
+++ b/source4/smb_server/smb_samba3.c
@@ -0,0 +1,176 @@
+/*
+ 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;
+ extern char **environ;
+
+ close(0);
+ close(1);
+ dup2(fd, 0);
+ dup2(fd, 1);
+ dup2(fd, 2);
+ for (i=3;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);
+}
diff --git a/source4/smb_server/smb_server.h b/source4/smb_server/smb_server.h
index 4676fc3e9c..e3e55ae040 100644
--- a/source4/smb_server/smb_server.h
+++ b/source4/smb_server/smb_server.h
@@ -23,7 +23,7 @@
#include "libcli/raw/interfaces.h"
#include "lib/events/events.h"
#include "lib/socket/socket.h"
-#include "lib/util/dlinklist.h"
+#include "../lib/util/dlinklist.h"
/*
this header declares the core context structures associated with smb
@@ -386,6 +386,8 @@ struct smbsrv_connection {
struct loadparm_context *lp_ctx;
bool smb2_signing_required;
+
+ uint64_t highest_smb2_seqnum;
};
struct model_ops;
diff --git a/source4/smb_server/tcon.c b/source4/smb_server/tcon.c
index b18901325c..12131ea259 100644
--- a/source4/smb_server/tcon.c
+++ b/source4/smb_server/tcon.c
@@ -20,7 +20,7 @@
*/
#include "includes.h"
-#include "lib/util/dlinklist.h"
+#include "../lib/util/dlinklist.h"
#include "smb_server/smb_server.h"
#include "smbd/service_stream.h"
#include "ntvfs/ntvfs.h"