s3: smbtorture3: Add a new test SMB2-NON-DFS-SHARE.
authorJeremy Allison <jra@samba.org>
Thu, 8 Sep 2022 23:42:26 +0000 (16:42 -0700)
committerJeremy Allison <jra@samba.org>
Wed, 14 Sep 2022 17:33:37 +0000 (17:33 +0000)
This one is tricky. It sends SMB2 DFS pathnames to a non-DFS
share, and sets the SMB2 flag FLAGS2_DFS_PATHNAMES in the SMB2
packet.

Windows will have non of it and (correctly) treats the pathnames
as local paths (they're going to a non-DFS share). Samba fails.

This proves the server looks as the share DFS capability to
override the flag in the SMB2 packet.

Passes against Windows. Added knownfail for Samba.

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Noel Power <npower@samba.org>
selftest/knownfail.d/dfs_paths
selftest/target/Samba3.pm
source3/selftest/tests.py
source3/torture/proto.h
source3/torture/test_smb2.c
source3/torture/torture.c

index ed86a4387366a1c7b67cfb6572085b693bb3e4dc..330c17d02a0f63dfd711d10ceac1a1389b863776 100644 (file)
@@ -1,3 +1,4 @@
 ^samba3.smbtorture_s3.smb2.SMB2-DFS-PATHS.smbtorture\(fileserver\)
+^samba3.smbtorture_s3.smb2.SMB2-NON-DFS-SHARE.smbtorture\(fileserver\)
 ^samba3.smbtorture_s3.smb1.SMB1-DFS-PATHS.smbtorture\(fileserver\)
 ^samba3.smbtorture_s3.smb1.SMB1-DFS-SEARCH-PATHS.smbtorture\(fileserver\)
index 7c7735f6f4d8c2e6d3eaf77c89fd4969d44727f5..800df1f81bd669785efee3ba61f973892ada1ec0 100755 (executable)
@@ -2537,6 +2537,9 @@ sub provision($$)
        my $msdfs_pathname_share="$shrdir/msdfs_pathname_share";
        push(@dirs,$msdfs_pathname_share);
 
+       my $non_msdfs_pathname_share="$shrdir/non_msdfs_pathname_share";
+       push(@dirs,$non_msdfs_pathname_share);
+
        my $msdfs_deeppath="$msdfs_shrdir/deeppath";
        push(@dirs,$msdfs_deeppath);
 
@@ -2968,6 +2971,10 @@ sub provision($$)
        path = $msdfs_pathname_share
        msdfs root = yes
        guest ok = yes
+[non-msdfs-pathname-share]
+       path = $non_msdfs_pathname_share
+       msdfs root = no
+       guest ok = yes
 [hideunread]
        copy = tmp
        hide unreadable = yes
index 4b192cf4ad544cf9f0a9858fb0c4effcf7a9f238..b11fedd6c4fa184ddb0538cf373107c790438fee 100755 (executable)
@@ -246,6 +246,24 @@ plantestsuite("samba3.smbtorture_s3.smb2.SMB2-DFS-PATHS",
                 smbtorture3,
                 "-mSMB2"])
 
+#
+# SMB2-NON-DFS-SHARE needs to run against a special share non-msdfs-pathname-share
+# This is an empty non-DFS share with no links, used merely to test
+# incoming DFS pathnames and how they map to local paths. We are testing
+# what happens if we set the FLAGS2_DFS_PATHNAMES and send DFS paths
+# on a non-DFS share.
+#
+plantestsuite("samba3.smbtorture_s3.smb2.SMB2-NON-DFS-SHARE",
+                "fileserver",
+                [os.path.join(samba3srcdir,
+                              "script/tests/test_smbtorture_s3.sh"),
+                'SMB2-NON-DFS-SHARE',
+                '//$SERVER_IP/non-msdfs-pathname-share',
+                '$USERNAME',
+                '$PASSWORD',
+                smbtorture3,
+                "-mSMB2"])
+
 #
 # SMB1-DFS-PATHS needs to run against a special share msdfs-pathname-share
 # This is an empty DFS share with no links, used merely to test
index 873543d748ce19c74f1d0c8f4758c626b6c99ddf..d5e404eaefa833c654691f46ba9a1ccb954376e8 100644 (file)
@@ -121,6 +121,7 @@ bool run_smb2_sacl(int dummy);
 bool run_smb2_quota1(int dummy);
 bool run_smb2_stream_acl(int dummy);
 bool run_smb2_dfs_paths(int dummy);
+bool run_smb2_non_dfs_share(int dummy);
 bool run_smb1_dfs_paths(int dummy);
 bool run_smb1_dfs_search_paths(int dummy);
 bool run_list_dir_async_test(int dummy);
index cdd66d4f4499469fdc51950dfb83156bc56a21d4..f6206ce5ffe27239fe1f1e5d8462245d677e9486 100644 (file)
@@ -4335,3 +4335,165 @@ bool run_smb2_dfs_paths(int dummy)
        (void)smb2_dfs_delete(cli, "BAD\\BAD\\hlink");
        return retval;
 }
+
+/*
+ * Add a test that sends DFS paths and sets the
+ * SMB2 flag FLAGS2_DFS_PATHNAMES, but to a non-DFS
+ * share. Windows passes this (it just treats the
+ * pathnames as non-DFS and ignores the FLAGS2_DFS_PATHNAMES
+ * bit).
+ */
+
+bool run_smb2_non_dfs_share(int dummy)
+{
+       struct cli_state *cli = NULL;
+       NTSTATUS status;
+       bool dfs_supported = false;
+       uint64_t fid_persistent = 0;
+       uint64_t fid_volatile = 0;
+       bool retval = false;
+       char *dfs_filename = NULL;
+
+       printf("Starting SMB2-DFS-NON-DFS-SHARE\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;
+       }
+
+       dfs_supported = smbXcli_conn_dfs_supported(cli->conn);
+       if (!dfs_supported) {
+               printf("Server %s does not support DFS\n",
+                       smbXcli_conn_remote_name(cli->conn));
+               return false;
+       }
+       /* Ensure this is *NOT* a DFS share. */
+       dfs_supported = smbXcli_tcon_is_dfs_share(cli->smb2.tcon);
+       if (dfs_supported) {
+               printf("Share %s is a DFS share.\n",
+                       cli->share);
+               return false;
+       }
+       /*
+        * Force the share to be DFS, as far as the client
+        * is concerned.
+        */
+       smb2cli_tcon_set_values(cli->smb2.tcon,
+                               cli->smb2.session,
+                               smb2cli_tcon_current_id(cli->smb2.tcon),
+                               0,
+                               smb2cli_tcon_flags(cli->smb2.tcon),
+                               smb2cli_tcon_capabilities(cli->smb2.tcon) |
+                                       SMB2_SHARE_CAP_DFS,
+                               0);
+
+       /* Come up with a "valid" SMB2 DFS name. */
+       dfs_filename = talloc_asprintf(talloc_tos(),
+                                      "%s\\%s\\file",
+                                      smbXcli_conn_remote_name(cli->conn),
+                                      cli->share);
+       if (dfs_filename == NULL) {
+               printf("Out of memory\n");
+               return false;
+       }
+
+       /* Now try create dfs_filename. */
+       status = smb2cli_create(cli->conn,
+                               cli->timeout,
+                               cli->smb2.session,
+                               cli->smb2.tcon,
+                               dfs_filename,
+                               SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
+                               SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
+                               SEC_STD_SYNCHRONIZE|
+                                       SEC_STD_DELETE |
+                                       SEC_FILE_READ_DATA|
+                                       SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
+                               FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
+                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
+                               FILE_CREATE, /* create_disposition, */
+                               0, /* create_options, */
+                               NULL, /* smb2_create_blobs *blobs */
+                               &fid_persistent,
+                               &fid_volatile,
+                               NULL, /* struct smb_create_returns * */
+                               talloc_tos(), /* mem_ctx. */
+                               NULL); /* struct smb2_create_blobs * */
+       /*
+        * Should fail with NT_STATUS_OBJECT_PATH_NOT_FOUND, as
+        * even though we set the FLAGS2_DFS_PATHNAMES the server
+        * knows this isn't a DFS share and so treats BAD\\BAD as
+        * part of the filename.
+        */
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
+               printf("%s:%d create of %s should fail "
+                       "with NT_STATUS_OBJECT_PATH_NOT_FOUND. Got %s\n",
+                       __FILE__,
+                       __LINE__,
+                       dfs_filename,
+                       nt_errstr(status));
+               goto err;
+       }
+       /*
+        * Prove we can still use non-DFS pathnames, even though
+        * we are setting the FLAGS2_DFS_PATHNAMES in the SMB2
+        * request.
+        */
+       status = smb2cli_create(cli->conn,
+                               cli->timeout,
+                               cli->smb2.session,
+                               cli->smb2.tcon,
+                               "file",
+                               SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
+                               SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
+                               SEC_STD_SYNCHRONIZE|
+                                       SEC_STD_DELETE |
+                                       SEC_FILE_READ_DATA|
+                                       SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
+                               FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
+                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
+                               FILE_CREATE, /* create_disposition, */
+                               0, /* create_options, */
+                               NULL, /* smb2_create_blobs *blobs */
+                               &fid_persistent,
+                               &fid_volatile,
+                               NULL, /* struct smb_create_returns * */
+                               talloc_tos(), /* mem_ctx. */
+                               NULL); /* struct smb2_create_blobs * */
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("%s:%d smb2cli_create on %s returned %s\n",
+                       __FILE__,
+                       __LINE__,
+                       "file",
+                       nt_errstr(status));
+               return false;
+       }
+
+       retval = true;
+
+  err:
+
+       (void)smb2_dfs_delete(cli, dfs_filename);
+       (void)smb2_dfs_delete(cli, "file");
+       return retval;
+}
index 8e496320dda8b68675513cf3cb1ff260f500e048..75d0248d773431e56ba4b08ad7669265e230f154 100644 (file)
@@ -15363,6 +15363,10 @@ static struct {
                .name  = "SMB2-DFS-PATHS",
                .fn    = run_smb2_dfs_paths,
        },
+       {
+               .name  = "SMB2-NON-DFS-SHARE",
+               .fn    = run_smb2_non_dfs_share,
+       },
        {
                .name  = "SMB1-DFS-PATHS",
                .fn    = run_smb1_dfs_paths,