summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2017-06-29 11:29:33 -0700
committerJeremy Allison <jra@samba.org>2017-07-01 03:07:11 +0200
commit6acb0d6ca08d72f776d3ba9dc934261a481aa737 (patch)
tree0ca605c49d66648ce79c274ec7fdbbfa7a3571a3 /source3
parent73bee8b690edcc946f2e98aca711dd77d104e76e (diff)
downloadsamba-6acb0d6ca08d72f776d3ba9dc934261a481aa737.tar.gz
s3: VFS: Change SMB_VFS_CHDIR to use const struct smb_filename * instead of const char *.
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>
Diffstat (limited to 'source3')
-rw-r--r--source3/include/vfs.h8
-rw-r--r--source3/include/vfs_macros.h8
-rw-r--r--source3/modules/vfs_acl_common.c20
-rw-r--r--source3/modules/vfs_cap.c32
-rw-r--r--source3/modules/vfs_catia.c22
-rw-r--r--source3/modules/vfs_ceph.c12
-rw-r--r--source3/modules/vfs_default.c17
-rw-r--r--source3/modules/vfs_full_audit.c7
-rw-r--r--source3/modules/vfs_glusterfs.c5
-rw-r--r--source3/modules/vfs_media_harmony.c26
-rw-r--r--source3/modules/vfs_shadow_copy2.c28
-rw-r--r--source3/modules/vfs_snapper.c42
-rw-r--r--source3/modules/vfs_time_audit.c9
-rw-r--r--source3/modules/vfs_unityed_media.c18
-rw-r--r--source3/printing/nt_printing.c21
-rw-r--r--source3/rpc_server/srvsvc/srv_srvsvc_nt.c31
-rw-r--r--source3/smbd/dir.c17
-rw-r--r--source3/smbd/msdfs.c83
-rw-r--r--source3/smbd/open.c87
-rw-r--r--source3/smbd/proto.h9
-rw-r--r--source3/smbd/service.c27
-rw-r--r--source3/smbd/vfs.c52
-rw-r--r--source3/torture/cmd_vfs.c3
23 files changed, 395 insertions, 189 deletions
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index db555f2cc2b..f5ac5b5c82e 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -228,6 +228,8 @@
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,
diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h
index 77646b45f06..367009bad07 100644
--- a/source3/include/vfs_macros.h
+++ b/source3/include/vfs_macros.h
@@ -266,10 +266,10 @@
#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)
diff --git a/source3/modules/vfs_acl_common.c b/source3/modules/vfs_acl_common.c
index bd1d755c91f..3b054df2b7d 100644
--- a/source3/modules/vfs_acl_common.c
+++ b/source3/modules/vfs_acl_common.c
@@ -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);
}
diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c
index c07a05954c0..44a81bbcefb 100644
--- a/source3/modules/vfs_cap.c
+++ b/source3/modules/vfs_cap.c
@@ -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,
diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c
index ed16e43aa38..7db50a26206 100644
--- a/source3/modules/vfs_catia.c
+++ b/source3/modules/vfs_catia.c
@@ -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;
}
diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c
index 7e2bd0e95d2..6b298a2e38f 100644
--- a/source3/modules/vfs_ceph.c
+++ b/source3/modules/vfs_ceph.c
@@ -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);
}
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index d339f39aa06..7a2fae2156d 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -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;
}
diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c
index 1267ef3d226..5d35c340371 100644
--- a/source3/modules/vfs_full_audit.c
+++ b/source3/modules/vfs_full_audit.c
@@ -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;
}
diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
index 2528959d968..833f093ac42 100644
--- a/source3/modules/vfs_glusterfs.c
+++ b/source3/modules/vfs_glusterfs.c
@@ -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)
diff --git a/source3/modules/vfs_media_harmony.c b/source3/modules/vfs_media_harmony.c
index ca8d6ce1a6d..bd774b83909 100644
--- a/source3/modules/vfs_media_harmony.c
+++ b/source3/modules/vfs_media_harmony.c
@@ -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;
}
diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
index 31ef499527e..4b5a7bccc97 100644
--- a/source3/modules/vfs_shadow_copy2.c
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -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;
diff --git a/source3/modules/vfs_snapper.c b/source3/modules/vfs_snapper.c
index 4c814327feb..05d57671db7 100644
--- a/source3/modules/vfs_snapper.c
+++ b/source3/modules/vfs_snapper.c
@@ -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;
}
diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c
index d3992018542..820de3ffa2c 100644
--- a/source3/modules/vfs_time_audit.c
+++ b/source3/modules/vfs_time_audit.c
@@ -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;
diff --git a/source3/modules/vfs_unityed_media.c b/source3/modules/vfs_unityed_media.c
index 45232e1781c..435deeb0579 100644
--- a/source3/modules/vfs_unityed_media.c
+++ b/source3/modules/vfs_unityed_media.c
@@ -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;
}
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c
index f87703905ed..47590f67fc7 100644
--- a/source3/printing/nt_printing.c
+++ b/source3/printing/nt_printing.c
@@ -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);
}
diff --git a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c
index fdf42ea030b..f3173aee42f 100644
--- a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c
+++ b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c
@@ -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;
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index 1348d12298c..9391e3c827c 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -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;
}
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index 9c25d8ba8fe..d87b9b9bace 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -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;
}
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index fa74f48b66d..031ba11f1d2 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -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;
}
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 722edf3e67c..4823e1170fc 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -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,
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index 0376a330e23..47cd0fa19d5 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -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);
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 5acfb9af38a..40c41ed27fc 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -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)
diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c
index 65a8e258d0d..f6d9d5b6be7 100644
--- a/source3/torture/cmd_vfs.c
+++ b/source3/torture/cmd_vfs.c
@@ -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;