From 318ee3f9625084097cd34cbd7011c5762f3f2b4a 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 (cherry picked from commit 3dcdab86f13fabb7a8c6ce71c59a565287d11244) --- .../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 afb326029dc8..7e122cdcf4ea 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -1080,6 +1080,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 df712ec00208..54906ae589c9 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -389,6 +389,7 @@ smb2_s3only = [ "smb2.async_dosmode", "smb2.twrp", "smb2.ea", + "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 9277488e9d7f..9357528909e2 100644 --- a/source4/torture/smb2/create.c +++ b/source4/torture/smb2/create.c @@ -3979,3 +3979,51 @@ struct torture_suite *torture_smb2_bench_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 85c51c2e8907..21e03360cd9c 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_ea(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 fb03a641d60bbec86753e81e1b366a40a3ca591a 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 3dd9f69b8ccd..c24c55d6a76b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -6310,7 +6310,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 5b5527c2fa8a99c6e2218b8a2b47368eee8db285 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 2 Sep 2022 11:46:53 +0200 Subject: [PATCH 3/3] smbd: Catch streams on non-stream shares MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BUG: https://bugzilla.samba.org/show_bug.cgi?id=15126 BUG: https://bugzilla.samba.org/show_bug.cgi?id=15161 Signed-off-by: Volker Lendecke Reviewed-by: Ralph Boehme Autobuild-User(master): Ralph Böhme Autobuild-Date(master): Fri Sep 2 15:56:56 UTC 2022 on sn-devel-184 (cherry picked from commit 3a37e4155c3cd82388652f89b611f2c46fee8525) --- selftest/knownfail.d/samba3.smb2.create_no_streams | 1 - source3/smbd/filename.c | 6 ++++++ source3/smbd/files.c | 10 ++++++++-- 3 files changed, 14 insertions(+), 3 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 ca94b7ec7f96..0be8e320ffa0 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -1120,6 +1120,12 @@ static NTSTATUS filename_convert_dirfsp_nosymlink( goto fail; } + if ((streamname != NULL) && + ((conn->fs_capabilities & FILE_NAMED_STREAMS) == 0)) { + status = NT_STATUS_OBJECT_NAME_INVALID; + goto fail; + } + if (!posix) { bool name_has_wild = ms_has_wild(dirname); name_has_wild |= ms_has_wild(fname_rel); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index b494a8b789ae..179c3e11a76b 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -565,8 +565,14 @@ NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp, return NT_STATUS_OK; } - if (!(conn->fs_capabilities & FILE_NAMED_STREAMS) || - !is_named_stream(smb_fname)) { + if (is_named_stream(smb_fname) && + ((conn->fs_capabilities & FILE_NAMED_STREAMS) == 0)) { + DBG_DEBUG("stream open [%s] on non-stream share\n", + smb_fname_str_dbg(smb_fname)); + return NT_STATUS_OBJECT_NAME_INVALID; + } + + if (!is_named_stream(smb_fname)) { /* * openat_pathref_fullname() will make "full_fname" a * talloc child of the smb_fname->fsp. Don't use -- 2.37.2