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/>.
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25 #include "torture/torture.h"
26 #include "torture/smb2/proto.h"
28 #define CHECK_STATUS(status, correct) do { \
29 if (!NT_STATUS_EQUAL(status, correct)) { \
30 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
31 nt_errstr(status), nt_errstr(correct)); \
36 static bool test_compound_related1(struct torture_context
*tctx
,
37 struct smb2_tree
*tree
)
39 struct smb2_handle hd
;
40 struct smb2_create cr
;
42 const char *fname
= "compound_related1.dat";
45 struct smb2_request
*req
[2];
47 smb2_transport_credits_ask_num(tree
->session
->transport
, 2);
49 smb2_util_unlink(tree
, fname
);
51 smb2_transport_credits_ask_num(tree
->session
->transport
, 1);
54 cr
.in
.security_flags
= 0x00;
55 cr
.in
.oplock_level
= 0;
56 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
57 cr
.in
.create_flags
= 0x00000000;
58 cr
.in
.reserved
= 0x00000000;
59 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
60 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
61 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
62 NTCREATEX_SHARE_ACCESS_WRITE
|
63 NTCREATEX_SHARE_ACCESS_DELETE
;
64 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
65 cr
.in
.create_options
= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY
|
66 NTCREATEX_OPTIONS_ASYNC_ALERT
|
67 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
|
71 smb2_transport_compound_start(tree
->session
->transport
, 2);
73 req
[0] = smb2_create_send(tree
, &cr
);
75 smb2_transport_compound_set_related(tree
->session
->transport
, true);
77 hd
.data
[0] = UINT64_MAX
;
78 hd
.data
[1] = UINT64_MAX
;
81 cl
.in
.file
.handle
= hd
;
82 req
[1] = smb2_close_send(tree
, &cl
);
84 status
= smb2_create_recv(req
[0], tree
, &cr
);
85 CHECK_STATUS(status
, NT_STATUS_OK
);
86 status
= smb2_close_recv(req
[1], &cl
);
87 CHECK_STATUS(status
, NT_STATUS_OK
);
89 smb2_util_unlink(tree
, fname
);
94 static bool test_compound_related2(struct torture_context
*tctx
,
95 struct smb2_tree
*tree
)
97 struct smb2_handle hd
;
98 struct smb2_create cr
;
100 const char *fname
= "compound_related2.dat";
101 struct smb2_close cl
;
103 struct smb2_request
*req
[5];
105 smb2_transport_credits_ask_num(tree
->session
->transport
, 5);
107 smb2_util_unlink(tree
, fname
);
109 smb2_transport_credits_ask_num(tree
->session
->transport
, 1);
112 cr
.in
.security_flags
= 0x00;
113 cr
.in
.oplock_level
= 0;
114 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
115 cr
.in
.create_flags
= 0x00000000;
116 cr
.in
.reserved
= 0x00000000;
117 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
118 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
119 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
120 NTCREATEX_SHARE_ACCESS_WRITE
|
121 NTCREATEX_SHARE_ACCESS_DELETE
;
122 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
123 cr
.in
.create_options
= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY
|
124 NTCREATEX_OPTIONS_ASYNC_ALERT
|
125 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
|
129 smb2_transport_compound_start(tree
->session
->transport
, 5);
131 req
[0] = smb2_create_send(tree
, &cr
);
133 hd
.data
[0] = UINT64_MAX
;
134 hd
.data
[1] = UINT64_MAX
;
136 smb2_transport_compound_set_related(tree
->session
->transport
, true);
139 cl
.in
.file
.handle
= hd
;
140 req
[1] = smb2_close_send(tree
, &cl
);
141 req
[2] = smb2_close_send(tree
, &cl
);
142 req
[3] = smb2_close_send(tree
, &cl
);
143 req
[4] = smb2_close_send(tree
, &cl
);
145 status
= smb2_create_recv(req
[0], tree
, &cr
);
146 CHECK_STATUS(status
, NT_STATUS_OK
);
147 status
= smb2_close_recv(req
[1], &cl
);
148 CHECK_STATUS(status
, NT_STATUS_OK
);
149 status
= smb2_close_recv(req
[2], &cl
);
150 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
151 status
= smb2_close_recv(req
[3], &cl
);
152 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
153 status
= smb2_close_recv(req
[4], &cl
);
154 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
156 smb2_util_unlink(tree
, fname
);
161 static bool test_compound_unrelated1(struct torture_context
*tctx
,
162 struct smb2_tree
*tree
)
164 struct smb2_handle hd
;
165 struct smb2_create cr
;
167 const char *fname
= "compound_unrelated1.dat";
168 struct smb2_close cl
;
170 struct smb2_request
*req
[5];
172 smb2_transport_credits_ask_num(tree
->session
->transport
, 5);
174 smb2_util_unlink(tree
, fname
);
176 smb2_transport_credits_ask_num(tree
->session
->transport
, 1);
179 cr
.in
.security_flags
= 0x00;
180 cr
.in
.oplock_level
= 0;
181 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
182 cr
.in
.create_flags
= 0x00000000;
183 cr
.in
.reserved
= 0x00000000;
184 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
185 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
186 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
187 NTCREATEX_SHARE_ACCESS_WRITE
|
188 NTCREATEX_SHARE_ACCESS_DELETE
;
189 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
190 cr
.in
.create_options
= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY
|
191 NTCREATEX_OPTIONS_ASYNC_ALERT
|
192 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
|
196 smb2_transport_compound_start(tree
->session
->transport
, 5);
198 req
[0] = smb2_create_send(tree
, &cr
);
200 hd
.data
[0] = UINT64_MAX
;
201 hd
.data
[1] = UINT64_MAX
;
204 cl
.in
.file
.handle
= hd
;
205 req
[1] = smb2_close_send(tree
, &cl
);
206 req
[2] = smb2_close_send(tree
, &cl
);
207 req
[3] = smb2_close_send(tree
, &cl
);
208 req
[4] = smb2_close_send(tree
, &cl
);
210 status
= smb2_create_recv(req
[0], tree
, &cr
);
211 CHECK_STATUS(status
, NT_STATUS_OK
);
212 status
= smb2_close_recv(req
[1], &cl
);
213 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
214 status
= smb2_close_recv(req
[2], &cl
);
215 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
216 status
= smb2_close_recv(req
[3], &cl
);
217 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
218 status
= smb2_close_recv(req
[4], &cl
);
219 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
221 smb2_util_unlink(tree
, fname
);
226 static bool test_compound_invalid1(struct torture_context
*tctx
,
227 struct smb2_tree
*tree
)
229 struct smb2_handle hd
;
230 struct smb2_create cr
;
232 const char *fname
= "compound_invalid1.dat";
233 struct smb2_close cl
;
235 struct smb2_request
*req
[2];
237 smb2_transport_credits_ask_num(tree
->session
->transport
, 2);
239 smb2_util_unlink(tree
, fname
);
241 smb2_transport_credits_ask_num(tree
->session
->transport
, 1);
244 cr
.in
.security_flags
= 0x00;
245 cr
.in
.oplock_level
= 0;
246 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
247 cr
.in
.create_flags
= 0x00000000;
248 cr
.in
.reserved
= 0x00000000;
249 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
250 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
251 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
252 NTCREATEX_SHARE_ACCESS_WRITE
|
253 NTCREATEX_SHARE_ACCESS_DELETE
;
254 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
255 cr
.in
.create_options
= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY
|
256 NTCREATEX_OPTIONS_ASYNC_ALERT
|
257 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
|
261 smb2_transport_compound_start(tree
->session
->transport
, 2);
263 /* passing the first request with the related flag is invalid */
264 smb2_transport_compound_set_related(tree
->session
->transport
, true);
266 req
[0] = smb2_create_send(tree
, &cr
);
268 hd
.data
[0] = UINT64_MAX
;
269 hd
.data
[1] = UINT64_MAX
;
272 cl
.in
.file
.handle
= hd
;
273 req
[1] = smb2_close_send(tree
, &cl
);
275 status
= smb2_create_recv(req
[0], tree
, &cr
);
276 /* TODO: check why this fails with --signing=required */
277 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
278 status
= smb2_close_recv(req
[1], &cl
);
279 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
281 smb2_util_unlink(tree
, fname
);
286 static bool test_compound_invalid2(struct torture_context
*tctx
,
287 struct smb2_tree
*tree
)
289 struct smb2_handle hd
;
290 struct smb2_create cr
;
292 const char *fname
= "compound_invalid2.dat";
293 struct smb2_close cl
;
295 struct smb2_request
*req
[5];
297 smb2_transport_credits_ask_num(tree
->session
->transport
, 5);
299 smb2_util_unlink(tree
, fname
);
301 smb2_transport_credits_ask_num(tree
->session
->transport
, 1);
304 cr
.in
.security_flags
= 0x00;
305 cr
.in
.oplock_level
= 0;
306 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
307 cr
.in
.create_flags
= 0x00000000;
308 cr
.in
.reserved
= 0x00000000;
309 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
310 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
311 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
312 NTCREATEX_SHARE_ACCESS_WRITE
|
313 NTCREATEX_SHARE_ACCESS_DELETE
;
314 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
315 cr
.in
.create_options
= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY
|
316 NTCREATEX_OPTIONS_ASYNC_ALERT
|
317 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
|
321 smb2_transport_compound_start(tree
->session
->transport
, 5);
323 req
[0] = smb2_create_send(tree
, &cr
);
325 hd
.data
[0] = UINT64_MAX
;
326 hd
.data
[1] = UINT64_MAX
;
328 smb2_transport_compound_set_related(tree
->session
->transport
, true);
331 cl
.in
.file
.handle
= hd
;
332 req
[1] = smb2_close_send(tree
, &cl
);
333 /* strange that this is not generating invalid parameter */
334 smb2_transport_compound_set_related(tree
->session
->transport
, false);
335 req
[2] = smb2_close_send(tree
, &cl
);
336 req
[3] = smb2_close_send(tree
, &cl
);
337 smb2_transport_compound_set_related(tree
->session
->transport
, true);
338 req
[4] = smb2_close_send(tree
, &cl
);
340 status
= smb2_create_recv(req
[0], tree
, &cr
);
341 CHECK_STATUS(status
, NT_STATUS_OK
);
342 status
= smb2_close_recv(req
[1], &cl
);
343 CHECK_STATUS(status
, NT_STATUS_OK
);
344 status
= smb2_close_recv(req
[2], &cl
);
345 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
346 status
= smb2_close_recv(req
[3], &cl
);
347 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
348 status
= smb2_close_recv(req
[4], &cl
);
349 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
351 smb2_util_unlink(tree
, fname
);
356 static bool test_compound_invalid3(struct torture_context
*tctx
,
357 struct smb2_tree
*tree
)
359 struct smb2_handle hd
;
360 struct smb2_create cr
;
362 const char *fname
= "compound_invalid3.dat";
363 struct smb2_close cl
;
365 struct smb2_request
*req
[5];
367 smb2_transport_credits_ask_num(tree
->session
->transport
, 5);
369 smb2_util_unlink(tree
, fname
);
371 smb2_transport_credits_ask_num(tree
->session
->transport
, 1);
374 cr
.in
.security_flags
= 0x00;
375 cr
.in
.oplock_level
= 0;
376 cr
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
377 cr
.in
.create_flags
= 0x00000000;
378 cr
.in
.reserved
= 0x00000000;
379 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
380 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
381 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
382 NTCREATEX_SHARE_ACCESS_WRITE
|
383 NTCREATEX_SHARE_ACCESS_DELETE
;
384 cr
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
385 cr
.in
.create_options
= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY
|
386 NTCREATEX_OPTIONS_ASYNC_ALERT
|
387 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
|
391 smb2_transport_compound_start(tree
->session
->transport
, 5);
393 req
[0] = smb2_create_send(tree
, &cr
);
395 hd
.data
[0] = UINT64_MAX
;
396 hd
.data
[1] = UINT64_MAX
;
399 cl
.in
.file
.handle
= hd
;
400 req
[1] = smb2_close_send(tree
, &cl
);
401 req
[2] = smb2_close_send(tree
, &cl
);
402 /* flipping the related flag is invalid */
403 smb2_transport_compound_set_related(tree
->session
->transport
, true);
404 req
[3] = smb2_close_send(tree
, &cl
);
405 req
[4] = smb2_close_send(tree
, &cl
);
407 status
= smb2_create_recv(req
[0], tree
, &cr
);
408 CHECK_STATUS(status
, NT_STATUS_OK
);
409 status
= smb2_close_recv(req
[1], &cl
);
410 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
411 status
= smb2_close_recv(req
[2], &cl
);
412 CHECK_STATUS(status
, NT_STATUS_FILE_CLOSED
);
413 status
= smb2_close_recv(req
[3], &cl
);
414 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
415 status
= smb2_close_recv(req
[4], &cl
);
416 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
418 smb2_util_unlink(tree
, fname
);
423 struct torture_suite
*torture_smb2_compound_init(void)
425 struct torture_suite
*suite
=
426 torture_suite_create(talloc_autofree_context(), "COMPOUND");
428 torture_suite_add_1smb2_test(suite
, "RELATED1", test_compound_related1
);
429 torture_suite_add_1smb2_test(suite
, "RELATED2", test_compound_related2
);
430 torture_suite_add_1smb2_test(suite
, "UNRELATED1", test_compound_unrelated1
);
431 torture_suite_add_1smb2_test(suite
, "INVALID1", test_compound_invalid1
);
432 torture_suite_add_1smb2_test(suite
, "INVALID2", test_compound_invalid2
);
433 torture_suite_add_1smb2_test(suite
, "INVALID3", test_compound_invalid3
);
435 suite
->description
= talloc_strdup(suite
, "SMB2-COMPOUND tests");