s3: torture: Add 2 new tests SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO, SMB2-DEL-ON-CLOSE...
authorJeremy Allison <jra@samba.org>
Mon, 21 Mar 2022 20:45:25 +0000 (13:45 -0700)
committerJeremy Allison <jra@samba.org>
Tue, 22 Mar 2022 16:49:34 +0000 (16:49 +0000)
We currently allow setting the delete on close bit for
a directory containing only explicitly hidden/vetoed files
in the case where "delete veto files = yes" *and*
"delete veto files = no". For the "delete veto files = no"
case we should be denying setting the delete on close bit
when the client tries to set it (that's the only time Windows
looks at the bit and returns an error to the user). We
already do the in the dangling symlink case, we just
missed it in the !is_visible_fsp() case.

Mark SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO as knownfail
for now.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15023

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Noel Power <npower@samba.org>
selftest/knownfail.d/smb2_del_on_close_nonwrite [new file with mode: 0644]
selftest/target/Samba3.pm
source3/selftest/tests.py
source3/torture/proto.h
source3/torture/test_smb2.c
source3/torture/torture.c

diff --git a/selftest/knownfail.d/smb2_del_on_close_nonwrite b/selftest/knownfail.d/smb2_del_on_close_nonwrite
new file mode 100644 (file)
index 0000000..7e81a11
--- /dev/null
@@ -0,0 +1 @@
+^samba3.smbtorture_s3.plain.SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO.smbtorture\(fileserver\)
index 9204348e5783849560f2bc98031dd1ab2b10bfbe..068d3b1f06e4be7188f4d5591fd1a6231a5d65fa 100755 (executable)
@@ -1774,6 +1774,11 @@ sub setup_fileserver
        my $virusfilter_sharedir="$share_dir/virusfilter";
        push(@dirs,$virusfilter_sharedir);
 
+       my $delete_unwrite_sharedir="$share_dir/delete_unwrite";
+       push(@dirs,$delete_unwrite_sharedir);
+       push(@dirs, "$delete_unwrite_sharedir/delete_veto_yes");
+       push(@dirs, "$delete_unwrite_sharedir/delete_veto_no");
+
        my $ip4 = Samba::get_ipv4_addr("FILESERVER");
        my $fileserver_options = "
        kernel change notify = yes
@@ -1898,6 +1903,18 @@ sub setup_fileserver
        path = $veto_sharedir
        delete veto files = yes
 
+[delete_yes_unwrite]
+       read only = no
+       path = $delete_unwrite_sharedir
+       hide unwriteable files = yes
+       delete veto files = yes
+
+[delete_no_unwrite]
+       read only = no
+       path = $delete_unwrite_sharedir
+       hide unwriteable files = yes
+       delete veto files = no
+
 [virusfilter]
        path = $virusfilter_sharedir
        vfs objects = acl_xattr virusfilter
@@ -1984,6 +2001,14 @@ sub setup_fileserver
        ##
        create_file_chmod("$bad_iconv_sharedir/\xED\x9F\xBF", 0644) or return undef;
 
+       ##
+       ## create unwritable files inside inside the delete unwrite veto share dirs.
+       ##
+       unlink("$delete_unwrite_sharedir/delete_veto_yes/file_444");
+       create_file_chmod("$delete_unwrite_sharedir/delete_veto_yes/file_444", 0444) or return undef;
+       unlink("$delete_unwrite_sharedir/delete_veto_no/file_444");
+       create_file_chmod("$delete_unwrite_sharedir/delete_veto_no/file_444", 0444) or return undef;
+
        return $vars;
 }
 
index 5849d39445adc9c4e24f1478c1348b448aad39ef..2bfb38fdfff74c5f2024c4cd822f97c7fff94b23 100755 (executable)
@@ -271,7 +271,35 @@ plantestsuite("samba3.smbtorture_s3.plain.%s" % "SMB2-DEL-ON-CLOSE-NONEMPTY",
                 "",
                 "-l $LOCAL_PATH"])
 
+#
+# SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES needs to run against a special fileserver share delete_yes_unwrite
+#
+plantestsuite("samba3.smbtorture_s3.plain.%s" % "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
+                "fileserver",
+                [os.path.join(samba3srcdir,
+                              "script/tests/test_smbtorture_s3.sh"),
+                'SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES',
+                '//$SERVER_IP/delete_yes_unwrite',
+                '$USERNAME',
+                '$PASSWORD',
+                smbtorture3,
+                "",
+                "-l $LOCAL_PATH"])
 
+#
+# SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO needs to run against a special fileserver share delete_no_unwrite
+#
+plantestsuite("samba3.smbtorture_s3.plain.%s" % "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
+                "fileserver",
+                [os.path.join(samba3srcdir,
+                              "script/tests/test_smbtorture_s3.sh"),
+                'SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO',
+                '//$SERVER_IP/delete_no_unwrite',
+                '$USERNAME',
+                '$PASSWORD',
+                smbtorture3,
+                "",
+                "-l $LOCAL_PATH"])
 
 shares = [
     "vfs_aio_pthread_async_dosmode_default1",
index d4db60f9dde3fadb8517e41b2dbf65095c3d5fd5..551c4ea80ac684379decf0fa4ff1c359b26b0b5d 100644 (file)
@@ -122,6 +122,8 @@ bool run_smb2_quota1(int dummy);
 bool run_smb2_stream_acl(int dummy);
 bool run_list_dir_async_test(int dummy);
 bool run_delete_on_close_non_empty(int dummy);
+bool run_delete_on_close_nonwrite_delete_yes_test(int dummy);
+bool run_delete_on_close_nonwrite_delete_no_test(int dummy);
 bool run_chain3(int dummy);
 bool run_local_conv_auth_info(int dummy);
 bool run_local_sprintf_append(int dummy);
index 0fac5125c081ffccc0666dd17af22632cfb76352..c3f014100d92c803eb54e7356cf14f244dbb6c5d 100644 (file)
@@ -3364,3 +3364,247 @@ bool run_delete_on_close_non_empty(int dummy)
        (void)cli_rmdir(cli, dname);
        return ret;
 }
+
+static NTSTATUS check_empty_fn(struct file_info *finfo,
+                               const char *mask,
+                               void *private_data)
+{
+       unsigned int *pcount = (unsigned int *)private_data;
+
+       if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
+               (*pcount)++;
+               return NT_STATUS_OK;
+       }
+       return NT_STATUS_DIRECTORY_NOT_EMPTY;
+}
+
+/*
+ * Test setting the delete on close bit on a directory
+ * containing an unwritable file fails or succeeds
+ * an a share set with "hide unwritable = yes"
+ * depending on the setting of "delete veto files".
+ * BUG: https://bugzilla.samba.org/show_bug.cgi?id=15023
+ *
+ * First version. With "delete veto files = yes"
+ * setting the delete on close should succeed.
+ */
+
+bool run_delete_on_close_nonwrite_delete_yes_test(int dummy)
+{
+       struct cli_state *cli = NULL;
+       NTSTATUS status;
+       const char *dname = "delete_veto_yes";
+       const char *list_dname = "delete_veto_yes\\*";
+       uint16_t fnum = (uint16_t)-1;
+       bool ret = false;
+       unsigned int list_count = 0;
+
+       printf("SMB2 delete on close nonwrite - delete veto yes\n");
+
+       if (!torture_init_connection(&cli)) {
+               return false;
+       }
+
+       status = smbXcli_negprot(cli->conn,
+                               cli->timeout,
+                               PROTOCOL_SMB2_02,
+                               PROTOCOL_SMB3_11);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("smbXcli_negprot returned %s\n", nt_errstr(status));
+               return false;
+       }
+
+       status = cli_session_setup_creds(cli, torture_creds);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_session_setup returned %s\n", nt_errstr(status));
+               return false;
+       }
+
+       status = cli_tree_connect(cli, share, "?????", NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_tree_connect returned %s\n", nt_errstr(status));
+               return false;
+       }
+
+       /* Ensure target directory is seen as empty. */
+       status = cli_list(cli,
+                       list_dname,
+                       FILE_ATTRIBUTE_DIRECTORY |
+                               FILE_ATTRIBUTE_HIDDEN |
+                               FILE_ATTRIBUTE_SYSTEM,
+                       check_empty_fn,
+                       &list_count);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_list of %s returned %s\n",
+                       dname,
+                       nt_errstr(status));
+               return false;
+       }
+       if (list_count != 2) {
+               printf("cli_list of %s returned a count of %u\n",
+                       dname,
+                       list_count);
+               return false;
+       }
+
+       /* Open target directory. */
+       status = cli_ntcreate(cli,
+                               dname,
+                               0,
+                               DELETE_ACCESS|FILE_READ_DATA,
+                               FILE_ATTRIBUTE_DIRECTORY,
+                               FILE_SHARE_READ|
+                                       FILE_SHARE_WRITE|
+                                       FILE_SHARE_DELETE,
+                               FILE_OPEN,
+                               FILE_DIRECTORY_FILE,
+                               0,
+                               &fnum,
+                               NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_ntcreate for directory %s returned %s\n",
+                               dname,
+                               nt_errstr(status));
+               goto out;
+       }
+
+       /* Now set the delete on close bit. */
+       status = cli_nt_delete_on_close(cli, fnum, 1);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_cli_nt_delete_on_close set for directory "
+                       "%s returned %s (should have succeeded)\n",
+                       dname,
+                       nt_errstr(status));
+               goto out;
+       }
+
+       ret = true;
+
+  out:
+
+       if (fnum != (uint16_t)-1) {
+               (void)cli_nt_delete_on_close(cli, fnum, 0);
+               (void)cli_close(cli, fnum);
+       }
+       return ret;
+}
+
+/*
+ * Test setting the delete on close bit on a directory
+ * containing an unwritable file fails or succeeds
+ * an a share set with "hide unwritable = yes"
+ * depending on the setting of "delete veto files".
+ * BUG: https://bugzilla.samba.org/show_bug.cgi?id=15023
+ *
+ * Second version. With "delete veto files = no"
+ * setting the delete on close should fail.
+ */
+
+bool run_delete_on_close_nonwrite_delete_no_test(int dummy)
+{
+       struct cli_state *cli = NULL;
+       NTSTATUS status;
+       const char *dname = "delete_veto_no";
+       const char *list_dname = "delete_veto_no\\*";
+       uint16_t fnum = (uint16_t)-1;
+       bool ret = false;
+       unsigned int list_count = 0;
+
+       printf("SMB2 delete on close nonwrite - delete veto yes\n");
+
+       if (!torture_init_connection(&cli)) {
+               return false;
+       }
+
+       status = smbXcli_negprot(cli->conn,
+                               cli->timeout,
+                               PROTOCOL_SMB2_02,
+                               PROTOCOL_SMB3_11);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("smbXcli_negprot returned %s\n", nt_errstr(status));
+               return false;
+       }
+
+       status = cli_session_setup_creds(cli, torture_creds);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_session_setup returned %s\n", nt_errstr(status));
+               return false;
+       }
+
+       status = cli_tree_connect(cli, share, "?????", NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_tree_connect returned %s\n", nt_errstr(status));
+               return false;
+       }
+
+       /* Ensure target directory is seen as empty. */
+       status = cli_list(cli,
+                       list_dname,
+                       FILE_ATTRIBUTE_DIRECTORY |
+                               FILE_ATTRIBUTE_HIDDEN |
+                               FILE_ATTRIBUTE_SYSTEM,
+                       check_empty_fn,
+                       &list_count);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_list of %s returned %s\n",
+                       dname,
+                       nt_errstr(status));
+               return false;
+       }
+       if (list_count != 2) {
+               printf("cli_list of %s returned a count of %u\n",
+                       dname,
+                       list_count);
+               return false;
+       }
+
+       /* Open target directory. */
+       status = cli_ntcreate(cli,
+                               dname,
+                               0,
+                               DELETE_ACCESS|FILE_READ_DATA,
+                               FILE_ATTRIBUTE_DIRECTORY,
+                               FILE_SHARE_READ|
+                                       FILE_SHARE_WRITE|
+                                       FILE_SHARE_DELETE,
+                               FILE_OPEN,
+                               FILE_DIRECTORY_FILE,
+                               0,
+                               &fnum,
+                               NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_ntcreate for directory %s returned %s\n",
+                               dname,
+                               nt_errstr(status));
+               goto out;
+       }
+
+       /* Now set the delete on close bit. */
+       status = cli_nt_delete_on_close(cli, fnum, 1);
+       if (NT_STATUS_IS_OK(status)) {
+               printf("cli_cli_nt_delete_on_close set for directory "
+                       "%s returned NT_STATUS_OK "
+                       "(should have failed)\n",
+                       dname);
+               goto out;
+       }
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) {
+               printf("cli_cli_nt_delete_on_close set for directory "
+                       "%s returned %s "
+                       "(should have returned "
+                       "NT_STATUS_DIRECTORY_NOT_EMPTY)\n",
+                       dname,
+                       nt_errstr(status));
+               goto out;
+       }
+
+       ret = true;
+
+  out:
+
+       if (fnum != (uint16_t)-1) {
+               (void)cli_nt_delete_on_close(cli, fnum, 0);
+               (void)cli_close(cli, fnum);
+       }
+       return ret;
+}
index c1ee78cdac4a6461407741cb4f0c8f15d03a44d5..f070d56bed0fe9082ed5ee7214a89e9b3b021289 100644 (file)
@@ -15342,6 +15342,14 @@ static struct {
                .name  = "SMB2-DEL-ON-CLOSE-NONEMPTY",
                .fn    = run_delete_on_close_non_empty,
        },
+       {
+               .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
+               .fn    = run_delete_on_close_nonwrite_delete_yes_test,
+       },
+       {
+               .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
+               .fn    = run_delete_on_close_nonwrite_delete_no_test,
+       },
        {
                .name  = "CLEANUP1",
                .fn    = run_cleanup1,