[SCM] Samba Shared Repository - branch master updated

Volker Lendecke vlendec at samba.org
Fri Jun 30 11:44:01 UTC 2023


The branch, master has been updated
       via  358631ce331 smbd: Merge openat_pathref_fsp_nosymlink() into _internal()
       via  f19f3c1a16c smbd: Factor out create_open_symlink_err()
       via  e4422b2ff33 smbd: Remove "atname" from smbd_dirptr_get_entry()'s mode_fn
       via  88f32b783c4 smbd: Rewrite smbd_dirptr_get_entry()
       via  e9040fa42a5 smbd: Factor out full_path_from_dirfsp_at_basename()
       via  b4698f3b13e smbd: Introduce dir_fname helper var in smbd_dirptr_get_entry()
       via  16ae3c2e26d smbd: Modernize two DEBUG statements
       via  f56ceab909a smbd: Pass name and stat_ex to dos_mode_msdfs()
       via  614debf4d96 smbd: Pass "char*" to dos_mode_from_name()
       via  0958afd297d smbd: Pass stat_ex and files_struct to dos_mode_from_sbuf()
       via  e9363926dc8 smbd: Extend openat_pathref_dirfsp_nosymlink()
       via  eb2978f55cb test: skip the open-eintr test
       via  7a71e275e44 smbd: Fully fill in fsp in openat_pathref_fsp_nosymlink_internal()
       via  03660778f07 smbd: Lift up conn->cwd from openat_pathref_dirfsp_nosymlink()
       via  8b651a68471 smbd: Factor out full_path_extend()
       via  58f7ec12bd4 smbd: Add read_symlink_reparse()
       via  633d71eeffc smbd: Apply some README.Coding to dos_mode_from_sbuf()
       via  08e881aeb58 smbd: Simplify dos_mode_msdfs()
       via  c921cdf87e6 smbd: Move dos_mode_from_name() up in dosmode.c
       via  290ca547a89 smbd: Slightly simplify smbd_dirptr_get_entry()
      from  7b6cedf5385 .gitlab-ci:bootstrap: remove ubuntu1804*, add debian12, upgrade opensuse 15.5

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


- Log -----------------------------------------------------------------
commit 358631ce3314f952e9b205fc69f0a5b6e067e242
Author: Volker Lendecke <vl at samba.org>
Date:   Fri Jun 30 11:18:42 2023 +0200

    smbd: Merge openat_pathref_fsp_nosymlink() into _internal()
    
    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): Fri Jun 30 11:43:46 UTC 2023 on atb-devel-224

commit f19f3c1a16c8df9caaee14f176f8e332d3d6a2bc
Author: Volker Lendecke <vl at samba.org>
Date:   Fri Jun 30 10:57:58 2023 +0200

    smbd: Factor out create_open_symlink_err()
    
    3 times talloc_zero() and read_symlink_reparse() makes a nice separate
    function.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit e4422b2ff33c5d49df23da1686a7be636779d5ab
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Jun 24 10:02:05 2023 +0200

    smbd: Remove "atname" from smbd_dirptr_get_entry()'s mode_fn
    
    Unused.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 88f32b783c43573ec3e2a82a640ad082e996aae2
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Jun 22 15:12:25 2023 +0200

    smbd: Rewrite smbd_dirptr_get_entry()
    
    Move filtering of entries, in particular symlinks, fully into
    smbd_dirptr_get_entry(). Before, this was hidden in magic code inside
    openat_pathref_fsp() and the mode_fn()s. Changing anything file open
    code led to changes in very distant code paths because of unforeseen
    consequences to directory listing. This change centralizes the
    decision what directory entries to show into
    smbd_dirptr_get_entry(). It uses openat_pathref_fsp_nosymlink()
    without any symlink magic. It might need some tweaking when we also
    want to show other special files, but this will hopefully be easier.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit e9040fa42a5539c8bdbf41bd99db74759e966e88
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Jun 22 14:46:01 2023 +0200

    smbd: Factor out full_path_from_dirfsp_at_basename()
    
    Will use this logic in the next patch
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit b4698f3b13e9e7560e6fa42fca81333d527c25cc
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Jun 22 11:33:05 2023 +0200

    smbd: Introduce dir_fname helper var in smbd_dirptr_get_entry()
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 16ae3c2e26dbb1af45df99db373d671f83babd45
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Jun 22 11:19:29 2023 +0200

    smbd: Modernize two DEBUG statements
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit f56ceab909a23e1bd114c4a914d5c1a10626022a
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Jun 20 16:28:19 2023 +0200

    smbd: Pass name and stat_ex to dos_mode_msdfs()
    
    We'll use it in a place without a smb_fname soon.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 614debf4d9670b5919ac614d03b834c2859dc454
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Jun 20 16:22:30 2023 +0200

    smbd: Pass "char*" to dos_mode_from_name()
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 0958afd297df458ee6d10f9531708b77fc65fb60
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Jun 20 16:19:50 2023 +0200

    smbd: Pass stat_ex and files_struct to dos_mode_from_sbuf()
    
    Will enable simplification of dos_mode_msdfs()
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit e9363926dc8925cbe25024e1dee357cc9bfd0a04
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Dec 12 14:04:00 2022 +0100

    smbd: Extend openat_pathref_dirfsp_nosymlink()
    
    Turn it into openat_pathref_fsp_nosymlink() which opens not only
    directories but normal files and symlinks too. If it finds a symlink,
    return NT_STATUS_STOPPED_ON_SYMLINK and all the metadata we can find:
    struct stat_ex plus the symlink target.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit eb2978f55cb14941605065a54e29d5b6fca756e2
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Dec 8 11:07:53 2022 +0100

    test: skip the open-eintr test
    
    With 7bb8af3f74c we already had to tune the error_inject VFS object to filter
    out the openat-calls coming from filename_convert_dirfsp&friends. With
    the next patch openat() will be called from even more places, and I
    don't really see a good way to properly deal with EINTR in all the
    places where it can happen. The real case where EINTR is something we
    need to handle properly I guess is with kernel oplocks active: open()
    waits for another process to give up its kernel oplock, which opens
    the window for EINTR to become a valid case to properly take care
    of. For all other opens I would be willing to live with the fact that
    we just return an error message that might be different from Windows.
    
    To detect that kernel oplock case properly, with O_PATH we have to
    look at the /proc/self/fd/<n> reopen or the O_EMPTY_PATH FreeBSD
    flavor from inside the error_inject module I guess. But then, the
    second time we come around the corner we have to let it pass.
    
    Difficult to properly test, disable the test for now.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 7a71e275e444499e94266cc108cba35da28661da
Author: Volker Lendecke <vl at samba.org>
Date:   Tue May 16 11:24:35 2023 +0200

    smbd: Fully fill in fsp in openat_pathref_fsp_nosymlink_internal()
    
    Prepare for allowing openat_pathref_fsp_nosymlink() to open real files
    in the next patches.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 03660778f07879baa31f9bd47d89db58a0b2718b
Author: Volker Lendecke <vl at samba.org>
Date:   Tue May 16 11:13:35 2023 +0200

    smbd: Lift up conn->cwd from openat_pathref_dirfsp_nosymlink()
    
    The goal of this patch is to make the next patches smaller. Next
    patches will also make openat_pathref_dirfsp_nosymlink() open real
    files, not only directories.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 8b651a68471805fd02442500f0724a83a943171a
Author: Volker Lendecke <vl at samba.org>
Date:   Tue May 16 10:49:08 2023 +0200

    smbd: Factor out full_path_extend()
    
    This logic will be used in another place in the next commit
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 58f7ec12bd46b010f81284bb32f644576a253aef
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Dec 5 12:15:21 2022 +0100

    smbd: Add read_symlink_reparse()
    
    Fake up a symlink reparse point structure from an on-disk reparse
    point.
    
    Turn in-share absolute symlinks into relative ones for the client to
    properly follow symlinks. Pass on everything else as-is. In particular
    clients follow symlinks pointing at \\server\share\...
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 633d71eeffcb685a981735b20309bff6d0d2b9f7
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Jun 20 16:16:23 2023 +0200

    smbd: Apply some README.Coding to dos_mode_from_sbuf()
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 08e881aeb588d9337a281cec166916c3713303e3
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Jun 20 15:34:28 2023 +0200

    smbd: Simplify dos_mode_msdfs()
    
    This is exactly what dos_mode_from_name() does.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit c921cdf87e620b8120835f304e3e30f5ef28d3fe
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Jun 20 15:31:34 2023 +0200

    smbd: Move dos_mode_from_name() up in dosmode.c
    
    Is useful in dos_mode_msdfs() as well.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 290ca547a8936d637e5b229c9c436c8163720877
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Jun 21 17:48:24 2023 +0200

    smbd: Slightly simplify smbd_dirptr_get_entry()
    
    Implementing virtually empty directories for "dont descend" looks
    easier to me this way. It should also be an optimization, because now
    we don't walk the whole directory anymore after . and .., which always
    come first anyway.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

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

Summary of changes:
 selftest/skip              |   1 +
 source3/include/proto.h    |   3 +
 source3/smbd/dir.c         | 351 +++++++++++++++++++++------------------------
 source3/smbd/dosmode.c     | 126 +++++++---------
 source3/smbd/filename.c    |  87 ++++++-----
 source3/smbd/files.c       | 301 +++++++++++++++++++++++++++++---------
 source3/smbd/globals.h     |   1 -
 source3/smbd/proto.h       |  37 +++--
 source3/smbd/smb1_reply.c  |  13 +-
 source3/smbd/smb2_trans2.c |  75 +---------
 10 files changed, 553 insertions(+), 442 deletions(-)


Changeset truncated at 500 lines:

diff --git a/selftest/skip b/selftest/skip
index 1a9e0da9e30..a8b86663689 100644
--- a/selftest/skip
+++ b/selftest/skip
@@ -150,3 +150,4 @@ bench # don't run benchmarks in our selftest
 ^samba4.smb2.mkdir.*\(ad_dc_ntvfs\)$ # Ignore ad_dc_ntvfs since this is a new test
 ^samba.tests.reparsepoints.*
 ^samba.tests.smb2symlink.*
+^samba3.blackbox.open-eintr.*
diff --git a/source3/include/proto.h b/source3/include/proto.h
index f71796b57ae..bf6797514e3 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -726,6 +726,9 @@ NTSTATUS filename_convert_dirfsp(
 	NTTIME twrp,
 	struct files_struct **pdirfsp,
 	struct smb_filename **psmb_name_rel);
+char *full_path_from_dirfsp_at_basename(TALLOC_CTX *mem_ctx,
+					const struct files_struct *dirfsp,
+					const char *at_base_name);
 struct smb_filename *full_path_from_dirfsp_atname(
 	TALLOC_CTX *mem_ctx,
 	const struct files_struct *dirfsp,
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index 8c5943bf88b..59fbe548501 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -28,6 +28,7 @@
 #include "../lib/util/memcache.h"
 #include "../librpc/gen_ndr/open_files.h"
 #include "lib/util/string_wrappers.h"
+#include "libcli/smb/reparse_symlink.h"
 
 /*
    This module implements directory related functions for Samba.
@@ -519,7 +520,6 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
 			   bool (*mode_fn)(TALLOC_CTX *ctx,
 					   void *private_data,
 					   struct files_struct *dirfsp,
-					   struct smb_filename *atname,
 					   struct smb_filename *smb_fname,
 					   bool get_dosmode,
 					   uint32_t *_mode),
@@ -530,10 +530,9 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
 {
 	connection_struct *conn = dirptr->conn;
 	struct smb_Dir *dir_hnd = dirptr->dir_hnd;
-	size_t slashlen;
-	size_t pathlen;
-	const char *dpath = dir_hnd->dir_smb_fname->base_name;
-	bool dirptr_path_is_dot = ISDOT(dpath);
+	struct smb_filename *dir_fname = dir_hnd->dir_smb_fname;
+	bool posix = (dir_fname->flags & SMB_FILENAME_POSIX_PATH);
+	const char *dpath = dir_fname->base_name;
 	NTSTATUS status;
 
 	*_smb_fname = NULL;
@@ -546,18 +545,20 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
 		return true;
 	}
 
-	pathlen = strlen(dpath);
-	slashlen = ( dpath[pathlen-1] != '/') ? 1 : 0;
+	if (dont_descend && (dptr_FileNumber(dirptr) >= 2)) {
+		/*
+		 * . and .. were returned first, we're done showing
+		 * the directory as empty.
+		 */
+		return false;
+	}
 
 	while (true) {
 		char *dname = NULL;
-		bool isdots;
 		char *fname = NULL;
-		char *pathreal = NULL;
-		struct smb_filename *atname = NULL;
 		struct smb_filename *smb_fname = NULL;
+		struct open_symlink_err *symlink_err = NULL;
 		uint32_t mode = 0;
-		bool check_dfs_symlink = false;
 		bool get_dosmode = get_dosmode_in;
 		bool ok;
 
@@ -565,7 +566,7 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
 
 		DBG_DEBUG("dir [%s] dirptr [%p] offset [%u] => "
 			  "dname [%s]\n",
-			  smb_fname_str_dbg(dir_hnd->dir_smb_fname),
+			  smb_fname_str_dbg(dir_fname),
 			  dirptr,
 			  dir_hnd->file_number,
 			  dname ? dname : "(finished)");
@@ -574,12 +575,6 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
 			return false;
 		}
 
-		isdots = (ISDOT(dname) || ISDOTDOT(dname));
-		if (dont_descend && !isdots) {
-			TALLOC_FREE(dname);
-			continue;
-		}
-
 		if (IS_VETO_PATH(conn, dname)) {
 			TALLOC_FREE(dname);
 			continue;
@@ -597,203 +592,190 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
 			continue;
 		}
 
-		/*
-		 * This used to be
-		 * pathreal = talloc_asprintf(ctx, "%s%s%s", dirptr->path,
-		 *			      needslash?"/":"", dname);
-		 * but this was measurably slower than doing the memcpy.
-		 */
+		if (ISDOT(dname) || ISDOTDOT(dname)) {
 
-		pathreal = talloc_array(
-			ctx, char,
-			pathlen + slashlen + talloc_get_size(dname));
-		if (!pathreal) {
-			TALLOC_FREE(dname);
-			TALLOC_FREE(fname);
-			return false;
-		}
+			const char *dotname = dname;
 
-		/*
-		 * We don't want to pass ./xxx to modules below us so don't
-		 * add the path if it is just . by itself.
-		 */
-		if (dirptr_path_is_dot) {
-			memcpy(pathreal, dname, talloc_get_size(dname));
-		} else {
-			memcpy(pathreal, dpath, pathlen);
-			pathreal[pathlen] = '/';
-			memcpy(pathreal + slashlen + pathlen, dname,
-			       talloc_get_size(dname));
-		}
+			if (ISDOTDOT(dname) && ISDOT(dpath)) {
+				/*
+				 * Handle ".." in toplevel like "." to not
+				 * leak info from outside the share.
+				 */
+				dotname = ".";
+			}
 
-		/* Create smb_fname with NULL stream_name. */
-		smb_fname = synthetic_smb_fname(talloc_tos(),
-						pathreal,
-						NULL,
-						NULL,
-						dir_hnd->dir_smb_fname->twrp,
-						dir_hnd->dir_smb_fname->flags);
-		TALLOC_FREE(pathreal);
-		if (smb_fname == NULL) {
-			TALLOC_FREE(dname);
-			TALLOC_FREE(fname);
-			return false;
-		}
+			smb_fname = synthetic_smb_fname(talloc_tos(),
+							dotname,
+							NULL,
+							NULL,
+							dir_fname->twrp,
+							dir_fname->flags);
+			if (smb_fname == NULL) {
+				TALLOC_FREE(dname);
+				return false;
+			}
 
-		/* Create smb_fname with NULL stream_name. */
-		atname = synthetic_smb_fname(talloc_tos(),
-					     dname,
-					     NULL,
-					     NULL,
-					     dir_hnd->dir_smb_fname->twrp,
-					     dir_hnd->dir_smb_fname->flags);
-		if (atname == NULL) {
-			TALLOC_FREE(dname);
-			TALLOC_FREE(fname);
-			TALLOC_FREE(smb_fname);
-			return false;
-		}
+			status = openat_pathref_fsp(dir_hnd->fsp, smb_fname);
+			if (!NT_STATUS_IS_OK(status)) {
+				DBG_INFO("Could not open \"..\": %s\n",
+					 nt_errstr(status));
+				TALLOC_FREE(smb_fname);
+				TALLOC_FREE(dname);
+				continue;
+			}
 
-		/*
-		 * openat_pathref_fsp() will return
-		 * NT_STATUS_OBJECT_NAME_NOT_FOUND in non-POSIX context when
-		 * hitting a dangling symlink. It may be a DFS symlink, this is
-		 * checked below by the mode_fn() call, so we have to allow this
-		 * here.
-		 *
-		 * NT_STATUS_STOPPED_ON_SYMLINK is returned in POSIX context
-		 * when hitting a symlink and ensures we always return directory
-		 * entries that are symlinks in POSIX context.
-		 */
-		status = openat_pathref_fsp(dir_hnd->fsp, atname);
-		if (!NT_STATUS_IS_OK(status) &&
-		    !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND))
-		{
-			TALLOC_FREE(atname);
-			TALLOC_FREE(dname);
-			TALLOC_FREE(fname);
-			TALLOC_FREE(smb_fname);
-			continue;
-		}
+			mode = fdos_mode(smb_fname->fsp);
 
-		if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
-			if (!(atname->flags & SMB_FILENAME_POSIX_PATH)) {
-				check_dfs_symlink = true;
-			}
 			/*
-			 * Check if it's a symlink. We only want to return this
-			 * if it's a DFS symlink or in POSIX mode. Disable
-			 * getting dosmode in the mode_fn() and prime the mode
-			 * as FILE_ATTRIBUTE_NORMAL.
+			 * Don't leak INO/DEV/User SID/Group SID about
+			 * the containing directory of the share.
 			 */
-			mode = FILE_ATTRIBUTE_NORMAL;
-			get_dosmode = false;
-		}
-
-		/*
-		 * openat_pathref_fsp() filled atname->st, but from
-		 * now on we're working with smb_fname. Keep the stat
-		 * info for mode_fn's use.
-		 */
-		smb_fname->st = atname->st;
-
-		status = move_smb_fname_fsp_link(smb_fname, atname);
-		if (!NT_STATUS_IS_OK(status)) {
-			DBG_WARNING("Failed to move pathref for [%s]: %s\n",
-				    smb_fname_str_dbg(smb_fname),
-				    nt_errstr(status));
-			TALLOC_FREE(atname);
-			TALLOC_FREE(smb_fname);
-			TALLOC_FREE(dname);
-			TALLOC_FREE(fname);
-			continue;
-		}
+			if (ISDOT(dpath) && ISDOTDOT(dname)) {
+				/*
+				 * Ensure posix fileid and sids are hidden
+				 */
+				smb_fname->st.st_ex_ino = 0;
+				smb_fname->st.st_ex_dev = 0;
+				smb_fname->st.st_ex_uid = -1;
+				smb_fname->st.st_ex_gid = -1;
+			}
 
-		if (!is_visible_fsp(smb_fname->fsp)) {
-			TALLOC_FREE(atname);
-			TALLOC_FREE(smb_fname);
-			TALLOC_FREE(dname);
-			TALLOC_FREE(fname);
-			continue;
+			goto done;
 		}
 
-		/*
-		 * Don't leak metadata about the containing
-		 * directory of the share.
-		 */
-		if (dirptr_path_is_dot && ISDOTDOT(dname)) {
-			/*
-			 * Making a copy here, then freeing
-			 * the original will close the smb_fname->fsp.
-			 */
-			struct smb_filename *tmp_smb_fname =
-				cp_smb_filename(ctx, smb_fname);
+		status = openat_pathref_fsp_nosymlink(talloc_tos(),
+						      conn,
+						      dir_hnd->fsp,
+						      dname,
+						      dir_fname->twrp,
+						      posix,
+						      &smb_fname,
+						      &symlink_err);
 
-			if (tmp_smb_fname == NULL) {
-				TALLOC_FREE(atname);
+		if (NT_STATUS_IS_OK(status)) {
+			bool visible = is_visible_fsp(smb_fname->fsp);
+			if (!visible) {
 				TALLOC_FREE(smb_fname);
 				TALLOC_FREE(dname);
 				TALLOC_FREE(fname);
+				continue;
+			}
+		} else if (NT_STATUS_EQUAL(status,
+					   NT_STATUS_STOPPED_ON_SYMLINK)) {
+			struct symlink_reparse_struct *reparse =
+				symlink_err->reparse;
+			const char *target = reparse->substitute_name;
+			bool is_msdfs_link;
+
+			is_msdfs_link = lp_host_msdfs();
+			is_msdfs_link &= lp_msdfs_root(SNUM(conn));
+			is_msdfs_link &= (strncmp(target, "msdfs:", 6) == 0);
+
+			if (is_msdfs_link) {
+				char *path = NULL;
+
+				path = full_path_from_dirfsp_at_basename(
+					talloc_tos(),
+					dir_hnd->fsp,
+					dname);
+				if (path == NULL) {
+					return false;
+				}
+
+				smb_fname =
+					synthetic_smb_fname(talloc_tos(),
+							    path,
+							    NULL,
+							    &symlink_err->st,
+							    dir_fname->twrp,
+							    dir_fname->flags);
+				TALLOC_FREE(path);
+				if (smb_fname == NULL) {
+					return false;
+				}
+
+				DBG_INFO("Masquerading msdfs link %s as a"
+					 "directory\n",
+					 smb_fname->base_name);
+
+				smb_fname->st.st_ex_mode =
+					(smb_fname->st.st_ex_mode & ~S_IFMT) |
+					S_IFDIR;
+
+				mode = dos_mode_msdfs(conn,
+						      dname,
+						      &smb_fname->st);
+				get_dosmode = false;
+				ask_sharemode = false;
+				goto done;
+			}
+
+			smb_fname = synthetic_smb_fname(talloc_tos(),
+							dname,
+							NULL,
+							&symlink_err->st,
+							dir_fname->twrp,
+							dir_fname->flags);
+			if (smb_fname == NULL) {
 				return false;
 			}
+
+			status = openat_pathref_fsp(dir_hnd->fsp, smb_fname);
+
+			if (posix) {
+				/*
+				 * Posix always wants to see symlinks,
+				 * dangling or not. We've done the
+				 * openat_pathref_fsp() to fill in
+				 * smb_fname->fsp just in case it's
+				 * not dangling.
+				 */
+				mode = FILE_ATTRIBUTE_NORMAL;
+				get_dosmode = false;
+				ask_sharemode = false;
+				goto done;
+			}
+
+			if (!NT_STATUS_IS_OK(status)) {
+				/*
+				 * Dangling symlink. Hide.
+				 */
+				TALLOC_FREE(smb_fname);
+				TALLOC_FREE(fname);
+				TALLOC_FREE(dname);
+				continue;
+			}
+		} else {
+			DBG_NOTICE("Could not open %s: %s\n",
+				   dname,
+				   nt_errstr(status));
+			TALLOC_FREE(dname);
+			TALLOC_FREE(fname);
 			TALLOC_FREE(smb_fname);
-			smb_fname = tmp_smb_fname;
-			mode = FILE_ATTRIBUTE_DIRECTORY;
-			get_dosmode = false;
+			continue;
 		}
 
 		ok = mode_fn(ctx,
 			     private_data,
 			     dir_hnd->fsp,
-			     atname,
 			     smb_fname,
 			     get_dosmode,
 			     &mode);
 		if (!ok) {
-			TALLOC_FREE(atname);
 			TALLOC_FREE(smb_fname);
 			TALLOC_FREE(dname);
 			TALLOC_FREE(fname);
 			continue;
 		}
 
-		TALLOC_FREE(atname);
-
-		/*
-		 * Don't leak INO/DEV/User SID/Group SID about the containing
-		 * directory of the share. This MUST happen AFTER the call to
-		 * mode_fn().
-		 */
-		if (dirptr_path_is_dot && ISDOTDOT(dname)) {
-			/* Ensure posix fileid and sids are hidden
-			 */
-			smb_fname->st.st_ex_ino = 0;
-			smb_fname->st.st_ex_dev = 0;
-			smb_fname->st.st_ex_uid = -1;
-			smb_fname->st.st_ex_gid = -1;
-		}
-
-		/*
-		 * The only valid cases where we return the directory entry if
-		 * it's a symlink are:
-		 *
-		 * 1. POSIX context, always return it, or
-		 *
-		 * 2. a DFS symlink where the mode_fn() call above has verified
-		 *    this and set mode to FILE_ATTRIBUTE_REPARSE_POINT.
-		 */
-		if (check_dfs_symlink &&
-		    !(mode & FILE_ATTRIBUTE_REPARSE_POINT))
-		{
-			TALLOC_FREE(smb_fname);
-			TALLOC_FREE(dname);
-			TALLOC_FREE(fname);
-			continue;
-		}
+	done:
 
 		if (!dir_check_ftype(mode, dirtype)) {
-			DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
-				fname, (unsigned int)mode, (unsigned int)dirtype));
+			DBG_INFO("[%s] attribs 0x%" PRIx32 " didn't match "
+				 "0x%" PRIx32 "\n",
+				 fname,
+				 mode,
+				 dirtype);
 			TALLOC_FREE(smb_fname);
 			TALLOC_FREE(dname);
 			TALLOC_FREE(fname);
@@ -813,10 +795,11 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
 			}
 		}
 
-		DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
-			"fname=%s (%s)\n",
-			mask, smb_fname_str_dbg(smb_fname),
-			dname, fname));
+		DBG_NOTICE("mask=[%s] found %s fname=%s (%s)\n",
+			   mask,
+			   smb_fname_str_dbg(smb_fname),
+			   dname,
+			   fname);
 
 		TALLOC_FREE(dname);
 
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 5a88cd059b0..b8d00209c1e 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -189,44 +189,48 @@ mode_t unix_mode(connection_struct *conn, int dosmode,
 ****************************************************************************/
 
 static uint32_t dos_mode_from_sbuf(connection_struct *conn,
-				 const struct smb_filename *smb_fname)
+				   const struct stat_ex *st,
+				   struct files_struct *fsp)
 {
 	int result = 0;
-	enum mapreadonly_options ro_opts = (enum mapreadonly_options)lp_map_readonly(SNUM(conn));
+	enum mapreadonly_options ro_opts =
+		(enum mapreadonly_options)lp_map_readonly(SNUM(conn));
 
 #if defined(UF_IMMUTABLE) && defined(SF_IMMUTABLE)
 	/* if we can find out if a file is immutable we should report it r/o */
-	if (smb_fname->st.st_ex_flags & (UF_IMMUTABLE | SF_IMMUTABLE)) {
+	if (st->st_ex_flags & (UF_IMMUTABLE | SF_IMMUTABLE)) {
 		result |= FILE_ATTRIBUTE_READONLY;
 	}
 #endif
 	if (ro_opts == MAP_READONLY_YES) {


-- 
Samba Shared Repository



More information about the samba-cvs mailing list