The Samba-Bugzilla – Attachment 11305 Details for
Bug 11278
Stream names with colon don't work with fruit:encoding = native
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for master
fruit_stream_names.patch (text/plain), 12.16 KB, created by
Ralph Böhme
on 2015-08-04 12:22:07 UTC
(
hide
)
Description:
Patch for master
Filename:
MIME Type:
Creator:
Ralph Böhme
Created:
2015-08-04 12:22:07 UTC
Size:
12.16 KB
patch
obsolete
>From 54db3bf590758c195efb90b74d9f50e2771146c4 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Sat, 9 May 2015 15:02:03 +0200 >Subject: [PATCH 1/3] 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. > >Signed-off-by: Ralph Boehme <slow@samba.org> >--- > source3/modules/vfs_streams_xattr.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c >index d149fc8..0b01f3b 100644 >--- a/source3/modules/vfs_streams_xattr.c >+++ b/source3/modules/vfs_streams_xattr.c >@@ -112,7 +112,7 @@ 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, ':'); >+ stype = strrchr_m(stream_name + 1, ':'); > > if (stype) { > if (strcasecmp_m(stype, ":$DATA") != 0) { >-- >2.1.0 > > >From 6e371bac3fa3d22b8de6577b33a62e74521b03f2 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Sat, 9 May 2015 15:12:41 +0200 >Subject: [PATCH 2/3] 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. > >Signed-off-by: Ralph Boehme <slow@samba.org> >--- > source3/modules/vfs_catia.c | 60 +++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 60 insertions(+) > >diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c >index f2769a9..4fb4ae8 100644 >--- a/source3/modules/vfs_catia.c >+++ b/source3/modules/vfs_catia.c >@@ -710,7 +710,11 @@ catia_streaminfo(struct vfs_handle_struct *handle, > struct stream_struct **streams) > { > char *mapped_name = NULL; >+ char *stream_name = NULL; > NTSTATUS status; >+ int i; >+ struct stream_struct *pstream; >+ size_t sname_len; > > status = catia_string_replace_allocate(handle->conn, path, > &mapped_name, vfs_translate_to_unix); >@@ -723,6 +727,62 @@ catia_streaminfo(struct vfs_handle_struct *handle, > mem_ctx, num_streams,streams); > TALLOC_FREE(mapped_name); > >+ pstream = *streams; >+ /* >+ * 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. We need the string buffer >+ * length, not the glyph count, which is why I call >+ * strlen not strlen_m. >+ */ >+ sname_len = strlen(pstream[i].name + 1); >+ >+ /* Compiler will optimize out strlen(":$DATA") */ >+ if (sname_len < strlen(":$DATA")) { >+ DEBUG(1,("%s: unexpected stream: %s\n", __func__, pstream[i].name)); >+ return NT_STATUS_UNSUCCESSFUL; >+ } >+ if (sname_len == strlen(":$DATA")) { >+ /* >+ * sname_len started at streamname+1 so we >+ * skip the first ':' in the canonical default >+ * stream name "::$DATA" >+ */ >+ continue; >+ } >+ sname_len -= strlen(":$DATA"); >+ if (strcasecmp_m(pstream[i].name + 1 + sname_len, ":$DATA") != 0) { >+ /* We're not expecting any other streamtype then $DATA */ >+ DEBUG(1,("%s: unexpected stream: %s\n", __func__, pstream[i].name)); >+ return NT_STATUS_UNSUCCESSFUL; >+ } >+ stream_name = talloc_strndup(mem_ctx, >+ pstream[i].name + 1, >+ sname_len); >+ if (stream_name == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ status = catia_string_replace_allocate(handle->conn, stream_name, >+ &mapped_name, vfs_translate_to_windows); >+ TALLOC_FREE(stream_name); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ >+ TALLOC_FREE(pstream[i].name); >+ pstream[i].name = talloc_asprintf(mem_ctx, ":%s:$DATA", mapped_name); >+ if (pstream[i].name == NULL) { >+ TALLOC_FREE(mapped_name); >+ return NT_STATUS_NO_MEMORY; >+ } >+ TALLOC_FREE(mapped_name); >+ DEBUG(10,("%s: stream: %s\n", __func__, pstream[i].name)); >+ } >+ > return status; > } > >-- >2.1.0 > > >From 8a6129da688963b251e5b7adc5749d31a6aa44cf Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Sun, 10 May 2015 11:58:32 +0200 >Subject: [PATCH 3/3] s4:torture:vfs_fruit: add a test for stream names > >Signed-off-by: Ralph Boehme <slow@samba.org> >--- > source4/torture/vfs/fruit.c | 221 ++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 221 insertions(+) > >diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c >index 4de21b2..8f34845 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? >@@ -2163,6 +2174,215 @@ 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; >+ bool ret = false; >+ >+ finfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION; >+ finfo.generic.in.file.handle = h; >+ >+ status = smb2_getinfo_file(tree, tctx, &finfo); >+ if (!NT_STATUS_IS_OK(status)) { >+ torture_comment(tctx, "(%s) smb_raw_pathinfo failed: %s\n", >+ __location__, nt_errstr(status)); >+ goto fail; >+ } >+ >+ if (finfo.stream_info.out.num_streams != num_exp) { >+ torture_comment(tctx, "(%s) expected %d streams, got %d\n", >+ __location__, num_exp, finfo.stream_info.out.num_streams); >+ goto fail; >+ } >+ >+ if (num_exp == 0) { >+ ret = true; >+ goto fail; >+ } >+ >+ exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp)); >+ >+ if (exp_sort == NULL) { >+ goto fail; >+ } >+ >+ 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)); >+ >+ if (stream_sort == NULL) { >+ goto fail; >+ } >+ >+ TYPESAFE_QSORT(stream_sort, finfo.stream_info.out.num_streams, qsort_stream); >+ >+ for (i=0; i<num_exp; i++) { >+ torture_comment(tctx, "%s ... %s\n", exp_sort[i], stream_sort[i].stream_name.s); >+ if (strcmp(exp_sort[i], stream_sort[i].stream_name.s) != 0) { >+ torture_comment(tctx, >+ "(%s) expected stream name %s, got %s\n", >+ __location__, exp_sort[i], >+ stream_sort[i].stream_name.s); >+ goto fail; >+ } >+ } >+ >+ ret = true; >+ fail: >+ talloc_free(tmp_ctx); >+ return ret; >+} >+ >+/* >+ test stream names >+*/ >+static bool test_stream_names(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ NTSTATUS status; >+ union smb_open io; >+ const char *fname = BASEDIR "\\stream_names.txt"; >+ const char *sname1, *sname1b, *sname1c, *sname1d; >+ const char *sname2, *snamew, *snamew2, *sname3; >+ bool ret = true; >+ struct smb2_handle h, h1, h2, h3, h4; >+ /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */ >+ const char *streams[] = { >+ "::$DATA", >+ ":\xef\x80\x85Stream\xef\x80\x8a One:$DATA", >+ ":MStream Two:$DATA", >+ ":\xef\x80\xa5Stream\xef\x80\xa1:$DATA", >+ ":foo\xef\x80\xa2" "bar:$DATA" >+ }; >+ >+ sname1 = talloc_asprintf(mem_ctx, "%s:%s", fname, "\x05Stream\n One"); >+ sname1b = talloc_asprintf(mem_ctx, "%s:", sname1); >+ sname1c = talloc_asprintf(mem_ctx, "%s:$FOO", sname1); >+ sname1d = talloc_asprintf(mem_ctx, "%s:?D*a", sname1); >+ sname2 = talloc_asprintf(mem_ctx, "%s:%s:$DaTa", fname, "MStream Two"); >+ snamew = talloc_asprintf(mem_ctx, "%s:%s:$DATA", fname, "?Stream*"); >+ snamew2 = talloc_asprintf(mem_ctx, "%s\\stream*:%s:$DATA", BASEDIR, >+ "?Stream*"); >+ sname3 = talloc_asprintf(mem_ctx, "%s:foo\xef\x80\xa2" "bar:$data", fname); >+ >+ /* clean slate ...*/ >+ smb2_util_unlink(tree, fname); >+ smb2_deltree(tree, fname); >+ smb2_deltree(tree, BASEDIR); >+ >+ status = torture_smb2_testdir(tree, BASEDIR, &h); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ torture_comment(tctx, "(%s) testing stream names\n", __location__); >+ ZERO_STRUCT(io.smb2); >+ io.smb2.in.create_flags = 0; >+ io.smb2.in.desired_access = SEC_FILE_WRITE_DATA; >+ io.smb2.in.create_options = 0; >+ io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ io.smb2.in.share_access = 0; >+ io.smb2.in.alloc_size = 0; >+ io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; >+ io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; >+ io.smb2.in.security_flags = 0; >+ io.smb2.in.fname = sname1; >+ >+ status = smb2_create(tree, mem_ctx, &(io.smb2)); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h1 = io.smb2.out.file.handle; >+ >+ /* >+ * A different stream does not give a sharing violation >+ */ >+ >+ io.smb2.in.fname = sname2; >+ io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF; >+ status = smb2_create(tree, mem_ctx, &(io.smb2)); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h2 = io.smb2.out.file.handle; >+ >+ /* >+ * ... whereas the same stream does with unchanged access/share_access >+ * flags >+ */ >+ >+ io.smb2.in.fname = sname1; >+ io.smb2.in.create_disposition = NTCREATEX_DISP_SUPERSEDE; >+ status = smb2_create(tree, mem_ctx, &(io.smb2)); >+ CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION); >+ >+ io.smb2.in.fname = sname1b; >+ status = smb2_create(tree, mem_ctx, &(io.smb2)); >+ CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); >+ >+ io.smb2.in.fname = sname1c; >+ status = smb2_create(tree, mem_ctx, &(io.smb2)); >+ if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) { >+ /* w2k returns INVALID_PARAMETER */ >+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); >+ } else { >+ CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); >+ } >+ >+ io.smb2.in.fname = sname1d; >+ status = smb2_create(tree, mem_ctx, &(io.smb2)); >+ if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) { >+ /* w2k returns INVALID_PARAMETER */ >+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); >+ } else { >+ CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); >+ } >+ >+ io.smb2.in.fname = sname2; >+ status = smb2_create(tree, mem_ctx, &(io.smb2)); >+ CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION); >+ >+ io.smb2.in.fname = snamew; >+ status = smb2_create(tree, mem_ctx, &(io.smb2)); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h3 = io.smb2.out.file.handle; >+ >+ io.smb2.in.fname = sname3; >+ status = smb2_create(tree, mem_ctx, &(io.smb2)); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h4 = io.smb2.out.file.handle; >+ >+ io.smb2.in.fname = snamew2; >+ status = smb2_create(tree, mem_ctx, &(io.smb2)); >+ CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); >+ >+ io.smb2.in.fname = fname; >+ io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN; >+ status = smb2_create(tree, mem_ctx, &(io.smb2)); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ ret &= check_stream_list(tree, tctx, fname, 5, streams, >+ io.smb2.out.file.handle); >+ >+ smb2_util_close(tree, h1); >+ smb2_util_close(tree, h2); >+ smb2_util_close(tree, h3); >+ smb2_util_close(tree, h4); >+ >+done: >+ status = smb2_util_unlink(tree, fname); >+ smb2_deltree(tree, BASEDIR); >+ talloc_free(mem_ctx); >+ >+ return ret; >+} >+ > /* > * Note: This test depends on "vfs objects = catia fruit > * streams_xattr". Note: To run this test, use >@@ -2183,6 +2403,7 @@ struct torture_suite *torture_vfs_fruit(void) > torture_suite_add_2ns_smb2_test(suite, "resource fork IO", test_write_atalk_rfork_io); > torture_suite_add_2ns_smb2_test(suite, "OS X AppleDouble file conversion", test_adouble_conversion); > torture_suite_add_2ns_smb2_test(suite, "SMB2/CREATE context AAPL", test_aapl); >+ torture_suite_add_1smb2_test(suite, "stream names", test_stream_names); > > return suite; > } >-- >2.1.0 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 11278
:
11305
|
11316
|
11325
|
11326