1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-28 01:58:17 +03:00

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>
This commit is contained in:
Ralph Boehme 2019-09-23 15:15:01 -07:00
parent 84fae0ed1b
commit 432202413f
2 changed files with 280 additions and 62 deletions

View File

@ -0,0 +1 @@
^samba3.smb2.fileid.fileid\(nt4_dc\)

View File

@ -1927,8 +1927,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;
@ -1938,6 +1938,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,
@ -1951,9 +1954,11 @@ 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);
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,
@ -1962,34 +1967,93 @@ 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,
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);
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_OVERWRITE_IF,
.in.fname = sname,
.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;
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,
};
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,
};
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 open with overwrite 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");
/*
* 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,
};
@ -1998,43 +2062,21 @@ static bool test_fileid(struct torture_context *tctx,
"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");
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, fileid,
torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
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,
};
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,
@ -2049,16 +2091,183 @@ 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");
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_CREATE,
.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 created 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");
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");
smb2_util_close(tree, h1);
/*
* 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,
};
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 opened 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");
/*
* 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,
};
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");
/*
* Final open of the basefile with QFID
*/
create = (struct smb2_create) {
.in.desired_access = SEC_FILE_ALL,
.in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
@ -2072,7 +2281,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,
@ -2081,10 +2296,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",
@ -2096,14 +2316,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);