From 33be5308a311f736ce9538af5a3999b44616b0e2 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Sat, 9 May 2015 15:02:03 +0200 Subject: [PATCH 1/4] vfs_streams_xattr: stream names may contain colons With vfs_fruit option "fruit:encoding = native" we're already converting stream names that contain illegal NTFS characters from their on-the-wire Unicode Private Range encoding to their native ASCII representation. As as result the name of xattrs storing the streams (via vfs_streams_xattr) may contain a colon, so we have to use strrchr_m() instead of strchr_m() for matching the stream type suffix. Bug: https://bugzilla.samba.org/show_bug.cgi?id=11278 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit fb9a64ea37dd4b0cd754fe6d421417a4c8ccbc57) --- source3/modules/vfs_streams_xattr.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c index d149fc8..92bd1c9 100644 --- a/source3/modules/vfs_streams_xattr.c +++ b/source3/modules/vfs_streams_xattr.c @@ -112,7 +112,21 @@ static NTSTATUS streams_xattr_get_name(vfs_handle_struct *handle, SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config, return NT_STATUS_UNSUCCESSFUL); - stype = strchr_m(stream_name + 1, ':'); + /* + * With vfs_fruit option "fruit:encoding = native" we're + * already converting stream names that contain illegal NTFS + * characters from their on-the-wire Unicode Private Range + * encoding to their native ASCII representation. + * + * As as result the name of xattrs storing the streams (via + * vfs_streams_xattr) may contain a colon, so we have to use + * strrchr_m() instead of strchr_m() for matching the stream + * type suffix. + * + * In check_path_syntax() we've already ensured the streamname + * we got from the client is valid. + */ + stype = strrchr_m(stream_name + 1, ':'); if (stype) { if (strcasecmp_m(stype, ":$DATA") != 0) { -- 2.1.0 From 515a2f0515ee9cf123225ed5b75df317dbd872b2 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Sat, 9 May 2015 15:12:41 +0200 Subject: [PATCH 2/4] vfs_catia: run translation on stream names With vfs_fruit option "fruit:encoding = native" we're already converting stream names that contain illegal NTFS characters from their on-the-wire Unicode Private Range encoding to their native ASCII representation. Unfortunately the reverse mapping for stream names was not perfomed. Bug: https://bugzilla.samba.org/show_bug.cgi?id=11278 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit 1db11998bf1b0eef5f543377700b03ab8739338d) --- source3/modules/vfs_catia.c | 58 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c index f2769a9..f455afd 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/modules/vfs_catia.c @@ -706,11 +706,17 @@ catia_streaminfo(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *path, TALLOC_CTX *mem_ctx, - unsigned int *num_streams, - struct stream_struct **streams) + unsigned int *_num_streams, + struct stream_struct **_streams) { char *mapped_name = NULL; NTSTATUS status; + int i; + unsigned int num_streams = 0; + struct stream_struct *streams = NULL; + + *_num_streams = 0; + *_streams = NULL; status = catia_string_replace_allocate(handle->conn, path, &mapped_name, vfs_translate_to_unix); @@ -720,10 +726,54 @@ catia_streaminfo(struct vfs_handle_struct *handle, } status = SMB_VFS_NEXT_STREAMINFO(handle, fsp, mapped_name, - mem_ctx, num_streams,streams); + mem_ctx, &num_streams, &streams); TALLOC_FREE(mapped_name); + if (!NT_STATUS_IS_OK(status)) { + return status; + } - return status; + /* + * Translate stream names just like the base names + */ + for (i = 0; i < num_streams; i++) { + /* + * Strip ":" prefix and ":$DATA" suffix to get a + * "pure" stream name and only translate that. + */ + void *old_ptr = streams[i].name; + char *stream_name = streams[i].name + 1; + char *stream_type = strrchr_m(stream_name, ':'); + + if (stream_type != NULL) { + *stream_type = '\0'; + stream_type += 1; + } + + status = catia_string_replace_allocate(handle->conn, stream_name, + &mapped_name, vfs_translate_to_windows); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(streams); + return status; + } + + if (stream_type != NULL) { + streams[i].name = talloc_asprintf(streams, ":%s:%s", + mapped_name, stream_type); + } else { + streams[i].name = talloc_asprintf(streams, ":%s", + mapped_name); + } + TALLOC_FREE(mapped_name); + TALLOC_FREE(old_ptr); + if (streams[i].name == NULL) { + TALLOC_FREE(streams); + return NT_STATUS_NO_MEMORY; + } + } + + *_num_streams = num_streams; + *_streams = streams; + return NT_STATUS_OK; } static NTSTATUS -- 2.1.0 From 33c34c16bfc3539c1e6de347bbec9eb7982e8a30 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 6 Aug 2015 13:48:54 +0200 Subject: [PATCH 3/4] s4:torture:vfs_fruit: pass xattr name as arg to torture_setup_local_xattr() Bug: https://bugzilla.samba.org/show_bug.cgi?id=11278 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit fe4909f1cab72f80715a996a63290462102aabc6) --- source4/torture/vfs/fruit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c index 4de21b2..87102be 100644 --- a/source4/torture/vfs/fruit.c +++ b/source4/torture/vfs/fruit.c @@ -1060,6 +1060,7 @@ static bool write_stream(struct smb2_tree *tree, static bool torture_setup_local_xattr(struct torture_context *tctx, const char *path_option, const char *name, + const char *xattr, const char *metadata, size_t size) { @@ -1076,7 +1077,7 @@ static bool torture_setup_local_xattr(struct torture_context *tctx, path = talloc_asprintf(tctx, "%s/%s", spath, name); - result = setxattr(path, AFPINFO_EA_NETATALK, metadata, size, 0); + result = setxattr(path, xattr, metadata, size, 0); if (result != 0) { ret = false; } @@ -1195,6 +1196,7 @@ static bool test_read_atalk_metadata(struct torture_context *tctx, ret = torture_setup_local_xattr(tctx, "localdir", BASEDIR "/torture_read_metadata", + AFPINFO_EA_NETATALK, metadata_xattr, sizeof(metadata_xattr)); if (ret == false) { goto done; -- 2.1.0 From c1b225f6124a816f436e49006c85caa0077fcea9 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Sun, 10 May 2015 11:58:32 +0200 Subject: [PATCH 4/4] s4:torture:vfs_fruit: add a test for stream names Bug: https://bugzilla.samba.org/show_bug.cgi?id=11278 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit 7258061e5e9cd4b68f1c010c3667c3fd2b0663cc) --- selftest/target/Samba3.pm | 3 +- selftest/target/Samba4.pm | 3 +- source4/torture/vfs/fruit.c | 139 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 2 deletions(-) diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 9af8faa..d48dbec 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1446,7 +1446,8 @@ sub provision($$$$$$$$) [vfs_fruit] path = $shrdir - vfs objects = catia fruit streams_xattr + vfs objects = catia fruit streams_xattr acl_xattr + ea support = yes fruit:ressource = file fruit:metadata = netatalk fruit:locking = netatalk diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 8e7ac94..16d4b28 100755 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -1070,7 +1070,8 @@ sub provision($$$$$$$$$$) [vfs_fruit] path = $ctx->{share} - vfs objects = catia fruit streams_xattr + vfs objects = catia fruit streams_xattr acl_xattr + ea support = yes fruit:ressource = file fruit:metadata = netatalk fruit:locking = netatalk diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c index 87102be..a74dd7d 100644 --- a/source4/torture/vfs/fruit.c +++ b/source4/torture/vfs/fruit.c @@ -29,6 +29,7 @@ #include "param/param.h" #include "libcli/resolve/resolve.h" #include "MacExtensions.h" +#include "lib/util/tsort.h" #include "torture/torture.h" #include "torture/util.h" @@ -58,6 +59,16 @@ goto done; \ }} while (0) +static int qsort_string(char * const *s1, char * const *s2) +{ + return strcmp(*s1, *s2); +} + +static int qsort_stream(const struct stream_struct * s1, const struct stream_struct *s2) +{ + return strcmp(s1->stream_name.s, s2->stream_name.s); +} + /* * REVIEW: * This is hokey, but what else can we do? @@ -2165,6 +2176,133 @@ done: return true; } +static bool check_stream_list(struct smb2_tree *tree, + struct torture_context *tctx, + const char *fname, + int num_exp, + const char **exp, + struct smb2_handle h) +{ + union smb_fileinfo finfo; + NTSTATUS status; + int i; + TALLOC_CTX *tmp_ctx = talloc_new(tctx); + char **exp_sort; + struct stream_struct *stream_sort; + + finfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION; + finfo.generic.in.file.handle = h; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok(tctx, status, "get stream info"); + + torture_assert_int_equal(tctx, finfo.stream_info.out.num_streams, num_exp, + "stream count"); + + if (num_exp == 0) { + TALLOC_FREE(tmp_ctx); + return true; + } + + exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp)); + torture_assert(tctx, exp_sort != NULL, __location__); + + TYPESAFE_QSORT(exp_sort, num_exp, qsort_string); + + stream_sort = talloc_memdup(tmp_ctx, finfo.stream_info.out.streams, + finfo.stream_info.out.num_streams * + sizeof(*stream_sort)); + torture_assert(tctx, stream_sort != NULL, __location__); + + TYPESAFE_QSORT(stream_sort, finfo.stream_info.out.num_streams, qsort_stream); + + for (i=0; i