The branch, master has been updated
       via  1cc250b46e9 s3: smbd: RIP smb_filename->original_lcomp.
       via  d875f60e970 s3: smbd: Remove UCF_SAVE_LCOMP flag. Note it is no 
longer used.
       via  e0d3190b4b1 s3: smbd: Remove all references to original_lcomp from 
name copying code.
       via  79b945d44ea s3: smbd: Now we no longer use it, remove all 
references to original_lcomp from pathname processing code.
       via  5104ec8dec8 s3: smbd: Use get_original_lcomp() inside 
smb_file_rename_information().
       via  d7f2143206e s3: smbd: Use get_original_lcomp() inside 
smb2_file_rename_information().
       via  aa80e9732f8 s3: smbd: Use get_original_lcomp() inside reply_mv().
       via  7d2cb52163b s3: smbd: Use get_original_lcomp() inside 
reply_ntrename().
       via  d5408193953 s3: smbd: Inside rename_internals() wildcard case, 
re-purpose dst_original_lcomp.
       via  6c6e5d52ea3 s3: smbd: Add 'const char *dst_original_lcomp' 
parameter to rename_internals()
       via  6c53372a3ea s3: smbd: Reformatting caller of rename_internals() to 
make it easer to see changed parameters.
       via  454ecaf3b4b s3: smbd: Add a dst_original_lcomp parameter to 
rename_internals_fsp().
       via  614b3003017 s3: smbd: Reformatting callers of 
rename_internals_fsp() to make it easer to see changed parameters.
       via  500037f2181 s3: smbd: Remove use of smb_fname->original_lcomp from 
call_trans2findfirst().
       via  9d785ae5170 s3: smbd: Remove use of smb_fname->original_lcomp from 
smb2 query directory.
       via  f88c36b3947 s3: smbd: Add utility function get_original_lcomp().
       via  dd015436b3e s3: smbd: Extract large directory case normalization 
code into a utility function normalize_filename_case().
      from  047b0d8ab53 nsswitch: fix use-after-free causing segfault in 
_pam_delete_cred

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 1cc250b46e932511b878fd66bb9014b15dcaffaa
Author: Jeremy Allison <[email protected]>
Date:   Thu Mar 26 16:30:48 2020 -0700

    s3: smbd: RIP smb_filename->original_lcomp.
    
    Removed from struct smb_filename. You will not be missed :-).
    Note that VFS ABI modified.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Ralph Boehme <[email protected]>
    
    Autobuild-User(master): Ralph Böhme <[email protected]>
    Autobuild-Date(master): Mon Mar 30 16:23:45 UTC 2020 on sn-devel-184

commit d875f60e970298ba27e7c9f3118c0e1040944774
Author: Jeremy Allison <[email protected]>
Date:   Thu Mar 26 16:27:25 2020 -0700

    s3: smbd: Remove UCF_SAVE_LCOMP flag. Note it is no longer used.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Ralph Boehme <[email protected]>

commit e0d3190b4b199dff4f2089533db6fb32b939a826
Author: Jeremy Allison <[email protected]>
Date:   Thu Mar 26 16:24:08 2020 -0700

    s3: smbd: Remove all references to original_lcomp from name copying code.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Ralph Boehme <[email protected]>

commit 79b945d44eac5891e2a3cd4ef3c4aef9a1923c0a
Author: Jeremy Allison <[email protected]>
Date:   Thu Mar 26 16:22:36 2020 -0700

    s3: smbd: Now we no longer use it, remove all references to original_lcomp 
from pathname processing code.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Ralph Boehme <[email protected]>

commit 5104ec8dec8c0bcf05bfa8569d54dc55b3b8bc22
Author: Jeremy Allison <[email protected]>
Date:   Thu Mar 26 16:18:53 2020 -0700

    s3: smbd: Use get_original_lcomp() inside smb_file_rename_information().
    
    Pass to rename_internals_fsp() and rename_internals().
    
    Removes the last uses of the struct member original_lcomp
    outside of the filename and struct util copying code.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Ralph Boehme <[email protected]>

commit d7f2143206ebc5d1ac8e0add273147b5da94b3b7
Author: Jeremy Allison <[email protected]>
Date:   Thu Mar 26 15:59:51 2020 -0700

    s3: smbd: Use get_original_lcomp() inside smb2_file_rename_information().
    
    Pass to rename_internals_fsp(). Note this is a logic change,
    as the original code only set smb_fname->original_lcomp if
    it was doing a stream rename. Inside rename_internals_fsp()
    we only look at original_lcomp in the stream rename case, so
    this code worked. However, it is much safer to always correctly
    create dst_original_lcomp than pass in a NULL here. It won't
    hurt if it's not actually looked at.
    
    Removes one more use of the struct member original_lcomp.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Ralph Boehme <[email protected]>

commit aa80e9732f84626c36b8d7dce4cdd28c1d0be2e9
Author: Jeremy Allison <[email protected]>
Date:   Thu Mar 26 15:51:18 2020 -0700

    s3: smbd: Use get_original_lcomp() inside reply_mv().
    
    Pass to rename_internals().
    
    Removes one more use of the struct member original_lcomp.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Ralph Boehme <[email protected]>

commit 7d2cb52163baed3cfd5e7f16cb42d513371d4cbf
Author: Jeremy Allison <[email protected]>
Date:   Thu Mar 26 15:48:08 2020 -0700

    s3: smbd: Use get_original_lcomp() inside reply_ntrename().
    
    Pass to rename_internals().
    
    Removes one more use of the struct member original_lcomp.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Ralph Boehme <[email protected]>

commit d5408193953c1b185e5e74a7e39bb40d0f6ff093
Author: Jeremy Allison <[email protected]>
Date:   Thu Mar 26 15:32:36 2020 -0700

    s3: smbd: Inside rename_internals() wildcard case, re-purpose 
dst_original_lcomp.
    
    Pass to rename_internals_fsp() instead of using 
smb_fname_dst->original_lcomp.
    
    Removes one more use of the struct member original_lcomp.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Ralph Boehme <[email protected]>

commit 6c6e5d52ea31f6ddc81823603573c4e3f1a6e93c
Author: Jeremy Allison <[email protected]>
Date:   Wed Mar 25 18:41:10 2020 -0700

    s3: smbd: Add 'const char *dst_original_lcomp' parameter to 
rename_internals()
    
    Pass through the existing smb_fname_dst->original_lcomp
    parameter so no logic change. Preparing to remove the
    use of original_lcomp.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Ralph Boehme <[email protected]>

commit 6c53372a3ea79d0f799c99fe3a63c40d54d5ca01
Author: Jeremy Allison <[email protected]>
Date:   Wed Mar 25 17:17:30 2020 -0700

    s3: smbd: Reformatting caller of rename_internals() to make it easer to see 
changed parameters.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Ralph Boehme <[email protected]>

commit 454ecaf3b4b26619f5a82b265a9f3bb65b8967a2
Author: Jeremy Allison <[email protected]>
Date:   Wed Mar 25 16:20:23 2020 -0700

    s3: smbd: Add a dst_original_lcomp parameter to rename_internals_fsp().
    
    Currently passed in as dst_fname->original_lcomp in all callers
    but will eventually be converted to allow original_lcomp to be
    removed from struct smb_filename.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Ralph Boehme <[email protected]>

commit 614b3003017657e8a6268d3cf73513ab557ed4b2
Author: Jeremy Allison <[email protected]>
Date:   Wed Mar 25 13:42:34 2020 -0700

    s3: smbd: Reformatting callers of rename_internals_fsp() to make it easer 
to see changed parameters.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Ralph Boehme <[email protected]>

commit 500037f218157b9473e684abaf5d6a990b3466a8
Author: Jeremy Allison <[email protected]>
Date:   Wed Mar 25 10:20:14 2020 -0700

    s3: smbd: Remove use of smb_fname->original_lcomp from 
call_trans2findfirst().
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Ralph Boehme <[email protected]>

commit 9d785ae5170ef8f4a072afa01a8965c4d0ff19fc
Author: Jeremy Allison <[email protected]>
Date:   Wed Mar 25 10:03:16 2020 -0700

    s3: smbd: Remove use of smb_fname->original_lcomp from smb2 query directory.
    
    Use get_original_lcomp() call. Removes one use of smb_fname->original_lcomp.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Ralph Boehme <[email protected]>

commit f88c36b394716b8ed7ad43b027ce4152e9024cd3
Author: Jeremy Allison <[email protected]>
Date:   Wed Mar 25 10:00:57 2020 -0700

    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 <[email protected]>
    Reviewed-by: Ralph Boehme <[email protected]>

commit dd015436b3e671f8cf7b503f23f6bd990e4e857c
Author: Jeremy Allison <[email protected]>
Date:   Thu Mar 26 12:35:26 2020 -0700

    s3: smbd: Extract large directory case normalization code into a utility 
function normalize_filename_case().
    
    It is done before the original_lcomp is extracted
    from the client pathname, so the new function that
    will allow us to remove original_lcomp also needs
    this logic.
    
    Signed-off-by: Jeremy Allison <[email protected]>
    Reviewed-by: Ralph Boehme <[email protected]>

-----------------------------------------------------------------------

Summary of changes:
 source3/include/vfs.h               |   2 +-
 source3/lib/filename_util.c         |  13 +--
 source3/smbd/filename.c             | 156 ++++++++++++++++++++++++++----------
 source3/smbd/nttrans.c              |  29 +++++--
 source3/smbd/proto.h                |   6 ++
 source3/smbd/reply.c                |  59 ++++++++++----
 source3/smbd/smb2_query_directory.c |  18 ++++-
 source3/smbd/smbd.h                 |   2 +-
 source3/smbd/trans2.c               |  91 ++++++++++++++-------
 9 files changed, 266 insertions(+), 110 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index bda6cde3fdc..eae9f97179f 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -293,6 +293,7 @@
 /* Change to Version 43 - will ship with 4.13. */
 /* Version 43 - Remove deferred_close from struct files_struct */
 /* Version 43 - Remove SMB_VFS_OPENDIR() */
+/* Version 43 - Remove original_lcomp from struct smb_filename */
 
 #define SMB_VFS_INTERFACE_VERSION 43
 
@@ -639,7 +640,6 @@ struct smb_file_time {
 struct smb_filename {
        char *base_name;
        char *stream_name;
-       char *original_lcomp;
        uint32_t flags;
        SMB_STRUCT_STAT st;
 };
diff --git a/source3/lib/filename_util.c b/source3/lib/filename_util.c
index 66c07001eba..1f2e4d31072 100644
--- a/source3/lib/filename_util.c
+++ b/source3/lib/filename_util.c
@@ -183,7 +183,6 @@ struct smb_filename *cp_smb_filename(TALLOC_CTX *mem_ctx,
        struct smb_filename *out;
        size_t base_len = 0;
        size_t stream_len = 0;
-       size_t lcomp_len = 0;
        int num = 0;
 
        /* stream_name must always be NULL if there is no stream. */
@@ -199,13 +198,9 @@ struct smb_filename *cp_smb_filename(TALLOC_CTX *mem_ctx,
                stream_len = strlen(in->stream_name) + 1;
                num += 1;
        }
-       if (in->original_lcomp != NULL) {
-               lcomp_len = strlen(in->original_lcomp) + 1;
-               num += 1;
-       }
 
        out = talloc_pooled_object(mem_ctx, struct smb_filename,
-                               num, stream_len + base_len + lcomp_len);
+                               num, stream_len + base_len);
        if (out == NULL) {
                return NULL;
        }
@@ -228,12 +223,6 @@ struct smb_filename *cp_smb_filename(TALLOC_CTX *mem_ctx,
                talloc_set_name_const(out->stream_name,
                                      out->stream_name);
        }
-       if (in->original_lcomp != NULL) {
-               out->original_lcomp = talloc_memdup(
-                               out, in->original_lcomp, lcomp_len);
-               talloc_set_name_const(out->original_lcomp,
-                                     out->original_lcomp);
-       }
        out->flags = in->flags;
        out->st = in->st;
        return out;
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index d1dc1aef4f2..9faff9da45a 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -399,6 +399,32 @@ static NTSTATUS canonicalize_snapshot_path(struct 
smb_filename *smb_fname)
                                endp);
 }
 
+/*
+ * Utility function to normalize case on an incoming client filename
+ * if required on this connection struct.
+ * Performs an in-place case conversion guaranteed to stay the same size.
+ */
+
+static NTSTATUS normalize_filename_case(connection_struct *conn, char 
*filename)
+{
+       bool ok;
+
+       if (!conn->case_sensitive) {
+               return NT_STATUS_OK;
+       }
+       if (conn->case_preserve) {
+               return NT_STATUS_OK;
+       }
+       if (conn->short_case_preserve) {
+               return NT_STATUS_OK;
+       }
+       ok = strnorm(filename, lp_default_case(SNUM(conn)));
+       if (!ok) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       return NT_STATUS_OK;
+}
+
 /****************************************************************************
 This routine is called to convert names from the dos namespace to unix
 namespace. It needs to handle any case conversions, mangling, format changes,
@@ -419,9 +445,6 @@ Note NT_STATUS_OK doesn't mean the name exists or is valid, 
just that we
 didn't get any fatal errors that should immediately terminate the calling SMB
 processing whilst resolving.
 
-If the UCF_SAVE_LCOMP flag is passed in, then the unmodified last component
-of the pathname is set in smb_filename->original_lcomp.
-
 If UCF_ALWAYS_ALLOW_WCARD_LCOMP is passed in, then a MS wildcard was detected
 and should be allowed in the last component of the path only.
 
@@ -451,7 +474,6 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
        bool posix_pathnames = (ucf_flags & UCF_POSIX_PATHNAMES);
        bool allow_wcard_last_component =
            (ucf_flags & UCF_ALWAYS_ALLOW_WCARD_LCOMP);
-       bool save_last_component = ucf_flags & UCF_SAVE_LCOMP;
        bool snapshot_path = (ucf_flags & UCF_GMT_PATHNAME);
        NTSTATUS status;
        int ret = -1;
@@ -542,32 +564,11 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
         * the man page. Thanks to [email protected] for finding this. JRA.
         */
 
-       if (conn->case_sensitive && !conn->case_preserve &&
-                       !conn->short_case_preserve) {
-               if (!strnorm(smb_fname->base_name, 
lp_default_case(SNUM(conn)))) {
-                       DBG_ERR("strnorm [%s] failed\n", smb_fname->base_name);
-                       status = NT_STATUS_INVALID_PARAMETER;
-                       goto err;
-               }
-       }
-
-       /*
-        * Ensure saved_last_component is valid even if file exists.
-        */
-
-       if(save_last_component) {
-               end = strrchr_m(smb_fname->base_name, '/');
-               if (end) {
-                       smb_fname->original_lcomp = talloc_strdup(smb_fname,
-                                                                 end + 1);
-               } else {
-                       smb_fname->original_lcomp =
-                           talloc_strdup(smb_fname, smb_fname->base_name);
-               }
-               if (smb_fname->original_lcomp == NULL) {
-                       status = NT_STATUS_NO_MEMORY;
-                       goto err;
-               }
+       status = normalize_filename_case(conn, smb_fname->base_name);
+       if (!NT_STATUS_IS_OK(status)) {
+               DBG_ERR("normalize_filename_case %s failed\n",
+                               smb_fname->base_name);
+               goto err;
        }
 
        /*
@@ -832,17 +833,6 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
                        *end = 0;
                }
 
-               if (save_last_component) {
-                       TALLOC_FREE(smb_fname->original_lcomp);
-                       smb_fname->original_lcomp = talloc_strdup(smb_fname,
-                                                       end ? end + 1 : start);
-                       if (!smb_fname->original_lcomp) {
-                               DBG_ERR("talloc failed\n");
-                               status = NT_STATUS_NO_MEMORY;
-                               goto err;
-                       }
-               }
-
                /* The name cannot have a component of "." */
 
                if (ISDOT(start)) {
@@ -1668,6 +1658,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/nttrans.c b/source3/smbd/nttrans.c
index d169a59a620..001dbe2a79d 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -1585,6 +1585,7 @@ void reply_ntrename(struct smb_request *req)
        struct smb_filename *smb_fname_new = NULL;
        char *oldname = NULL;
        char *newname = NULL;
+       const char *dst_original_lcomp = NULL;
        const char *p;
        NTSTATUS status;
        bool src_has_wcard = False;
@@ -1645,7 +1646,7 @@ void reply_ntrename(struct smb_request *req)
         */
        if (rename_type == RENAME_FLAG_RENAME) {
                ucf_flags_src |= UCF_COND_ALLOW_WCARD_LCOMP;
-               ucf_flags_dst |= UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP;
+               ucf_flags_dst |= UCF_COND_ALLOW_WCARD_LCOMP;
        }
 
        /* rename_internals() calls unix_convert(), so don't call it here. */
@@ -1685,6 +1686,16 @@ void reply_ntrename(struct smb_request *req)
                goto out;
        }
 
+       /* Get the last component of the destination for rename_internals(). */
+       dst_original_lcomp = get_original_lcomp(ctx,
+                                       conn,
+                                       newname,
+                                       ucf_flags_dst);
+       if (dst_original_lcomp == NULL) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               goto out;
+       }
+
        if (stream_rename) {
                /* smb_fname_new must be the same as smb_fname_old. */
                TALLOC_FREE(smb_fname_new->base_name);
@@ -1702,11 +1713,17 @@ void reply_ntrename(struct smb_request *req)
 
        switch(rename_type) {
                case RENAME_FLAG_RENAME:
-                       status = rename_internals(ctx, conn, req,
-                                                 smb_fname_old, smb_fname_new,
-                                                 attrs, False, src_has_wcard,
-                                                 dest_has_wcard,
-                                                 DELETE_ACCESS);
+                       status = rename_internals(ctx,
+                                               conn,
+                                               req,
+                                               smb_fname_old,
+                                               smb_fname_new,
+                                               dst_original_lcomp,
+                                               attrs,
+                                               false,
+                                               src_has_wcard,
+                                               dest_has_wcard,
+                                               DELETE_ACCESS);
                        break;
                case RENAME_FLAG_HARD_LINK:
                        if (src_has_wcard || dest_has_wcard) {
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index c79e82fb69d..cb32ebaca5e 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,
@@ -1014,6 +1018,7 @@ void reply_rmdir(struct smb_request *req);
 NTSTATUS rename_internals_fsp(connection_struct *conn,
                        files_struct *fsp,
                        const struct smb_filename *smb_fname_dst_in,
+                       const char *dst_original_lcomp,
                        uint32_t attrs,
                        bool replace_if_exists);
 NTSTATUS rename_internals(TALLOC_CTX *ctx,
@@ -1021,6 +1026,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                        struct smb_request *req,
                        struct smb_filename *smb_fname_src,
                        struct smb_filename *smb_fname_dst,
+                       const char *dst_original_lcomp,
                        uint32_t attrs,
                        bool replace_if_exists,
                        bool src_has_wild,
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 58bc7d05eab..b23a2d373b2 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -7575,6 +7575,7 @@ static NTSTATUS 
parent_dirname_compatible_open(connection_struct *conn,
 NTSTATUS rename_internals_fsp(connection_struct *conn,
                        files_struct *fsp,
                        const struct smb_filename *smb_fname_dst_in,
+                       const char *dst_original_lcomp,
                        uint32_t attrs,
                        bool replace_if_exists)
 {
@@ -7627,7 +7628,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
                /*
                 * Split off the last component of the processed
                 * destination name. We will compare this to
-                * the split components of smb_fname_dst->original_lcomp.
+                * the split components of dst_original_lcomp.
                 */
                if (!parent_dirname(ctx,
                                smb_fname_dst->base_name,
@@ -7638,7 +7639,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
                }
 
                /*
-                * The original_lcomp component contains
+                * The dst_original_lcomp component contains
                 * the last_component of the path + stream
                 * name (if a stream exists).
                 *
@@ -7649,13 +7650,13 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
                if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
                        /* POSIX - no stream component. */
                        orig_lcomp_path = talloc_strdup(ctx,
-                                               smb_fname_dst->original_lcomp);
+                                               dst_original_lcomp);
                        if (orig_lcomp_path == NULL) {
                                ok = false;
                        }
                } else {
                        ok = split_stream_filename(ctx,
-                                       smb_fname_dst->original_lcomp,
+                                       dst_original_lcomp,
                                        &orig_lcomp_path,
                                        &orig_lcomp_stream);
                }
@@ -7899,6 +7900,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                        struct smb_request *req,
                        struct smb_filename *smb_fname_src,
                        struct smb_filename *smb_fname_dst,
+                       const char *dst_original_lcomp,
                        uint32_t attrs,
                        bool replace_if_exists,
                        bool src_has_wild,
@@ -7997,7 +7999,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                          conn->short_case_preserve,
                          smb_fname_str_dbg(smb_fname_src),
                          smb_fname_str_dbg(smb_fname_dst),
-                         smb_fname_dst->original_lcomp));
+                         dst_original_lcomp));
 
                /* The dest name still may have wildcards. */
                if (dest_has_wild) {
@@ -8061,8 +8063,12 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                        goto out;
                }
 
-               status = rename_internals_fsp(conn, fsp, smb_fname_dst,
-                                             attrs, replace_if_exists);
+               status = rename_internals_fsp(conn,
+                                       fsp,
+                                       smb_fname_dst,
+                                       dst_original_lcomp,
+                                       attrs,
+                                       replace_if_exists);
 
                close_file(req, fsp, NORMAL_CLOSE);
 
@@ -8222,15 +8228,18 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                        break;
                }
 
-               smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
-                                                             dname);
-               if (!smb_fname_dst->original_lcomp) {
+               dst_original_lcomp = talloc_strdup(smb_fname_dst, dname);
+               if (dst_original_lcomp == NULL) {
                        status = NT_STATUS_NO_MEMORY;
                        goto out;
                }
 
-               status = rename_internals_fsp(conn, fsp, smb_fname_dst,
-                                             attrs, replace_if_exists);
+               status = rename_internals_fsp(conn,
+                                       fsp,
+                                       smb_fname_dst,
+                                       dst_original_lcomp,
+                                       attrs,
+                                       replace_if_exists);
 
                close_file(req, fsp, NORMAL_CLOSE);
 
@@ -8281,12 +8290,12 @@ void reply_mv(struct smb_request *req)
        TALLOC_CTX *ctx = talloc_tos();
        struct smb_filename *smb_fname_src = NULL;
        struct smb_filename *smb_fname_dst = NULL;
+       const char *dst_original_lcomp = NULL;
        uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
                (req->posix_pathnames ?
                        UCF_UNIX_NAME_LOOKUP :
                        UCF_COND_ALLOW_WCARD_LCOMP);
        uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
-               UCF_SAVE_LCOMP |
                (req->posix_pathnames ?
                        0 :
                        UCF_COND_ALLOW_WCARD_LCOMP);
@@ -8364,6 +8373,16 @@ void reply_mv(struct smb_request *req)
                goto out;
        }
 
+       /* Get the last component of the destination for rename_internals(). */
+       dst_original_lcomp = get_original_lcomp(ctx,
+                                       conn,
+                                       newname,
+                                       dst_ucf_flags);
+       if (dst_original_lcomp == NULL) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               goto out;
+       }
+
        if (stream_rename) {
                /* smb_fname_dst->base_name must be the same as
                   smb_fname_src->base_name. */
@@ -8379,9 +8398,17 @@ void reply_mv(struct smb_request *req)
        DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
                 smb_fname_str_dbg(smb_fname_dst)));
 
-       status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
-                                 attrs, False, src_has_wcard, dest_has_wcard,
-                                 DELETE_ACCESS);
+       status = rename_internals(ctx,
+                               conn,
+                               req,
+                               smb_fname_src,
+                               smb_fname_dst,
+                               dst_original_lcomp,


-- 
Samba Shared Repository

Reply via email to