]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbtorture: add subtests for overwrite dispositions vs sharemodes
authorRalph Boehme <slow@samba.org>
Wed, 2 Oct 2024 12:08:36 +0000 (14:08 +0200)
committerJule Anger <janger@samba.org>
Thu, 7 Nov 2024 08:18:17 +0000 (08:18 +0000)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15732

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
(cherry picked from commit 849afe05ade140898b1eab9b28d46edc8357c844)

selftest/knownfail.d/samba3.smb2.acls [new file with mode: 0644]
source4/torture/smb2/acls.c

diff --git a/selftest/knownfail.d/samba3.smb2.acls b/selftest/knownfail.d/samba3.smb2.acls
new file mode 100644 (file)
index 0000000..18df260
--- /dev/null
@@ -0,0 +1 @@
+^samba3.smb2.acls.OVERWRITE_READ_ONLY_FILE
index f9c1158ee47ccf60c1d8e48027a4d334206c8570..0459d6547dc7beacf0fbaac013395b570bf8c136 100644 (file)
@@ -2994,8 +2994,10 @@ static bool test_overwrite_read_only_file(struct torture_context *tctx,
 {
        NTSTATUS status;
        struct smb2_create c = {};
+       struct smb2_create c2 = {};
        const char *fname = BASEDIR "\\test_overwrite_read_only_file.txt";
        struct smb2_handle handle = {{0}};
+       struct smb2_handle h2 = {};
        union smb_fileinfo q;
        union smb_setfileinfo set;
        struct security_descriptor *sd = NULL, *sd_orig = NULL;
@@ -3021,6 +3023,12 @@ static bool test_overwrite_read_only_file(struct torture_context *tctx,
                TCASE(NTCREATEX_DISP_OVERWRITE, NT_STATUS_ACCESS_DENIED),
                TCASE(NTCREATEX_DISP_OVERWRITE_IF, NT_STATUS_ACCESS_DENIED),
        };
+
+       struct tcase sharing_tcases[] = {
+               TCASE(NTCREATEX_DISP_SUPERSEDE, NT_STATUS_SHARING_VIOLATION),
+               TCASE(NTCREATEX_DISP_OVERWRITE, NT_STATUS_SHARING_VIOLATION),
+               TCASE(NTCREATEX_DISP_OVERWRITE_IF, NT_STATUS_SHARING_VIOLATION),
+       };
 #undef TCASE
 
        ret = smb2_util_setup_dir(tctx, tree, BASEDIR);
@@ -3124,11 +3132,108 @@ static bool test_overwrite_read_only_file(struct torture_context *tctx,
        torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                        "smb2_setinfo_file failed\n");
 
-       smb2_util_close(tree, handle);
+       status = smb2_util_close(tree, handle);
+       torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+                                       "smb2_util_close failed\n");
        ZERO_STRUCT(handle);
 
+       for (i = 0; i < ARRAY_SIZE(sharing_tcases); i++) {
+               struct tcase *tcase = &sharing_tcases[i];
+
+               torture_comment(tctx, "Verify %s disposition\n",
+                               tcase->disposition_string);
+
+               torture_comment(tctx, "Read-nonly open file with SHARE_READ\n");
+
+               c = (struct smb2_create) {
+                       .in.desired_access = SEC_FILE_READ_DATA,
+                       .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
+                       .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
+                       .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
+                       .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
+                       .in.fname = fname,
+               };
+
+               status = smb2_create(tree, tctx, &c);
+               torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+                                               "smb2_create failed\n");
+               handle = c.out.file.handle;
+
+               torture_comment(tctx, "A second open with %s must return %s\n",
+                       tcase->disposition_string, nt_errstr(tcase->expected_status));
+
+               c2 = (struct smb2_create) {
+                       .in.desired_access = SEC_FILE_READ_DATA,
+                       .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
+                       .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
+                       .in.create_disposition = tcase->disposition,
+                       .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
+                       .in.fname = fname,
+               };
+
+               status = smb2_create(tree, tctx, &c2);
+               torture_assert_ntstatus_equal_goto(tctx, status,
+                                                  tcase->expected_status,
+                                                  ret, done,
+                                                  "Wrong status code\n");
+
+               status = smb2_util_close(tree, handle);
+               torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+                                               "smb2_util_close failed\n");
+               ZERO_STRUCT(handle);
+
+               torture_comment(tctx, "First open with %s\n",
+                               tcase->disposition_string);
+
+               c = (struct smb2_create) {
+                       .in.desired_access = SEC_FILE_READ_DATA,
+                       .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
+                       .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
+                       .in.create_disposition = tcase->disposition,
+                       .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
+                       .in.fname = fname,
+               };
+
+               status = smb2_create(tree, tctx, &c);
+               torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+                                               "smb2_create failed\n");
+               handle = c.out.file.handle;
+
+               torture_comment(tctx, "A second read-only open with SHARE_READ "
+                               "must work\n");
+
+               c = (struct smb2_create) {
+                       .in.desired_access = SEC_FILE_READ_DATA,
+                       .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
+                       .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
+                       .in.create_disposition = NTCREATEX_DISP_OPEN,
+                       .in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
+                       .in.fname = fname,
+               };
+
+               status = smb2_create(tree, tctx, &c);
+               torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+                                               "smb2_create failed\n");
+               h2 = c.out.file.handle;
+
+               status = smb2_util_close(tree, handle);
+               torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+                                               "smb2_util_close failed\n");
+               ZERO_STRUCT(handle);
+
+               status = smb2_util_close(tree, h2);
+               torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+                                               "smb2_util_close failed\n");
+               ZERO_STRUCT(h2);
+       }
+
 done:
-       smb2_util_close(tree, handle);
+       if (!smb2_util_handle_empty(handle)) {
+               smb2_util_close(tree, handle);
+       }
+       if (!smb2_util_handle_empty(h2)) {
+               smb2_util_close(tree, h2);
+       }
        smb2_util_unlink(tree, fname);
        smb2_deltree(tree, BASEDIR);
        return ret;