s3: smbd: Remove all DFS path prefixes before passing to check_path_syntax_smb2().
authorJeremy Allison <jra@samba.org>
Mon, 27 Mar 2023 19:01:56 +0000 (12:01 -0700)
committerRalph Boehme <slow@samba.org>
Fri, 31 Mar 2023 05:12:32 +0000 (05:12 +0000)
In smb2, smb1req->flags2 now never uses FLAGS2_DFS_PATHNAMES,
ucf_flags never has UCF_DFS_PATHNAME, and all calls to check_path_syntax_smb2()
pass "false" in this is_dfs parameter.

Remove all knownfails for smb2.SMB2-DFS* tests.

Now I can clean up check_path_syntax_smb2() and add
an assertion into filename_convert_dirfsp_nosymlink() that
UCF_DFS_PATHNAME is *NEVER* set in the ucf_flags for an
SMB2 connection.

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
selftest/knownfail.d/dfs_paths
source3/smbd/smb2_create.c
source3/smbd/smb2_trans2.c

index 142d0540b90fd85556b8dfc7a9258e02446dadf9..eb29a85ad96bfa8e16f40ba9255eeddef23295ed 100644 (file)
@@ -1,5 +1,3 @@
-^samba3.smbtorture_s3.smb2.SMB2-DFS-PATHS.smbtorture\(fileserver\)
-^samba3.smbtorture_s3.smb2.SMB2-DFS-SHARE-NON-DFS-PATH.smbtorture\(fileserver\)
 ^samba3.smbtorture_s3.smb1.SMB1-DFS-PATHS.smbtorture\(fileserver\)
 ^samba3.smbtorture_s3.smb1.SMB1-DFS-SEARCH-PATHS.smbtorture\(fileserver\)
 ^samba3.smbtorture_s3.smb1.SMB1-DFS-OPERATIONS.smbtorture\(fileserver\)
index 68abb3f5e8292da18184ebe158ffab8821d3c564..8e5667f2ebcf980d27870a55d8297aede0bc7acd 100644 (file)
@@ -475,6 +475,36 @@ static NTSTATUS smbd_smb2_create_durable_lease_check(struct smb_request *smb1req
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
+       if (is_dfs) {
+               const char *non_dfs_requested_filename = NULL;
+               /*
+                * With a DFS flag set, remove any DFS prefix
+                * before further processing.
+                */
+               status = smb2_strip_dfs_path(requested_filename,
+                                            &non_dfs_requested_filename);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+               /*
+                * TODO: Note for dealing with reparse point errors.
+                * We will need to remember and store the number of characters
+                * we have removed here, which is
+                * (requested_filename - non_dfs_requested_filename)
+                * in order to correctly report how many characters we
+                * have removed before hitting the reparse point.
+                * This will be a patch needed once we properly
+                * deal with reparse points later.
+                */
+               requested_filename = non_dfs_requested_filename;
+               /*
+                * Now we're no longer dealing with a DFS path, so
+                * remove the flag.
+                */
+               smb1req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
+               is_dfs = false;
+       }
+
        filename = talloc_strdup(talloc_tos(), requested_filename);
        if (filename == NULL) {
                return NT_STATUS_NO_MEMORY;
@@ -798,13 +828,32 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 
        is_dfs = (smb1req->flags2 & FLAGS2_DFS_PATHNAMES);
        if (is_dfs) {
+               const char *non_dfs_in_name = NULL;
                /*
-                * With a DFS flag set, remove any leading '\\'
-                * characters from in_name before further processing.
+                * With a DFS flag set, remove any DFS prefix
+                * before further processing.
                 */
-               while (in_name[0] == '\\') {
-                       in_name++;
+               status = smb2_strip_dfs_path(in_name, &non_dfs_in_name);
+               if (!NT_STATUS_IS_OK(status)) {
+                       tevent_req_nterror(req, status);
+                       return tevent_req_post(req, state->ev);
                }
+               /*
+                * TODO: Note for dealing with reparse point errors.
+                * We will need to remember and store the number of characters
+                * we have removed here, which is (non_dfs_in_name - in_name)
+                * in order to correctly report how many characters we
+                * have removed before hitting the reparse point.
+                * This will be a patch needed once we properly
+                * deal with reparse points later.
+                */
+               in_name = non_dfs_in_name;
+               /*
+                * Now we're no longer dealing with a DFS path, so
+                * remove the flag.
+                */
+               smb1req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
+               is_dfs = false;
        }
 
        state->fname = talloc_strdup(state, in_name);
index f9544cddb72f0d94989f3b1e84b4539fc5b6483c..e01c50c762d715945cf25629e1bd1e0818cf74ba 100644 (file)
@@ -4412,7 +4412,6 @@ static NTSTATUS smb2_file_rename_information(connection_struct *conn,
        const char *dst_original_lcomp = NULL;
        uint32_t ucf_flags = ucf_flags_from_smb_request(req);
        NTSTATUS status = NT_STATUS_OK;
-       bool is_dfs = (req->flags2 & FLAGS2_DFS_PATHNAMES);
        TALLOC_CTX *ctx = talloc_tos();
 
        if (!fsp) {
@@ -4441,7 +4440,12 @@ static NTSTATUS smb2_file_rename_information(connection_struct *conn,
        if (newname == NULL) {
                return NT_STATUS_INVALID_PARAMETER;
        }
-       status = check_path_syntax_smb2(newname, is_dfs);
+
+       /* SMB2 rename paths are never DFS. */
+       req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
+       ucf_flags &= ~UCF_DFS_PATHNAME;
+
+       status = check_path_syntax_smb2(newname, false);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -4519,7 +4523,6 @@ static NTSTATUS smb2_file_link_information(connection_struct *conn,
        NTSTATUS status = NT_STATUS_OK;
        uint32_t ucf_flags = ucf_flags_from_smb_request(req);
        size_t ret;
-       bool is_dfs = (req->flags2 & FLAGS2_DFS_PATHNAMES);
        TALLOC_CTX *ctx = talloc_tos();
 
        if (!fsp) {
@@ -4549,7 +4552,11 @@ static NTSTATUS smb2_file_link_information(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       status = check_path_syntax_smb2(newname, is_dfs);
+       /* SMB2 hardlink paths are never DFS. */
+       req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
+       ucf_flags &= ~UCF_DFS_PATHNAME;
+
+       status = check_path_syntax_smb2(newname, false);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }