From: Jeremy Allison Date: Wed, 25 Mar 2020 17:00:57 +0000 (-0700) Subject: s3: smbd: Add utility function get_original_lcomp(). X-Git-Tag: ldb-2.2.0~1158 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f88c36b394716b8ed7ad43b027ce4152e9024cd3;p=thirdparty%2Fsamba.git s3: smbd: Add utility function get_original_lcomp(). Gets the last component from a client passed-in filename. Copes with @GMT snapshot and MS-DFS names. Preparing to remove original_lcomp from struct smb_filename. Signed-off-by: Jeremy Allison Reviewed-by: Ralph Boehme --- diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index cb1f5d7ea3f..d967366a089 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -1692,6 +1692,90 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, return status; } +/* + * Lightweight function to just get last component + * for rename / enumerate directory calls. + */ + +char *get_original_lcomp(TALLOC_CTX *ctx, + connection_struct *conn, + const char *filename_in, + uint32_t ucf_flags) +{ + struct smb_filename *smb_fname = NULL; + char *last_slash = NULL; + char *orig_lcomp; + char *fname = NULL; + NTSTATUS status; + + if (ucf_flags & UCF_DFS_PATHNAME) { + status = resolve_dfspath_wcard(ctx, + conn, + filename_in, + ucf_flags, + !conn->sconn->using_smb2, + &fname, + NULL); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("resolve_dfspath " + "failed for name %s with %s\n", + filename_in, + nt_errstr(status)); + return NULL; + } + filename_in = fname; + ucf_flags &= ~UCF_DFS_PATHNAME; + } + + /* + * NB. We don't need to care about + * is_fake_file_path(filename_in) here as these + * code paths don't ever return original_lcomp + * or use it anyway. + */ + + if (ucf_flags & UCF_GMT_PATHNAME) { + /* + * Ensure we don't return a @GMT + * value as the last component. + */ + smb_fname = synthetic_smb_fname(ctx, + filename_in, + NULL, + NULL, + 0); + if (smb_fname == NULL) { + TALLOC_FREE(fname); + return NULL; + } + status = canonicalize_snapshot_path(smb_fname); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(fname); + TALLOC_FREE(smb_fname); + return NULL; + } + filename_in = smb_fname->base_name; + } + last_slash = strrchr(filename_in, '/'); + if (last_slash != NULL) { + orig_lcomp = talloc_strdup(ctx, last_slash+1); + } else { + orig_lcomp = talloc_strdup(ctx, filename_in); + } + /* We're done with any temp names here. */ + TALLOC_FREE(smb_fname); + TALLOC_FREE(fname); + if (orig_lcomp == NULL) { + return NULL; + } + status = normalize_filename_case(conn, orig_lcomp); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(orig_lcomp); + return NULL; + } + return orig_lcomp; +} + /** * Go through all the steps to validate a filename. * diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index c79e82fb69d..12d0753ae5f 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -357,6 +357,10 @@ NTSTATUS check_name(connection_struct *conn, int get_real_filename(connection_struct *conn, const char *path, const char *name, TALLOC_CTX *mem_ctx, char **found_name); +char *get_original_lcomp(TALLOC_CTX *ctx, + connection_struct *conn, + const char *filename_in, + uint32_t ucf_flags); NTSTATUS filename_convert(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *name_in,