Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : test suite for SMB2 compounded requests
5 :
6 : Copyright (C) Stefan Metzmacher 2009
7 :
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.
12 :
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.
17 :
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/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "libcli/smb2/smb2.h"
24 : #include "libcli/smb2/smb2_calls.h"
25 : #include "torture/torture.h"
26 : #include "torture/smb2/proto.h"
27 : #include "libcli/security/security.h"
28 : #include "librpc/gen_ndr/ndr_security.h"
29 : #include "../libcli/smb/smbXcli_base.h"
30 :
31 : #define CHECK_STATUS(status, correct) do { \
32 : if (!NT_STATUS_EQUAL(status, correct)) { \
33 : torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
34 : nt_errstr(status), nt_errstr(correct)); \
35 : ret = false; \
36 : goto done; \
37 : }} while (0)
38 :
39 : #define CHECK_VALUE(v, correct) do { \
40 : if ((v) != (correct)) { \
41 : torture_result(tctx, TORTURE_FAIL, \
42 : "(%s) Incorrect value %s=%d - should be %d\n", \
43 : __location__, #v, (int)v, (int)correct); \
44 : ret = false; \
45 : }} while (0)
46 :
47 : static struct {
48 : struct smb2_handle handle;
49 : uint8_t level;
50 : struct smb2_break br;
51 : int count;
52 : int failures;
53 : NTSTATUS failure_status;
54 : } break_info;
55 :
56 6 : static void torture_oplock_break_callback(struct smb2_request *req)
57 : {
58 : NTSTATUS status;
59 : struct smb2_break br;
60 :
61 6 : ZERO_STRUCT(br);
62 6 : status = smb2_break_recv(req, &break_info.br);
63 6 : if (!NT_STATUS_IS_OK(status)) {
64 0 : break_info.failures++;
65 0 : break_info.failure_status = status;
66 : }
67 :
68 6 : return;
69 : }
70 :
71 : /* A general oplock break notification handler. This should be used when a
72 : * test expects to break from batch or exclusive to a lower level. */
73 6 : static bool torture_oplock_handler(struct smb2_transport *transport,
74 : const struct smb2_handle *handle,
75 : uint8_t level,
76 : void *private_data)
77 : {
78 6 : struct smb2_tree *tree = private_data;
79 : const char *name;
80 : struct smb2_request *req;
81 6 : ZERO_STRUCT(break_info.br);
82 :
83 6 : break_info.handle = *handle;
84 6 : break_info.level = level;
85 6 : break_info.count++;
86 :
87 6 : switch (level) {
88 6 : case SMB2_OPLOCK_LEVEL_II:
89 6 : name = "level II";
90 6 : break;
91 0 : case SMB2_OPLOCK_LEVEL_NONE:
92 0 : name = "none";
93 0 : break;
94 0 : default:
95 0 : name = "unknown";
96 0 : break_info.failures++;
97 : }
98 6 : printf("Acking to %s [0x%02X] in oplock handler\n", name, level);
99 :
100 6 : break_info.br.in.file.handle = *handle;
101 6 : break_info.br.in.oplock_level = level;
102 6 : break_info.br.in.reserved = 0;
103 6 : break_info.br.in.reserved2 = 0;
104 :
105 6 : req = smb2_break_send(tree, &break_info.br);
106 6 : req->async.fn = torture_oplock_break_callback;
107 6 : req->async.private_data = NULL;
108 6 : return true;
109 : }
110 :
111 6 : static bool test_compound_break(struct torture_context *tctx,
112 : struct smb2_tree *tree)
113 : {
114 6 : const char *fname1 = "some-file.pptx";
115 : NTSTATUS status;
116 6 : bool ret = true;
117 : union smb_open io1;
118 : struct smb2_create io2;
119 : struct smb2_getinfo gf;
120 : struct smb2_request *req[2];
121 : struct smb2_handle h1;
122 : struct smb2_handle h;
123 :
124 6 : tree->session->transport->oplock.handler = torture_oplock_handler;
125 6 : tree->session->transport->oplock.private_data = tree;
126 :
127 6 : ZERO_STRUCT(break_info);
128 :
129 : /*
130 : base ntcreatex parms
131 : */
132 6 : ZERO_STRUCT(io1.smb2);
133 6 : io1.generic.level = RAW_OPEN_SMB2;
134 6 : io1.smb2.in.desired_access = (SEC_STD_SYNCHRONIZE|
135 : SEC_STD_READ_CONTROL|
136 : SEC_FILE_READ_ATTRIBUTE|
137 : SEC_FILE_READ_EA|
138 : SEC_FILE_READ_DATA);
139 6 : io1.smb2.in.alloc_size = 0;
140 6 : io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
141 6 : io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
142 : NTCREATEX_SHARE_ACCESS_WRITE|
143 : NTCREATEX_SHARE_ACCESS_DELETE;
144 6 : io1.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
145 6 : io1.smb2.in.create_options = 0;
146 6 : io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
147 6 : io1.smb2.in.security_flags = 0;
148 6 : io1.smb2.in.fname = fname1;
149 :
150 6 : torture_comment(tctx, "TEST2: open a file with an batch "
151 : "oplock (share mode: all)\n");
152 6 : io1.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
153 :
154 6 : status = smb2_create(tree, tctx, &(io1.smb2));
155 6 : torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
156 :
157 6 : h1 = io1.smb2.out.file.handle;
158 :
159 6 : torture_comment(tctx, "TEST2: Opening second time with compound\n");
160 :
161 6 : ZERO_STRUCT(io2);
162 :
163 6 : io2.in.desired_access = (SEC_STD_SYNCHRONIZE|
164 : SEC_FILE_READ_ATTRIBUTE|
165 : SEC_FILE_READ_EA);
166 6 : io2.in.alloc_size = 0;
167 6 : io2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
168 6 : io2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
169 : NTCREATEX_SHARE_ACCESS_WRITE|
170 : NTCREATEX_SHARE_ACCESS_DELETE;
171 6 : io2.in.create_disposition = NTCREATEX_DISP_OPEN;
172 6 : io2.in.create_options = 0;
173 6 : io2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
174 6 : io2.in.security_flags = 0;
175 6 : io2.in.fname = fname1;
176 6 : io2.in.oplock_level = 0;
177 :
178 6 : smb2_transport_compound_start(tree->session->transport, 2);
179 :
180 6 : req[0] = smb2_create_send(tree, &io2);
181 :
182 6 : smb2_transport_compound_set_related(tree->session->transport, true);
183 :
184 6 : h.data[0] = UINT64_MAX;
185 6 : h.data[1] = UINT64_MAX;
186 :
187 6 : ZERO_STRUCT(gf);
188 6 : gf.in.file.handle = h;
189 6 : gf.in.info_type = SMB2_0_INFO_FILE;
190 6 : gf.in.info_class = 0x16;
191 6 : gf.in.output_buffer_length = 0x1000;
192 6 : gf.in.input_buffer = data_blob_null;
193 :
194 6 : req[1] = smb2_getinfo_send(tree, &gf);
195 :
196 6 : status = smb2_create_recv(req[0], tree, &io2);
197 6 : CHECK_STATUS(status, NT_STATUS_OK);
198 :
199 6 : status = smb2_getinfo_recv(req[1], tree, &gf);
200 6 : CHECK_STATUS(status, NT_STATUS_OK);
201 :
202 11 : done:
203 :
204 6 : smb2_util_close(tree, h1);
205 6 : smb2_util_unlink(tree, fname1);
206 6 : return ret;
207 : }
208 :
209 6 : static bool test_compound_related1(struct torture_context *tctx,
210 : struct smb2_tree *tree)
211 : {
212 : struct smb2_handle hd;
213 : struct smb2_create cr;
214 : NTSTATUS status;
215 6 : const char *fname = "compound_related1.dat";
216 : struct smb2_close cl;
217 6 : bool ret = true;
218 : struct smb2_request *req[2];
219 6 : struct smbXcli_tcon *saved_tcon = tree->smbXcli;
220 6 : struct smbXcli_session *saved_session = tree->session->smbXcli;
221 :
222 6 : smb2_transport_credits_ask_num(tree->session->transport, 2);
223 :
224 6 : smb2_util_unlink(tree, fname);
225 :
226 6 : smb2_transport_credits_ask_num(tree->session->transport, 1);
227 :
228 6 : ZERO_STRUCT(cr);
229 6 : cr.in.security_flags = 0x00;
230 6 : cr.in.oplock_level = 0;
231 6 : cr.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
232 6 : cr.in.create_flags = 0x00000000;
233 6 : cr.in.reserved = 0x00000000;
234 6 : cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
235 6 : cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
236 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
237 : NTCREATEX_SHARE_ACCESS_WRITE |
238 : NTCREATEX_SHARE_ACCESS_DELETE;
239 6 : cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
240 6 : cr.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
241 : NTCREATEX_OPTIONS_ASYNC_ALERT |
242 : NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
243 : 0x00200000;
244 6 : cr.in.fname = fname;
245 :
246 6 : smb2_transport_compound_start(tree->session->transport, 2);
247 :
248 6 : req[0] = smb2_create_send(tree, &cr);
249 :
250 6 : smb2_transport_compound_set_related(tree->session->transport, true);
251 :
252 6 : hd.data[0] = UINT64_MAX;
253 6 : hd.data[1] = UINT64_MAX;
254 :
255 6 : ZERO_STRUCT(cl);
256 6 : cl.in.file.handle = hd;
257 :
258 6 : tree->smbXcli = smbXcli_tcon_create(tree);
259 6 : smb2cli_tcon_set_values(tree->smbXcli,
260 : NULL, /* session */
261 : 0xFFFFFFFF, /* tcon_id */
262 : 0, /* type */
263 : 0, /* flags */
264 : 0, /* capabilities */
265 : 0 /* maximal_access */);
266 :
267 7 : tree->session->smbXcli = smbXcli_session_shallow_copy(tree->session,
268 6 : tree->session->smbXcli);
269 6 : smb2cli_session_set_id_and_flags(tree->session->smbXcli, UINT64_MAX, 0);
270 :
271 6 : req[1] = smb2_close_send(tree, &cl);
272 :
273 6 : status = smb2_create_recv(req[0], tree, &cr);
274 6 : CHECK_STATUS(status, NT_STATUS_OK);
275 6 : status = smb2_close_recv(req[1], &cl);
276 6 : CHECK_STATUS(status, NT_STATUS_OK);
277 :
278 6 : TALLOC_FREE(tree->smbXcli);
279 6 : tree->smbXcli = saved_tcon;
280 6 : TALLOC_FREE(tree->session->smbXcli);
281 6 : tree->session->smbXcli = saved_session;
282 :
283 6 : smb2_util_unlink(tree, fname);
284 6 : done:
285 6 : return ret;
286 : }
287 :
288 6 : static bool test_compound_related2(struct torture_context *tctx,
289 : struct smb2_tree *tree)
290 : {
291 : struct smb2_handle hd;
292 : struct smb2_create cr;
293 : NTSTATUS status;
294 6 : const char *fname = "compound_related2.dat";
295 : struct smb2_close cl;
296 6 : bool ret = true;
297 : struct smb2_request *req[5];
298 6 : struct smbXcli_tcon *saved_tcon = tree->smbXcli;
299 6 : struct smbXcli_session *saved_session = tree->session->smbXcli;
300 :
301 6 : smb2_transport_credits_ask_num(tree->session->transport, 5);
302 :
303 6 : smb2_util_unlink(tree, fname);
304 :
305 6 : smb2_transport_credits_ask_num(tree->session->transport, 1);
306 :
307 6 : ZERO_STRUCT(cr);
308 6 : cr.in.security_flags = 0x00;
309 6 : cr.in.oplock_level = 0;
310 6 : cr.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
311 6 : cr.in.create_flags = 0x00000000;
312 6 : cr.in.reserved = 0x00000000;
313 6 : cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
314 6 : cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
315 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
316 : NTCREATEX_SHARE_ACCESS_WRITE |
317 : NTCREATEX_SHARE_ACCESS_DELETE;
318 6 : cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
319 6 : cr.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
320 : NTCREATEX_OPTIONS_ASYNC_ALERT |
321 : NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
322 : 0x00200000;
323 6 : cr.in.fname = fname;
324 :
325 6 : smb2_transport_compound_start(tree->session->transport, 5);
326 :
327 6 : req[0] = smb2_create_send(tree, &cr);
328 :
329 6 : hd.data[0] = UINT64_MAX;
330 6 : hd.data[1] = UINT64_MAX;
331 :
332 6 : smb2_transport_compound_set_related(tree->session->transport, true);
333 :
334 6 : ZERO_STRUCT(cl);
335 6 : cl.in.file.handle = hd;
336 :
337 6 : tree->smbXcli = smbXcli_tcon_create(tree);
338 6 : smb2cli_tcon_set_values(tree->smbXcli,
339 : NULL, /* session */
340 : 0xFFFFFFFF, /* tcon_id */
341 : 0, /* type */
342 : 0, /* flags */
343 : 0, /* capabilities */
344 : 0 /* maximal_access */);
345 :
346 7 : tree->session->smbXcli = smbXcli_session_shallow_copy(tree->session,
347 6 : tree->session->smbXcli);
348 6 : smb2cli_session_set_id_and_flags(tree->session->smbXcli, UINT64_MAX, 0);
349 :
350 6 : req[1] = smb2_close_send(tree, &cl);
351 6 : req[2] = smb2_close_send(tree, &cl);
352 6 : req[3] = smb2_close_send(tree, &cl);
353 6 : req[4] = smb2_close_send(tree, &cl);
354 :
355 6 : status = smb2_create_recv(req[0], tree, &cr);
356 6 : CHECK_STATUS(status, NT_STATUS_OK);
357 6 : status = smb2_close_recv(req[1], &cl);
358 6 : CHECK_STATUS(status, NT_STATUS_OK);
359 6 : status = smb2_close_recv(req[2], &cl);
360 6 : CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
361 6 : status = smb2_close_recv(req[3], &cl);
362 6 : CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
363 6 : status = smb2_close_recv(req[4], &cl);
364 6 : CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
365 :
366 6 : TALLOC_FREE(tree->smbXcli);
367 6 : tree->smbXcli = saved_tcon;
368 6 : TALLOC_FREE(tree->session->smbXcli);
369 6 : tree->session->smbXcli = saved_session;
370 :
371 6 : smb2_util_unlink(tree, fname);
372 6 : done:
373 6 : return ret;
374 : }
375 :
376 6 : static bool test_compound_related3(struct torture_context *tctx,
377 : struct smb2_tree *tree)
378 : {
379 : struct smb2_handle hd;
380 : struct smb2_ioctl io;
381 : struct smb2_create cr;
382 : struct smb2_close cl;
383 6 : const char *fname = "compound_related3.dat";
384 : struct smb2_request *req[3];
385 : NTSTATUS status;
386 6 : bool ret = false;
387 :
388 6 : smb2_util_unlink(tree, fname);
389 :
390 6 : ZERO_STRUCT(cr);
391 6 : cr.in.security_flags = 0x00;
392 6 : cr.in.oplock_level = 0;
393 6 : cr.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
394 6 : cr.in.create_flags = 0x00000000;
395 6 : cr.in.reserved = 0x00000000;
396 6 : cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
397 6 : cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
398 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
399 : NTCREATEX_SHARE_ACCESS_WRITE |
400 : NTCREATEX_SHARE_ACCESS_DELETE;
401 6 : cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
402 6 : cr.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
403 : NTCREATEX_OPTIONS_ASYNC_ALERT |
404 : NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
405 : 0x00200000;
406 6 : cr.in.fname = fname;
407 :
408 6 : smb2_transport_compound_start(tree->session->transport, 3);
409 :
410 6 : req[0] = smb2_create_send(tree, &cr);
411 :
412 6 : hd.data[0] = UINT64_MAX;
413 6 : hd.data[1] = UINT64_MAX;
414 :
415 6 : smb2_transport_compound_set_related(tree->session->transport, true);
416 :
417 6 : ZERO_STRUCT(io);
418 6 : io.in.function = FSCTL_CREATE_OR_GET_OBJECT_ID;
419 6 : io.in.file.handle = hd;
420 6 : io.in.reserved2 = 0;
421 6 : io.in.max_output_response = 64;
422 6 : io.in.flags = 1;
423 :
424 6 : req[1] = smb2_ioctl_send(tree, &io);
425 :
426 6 : ZERO_STRUCT(cl);
427 6 : cl.in.file.handle = hd;
428 :
429 6 : req[2] = smb2_close_send(tree, &cl);
430 :
431 6 : status = smb2_create_recv(req[0], tree, &cr);
432 6 : CHECK_STATUS(status, NT_STATUS_OK);
433 6 : status = smb2_ioctl_recv(req[1], tree, &io);
434 6 : CHECK_STATUS(status, NT_STATUS_OK);
435 6 : status = smb2_close_recv(req[2], &cl);
436 6 : CHECK_STATUS(status, NT_STATUS_OK);
437 :
438 6 : status = smb2_util_unlink(tree, fname);
439 6 : CHECK_STATUS(status, NT_STATUS_OK);
440 :
441 6 : ret = true;
442 6 : done:
443 6 : return ret;
444 : }
445 :
446 6 : static bool test_compound_related4(struct torture_context *tctx,
447 : struct smb2_tree *tree)
448 : {
449 6 : const char *fname = "compound_related4.dat";
450 6 : struct security_descriptor *sd = NULL;
451 : struct smb2_handle hd;
452 : struct smb2_create cr;
453 : union smb_setfileinfo set;
454 : struct smb2_ioctl io;
455 : struct smb2_close cl;
456 : struct smb2_request *req[4];
457 : NTSTATUS status;
458 6 : bool ret = true;
459 :
460 6 : smb2_util_unlink(tree, fname);
461 :
462 6 : ZERO_STRUCT(cr);
463 6 : cr.level = RAW_OPEN_SMB2;
464 6 : cr.in.create_flags = 0;
465 6 : cr.in.desired_access = SEC_STD_READ_CONTROL |
466 : SEC_STD_WRITE_DAC |
467 : SEC_STD_WRITE_OWNER;
468 6 : cr.in.create_options = 0;
469 6 : cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
470 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
471 : NTCREATEX_SHARE_ACCESS_READ |
472 : NTCREATEX_SHARE_ACCESS_WRITE;
473 6 : cr.in.alloc_size = 0;
474 6 : cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
475 6 : cr.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
476 6 : cr.in.security_flags = 0;
477 6 : cr.in.fname = fname;
478 :
479 6 : status = smb2_create(tree, tctx, &cr);
480 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed\n");
481 :
482 6 : hd = cr.out.file.handle;
483 6 : torture_comment(tctx, "set a sec desc allowing no write by CREATOR_OWNER\n");
484 :
485 6 : sd = security_descriptor_dacl_create(tctx,
486 : 0, NULL, NULL,
487 : SID_CREATOR_OWNER,
488 : SEC_ACE_TYPE_ACCESS_ALLOWED,
489 : SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
490 : 0,
491 : NULL);
492 6 : torture_assert_not_null_goto(tctx, sd, ret, done,
493 : "security_descriptor_dacl_create failed\n");
494 :
495 6 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
496 6 : set.set_secdesc.in.file.handle = hd;
497 6 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
498 6 : set.set_secdesc.in.sd = sd;
499 :
500 6 : status = smb2_setinfo_file(tree, &set);
501 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
502 : "smb2_setinfo_file failed\n");
503 :
504 6 : torture_comment(tctx, "try open for write\n");
505 6 : cr.in.desired_access = SEC_FILE_WRITE_DATA;
506 6 : smb2_transport_compound_start(tree->session->transport, 4);
507 :
508 6 : req[0] = smb2_create_send(tree, &cr);
509 6 : torture_assert_not_null_goto(tctx, req[0], ret, done,
510 : "smb2_create_send failed\n");
511 :
512 6 : hd.data[0] = UINT64_MAX;
513 6 : hd.data[1] = UINT64_MAX;
514 :
515 6 : smb2_transport_compound_set_related(tree->session->transport, true);
516 6 : ZERO_STRUCT(io);
517 6 : io.in.function = FSCTL_CREATE_OR_GET_OBJECT_ID;
518 6 : io.in.file.handle = hd;
519 6 : io.in.flags = 1;
520 :
521 6 : req[1] = smb2_ioctl_send(tree, &io);
522 6 : torture_assert_not_null_goto(tctx, req[1], ret, done,
523 : "smb2_ioctl_send failed\n");
524 :
525 6 : ZERO_STRUCT(cl);
526 6 : cl.in.file.handle = hd;
527 :
528 6 : req[2] = smb2_close_send(tree, &cl);
529 6 : torture_assert_not_null_goto(tctx, req[2], ret, done,
530 : "smb2_create_send failed\n");
531 :
532 6 : set.set_secdesc.in.file.handle = hd;
533 :
534 6 : req[3] = smb2_setinfo_file_send(tree, &set);
535 6 : torture_assert_not_null_goto(tctx, req[3], ret, done,
536 : "smb2_create_send failed\n");
537 :
538 6 : status = smb2_create_recv(req[0], tree, &cr);
539 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
540 : ret, done,
541 : "smb2_create_recv failed\n");
542 :
543 6 : status = smb2_ioctl_recv(req[1], tree, &io);
544 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
545 : ret, done,
546 : "smb2_ioctl_recv failed\n");
547 :
548 6 : status = smb2_close_recv(req[2], &cl);
549 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
550 : ret, done,
551 : "smb2_close_recv failed\n");
552 :
553 6 : status = smb2_setinfo_recv(req[3]);
554 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
555 : ret, done,
556 : "smb2_setinfo_recv failed\n");
557 :
558 6 : done:
559 6 : smb2_util_unlink(tree, fname);
560 6 : smb2_tdis(tree);
561 6 : smb2_logoff(tree->session);
562 6 : return ret;
563 : }
564 :
565 6 : static bool test_compound_related5(struct torture_context *tctx,
566 : struct smb2_tree *tree)
567 : {
568 : struct smb2_handle hd;
569 : struct smb2_ioctl io;
570 : struct smb2_close cl;
571 : struct smb2_request *req[2];
572 : NTSTATUS status;
573 6 : bool ret = false;
574 :
575 6 : smb2_transport_compound_start(tree->session->transport, 2);
576 :
577 6 : hd.data[0] = UINT64_MAX;
578 6 : hd.data[1] = UINT64_MAX;
579 :
580 6 : ZERO_STRUCT(io);
581 6 : io.in.function = FSCTL_CREATE_OR_GET_OBJECT_ID;
582 6 : io.in.file.handle = hd;
583 6 : io.in.flags = 1;
584 :
585 6 : req[0] = smb2_ioctl_send(tree, &io);
586 6 : torture_assert_not_null_goto(tctx, req[0], ret, done,
587 : "smb2_ioctl_send failed\n");
588 :
589 6 : smb2_transport_compound_set_related(tree->session->transport, true);
590 :
591 6 : ZERO_STRUCT(cl);
592 6 : cl.in.file.handle = hd;
593 :
594 6 : req[1] = smb2_close_send(tree, &cl);
595 6 : torture_assert_not_null_goto(tctx, req[1], ret, done,
596 : "smb2_create_send failed\n");
597 :
598 6 : status = smb2_ioctl_recv(req[0], tree, &io);
599 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_FILE_CLOSED,
600 : ret, done,
601 : "smb2_ioctl_recv failed\n");
602 :
603 6 : status = smb2_close_recv(req[1], &cl);
604 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_FILE_CLOSED,
605 : ret, done,
606 : "smb2_close_recv failed\n");
607 :
608 6 : ret = true;
609 :
610 6 : done:
611 6 : smb2_tdis(tree);
612 6 : smb2_logoff(tree->session);
613 6 : return ret;
614 : }
615 :
616 6 : static bool test_compound_related6(struct torture_context *tctx,
617 : struct smb2_tree *tree)
618 : {
619 : struct smb2_handle hd;
620 : struct smb2_create cr;
621 : struct smb2_read rd;
622 : struct smb2_write wr;
623 : struct smb2_close cl;
624 : NTSTATUS status;
625 6 : const char *fname = "compound_related6.dat";
626 : struct smb2_request *req[5];
627 : uint8_t buf[64];
628 6 : bool ret = true;
629 :
630 6 : smb2_util_unlink(tree, fname);
631 :
632 6 : ZERO_STRUCT(cr);
633 6 : cr.level = RAW_OPEN_SMB2;
634 6 : cr.in.create_flags = 0;
635 6 : cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
636 6 : cr.in.create_options = 0;
637 6 : cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
638 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
639 : NTCREATEX_SHARE_ACCESS_READ |
640 : NTCREATEX_SHARE_ACCESS_WRITE;
641 6 : cr.in.alloc_size = 0;
642 6 : cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
643 6 : cr.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
644 6 : cr.in.security_flags = 0;
645 6 : cr.in.fname = fname;
646 :
647 6 : status = smb2_create(tree, tctx, &cr);
648 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
649 : "smb2_create failed\n");
650 :
651 6 : hd = cr.out.file.handle;
652 :
653 6 : ZERO_STRUCT(buf);
654 6 : status = smb2_util_write(tree, hd, buf, 0, ARRAY_SIZE(buf));
655 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
656 : "smb2_util_write failed\n");
657 :
658 6 : torture_comment(tctx, "try open for read\n");
659 6 : cr.in.desired_access = SEC_FILE_READ_DATA;
660 6 : smb2_transport_compound_start(tree->session->transport, 5);
661 :
662 6 : req[0] = smb2_create_send(tree, &cr);
663 6 : torture_assert_not_null_goto(tctx, req[0], ret, done,
664 : "smb2_create_send failed\n");
665 :
666 6 : hd.data[0] = UINT64_MAX;
667 6 : hd.data[1] = UINT64_MAX;
668 :
669 6 : smb2_transport_compound_set_related(tree->session->transport, true);
670 :
671 6 : ZERO_STRUCT(rd);
672 6 : rd.in.file.handle = hd;
673 6 : rd.in.length = 1;
674 6 : rd.in.offset = 0;
675 :
676 6 : req[1] = smb2_read_send(tree, &rd);
677 6 : torture_assert_not_null_goto(tctx, req[1], ret, done,
678 : "smb2_read_send failed\n");
679 :
680 6 : ZERO_STRUCT(wr);
681 6 : wr.in.file.handle = hd;
682 6 : wr.in.offset = 0;
683 6 : wr.in.data = data_blob_talloc(tctx, NULL, 64);
684 :
685 6 : req[2] = smb2_write_send(tree, &wr);
686 6 : torture_assert_not_null_goto(tctx, req[2], ret, done,
687 : "smb2_write_send failed\n");
688 :
689 6 : ZERO_STRUCT(rd);
690 6 : rd.in.file.handle = hd;
691 6 : rd.in.length = 1;
692 6 : rd.in.offset = 0;
693 :
694 6 : req[3] = smb2_read_send(tree, &rd);
695 6 : torture_assert_not_null_goto(tctx, req[3], ret, done,
696 : "smb2_read_send failed\n");
697 :
698 6 : ZERO_STRUCT(cl);
699 6 : cl.in.file.handle = hd;
700 :
701 6 : req[4] = smb2_close_send(tree, &cl);
702 6 : torture_assert_not_null_goto(tctx, req[4], ret, done,
703 : "smb2_close_send failed\n");
704 :
705 6 : status = smb2_create_recv(req[0], tree, &cr);
706 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
707 : "smb2_create_recv failed\n");
708 :
709 6 : status = smb2_read_recv(req[1], tree, &rd);
710 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
711 : "smb2_read_recv failed\n");
712 :
713 6 : status = smb2_write_recv(req[2], &wr);
714 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
715 : ret, done,
716 : "smb2_write_recv failed\n");
717 :
718 6 : status = smb2_read_recv(req[3], tree, &rd);
719 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
720 : "smb2_read_recv failed\n");
721 :
722 6 : status = smb2_close_recv(req[4], &cl);
723 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
724 : "smb2_close_recv failed\n");
725 :
726 6 : done:
727 6 : smb2_util_unlink(tree, fname);
728 6 : smb2_tdis(tree);
729 6 : smb2_logoff(tree->session);
730 6 : return ret;
731 : }
732 :
733 6 : static bool test_compound_related7(struct torture_context *tctx,
734 : struct smb2_tree *tree)
735 : {
736 6 : const char *fname = "compound_related4.dat";
737 6 : struct security_descriptor *sd = NULL;
738 : struct smb2_handle hd;
739 : struct smb2_create cr;
740 : union smb_setfileinfo set;
741 : struct smb2_notify nt;
742 : struct smb2_close cl;
743 : NTSTATUS status;
744 : struct smb2_request *req[4];
745 6 : bool ret = true;
746 :
747 6 : smb2_util_unlink(tree, fname);
748 :
749 6 : ZERO_STRUCT(cr);
750 6 : cr.level = RAW_OPEN_SMB2;
751 6 : cr.in.create_flags = 0;
752 6 : cr.in.desired_access = SEC_STD_READ_CONTROL |
753 : SEC_STD_WRITE_DAC |
754 : SEC_STD_WRITE_OWNER;
755 6 : cr.in.create_options = 0;
756 6 : cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
757 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
758 : NTCREATEX_SHARE_ACCESS_READ |
759 : NTCREATEX_SHARE_ACCESS_WRITE;
760 6 : cr.in.alloc_size = 0;
761 6 : cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
762 6 : cr.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
763 6 : cr.in.security_flags = 0;
764 6 : cr.in.fname = fname;
765 :
766 6 : status = smb2_create(tree, tctx, &cr);
767 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
768 : "smb2_create failed\n");
769 :
770 6 : hd = cr.out.file.handle;
771 6 : torture_comment(tctx, "set a sec desc allowing no write by CREATOR_OWNER\n");
772 6 : sd = security_descriptor_dacl_create(tctx,
773 : 0, NULL, NULL,
774 : SID_CREATOR_OWNER,
775 : SEC_ACE_TYPE_ACCESS_ALLOWED,
776 : SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
777 : 0,
778 : NULL);
779 6 : torture_assert_not_null_goto(tctx, sd, ret, done,
780 : "security_descriptor_dacl_create failed\n");
781 :
782 6 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
783 6 : set.set_secdesc.in.file.handle = hd;
784 6 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
785 6 : set.set_secdesc.in.sd = sd;
786 :
787 6 : status = smb2_setinfo_file(tree, &set);
788 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
789 : "smb2_setinfo_file failed\n");
790 :
791 6 : torture_comment(tctx, "try open for write\n");
792 6 : cr.in.desired_access = SEC_FILE_WRITE_DATA;
793 6 : smb2_transport_compound_start(tree->session->transport, 4);
794 :
795 6 : req[0] = smb2_create_send(tree, &cr);
796 6 : torture_assert_not_null_goto(tctx, req[0], ret, done,
797 : "smb2_create_send failed\n");
798 :
799 6 : hd.data[0] = UINT64_MAX;
800 6 : hd.data[1] = UINT64_MAX;
801 :
802 6 : smb2_transport_compound_set_related(tree->session->transport, true);
803 :
804 6 : ZERO_STRUCT(nt);
805 6 : nt.in.recursive = true;
806 6 : nt.in.buffer_size = 0x1000;
807 6 : nt.in.file.handle = hd;
808 6 : nt.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
809 6 : nt.in.unknown = 0x00000000;
810 :
811 6 : req[1] = smb2_notify_send(tree, &nt);
812 6 : torture_assert_not_null_goto(tctx, req[1], ret, done,
813 : "smb2_notify_send failed\n");
814 :
815 6 : ZERO_STRUCT(cl);
816 6 : cl.in.file.handle = hd;
817 :
818 6 : req[2] = smb2_close_send(tree, &cl);
819 6 : torture_assert_not_null_goto(tctx, req[2], ret, done,
820 : "smb2_close_send failed\n");
821 :
822 6 : set.set_secdesc.in.file.handle = hd;
823 :
824 6 : req[3] = smb2_setinfo_file_send(tree, &set);
825 6 : torture_assert_not_null_goto(tctx, req[3], ret, done,
826 : "smb2_setinfo_file_send failed\n");
827 :
828 6 : status = smb2_create_recv(req[0], tree, &cr);
829 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
830 : ret, done,
831 : "smb2_create_recv failed\n");
832 :
833 6 : status = smb2_notify_recv(req[1], tree, &nt);
834 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
835 : ret, done,
836 : "smb2_notify_recv failed\n");
837 :
838 6 : status = smb2_close_recv(req[2], &cl);
839 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
840 : ret, done,
841 : "smb2_close_recv failed\n");
842 :
843 6 : status = smb2_setinfo_recv(req[3]);
844 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
845 : ret, done,
846 : "smb2_setinfo_recv failed\n");
847 :
848 6 : done:
849 6 : smb2_util_unlink(tree, fname);
850 6 : smb2_tdis(tree);
851 6 : smb2_logoff(tree->session);
852 6 : return ret;
853 : }
854 :
855 6 : static bool test_compound_related8(struct torture_context *tctx,
856 : struct smb2_tree *tree)
857 : {
858 6 : const char *fname = "compound_related8.dat";
859 6 : const char *fname_nonexisting = "compound_related8.dat.void";
860 6 : struct security_descriptor *sd = NULL;
861 : struct smb2_handle hd;
862 : struct smb2_create cr;
863 : union smb_setfileinfo set;
864 : struct smb2_notify nt;
865 : struct smb2_close cl;
866 : NTSTATUS status;
867 : struct smb2_request *req[4];
868 6 : bool ret = true;
869 :
870 6 : smb2_util_unlink(tree, fname);
871 :
872 6 : ZERO_STRUCT(cr);
873 6 : cr.level = RAW_OPEN_SMB2;
874 6 : cr.in.create_flags = 0;
875 6 : cr.in.desired_access = SEC_STD_READ_CONTROL |
876 : SEC_STD_WRITE_DAC |
877 : SEC_STD_WRITE_OWNER;
878 6 : cr.in.create_options = 0;
879 6 : cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
880 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
881 : NTCREATEX_SHARE_ACCESS_READ |
882 : NTCREATEX_SHARE_ACCESS_WRITE;
883 6 : cr.in.alloc_size = 0;
884 6 : cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
885 6 : cr.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
886 6 : cr.in.security_flags = 0;
887 6 : cr.in.fname = fname;
888 :
889 6 : status = smb2_create(tree, tctx, &cr);
890 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
891 : "smb2_create failed\n");
892 :
893 6 : hd = cr.out.file.handle;
894 :
895 6 : smb2_transport_compound_start(tree->session->transport, 4);
896 :
897 6 : torture_comment(tctx, "try open for write\n");
898 6 : cr.in.fname = fname_nonexisting;
899 6 : cr.in.create_disposition = NTCREATEX_DISP_OPEN;
900 :
901 6 : req[0] = smb2_create_send(tree, &cr);
902 6 : torture_assert_not_null_goto(tctx, req[0], ret, done,
903 : "smb2_create_send failed\n");
904 :
905 6 : hd.data[0] = UINT64_MAX;
906 6 : hd.data[1] = UINT64_MAX;
907 :
908 6 : smb2_transport_compound_set_related(tree->session->transport, true);
909 :
910 6 : ZERO_STRUCT(nt);
911 6 : nt.in.recursive = true;
912 6 : nt.in.buffer_size = 0x1000;
913 6 : nt.in.file.handle = hd;
914 6 : nt.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
915 6 : nt.in.unknown = 0x00000000;
916 :
917 6 : req[1] = smb2_notify_send(tree, &nt);
918 6 : torture_assert_not_null_goto(tctx, req[1], ret, done,
919 : "smb2_notify_send failed\n");
920 :
921 6 : ZERO_STRUCT(cl);
922 6 : cl.in.file.handle = hd;
923 :
924 6 : req[2] = smb2_close_send(tree, &cl);
925 6 : torture_assert_not_null_goto(tctx, req[2], ret, done,
926 : "smb2_close_send failed\n");
927 :
928 6 : sd = security_descriptor_dacl_create(tctx,
929 : 0, NULL, NULL,
930 : SID_CREATOR_OWNER,
931 : SEC_ACE_TYPE_ACCESS_ALLOWED,
932 : SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
933 : 0,
934 : NULL);
935 6 : torture_assert_not_null_goto(tctx, sd, ret, done,
936 : "security_descriptor_dacl_create failed\n");
937 :
938 6 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
939 6 : set.set_secdesc.in.file.handle = hd;
940 6 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
941 6 : set.set_secdesc.in.sd = sd;
942 :
943 6 : req[3] = smb2_setinfo_file_send(tree, &set);
944 6 : torture_assert_not_null_goto(tctx, req[3], ret, done,
945 : "smb2_setinfo_file_send failed\n");
946 :
947 6 : status = smb2_create_recv(req[0], tree, &cr);
948 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
949 : ret, done,
950 : "smb2_create_recv failed\n");
951 :
952 6 : status = smb2_notify_recv(req[1], tree, &nt);
953 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
954 : ret, done,
955 : "smb2_notify_recv failed\n");
956 :
957 6 : status = smb2_close_recv(req[2], &cl);
958 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
959 : ret, done,
960 : "smb2_close_recv failed\n");
961 :
962 6 : status = smb2_setinfo_recv(req[3]);
963 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
964 : ret, done,
965 : "smb2_setinfo_recv failed\n");
966 :
967 6 : done:
968 6 : smb2_util_unlink(tree, fname);
969 6 : smb2_tdis(tree);
970 6 : smb2_logoff(tree->session);
971 6 : return ret;
972 : }
973 :
974 6 : static bool test_compound_related9(struct torture_context *tctx,
975 : struct smb2_tree *tree)
976 : {
977 6 : const char *fname = "compound_related9.dat";
978 6 : struct security_descriptor *sd = NULL;
979 : struct smb2_handle hd;
980 : struct smb2_create cr;
981 : union smb_setfileinfo set;
982 : struct smb2_notify nt;
983 : struct smb2_close cl;
984 : NTSTATUS status;
985 : struct smb2_request *req[3];
986 6 : bool ret = true;
987 :
988 6 : smb2_util_unlink(tree, fname);
989 :
990 6 : ZERO_STRUCT(cr);
991 6 : cr.level = RAW_OPEN_SMB2;
992 6 : cr.in.create_flags = 0;
993 6 : cr.in.desired_access = SEC_STD_READ_CONTROL |
994 : SEC_STD_WRITE_DAC |
995 : SEC_STD_WRITE_OWNER;
996 6 : cr.in.create_options = 0;
997 6 : cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
998 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
999 : NTCREATEX_SHARE_ACCESS_READ |
1000 : NTCREATEX_SHARE_ACCESS_WRITE;
1001 6 : cr.in.alloc_size = 0;
1002 6 : cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1003 6 : cr.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
1004 6 : cr.in.security_flags = 0;
1005 6 : cr.in.fname = fname;
1006 :
1007 6 : status = smb2_create(tree, tctx, &cr);
1008 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1009 : "smb2_create failed\n");
1010 :
1011 6 : hd = cr.out.file.handle;
1012 :
1013 6 : smb2_transport_compound_start(tree->session->transport, 3);
1014 6 : smb2_transport_compound_set_related(tree->session->transport, true);
1015 :
1016 6 : ZERO_STRUCT(nt);
1017 6 : nt.in.recursive = true;
1018 6 : nt.in.buffer_size = 0x1000;
1019 6 : nt.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
1020 :
1021 6 : req[0] = smb2_notify_send(tree, &nt);
1022 6 : torture_assert_not_null_goto(tctx, req[0], ret, done,
1023 : "smb2_notify_send failed\n");
1024 :
1025 6 : ZERO_STRUCT(cl);
1026 6 : cl.in.file.handle = hd;
1027 :
1028 6 : req[1] = smb2_close_send(tree, &cl);
1029 6 : torture_assert_not_null_goto(tctx, req[1], ret, done,
1030 : "smb2_close_send failed\n");
1031 :
1032 6 : sd = security_descriptor_dacl_create(tctx,
1033 : 0, NULL, NULL,
1034 : SID_CREATOR_OWNER,
1035 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1036 : SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
1037 : 0,
1038 : NULL);
1039 6 : torture_assert_not_null_goto(tctx, sd, ret, done,
1040 : "security_descriptor_dacl_create failed\n");
1041 :
1042 6 : set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1043 6 : set.set_secdesc.in.file.handle = hd;
1044 6 : set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1045 6 : set.set_secdesc.in.sd = sd;
1046 :
1047 6 : req[2] = smb2_setinfo_file_send(tree, &set);
1048 6 : torture_assert_not_null_goto(tctx, req[2], ret, done,
1049 : "smb2_setinfo_file_send failed\n");
1050 :
1051 6 : status = smb2_notify_recv(req[0], tree, &nt);
1052 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_INVALID_PARAMETER,
1053 : ret, done,
1054 : "smb2_notify_recv failed\n");
1055 :
1056 6 : status = smb2_close_recv(req[1], &cl);
1057 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_INVALID_PARAMETER,
1058 : ret, done,
1059 : "smb2_close_recv failed\n");
1060 :
1061 6 : status = smb2_setinfo_recv(req[2]);
1062 6 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_INVALID_PARAMETER,
1063 : ret, done,
1064 : "smb2_setinfo_recv failed\n");
1065 :
1066 6 : done:
1067 6 : smb2_util_unlink(tree, fname);
1068 6 : smb2_tdis(tree);
1069 6 : smb2_logoff(tree->session);
1070 6 : return ret;
1071 : }
1072 :
1073 6 : static bool test_compound_padding(struct torture_context *tctx,
1074 : struct smb2_tree *tree)
1075 : {
1076 : struct smb2_handle h;
1077 : struct smb2_create cr;
1078 : struct smb2_read r;
1079 6 : const char *fname = "compound_read.dat";
1080 6 : const char *sname = "compound_read.dat:foo";
1081 : struct smb2_request *req[3];
1082 : NTSTATUS status;
1083 6 : bool ret = false;
1084 :
1085 6 : smb2_util_unlink(tree, fname);
1086 :
1087 : /* Write file */
1088 6 : ZERO_STRUCT(cr);
1089 6 : cr.in.desired_access = SEC_FILE_WRITE_DATA;
1090 6 : cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1091 6 : cr.in.create_disposition = NTCREATEX_DISP_CREATE;
1092 6 : cr.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1093 6 : cr.in.fname = fname;
1094 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1095 : NTCREATEX_SHARE_ACCESS_WRITE|
1096 : NTCREATEX_SHARE_ACCESS_DELETE;
1097 6 : status = smb2_create(tree, tctx, &cr);
1098 6 : CHECK_STATUS(status, NT_STATUS_OK);
1099 6 : h = cr.out.file.handle;
1100 :
1101 6 : status = smb2_util_write(tree, h, "123", 0, 3);
1102 6 : CHECK_STATUS(status, NT_STATUS_OK);
1103 :
1104 6 : smb2_util_close(tree, h);
1105 :
1106 : /* Write stream */
1107 6 : ZERO_STRUCT(cr);
1108 6 : cr.in.desired_access = SEC_FILE_WRITE_DATA;
1109 6 : cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1110 6 : cr.in.create_disposition = NTCREATEX_DISP_CREATE;
1111 6 : cr.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1112 6 : cr.in.fname = sname;
1113 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1114 : NTCREATEX_SHARE_ACCESS_WRITE|
1115 : NTCREATEX_SHARE_ACCESS_DELETE;
1116 6 : status = smb2_create(tree, tctx, &cr);
1117 6 : CHECK_STATUS(status, NT_STATUS_OK);
1118 6 : h = cr.out.file.handle;
1119 :
1120 6 : status = smb2_util_write(tree, h, "456", 0, 3);
1121 6 : CHECK_STATUS(status, NT_STATUS_OK);
1122 :
1123 6 : smb2_util_close(tree, h);
1124 :
1125 : /* Check compound read from basefile */
1126 6 : smb2_transport_compound_start(tree->session->transport, 2);
1127 :
1128 6 : ZERO_STRUCT(cr);
1129 6 : cr.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1130 6 : cr.in.desired_access = SEC_FILE_READ_DATA;
1131 6 : cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1132 6 : cr.in.create_disposition = NTCREATEX_DISP_OPEN;
1133 6 : cr.in.fname = fname;
1134 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1135 : NTCREATEX_SHARE_ACCESS_WRITE|
1136 : NTCREATEX_SHARE_ACCESS_DELETE;
1137 6 : req[0] = smb2_create_send(tree, &cr);
1138 :
1139 6 : smb2_transport_compound_set_related(tree->session->transport, true);
1140 :
1141 6 : ZERO_STRUCT(r);
1142 6 : h.data[0] = UINT64_MAX;
1143 6 : h.data[1] = UINT64_MAX;
1144 6 : r.in.file.handle = h;
1145 6 : r.in.length = 3;
1146 6 : r.in.offset = 0;
1147 6 : r.in.min_count = 1;
1148 6 : req[1] = smb2_read_send(tree, &r);
1149 :
1150 6 : status = smb2_create_recv(req[0], tree, &cr);
1151 6 : CHECK_STATUS(status, NT_STATUS_OK);
1152 :
1153 : /*
1154 : * We must do a manual smb2_request_receive() in order to be
1155 : * able to check the transport layer info, as smb2_read_recv()
1156 : * will destroy the req. smb2_read_recv() will call
1157 : * smb2_request_receive() again, but that's ok.
1158 : */
1159 11 : if (!smb2_request_receive(req[1]) ||
1160 6 : !smb2_request_is_ok(req[1])) {
1161 0 : torture_fail(tctx, "failed to receive read request");
1162 : }
1163 :
1164 : /*
1165 : * size must be 24: 16 byte read response header plus 3
1166 : * requested bytes padded to an 8 byte boundary.
1167 : */
1168 6 : CHECK_VALUE(req[1]->in.body_size, 24);
1169 :
1170 6 : status = smb2_read_recv(req[1], tree, &r);
1171 6 : CHECK_STATUS(status, NT_STATUS_OK);
1172 :
1173 6 : smb2_util_close(tree, cr.out.file.handle);
1174 :
1175 : /* Check compound read from stream */
1176 6 : smb2_transport_compound_start(tree->session->transport, 2);
1177 :
1178 6 : ZERO_STRUCT(cr);
1179 6 : cr.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1180 6 : cr.in.desired_access = SEC_FILE_READ_DATA;
1181 6 : cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1182 6 : cr.in.create_disposition = NTCREATEX_DISP_OPEN;
1183 6 : cr.in.fname = sname;
1184 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1185 : NTCREATEX_SHARE_ACCESS_WRITE|
1186 : NTCREATEX_SHARE_ACCESS_DELETE;
1187 6 : req[0] = smb2_create_send(tree, &cr);
1188 :
1189 6 : smb2_transport_compound_set_related(tree->session->transport, true);
1190 :
1191 6 : ZERO_STRUCT(r);
1192 6 : h.data[0] = UINT64_MAX;
1193 6 : h.data[1] = UINT64_MAX;
1194 6 : r.in.file.handle = h;
1195 6 : r.in.length = 3;
1196 6 : r.in.offset = 0;
1197 6 : r.in.min_count = 1;
1198 6 : req[1] = smb2_read_send(tree, &r);
1199 :
1200 6 : status = smb2_create_recv(req[0], tree, &cr);
1201 6 : CHECK_STATUS(status, NT_STATUS_OK);
1202 :
1203 : /*
1204 : * We must do a manual smb2_request_receive() in order to be
1205 : * able to check the transport layer info, as smb2_read_recv()
1206 : * will destroy the req. smb2_read_recv() will call
1207 : * smb2_request_receive() again, but that's ok.
1208 : */
1209 11 : if (!smb2_request_receive(req[1]) ||
1210 6 : !smb2_request_is_ok(req[1])) {
1211 0 : torture_fail(tctx, "failed to receive read request");
1212 : }
1213 :
1214 : /*
1215 : * size must be 24: 16 byte read response header plus 3
1216 : * requested bytes padded to an 8 byte boundary.
1217 : */
1218 6 : CHECK_VALUE(req[1]->in.body_size, 24);
1219 :
1220 6 : status = smb2_read_recv(req[1], tree, &r);
1221 6 : CHECK_STATUS(status, NT_STATUS_OK);
1222 :
1223 6 : h = cr.out.file.handle;
1224 :
1225 : /* Check 2 compound (unrelateated) reads from existing stream handle */
1226 6 : smb2_transport_compound_start(tree->session->transport, 2);
1227 :
1228 6 : ZERO_STRUCT(r);
1229 6 : r.in.file.handle = h;
1230 6 : r.in.length = 3;
1231 6 : r.in.offset = 0;
1232 6 : r.in.min_count = 1;
1233 6 : req[0] = smb2_read_send(tree, &r);
1234 6 : req[1] = smb2_read_send(tree, &r);
1235 :
1236 : /*
1237 : * We must do a manual smb2_request_receive() in order to be
1238 : * able to check the transport layer info, as smb2_read_recv()
1239 : * will destroy the req. smb2_read_recv() will call
1240 : * smb2_request_receive() again, but that's ok.
1241 : */
1242 11 : if (!smb2_request_receive(req[0]) ||
1243 6 : !smb2_request_is_ok(req[0])) {
1244 0 : torture_fail(tctx, "failed to receive read request");
1245 : }
1246 11 : if (!smb2_request_receive(req[1]) ||
1247 6 : !smb2_request_is_ok(req[1])) {
1248 0 : torture_fail(tctx, "failed to receive read request");
1249 : }
1250 :
1251 : /*
1252 : * size must be 24: 16 byte read response header plus 3
1253 : * requested bytes padded to an 8 byte boundary.
1254 : */
1255 6 : CHECK_VALUE(req[0]->in.body_size, 24);
1256 6 : CHECK_VALUE(req[1]->in.body_size, 24);
1257 :
1258 6 : status = smb2_read_recv(req[0], tree, &r);
1259 6 : CHECK_STATUS(status, NT_STATUS_OK);
1260 6 : status = smb2_read_recv(req[1], tree, &r);
1261 6 : CHECK_STATUS(status, NT_STATUS_OK);
1262 :
1263 : /*
1264 : * now try a single read from the stream and verify there's no padding
1265 : */
1266 6 : ZERO_STRUCT(r);
1267 6 : r.in.file.handle = h;
1268 6 : r.in.length = 3;
1269 6 : r.in.offset = 0;
1270 6 : r.in.min_count = 1;
1271 6 : req[0] = smb2_read_send(tree, &r);
1272 :
1273 : /*
1274 : * We must do a manual smb2_request_receive() in order to be
1275 : * able to check the transport layer info, as smb2_read_recv()
1276 : * will destroy the req. smb2_read_recv() will call
1277 : * smb2_request_receive() again, but that's ok.
1278 : */
1279 11 : if (!smb2_request_receive(req[0]) ||
1280 6 : !smb2_request_is_ok(req[0])) {
1281 0 : torture_fail(tctx, "failed to receive read request");
1282 : }
1283 :
1284 : /*
1285 : * size must be 19: 16 byte read response header plus 3
1286 : * requested bytes without padding.
1287 : */
1288 6 : CHECK_VALUE(req[0]->in.body_size, 19);
1289 :
1290 6 : status = smb2_read_recv(req[0], tree, &r);
1291 6 : CHECK_STATUS(status, NT_STATUS_OK);
1292 :
1293 6 : smb2_util_close(tree, h);
1294 :
1295 6 : status = smb2_util_unlink(tree, fname);
1296 6 : CHECK_STATUS(status, NT_STATUS_OK);
1297 :
1298 6 : ret = true;
1299 6 : done:
1300 6 : return ret;
1301 : }
1302 :
1303 6 : static bool test_compound_create_write_close(struct torture_context *tctx,
1304 : struct smb2_tree *tree)
1305 : {
1306 6 : struct smb2_handle handle = { .data = { UINT64_MAX, UINT64_MAX } };
1307 : struct smb2_create create;
1308 : struct smb2_write write;
1309 : struct smb2_close close;
1310 6 : const char *fname = "compound_create_write_close.dat";
1311 : struct smb2_request *req[3];
1312 : NTSTATUS status;
1313 6 : bool ret = false;
1314 :
1315 6 : smb2_util_unlink(tree, fname);
1316 :
1317 6 : ZERO_STRUCT(create);
1318 6 : create.in.security_flags = 0x00;
1319 6 : create.in.oplock_level = 0;
1320 6 : create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
1321 6 : create.in.create_flags = 0x00000000;
1322 6 : create.in.reserved = 0x00000000;
1323 6 : create.in.desired_access = SEC_RIGHTS_FILE_ALL;
1324 6 : create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1325 6 : create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1326 : NTCREATEX_SHARE_ACCESS_WRITE |
1327 : NTCREATEX_SHARE_ACCESS_DELETE;
1328 6 : create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1329 6 : create.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
1330 : NTCREATEX_OPTIONS_ASYNC_ALERT |
1331 : NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
1332 : 0x00200000;
1333 6 : create.in.fname = fname;
1334 :
1335 6 : smb2_transport_compound_start(tree->session->transport, 3);
1336 :
1337 6 : req[0] = smb2_create_send(tree, &create);
1338 :
1339 6 : smb2_transport_compound_set_related(tree->session->transport, true);
1340 :
1341 6 : ZERO_STRUCT(write);
1342 6 : write.in.file.handle = handle;
1343 6 : write.in.offset = 0;
1344 6 : write.in.data = data_blob_talloc(tctx, NULL, 1024);
1345 :
1346 6 : req[1] = smb2_write_send(tree, &write);
1347 :
1348 6 : ZERO_STRUCT(close);
1349 6 : close.in.file.handle = handle;
1350 :
1351 6 : req[2] = smb2_close_send(tree, &close);
1352 :
1353 6 : status = smb2_create_recv(req[0], tree, &create);
1354 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1355 : "CREATE failed.");
1356 :
1357 6 : status = smb2_write_recv(req[1], &write);
1358 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1359 : "WRITE failed.");
1360 :
1361 6 : status = smb2_close_recv(req[2], &close);
1362 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1363 : "CLOSE failed.");
1364 :
1365 6 : status = smb2_util_unlink(tree, fname);
1366 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1367 : "File deletion failed.");
1368 :
1369 6 : ret = true;
1370 6 : done:
1371 6 : return ret;
1372 : }
1373 :
1374 6 : static bool test_compound_unrelated1(struct torture_context *tctx,
1375 : struct smb2_tree *tree)
1376 : {
1377 : struct smb2_handle hd;
1378 : struct smb2_create cr;
1379 : NTSTATUS status;
1380 6 : const char *fname = "compound_unrelated1.dat";
1381 : struct smb2_close cl;
1382 6 : bool ret = true;
1383 : struct smb2_request *req[5];
1384 :
1385 6 : smb2_transport_credits_ask_num(tree->session->transport, 5);
1386 :
1387 6 : smb2_util_unlink(tree, fname);
1388 :
1389 6 : smb2_transport_credits_ask_num(tree->session->transport, 1);
1390 :
1391 6 : ZERO_STRUCT(cr);
1392 6 : cr.in.security_flags = 0x00;
1393 6 : cr.in.oplock_level = 0;
1394 6 : cr.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
1395 6 : cr.in.create_flags = 0x00000000;
1396 6 : cr.in.reserved = 0x00000000;
1397 6 : cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
1398 6 : cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1399 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1400 : NTCREATEX_SHARE_ACCESS_WRITE |
1401 : NTCREATEX_SHARE_ACCESS_DELETE;
1402 6 : cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1403 6 : cr.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
1404 : NTCREATEX_OPTIONS_ASYNC_ALERT |
1405 : NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
1406 : 0x00200000;
1407 6 : cr.in.fname = fname;
1408 :
1409 6 : smb2_transport_compound_start(tree->session->transport, 5);
1410 :
1411 6 : req[0] = smb2_create_send(tree, &cr);
1412 :
1413 6 : hd.data[0] = UINT64_MAX;
1414 6 : hd.data[1] = UINT64_MAX;
1415 :
1416 6 : ZERO_STRUCT(cl);
1417 6 : cl.in.file.handle = hd;
1418 6 : req[1] = smb2_close_send(tree, &cl);
1419 6 : req[2] = smb2_close_send(tree, &cl);
1420 6 : req[3] = smb2_close_send(tree, &cl);
1421 6 : req[4] = smb2_close_send(tree, &cl);
1422 :
1423 6 : status = smb2_create_recv(req[0], tree, &cr);
1424 6 : CHECK_STATUS(status, NT_STATUS_OK);
1425 6 : status = smb2_close_recv(req[1], &cl);
1426 6 : CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
1427 6 : status = smb2_close_recv(req[2], &cl);
1428 6 : CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
1429 6 : status = smb2_close_recv(req[3], &cl);
1430 6 : CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
1431 6 : status = smb2_close_recv(req[4], &cl);
1432 6 : CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
1433 :
1434 6 : smb2_util_unlink(tree, fname);
1435 6 : done:
1436 6 : return ret;
1437 : }
1438 :
1439 6 : static bool test_compound_invalid1(struct torture_context *tctx,
1440 : struct smb2_tree *tree)
1441 : {
1442 : struct smb2_handle hd;
1443 : struct smb2_create cr;
1444 : NTSTATUS status;
1445 6 : const char *fname = "compound_invalid1.dat";
1446 : struct smb2_close cl;
1447 6 : bool ret = true;
1448 : struct smb2_request *req[3];
1449 :
1450 6 : smb2_transport_credits_ask_num(tree->session->transport, 3);
1451 :
1452 6 : smb2_util_unlink(tree, fname);
1453 :
1454 6 : smb2_transport_credits_ask_num(tree->session->transport, 1);
1455 :
1456 6 : ZERO_STRUCT(cr);
1457 6 : cr.in.security_flags = 0x00;
1458 6 : cr.in.oplock_level = 0;
1459 6 : cr.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
1460 6 : cr.in.create_flags = 0x00000000;
1461 6 : cr.in.reserved = 0x00000000;
1462 6 : cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
1463 6 : cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1464 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1465 : NTCREATEX_SHARE_ACCESS_WRITE |
1466 : NTCREATEX_SHARE_ACCESS_DELETE;
1467 6 : cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1468 6 : cr.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
1469 : NTCREATEX_OPTIONS_ASYNC_ALERT |
1470 : NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
1471 : 0x00200000;
1472 6 : cr.in.fname = fname;
1473 :
1474 6 : smb2_transport_compound_start(tree->session->transport, 3);
1475 :
1476 : /* passing the first request with the related flag is invalid */
1477 6 : smb2_transport_compound_set_related(tree->session->transport, true);
1478 :
1479 6 : req[0] = smb2_create_send(tree, &cr);
1480 :
1481 6 : hd.data[0] = UINT64_MAX;
1482 6 : hd.data[1] = UINT64_MAX;
1483 :
1484 6 : ZERO_STRUCT(cl);
1485 6 : cl.in.file.handle = hd;
1486 6 : req[1] = smb2_close_send(tree, &cl);
1487 :
1488 6 : smb2_transport_compound_set_related(tree->session->transport, false);
1489 6 : req[2] = smb2_close_send(tree, &cl);
1490 :
1491 6 : status = smb2_create_recv(req[0], tree, &cr);
1492 : /* TODO: check why this fails with --signing=required */
1493 6 : CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1494 6 : status = smb2_close_recv(req[1], &cl);
1495 6 : CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1496 6 : status = smb2_close_recv(req[2], &cl);
1497 6 : CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
1498 :
1499 6 : smb2_util_unlink(tree, fname);
1500 6 : done:
1501 6 : return ret;
1502 : }
1503 :
1504 6 : static bool test_compound_invalid2(struct torture_context *tctx,
1505 : struct smb2_tree *tree)
1506 : {
1507 : struct smb2_handle hd;
1508 : struct smb2_create cr;
1509 : NTSTATUS status;
1510 6 : const char *fname = "compound_invalid2.dat";
1511 : struct smb2_close cl;
1512 6 : bool ret = true;
1513 : struct smb2_request *req[5];
1514 6 : struct smbXcli_tcon *saved_tcon = tree->smbXcli;
1515 6 : struct smbXcli_session *saved_session = tree->session->smbXcli;
1516 :
1517 6 : smb2_transport_credits_ask_num(tree->session->transport, 5);
1518 :
1519 6 : smb2_util_unlink(tree, fname);
1520 :
1521 6 : smb2_transport_credits_ask_num(tree->session->transport, 1);
1522 :
1523 6 : ZERO_STRUCT(cr);
1524 6 : cr.in.security_flags = 0x00;
1525 6 : cr.in.oplock_level = 0;
1526 6 : cr.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
1527 6 : cr.in.create_flags = 0x00000000;
1528 6 : cr.in.reserved = 0x00000000;
1529 6 : cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
1530 6 : cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1531 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1532 : NTCREATEX_SHARE_ACCESS_WRITE |
1533 : NTCREATEX_SHARE_ACCESS_DELETE;
1534 6 : cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1535 6 : cr.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
1536 : NTCREATEX_OPTIONS_ASYNC_ALERT |
1537 : NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
1538 : 0x00200000;
1539 6 : cr.in.fname = fname;
1540 :
1541 6 : smb2_transport_compound_start(tree->session->transport, 5);
1542 :
1543 6 : req[0] = smb2_create_send(tree, &cr);
1544 :
1545 6 : hd.data[0] = UINT64_MAX;
1546 6 : hd.data[1] = UINT64_MAX;
1547 :
1548 6 : smb2_transport_compound_set_related(tree->session->transport, true);
1549 :
1550 6 : ZERO_STRUCT(cl);
1551 6 : cl.in.file.handle = hd;
1552 :
1553 6 : tree->smbXcli = smbXcli_tcon_create(tree);
1554 6 : smb2cli_tcon_set_values(tree->smbXcli,
1555 : NULL, /* session */
1556 : 0xFFFFFFFF, /* tcon_id */
1557 : 0, /* type */
1558 : 0, /* flags */
1559 : 0, /* capabilities */
1560 : 0 /* maximal_access */);
1561 :
1562 7 : tree->session->smbXcli = smbXcli_session_shallow_copy(tree->session,
1563 6 : tree->session->smbXcli);
1564 6 : smb2cli_session_set_id_and_flags(tree->session->smbXcli, UINT64_MAX, 0);
1565 :
1566 6 : req[1] = smb2_close_send(tree, &cl);
1567 : /* strange that this is not generating invalid parameter */
1568 6 : smb2_transport_compound_set_related(tree->session->transport, false);
1569 6 : req[2] = smb2_close_send(tree, &cl);
1570 6 : req[3] = smb2_close_send(tree, &cl);
1571 6 : smb2_transport_compound_set_related(tree->session->transport, true);
1572 6 : req[4] = smb2_close_send(tree, &cl);
1573 :
1574 6 : status = smb2_create_recv(req[0], tree, &cr);
1575 6 : CHECK_STATUS(status, NT_STATUS_OK);
1576 6 : status = smb2_close_recv(req[1], &cl);
1577 6 : CHECK_STATUS(status, NT_STATUS_OK);
1578 6 : status = smb2_close_recv(req[2], &cl);
1579 6 : CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
1580 6 : status = smb2_close_recv(req[3], &cl);
1581 6 : CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
1582 6 : status = smb2_close_recv(req[4], &cl);
1583 6 : CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1584 :
1585 6 : TALLOC_FREE(tree->smbXcli);
1586 6 : tree->smbXcli = saved_tcon;
1587 6 : TALLOC_FREE(tree->session->smbXcli);
1588 6 : tree->session->smbXcli = saved_session;
1589 :
1590 6 : smb2_util_unlink(tree, fname);
1591 6 : done:
1592 6 : return ret;
1593 : }
1594 :
1595 6 : static bool test_compound_invalid3(struct torture_context *tctx,
1596 : struct smb2_tree *tree)
1597 : {
1598 : struct smb2_handle hd;
1599 : struct smb2_create cr;
1600 : NTSTATUS status;
1601 6 : const char *fname = "compound_invalid3.dat";
1602 : struct smb2_close cl;
1603 6 : bool ret = true;
1604 : struct smb2_request *req[5];
1605 :
1606 6 : smb2_transport_credits_ask_num(tree->session->transport, 5);
1607 :
1608 6 : smb2_util_unlink(tree, fname);
1609 :
1610 6 : smb2_transport_credits_ask_num(tree->session->transport, 1);
1611 :
1612 6 : ZERO_STRUCT(cr);
1613 6 : cr.in.security_flags = 0x00;
1614 6 : cr.in.oplock_level = 0;
1615 6 : cr.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
1616 6 : cr.in.create_flags = 0x00000000;
1617 6 : cr.in.reserved = 0x00000000;
1618 6 : cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
1619 6 : cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1620 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1621 : NTCREATEX_SHARE_ACCESS_WRITE |
1622 : NTCREATEX_SHARE_ACCESS_DELETE;
1623 6 : cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1624 6 : cr.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
1625 : NTCREATEX_OPTIONS_ASYNC_ALERT |
1626 : NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
1627 : 0x00200000;
1628 6 : cr.in.fname = fname;
1629 :
1630 6 : smb2_transport_compound_start(tree->session->transport, 5);
1631 :
1632 6 : req[0] = smb2_create_send(tree, &cr);
1633 :
1634 6 : hd.data[0] = UINT64_MAX;
1635 6 : hd.data[1] = UINT64_MAX;
1636 :
1637 6 : ZERO_STRUCT(cl);
1638 6 : cl.in.file.handle = hd;
1639 6 : req[1] = smb2_close_send(tree, &cl);
1640 6 : req[2] = smb2_close_send(tree, &cl);
1641 : /* flipping the related flag is invalid */
1642 6 : smb2_transport_compound_set_related(tree->session->transport, true);
1643 6 : req[3] = smb2_close_send(tree, &cl);
1644 6 : req[4] = smb2_close_send(tree, &cl);
1645 :
1646 6 : status = smb2_create_recv(req[0], tree, &cr);
1647 6 : CHECK_STATUS(status, NT_STATUS_OK);
1648 6 : status = smb2_close_recv(req[1], &cl);
1649 6 : CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
1650 6 : status = smb2_close_recv(req[2], &cl);
1651 6 : CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
1652 6 : status = smb2_close_recv(req[3], &cl);
1653 6 : CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
1654 6 : status = smb2_close_recv(req[4], &cl);
1655 6 : CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
1656 :
1657 6 : smb2_util_unlink(tree, fname);
1658 6 : done:
1659 6 : return ret;
1660 : }
1661 :
1662 6 : static bool test_compound_invalid4(struct torture_context *tctx,
1663 : struct smb2_tree *tree)
1664 : {
1665 : struct smb2_create cr;
1666 : struct smb2_read rd;
1667 : NTSTATUS status;
1668 6 : const char *fname = "compound_invalid4.dat";
1669 : struct smb2_close cl;
1670 6 : bool ret = true;
1671 : bool ok;
1672 : struct smb2_request *req[2];
1673 :
1674 6 : smb2_transport_credits_ask_num(tree->session->transport, 2);
1675 :
1676 6 : smb2_util_unlink(tree, fname);
1677 :
1678 6 : ZERO_STRUCT(cr);
1679 6 : cr.in.security_flags = 0x00;
1680 6 : cr.in.oplock_level = 0;
1681 6 : cr.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
1682 6 : cr.in.create_flags = 0x00000000;
1683 6 : cr.in.reserved = 0x00000000;
1684 6 : cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
1685 6 : cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1686 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1687 : NTCREATEX_SHARE_ACCESS_WRITE |
1688 : NTCREATEX_SHARE_ACCESS_DELETE;
1689 6 : cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1690 6 : cr.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
1691 : NTCREATEX_OPTIONS_ASYNC_ALERT |
1692 : NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
1693 : 0x00200000;
1694 6 : cr.in.fname = fname;
1695 :
1696 6 : status = smb2_create(tree, tctx, &cr);
1697 6 : CHECK_STATUS(status, NT_STATUS_OK);
1698 :
1699 6 : smb2_transport_compound_start(tree->session->transport, 2);
1700 :
1701 6 : ZERO_STRUCT(rd);
1702 6 : rd.in.file.handle = cr.out.file.handle;
1703 6 : rd.in.length = 1;
1704 6 : rd.in.offset = 0;
1705 6 : req[0] = smb2_read_send(tree, &rd);
1706 :
1707 6 : smb2_transport_compound_set_related(tree->session->transport, true);
1708 :
1709 : /*
1710 : * Send a completely bogus request as second compound
1711 : * element. This triggers smbd_smb2_request_error() in in
1712 : * smbd_smb2_request_dispatch() before calling
1713 : * smbd_smb2_request_dispatch_update_counts().
1714 : */
1715 :
1716 6 : req[1] = smb2_request_init_tree(tree, 0xff, 0x04, false, 0);
1717 6 : smb2_transport_send(req[1]);
1718 :
1719 6 : status = smb2_read_recv(req[0], tctx, &rd);
1720 6 : CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
1721 :
1722 6 : ok = smb2_request_receive(req[1]);
1723 6 : torture_assert(tctx, ok, "Invalid request failed\n");
1724 6 : CHECK_STATUS(req[1]->status, NT_STATUS_INVALID_PARAMETER);
1725 :
1726 6 : ZERO_STRUCT(cl);
1727 6 : cl.in.file.handle = cr.out.file.handle;
1728 :
1729 6 : status = smb2_close(tree, &cl);
1730 6 : CHECK_STATUS(status, NT_STATUS_OK);
1731 :
1732 6 : smb2_util_unlink(tree, fname);
1733 6 : done:
1734 6 : return ret;
1735 : }
1736 :
1737 : /* Send a compound request where we expect the last request (Create, Notify)
1738 : * to go asynchronous. This works against a Win7 server and the reply is
1739 : * sent in two different packets. */
1740 6 : static bool test_compound_interim1(struct torture_context *tctx,
1741 : struct smb2_tree *tree)
1742 : {
1743 : struct smb2_handle hd;
1744 : struct smb2_create cr;
1745 6 : NTSTATUS status = NT_STATUS_OK;
1746 6 : const char *dname = "compound_interim_dir";
1747 : struct smb2_notify nt;
1748 6 : bool ret = true;
1749 : struct smb2_request *req[2];
1750 :
1751 : /* Win7 compound request implementation deviates substantially from the
1752 : * SMB2 spec as noted in MS-SMB2 <159>, <162>. This, test currently
1753 : * verifies the Windows behavior, not the general spec behavior. */
1754 :
1755 6 : smb2_transport_credits_ask_num(tree->session->transport, 5);
1756 :
1757 6 : smb2_deltree(tree, dname);
1758 :
1759 6 : smb2_transport_credits_ask_num(tree->session->transport, 1);
1760 :
1761 6 : ZERO_STRUCT(cr);
1762 6 : cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
1763 6 : cr.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1764 6 : cr.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1765 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1766 : NTCREATEX_SHARE_ACCESS_WRITE |
1767 : NTCREATEX_SHARE_ACCESS_DELETE;
1768 6 : cr.in.create_disposition = NTCREATEX_DISP_CREATE;
1769 6 : cr.in.fname = dname;
1770 :
1771 6 : smb2_transport_compound_start(tree->session->transport, 2);
1772 :
1773 6 : req[0] = smb2_create_send(tree, &cr);
1774 :
1775 6 : smb2_transport_compound_set_related(tree->session->transport, true);
1776 :
1777 6 : hd.data[0] = UINT64_MAX;
1778 6 : hd.data[1] = UINT64_MAX;
1779 :
1780 6 : ZERO_STRUCT(nt);
1781 6 : nt.in.recursive = true;
1782 6 : nt.in.buffer_size = 0x1000;
1783 6 : nt.in.file.handle = hd;
1784 6 : nt.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
1785 6 : nt.in.unknown = 0x00000000;
1786 :
1787 6 : req[1] = smb2_notify_send(tree, &nt);
1788 :
1789 6 : status = smb2_create_recv(req[0], tree, &cr);
1790 6 : CHECK_STATUS(status, NT_STATUS_OK);
1791 :
1792 6 : smb2_cancel(req[1]);
1793 6 : status = smb2_notify_recv(req[1], tree, &nt);
1794 6 : CHECK_STATUS(status, NT_STATUS_CANCELLED);
1795 :
1796 6 : smb2_util_close(tree, cr.out.file.handle);
1797 :
1798 6 : smb2_deltree(tree, dname);
1799 6 : done:
1800 6 : return ret;
1801 : }
1802 :
1803 : /* Send a compound request where we expect the middle request (Create, Notify,
1804 : * GetInfo) to go asynchronous. Against Win7 the sync request succeed while
1805 : * the async fails. All are returned in the same compound response. */
1806 6 : static bool test_compound_interim2(struct torture_context *tctx,
1807 : struct smb2_tree *tree)
1808 : {
1809 : struct smb2_handle hd;
1810 : struct smb2_create cr;
1811 6 : NTSTATUS status = NT_STATUS_OK;
1812 6 : const char *dname = "compound_interim_dir";
1813 : struct smb2_getinfo gf;
1814 : struct smb2_notify nt;
1815 6 : bool ret = true;
1816 : struct smb2_request *req[3];
1817 :
1818 : /* Win7 compound request implementation deviates substantially from the
1819 : * SMB2 spec as noted in MS-SMB2 <159>, <162>. This, test currently
1820 : * verifies the Windows behavior, not the general spec behavior. */
1821 :
1822 6 : smb2_transport_credits_ask_num(tree->session->transport, 5);
1823 :
1824 6 : smb2_deltree(tree, dname);
1825 :
1826 6 : smb2_transport_credits_ask_num(tree->session->transport, 1);
1827 :
1828 6 : ZERO_STRUCT(cr);
1829 6 : cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
1830 6 : cr.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1831 6 : cr.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1832 6 : cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1833 : NTCREATEX_SHARE_ACCESS_WRITE |
1834 : NTCREATEX_SHARE_ACCESS_DELETE;
1835 6 : cr.in.create_disposition = NTCREATEX_DISP_CREATE;
1836 6 : cr.in.fname = dname;
1837 :
1838 6 : smb2_transport_compound_start(tree->session->transport, 3);
1839 :
1840 6 : req[0] = smb2_create_send(tree, &cr);
1841 :
1842 6 : smb2_transport_compound_set_related(tree->session->transport, true);
1843 :
1844 6 : hd.data[0] = UINT64_MAX;
1845 6 : hd.data[1] = UINT64_MAX;
1846 :
1847 6 : ZERO_STRUCT(nt);
1848 6 : nt.in.recursive = true;
1849 6 : nt.in.buffer_size = 0x1000;
1850 6 : nt.in.file.handle = hd;
1851 6 : nt.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
1852 6 : nt.in.unknown = 0x00000000;
1853 :
1854 6 : req[1] = smb2_notify_send(tree, &nt);
1855 :
1856 6 : ZERO_STRUCT(gf);
1857 6 : gf.in.file.handle = hd;
1858 6 : gf.in.info_type = SMB2_0_INFO_FILE;
1859 6 : gf.in.info_class = 0x04; /* FILE_BASIC_INFORMATION */
1860 6 : gf.in.output_buffer_length = 0x1000;
1861 6 : gf.in.input_buffer = data_blob_null;
1862 :
1863 6 : req[2] = smb2_getinfo_send(tree, &gf);
1864 :
1865 6 : status = smb2_create_recv(req[0], tree, &cr);
1866 6 : CHECK_STATUS(status, NT_STATUS_OK);
1867 :
1868 6 : status = smb2_notify_recv(req[1], tree, &nt);
1869 6 : CHECK_STATUS(status, NT_STATUS_INTERNAL_ERROR);
1870 :
1871 0 : status = smb2_getinfo_recv(req[2], tree, &gf);
1872 0 : CHECK_STATUS(status, NT_STATUS_OK);
1873 :
1874 0 : smb2_util_close(tree, cr.out.file.handle);
1875 :
1876 0 : smb2_deltree(tree, dname);
1877 6 : done:
1878 6 : return ret;
1879 : }
1880 :
1881 : /* Test compound related finds */
1882 12 : static bool test_compound_find_related(struct torture_context *tctx,
1883 : struct smb2_tree *tree)
1884 : {
1885 12 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
1886 12 : const char *dname = "compound_find_dir";
1887 : struct smb2_create create;
1888 : struct smb2_find f;
1889 : struct smb2_handle h;
1890 : struct smb2_request *req[2];
1891 : NTSTATUS status;
1892 12 : bool ret = true;
1893 :
1894 12 : smb2_deltree(tree, dname);
1895 :
1896 12 : ZERO_STRUCT(create);
1897 12 : create.in.desired_access = SEC_RIGHTS_DIR_ALL;
1898 12 : create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1899 12 : create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1900 12 : create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1901 : NTCREATEX_SHARE_ACCESS_WRITE |
1902 : NTCREATEX_SHARE_ACCESS_DELETE;
1903 12 : create.in.create_disposition = NTCREATEX_DISP_CREATE;
1904 12 : create.in.fname = dname;
1905 :
1906 12 : status = smb2_create(tree, mem_ctx, &create);
1907 12 : h = create.out.file.handle;
1908 :
1909 12 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed\n");
1910 :
1911 12 : smb2_transport_compound_start(tree->session->transport, 2);
1912 :
1913 12 : ZERO_STRUCT(f);
1914 12 : f.in.file.handle = h;
1915 12 : f.in.pattern = "*";
1916 12 : f.in.max_response_size = 0x100;
1917 12 : f.in.level = SMB2_FIND_BOTH_DIRECTORY_INFO;
1918 :
1919 12 : req[0] = smb2_find_send(tree, &f);
1920 :
1921 12 : smb2_transport_compound_set_related(tree->session->transport, true);
1922 :
1923 12 : req[1] = smb2_find_send(tree, &f);
1924 :
1925 12 : status = smb2_find_recv(req[0], mem_ctx, &f);
1926 12 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_find_recv failed\n");
1927 :
1928 12 : status = smb2_find_recv(req[1], mem_ctx, &f);
1929 12 : torture_assert_ntstatus_equal_goto(tctx, status, STATUS_NO_MORE_FILES, ret, done, "smb2_find_recv failed\n");
1930 :
1931 12 : done:
1932 12 : smb2_util_close(tree, h);
1933 12 : smb2_deltree(tree, dname);
1934 12 : TALLOC_FREE(mem_ctx);
1935 12 : return ret;
1936 : }
1937 :
1938 : /* Test compound related finds */
1939 12 : static bool test_compound_find_close(struct torture_context *tctx,
1940 : struct smb2_tree *tree)
1941 : {
1942 12 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
1943 12 : const char *dname = "compound_find_dir";
1944 : struct smb2_create create;
1945 : struct smb2_find f;
1946 : struct smb2_handle h;
1947 12 : struct smb2_request *req = NULL;
1948 12 : const int num_files = 5000;
1949 : int i;
1950 : NTSTATUS status;
1951 12 : bool ret = true;
1952 :
1953 12 : smb2_deltree(tree, dname);
1954 :
1955 12 : ZERO_STRUCT(create);
1956 12 : create.in.desired_access = SEC_RIGHTS_DIR_ALL;
1957 12 : create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1958 12 : create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1959 12 : create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1960 : NTCREATEX_SHARE_ACCESS_WRITE |
1961 : NTCREATEX_SHARE_ACCESS_DELETE;
1962 12 : create.in.create_disposition = NTCREATEX_DISP_CREATE;
1963 12 : create.in.fname = dname;
1964 :
1965 12 : smb2cli_conn_set_max_credits(tree->session->transport->conn, 256);
1966 :
1967 12 : status = smb2_create(tree, mem_ctx, &create);
1968 12 : h = create.out.file.handle;
1969 :
1970 12 : ZERO_STRUCT(create);
1971 12 : create.in.desired_access = SEC_RIGHTS_FILE_ALL;
1972 12 : create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1973 12 : create.in.create_disposition = NTCREATEX_DISP_CREATE;
1974 :
1975 60012 : for (i = 0; i < num_files; i++) {
1976 60000 : create.in.fname = talloc_asprintf(mem_ctx, "%s\\file%d",
1977 : dname, i);
1978 60000 : status = smb2_create(tree, mem_ctx, &create);
1979 60000 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "");
1980 60000 : smb2_util_close(tree, create.out.file.handle);
1981 : }
1982 :
1983 12 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed\n");
1984 :
1985 12 : ZERO_STRUCT(f);
1986 12 : f.in.file.handle = h;
1987 12 : f.in.pattern = "*";
1988 12 : f.in.max_response_size = 8*1024*1024;
1989 12 : f.in.level = SMB2_FIND_BOTH_DIRECTORY_INFO;
1990 :
1991 12 : req = smb2_find_send(tree, &f);
1992 :
1993 12 : status = smb2_util_close(tree, h);
1994 12 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close failed\n");
1995 :
1996 12 : status = smb2_find_recv(req, mem_ctx, &f);
1997 12 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_find_recv failed\n");
1998 :
1999 12 : done:
2000 12 : smb2_util_close(tree, h);
2001 12 : smb2_deltree(tree, dname);
2002 12 : TALLOC_FREE(mem_ctx);
2003 12 : return ret;
2004 : }
2005 :
2006 : /* Test compound unrelated finds */
2007 12 : static bool test_compound_find_unrelated(struct torture_context *tctx,
2008 : struct smb2_tree *tree)
2009 : {
2010 12 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
2011 12 : const char *dname = "compound_find_dir";
2012 : struct smb2_create create;
2013 : struct smb2_find f;
2014 : struct smb2_handle h;
2015 : struct smb2_request *req[2];
2016 : NTSTATUS status;
2017 12 : bool ret = true;
2018 :
2019 12 : smb2_deltree(tree, dname);
2020 :
2021 12 : ZERO_STRUCT(create);
2022 12 : create.in.desired_access = SEC_RIGHTS_DIR_ALL;
2023 12 : create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2024 12 : create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2025 12 : create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2026 : NTCREATEX_SHARE_ACCESS_WRITE |
2027 : NTCREATEX_SHARE_ACCESS_DELETE;
2028 12 : create.in.create_disposition = NTCREATEX_DISP_CREATE;
2029 12 : create.in.fname = dname;
2030 :
2031 12 : status = smb2_create(tree, mem_ctx, &create);
2032 12 : h = create.out.file.handle;
2033 :
2034 12 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed\n");
2035 :
2036 12 : smb2_transport_compound_start(tree->session->transport, 2);
2037 :
2038 12 : ZERO_STRUCT(f);
2039 12 : f.in.file.handle = h;
2040 12 : f.in.pattern = "*";
2041 12 : f.in.max_response_size = 0x100;
2042 12 : f.in.level = SMB2_FIND_BOTH_DIRECTORY_INFO;
2043 :
2044 12 : req[0] = smb2_find_send(tree, &f);
2045 12 : req[1] = smb2_find_send(tree, &f);
2046 :
2047 12 : status = smb2_find_recv(req[0], mem_ctx, &f);
2048 12 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_find_recv failed\n");
2049 :
2050 12 : status = smb2_find_recv(req[1], mem_ctx, &f);
2051 12 : torture_assert_ntstatus_equal_goto(tctx, status, STATUS_NO_MORE_FILES, ret, done, "smb2_find_recv failed\n");
2052 :
2053 12 : done:
2054 12 : smb2_util_close(tree, h);
2055 12 : smb2_deltree(tree, dname);
2056 12 : TALLOC_FREE(mem_ctx);
2057 12 : return ret;
2058 : }
2059 :
2060 2355 : struct torture_suite *torture_smb2_compound_init(TALLOC_CTX *ctx)
2061 : {
2062 2355 : struct torture_suite *suite = torture_suite_create(ctx, "compound");
2063 :
2064 2355 : torture_suite_add_1smb2_test(suite, "related1", test_compound_related1);
2065 2355 : torture_suite_add_1smb2_test(suite, "related2", test_compound_related2);
2066 2355 : torture_suite_add_1smb2_test(suite, "related3",
2067 : test_compound_related3);
2068 2355 : torture_suite_add_1smb2_test(suite, "related4",
2069 : test_compound_related4);
2070 2355 : torture_suite_add_1smb2_test(suite, "related5",
2071 : test_compound_related5);
2072 2355 : torture_suite_add_1smb2_test(suite, "related6",
2073 : test_compound_related6);
2074 2355 : torture_suite_add_1smb2_test(suite, "related7",
2075 : test_compound_related7);
2076 2355 : torture_suite_add_1smb2_test(suite, "related8",
2077 : test_compound_related8);
2078 2355 : torture_suite_add_1smb2_test(suite, "related9",
2079 : test_compound_related9);
2080 2355 : torture_suite_add_1smb2_test(suite, "unrelated1", test_compound_unrelated1);
2081 2355 : torture_suite_add_1smb2_test(suite, "invalid1", test_compound_invalid1);
2082 2355 : torture_suite_add_1smb2_test(suite, "invalid2", test_compound_invalid2);
2083 2355 : torture_suite_add_1smb2_test(suite, "invalid3", test_compound_invalid3);
2084 2355 : torture_suite_add_1smb2_test(
2085 : suite, "invalid4", test_compound_invalid4);
2086 2355 : torture_suite_add_1smb2_test(suite, "interim1", test_compound_interim1);
2087 2355 : torture_suite_add_1smb2_test(suite, "interim2", test_compound_interim2);
2088 2355 : torture_suite_add_1smb2_test(suite, "compound-break", test_compound_break);
2089 2355 : torture_suite_add_1smb2_test(suite, "compound-padding", test_compound_padding);
2090 2355 : torture_suite_add_1smb2_test(suite, "create-write-close",
2091 : test_compound_create_write_close);
2092 :
2093 2355 : suite->description = talloc_strdup(suite, "SMB2-COMPOUND tests");
2094 :
2095 2355 : return suite;
2096 : }
2097 :
2098 2355 : struct torture_suite *torture_smb2_compound_find_init(TALLOC_CTX *ctx)
2099 : {
2100 2355 : struct torture_suite *suite = torture_suite_create(ctx, "compound_find");
2101 :
2102 2355 : torture_suite_add_1smb2_test(suite, "compound_find_related", test_compound_find_related);
2103 2355 : torture_suite_add_1smb2_test(suite, "compound_find_unrelated", test_compound_find_unrelated);
2104 2355 : torture_suite_add_1smb2_test(suite, "compound_find_close", test_compound_find_close);
2105 :
2106 2355 : suite->description = talloc_strdup(suite, "SMB2-COMPOUND-FIND tests");
2107 :
2108 2355 : return suite;
2109 : }
|