2 Unix SMB/CIFS implementation.
4 SMB2 getinfo test suite
6 Copyright (C) Andrew Tridgell 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25 #include "libcli/smb/smbXcli_base.h"
27 #include "torture/torture.h"
28 #include "torture/smb2/proto.h"
29 #include "torture/util.h"
36 union smb_fileinfo finfo
;
37 union smb_fileinfo dinfo
;
39 #define LEVEL(x) #x, x
40 { LEVEL(RAW_FILEINFO_BASIC_INFORMATION
) },
41 { LEVEL(RAW_FILEINFO_STANDARD_INFORMATION
) },
42 { LEVEL(RAW_FILEINFO_INTERNAL_INFORMATION
) },
43 { LEVEL(RAW_FILEINFO_EA_INFORMATION
) },
44 { LEVEL(RAW_FILEINFO_ACCESS_INFORMATION
) },
45 { LEVEL(RAW_FILEINFO_POSITION_INFORMATION
) },
46 { LEVEL(RAW_FILEINFO_MODE_INFORMATION
) },
47 { LEVEL(RAW_FILEINFO_ALIGNMENT_INFORMATION
) },
48 { LEVEL(RAW_FILEINFO_ALL_INFORMATION
) },
49 { LEVEL(RAW_FILEINFO_ALT_NAME_INFORMATION
) },
50 { LEVEL(RAW_FILEINFO_STREAM_INFORMATION
) },
51 { LEVEL(RAW_FILEINFO_COMPRESSION_INFORMATION
) },
52 { LEVEL(RAW_FILEINFO_NETWORK_OPEN_INFORMATION
) },
53 { LEVEL(RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION
) },
55 { LEVEL(RAW_FILEINFO_SMB2_ALL_EAS
) },
57 { LEVEL(RAW_FILEINFO_SMB2_ALL_INFORMATION
) },
58 { LEVEL(RAW_FILEINFO_SEC_DESC
) }
65 union smb_fsinfo info
;
67 { LEVEL(RAW_QFS_VOLUME_INFORMATION
) },
68 { LEVEL(RAW_QFS_SIZE_INFORMATION
) },
69 { LEVEL(RAW_QFS_DEVICE_INFORMATION
) },
70 { LEVEL(RAW_QFS_ATTRIBUTE_INFORMATION
) },
71 { LEVEL(RAW_QFS_QUOTA_INFORMATION
) },
72 { LEVEL(RAW_QFS_FULL_SIZE_INFORMATION
) },
73 { LEVEL(RAW_QFS_OBJECTID_INFORMATION
) }
76 #define FNAME "testsmb2_file.dat"
77 #define DNAME "testsmb2_dir"
82 static bool torture_smb2_fileinfo(struct torture_context
*tctx
, struct smb2_tree
*tree
)
84 struct smb2_handle hfile
, hdir
;
88 status
= torture_smb2_testfile(tree
, FNAME
, &hfile
);
89 torture_assert_ntstatus_ok(tctx
, status
, "Unable to create test file "
92 status
= torture_smb2_testdir(tree
, DNAME
, &hdir
);
93 torture_assert_ntstatus_ok(tctx
, status
, "Unable to create test dir "
96 printf("Testing file info levels\n");
97 torture_smb2_all_info(tree
, hfile
);
98 torture_smb2_all_info(tree
, hdir
);
100 for (i
=0;i
<ARRAY_SIZE(file_levels
);i
++) {
101 if (file_levels
[i
].level
== RAW_FILEINFO_SEC_DESC
) {
102 file_levels
[i
].finfo
.query_secdesc
.in
.secinfo_flags
= 0x7;
103 file_levels
[i
].dinfo
.query_secdesc
.in
.secinfo_flags
= 0x7;
105 if (file_levels
[i
].level
== RAW_FILEINFO_SMB2_ALL_EAS
) {
106 file_levels
[i
].finfo
.all_eas
.in
.continue_flags
=
107 SMB2_CONTINUE_FLAG_RESTART
;
108 file_levels
[i
].dinfo
.all_eas
.in
.continue_flags
=
109 SMB2_CONTINUE_FLAG_RESTART
;
111 file_levels
[i
].finfo
.generic
.level
= file_levels
[i
].level
;
112 file_levels
[i
].finfo
.generic
.in
.file
.handle
= hfile
;
113 file_levels
[i
].fstatus
= smb2_getinfo_file(tree
, tree
, &file_levels
[i
].finfo
);
114 torture_assert_ntstatus_ok(tctx
, file_levels
[i
].fstatus
,
115 talloc_asprintf(tctx
, "%s on file",
116 file_levels
[i
].name
));
117 file_levels
[i
].dinfo
.generic
.level
= file_levels
[i
].level
;
118 file_levels
[i
].dinfo
.generic
.in
.file
.handle
= hdir
;
119 file_levels
[i
].dstatus
= smb2_getinfo_file(tree
, tree
, &file_levels
[i
].dinfo
);
120 torture_assert_ntstatus_ok(tctx
, file_levels
[i
].dstatus
,
121 talloc_asprintf(tctx
, "%s on dir",
122 file_levels
[i
].name
));
132 static bool torture_smb2_fsinfo(struct torture_context
*tctx
)
135 struct smb2_tree
*tree
;
138 struct smb2_handle handle
;
140 printf("Testing fsinfo levels\n");
142 ret
= torture_smb2_connection(tctx
, &tree
);
143 torture_assert(tctx
, ret
, "connection failed");
145 status
= smb2_util_roothandle(tree
, &handle
);
146 torture_assert_ntstatus_ok(tctx
, status
, "Unable to create root handle");
148 for (i
=0;i
<ARRAY_SIZE(fs_levels
);i
++) {
149 fs_levels
[i
].info
.generic
.level
= fs_levels
[i
].level
;
150 fs_levels
[i
].info
.generic
.handle
= handle
;
151 fs_levels
[i
].status
= smb2_getinfo_fs(tree
, tree
, &fs_levels
[i
].info
);
152 torture_assert_ntstatus_ok(tctx
, fs_levels
[i
].status
,
159 static bool torture_smb2_buffercheck_err(struct torture_context
*tctx
,
160 struct smb2_tree
*tree
,
161 struct smb2_getinfo
*b
,
167 for (i
=0; i
<=full
.length
; i
++) {
170 b
->in
.output_buffer_length
= i
;
172 status
= smb2_getinfo(tree
, tree
, b
);
175 torture_assert_ntstatus_equal(
176 tctx
, status
, NT_STATUS_INFO_LENGTH_MISMATCH
,
177 "Wrong error code small buffer");
182 torture_assert_ntstatus_equal(
183 tctx
, status
, STATUS_BUFFER_OVERFLOW
,
184 "Wrong error code for large buffer");
186 * TODO: compare the output buffer. That seems a bit
187 * difficult, because for level 5 for example the
188 * label length is adjusted to what is there. And some
189 * reserved fields seem to be not initialized to 0.
191 TALLOC_FREE(b
->out
.blob
.data
);
195 torture_assert_ntstatus_equal(
196 tctx
, status
, NT_STATUS_OK
,
197 "Wrong error code for right sized buffer");
203 struct level_buffersize
{
208 static bool torture_smb2_qfs_buffercheck(struct torture_context
*tctx
)
211 struct smb2_tree
*tree
;
213 struct smb2_handle handle
;
216 struct level_buffersize levels
[] = {
217 { 1, 24 }, /* We don't have proper defines here */
226 printf("Testing SMB2_GETINFO_FS buffer sizes\n");
228 ret
= torture_smb2_connection(tctx
, &tree
);
229 torture_assert(tctx
, ret
, "connection failed");
231 status
= smb2_util_roothandle(tree
, &handle
);
232 torture_assert_ntstatus_ok(
233 tctx
, status
, "Unable to create root handle");
235 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
236 struct smb2_getinfo b
;
238 if (TARGET_IS_SAMBA3(tctx
) &&
239 ((levels
[i
].level
== 6) || (levels
[i
].level
== 11))) {
244 b
.in
.info_type
= SMB2_GETINFO_FS
;
245 b
.in
.info_class
= levels
[i
].level
;
246 b
.in
.file
.handle
= handle
;
247 b
.in
.output_buffer_length
= 65535;
249 status
= smb2_getinfo(tree
, tree
, &b
);
251 torture_assert_ntstatus_equal(
252 tctx
, status
, NT_STATUS_OK
,
253 "Wrong error code for large buffer");
255 ret
= torture_smb2_buffercheck_err(
256 tctx
, tree
, &b
, levels
[i
].fixed
, b
.out
.blob
);
265 static bool torture_smb2_qfile_buffercheck(struct torture_context
*tctx
)
268 struct smb2_tree
*tree
;
269 struct smb2_create c
;
271 struct smb2_handle handle
;
274 struct level_buffersize levels
[] = {
290 printf("Testing SMB2_GETINFO_FILE buffer sizes\n");
292 ret
= torture_smb2_connection(tctx
, &tree
);
293 torture_assert(tctx
, ret
, "connection failed");
296 c
.in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
;
297 c
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
298 c
.in
.create_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
300 NTCREATEX_SHARE_ACCESS_DELETE
|
301 NTCREATEX_SHARE_ACCESS_READ
|
302 NTCREATEX_SHARE_ACCESS_WRITE
;
303 c
.in
.create_options
= 0;
304 c
.in
.fname
= "bufsize.txt";
306 c
.in
.eas
.num_eas
= 2;
307 c
.in
.eas
.eas
= talloc_array(tree
, struct ea_struct
, 2);
308 c
.in
.eas
.eas
[0].flags
= 0;
309 c
.in
.eas
.eas
[0].name
.s
= "EAONE";
310 c
.in
.eas
.eas
[0].value
= data_blob_talloc(c
.in
.eas
.eas
, "VALUE1", 6);
311 c
.in
.eas
.eas
[1].flags
= 0;
312 c
.in
.eas
.eas
[1].name
.s
= "SECONDEA";
313 c
.in
.eas
.eas
[1].value
= data_blob_talloc(c
.in
.eas
.eas
, "ValueTwo", 8);
315 status
= smb2_create(tree
, tree
, &c
);
316 torture_assert_ntstatus_ok(
317 tctx
, status
, "Unable to create test file");
319 handle
= c
.out
.file
.handle
;
321 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
322 struct smb2_getinfo b
;
325 b
.in
.info_type
= SMB2_GETINFO_FILE
;
326 b
.in
.info_class
= levels
[i
].level
;
327 b
.in
.file
.handle
= handle
;
328 b
.in
.output_buffer_length
= 65535;
330 status
= smb2_getinfo(tree
, tree
, &b
);
331 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_IMPLEMENTED
)) {
334 torture_assert_ntstatus_equal(
335 tctx
, status
, NT_STATUS_OK
,
336 "Wrong error code for large buffer");
338 ret
= torture_smb2_buffercheck_err(
339 tctx
, tree
, &b
, levels
[i
].fixed
, b
.out
.blob
);
347 static bool torture_smb2_qsec_buffercheck(struct torture_context
*tctx
)
349 struct smb2_getinfo b
;
351 struct smb2_tree
*tree
;
352 struct smb2_create c
;
354 struct smb2_handle handle
;
356 printf("Testing SMB2_GETINFO_SECURITY buffer sizes\n");
358 ret
= torture_smb2_connection(tctx
, &tree
);
359 torture_assert(tctx
, ret
, "connection failed");
362 c
.in
.oplock_level
= 0;
363 c
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_DIR_READ_ATTRIBUTE
|
364 SEC_DIR_LIST
| SEC_STD_READ_CONTROL
;
365 c
.in
.file_attributes
= 0;
366 c
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
367 c
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
368 NTCREATEX_SHARE_ACCESS_DELETE
;
369 c
.in
.create_options
= NTCREATEX_OPTIONS_ASYNC_ALERT
;
372 status
= smb2_create(tree
, tree
, &c
);
373 torture_assert_ntstatus_ok(
374 tctx
, status
, "Unable to create root handle");
376 handle
= c
.out
.file
.handle
;
379 b
.in
.info_type
= SMB2_GETINFO_SECURITY
;
381 b
.in
.file
.handle
= handle
;
382 b
.in
.output_buffer_length
= 0;
384 status
= smb2_getinfo(tree
, tree
, &b
);
385 torture_assert_ntstatus_equal(
386 tctx
, status
, NT_STATUS_BUFFER_TOO_SMALL
,
387 "Wrong error code for large buffer");
389 b
.in
.output_buffer_length
= 1;
390 status
= smb2_getinfo(tree
, tree
, &b
);
391 torture_assert_ntstatus_equal(
392 tctx
, status
, NT_STATUS_BUFFER_TOO_SMALL
,
393 "Wrong error code for large buffer");
398 /* basic testing of all SMB2 getinfo levels
400 static bool torture_smb2_getinfo(struct torture_context
*torture
)
402 struct smb2_tree
*tree
;
406 ret
= torture_smb2_connection(torture
, &tree
);
407 torture_assert(torture
, ret
, "connection failed");
409 smb2_deltree(tree
, FNAME
);
410 smb2_deltree(tree
, DNAME
);
412 status
= torture_setup_complex_file(tree
, FNAME
);
413 torture_assert_ntstatus_ok(torture
, status
,
414 "setup complex file " FNAME
);
416 status
= torture_setup_complex_file(tree
, FNAME
":streamtwo");
417 torture_assert_ntstatus_ok(torture
, status
,
418 "setup complex file " FNAME
":streamtwo");
420 status
= torture_setup_complex_dir(tree
, DNAME
);
421 torture_assert_ntstatus_ok(torture
, status
,
422 "setup complex dir " DNAME
);
424 status
= torture_setup_complex_file(tree
, DNAME
":streamtwo");
425 torture_assert_ntstatus_ok(torture
, status
,
426 "setup complex dir " DNAME
":streamtwo");
428 ret
&= torture_smb2_fileinfo(torture
, tree
);
433 struct torture_suite
*torture_smb2_getinfo_init(void)
435 struct torture_suite
*suite
= torture_suite_create(
436 talloc_autofree_context(), "getinfo");
438 torture_suite_add_simple_test(suite
, "complex", torture_smb2_getinfo
);
439 torture_suite_add_simple_test(suite
, "fsinfo", torture_smb2_fsinfo
);
440 torture_suite_add_simple_test(suite
, "qfs_buffercheck",
441 torture_smb2_qfs_buffercheck
);
442 torture_suite_add_simple_test(suite
, "qfile_buffercheck",
443 torture_smb2_qfile_buffercheck
);
444 torture_suite_add_simple_test(suite
, "qsec_buffercheck",
445 torture_smb2_qsec_buffercheck
);