From 422302accb8c35f7e7f7aa437a607d4bc29c85a8 Mon Sep 17 00:00:00 2001 From: Anubhav Rakshit Date: Wed, 15 Jul 2020 10:14:52 +0530 Subject: [PATCH] torture: add smbtorture testcase "related7" for failure in compound related chain We want to verify what Windows does when the first request of the chain has failed and an async request is part of the chain. We see Windows fails the async request with the same error. Also the async request is immediately failed. Signed-off-by: Anubhav Rakshit Reviewed-by: Ralph Boehme Reviewed-by: Jeremy Allison --- selftest/knownfail.d/samba3.smb2.compound | 2 + source4/torture/smb2/compound.c | 123 ++++++++++++++++++++++ 2 files changed, 125 insertions(+) diff --git a/selftest/knownfail.d/samba3.smb2.compound b/selftest/knownfail.d/samba3.smb2.compound index 2286f6a682b..f2905ec0025 100644 --- a/selftest/knownfail.d/samba3.smb2.compound +++ b/selftest/knownfail.d/samba3.smb2.compound @@ -1,2 +1,4 @@ ^samba3.smb2.compound.related4 ^samba3.smb2.compound aio.related4 +^samba3.smb2.compound.related7 +^samba3.smb2.compound aio.related7 diff --git a/source4/torture/smb2/compound.c b/source4/torture/smb2/compound.c index bf85fed78b9..13172306c8b 100644 --- a/source4/torture/smb2/compound.c +++ b/source4/torture/smb2/compound.c @@ -730,6 +730,127 @@ static bool test_compound_related6(struct torture_context *tctx, return ret; } +static bool test_compound_related7(struct torture_context *tctx, + struct smb2_tree *tree) +{ + const char *fname = "compound_related4.dat"; + struct security_descriptor *sd = NULL; + struct smb2_handle hd; + struct smb2_create cr; + union smb_setfileinfo set; + struct smb2_notify nt; + struct smb2_close cl; + NTSTATUS status; + struct smb2_request *req[4]; + bool ret = true; + + smb2_util_unlink(tree, fname); + + ZERO_STRUCT(cr); + cr.level = RAW_OPEN_SMB2; + cr.in.create_flags = 0; + cr.in.desired_access = SEC_STD_READ_CONTROL | + SEC_STD_WRITE_DAC | + SEC_STD_WRITE_OWNER; + cr.in.create_options = 0; + cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL; + cr.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE | + NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE; + cr.in.alloc_size = 0; + cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF; + cr.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS; + cr.in.security_flags = 0; + cr.in.fname = fname; + + status = smb2_create(tree, tctx, &cr); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_create failed\n"); + + hd = cr.out.file.handle; + torture_comment(tctx, "set a sec desc allowing no write by CREATOR_OWNER\n"); + sd = security_descriptor_dacl_create(tctx, + 0, NULL, NULL, + SID_CREATOR_OWNER, + SEC_ACE_TYPE_ACCESS_ALLOWED, + SEC_RIGHTS_FILE_READ | SEC_STD_ALL, + 0, + NULL); + torture_assert_not_null_goto(tctx, sd, ret, done, + "security_descriptor_dacl_create failed\n"); + + set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; + set.set_secdesc.in.file.handle = hd; + set.set_secdesc.in.secinfo_flags = SECINFO_DACL; + set.set_secdesc.in.sd = sd; + + status = smb2_setinfo_file(tree, &set); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_setinfo_file failed\n"); + + torture_comment(tctx, "try open for write\n"); + cr.in.desired_access = SEC_FILE_WRITE_DATA; + smb2_transport_compound_start(tree->session->transport, 4); + + req[0] = smb2_create_send(tree, &cr); + torture_assert_not_null_goto(tctx, req[0], ret, done, + "smb2_create_send failed\n"); + + hd.data[0] = UINT64_MAX; + hd.data[1] = UINT64_MAX; + + smb2_transport_compound_set_related(tree->session->transport, true); + + ZERO_STRUCT(nt); + nt.in.recursive = true; + nt.in.buffer_size = 0x1000; + nt.in.file.handle = hd; + nt.in.completion_filter = FILE_NOTIFY_CHANGE_NAME; + nt.in.unknown = 0x00000000; + + req[1] = smb2_notify_send(tree, &nt); + torture_assert_not_null_goto(tctx, req[1], ret, done, + "smb2_notify_send failed\n"); + + ZERO_STRUCT(cl); + cl.in.file.handle = hd; + + req[2] = smb2_close_send(tree, &cl); + torture_assert_not_null_goto(tctx, req[2], ret, done, + "smb2_close_send failed\n"); + + set.set_secdesc.in.file.handle = hd; + + req[3] = smb2_setinfo_file_send(tree, &set); + torture_assert_not_null_goto(tctx, req[3], ret, done, + "smb2_setinfo_file_send failed\n"); + + status = smb2_create_recv(req[0], tree, &cr); + torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED, + ret, done, + "smb2_create_recv failed\n"); + + status = smb2_notify_recv(req[1], tree, &nt); + torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED, + ret, done, + "smb2_notify_recv failed\n"); + + status = smb2_close_recv(req[2], &cl); + torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED, + ret, done, + "smb2_close_recv failed\n"); + + status = smb2_setinfo_recv(req[3]); + torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED, + ret, done, + "smb2_setinfo_recv failed\n"); + +done: + smb2_util_unlink(tree, fname); + smb2_tdis(tree); + smb2_logoff(tree->session); + return ret; +} static bool test_compound_padding(struct torture_context *tctx, struct smb2_tree *tree) { @@ -1731,6 +1852,8 @@ struct torture_suite *torture_smb2_compound_init(TALLOC_CTX *ctx) test_compound_related5); torture_suite_add_1smb2_test(suite, "related6", test_compound_related6); + torture_suite_add_1smb2_test(suite, "related7", + test_compound_related7); torture_suite_add_1smb2_test(suite, "unrelated1", test_compound_unrelated1); torture_suite_add_1smb2_test(suite, "invalid1", test_compound_invalid1); torture_suite_add_1smb2_test(suite, "invalid2", test_compound_invalid2);