Patches: Fix bug 10106
Volker Lendecke
Volker.Lendecke at SerNet.DE
Tue Aug 27 08:11:01 MDT 2013
Hi!
Attached find a bugfix that intends to fix bug 10106.
Please review & push.
Thanks,
Volker
--
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
*****************************************************************
visit us on it-sa:IT security exhibitions in Nürnberg, Germany
October 8th - 10th 2013, hall 12, booth 333
free tickets available via code 270691 on: www.it-sa.de/gutschein
******************************************************************
-------------- next part --------------
From 2352c090cfc12cac26d5bbc8ca509869cf86c6a1 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 23 Aug 2013 13:57:03 +0000
Subject: [PATCH 1/9] torture3: add clipathinfo-bufsize
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/torture/proto.h | 1 +
source3/torture/test_buffersize.c | 56 +++++++++++++++++++++++++++++++++++++++
source3/torture/torture.c | 1 +
source3/wscript_build | 1 +
4 files changed, 59 insertions(+)
create mode 100644 source3/torture/test_buffersize.c
diff --git a/source3/torture/proto.h b/source3/torture/proto.h
index 4f4c9e2..f6453fd 100644
--- a/source3/torture/proto.h
+++ b/source3/torture/proto.h
@@ -111,5 +111,6 @@ bool run_notify_bench3(int dummy);
bool run_dbwrap_watch1(int dummy);
bool run_idmap_tdb_common_test(int dummy);
bool run_local_dbwrap_ctdb(int dummy);
+bool run_qpathinfo_bufsize(int dummy);
#endif /* __TORTURE_H__ */
diff --git a/source3/torture/test_buffersize.c b/source3/torture/test_buffersize.c
new file mode 100644
index 0000000..6e86374
--- /dev/null
+++ b/source3/torture/test_buffersize.c
@@ -0,0 +1,56 @@
+/*
+ Unix SMB/CIFS implementation.
+ Test buffer sizes in cli_qpathinfo
+ Copyright (C) Volker Lendecke 2012
+
+ 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 "torture/proto.h"
+#include "libsmb/libsmb.h"
+#include "libcli/security/dom_sid.h"
+#include "libcli/security/secdesc.h"
+#include "libcli/security/security.h"
+#include "trans2.h"
+#include "source3/libsmb/clirap.h"
+
+bool run_qpathinfo_bufsize(int dummy)
+{
+ struct cli_state *cli = NULL;
+ NTSTATUS status, status2;
+ bool ret = false;
+ int i;
+
+ printf("Starting qpathinfo_bufsize\n");
+
+ if (!torture_open_connection(&cli, 0)) {
+ printf("torture_open_connection failed\n");
+ goto fail;
+ }
+
+ for (i=0; i<500; i++) {
+ uint8_t *rdata;
+ uint32_t num_rdata;
+ cli_qpathinfo(cli, cli, "\\", SMB_FILE_ALL_INFORMATION,
+ 0, i, &rdata, &num_rdata);
+ }
+
+ ret = true;
+fail:
+ if (cli != NULL) {
+ torture_close_connection(cli);
+ }
+ return ret;
+}
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 4a8e3ed..359baa9 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -9579,6 +9579,7 @@ static struct {
{ "local-tdb-opener", run_local_tdb_opener, 0 },
{ "local-tdb-writer", run_local_tdb_writer, 0 },
{ "LOCAL-DBWRAP-CTDB", run_local_dbwrap_ctdb, 0 },
+ { "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 },
{NULL, NULL, 0}};
/*
diff --git a/source3/wscript_build b/source3/wscript_build
index e166b16..e4417ea 100755
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -560,6 +560,7 @@ SMBTORTURE_SRC1 = '''torture/torture.c torture/nbio.c torture/scanner.c torture/
torture/test_dbwrap_watch.c
torture/test_idmap_tdb_common.c
torture/test_dbwrap_ctdb.c
+ torture/test_buffersize.c
torture/t_strappend.c'''
SMBTORTURE_SRC = '''${SMBTORTURE_SRC1}
--
1.8.1.2
From 162d375a0eba714e28689c9a9fca310d46874776 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 27 Aug 2013 09:06:27 +0000
Subject: [PATCH 2/9] smbd: qfilepathinfo has fixed/variable buffers
The error message will have to change depending whether the buffer is
too small for the fixed or variable buffers
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10106
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/smbd/globals.h | 1 +
source3/smbd/smb2_getinfo.c | 2 ++
source3/smbd/trans2.c | 22 ++++++++++++++++++++++
3 files changed, 25 insertions(+)
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index d618aea..6ccb57e 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -138,6 +138,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
char *lock_data,
uint16_t flags2,
unsigned int max_data_bytes,
+ size_t *fixed_portion,
char **ppdata,
unsigned int *pdata_size);
diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c
index 4420f94..0d75c36 100644
--- a/source3/smbd/smb2_getinfo.c
+++ b/source3/smbd/smb2_getinfo.c
@@ -293,6 +293,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
struct ea_list *ea_list = NULL;
int lock_data_count = 0;
char *lock_data = NULL;
+ size_t fixed_portion;
ZERO_STRUCT(write_time_ts);
@@ -380,6 +381,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
lock_data,
STR_UNICODE,
in_output_buffer_length,
+ &fixed_portion,
&data,
&data_size);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index b6cb3cc..1d55dbe 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -4388,6 +4388,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
char *lock_data,
uint16_t flags2,
unsigned int max_data_bytes,
+ size_t *fixed_portion,
char **ppdata,
unsigned int *pdata_size)
{
@@ -4528,6 +4529,8 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
BasicFileInformationTest. -tpot */
file_index = get_FileIndex(conn, psbuf);
+ *fixed_portion = 0;
+
switch (info_level) {
case SMB_INFO_STANDARD:
DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
@@ -4674,6 +4677,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
DEBUG(5,("write: %s ", ctime(&mtime)));
DEBUG(5,("change: %s ", ctime(&c_time)));
DEBUG(5,("mode: %x\n", mode));
+ *fixed_portion = data_size;
break;
case SMB_FILE_STANDARD_INFORMATION:
@@ -4687,6 +4691,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
SCVAL(pdata,20,delete_pending?1:0);
SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
SSVAL(pdata,22,0); /* Padding. */
+ *fixed_portion = 24;
break;
case SMB_FILE_EA_INFORMATION:
@@ -4696,6 +4701,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
estimate_ea_size(conn, fsp, smb_fname);
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
data_size = 4;
+ *fixed_portion = 4;
SIVAL(pdata,0,ea_size);
break;
}
@@ -4717,6 +4723,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
STR_UNICODE);
data_size = 4 + len;
SIVAL(pdata,0,len);
+ *fixed_portion = 8;
break;
}
@@ -4780,6 +4787,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
SIVAL(pdata,0,len);
pdata += 4 + len;
data_size = PTR_DIFF(pdata,(*ppdata));
+ *fixed_portion = 10;
break;
}
@@ -4817,6 +4825,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
SIVAL(pdata,0,len);
pdata += 4 + len;
data_size = PTR_DIFF(pdata,(*ppdata));
+ *fixed_portion = 104;
break;
}
case SMB_FILE_INTERNAL_INFORMATION:
@@ -4824,12 +4833,14 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
SBVAL(pdata, 0, file_index);
data_size = 8;
+ *fixed_portion = 8;
break;
case SMB_FILE_ACCESS_INFORMATION:
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
SIVAL(pdata, 0, access_mask);
data_size = 4;
+ *fixed_portion = 4;
break;
case SMB_FILE_NAME_INFORMATION:
@@ -4847,24 +4858,28 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
data_size = 1;
SCVAL(pdata,0,delete_pending);
+ *fixed_portion = 1;
break;
case SMB_FILE_POSITION_INFORMATION:
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
data_size = 8;
SOFF_T(pdata,0,pos);
+ *fixed_portion = 8;
break;
case SMB_FILE_MODE_INFORMATION:
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
SIVAL(pdata,0,mode);
data_size = 4;
+ *fixed_portion = 4;
break;
case SMB_FILE_ALIGNMENT_INFORMATION:
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
SIVAL(pdata,0,0); /* No alignment needed. */
data_size = 4;
+ *fixed_portion = 4;
break;
/*
@@ -4909,6 +4924,8 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
TALLOC_FREE(streams);
+ *fixed_portion = 32;
+
break;
}
case SMB_QUERY_COMPRESSION_INFO:
@@ -4918,6 +4935,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
SIVAL(pdata,8,0); /* ??? */
SIVAL(pdata,12,0); /* ??? */
data_size = 16;
+ *fixed_portion = 16;
break;
case SMB_FILE_NETWORK_OPEN_INFORMATION:
@@ -4931,6 +4949,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
SIVAL(pdata,48,mode);
SIVAL(pdata,52,0); /* ??? */
data_size = 56;
+ *fixed_portion = 56;
break;
case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
@@ -4938,6 +4957,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
SIVAL(pdata,0,mode);
SIVAL(pdata,4,0);
data_size = 8;
+ *fixed_portion = 8;
break;
/*
@@ -5211,6 +5231,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
struct ea_list *ea_list = NULL;
int lock_data_count = 0;
char *lock_data = NULL;
+ size_t fixed_portion;
NTSTATUS status = NT_STATUS_OK;
if (!params) {
@@ -5570,6 +5591,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
ea_list,
lock_data_count, lock_data,
req->flags2, max_data_bytes,
+ &fixed_portion,
ppdata, &data_size);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
--
1.8.1.2
From 20af936c60f19b8c87845e83a0ec04739a632fea Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 27 Aug 2013 09:06:27 +0000
Subject: [PATCH 3/9] smbd: qfsinfo has fixed/variable buffers
The error message will have to change depending whether the buffer is
too small for the fixed or variable buffers
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10106
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/smbd/globals.h | 1 +
source3/smbd/smb2_getinfo.c | 2 ++
source3/smbd/trans2.c | 10 ++++++++++
3 files changed, 13 insertions(+)
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 6ccb57e..9ea5e25 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -156,6 +156,7 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
uint16_t info_level,
uint16_t flags2,
unsigned int max_data_bytes,
+ size_t *fixed_portion,
struct smb_filename *smb_fname,
char **ppdata,
int *ret_data_len);
diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c
index 0d75c36..698e775 100644
--- a/source3/smbd/smb2_getinfo.c
+++ b/source3/smbd/smb2_getinfo.c
@@ -410,6 +410,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
uint16_t file_info_level;
char *data = NULL;
int data_size = 0;
+ size_t fixed_portion;
/* the levels directly map to the passthru levels */
file_info_level = in_file_info_class + 1000;
@@ -418,6 +419,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
file_info_level,
STR_UNICODE,
in_output_buffer_length,
+ &fixed_portion,
fsp->fsp_name,
&data,
&data_size);
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 1d55dbe..37f578c 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -3068,6 +3068,7 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
uint16_t info_level,
uint16_t flags2,
unsigned int max_data_bytes,
+ size_t *fixed_portion,
struct smb_filename *fname,
char **ppdata,
int *ret_data_len)
@@ -3124,6 +3125,8 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
+ *fixed_portion = 0;
+
switch (info_level) {
case SMB_INFO_ALLOCATION:
{
@@ -3222,6 +3225,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
data_len = max_data_bytes;
status = STATUS_BUFFER_OVERFLOW;
}
+ *fixed_portion = 16;
break;
case SMB_QUERY_FS_LABEL_INFO:
@@ -3258,6 +3262,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
data_len = max_data_bytes;
status = STATUS_BUFFER_OVERFLOW;
}
+ *fixed_portion = 24;
break;
case SMB_QUERY_FS_SIZE_INFO:
@@ -3290,6 +3295,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
SBIG_UINT(pdata,8,dfree);
SIVAL(pdata,16,sectors_per_unit);
SIVAL(pdata,20,bytes_per_sector);
+ *fixed_portion = 24;
break;
}
@@ -3323,6 +3329,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
+ *fixed_portion = 32;
break;
}
@@ -3337,6 +3344,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
data_len = 8;
SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
SIVAL(pdata,4,characteristics);
+ *fixed_portion = 8;
break;
}
@@ -3645,6 +3653,7 @@ static void call_trans2qfsinfo(connection_struct *conn,
char *params = *pparams;
uint16_t info_level;
int data_len = 0;
+ size_t fixed_portion;
NTSTATUS status;
if (total_params < 2) {
@@ -3670,6 +3679,7 @@ static void call_trans2qfsinfo(connection_struct *conn,
info_level,
req->flags2,
max_data_bytes,
+ &fixed_portion,
NULL,
ppdata, &data_len);
if (!NT_STATUS_IS_OK(status)) {
--
1.8.1.2
From fcfeae27971998996ced138a8d456a9ba257e7df Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 27 Aug 2013 09:36:03 +0000
Subject: [PATCH 4/9] smbd: Correctly return INFO_LENGTH_MISMATCH in
smb2_getinfo
We have to return this error if the client offered less than the fixed
portion of the infolevel data requires
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10106
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/smbd/smb2_getinfo.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c
index 698e775..c6a1433 100644
--- a/source3/smbd/smb2_getinfo.c
+++ b/source3/smbd/smb2_getinfo.c
@@ -392,6 +392,12 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
tevent_req_nterror(req, status);
return tevent_req_post(req, ev);
}
+ if (in_output_buffer_length < fixed_portion) {
+ SAFE_FREE(data);
+ tevent_req_nterror(
+ req, NT_STATUS_INFO_LENGTH_MISMATCH);
+ return tevent_req_post(req, ev);
+ }
if (data_size > 0) {
state->out_output_buffer = data_blob_talloc(state,
data,
@@ -434,6 +440,12 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
tevent_req_nterror(req, status);
return tevent_req_post(req, ev);
}
+ if (in_output_buffer_length < fixed_portion) {
+ SAFE_FREE(data);
+ tevent_req_nterror(
+ req, NT_STATUS_INFO_LENGTH_MISMATCH);
+ return tevent_req_post(req, ev);
+ }
if (data_size > 0) {
state->out_output_buffer = data_blob_talloc(state,
data,
--
1.8.1.2
From d673650e6cca75e81d29705c0c358b5e95fdea7d Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 27 Aug 2013 09:37:34 +0000
Subject: [PATCH 5/9] smbd: Correctly return BUFFER_OVERFLOW in smb2_getinfo
Also, don't overflow the client buffer
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10106
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/smbd/smb2_getinfo.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c
index c6a1433..4111aa1 100644
--- a/source3/smbd/smb2_getinfo.c
+++ b/source3/smbd/smb2_getinfo.c
@@ -406,6 +406,11 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
if (tevent_req_nomem(state->out_output_buffer.data, req)) {
return tevent_req_post(req, ev);
}
+ if (data_size > in_output_buffer_length) {
+ state->out_output_buffer.length =
+ in_output_buffer_length;
+ status = STATUS_BUFFER_OVERFLOW;
+ }
}
SAFE_FREE(data);
break;
@@ -454,6 +459,11 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
if (tevent_req_nomem(state->out_output_buffer.data, req)) {
return tevent_req_post(req, ev);
}
+ if (data_size > in_output_buffer_length) {
+ state->out_output_buffer.length =
+ in_output_buffer_length;
+ status = STATUS_BUFFER_OVERFLOW;
+ }
}
SAFE_FREE(data);
break;
--
1.8.1.2
From c80e601606d9d8771a9dd5f0f12f55392d7c6932 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 27 Aug 2013 09:38:29 +0000
Subject: [PATCH 6/9] smbd: Revert a93f9c3
This was too broad and has been replaced by finer-grained error checks
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10106
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/smbd/smb2_getinfo.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c
index 4111aa1..449aeb3 100644
--- a/source3/smbd/smb2_getinfo.c
+++ b/source3/smbd/smb2_getinfo.c
@@ -530,11 +530,6 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
- if (state->out_output_buffer.length > in_output_buffer_length) {
- tevent_req_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
- return tevent_req_post(req, ev);
- }
-
state->status = status;
tevent_req_done(req);
return tevent_req_post(req, ev);
--
1.8.1.2
From 61b44463894bd269363714efb12042415f7f76c1 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 27 Aug 2013 09:39:17 +0000
Subject: [PATCH 7/9] smbd: Fix error return for STREAM_INFO
The stream_info marshalling follows its own rules. This needs unifying
eventually...
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10106
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/smbd/trans2.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 37f578c..576e289 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -4243,6 +4243,10 @@ static NTSTATUS marshall_stream_info(unsigned int num_streams,
unsigned int i;
unsigned int ofs = 0;
+ if (max_data_bytes < 32) {
+ return NT_STATUS_INFO_LENGTH_MISMATCH;
+ }
+
for (i = 0; i < num_streams; i++) {
unsigned int next_offset;
size_t namelen;
--
1.8.1.2
From a4f50ecf003a48dccc51e5208cea4154e7e3646f Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 27 Aug 2013 09:40:19 +0000
Subject: [PATCH 8/9] smbd: Correctly return INFO_LENGTH_MISMATCH for smb1
This is required if the client offered less buffer than the fixed portion
of the info level data requires
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10106
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/smbd/trans2.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 576e289..aaf0e62 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -5611,6 +5611,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
reply_nterror(req, status);
return;
}
+ if (fixed_portion > max_data_bytes) {
+ reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
+ return;
+ }
send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
max_data_bytes);
--
1.8.1.2
From 01827c0bbbfbc360f5e7c98eeabf19039b0588f6 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 27 Aug 2013 09:41:13 +0000
Subject: [PATCH 9/9] torture: Add buffercheck tests
Make sure we get the smb2 infolevel fixed portions right
I could not find correct #defines for the infolevels
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10106
Signed-off-by: Volker Lendecke <vl at samba.org>
---
selftest/knownfail | 3 +
source4/torture/smb2/getinfo.c | 244 ++++++++++++++++++++++++++++++++++++++---
2 files changed, 229 insertions(+), 18 deletions(-)
diff --git a/selftest/knownfail b/selftest/knownfail
index dd536df..6fe7ce5 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -171,6 +171,9 @@
^samba4.smb2.oplock.batch20\(.*\)$ # samba 4 oplocks are a mess
^samba4.smb2.oplock.stream1 # samba 4 oplocks are a mess
^samba4.smb2.getinfo.complex # streams on directories does not work
+^samba4.smb2.getinfo.qfs_buffercheck # S4 does not do the INFO_LENGTH_MISMATCH/BUFFER_OVERFLOW thingy
+^samba4.smb2.getinfo.qfile_buffercheck # S4 does not do the INFO_LENGTH_MISMATCH/BUFFER_OVERFLOW thingy
+^samba4.smb2.getinfo.qsec_buffercheck # S4 does not do the BUFFER_TOO_SMALL thingy
^samba4.ntvfs.cifs.krb5.base.createx_access.createx_access\(.*\)$
^samba4.rpc.lsa.forest.trust #Not fully provided by Samba4
^samba4.blackbox.kinit\(.*\).kinit with user password for expired password\(.*\) # We need to work out why this fails only during the pw change
diff --git a/source4/torture/smb2/getinfo.c b/source4/torture/smb2/getinfo.c
index 10dd550..fafc36c 100644
--- a/source4/torture/smb2/getinfo.c
+++ b/source4/torture/smb2/getinfo.c
@@ -22,9 +22,11 @@
#include "includes.h"
#include "libcli/smb2/smb2.h"
#include "libcli/smb2/smb2_calls.h"
+#include "libcli/smb/smbXcli_base.h"
#include "torture/torture.h"
#include "torture/smb2/proto.h"
+#include "torture/util.h"
static struct {
const char *name;
@@ -154,41 +156,243 @@ static bool torture_smb2_fsinfo(struct torture_context *tctx)
return true;
}
+static bool torture_smb2_buffercheck_err(struct torture_context *tctx,
+ struct smb2_tree *tree,
+ struct smb2_getinfo *b,
+ size_t fixed,
+ DATA_BLOB full)
+{
+ size_t i;
-/*
- test for buffer size handling
-*/
-static bool torture_smb2_buffercheck(struct torture_context *tctx)
+ for (i=0; i<=full.length; i++) {
+ NTSTATUS status;
+
+ b->in.output_buffer_length = i;
+
+ status = smb2_getinfo(tree, tree, b);
+
+ if (i < fixed) {
+ torture_assert_ntstatus_equal(
+ tctx, status, NT_STATUS_INFO_LENGTH_MISMATCH,
+ "Wrong error code small buffer");
+ continue;
+ }
+
+ if (i<full.length) {
+ torture_assert_ntstatus_equal(
+ tctx, status, STATUS_BUFFER_OVERFLOW,
+ "Wrong error code for large buffer");
+ /*
+ * TODO: compare the output buffer. That seems a bit
+ * difficult, because for level 5 for example the
+ * label length is adjusted to what is there. And some
+ * reserved fields seem to be not initialized to 0.
+ */
+ TALLOC_FREE(b->out.blob.data);
+ continue;
+ }
+
+ torture_assert_ntstatus_equal(
+ tctx, status, NT_STATUS_OK,
+ "Wrong error code for right sized buffer");
+ }
+
+ return true;
+}
+
+struct level_buffersize {
+ int level;
+ size_t fixed;
+};
+
+static bool torture_smb2_qfs_buffercheck(struct torture_context *tctx)
{
bool ret;
struct smb2_tree *tree;
NTSTATUS status;
struct smb2_handle handle;
- struct smb2_getinfo b;
+ int i;
+
+ struct level_buffersize levels[] = {
+ { 1, 24 }, /* We don't have proper defines here */
+ { 3, 24 },
+ { 4, 8 },
+ { 5, 16 },
+ { 6, 48 },
+ { 7, 32 },
+ { 11, 28 },
+ };
- printf("Testing buffer size handling\n");
+ printf("Testing SMB2_GETINFO_FS buffer sizes\n");
ret = torture_smb2_connection(tctx, &tree);
torture_assert(tctx, ret, "connection failed");
status = smb2_util_roothandle(tree, &handle);
- torture_assert_ntstatus_ok(tctx, status, "Unable to create root handle");
+ torture_assert_ntstatus_ok(
+ tctx, status, "Unable to create root handle");
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+ struct smb2_getinfo b;
+
+ if (TARGET_IS_SAMBA3(tctx) &&
+ ((levels[i].level == 6) || (levels[i].level == 11))) {
+ continue;
+ }
+
+ ZERO_STRUCT(b);
+ b.in.info_type = SMB2_GETINFO_FS;
+ b.in.info_class = levels[i].level;
+ b.in.file.handle = handle;
+ b.in.output_buffer_length = 65535;
+
+ status = smb2_getinfo(tree, tree, &b);
+
+ torture_assert_ntstatus_equal(
+ tctx, status, NT_STATUS_OK,
+ "Wrong error code for large buffer");
+
+ ret = torture_smb2_buffercheck_err(
+ tctx, tree, &b, levels[i].fixed, b.out.blob);
+ if (!ret) {
+ return ret;
+ }
+ }
+
+ return true;
+}
+
+static bool torture_smb2_qfile_buffercheck(struct torture_context *tctx)
+{
+ bool ret;
+ struct smb2_tree *tree;
+ struct smb2_create c;
+ NTSTATUS status;
+ struct smb2_handle handle;
+ int i;
+
+ struct level_buffersize levels[] = {
+ { 4, 40 },
+ { 5, 24 },
+ { 6, 8 },
+ { 7, 4 },
+ { 8, 4 },
+ { 16, 4 },
+ { 17, 4 },
+ { 18, 104 },
+ { 21, 8 },
+ { 22, 32 },
+ { 28, 16 },
+ { 34, 56 },
+ { 35, 8 },
+ };
+
+ printf("Testing SMB2_GETINFO_FILE buffer sizes\n");
+
+ ret = torture_smb2_connection(tctx, &tree);
+ torture_assert(tctx, ret, "connection failed");
+
+ ZERO_STRUCT(c);
+ c.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
+ c.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ c.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
+ c.in.share_access =
+ NTCREATEX_SHARE_ACCESS_DELETE|
+ NTCREATEX_SHARE_ACCESS_READ|
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ c.in.create_options = 0;
+ c.in.fname = "bufsize.txt";
+
+ c.in.eas.num_eas = 2;
+ c.in.eas.eas = talloc_array(tree, struct ea_struct, 2);
+ c.in.eas.eas[0].flags = 0;
+ c.in.eas.eas[0].name.s = "EAONE";
+ c.in.eas.eas[0].value = data_blob_talloc(c.in.eas.eas, "VALUE1", 6);
+ c.in.eas.eas[1].flags = 0;
+ c.in.eas.eas[1].name.s = "SECONDEA";
+ c.in.eas.eas[1].value = data_blob_talloc(c.in.eas.eas, "ValueTwo", 8);
+
+ status = smb2_create(tree, tree, &c);
+ torture_assert_ntstatus_ok(
+ tctx, status, "Unable to create test file");
+
+ handle = c.out.file.handle;
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+ struct smb2_getinfo b;
+
+ ZERO_STRUCT(b);
+ b.in.info_type = SMB2_GETINFO_FILE;
+ b.in.info_class = levels[i].level;
+ b.in.file.handle = handle;
+ b.in.output_buffer_length = 65535;
+
+ status = smb2_getinfo(tree, tree, &b);
+ torture_assert_ntstatus_equal(
+ tctx, status, NT_STATUS_OK,
+ "Wrong error code for large buffer");
+
+ ret = torture_smb2_buffercheck_err(
+ tctx, tree, &b, levels[i].fixed, b.out.blob);
+ if (!ret) {
+ return ret;
+ }
+ }
+ return true;
+}
+
+static bool torture_smb2_qsec_buffercheck(struct torture_context *tctx)
+{
+ struct smb2_getinfo b;
+ bool ret;
+ struct smb2_tree *tree;
+ struct smb2_create c;
+ NTSTATUS status;
+ struct smb2_handle handle;
+ int i;
+
+ printf("Testing SMB2_GETINFO_SECURITY buffer sizes\n");
+
+ ret = torture_smb2_connection(tctx, &tree);
+ torture_assert(tctx, ret, "connection failed");
+
+ ZERO_STRUCT(c);
+ c.in.oplock_level = 0;
+ c.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_DIR_READ_ATTRIBUTE |
+ SEC_DIR_LIST | SEC_STD_READ_CONTROL;
+ c.in.file_attributes = 0;
+ c.in.create_disposition = NTCREATEX_DISP_OPEN;
+ c.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+ NTCREATEX_SHARE_ACCESS_DELETE;
+ c.in.create_options = NTCREATEX_OPTIONS_ASYNC_ALERT;
+ c.in.fname = "";
+
+ status = smb2_create(tree, tree, &c);
+ torture_assert_ntstatus_ok(
+ tctx, status, "Unable to create root handle");
+
+ handle = c.out.file.handle;
ZERO_STRUCT(b);
- b.in.info_type = SMB2_GETINFO_FS;
- b.in.info_class = 1;
- b.in.output_buffer_length = 0x1;
- b.in.input_buffer_length = 0;
- b.in.file.handle = handle;
+ b.in.info_type = SMB2_GETINFO_SECURITY;
+ b.in.info_class = 0;
+ b.in.file.handle = handle;
+ b.in.output_buffer_length = 0;
status = smb2_getinfo(tree, tree, &b);
- torture_assert_ntstatus_equal(tctx, status,
- NT_STATUS_INFO_LENGTH_MISMATCH,
- "Wrong error code for small buffer");
+ torture_assert_ntstatus_equal(
+ tctx, status, NT_STATUS_BUFFER_TOO_SMALL,
+ "Wrong error code for large buffer");
+
+ b.in.output_buffer_length = 1;
+ status = smb2_getinfo(tree, tree, &b);
+ torture_assert_ntstatus_equal(
+ tctx, status, NT_STATUS_BUFFER_TOO_SMALL,
+ "Wrong error code for large buffer");
+
return true;
}
-
/* basic testing of all SMB2 getinfo levels
*/
static bool torture_smb2_getinfo(struct torture_context *torture)
@@ -231,7 +435,11 @@ struct torture_suite *torture_smb2_getinfo_init(void)
torture_suite_add_simple_test(suite, "complex", torture_smb2_getinfo);
torture_suite_add_simple_test(suite, "fsinfo", torture_smb2_fsinfo);
- torture_suite_add_simple_test(suite, "buffercheck",
- torture_smb2_buffercheck);
+ torture_suite_add_simple_test(suite, "qfs_buffercheck",
+ torture_smb2_qfs_buffercheck);
+ torture_suite_add_simple_test(suite, "qfile_buffercheck",
+ torture_smb2_qfile_buffercheck);
+ torture_suite_add_simple_test(suite, "qsec_buffercheck",
+ torture_smb2_qsec_buffercheck);
return suite;
}
--
1.8.1.2
More information about the samba-technical
mailing list