diff options
author | Ralph Boehme <slow@samba.org> | 2019-09-23 15:15:01 -0700 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2019-10-16 19:25:11 +0000 |
commit | f5c8dea0ae75e2d24fd3268e2b5b427cb81225c9 (patch) | |
tree | 499850128a5fe5a12e4787881a6c870ec31d052f | |
parent | fc0efd56d0584d8ca950ad837bd19e7341833dbf (diff) | |
download | samba-f5c8dea0ae75e2d24fd3268e2b5b427cb81225c9.tar.gz |
torture:smb2: extend test for File-IDs
This now hopefully covers most possible combinations of creating and opening
files plus, checking the file's File-ID after every operation.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14137
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
(cherry picked from commit 432202413f4d11d761c62f46a50747fcb9b6f0cf)
-rw-r--r-- | selftest/knownfail.d/samba3.smb2.fileid | 1 | ||||
-rw-r--r-- | source4/torture/smb2/create.c | 299 |
2 files changed, 259 insertions, 41 deletions
diff --git a/selftest/knownfail.d/samba3.smb2.fileid b/selftest/knownfail.d/samba3.smb2.fileid new file mode 100644 index 00000000000..89455dacdf0 --- /dev/null +++ b/selftest/knownfail.d/samba3.smb2.fileid @@ -0,0 +1 @@ +^samba3.smb2.fileid.fileid\(nt4_dc\) diff --git a/source4/torture/smb2/create.c b/source4/torture/smb2/create.c index beddefc4c8d..ea83b483491 100644 --- a/source4/torture/smb2/create.c +++ b/source4/torture/smb2/create.c @@ -1919,8 +1919,8 @@ static bool test_fileid(struct torture_context *tctx, struct smb2_find f; unsigned int count; union smb_search_data *d; - uint64_t fileid; - uint64_t stream_fileid; + uint64_t expected_fileid; + uint64_t returned_fileid; NTSTATUS status; bool ret = true; @@ -1930,6 +1930,9 @@ static bool test_fileid(struct torture_context *tctx, torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed\n"); + /* + * Initial create with QFID + */ create = (struct smb2_create) { .in.desired_access = SEC_FILE_ALL, .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, @@ -1943,9 +1946,47 @@ static bool test_fileid(struct torture_context *tctx, torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "test file could not be created\n"); h1 = create.out.file.handle; + expected_fileid = BVAL(&create.out.on_disk_id, 0); + + /* + * Getinfo the File-ID on the just opened 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"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Open existing with QFID + */ + 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, + }; - fileid = BVAL(&create.out.on_disk_id, 0); + 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; + returned_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid, + ret, done, "bad fileid\n"); + /* + * Getinfo the File-ID on the just opened handle + */ finfo = (union smb_fileinfo) { .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, .generic.in.file.handle = h1, @@ -1954,33 +1995,111 @@ static bool test_fileid(struct torture_context *tctx, status = smb2_getinfo_file(tree, tctx, &finfo); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir\n"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Overwrite with QFID + */ + 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, + .in.fname = fname, + .in.query_on_disk_id = true, + }; - torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, + 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; + returned_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, returned_fileid, expected_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, + /* + * Getinfo the File-ID on the open with overwrite handle + */ + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, }; - status = smb2_find_level(tree, tree, &f, &count, &d); + status = smb2_getinfo_file(tree, tctx, &finfo); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, - "smb2_find_level failed\n"); + "torture_smb2_testdir\n"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); - torture_assert_u64_equal_goto(tctx, - d->id_both_directory_info.file_id, - fileid, + /* + * Do some modifications on the basefile (IO, setinfo), verifying + * File-ID after each step. + */ + 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; + + status = smb2_util_write(tree, h1, "foo", 0, strlen("foo")); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_util_write 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, + expected_fileid, ret, done, "bad fileid\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"); smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + /* + * Create stream, check the stream's File-ID, should be the same as the + * base file (sic!, tested against Windows). + */ 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.create_disposition = NTCREATEX_DISP_CREATE, .in.fname = sname, .in.query_on_disk_id = true, }; @@ -1989,11 +2108,13 @@ static bool test_fileid(struct torture_context *tctx, 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, + returned_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid, ret, done, "bad fileid\n"); + /* + * Getinfo the File-ID on the created stream + */ finfo = (union smb_fileinfo) { .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, .generic.in.file.handle = h1, @@ -2002,31 +2123,118 @@ static bool test_fileid(struct torture_context *tctx, status = smb2_getinfo_file(tree, tctx, &finfo); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file failed\n"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Open stream, check the stream's File-ID, should be the same as the + * base file (sic!, tested against Windows). + */ + 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 = sname, + .in.query_on_disk_id = true, + }; - torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, + 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; + returned_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, returned_fileid, expected_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, + /* + * Getinfo the File-ID on the opened stream + */ + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, }; - status = smb2_find_level(tree, tree, &f, &count, &d); + status = smb2_getinfo_file(tree, tctx, &finfo); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, - "smb2_find_level failed\n"); + "smb2_getinfo_file failed\n"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); - torture_assert_u64_equal_goto(tctx, - d->id_both_directory_info.file_id, - fileid, + /* + * Overwrite stream, check the stream's File-ID, should be the same as + * the base file (sic!, tested against Windows). + */ + 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, + .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; + returned_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid, ret, done, "bad fileid\n"); + /* + * Getinfo the File-ID on the overwritten stream + */ + 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"); + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + + /* + * Do some modifications on the stream (IO, setinfo), verifying File-ID + * after earch step. + */ + 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 = 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; + status = smb2_util_write(tree, h1, "foo", 0, strlen("foo")); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write 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, + expected_fileid, + ret, done, "bad fileid\n"); + sinfo = (union smb_setfileinfo) { .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION, .basic_info.in.file.handle = h1, @@ -2041,16 +2249,17 @@ static bool test_fileid(struct torture_context *tctx, .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); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, + ret, done, "bad fileid\n"); + /* + * Final open of the basefile with QFID + */ create = (struct smb2_create) { .in.desired_access = SEC_FILE_ALL, .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, @@ -2064,7 +2273,13 @@ static bool test_fileid(struct torture_context *tctx, torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "test file could not be created\n"); h1 = create.out.file.handle; + returned_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid, + ret, done, "bad fileid\n"); + /* + * Final Getinfo checking File-ID + */ finfo = (union smb_fileinfo) { .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, .generic.in.file.handle = h1, @@ -2073,10 +2288,15 @@ static bool test_fileid(struct torture_context *tctx, 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, + smb2_util_close(tree, h1); + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, + expected_fileid, ret, done, "bad fileid\n"); + /* + * Final list directory, verifying the operations on basefile and stream + * didn't modify the base file metadata. + */ f = (struct smb2_find) { .in.file.handle = testdirh, .in.pattern = "foo", @@ -2088,14 +2308,11 @@ static bool test_fileid(struct torture_context *tctx, 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, + expected_fileid, ret, done, "bad fileid\n"); - smb2_util_close(tree, h1); - done: smb2_util_close(tree, testdirh); smb2_deltree(tree, DNAME); |