From 862053ae40d7e9c44a3e1eb4227c766cd37abfde Mon Sep 17 00:00:00 2001 Date: Thu, 1 Sep 2011 16:51:53 -0700 Subject: [PATCH 5/5] Fix access check, thereby removing widelinks requirement. shadow_copy2_connectpath() was not properly converting the @GMT-... parts to the real snapshot name, so this was failing whenever a shadow:format was specified. The error logged was something like this: check_reduced_name: Bad access attempt: foo/* is a symlink outside the share path conn_rootdir =/base/snapshots/@GMT-2011.08.31-20.55.50/ resolved_name=/base/snapshots/snap_20110831205550/foo/* Furthermore, the function was duplicating most of the code in convert_shadow2_name() (but incompletely). Therefore this patch now re-uses convert_shadow2_name(). This is a slightly modified version of the patch presented here (that patch did not properly handle narrow symlinks): http://lists.samba.org/archive/samba-technical/2011-January/075707.html http://samba.2283325.n4.nabble.com/shadow-copy2-requires-wide-links-enabled-td3178583.html --- source3/modules/vfs_shadow_copy2.c | 72 ++++++------------------------------ 1 files changed, 12 insertions(+), 60 deletions(-) diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index fedfb53..8255bbf 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -237,7 +237,7 @@ static const char *shadow_copy2_normalise_path(TALLOC_CTX *mem_ctx, const char * if (shadow_copy2_match_name(fname, &gmt_start)) { \ char *name2; \ rtype ret; \ - name2 = convert_shadow2_name(handle, fname, gmt_start); \ + name2 = convert_shadow2_name(handle, fname, gmt_start, True); \ if (name2 == NULL) { \ errno = EINVAL; \ return eret; \ @@ -258,7 +258,7 @@ static const char *shadow_copy2_normalise_path(TALLOC_CTX *mem_ctx, const char * char *name2; \ char *smb_base_name_tmp = NULL; \ rtype ret; \ - name2 = convert_shadow2_name(handle, smb_fname->base_name, gmt_start); \ + name2 = convert_shadow2_name(handle, smb_fname->base_name, gmt_start, True); \ if (name2 == NULL) { \ errno = EINVAL; \ return eret; \ @@ -285,7 +285,7 @@ static const char *shadow_copy2_normalise_path(TALLOC_CTX *mem_ctx, const char * if (shadow_copy2_match_name(fname, &gmt_start)) { \ char *name2; \ NTSTATUS ret; \ - name2 = convert_shadow2_name(handle, fname, gmt_start); \ + name2 = convert_shadow2_name(handle, fname, gmt_start, True); \ if (name2 == NULL) { \ errno = EINVAL; \ return eret; \ @@ -409,7 +409,8 @@ static const char *shadow_copy2_find_basedir(TALLOC_CTX *mem_ctx, vfs_handle_str convert a filename from a share relative path, to a path in the snapshot directory */ -static char *convert_shadow2_name(vfs_handle_struct *handle, const char *fname, const char *gmt_path) +static char *convert_shadow2_name(vfs_handle_struct *handle, const char *fname, + const char *gmt_path, const bool incl_rel) { TALLOC_CTX *tmp_ctx = talloc_new(handle->data); const char *snapdir, *relpath, *baseoffset, *basedir; @@ -486,11 +487,13 @@ static char *convert_shadow2_name(vfs_handle_struct *handle, const char *fname, if (*relpath == '/') relpath++; if (*baseoffset == '/') baseoffset++; - ret = talloc_asprintf(handle->data, "%s/%s/%s/%s", + ret = talloc_asprintf(handle->data, "%s/%s%s%s%s%s", snapdir, snapshot, + *baseoffset ? "/" : "", baseoffset, - relpath); + *relpath ? "/" : "", + incl_rel ? relpath : ""); DEBUG(6,("convert_shadow2_name: '%s' -> '%s'\n", fname, ret)); talloc_free(tmp_ctx); return ret; @@ -687,68 +690,17 @@ static char *shadow_copy2_realpath(vfs_handle_struct *handle, static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle, const char *fname) { - TALLOC_CTX *tmp_ctx; - const char *snapdir, *baseoffset, *basedir, *gmt_start; - size_t baselen; + const char *gmt_start; char *ret; DEBUG(10, ("shadow_copy2_connectpath called with %s\n", fname)); if (!shadow_copy2_match_name(fname, &gmt_start)) { - return handle->conn->connectpath; - } - - /* - * We have to create a real temporary context because we have - * to put our result on talloc_tos(). Thus we can't use a - * talloc_stackframe() here. - */ - tmp_ctx = talloc_new(talloc_tos()); - - fname = shadow_copy2_normalise_path(tmp_ctx, fname, gmt_start); - if (fname == NULL) { - TALLOC_FREE(tmp_ctx); - return NULL; - } - - snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle); - if (snapdir == NULL) { - DEBUG(2,("no snapdir found for share at %s\n", - handle->conn->connectpath)); - TALLOC_FREE(tmp_ctx); - return NULL; - } - - basedir = shadow_copy2_find_basedir(tmp_ctx, handle); - if (basedir == NULL) { - DEBUG(2,("no basedir found for share at %s\n", - handle->conn->connectpath)); - TALLOC_FREE(tmp_ctx); - return NULL; - } - - baselen = strlen(basedir); - baseoffset = handle->conn->connectpath + baselen; - - /* some sanity checks */ - if (strncmp(basedir, handle->conn->connectpath, baselen) != 0 || - (handle->conn->connectpath[baselen] != 0 - && handle->conn->connectpath[baselen] != '/')) { - DEBUG(0,("shadow_copy2_connectpath: basedir %s is not a " - "parent of %s\n", basedir, - handle->conn->connectpath)); - TALLOC_FREE(tmp_ctx); - return NULL; + return SMB_VFS_NEXT_CONNECTPATH(handle, fname); } - if (*baseoffset == '/') baseoffset++; - - ret = talloc_asprintf(talloc_tos(), "%s/%.*s/%s", - snapdir, - GMT_NAME_LEN, fname, - baseoffset); + ret = convert_shadow2_name(handle, fname, gmt_start, False); DEBUG(6,("shadow_copy2_connectpath: '%s' -> '%s'\n", fname, ret)); - TALLOC_FREE(tmp_ctx); return ret; } -- 1.7.3.4