From: Jeremy Allison Date: Mon, 27 Mar 2023 19:01:56 +0000 (-0700) Subject: s3: smbd: Remove all DFS path prefixes before passing to check_path_syntax_smb2(). X-Git-Tag: talloc-2.4.1~1224 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2c40e28908e9fab8dce7e50d3357b513d9af78c4;p=thirdparty%2Fsamba.git s3: smbd: Remove all DFS path prefixes before passing to check_path_syntax_smb2(). 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 Reviewed-by: Ralph Boehme --- diff --git a/selftest/knownfail.d/dfs_paths b/selftest/knownfail.d/dfs_paths index 142d0540b90..eb29a85ad96 100644 --- a/selftest/knownfail.d/dfs_paths +++ b/selftest/knownfail.d/dfs_paths @@ -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\) diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c index 68abb3f5e82..8e5667f2ebc 100644 --- a/source3/smbd/smb2_create.c +++ b/source3/smbd/smb2_create.c @@ -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); diff --git a/source3/smbd/smb2_trans2.c b/source3/smbd/smb2_trans2.c index f9544cddb72..e01c50c762d 100644 --- a/source3/smbd/smb2_trans2.c +++ b/source3/smbd/smb2_trans2.c @@ -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; }