1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-27 22:50:26 +03:00

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>
This commit is contained in:
Jeremy Allison 2017-06-29 11:29:33 -07:00
parent 73bee8b690
commit 6acb0d6ca0
25 changed files with 400 additions and 192 deletions

View 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;

View 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)

View File

@ -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,

View File

@ -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)

View 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);
}

View 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,

View 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;
}

View 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);
}

View 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;
}

View 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;
}

View 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)

View 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;
}

View 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;

View 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;
}

View 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;

View 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;
}

View 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);
}

View 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;

View 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;
}

View 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;
}

View 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;
}

View 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,

View 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);

View 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)

View 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;