From 50ff90c6afac4158a0ee63c67438b39454d1e223 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 1 Sep 2022 18:55:23 +0200 Subject: [PATCH 1/3] smbtorture: add a test trying to create a stream on share without streams support BUG: https://bugzilla.samba.org/show_bug.cgi?id=15126 BUG: https://bugzilla.samba.org/show_bug.cgi?id=15161 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (backported from commit 3dcdab86f13fabb7a8c6ce71c59a565287d11244) [slow@samba.org: context changes from different tests] --- .../knownfail.d/samba3.smb2.create_no_streams | 1 + source3/selftest/tests.py | 2 + source4/selftest/tests.py | 1 + source4/torture/smb2/create.c | 48 +++++++++++++++++++ source4/torture/smb2/smb2.c | 1 + 5 files changed, 53 insertions(+) create mode 100644 selftest/knownfail.d/samba3.smb2.create_no_streams diff --git a/selftest/knownfail.d/samba3.smb2.create_no_streams b/selftest/knownfail.d/samba3.smb2.create_no_streams new file mode 100644 index 000000000000..c8476081f2da --- /dev/null +++ b/selftest/knownfail.d/samba3.smb2.create_no_streams @@ -0,0 +1 @@ +^samba3.smb2.create_no_streams.no_stream\(fileserver\) diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index bec30df50b18..c9384403ba5d 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -1027,6 +1027,8 @@ tests = base + raw + smb2 + rpc + unix + local + rap + nbt + idmap + vfs elif t == "smb2.twrp": # This is being driven by samba3.blackbox.shadow_copy_torture pass + elif t == "smb2.create_no_streams": + plansmbtorture4testsuite(t, "fileserver", '//$SERVER_IP/nfs4acl_simple_40 -U$USERNAME%$PASSWORD') elif t == "rpc.wkssvc": plansmbtorture4testsuite(t, "ad_member", '//$SERVER/tmp -U$DC_USERNAME%$DC_PASSWORD') elif t == "rpc.srvsvc": diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 3af8e92d7f2b..576834bfd911 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -381,6 +381,7 @@ smb2_s3only = [ "smb2.timestamps", "smb2.async_dosmode", "smb2.twrp", + "smb2.create_no_streams", ] smb2 = [x for x in smbtorture4_testsuites("smb2.") if x not in smb2_s3only] diff --git a/source4/torture/smb2/create.c b/source4/torture/smb2/create.c index 09eab3f13310..94dbae917fd2 100644 --- a/source4/torture/smb2/create.c +++ b/source4/torture/smb2/create.c @@ -3196,3 +3196,51 @@ struct torture_suite *torture_smb2_fileid_unique_init(TALLOC_CTX *ctx) return suite; } + +static bool test_no_stream(struct torture_context *tctx, + struct smb2_tree *tree) +{ + struct smb2_create c; + NTSTATUS status; + bool ret = true; + const char *names[] = { + "test_no_stream::$DATA", + "test_no_stream::foooooooooooo", + "test_no_stream:stream", + "test_no_stream:stream:$DATA", + NULL + }; + int i; + + for (i = 0; names[i] != NULL; i++) { + c = (struct smb2_create) { + .in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OPEN, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.fname = names[i], + }; + + status = smb2_create(tree, tctx, &c); + if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_INVALID)) { + torture_comment( + tctx, "Expected NT_STATUS_OBJECT_NAME_INVALID, " + "got %s, name: '%s'\n", + nt_errstr(status), names[i]); + torture_fail_goto(tctx, done, "Bad create result\n"); + } + } +done: + return ret; +} + +struct torture_suite *torture_smb2_create_no_streams_init(TALLOC_CTX *ctx) +{ + struct torture_suite *suite = torture_suite_create(ctx, "create_no_streams"); + + torture_suite_add_1smb2_test(suite, "no_stream", test_no_stream); + + suite->description = talloc_strdup(suite, "SMB2-CREATE stream test on share without streams support"); + + return suite; +} diff --git a/source4/torture/smb2/smb2.c b/source4/torture/smb2/smb2.c index 3c69d8c7fa0b..1d9b7d5573f4 100644 --- a/source4/torture/smb2/smb2.c +++ b/source4/torture/smb2/smb2.c @@ -215,6 +215,7 @@ NTSTATUS torture_smb2_init(TALLOC_CTX *ctx) torture_suite_add_1smb2_test(suite, "session-id", run_sessidtest); torture_suite_add_suite(suite, torture_smb2_deny_init(suite)); torture_suite_add_suite(suite, torture_smb2_fileid_unique_init(suite)); + torture_suite_add_suite(suite, torture_smb2_create_no_streams_init(suite)); suite->description = talloc_strdup(suite, "SMB2-specific tests"); -- 2.37.2 From 8260aba4f9f16e9382497c7df7e7eb39472efba4 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 2 Sep 2022 12:09:53 +0200 Subject: [PATCH 2/3] smbd: return NT_STATUS_OBJECT_NAME_INVALID if a share doesn't support streams This is what a Windows server returns. Tested with a share residing on a FAT formatted drive, a Windows filesystem that doesn't support streams. Combinations tested: file::$DATA file:stream file:stream:$DATA All three fail with NT_STATUS_OBJECT_NAME_INVALID. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15126 BUG: https://bugzilla.samba.org/show_bug.cgi?id=15161 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (cherry picked from commit 201e1969bf31af07e8bd52876ff7f4d72b48a848) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7cc7f3b0678a..7e5e59921698 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -6224,7 +6224,7 @@ NTSTATUS create_file_default(connection_struct *conn, } if (!(conn->fs_capabilities & FILE_NAMED_STREAMS)) { - status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + status = NT_STATUS_OBJECT_NAME_INVALID; goto fail; } } -- 2.37.2 From c5542ba182738503812de7f02a3b0a561d2e99e5 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 1 Sep 2022 18:55:52 +0200 Subject: [PATCH 3/3] smbd: check for streams support in unix_convert() Fixes a regression introduced by the fixes for bug 15126 where we crash in vfs_default in vfswrap_stat(): assert failed: !is_named_stream(smb_fname) The frontend calls into the VFS from build_stream_path() with a stream path without checking if the share supports streams. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15126 BUG: https://bugzilla.samba.org/show_bug.cgi?id=15161 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke [slow@samba.org: change from master adapted for unix_convert()] --- selftest/knownfail.d/samba3.smb2.create_no_streams | 1 - source3/smbd/filename.c | 9 ++++++++- 2 files changed, 8 insertions(+), 2 deletions(-) delete mode 100644 selftest/knownfail.d/samba3.smb2.create_no_streams diff --git a/selftest/knownfail.d/samba3.smb2.create_no_streams b/selftest/knownfail.d/samba3.smb2.create_no_streams deleted file mode 100644 index c8476081f2da..000000000000 --- a/selftest/knownfail.d/samba3.smb2.create_no_streams +++ /dev/null @@ -1 +0,0 @@ -^samba3.smb2.create_no_streams.no_stream\(fileserver\) diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 9146bf07ddc6..c5be83665886 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -1067,7 +1067,14 @@ NTSTATUS unix_convert(TALLOC_CTX *mem_ctx, state->stream = strchr_m(state->smb_fname->base_name, ':'); if (state->stream != NULL) { - char *tmp = talloc_strdup(state->smb_fname, state->stream); + char *tmp = NULL; + + if (!(conn->fs_capabilities & FILE_NAMED_STREAMS)) { + status = NT_STATUS_OBJECT_NAME_INVALID; + goto err; + } + + tmp = talloc_strdup(state->smb_fname, state->stream); if (tmp == NULL) { status = NT_STATUS_NO_MEMORY; goto err; -- 2.37.2