smbd: pass symlink target path to safe_symlink_target_path()
authorRalph Boehme <slow@samba.org>
Tue, 2 Jan 2024 11:49:14 +0000 (12:49 +0100)
committerJule Anger <janger@samba.org>
Mon, 29 Jan 2024 10:45:17 +0000 (10:45 +0000)
Moves processing the symlink error response to the caller
filename_convert_dirfsp(). Prepares for using this in
non_widelink_open(), where it will replace symlink_target_below_conn()
with the same functionality.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15549

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
(back-ported from commit 0515dded4ddb49e5570ae7df51126af1a2d643de)

source3/include/proto.h
source3/smbd/filename.c

index f71796b57ae9c38c564c9160c68ee6c956ecd578..5e1e807b1adc5b2a123d55923418ccc0bd3492ed 100644 (file)
@@ -718,6 +718,11 @@ struct smb_filename *synthetic_smb_fname(TALLOC_CTX *mem_ctx,
                                         const SMB_STRUCT_STAT *psbuf,
                                         NTTIME twrp,
                                         uint32_t flags);
+NTSTATUS safe_symlink_target_path(TALLOC_CTX *mem_ctx,
+                                 const char *connectpath,
+                                 const char *target,
+                                 size_t unparsed,
+                                 char **_relative);
 NTSTATUS filename_convert_dirfsp(
        TALLOC_CTX *ctx,
        connection_struct *conn,
index dd0239777e89b8e737301ae444e2af691a041df4..606959d0805f5c3e22172269dd8c76d52740ec6b 100644 (file)
@@ -943,44 +943,34 @@ static char *symlink_target_path(
        return ret;
 }
 
-static NTSTATUS safe_symlink_target_path(
-       TALLOC_CTX *mem_ctx,
-       const char *connectpath,
-       const char *name_in,
-       const char *substitute,
-       size_t unparsed,
-       char **_name_out)
+NTSTATUS safe_symlink_target_path(TALLOC_CTX *mem_ctx,
+                                 const char *connectpath,
+                                 const char *target,
+                                 size_t unparsed,
+                                 char **_relative)
 {
-       char *target = NULL;
        char *abs_target = NULL;
        char *abs_target_canon = NULL;
        const char *relative = NULL;
-       char *name_out = NULL;
-       NTSTATUS status = NT_STATUS_NO_MEMORY;
        bool in_share;
+       NTSTATUS status = NT_STATUS_NO_MEMORY;
 
-       target = symlink_target_path(mem_ctx, name_in, substitute, unparsed);
-       if (target == NULL) {
-               goto fail;
-       }
-
-       DBG_DEBUG("name_in: %s, substitute: %s, unparsed: %zu, target=%s\n",
-                 name_in,
-                 substitute,
-                 unparsed,
-                 target);
+       DBG_DEBUG("connectpath [%s] target [%s] unparsed [%zu]\n",
+                 connectpath, target, unparsed);
 
        if (target[0] == '/') {
-               abs_target = target;
+               abs_target = talloc_strdup(mem_ctx, target);
        } else {
-               abs_target = talloc_asprintf(
-                       target, "%s/%s", connectpath, target);
-               if (abs_target == NULL) {
-                       goto fail;
-               }
+               abs_target = talloc_asprintf(mem_ctx,
+                                            "%s/%s",
+                                            connectpath,
+                                            target);
+       }
+       if (abs_target == NULL) {
+               goto fail;
        }
 
-       abs_target_canon = canonicalize_absolute_path(target, abs_target);
+       abs_target_canon = canonicalize_absolute_path(abs_target, abs_target);
        if (abs_target_canon == NULL) {
                goto fail;
        }
@@ -995,15 +985,14 @@ static NTSTATUS safe_symlink_target_path(
                goto fail;
        }
 
-       name_out = talloc_strdup(mem_ctx, relative);
-       if (name_out == NULL) {
+       *_relative = talloc_strdup(mem_ctx, relative);
+       if (*_relative == NULL) {
                goto fail;
        }
 
        status = NT_STATUS_OK;
-       *_name_out = name_out;
 fail:
-       TALLOC_FREE(target);
+       TALLOC_FREE(abs_target);
        return status;
 }
 
@@ -1456,6 +1445,7 @@ NTSTATUS filename_convert_dirfsp(
        size_t unparsed = 0;
        NTSTATUS status;
        char *target = NULL;
+       char *safe_target = NULL;
        size_t symlink_redirects = 0;
 
 next:
@@ -1494,17 +1484,21 @@ next:
         * resolve all symlinks locally.
         */
 
-       status = safe_symlink_target_path(
-               mem_ctx,
-               conn->connectpath,
-               name_in,
-               substitute,
-               unparsed,
-               &target);
+       target = symlink_target_path(mem_ctx, name_in, substitute, unparsed);
+       if (target == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       status = safe_symlink_target_path(mem_ctx,
+                                         conn->connectpath,
+                                         target,
+                                         unparsed,
+                                         &safe_target);
+       TALLOC_FREE(target);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
-       name_in = target;
+       name_in = safe_target;
 
        symlink_redirects += 1;