torture: Add buffercheck tests
authorVolker Lendecke <vl@samba.org>
Tue, 27 Aug 2013 09:41:13 +0000 (09:41 +0000)
committerJeremy Allison <jra@samba.org>
Wed, 28 Aug 2013 23:27:11 +0000 (01:27 +0200)
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@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Thu Aug 29 01:27:11 CEST 2013 on sn-devel-104

selftest/knownfail
source4/torture/smb2/getinfo.c

index dd536df57af822f599554f9789e1e3de15a32985..6fe7ce5c01fac396d30df8d70c9817fdef97b70f 100644 (file)
 ^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
index 10dd550cdd4a5500e3a8899651ed8ac1029556b6..fafc36c31de43bf44cefdaa7bb7b1ac6126fa467 100644 (file)
 #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;
 }