The branch, master has been updated via cc9ba98 selftest: add a test for accessing previous version of directories with snapdirseverywhere via b886a94 s3/smbd: let non_widelink_open() chdir() to directories directly from 4b3de61 ldb/tests: more thoroughly test empty ldb_msg elements
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit cc9ba98c08665e0ed6927fd81fa43a7bb7842e45 Author: Ralph Boehme <s...@samba.org> Date: Fri Jul 7 13:12:19 2017 +0200 selftest: add a test for accessing previous version of directories with snapdirseverywhere Bug: https://bugzilla.samba.org/show_bug.cgi?id=12885 Signed-off-by: Ralph Boehme <s...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Autobuild-User(master): Ralph Böhme <s...@samba.org> Autobuild-Date(master): Sat Jul 8 00:33:51 CEST 2017 on sn-devel-144 commit b886a9443d49f6e27fa3863d87c9e24d12e62874 Author: Ralph Boehme <s...@samba.org> Date: Fri Jul 7 12:57:57 2017 +0200 s3/smbd: let non_widelink_open() chdir() to directories directly If the caller passes O_DIRECTORY we just try to chdir() to smb_fname directly, not to the parent directory. The security check in check_reduced_name() will continue to work, but this fixes the case of an open() for a previous version of a subdirectory that contains snapshopt. Eg: [share] path = /shares/test vfs objects = shadow_copy2 shadow:snapdir = .snapshots shadow:snapdirseverywhere = yes Directory tree with fake snapshots: $ tree -a /shares/test/ /shares/test/ ├── dir │ ├── file │ └── .snapshots │ └── @GMT-2017.07.04-04.30.12 │ └── file ├── dir2 │ └── file ├── file ├── .snapshots │ └── @GMT-2001.01.01-00.00.00 │ ├── dir2 │ │ └── file │ └── file └── testfsctl.dat ./bin/smbclient -U slow%x //localhost/share -c 'ls @GMT-2017.07.04-04.30.12/dir/*' NT_STATUS_OBJECT_NAME_NOT_FOUND listing \@GMT-2017.07.04-04.30.12\dir\* Bug: https://bugzilla.samba.org/show_bug.cgi?id=12885 Signed-off-by: Ralph Boehme <s...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> ----------------------------------------------------------------------- Summary of changes: source3/script/tests/test_shadow_copy.sh | 23 +++++++++++++++++++++++ source3/smbd/open.c | 30 +++++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 5 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/script/tests/test_shadow_copy.sh b/source3/script/tests/test_shadow_copy.sh index 783e7f32..eba873f 100755 --- a/source3/script/tests/test_shadow_copy.sh +++ b/source3/script/tests/test_shadow_copy.sh @@ -221,6 +221,26 @@ test_fetch_snap_file() -c "get ${SNAPSHOTS[$snapidx]}/$path $WORKDIR/foo" } +# Test fetching a previous version of a file +test_fetch_snap_dir() +{ + local share + local path + local snapidx + + share=$1 + path=$2 + snapidx=$3 + + # This first command is not strictly needed, but it causes the snapshots to + # appear in a network trace which helps debugging... + $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP \ + -c "allinfo $path" + + $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP \ + -c "ls ${SNAPSHOTS[$snapidx]}/$path/*" +} + test_shadow_copy_fixed() { local share #share to contact @@ -329,6 +349,9 @@ test_shadow_copy_everywhere() test_fetch_snap_file $share "bar/lfoo" 3 || \ failed=`expr $failed + 1` + testit "list a previous version directory" \ + test_fetch_snap_dir $share "bar" 6 || \ + failed=`expr $failed + 1` } test_shadow_copy_format() diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3ccee36..7781a6f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -550,12 +550,32 @@ static int non_widelink_open(struct connection_struct *conn, char *parent_dir = NULL; struct smb_filename parent_dir_fname = {0}; const char *final_component = NULL; + bool is_directory = false; + bool ok; - if (!parent_dirname(talloc_tos(), - smb_fname->base_name, - &parent_dir, - &final_component)) { - goto out; +#ifdef O_DIRECTORY + if (flags & O_DIRECTORY) { + is_directory = true; + } +#endif + + if (is_directory) { + parent_dir = talloc_strdup(talloc_tos(), smb_fname->base_name); + if (parent_dir == NULL) { + saved_errno = errno; + goto out; + } + + final_component = "."; + } else { + ok = parent_dirname(talloc_tos(), + smb_fname->base_name, + &parent_dir, + &final_component); + if (!ok) { + saved_errno = errno; + goto out; + } } parent_dir_fname = (struct smb_filename) { .base_name = parent_dir }; -- Samba Shared Repository