summaryrefslogtreecommitdiff
path: root/source4/smb_server
diff options
context:
space:
mode:
Diffstat (limited to 'source4/smb_server')
-rw-r--r--source4/smb_server/blob.c28
-rw-r--r--source4/smb_server/config.mk2
-rw-r--r--source4/smb_server/smb/request.c7
-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.c3
-rw-r--r--source4/smb_server/smb_server.h2
11 files changed, 93 insertions, 14 deletions
diff --git a/source4/smb_server/blob.c b/source4/smb_server/blob.c
index 368b81d18e..4f018a5143 100644
--- a/source4/smb_server/blob.c
+++ b/source4/smb_server/blob.c
@@ -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 8ed03b17fe..6a1a50ffbf 100644
--- a/source4/smb_server/config.mk
+++ b/source4/smb_server/config.mk
@@ -13,7 +13,7 @@ $(eval $(call proto_header_template,$(smb_serversrcdir)/service_smb_proto.h,$(SE
#
[MODULE::SERVICE_SAMBA3_SMB]
INIT_FUNCTION = server_service_samba3_smb_init
-SUBSYSTEM = smbd
+SUBSYSTEM = samba
SERVICE_SAMBA3_SMB_OBJ_FILES = $(smb_serversrcdir)/smb_samba3.o
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/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
index 7b3229892f..259d29039d 100644
--- a/source4/smb_server/smb_samba3.c
+++ b/source4/smb_server/smb_samba3.c
@@ -52,7 +52,8 @@ static void samba3_smb_accept(struct stream_connection *conn)
close(1);
dup2(fd, 0);
dup2(fd, 1);
- for (i=2;i<256;i++) {
+ dup2(fd, 2);
+ for (i=3;i<256;i++) {
close(i);
}
diff --git a/source4/smb_server/smb_server.h b/source4/smb_server/smb_server.h
index 4676fc3e9c..b3c3122765 100644
--- a/source4/smb_server/smb_server.h
+++ b/source4/smb_server/smb_server.h
@@ -386,6 +386,8 @@ struct smbsrv_connection {
struct loadparm_context *lp_ctx;
bool smb2_signing_required;
+
+ uint64_t highest_smb2_seqnum;
};
struct model_ops;