ctdb-scripts: Support storing statd-callout state in cluster filesystem
[samba4-gss.git] / source4 / torture / smb2 / read.c
blob2bc0dc98bbac4f54b3ccafc87a143bfe1caf0e11
1 /*
2 Unix SMB/CIFS implementation.
4 SMB2 read test suite
6 Copyright (C) Andrew Tridgell 2008
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/>.
22 #include "includes.h"
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25 #include <tevent.h>
27 #include "torture/torture.h"
28 #include "torture/smb2/proto.h"
29 #include "../libcli/smb/smbXcli_base.h"
30 #include "librpc/gen_ndr/ndr_ioctl.h"
33 #define CHECK_STATUS(_status, _expected) \
34 torture_assert_ntstatus_equal_goto(torture, _status, _expected, \
35 ret, done, "Incorrect status")
37 #define CHECK_VALUE(v, correct) \
38 torture_assert_int_equal_goto(torture, v, correct, \
39 ret, done, "Incorrect value")
41 #define FNAME "smb2_readtest.dat"
42 #define DNAME "smb2_readtest.dir"
44 static bool test_read_eof(struct torture_context *torture, struct smb2_tree *tree)
46 bool ret = true;
47 NTSTATUS status;
48 struct smb2_handle h;
49 uint8_t buf[64*1024];
50 struct smb2_read rd;
51 TALLOC_CTX *tmp_ctx = talloc_new(tree);
53 ZERO_STRUCT(buf);
55 smb2_util_unlink(tree, FNAME);
57 status = torture_smb2_testfile(tree, FNAME, &h);
58 CHECK_STATUS(status, NT_STATUS_OK);
60 ZERO_STRUCT(rd);
61 rd.in.file.handle = h;
62 rd.in.length = 5;
63 rd.in.offset = 0;
64 status = smb2_read(tree, tree, &rd);
65 CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
67 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
68 CHECK_STATUS(status, NT_STATUS_OK);
70 ZERO_STRUCT(rd);
71 rd.in.file.handle = h;
72 rd.in.length = 10;
73 rd.in.offset = 0;
74 rd.in.min_count = 1;
76 status = smb2_read(tree, tmp_ctx, &rd);
77 CHECK_STATUS(status, NT_STATUS_OK);
78 CHECK_VALUE(rd.out.data.length, 10);
80 rd.in.min_count = 0;
81 rd.in.length = 10;
82 rd.in.offset = sizeof(buf);
83 status = smb2_read(tree, tmp_ctx, &rd);
84 CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
86 rd.in.min_count = 0;
87 rd.in.length = 0;
88 rd.in.offset = sizeof(buf);
89 status = smb2_read(tree, tmp_ctx, &rd);
90 CHECK_STATUS(status, NT_STATUS_OK);
91 CHECK_VALUE(rd.out.data.length, 0);
93 rd.in.min_count = 1;
94 rd.in.length = 0;
95 rd.in.offset = sizeof(buf);
96 status = smb2_read(tree, tmp_ctx, &rd);
97 CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
99 rd.in.min_count = 0;
100 rd.in.length = 2;
101 rd.in.offset = sizeof(buf) - 1;
102 status = smb2_read(tree, tmp_ctx, &rd);
103 CHECK_STATUS(status, NT_STATUS_OK);
104 CHECK_VALUE(rd.out.data.length, 1);
106 rd.in.min_count = 2;
107 rd.in.length = 1;
108 rd.in.offset = sizeof(buf) - 1;
109 status = smb2_read(tree, tmp_ctx, &rd);
110 CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
112 rd.in.min_count = 0x10000;
113 rd.in.length = 1;
114 rd.in.offset = 0;
115 status = smb2_read(tree, tmp_ctx, &rd);
116 CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
118 rd.in.min_count = 0x10000 - 2;
119 rd.in.length = 1;
120 rd.in.offset = 0;
121 status = smb2_read(tree, tmp_ctx, &rd);
122 CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
124 rd.in.min_count = 10;
125 rd.in.length = 5;
126 rd.in.offset = 0;
127 status = smb2_read(tree, tmp_ctx, &rd);
128 CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
130 done:
131 talloc_free(tmp_ctx);
132 return ret;
136 static bool test_read_position(struct torture_context *torture, struct smb2_tree *tree)
138 bool ret = true;
139 NTSTATUS status;
140 struct smb2_handle h;
141 uint8_t buf[64*1024];
142 struct smb2_read rd;
143 TALLOC_CTX *tmp_ctx = talloc_new(tree);
144 union smb_fileinfo info;
146 ZERO_STRUCT(buf);
148 smb2_util_unlink(tree, FNAME);
150 status = torture_smb2_testfile(tree, FNAME, &h);
151 CHECK_STATUS(status, NT_STATUS_OK);
153 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
154 CHECK_STATUS(status, NT_STATUS_OK);
156 ZERO_STRUCT(rd);
157 rd.in.file.handle = h;
158 rd.in.length = 10;
159 rd.in.offset = 0;
160 rd.in.min_count = 1;
162 status = smb2_read(tree, tmp_ctx, &rd);
163 CHECK_STATUS(status, NT_STATUS_OK);
164 CHECK_VALUE(rd.out.data.length, 10);
166 info.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
167 info.generic.in.file.handle = h;
169 status = smb2_getinfo_file(tree, tmp_ctx, &info);
170 CHECK_STATUS(status, NT_STATUS_OK);
171 if (torture_setting_bool(torture, "windows", false)) {
172 CHECK_VALUE(info.all_info2.out.position, 0);
173 } else {
174 CHECK_VALUE(info.all_info2.out.position, 10);
178 done:
179 talloc_free(tmp_ctx);
180 return ret;
183 static bool test_read_dir(struct torture_context *torture, struct smb2_tree *tree)
185 bool ret = true;
186 NTSTATUS status;
187 struct smb2_handle h;
188 struct smb2_read rd;
189 TALLOC_CTX *tmp_ctx = talloc_new(tree);
191 status = torture_smb2_testdir(tree, DNAME, &h);
192 if (!NT_STATUS_IS_OK(status)) {
193 printf(__location__ " Unable to create test directory '%s' - %s\n", DNAME, nt_errstr(status));
194 return false;
197 ZERO_STRUCT(rd);
198 rd.in.file.handle = h;
199 rd.in.length = 10;
200 rd.in.offset = 0;
201 rd.in.min_count = 1;
203 status = smb2_read(tree, tmp_ctx, &rd);
204 CHECK_STATUS(status, NT_STATUS_INVALID_DEVICE_REQUEST);
206 rd.in.min_count = 11;
207 status = smb2_read(tree, tmp_ctx, &rd);
208 CHECK_STATUS(status, NT_STATUS_INVALID_DEVICE_REQUEST);
210 rd.in.length = 0;
211 rd.in.min_count = 2592;
212 status = smb2_read(tree, tmp_ctx, &rd);
213 if (torture_setting_bool(torture, "windows", false)) {
214 CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
215 } else {
216 CHECK_STATUS(status, NT_STATUS_INVALID_DEVICE_REQUEST);
219 rd.in.length = 0;
220 rd.in.min_count = 0;
221 rd.in.channel = 0;
222 status = smb2_read(tree, tmp_ctx, &rd);
223 if (torture_setting_bool(torture, "windows", false)) {
224 CHECK_STATUS(status, NT_STATUS_OK);
225 } else {
226 CHECK_STATUS(status, NT_STATUS_INVALID_DEVICE_REQUEST);
229 done:
230 talloc_free(tmp_ctx);
231 return ret;
234 static bool test_read_access(struct torture_context *torture,
235 struct smb2_tree *tree)
237 bool ret = true;
238 NTSTATUS status;
239 struct smb2_handle h;
240 uint8_t buf[64 * 1024];
241 struct smb2_read rd;
242 TALLOC_CTX *tmp_ctx = talloc_new(tree);
244 ZERO_STRUCT(buf);
246 /* create a file */
247 smb2_util_unlink(tree, FNAME);
249 status = torture_smb2_testfile(tree, FNAME, &h);
250 CHECK_STATUS(status, NT_STATUS_OK);
252 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
253 CHECK_STATUS(status, NT_STATUS_OK);
255 status = smb2_util_close(tree, h);
256 CHECK_STATUS(status, NT_STATUS_OK);
258 /* open w/ READ access - success */
259 status = torture_smb2_testfile_access(
260 tree, FNAME, &h, SEC_FILE_READ_ATTRIBUTE | SEC_FILE_READ_DATA);
261 CHECK_STATUS(status, NT_STATUS_OK);
263 ZERO_STRUCT(rd);
264 rd.in.file.handle = h;
265 rd.in.length = 5;
266 rd.in.offset = 0;
267 status = smb2_read(tree, tree, &rd);
268 CHECK_STATUS(status, NT_STATUS_OK);
270 status = smb2_util_close(tree, h);
271 CHECK_STATUS(status, NT_STATUS_OK);
273 /* open w/ EXECUTE access - success */
274 status = torture_smb2_testfile_access(
275 tree, FNAME, &h, SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE);
276 CHECK_STATUS(status, NT_STATUS_OK);
278 ZERO_STRUCT(rd);
279 rd.in.file.handle = h;
280 rd.in.length = 5;
281 rd.in.offset = 0;
282 status = smb2_read(tree, tree, &rd);
283 CHECK_STATUS(status, NT_STATUS_OK);
285 status = smb2_util_close(tree, h);
286 CHECK_STATUS(status, NT_STATUS_OK);
288 /* open without READ or EXECUTE access - access denied */
289 status = torture_smb2_testfile_access(tree, FNAME, &h,
290 SEC_FILE_READ_ATTRIBUTE);
291 CHECK_STATUS(status, NT_STATUS_OK);
293 ZERO_STRUCT(rd);
294 rd.in.file.handle = h;
295 rd.in.length = 5;
296 rd.in.offset = 0;
297 status = smb2_read(tree, tree, &rd);
298 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
300 status = smb2_util_close(tree, h);
301 CHECK_STATUS(status, NT_STATUS_OK);
303 done:
304 talloc_free(tmp_ctx);
305 return ret;
309 basic regression test for BUG 14607
310 https://bugzilla.samba.org/show_bug.cgi?id=14607
312 static bool test_read_bug14607(struct torture_context *torture,
313 struct smb2_tree *tree)
315 bool ret = true;
316 NTSTATUS status;
317 struct smb2_handle h;
318 uint8_t buf[64 * 1024];
319 struct smb2_read rd;
320 uint32_t timeout_msec;
321 DATA_BLOB out_input_buffer = data_blob_null;
322 DATA_BLOB out_output_buffer = data_blob_null;
323 TALLOC_CTX *tmp_ctx = talloc_new(tree);
324 uint8_t *data = NULL;
325 uint32_t data_length = 0;
327 memset(buf, 0x1f, ARRAY_SIZE(buf));
329 /* create a file */
330 smb2_util_unlink(tree, FNAME);
332 status = torture_smb2_testfile(tree, FNAME, &h);
333 CHECK_STATUS(status, NT_STATUS_OK);
335 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
336 CHECK_STATUS(status, NT_STATUS_OK);
338 ZERO_STRUCT(rd);
339 rd.in.file.handle = h;
340 rd.in.length = ARRAY_SIZE(buf);
341 rd.in.offset = 0;
342 status = smb2_read(tree, tree, &rd);
343 CHECK_STATUS(status, NT_STATUS_OK);
344 CHECK_VALUE(rd.out.data.length, ARRAY_SIZE(buf));
345 torture_assert_mem_equal_goto(torture, rd.out.data.data,
346 buf, ARRAY_SIZE(buf),
347 ret, done,
348 "Invalid content smb2_read");
350 timeout_msec = tree->session->transport->options.request_timeout * 1000;
352 status = smb2cli_read(tree->session->transport->conn,
353 timeout_msec,
354 tree->session->smbXcli,
355 tree->smbXcli,
356 rd.in.length,
357 rd.in.offset,
358 h.data[0],
359 h.data[1],
360 rd.in.min_count,
361 rd.in.remaining,
362 tmp_ctx,
363 &data, &data_length);
364 CHECK_STATUS(status, NT_STATUS_OK);
365 CHECK_VALUE(data_length, ARRAY_SIZE(buf));
366 torture_assert_mem_equal_goto(torture, data,
367 buf, ARRAY_SIZE(buf),
368 ret, done,
369 "Invalid content smb2cli_read");
371 status = smb2cli_ioctl(tree->session->transport->conn,
372 timeout_msec,
373 tree->session->smbXcli,
374 tree->smbXcli,
375 UINT64_MAX, /* in_fid_persistent */
376 UINT64_MAX, /* in_fid_volatile */
377 FSCTL_SMBTORTURE_GLOBAL_READ_RESPONSE_BODY_PADDING8,
378 0, /* in_max_input_length */
379 NULL, /* in_input_buffer */
380 1, /* in_max_output_length */
381 NULL, /* in_output_buffer */
382 SMB2_IOCTL_FLAG_IS_FSCTL,
383 tmp_ctx,
384 &out_input_buffer,
385 &out_output_buffer);
386 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED) ||
387 NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) ||
388 NT_STATUS_EQUAL(status, NT_STATUS_FS_DRIVER_REQUIRED) ||
389 NT_STATUS_EQUAL(status, NT_STATUS_INVALID_DEVICE_REQUEST))
391 torture_comment(torture,
392 "FSCTL_SMBTORTURE_GLOBAL_READ_RESPONSE_BODY_PADDING8: %s\n",
393 nt_errstr(status));
394 torture_skip(torture, "server doesn't support FSCTL_SMBTORTURE_GLOBAL_READ_RESPONSE_BODY_PADDING8\n");
396 torture_assert_ntstatus_ok(torture, status, "FSCTL_SMBTORTURE_GLOBAL_READ_RESPONSE_BODY_PADDING8");
398 torture_assert_int_equal(torture, out_output_buffer.length, 0,
399 "output length");
401 ZERO_STRUCT(rd);
402 rd.in.file.handle = h;
403 rd.in.length = ARRAY_SIZE(buf);
404 rd.in.offset = 0;
405 status = smb2_read(tree, tree, &rd);
406 CHECK_STATUS(status, NT_STATUS_OK);
407 CHECK_VALUE(rd.out.data.length, ARRAY_SIZE(buf));
408 torture_assert_mem_equal_goto(torture, rd.out.data.data,
409 buf, ARRAY_SIZE(buf),
410 ret, done,
411 "Invalid content after padding smb2_read");
413 status = smb2cli_read(tree->session->transport->conn,
414 timeout_msec,
415 tree->session->smbXcli,
416 tree->smbXcli,
417 rd.in.length,
418 rd.in.offset,
419 h.data[0],
420 h.data[1],
421 rd.in.min_count,
422 rd.in.remaining,
423 tmp_ctx,
424 &data, &data_length);
425 CHECK_STATUS(status, NT_STATUS_OK);
426 CHECK_VALUE(data_length, ARRAY_SIZE(buf));
427 torture_assert_mem_equal_goto(torture, data,
428 buf, ARRAY_SIZE(buf),
429 ret, done,
430 "Invalid content after padding smb2cli_read");
432 status = smb2_util_close(tree, h);
433 CHECK_STATUS(status, NT_STATUS_OK);
435 done:
436 talloc_free(tmp_ctx);
437 return ret;
441 basic testing of SMB2 read
443 struct torture_suite *torture_smb2_read_init(TALLOC_CTX *ctx)
445 struct torture_suite *suite = torture_suite_create(ctx, "read");
447 torture_suite_add_1smb2_test(suite, "eof", test_read_eof);
448 torture_suite_add_1smb2_test(suite, "position", test_read_position);
449 torture_suite_add_1smb2_test(suite, "dir", test_read_dir);
450 torture_suite_add_1smb2_test(suite, "access", test_read_access);
451 torture_suite_add_1smb2_test(suite, "bug14607",
452 test_read_bug14607);
454 suite->description = talloc_strdup(suite, "SMB2-READ tests");
456 return suite;
459 static bool test_aio_cancel(struct torture_context *tctx,
460 struct smb2_tree *tree)
462 struct smb2_handle h;
463 uint8_t buf[64 * 1024];
464 struct smb2_read r;
465 struct smb2_request *req = NULL;
466 int rc;
467 NTSTATUS status;
468 bool ret = true;
470 ZERO_STRUCT(buf);
472 smb2_util_unlink(tree, FNAME);
474 status = torture_smb2_testfile(tree, FNAME, &h);
475 torture_assert_ntstatus_ok_goto(
476 tctx,
477 status,
478 ret,
479 done,
480 "torture_smb2_testfile failed\n");
482 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
483 torture_assert_ntstatus_ok_goto(
484 tctx,
485 status,
486 ret,
487 done,
488 "smb2_util_write failed\n");
490 status = smb2_util_close(tree, h);
491 torture_assert_ntstatus_ok_goto(
492 tctx,
493 status,
494 ret,
495 done,
496 "smb2_util_close failed\n");
498 status = torture_smb2_testfile_access(
499 tree, FNAME, &h, SEC_RIGHTS_FILE_ALL);
500 torture_assert_ntstatus_ok_goto(
501 tctx,
502 status,
503 ret,
504 done,
505 "torture_smb2_testfile_access failed\n");
507 r = (struct smb2_read) {
508 .in.file.handle = h,
509 .in.length = 1,
510 .in.offset = 0,
511 .in.min_count = 1,
514 req = smb2_read_send(tree, &r);
515 torture_assert_goto(
516 tctx,
517 req != NULL,
518 ret,
519 done,
520 "smb2_read_send failed\n");
522 while (!req->cancel.can_cancel) {
523 rc = tevent_loop_once(tctx->ev);
524 torture_assert_goto(
525 tctx,
526 rc == 0,
527 ret,
528 done,
529 "tevent_loop_once failed\n");
532 status = smb2_cancel(req);
533 torture_assert_ntstatus_ok_goto(
534 tctx,
535 status,
536 ret,
537 done,
538 "smb2_cancel failed\n");
540 status = smb2_read_recv(req, tree, &r);
541 torture_assert_ntstatus_ok_goto(
542 tctx,
543 status,
544 ret,
545 done,
546 "smb2_read_recv failed\n");
548 status = smb2_util_close(tree, h);
549 torture_assert_ntstatus_ok_goto(
550 tctx,
551 status,
552 ret,
553 done,
554 "smb2_util_close failed\n");
556 done:
557 smb2_util_unlink(tree, FNAME);
558 return ret;
562 * aio testing against share with VFS module "delay_inject"
564 struct torture_suite *torture_smb2_aio_delay_init(TALLOC_CTX *ctx)
566 struct torture_suite *suite = torture_suite_create(ctx, "aio_delay");
568 torture_suite_add_1smb2_test(suite, "aio_cancel", test_aio_cancel);
570 suite->description = talloc_strdup(suite, "SMB2 delayed aio tests");
572 return suite;