>From a5c007ba5f4ae7635746685c0209f7bfd3bc9b7f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 26 Feb 2016 14:53:12 -0800 Subject: [PATCH 1/5] VFS: Modify opendir to take a const struct smb_filename * instead of const char * Preparing to reduce use of lp_posix_pathnames(). Uses the same techniques as commit 616d068f0cebb8e50a855b6e30f36fccb7f5a3c8 (synthetic_smb_fname()) to cope with modules that modify the incoming pathname. Signed-off-by: Jeremy Allison --- examples/VFS/skel_opaque.c | 6 ++++-- examples/VFS/skel_transparent.c | 8 +++++--- source3/include/vfs.h | 12 ++++++++--- source3/include/vfs_macros.h | 8 ++++---- source3/modules/vfs_audit.c | 9 ++++++--- source3/modules/vfs_cap.c | 19 +++++++++++++++--- source3/modules/vfs_catia.c | 27 +++++++++++++++++++------ source3/modules/vfs_default.c | 7 +++++-- source3/modules/vfs_dirsort.c | 9 +++++---- source3/modules/vfs_extd_audit.c | 11 ++++++---- source3/modules/vfs_full_audit.c | 9 ++++++--- source3/modules/vfs_media_harmony.c | 24 ++++++++++++++++------ source3/modules/vfs_netatalk.c | 7 +++++-- source3/modules/vfs_shadow_copy.c | 25 +++++++++++++++++++---- source3/modules/vfs_shadow_copy2.c | 40 +++++++++++++++++++++++++++++-------- source3/modules/vfs_snapper.c | 25 ++++++++++++++++++----- source3/modules/vfs_streams_depot.c | 14 ++++++++++++- source3/modules/vfs_time_audit.c | 6 +++--- source3/modules/vfs_unityed_media.c | 23 +++++++++++++++------ source3/smbd/dir.c | 17 ++++++++++++++-- source3/smbd/msdfs.c | 24 ++++++++++++++++++++-- source3/smbd/vfs.c | 7 ++++--- source3/torture/cmd_vfs.c | 28 ++++++++++++++++++++++++-- 23 files changed, 284 insertions(+), 81 deletions(-) diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index 8961627..ae165a6 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -97,8 +97,10 @@ static NTSTATUS skel_get_dfs_referrals(struct vfs_handle_struct *handle, return NT_STATUS_NOT_IMPLEMENTED; } -static DIR *skel_opendir(vfs_handle_struct *handle, const char *fname, - const char *mask, uint32_t attr) +static DIR *skel_opendir(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attr) { return NULL; } diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index ac82432..549d7d8 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -95,10 +95,12 @@ static NTSTATUS skel_get_dfs_referrals(struct vfs_handle_struct *handle, return SMB_VFS_NEXT_GET_DFS_REFERRALS(handle, r); } -static DIR *skel_opendir(vfs_handle_struct *handle, const char *fname, - const char *mask, uint32_t attr) +static DIR *skel_opendir(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attr) { - return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); + return SMB_VFS_NEXT_OPENDIR(handle, smb_fname, mask, attr); } static NTSTATUS skel_snap_check_path(struct vfs_handle_struct *handle, diff --git a/source3/include/vfs.h b/source3/include/vfs.h index b291206..2f34c22 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -177,6 +177,8 @@ const struct smb_filename * */ /* Version 35 - Change rmdir from const char *, to const struct smb_filename * */ +/* Version 35 - Change opendir from const char *, to + const struct smb_filename * */ #define SMB_VFS_INTERFACE_VERSION 35 @@ -550,7 +552,10 @@ struct vfs_fn_pointers { /* Directory operations */ - DIR *(*opendir_fn)(struct vfs_handle_struct *handle, const char *fname, const char *mask, uint32_t attributes); + DIR *(*opendir_fn)(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attributes); DIR *(*fdopendir_fn)(struct vfs_handle_struct *handle, files_struct *fsp, const char *mask, uint32_t attributes); struct dirent *(*readdir_fn)(struct vfs_handle_struct *handle, DIR *dirp, @@ -963,8 +968,9 @@ uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle, NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle, struct dfs_GetDFSReferral *r); DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle, - const char *fname, const char *mask, - uint32_t attributes); + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attributes); DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *mask, diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index e50c6a6..2e8ca18 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -79,10 +79,10 @@ smb_vfs_call_get_dfs_referrals((handle)->next, (r)) /* Directory operations */ -#define SMB_VFS_OPENDIR(conn, fname, mask, attr) \ - smb_vfs_call_opendir((conn)->vfs_handles, (fname), (mask), (attr)) -#define SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr) \ - smb_vfs_call_opendir((handle)->next, (fname), (mask), (attr)) +#define SMB_VFS_OPENDIR(conn, smb_fname, mask, attr) \ + smb_vfs_call_opendir((conn)->vfs_handles, (smb_fname), (mask), (attr)) +#define SMB_VFS_NEXT_OPENDIR(handle, smb_fname, mask, attr) \ + smb_vfs_call_opendir((handle)->next, (smb_fname), (mask), (attr)) #define SMB_VFS_FDOPENDIR(fsp, mask, attr) \ smb_vfs_call_fdopendir((fsp)->conn->vfs_handles, (fsp), (mask), (attr)) diff --git a/source3/modules/vfs_audit.c b/source3/modules/vfs_audit.c index e16355a..fa47b3c 100644 --- a/source3/modules/vfs_audit.c +++ b/source3/modules/vfs_audit.c @@ -106,14 +106,17 @@ static void audit_disconnect(vfs_handle_struct *handle) return; } -static DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32_t attr) +static DIR *audit_opendir(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attr) { DIR *result; - result = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); + result = SMB_VFS_NEXT_OPENDIR(handle, smb_fname, mask, attr); syslog(audit_syslog_priority(handle), "opendir %s %s%s\n", - fname, + smb_fname->base_name, (result == NULL) ? "failed: " : "", (result == NULL) ? strerror(errno) : ""); diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c index fb97412..f96455c 100644 --- a/source3/modules/vfs_cap.c +++ b/source3/modules/vfs_cap.c @@ -54,15 +54,28 @@ static int cap_get_quota(vfs_handle_struct *handle, const char *path, return SMB_VFS_NEXT_GET_QUOTA(handle, cappath, qtype, id, dq); } -static DIR *cap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32_t attr) +static DIR *cap_opendir(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attr) { - char *capname = capencode(talloc_tos(), fname); + char *capname = capencode(talloc_tos(), smb_fname->base_name); + struct smb_filename *cap_smb_fname = NULL; if (!capname) { errno = ENOMEM; return NULL; } - return SMB_VFS_NEXT_OPENDIR(handle, capname, mask, attr); + cap_smb_fname = synthetic_smb_fname(talloc_tos(), + capname, + NULL, + NULL); + if (cap_smb_fname == NULL) { + TALLOC_FREE(capname); + errno = ENOMEM; + return NULL; + } + return SMB_VFS_NEXT_OPENDIR(handle, cap_smb_fname, mask, attr); } static struct dirent *cap_readdir(vfs_handle_struct *handle, diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c index f65ed4c..9f42e5f 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/modules/vfs_catia.c @@ -269,23 +269,38 @@ static NTSTATUS catia_string_replace_allocate(connection_struct *conn, } static DIR *catia_opendir(vfs_handle_struct *handle, - const char *fname, - const char *mask, - uint32_t attr) + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attr) { char *name_mapped = NULL; NTSTATUS status; DIR *ret; + struct smb_filename *mapped_smb_fname = NULL; - status = catia_string_replace_allocate(handle->conn, fname, - &name_mapped, vfs_translate_to_unix); + status = catia_string_replace_allocate(handle->conn, + smb_fname->base_name, + &name_mapped, + vfs_translate_to_unix); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); return NULL; } - ret = SMB_VFS_NEXT_OPENDIR(handle, name_mapped, mask, attr); + mapped_smb_fname = synthetic_smb_fname(talloc_tos(), + name_mapped, + NULL, + NULL); + if (mapped_smb_fname == NULL) { + TALLOC_FREE(mapped_smb_fname); + errno = ENOMEM; + return NULL; + } + + ret = SMB_VFS_NEXT_OPENDIR(handle, mapped_smb_fname, mask, attr); + TALLOC_FREE(name_mapped); + TALLOC_FREE(mapped_smb_fname); return ret; } diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index b13b517..c96bd0d 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -375,12 +375,15 @@ static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle, /* Directory operations */ -static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32_t attr) +static DIR *vfswrap_opendir(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attr) { DIR *result; START_PROFILE(syscall_opendir); - result = opendir(fname); + result = opendir(smb_fname->base_name); END_PROFILE(syscall_opendir); return result; } diff --git a/source3/modules/vfs_dirsort.c b/source3/modules/vfs_dirsort.c index d164088..f856835 100644 --- a/source3/modules/vfs_dirsort.c +++ b/source3/modules/vfs_dirsort.c @@ -113,8 +113,9 @@ static bool open_and_sort_dir(vfs_handle_struct *handle, } static DIR *dirsort_opendir(vfs_handle_struct *handle, - const char *fname, const char *mask, - uint32_t attr) + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attr) { struct dirsort_privates *list_head = NULL; struct dirsort_privates *data = NULL; @@ -131,14 +132,14 @@ static DIR *dirsort_opendir(vfs_handle_struct *handle, return NULL; } - data->smb_fname = synthetic_smb_fname(data, fname, NULL, NULL); + data->smb_fname = cp_smb_filename(data, smb_fname); if (data->smb_fname == NULL) { TALLOC_FREE(data); return NULL; } /* Open the underlying directory and count the number of entries */ - data->source_directory = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, + data->source_directory = SMB_VFS_NEXT_OPENDIR(handle, smb_fname, mask, attr); if (data->source_directory == NULL) { diff --git a/source3/modules/vfs_extd_audit.c b/source3/modules/vfs_extd_audit.c index 6429370..137bf72 100644 --- a/source3/modules/vfs_extd_audit.c +++ b/source3/modules/vfs_extd_audit.c @@ -116,20 +116,23 @@ static void audit_disconnect(vfs_handle_struct *handle) return; } -static DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32_t attr) +static DIR *audit_opendir(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attr) { DIR *result; - result = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); + result = SMB_VFS_NEXT_OPENDIR(handle, smb_fname, mask, attr); if (lp_syslog() > 0) { syslog(audit_syslog_priority(handle), "opendir %s %s%s\n", - fname, + smb_fname->base_name, (result == NULL) ? "failed: " : "", (result == NULL) ? strerror(errno) : ""); } DEBUG(1, ("vfs_extd_audit: opendir %s %s %s\n", - fname, + smb_fname->base_name, (result == NULL) ? "failed: " : "", (result == NULL) ? strerror(errno) : "")); diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index 3dd2005..311c760 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -776,13 +776,16 @@ static NTSTATUS smb_full_audit_snap_delete(struct vfs_handle_struct *handle, } static DIR *smb_full_audit_opendir(vfs_handle_struct *handle, - const char *fname, const char *mask, uint32_t attr) + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attr) { DIR *result; - result = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); + result = SMB_VFS_NEXT_OPENDIR(handle, smb_fname, mask, attr); - do_log(SMB_VFS_OP_OPENDIR, (result != NULL), handle, "%s", fname); + do_log(SMB_VFS_OP_OPENDIR, (result != NULL), handle, "%s", + smb_fname->base_name); return result; } diff --git a/source3/modules/vfs_media_harmony.c b/source3/modules/vfs_media_harmony.c index b5173af..786cee9 100644 --- a/source3/modules/vfs_media_harmony.c +++ b/source3/modules/vfs_media_harmony.c @@ -760,15 +760,16 @@ err: * Failure: set errno, return NULL */ static DIR *mh_opendir(vfs_handle_struct *handle, - const char *fname, + const struct smb_filename *smb_fname, const char *mask, uint32_t attr) { struct mh_dirinfo_struct *dirInfo; - DEBUG(MH_INFO_DEBUG, ("Entering with fname '%s'\n", fname)); + DEBUG(MH_INFO_DEBUG, ("Entering with fname '%s'\n", + smb_fname->base_name)); - if (alloc_set_client_dirinfo(handle, fname, &dirInfo)) + if (alloc_set_client_dirinfo(handle, smb_fname->base_name, &dirInfo)) { goto err; } @@ -776,10 +777,20 @@ static DIR *mh_opendir(vfs_handle_struct *handle, if (!dirInfo->isInMediaFiles) { dirInfo->dirstream = SMB_VFS_NEXT_OPENDIR(handle, - fname, mask, attr); + smb_fname, mask, attr); } else { + struct smb_filename *smb_fname_clientpath = + synthetic_smb_fname(talloc_tos(), + dirInfo->clientPath, + NULL, + NULL); + if (smb_fname_clientpath == NULL) { + goto err; + } + dirInfo->dirstream = SMB_VFS_NEXT_OPENDIR(handle, - dirInfo->clientPath, mask, attr); + smb_fname_clientpath, mask, attr); + TALLOC_FREE(smb_fname_clientpath); } if (dirInfo->dirstream == NULL) { @@ -794,7 +805,8 @@ static DIR *mh_opendir(vfs_handle_struct *handle, return (DIR*)dirInfo; err: /* Failure is freed here. */ - DEBUG(MH_ERR_DEBUG, ("Failing with fname '%s'\n", fname)); + DEBUG(MH_ERR_DEBUG, ("Failing with fname '%s'\n", + smb_fname->base_name)); TALLOC_FREE(dirInfo); return NULL; } diff --git a/source3/modules/vfs_netatalk.c b/source3/modules/vfs_netatalk.c index 487ab50..d8f9f34 100644 --- a/source3/modules/vfs_netatalk.c +++ b/source3/modules/vfs_netatalk.c @@ -177,11 +177,14 @@ static void atalk_rrmdir(TALLOC_CTX *ctx, char *path) /* Directory operations */ -static DIR *atalk_opendir(struct vfs_handle_struct *handle, const char *fname, const char *mask, uint32_t attr) +static DIR *atalk_opendir(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attr) { DIR *ret = 0; - ret = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); + ret = SMB_VFS_NEXT_OPENDIR(handle, smb_fname, mask, attr); /* * when we try to perform delete operation upon file which has fork diff --git a/source3/modules/vfs_shadow_copy.c b/source3/modules/vfs_shadow_copy.c index 5c05e25..77dc163 100644 --- a/source3/modules/vfs_shadow_copy.c +++ b/source3/modules/vfs_shadow_copy.c @@ -73,13 +73,18 @@ static bool shadow_copy_match_name(const char *name) return False; } -static DIR *shadow_copy_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32_t attr) +static DIR *shadow_copy_opendir(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attr) { shadow_copy_Dir *dirp; - DIR *p = SMB_VFS_NEXT_OPENDIR(handle,fname,mask,attr); + DIR *p = SMB_VFS_NEXT_OPENDIR(handle,smb_fname,mask,attr); if (!p) { - DEBUG(0,("shadow_copy_opendir: SMB_VFS_NEXT_OPENDIR() failed for [%s]\n",fname)); + DEBUG(0,("shadow_copy_opendir: SMB_VFS_NEXT_OPENDIR() " + "failed for [%s]\n", + smb_fname->base_name)); return NULL; } @@ -221,7 +226,19 @@ static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, struct shadow_copy_data *shadow_copy_data, bool labels) { - DIR *p = SMB_VFS_NEXT_OPENDIR(handle,fsp->conn->connectpath,NULL,0); + DIR *p = NULL; + struct smb_filename *smb_fname = synthetic_smb_fname(talloc_tos(), + fsp->conn->connectpath, + NULL, + NULL); + if (smb_fname == NULL) { + errno = ENOMEM; + return -1; + } + + p = SMB_VFS_NEXT_OPENDIR(handle,smb_fname,NULL,0); + + TALLOC_FREE(smb_fname); shadow_copy_data->num_volumes = 0; shadow_copy_data->labels = NULL; diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index 7817168..27fc8a9 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -690,31 +690,44 @@ static void convert_sbuf(vfs_handle_struct *handle, const char *fname, } static DIR *shadow_copy2_opendir(vfs_handle_struct *handle, - const char *fname, - const char *mask, - uint32_t attr) + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attr) { time_t timestamp; char *stripped; DIR *ret; int saved_errno; char *conv; + struct smb_filename *conv_smb_fname = NULL; - if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, - ×tamp, &stripped)) { + if (!shadow_copy2_strip_snapshot(talloc_tos(), + handle, + smb_fname->base_name, + ×tamp, + &stripped)) { return NULL; } if (timestamp == 0) { - return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); + return SMB_VFS_NEXT_OPENDIR(handle, smb_fname, mask, attr); } conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); TALLOC_FREE(stripped); if (conv == NULL) { return NULL; } - ret = SMB_VFS_NEXT_OPENDIR(handle, conv, mask, attr); + conv_smb_fname = synthetic_smb_fname(talloc_tos(), + conv, + NULL, + NULL); + if (conv_smb_fname == NULL) { + TALLOC_FREE(conv); + return NULL; + } + ret = SMB_VFS_NEXT_OPENDIR(handle, conv_smb_fname, mask, attr); saved_errno = errno; TALLOC_FREE(conv); + TALLOC_FREE(conv_smb_fname); errno = saved_errno; return ret; } @@ -1372,6 +1385,7 @@ static int shadow_copy2_get_shadow_copy_data( { DIR *p; const char *snapdir; + struct smb_filename *snapdir_smb_fname = NULL; struct dirent *d; TALLOC_CTX *tmp_ctx = talloc_stackframe(); bool ret; @@ -1392,7 +1406,17 @@ static int shadow_copy2_get_shadow_copy_data( return -1; } - p = SMB_VFS_NEXT_OPENDIR(handle, snapdir, NULL, 0); + snapdir_smb_fname = synthetic_smb_fname(talloc_tos(), + snapdir, + NULL, + NULL); + if (snapdir_smb_fname == NULL) { + errno = ENOMEM; + talloc_free(tmp_ctx); + return -1; + } + + p = SMB_VFS_NEXT_OPENDIR(handle, snapdir_smb_fname, NULL, 0); if (!p) { DEBUG(2,("shadow_copy2: SMB_VFS_NEXT_OPENDIR() failed for '%s'" diff --git a/source3/modules/vfs_snapper.c b/source3/modules/vfs_snapper.c index 80396c4..5f5e296 100644 --- a/source3/modules/vfs_snapper.c +++ b/source3/modules/vfs_snapper.c @@ -1943,7 +1943,7 @@ err_out: } static DIR *snapper_gmt_opendir(vfs_handle_struct *handle, - const char *fname, + const struct smb_filename *smb_fname, const char *mask, uint32_t attr) { @@ -1952,22 +1952,37 @@ static DIR *snapper_gmt_opendir(vfs_handle_struct *handle, DIR *ret; int saved_errno; char *conv; + struct smb_filename *conv_smb_fname = NULL; - if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, fname, - ×tamp, &stripped)) { + if (!snapper_gmt_strip_snapshot(talloc_tos(), + handle, + smb_fname->base_name, + ×tamp, + &stripped)) { return NULL; } if (timestamp == 0) { - return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); + return SMB_VFS_NEXT_OPENDIR(handle, smb_fname, mask, attr); } conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp); TALLOC_FREE(stripped); if (conv == NULL) { return NULL; } - ret = SMB_VFS_NEXT_OPENDIR(handle, conv, mask, attr); + conv_smb_fname = synthetic_smb_fname(talloc_tos(), + conv, + NULL, + NULL); + if (conv_smb_fname == NULL) { + TALLOC_FREE(conv); + errno = ENOMEM; + return NULL; + } + + ret = SMB_VFS_NEXT_OPENDIR(handle, conv_smb_fname, mask, attr); saved_errno = errno; TALLOC_FREE(conv); + TALLOC_FREE(conv_smb_fname); errno = saved_errno; return ret; } diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c index f6226e7..d998dc5 100644 --- a/source3/modules/vfs_streams_depot.c +++ b/source3/modules/vfs_streams_depot.c @@ -420,6 +420,7 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle, void *private_data) { char *dirname; + struct smb_filename *dir_smb_fname = NULL; DIR *dirhandle = NULL; const char *dirent = NULL; char *talloced = NULL; @@ -439,7 +440,18 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle, DEBUG(10, ("walk_streams: dirname=%s\n", dirname)); - dirhandle = SMB_VFS_NEXT_OPENDIR(handle, dirname, NULL, 0); + dir_smb_fname = synthetic_smb_fname(talloc_tos(), + dirname, + NULL, + NULL); + if (dir_smb_fname == NULL) { + TALLOC_FREE(dirname); + return NT_STATUS_NO_MEMORY; + } + + dirhandle = SMB_VFS_NEXT_OPENDIR(handle, dir_smb_fname, NULL, 0); + + TALLOC_FREE(dir_smb_fname); if (dirhandle == NULL) { TALLOC_FREE(dirname); diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c index 11866fa..7998bac 100644 --- a/source3/modules/vfs_time_audit.c +++ b/source3/modules/vfs_time_audit.c @@ -347,7 +347,7 @@ static NTSTATUS smb_time_audit_snap_delete(struct vfs_handle_struct *handle, } static DIR *smb_time_audit_opendir(vfs_handle_struct *handle, - const char *fname, + const struct smb_filename *smb_fname, const char *mask, uint32_t attr) { DIR *result; @@ -355,12 +355,12 @@ static DIR *smb_time_audit_opendir(vfs_handle_struct *handle, double timediff; clock_gettime_mono(&ts1); - result = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); + result = SMB_VFS_NEXT_OPENDIR(handle, smb_fname, mask, attr); clock_gettime_mono(&ts2); timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9; if (timediff > audit_timeout) { - smb_time_audit_log_fname("opendir", timediff, fname); + smb_time_audit_log_smb_fname("opendir", timediff, smb_fname); } return result; diff --git a/source3/modules/vfs_unityed_media.c b/source3/modules/vfs_unityed_media.c index 2e581e3..191d39f 100644 --- a/source3/modules/vfs_unityed_media.c +++ b/source3/modules/vfs_unityed_media.c @@ -551,24 +551,35 @@ err: * Failure: set errno, return NULL */ static DIR *um_opendir(vfs_handle_struct *handle, - const char *fname, + const struct smb_filename *smb_fname, const char *mask, uint32_t attr) { struct um_dirinfo_struct *dirInfo; - DEBUG(10, ("Entering with fname '%s'\n", fname)); + DEBUG(10, ("Entering with fname '%s'\n", smb_fname->base_name)); - if (alloc_set_client_dirinfo(handle, fname, &dirInfo)) { + if (alloc_set_client_dirinfo(handle, smb_fname->base_name, &dirInfo)) { goto err; } if (!dirInfo->isInMediaFiles) { dirInfo->dirstream = SMB_VFS_NEXT_OPENDIR( - handle, fname, mask, attr); + handle, smb_fname, mask, attr); } else { + struct smb_filename *client_smb_fname = + synthetic_smb_fname(talloc_tos(), + dirInfo->clientPath, + NULL, + NULL); + if (client_smb_fname == NULL) { + goto err; + } + dirInfo->dirstream = SMB_VFS_NEXT_OPENDIR( - handle, dirInfo->clientPath, mask, attr); + handle, client_smb_fname, mask, attr); + + TALLOC_FREE(client_smb_fname); } if (dirInfo->dirstream == NULL) { @@ -582,7 +593,7 @@ static DIR *um_opendir(vfs_handle_struct *handle, return (DIR*)dirInfo; err: - DEBUG(1, ("Failing with fname '%s'\n", fname)); + DEBUG(1, ("Failing with fname '%s'\n", smb_fname->base_name)); TALLOC_FREE(dirInfo); return NULL; } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index a586edf..bdd79ca 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1595,6 +1595,7 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, { struct smb_Dir *dirp = talloc_zero(mem_ctx, struct smb_Dir); struct smbd_server_connection *sconn = conn->sconn; + struct smb_filename *smb_fname = NULL; if (!dirp) { return NULL; @@ -1614,7 +1615,19 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, } talloc_set_destructor(dirp, smb_Dir_destructor); - dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr); + smb_fname = synthetic_smb_fname(talloc_tos(), + dirp->dir_path, + NULL, + NULL); + if (smb_fname == NULL) { + errno = ENOMEM; + goto fail; + } + + dirp->dir = SMB_VFS_OPENDIR(conn, smb_fname, mask, attr); + + TALLOC_FREE(smb_fname); + if (!dirp->dir) { DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) )); @@ -1675,7 +1688,7 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn, if (dirp->dir == NULL) { /* FDOPENDIR didn't work. Use OPENDIR instead. */ - dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr); + dirp->dir = SMB_VFS_OPENDIR(conn, fsp->fsp_name, mask, attr); } if (!dirp->dir) { diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index e895c1f..fe95877 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1385,6 +1385,7 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) connection_struct *conn; NTSTATUS status; char *cwd; + struct smb_filename *smb_fname = NULL; if(*connect_path == '\0') { return 0; @@ -1413,8 +1414,16 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) goto out; } + smb_fname = synthetic_smb_fname(talloc_tos(), + ".", + NULL, + NULL); + if (smb_fname == NULL) { + goto out; + } + /* Now enumerate all dfs links */ - dirp = SMB_VFS_OPENDIR(conn, ".", NULL, 0); + dirp = SMB_VFS_OPENDIR(conn, smb_fname, NULL, 0); if(!dirp) { goto out; } @@ -1432,6 +1441,7 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) SMB_VFS_CLOSEDIR(conn,dirp); out: + TALLOC_FREE(smb_fname); vfs_ChDir(conn, cwd); SMB_VFS_DISCONNECT(conn); conn_free(conn); @@ -1456,6 +1466,7 @@ static int form_junctions(TALLOC_CTX *ctx, connection_struct *conn; struct referral *ref = NULL; char *cwd; + struct smb_filename *smb_fname = NULL; NTSTATUS status; if (jn_remain == 0) { @@ -1520,8 +1531,16 @@ static int form_junctions(TALLOC_CTX *ctx, goto out; } + smb_fname = synthetic_smb_fname(talloc_tos(), + ".", + NULL, + NULL); + if (smb_fname == NULL) { + goto out; + } + /* Now enumerate all dfs links */ - dirp = SMB_VFS_OPENDIR(conn, ".", NULL, 0); + dirp = SMB_VFS_OPENDIR(conn, smb_fname, NULL, 0); if(!dirp) { goto out; } @@ -1567,6 +1586,7 @@ out: SMB_VFS_CLOSEDIR(conn,dirp); } + TALLOC_FREE(smb_fname); vfs_ChDir(conn, cwd); conn_free(conn); return cnt; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index dfc22be..d29586b 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1452,11 +1452,12 @@ NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle, } DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle, - const char *fname, const char *mask, - uint32_t attributes) + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attributes) { VFS_FIND(opendir); - return handle->fns->opendir_fn(handle, fname, mask, attributes); + return handle->fns->opendir_fn(handle, smb_fname, mask, attributes); } DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle, diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c index 6dcf805..0bc6dbc 100644 --- a/source3/torture/cmd_vfs.c +++ b/source3/torture/cmd_vfs.c @@ -129,17 +129,29 @@ static NTSTATUS cmd_disk_free(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int ar static NTSTATUS cmd_opendir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { + struct smb_filename *smb_fname = NULL; + if (argc != 2) { printf("Usage: opendir \n"); return NT_STATUS_OK; } - vfs->currentdir = SMB_VFS_OPENDIR(vfs->conn, argv[1], NULL, 0); + smb_fname = synthetic_smb_fname(talloc_tos(), + argv[1], + NULL, + NULL); + if (smb_fname == NULL) { + return NT_STATUS_NO_MEMORY; + } + + vfs->currentdir = SMB_VFS_OPENDIR(vfs->conn, smb_fname, NULL, 0); if (vfs->currentdir == NULL) { printf("opendir error=%d (%s)\n", errno, strerror(errno)); + TALLOC_FREE(smb_fname); return NT_STATUS_UNSUCCESSFUL; } + TALLOC_FREE(smb_fname); printf("opendir: ok\n"); return NT_STATUS_OK; } @@ -1729,6 +1741,7 @@ static NTSTATUS cmd_translate_name(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, SMB_STRUCT_STAT st; bool found = false; char *translated = NULL; + struct smb_filename *smb_fname = NULL; NTSTATUS status; if (argc != 2) { @@ -1736,10 +1749,19 @@ static NTSTATUS cmd_translate_name(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, return NT_STATUS_UNSUCCESSFUL; } - vfs->currentdir = SMB_VFS_OPENDIR(vfs->conn, ".", NULL, 0); + smb_fname = synthetic_smb_fname(talloc_tos(), + ".", + NULL, + NULL); + if (smb_fname == NULL) { + return NT_STATUS_NO_MEMORY; + } + + vfs->currentdir = SMB_VFS_OPENDIR(vfs->conn, smb_fname, NULL, 0); if (vfs->currentdir == NULL) { DEBUG(0, ("cmd_translate_name: opendir error=%d (%s)\n", errno, strerror(errno))); + TALLOC_FREE(smb_fname); return NT_STATUS_UNSUCCESSFUL; } @@ -1775,9 +1797,11 @@ static NTSTATUS cmd_translate_name(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, DEBUG(0, ("cmd_translate_name: file '%s' --> '%s'\n", argv[1], translated)); + TALLOC_FREE(smb_fname); TALLOC_FREE(translated); cleanup: + TALLOC_FREE(smb_fname); ret = SMB_VFS_CLOSEDIR(vfs->conn, vfs->currentdir); if (ret == -1) { DEBUG(0, ("cmd_translate_name: closedir failure: %s\n", -- 2.5.0 >From 5b85f6309a833cce71716341d6a43f392dd9b4ce Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 26 Feb 2016 14:59:51 -0800 Subject: [PATCH 2/5] s3: smbd: Change the internals of the private struct smb_Dir. Store a struct smb_filename *, not a char *. This will allow us to change the interface to OpenDir() in the next commit to pass in a struct smb_filename *, not a char *. Signed-off-by: Jeremy Allison --- source3/smbd/dir.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index bdd79ca..527bd78 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -52,7 +52,7 @@ struct smb_Dir { connection_struct *conn; DIR *dir; long offset; - char *dir_path; + struct smb_filename *dir_smb_fname; size_t name_cache_size; struct name_cache_entry *name_cache; unsigned int name_cache_index; @@ -1595,7 +1595,6 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, { struct smb_Dir *dirp = talloc_zero(mem_ctx, struct smb_Dir); struct smbd_server_connection *sconn = conn->sconn; - struct smb_filename *smb_fname = NULL; if (!dirp) { return NULL; @@ -1604,8 +1603,11 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, dirp->conn = conn; dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn)); - dirp->dir_path = talloc_strdup(dirp, name); - if (!dirp->dir_path) { + dirp->dir_smb_fname = synthetic_smb_fname(dirp, + name, + NULL, + NULL); + if (!dirp->dir_smb_fname) { errno = ENOMEM; goto fail; } @@ -1615,22 +1617,12 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, } talloc_set_destructor(dirp, smb_Dir_destructor); - smb_fname = synthetic_smb_fname(talloc_tos(), - dirp->dir_path, - NULL, - NULL); - if (smb_fname == NULL) { - errno = ENOMEM; - goto fail; - } - - dirp->dir = SMB_VFS_OPENDIR(conn, smb_fname, mask, attr); - - TALLOC_FREE(smb_fname); + dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_smb_fname, mask, attr); if (!dirp->dir) { - DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, - strerror(errno) )); + DEBUG(5,("OpenDir: Can't open %s. %s\n", + dirp->dir_smb_fname->base_name, + strerror(errno) )); goto fail; } @@ -1660,8 +1652,8 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn, dirp->conn = conn; dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn)); - dirp->dir_path = talloc_strdup(dirp, fsp->fsp_name->base_name); - if (!dirp->dir_path) { + dirp->dir_smb_fname = cp_smb_filename(dirp, fsp->fsp_name); + if (!dirp->dir_smb_fname) { errno = ENOMEM; goto fail; } @@ -1678,7 +1670,7 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn, } else { DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned " "NULL (%s)\n", - dirp->dir_path, + dirp->dir_smb_fname->base_name, strerror(errno))); if (errno != ENOSYS) { return NULL; @@ -1688,12 +1680,16 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn, if (dirp->dir == NULL) { /* FDOPENDIR didn't work. Use OPENDIR instead. */ - dirp->dir = SMB_VFS_OPENDIR(conn, fsp->fsp_name, mask, attr); + dirp->dir = SMB_VFS_OPENDIR(conn, + dirp->dir_smb_fname, + mask, + attr); } if (!dirp->dir) { - DEBUG(5,("OpenDir_fsp: Can't open %s. %s\n", dirp->dir_path, - strerror(errno) )); + DEBUG(5,("OpenDir_fsp: Can't open %s. %s\n", + dirp->dir_smb_fname->base_name, + strerror(errno) )); goto fail; } -- 2.5.0 >From ff89fd646b0f2b82b94dbbf2b115ff05b94460dc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 26 Feb 2016 15:55:14 -0800 Subject: [PATCH 3/5] s3: smbd: Change OpenDir() to take a struct smb_filename *, not a char *. Enhances plumbing to remove lp_posix_pathnames() later. Signed-off-by: Jeremy Allison --- source3/smbd/close.c | 4 ++-- source3/smbd/dir.c | 36 +++++++++++++++++++++++++----------- source3/smbd/filename.c | 15 ++++++++++++++- source3/smbd/proto.h | 7 +++++-- source3/smbd/reply.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 86 insertions(+), 19 deletions(-) diff --git a/source3/smbd/close.c b/source3/smbd/close.c index cf11ae5..f3d6620 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -800,7 +800,7 @@ bool recursive_rmdir(TALLOC_CTX *ctx, SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname)); - dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0); + dir_hnd = OpenDir(talloc_tos(), conn, smb_dname, NULL, 0); if(dir_hnd == NULL) return False; @@ -916,7 +916,7 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp) char *talloced = NULL; long dirpos = 0; struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, - smb_dname->base_name, NULL, + smb_dname, NULL, 0); if(dir_hnd == NULL) { diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 527bd78..b71234e 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -163,16 +163,33 @@ static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn, for(dptr = sconn->searches.dirptrs; dptr; dptr = dptr->next) { if(dptr->dnum == key) { if (!forclose && !dptr->dir_hnd) { + struct smb_filename *smb_dname = NULL; + if (sconn->searches.dirhandles_open >= MAX_OPEN_DIRECTORIES) dptr_idleoldest(sconn); DEBUG(4,("dptr_get: Reopening dptr key %d\n",key)); - if (!(dptr->dir_hnd = OpenDir( - NULL, dptr->conn, dptr->path, - dptr->wcard, dptr->attr))) { - DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path, + + smb_dname = synthetic_smb_fname(talloc_tos(), + dptr->path, + NULL, + NULL); + if (smb_dname == NULL) { + return NULL; + } + + if (!(dptr->dir_hnd = OpenDir(NULL, + dptr->conn, + smb_dname, + dptr->wcard, + dptr->attr))) { + DEBUG(4,("dptr_get: Failed to " + "open %s (%s)\n", + dptr->path, strerror(errno))); + TALLOC_FREE(smb_dname); return NULL; } + TALLOC_FREE(smb_dname); } DLIST_PROMOTE(sconn->searches.dirptrs,dptr); return dptr; @@ -424,7 +441,7 @@ static struct smb_Dir *open_dir_with_privilege(connection_struct *conn, goto out; } - dir_hnd = OpenDir(NULL, conn, ".", wcard, attr); + dir_hnd = OpenDir(NULL, conn, smb_fname_cwd, wcard, attr); out: @@ -510,7 +527,7 @@ NTSTATUS dptr_create(connection_struct *conn, wcard, attr); } else { - dir_hnd = OpenDir(NULL, conn, path, wcard, attr); + dir_hnd = OpenDir(NULL, conn, smb_dname, wcard, attr); } } @@ -1589,7 +1606,7 @@ static int smb_Dir_destructor(struct smb_Dir *dirp) ********************************************************************/ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, - const char *name, + const struct smb_filename *smb_dname, const char *mask, uint32_t attr) { @@ -1603,10 +1620,7 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, dirp->conn = conn; dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn)); - dirp->dir_smb_fname = synthetic_smb_fname(dirp, - name, - NULL, - NULL); + dirp->dir_smb_fname = cp_smb_filename(dirp, smb_dname); if (!dirp->dir_smb_fname) { errno = ENOMEM; goto fail; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index f2c9184..86f6686 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -1156,6 +1156,7 @@ static int get_real_filename_full_scan(connection_struct *conn, char *talloced = NULL; char *unmangled_name = NULL; long curpos; + struct smb_filename *smb_fname = NULL; /* handle null paths */ if ((path == NULL) || (*path == 0)) { @@ -1196,13 +1197,25 @@ static int get_real_filename_full_scan(connection_struct *conn, } } + smb_fname = synthetic_smb_fname(talloc_tos(), + path, + NULL, + NULL); + if (smb_fname == NULL) { + TALLOC_FREE(unmangled_name); + return -1; + } + /* open the directory */ - if (!(cur_dir = OpenDir(talloc_tos(), conn, path, NULL, 0))) { + if (!(cur_dir = OpenDir(talloc_tos(), conn, smb_fname, NULL, 0))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); TALLOC_FREE(unmangled_name); + TALLOC_FREE(smb_fname); return -1; } + TALLOC_FREE(smb_fname); + /* now scan for matching names */ curpos = 0; while ((dname = ReadDirName(cur_dir, &curpos, NULL, &talloced))) { diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index fe099ae..3f9ddb5 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -221,8 +221,11 @@ bool get_dir_entry(TALLOC_CTX *ctx, bool check_descend, bool ask_sharemode); bool is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, bool use_veto); -struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, - const char *name, const char *mask, uint32_t attr); +struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, + connection_struct *conn, + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attr); const char *ReadDirName(struct smb_Dir *dirp, long *poffset, SMB_STRUCT_STAT *sbuf, char **talloced); void RewindDir(struct smb_Dir *dirp, long *poffset); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 77d5b6e..6763218 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2977,6 +2977,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, char *fname_mask = NULL; int count=0; NTSTATUS status = NT_STATUS_OK; + struct smb_filename *smb_fname_dir = NULL; TALLOC_CTX *ctx = talloc_tos(); /* Split up the directory from the filename/mask. */ @@ -3071,7 +3072,16 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, goto out; } - dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask, + smb_fname_dir = synthetic_smb_fname(talloc_tos(), + fname_dir, + NULL, + NULL); + if (smb_fname_dir == NULL) { + status = NT_STATUS_NO_MEMORY; + goto out; + } + + dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask, dirtype); if (dir_hnd == NULL) { status = map_nt_error_from_unix(errno); @@ -3161,6 +3171,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, } out: + TALLOC_FREE(smb_fname_dir); TALLOC_FREE(fname_dir); TALLOC_FREE(fname_mask); return status; @@ -6847,6 +6858,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, uint32_t access_mask) { char *fname_src_dir = NULL; + struct smb_filename *smb_fname_src_dir = NULL; char *fname_src_mask = NULL; int count=0; NTSTATUS status = NT_STATUS_OK; @@ -7019,7 +7031,16 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, goto out; } - dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask, + smb_fname_src_dir = synthetic_smb_fname(talloc_tos(), + fname_src_dir, + NULL, + NULL); + if (smb_fname_src_dir == NULL) { + status = NT_STATUS_NO_MEMORY; + goto out; + } + + dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask, attrs); if (dir_hnd == NULL) { status = map_nt_error_from_unix(errno); @@ -7175,6 +7196,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, out: TALLOC_FREE(talloced); + TALLOC_FREE(smb_fname_src_dir); TALLOC_FREE(fname_src_dir); TALLOC_FREE(fname_src_mask); return status; @@ -7498,6 +7520,7 @@ void reply_copy(struct smb_request *req) { connection_struct *conn = req->conn; struct smb_filename *smb_fname_src = NULL; + struct smb_filename *smb_fname_src_dir = NULL; struct smb_filename *smb_fname_dst = NULL; char *fname_src = NULL; char *fname_dst = NULL; @@ -7723,7 +7746,20 @@ void reply_copy(struct smb_request *req) goto out; } - dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0); + smb_fname_src_dir = synthetic_smb_fname(talloc_tos(), + fname_src_dir, + NULL, + NULL); + if (smb_fname_src_dir == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + goto out; + } + + dir_hnd = OpenDir(ctx, + conn, + smb_fname_src_dir, + fname_src_mask, + 0); if (dir_hnd == NULL) { status = map_nt_error_from_unix(errno); reply_nterror(req, status); @@ -7833,6 +7869,7 @@ void reply_copy(struct smb_request *req) SSVAL(req->outbuf,smb_vwv0,count); out: TALLOC_FREE(smb_fname_src); + TALLOC_FREE(smb_fname_src_dir); TALLOC_FREE(smb_fname_dst); TALLOC_FREE(fname_src); TALLOC_FREE(fname_dst); -- 2.5.0 >From 7c7fc8bf60ad6536f3fab1e79914f440caa18ee4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 26 Feb 2016 16:31:10 -0800 Subject: [PATCH 4/5] s3: smbd: In call_trans2findfirst() all use of ctx is really talloc_tos(). Use talloc_tos() explicitly to make this clear. Will help make the next commit clearer. Signed-off-by: Jeremy Allison --- source3/smbd/trans2.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ab6e118..bc34add 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2491,7 +2491,6 @@ static void call_trans2findfirst(connection_struct *conn, struct ea_list *ea_list = NULL; NTSTATUS ntstatus = NT_STATUS_OK; bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); - TALLOC_CTX *ctx = talloc_tos(); struct dptr_struct *dirptr = NULL; struct smbd_server_connection *sconn = req->sconn; uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP | @@ -2554,7 +2553,7 @@ close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_da } if (req->posix_pathnames) { - srvstr_get_path_wcard_posix(ctx, + srvstr_get_path_wcard_posix(talloc_tos(), params, req->flags2, &directory, @@ -2564,7 +2563,7 @@ close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_da &ntstatus, &mask_contains_wcard); } else { - srvstr_get_path_wcard(ctx, + srvstr_get_path_wcard(talloc_tos(), params, req->flags2, &directory, @@ -2582,7 +2581,7 @@ close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_da if (backup_priv) { become_root(); as_root = true; - ntstatus = filename_convert_with_privilege(ctx, + ntstatus = filename_convert_with_privilege(talloc_tos(), conn, req, directory, @@ -2590,7 +2589,7 @@ close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_da &mask_contains_wcard, &smb_dname); } else { - ntstatus = filename_convert(ctx, conn, + ntstatus = filename_convert(talloc_tos(), conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory, ucf_flags, @@ -2616,7 +2615,7 @@ close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_da if(p == NULL) { /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */ if((directory[0] == '.') && (directory[1] == '\0')) { - mask = talloc_strdup(ctx,"*"); + mask = talloc_strdup(talloc_tos(),"*"); if (!mask) { reply_nterror(req, NT_STATUS_NO_MEMORY); goto out; @@ -2660,7 +2659,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } /* Pull out the list of names. */ - ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4); + ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4); if (!ea_list) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); goto out; @@ -2729,9 +2728,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd a different TRANS2 call. */ DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", - directory,lp_dont_descend(ctx, SNUM(conn)))); - if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive)) + directory,lp_dont_descend(talloc_tos(), SNUM(conn)))); + if (in_list(directory, + lp_dont_descend(talloc_tos(), SNUM(conn)), + conn->case_sensitive)) { dont_descend = True; + } p = pdata; space_remaining = max_data_bytes; @@ -2746,7 +2748,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd out_of_space = True; finished = False; } else { - ntstatus = get_lanman2_dir_entry(ctx, + ntstatus = get_lanman2_dir_entry(talloc_tos(), conn, dirptr, req->flags2, -- 2.5.0 >From 726ff0f2ab8a3538daab856c1950e846e7c8557b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 26 Feb 2016 16:35:17 -0800 Subject: [PATCH 5/5] s3: smbd: Change dptr_create() to take a const struct smb_filename * instead of const char *. Also internally change path storage inside struct dptr_struct to a struct smb_filename *. This allows me to remove several of the synthetic_smb_fname() calls I had to add in the previous patches, as we're now dealing with struct smb_filename * throughout the dptr and OpenDir code. Signed-off-by: Jeremy Allison --- source3/smbd/dir.c | 123 +++++++++++++++++++++--------------- source3/smbd/proto.h | 10 ++- source3/smbd/reply.c | 15 ++++- source3/smbd/smb2_query_directory.c | 2 +- source3/smbd/trans2.c | 4 +- 5 files changed, 97 insertions(+), 57 deletions(-) diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index b71234e..82841eb 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -70,7 +70,7 @@ struct dptr_struct { bool expect_close; char *wcard; uint32_t attr; - char *path; + struct smb_filename *smb_dname; bool has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */ bool did_stat; /* Optimisation for non-wcard searches. */ bool priv; /* Directory handle opened with privilege. */ @@ -163,33 +163,21 @@ static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn, for(dptr = sconn->searches.dirptrs; dptr; dptr = dptr->next) { if(dptr->dnum == key) { if (!forclose && !dptr->dir_hnd) { - struct smb_filename *smb_dname = NULL; - if (sconn->searches.dirhandles_open >= MAX_OPEN_DIRECTORIES) dptr_idleoldest(sconn); DEBUG(4,("dptr_get: Reopening dptr key %d\n",key)); - smb_dname = synthetic_smb_fname(talloc_tos(), - dptr->path, - NULL, - NULL); - if (smb_dname == NULL) { - return NULL; - } - if (!(dptr->dir_hnd = OpenDir(NULL, dptr->conn, - smb_dname, + dptr->smb_dname, dptr->wcard, dptr->attr))) { DEBUG(4,("dptr_get: Failed to " "open %s (%s)\n", - dptr->path, + dptr->smb_dname->base_name, strerror(errno))); - TALLOC_FREE(smb_dname); return NULL; } - TALLOC_FREE(smb_dname); } DLIST_PROMOTE(sconn->searches.dirptrs,dptr); return dptr; @@ -206,7 +194,7 @@ const char *dptr_path(struct smbd_server_connection *sconn, int key) { struct dptr_struct *dptr = dptr_get(sconn, key, false); if (dptr) - return(dptr->path); + return(dptr->smb_dname->base_name); return(NULL); } @@ -356,8 +344,10 @@ void dptr_closepath(struct smbd_server_connection *sconn, struct dptr_struct *dptr, *next; for(dptr = sconn->searches.dirptrs; dptr; dptr = next) { next = dptr->next; - if (spid == dptr->spid && strequal(dptr->path,path)) + if (spid == dptr->spid && + strequal(dptr->smb_dname->base_name,path)) { dptr_close_internal(dptr); + } } } @@ -404,7 +394,7 @@ static void dptr_close_oldest(struct smbd_server_connection *sconn, static struct smb_Dir *open_dir_with_privilege(connection_struct *conn, struct smb_request *req, - const char *path, + const struct smb_filename *smb_dname, const char *wcard, uint32_t attr) { @@ -418,7 +408,7 @@ static struct smb_Dir *open_dir_with_privilege(connection_struct *conn, return NULL; } - if (vfs_ChDir(conn, path) == -1) { + if (vfs_ChDir(conn, smb_dname->base_name) == -1) { return NULL; } @@ -436,7 +426,7 @@ static struct smb_Dir *open_dir_with_privilege(connection_struct *conn, if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) { DEBUG(0,("open_dir_with_privilege: stat mismatch between %s " "and %s\n", - path, + smb_dname->base_name, smb_fname_str_dbg(&priv_paths->parent_name))); goto out; } @@ -461,18 +451,24 @@ static struct smb_Dir *open_dir_with_privilege(connection_struct *conn, NTSTATUS dptr_create(connection_struct *conn, struct smb_request *req, files_struct *fsp, - const char *path, bool old_handle, bool expect_close,uint16_t spid, - const char *wcard, bool wcard_has_wild, uint32_t attr, struct dptr_struct **dptr_ret) + const struct smb_filename *smb_dname, + bool old_handle, + bool expect_close, + uint16_t spid, + const char *wcard, + bool wcard_has_wild, + uint32_t attr, + struct dptr_struct **dptr_ret) { struct smbd_server_connection *sconn = conn->sconn; struct dptr_struct *dptr = NULL; struct smb_Dir *dir_hnd; if (fsp && fsp->is_directory && fsp->fh->fd != -1) { - path = fsp->fsp_name->base_name; + smb_dname = fsp->fsp_name; } - DEBUG(5,("dptr_create dir=%s\n", path)); + DEBUG(5,("dptr_create dir=%s\n", smb_dname->base_name)); if (sconn == NULL) { DEBUG(0,("dptr_create: called with fake connection_struct\n")); @@ -487,48 +483,57 @@ NTSTATUS dptr_create(connection_struct *conn, if (!(fsp->access_mask & SEC_DIR_LIST)) { DEBUG(5,("dptr_create: directory %s " "not open for LIST access\n", - path)); + smb_dname->base_name)); return NT_STATUS_ACCESS_DENIED; } dir_hnd = OpenDir_fsp(NULL, conn, fsp, wcard, attr); } else { int ret; bool backup_intent = (req && req->priv_paths); - struct smb_filename *smb_dname; NTSTATUS status; + struct smb_filename *smb_dname_cp = + cp_smb_filename(talloc_tos(), smb_dname); - smb_dname = synthetic_smb_fname(talloc_tos(), path, - NULL, NULL); - if (smb_dname == NULL) { + if (smb_dname_cp == NULL) { return NT_STATUS_NO_MEMORY; } + if (req != NULL && req->posix_pathnames) { - ret = SMB_VFS_LSTAT(conn, smb_dname); + ret = SMB_VFS_LSTAT(conn, smb_dname_cp); } else { - ret = SMB_VFS_STAT(conn, smb_dname); + ret = SMB_VFS_STAT(conn, smb_dname_cp); } if (ret == -1) { - return map_nt_error_from_unix(errno); + status = map_nt_error_from_unix(errno); + TALLOC_FREE(smb_dname_cp); + return status; } - if (!S_ISDIR(smb_dname->st.st_ex_mode)) { + if (!S_ISDIR(smb_dname_cp->st.st_ex_mode)) { + TALLOC_FREE(smb_dname_cp); return NT_STATUS_NOT_A_DIRECTORY; } status = smbd_check_access_rights(conn, - smb_dname, + smb_dname_cp, backup_intent, SEC_DIR_LIST); if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(smb_dname_cp); return status; } if (backup_intent) { dir_hnd = open_dir_with_privilege(conn, req, - path, + smb_dname_cp, wcard, attr); } else { - dir_hnd = OpenDir(NULL, conn, smb_dname, wcard, attr); + dir_hnd = OpenDir(NULL, + conn, + smb_dname_cp, + wcard, + attr); } + TALLOC_FREE(smb_dname_cp); } if (!dir_hnd) { @@ -546,8 +551,8 @@ NTSTATUS dptr_create(connection_struct *conn, return NT_STATUS_NO_MEMORY; } - dptr->path = talloc_strdup(dptr, path); - if (!dptr->path) { + dptr->smb_dname = cp_smb_filename(dptr, smb_dname); + if (!dptr->smb_dname) { TALLOC_FREE(dptr); TALLOC_FREE(dir_hnd); return NT_STATUS_NO_MEMORY; @@ -643,7 +648,9 @@ NTSTATUS dptr_create(connection_struct *conn, done: DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n", - dptr->dnum,path,expect_close)); + dptr->dnum, + dptr->smb_dname->base_name, + expect_close)); *dptr_ret = dptr; @@ -712,7 +719,11 @@ static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, while ((name = ReadDirName(dptr->dir_hnd, poffset, pst, &talloced)) != NULL) { - if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) { + if (is_visible_file(dptr->conn, + dptr->smb_dname->base_name, + name, + pst, + true)) { *ptalloced = talloced; return name; } @@ -766,9 +777,11 @@ static char *dptr_ReadDirName(TALLOC_CTX *ctx, dptr->did_stat = true; /* First check if it should be visible. */ - if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, - pst, true)) - { + if (!is_visible_file(dptr->conn, + dptr->smb_dname->base_name, + dptr->wcard, + pst, + true)) { /* This only returns false if the file was found, but is explicitly not visible. Set us to end of directory, but return NULL as we know we can't ever @@ -783,7 +796,7 @@ static char *dptr_ReadDirName(TALLOC_CTX *ctx, pathreal = talloc_asprintf(ctx, "%s/%s", - dptr->path, + dptr->smb_dname->base_name, dptr->wcard); if (!pathreal) return NULL; @@ -818,8 +831,11 @@ static char *dptr_ReadDirName(TALLOC_CTX *ctx, * Try case-insensitive stat if the fs has the ability. This avoids * scanning the whole directory. */ - ret = SMB_VFS_GET_REAL_FILENAME(dptr->conn, dptr->path, dptr->wcard, - ctx, &found_name); + ret = SMB_VFS_GET_REAL_FILENAME(dptr->conn, + dptr->smb_dname->base_name, + dptr->wcard, + ctx, + &found_name); if (ret == 0) { name = found_name; goto clean; @@ -1029,7 +1045,7 @@ struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn, seekoff = map_wire_to_dir_offset(dptr, wire_offset); SeekDir(dptr->dir_hnd,seekoff); DEBUG(3,("fetching dirptr %d for path %s at offset %d\n", - key, dptr->path, (int)seekoff)); + key, dptr->smb_dname->base_name, (int)seekoff)); return(dptr); } @@ -1046,7 +1062,9 @@ struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn, DEBUG(3,("fetched null dirptr %d\n",dptr_num)); return(NULL); } - DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr->path)); + DEBUG(3,("fetching dirptr %d for path %s\n", + dptr_num, + dptr->smb_dname->base_name)); return(dptr); } @@ -1086,13 +1104,14 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx, connection_struct *conn = dirptr->conn; size_t slashlen; size_t pathlen; - bool dirptr_path_is_dot = ISDOT(dirptr->path); + const char *dpath = dirptr->smb_dname->base_name; + bool dirptr_path_is_dot = ISDOT(dpath); *_smb_fname = NULL; *_mode = 0; - pathlen = strlen(dirptr->path); - slashlen = ( dirptr->path[pathlen-1] != '/') ? 1 : 0; + pathlen = strlen(dpath); + slashlen = ( dpath[pathlen-1] != '/') ? 1 : 0; while (true) { long cur_offset; @@ -1158,7 +1177,7 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx, if (dirptr_path_is_dot) { memcpy(pathreal, dname, talloc_get_size(dname)); } else { - memcpy(pathreal, dirptr->path, pathlen); + memcpy(pathreal, dpath, pathlen); pathreal[pathlen] = '/'; memcpy(pathreal + slashlen + pathlen, dname, talloc_get_size(dname)); diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 3f9ddb5..8df3197 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -193,8 +193,14 @@ void dptr_closepath(struct smbd_server_connection *sconn, NTSTATUS dptr_create(connection_struct *conn, struct smb_request *req, files_struct *fsp, - const char *path, bool old_handle, bool expect_close,uint16_t spid, - const char *wcard, bool wcard_has_wild, uint32_t attr, struct dptr_struct **dptr_ret); + const struct smb_filename *smb_dname, + bool old_handle, + bool expect_close, + uint16_t spid, + const char *wcard, + bool wcard_has_wild, + uint32_t attr, + struct dptr_struct **dptr_ret); void dptr_CloseDir(files_struct *fsp); void dptr_SeekDir(struct dptr_struct *dptr, long offset); long dptr_TellDir(struct dptr_struct *dptr); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6763218..bb91d77 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1783,6 +1783,7 @@ void reply_search(struct smb_request *req) /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */ if (status_len == 0) { + struct smb_filename *smb_dname = NULL; uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP | (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0); nt_status = filename_convert(ctx, conn, @@ -1821,10 +1822,19 @@ void reply_search(struct smb_request *req) memset((char *)status,'\0',21); SCVAL(status,0,(dirtype & 0x1F)); + smb_dname = synthetic_smb_fname(talloc_tos(), + directory, + NULL, + NULL); + if (smb_dname == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + goto out; + } + nt_status = dptr_create(conn, NULL, /* req */ NULL, /* fsp */ - directory, + smb_dname, True, expect_close, req->smbpid, @@ -1832,6 +1842,9 @@ void reply_search(struct smb_request *req) mask_contains_wcard, dirtype, &dirptr); + + TALLOC_FREE(smb_dname); + if (!NT_STATUS_IS_OK(nt_status)) { reply_nterror(req, nt_status); goto out; diff --git a/source3/smbd/smb2_query_directory.c b/source3/smbd/smb2_query_directory.c index 4b6ca1b..e18a279 100644 --- a/source3/smbd/smb2_query_directory.c +++ b/source3/smbd/smb2_query_directory.c @@ -376,7 +376,7 @@ static struct tevent_req *smbd_smb2_query_directory_send(TALLOC_CTX *mem_ctx, status = dptr_create(conn, NULL, /* req */ fsp, - fsp->fsp_name->base_name, + fsp->fsp_name, false, /* old_handle */ false, /* expect_close */ 0, /* spid */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index bc34add..584039f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2633,6 +2633,8 @@ close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_da reply_nterror(req, NT_STATUS_NO_MEMORY); goto out; } + /* Ensure smb_dname->base_name matches. */ + smb_dname->base_name = directory; } DEBUG(5,("dir=%s, mask = %s\n",directory, mask)); @@ -2698,7 +2700,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd ntstatus = dptr_create(conn, req, NULL, /* fsp */ - directory, + smb_dname, False, True, req->smbpid, -- 2.5.0