From 0318b68675d0318027ff5b6abf4a0d010839e6fd Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 30 Aug 2019 14:49:24 +0200 Subject: s4:torture: add a file-id related test Note I'm using the share vfs_fruit_xattr because I need a share with both a streams and a acl_* VFS object. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit 2ecab3c60abf9baa16a6a5e3eba0fc4720def840) --- selftest/knownfail.d/samba3.smb2.create | 1 + source3/selftest/tests.py | 2 + source4/selftest/tests.py | 1 + source4/torture/smb2/create.c | 212 ++++++++++++++++++++++++++++++++ source4/torture/smb2/smb2.c | 1 + 5 files changed, 217 insertions(+) create mode 100644 selftest/knownfail.d/samba3.smb2.create diff --git a/selftest/knownfail.d/samba3.smb2.create b/selftest/knownfail.d/samba3.smb2.create new file mode 100644 index 00000000000..89455dacdf0 --- /dev/null +++ b/selftest/knownfail.d/samba3.smb2.create @@ -0,0 +1 @@ +^samba3.smb2.fileid.fileid\(nt4_dc\) diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 31cb8ca33f1..20f2eea7661 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -689,6 +689,8 @@ for t in tests: plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD') plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/delete_readonly -U$USERNAME%$PASSWORD --option=torture:delete_readonly=true') plansmbtorture4testsuite(t, "ad_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD') + elif t == "smb2.fileid": + plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/vfs_fruit_xattr -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 bf3dd98cbef..3f55649f217 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -342,6 +342,7 @@ smb2_s3only = [ "smb2.kernel-oplocks", "smb2.durable-v2-delay", "smb2.aio_delay", + "smb2.fileid", ] 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 9b32062ab07..beddefc4c8d 100644 --- a/source4/torture/smb2/create.c +++ b/source4/torture/smb2/create.c @@ -1905,6 +1905,204 @@ done: return ret; } +static bool test_fileid(struct torture_context *tctx, + struct smb2_tree *tree) +{ + TALLOC_CTX *mem_ctx = talloc_new(tctx); + const char *fname = DNAME "\\foo"; + const char *sname = DNAME "\\foo:bar"; + struct smb2_handle testdirh; + struct smb2_handle h1; + struct smb2_create create; + union smb_fileinfo finfo; + union smb_setfileinfo sinfo; + struct smb2_find f; + unsigned int count; + union smb_search_data *d; + uint64_t fileid; + uint64_t stream_fileid; + NTSTATUS status; + bool ret = true; + + smb2_deltree(tree, DNAME); + + status = torture_smb2_testdir(tree, DNAME, &testdirh); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "torture_smb2_testdir failed\n"); + + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OPEN_IF, + .in.fname = fname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + + fileid = BVAL(&create.out.on_disk_id, 0); + + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "torture_smb2_testdir\n"); + + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, + ret, done, "bad fileid\n"); + + f = (struct smb2_find) { + .in.file.handle = testdirh, + .in.pattern = "foo", + .in.max_response_size = 0x1000, + .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO, + }; + + status = smb2_find_level(tree, tree, &f, &count, &d); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_find_level failed\n"); + + torture_assert_u64_equal_goto(tctx, + d->id_both_directory_info.file_id, + fileid, + ret, done, "bad fileid\n"); + + smb2_util_close(tree, h1); + + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF, + .in.fname = sname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + + stream_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, stream_fileid, fileid, + ret, done, "bad fileid\n"); + + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed\n"); + + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, + ret, done, "bad fileid\n"); + + f = (struct smb2_find) { + .in.file.handle = testdirh, + .in.pattern = "foo", + .in.max_response_size = 0x1000, + .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO, + .in.continue_flags = SMB2_CONTINUE_FLAG_RESTART, + }; + + status = smb2_find_level(tree, tree, &f, &count, &d); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_find_level failed\n"); + + torture_assert_u64_equal_goto(tctx, + d->id_both_directory_info.file_id, + fileid, + ret, done, "bad fileid\n"); + + status = smb2_util_write(tree, h1, "foo", 0, strlen("foo")); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_util_write failed\n"); + + sinfo = (union smb_setfileinfo) { + .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION, + .basic_info.in.file.handle = h1, + }; + unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL)); + + status = smb2_setinfo_file(tree, &sinfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_setinfo_file failed\n"); + + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed\n"); + + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, + ret, done, "bad fileid\n"); + + smb2_util_close(tree, h1); + + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OPEN, + .in.fname = fname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "torture_smb2_testdir\n"); + + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, + ret, done, "bad fileid\n"); + + f = (struct smb2_find) { + .in.file.handle = testdirh, + .in.pattern = "foo", + .in.max_response_size = 0x1000, + .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO, + .in.continue_flags = SMB2_CONTINUE_FLAG_RESTART, + }; + + status = smb2_find_level(tree, tree, &f, &count, &d); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_find_level failed\n"); + + torture_assert_u64_equal_goto(tctx, + d->id_both_directory_info.file_id, + fileid, + ret, done, "bad fileid\n"); + + smb2_util_close(tree, h1); + +done: + smb2_util_close(tree, testdirh); + smb2_deltree(tree, DNAME); + talloc_free(mem_ctx); + return ret; +} + /* basic testing of SMB2 read */ @@ -1942,3 +2140,17 @@ struct torture_suite *torture_smb2_twrp_init(TALLOC_CTX *ctx) return suite; } + +/* + basic testing of SMB2 File-IDs +*/ +struct torture_suite *torture_smb2_fileid_init(TALLOC_CTX *ctx) +{ + struct torture_suite *suite = torture_suite_create(ctx, "fileid"); + + torture_suite_add_1smb2_test(suite, "fileid", test_fileid); + + suite->description = talloc_strdup(suite, "SMB2-CREATE tests"); + + return suite; +} diff --git a/source4/torture/smb2/smb2.c b/source4/torture/smb2/smb2.c index e57dba3c1d9..7cca19e65d3 100644 --- a/source4/torture/smb2/smb2.c +++ b/source4/torture/smb2/smb2.c @@ -155,6 +155,7 @@ NTSTATUS torture_smb2_init(TALLOC_CTX *ctx) torture_suite_add_suite(suite, torture_smb2_aio_delay_init(suite)); torture_suite_add_suite(suite, torture_smb2_create_init(suite)); torture_suite_add_suite(suite, torture_smb2_twrp_init(suite)); + torture_suite_add_suite(suite, torture_smb2_fileid_init(suite)); torture_suite_add_suite(suite, torture_smb2_acls_init(suite)); torture_suite_add_suite(suite, torture_smb2_notify_init(suite)); torture_suite_add_suite(suite, torture_smb2_notify_inotify_init(suite)); -- cgit v1.2.1