s3: VFS: Change SMB_VFS_CHDIR to use const struct smb_filename * instead of const...
authorJeremy Allison <jra@samba.org>
Thu, 29 Jun 2017 18:29:33 +0000 (11:29 -0700)
committerJeremy Allison <jra@samba.org>
Sat, 1 Jul 2017 01:07:11 +0000 (03:07 +0200)
We need to migrate all pathname based VFS calls to use a struct
to finish modernising the VFS with extra timestamp and flags parameters.

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Richard Sharpe <realrichardsharpe@gmail.com>
25 files changed:
examples/VFS/skel_opaque.c
examples/VFS/skel_transparent.c
source3/include/vfs.h
source3/include/vfs_macros.h
source3/modules/vfs_acl_common.c
source3/modules/vfs_cap.c
source3/modules/vfs_catia.c
source3/modules/vfs_ceph.c
source3/modules/vfs_default.c
source3/modules/vfs_full_audit.c
source3/modules/vfs_glusterfs.c
source3/modules/vfs_media_harmony.c
source3/modules/vfs_shadow_copy2.c
source3/modules/vfs_snapper.c
source3/modules/vfs_time_audit.c
source3/modules/vfs_unityed_media.c
source3/printing/nt_printing.c
source3/rpc_server/srvsvc/srv_srvsvc_nt.c
source3/smbd/dir.c
source3/smbd/msdfs.c
source3/smbd/open.c
source3/smbd/proto.h
source3/smbd/service.c
source3/smbd/vfs.c
source3/torture/cmd_vfs.c

index d5c468e..fd81ca0 100644 (file)
@@ -412,7 +412,8 @@ static int skel_lchown(vfs_handle_struct *handle,
        return -1;
 }
 
-static int skel_chdir(vfs_handle_struct *handle, const char *path)
+static int skel_chdir(vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname)
 {
        errno = ENOSYS;
        return -1;
index 9387276..4c061ca 100644 (file)
@@ -515,9 +515,10 @@ static int skel_lchown(vfs_handle_struct *handle,
        return SMB_VFS_NEXT_LCHOWN(handle, smb_fname, uid, gid);
 }
 
-static int skel_chdir(vfs_handle_struct *handle, const char *path)
+static int skel_chdir(vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname)
 {
-       return SMB_VFS_NEXT_CHDIR(handle, path);
+       return SMB_VFS_NEXT_CHDIR(handle, smb_fname);
 }
 
 static char *skel_getwd(vfs_handle_struct *handle)
index db555f2..f5ac5b5 100644 (file)
                to const struct smb_filename * */
 /* Version 37 - Change symlink from const char *
                to const struct smb_filename * */
+/* Version 37 - Change chdir from const char *
+               to const struct smb_filename * */
 
 #define SMB_VFS_INTERFACE_VERSION 37
 
@@ -731,7 +733,8 @@ struct vfs_fn_pointers {
                        const struct smb_filename *smb_fname,
                        uid_t uid,
                        gid_t gid);
-       int (*chdir_fn)(struct vfs_handle_struct *handle, const char *path);
+       int (*chdir_fn)(struct vfs_handle_struct *handle,
+                        const struct smb_filename *smb_fname);
        char *(*getwd_fn)(struct vfs_handle_struct *handle);
        int (*ntimes_fn)(struct vfs_handle_struct *handle,
                         const struct smb_filename *smb_fname,
@@ -1232,7 +1235,8 @@ int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
                        const struct smb_filename *smb_fname,
                        uid_t uid,
                        gid_t gid);
-int smb_vfs_call_chdir(struct vfs_handle_struct *handle, const char *path);
+int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname);
 char *smb_vfs_call_getwd(struct vfs_handle_struct *handle);
 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
                        const struct smb_filename *smb_fname,
index 77646b4..367009b 100644 (file)
 #define SMB_VFS_NEXT_LCHOWN(handle, smb_fname, uid, gid) \
        smb_vfs_call_lchown((handle)->next, (smb_fname), (uid), (gid))
 
-#define SMB_VFS_CHDIR(conn, path) \
-       smb_vfs_call_chdir((conn)->vfs_handles, (path))
-#define SMB_VFS_NEXT_CHDIR(handle, path) \
-       smb_vfs_call_chdir((handle)->next, (path))
+#define SMB_VFS_CHDIR(conn, smb_fname) \
+       smb_vfs_call_chdir((conn)->vfs_handles, (smb_fname))
+#define SMB_VFS_NEXT_CHDIR(handle, smb_fname) \
+       smb_vfs_call_chdir((handle)->next, (smb_fname))
 
 #define SMB_VFS_GETWD(conn) \
        smb_vfs_call_getwd((conn)->vfs_handles)
index bd1d755..3b054df 100644 (file)
@@ -1288,7 +1288,7 @@ static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
 }
 
 static int acl_common_remove_object(vfs_handle_struct *handle,
-                                       const char *path,
+                                       const struct smb_filename *smb_fname,
                                        bool is_directory)
 {
        connection_struct *conn = handle->conn;
@@ -1297,17 +1297,20 @@ static int acl_common_remove_object(vfs_handle_struct *handle,
        int ret = 0;
        char *parent_dir = NULL;
        const char *final_component = NULL;
-       struct smb_filename local_fname;
+       struct smb_filename local_fname = {0};
+       struct smb_filename parent_dir_fname = {0};
        int saved_errno = 0;
        char *saved_dir = NULL;
+       struct smb_filename saved_dir_fname = {0};
 
        saved_dir = vfs_GetWd(talloc_tos(),conn);
        if (!saved_dir) {
                saved_errno = errno;
                goto out;
        }
+       saved_dir_fname = (struct smb_filename) { .base_name = saved_dir };
 
-       if (!parent_dirname(talloc_tos(), path,
+       if (!parent_dirname(talloc_tos(), smb_fname->base_name,
                        &parent_dir, &final_component)) {
                saved_errno = ENOMEM;
                goto out;
@@ -1316,14 +1319,15 @@ static int acl_common_remove_object(vfs_handle_struct *handle,
        DBG_DEBUG("removing %s %s/%s\n", is_directory ? "directory" : "file",
                  parent_dir, final_component);
 
+       parent_dir_fname = (struct smb_filename) { .base_name = parent_dir };
+
        /* cd into the parent dir to pin it. */
-       ret = vfs_ChDir(conn, parent_dir);
+       ret = vfs_ChDir(conn, &parent_dir_fname);
        if (ret == -1) {
                saved_errno = errno;
                goto out;
        }
 
-       ZERO_STRUCT(local_fname);
        local_fname.base_name = discard_const_p(char, final_component);
 
        /* Must use lstat here. */
@@ -1371,7 +1375,7 @@ static int acl_common_remove_object(vfs_handle_struct *handle,
        TALLOC_FREE(parent_dir);
 
        if (saved_dir) {
-               vfs_ChDir(conn, saved_dir);
+               vfs_ChDir(conn, &saved_dir_fname);
        }
        if (saved_errno) {
                errno = saved_errno;
@@ -1393,7 +1397,7 @@ static int rmdir_acl_common(struct vfs_handle_struct *handle,
                /* Failed due to access denied,
                   see if we need to root override. */
                return acl_common_remove_object(handle,
-                                               smb_fname->base_name,
+                                               smb_fname,
                                                true);
        }
 
@@ -1422,7 +1426,7 @@ static int unlink_acl_common(struct vfs_handle_struct *handle,
                        return -1;
                }
                return acl_common_remove_object(handle,
-                                       smb_fname->base_name,
+                                       smb_fname,
                                        false);
        }
 
index c07a059..44a81bb 100644 (file)
@@ -436,16 +436,40 @@ static int cap_lchown(vfs_handle_struct *handle,
        return ret;
 }
 
-static int cap_chdir(vfs_handle_struct *handle, const char *path)
+static int cap_chdir(vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname)
 {
-       char *cappath = capencode(talloc_tos(), path);
+       struct smb_filename *cap_smb_fname = NULL;
+       char *cappath = capencode(talloc_tos(), smb_fname->base_name);
+       int ret;
+       int saved_errno = 0;
 
        if (!cappath) {
                errno = ENOMEM;
                return -1;
        }
-       DEBUG(3,("cap: cap_chdir for %s\n", path));
-       return SMB_VFS_NEXT_CHDIR(handle, cappath);
+       DEBUG(3,("cap: cap_chdir for %s\n", smb_fname->base_name));
+
+       cap_smb_fname = synthetic_smb_fname(talloc_tos(),
+                                       cappath,
+                                       NULL,
+                                       NULL,
+                                       smb_fname->flags);
+       if (cap_smb_fname == NULL) {
+               TALLOC_FREE(cappath);
+               errno = ENOMEM;
+               return -1;
+       }
+       ret = SMB_VFS_NEXT_CHDIR(handle, cap_smb_fname);
+       if (ret == -1) {
+               saved_errno = errno;
+       }
+       TALLOC_FREE(cappath);
+       TALLOC_FREE(cap_smb_fname);
+       if (saved_errno != 0) {
+               errno = saved_errno;
+       }
+       return ret;
 }
 
 static int cap_ntimes(vfs_handle_struct *handle,
index ed16e43..7db50a2 100644 (file)
@@ -991,21 +991,35 @@ static int catia_mkdir(vfs_handle_struct *handle,
 }
 
 static int catia_chdir(vfs_handle_struct *handle,
-                      const char *path)
+                       const struct smb_filename *smb_fname)
 {
        char *name = NULL;
+       struct smb_filename *catia_smb_fname = NULL;
        NTSTATUS status;
        int ret;
 
-       status = catia_string_replace_allocate(handle->conn, path,
-                                       &name, vfs_translate_to_unix);
+       status = catia_string_replace_allocate(handle->conn,
+                                       smb_fname->base_name,
+                                       &name,
+                                       vfs_translate_to_unix);
        if (!NT_STATUS_IS_OK(status)) {
                errno = map_errno_from_nt_status(status);
                return -1;
        }
 
-       ret = SMB_VFS_NEXT_CHDIR(handle, name);
+       catia_smb_fname = synthetic_smb_fname(talloc_tos(),
+                                       name,
+                                       NULL,
+                                       NULL,
+                                       smb_fname->flags);
+       if (catia_smb_fname == NULL) {
+               TALLOC_FREE(name);
+               errno = ENOMEM;
+               return -1;
+       }
+       ret = SMB_VFS_NEXT_CHDIR(handle, catia_smb_fname);
        TALLOC_FREE(name);
+       TALLOC_FREE(catia_smb_fname);
 
        return ret;
 }
index 7e2bd0e..6b298a2 100644 (file)
@@ -931,18 +931,20 @@ static int cephwrap_lchown(struct vfs_handle_struct *handle,
        WRAP_RETURN(result);
 }
 
-static int cephwrap_chdir(struct vfs_handle_struct *handle,  const char *path)
+static int cephwrap_chdir(struct vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname)
 {
        int result = -1;
-       DBG_DEBUG("[CEPH] chdir(%p, %s)\n", handle, path);
+       DBG_DEBUG("[CEPH] chdir(%p, %s)\n", handle, smb_fname->base_name);
        /*
         * If the path is just / use chdir because Ceph is below / and
         * cannot deal with changing directory above its mount point
         */
-       if (path && !strcmp(path, "/"))
-               return chdir(path);
+       if (!strcmp(smb_fname->base_name, "/")) {
+               return chdir(smb_fname->base_name);
+       }
 
-       result = ceph_chdir(handle->data, path);
+       result = ceph_chdir(handle->data, smb_fname->base_name);
        DBG_DEBUG("[CEPH] chdir(...) = %d\n", result);
        WRAP_RETURN(result);
 }
index d339f39..7a2fae2 100644 (file)
@@ -228,10 +228,18 @@ static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
                                   !handle->conn->sconn->using_smb2,
                                   junction, &consumedcnt, &self_referral);
        if (!NT_STATUS_IS_OK(status)) {
-               vfs_ChDir(handle->conn, handle->conn->connectpath);
+               struct smb_filename connectpath_fname = {
+                       .base_name = handle->conn->connectpath
+               };
+               vfs_ChDir(handle->conn, &connectpath_fname);
                return status;
        }
-       vfs_ChDir(handle->conn, handle->conn->connectpath);
+       {
+               struct smb_filename connectpath_fname = {
+                       .base_name = handle->conn->connectpath
+               };
+               vfs_ChDir(handle->conn, &connectpath_fname);
+       }
 
        if (!self_referral) {
                pathnamep[consumedcnt] = '\0';
@@ -2080,12 +2088,13 @@ static int vfswrap_lchown(vfs_handle_struct *handle,
        return result;
 }
 
-static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
+static int vfswrap_chdir(vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname)
 {
        int result;
 
        START_PROFILE(syscall_chdir);
-       result = chdir(path);
+       result = chdir(smb_fname->base_name);
        END_PROFILE(syscall_chdir);
        return result;
 }
index 1267ef3..5d35c34 100644 (file)
@@ -1509,13 +1509,14 @@ static int smb_full_audit_lchown(vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_chdir(vfs_handle_struct *handle,
-                      const char *path)
+                       const struct smb_filename *smb_fname)
 {
        int result;
 
-       result = SMB_VFS_NEXT_CHDIR(handle, path);
+       result = SMB_VFS_NEXT_CHDIR(handle, smb_fname);
 
-       do_log(SMB_VFS_OP_CHDIR, (result >= 0), handle, "chdir|%s", path);
+       do_log(SMB_VFS_OP_CHDIR, (result >= 0), handle, "chdir|%s",
+               smb_fname->base_name);
 
        return result;
 }
index 2528959..833f093 100644 (file)
@@ -1070,9 +1070,10 @@ static int vfs_gluster_lchown(struct vfs_handle_struct *handle,
        return glfs_lchown(handle->data, smb_fname->base_name, uid, gid);
 }
 
-static int vfs_gluster_chdir(struct vfs_handle_struct *handle, const char *path)
+static int vfs_gluster_chdir(struct vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname)
 {
-       return glfs_chdir(handle->data, path);
+       return glfs_chdir(handle->data, smb_fname->base_name);
 }
 
 static char *vfs_gluster_getwd(struct vfs_handle_struct *handle)
index ca8d6ce..bd774b8 100644 (file)
@@ -1648,32 +1648,28 @@ out:
  * Failure: set errno, return -1
  */
 static int mh_chdir(vfs_handle_struct *handle,
-               const char *path)
+               const struct smb_filename *smb_fname)
 {
        int status;
-       char *clientPath;
-       TALLOC_CTX *ctx;
+       struct smb_filename *clientFname = NULL;
 
        DEBUG(MH_INFO_DEBUG, ("Entering mh_chdir\n"));
-       if (!is_in_media_files(path))
-       {
-               status = SMB_VFS_NEXT_CHDIR(handle, path);
+       if (!is_in_media_files(smb_fname->base_name)) {
+               status = SMB_VFS_NEXT_CHDIR(handle, smb_fname);
                goto out;
        }
 
-       clientPath = NULL;
-       ctx = talloc_tos();
-
-       if ((status = alloc_get_client_path(handle, ctx,
-                               path,
-                               &clientPath)))
-       {
+       status = alloc_get_client_smb_fname(handle,
+                               talloc_tos(),
+                               smb_fname,
+                               &clientFname);
+       if (status != 0) {
                goto err;
        }
 
-       status = SMB_VFS_NEXT_CHDIR(handle, clientPath);
+       status = SMB_VFS_NEXT_CHDIR(handle, clientFname);
 err:
-       TALLOC_FREE(clientPath);
+       TALLOC_FREE(clientFname);
 out:
        return status;
 }
index 31ef499..4b5a7bc 100644 (file)
@@ -1550,7 +1550,7 @@ static void store_cwd_data(vfs_handle_struct *handle,
 }
 
 static int shadow_copy2_chdir(vfs_handle_struct *handle,
-                             const char *fname)
+                              const struct smb_filename *smb_fname)
 {
        time_t timestamp = 0;
        char *stripped = NULL;
@@ -1559,9 +1559,14 @@ static int shadow_copy2_chdir(vfs_handle_struct *handle,
        int saved_errno = 0;
        char *conv = NULL;
        size_t rootpath_len = 0;
+       struct smb_filename *conv_smb_fname = NULL;
 
-       if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, fname,
-                                       &timestamp, &stripped, &snappath)) {
+       if (!shadow_copy2_strip_snapshot_internal(talloc_tos(),
+                                       handle,
+                                       smb_fname->base_name,
+                                       &timestamp,
+                                       &stripped,
+                                       &snappath)) {
                return -1;
        }
        if (stripped != NULL) {
@@ -1574,10 +1579,22 @@ static int shadow_copy2_chdir(vfs_handle_struct *handle,
                if (conv == NULL) {
                        return -1;
                }
-               fname = conv;
+               conv_smb_fname = synthetic_smb_fname(talloc_tos(),
+                                       conv,
+                                       NULL,
+                                       NULL,
+                                       smb_fname->flags);
+       } else {
+               conv_smb_fname = cp_smb_filename(talloc_tos(), smb_fname);
        }
 
-       ret = SMB_VFS_NEXT_CHDIR(handle, fname);
+       if (conv_smb_fname == NULL) {
+               TALLOC_FREE(conv);
+               errno = ENOMEM;
+               return -1;
+       }
+
+       ret = SMB_VFS_NEXT_CHDIR(handle, conv_smb_fname);
        if (ret == -1) {
                saved_errno = errno;
        }
@@ -1594,6 +1611,7 @@ static int shadow_copy2_chdir(vfs_handle_struct *handle,
 
        TALLOC_FREE(stripped);
        TALLOC_FREE(conv);
+       TALLOC_FREE(conv_smb_fname);
 
        if (saved_errno != 0) {
                errno = saved_errno;
index 4c81432..05d5767 100644 (file)
@@ -2344,29 +2344,49 @@ static int snapper_gmt_chown(vfs_handle_struct *handle,
 }
 
 static int snapper_gmt_chdir(vfs_handle_struct *handle,
-                            const char *fname)
+                       const struct smb_filename *smb_fname)
 {
-       time_t timestamp;
-       char *stripped;
-       int ret, saved_errno;
-       char *conv;
+       time_t timestamp = 0;
+       char *stripped = NULL;
+       int ret;
+       int saved_errno = 0;
+       char *conv = NULL;
+       struct smb_filename *conv_smb_fname = NULL;
 
-       if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, fname,
-                                       &timestamp, &stripped)) {
+       if (!snapper_gmt_strip_snapshot(talloc_tos(),
+                               handle,
+                               smb_fname->base_name,
+                               &timestamp,
+                               &stripped)) {
                return -1;
        }
        if (timestamp == 0) {
-               return SMB_VFS_NEXT_CHDIR(handle, fname);
+               return SMB_VFS_NEXT_CHDIR(handle, smb_fname);
        }
        conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
        TALLOC_FREE(stripped);
        if (conv == NULL) {
                return -1;
        }
-       ret = SMB_VFS_NEXT_CHDIR(handle, conv);
-       saved_errno = errno;
+       conv_smb_fname = synthetic_smb_fname(talloc_tos(),
+                                       conv,
+                                       NULL,
+                                       NULL,
+                                       smb_fname->flags);
+       if (conv_smb_fname == NULL) {
+               TALLOC_FREE(conv);
+               errno = ENOMEM;
+               return -1;
+       }
+       ret = SMB_VFS_NEXT_CHDIR(handle, conv_smb_fname);
+       if (ret == -1) {
+               saved_errno = errno;
+       }
        TALLOC_FREE(conv);
-       errno = saved_errno;
+       TALLOC_FREE(conv_smb_fname);
+       if (saved_errno != 0) {
+               errno = saved_errno;
+       }
        return ret;
 }
 
index d399201..820de3f 100644 (file)
@@ -1236,19 +1236,22 @@ static int smb_time_audit_lchown(vfs_handle_struct *handle,
        return result;
 }
 
-static int smb_time_audit_chdir(vfs_handle_struct *handle, const char *path)
+static int smb_time_audit_chdir(vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname)
 {
        int result;
        struct timespec ts1,ts2;
        double timediff;
 
        clock_gettime_mono(&ts1);
-       result = SMB_VFS_NEXT_CHDIR(handle, path);
+       result = SMB_VFS_NEXT_CHDIR(handle, smb_fname);
        clock_gettime_mono(&ts2);
        timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
 
        if (timediff > audit_timeout) {
-               smb_time_audit_log_fname("chdir", timediff, path);
+               smb_time_audit_log_fname("chdir",
+                       timediff,
+                       smb_fname->base_name);
        }
 
        return result;
index 45232e1..435deeb 100644 (file)
@@ -1267,27 +1267,29 @@ err:
 }
 
 static int um_chdir(vfs_handle_struct *handle,
-                   const char *path)
+                       const struct smb_filename *smb_fname)
 {
        int status;
-       char *client_path = NULL;
+       struct smb_filename *client_fname = NULL;
 
        DEBUG(10, ("Entering um_chdir\n"));
 
-       if (!is_in_media_files(path)) {
-               return SMB_VFS_NEXT_CHDIR(handle, path);
+       if (!is_in_media_files(smb_fname->base_name)) {
+               return SMB_VFS_NEXT_CHDIR(handle, smb_fname);
        }
 
-       status = alloc_get_client_path(handle, talloc_tos(),
-                                      path, &client_path);
+       status = alloc_get_client_smb_fname(handle,
+                               talloc_tos(),
+                               smb_fname,
+                               &client_fname);
        if (status != 0) {
                goto err;
        }
 
-       status = SMB_VFS_NEXT_CHDIR(handle, client_path);
+       status = SMB_VFS_NEXT_CHDIR(handle, client_fname);
 
 err:
-       TALLOC_FREE(client_path);
+       TALLOC_FREE(client_fname);
        return status;
 }
 
index f877039..47590f6 100644 (file)
@@ -674,7 +674,7 @@ static uint32_t get_correct_cversion(struct auth_session_info *session_info,
        struct smb_filename *smb_fname = NULL;
        files_struct      *fsp = NULL;
        connection_struct *conn = NULL;
-       char *oldcwd;
+       struct smb_filename *oldcwd_fname = NULL;
        char *printdollar = NULL;
        char *printdollar_path = NULL;
        char *working_dir = NULL;
@@ -733,7 +733,7 @@ static uint32_t get_correct_cversion(struct auth_session_info *session_info,
                                           &conn,
                                           printdollar_snum,
                                           working_dir,
-                                          session_info, &oldcwd);
+                                          session_info, &oldcwd_fname);
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0,("get_correct_cversion: create_conn_struct "
                         "returned %s\n", nt_errstr(nt_status)));
@@ -851,7 +851,8 @@ static uint32_t get_correct_cversion(struct auth_session_info *session_info,
                close_file(NULL, fsp, NORMAL_CLOSE);
        }
        if (conn != NULL) {
-               vfs_ChDir(conn, oldcwd);
+               vfs_ChDir(conn, oldcwd_fname);
+               TALLOC_FREE(oldcwd_fname);
                SMB_VFS_DISCONNECT(conn);
                conn_free(conn);
        }
@@ -1168,7 +1169,7 @@ WERROR move_driver_to_download_area(struct auth_session_info *session_info,
        int i;
        TALLOC_CTX *ctx = talloc_tos();
        int ver = 0;
-       char *oldcwd;
+       struct smb_filename *oldcwd_fname = NULL;
        char *printdollar = NULL;
        int printdollar_snum;
        WERROR err = WERR_OK;
@@ -1209,7 +1210,7 @@ WERROR move_driver_to_download_area(struct auth_session_info *session_info,
                                           &conn,
                                           printdollar_snum,
                                           lp_path(talloc_tos(), printdollar_snum),
-                                          session_info, &oldcwd);
+                                          session_info, &oldcwd_fname);
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0,("move_driver_to_download_area: create_conn_struct "
                         "returned %s\n", nt_errstr(nt_status)));
@@ -1374,7 +1375,8 @@ WERROR move_driver_to_download_area(struct auth_session_info *session_info,
        TALLOC_FREE(smb_dname);
 
        if (conn != NULL) {
-               vfs_ChDir(conn, oldcwd);
+               vfs_ChDir(conn, oldcwd_fname);
+               TALLOC_FREE(oldcwd_fname);
                SMB_VFS_DISCONNECT(conn);
                conn_free(conn);
        }
@@ -1728,7 +1730,7 @@ bool delete_driver_files(const struct auth_session_info *session_info,
        const char *short_arch;
        connection_struct *conn;
        NTSTATUS nt_status;
-       char *oldcwd;
+       struct smb_filename *oldcwd_fname = NULL;
        char *printdollar = NULL;
        int printdollar_snum;
        bool ret = false;
@@ -1754,7 +1756,7 @@ bool delete_driver_files(const struct auth_session_info *session_info,
                                           &conn,
                                           printdollar_snum,
                                           lp_path(talloc_tos(), printdollar_snum),
-                                          session_info, &oldcwd);
+                                          session_info, &oldcwd_fname);
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0,("delete_driver_files: create_conn_struct "
                         "returned %s\n", nt_errstr(nt_status)));
@@ -1823,7 +1825,8 @@ bool delete_driver_files(const struct auth_session_info *session_info,
        unbecome_user();
  err_free_conn:
        if (conn != NULL) {
-               vfs_ChDir(conn, oldcwd);
+               vfs_ChDir(conn, oldcwd_fname);
+               TALLOC_FREE(oldcwd_fname);
                SMB_VFS_DISCONNECT(conn);
                conn_free(conn);
        }
index fdf42ea..f3173ae 100644 (file)
@@ -2323,7 +2323,7 @@ WERROR _srvsvc_NetGetFileSecurity(struct pipes_struct *p,
        struct sec_desc_buf *sd_buf = NULL;
        files_struct *fsp = NULL;
        int snum;
-       char *oldcwd = NULL;
+       struct smb_filename *oldcwd_fname = NULL;
        uint32_t ucf_flags = 0;
 
        ZERO_STRUCT(st);
@@ -2348,7 +2348,7 @@ WERROR _srvsvc_NetGetFileSecurity(struct pipes_struct *p,
                                           server_messaging_context(),
                                           &conn,
                                           snum, lp_path(talloc_tos(), snum),
-                                          p->session_info, &oldcwd);
+                                          p->session_info, &oldcwd_fname);
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(10, ("create_conn_struct failed: %s\n",
                           nt_errstr(nt_status)));
@@ -2423,12 +2423,7 @@ WERROR _srvsvc_NetGetFileSecurity(struct pipes_struct *p,
 
        *r->out.sd_buf = sd_buf;
 
-       close_file(NULL, fsp, NORMAL_CLOSE);
-       vfs_ChDir(conn, oldcwd);
-       SMB_VFS_DISCONNECT(conn);
-       conn_free(conn);
        werr = WERR_OK;
-       goto done;
 
 error_exit:
 
@@ -2436,8 +2431,9 @@ error_exit:
                close_file(NULL, fsp, NORMAL_CLOSE);
        }
 
-       if (oldcwd) {
-               vfs_ChDir(conn, oldcwd);
+       if (oldcwd_fname) {
+                vfs_ChDir(conn, oldcwd_fname);
+                TALLOC_FREE(oldcwd_fname);
        }
 
        if (conn) {
@@ -2445,8 +2441,6 @@ error_exit:
                conn_free(conn);
        }
 
- done:
-
        TALLOC_FREE(smb_fname);
 
        return werr;
@@ -2468,7 +2462,7 @@ WERROR _srvsvc_NetSetFileSecurity(struct pipes_struct *p,
        WERROR werr;
        connection_struct *conn = NULL;
        int snum;
-       char *oldcwd = NULL;
+       struct smb_filename *oldcwd_fname = NULL;
        struct security_descriptor *psd = NULL;
        uint32_t security_info_sent = 0;
        uint32_t ucf_flags = 0;
@@ -2497,7 +2491,7 @@ WERROR _srvsvc_NetSetFileSecurity(struct pipes_struct *p,
                                           server_messaging_context(),
                                           &conn,
                                           snum, lp_path(talloc_tos(), snum),
-                                          p->session_info, &oldcwd);
+                                          p->session_info, &oldcwd_fname);
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(10, ("create_conn_struct failed: %s\n",
                           nt_errstr(nt_status)));
@@ -2555,12 +2549,7 @@ WERROR _srvsvc_NetSetFileSecurity(struct pipes_struct *p,
                goto error_exit;
        }
 
-       close_file(NULL, fsp, NORMAL_CLOSE);
-       vfs_ChDir(conn, oldcwd);
-       SMB_VFS_DISCONNECT(conn);
-       conn_free(conn);
        werr = WERR_OK;
-       goto done;
 
 error_exit:
 
@@ -2568,8 +2557,9 @@ error_exit:
                close_file(NULL, fsp, NORMAL_CLOSE);
        }
 
-       if (oldcwd) {
-               vfs_ChDir(conn, oldcwd);
+       if (oldcwd_fname) {
+               vfs_ChDir(conn, oldcwd_fname);
+               TALLOC_FREE(oldcwd_fname);
        }
 
        if (conn) {
@@ -2577,7 +2567,6 @@ error_exit:
                conn_free(conn);
        }
 
- done:
        TALLOC_FREE(smb_fname);
 
        return werr;
index 1348d12..9391e3c 100644 (file)
@@ -399,7 +399,8 @@ static struct smb_Dir *open_dir_with_privilege(connection_struct *conn,
                                        uint32_t attr)
 {
        struct smb_Dir *dir_hnd = NULL;
-       struct smb_filename *smb_fname_cwd;
+       struct smb_filename *smb_fname_cwd = NULL;
+       struct smb_filename saved_dir_fname = {0};
        char *saved_dir = vfs_GetWd(talloc_tos(), conn);
        struct privilege_paths *priv_paths = req->priv_paths;
        int ret;
@@ -408,7 +409,9 @@ static struct smb_Dir *open_dir_with_privilege(connection_struct *conn,
                return NULL;
        }
 
-       if (vfs_ChDir(conn, smb_dname->base_name) == -1) {
+       saved_dir_fname = (struct smb_filename) { .base_name = saved_dir };
+
+       if (vfs_ChDir(conn, smb_dname) == -1) {
                return NULL;
        }
 
@@ -438,7 +441,8 @@ static struct smb_Dir *open_dir_with_privilege(connection_struct *conn,
 
   out:
 
-       vfs_ChDir(conn, saved_dir);
+       vfs_ChDir(conn, &saved_dir_fname);
+       TALLOC_FREE(saved_dir);
        return dir_hnd;
 }
 
@@ -1679,6 +1683,7 @@ static struct smb_Dir *open_dir_safely(TALLOC_CTX *ctx,
 {
        struct smb_Dir *dir_hnd = NULL;
        struct smb_filename *smb_fname_cwd = NULL;
+       struct smb_filename saved_dir_fname = {0};
        char *saved_dir = vfs_GetWd(ctx, conn);
        NTSTATUS status;
 
@@ -1686,7 +1691,9 @@ static struct smb_Dir *open_dir_safely(TALLOC_CTX *ctx,
                return NULL;
        }
 
-       if (vfs_ChDir(conn, smb_dname->base_name) == -1) {
+       saved_dir_fname = (struct smb_filename) { .base_name = saved_dir };
+
+       if (vfs_ChDir(conn, smb_dname) == -1) {
                goto out;
        }
 
@@ -1731,7 +1738,7 @@ static struct smb_Dir *open_dir_safely(TALLOC_CTX *ctx,
 
   out:
 
-       vfs_ChDir(conn, saved_dir);
+       vfs_ChDir(conn, &saved_dir_fname);
        TALLOC_FREE(saved_dir);
        return dir_hnd;
 }
index 9c25d8b..d87b9b9 100644 (file)
@@ -400,10 +400,12 @@ NTSTATUS create_conn_struct_cwd(TALLOC_CTX *ctx,
                                int snum,
                                const char *path,
                                const struct auth_session_info *session_info,
-                               char **poldcwd)
+                               struct smb_filename **poldcwd_fname)
 {
        connection_struct *conn;
-       char *oldcwd;
+       char *oldcwd = NULL;
+       struct smb_filename *smb_fname_oldcwd = NULL;
+       struct smb_filename smb_fname_connectpath = {0};
 
        NTSTATUS status = create_conn_struct(ctx, ev,
                                             msg, &conn,
@@ -427,17 +429,33 @@ NTSTATUS create_conn_struct_cwd(TALLOC_CTX *ctx,
                return status;
        }
 
-       if (vfs_ChDir(conn,conn->connectpath) != 0) {
+       smb_fname_oldcwd = synthetic_smb_fname(ctx,
+                               oldcwd,
+                               NULL,
+                               NULL,
+                               0);
+       if (smb_fname_oldcwd == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               conn_free(conn);
+               return status;
+       }
+
+       smb_fname_connectpath = (struct smb_filename) {
+               .base_name = conn->connectpath
+       };
+
+       if (vfs_ChDir(conn, &smb_fname_connectpath) != 0) {
                status = map_nt_error_from_unix(errno);
                DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. "
                        "Error was %s\n",
                        conn->connectpath, strerror(errno) ));
+               TALLOC_FREE(smb_fname_oldcwd);
                conn_free(conn);
                return status;
        }
 
        *pconn = conn;
-       *poldcwd = oldcwd;
+       *poldcwd_fname = smb_fname_oldcwd;
 
        return NT_STATUS_OK;
 }
@@ -957,7 +975,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx,
        NTSTATUS status = NT_STATUS_NOT_FOUND;
        bool dummy;
        struct dfs_path *pdp = talloc(ctx, struct dfs_path);
-       char *oldpath;
+       struct smb_filename *oldcwd_fname = NULL;
 
        if (!pdp) {
                return NT_STATUS_NO_MEMORY;
@@ -1054,8 +1072,11 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx,
        status = create_conn_struct_cwd(ctx,
                                        server_event_context(),
                                        server_messaging_context(),
-                                       &conn, snum,
-                                       lp_path(talloc_tos(), snum), NULL, &oldpath);
+                                       &conn,
+                                       snum,
+                                       lp_path(talloc_tos(), snum),
+                                       NULL,
+                                       &oldcwd_fname);
        if (!NT_STATUS_IS_OK(status)) {
                TALLOC_FREE(pdp);
                return status;
@@ -1121,7 +1142,8 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx,
 
        status = NT_STATUS_OK;
  err_exit:
-       vfs_ChDir(conn, oldpath);
+       vfs_ChDir(conn, oldcwd_fname);
+       TALLOC_FREE(oldcwd_fname);
        SMB_VFS_DISCONNECT(conn);
        conn_free(conn);
        TALLOC_FREE(pdp);
@@ -1257,7 +1279,7 @@ bool create_junction(TALLOC_CTX *ctx,
 static bool junction_to_local_path(const struct junction_map *jucn,
                                   char **pp_path_out,
                                   connection_struct **conn_out,
-                                  char **oldpath)
+                                  struct smb_filename **oldpath_fname)
 {
        int snum;
        NTSTATUS status;
@@ -1270,7 +1292,10 @@ static bool junction_to_local_path(const struct junction_map *jucn,
                                        server_event_context(),
                                        server_messaging_context(),
                                        conn_out,
-                                       snum, lp_path(talloc_tos(), snum), NULL, oldpath);
+                                       snum,
+                                       lp_path(talloc_tos(), snum),
+                                       NULL,
+                                       oldpath_fname);
        if (!NT_STATUS_IS_OK(status)) {
                return False;
        }
@@ -1280,7 +1305,7 @@ static bool junction_to_local_path(const struct junction_map *jucn,
                        lp_path(talloc_tos(), snum),
                        jucn->volume_name);
        if (!*pp_path_out) {
-               vfs_ChDir(*conn_out, *oldpath);
+               vfs_ChDir(*conn_out, *oldpath_fname);
                SMB_VFS_DISCONNECT(*conn_out);
                conn_free(*conn_out);
                return False;
@@ -1291,7 +1316,7 @@ static bool junction_to_local_path(const struct junction_map *jucn,
 bool create_msdfs_link(const struct junction_map *jucn)
 {
        char *path = NULL;
-       char *cwd;
+       struct smb_filename *cwd_fname = NULL;
        char *msdfs_link = NULL;
        connection_struct *conn;
        int i=0;
@@ -1299,7 +1324,7 @@ bool create_msdfs_link(const struct junction_map *jucn)
        bool ret = False;
        struct smb_filename *smb_fname = NULL;
 
-       if(!junction_to_local_path(jucn, &path, &conn, &cwd)) {
+       if(!junction_to_local_path(jucn, &path, &conn, &cwd_fname)) {
                return False;
        }
 
@@ -1369,7 +1394,8 @@ bool create_msdfs_link(const struct junction_map *jucn)
 
 out:
        TALLOC_FREE(smb_fname);
-       vfs_ChDir(conn, cwd);
+       vfs_ChDir(conn, cwd_fname);
+       TALLOC_FREE(cwd_fname);
        SMB_VFS_DISCONNECT(conn);
        conn_free(conn);
        return ret;
@@ -1378,12 +1404,12 @@ out:
 bool remove_msdfs_link(const struct junction_map *jucn)
 {
        char *path = NULL;
-       char *cwd;
+       struct smb_filename *cwd_fname = NULL;
        connection_struct *conn;
        bool ret = False;
        struct smb_filename *smb_fname;
 
-       if (!junction_to_local_path(jucn, &path, &conn, &cwd)) {
+       if (!junction_to_local_path(jucn, &path, &conn, &cwd_fname)) {
                return false;
        }
 
@@ -1402,7 +1428,8 @@ bool remove_msdfs_link(const struct junction_map *jucn)
        }
 
        TALLOC_FREE(smb_fname);
-       vfs_ChDir(conn, cwd);
+       vfs_ChDir(conn, cwd_fname);
+       TALLOC_FREE(cwd_fname);
        SMB_VFS_DISCONNECT(conn);
        conn_free(conn);
        return ret;
@@ -1422,7 +1449,7 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum)
        const char *msdfs_proxy = lp_msdfs_proxy(talloc_tos(), snum);
        connection_struct *conn;
        NTSTATUS status;
-       char *cwd;
+       struct smb_filename *cwd_fname = NULL;
        struct smb_filename *smb_fname = NULL;
 
        if(*connect_path == '\0') {
@@ -1437,7 +1464,10 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum)
                                        server_event_context(),
                                        server_messaging_context(),
                                        &conn,
-                                       snum, connect_path, NULL, &cwd);
+                                       snum,
+                                       connect_path,
+                                       NULL,
+                                       &cwd_fname);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(3, ("create_conn_struct failed: %s\n",
                          nt_errstr(status)));
@@ -1489,7 +1519,8 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum)
 
 out:
        TALLOC_FREE(smb_fname);
-       vfs_ChDir(conn, cwd);
+       vfs_ChDir(conn, cwd_fname);
+       TALLOC_FREE(cwd_fname);
        SMB_VFS_DISCONNECT(conn);
        conn_free(conn);
        return cnt;
@@ -1512,7 +1543,7 @@ static int form_junctions(TALLOC_CTX *ctx,
        const char *msdfs_proxy = lp_msdfs_proxy(talloc_tos(), snum);
        connection_struct *conn;
        struct referral *ref = NULL;
-       char *cwd;
+       struct smb_filename *cwd_fname = NULL;
        struct smb_filename *smb_fname = NULL;
        NTSTATUS status;
 
@@ -1531,8 +1562,11 @@ static int form_junctions(TALLOC_CTX *ctx,
        status = create_conn_struct_cwd(ctx,
                                        server_event_context(),
                                        server_messaging_context(),
-                                       &conn, snum, connect_path, NULL,
-                                       &cwd);
+                                       &conn,
+                                       snum,
+                                       connect_path,
+                                       NULL,
+                                       &cwd_fname);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(3, ("create_conn_struct failed: %s\n",
                          nt_errstr(status)));
@@ -1646,7 +1680,8 @@ out:
        }
 
        TALLOC_FREE(smb_fname);
-       vfs_ChDir(conn, cwd);
+       vfs_ChDir(conn, cwd_fname);
+       TALLOC_FREE(cwd_fname);
        conn_free(conn);
        return cnt;
 }
index fa74f48..031ba11 100644 (file)
@@ -389,7 +389,7 @@ static int link_errno_convert(int err)
 }
 
 static int non_widelink_open(struct connection_struct *conn,
-                       const char *conn_rootdir,
+                       const struct smb_filename *conn_rootdir_fname,
                        files_struct *fsp,
                        struct smb_filename *smb_fname,
                        int flags,
@@ -401,7 +401,7 @@ static int non_widelink_open(struct connection_struct *conn,
 ****************************************************************************/
 
 static int process_symlink_open(struct connection_struct *conn,
-                       const char *conn_rootdir,
+                       const struct smb_filename *conn_rootdir_fname,
                        files_struct *fsp,
                        struct smb_filename *smb_fname,
                        int flags,
@@ -412,6 +412,7 @@ static int process_symlink_open(struct connection_struct *conn,
        char *link_target = NULL;
        int link_len = -1;
        char *oldwd = NULL;
+       struct smb_filename oldwd_fname = {0};
        size_t rootdir_len = 0;
        char *resolved_name = NULL;
        bool matched = false;
@@ -456,9 +457,11 @@ static int process_symlink_open(struct connection_struct *conn,
         * does not end in '/'. FIXME ! Should we
         * smb_assert this ?
         */
-       rootdir_len = strlen(conn_rootdir);
+       rootdir_len = strlen(conn_rootdir_fname->base_name);
 
-       matched = (strncmp(conn_rootdir, resolved_name, rootdir_len) == 0);
+       matched = (strncmp(conn_rootdir_fname->base_name,
+                               resolved_name,
+                               rootdir_len) == 0);
        if (!matched) {
                errno = EACCES;
                goto out;
@@ -486,14 +489,16 @@ static int process_symlink_open(struct connection_struct *conn,
                goto out;
        }
 
+       oldwd_fname = (struct smb_filename) { .base_name = oldwd };
+
        /* Ensure we operate from the root of the share. */
-       if (vfs_ChDir(conn, conn_rootdir) == -1) {
+       if (vfs_ChDir(conn, conn_rootdir_fname) == -1) {
                goto out;
        }
 
        /* And do it all again.. */
        fd = non_widelink_open(conn,
-                               conn_rootdir,
+                               conn_rootdir_fname,
                                fsp,
                                smb_fname,
                                flags,
@@ -508,7 +513,7 @@ static int process_symlink_open(struct connection_struct *conn,
        SAFE_FREE(resolved_name);
        TALLOC_FREE(link_target);
        if (oldwd != NULL) {
-               int ret = vfs_ChDir(conn, oldwd);
+               int ret = vfs_ChDir(conn, &oldwd_fname);
                if (ret == -1) {
                        smb_panic("unable to get back to old directory\n");
                }
@@ -525,7 +530,7 @@ static int process_symlink_open(struct connection_struct *conn,
 ****************************************************************************/
 
 static int non_widelink_open(struct connection_struct *conn,
-                       const char *conn_rootdir,
+                       const struct smb_filename *conn_rootdir_fname,
                        files_struct *fsp,
                        struct smb_filename *smb_fname,
                        int flags,
@@ -537,7 +542,9 @@ static int non_widelink_open(struct connection_struct *conn,
        struct smb_filename *smb_fname_rel = NULL;
        int saved_errno = 0;
        char *oldwd = NULL;
+       struct smb_filename oldwd_fname = {0};
        char *parent_dir = NULL;
+       struct smb_filename parent_dir_fname = {0};
        const char *final_component = NULL;
 
        if (!parent_dirname(talloc_tos(),
@@ -547,13 +554,17 @@ static int non_widelink_open(struct connection_struct *conn,
                goto out;
        }
 
+       parent_dir_fname = (struct smb_filename) { .base_name = parent_dir };
+
        oldwd = vfs_GetWd(talloc_tos(), conn);
        if (oldwd == NULL) {
                goto out;
        }
 
+       oldwd_fname = (struct smb_filename) { .base_name = oldwd };
+
        /* Pin parent directory in place. */
-       if (vfs_ChDir(conn, parent_dir) == -1) {
+       if (vfs_ChDir(conn, &parent_dir_fname) == -1) {
                goto out;
        }
 
@@ -606,7 +617,7 @@ static int non_widelink_open(struct connection_struct *conn,
                         * to ensure it's under the share definition.
                         */
                        fd = process_symlink_open(conn,
-                                       conn_rootdir,
+                                       conn_rootdir_fname,
                                        fsp,
                                        smb_fname_rel,
                                        flags,
@@ -634,7 +645,7 @@ static int non_widelink_open(struct connection_struct *conn,
        TALLOC_FREE(smb_fname_rel);
 
        if (oldwd != NULL) {
-               int ret = vfs_ChDir(conn, oldwd);
+               int ret = vfs_ChDir(conn, &oldwd_fname);
                if (ret == -1) {
                        smb_panic("unable to get back to old directory\n");
                }
@@ -669,22 +680,41 @@ NTSTATUS fd_open(struct connection_struct *conn,
 
        /* Ensure path is below share definition. */
        if (!lp_widelinks(SNUM(conn))) {
+               struct smb_filename *conn_rootdir_fname = NULL;
                const char *conn_rootdir = SMB_VFS_CONNECTPATH(conn,
                                                smb_fname->base_name);
+               int saved_errno = 0;
+
                if (conn_rootdir == NULL) {
                        return NT_STATUS_NO_MEMORY;
                }
+               conn_rootdir_fname = synthetic_smb_fname(talloc_tos(),
+                                               conn_rootdir,
+                                               NULL,
+                                               NULL,
+                                               0);
+               if (conn_rootdir_fname == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
                /*
                 * Only follow symlinks within a share
                 * definition.
                 */
                fsp->fh->fd = non_widelink_open(conn,
-                                       conn_rootdir,
+                                       conn_rootdir_fname,
                                        fsp,
                                        smb_fname,
                                        flags,
                                        mode,
                                        0);
+               if (fsp->fh->fd == -1) {
+                       saved_errno = errno;
+               }
+               TALLOC_FREE(conn_rootdir_fname);
+               if (saved_errno != 0) {
+                       errno = saved_errno;
+               }
        } else {
                fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, mode);
        }
@@ -800,14 +830,15 @@ void change_file_owner_to_parent(connection_struct *conn,
        TALLOC_FREE(smb_fname_parent);
 }
 
-NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
-                                      const char *inherit_from_dir,
-                                      const char *fname,
-                                      SMB_STRUCT_STAT *psbuf)
+static NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
+                                       const char *inherit_from_dir,
+                                       struct smb_filename *smb_dname,
+                                       SMB_STRUCT_STAT *psbuf)
 {
        struct smb_filename *smb_fname_parent;
        struct smb_filename *smb_fname_cwd = NULL;
        char *saved_dir = NULL;
+       struct smb_filename smb_fname_saved_dir = {0};
        TALLOC_CTX *ctx = talloc_tos();
        NTSTATUS status = NT_STATUS_OK;
        int ret;
@@ -847,12 +878,14 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
                goto out;
        }
 
+       smb_fname_saved_dir = (struct smb_filename) { .base_name = saved_dir };
+
        /* Chdir into the new path. */
-       if (vfs_ChDir(conn, fname) == -1) {
+       if (vfs_ChDir(conn, smb_dname) == -1) {
                status = map_nt_error_from_unix(errno);
                DEBUG(0,("change_dir_owner_to_parent: failed to change "
                         "current working directory to %s. Error "
-                        "was %s\n", fname, strerror(errno) ));
+                        "was %s\n", smb_dname->base_name, strerror(errno) ));
                goto chdir;
        }
 
@@ -867,7 +900,7 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
                status = map_nt_error_from_unix(errno);
                DEBUG(0,("change_dir_owner_to_parent: failed to stat "
                         "directory '.' (%s) Error was %s\n",
-                        fname, strerror(errno)));
+                        smb_dname->base_name, strerror(errno)));
                goto chdir;
        }
 
@@ -876,7 +909,8 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
            smb_fname_cwd->st.st_ex_ino != psbuf->st_ex_ino) {
                DEBUG(0,("change_dir_owner_to_parent: "
                         "device/inode on directory %s changed. "
-                        "Refusing to chown !\n", fname ));
+                        "Refusing to chown !\n",
+                       smb_dname->base_name ));
                status = NT_STATUS_ACCESS_DENIED;
                goto chdir;
        }
@@ -885,7 +919,7 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
                /* Already this uid - no need to change. */
                DEBUG(10,("change_dir_owner_to_parent: directory %s "
                        "is already owned by uid %d\n",
-                       fname,
+                       smb_dname->base_name,
                        (int)smb_fname_cwd->st.st_ex_uid ));
                status = NT_STATUS_OK;
                goto chdir;
@@ -901,20 +935,23 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
                status = map_nt_error_from_unix(errno);
                DEBUG(10,("change_dir_owner_to_parent: failed to chown "
                          "directory %s to parent directory uid %u. "
-                         "Error was %s\n", fname,
+                         "Error was %s\n",
+                         smb_dname->base_name,
                          (unsigned int)smb_fname_parent->st.st_ex_uid,
                          strerror(errno) ));
        } else {
                DEBUG(10,("change_dir_owner_to_parent: changed ownership of new "
                        "directory %s to parent directory uid %u.\n",
-                       fname, (unsigned int)smb_fname_parent->st.st_ex_uid ));
+                       smb_dname->base_name,
+                       (unsigned int)smb_fname_parent->st.st_ex_uid ));
                /* Ensure the uid entry is updated. */
                psbuf->st_ex_uid = smb_fname_parent->st.st_ex_uid;
        }
 
  chdir:
-       vfs_ChDir(conn,saved_dir);
+       vfs_ChDir(conn, &smb_fname_saved_dir);
  out:
+       TALLOC_FREE(saved_dir);
        TALLOC_FREE(smb_fname_parent);
        TALLOC_FREE(smb_fname_cwd);
        return status;
@@ -3875,7 +3912,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
        /* Change the owner if required. */
        if (lp_inherit_owner(SNUM(conn)) != INHERIT_OWNER_NO) {
                change_dir_owner_to_parent(conn, parent_dir,
-                                          smb_dname->base_name,
+                                          smb_dname,
                                           &smb_dname->st);
                need_re_stat = true;
        }
index 722edf3..4823e11 100644 (file)
@@ -510,7 +510,7 @@ NTSTATUS create_conn_struct_cwd(TALLOC_CTX *ctx,
                                int snum,
                                const char *path,
                                const struct auth_session_info *session_info,
-                               char **poldcwd);
+                               struct smb_filename **poldcwd_fname);
 
 /* The following definitions come from smbd/negprot.c  */
 
@@ -649,10 +649,6 @@ NTSTATUS fd_close(files_struct *fsp);
 void change_file_owner_to_parent(connection_struct *conn,
                                 const char *inherit_from_dir,
                                 files_struct *fsp);
-NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
-                                   const char *inherit_from_dir,
-                                   const char *fname,
-                                   SMB_STRUCT_STAT *psbuf);
 bool is_stat_open(uint32_t access_mask);
 NTSTATUS send_break_message(struct messaging_context *msg_ctx,
                                const struct share_mode_entry *exclusive,
@@ -1234,7 +1230,8 @@ int vfs_fill_sparse(files_struct *fsp, off_t len);
 off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n);
 const char *vfs_readdirname(connection_struct *conn, void *p,
                            SMB_STRUCT_STAT *sbuf, char **talloced);
-int vfs_ChDir(connection_struct *conn, const char *path);
+int vfs_ChDir(connection_struct *conn,
+                       const struct smb_filename *smb_fname);
 char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn);
 NTSTATUS check_reduced_name(connection_struct *conn,
                        const char *cwd_name,
index 0376a33..47cd0fa 100644 (file)
@@ -95,12 +95,22 @@ bool set_current_service(connection_struct *conn, uint16_t flags, bool do_chdir)
 
        snum = SNUM(conn);
 
-       if (do_chdir &&
-           vfs_ChDir(conn,conn->connectpath) != 0 &&
-           vfs_ChDir(conn,conn->origpath) != 0) {
-                DEBUG(((errno!=EACCES)?0:3),("chdir (%s) failed, reason: %s\n",
-                         conn->connectpath, strerror(errno)));
-               return(False);
+       {
+               struct smb_filename connectpath_fname = {
+                       .base_name = conn->connectpath
+               };
+               struct smb_filename origpath_fname = {
+                       .base_name = conn->origpath
+               };
+
+               if (do_chdir &&
+                   vfs_ChDir(conn, &connectpath_fname) != 0 &&
+                   vfs_ChDir(conn, &origpath_fname) != 0) {
+                       DEBUG(((errno!=EACCES)?0:3),
+                               ("chdir (%s) failed, reason: %s\n",
+                               conn->connectpath, strerror(errno)));
+                       return(False);
+               }
        }
 
        if ((conn == last_conn) && (last_flags == flags)) {
@@ -1083,6 +1093,9 @@ connection_struct *make_connection(struct smb_request *req,
 
 void close_cnum(connection_struct *conn, uint64_t vuid)
 {
+       char rootpath[2] = { '/', '\0'};
+       struct smb_filename root_fname = { .base_name = rootpath };
+
        file_close_conn(conn);
 
        if (!IS_IPC(conn)) {
@@ -1098,7 +1111,7 @@ void close_cnum(connection_struct *conn, uint64_t vuid)
                                 lp_servicename(talloc_tos(), SNUM(conn))));
 
        /* make sure we leave the directory available for unmount */
-       vfs_ChDir(conn, "/");
+       vfs_ChDir(conn, &root_fname);
 
        /* Call VFS disconnect hook */
        SMB_VFS_DISCONNECT(conn);
index 5acfb9a..40c41ed 100644 (file)
@@ -855,7 +855,7 @@ const char *vfs_readdirname(connection_struct *conn, void *p,
  A wrapper for vfs_chdir().
 ********************************************************************/
 
-int vfs_ChDir(connection_struct *conn, const char *path)
+int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
 {
        int ret;
 
@@ -863,21 +863,22 @@ int vfs_ChDir(connection_struct *conn, const char *path)
                LastDir = SMB_STRDUP("");
        }
 
-       if (ISDOT(path)) {
+       if (ISDOT(smb_fname->base_name)) {
                return 0;
        }
 
-       if (*path == '/' && strcsequal(LastDir,path)) {
+       if (*smb_fname->base_name == '/' &&
+                       strcsequal(LastDir,smb_fname->base_name)) {
                return 0;
        }
 
-       DEBUG(4,("vfs_ChDir to %s\n",path));
+       DEBUG(4,("vfs_ChDir to %s\n", smb_fname->base_name));
 
-       ret = SMB_VFS_CHDIR(conn,path);
+       ret = SMB_VFS_CHDIR(conn, smb_fname);
        if (ret == 0) {
                /* Global cache. */
                SAFE_FREE(LastDir);
-               LastDir = SMB_STRDUP(path);
+               LastDir = SMB_STRDUP(smb_fname->base_name);
 
                /* conn cache. */
                TALLOC_FREE(conn->cwd);
@@ -1009,6 +1010,7 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
        const char *last_component = NULL;
        char *resolved_name = NULL;
        char *saved_dir = NULL;
+       struct smb_filename *saved_dir_fname = NULL;
        struct smb_filename *smb_fname_cwd = NULL;
        struct privilege_paths *priv_paths = NULL;
        int ret;
@@ -1049,8 +1051,18 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
                goto err;
        }
 
+       saved_dir_fname = synthetic_smb_fname(ctx,
+                                       saved_dir,
+                                       NULL,
+                                       NULL,
+                                       0);
+       if (saved_dir_fname == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto err;
+       }
+
        /* Go to the parent directory to lock in memory. */
-       if (vfs_ChDir(conn, priv_paths->parent_name.base_name) == -1) {
+       if (vfs_ChDir(conn, &priv_paths->parent_name) == -1) {
                status = map_nt_error_from_unix(errno);
                goto err;
        }
@@ -1165,8 +1177,10 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
 
   err:
 
-       if (saved_dir) {
-               vfs_ChDir(conn, saved_dir);
+       if (saved_dir_fname) {
+               vfs_ChDir(conn, saved_dir_fname);
+               TALLOC_FREE(saved_dir);
+               TALLOC_FREE(saved_dir_fname);
        }
        SAFE_FREE(resolved_name);
        if (!NT_STATUS_IS_OK(status)) {
@@ -2014,6 +2028,8 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
                char *parent_dir = NULL;
                const char *final_component = NULL;
                struct smb_filename *local_smb_fname = NULL;
+               struct smb_filename parent_dir_fname = {0};
+               struct smb_filename saved_dir_fname = {0};
 
                saved_dir = vfs_GetWd(talloc_tos(),fsp->conn);
                if (!saved_dir) {
@@ -2024,6 +2040,10 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
                        return status;
                }
 
+               saved_dir_fname = (struct smb_filename) {
+                       .base_name = saved_dir
+               };
+
                if (!parent_dirname(talloc_tos(),
                                fsp->fsp_name->base_name,
                                &parent_dir,
@@ -2031,8 +2051,13 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
                        return NT_STATUS_NO_MEMORY;
                }
 
+               parent_dir_fname = (struct smb_filename) {
+                       .base_name = parent_dir,
+                       .flags = fsp->fsp_name->flags
+               };
+
                /* cd into the parent dir to pin it. */
-               ret = vfs_ChDir(fsp->conn, parent_dir);
+               ret = vfs_ChDir(fsp->conn, &parent_dir_fname);
                if (ret == -1) {
                        return map_nt_error_from_unix(errno);
                }
@@ -2073,7 +2098,7 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
 
   out:
 
-               vfs_ChDir(fsp->conn,saved_dir);
+               vfs_ChDir(fsp->conn, &saved_dir_fname);
                TALLOC_FREE(local_smb_fname);
                TALLOC_FREE(saved_dir);
                TALLOC_FREE(parent_dir);
@@ -2099,10 +2124,11 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
        return status;
 }
 
-int smb_vfs_call_chdir(struct vfs_handle_struct *handle, const char *path)
+int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname)
 {
        VFS_FIND(chdir);
-       return handle->fns->chdir_fn(handle, path);
+       return handle->fns->chdir_fn(handle, smb_fname);
 }
 
 char *smb_vfs_call_getwd(struct vfs_handle_struct *handle)
index 65a8e25..f6d9d5b 100644 (file)
@@ -463,7 +463,8 @@ static NTSTATUS cmd_pathfunc(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int arg
                ret = SMB_VFS_UNLINK(vfs->conn, smb_fname);
                TALLOC_FREE(smb_fname);
        } else if (strcmp("chdir", argv[0]) == 0 ) {
-               ret = SMB_VFS_CHDIR(vfs->conn, argv[1]);
+               ret = SMB_VFS_CHDIR(vfs->conn, smb_fname);
+               TALLOC_FREE(smb_fname);
        } else {
                printf("%s: error=%d (invalid function name!)\n", argv[0], errno);
                return NT_STATUS_UNSUCCESSFUL;