summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--selftest/knownfail3
-rw-r--r--source4/torture/smb2/getinfo.c244
2 files changed, 229 insertions, 18 deletions
diff --git a/selftest/knownfail b/selftest/knownfail
index dd536df57a..6fe7ce5c01 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 10dd550cdd..fafc36c31d 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;
}