[PATCHES] vfs_shadow_copy2: allow snapshots outside share's root

Uri Simchoni uri at samba.org
Tue Dec 29 06:12:14 UTC 2015


Resubmitting a rebased patch. No actual changes, still passes autobuild 
after the security fixes in shadow_copy2.


Thanks,
Uri

On 11/02/2015 09:20 AM, Uri Simchoni wrote:
> Attached is a modified fix which does not break "snapdirseverywhere", 
> and a test suite for most of the configuration options which affect 
> the logic of path processing.
>
> Thanks,
> Uri.
>
> On 11/01/2015 03:00 PM, Uri Simchoni wrote:
>>
>>
>> On 10/30/2015 10:53 PM, Michael Adam wrote:
>>> On 2015-10-30 at 13:35 -0700, Jeremy Allison wrote:
>>>> On Fri, Oct 30, 2015 at 12:41:28AM +0200, Uri Simchoni wrote:
>>>>> Hi,
>>>>>
>>>>> I may just be misconfiguring shadow_copy2 here, but it does seem
>>>>> like a bug to me, so here's a fix and some tests.
>>>>>
>>>>> I filed https://bugzilla.samba.org/show_bug.cgi?id=11580 where I
>>>>> describe what kind of snapshot setup I'm using, and how I configure
>>>>> shadow_copy2 for that.
>>>>>
>>>>> - If there's a way to get this to work without the patch - I'd love
>>>>> to stand corrected
>>>>> - Haven't wrapped my mind around "snapshots everywhere" - need to
>>>>> verify this isn't broken by the fix, however I figured I'd submit
>>>>> the patch anyway to get feedback if it's a non-bug.
>>>> Hmmmm. Gonna take a look. I'm not sure if shadow_copy2 is
>>>> supposed to allow out-of-share snapshot location.
>>> I guess it should. I am going to have a look, too...
>>> But might be next week. :-)
>>>
>>> Cheers - Michael
>> In the meantime I've extended the test suite to cover wide and 
>> non-wide links and "snapdirseverywhere" and seems like my fix breaks 
>> "snapdirseverywhere" so stay tuned for a v2 patch :)
>>
>> Thanks,
>> Uri.
>>
>>
>

-------------- next part --------------
From 2a918769b26e6698f4189099860a64332649192b Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Sun, 1 Nov 2015 22:28:46 +0200
Subject: [PATCH 1/3] vfs_shadow_copy2: add shadow_copy2_do_convert()

Add a new routine shadow_copy2_do_convert() which is
like shadow_copy2_convert(), but beside calculating the
path of the snapshot file, it also returns the minimum length
of the subpath which is both inside the share and inside the
same snapshot as the file in question.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11580

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/modules/vfs_shadow_copy2.c | 38 ++++++++++++++++++++++++++++++++++----
 1 file changed, 34 insertions(+), 4 deletions(-)

diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
index d1673a4..ec17d21 100644
--- a/source3/modules/vfs_shadow_copy2.c
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -434,10 +434,12 @@ static char *shadow_copy2_find_mount_point(TALLOC_CTX *mem_ctx,
  * Convert from a name as handed in via the SMB layer
  * and a timestamp into the local path of the snapshot
  * of the provided file at the provided time.
+ * Also return the snapshot file's share root.
  */
-static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
-				  struct vfs_handle_struct *handle,
-				  const char *name, time_t timestamp)
+static char *shadow_copy2_do_convert(TALLOC_CTX *mem_ctx,
+				     struct vfs_handle_struct *handle,
+				     const char *name, time_t timestamp,
+				     size_t *snaproot_len)
 {
 	struct smb_filename converted_fname;
 	char *result = NULL;
@@ -447,10 +449,11 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
 	size_t pathlen;
 	char *insert = NULL;
 	char *converted = NULL;
-	size_t insertlen;
+	size_t insertlen, connectlen = 0;
 	int i, saved_errno;
 	size_t min_offset;
 	struct shadow_copy2_config *config;
+	size_t in_share_offset = 0;
 
 	SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
 				return NULL);
@@ -492,6 +495,13 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
 			DEBUG(10, ("Found %s\n", converted));
 			result = converted;
 			converted = NULL;
+			if (snaproot_len != NULL) {
+				*snaproot_len = strlen(snapshot_path);
+				if (config->rel_connectpath != NULL) {
+					*snaproot_len +=
+					    strlen(config->rel_connectpath) + 1;
+				}
+			}
 			goto fail;
 		} else {
 			errno = ENOENT;
@@ -500,6 +510,7 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
 		/* never reached ... */
 	}
 
+	connectlen = strlen(handle->conn->connectpath);
 	if (name[0] == 0) {
 		path = talloc_strdup(mem_ctx, handle->conn->connectpath);
 	} else {
@@ -575,6 +586,10 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
 			goto fail;
 		}
 
+		if (offset >= connectlen) {
+			in_share_offset = offset;
+		}
+
 		memcpy(converted+offset, insert, insertlen);
 
 		offset += insertlen;
@@ -588,6 +603,9 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
 			   ret, ret == 0 ? "ok" : strerror(errno)));
 		if (ret == 0) {
 			/* success */
+			if (snaproot_len != NULL) {
+				*snaproot_len = in_share_offset + insertlen;
+			}
 			break;
 		}
 		if (errno == ENOTDIR) {
@@ -624,6 +642,18 @@ fail:
 	return result;
 }
 
+/**
+ * Convert from a name as handed in via the SMB layer
+ * and a timestamp into the local path of the snapshot
+ * of the provided file at the provided time.
+ */
+static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
+				  struct vfs_handle_struct *handle,
+				  const char *name, time_t timestamp)
+{
+	return shadow_copy2_do_convert(mem_ctx, handle, name, timestamp, NULL);
+}
+
 /*
   modify a sbuf return to ensure that inodes in the shadow directory
   are different from those in the main directory
-- 
2.4.3


From e6e1875928eda7ee84b3c38d352135999eae4151 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Mon, 2 Nov 2015 09:08:53 +0200
Subject: [PATCH 2/3] vfs_shadow_copy2: fix case where snapshots are outside
 the share

Adjust the connect path to the root of the share in the snapshot,
or to the root of the snapshot if the snapshot is "inside" the
share.

This way snapshot symlink regarded as "wide links" if and only if
they point outside the snapshot or they were wide links when
the snapshot was taken.

This allows mounting the snapshots outside the share's root.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11580

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/modules/vfs_shadow_copy2.c | 68 ++++++++++++++++++++++++++------------
 1 file changed, 46 insertions(+), 22 deletions(-)

diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
index ec17d21..8918536 100644
--- a/source3/modules/vfs_shadow_copy2.c
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -1133,8 +1133,6 @@ static char *shadow_copy2_realpath(vfs_handle_struct *handle,
 	char *stripped = NULL;
 	char *tmp = NULL;
 	char *result = NULL;
-	char *inserted = NULL;
-	char *inserted_to, *inserted_end;
 	int saved_errno;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
@@ -1151,29 +1149,9 @@ static char *shadow_copy2_realpath(vfs_handle_struct *handle,
 	}
 
 	result = SMB_VFS_NEXT_REALPATH(handle, tmp);
-	if (result == NULL) {
-		goto done;
-	}
-
-	/*
-	 * Take away what we've inserted. This removes the @GMT-thingy
-	 * completely, but will give a path under the share root.
-	 */
-	inserted = shadow_copy2_insert_string(talloc_tos(), handle, timestamp);
-	if (inserted == NULL) {
-		goto done;
-	}
-	inserted_to = strstr_m(result, inserted);
-	if (inserted_to == NULL) {
-		DEBUG(2, ("SMB_VFS_NEXT_REALPATH removed %s\n", inserted));
-		goto done;
-	}
-	inserted_end = inserted_to + talloc_get_size(inserted) - 1;
-	memmove(inserted_to, inserted_end, strlen(inserted_end)+1);
 
 done:
 	saved_errno = errno;
-	TALLOC_FREE(inserted);
 	TALLOC_FREE(tmp);
 	TALLOC_FREE(stripped);
 	errno = saved_errno;
@@ -1807,6 +1785,51 @@ static int shadow_copy2_get_real_filename(struct vfs_handle_struct *handle,
 	return ret;
 }
 
+static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle,
+					    const char *fname)
+{
+	time_t timestamp;
+	char *stripped = NULL;
+	char *tmp = NULL;
+	char *result = NULL;
+	int saved_errno;
+	size_t rootpath_len = 0;
+
+	DBG_DEBUG("Calc connect path for [%s]\n", fname);
+
+	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
+					 &timestamp, &stripped)) {
+		goto done;
+	}
+	if (timestamp == 0) {
+		return SMB_VFS_NEXT_CONNECTPATH(handle, fname);
+	}
+
+	tmp = shadow_copy2_do_convert(talloc_tos(), handle, stripped, timestamp,
+				      &rootpath_len);
+	if (tmp == NULL) {
+		goto done;
+	}
+
+	DBG_DEBUG("converted path is [%s] root path is [%.*s]\n", tmp,
+		  (int)rootpath_len, tmp);
+
+	tmp[rootpath_len] = '\0';
+	result = SMB_VFS_NEXT_REALPATH(handle, tmp);
+	if (result == NULL) {
+		goto done;
+	}
+
+	DBG_DEBUG("connect path is [%s]\n", result);
+
+done:
+	saved_errno = errno;
+	TALLOC_FREE(tmp);
+	TALLOC_FREE(stripped);
+	errno = saved_errno;
+	return result;
+}
+
 static uint64_t shadow_copy2_disk_free(vfs_handle_struct *handle,
 				       const char *path, uint64_t *bsize,
 				       uint64_t *dfree, uint64_t *dsize)
@@ -2108,6 +2131,7 @@ static struct vfs_fn_pointers vfs_shadow_copy2_fns = {
 	.chmod_acl_fn = shadow_copy2_chmod_acl,
 	.chflags_fn = shadow_copy2_chflags,
 	.get_real_filename_fn = shadow_copy2_get_real_filename,
+	.connectpath_fn = shadow_copy2_connectpath,
 };
 
 NTSTATUS vfs_shadow_copy2_init(void);
-- 
2.4.3


From 38b5b5ca16a3f212068ce8af71348ba4cdf2c663 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Thu, 29 Oct 2015 22:24:30 +0200
Subject: [PATCH 3/3] vfs_shadow_copy2: add a blackbox test suite

Add a blackbox test suite for vfs_shadow_copy2, testing
parameters mountpoint, basedir, snapdir, snapdirseverywhere,
and testing correct wide-link processing.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11580

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 selftest/target/Samba3.pm                |  69 ++++++++
 source3/script/tests/test_shadow_copy.sh | 290 +++++++++++++++++++++++++++++++
 source3/selftest/tests.py                |   1 +
 3 files changed, 360 insertions(+)
 create mode 100755 source3/script/tests/test_shadow_copy.sh

diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index c9e57ad..493602a 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -1124,6 +1124,15 @@ sub provision($$$$$$$$)
 	my $widelinks_linkdir="$shrdir/widelinks_foo";
 	push(@dirs,$widelinks_linkdir);
 
+	my $shadow_tstdir="$shrdir/shadow";
+	push(@dirs,$shadow_tstdir);
+	my $shadow_mntdir="$shadow_tstdir/mount";
+	push(@dirs,$shadow_mntdir);
+	my $shadow_basedir="$shadow_mntdir/base";
+	push(@dirs,$shadow_basedir);
+	my $shadow_shrdir="$shadow_basedir/share";
+	push(@dirs,$shadow_shrdir);
+
 	# this gets autocreated by winbindd
 	my $wbsockdir="$prefix_abs/winbindd";
 	my $wbsockprivdir="$lockdir/winbindd_privileged";
@@ -1390,6 +1399,10 @@ sub provision($$$$$$$$)
 	# fruit:copyfile is a global option
 	fruit:copyfile = yes
 
+	#this does not mean that we use non-secure test env,
+	#it just means we ALLOW one to be configured.
+	allow insecure wide links = yes
+
 	# Begin extra options
 	$extra_options
 	# End extra options
@@ -1551,6 +1564,62 @@ sub provision($$$$$$$$)
 	shell_snap:delete command = $fake_snap_pl --delete
 	# a relative path here fails, the snapshot dir is no longer found
 	shadow:snapdir = $shrdir/.snapshots
+
+[shadow1]
+	path = $shadow_shrdir
+	comment = previous versions snapshots under mount point
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $shadow_mntdir
+
+[shadow2]
+	path = $shadow_shrdir
+	comment = previous versions snapshots outside mount point
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $shadow_mntdir
+	shadow:snapdir = $shadow_tstdir/.snapshots
+
+[shadow3]
+	path = $shadow_shrdir
+	comment = previous versions with subvolume snapshots, snapshots under base dir
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $shadow_mntdir
+	shadow:basedir = $shadow_basedir
+	shadow:snapdir = $shadow_basedir/.snapshots
+
+[shadow4]
+	path = $shadow_shrdir
+	comment = previous versions with subvolume snapshots, snapshots outside mount point
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $shadow_mntdir
+	shadow:basedir = $shadow_basedir
+	shadow:snapdir = $shadow_tstdir/.snapshots
+
+[shadow5]
+	path = $shadow_shrdir
+	comment = previous versions at volume root snapshots under mount point
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $shadow_shrdir
+
+[shadow6]
+	path = $shadow_shrdir
+	comment = previous versions at volume root snapshots outside mount point
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $shadow_shrdir
+	shadow:snapdir = $shadow_tstdir/.snapshots
+
+[shadow7]
+	path = $shadow_shrdir
+	comment = previous versions snapshots everywhere
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $shadow_mntdir
+	shadow:snapdirseverywhere = yes
+
+[shadow_wl]
+	path = $shadow_shrdir
+	comment = previous versions with wide links allowed
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $shadow_mntdir
+	wide links = yes
 	";
 	close(CONF);
 
diff --git a/source3/script/tests/test_shadow_copy.sh b/source3/script/tests/test_shadow_copy.sh
new file mode 100755
index 0000000..8e2b064
--- /dev/null
+++ b/source3/script/tests/test_shadow_copy.sh
@@ -0,0 +1,290 @@
+#!/bin/sh
+#
+# Blackbox test for shadow_copy2 VFS.
+#
+
+if [ $# -lt 7 ]; then
+cat <<EOF
+Usage: test_shadow_copy SERVER SERVER_IP DOMAIN USERNAME PASSWORD WORKDIR SMBCLIENT
+EOF
+exit 1;
+fi
+
+SERVER=${1}
+SERVER_IP=${2}
+DOMAIN=${3}
+USERNAME=${4}
+PASSWORD=${5}
+WORKDIR=${6}
+SMBCLIENT=${7}
+shift 7
+SMBCLIENT="$VALGRIND ${SMBCLIENT}"
+ADDARGS="$*"
+
+incdir=`dirname $0`/../../../testprogs/blackbox
+. $incdir/subunit.sh
+
+SNAPSHOTS[0]='@GMT-2015.10.31-19.40.30'
+SNAPSHOTS[1]='@GMT-2016.10.31-19.40.30'
+SNAPSHOTS[2]='@GMT-2017.10.31-19.40.30'
+SNAPSHOTS[3]='@GMT-2018.10.31-19.40.30'
+SNAPSHOTS[4]='@GMT-2019.10.31-19.40.30'
+SNAPSHOTS[5]='@GMT-2020.10.31-19.40.30'
+SNAPSHOTS[6]='@GMT-2021.10.31-19.40.30'
+SNAPSHOTS[7]='@GMT-2022.10.31-19.40.30'
+SNAPSHOTS[8]='@GMT-2023.10.31-19.40.30'
+SNAPSHOTS[9]='@GMT-2024.10.31-19.40.30'
+
+# build a hierarchy of files, symlinks, and directories
+build_files()
+{
+    local rootdir
+    local prefix
+    local version
+    local destdir
+    rootdir=$1
+    prefix=$2
+    version=$3
+    if [ -n "$prefix" ] ; then
+        destdir=$rootdir/$prefix
+    else
+        destdir=$rootdir
+    fi
+
+    mkdir -p $destdir
+    if [ "$version" = "latest" ] ; then
+        #non-snapshot files
+        # for non-snapshot version, create legit files
+        # so that wide-link checks focus on snapshot files
+        touch $destdir/foo
+        mkdir -p $destdir/bar
+        touch $destdir/bar/baz
+        touch $destdir/bar/lfoo
+        touch $destdir/bar/letcpasswd
+        touch $destdir/bar/loutside
+    elif [ "$version" = "fullsnap" ] ; then
+        #snapshot files
+        touch $destdir/foo
+        mkdir -p $destdir/bar
+        touch $destdir/bar/baz
+        ln -fs ../foo $destdir/bar/lfoo
+        ln -fs /etc/passwd $destdir/bar/letcpasswd
+        ln -fs ../../outside $destdir/bar/loutside
+        touch `dirname $destdir`/outside
+    else #subshare snapshot - at bar
+        touch $destdir/baz
+        ln -fs ../foo $destdir/lfoo
+        ln -fs /etc/passwd $destdir/letcpasswd
+        ln -fs ../../outside $destdir/loutside
+        touch `dirname $destdir`/../outside
+    fi
+
+}
+
+# build a snapshots directory
+build_snapshots()
+{
+    local where     #where to build snapshots
+    local prefix    #prefix from snapshot dir to share root
+    local start     #timestamp index of first snapshot
+    local end       #timestamp index of last snapshot
+    local sub       #creat a snapshot of subtree of share
+    local snapdir
+    local snapname
+    local i
+    local version
+
+    where=$1
+    prefix=$2
+    start=$3
+    end=$4
+    sub=$5
+
+    snapdir=$where/.snapshots
+    mkdir -p $snapdir
+
+    version="fullsnap"
+    if [ "$sub" = "1" ] ; then
+        version="subsnap"
+        prefix=""
+
+        # a valid link target for an inner symlink -
+        # the link is not broken yet should be blocked
+        # by wide link checks
+        touch $snapdir/foo
+    fi
+
+    for i in `seq $start $end` ; do
+        snapname=${SNAPSHOTS[$i]}
+        mkdir $snapdir/$snapname
+        build_files $snapdir/$snapname "$prefix" $version
+    done
+}
+
+# Test listing previous versions of a file
+test_count_versions()
+{
+    local share
+    local path
+    local expected_count
+    local versions
+
+    share=$1
+    path=$2
+    expected_count=$3
+    versions=`$SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "allinfo $path" | grep "^create_time:" | wc -l`
+    if [ "$versions" = "$expected_count" ] ; then
+        true
+    else
+        echo "expected $expected_count versions of $path, got $versions"
+        false
+    fi
+}
+
+# Test fetching a previous version of a file
+test_fetch_snap_file()
+{
+    local share
+    local path
+    local snapidx
+
+    share=$1
+    path=$2
+    snapidx=$3
+    $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP \
+        -c "get ${SNAPSHOTS[$snapidx]}/$path $WORKDIR/foo"
+}
+
+test_shadow_copy_fixed()
+{
+    local share     #share to contact
+    local where     #where to place snapshots
+    local prefix    #prefix to files inside snapshot
+    local msg
+    local allow_wl
+    local ncopies_allowd
+    local ncopies_blocked
+
+    share=$1
+    where=$2
+    prefix=$3
+    msg=$4
+    allow_wl=$5
+
+    ncopies_allowed=4
+    ncopies_blocked=1
+    if [ -n "$allow_wl" ] ; then
+        ncopies_blocked=4
+    fi
+
+    #delete snapshots from previous tests
+    find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1
+    build_snapshots $WORKDIR/$where "$prefix" 0 2
+
+    testit "$msg - regular file" \
+        test_count_versions $share foo $ncopies_allowed || \
+        failed=`expr $failed + 1`
+
+    testit "$msg - regular file in subdir" \
+        test_count_versions $share bar/baz $ncopies_allowed || \
+        failed=`expr $failed + 1`
+
+    testit "$msg - local symlink" \
+        test_count_versions $share bar/lfoo $ncopies_allowed || \
+        failed=`expr $failed + 1`
+
+    testit "$msg - abs symlink outside" \
+        test_count_versions $share bar/letcpasswd $ncopies_blocked || \
+        failed=`expr $failed + 1`
+
+    testit "$msg - rel symlink outside" \
+        test_count_versions $share bar/loutside $ncopies_blocked || \
+        failed=`expr $failed + 1`
+}
+
+test_shadow_copy_everywhere()
+{
+    local share     #share to contact
+
+    share=$1
+
+    #delete snapshots from previous tests
+    find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1
+    build_snapshots "$WORKDIR/mount" "base/share" 0 0
+    build_snapshots "$WORKDIR/mount/base" "share" 1 2
+    build_snapshots "$WORKDIR/mount/base/share" "" 3 5
+    build_snapshots "$WORKDIR/mount/base/share/bar" "" 6 9 1
+
+    testit "snapshots in each dir - regular file" \
+        test_count_versions $share foo 4 || \
+        failed=`expr $failed + 1`
+
+    testit "snapshots in each dir - regular file in subdir" \
+        test_count_versions $share bar/baz 5 || \
+        failed=`expr $failed + 1`
+
+    testit "snapshots in each dir - local symlink (but outside snapshot)" \
+        test_count_versions $share bar/lfoo 1 || \
+        failed=`expr $failed + 1`
+
+    testit "snapshots in each dir - abs symlink outside" \
+        test_count_versions $share bar/letcpasswd 1 || \
+        failed=`expr $failed + 1`
+
+    testit "snapshots in each dir - rel symlink outside" \
+        test_count_versions $share bar/loutside 1 || \
+        failed=`expr $failed + 1`
+
+    #the previous versions of the file bar/lfoo points to are outside its
+    #snapshot, and are not reachable. However, but previous versions
+    #taken at different, non-overlapping times higher up the
+    #hierarchy are still reachable.
+    testit "fetch a previous version of a regular file" \
+        test_fetch_snap_file $share "bar/baz" 6 || \
+        failed=`expr $failed + 1`
+
+    testit_expect_failure "fetch a (non-existent) previous version of a symlink" \
+        test_fetch_snap_file $share "bar/lfoo" 6 || \
+        failed=`expr $failed + 1`
+
+    testit "fetch a previous version of a symlink via browsing (1)" \
+        test_fetch_snap_file $share "bar/lfoo" 0 || \
+        failed=`expr $failed + 1`
+
+    testit "fetch a previous version of a symlink via browsing (2)" \
+        test_fetch_snap_file $share "bar/lfoo" 1 || \
+        failed=`expr $failed + 1`
+
+    testit "fetch a previous version of a symlink via browsing (3)" \
+        test_fetch_snap_file $share "bar/lfoo" 3 || \
+        failed=`expr $failed + 1`
+
+}
+
+#build "latest" files
+build_files $WORKDIR/mount base/share "latest"
+
+failed=0
+
+# a test with wide links allowed - also to verify that what's later
+# being blocked is a result of server security measures and not
+# a testing artifact.
+test_shadow_copy_fixed shadow_wl mount base/share "shadow copies with wide links allowed" 1
+
+# tests for a fixed snapshot location
+test_shadow_copy_fixed shadow1 mount base/share "full volume snapshots mounted under volume"
+test_shadow_copy_fixed shadow2 . base/share "full volume snapshots mounted outside volume"
+test_shadow_copy_fixed shadow3 mount/base share "sub volume snapshots mounted under snapshot point"
+test_shadow_copy_fixed shadow4 . share "sub volume snapshots mounted outside"
+test_shadow_copy_fixed shadow5 mount/base/share "" "full volume snapshots and share mounted under volume"
+test_shadow_copy_fixed shadow6 . "" "full volume snapshots and share mounted outside"
+
+# tests for snapshot everywhere - one snapshot location
+test_shadow_copy_fixed shadow7 mount base/share "'everywhere' full volume snapshots"
+test_shadow_copy_fixed shadow7 mount/base share "'everywhere' sub volume snapshots"
+test_shadow_copy_fixed shadow7 mount/base/share "" "'everywhere' share snapshots"
+
+# a test for snapshots everywhere - multiple snapshot locations
+test_shadow_copy_everywhere shadow7
+
+exit $failed
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 655c593..25d20fe 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -179,6 +179,7 @@ for env in ["fileserver"]:
     plantestsuite("samba3.blackbox.dfree_command (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_dfree_command.sh"), '$SERVER', '$DOMAIN', '$USERNAME', '$PASSWORD', '$PREFIX', smbclient3])
     plantestsuite("samba3.blackbox.valid_users (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_valid_users.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$PREFIX', smbclient3])
     plantestsuite("samba3.blackbox.offline (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_offline.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/offline', smbclient3])
+    plantestsuite("samba3.blackbox.shadow_copy2 (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_shadow_copy.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/shadow', smbclient3])
 
     #
     # tar command tests
-- 
2.4.3



More information about the samba-technical mailing list