[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Sat Sep 17 05:16:02 UTC 2022


The branch, master has been updated
       via  6e5d79ff408 shadow_copy2: Remove an intermediate if-statement
       via  f3350bff453 smbd: Remove non_widelink_open() support code
       via  2c8935cf3d7 smbd: Rewrite non_widelink_open()
       via  1bf0289b23c smbd: Make readlink_talloc() public
       via  b4445ef9ab1 smbd: Slightly simplify non_widelink_open()
       via  dbf93c9e0f5 shadow_copy2: Use dirfsp if it's around
       via  fbc17c41aeb shadow_copy2: Use dirfsp for connectpath
       via  e1ca4e28d89 vfs: Add dirfsp to connectpath_fn()
      from  9ef2f7345f0 s3:auth: Flush the GETPWSID in memory cache for NTLM auth

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


- Log -----------------------------------------------------------------
commit 6e5d79ff40892b4f8f4962b36c1c3fb2d2ce9d55
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Sep 15 08:55:01 2022 -0700

    shadow_copy2: Remove an intermediate if-statement
    
    Now we always pass in a dirfsp from our only caller
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Sat Sep 17 05:15:04 UTC 2022 on sn-devel-184

commit f3350bff4532b35b3c9e99e0d0865ecec55e1be5
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Sep 13 09:49:31 2022 -0700

    smbd: Remove non_widelink_open() support code
    
    process_symlink_open() and check_reduced_name() are no longer used,
    non_widelink_open() was the only user of both.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 2c8935cf3d79dd09bc6d00793cf8fdaf031d21fc
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Sep 12 12:08:13 2022 -0700

    smbd: Rewrite non_widelink_open()
    
    The previous implementation relied on recursion into
    non_widelink_open() via process_symlink_open(). The latter used
    readlink() to just make sure that the opened file is actually a
    symlink.
    
    This implementation now relies on a fstat/fstatat on failure to open a
    file, removing a little complexity deciphering error codes
    correctly. It also relies on reading the symlink in user space,
    turning the recursion into a loop.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 1bf0289b23cae861ec1fa3c4a46e267392315726
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Sep 7 10:43:23 2022 +0200

    smbd: Make readlink_talloc() public
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit b4445ef9ab1b258fbb17bb5aaa9998f14e4adfcc
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Sep 10 01:36:11 2022 -0700

    smbd: Slightly simplify non_widelink_open()
    
    Avoid the "is_share_root" boolean: One special case less to take care
    of further down and in callers: Sanitize the relative name so that it
    can never contain a path separator
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit dbf93c9e0f5d592b3cbac4c705cb10dbc9e20ea6
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Sep 15 06:11:55 2022 -0700

    shadow_copy2: Use dirfsp if it's around
    
    Not used yet, and the "if" around dirfsp!=NULL will go away in a later
    patch.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit fbc17c41aeb8eae4e603aef0fe8822b468b57205
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Sep 15 03:41:55 2022 +0000

    shadow_copy2: Use dirfsp for connectpath
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit e1ca4e28d89237c8910e77146824ecc3444ce272
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Sep 14 20:18:33 2022 -0700

    vfs: Add dirfsp to connectpath_fn()
    
    So far we only call CONNECTPATH on full paths. In the future, we'll
    have a call that will not have converted a relative path to absolute
    just for efficiency reasons. To give shadow_copy2 the chance to still
    find the snapshot directory, pass the dirfsp down to it.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

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

Summary of changes:
 examples/VFS/skel_opaque.c            |   6 +-
 examples/VFS/skel_transparent.c       |   8 +-
 source3/include/vfs.h                 |  11 +-
 source3/include/vfs_macros.h          |   8 +-
 source3/modules/vfs_ceph.c            |   6 +-
 source3/modules/vfs_default.c         |   1 +
 source3/modules/vfs_full_audit.c      |   8 +-
 source3/modules/vfs_glusterfs.c       |   6 +-
 source3/modules/vfs_not_implemented.c |   6 +-
 source3/modules/vfs_shadow_copy2.c    |  17 +-
 source3/modules/vfs_time_audit.c      |   8 +-
 source3/smbd/files.c                  |   2 +-
 source3/smbd/open.c                   | 605 ++++++++++++++++++----------------
 source3/smbd/proto.h                  |   8 +-
 source3/smbd/vfs.c                    | 218 +-----------
 15 files changed, 391 insertions(+), 527 deletions(-)


Changeset truncated at 500 lines:

diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c
index a72ba57e1a7..98b090728f2 100644
--- a/examples/VFS/skel_opaque.c
+++ b/examples/VFS/skel_opaque.c
@@ -665,8 +665,10 @@ static NTSTATUS skel_get_real_filename_at(struct vfs_handle_struct *handle,
 	return NT_STATUS_NOT_IMPLEMENTED;
 }
 
-static const char *skel_connectpath(struct vfs_handle_struct *handle,
-				const struct smb_filename *smb_fname)
+static const char *skel_connectpath(
+	struct vfs_handle_struct *handle,
+	const struct files_struct *dirfsp,
+	const struct smb_filename *smb_fname)
 {
 	errno = ENOSYS;
 	return NULL;
diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c
index 8fb8644ad09..b152f3596c5 100644
--- a/examples/VFS/skel_transparent.c
+++ b/examples/VFS/skel_transparent.c
@@ -886,10 +886,12 @@ static NTSTATUS skel_get_real_filename_at(struct vfs_handle_struct *handle,
 		handle, dirfsp, name, mem_ctx, found_name);
 }
 
-static const char *skel_connectpath(struct vfs_handle_struct *handle,
-				const struct smb_filename *smb_fname)
+static const char *skel_connectpath(
+	struct vfs_handle_struct *handle,
+	const struct files_struct *dirfsp,
+	const struct smb_filename *smb_fname)
 {
-	return SMB_VFS_NEXT_CONNECTPATH(handle, smb_fname);
+	return SMB_VFS_NEXT_CONNECTPATH(handle, dirfsp, smb_fname);
 }
 
 static NTSTATUS skel_brl_lock_windows(struct vfs_handle_struct *handle,
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index fc7afccfdb3..20b6eb57900 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -377,6 +377,7 @@
  * Version 47 - Add VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS for SMB_VFS_OPENAT()
  * Change to Version 48 - will ship with 4.18
  * Version 48 - Add cached_dos_attributes to struct stat_ex
+ * Version 48 - Add dirfsp to connectpath_fn()
  */
 
 #define SMB_VFS_INTERFACE_VERSION 48
@@ -1172,6 +1173,7 @@ struct vfs_fn_pointers {
 					    char **found_name);
 
 	const char *(*connectpath_fn)(struct vfs_handle_struct *handle,
+				      const struct files_struct *dirfsp,
 				      const struct smb_filename *smb_fname);
 
 	NTSTATUS (*brl_lock_windows_fn)(struct vfs_handle_struct *handle,
@@ -1640,7 +1642,8 @@ NTSTATUS smb_vfs_call_get_real_filename_at(struct vfs_handle_struct *handle,
 					   TALLOC_CTX *mem_ctx,
 					   char **found_name);
 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
-				     const struct smb_filename *smb_fname);
+				 const struct files_struct *dirfsp,
+				 const struct smb_filename *smb_fname);
 NTSTATUS smb_vfs_call_brl_lock_windows(struct vfs_handle_struct *handle,
 				       struct byte_range_lock *br_lck,
 				       struct lock_struct *plock);
@@ -2112,8 +2115,10 @@ NTSTATUS vfs_not_implemented_get_real_filename_at(
 	const char *name,
 	TALLOC_CTX *mem_ctx,
 	char **found_name);
-const char *vfs_not_implemented_connectpath(struct vfs_handle_struct *handle,
-					    const struct smb_filename *smb_fname);
+const char *vfs_not_implemented_connectpath(
+	struct vfs_handle_struct *handle,
+	const struct files_struct *dirfsp,
+	const struct smb_filename *smb_fname);
 NTSTATUS vfs_not_implemented_brl_lock_windows(struct vfs_handle_struct *handle,
 					      struct byte_range_lock *br_lck,
 					      struct lock_struct *plock);
diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h
index c7089b62964..f1a59e1d13a 100644
--- a/source3/include/vfs_macros.h
+++ b/source3/include/vfs_macros.h
@@ -385,10 +385,10 @@
 		(mem_ctx), \
 		(found_name))
 
-#define SMB_VFS_CONNECTPATH(conn, smb_fname) \
-	smb_vfs_call_connectpath((conn)->vfs_handles, (smb_fname))
-#define SMB_VFS_NEXT_CONNECTPATH(conn, smb_fname) \
-	smb_vfs_call_connectpath((conn)->next, (smb_fname))
+#define SMB_VFS_CONNECTPATH(conn, dirfsp, smb_fname)			\
+	smb_vfs_call_connectpath((conn)->vfs_handles, (dirfsp), (smb_fname))
+#define SMB_VFS_NEXT_CONNECTPATH(conn, dirfsp, smb_fname)	\
+	smb_vfs_call_connectpath((conn)->next, (dirfsp), (smb_fname))
 
 #define SMB_VFS_BRL_LOCK_WINDOWS(conn, br_lck, plock) \
 	smb_vfs_call_brl_lock_windows((conn)->vfs_handles, (br_lck), (plock))
diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c
index 2186bfdb2ce..b8190fa25e4 100644
--- a/source3/modules/vfs_ceph.c
+++ b/source3/modules/vfs_ceph.c
@@ -1292,8 +1292,10 @@ static NTSTATUS cephwrap_get_real_filename_at(
 	return NT_STATUS_NOT_SUPPORTED;
 }
 
-static const char *cephwrap_connectpath(struct vfs_handle_struct *handle,
-				       const struct smb_filename *smb_fname)
+static const char *cephwrap_connectpath(
+	struct vfs_handle_struct *handle,
+	const struct files_struct *dirfsp,
+	const struct smb_filename *smb_fname)
 {
 	return handle->conn->connectpath;
 }
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 9481c9f36d5..6cad87152ef 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -3453,6 +3453,7 @@ static NTSTATUS vfswrap_get_real_filename_at(
 }
 
 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
+				   const struct files_struct *dirfsp,
 				   const struct smb_filename *smb_fname)
 {
 	return handle->conn->connectpath;
diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c
index 25fd0cad326..011e483de2f 100644
--- a/source3/modules/vfs_full_audit.c
+++ b/source3/modules/vfs_full_audit.c
@@ -2115,12 +2115,14 @@ static NTSTATUS smb_full_audit_get_real_filename_at(
 	return result;
 }
 
-static const char *smb_full_audit_connectpath(vfs_handle_struct *handle,
-					const struct smb_filename *smb_fname)
+static const char *smb_full_audit_connectpath(
+	vfs_handle_struct *handle,
+	const struct files_struct *dirfsp,
+	const struct smb_filename *smb_fname)
 {
 	const char *result;
 
-	result = SMB_VFS_NEXT_CONNECTPATH(handle, smb_fname);
+	result = SMB_VFS_NEXT_CONNECTPATH(handle, dirfsp, smb_fname);
 
 	do_log(SMB_VFS_OP_CONNECTPATH,
 	       result != NULL,
diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
index ffbe0f414ae..33f941aaca9 100644
--- a/source3/modules/vfs_glusterfs.c
+++ b/source3/modules/vfs_glusterfs.c
@@ -2348,8 +2348,10 @@ static NTSTATUS vfs_gluster_get_real_filename_at(
 	return NT_STATUS_OK;
 }
 
-static const char *vfs_gluster_connectpath(struct vfs_handle_struct *handle,
-				const struct smb_filename *smb_fname)
+static const char *vfs_gluster_connectpath(
+	struct vfs_handle_struct *handle,
+	const struct files_struct *dirfsp,
+	const struct smb_filename *smb_fname)
 {
 	return handle->conn->connectpath;
 }
diff --git a/source3/modules/vfs_not_implemented.c b/source3/modules/vfs_not_implemented.c
index 3c017c68bb8..0d3294658cf 100644
--- a/source3/modules/vfs_not_implemented.c
+++ b/source3/modules/vfs_not_implemented.c
@@ -735,8 +735,10 @@ NTSTATUS vfs_not_implemented_get_real_filename_at(
 }
 
 _PUBLIC_
-const char *vfs_not_implemented_connectpath(struct vfs_handle_struct *handle,
-					    const struct smb_filename *smb_fname)
+const char *vfs_not_implemented_connectpath(
+	struct vfs_handle_struct *handle,
+	const struct files_struct *dirfsp,
+	const struct smb_filename *smb_fname)
 {
 	errno = ENOSYS;
 	return NULL;
diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
index a3a6afbc3ac..43f02488f84 100644
--- a/source3/modules/vfs_shadow_copy2.c
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -2625,13 +2625,16 @@ static NTSTATUS shadow_copy2_get_real_filename_at(
 	return NT_STATUS_OK;
 }
 
-static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle,
-					const struct smb_filename *smb_fname_in)
+static const char *shadow_copy2_connectpath(
+	struct vfs_handle_struct *handle,
+	const struct files_struct *dirfsp,
+	const struct smb_filename *smb_fname_in)
 {
 	time_t timestamp = 0;
 	char *stripped = NULL;
 	char *tmp = NULL;
 	const char *fname = smb_fname_in->base_name;
+	const struct smb_filename *full = NULL;
 	struct smb_filename smb_fname = {0};
 	struct smb_filename *result_fname = NULL;
 	char *result = NULL;
@@ -2651,12 +2654,18 @@ static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle,
 		return priv->shadow_connectpath;
 	}
 
-	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, smb_fname_in,
+	full = full_path_from_dirfsp_atname(
+		talloc_tos(), dirfsp, smb_fname_in);
+	if (full == NULL) {
+		return NULL;
+	}
+
+	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, full,
 					 &timestamp, &stripped)) {
 		goto done;
 	}
 	if (timestamp == 0) {
-		return SMB_VFS_NEXT_CONNECTPATH(handle, smb_fname_in);
+		return SMB_VFS_NEXT_CONNECTPATH(handle, dirfsp, smb_fname_in);
 	}
 
 	tmp = shadow_copy2_do_convert(talloc_tos(), handle, stripped, timestamp,
diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c
index e7633285607..4942e4b8491 100644
--- a/source3/modules/vfs_time_audit.c
+++ b/source3/modules/vfs_time_audit.c
@@ -1743,15 +1743,17 @@ static NTSTATUS smb_time_audit_get_real_filename_at(
 	return result;
 }
 
-static const char *smb_time_audit_connectpath(vfs_handle_struct *handle,
-					const struct smb_filename *smb_fname)
+static const char *smb_time_audit_connectpath(
+	vfs_handle_struct *handle,
+	const struct files_struct *dirfsp,
+	const struct smb_filename *smb_fname)
 {
 	const char *result;
 	struct timespec ts1,ts2;
 	double timediff;
 
 	clock_gettime_mono(&ts1);
-	result = SMB_VFS_NEXT_CONNECTPATH(handle, smb_fname);
+	result = SMB_VFS_NEXT_CONNECTPATH(handle, dirfsp, smb_fname);
 	clock_gettime_mono(&ts2);
 	timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
 
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index 0b071be33f2..9dc4e2a805b 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -679,7 +679,7 @@ static char *path_to_strv(TALLOC_CTX *mem_ctx, const char *path)
 	return result;
 }
 
-static NTSTATUS readlink_talloc(
+NTSTATUS readlink_talloc(
 	TALLOC_CTX *mem_ctx,
 	struct files_struct *dirfsp,
 	struct smb_filename *smb_relname,
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index d443a0291f9..0f5be7c1f6a 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -475,204 +475,248 @@ static NTSTATUS check_base_file_access(struct files_struct *fsp,
 					access_mask);
 }
 
-/****************************************************************************
- Handle differing symlink errno's
-****************************************************************************/
+/*
+ * Take two absolute paths, figure out if "subdir" is a proper
+ * subdirectory of "parent". Return the component relative to the
+ * "parent" without the potential "/". Take care of "parent"
+ * possibly ending in "/".
+ */
+static bool subdir_of(
+	const char *parent,
+	size_t parent_len,
+	const char *subdir,
+	const char **_relative)
 
-static NTSTATUS link_errno_convert(int err)
 {
-#if defined(ENOTSUP) && defined(OSF1)
-	/* handle special Tru64 errno */
-	if (err == ENOTSUP) {
-		err = ELOOP;
-	}
-#endif /* ENOTSUP */
-#ifdef EFTYPE
-	/* fix broken NetBSD errno */
-	if (err == EFTYPE) {
-		err = ELOOP;
-	}
-#endif /* EFTYPE */
-	/* fix broken FreeBSD errno */
-	if (err == EMLINK) {
-		err = ELOOP;
-	}
-	if (err == ELOOP) {
-		return NT_STATUS_STOPPED_ON_SYMLINK;
-	}
-	return map_nt_error_from_unix(err);
-}
+	const char *relative = NULL;
+	bool matched;
 
-static NTSTATUS non_widelink_open(const struct files_struct *dirfsp,
-			files_struct *fsp,
-			struct smb_filename *smb_fname,
-			const struct vfs_open_how *how,
-			unsigned int link_depth);
+	SMB_ASSERT(parent[0] == '/');
+	SMB_ASSERT(subdir[0] == '/');
 
-/****************************************************************************
- Follow a symlink in userspace.
-****************************************************************************/
-
-static NTSTATUS process_symlink_open(const struct files_struct *dirfsp,
-			files_struct *fsp,
-			struct smb_filename *smb_fname,
-			const struct vfs_open_how *how,
-			unsigned int link_depth)
-{
-	struct connection_struct *conn = dirfsp->conn;
-	const char *conn_rootdir = NULL;
-	struct smb_filename conn_rootdir_fname = { 0 };
-	char *link_target = NULL;
-	int link_len = -1;
-	struct smb_filename *oldwd_fname = NULL;
-	size_t rootdir_len = 0;
-	struct smb_filename *resolved_fname = NULL;
-	char *resolved_name = NULL;
-	bool matched = false;
-	struct smb_filename *full_fname = NULL;
-	NTSTATUS status;
+	if (parent_len == 1) {
+		/*
+		 * Everything is below "/"
+		 */
+		*_relative = subdir+1;
+		return true;
+	}
 
-	conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
-	if (conn_rootdir == NULL) {
-		return NT_STATUS_NO_MEMORY;
+	if (parent[parent_len-1] == '/') {
+		parent_len -= 1;
 	}
-	/*
-	 * With shadow_copy2 conn_rootdir can be talloc_freed
-	 * whilst we use it in this function. We must take a copy.
-	 */
-	conn_rootdir_fname.base_name = talloc_strdup(talloc_tos(),
-						     conn_rootdir);
-	if (conn_rootdir_fname.base_name == NULL) {
-		return NT_STATUS_NO_MEMORY;
+
+	matched = (strncmp(subdir, parent, parent_len) == 0);
+	if (!matched) {
+		return false;
 	}
 
-	/*
-	 * Ensure we don't get stuck in a symlink loop.
-	 */
-	link_depth++;
-	if (link_depth >= 20) {
-		status = NT_STATUS_STOPPED_ON_SYMLINK;
-		goto out;
+	relative = &subdir[parent_len];
+
+	if (relative[0] == '\0') {
+		*_relative = relative; /* nothing left */
+		return true;
 	}
 
-	/* Allocate space for the link target. */
-	link_target = talloc_array(talloc_tos(), char, PATH_MAX);
-	if (link_target == NULL) {
-		status = NT_STATUS_NO_MEMORY;
-		goto out;
+	if (relative[0] == '/') {
+		/* End of parent must match a '/' in subdir. */
+		*_relative = relative+1;
+		return true;
 	}
 
-	/*
-	 * Read the link target. We do this just to verify that smb_fname indeed
-	 * points at a symbolic link and return NT_STATUS_NOT_A_DIRECTORY
-	 * and failure in case smb_fname is NOT a symlink.
-	 *
-	 * The caller needs this piece of information to distinguish two cases
-	 * where open() fails with errno=ENOTDIR, cf the comment in
-	 * non_widelink_open().
-	 *
-	 * We rely on SMB_VFS_REALPATH() to resolve the path including the
-	 * symlink. Once we have SMB_VFS_STATX() or something similar in our VFS
-	 * we may want to use that instead of SMB_VFS_READLINKAT().
-	 */
-	link_len = SMB_VFS_READLINKAT(conn,
-				dirfsp,
-				smb_fname,
-				link_target,
-				PATH_MAX - 1);
-	if (link_len == -1) {
-		status = NT_STATUS_INVALID_PARAMETER;
-		goto out;
+	return false;
+}
+
+static NTSTATUS chdir_below_conn(
+	TALLOC_CTX *mem_ctx,
+	connection_struct *conn,
+	const char *connectpath,
+	size_t connectpath_len,
+	struct smb_filename *dir_fname,
+	struct smb_filename **_oldwd_fname)
+{
+	struct smb_filename *oldwd_fname = NULL;
+	struct smb_filename *smb_fname_dot = NULL;
+	struct smb_filename *real_fname = NULL;
+	const char *relative = NULL;
+	NTSTATUS status;
+	int ret;
+	bool ok;
+
+	if (!ISDOT(dir_fname->base_name)) {
+
+		oldwd_fname = vfs_GetWd(talloc_tos(), conn);
+		if (oldwd_fname == NULL) {
+			status = map_nt_error_from_unix(errno);
+			goto out;
+		}
+
+		/* Pin parent directory in place. */
+		ret = vfs_ChDir(conn, dir_fname);
+		if (ret == -1) {
+			status = map_nt_error_from_unix(errno);
+			DBG_DEBUG("chdir to %s failed: %s\n",
+				  dir_fname->base_name,
+				  strerror(errno));
+			goto out;
+		}
 	}
 
-	full_fname = full_path_from_dirfsp_atname(
-		talloc_tos(), dirfsp, smb_fname);
-	if (full_fname == NULL) {
+	smb_fname_dot = synthetic_smb_fname(
+		talloc_tos(),
+		".",
+		NULL,
+		NULL,
+		dir_fname->twrp,
+		dir_fname->flags);
+	if (smb_fname_dot == NULL) {
 		status = NT_STATUS_NO_MEMORY;
 		goto out;
 	}
 
-	/* Convert to an absolute path. */
-	resolved_fname = SMB_VFS_REALPATH(conn, talloc_tos(), full_fname);
-	if (resolved_fname == NULL) {
+	real_fname = SMB_VFS_REALPATH(conn, talloc_tos(), smb_fname_dot);
+	if (real_fname == NULL) {
 		status = map_nt_error_from_unix(errno);
+		DBG_DEBUG("realpath in %s failed: %s\n",
+			  dir_fname->base_name,
+			  strerror(errno));
 		goto out;
 	}
-	resolved_name = resolved_fname->base_name;
+	TALLOC_FREE(smb_fname_dot);
 
-	/*
-	 * We know conn_rootdir starts with '/' and
-	 * does not end in '/'. FIXME ! Should we
-	 * smb_assert this ?
-	 */
-	rootdir_len = strlen(conn_rootdir_fname.base_name);
+	ok = subdir_of(connectpath,
+		       connectpath_len,
+		       real_fname->base_name,
+		       &relative);
+	if (ok) {
+		TALLOC_FREE(real_fname);
+		*_oldwd_fname = oldwd_fname;
+		return NT_STATUS_OK;


-- 
Samba Shared Repository



More information about the samba-cvs mailing list