2 Unix SMB/CIFS implementation.
4 test suite for SMB2 compounded requests
6 Copyright (C) Stefan Metzmacher 2009
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/>.
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 "libcli/security/security.h"
29 #include "librpc/gen_ndr/ndr_security.h"
30 #include "../libcli/smb/smbXcli_base.h"
32 #define CHECK_STATUS(status, correct) do { \
33 if (!NT_STATUS_EQUAL(status, correct)) { \
34 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
35 nt_errstr(status), nt_errstr(correct)); \
40 #define CHECK_VALUE(v, correct) do { \
41 if ((v) != (correct)) { \
42 torture_result(tctx, TORTURE_FAIL, \
43 "(%s) Incorrect value %s=%d - should be %d\n", \
44 __location__, #v, (int)v, (int)correct); \
48 #define WAIT_FOR_ASYNC_RESPONSE(req) \
49 while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) { \
50 if (tevent_loop_once(tctx->ev) != 0) { \
56 struct smb2_handle handle
;
61 NTSTATUS failure_status
;
64 static void torture_oplock_break_callback(struct smb2_request
*req
)
70 status
= smb2_break_recv(req
, &break_info
.br
);
71 if (!NT_STATUS_IS_OK(status
)) {
72 break_info
.failures
++;
73 break_info
.failure_status
= status
;
79 /* A general oplock break notification handler. This should be used when a
80 * test expects to break from batch or exclusive to a lower level. */
81 static bool torture_oplock_handler(struct smb2_transport
*transport
,
82 const struct smb2_handle
*handle
,
86 struct smb2_tree
*tree
= private_data
;
88 struct smb2_request
*req
;
89 ZERO_STRUCT(break_info
.br
);
91 break_info
.handle
= *handle
;
92 break_info
.level
= level
;
96 case SMB2_OPLOCK_LEVEL_II
:
99 case SMB2_OPLOCK_LEVEL_NONE
:
104 break_info
.failures
++;
106 printf("Acking to %s [0x%02X] in oplock handler\n", name
, level
);
108 break_info
.br
.in
.file
.handle
= *handle
;
109 break_info
.br
.in
.oplock_level
= level
;
110 break_info
.br
.in
.reserved
= 0;
111 break_info
.br
.in
.reserved2
= 0;
113 req
= smb2_break_send(tree
, &break_info
.br
);
114 req
->async
.fn
= torture_oplock_break_callback
;
115 req
->async
.private_data
= NULL
;
119 static bool test_compound_break(struct torture_context
*tctx
,
120 struct smb2_tree
*tree
)
122 const char *fname1
= "some-file.pptx";
126 struct smb2_create io2
;
127 struct smb2_getinfo gf
;
128 struct smb2_request
*req
[2];
129 struct smb2_handle h1
;
130 struct smb2_handle h
;
132 tree
->session
->transport
->oplock
.handler
= torture_oplock_handler
;
133 tree
->session
->transport
->oplock
.private_data
= tree
;
135 ZERO_STRUCT(break_info
);
140 ZERO_STRUCT(io1
.smb2
);
141 io1
.generic
.level
= RAW_OPEN_SMB2
;
142 io1
.smb2
.in
.desired_access
= (SEC_STD_SYNCHRONIZE
|
143 SEC_STD_READ_CONTROL
|
144 SEC_FILE_READ_ATTRIBUTE
|
147 io1
.smb2
.in
.alloc_size
= 0;
148 io1
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
149 io1
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
150 NTCREATEX_SHARE_ACCESS_WRITE
|
151 NTCREATEX_SHARE_ACCESS_DELETE
;
152 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
153 io1
.smb2
.in
.create_options
= 0;
154 io1
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
155 io1
.smb2
.in
.security_flags
= 0;
156 io1
.smb2
.in
.fname
= fname1
;
158 torture_comment(tctx
, "TEST2: open a file with an batch "
159 "oplock (share mode: all)\n");
160 io1
.smb2
.in
.oplock_level
= SMB2_OPLOCK_LEVEL_BATCH
;
162 status
= smb2_create(tree
, tctx
, &(io1
.smb2
));
163 torture_assert_ntstatus_ok(tctx
, status
, "Error opening the file");
165 h1
= io1
.smb2
.out
.file
.handle
;
167 torture_comment(tctx
, "TEST2: Opening second time with compound\n");
171 io2
.in
.desired_access
= (SEC_STD_SYNCHRONIZE
|
172 SEC_FILE_READ_ATTRIBUTE
|
174 io2
.in
.alloc_size
= 0;
175 io2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
176 io2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
177 NTCREATEX_SHARE_ACCESS_WRITE
|
178 NTCREATEX_SHARE_ACCESS_DELETE
;
179 io2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
180 io2
.in
.create_options
= 0;
181 io2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
182 io2
.in
.security_flags
= 0;
183 io2
.in
.fname
= fname1
;
184 io2
.in
.oplock_level
= 0;
186 smb2_transport_compound_start(tree
->session
->transport
, 2);
188 req
[0] = smb2_create_send(tree
, &io2
);
190 smb2_transport_compound_set_related(tree
->session
->transport
, true);
192 h
.data
[0] = UINT64_MAX
;
193 h
.data
[1] = UINT64_MAX
;
196 gf
.in
.file
.handle
= h
;
197 gf
.in
.info_type
= SMB2_0_INFO_FILE
;
198 gf
.in
.info_class
= 0x16;
199 gf
.in
.output_buffer_length
= 0x1000;
200 gf
.in
.input_buffer
= data_blob_null
;
202 req
[1] = smb2_getinfo_send(tree
, &gf
);
204 status
= smb2_create_recv(req
[0], tree
, &io2
);
205 CHECK_STATUS(status
, NT_STATUS_OK
);
207 status
= smb2_getinfo_recv(req
[1], tree
, &gf
);
208 CHECK_STATUS(status
, NT_STATUS_OK
);
212 smb2_util_close(tree
, h1
);
213 smb2_util_unlink(tree
, fname1
);
217 static bool test_compound_related1(struct torture_context
*tctx
,
218 struct smb2_tree
*tree
)
220 struct smb2_handle hd
;
221 struct smb2_create cr
;
223 const char *fname
= "compound_related1.dat";
224 struct smb2_close cl
;
226 struct smb2_request
*req
[2];
227 struct smbXcli_tcon
*saved_tcon
= tree
->smbXcli
;
228 struct smbXcli_session
*saved_session
= tree
->session
->smbXcli
;
230 smb2_transport_credits_ask_num(tree
->session
->transport
, 2);
232 smb2_util_unlink(tree
, fname
);
234 smb2_transport_credits_ask_num(tree
->session
->transport
, 1);
237 cr
.in
.security_flags
= 0x00;
238 cr
.in
.oplock_level
= 0;
239 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
240 cr
.in
.create_flags
= 0x00000000;
241 cr
.in
.reserved
= 0x00000000;
242 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
243 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
244 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
245 NTCREATEX_SHARE_ACCESS_WRITE
|
246 NTCREATEX_SHARE_ACCESS_DELETE
;
247 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
248 cr
.in
.create_options
= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY
|
249 NTCREATEX_OPTIONS_ASYNC_ALERT
|
250 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
|
254 smb2_transport_compound_start(tree
->session
->transport
, 2);
256 req
[0] = smb2_create_send(tree
, &cr
);
258 smb2_transport_compound_set_related(tree
->session
->transport
, true);
260 hd
.data
[0] = UINT64_MAX
;
261 hd
.data
[1] = UINT64_MAX
;
264 cl
.in
.file
.handle
= hd
;
266 tree
->smbXcli
= smbXcli_tcon_create(tree
);
267 smb2cli_tcon_set_values(tree
->smbXcli
,
269 0xFFFFFFFF, /* tcon_id */
272 0, /* capabilities */
273 0 /* maximal_access */);
275 tree
->session
->smbXcli
= smbXcli_session_shallow_copy(tree
->session
,
276 tree
->session
->smbXcli
);
277 smb2cli_session_set_id_and_flags(tree
->session
->smbXcli
, UINT64_MAX
, 0);
279 req
[1] = smb2_close_send(tree
, &cl
);
281 status
= smb2_create_recv(req
[0], tree
, &cr
);
282 CHECK_STATUS(status
, NT_STATUS_OK
);
283 status
= smb2_close_recv(req
[1], &cl
);
284 CHECK_STATUS(status
, NT_STATUS_OK
);
286 TALLOC_FREE(tree
->smbXcli
);
287 tree
->smbXcli
= saved_tcon
;
288 TALLOC_FREE(tree
->session
->smbXcli
);
289 tree
->session
->smbXcli
= saved_session
;
291 smb2_util_unlink(tree
, fname
);
296 static bool test_compound_related2(struct torture_context
*tctx
,
297 struct smb2_tree
*tree
)
299 struct smb2_handle hd
;
300 struct smb2_create cr
;
302 const char *fname
= "compound_related2.dat";
303 struct smb2_close cl
;
305 struct smb2_request
*req
[5];
306 struct smbXcli_tcon
*saved_tcon
= tree
->smbXcli
;
307 struct smbXcli_session
*saved_session
= tree
->session
->smbXcli
;
309 smb2_transport_credits_ask_num(tree
->session
->transport
, 5);
311 smb2_util_unlink(tree
, fname
);
313 smb2_transport_credits_ask_num(tree
->session
->transport
, 1);
316 cr
.in
.security_flags
= 0x00;
317 cr
.in
.oplock_level
= 0;
318 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
319 cr
.in
.create_flags
= 0x00000000;
320 cr
.in
.reserved
= 0x00000000;
321 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
322 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
323 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
324 NTCREATEX_SHARE_ACCESS_WRITE
|
325 NTCREATEX_SHARE_ACCESS_DELETE
;
326 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
327 cr
.in
.create_options
= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY
|
328 NTCREATEX_OPTIONS_ASYNC_ALERT
|
329 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
|
333 smb2_transport_compound_start(tree
->session
->transport
, 5);
335 req
[0] = smb2_create_send(tree
, &cr
);
337 hd
.data
[0] = UINT64_MAX
;
338 hd
.data
[1] = UINT64_MAX
;
340 smb2_transport_compound_set_related(tree
->session
->transport
, true);
343 cl
.in
.file
.handle
= hd
;
345 tree
->smbXcli
= smbXcli_tcon_create(tree
);
346 smb2cli_tcon_set_values(tree
->smbXcli
,
348 0xFFFFFFFF, /* tcon_id */
351 0, /* capabilities */
352 0 /* maximal_access */);
354 tree
->session
->smbXcli
= smbXcli_session_shallow_copy(tree
->session
,
355 tree
->session
->smbXcli
);
356 smb2cli_session_set_id_and_flags(tree
->session
->smbXcli
, UINT64_MAX
, 0);
358 req
[1] = smb2_close_send(tree
, &cl
);
359 req
[2] = smb2_close_send(tree
, &cl
);
360 req
[3] = smb2_close_send(tree
, &cl
);
361 req
[4] = smb2_close_send(tree
, &cl
);
363 status
= smb2_create_recv(req
[0], tree
, &cr
);
364 CHECK_STATUS(status
, NT_STATUS_OK
);
365 status
= smb2_close_recv(req
[1], &cl
);
366 CHECK_STATUS(status
, NT_STATUS_OK
);
367 status
= smb2_close_recv(req
[2], &cl
);
368 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
369 status
= smb2_close_recv(req
[3], &cl
);
370 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
371 status
= smb2_close_recv(req
[4], &cl
);
372 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
374 TALLOC_FREE(tree
->smbXcli
);
375 tree
->smbXcli
= saved_tcon
;
376 TALLOC_FREE(tree
->session
->smbXcli
);
377 tree
->session
->smbXcli
= saved_session
;
379 smb2_util_unlink(tree
, fname
);
384 static bool test_compound_related3(struct torture_context
*tctx
,
385 struct smb2_tree
*tree
)
387 struct smb2_handle hd
;
388 struct smb2_ioctl io
;
389 struct smb2_create cr
;
390 struct smb2_close cl
;
391 const char *fname
= "compound_related3.dat";
392 struct smb2_request
*req
[3];
396 smb2_util_unlink(tree
, fname
);
399 cr
.in
.security_flags
= 0x00;
400 cr
.in
.oplock_level
= 0;
401 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
402 cr
.in
.create_flags
= 0x00000000;
403 cr
.in
.reserved
= 0x00000000;
404 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
405 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
406 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
407 NTCREATEX_SHARE_ACCESS_WRITE
|
408 NTCREATEX_SHARE_ACCESS_DELETE
;
409 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
410 cr
.in
.create_options
= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY
|
411 NTCREATEX_OPTIONS_ASYNC_ALERT
|
412 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
|
416 smb2_transport_compound_start(tree
->session
->transport
, 3);
418 req
[0] = smb2_create_send(tree
, &cr
);
420 hd
.data
[0] = UINT64_MAX
;
421 hd
.data
[1] = UINT64_MAX
;
423 smb2_transport_compound_set_related(tree
->session
->transport
, true);
426 io
.in
.function
= FSCTL_CREATE_OR_GET_OBJECT_ID
;
427 io
.in
.file
.handle
= hd
;
429 io
.in
.max_output_response
= 64;
432 req
[1] = smb2_ioctl_send(tree
, &io
);
435 cl
.in
.file
.handle
= hd
;
437 req
[2] = smb2_close_send(tree
, &cl
);
439 status
= smb2_create_recv(req
[0], tree
, &cr
);
440 CHECK_STATUS(status
, NT_STATUS_OK
);
441 status
= smb2_ioctl_recv(req
[1], tree
, &io
);
442 CHECK_STATUS(status
, NT_STATUS_OK
);
443 status
= smb2_close_recv(req
[2], &cl
);
444 CHECK_STATUS(status
, NT_STATUS_OK
);
446 status
= smb2_util_unlink(tree
, fname
);
447 CHECK_STATUS(status
, NT_STATUS_OK
);
454 static bool test_compound_related4(struct torture_context
*tctx
,
455 struct smb2_tree
*tree
)
457 const char *fname
= "compound_related4.dat";
458 struct security_descriptor
*sd
= NULL
;
459 struct smb2_handle hd
;
460 struct smb2_create cr
;
461 union smb_setfileinfo set
;
462 struct smb2_ioctl io
;
463 struct smb2_close cl
;
464 struct smb2_request
*req
[4];
468 smb2_util_unlink(tree
, fname
);
471 cr
.level
= RAW_OPEN_SMB2
;
472 cr
.in
.create_flags
= 0;
473 cr
.in
.desired_access
= SEC_STD_READ_CONTROL
|
476 cr
.in
.create_options
= 0;
477 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
478 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_DELETE
|
479 NTCREATEX_SHARE_ACCESS_READ
|
480 NTCREATEX_SHARE_ACCESS_WRITE
;
481 cr
.in
.alloc_size
= 0;
482 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
483 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
484 cr
.in
.security_flags
= 0;
487 status
= smb2_create(tree
, tctx
, &cr
);
488 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
, "smb2_create failed\n");
490 hd
= cr
.out
.file
.handle
;
491 torture_comment(tctx
, "set a sec desc allowing no write by CREATOR_OWNER\n");
493 sd
= security_descriptor_dacl_create(tctx
,
496 SEC_ACE_TYPE_ACCESS_ALLOWED
,
497 SEC_RIGHTS_FILE_READ
| SEC_STD_ALL
,
500 torture_assert_not_null_goto(tctx
, sd
, ret
, done
,
501 "security_descriptor_dacl_create failed\n");
503 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
504 set
.set_secdesc
.in
.file
.handle
= hd
;
505 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
506 set
.set_secdesc
.in
.sd
= sd
;
508 status
= smb2_setinfo_file(tree
, &set
);
509 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
510 "smb2_setinfo_file failed\n");
512 torture_comment(tctx
, "try open for write\n");
513 cr
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
514 smb2_transport_compound_start(tree
->session
->transport
, 4);
516 req
[0] = smb2_create_send(tree
, &cr
);
517 torture_assert_not_null_goto(tctx
, req
[0], ret
, done
,
518 "smb2_create_send failed\n");
520 hd
.data
[0] = UINT64_MAX
;
521 hd
.data
[1] = UINT64_MAX
;
523 smb2_transport_compound_set_related(tree
->session
->transport
, true);
525 io
.in
.function
= FSCTL_CREATE_OR_GET_OBJECT_ID
;
526 io
.in
.file
.handle
= hd
;
529 req
[1] = smb2_ioctl_send(tree
, &io
);
530 torture_assert_not_null_goto(tctx
, req
[1], ret
, done
,
531 "smb2_ioctl_send failed\n");
534 cl
.in
.file
.handle
= hd
;
536 req
[2] = smb2_close_send(tree
, &cl
);
537 torture_assert_not_null_goto(tctx
, req
[2], ret
, done
,
538 "smb2_create_send failed\n");
540 set
.set_secdesc
.in
.file
.handle
= hd
;
542 req
[3] = smb2_setinfo_file_send(tree
, &set
);
543 torture_assert_not_null_goto(tctx
, req
[3], ret
, done
,
544 "smb2_create_send failed\n");
546 status
= smb2_create_recv(req
[0], tree
, &cr
);
547 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_ACCESS_DENIED
,
549 "smb2_create_recv failed\n");
551 status
= smb2_ioctl_recv(req
[1], tree
, &io
);
552 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_ACCESS_DENIED
,
554 "smb2_ioctl_recv failed\n");
556 status
= smb2_close_recv(req
[2], &cl
);
557 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_ACCESS_DENIED
,
559 "smb2_close_recv failed\n");
561 status
= smb2_setinfo_recv(req
[3]);
562 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_ACCESS_DENIED
,
564 "smb2_setinfo_recv failed\n");
567 smb2_util_unlink(tree
, fname
);
569 smb2_logoff(tree
->session
);
573 static bool test_compound_related5(struct torture_context
*tctx
,
574 struct smb2_tree
*tree
)
576 struct smb2_handle hd
;
577 struct smb2_ioctl io
;
578 struct smb2_close cl
;
579 struct smb2_request
*req
[2];
583 smb2_transport_compound_start(tree
->session
->transport
, 2);
585 hd
.data
[0] = UINT64_MAX
;
586 hd
.data
[1] = UINT64_MAX
;
589 io
.in
.function
= FSCTL_CREATE_OR_GET_OBJECT_ID
;
590 io
.in
.file
.handle
= hd
;
593 req
[0] = smb2_ioctl_send(tree
, &io
);
594 torture_assert_not_null_goto(tctx
, req
[0], ret
, done
,
595 "smb2_ioctl_send failed\n");
597 smb2_transport_compound_set_related(tree
->session
->transport
, true);
600 cl
.in
.file
.handle
= hd
;
602 req
[1] = smb2_close_send(tree
, &cl
);
603 torture_assert_not_null_goto(tctx
, req
[1], ret
, done
,
604 "smb2_create_send failed\n");
606 status
= smb2_ioctl_recv(req
[0], tree
, &io
);
607 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_FILE_CLOSED
,
609 "smb2_ioctl_recv failed\n");
611 status
= smb2_close_recv(req
[1], &cl
);
612 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_FILE_CLOSED
,
614 "smb2_close_recv failed\n");
620 smb2_logoff(tree
->session
);
624 static bool test_compound_related6(struct torture_context
*tctx
,
625 struct smb2_tree
*tree
)
627 struct smb2_handle hd
;
628 struct smb2_create cr
;
630 struct smb2_write wr
;
631 struct smb2_close cl
;
633 const char *fname
= "compound_related6.dat";
634 struct smb2_request
*req
[5];
638 smb2_util_unlink(tree
, fname
);
641 cr
.level
= RAW_OPEN_SMB2
;
642 cr
.in
.create_flags
= 0;
643 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
644 cr
.in
.create_options
= 0;
645 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
646 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_DELETE
|
647 NTCREATEX_SHARE_ACCESS_READ
|
648 NTCREATEX_SHARE_ACCESS_WRITE
;
649 cr
.in
.alloc_size
= 0;
650 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
651 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
652 cr
.in
.security_flags
= 0;
655 status
= smb2_create(tree
, tctx
, &cr
);
656 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
657 "smb2_create failed\n");
659 hd
= cr
.out
.file
.handle
;
662 status
= smb2_util_write(tree
, hd
, buf
, 0, ARRAY_SIZE(buf
));
663 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
664 "smb2_util_write failed\n");
666 torture_comment(tctx
, "try open for read\n");
667 cr
.in
.desired_access
= SEC_FILE_READ_DATA
;
668 smb2_transport_compound_start(tree
->session
->transport
, 5);
670 req
[0] = smb2_create_send(tree
, &cr
);
671 torture_assert_not_null_goto(tctx
, req
[0], ret
, done
,
672 "smb2_create_send failed\n");
674 hd
.data
[0] = UINT64_MAX
;
675 hd
.data
[1] = UINT64_MAX
;
677 smb2_transport_compound_set_related(tree
->session
->transport
, true);
680 rd
.in
.file
.handle
= hd
;
684 req
[1] = smb2_read_send(tree
, &rd
);
685 torture_assert_not_null_goto(tctx
, req
[1], ret
, done
,
686 "smb2_read_send failed\n");
689 wr
.in
.file
.handle
= hd
;
691 wr
.in
.data
= data_blob_talloc(tctx
, NULL
, 64);
693 req
[2] = smb2_write_send(tree
, &wr
);
694 torture_assert_not_null_goto(tctx
, req
[2], ret
, done
,
695 "smb2_write_send failed\n");
698 rd
.in
.file
.handle
= hd
;
702 req
[3] = smb2_read_send(tree
, &rd
);
703 torture_assert_not_null_goto(tctx
, req
[3], ret
, done
,
704 "smb2_read_send failed\n");
707 cl
.in
.file
.handle
= hd
;
709 req
[4] = smb2_close_send(tree
, &cl
);
710 torture_assert_not_null_goto(tctx
, req
[4], ret
, done
,
711 "smb2_close_send failed\n");
713 status
= smb2_create_recv(req
[0], tree
, &cr
);
714 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
715 "smb2_create_recv failed\n");
717 status
= smb2_read_recv(req
[1], tree
, &rd
);
718 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
719 "smb2_read_recv failed\n");
721 status
= smb2_write_recv(req
[2], &wr
);
722 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_ACCESS_DENIED
,
724 "smb2_write_recv failed\n");
726 status
= smb2_read_recv(req
[3], tree
, &rd
);
727 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
728 "smb2_read_recv failed\n");
730 status
= smb2_close_recv(req
[4], &cl
);
731 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
732 "smb2_close_recv failed\n");
735 smb2_util_unlink(tree
, fname
);
737 smb2_logoff(tree
->session
);
741 static bool test_compound_related7(struct torture_context
*tctx
,
742 struct smb2_tree
*tree
)
744 const char *fname
= "compound_related4.dat";
745 struct security_descriptor
*sd
= NULL
;
746 struct smb2_handle hd
;
747 struct smb2_create cr
;
748 union smb_setfileinfo set
;
749 struct smb2_notify nt
;
750 struct smb2_close cl
;
752 struct smb2_request
*req
[4];
755 smb2_util_unlink(tree
, fname
);
758 cr
.level
= RAW_OPEN_SMB2
;
759 cr
.in
.create_flags
= 0;
760 cr
.in
.desired_access
= SEC_STD_READ_CONTROL
|
763 cr
.in
.create_options
= 0;
764 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
765 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_DELETE
|
766 NTCREATEX_SHARE_ACCESS_READ
|
767 NTCREATEX_SHARE_ACCESS_WRITE
;
768 cr
.in
.alloc_size
= 0;
769 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
770 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
771 cr
.in
.security_flags
= 0;
774 status
= smb2_create(tree
, tctx
, &cr
);
775 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
776 "smb2_create failed\n");
778 hd
= cr
.out
.file
.handle
;
779 torture_comment(tctx
, "set a sec desc allowing no write by CREATOR_OWNER\n");
780 sd
= security_descriptor_dacl_create(tctx
,
783 SEC_ACE_TYPE_ACCESS_ALLOWED
,
784 SEC_RIGHTS_FILE_READ
| SEC_STD_ALL
,
787 torture_assert_not_null_goto(tctx
, sd
, ret
, done
,
788 "security_descriptor_dacl_create failed\n");
790 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
791 set
.set_secdesc
.in
.file
.handle
= hd
;
792 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
793 set
.set_secdesc
.in
.sd
= sd
;
795 status
= smb2_setinfo_file(tree
, &set
);
796 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
797 "smb2_setinfo_file failed\n");
799 torture_comment(tctx
, "try open for write\n");
800 cr
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
801 smb2_transport_compound_start(tree
->session
->transport
, 4);
803 req
[0] = smb2_create_send(tree
, &cr
);
804 torture_assert_not_null_goto(tctx
, req
[0], ret
, done
,
805 "smb2_create_send failed\n");
807 hd
.data
[0] = UINT64_MAX
;
808 hd
.data
[1] = UINT64_MAX
;
810 smb2_transport_compound_set_related(tree
->session
->transport
, true);
813 nt
.in
.recursive
= true;
814 nt
.in
.buffer_size
= 0x1000;
815 nt
.in
.file
.handle
= hd
;
816 nt
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
817 nt
.in
.unknown
= 0x00000000;
819 req
[1] = smb2_notify_send(tree
, &nt
);
820 torture_assert_not_null_goto(tctx
, req
[1], ret
, done
,
821 "smb2_notify_send failed\n");
824 cl
.in
.file
.handle
= hd
;
826 req
[2] = smb2_close_send(tree
, &cl
);
827 torture_assert_not_null_goto(tctx
, req
[2], ret
, done
,
828 "smb2_close_send failed\n");
830 set
.set_secdesc
.in
.file
.handle
= hd
;
832 req
[3] = smb2_setinfo_file_send(tree
, &set
);
833 torture_assert_not_null_goto(tctx
, req
[3], ret
, done
,
834 "smb2_setinfo_file_send failed\n");
836 status
= smb2_create_recv(req
[0], tree
, &cr
);
837 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_ACCESS_DENIED
,
839 "smb2_create_recv failed\n");
841 status
= smb2_notify_recv(req
[1], tree
, &nt
);
842 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_ACCESS_DENIED
,
844 "smb2_notify_recv failed\n");
846 status
= smb2_close_recv(req
[2], &cl
);
847 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_ACCESS_DENIED
,
849 "smb2_close_recv failed\n");
851 status
= smb2_setinfo_recv(req
[3]);
852 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_ACCESS_DENIED
,
854 "smb2_setinfo_recv failed\n");
857 smb2_util_unlink(tree
, fname
);
859 smb2_logoff(tree
->session
);
863 static bool test_compound_related8(struct torture_context
*tctx
,
864 struct smb2_tree
*tree
)
866 const char *fname
= "compound_related8.dat";
867 const char *fname_nonexisting
= "compound_related8.dat.void";
868 struct security_descriptor
*sd
= NULL
;
869 struct smb2_handle hd
;
870 struct smb2_create cr
;
871 union smb_setfileinfo set
;
872 struct smb2_notify nt
;
873 struct smb2_close cl
;
875 struct smb2_request
*req
[4];
878 smb2_util_unlink(tree
, fname
);
881 cr
.level
= RAW_OPEN_SMB2
;
882 cr
.in
.create_flags
= 0;
883 cr
.in
.desired_access
= SEC_STD_READ_CONTROL
|
886 cr
.in
.create_options
= 0;
887 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
888 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_DELETE
|
889 NTCREATEX_SHARE_ACCESS_READ
|
890 NTCREATEX_SHARE_ACCESS_WRITE
;
891 cr
.in
.alloc_size
= 0;
892 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
893 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
894 cr
.in
.security_flags
= 0;
897 status
= smb2_create(tree
, tctx
, &cr
);
898 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
899 "smb2_create failed\n");
901 hd
= cr
.out
.file
.handle
;
903 smb2_transport_compound_start(tree
->session
->transport
, 4);
905 torture_comment(tctx
, "try open for write\n");
906 cr
.in
.fname
= fname_nonexisting
;
907 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
909 req
[0] = smb2_create_send(tree
, &cr
);
910 torture_assert_not_null_goto(tctx
, req
[0], ret
, done
,
911 "smb2_create_send failed\n");
913 hd
.data
[0] = UINT64_MAX
;
914 hd
.data
[1] = UINT64_MAX
;
916 smb2_transport_compound_set_related(tree
->session
->transport
, true);
919 nt
.in
.recursive
= true;
920 nt
.in
.buffer_size
= 0x1000;
921 nt
.in
.file
.handle
= hd
;
922 nt
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
923 nt
.in
.unknown
= 0x00000000;
925 req
[1] = smb2_notify_send(tree
, &nt
);
926 torture_assert_not_null_goto(tctx
, req
[1], ret
, done
,
927 "smb2_notify_send failed\n");
930 cl
.in
.file
.handle
= hd
;
932 req
[2] = smb2_close_send(tree
, &cl
);
933 torture_assert_not_null_goto(tctx
, req
[2], ret
, done
,
934 "smb2_close_send failed\n");
936 sd
= security_descriptor_dacl_create(tctx
,
939 SEC_ACE_TYPE_ACCESS_ALLOWED
,
940 SEC_RIGHTS_FILE_READ
| SEC_STD_ALL
,
943 torture_assert_not_null_goto(tctx
, sd
, ret
, done
,
944 "security_descriptor_dacl_create failed\n");
946 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
947 set
.set_secdesc
.in
.file
.handle
= hd
;
948 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
949 set
.set_secdesc
.in
.sd
= sd
;
951 req
[3] = smb2_setinfo_file_send(tree
, &set
);
952 torture_assert_not_null_goto(tctx
, req
[3], ret
, done
,
953 "smb2_setinfo_file_send failed\n");
955 status
= smb2_create_recv(req
[0], tree
, &cr
);
956 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
958 "smb2_create_recv failed\n");
960 status
= smb2_notify_recv(req
[1], tree
, &nt
);
961 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
963 "smb2_notify_recv failed\n");
965 status
= smb2_close_recv(req
[2], &cl
);
966 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
968 "smb2_close_recv failed\n");
970 status
= smb2_setinfo_recv(req
[3]);
971 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
973 "smb2_setinfo_recv failed\n");
976 smb2_util_unlink(tree
, fname
);
978 smb2_logoff(tree
->session
);
982 static bool test_compound_related9(struct torture_context
*tctx
,
983 struct smb2_tree
*tree
)
985 const char *fname
= "compound_related9.dat";
986 struct security_descriptor
*sd
= NULL
;
987 struct smb2_handle hd
;
988 struct smb2_create cr
;
989 union smb_setfileinfo set
;
990 struct smb2_notify nt
;
991 struct smb2_close cl
;
993 struct smb2_request
*req
[3];
996 smb2_util_unlink(tree
, fname
);
999 cr
.level
= RAW_OPEN_SMB2
;
1000 cr
.in
.create_flags
= 0;
1001 cr
.in
.desired_access
= SEC_STD_READ_CONTROL
|
1003 SEC_STD_WRITE_OWNER
;
1004 cr
.in
.create_options
= 0;
1005 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1006 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_DELETE
|
1007 NTCREATEX_SHARE_ACCESS_READ
|
1008 NTCREATEX_SHARE_ACCESS_WRITE
;
1009 cr
.in
.alloc_size
= 0;
1010 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1011 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1012 cr
.in
.security_flags
= 0;
1013 cr
.in
.fname
= fname
;
1015 status
= smb2_create(tree
, tctx
, &cr
);
1016 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1017 "smb2_create failed\n");
1019 hd
= cr
.out
.file
.handle
;
1021 smb2_transport_compound_start(tree
->session
->transport
, 3);
1022 smb2_transport_compound_set_related(tree
->session
->transport
, true);
1025 nt
.in
.recursive
= true;
1026 nt
.in
.buffer_size
= 0x1000;
1027 nt
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1029 req
[0] = smb2_notify_send(tree
, &nt
);
1030 torture_assert_not_null_goto(tctx
, req
[0], ret
, done
,
1031 "smb2_notify_send failed\n");
1034 cl
.in
.file
.handle
= hd
;
1036 req
[1] = smb2_close_send(tree
, &cl
);
1037 torture_assert_not_null_goto(tctx
, req
[1], ret
, done
,
1038 "smb2_close_send failed\n");
1040 sd
= security_descriptor_dacl_create(tctx
,
1043 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1044 SEC_RIGHTS_FILE_READ
| SEC_STD_ALL
,
1047 torture_assert_not_null_goto(tctx
, sd
, ret
, done
,
1048 "security_descriptor_dacl_create failed\n");
1050 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1051 set
.set_secdesc
.in
.file
.handle
= hd
;
1052 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1053 set
.set_secdesc
.in
.sd
= sd
;
1055 req
[2] = smb2_setinfo_file_send(tree
, &set
);
1056 torture_assert_not_null_goto(tctx
, req
[2], ret
, done
,
1057 "smb2_setinfo_file_send failed\n");
1059 status
= smb2_notify_recv(req
[0], tree
, &nt
);
1060 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_INVALID_PARAMETER
,
1062 "smb2_notify_recv failed\n");
1064 status
= smb2_close_recv(req
[1], &cl
);
1065 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_INVALID_PARAMETER
,
1067 "smb2_close_recv failed\n");
1069 status
= smb2_setinfo_recv(req
[2]);
1070 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_INVALID_PARAMETER
,
1072 "smb2_setinfo_recv failed\n");
1075 smb2_util_unlink(tree
, fname
);
1077 smb2_logoff(tree
->session
);
1081 static bool test_compound_padding(struct torture_context
*tctx
,
1082 struct smb2_tree
*tree
)
1084 struct smb2_handle h
;
1085 struct smb2_create cr
;
1087 struct smb2_read r2
;
1088 const char *fname
= "compound_read.dat";
1089 const char *sname
= "compound_read.dat:foo";
1090 struct smb2_request
*req
[3];
1094 smb2_util_unlink(tree
, fname
);
1098 cr
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
1099 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1100 cr
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1101 cr
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1102 cr
.in
.fname
= fname
;
1103 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1104 NTCREATEX_SHARE_ACCESS_WRITE
|
1105 NTCREATEX_SHARE_ACCESS_DELETE
;
1106 status
= smb2_create(tree
, tctx
, &cr
);
1107 CHECK_STATUS(status
, NT_STATUS_OK
);
1108 h
= cr
.out
.file
.handle
;
1110 status
= smb2_util_write(tree
, h
, "123", 0, 3);
1111 CHECK_STATUS(status
, NT_STATUS_OK
);
1113 smb2_util_close(tree
, h
);
1117 cr
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
1118 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1119 cr
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1120 cr
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1121 cr
.in
.fname
= sname
;
1122 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1123 NTCREATEX_SHARE_ACCESS_WRITE
|
1124 NTCREATEX_SHARE_ACCESS_DELETE
;
1125 status
= smb2_create(tree
, tctx
, &cr
);
1126 CHECK_STATUS(status
, NT_STATUS_OK
);
1127 h
= cr
.out
.file
.handle
;
1129 status
= smb2_util_write(tree
, h
, "456", 0, 3);
1130 CHECK_STATUS(status
, NT_STATUS_OK
);
1132 smb2_util_close(tree
, h
);
1134 /* Check compound read from basefile */
1135 smb2_transport_compound_start(tree
->session
->transport
, 3);
1138 cr
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1139 cr
.in
.desired_access
= SEC_FILE_READ_DATA
;
1140 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1141 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1142 cr
.in
.fname
= fname
;
1143 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1144 NTCREATEX_SHARE_ACCESS_WRITE
|
1145 NTCREATEX_SHARE_ACCESS_DELETE
;
1146 req
[0] = smb2_create_send(tree
, &cr
);
1148 smb2_transport_compound_set_related(tree
->session
->transport
, true);
1151 * We send 2 reads in the compound here as the protocol
1152 * allows the last read to be split off and possibly
1153 * go async. Check the padding on the first read returned,
1154 * not the second as the second may not be part of the
1155 * returned compound.
1159 h
.data
[0] = UINT64_MAX
;
1160 h
.data
[1] = UINT64_MAX
;
1161 r
.in
.file
.handle
= h
;
1165 req
[1] = smb2_read_send(tree
, &r
);
1168 h
.data
[0] = UINT64_MAX
;
1169 h
.data
[1] = UINT64_MAX
;
1170 r2
.in
.file
.handle
= h
;
1173 r2
.in
.min_count
= 1;
1174 req
[2] = smb2_read_send(tree
, &r2
);
1176 status
= smb2_create_recv(req
[0], tree
, &cr
);
1177 CHECK_STATUS(status
, NT_STATUS_OK
);
1180 * We must do a manual smb2_request_receive() in order to be
1181 * able to check the transport layer info, as smb2_read_recv()
1182 * will destroy the req. smb2_read_recv() will call
1183 * smb2_request_receive() again, but that's ok.
1185 if (!smb2_request_receive(req
[1]) ||
1186 !smb2_request_is_ok(req
[1])) {
1187 torture_fail(tctx
, "failed to receive read request");
1191 * size must be 24: 16 byte read response header plus 3
1192 * requested bytes padded to an 8 byte boundary.
1194 CHECK_VALUE(req
[1]->in
.body_size
, 24);
1196 status
= smb2_read_recv(req
[1], tree
, &r
);
1197 CHECK_STATUS(status
, NT_STATUS_OK
);
1199 /* Pick up the second, possibly async, read. */
1200 status
= smb2_read_recv(req
[2], tree
, &r2
);
1201 CHECK_STATUS(status
, NT_STATUS_OK
);
1203 smb2_util_close(tree
, cr
.out
.file
.handle
);
1205 /* Check compound read from stream */
1206 smb2_transport_compound_start(tree
->session
->transport
, 3);
1209 cr
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1210 cr
.in
.desired_access
= SEC_FILE_READ_DATA
;
1211 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1212 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1213 cr
.in
.fname
= sname
;
1214 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1215 NTCREATEX_SHARE_ACCESS_WRITE
|
1216 NTCREATEX_SHARE_ACCESS_DELETE
;
1217 req
[0] = smb2_create_send(tree
, &cr
);
1219 smb2_transport_compound_set_related(tree
->session
->transport
, true);
1222 * We send 2 reads in the compound here as the protocol
1223 * allows the last read to be split off and possibly
1224 * go async. Check the padding on the first read returned,
1225 * not the second as the second may not be part of the
1226 * returned compound.
1230 h
.data
[0] = UINT64_MAX
;
1231 h
.data
[1] = UINT64_MAX
;
1232 r
.in
.file
.handle
= h
;
1236 req
[1] = smb2_read_send(tree
, &r
);
1239 h
.data
[0] = UINT64_MAX
;
1240 h
.data
[1] = UINT64_MAX
;
1241 r2
.in
.file
.handle
= h
;
1244 r2
.in
.min_count
= 1;
1245 req
[2] = smb2_read_send(tree
, &r2
);
1247 status
= smb2_create_recv(req
[0], tree
, &cr
);
1248 CHECK_STATUS(status
, NT_STATUS_OK
);
1251 * We must do a manual smb2_request_receive() in order to be
1252 * able to check the transport layer info, as smb2_read_recv()
1253 * will destroy the req. smb2_read_recv() will call
1254 * smb2_request_receive() again, but that's ok.
1256 if (!smb2_request_receive(req
[1]) ||
1257 !smb2_request_is_ok(req
[1])) {
1258 torture_fail(tctx
, "failed to receive read request");
1262 * size must be 24: 16 byte read response header plus 3
1263 * requested bytes padded to an 8 byte boundary.
1265 CHECK_VALUE(req
[1]->in
.body_size
, 24);
1267 status
= smb2_read_recv(req
[1], tree
, &r
);
1268 CHECK_STATUS(status
, NT_STATUS_OK
);
1270 /* Pick up the second, possibly async, read. */
1271 status
= smb2_read_recv(req
[2], tree
, &r2
);
1272 CHECK_STATUS(status
, NT_STATUS_OK
);
1274 h
= cr
.out
.file
.handle
;
1276 /* Check 2 compound (unrelateated) reads from existing stream handle */
1277 smb2_transport_compound_start(tree
->session
->transport
, 2);
1280 r
.in
.file
.handle
= h
;
1284 req
[0] = smb2_read_send(tree
, &r
);
1285 req
[1] = smb2_read_send(tree
, &r
);
1288 * We must do a manual smb2_request_receive() in order to be
1289 * able to check the transport layer info, as smb2_read_recv()
1290 * will destroy the req. smb2_read_recv() will call
1291 * smb2_request_receive() again, but that's ok.
1293 if (!smb2_request_receive(req
[0]) ||
1294 !smb2_request_is_ok(req
[0])) {
1295 torture_fail(tctx
, "failed to receive read request");
1297 if (!smb2_request_receive(req
[1]) ||
1298 !smb2_request_is_ok(req
[1])) {
1299 torture_fail(tctx
, "failed to receive read request");
1303 * size must be 24: 16 byte read response header plus 3
1304 * requested bytes padded to an 8 byte boundary.
1306 CHECK_VALUE(req
[0]->in
.body_size
, 24);
1307 CHECK_VALUE(req
[1]->in
.body_size
, 24);
1309 status
= smb2_read_recv(req
[0], tree
, &r
);
1310 CHECK_STATUS(status
, NT_STATUS_OK
);
1311 status
= smb2_read_recv(req
[1], tree
, &r
);
1312 CHECK_STATUS(status
, NT_STATUS_OK
);
1315 * now try a single read from the stream and verify there's no padding
1318 r
.in
.file
.handle
= h
;
1322 req
[0] = smb2_read_send(tree
, &r
);
1325 * We must do a manual smb2_request_receive() in order to be
1326 * able to check the transport layer info, as smb2_read_recv()
1327 * will destroy the req. smb2_read_recv() will call
1328 * smb2_request_receive() again, but that's ok.
1330 if (!smb2_request_receive(req
[0]) ||
1331 !smb2_request_is_ok(req
[0])) {
1332 torture_fail(tctx
, "failed to receive read request");
1336 * size must be 19: 16 byte read response header plus 3
1337 * requested bytes without padding.
1339 CHECK_VALUE(req
[0]->in
.body_size
, 19);
1341 status
= smb2_read_recv(req
[0], tree
, &r
);
1342 CHECK_STATUS(status
, NT_STATUS_OK
);
1344 smb2_util_close(tree
, h
);
1346 status
= smb2_util_unlink(tree
, fname
);
1347 CHECK_STATUS(status
, NT_STATUS_OK
);
1354 static bool test_compound_create_write_close(struct torture_context
*tctx
,
1355 struct smb2_tree
*tree
)
1357 struct smb2_handle handle
= { .data
= { UINT64_MAX
, UINT64_MAX
} };
1358 struct smb2_create create
;
1359 struct smb2_write write
;
1360 struct smb2_close close
;
1361 const char *fname
= "compound_create_write_close.dat";
1362 struct smb2_request
*req
[3];
1366 smb2_util_unlink(tree
, fname
);
1368 ZERO_STRUCT(create
);
1369 create
.in
.security_flags
= 0x00;
1370 create
.in
.oplock_level
= 0;
1371 create
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
1372 create
.in
.create_flags
= 0x00000000;
1373 create
.in
.reserved
= 0x00000000;
1374 create
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1375 create
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1376 create
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1377 NTCREATEX_SHARE_ACCESS_WRITE
|
1378 NTCREATEX_SHARE_ACCESS_DELETE
;
1379 create
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1380 create
.in
.create_options
= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY
|
1381 NTCREATEX_OPTIONS_ASYNC_ALERT
|
1382 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
|
1384 create
.in
.fname
= fname
;
1386 smb2_transport_compound_start(tree
->session
->transport
, 3);
1388 req
[0] = smb2_create_send(tree
, &create
);
1390 smb2_transport_compound_set_related(tree
->session
->transport
, true);
1393 write
.in
.file
.handle
= handle
;
1394 write
.in
.offset
= 0;
1395 write
.in
.data
= data_blob_talloc(tctx
, NULL
, 1024);
1397 req
[1] = smb2_write_send(tree
, &write
);
1400 close
.in
.file
.handle
= handle
;
1402 req
[2] = smb2_close_send(tree
, &close
);
1404 status
= smb2_create_recv(req
[0], tree
, &create
);
1405 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1408 status
= smb2_write_recv(req
[1], &write
);
1409 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1412 status
= smb2_close_recv(req
[2], &close
);
1413 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1416 status
= smb2_util_unlink(tree
, fname
);
1417 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1418 "File deletion failed.");
1425 static bool test_compound_unrelated1(struct torture_context
*tctx
,
1426 struct smb2_tree
*tree
)
1428 struct smb2_handle hd
;
1429 struct smb2_create cr
;
1431 const char *fname
= "compound_unrelated1.dat";
1432 struct smb2_close cl
;
1434 struct smb2_request
*req
[5];
1436 smb2_transport_credits_ask_num(tree
->session
->transport
, 5);
1438 smb2_util_unlink(tree
, fname
);
1440 smb2_transport_credits_ask_num(tree
->session
->transport
, 1);
1443 cr
.in
.security_flags
= 0x00;
1444 cr
.in
.oplock_level
= 0;
1445 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
1446 cr
.in
.create_flags
= 0x00000000;
1447 cr
.in
.reserved
= 0x00000000;
1448 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1449 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1450 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1451 NTCREATEX_SHARE_ACCESS_WRITE
|
1452 NTCREATEX_SHARE_ACCESS_DELETE
;
1453 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1454 cr
.in
.create_options
= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY
|
1455 NTCREATEX_OPTIONS_ASYNC_ALERT
|
1456 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
|
1458 cr
.in
.fname
= fname
;
1460 smb2_transport_compound_start(tree
->session
->transport
, 5);
1462 req
[0] = smb2_create_send(tree
, &cr
);
1464 hd
.data
[0] = UINT64_MAX
;
1465 hd
.data
[1] = UINT64_MAX
;
1468 cl
.in
.file
.handle
= hd
;
1469 req
[1] = smb2_close_send(tree
, &cl
);
1470 req
[2] = smb2_close_send(tree
, &cl
);
1471 req
[3] = smb2_close_send(tree
, &cl
);
1472 req
[4] = smb2_close_send(tree
, &cl
);
1474 status
= smb2_create_recv(req
[0], tree
, &cr
);
1475 CHECK_STATUS(status
, NT_STATUS_OK
);
1476 status
= smb2_close_recv(req
[1], &cl
);
1477 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
1478 status
= smb2_close_recv(req
[2], &cl
);
1479 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
1480 status
= smb2_close_recv(req
[3], &cl
);
1481 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
1482 status
= smb2_close_recv(req
[4], &cl
);
1483 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
1485 smb2_util_unlink(tree
, fname
);
1490 static bool test_compound_invalid1(struct torture_context
*tctx
,
1491 struct smb2_tree
*tree
)
1493 struct smb2_handle hd
;
1494 struct smb2_create cr
;
1496 const char *fname
= "compound_invalid1.dat";
1497 struct smb2_close cl
;
1499 struct smb2_request
*req
[3];
1501 smb2_transport_credits_ask_num(tree
->session
->transport
, 3);
1503 smb2_util_unlink(tree
, fname
);
1505 smb2_transport_credits_ask_num(tree
->session
->transport
, 1);
1508 cr
.in
.security_flags
= 0x00;
1509 cr
.in
.oplock_level
= 0;
1510 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
1511 cr
.in
.create_flags
= 0x00000000;
1512 cr
.in
.reserved
= 0x00000000;
1513 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1514 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1515 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1516 NTCREATEX_SHARE_ACCESS_WRITE
|
1517 NTCREATEX_SHARE_ACCESS_DELETE
;
1518 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1519 cr
.in
.create_options
= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY
|
1520 NTCREATEX_OPTIONS_ASYNC_ALERT
|
1521 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
|
1523 cr
.in
.fname
= fname
;
1525 smb2_transport_compound_start(tree
->session
->transport
, 3);
1527 /* passing the first request with the related flag is invalid */
1528 smb2_transport_compound_set_related(tree
->session
->transport
, true);
1530 req
[0] = smb2_create_send(tree
, &cr
);
1532 hd
.data
[0] = UINT64_MAX
;
1533 hd
.data
[1] = UINT64_MAX
;
1536 cl
.in
.file
.handle
= hd
;
1537 req
[1] = smb2_close_send(tree
, &cl
);
1539 smb2_transport_compound_set_related(tree
->session
->transport
, false);
1540 req
[2] = smb2_close_send(tree
, &cl
);
1542 status
= smb2_create_recv(req
[0], tree
, &cr
);
1543 /* TODO: check why this fails with --signing=required */
1544 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
1545 status
= smb2_close_recv(req
[1], &cl
);
1546 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
1547 status
= smb2_close_recv(req
[2], &cl
);
1548 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
1550 smb2_util_unlink(tree
, fname
);
1555 static bool test_compound_invalid2(struct torture_context
*tctx
,
1556 struct smb2_tree
*tree
)
1558 struct smb2_handle hd
;
1559 struct smb2_create cr
;
1561 const char *fname
= "compound_invalid2.dat";
1562 struct smb2_close cl
;
1564 struct smb2_request
*req
[5];
1565 struct smbXcli_tcon
*saved_tcon
= tree
->smbXcli
;
1566 struct smbXcli_session
*saved_session
= tree
->session
->smbXcli
;
1568 smb2_transport_credits_ask_num(tree
->session
->transport
, 5);
1570 smb2_util_unlink(tree
, fname
);
1572 smb2_transport_credits_ask_num(tree
->session
->transport
, 1);
1575 cr
.in
.security_flags
= 0x00;
1576 cr
.in
.oplock_level
= 0;
1577 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
1578 cr
.in
.create_flags
= 0x00000000;
1579 cr
.in
.reserved
= 0x00000000;
1580 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1581 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1582 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1583 NTCREATEX_SHARE_ACCESS_WRITE
|
1584 NTCREATEX_SHARE_ACCESS_DELETE
;
1585 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1586 cr
.in
.create_options
= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY
|
1587 NTCREATEX_OPTIONS_ASYNC_ALERT
|
1588 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
|
1590 cr
.in
.fname
= fname
;
1592 smb2_transport_compound_start(tree
->session
->transport
, 5);
1594 req
[0] = smb2_create_send(tree
, &cr
);
1596 hd
.data
[0] = UINT64_MAX
;
1597 hd
.data
[1] = UINT64_MAX
;
1599 smb2_transport_compound_set_related(tree
->session
->transport
, true);
1602 cl
.in
.file
.handle
= hd
;
1604 tree
->smbXcli
= smbXcli_tcon_create(tree
);
1605 smb2cli_tcon_set_values(tree
->smbXcli
,
1607 0xFFFFFFFF, /* tcon_id */
1610 0, /* capabilities */
1611 0 /* maximal_access */);
1613 tree
->session
->smbXcli
= smbXcli_session_shallow_copy(tree
->session
,
1614 tree
->session
->smbXcli
);
1615 smb2cli_session_set_id_and_flags(tree
->session
->smbXcli
, UINT64_MAX
, 0);
1617 req
[1] = smb2_close_send(tree
, &cl
);
1618 /* strange that this is not generating invalid parameter */
1619 smb2_transport_compound_set_related(tree
->session
->transport
, false);
1620 req
[2] = smb2_close_send(tree
, &cl
);
1621 req
[3] = smb2_close_send(tree
, &cl
);
1622 smb2_transport_compound_set_related(tree
->session
->transport
, true);
1623 req
[4] = smb2_close_send(tree
, &cl
);
1625 status
= smb2_create_recv(req
[0], tree
, &cr
);
1626 CHECK_STATUS(status
, NT_STATUS_OK
);
1627 status
= smb2_close_recv(req
[1], &cl
);
1628 CHECK_STATUS(status
, NT_STATUS_OK
);
1629 status
= smb2_close_recv(req
[2], &cl
);
1630 CHECK_STATUS(status
, NT_STATUS_USER_SESSION_DELETED
);
1631 status
= smb2_close_recv(req
[3], &cl
);
1632 CHECK_STATUS(status
, NT_STATUS_USER_SESSION_DELETED
);
1633 status
= smb2_close_recv(req
[4], &cl
);
1634 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
1636 TALLOC_FREE(tree
->smbXcli
);
1637 tree
->smbXcli
= saved_tcon
;
1638 TALLOC_FREE(tree
->session
->smbXcli
);
1639 tree
->session
->smbXcli
= saved_session
;
1641 smb2_util_unlink(tree
, fname
);
1646 static bool test_compound_invalid3(struct torture_context
*tctx
,
1647 struct smb2_tree
*tree
)
1649 struct smb2_handle hd
;
1650 struct smb2_create cr
;
1652 const char *fname
= "compound_invalid3.dat";
1653 struct smb2_close cl
;
1655 struct smb2_request
*req
[5];
1657 smb2_transport_credits_ask_num(tree
->session
->transport
, 5);
1659 smb2_util_unlink(tree
, fname
);
1661 smb2_transport_credits_ask_num(tree
->session
->transport
, 1);
1664 cr
.in
.security_flags
= 0x00;
1665 cr
.in
.oplock_level
= 0;
1666 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
1667 cr
.in
.create_flags
= 0x00000000;
1668 cr
.in
.reserved
= 0x00000000;
1669 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1670 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1671 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1672 NTCREATEX_SHARE_ACCESS_WRITE
|
1673 NTCREATEX_SHARE_ACCESS_DELETE
;
1674 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1675 cr
.in
.create_options
= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY
|
1676 NTCREATEX_OPTIONS_ASYNC_ALERT
|
1677 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
|
1679 cr
.in
.fname
= fname
;
1681 smb2_transport_compound_start(tree
->session
->transport
, 5);
1683 req
[0] = smb2_create_send(tree
, &cr
);
1685 hd
.data
[0] = UINT64_MAX
;
1686 hd
.data
[1] = UINT64_MAX
;
1689 cl
.in
.file
.handle
= hd
;
1690 req
[1] = smb2_close_send(tree
, &cl
);
1691 req
[2] = smb2_close_send(tree
, &cl
);
1692 /* flipping the related flag is invalid */
1693 smb2_transport_compound_set_related(tree
->session
->transport
, true);
1694 req
[3] = smb2_close_send(tree
, &cl
);
1695 req
[4] = smb2_close_send(tree
, &cl
);
1697 status
= smb2_create_recv(req
[0], tree
, &cr
);
1698 CHECK_STATUS(status
, NT_STATUS_OK
);
1699 status
= smb2_close_recv(req
[1], &cl
);
1700 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
1701 status
= smb2_close_recv(req
[2], &cl
);
1702 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
1703 status
= smb2_close_recv(req
[3], &cl
);
1704 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
1705 status
= smb2_close_recv(req
[4], &cl
);
1706 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
1708 smb2_util_unlink(tree
, fname
);
1713 static bool test_compound_invalid4(struct torture_context
*tctx
,
1714 struct smb2_tree
*tree
)
1716 struct smb2_create cr
;
1717 struct smb2_read rd
;
1719 const char *fname
= "compound_invalid4.dat";
1720 struct smb2_close cl
;
1723 struct smb2_request
*req
[2];
1725 smb2_transport_credits_ask_num(tree
->session
->transport
, 2);
1727 smb2_util_unlink(tree
, fname
);
1730 cr
.in
.security_flags
= 0x00;
1731 cr
.in
.oplock_level
= 0;
1732 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
1733 cr
.in
.create_flags
= 0x00000000;
1734 cr
.in
.reserved
= 0x00000000;
1735 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1736 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1737 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1738 NTCREATEX_SHARE_ACCESS_WRITE
|
1739 NTCREATEX_SHARE_ACCESS_DELETE
;
1740 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1741 cr
.in
.create_options
= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY
|
1742 NTCREATEX_OPTIONS_ASYNC_ALERT
|
1743 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
|
1745 cr
.in
.fname
= fname
;
1747 status
= smb2_create(tree
, tctx
, &cr
);
1748 CHECK_STATUS(status
, NT_STATUS_OK
);
1750 smb2_transport_compound_start(tree
->session
->transport
, 2);
1753 rd
.in
.file
.handle
= cr
.out
.file
.handle
;
1756 req
[0] = smb2_read_send(tree
, &rd
);
1758 smb2_transport_compound_set_related(tree
->session
->transport
, true);
1761 * Send a completely bogus request as second compound
1762 * element. This triggers smbd_smb2_request_error() in in
1763 * smbd_smb2_request_dispatch() before calling
1764 * smbd_smb2_request_dispatch_update_counts().
1767 req
[1] = smb2_request_init_tree(tree
, 0xff, 0x04, false, 0);
1768 smb2_transport_send(req
[1]);
1770 status
= smb2_read_recv(req
[0], tctx
, &rd
);
1771 CHECK_STATUS(status
, NT_STATUS_END_OF_FILE
);
1773 ok
= smb2_request_receive(req
[1]);
1774 torture_assert(tctx
, ok
, "Invalid request failed\n");
1775 CHECK_STATUS(req
[1]->status
, NT_STATUS_INVALID_PARAMETER
);
1778 cl
.in
.file
.handle
= cr
.out
.file
.handle
;
1780 status
= smb2_close(tree
, &cl
);
1781 CHECK_STATUS(status
, NT_STATUS_OK
);
1783 smb2_util_unlink(tree
, fname
);
1788 /* Send a compound request where we expect the last request (Create, Notify)
1789 * to go asynchronous. This works against a Win7 server and the reply is
1790 * sent in two different packets. */
1791 static bool test_compound_interim1(struct torture_context
*tctx
,
1792 struct smb2_tree
*tree
)
1794 struct smb2_handle hd
;
1795 struct smb2_create cr
;
1796 NTSTATUS status
= NT_STATUS_OK
;
1797 const char *dname
= "compound_interim_dir";
1798 struct smb2_notify nt
;
1800 struct smb2_request
*req
[2];
1802 /* Win7 compound request implementation deviates substantially from the
1803 * SMB2 spec as noted in MS-SMB2 <159>, <162>. This, test currently
1804 * verifies the Windows behavior, not the general spec behavior. */
1806 smb2_transport_credits_ask_num(tree
->session
->transport
, 5);
1808 smb2_deltree(tree
, dname
);
1810 smb2_transport_credits_ask_num(tree
->session
->transport
, 1);
1813 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1814 cr
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1815 cr
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
1816 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1817 NTCREATEX_SHARE_ACCESS_WRITE
|
1818 NTCREATEX_SHARE_ACCESS_DELETE
;
1819 cr
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1820 cr
.in
.fname
= dname
;
1822 smb2_transport_compound_start(tree
->session
->transport
, 2);
1824 req
[0] = smb2_create_send(tree
, &cr
);
1826 smb2_transport_compound_set_related(tree
->session
->transport
, true);
1828 hd
.data
[0] = UINT64_MAX
;
1829 hd
.data
[1] = UINT64_MAX
;
1832 nt
.in
.recursive
= true;
1833 nt
.in
.buffer_size
= 0x1000;
1834 nt
.in
.file
.handle
= hd
;
1835 nt
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1836 nt
.in
.unknown
= 0x00000000;
1838 req
[1] = smb2_notify_send(tree
, &nt
);
1840 status
= smb2_create_recv(req
[0], tree
, &cr
);
1841 CHECK_STATUS(status
, NT_STATUS_OK
);
1843 smb2_cancel(req
[1]);
1844 status
= smb2_notify_recv(req
[1], tree
, &nt
);
1845 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1847 smb2_util_close(tree
, cr
.out
.file
.handle
);
1849 smb2_deltree(tree
, dname
);
1854 /* Send a compound request where we expect the middle request (Create, Notify,
1855 * GetInfo) to go asynchronous. Against Win7 the sync request succeed while
1856 * the async fails. All are returned in the same compound response. */
1857 static bool test_compound_interim2(struct torture_context
*tctx
,
1858 struct smb2_tree
*tree
)
1860 struct smb2_handle hd
;
1861 struct smb2_create cr
;
1862 NTSTATUS status
= NT_STATUS_OK
;
1863 const char *dname
= "compound_interim_dir";
1864 struct smb2_getinfo gf
;
1865 struct smb2_notify nt
;
1867 struct smb2_request
*req
[3];
1869 /* Win7 compound request implementation deviates substantially from the
1870 * SMB2 spec as noted in MS-SMB2 <159>, <162>. This, test currently
1871 * verifies the Windows behavior, not the general spec behavior. */
1873 smb2_transport_credits_ask_num(tree
->session
->transport
, 5);
1875 smb2_deltree(tree
, dname
);
1877 smb2_transport_credits_ask_num(tree
->session
->transport
, 1);
1880 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1881 cr
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1882 cr
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
1883 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1884 NTCREATEX_SHARE_ACCESS_WRITE
|
1885 NTCREATEX_SHARE_ACCESS_DELETE
;
1886 cr
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1887 cr
.in
.fname
= dname
;
1889 smb2_transport_compound_start(tree
->session
->transport
, 3);
1891 req
[0] = smb2_create_send(tree
, &cr
);
1893 smb2_transport_compound_set_related(tree
->session
->transport
, true);
1895 hd
.data
[0] = UINT64_MAX
;
1896 hd
.data
[1] = UINT64_MAX
;
1899 nt
.in
.recursive
= true;
1900 nt
.in
.buffer_size
= 0x1000;
1901 nt
.in
.file
.handle
= hd
;
1902 nt
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1903 nt
.in
.unknown
= 0x00000000;
1905 req
[1] = smb2_notify_send(tree
, &nt
);
1908 gf
.in
.file
.handle
= hd
;
1909 gf
.in
.info_type
= SMB2_0_INFO_FILE
;
1910 gf
.in
.info_class
= 0x04; /* FILE_BASIC_INFORMATION */
1911 gf
.in
.output_buffer_length
= 0x1000;
1912 gf
.in
.input_buffer
= data_blob_null
;
1914 req
[2] = smb2_getinfo_send(tree
, &gf
);
1916 status
= smb2_create_recv(req
[0], tree
, &cr
);
1917 CHECK_STATUS(status
, NT_STATUS_OK
);
1919 status
= smb2_notify_recv(req
[1], tree
, &nt
);
1920 CHECK_STATUS(status
, NT_STATUS_INTERNAL_ERROR
);
1922 status
= smb2_getinfo_recv(req
[2], tree
, &gf
);
1923 CHECK_STATUS(status
, NT_STATUS_OK
);
1925 smb2_util_close(tree
, cr
.out
.file
.handle
);
1927 smb2_deltree(tree
, dname
);
1932 /* Test compound related finds */
1933 static bool test_compound_find_related(struct torture_context
*tctx
,
1934 struct smb2_tree
*tree
)
1936 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
1937 const char *dname
= "compound_find_dir";
1938 struct smb2_create create
;
1940 struct smb2_handle h
;
1941 struct smb2_request
*req
[2];
1945 smb2_deltree(tree
, dname
);
1947 ZERO_STRUCT(create
);
1948 create
.in
.desired_access
= SEC_RIGHTS_DIR_ALL
;
1949 create
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1950 create
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
1951 create
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1952 NTCREATEX_SHARE_ACCESS_WRITE
|
1953 NTCREATEX_SHARE_ACCESS_DELETE
;
1954 create
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1955 create
.in
.fname
= dname
;
1957 status
= smb2_create(tree
, mem_ctx
, &create
);
1958 h
= create
.out
.file
.handle
;
1960 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
, "smb2_create failed\n");
1962 smb2_transport_compound_start(tree
->session
->transport
, 2);
1965 f
.in
.file
.handle
= h
;
1967 f
.in
.max_response_size
= 0x100;
1968 f
.in
.level
= SMB2_FIND_BOTH_DIRECTORY_INFO
;
1970 req
[0] = smb2_find_send(tree
, &f
);
1972 smb2_transport_compound_set_related(tree
->session
->transport
, true);
1974 req
[1] = smb2_find_send(tree
, &f
);
1976 status
= smb2_find_recv(req
[0], mem_ctx
, &f
);
1977 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
, "smb2_find_recv failed\n");
1979 status
= smb2_find_recv(req
[1], mem_ctx
, &f
);
1980 torture_assert_ntstatus_equal_goto(tctx
, status
, STATUS_NO_MORE_FILES
, ret
, done
, "smb2_find_recv failed\n");
1983 smb2_util_close(tree
, h
);
1984 smb2_deltree(tree
, dname
);
1985 TALLOC_FREE(mem_ctx
);
1989 /* Test compound related finds */
1990 static bool test_compound_find_close(struct torture_context
*tctx
,
1991 struct smb2_tree
*tree
)
1993 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
1994 const char *dname
= "compound_find_dir";
1995 struct smb2_create create
;
1997 struct smb2_handle h
;
1998 struct smb2_request
*req
= NULL
;
1999 const int num_files
= 5000;
2004 smb2_deltree(tree
, dname
);
2006 ZERO_STRUCT(create
);
2007 create
.in
.desired_access
= SEC_RIGHTS_DIR_ALL
;
2008 create
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
2009 create
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
2010 create
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2011 NTCREATEX_SHARE_ACCESS_WRITE
|
2012 NTCREATEX_SHARE_ACCESS_DELETE
;
2013 create
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
2014 create
.in
.fname
= dname
;
2016 smb2cli_conn_set_max_credits(tree
->session
->transport
->conn
, 256);
2018 status
= smb2_create(tree
, mem_ctx
, &create
);
2019 h
= create
.out
.file
.handle
;
2021 ZERO_STRUCT(create
);
2022 create
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
2023 create
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
2024 create
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
2026 for (i
= 0; i
< num_files
; i
++) {
2027 create
.in
.fname
= talloc_asprintf(mem_ctx
, "%s\\file%d",
2029 status
= smb2_create(tree
, mem_ctx
, &create
);
2030 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
, "");
2031 smb2_util_close(tree
, create
.out
.file
.handle
);
2034 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
, "smb2_create failed\n");
2037 f
.in
.file
.handle
= h
;
2039 f
.in
.max_response_size
= 8*1024*1024;
2040 f
.in
.level
= SMB2_FIND_BOTH_DIRECTORY_INFO
;
2042 req
= smb2_find_send(tree
, &f
);
2044 status
= smb2_util_close(tree
, h
);
2045 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
, "smb2_util_close failed\n");
2047 status
= smb2_find_recv(req
, mem_ctx
, &f
);
2048 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
, "smb2_find_recv failed\n");
2051 smb2_util_close(tree
, h
);
2052 smb2_deltree(tree
, dname
);
2053 TALLOC_FREE(mem_ctx
);
2057 /* Test compound unrelated finds */
2058 static bool test_compound_find_unrelated(struct torture_context
*tctx
,
2059 struct smb2_tree
*tree
)
2061 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
2062 const char *dname
= "compound_find_dir";
2063 struct smb2_create create
;
2065 struct smb2_handle h
;
2066 struct smb2_request
*req
[2];
2070 smb2_deltree(tree
, dname
);
2072 ZERO_STRUCT(create
);
2073 create
.in
.desired_access
= SEC_RIGHTS_DIR_ALL
;
2074 create
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
2075 create
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
2076 create
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2077 NTCREATEX_SHARE_ACCESS_WRITE
|
2078 NTCREATEX_SHARE_ACCESS_DELETE
;
2079 create
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
2080 create
.in
.fname
= dname
;
2082 status
= smb2_create(tree
, mem_ctx
, &create
);
2083 h
= create
.out
.file
.handle
;
2085 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
, "smb2_create failed\n");
2087 smb2_transport_compound_start(tree
->session
->transport
, 2);
2090 f
.in
.file
.handle
= h
;
2092 f
.in
.max_response_size
= 0x100;
2093 f
.in
.level
= SMB2_FIND_BOTH_DIRECTORY_INFO
;
2095 req
[0] = smb2_find_send(tree
, &f
);
2096 req
[1] = smb2_find_send(tree
, &f
);
2098 status
= smb2_find_recv(req
[0], mem_ctx
, &f
);
2099 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
, "smb2_find_recv failed\n");
2101 status
= smb2_find_recv(req
[1], mem_ctx
, &f
);
2102 torture_assert_ntstatus_equal_goto(tctx
, status
, STATUS_NO_MORE_FILES
, ret
, done
, "smb2_find_recv failed\n");
2105 smb2_util_close(tree
, h
);
2106 smb2_deltree(tree
, dname
);
2107 TALLOC_FREE(mem_ctx
);
2111 static bool test_compound_async_flush_close(struct torture_context
*tctx
,
2112 struct smb2_tree
*tree
)
2114 struct smb2_handle fhandle
= { .data
= { 0, 0 } };
2115 struct smb2_handle relhandle
= { .data
= { UINT64_MAX
, UINT64_MAX
} };
2116 struct smb2_close cl
;
2117 struct smb2_flush fl
;
2118 const char *fname
= "compound_async_flush_close";
2119 struct smb2_request
*req
[2];
2124 smb2_util_unlink(tree
, fname
);
2126 /* Create a file. */
2127 status
= torture_smb2_testfile_access(tree
,
2130 SEC_RIGHTS_FILE_ALL
);
2131 CHECK_STATUS(status
, NT_STATUS_OK
);
2133 /* Now do a compound flush + close handle. */
2134 smb2_transport_compound_start(tree
->session
->transport
, 2);
2137 fl
.in
.file
.handle
= fhandle
;
2139 req
[0] = smb2_flush_send(tree
, &fl
);
2140 torture_assert_not_null_goto(tctx
, req
[0], ret
, done
,
2141 "smb2_flush_send failed\n");
2143 smb2_transport_compound_set_related(tree
->session
->transport
, true);
2146 cl
.in
.file
.handle
= relhandle
;
2147 req
[1] = smb2_close_send(tree
, &cl
);
2148 torture_assert_not_null_goto(tctx
, req
[1], ret
, done
,
2149 "smb2_close_send failed\n");
2151 status
= smb2_flush_recv(req
[0], &fl
);
2153 * On Windows, this flush will usually
2154 * succeed as we have nothing to flush,
2155 * so allow NT_STATUS_OK. Once bug #15172
2156 * is fixed Samba will do the flush synchronously
2157 * so allow NT_STATUS_OK.
2159 if (!NT_STATUS_IS_OK(status
)) {
2161 * If we didn't get NT_STATUS_OK, we *must*
2162 * get NT_STATUS_INTERNAL_ERROR if the flush
2165 * For pre-bugfix #15172 Samba, the flush goes async and
2166 * we should get NT_STATUS_INTERNAL_ERROR.
2168 torture_assert_ntstatus_equal_goto(tctx
,
2170 NT_STATUS_INTERNAL_ERROR
,
2173 "smb2_flush_recv didn't return "
2174 "NT_STATUS_INTERNAL_ERROR.\n");
2176 status
= smb2_close_recv(req
[1], &cl
);
2177 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2178 "smb2_close_recv failed.");
2180 ZERO_STRUCT(fhandle
);
2183 * Do several more operations on the tree, spaced
2184 * out by 1 sec sleeps to make sure the server didn't
2185 * crash on the close. The sleeps are required to
2186 * make test test for a crash reliable, as we ensure
2187 * the pthread fsync internally finishes and accesses
2188 * freed memory. Without them the test occassionally
2189 * passes as we disconnect before the pthread fsync
2192 status
= smb2_util_unlink(tree
, fname
);
2193 CHECK_STATUS(status
, NT_STATUS_OK
);
2196 status
= smb2_util_unlink(tree
, fname
);
2197 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2200 status
= smb2_util_unlink(tree
, fname
);
2201 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2207 if (fhandle
.data
[0] != 0) {
2208 smb2_util_close(tree
, fhandle
);
2211 smb2_util_unlink(tree
, fname
);
2215 static bool test_compound_async_flush_flush(struct torture_context
*tctx
,
2216 struct smb2_tree
*tree
)
2218 struct smb2_handle fhandle
= { .data
= { 0, 0 } };
2219 struct smb2_handle relhandle
= { .data
= { UINT64_MAX
, UINT64_MAX
} };
2220 struct smb2_flush fl1
;
2221 struct smb2_flush fl2
;
2222 const char *fname
= "compound_async_flush_flush";
2223 struct smb2_request
*req
[2];
2228 smb2_util_unlink(tree
, fname
);
2230 /* Create a file. */
2231 status
= torture_smb2_testfile_access(tree
,
2234 SEC_RIGHTS_FILE_ALL
);
2235 CHECK_STATUS(status
, NT_STATUS_OK
);
2237 /* Now do a compound flush + flush handle. */
2238 smb2_transport_compound_start(tree
->session
->transport
, 2);
2241 fl1
.in
.file
.handle
= fhandle
;
2243 req
[0] = smb2_flush_send(tree
, &fl1
);
2244 torture_assert_not_null_goto(tctx
, req
[0], ret
, done
,
2245 "smb2_flush_send (1) failed\n");
2247 smb2_transport_compound_set_related(tree
->session
->transport
, true);
2250 fl2
.in
.file
.handle
= relhandle
;
2252 req
[1] = smb2_flush_send(tree
, &fl2
);
2253 torture_assert_not_null_goto(tctx
, req
[1], ret
, done
,
2254 "smb2_flush_send (2) failed\n");
2256 status
= smb2_flush_recv(req
[0], &fl1
);
2258 * On Windows, this flush will usually
2259 * succeed as we have nothing to flush,
2260 * so allow NT_STATUS_OK. Once bug #15172
2261 * is fixed Samba will do the flush synchronously
2262 * so allow NT_STATUS_OK.
2264 if (!NT_STATUS_IS_OK(status
)) {
2266 * If we didn't get NT_STATUS_OK, we *must*
2267 * get NT_STATUS_INTERNAL_ERROR if the flush
2270 * For pre-bugfix #15172 Samba, the flush goes async and
2271 * we should get NT_STATUS_INTERNAL_ERROR.
2273 torture_assert_ntstatus_equal_goto(tctx
,
2275 NT_STATUS_INTERNAL_ERROR
,
2278 "smb2_flush_recv (1) didn't return "
2279 "NT_STATUS_INTERNAL_ERROR.\n");
2283 * If the flush is the last entry in a compound,
2284 * it should always succeed even if it goes async.
2286 status
= smb2_flush_recv(req
[1], &fl2
);
2287 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2288 "smb2_flush_recv (2) failed.");
2290 status
= smb2_util_close(tree
, fhandle
);
2291 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2292 "smb2_util_close failed.");
2293 ZERO_STRUCT(fhandle
);
2296 * Do several more operations on the tree, spaced
2297 * out by 1 sec sleeps to make sure the server didn't
2298 * crash on the close. The sleeps are required to
2299 * make test test for a crash reliable, as we ensure
2300 * the pthread fsync internally finishes and accesses
2301 * freed memory. Without them the test occassionally
2302 * passes as we disconnect before the pthread fsync
2305 status
= smb2_util_unlink(tree
, fname
);
2306 CHECK_STATUS(status
, NT_STATUS_OK
);
2309 status
= smb2_util_unlink(tree
, fname
);
2310 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2313 status
= smb2_util_unlink(tree
, fname
);
2314 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2320 if (fhandle
.data
[0] != 0) {
2321 smb2_util_close(tree
, fhandle
);
2324 smb2_util_unlink(tree
, fname
);
2329 * For Samba/smbd this test must be run against the aio_delay_inject share
2330 * as we need to ensure the last write in the compound takes longer than
2331 * 500 us, which is the threshold for going async in smbd SMB2 writes.
2334 static bool test_compound_async_write_write(struct torture_context
*tctx
,
2335 struct smb2_tree
*tree
)
2337 struct smb2_handle fhandle
= { .data
= { 0, 0 } };
2338 struct smb2_handle relhandle
= { .data
= { UINT64_MAX
, UINT64_MAX
} };
2339 struct smb2_write w1
;
2340 struct smb2_write w2
;
2341 const char *fname
= "compound_async_write_write";
2342 struct smb2_request
*req
[2];
2344 bool is_smbd
= torture_setting_bool(tctx
, "smbd", true);
2348 smb2_util_unlink(tree
, fname
);
2350 /* Create a file. */
2351 status
= torture_smb2_testfile_access(tree
,
2354 SEC_RIGHTS_FILE_ALL
);
2355 CHECK_STATUS(status
, NT_STATUS_OK
);
2357 /* Now do a compound write + write handle. */
2358 smb2_transport_compound_start(tree
->session
->transport
, 2);
2361 w1
.in
.file
.handle
= fhandle
;
2363 w1
.in
.data
= data_blob_talloc_zero(tctx
, 64);
2364 req
[0] = smb2_write_send(tree
, &w1
);
2366 torture_assert_not_null_goto(tctx
, req
[0], ret
, done
,
2367 "smb2_write_send (1) failed\n");
2369 smb2_transport_compound_set_related(tree
->session
->transport
, true);
2372 w2
.in
.file
.handle
= relhandle
;
2374 w2
.in
.data
= data_blob_talloc_zero(tctx
, 64);
2375 req
[1] = smb2_write_send(tree
, &w2
);
2377 torture_assert_not_null_goto(tctx
, req
[0], ret
, done
,
2378 "smb2_write_send (2) failed\n");
2380 status
= smb2_write_recv(req
[0], &w1
);
2381 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2382 "smb2_write_recv (1) failed.");
2386 * Windows and other servers don't go async.
2388 status
= smb2_write_recv(req
[1], &w2
);
2391 * For smbd, the second write should go async
2392 * as it's the last element of a compound.
2394 WAIT_FOR_ASYNC_RESPONSE(req
[1]);
2395 CHECK_VALUE(req
[1]->cancel
.can_cancel
, true);
2397 * Now pick up the real return.
2399 status
= smb2_write_recv(req
[1], &w2
);
2402 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2403 "smb2_write_recv (2) failed.");
2405 status
= smb2_util_close(tree
, fhandle
);
2406 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2407 "smb2_util_close failed.");
2408 ZERO_STRUCT(fhandle
);
2414 if (fhandle
.data
[0] != 0) {
2415 smb2_util_close(tree
, fhandle
);
2418 smb2_util_unlink(tree
, fname
);
2423 * For Samba/smbd this test must be run against the aio_delay_inject share
2424 * as we need to ensure the last read in the compound takes longer than
2425 * 500 us, which is the threshold for going async in smbd SMB2 reads.
2428 static bool test_compound_async_read_read(struct torture_context
*tctx
,
2429 struct smb2_tree
*tree
)
2431 struct smb2_handle fhandle
= { .data
= { 0, 0 } };
2432 struct smb2_handle relhandle
= { .data
= { UINT64_MAX
, UINT64_MAX
} };
2433 struct smb2_write w
;
2434 struct smb2_read r1
;
2435 struct smb2_read r2
;
2436 const char *fname
= "compound_async_read_read";
2437 struct smb2_request
*req
[2];
2439 bool is_smbd
= torture_setting_bool(tctx
, "smbd", true);
2443 smb2_util_unlink(tree
, fname
);
2445 /* Create a file. */
2446 status
= torture_smb2_testfile_access(tree
,
2449 SEC_RIGHTS_FILE_ALL
);
2450 CHECK_STATUS(status
, NT_STATUS_OK
);
2452 /* Write 128 bytes. */
2454 w
.in
.file
.handle
= fhandle
;
2456 w
.in
.data
= data_blob_talloc_zero(tctx
, 128);
2457 status
= smb2_write(tree
, &w
);
2458 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2459 "smb2_write_recv (1) failed.");
2461 /* Now do a compound read + read handle. */
2462 smb2_transport_compound_start(tree
->session
->transport
, 2);
2465 r1
.in
.file
.handle
= fhandle
;
2468 req
[0] = smb2_read_send(tree
, &r1
);
2470 torture_assert_not_null_goto(tctx
, req
[0], ret
, done
,
2471 "smb2_read_send (1) failed\n");
2473 smb2_transport_compound_set_related(tree
->session
->transport
, true);
2476 r2
.in
.file
.handle
= relhandle
;
2479 req
[1] = smb2_read_send(tree
, &r2
);
2481 torture_assert_not_null_goto(tctx
, req
[0], ret
, done
,
2482 "smb2_read_send (2) failed\n");
2484 status
= smb2_read_recv(req
[0], tree
, &r1
);
2485 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2486 "smb2_read_recv (1) failed.");
2490 * Windows and other servers don't go async.
2492 status
= smb2_read_recv(req
[1], tree
, &r2
);
2495 * For smbd, the second write should go async
2496 * as it's the last element of a compound.
2498 WAIT_FOR_ASYNC_RESPONSE(req
[1]);
2499 CHECK_VALUE(req
[1]->cancel
.can_cancel
, true);
2501 * Now pick up the real return.
2503 status
= smb2_read_recv(req
[1], tree
, &r2
);
2506 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2507 "smb2_read_recv (2) failed.");
2509 status
= smb2_util_close(tree
, fhandle
);
2510 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2511 "smb2_util_close failed.");
2512 ZERO_STRUCT(fhandle
);
2518 if (fhandle
.data
[0] != 0) {
2519 smb2_util_close(tree
, fhandle
);
2522 smb2_util_unlink(tree
, fname
);
2527 struct torture_suite
*torture_smb2_compound_init(TALLOC_CTX
*ctx
)
2529 struct torture_suite
*suite
= torture_suite_create(ctx
, "compound");
2531 torture_suite_add_1smb2_test(suite
, "related1", test_compound_related1
);
2532 torture_suite_add_1smb2_test(suite
, "related2", test_compound_related2
);
2533 torture_suite_add_1smb2_test(suite
, "related3",
2534 test_compound_related3
);
2535 torture_suite_add_1smb2_test(suite
, "related4",
2536 test_compound_related4
);
2537 torture_suite_add_1smb2_test(suite
, "related5",
2538 test_compound_related5
);
2539 torture_suite_add_1smb2_test(suite
, "related6",
2540 test_compound_related6
);
2541 torture_suite_add_1smb2_test(suite
, "related7",
2542 test_compound_related7
);
2543 torture_suite_add_1smb2_test(suite
, "related8",
2544 test_compound_related8
);
2545 torture_suite_add_1smb2_test(suite
, "related9",
2546 test_compound_related9
);
2547 torture_suite_add_1smb2_test(suite
, "unrelated1", test_compound_unrelated1
);
2548 torture_suite_add_1smb2_test(suite
, "invalid1", test_compound_invalid1
);
2549 torture_suite_add_1smb2_test(suite
, "invalid2", test_compound_invalid2
);
2550 torture_suite_add_1smb2_test(suite
, "invalid3", test_compound_invalid3
);
2551 torture_suite_add_1smb2_test(
2552 suite
, "invalid4", test_compound_invalid4
);
2553 torture_suite_add_1smb2_test(suite
, "interim1", test_compound_interim1
);
2554 torture_suite_add_1smb2_test(suite
, "interim2", test_compound_interim2
);
2555 torture_suite_add_1smb2_test(suite
, "compound-break", test_compound_break
);
2556 torture_suite_add_1smb2_test(suite
, "compound-padding", test_compound_padding
);
2557 torture_suite_add_1smb2_test(suite
, "create-write-close",
2558 test_compound_create_write_close
);
2560 suite
->description
= talloc_strdup(suite
, "SMB2-COMPOUND tests");
2565 struct torture_suite
*torture_smb2_compound_find_init(TALLOC_CTX
*ctx
)
2567 struct torture_suite
*suite
= torture_suite_create(ctx
, "compound_find");
2569 torture_suite_add_1smb2_test(suite
, "compound_find_related", test_compound_find_related
);
2570 torture_suite_add_1smb2_test(suite
, "compound_find_unrelated", test_compound_find_unrelated
);
2571 torture_suite_add_1smb2_test(suite
, "compound_find_close", test_compound_find_close
);
2573 suite
->description
= talloc_strdup(suite
, "SMB2-COMPOUND-FIND tests");
2578 struct torture_suite
*torture_smb2_compound_async_init(TALLOC_CTX
*ctx
)
2580 struct torture_suite
*suite
= torture_suite_create(ctx
,
2583 torture_suite_add_1smb2_test(suite
, "flush_close",
2584 test_compound_async_flush_close
);
2585 torture_suite_add_1smb2_test(suite
, "flush_flush",
2586 test_compound_async_flush_flush
);
2587 torture_suite_add_1smb2_test(suite
, "write_write",
2588 test_compound_async_write_write
);
2589 torture_suite_add_1smb2_test(suite
, "read_read",
2590 test_compound_async_read_read
);
2592 suite
->description
= talloc_strdup(suite
, "SMB2-COMPOUND-ASYNC tests");