The branch, master has been updated via 0e1deb7 s3: VFS: Don't allow symlink, link or rename on already converted paths. via cda6764 s3: VFS: shadow_copy2: Fix usage of saved_errno to only set errno on error. via 4d339a8 s3: VFS: shadow_copy2: Fix a memory leak in the connectpath function. via 128d5f2 s3: VFS: shadow_copy2: Fix module to work with variable current working directory. via b94dc85 s3: VFS: Add utility function check_for_converted_path(). via cd4f940 s3: VFS: Ensure shadow:format cannot contain a / path separator. via 42bd1ac s3: VFS: Allow shadow_copy2_connectpath() to return the cached path derived from $cwd. via 27340df s3: VFS: shadow_copy2: Fix chdir to store off the needed private variables. via 9d65107 s3: VFS: shadow_copy2: Add two currently unused functions to make pathnames absolute or relative to $cwd. via 2887465 s3: VFS: shadow_copy2: Change a parameter name. via 5aa1ea9 s3: VFS: shadow_copy2: Add a wrapper function to call the original shadow_copy2_strip_snapshot(). via 72fe2b6 s3: VFS: shadow_copy2: Add two new variables to the private data. Not yet used. via 37ef8d3 s3: VFS: shadow_copy2: Fix length comparison to ensure we don't overstep a length. via 979e392 s3: VFS: shadow_copy2: Ensure pathnames for parameters are correctly relative and terminated. via 0a190f4 s3: VFS: shadow_copy2: Correctly initialize timestamp and stripped variables. via d650d65 s3: smbd: Make set_conn_connectpath() call canonicalize_absolute_path(). via a513633 s3: smbtorture: Add new local test LOCAL-CANONICALIZE-PATH via 82979af s3: lib: Fix two old, old bugs in set_conn_connectpath(), now in canonicalize_absolute_path(). via 02599c3 s3: lib: Add canonicalize_absolute_path(). via 39678ed s3: smbd: Correctly canonicalize any incoming shadow copy path. from 26ffc20 build: vfs_posix_eadb is only built with the AD DC enabled
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 0e1deb77f2b310ad7e5dd784174207adacf1c981 Author: Jeremy Allison <j...@samba.org> Date: Thu Jan 26 17:19:24 2017 -0800 s3: VFS: Don't allow symlink, link or rename on already converted paths. Snapshot paths are a read-only filesystem. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Mon Jan 30 22:26:29 CET 2017 on sn-devel-144 commit cda6764f1a8db96182bfd1855440bc6a1ba1abee Author: Jeremy Allison <j...@samba.org> Date: Mon Jan 23 10:20:13 2017 -0800 s3: VFS: shadow_copy2: Fix usage of saved_errno to only set errno on error. Rationale: VFS calls must act like their POSIX equivalents, and the POSIX versions *only* set errno on a failure. There is actually code in the upper smbd layers that depends on errno being correct on a fail return from a VFS call. For a compound VFS module like this, a common pattern is : SMB_VFS_CALL_X() { int ret; syscall1(); ret = syscall2(); syscall3(); return ret; } Where if *any* of the contained syscallX()'s fail, they'll set errno. However, the actual errno we should return is *only* the one returned if syscall2() fails (the others are lstat's checking for existence etc.). So what we should do to correctly return only the errno from syscall2() is: SMB_VFS_CALL_X() { int ret; int saved_errno = 0; syscall1() ret = syscall2(); if (ret == -1) { saved_errno = errno; } syscall3() if (saved_errno != 0) { errno = saved_errno; } return ret; } BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit 4d339a88851f601fae195ac8ff0691cbd3504f41 Author: Jeremy Allison <j...@samba.org> Date: Mon Jan 23 10:06:44 2017 -0800 s3: VFS: shadow_copy2: Fix a memory leak in the connectpath function. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit 128d5f27cd42b0c7efcbe3d28fe3eee881e0734b Author: Jeremy Allison <j...@samba.org> Date: Thu Jan 26 10:49:51 2017 -0800 s3: VFS: shadow_copy2: Fix module to work with variable current working directory. Completely cleans up the horrible shadow_copy2_strip_snapshot() and adds an explaination of what it's actually trying to do. * This function does two things. * * 1). Checks if an incoming filename is already a * snapshot converted pathname. * If so, it returns the pathname truncated * at the snapshot point which will be used * as the connectpath, and then does an early return. * * 2). Checks if an incoming filename contains an * SMB-layer @GMT- style timestamp. * If so, it strips the timestamp, and returns * both the timestamp and the stripped path * (making it cwd-relative). BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit b94dc85d339c9a10496edd07b85bdd7808d2e332 Author: Jeremy Allison <j...@samba.org> Date: Thu Jan 26 10:35:50 2017 -0800 s3: VFS: Add utility function check_for_converted_path(). Detects an already converted path. Not yet used. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit cd4f940162b17e4f7345d392326a31ae478230fa Author: Jeremy Allison <j...@samba.org> Date: Thu Jan 26 10:24:52 2017 -0800 s3: VFS: Ensure shadow:format cannot contain a / path separator. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit 42bd1acad75a6b5ea81fe4b30c067dd82623c042 Author: Jeremy Allison <j...@samba.org> Date: Fri Jan 20 12:09:08 2017 -0800 s3: VFS: Allow shadow_copy2_connectpath() to return the cached path derived from $cwd. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit 27340df4b52e4341f134667c59d71656a7a1fdae Author: Jeremy Allison <j...@samba.org> Date: Fri Jan 20 12:06:55 2017 -0800 s3: VFS: shadow_copy2: Fix chdir to store off the needed private variables. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 This is not yet used, the users of this will be added later. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit 9d65107b8f2864dba8d41b3316c483b3f36d0697 Author: Jeremy Allison <j...@samba.org> Date: Fri Jan 20 12:00:08 2017 -0800 s3: VFS: shadow_copy2: Add two currently unused functions to make pathnames absolute or relative to $cwd. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit 2887465108aef5e2e7c64417437ecb86c7460e16 Author: Jeremy Allison <j...@samba.org> Date: Fri Jan 20 11:56:21 2017 -0800 s3: VFS: shadow_copy2: Change a parameter name. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Allows easy substitution later. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit 5aa1ea95157475dfd2d056f0158b14b2b90895a9 Author: Jeremy Allison <j...@samba.org> Date: Fri Jan 20 11:54:56 2017 -0800 s3: VFS: shadow_copy2: Add a wrapper function to call the original shadow_copy2_strip_snapshot(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Allows an extra (currently unused) parameter to be added. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit 72fe2b62e3ee7462e5be855b01943f28b26c36c1 Author: Jeremy Allison <j...@samba.org> Date: Fri Jan 20 11:50:49 2017 -0800 s3: VFS: shadow_copy2: Add two new variables to the private data. Not yet used. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit 37ef8d3f65bd1215717eb51b2e1cdb84a7bed348 Author: Jeremy Allison <j...@samba.org> Date: Fri Jan 20 11:48:40 2017 -0800 s3: VFS: shadow_copy2: Fix length comparison to ensure we don't overstep a length. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit 979e39252bcc88e8aacb543b8bf322dd6f17fe7f Author: Jeremy Allison <j...@samba.org> Date: Fri Jan 20 11:45:54 2017 -0800 s3: VFS: shadow_copy2: Ensure pathnames for parameters are correctly relative and terminated. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit 0a190f4dd950c947d47c42163d11ea4bd6e6e508 Author: Jeremy Allison <j...@samba.org> Date: Fri Jan 20 11:42:39 2017 -0800 s3: VFS: shadow_copy2: Correctly initialize timestamp and stripped variables. Allow the called functions to be fixed to not touch them on error. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit d650d65488761b30fa34d42cb1ab400618a78c33 Author: Jeremy Allison <j...@samba.org> Date: Tue Jan 17 11:35:52 2017 -0800 s3: smbd: Make set_conn_connectpath() call canonicalize_absolute_path(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit a51363309a4330b65e34ae941ec99d180bdbab56 Author: Jeremy Allison <j...@samba.org> Date: Thu Jan 26 16:08:42 2017 -0800 s3: smbtorture: Add new local test LOCAL-CANONICALIZE-PATH Tests new canonicalize_absolute_path() function. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit 82979afc46cc5e466bdd999a94080e7a5df95518 Author: Jeremy Allison <j...@samba.org> Date: Thu Jan 19 15:18:41 2017 -0800 s3: lib: Fix two old, old bugs in set_conn_connectpath(), now in canonicalize_absolute_path(). Canonicalizing a path of /foo/bar/../baz would return /foo/barbaz as moving forward 3 characters would delete the / character. Canonicalizing /foo/.. would end up as '\0'. Test to follow. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit 02599c39337c3049762a6b0bd6290577817ee5a5 Author: Jeremy Allison <j...@samba.org> Date: Tue Jan 17 11:33:18 2017 -0800 s3: lib: Add canonicalize_absolute_path(). Resolves any invalid path components (.) (..) in an absolute POSIX path. We will be re-using this in several places. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit 39678ed6af708fb6f2760bfb51051add11e3c498 Author: Jeremy Allison <j...@samba.org> Date: Wed Jan 11 16:30:38 2017 -0800 s3: smbd: Correctly canonicalize any incoming shadow copy path. Converts to: @GMT-token/path/last_component from all incoming path types. Allows shadow_copy modules to work when current directory is changed after removing last component. Ultimately when the VFS ABI is changed to add a timestamp to struct smb_filename, this is where the parsing will be done. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> ----------------------------------------------------------------------- Summary of changes: source3/lib/util_path.c | 139 ++++++ source3/lib/util_path.h | 1 + source3/modules/vfs_shadow_copy2.c | 909 ++++++++++++++++++++++++++----------- source3/selftest/tests.py | 1 + source3/smbd/filename.c | 150 ++++++ source3/smbd/service.c | 103 +---- source3/torture/torture.c | 44 ++ 7 files changed, 994 insertions(+), 353 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/lib/util_path.c b/source3/lib/util_path.c index 509ba5f..6f58a03 100644 --- a/source3/lib/util_path.c +++ b/source3/lib/util_path.c @@ -93,3 +93,142 @@ char *cache_path(const char *name) { return xx_path(name, lp_cache_directory()); } + +/** + * @brief Removes any invalid path components in an absolute POSIX path. + * + * @param ctx Talloc context to return string. + * + * @param abs_path Absolute path string to process. + * + * @retval Pointer to a talloc'ed string containing the absolute full path. + **/ + +char *canonicalize_absolute_path(TALLOC_CTX *ctx, const char *abs_path) +{ + char *destname; + char *d; + const char *s = abs_path; + bool start_of_name_component = true; + + /* Allocate for strlen + '\0' + possible leading '/' */ + destname = (char *)talloc_size(ctx, strlen(abs_path) + 2); + if (destname == NULL) { + return NULL; + } + d = destname; + + *d++ = '/'; /* Always start with root. */ + + while (*s) { + if (*s == '/') { + /* Eat multiple '/' */ + while (*s == '/') { + s++; + } + if ((d > destname + 1) && (*s != '\0')) { + *d++ = '/'; + } + start_of_name_component = true; + continue; + } + + if (start_of_name_component) { + if ((s[0] == '.') && (s[1] == '.') && + (s[2] == '/' || s[2] == '\0')) { + /* Uh oh - "/../" or "/..\0" ! */ + + /* Go past the .. leaving us on the / or '\0' */ + s += 2; + + /* If we just added a '/' - delete it */ + if ((d > destname) && (*(d-1) == '/')) { + *(d-1) = '\0'; + d--; + } + + /* + * Are we at the start ? + * Can't go back further if so. + */ + if (d <= destname) { + *d++ = '/'; /* Can't delete root */ + continue; + } + /* Go back one level... */ + /* + * Decrement d first as d points to + * the *next* char to write into. + */ + for (d--; d > destname; d--) { + if (*d == '/') { + break; + } + } + + /* + * Are we at the start ? + * Can't go back further if so. + */ + if (d <= destname) { + *d++ = '/'; /* Can't delete root */ + continue; + } + + /* + * We're still at the start of a name + * component, just the previous one. + */ + continue; + } else if ((s[0] == '.') && + ((s[1] == '\0') || s[1] == '/')) { + /* + * Component of pathname can't be "." only. + * Skip the '.' . + */ + if (s[1] == '/') { + s += 2; + } else { + s++; + } + continue; + } + } + + if (!(*s & 0x80)) { + *d++ = *s++; + } else { + size_t siz; + /* Get the size of the next MB character. */ + next_codepoint(s,&siz); + switch(siz) { + case 5: + *d++ = *s++; + /*fall through*/ + case 4: + *d++ = *s++; + /*fall through*/ + case 3: + *d++ = *s++; + /*fall through*/ + case 2: + *d++ = *s++; + /*fall through*/ + case 1: + *d++ = *s++; + break; + default: + break; + } + } + start_of_name_component = false; + } + *d = '\0'; + + /* And must not end in '/' */ + if (d > destname + 1 && (*(d-1) == '/')) { + *(d-1) = '\0'; + } + + return destname; +} diff --git a/source3/lib/util_path.h b/source3/lib/util_path.h index 118a4be..16e2792 100644 --- a/source3/lib/util_path.h +++ b/source3/lib/util_path.h @@ -27,5 +27,6 @@ char *lock_path(const char *name); char *state_path(const char *name); char *cache_path(const char *name); +char *canonicalize_absolute_path(TALLOC_CTX *ctx, const char *abs_path); #endif diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index 6a25c87..402eb70 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -35,6 +35,7 @@ #include "system/filesys.h" #include "include/ntioctl.h" #include "util_tdb.h" +#include "lib/util_path.h" struct shadow_copy2_config { char *gmt_format; @@ -74,6 +75,11 @@ struct shadow_copy2_snaplist_info { struct shadow_copy2_private { struct shadow_copy2_config *config; struct shadow_copy2_snaplist_info *snaps; + char *shadow_cwd; /* Absolute $cwd path. */ + /* Absolute connectpath - can vary depending on $cwd. */ + char *shadow_connectpath; + /* malloc'ed realpath return. */ + char *shadow_realpath; }; static int shadow_copy2_get_shadow_copy_data( @@ -404,79 +410,254 @@ static char *shadow_copy2_snapshot_path(TALLOC_CTX *mem_ctx, return result; } +static char *make_path_absolute(TALLOC_CTX *mem_ctx, + struct shadow_copy2_private *priv, + const char *name) +{ + char *newpath = NULL; + char *abs_path = NULL; + + if (name[0] != '/') { + newpath = talloc_asprintf(mem_ctx, + "%s/%s", + priv->shadow_cwd, + name); + if (newpath == NULL) { + return NULL; + } + name = newpath; + } + abs_path = canonicalize_absolute_path(mem_ctx, name); + TALLOC_FREE(newpath); + return abs_path; +} + +/* Return a $cwd-relative path. */ +static bool make_relative_path(const char *cwd, char *abs_path) +{ + size_t cwd_len = strlen(cwd); + size_t abs_len = strlen(abs_path); + + if (abs_len < cwd_len) { + return false; + } + if (memcmp(abs_path, cwd, cwd_len) != 0) { + return false; + } + if (abs_path[cwd_len] != '/' && abs_path[cwd_len] != '\0') { + return false; + } + if (abs_path[cwd_len] == '/') { + cwd_len++; + } + memmove(abs_path, &abs_path[cwd_len], abs_len + 1 - cwd_len); + return true; +} + +static bool shadow_copy2_snapshot_to_gmt(vfs_handle_struct *handle, + const char *name, + char *gmt, size_t gmt_len); + +/* + * Check if an incoming filename is already a snapshot converted pathname. + * + * If so, it returns the pathname truncated at the snapshot point which + * will be used as the connectpath. + */ + +static int check_for_converted_path(TALLOC_CTX *mem_ctx, + struct vfs_handle_struct *handle, + struct shadow_copy2_private *priv, + char *abs_path, + bool *ppath_already_converted, + char **pconnectpath) +{ + size_t snapdirlen = 0; + char *p = strstr_m(abs_path, priv->config->snapdir); + char *q = NULL; + char *connect_path = NULL; + char snapshot[GMT_NAME_LEN+1]; + + *ppath_already_converted = false; + + if (p == NULL) { + /* Must at least contain shadow:snapdir. */ + return 0; + } + + if (priv->config->snapdir[0] == '/' && + p != abs_path) { + /* Absolute shadow:snapdir must be at the start. */ + return 0; + } + + snapdirlen = strlen(priv->config->snapdir); + if (p[snapdirlen] != '/') { + /* shadow:snapdir must end as a separate component. */ + return 0; + } + + if (p > abs_path && p[-1] != '/') { + /* shadow:snapdir must start as a separate component. */ + return 0; + } + + p += snapdirlen; + p++; /* Move past the / */ + + /* + * Need to return up to the next path + * component after the time. + * This will be used as the connectpath. + */ + q = strchr(p, '/'); + if (q == NULL) { + /* + * No next path component. + * Use entire string. + */ + connect_path = talloc_strdup(mem_ctx, + abs_path); + } else { + connect_path = talloc_strndup(mem_ctx, + abs_path, + q - abs_path); + } + if (connect_path == NULL) { + return ENOMEM; + } + + /* + * Point p at the same offset in connect_path as + * it is in abs_path. + */ + + p = &connect_path[p - abs_path]; + + /* + * Now ensure there is a time string at p. + * The SMB-format @GMT-token string is returned + * in snapshot. + */ + + if (!shadow_copy2_snapshot_to_gmt(handle, + p, + snapshot, + sizeof(snapshot))) { + TALLOC_FREE(connect_path); + return 0; + } + + if (pconnectpath != NULL) { + *pconnectpath = connect_path; + } + + *ppath_already_converted = true; + + DBG_DEBUG("path |%s| is already converted. " + "connect path = |%s|\n", + abs_path, + connect_path); + + return 0; +} + /** - * Strip a snapshot component from a filename as - * handed in via the smb layer. - * Returns the parsed timestamp and the stripped filename. + * This function does two things. + * + * 1). Checks if an incoming filename is already a + * snapshot converted pathname. + * If so, it returns the pathname truncated + * at the snapshot point which will be used + * as the connectpath, and then does an early return. + * + * 2). Checks if an incoming filename contains an + * SMB-layer @GMT- style timestamp. + * If so, it strips the timestamp, and returns + * both the timestamp and the stripped path + * (making it cwd-relative). */ -static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx, + +static bool shadow_copy2_strip_snapshot_internal(TALLOC_CTX *mem_ctx, struct vfs_handle_struct *handle, - const char *name, + const char *orig_name, time_t *ptimestamp, - char **pstripped) + char **pstripped, + char **psnappath) { struct tm tm; - time_t timestamp; + time_t timestamp = 0; const char *p; char *q; - char *stripped; + char *stripped = NULL; size_t rest_len, dst_len; struct shadow_copy2_private *priv; - const char *snapdir; - ssize_t snapdirlen; ptrdiff_t len_before_gmt; + const char *name = orig_name; + char *abs_path = NULL; + bool ret = true; + bool already_converted = false; + int err = 0; SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private, return false); DEBUG(10, (__location__ ": enter path '%s'\n", name)); + abs_path = make_path_absolute(mem_ctx, priv, name); + if (abs_path == NULL) { + ret = false; + goto out; + } + name = abs_path; + + DEBUG(10, (__location__ ": abs path '%s'\n", name)); + + err = check_for_converted_path(mem_ctx, + handle, + priv, + abs_path, + &already_converted, + psnappath); + if (err != 0) { + /* error in conversion. */ + ret = false; + goto out; + } + + if (already_converted) { + goto out; + } + + /* + * From here we're only looking to strip an + * SMB-layer @GMT- token. + */ + p = strstr_m(name, "@GMT-"); if (p == NULL) { DEBUG(11, ("@GMT not found\n")); - goto no_snapshot; + goto out; } if ((p > name) && (p[-1] != '/')) { /* the GMT-token does not start a path-component */ DEBUG(10, ("not at start, p=%p, name=%p, p[-1]=%d\n", p, name, (int)p[-1])); - goto no_snapshot; + goto out; } - /* - * Figure out whether we got an already converted string. One - * case where this happens is in a smb2 create call with the - * mxac create blob set. We do the get_acl call on - * fsp->fsp_name, which is already converted. We are converted - * if we got a file name of the form ".snapshots/@GMT-", - * i.e. ".snapshots/" precedes "p". - */ - - snapdir = lp_parm_const_string(SNUM(handle->conn), "shadow", "snapdir", - ".snapshots"); - snapdirlen = strlen(snapdir); len_before_gmt = p - name; - if ((len_before_gmt >= (snapdirlen + 1)) && (p[-1] == '/')) { - const char *parent_snapdir = p - (snapdirlen+1); - - DEBUG(10, ("parent_snapdir = %s\n", parent_snapdir)); - - if (strncmp(parent_snapdir, snapdir, snapdirlen) == 0) { - DEBUG(10, ("name=%s is already converted\n", name)); - goto no_snapshot; - } - } q = strptime(p, GMT_FORMAT, &tm); if (q == NULL) { DEBUG(10, ("strptime failed\n")); - goto no_snapshot; + goto out; } tm.tm_isdst = -1; timestamp = timegm(&tm); if (timestamp == (time_t)-1) { DEBUG(10, ("timestamp==-1\n")); - goto no_snapshot; + goto out; } if (q[0] == '\0') { /* @@ -496,12 +677,24 @@ static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx, stripped = talloc_strndup(mem_ctx, name, len_before_gmt); if (stripped == NULL) { - return false; + ret = false; + goto out; + } + if (orig_name[0] != '/') { + if (make_relative_path(priv->shadow_cwd, + stripped) == false) { + DEBUG(10, (__location__ ": path '%s' " + "doesn't start with cwd '%s\n", + stripped, priv->shadow_cwd)); + ret = false; + errno = ENOENT; + goto out; + } } *pstripped = stripped; } *ptimestamp = timestamp; - return true; + goto out; } if (q[0] != '/') { /* -- Samba Shared Repository