2 Unix SMB/CIFS implementation.
4 test suite for SMB2 ioctl operations
6 Copyright (C) David Disseldorp 2011
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 "librpc/gen_ndr/security.h"
24 #include "libcli/smb2/smb2.h"
25 #include "libcli/smb2/smb2_calls.h"
26 #include "torture/torture.h"
27 #include "torture/smb2/proto.h"
28 #include "librpc/gen_ndr/ndr_ioctl.h"
30 #define FNAME "testfsctl.dat"
31 #define FNAME2 "testfsctl2.dat"
32 #define DNAME "testfsctl_dir"
35 basic testing of SMB2 shadow copy calls
37 static bool test_ioctl_get_shadow_copy(struct torture_context
*torture
,
38 struct smb2_tree
*tree
)
43 union smb_ioctl ioctl
;
44 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
46 smb2_util_unlink(tree
, FNAME
);
48 status
= torture_smb2_testfile(tree
, FNAME
, &h
);
49 torture_assert_ntstatus_ok(torture
, status
, "create write");
52 status
= smb2_util_write(tree
, h
, buf
, 0, ARRAY_SIZE(buf
));
53 torture_assert_ntstatus_ok(torture
, status
, "write");
56 ioctl
.smb2
.level
= RAW_IOCTL_SMB2
;
57 ioctl
.smb2
.in
.file
.handle
= h
;
58 ioctl
.smb2
.in
.function
= FSCTL_SRV_ENUM_SNAPS
;
59 ioctl
.smb2
.in
.max_response_size
= 16;
60 ioctl
.smb2
.in
.flags
= SMB2_IOCTL_FLAG_IS_FSCTL
;
62 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
63 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_SUPPORTED
)
64 || NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_DEVICE_REQUEST
)) {
65 torture_skip(torture
, "FSCTL_SRV_ENUM_SNAPS not supported\n");
67 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_SRV_ENUM_SNAPS");
73 basic testing of the SMB2 server side copy ioctls
75 static bool test_ioctl_req_resume_key(struct torture_context
*torture
,
76 struct smb2_tree
*tree
)
81 union smb_ioctl ioctl
;
82 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
83 struct req_resume_key_rsp res_key
;
84 enum ndr_err_code ndr_ret
;
86 smb2_util_unlink(tree
, FNAME
);
88 status
= torture_smb2_testfile(tree
, FNAME
, &h
);
89 torture_assert_ntstatus_ok(torture
, status
, "create write");
92 status
= smb2_util_write(tree
, h
, buf
, 0, ARRAY_SIZE(buf
));
93 torture_assert_ntstatus_ok(torture
, status
, "write");
96 ioctl
.smb2
.level
= RAW_IOCTL_SMB2
;
97 ioctl
.smb2
.in
.file
.handle
= h
;
98 ioctl
.smb2
.in
.function
= FSCTL_SRV_REQUEST_RESUME_KEY
;
99 ioctl
.smb2
.in
.max_response_size
= 32;
100 ioctl
.smb2
.in
.flags
= SMB2_IOCTL_FLAG_IS_FSCTL
;
102 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
103 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_SRV_REQUEST_RESUME_KEY");
105 ndr_ret
= ndr_pull_struct_blob(&ioctl
.smb2
.out
.out
, tmp_ctx
, &res_key
,
106 (ndr_pull_flags_fn_t
)ndr_pull_req_resume_key_rsp
);
107 torture_assert_ndr_success(torture
, ndr_ret
,
108 "ndr_pull_req_resume_key_rsp");
110 ndr_print_debug((ndr_print_fn_t
)ndr_print_req_resume_key_rsp
, "yo", &res_key
);
112 talloc_free(tmp_ctx
);
116 static uint64_t patt_hash(uint64_t off
)
121 static bool check_pattern(struct torture_context
*torture
,
122 struct smb2_tree
*tree
, TALLOC_CTX
*mem_ctx
,
123 struct smb2_handle h
, uint64_t off
, uint64_t len
,
131 r
.in
.file
.handle
= h
;
134 status
= smb2_read(tree
, mem_ctx
, &r
);
135 torture_assert_ntstatus_ok(torture
, status
, "read");
137 torture_assert_u64_equal(torture
, r
.out
.data
.length
, len
,
138 "read data len mismatch");
140 for (i
= 0; i
<= len
- 8; i
+= 8, patt_off
+= 8) {
141 uint64_t data
= BVAL(r
.out
.data
.data
, i
);
142 torture_assert_u64_equal(torture
, data
, patt_hash(patt_off
),
143 talloc_asprintf(torture
, "read data "
144 "pattern bad at %llu\n",
145 (unsigned long long)i
));
148 talloc_free(r
.out
.data
.data
);
152 static bool test_setup_create_fill(struct torture_context
*torture
,
153 struct smb2_tree
*tree
, TALLOC_CTX
*mem_ctx
,
155 struct smb2_handle
*fh
,
157 uint32_t desired_access
)
159 struct smb2_create io
;
162 uint8_t *buf
= talloc_zero_size(mem_ctx
, size
);
163 torture_assert(torture
, (buf
!= NULL
), "no memory for file data buf");
165 smb2_util_unlink(tree
, fname
);
168 io
.in
.desired_access
= desired_access
;
169 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
170 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
172 NTCREATEX_SHARE_ACCESS_DELETE
|
173 NTCREATEX_SHARE_ACCESS_READ
|
174 NTCREATEX_SHARE_ACCESS_WRITE
;
177 status
= smb2_create(tree
, mem_ctx
, &io
);
178 torture_assert_ntstatus_ok(torture
, status
, "file create");
180 *fh
= io
.out
.file
.handle
;
183 uint64_t cur_off
= 0;
184 for (i
= 0; i
<= size
- 8; i
+= 8) {
185 SBVAL(buf
, i
, patt_hash(i
));
188 uint64_t io_sz
= MIN(1024 * 1024, size
);
189 status
= smb2_util_write(tree
, *fh
,
190 buf
+ cur_off
, cur_off
, io_sz
);
191 torture_assert_ntstatus_ok(torture
, status
, "file write");
200 static bool test_setup_copy_chunk(struct torture_context
*torture
,
201 struct smb2_tree
*tree
, TALLOC_CTX
*mem_ctx
,
203 struct smb2_handle
*src_h
,
205 uint32_t src_desired_access
,
206 struct smb2_handle
*dest_h
,
208 uint32_t dest_desired_access
,
209 struct srv_copychunk_copy
*cc_copy
,
210 union smb_ioctl
*ioctl
)
212 struct req_resume_key_rsp res_key
;
215 enum ndr_err_code ndr_ret
;
217 ok
= test_setup_create_fill(torture
, tree
, mem_ctx
, FNAME
,
218 src_h
, src_size
, src_desired_access
);
219 torture_assert(torture
, ok
, "src file create fill");
221 ok
= test_setup_create_fill(torture
, tree
, mem_ctx
, FNAME2
,
222 dest_h
, dest_size
, dest_desired_access
);
223 torture_assert(torture
, ok
, "dest file create fill");
225 ZERO_STRUCTPN(ioctl
);
226 ioctl
->smb2
.level
= RAW_IOCTL_SMB2
;
227 ioctl
->smb2
.in
.file
.handle
= *src_h
;
228 ioctl
->smb2
.in
.function
= FSCTL_SRV_REQUEST_RESUME_KEY
;
229 /* Allow for Key + ContextLength + Context */
230 ioctl
->smb2
.in
.max_response_size
= 32;
231 ioctl
->smb2
.in
.flags
= SMB2_IOCTL_FLAG_IS_FSCTL
;
233 status
= smb2_ioctl(tree
, mem_ctx
, &ioctl
->smb2
);
234 torture_assert_ntstatus_ok(torture
, status
,
235 "FSCTL_SRV_REQUEST_RESUME_KEY");
237 ndr_ret
= ndr_pull_struct_blob(&ioctl
->smb2
.out
.out
, mem_ctx
, &res_key
,
238 (ndr_pull_flags_fn_t
)ndr_pull_req_resume_key_rsp
);
240 torture_assert_ndr_success(torture
, ndr_ret
,
241 "ndr_pull_req_resume_key_rsp");
243 ZERO_STRUCTPN(ioctl
);
244 ioctl
->smb2
.level
= RAW_IOCTL_SMB2
;
245 ioctl
->smb2
.in
.file
.handle
= *dest_h
;
246 ioctl
->smb2
.in
.function
= FSCTL_SRV_COPYCHUNK
;
247 ioctl
->smb2
.in
.max_response_size
= sizeof(struct srv_copychunk_rsp
);
248 ioctl
->smb2
.in
.flags
= SMB2_IOCTL_FLAG_IS_FSCTL
;
250 ZERO_STRUCTPN(cc_copy
);
251 memcpy(cc_copy
->source_key
, res_key
.resume_key
, ARRAY_SIZE(cc_copy
->source_key
));
252 cc_copy
->chunk_count
= nchunks
;
253 cc_copy
->chunks
= talloc_zero_array(mem_ctx
, struct srv_copychunk
, nchunks
);
254 torture_assert(torture
, (cc_copy
->chunks
!= NULL
), "no memory for chunks");
260 static bool check_copy_chunk_rsp(struct torture_context
*torture
,
261 struct srv_copychunk_rsp
*cc_rsp
,
262 uint32_t ex_chunks_written
,
263 uint32_t ex_chunk_bytes_written
,
264 uint32_t ex_total_bytes_written
)
266 torture_assert_int_equal(torture
, cc_rsp
->chunks_written
,
267 ex_chunks_written
, "num chunks");
268 torture_assert_int_equal(torture
, cc_rsp
->chunk_bytes_written
,
269 ex_chunk_bytes_written
, "chunk bytes written");
270 torture_assert_int_equal(torture
, cc_rsp
->total_bytes_written
,
271 ex_total_bytes_written
, "chunk total bytes");
275 static bool test_ioctl_copy_chunk_simple(struct torture_context
*torture
,
276 struct smb2_tree
*tree
)
278 struct smb2_handle src_h
;
279 struct smb2_handle dest_h
;
281 union smb_ioctl ioctl
;
282 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
283 struct srv_copychunk_copy cc_copy
;
284 struct srv_copychunk_rsp cc_rsp
;
285 enum ndr_err_code ndr_ret
;
288 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
290 &src_h
, 4096, /* fill 4096 byte src file */
292 &dest_h
, 0, /* 0 byte dest file */
297 torture_fail(torture
, "setup copy chunk error");
300 /* copy all src file data (via a single chunk desc) */
301 cc_copy
.chunks
[0].source_off
= 0;
302 cc_copy
.chunks
[0].target_off
= 0;
303 cc_copy
.chunks
[0].length
= 4096;
305 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
307 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
308 torture_assert_ndr_success(torture
, ndr_ret
,
309 "ndr_push_srv_copychunk_copy");
311 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
312 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_SRV_COPYCHUNK");
314 ndr_ret
= ndr_pull_struct_blob(&ioctl
.smb2
.out
.out
, tmp_ctx
,
316 (ndr_pull_flags_fn_t
)ndr_pull_srv_copychunk_rsp
);
317 torture_assert_ndr_success(torture
, ndr_ret
,
318 "ndr_pull_srv_copychunk_rsp");
320 ok
= check_copy_chunk_rsp(torture
, &cc_rsp
,
321 1, /* chunks written */
322 0, /* chunk bytes unsuccessfully written */
323 4096); /* total bytes written */
325 torture_fail(torture
, "bad copy chunk response data");
328 ok
= check_pattern(torture
, tree
, tmp_ctx
, dest_h
, 0, 4096, 0);
330 torture_fail(torture
, "inconsistent file data");
333 smb2_util_close(tree
, src_h
);
334 smb2_util_close(tree
, dest_h
);
335 talloc_free(tmp_ctx
);
339 static bool test_ioctl_copy_chunk_multi(struct torture_context
*torture
,
340 struct smb2_tree
*tree
)
342 struct smb2_handle src_h
;
343 struct smb2_handle dest_h
;
345 union smb_ioctl ioctl
;
346 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
347 struct srv_copychunk_copy cc_copy
;
348 struct srv_copychunk_rsp cc_rsp
;
349 enum ndr_err_code ndr_ret
;
352 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
354 &src_h
, 8192, /* src file */
356 &dest_h
, 0, /* dest file */
361 torture_fail(torture
, "setup copy chunk error");
364 /* copy all src file data via two chunks */
365 cc_copy
.chunks
[0].source_off
= 0;
366 cc_copy
.chunks
[0].target_off
= 0;
367 cc_copy
.chunks
[0].length
= 4096;
369 cc_copy
.chunks
[1].source_off
= 4096;
370 cc_copy
.chunks
[1].target_off
= 4096;
371 cc_copy
.chunks
[1].length
= 4096;
373 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
375 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
376 torture_assert_ndr_success(torture
, ndr_ret
,
377 "ndr_push_srv_copychunk_copy");
379 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
380 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_SRV_COPYCHUNK");
382 ndr_ret
= ndr_pull_struct_blob(&ioctl
.smb2
.out
.out
, tmp_ctx
,
384 (ndr_pull_flags_fn_t
)ndr_pull_srv_copychunk_rsp
);
385 torture_assert_ndr_success(torture
, ndr_ret
,
386 "ndr_pull_srv_copychunk_rsp");
388 ok
= check_copy_chunk_rsp(torture
, &cc_rsp
,
389 2, /* chunks written */
390 0, /* chunk bytes unsuccessfully written */
391 8192); /* total bytes written */
393 torture_fail(torture
, "bad copy chunk response data");
396 smb2_util_close(tree
, src_h
);
397 smb2_util_close(tree
, dest_h
);
398 talloc_free(tmp_ctx
);
402 static bool test_ioctl_copy_chunk_tiny(struct torture_context
*torture
,
403 struct smb2_tree
*tree
)
405 struct smb2_handle src_h
;
406 struct smb2_handle dest_h
;
408 union smb_ioctl ioctl
;
409 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
410 struct srv_copychunk_copy cc_copy
;
411 struct srv_copychunk_rsp cc_rsp
;
412 enum ndr_err_code ndr_ret
;
415 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
417 &src_h
, 100, /* src file */
419 &dest_h
, 0, /* dest file */
424 torture_fail(torture
, "setup copy chunk error");
427 /* copy all src file data via two chunks, sub block size chunks */
428 cc_copy
.chunks
[0].source_off
= 0;
429 cc_copy
.chunks
[0].target_off
= 0;
430 cc_copy
.chunks
[0].length
= 50;
432 cc_copy
.chunks
[1].source_off
= 50;
433 cc_copy
.chunks
[1].target_off
= 50;
434 cc_copy
.chunks
[1].length
= 50;
436 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
438 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
439 torture_assert_ndr_success(torture
, ndr_ret
,
440 "ndr_push_srv_copychunk_copy");
442 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
443 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_SRV_COPYCHUNK");
445 ndr_ret
= ndr_pull_struct_blob(&ioctl
.smb2
.out
.out
, tmp_ctx
,
447 (ndr_pull_flags_fn_t
)ndr_pull_srv_copychunk_rsp
);
448 torture_assert_ndr_success(torture
, ndr_ret
,
449 "ndr_pull_srv_copychunk_rsp");
451 ok
= check_copy_chunk_rsp(torture
, &cc_rsp
,
452 2, /* chunks written */
453 0, /* chunk bytes unsuccessfully written */
454 100); /* total bytes written */
456 torture_fail(torture
, "bad copy chunk response data");
459 ok
= check_pattern(torture
, tree
, tmp_ctx
, dest_h
, 0, 100, 0);
461 torture_fail(torture
, "inconsistent file data");
464 smb2_util_close(tree
, src_h
);
465 smb2_util_close(tree
, dest_h
);
466 talloc_free(tmp_ctx
);
470 static bool test_ioctl_copy_chunk_over(struct torture_context
*torture
,
471 struct smb2_tree
*tree
)
473 struct smb2_handle src_h
;
474 struct smb2_handle dest_h
;
476 union smb_ioctl ioctl
;
477 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
478 struct srv_copychunk_copy cc_copy
;
479 struct srv_copychunk_rsp cc_rsp
;
480 enum ndr_err_code ndr_ret
;
483 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
485 &src_h
, 8192, /* src file */
487 &dest_h
, 4096, /* dest file */
492 torture_fail(torture
, "setup copy chunk error");
495 /* first chunk overwrites existing dest data */
496 cc_copy
.chunks
[0].source_off
= 0;
497 cc_copy
.chunks
[0].target_off
= 0;
498 cc_copy
.chunks
[0].length
= 4096;
500 /* second chunk overwrites the first */
501 cc_copy
.chunks
[1].source_off
= 4096;
502 cc_copy
.chunks
[1].target_off
= 0;
503 cc_copy
.chunks
[1].length
= 4096;
505 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
507 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
508 torture_assert_ndr_success(torture
, ndr_ret
,
509 "ndr_push_srv_copychunk_copy");
511 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
512 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_SRV_COPYCHUNK");
514 ndr_ret
= ndr_pull_struct_blob(&ioctl
.smb2
.out
.out
, tmp_ctx
,
516 (ndr_pull_flags_fn_t
)ndr_pull_srv_copychunk_rsp
);
517 torture_assert_ndr_success(torture
, ndr_ret
,
518 "ndr_pull_srv_copychunk_rsp");
520 ok
= check_copy_chunk_rsp(torture
, &cc_rsp
,
521 2, /* chunks written */
522 0, /* chunk bytes unsuccessfully written */
523 8192); /* total bytes written */
525 torture_fail(torture
, "bad copy chunk response data");
528 ok
= check_pattern(torture
, tree
, tmp_ctx
, dest_h
, 0, 4096, 4096);
530 torture_fail(torture
, "inconsistent file data");
533 smb2_util_close(tree
, src_h
);
534 smb2_util_close(tree
, dest_h
);
535 talloc_free(tmp_ctx
);
539 static bool test_ioctl_copy_chunk_append(struct torture_context
*torture
,
540 struct smb2_tree
*tree
)
542 struct smb2_handle src_h
;
543 struct smb2_handle dest_h
;
545 union smb_ioctl ioctl
;
546 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
547 struct srv_copychunk_copy cc_copy
;
548 struct srv_copychunk_rsp cc_rsp
;
549 enum ndr_err_code ndr_ret
;
552 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
554 &src_h
, 4096, /* src file */
556 &dest_h
, 0, /* dest file */
561 torture_fail(torture
, "setup copy chunk error");
564 cc_copy
.chunks
[0].source_off
= 0;
565 cc_copy
.chunks
[0].target_off
= 0;
566 cc_copy
.chunks
[0].length
= 4096;
568 /* second chunk appends the same data to the first */
569 cc_copy
.chunks
[1].source_off
= 0;
570 cc_copy
.chunks
[1].target_off
= 4096;
571 cc_copy
.chunks
[1].length
= 4096;
573 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
575 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
576 torture_assert_ndr_success(torture
, ndr_ret
,
577 "ndr_push_srv_copychunk_copy");
579 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
580 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_SRV_COPYCHUNK");
582 ndr_ret
= ndr_pull_struct_blob(&ioctl
.smb2
.out
.out
, tmp_ctx
,
584 (ndr_pull_flags_fn_t
)ndr_pull_srv_copychunk_rsp
);
585 torture_assert_ndr_success(torture
, ndr_ret
,
586 "ndr_pull_srv_copychunk_rsp");
588 ok
= check_copy_chunk_rsp(torture
, &cc_rsp
,
589 2, /* chunks written */
590 0, /* chunk bytes unsuccessfully written */
591 8192); /* total bytes written */
593 torture_fail(torture
, "bad copy chunk response data");
596 ok
= check_pattern(torture
, tree
, tmp_ctx
, dest_h
, 0, 4096, 0);
598 torture_fail(torture
, "inconsistent file data");
601 ok
= check_pattern(torture
, tree
, tmp_ctx
, dest_h
, 4096, 4096, 0);
603 torture_fail(torture
, "inconsistent file data");
606 smb2_util_close(tree
, src_h
);
607 smb2_util_close(tree
, dest_h
);
608 talloc_free(tmp_ctx
);
612 static bool test_ioctl_copy_chunk_limits(struct torture_context
*torture
,
613 struct smb2_tree
*tree
)
615 struct smb2_handle src_h
;
616 struct smb2_handle dest_h
;
618 union smb_ioctl ioctl
;
619 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
620 struct srv_copychunk_copy cc_copy
;
621 struct srv_copychunk_rsp cc_rsp
;
622 enum ndr_err_code ndr_ret
;
625 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
627 &src_h
, 4096, /* src file */
629 &dest_h
, 0, /* dest file */
634 torture_fail(torture
, "setup copy chunk error");
637 /* send huge chunk length request */
638 cc_copy
.chunks
[0].source_off
= 0;
639 cc_copy
.chunks
[0].target_off
= 0;
640 cc_copy
.chunks
[0].length
= UINT_MAX
;
642 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
644 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
645 torture_assert_ndr_success(torture
, ndr_ret
, "marshalling request");
647 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
648 torture_assert_ntstatus_equal(torture
, status
,
649 NT_STATUS_INVALID_PARAMETER
,
650 "bad oversize chunk response");
652 ndr_ret
= ndr_pull_struct_blob(&ioctl
.smb2
.out
.out
, tmp_ctx
,
654 (ndr_pull_flags_fn_t
)ndr_pull_srv_copychunk_rsp
);
655 torture_assert_ndr_success(torture
, ndr_ret
, "unmarshalling response");
657 torture_comment(torture
, "limit max chunks, got %u\n",
658 cc_rsp
.chunks_written
);
659 torture_comment(torture
, "limit max chunk len, got %u\n",
660 cc_rsp
.chunk_bytes_written
);
661 torture_comment(torture
, "limit max total bytes, got %u\n",
662 cc_rsp
.total_bytes_written
);
664 smb2_util_close(tree
, src_h
);
665 smb2_util_close(tree
, dest_h
);
666 talloc_free(tmp_ctx
);
670 static bool test_ioctl_copy_chunk_src_lck(struct torture_context
*torture
,
671 struct smb2_tree
*tree
)
673 struct smb2_handle src_h
;
674 struct smb2_handle src_h2
;
675 struct smb2_handle dest_h
;
677 union smb_ioctl ioctl
;
678 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
679 struct srv_copychunk_copy cc_copy
;
680 struct srv_copychunk_rsp cc_rsp
;
681 enum ndr_err_code ndr_ret
;
683 struct smb2_lock lck
;
684 struct smb2_lock_element el
[1];
686 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
688 &src_h
, 4096, /* src file */
690 &dest_h
, 0, /* dest file */
695 torture_fail(torture
, "setup copy chunk error");
698 cc_copy
.chunks
[0].source_off
= 0;
699 cc_copy
.chunks
[0].target_off
= 0;
700 cc_copy
.chunks
[0].length
= 4096;
702 /* open and lock the copychunk src file */
703 status
= torture_smb2_testfile(tree
, FNAME
, &src_h2
);
704 torture_assert_ntstatus_ok(torture
, status
, "2nd src open");
706 lck
.in
.lock_count
= 0x0001;
707 lck
.in
.lock_sequence
= 0x00000000;
708 lck
.in
.file
.handle
= src_h2
;
710 el
[0].offset
= cc_copy
.chunks
[0].source_off
;
711 el
[0].length
= cc_copy
.chunks
[0].length
;
713 el
[0].flags
= SMB2_LOCK_FLAG_EXCLUSIVE
;
715 status
= smb2_lock(tree
, &lck
);
716 torture_assert_ntstatus_ok(torture
, status
, "lock");
718 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
720 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
721 torture_assert_ndr_success(torture
, ndr_ret
,
722 "ndr_push_srv_copychunk_copy");
724 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
726 * 2k12 & Samba return lock_conflict, Windows 7 & 2k8 return success...
728 * Edgar Olougouna @ MS wrote:
729 * Regarding the FSCTL_SRV_COPYCHUNK and STATUS_FILE_LOCK_CONFLICT
730 * discrepancy observed between Windows versions, we confirm that the
731 * behavior change is expected.
733 * CopyChunk in Windows Server 2012 use regular Readfile/Writefile APIs
734 * to move the chunks from the source to the destination.
735 * These ReadFile/WriteFile APIs go through the byte-range lock checks,
736 * and this explains the observed STATUS_FILE_LOCK_CONFLICT error.
738 * Prior to Windows Server 2012, CopyChunk used mapped sections to move
739 * the data. And byte range locks are not enforced on mapped I/O, and
740 * this explains the STATUS_SUCCESS observed on Windows Server 2008 R2.
742 torture_assert_ntstatus_equal(torture
, status
,
743 NT_STATUS_FILE_LOCK_CONFLICT
,
744 "FSCTL_SRV_COPYCHUNK locked");
746 /* should get cc response data with the lock conflict status */
747 ndr_ret
= ndr_pull_struct_blob(&ioctl
.smb2
.out
.out
, tmp_ctx
,
749 (ndr_pull_flags_fn_t
)ndr_pull_srv_copychunk_rsp
);
750 torture_assert_ndr_success(torture
, ndr_ret
,
751 "ndr_pull_srv_copychunk_rsp");
752 ok
= check_copy_chunk_rsp(torture
, &cc_rsp
,
753 0, /* chunks written */
754 0, /* chunk bytes unsuccessfully written */
755 0); /* total bytes written */
757 lck
.in
.lock_count
= 0x0001;
758 lck
.in
.lock_sequence
= 0x00000001;
759 lck
.in
.file
.handle
= src_h2
;
761 el
[0].offset
= cc_copy
.chunks
[0].source_off
;
762 el
[0].length
= cc_copy
.chunks
[0].length
;
764 el
[0].flags
= SMB2_LOCK_FLAG_UNLOCK
;
765 status
= smb2_lock(tree
, &lck
);
766 torture_assert_ntstatus_ok(torture
, status
, "unlock");
768 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
769 torture_assert_ntstatus_ok(torture
, status
,
770 "FSCTL_SRV_COPYCHUNK unlocked");
772 ndr_ret
= ndr_pull_struct_blob(&ioctl
.smb2
.out
.out
, tmp_ctx
,
774 (ndr_pull_flags_fn_t
)ndr_pull_srv_copychunk_rsp
);
775 torture_assert_ndr_success(torture
, ndr_ret
,
776 "ndr_pull_srv_copychunk_rsp");
778 ok
= check_copy_chunk_rsp(torture
, &cc_rsp
,
779 1, /* chunks written */
780 0, /* chunk bytes unsuccessfully written */
781 4096); /* total bytes written */
783 torture_fail(torture
, "bad copy chunk response data");
786 ok
= check_pattern(torture
, tree
, tmp_ctx
, dest_h
, 0, 4096, 0);
788 torture_fail(torture
, "inconsistent file data");
791 smb2_util_close(tree
, src_h2
);
792 smb2_util_close(tree
, src_h
);
793 smb2_util_close(tree
, dest_h
);
794 talloc_free(tmp_ctx
);
798 static bool test_ioctl_copy_chunk_dest_lck(struct torture_context
*torture
,
799 struct smb2_tree
*tree
)
801 struct smb2_handle src_h
;
802 struct smb2_handle dest_h
;
803 struct smb2_handle dest_h2
;
805 union smb_ioctl ioctl
;
806 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
807 struct srv_copychunk_copy cc_copy
;
808 struct srv_copychunk_rsp cc_rsp
;
809 enum ndr_err_code ndr_ret
;
811 struct smb2_lock lck
;
812 struct smb2_lock_element el
[1];
814 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
816 &src_h
, 4096, /* src file */
818 &dest_h
, 4096, /* dest file */
823 torture_fail(torture
, "setup copy chunk error");
826 cc_copy
.chunks
[0].source_off
= 0;
827 cc_copy
.chunks
[0].target_off
= 0;
828 cc_copy
.chunks
[0].length
= 4096;
830 /* open and lock the copychunk dest file */
831 status
= torture_smb2_testfile(tree
, FNAME2
, &dest_h2
);
832 torture_assert_ntstatus_ok(torture
, status
, "2nd src open");
834 lck
.in
.lock_count
= 0x0001;
835 lck
.in
.lock_sequence
= 0x00000000;
836 lck
.in
.file
.handle
= dest_h2
;
838 el
[0].offset
= cc_copy
.chunks
[0].target_off
;
839 el
[0].length
= cc_copy
.chunks
[0].length
;
841 el
[0].flags
= SMB2_LOCK_FLAG_EXCLUSIVE
;
843 status
= smb2_lock(tree
, &lck
);
844 torture_assert_ntstatus_ok(torture
, status
, "lock");
846 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
848 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
849 torture_assert_ndr_success(torture
, ndr_ret
,
850 "ndr_push_srv_copychunk_copy");
852 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
853 torture_assert_ntstatus_equal(torture
, status
,
854 NT_STATUS_FILE_LOCK_CONFLICT
,
855 "FSCTL_SRV_COPYCHUNK locked");
857 lck
.in
.lock_count
= 0x0001;
858 lck
.in
.lock_sequence
= 0x00000001;
859 lck
.in
.file
.handle
= dest_h2
;
861 el
[0].offset
= cc_copy
.chunks
[0].target_off
;
862 el
[0].length
= cc_copy
.chunks
[0].length
;
864 el
[0].flags
= SMB2_LOCK_FLAG_UNLOCK
;
865 status
= smb2_lock(tree
, &lck
);
866 torture_assert_ntstatus_ok(torture
, status
, "unlock");
868 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
869 torture_assert_ntstatus_ok(torture
, status
,
870 "FSCTL_SRV_COPYCHUNK unlocked");
872 ndr_ret
= ndr_pull_struct_blob(&ioctl
.smb2
.out
.out
, tmp_ctx
,
874 (ndr_pull_flags_fn_t
)ndr_pull_srv_copychunk_rsp
);
875 torture_assert_ndr_success(torture
, ndr_ret
,
876 "ndr_pull_srv_copychunk_rsp");
878 ok
= check_copy_chunk_rsp(torture
, &cc_rsp
,
879 1, /* chunks written */
880 0, /* chunk bytes unsuccessfully written */
881 4096); /* total bytes written */
883 torture_fail(torture
, "bad copy chunk response data");
886 ok
= check_pattern(torture
, tree
, tmp_ctx
, dest_h
, 0, 4096, 0);
888 torture_fail(torture
, "inconsistent file data");
891 smb2_util_close(tree
, dest_h2
);
892 smb2_util_close(tree
, src_h
);
893 smb2_util_close(tree
, dest_h
);
894 talloc_free(tmp_ctx
);
898 static bool test_ioctl_copy_chunk_bad_key(struct torture_context
*torture
,
899 struct smb2_tree
*tree
)
901 struct smb2_handle src_h
;
902 struct smb2_handle dest_h
;
904 union smb_ioctl ioctl
;
905 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
906 struct srv_copychunk_copy cc_copy
;
907 enum ndr_err_code ndr_ret
;
910 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
919 torture_fail(torture
, "setup copy chunk error");
922 /* overwrite the resume key with a bogus value */
923 memcpy(cc_copy
.source_key
, "deadbeefdeadbeefdeadbeef", 24);
925 cc_copy
.chunks
[0].source_off
= 0;
926 cc_copy
.chunks
[0].target_off
= 0;
927 cc_copy
.chunks
[0].length
= 4096;
929 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
931 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
932 torture_assert_ndr_success(torture
, ndr_ret
,
933 "ndr_push_srv_copychunk_copy");
935 /* Server 2k12 returns NT_STATUS_OBJECT_NAME_NOT_FOUND */
936 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
937 torture_assert_ntstatus_equal(torture
, status
,
938 NT_STATUS_OBJECT_NAME_NOT_FOUND
,
939 "FSCTL_SRV_COPYCHUNK");
941 smb2_util_close(tree
, src_h
);
942 smb2_util_close(tree
, dest_h
);
943 talloc_free(tmp_ctx
);
947 static bool test_ioctl_copy_chunk_src_is_dest(struct torture_context
*torture
,
948 struct smb2_tree
*tree
)
950 struct smb2_handle src_h
;
951 struct smb2_handle dest_h
;
953 union smb_ioctl ioctl
;
954 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
955 struct srv_copychunk_copy cc_copy
;
956 struct srv_copychunk_rsp cc_rsp
;
957 enum ndr_err_code ndr_ret
;
960 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
969 torture_fail(torture
, "setup copy chunk error");
972 /* the source is also the destination */
973 ioctl
.smb2
.in
.file
.handle
= src_h
;
975 /* non-overlapping */
976 cc_copy
.chunks
[0].source_off
= 0;
977 cc_copy
.chunks
[0].target_off
= 4096;
978 cc_copy
.chunks
[0].length
= 4096;
980 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
982 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
983 torture_assert_ndr_success(torture
, ndr_ret
,
984 "ndr_push_srv_copychunk_copy");
986 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
987 torture_assert_ntstatus_ok(torture
, status
,
988 "FSCTL_SRV_COPYCHUNK");
990 ndr_ret
= ndr_pull_struct_blob(&ioctl
.smb2
.out
.out
, tmp_ctx
,
992 (ndr_pull_flags_fn_t
)ndr_pull_srv_copychunk_rsp
);
993 torture_assert_ndr_success(torture
, ndr_ret
,
994 "ndr_pull_srv_copychunk_rsp");
996 ok
= check_copy_chunk_rsp(torture
, &cc_rsp
,
997 1, /* chunks written */
998 0, /* chunk bytes unsuccessfully written */
999 4096); /* total bytes written */
1001 torture_fail(torture
, "bad copy chunk response data");
1004 ok
= check_pattern(torture
, tree
, tmp_ctx
, src_h
, 0, 4096, 0);
1006 torture_fail(torture
, "inconsistent file data");
1008 ok
= check_pattern(torture
, tree
, tmp_ctx
, src_h
, 4096, 4096, 0);
1010 torture_fail(torture
, "inconsistent file data");
1013 smb2_util_close(tree
, src_h
);
1014 smb2_util_close(tree
, dest_h
);
1015 talloc_free(tmp_ctx
);
1020 * Test a single-chunk copychunk request, where the source and target ranges
1021 * overlap, and the SourceKey refers to the same target file. E.g:
1025 * File: src_and_dest
1026 * Offset: 0123456789
1031 * FSCTL_SRV_COPYCHUNK(src_and_dest)
1032 * SourceKey = SRV_REQUEST_RESUME_KEY(src_and_dest)
1034 * Chunks[0].SourceOffset = 0
1035 * Chunks[0].TargetOffset = 4
1036 * Chunks[0].Length = 6
1040 * File: src_and_dest
1041 * Offset: 0123456789
1044 * The resultant contents of src_and_dest is dependent on the server's
1045 * copy algorithm. In the above example, the server uses an IO buffer
1046 * large enough to hold the entire six-byte source data before writing
1047 * to TargetOffset. If the server were to use a four-byte IO buffer and
1048 * started reads/writes from the lowest offset, then the two overlapping
1049 * bytes in the above example would be overwritten before being read. The
1050 * resultant file contents would be abcdabcdab.
1052 * Windows 2008r2 appears to use a 2048 byte copy buffer, overlapping bytes
1053 * after this offset are written before being read. Windows 2012 on the
1054 * other hand appears to use a buffer large enough to hold its maximum
1055 * supported chunk size (1M). Samba currently uses a 64k copy buffer by
1056 * default (vfs_cc_state.buf).
1058 * This test uses an 8-byte overlap at 2040-2048, so that it passes against
1059 * Windows 2008, 2012 and Samba servers.
1062 test_ioctl_copy_chunk_src_is_dest_overlap(struct torture_context
*torture
,
1063 struct smb2_tree
*tree
)
1065 struct smb2_handle src_h
;
1066 struct smb2_handle dest_h
;
1068 union smb_ioctl ioctl
;
1069 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
1070 struct srv_copychunk_copy cc_copy
;
1071 struct srv_copychunk_rsp cc_rsp
;
1072 enum ndr_err_code ndr_ret
;
1075 /* exceed the vfs_default copy buffer */
1076 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
1079 SEC_RIGHTS_FILE_ALL
,
1081 SEC_RIGHTS_FILE_ALL
,
1085 torture_fail(torture
, "setup copy chunk error");
1088 /* the source is also the destination */
1089 ioctl
.smb2
.in
.file
.handle
= src_h
;
1091 /* 8 bytes overlap between source and target ranges */
1092 cc_copy
.chunks
[0].source_off
= 0;
1093 cc_copy
.chunks
[0].target_off
= 2048 - 8;
1094 cc_copy
.chunks
[0].length
= 2048;
1096 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
1098 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
1099 torture_assert_ndr_success(torture
, ndr_ret
,
1100 "ndr_push_srv_copychunk_copy");
1102 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
1103 torture_assert_ntstatus_ok(torture
, status
,
1104 "FSCTL_SRV_COPYCHUNK");
1106 ndr_ret
= ndr_pull_struct_blob(&ioctl
.smb2
.out
.out
, tmp_ctx
,
1108 (ndr_pull_flags_fn_t
)ndr_pull_srv_copychunk_rsp
);
1109 torture_assert_ndr_success(torture
, ndr_ret
,
1110 "ndr_pull_srv_copychunk_rsp");
1112 ok
= check_copy_chunk_rsp(torture
, &cc_rsp
,
1113 1, /* chunks written */
1114 0, /* chunk bytes unsuccessfully written */
1115 2048); /* total bytes written */
1117 torture_fail(torture
, "bad copy chunk response data");
1120 ok
= check_pattern(torture
, tree
, tmp_ctx
, src_h
, 0, 2048 - 8, 0);
1122 torture_fail(torture
, "inconsistent file data");
1124 ok
= check_pattern(torture
, tree
, tmp_ctx
, src_h
, 2048 - 8, 2048, 0);
1126 torture_fail(torture
, "inconsistent file data");
1129 smb2_util_close(tree
, src_h
);
1130 smb2_util_close(tree
, dest_h
);
1131 talloc_free(tmp_ctx
);
1135 static bool test_ioctl_copy_chunk_bad_access(struct torture_context
*torture
,
1136 struct smb2_tree
*tree
)
1138 struct smb2_handle src_h
;
1139 struct smb2_handle dest_h
;
1141 union smb_ioctl ioctl
;
1142 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
1143 struct srv_copychunk_copy cc_copy
;
1144 enum ndr_err_code ndr_ret
;
1147 /* no read permission on src */
1148 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
1150 &src_h
, 4096, /* fill 4096 byte src file */
1151 SEC_RIGHTS_FILE_WRITE
,
1152 &dest_h
, 0, /* 0 byte dest file */
1153 SEC_RIGHTS_FILE_ALL
,
1157 torture_fail(torture
, "setup copy chunk error");
1160 cc_copy
.chunks
[0].source_off
= 0;
1161 cc_copy
.chunks
[0].target_off
= 0;
1162 cc_copy
.chunks
[0].length
= 4096;
1164 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
1166 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
1167 torture_assert_ndr_success(torture
, ndr_ret
,
1168 "ndr_push_srv_copychunk_copy");
1170 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
1171 torture_assert_ntstatus_equal(torture
, status
,
1172 NT_STATUS_ACCESS_DENIED
,
1173 "FSCTL_SRV_COPYCHUNK");
1175 smb2_util_close(tree
, src_h
);
1176 smb2_util_close(tree
, dest_h
);
1178 /* no write permission on dest */
1179 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
1181 &src_h
, 4096, /* fill 4096 byte src file */
1182 SEC_RIGHTS_FILE_ALL
,
1183 &dest_h
, 0, /* 0 byte dest file */
1184 (SEC_RIGHTS_FILE_READ
1185 | SEC_RIGHTS_FILE_EXECUTE
),
1189 torture_fail(torture
, "setup copy chunk error");
1192 cc_copy
.chunks
[0].source_off
= 0;
1193 cc_copy
.chunks
[0].target_off
= 0;
1194 cc_copy
.chunks
[0].length
= 4096;
1196 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
1198 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
1199 torture_assert_ndr_success(torture
, ndr_ret
,
1200 "ndr_push_srv_copychunk_copy");
1202 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
1203 torture_assert_ntstatus_equal(torture
, status
,
1204 NT_STATUS_ACCESS_DENIED
,
1205 "FSCTL_SRV_COPYCHUNK");
1207 smb2_util_close(tree
, src_h
);
1208 smb2_util_close(tree
, dest_h
);
1210 /* no read permission on dest */
1211 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
1213 &src_h
, 4096, /* fill 4096 byte src file */
1214 SEC_RIGHTS_FILE_ALL
,
1215 &dest_h
, 0, /* 0 byte dest file */
1216 (SEC_RIGHTS_FILE_WRITE
1217 | SEC_RIGHTS_FILE_EXECUTE
),
1221 torture_fail(torture
, "setup copy chunk error");
1224 cc_copy
.chunks
[0].source_off
= 0;
1225 cc_copy
.chunks
[0].target_off
= 0;
1226 cc_copy
.chunks
[0].length
= 4096;
1228 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
1230 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
1231 torture_assert_ndr_success(torture
, ndr_ret
,
1232 "ndr_push_srv_copychunk_copy");
1235 * FSCTL_SRV_COPYCHUNK requires read permission on dest,
1236 * FSCTL_SRV_COPYCHUNK_WRITE (not supported by Samba) on the other hand
1239 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
1240 torture_assert_ntstatus_equal(torture
, status
,
1241 NT_STATUS_ACCESS_DENIED
,
1242 "FSCTL_SRV_COPYCHUNK");
1244 smb2_util_close(tree
, src_h
);
1245 smb2_util_close(tree
, dest_h
);
1246 talloc_free(tmp_ctx
);
1251 static bool test_ioctl_copy_chunk_src_exceed(struct torture_context
*torture
,
1252 struct smb2_tree
*tree
)
1254 struct smb2_handle src_h
;
1255 struct smb2_handle dest_h
;
1257 union smb_ioctl ioctl
;
1258 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
1259 struct srv_copychunk_copy cc_copy
;
1260 struct srv_copychunk_rsp cc_rsp
;
1261 enum ndr_err_code ndr_ret
;
1264 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
1266 &src_h
, 4096, /* fill 4096 byte src file */
1267 SEC_RIGHTS_FILE_ALL
,
1268 &dest_h
, 0, /* 0 byte dest file */
1269 SEC_RIGHTS_FILE_ALL
,
1273 torture_fail(torture
, "setup copy chunk error");
1276 /* Request copy where off + length exceeds size of src */
1277 cc_copy
.chunks
[0].source_off
= 1024;
1278 cc_copy
.chunks
[0].target_off
= 0;
1279 cc_copy
.chunks
[0].length
= 4096;
1281 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
1283 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
1284 torture_assert_ndr_success(torture
, ndr_ret
,
1285 "ndr_push_srv_copychunk_copy");
1287 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
1288 torture_assert_ntstatus_equal(torture
, status
,
1289 NT_STATUS_INVALID_VIEW_SIZE
,
1290 "FSCTL_SRV_COPYCHUNK oversize");
1292 /* Request copy where length exceeds size of src */
1293 cc_copy
.chunks
[0].source_off
= 1024;
1294 cc_copy
.chunks
[0].target_off
= 0;
1295 cc_copy
.chunks
[0].length
= 3072;
1297 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
1299 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
1300 torture_assert_ndr_success(torture
, ndr_ret
,
1301 "ndr_push_srv_copychunk_copy");
1303 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
1304 torture_assert_ntstatus_ok(torture
, status
,
1305 "FSCTL_SRV_COPYCHUNK just right");
1307 ndr_ret
= ndr_pull_struct_blob(&ioctl
.smb2
.out
.out
, tmp_ctx
,
1309 (ndr_pull_flags_fn_t
)ndr_pull_srv_copychunk_rsp
);
1310 torture_assert_ndr_success(torture
, ndr_ret
,
1311 "ndr_pull_srv_copychunk_rsp");
1313 ok
= check_copy_chunk_rsp(torture
, &cc_rsp
,
1314 1, /* chunks written */
1315 0, /* chunk bytes unsuccessfully written */
1316 3072); /* total bytes written */
1318 torture_fail(torture
, "bad copy chunk response data");
1321 ok
= check_pattern(torture
, tree
, tmp_ctx
, dest_h
, 0, 3072, 1024);
1323 torture_fail(torture
, "inconsistent file data");
1326 smb2_util_close(tree
, src_h
);
1327 smb2_util_close(tree
, dest_h
);
1328 talloc_free(tmp_ctx
);
1333 test_ioctl_copy_chunk_src_exceed_multi(struct torture_context
*torture
,
1334 struct smb2_tree
*tree
)
1336 struct smb2_handle src_h
;
1337 struct smb2_handle dest_h
;
1339 union smb_ioctl ioctl
;
1340 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
1341 struct srv_copychunk_copy cc_copy
;
1342 struct srv_copychunk_rsp cc_rsp
;
1343 enum ndr_err_code ndr_ret
;
1346 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
1348 &src_h
, 8192, /* fill 8192 byte src file */
1349 SEC_RIGHTS_FILE_ALL
,
1350 &dest_h
, 0, /* 0 byte dest file */
1351 SEC_RIGHTS_FILE_ALL
,
1355 torture_fail(torture
, "setup copy chunk error");
1358 /* Request copy where off + length exceeds size of src */
1359 cc_copy
.chunks
[0].source_off
= 0;
1360 cc_copy
.chunks
[0].target_off
= 0;
1361 cc_copy
.chunks
[0].length
= 4096;
1363 cc_copy
.chunks
[1].source_off
= 4096;
1364 cc_copy
.chunks
[1].target_off
= 4096;
1365 cc_copy
.chunks
[1].length
= 8192;
1367 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
1369 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
1370 torture_assert_ndr_success(torture
, ndr_ret
,
1371 "ndr_push_srv_copychunk_copy");
1373 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
1374 torture_assert_ntstatus_equal(torture
, status
,
1375 NT_STATUS_INVALID_VIEW_SIZE
,
1376 "FSCTL_SRV_COPYCHUNK oversize");
1377 ndr_ret
= ndr_pull_struct_blob(&ioctl
.smb2
.out
.out
, tmp_ctx
,
1379 (ndr_pull_flags_fn_t
)ndr_pull_srv_copychunk_rsp
);
1380 torture_assert_ndr_success(torture
, ndr_ret
, "unmarshalling response");
1382 /* first chunk should still be written */
1383 ok
= check_copy_chunk_rsp(torture
, &cc_rsp
,
1384 1, /* chunks written */
1385 0, /* chunk bytes unsuccessfully written */
1386 4096); /* total bytes written */
1388 torture_fail(torture
, "bad copy chunk response data");
1390 ok
= check_pattern(torture
, tree
, tmp_ctx
, dest_h
, 0, 4096, 0);
1392 torture_fail(torture
, "inconsistent file data");
1395 smb2_util_close(tree
, src_h
);
1396 smb2_util_close(tree
, dest_h
);
1397 talloc_free(tmp_ctx
);
1401 static bool test_ioctl_copy_chunk_sparse_dest(struct torture_context
*torture
,
1402 struct smb2_tree
*tree
)
1404 struct smb2_handle src_h
;
1405 struct smb2_handle dest_h
;
1407 union smb_ioctl ioctl
;
1409 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
1410 struct srv_copychunk_copy cc_copy
;
1411 struct srv_copychunk_rsp cc_rsp
;
1412 enum ndr_err_code ndr_ret
;
1416 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
1418 &src_h
, 4096, /* fill 4096 byte src file */
1419 SEC_RIGHTS_FILE_ALL
,
1420 &dest_h
, 0, /* 0 byte dest file */
1421 SEC_RIGHTS_FILE_ALL
,
1425 torture_fail(torture
, "setup copy chunk error");
1428 /* copy all src file data (via a single chunk desc) */
1429 cc_copy
.chunks
[0].source_off
= 0;
1430 cc_copy
.chunks
[0].target_off
= 4096;
1431 cc_copy
.chunks
[0].length
= 4096;
1433 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
1435 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
1436 torture_assert_ndr_success(torture
, ndr_ret
,
1437 "ndr_push_srv_copychunk_copy");
1439 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
1440 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_SRV_COPYCHUNK");
1442 ndr_ret
= ndr_pull_struct_blob(&ioctl
.smb2
.out
.out
, tmp_ctx
,
1444 (ndr_pull_flags_fn_t
)ndr_pull_srv_copychunk_rsp
);
1445 torture_assert_ndr_success(torture
, ndr_ret
,
1446 "ndr_pull_srv_copychunk_rsp");
1448 ok
= check_copy_chunk_rsp(torture
, &cc_rsp
,
1449 1, /* chunks written */
1450 0, /* chunk bytes unsuccessfully written */
1451 4096); /* total bytes written */
1453 torture_fail(torture
, "bad copy chunk response data");
1456 /* check for zeros in first 4k */
1458 r
.in
.file
.handle
= dest_h
;
1461 status
= smb2_read(tree
, tmp_ctx
, &r
);
1462 torture_assert_ntstatus_ok(torture
, status
, "read");
1464 torture_assert_u64_equal(torture
, r
.out
.data
.length
, 4096,
1465 "read data len mismatch");
1467 for (i
= 0; i
< 4096; i
++) {
1468 torture_assert(torture
, (r
.out
.data
.data
[i
] == 0),
1469 "sparse did not pass class");
1472 ok
= check_pattern(torture
, tree
, tmp_ctx
, dest_h
, 4096, 4096, 0);
1474 torture_fail(torture
, "inconsistent file data");
1477 smb2_util_close(tree
, src_h
);
1478 smb2_util_close(tree
, dest_h
);
1479 talloc_free(tmp_ctx
);
1484 * set the ioctl MaxOutputResponse size to less than
1485 * sizeof(struct srv_copychunk_rsp)
1487 static bool test_ioctl_copy_chunk_max_output_sz(struct torture_context
*torture
,
1488 struct smb2_tree
*tree
)
1490 struct smb2_handle src_h
;
1491 struct smb2_handle dest_h
;
1493 union smb_ioctl ioctl
;
1494 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
1495 struct srv_copychunk_copy cc_copy
;
1496 enum ndr_err_code ndr_ret
;
1499 ok
= test_setup_copy_chunk(torture
, tree
, tmp_ctx
,
1501 &src_h
, 4096, /* fill 4096 byte src file */
1502 SEC_RIGHTS_FILE_ALL
,
1503 &dest_h
, 0, /* 0 byte dest file */
1504 SEC_RIGHTS_FILE_ALL
,
1508 torture_fail(torture
, "setup copy chunk error");
1511 cc_copy
.chunks
[0].source_off
= 0;
1512 cc_copy
.chunks
[0].target_off
= 0;
1513 cc_copy
.chunks
[0].length
= 4096;
1514 /* req is valid, but use undersize max_response_size */
1515 ioctl
.smb2
.in
.max_response_size
= sizeof(struct srv_copychunk_rsp
) - 1;
1517 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, tmp_ctx
,
1519 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
1520 torture_assert_ndr_success(torture
, ndr_ret
,
1521 "ndr_push_srv_copychunk_copy");
1523 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
1524 torture_assert_ntstatus_equal(torture
, status
,
1525 NT_STATUS_INVALID_PARAMETER
,
1526 "FSCTL_SRV_COPYCHUNK");
1528 smb2_util_close(tree
, src_h
);
1529 smb2_util_close(tree
, dest_h
);
1530 talloc_free(tmp_ctx
);
1534 static NTSTATUS
test_ioctl_compress_get(struct torture_context
*torture
,
1535 TALLOC_CTX
*mem_ctx
,
1536 struct smb2_tree
*tree
,
1537 struct smb2_handle fh
,
1538 uint16_t *_compression_fmt
)
1540 union smb_ioctl ioctl
;
1541 struct compression_state cmpr_state
;
1542 enum ndr_err_code ndr_ret
;
1546 ioctl
.smb2
.level
= RAW_IOCTL_SMB2
;
1547 ioctl
.smb2
.in
.file
.handle
= fh
;
1548 ioctl
.smb2
.in
.function
= FSCTL_GET_COMPRESSION
;
1549 ioctl
.smb2
.in
.max_response_size
= sizeof(struct compression_state
);
1550 ioctl
.smb2
.in
.flags
= SMB2_IOCTL_FLAG_IS_FSCTL
;
1552 status
= smb2_ioctl(tree
, mem_ctx
, &ioctl
.smb2
);
1553 if (!NT_STATUS_IS_OK(status
)) {
1557 ndr_ret
= ndr_pull_struct_blob(&ioctl
.smb2
.out
.out
, mem_ctx
,
1559 (ndr_pull_flags_fn_t
)ndr_pull_compression_state
);
1561 if (ndr_ret
!= NDR_ERR_SUCCESS
) {
1562 return NT_STATUS_INTERNAL_ERROR
;
1565 *_compression_fmt
= cmpr_state
.format
;
1566 return NT_STATUS_OK
;
1569 static NTSTATUS
test_ioctl_compress_set(struct torture_context
*torture
,
1570 TALLOC_CTX
*mem_ctx
,
1571 struct smb2_tree
*tree
,
1572 struct smb2_handle fh
,
1573 uint16_t compression_fmt
)
1575 union smb_ioctl ioctl
;
1576 struct compression_state cmpr_state
;
1577 enum ndr_err_code ndr_ret
;
1581 ioctl
.smb2
.level
= RAW_IOCTL_SMB2
;
1582 ioctl
.smb2
.in
.file
.handle
= fh
;
1583 ioctl
.smb2
.in
.function
= FSCTL_SET_COMPRESSION
;
1584 ioctl
.smb2
.in
.max_response_size
= 0;
1585 ioctl
.smb2
.in
.flags
= SMB2_IOCTL_FLAG_IS_FSCTL
;
1587 cmpr_state
.format
= compression_fmt
;
1588 ndr_ret
= ndr_push_struct_blob(&ioctl
.smb2
.in
.out
, mem_ctx
,
1590 (ndr_push_flags_fn_t
)ndr_push_compression_state
);
1591 if (ndr_ret
!= NDR_ERR_SUCCESS
) {
1592 return NT_STATUS_INTERNAL_ERROR
;
1595 status
= smb2_ioctl(tree
, mem_ctx
, &ioctl
.smb2
);
1599 static bool test_ioctl_compress_file_flag(struct torture_context
*torture
,
1600 struct smb2_tree
*tree
)
1602 struct smb2_handle fh
;
1604 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
1606 uint16_t compression_fmt
;
1608 ok
= test_setup_create_fill(torture
, tree
, tmp_ctx
,
1609 FNAME
, &fh
, 0, SEC_RIGHTS_FILE_ALL
);
1610 torture_assert(torture
, ok
, "setup compression file");
1612 status
= test_ioctl_compress_get(torture
, tmp_ctx
, tree
, fh
,
1614 if (NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_DEVICE_REQUEST
)) {
1615 smb2_util_close(tree
, fh
);
1616 torture_skip(torture
, "FSCTL_GET_COMPRESSION not supported\n");
1618 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_GET_COMPRESSION");
1620 torture_assert(torture
, (compression_fmt
== COMPRESSION_FORMAT_NONE
),
1621 "initial compression state not NONE");
1623 status
= test_ioctl_compress_set(torture
, tmp_ctx
, tree
, fh
,
1624 COMPRESSION_FORMAT_DEFAULT
);
1625 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_SET_COMPRESSION");
1627 status
= test_ioctl_compress_get(torture
, tmp_ctx
, tree
, fh
,
1629 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_GET_COMPRESSION");
1631 torture_assert(torture
, (compression_fmt
== COMPRESSION_FORMAT_LZNT1
),
1632 "invalid compression state after set");
1634 smb2_util_close(tree
, fh
);
1635 talloc_free(tmp_ctx
);
1639 static bool test_ioctl_compress_dir_inherit(struct torture_context
*torture
,
1640 struct smb2_tree
*tree
)
1642 struct smb2_handle dirh
;
1643 struct smb2_handle fh
;
1645 struct smb2_create io
;
1646 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
1647 uint16_t compression_fmt
;
1649 char path_buf
[PATH_MAX
];
1651 smb2_deltree(tree
, DNAME
);
1652 status
= smb2_util_mkdir(tree
, DNAME
);
1653 torture_assert_ntstatus_ok(torture
, status
, "mkdir");
1656 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1657 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
1658 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1659 io
.in
.share_access
=
1660 NTCREATEX_SHARE_ACCESS_DELETE
|
1661 NTCREATEX_SHARE_ACCESS_READ
|
1662 NTCREATEX_SHARE_ACCESS_WRITE
;
1663 io
.in
.fname
= DNAME
;
1665 status
= smb2_create(tree
, tmp_ctx
, &io
);
1666 torture_assert_ntstatus_ok(torture
, status
, "dir create");
1667 dirh
= io
.out
.file
.handle
;
1669 /* set compression on base share, then check for file inheritance */
1670 status
= test_ioctl_compress_set(torture
, tmp_ctx
, tree
, dirh
,
1671 COMPRESSION_FORMAT_LZNT1
);
1672 if (NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_DEVICE_REQUEST
)) {
1673 smb2_util_close(tree
, dirh
);
1674 smb2_deltree(tree
, DNAME
);
1675 torture_skip(torture
, "FSCTL_SET_COMPRESSION not supported\n");
1677 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_SET_COMPRESSION");
1679 status
= test_ioctl_compress_get(torture
, tmp_ctx
, tree
, dirh
,
1681 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_GET_COMPRESSION");
1683 torture_assert(torture
, (compression_fmt
== COMPRESSION_FORMAT_LZNT1
),
1684 "invalid compression state after set");
1686 snprintf(path_buf
, PATH_MAX
, "%s\\%s", DNAME
, FNAME
);
1687 ok
= test_setup_create_fill(torture
, tree
, tmp_ctx
,
1688 path_buf
, &fh
, 4096, SEC_RIGHTS_FILE_ALL
);
1689 torture_assert(torture
, ok
, "setup compression file");
1691 status
= test_ioctl_compress_get(torture
, tmp_ctx
, tree
, fh
,
1693 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_GET_COMPRESSION");
1695 torture_assert(torture
, (compression_fmt
== COMPRESSION_FORMAT_LZNT1
),
1696 "compression attr not inherited by new file");
1698 /* check compressed data is consistent */
1699 ok
= check_pattern(torture
, tree
, tmp_ctx
, fh
, 0, 4096, 0);
1701 /* disable dir compression attr, file should remain compressed */
1702 status
= test_ioctl_compress_set(torture
, tmp_ctx
, tree
, dirh
,
1703 COMPRESSION_FORMAT_NONE
);
1704 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_SET_COMPRESSION");
1706 status
= test_ioctl_compress_get(torture
, tmp_ctx
, tree
, fh
,
1708 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_GET_COMPRESSION");
1710 torture_assert(torture
, (compression_fmt
== COMPRESSION_FORMAT_LZNT1
),
1711 "file compression attr removed after dir change");
1712 smb2_util_close(tree
, fh
);
1714 /* new files should no longer inherit compression attr */
1715 snprintf(path_buf
, PATH_MAX
, "%s\\%s", DNAME
, FNAME2
);
1716 ok
= test_setup_create_fill(torture
, tree
, tmp_ctx
,
1717 path_buf
, &fh
, 0, SEC_RIGHTS_FILE_ALL
);
1718 torture_assert(torture
, ok
, "setup file");
1720 status
= test_ioctl_compress_get(torture
, tmp_ctx
, tree
, fh
,
1722 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_GET_COMPRESSION");
1724 torture_assert(torture
, (compression_fmt
== COMPRESSION_FORMAT_NONE
),
1725 "compression attr present on new file");
1727 smb2_util_close(tree
, fh
);
1728 smb2_util_close(tree
, dirh
);
1729 smb2_deltree(tree
, DNAME
);
1730 talloc_free(tmp_ctx
);
1734 static bool test_ioctl_compress_invalid_format(struct torture_context
*torture
,
1735 struct smb2_tree
*tree
)
1737 struct smb2_handle fh
;
1739 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
1741 uint16_t compression_fmt
;
1743 ok
= test_setup_create_fill(torture
, tree
, tmp_ctx
,
1744 FNAME
, &fh
, 0, SEC_RIGHTS_FILE_ALL
);
1745 torture_assert(torture
, ok
, "setup compression file");
1747 status
= test_ioctl_compress_set(torture
, tmp_ctx
, tree
, fh
,
1748 0x0042); /* bogus */
1749 if (NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_DEVICE_REQUEST
)) {
1750 smb2_util_close(tree
, fh
);
1751 torture_skip(torture
, "FSCTL_SET_COMPRESSION not supported\n");
1753 torture_assert_ntstatus_equal(torture
, status
,
1754 NT_STATUS_INVALID_PARAMETER
,
1755 "invalid FSCTL_SET_COMPRESSION");
1757 status
= test_ioctl_compress_get(torture
, tmp_ctx
, tree
, fh
,
1759 torture_assert_ntstatus_ok(torture
, status
, "FSCTL_GET_COMPRESSION");
1761 torture_assert(torture
, (compression_fmt
== COMPRESSION_FORMAT_NONE
),
1762 "initial compression state not NONE");
1764 smb2_util_close(tree
, fh
);
1765 talloc_free(tmp_ctx
);
1769 static bool test_ioctl_compress_invalid_buf(struct torture_context
*torture
,
1770 struct smb2_tree
*tree
)
1772 struct smb2_handle fh
;
1774 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
1776 union smb_ioctl ioctl
;
1778 ok
= test_setup_create_fill(torture
, tree
, tmp_ctx
,
1779 FNAME
, &fh
, 0, SEC_RIGHTS_FILE_ALL
);
1780 torture_assert(torture
, ok
, "setup compression file");
1783 ioctl
.smb2
.level
= RAW_IOCTL_SMB2
;
1784 ioctl
.smb2
.in
.file
.handle
= fh
;
1785 ioctl
.smb2
.in
.function
= FSCTL_GET_COMPRESSION
;
1786 ioctl
.smb2
.in
.max_response_size
= 0; /* no room for rsp data */
1787 ioctl
.smb2
.in
.flags
= SMB2_IOCTL_FLAG_IS_FSCTL
;
1789 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
1790 if (NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_DEVICE_REQUEST
)) {
1791 smb2_util_close(tree
, fh
);
1792 torture_skip(torture
, "FSCTL_GET_COMPRESSION not supported\n");
1794 /* expect Server 2k12 response status */
1795 torture_assert_ntstatus_equal(torture
, status
,
1796 NT_STATUS_INVALID_USER_BUFFER
,
1797 "invalid FSCTL_SET_COMPRESSION");
1799 smb2_util_close(tree
, fh
);
1800 talloc_free(tmp_ctx
);
1805 basic testing of SMB2 ioctls
1807 struct torture_suite
*torture_smb2_ioctl_init(void)
1809 struct torture_suite
*suite
= torture_suite_create(talloc_autofree_context(), "ioctl");
1811 torture_suite_add_1smb2_test(suite
, "shadow_copy",
1812 test_ioctl_get_shadow_copy
);
1813 torture_suite_add_1smb2_test(suite
, "req_resume_key",
1814 test_ioctl_req_resume_key
);
1815 torture_suite_add_1smb2_test(suite
, "copy_chunk_simple",
1816 test_ioctl_copy_chunk_simple
);
1817 torture_suite_add_1smb2_test(suite
, "copy_chunk_multi",
1818 test_ioctl_copy_chunk_multi
);
1819 torture_suite_add_1smb2_test(suite
, "copy_chunk_tiny",
1820 test_ioctl_copy_chunk_tiny
);
1821 torture_suite_add_1smb2_test(suite
, "copy_chunk_overwrite",
1822 test_ioctl_copy_chunk_over
);
1823 torture_suite_add_1smb2_test(suite
, "copy_chunk_append",
1824 test_ioctl_copy_chunk_append
);
1825 torture_suite_add_1smb2_test(suite
, "copy_chunk_limits",
1826 test_ioctl_copy_chunk_limits
);
1827 torture_suite_add_1smb2_test(suite
, "copy_chunk_src_lock",
1828 test_ioctl_copy_chunk_src_lck
);
1829 torture_suite_add_1smb2_test(suite
, "copy_chunk_dest_lock",
1830 test_ioctl_copy_chunk_dest_lck
);
1831 torture_suite_add_1smb2_test(suite
, "copy_chunk_bad_key",
1832 test_ioctl_copy_chunk_bad_key
);
1833 torture_suite_add_1smb2_test(suite
, "copy_chunk_src_is_dest",
1834 test_ioctl_copy_chunk_src_is_dest
);
1835 torture_suite_add_1smb2_test(suite
, "copy_chunk_src_is_dest_overlap",
1836 test_ioctl_copy_chunk_src_is_dest_overlap
);
1837 torture_suite_add_1smb2_test(suite
, "copy_chunk_bad_access",
1838 test_ioctl_copy_chunk_bad_access
);
1839 torture_suite_add_1smb2_test(suite
, "copy_chunk_src_exceed",
1840 test_ioctl_copy_chunk_src_exceed
);
1841 torture_suite_add_1smb2_test(suite
, "copy_chunk_src_exceed_multi",
1842 test_ioctl_copy_chunk_src_exceed_multi
);
1843 torture_suite_add_1smb2_test(suite
, "copy_chunk_sparse_dest",
1844 test_ioctl_copy_chunk_sparse_dest
);
1845 torture_suite_add_1smb2_test(suite
, "copy_chunk_max_output_sz",
1846 test_ioctl_copy_chunk_max_output_sz
);
1847 torture_suite_add_1smb2_test(suite
, "compress_file_flag",
1848 test_ioctl_compress_file_flag
);
1849 torture_suite_add_1smb2_test(suite
, "compress_dir_inherit",
1850 test_ioctl_compress_dir_inherit
);
1851 torture_suite_add_1smb2_test(suite
, "compress_invalid_format",
1852 test_ioctl_compress_invalid_format
);
1853 torture_suite_add_1smb2_test(suite
, "compress_invalid_buf",
1854 test_ioctl_compress_invalid_buf
);
1856 suite
->description
= talloc_strdup(suite
, "SMB2-IOCTL tests");