[SCM] Samba Shared Repository - branch master updated

Michael Adam obnox at samba.org
Wed Jan 13 16:12:02 UTC 2016


The branch, master has been updated
       via  7362c27 vfs_shadow_copy2: add a blackbox test suite
       via  8a49a63 vfs_shadow_copy2: fix case where snapshots are outside the share
       via  3703bca vfs_shadow_copy2: add shadow_copy2_do_convert()
      from  fba90fd s3:smbd_smb2_reauth_generic_return: make use of smb2req->xconn

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 7362c27a62e3802fc8df975ce50115b683811f4a
Author: Uri Simchoni <uri at samba.org>
Date:   Thu Oct 29 22:24:30 2015 +0200

    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>
    Reviewed-by: Michael Adam <obnox at samba.org>
    
    Autobuild-User(master): Michael Adam <obnox at samba.org>
    Autobuild-Date(master): Wed Jan 13 17:11:38 CET 2016 on sn-devel-144

commit 8a49a63a5a5d8014d32179df1789186223443b35
Author: Uri Simchoni <uri at samba.org>
Date:   Mon Nov 2 09:08:53 2015 +0200

    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>
    Reviewed-by: Michael Adam <obnox at samba.org>

commit 3703bca4d9e494aec0b40243add3e076cf353601
Author: Uri Simchoni <uri at samba.org>
Date:   Sun Nov 1 22:28:46 2015 +0200

    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, i.e. (at least in the
    classical case) the subdirectory of the the snapshot file's
    snapshot directory that corresponds to the file's share root.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11580
    
    Signed-off-by: Uri Simchoni <uri at samba.org>
    Reviewed-by: Michael Adam <obnox at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 selftest/target/Samba3.pm                |  69 ++++++++
 source3/modules/vfs_shadow_copy2.c       | 107 +++++++++---
 source3/script/tests/test_shadow_copy.sh | 290 +++++++++++++++++++++++++++++++
 source3/selftest/tests.py                |   1 +
 4 files changed, 441 insertions(+), 26 deletions(-)
 create mode 100755 source3/script/tests/test_shadow_copy.sh


Changeset truncated at 500 lines:

diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 0906620..cd293a6 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -1126,6 +1126,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";
@@ -1392,6 +1401,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
@@ -1553,6 +1566,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/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
index 93bca9c..018ec88 100644
--- a/source3/modules/vfs_shadow_copy2.c
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -434,10 +434,13 @@ 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 path in the snapshot corresponding
+ * to the 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 +450,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 +496,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 +511,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 +587,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 +604,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 +643,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
@@ -1103,8 +1134,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,
@@ -1121,29 +1150,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;
@@ -1777,6 +1786,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)
@@ -2079,6 +2133,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);
diff --git a/source3/script/tests/test_shadow_copy.sh b/source3/script/tests/test_shadow_copy.sh
new file mode 100755
index 0000000..eecd5b8
--- /dev/null
+++ b/source3/script/tests/test_shadow_copy.sh
@@ -0,0 +1,290 @@
+#!/bin/bash
+#
+# 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()


-- 
Samba Shared Repository



More information about the samba-cvs mailing list