[SCM] Samba Shared Repository - branch master updated

Volker Lendecke vlendec at samba.org
Tue Nov 7 13:59:01 UTC 2023


The branch, master has been updated
       via  d314fc5874e smbd: Make get_real_filename_cache_key() static in files.c
       via  8d00b0e664d smbd: Simplify openat_pathref_fsp_case_insensitive()
       via  ab56379c227 smbd: Make get_real_filename_cache_key() public
       via  552f9e9d558 smbd: We want to delete symlinks as such in reply_unlink()
       via  6ea681f36e0 smbd: Make create_open_symlink_err() public
       via  8308d25ff9d smbd: Make in_create_options available in smbd_smb2_create_after_exec()
       via  6c3c37cf209 smbd: Make a fake file's stat a valid regular file
       via  193df617816 smbd: Simplify fsp_fullbasepath()
       via  8392a832b59 smbd: Correct PATH_ vs NAME_NOT_FOUND for not following lcomp
       via  cee9586c6ee smbd: Return OBJECT_NAME_NOT_FOUND if lcomp points outside the share
       via  c81d1d3fe4e smbd: Return open_symlink_err from filename_convert_dirfsp_nosymlink()
       via  62800d6213e libcli: Fix whitespace
       via  ac60b7a1455 smbd: We don't reopen anything but dirs and files
       via  ae236f8f4db smbd: Remove a few pointless return; statements
       via  5b0500f0c90 smbd: Protect ea-reading on symlinks
       via  f72f9915680 smbd: Remove an assert that never triggers
       via  74e121f93b3 librpc: Fix error path cleanups in start_rpc_host_send()
      from  273d48504e1 CI: smb3unix.py: check more attributes of test files (and dirs) in test_posix_perm_files()

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


- Log -----------------------------------------------------------------
commit d314fc5874e243f9fd659aa9fdf3c5ed6c0c6a22
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Nov 4 16:17:36 2023 +0100

    smbd: Make get_real_filename_cache_key() static in files.c
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    
    Autobuild-User(master): Volker Lendecke <vl at samba.org>
    Autobuild-Date(master): Tue Nov  7 13:58:07 UTC 2023 on atb-devel-224

commit 8d00b0e664d76931dd29b417e90ec1e4ff488939
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Oct 18 11:50:20 2023 +0200

    smbd: Simplify openat_pathref_fsp_case_insensitive()
    
    This is more lines of code, but it's still a simplification. With this
    patch we don't call the full openat_pathref_fsp() anymore when looking
    up the last component in filename_convert_dirfsp(), instead we do the
    direct SMB_VFS_OPENAT(). We don't need the whole complexity of
    non_widelink_open() for this case, we do know that we have a real
    non-cwd dirfsp.
    
    The other big change that is not obvious just from looking at the
    patch: This removes the special case for looking up posix
    symlinks. Before this patch, filename_convert_dirfsp() returned a
    proper smb_filename but without an attached fsp when a smb1 posix
    client hits a symlink. This caused all sorts of special case code
    everywhere. For example smbd_do_qfilepathinfo() needs to cover both
    cases just for the smb1 posix symlink case. This special-case handling
    can go now. We can do the path lookup in the smb1-only qpathinfo code
    and call into the common code with a proper fsp.
    
    When hitting a symlink and with O_PATH available, we'll get the
    symlink opened with an O_PATH fd. Without O_PATH we obviously can't do
    that, there we get fd=-1 and an indication that we don't have the
    procfd fallback around.
    
    Why all this?
    
    I want to present FIFOs (and eventually symlinks) as reparse points as
    the very next step. Without this patch, there is no real unified way
    to get the file attributes from disk. Now we can use the proper logic
    of fdos_mode() everywhere and not rely on special cases for fsp==NULL.
    
    This patch also changes some error codes for smb1 posix extensions. I
    chose to just change the test instead of going after each and every
    change. As long as we do get an error, I'm willing to accept that we
    slightly change error path behaviour for this deprecated code.
    
    And, I tried to split this up into smaller patches but I failed.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit ab56379c22702d364b0b55fe993e407739b6af91
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Nov 4 15:41:40 2023 +0100

    smbd: Make get_real_filename_cache_key() public
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 552f9e9d5584dac4177aef70eb438530976557d6
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Oct 25 18:58:34 2023 +0200

    smbd: We want to delete symlinks as such in reply_unlink()
    
    Even with "follow symlinks = yes" we don't want to delete the target
    when being given a symlink name.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 6ea681f36e09c05ede087ec88809ed6805657354
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Oct 23 15:45:08 2023 +0200

    smbd: Make create_open_symlink_err() public
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 8308d25ff9d5cf1e0039aa900da1c75132f63495
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Dec 1 17:42:13 2022 +0100

    smbd: Make in_create_options available in smbd_smb2_create_after_exec()
    
    Enable NT_STATUS_IO_REPARSE_TAG_NOT_HANDLED and _STOPPED_ON_SYMLINK if
    not opening with FILE_OPEN_REPARSE_POINT. We only know after all the
    open logic what we have.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 6c3c37cf2092615375ad3fb6a06505a4d1363eb0
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Oct 23 16:40:55 2023 +0200

    smbd: Make a fake file's stat a valid regular file
    
    We'll add strict checks to only open IFDIR and IFREG soon.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 193df617816127a75bc4a29b46d3ada920c52f76
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Oct 29 12:10:08 2023 +0100

    smbd: Simplify fsp_fullbasepath()
    
    Don't call snprintf() if not necessary.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 8392a832b5921b02bfb7e1b5fd321d36069f044a
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Oct 25 19:22:11 2023 +0200

    smbd: Correct PATH_ vs NAME_NOT_FOUND for not following lcomp
    
    Right now this is handled in openat_pathref_fsp(), but this will
    change soon.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit cee9586c6eeb8a332f4406d3a1fc47c11230f302
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Oct 24 18:47:59 2023 +0200

    smbd: Return OBJECT_NAME_NOT_FOUND if lcomp points outside the share
    
    filename_convert_dirfsp() is the only caller of
    safe_symlink_target_path(). Right now this is not called with
    "unparsed==0" because the last component is handled in
    openat_pathref_fsp() and thus non_widelink_open(). I have code that
    will change this, so that we can simplify
    openat_pathref_fsp_case_insensitive() to directly call OPENAT, not
    going through non_widelink_open. This will cause
    safe_symlink_target_path() also be called for the last component,
    which means it needs logic to distinguish between PATH_ and
    NAME_NOT_FOUND.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit c81d1d3fe4e3aeb2761dc539e8fb87d2ad862e5f
Author: Volker Lendecke <vl at samba.org>
Date:   Fri Dec 16 16:35:00 2022 +0100

    smbd: Return open_symlink_err from filename_convert_dirfsp_nosymlink()
    
    Don't lose information returned from openat_pathref_fsp_nosymlink()
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 62800d6213e31f926e04db310bc3027e696947cf
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Oct 31 15:48:09 2023 +0100

    libcli: Fix whitespace
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit ac60b7a14557aaab5fe9c84df53c7bb8bebd6318
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Oct 15 17:56:46 2023 +0200

    smbd: We don't reopen anything but dirs and files
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit ae236f8f4db03c6bd6b7471565ad7341337dd405
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Nov 2 13:35:19 2023 +0100

    smbd: Remove a few pointless return; statements
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 5b0500f0c90c7188acd39e657a57000072eb263d
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Oct 31 15:38:46 2023 +0100

    smbd: Protect ea-reading on symlinks
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit f72f9915680f6c36351fb89049000b68c749565c
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Oct 31 15:35:59 2023 +0100

    smbd: Remove an assert that never triggers
    
    We've checked that right above.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 74e121f93b3bf7cd36f1f4554951280d71bbf8c2
Author: Volker Lendecke <vl at samba.org>
Date:   Fri Nov 3 16:02:32 2023 +0100

    librpc: Fix error path cleanups in start_rpc_host_send()
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

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

Summary of changes:
 source3/modules/vfs_widelinks.c                    |   2 +-
 source3/rpc_client/local_np.c                      |   4 +-
 .../tests/test_symlink_traversal_smb1_posix.sh     |  12 +-
 source3/smbd/filename.c                            | 343 ++++-------------
 source3/smbd/files.c                               | 407 ++++++++++++++++++---
 source3/smbd/open.c                                |  33 ++
 source3/smbd/proto.h                               |   8 +
 source3/smbd/smb1_reply.c                          |   2 +-
 source3/smbd/smb1_trans2.c                         |  10 -
 source3/smbd/smb2_create.c                         |  30 +-
 source3/smbd/smb2_trans2.c                         |  10 +-
 source4/libcli/raw/clierror.c                      |  10 +-
 source4/libcli/raw/clioplock.c                     |  10 +-
 source4/libcli/raw/clisession.c                    |  26 +-
 source4/libcli/raw/clisocket.c                     |   8 +-
 source4/libcli/raw/clitransport.c                  |  16 +-
 source4/libcli/raw/clitree.c                       |  22 +-
 source4/libcli/raw/interfaces.h                    | 116 +++---
 source4/libcli/raw/rawacl.c                        |  24 +-
 source4/libcli/raw/rawdate.c                       |  12 +-
 source4/libcli/raw/raweas.c                        |  18 +-
 source4/libcli/raw/rawfile.c                       | 106 +++---
 source4/libcli/raw/rawfileinfo.c                   | 104 +++---
 source4/libcli/raw/rawfsinfo.c                     |  76 ++--
 source4/libcli/raw/rawioctl.c                      |  38 +-
 source4/libcli/raw/rawlpq.c                        |   8 +-
 source4/libcli/raw/rawnegotiate.c                  |   8 +-
 source4/libcli/raw/rawnotify.c                     |  16 +-
 source4/libcli/raw/rawreadwrite.c                  |  32 +-
 source4/libcli/raw/rawrequest.c                    |  68 ++--
 source4/libcli/raw/rawsearch.c                     |  86 ++---
 source4/libcli/raw/rawsetfileinfo.c                |  76 ++--
 source4/libcli/raw/rawshadow.c                     |  20 +-
 source4/libcli/raw/rawtrans.c                      |   8 +-
 source4/libcli/raw/smb.h                           |  18 +-
 source4/libcli/raw/smb_signing.c                   |  31 +-
 source4/libcli/raw/trans2.h                        |   8 +-
 37 files changed, 987 insertions(+), 839 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/modules/vfs_widelinks.c b/source3/modules/vfs_widelinks.c
index 29f2d4834f6..c5b5084e108 100644
--- a/source3/modules/vfs_widelinks.c
+++ b/source3/modules/vfs_widelinks.c
@@ -389,7 +389,7 @@ static int widelinks_openat(vfs_handle_struct *handle,
 			fsp->fsp_name->st = full_fname->st;
 		}
 		TALLOC_FREE(full_fname);
-		errno = ENOENT;
+		errno = ELOOP;
 	}
 	return ret;
 }
diff --git a/source3/rpc_client/local_np.c b/source3/rpc_client/local_np.c
index 2e9d1b4febe..10c6434e397 100644
--- a/source3/rpc_client/local_np.c
+++ b/source3/rpc_client/local_np.c
@@ -403,11 +403,11 @@ static struct tevent_req *start_rpc_host_send(
 	return req;
 
 fail:
-	if (ready_fds[0] == -1) {
+	if (ready_fds[0] != -1) {
 		close(ready_fds[0]);
 		ready_fds[0] = -1;
 	}
-	if (ready_fds[1] == -1) {
+	if (ready_fds[1] != -1) {
 		close(ready_fds[1]);
 		ready_fds[1] = -1;
 	}
diff --git a/source3/script/tests/test_symlink_traversal_smb1_posix.sh b/source3/script/tests/test_symlink_traversal_smb1_posix.sh
index 1ad1d56f12a..52d6cfb9e3d 100755
--- a/source3/script/tests/test_symlink_traversal_smb1_posix.sh
+++ b/source3/script/tests/test_symlink_traversal_smb1_posix.sh
@@ -194,13 +194,13 @@ test_symlink_traversal_SMB1_posix_onename()
 	# ls commands.
 	#
 	smbclient_expect_error "ls" "$name" "" "NT_STATUS_OK" || return 1
-	smbclient_expect_error "ls" "$name/noexist" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1
-	smbclient_expect_error "ls" "$name/*" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1
+	smbclient_expect_error "ls" "$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+	smbclient_expect_error "ls" "$name/*" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
 	smbclient_expect_error "ls" "$name/*/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
 	# Now in subdirectory emptydir
 	smbclient_expect_error "ls" "emptydir/$name" "" "NT_STATUS_OK" || return 1
-	smbclient_expect_error "ls" "emptydir/$name/noexist" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1
-	smbclient_expect_error "ls" "emptydir/$name/*" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1
+	smbclient_expect_error "ls" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+	smbclient_expect_error "ls" "emptydir/$name/*" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
 	smbclient_expect_error "ls" "emptydir/$name/*/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
 	#
 	# SMB1+POSIX stat commands. All symlinks can be stat'ed.
@@ -211,9 +211,9 @@ test_symlink_traversal_SMB1_posix_onename()
 	# del commands. Under SMB1+POSIX we can legitimately delete symlinks, so don't
 	# try and delete symlink targets, we need them for the later tests.
 	#
-	smbclient_expect_error "del" "$name/noexist" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1
+	smbclient_expect_error "del" "$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
 	# Now in subdirectory emptydir
-	smbclient_expect_error "del" "emptydir/$name/noexist" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1
+	smbclient_expect_error "del" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
 
 	if [ "$do_rename" = "do rename" ]; then
 		#
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index 7032d218e52..5219fcd721e 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -29,7 +29,6 @@
 #include "fake_file.h"
 #include "smbd/smbd.h"
 #include "smbd/globals.h"
-#include "lib/util/memcache.h"
 #include "libcli/smb/reparse.h"
 
 uint32_t ucf_flags_from_smb_request(struct smb_request *req)
@@ -405,53 +404,6 @@ NTSTATUS get_real_filename_at(struct files_struct *dirfsp,
 	return status;
 }
 
-/*
- * Create the memcache-key for GETREALFILENAME_CACHE: This supplements
- * the stat cache for the last component to be looked up. Cache
- * contents is the correctly capitalized translation of the parameter
- * "name" as it exists on disk. This is indexed by inode of the dirfsp
- * and name, and contrary to stat_cahce_lookup() it does not
- * vfs_stat() the last component. This will be taken care of by an
- * attempt to do a openat_pathref_fsp().
- */
-static bool get_real_filename_cache_key(
-	TALLOC_CTX *mem_ctx,
-	struct files_struct *dirfsp,
-	const char *name,
-	DATA_BLOB *_key)
-{
-	struct file_id fid = vfs_file_id_from_sbuf(
-		dirfsp->conn, &dirfsp->fsp_name->st);
-	char *upper = NULL;
-	uint8_t *key = NULL;
-	size_t namelen, keylen;
-
-	upper = talloc_strdup_upper(mem_ctx, name);
-	if (upper == NULL) {
-		return false;
-	}
-	namelen = talloc_get_size(upper);
-
-	keylen = namelen + sizeof(fid);
-	if (keylen < sizeof(fid)) {
-		TALLOC_FREE(upper);
-		return false;
-	}
-
-	key = talloc_size(mem_ctx, keylen);
-	if (key == NULL) {
-		TALLOC_FREE(upper);
-		return false;
-	}
-
-	memcpy(key, &fid, sizeof(fid));
-	memcpy(key + sizeof(fid), upper, namelen);
-	TALLOC_FREE(upper);
-
-	*_key = (DATA_BLOB) { .data = key, .length = keylen, };
-	return true;
-}
-
 /*
  * Lightweight function to just get last component
  * for rename / enumerate directory calls.
@@ -641,155 +593,6 @@ static NTSTATUS filename_convert_normalize_new(
 	return NT_STATUS_OK;
 }
 
-/*
- * Open smb_fname_rel->fsp as a pathref fsp with a case insensitive
- * fallback using GETREALFILENAME_CACHE and get_real_filename_at() if
- * the first attempt based on the filename sent by the client gives
- * ENOENT.
- */
-static NTSTATUS openat_pathref_fsp_case_insensitive(
-	struct files_struct *dirfsp,
-	struct smb_filename *smb_fname_rel,
-	uint32_t ucf_flags)
-{
-	const bool posix = (ucf_flags & UCF_POSIX_PATHNAMES);
-	DATA_BLOB cache_key = { .data = NULL, };
-	char *found_name = NULL;
-	NTSTATUS status;
-	bool ok;
-
-	SET_STAT_INVALID(smb_fname_rel->st);
-
-	/* Check veto files - only looks at last component. */
-	if (IS_VETO_PATH(dirfsp->conn, smb_fname_rel->base_name)) {
-		DBG_DEBUG("veto files rejecting last component %s\n",
-			  smb_fname_str_dbg(smb_fname_rel));
-		return NT_STATUS_NETWORK_OPEN_RESTRICTION;
-	}
-
-	status = openat_pathref_fsp(dirfsp, smb_fname_rel);
-
-	if (NT_STATUS_IS_OK(status)) {
-		return NT_STATUS_OK;
-	}
-
-	if (VALID_STAT(smb_fname_rel->st)) {
-		/*
-		 * We got an error although the object existed. Might
-		 * be a symlink we don't want.
-		 */
-		return status;
-	}
-
-	if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
-		/*
-		 * Only retry on ENOENT
-		 */
-		return status;
-	}
-
-	if (posix || dirfsp->conn->case_sensitive) {
-		/*
-		 * Only return case insensitive if required
-		 */
-		return status;
-	}
-
-	if (lp_stat_cache()) {
-		char *base_name = smb_fname_rel->base_name;
-		char *original_relname = NULL;
-		DATA_BLOB value = { .data = NULL };
-
-		ok = get_real_filename_cache_key(
-			talloc_tos(), dirfsp, base_name, &cache_key);
-		if (!ok) {
-			/*
-			 * probably ENOMEM, just bail
-			 */
-			return status;
-		}
-
-		DO_PROFILE_INC(statcache_lookups);
-
-		ok = memcache_lookup(
-			NULL, GETREALFILENAME_CACHE, cache_key, &value);
-		if (!ok) {
-			DO_PROFILE_INC(statcache_misses);
-			goto lookup;
-		}
-		DO_PROFILE_INC(statcache_hits);
-
-		/*
-		 * For the "new filename" case we need to preserve the
-		 * capitalization the client sent us, see
-		 * https://bugzilla.samba.org/show_bug.cgi?id=15481
-		 */
-		original_relname = smb_fname_rel->base_name;
-
-		smb_fname_rel->base_name = talloc_memdup(
-			smb_fname_rel, value.data, value.length);
-		if (smb_fname_rel->base_name == NULL) {
-			TALLOC_FREE(cache_key.data);
-			return NT_STATUS_NO_MEMORY;
-		}
-
-		if (IS_VETO_PATH(dirfsp->conn, smb_fname_rel->base_name)) {
-			DBG_DEBUG("veto files rejecting last component %s\n",
-				  smb_fname_str_dbg(smb_fname_rel));
-			TALLOC_FREE(cache_key.data);
-			return NT_STATUS_NETWORK_OPEN_RESTRICTION;
-		}
-
-		status = openat_pathref_fsp(dirfsp, smb_fname_rel);
-		if (NT_STATUS_IS_OK(status)) {
-			TALLOC_FREE(cache_key.data);
-			TALLOC_FREE(original_relname);
-			return NT_STATUS_OK;
-		}
-
-		memcache_delete(NULL, GETREALFILENAME_CACHE, cache_key);
-		TALLOC_FREE(smb_fname_rel->base_name);
-		smb_fname_rel->base_name = original_relname;
-	}
-
-lookup:
-	status = get_real_filename_at(
-		dirfsp, smb_fname_rel->base_name, smb_fname_rel, &found_name);
-	if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
-	    (ucf_flags & UCF_PREP_CREATEFILE)) {
-		/*
-		 * dropbox
-		 */
-		status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
-	}
-
-	if (NT_STATUS_IS_OK(status)) {
-		TALLOC_FREE(smb_fname_rel->base_name);
-		smb_fname_rel->base_name = found_name;
-
-		if (IS_VETO_PATH(dirfsp->conn, smb_fname_rel->base_name)) {
-			DBG_DEBUG("veto files rejecting last component %s\n",
-				smb_fname_str_dbg(smb_fname_rel));
-			return NT_STATUS_NETWORK_OPEN_RESTRICTION;
-		}
-
-		status = openat_pathref_fsp(dirfsp, smb_fname_rel);
-	}
-
-	if (NT_STATUS_IS_OK(status) && (cache_key.data != NULL)) {
-		DATA_BLOB value = {
-			.data = (uint8_t *)smb_fname_rel->base_name,
-			.length = strlen(smb_fname_rel->base_name) + 1,
-		};
-
-		memcache_add(NULL, GETREALFILENAME_CACHE, cache_key, value);
-	}
-
-	TALLOC_FREE(cache_key.data);
-
-	return status;
-}
-
 static const char *previous_slash(const char *name_in, const char *slash)
 {
 	const char *prev = NULL;
@@ -903,7 +706,8 @@ static NTSTATUS safe_symlink_target_path(
 		connectpath, strlen(connectpath), abs_target_canon, &relative);
 	if (!in_share) {
 		DBG_DEBUG("wide link to %s\n", abs_target_canon);
-		status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+		status = (unparsed != 0) ? NT_STATUS_OBJECT_PATH_NOT_FOUND
+					 : NT_STATUS_OBJECT_NAME_NOT_FOUND;
 		goto fail;
 	}
 
@@ -931,12 +735,12 @@ static NTSTATUS filename_convert_dirfsp_nosymlink(
 	NTTIME twrp,
 	struct files_struct **_dirfsp,
 	struct smb_filename **_smb_fname,
-	char **_substitute,
-	size_t *_unparsed)
+	struct open_symlink_err **_symlink_err)
 {
 	struct smb_filename *smb_dirname = NULL;
 	struct smb_filename *smb_fname_rel = NULL;
 	struct smb_filename *smb_fname = NULL;
+	struct open_symlink_err *symlink_err = NULL;
 	const bool posix = (ucf_flags & UCF_POSIX_PATHNAMES);
 	char *dirname = NULL;
 	const char *fname_rel = NULL;
@@ -953,7 +757,10 @@ static NTSTATUS filename_convert_dirfsp_nosymlink(
 		if (smb_fname == NULL) {
 			return NT_STATUS_NO_MEMORY;
 		}
-		smb_fname->st = (SMB_STRUCT_STAT) { .st_ex_nlink = 1 };
+		smb_fname->st = (SMB_STRUCT_STAT){
+			.st_ex_nlink = 1,
+			.st_ex_mode = S_IFREG | 0644,
+		};
 		smb_fname->st.st_ex_btime =
 			(struct timespec){0, SAMBA_UTIME_OMIT};
 		smb_fname->st.st_ex_atime =
@@ -1019,8 +826,6 @@ static NTSTATUS filename_convert_dirfsp_nosymlink(
 			posix ? SMB_FILENAME_POSIX_PATH : 0,
 			&smb_dirname);
 	} else {
-		struct open_symlink_err *symlink_err = NULL;
-
 		status = normalize_filename_case(conn, dirname, ucf_flags);
 		if (!NT_STATUS_IS_OK(status)) {
 			DBG_ERR("normalize_filename_case %s failed: %s\n",
@@ -1041,24 +846,13 @@ static NTSTATUS filename_convert_dirfsp_nosymlink(
 		if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
 			size_t name_in_len, dirname_len;
 
-			if (lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) &&
-			    strnequal(symlink_err->reparse->substitute_name,
-				      "msdfs:",
-				      6)) {
-				status = NT_STATUS_PATH_NOT_COVERED;
-				goto fail;
-			}
-
 			name_in_len = strlen(name_in);
 			dirname_len = strlen(dirname);
 
 			SMB_ASSERT(name_in_len >= dirname_len);
 
-			*_substitute = talloc_move(
-				mem_ctx,
-				&symlink_err->reparse->substitute_name);
-			*_unparsed = symlink_err->unparsed +
-				     (name_in_len - dirname_len);
+			symlink_err->unparsed += (name_in_len - dirname_len);
+			*_symlink_err = symlink_err;
 
 			goto fail;
 		}
@@ -1144,45 +938,27 @@ static NTSTATUS filename_convert_dirfsp_nosymlink(
 		goto fail;
 	}
 
-	status = openat_pathref_fsp_case_insensitive(
-		smb_dirname->fsp, smb_fname_rel, ucf_flags);
+	status = openat_pathref_fsp_lcomp(smb_dirname->fsp,
+					  smb_fname_rel,
+					  ucf_flags);
 
-	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
-	    VALID_STAT(smb_fname_rel->st) &&
-	    S_ISLNK(smb_fname_rel->st.st_ex_mode)) {
+	if (NT_STATUS_IS_OK(status) && S_ISLNK(smb_fname_rel->st.st_ex_mode)) {
 
 		/*
-		 * If we're on an MSDFS share, see if this is
-		 * an MSDFS link.
+		 * Upper layers might need the link target. Here we
+		 * still have the relname around, get the symlink err.
 		 */
-		if (lp_host_msdfs() &&
-		    lp_msdfs_root(SNUM(conn)) &&
-		    is_msdfs_link(smb_dirname->fsp, smb_fname_rel))
-		{
-			status = NT_STATUS_PATH_NOT_COVERED;
+		status = create_open_symlink_err(mem_ctx,
+						 smb_dirname->fsp,
+						 smb_fname_rel,
+						 &symlink_err);
+		if (!NT_STATUS_IS_OK(status)) {
+			DBG_DEBUG("Could not read symlink for %s: %s\n",
+				  smb_fname_str_dbg(
+					  smb_fname_rel->fsp->fsp_name),
+				  nt_errstr(status));
 			goto fail;
 		}
-
-#if defined(WITH_SMB1SERVER)
-		/*
-		 * In SMB1 posix mode, if this is a symlink,
-		 * allow access to the name with a NULL smb_fname->fsp.
-		 */
-		if (ucf_flags & UCF_LCOMP_LNK_OK) {
-			SMB_ASSERT(smb_fname_rel->fsp == NULL);
-			SMB_ASSERT(streamname == NULL);
-
-			smb_fname = full_path_from_dirfsp_atname(
-				mem_ctx,
-				smb_dirname->fsp,
-				smb_fname_rel);
-			if (smb_fname == NULL) {
-				status = NT_STATUS_NO_MEMORY;
-				goto fail;
-			}
-			goto done;
-		}
-#endif
 	}
 
 	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
@@ -1315,6 +1091,7 @@ static NTSTATUS filename_convert_dirfsp_nosymlink(
 done:
 	*_dirfsp = smb_dirname->fsp;
 	*_smb_fname = smb_fname;
+	*_symlink_err = symlink_err;
 
 	smb_fname_fsp_unlink(smb_fname_rel);
 	TALLOC_FREE(smb_fname_rel);
@@ -1347,9 +1124,9 @@ NTSTATUS filename_convert_dirfsp(
 	struct files_struct **_dirfsp,
 	struct smb_filename **_smb_fname)
 {
-	char *substitute = NULL;
-	size_t unparsed = 0;
+	struct open_symlink_err *symlink_err = NULL;
 	NTSTATUS status;
+	char *substitute = NULL;
 	char *target = NULL;
 	size_t symlink_redirects = 0;
 
@@ -1358,23 +1135,49 @@ next:
 		return NT_STATUS_OBJECT_PATH_NOT_FOUND;
 	}
 
-	status = filename_convert_dirfsp_nosymlink(
-		mem_ctx,
-		conn,
-		name_in,
-		ucf_flags,
-		twrp,
-		_dirfsp,
-		_smb_fname,
-		&substitute,
-		&unparsed);
+	status = filename_convert_dirfsp_nosymlink(mem_ctx,
+						   conn,
+						   name_in,
+						   ucf_flags,
+						   twrp,
+						   _dirfsp,
+						   _smb_fname,
+						   &symlink_err);
+
+	if (NT_STATUS_IS_OK(status) && S_ISLNK((*_smb_fname)->st.st_ex_mode)) {
+		/*
+		 * lcomp is a symlink
+		 */
+		if (ucf_flags & UCF_LCOMP_LNK_OK) {
+			TALLOC_FREE(symlink_err);
+			return NT_STATUS_OK;
+		}
+		close_file_free(NULL, _dirfsp, ERROR_CLOSE);
+		status = NT_STATUS_STOPPED_ON_SYMLINK;
+	}
 
 	if (!NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
 		return status;
 	}
 
+	/*
+	 * If we're on an MSDFS share, see if this is
+	 * an MSDFS link.
+	 */
+	if (lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) &&
+	    strnequal(symlink_err->reparse->substitute_name, "msdfs:", 6))
+	{
+		TALLOC_FREE(*_smb_fname);
+		TALLOC_FREE(symlink_err);
+		return NT_STATUS_PATH_NOT_COVERED;
+	}
+
 	if (!lp_follow_symlinks(SNUM(conn))) {
-		return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+		status = (symlink_err->unparsed == 0)
+				 ? NT_STATUS_OBJECT_NAME_NOT_FOUND
+				 : NT_STATUS_OBJECT_PATH_NOT_FOUND;
+		TALLOC_FREE(symlink_err);
+		return status;
 	}


-- 
Samba Shared Repository



More information about the samba-cvs mailing list