summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2019-09-23 15:15:01 -0700
committerKarolin Seeger <kseeger@samba.org>2019-10-16 19:25:11 +0000
commitf5c8dea0ae75e2d24fd3268e2b5b427cb81225c9 (patch)
tree499850128a5fe5a12e4787881a6c870ec31d052f
parentfc0efd56d0584d8ca950ad837bd19e7341833dbf (diff)
downloadsamba-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.fileid1
-rw-r--r--source4/torture/smb2/create.c299
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);