]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3: torture: Add a test for setting and getting ACLs on stream handles (SMB2-STREAM...
authorJeremy Allison <jra@samba.org>
Thu, 25 Mar 2021 22:43:16 +0000 (15:43 -0700)
committerJeremy Allison <jra@samba.org>
Tue, 30 Mar 2021 19:16:34 +0000 (19:16 +0000)
It shows this isn't done correctly for streams_xattr.

A common config is:

vfs_objects = streams_xattr acl_xattr

to store both streams and Windows ACLs in xattrs.

Unfortunately getting and setting ACLs using handles
opened on stream files isn't being done correctly
in Samba.

This test passes against Windows 10.

This adds tests that prove this doesn't work. Next
patch will add the fix and remove the knownfail.

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
selftest/knownfail.d/stream-acl [new file with mode: 0644]
source3/selftest/tests.py
source3/torture/proto.h
source3/torture/test_smb2.c
source3/torture/torture.c

diff --git a/selftest/knownfail.d/stream-acl b/selftest/knownfail.d/stream-acl
new file mode 100644 (file)
index 0000000..8537396
--- /dev/null
@@ -0,0 +1 @@
+^samba3.smbtorture_s3.plain.SMB2-STREAM-ACL.smbtorture\(fileserver\)
index 6efbea8bc4b5060818d4c4d55e3fd49f742feda7..450a7159ef95fd5981804e1afb0d5cd8af5b2cc4 100755 (executable)
@@ -227,6 +227,21 @@ plantestsuite("samba3.smbtorture_s3.smb1.MSDFS-ATTRIBUTE",
                 "-mNT1",
                 "-f msdfs-src1"])
 
+#
+# SMB2-STREAM-ACL needs to run against a special share - vfs_wo_fruit
+#
+plantestsuite("samba3.smbtorture_s3.plain.%s" % "SMB2-STREAM-ACL",
+                "fileserver",
+                [os.path.join(samba3srcdir,
+                              "script/tests/test_smbtorture_s3.sh"),
+                'SMB2-STREAM-ACL',
+                '//$SERVER_IP/vfs_wo_fruit',
+                '$USERNAME',
+                '$PASSWORD',
+                smbtorture3,
+                "",
+                "-l $LOCAL_PATH"])
+
 shares = [
     "vfs_aio_pthread_async_dosmode_default1",
     "vfs_aio_pthread_async_dosmode_default2",
index 521c662e2fbc99eedc54f869941f4d1d2d8748a0..794a6044427b22c6d51ec8b130a1352845460ee0 100644 (file)
@@ -110,6 +110,7 @@ bool run_smb2_dir_fsync(int dummy);
 bool run_smb2_path_slash(int dummy);
 bool run_smb2_sacl(int dummy);
 bool run_smb2_quota1(int dummy);
+bool run_smb2_stream_acl(int dummy);
 bool run_chain3(int dummy);
 bool run_local_conv_auth_info(int dummy);
 bool run_local_sprintf_append(int dummy);
index a81e40568e8d006326177deb0cfc3ff09f51b41f..feb8b654f3bf64acc237388ca3d4c393c52f917f 100644 (file)
@@ -2937,3 +2937,210 @@ bool run_smb2_quota1(int dummy)
 
        return true;
 }
+
+bool run_smb2_stream_acl(int dummy)
+{
+       struct cli_state *cli = NULL;
+       NTSTATUS status;
+       uint16_t fnum = (uint16_t)-1;
+       const char *fname = "stream_acl_test_file";
+       const char *sname = "stream_acl_test_file:streamname";
+       struct security_descriptor *sd_dacl = NULL;
+       bool ret = false;
+
+       printf("SMB2 stream acl\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 file doesn't exist. */
+       (void)cli_unlink(cli, fname, 0);
+
+       /* Create the file. */
+       status = cli_ntcreate(cli,
+                               fname,
+                               0,
+                               GENERIC_ALL_ACCESS,
+                               FILE_ATTRIBUTE_NORMAL,
+                               FILE_SHARE_NONE,
+                               FILE_CREATE,
+                               0,
+                               0,
+                               &fnum,
+                               NULL);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Create of %s failed (%s)\n",
+                       fname,
+                       nt_errstr(status));
+                goto fail;
+       }
+
+       /* Close the handle. */
+       cli_smb2_close_fnum(cli, fnum);
+       fnum = (uint16_t)-1;
+
+       /* Create the stream. */
+       status = cli_ntcreate(cli,
+                               sname,
+                               0,
+                               FILE_READ_DATA|
+                                       SEC_STD_READ_CONTROL|
+                                       SEC_STD_WRITE_DAC,
+                               FILE_ATTRIBUTE_NORMAL,
+                               FILE_SHARE_NONE,
+                               FILE_CREATE,
+                               0,
+                               0,
+                               &fnum,
+                               NULL);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Create of %s failed (%s)\n",
+                       sname,
+                       nt_errstr(status));
+               goto fail;
+       }
+
+       /* Close the handle. */
+       cli_smb2_close_fnum(cli, fnum);
+       fnum = (uint16_t)-1;
+
+       /*
+        * Open the stream - for Samba this ensures
+        * we prove we have a pathref fsp.
+        */
+       status = cli_ntcreate(cli,
+                               sname,
+                               0,
+                               FILE_READ_DATA|
+                                       SEC_STD_READ_CONTROL|
+                                       SEC_STD_WRITE_DAC,
+                               FILE_ATTRIBUTE_NORMAL,
+                               FILE_SHARE_NONE,
+                               FILE_OPEN,
+                               0,
+                               0,
+                               &fnum,
+                               NULL);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Open of %s failed (%s)\n",
+                       sname,
+                       nt_errstr(status));
+                goto fail;
+       }
+
+       /* Read the security descriptor off the stream handle. */
+       status = cli_query_security_descriptor(cli,
+                               fnum,
+                               SECINFO_DACL,
+                               talloc_tos(),
+                               &sd_dacl);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Reading DACL on stream %s got (%s)\n",
+                       sname,
+                       nt_errstr(status));
+               goto fail;
+       }
+
+       if (sd_dacl == NULL || sd_dacl->dacl == NULL ||
+                       sd_dacl->dacl->num_aces < 1) {
+               printf("Invalid DACL returned on stream %s "
+                       "(this should not happen)\n",
+                       sname);
+               goto fail;
+       }
+
+       /*
+        * Ensure it allows FILE_READ_DATA in the first ace.
+        * It always should.
+        */
+       if ((sd_dacl->dacl->aces[0].access_mask & FILE_READ_DATA) == 0) {
+               printf("DACL->ace[0] returned on stream %s "
+                       "doesn't have read access (should not happen)\n",
+                       sname);
+               goto fail;
+       }
+
+       /* Remove FILE_READ_DATA from the first ace and set. */
+       sd_dacl->dacl->aces[0].access_mask &= ~FILE_READ_DATA;
+
+       status = cli_set_security_descriptor(cli,
+                               fnum,
+                               SECINFO_DACL,
+                               sd_dacl);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Setting DACL on stream %s got (%s)\n",
+                       sname,
+                       nt_errstr(status));
+               goto fail;
+       }
+
+       TALLOC_FREE(sd_dacl);
+
+       /* Read again and check it changed. */
+       status = cli_query_security_descriptor(cli,
+                               fnum,
+                               SECINFO_DACL,
+                               talloc_tos(),
+                               &sd_dacl);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Reading DACL on stream %s got (%s)\n",
+                       sname,
+                       nt_errstr(status));
+               goto fail;
+       }
+
+       if (sd_dacl == NULL || sd_dacl->dacl == NULL ||
+                       sd_dacl->dacl->num_aces < 1) {
+               printf("Invalid DACL (1) returned on stream %s "
+                       "(this should not happen)\n",
+                       sname);
+               goto fail;
+       }
+
+       /* FILE_READ_DATA should be gone from the first ace. */
+       if ((sd_dacl->dacl->aces[0].access_mask & FILE_READ_DATA) != 0) {
+               printf("DACL on stream %s did not change\n",
+                       sname);
+               goto fail;
+       }
+
+       ret = true;
+
+  fail:
+
+       if (fnum != (uint16_t)-1) {
+               cli_smb2_close_fnum(cli, fnum);
+               fnum = (uint16_t)-1;
+       }
+
+       (void)cli_unlink(cli, fname, 0);
+       return ret;
+}
index add58414f3369d18b46b3c7800cc007fd9d40f7a..2a78fb92bc415d6c7ce0bdf5ba8ab6339ccfddc5 100644 (file)
@@ -15217,6 +15217,10 @@ static struct {
                .name  = "SMB2-QUOTA1",
                .fn    = run_smb2_quota1,
        },
+       {
+               .name  = "SMB2-STREAM-ACL",
+               .fn    = run_smb2_stream_acl,
+       },
        {
                .name  = "CLEANUP1",
                .fn    = run_cleanup1,