s4:torture:smb2: remove an unused variable from the oplock-exclusive1 test
[Samba/gebeck_regimport.git] / source4 / torture / smb2 / oplock.c
blob7e0ea7d2e04184784000b613aac53b537ca691a7
1 /*
2 Unix SMB/CIFS implementation.
4 test suite for SMB2 oplocks
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Stefan Metzmacher 2008
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
25 #include "libcli/smb2/smb2.h"
26 #include "libcli/smb2/smb2_calls.h"
27 #include "libcli/smb_composite/smb_composite.h"
28 #include "libcli/resolve/resolve.h"
30 #include "lib/cmdline/popt_common.h"
31 #include "lib/events/events.h"
33 #include "param/param.h"
34 #include "system/filesys.h"
36 #include "torture/torture.h"
37 #include "torture/smb2/proto.h"
39 #define CHECK_RANGE(v, min, max) do { \
40 if ((v) < (min) || (v) > (max)) { \
41 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s " \
42 "got %d - should be between %d and %d\n", \
43 __location__, #v, (int)v, (int)min, (int)max); \
44 ret = false; \
45 }} while (0)
47 #define CHECK_STRMATCH(v, correct) do { \
48 if (!v || strstr((v),(correct)) == NULL) { \
49 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s "\
50 "got '%s' - should be '%s'\n", \
51 __location__, #v, v?v:"NULL", correct); \
52 ret = false; \
53 }} while (0)
55 #define CHECK_VAL(v, correct) do { \
56 if ((v) != (correct)) { \
57 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s " \
58 "got 0x%x - should be 0x%x\n", \
59 __location__, #v, (int)v, (int)correct); \
60 ret = false; \
61 }} while (0)
63 #define BASEDIR "oplock_test"
65 static struct {
66 struct smb2_handle handle;
67 uint8_t level;
68 struct smb2_break br;
69 int count;
70 int failures;
71 NTSTATUS failure_status;
72 } break_info;
74 static void torture_oplock_break_callback(struct smb2_request *req)
76 NTSTATUS status;
77 struct smb2_break br;
79 ZERO_STRUCT(br);
80 status = smb2_break_recv(req, &break_info.br);
81 if (!NT_STATUS_IS_OK(status)) {
82 break_info.failures++;
83 break_info.failure_status = status;
86 return;
89 /* A general oplock break notification handler. This should be used when a
90 * test expects to break from batch or exclusive to a lower level. */
91 static bool torture_oplock_handler(struct smb2_transport *transport,
92 const struct smb2_handle *handle,
93 uint8_t level,
94 void *private_data)
96 struct smb2_tree *tree = private_data;
97 const char *name;
98 struct smb2_request *req;
99 ZERO_STRUCT(break_info.br);
101 break_info.handle = *handle;
102 break_info.level = level;
103 break_info.count++;
105 switch (level) {
106 case SMB2_OPLOCK_LEVEL_II:
107 name = "level II";
108 break;
109 case SMB2_OPLOCK_LEVEL_NONE:
110 name = "none";
111 break;
112 default:
113 name = "unknown";
114 break_info.failures++;
116 printf("Acking to %s [0x%02X] in oplock handler\n", name, level);
118 break_info.br.in.file.handle = *handle;
119 break_info.br.in.oplock_level = level;
120 break_info.br.in.reserved = 0;
121 break_info.br.in.reserved2 = 0;
123 req = smb2_break_send(tree, &break_info.br);
124 req->async.fn = torture_oplock_break_callback;
125 req->async.private_data = NULL;
126 return true;
130 A handler function for oplock break notifications. Send a break to none
131 request.
133 static bool torture_oplock_handler_ack_to_none(struct smb2_transport *transport,
134 const struct smb2_handle *handle,
135 uint8_t level,
136 void *private_data)
138 struct smb2_tree *tree = private_data;
139 struct smb2_request *req;
141 break_info.handle = *handle;
142 break_info.level = level;
143 break_info.count++;
145 printf("Acking to none in oplock handler\n");
147 ZERO_STRUCT(break_info.br);
148 break_info.br.in.file.handle = *handle;
149 break_info.br.in.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
150 break_info.br.in.reserved = 0;
151 break_info.br.in.reserved2 = 0;
153 req = smb2_break_send(tree, &break_info.br);
154 req->async.fn = torture_oplock_break_callback;
155 req->async.private_data = NULL;
157 return true;
161 A handler function for oplock break notifications. Break from level II to
162 none. SMB2 requires that the client does not send an oplock break request to
163 the server in this case.
165 static bool torture_oplock_handler_level2_to_none(
166 struct smb2_transport *transport,
167 const struct smb2_handle *handle,
168 uint8_t level,
169 void *private_data)
171 break_info.handle = *handle;
172 break_info.level = level;
173 break_info.count++;
175 printf("Break from level II to none in oplock handler\n");
177 return true;
180 /* A handler function for oplock break notifications. This should be used when
181 * test expects two break notifications, first to level II, then to none. */
182 static bool torture_oplock_handler_two_notifications(
183 struct smb2_transport *transport,
184 const struct smb2_handle *handle,
185 uint8_t level,
186 void *private_data)
188 struct smb2_tree *tree = private_data;
189 const char *name;
190 struct smb2_request *req;
191 ZERO_STRUCT(break_info.br);
193 break_info.handle = *handle;
194 break_info.level = level;
195 break_info.count++;
197 switch (level) {
198 case SMB2_OPLOCK_LEVEL_II:
199 name = "level II";
200 break;
201 case SMB2_OPLOCK_LEVEL_NONE:
202 name = "none";
203 break;
204 default:
205 name = "unknown";
206 break_info.failures++;
208 printf("Breaking to %s [0x%02X] in oplock handler\n", name, level);
210 if (level == SMB2_OPLOCK_LEVEL_NONE)
211 return true;
213 break_info.br.in.file.handle = *handle;
214 break_info.br.in.oplock_level = level;
215 break_info.br.in.reserved = 0;
216 break_info.br.in.reserved2 = 0;
218 req = smb2_break_send(tree, &break_info.br);
219 req->async.fn = torture_oplock_break_callback;
220 req->async.private_data = NULL;
221 return true;
223 static void torture_oplock_handler_close_recv(struct smb2_request *req)
225 if (!smb2_request_receive(req)) {
226 printf("close failed in oplock_handler_close\n");
227 break_info.failures++;
232 a handler function for oplock break requests - close the file
234 static bool torture_oplock_handler_close(struct smb2_transport *transport,
235 const struct smb2_handle *handle,
236 uint8_t level,
237 void *private_data)
239 struct smb2_close io;
240 struct smb2_tree *tree = private_data;
241 struct smb2_request *req;
243 break_info.handle = *handle;
244 break_info.level = level;
245 break_info.count++;
247 ZERO_STRUCT(io);
248 io.in.file.handle = *handle;
249 io.in.flags = RAW_CLOSE_SMB2;
250 req = smb2_close_send(tree, &io);
251 if (req == NULL) {
252 printf("failed to send close in oplock_handler_close\n");
253 return false;
256 req->async.fn = torture_oplock_handler_close_recv;
257 req->async.private_data = NULL;
259 return true;
263 a handler function for oplock break requests. Let it timeout
265 static bool torture_oplock_handler_timeout(struct smb2_transport *transport,
266 const struct smb2_handle *handle,
267 uint8_t level,
268 void *private_data)
270 break_info.handle = *handle;
271 break_info.level = level;
272 break_info.count++;
274 printf("Let oplock break timeout\n");
275 return true;
278 static bool open_smb2_connection_no_level2_oplocks(struct torture_context *tctx,
279 struct smb2_tree **tree)
281 NTSTATUS status;
282 const char *host = torture_setting_string(tctx, "host", NULL);
283 const char *share = torture_setting_string(tctx, "share", NULL);
284 struct cli_credentials *credentials = cmdline_credentials;
285 struct smbcli_options options;
287 lpcfg_smbcli_options(tctx->lp_ctx, &options);
288 options.use_level2_oplocks = false;
290 status = smb2_connect(tctx, host,
291 lpcfg_smb_ports(tctx->lp_ctx), share,
292 lpcfg_resolve_context(tctx->lp_ctx),
293 credentials, tree, tctx->ev, &options,
294 lpcfg_socket_options(tctx->lp_ctx),
295 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
296 if (!NT_STATUS_IS_OK(status)) {
297 torture_comment(tctx, "Failed to connect to SMB2 share "
298 "\\\\%s\\%s - %s\n", host, share,
299 nt_errstr(status));
300 return false;
302 return true;
306 Timer handler function notifies the registering function that time is up
308 static void timeout_cb(struct tevent_context *ev,
309 struct tevent_timer *te,
310 struct timeval current_time,
311 void *private_data)
313 bool *timesup = (bool *)private_data;
314 *timesup = true;
315 return;
319 Wait a short period of time to receive a single oplock break request
321 static void torture_wait_for_oplock_break(struct torture_context *tctx)
323 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
324 struct tevent_timer *te = NULL;
325 struct timeval ne;
326 bool timesup = false;
327 int old_count = break_info.count;
329 /* Wait .1 seconds for an oplock break */
330 ne = tevent_timeval_current_ofs(0, 100000);
332 if ((te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, &timesup))
333 == NULL)
335 torture_comment(tctx, "Failed to wait for an oplock break. "
336 "test results may not be accurate.");
337 goto done;
340 while (!timesup && break_info.count < old_count + 1) {
341 if (tevent_loop_once(tctx->ev) != 0) {
342 torture_comment(tctx, "Failed to wait for an oplock "
343 "break. test results may not be "
344 "accurate.");
345 goto done;
349 done:
350 /* We don't know if the timed event fired and was freed, we received
351 * our oplock break, or some other event triggered the loop. Thus,
352 * we create a tmp_ctx to be able to safely free/remove the timed
353 * event in all 3 cases. */
354 talloc_free(tmp_ctx);
356 return;
359 static bool test_smb2_oplock_exclusive1(struct torture_context *tctx,
360 struct smb2_tree *tree1,
361 struct smb2_tree *tree2)
363 const char *fname = BASEDIR "\\test_exclusive1.dat";
364 NTSTATUS status;
365 bool ret = true;
366 union smb_open io;
367 struct smb2_handle h1;
368 struct smb2_handle h;
370 status = torture_smb2_testdir(tree1, BASEDIR, &h);
371 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
373 /* cleanup */
374 smb2_util_unlink(tree1, fname);
376 tree1->session->transport->oplock.handler = torture_oplock_handler;
377 tree1->session->transport->oplock.private_data = tree1;
380 base ntcreatex parms
382 ZERO_STRUCT(io.smb2);
383 io.generic.level = RAW_OPEN_SMB2;
384 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
385 io.smb2.in.alloc_size = 0;
386 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
387 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
388 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
389 io.smb2.in.create_options = 0;
390 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
391 io.smb2.in.security_flags = 0;
392 io.smb2.in.fname = fname;
394 torture_comment(tctx, "EXCLUSIVE1: open a file with an exclusive "
395 "oplock (share mode: none)\n");
396 ZERO_STRUCT(break_info);
397 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
399 status = smb2_create(tree1, tctx, &(io.smb2));
400 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
401 h1 = io.smb2.out.file.handle;
402 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
404 torture_comment(tctx, "a 2nd open should not cause a break\n");
405 status = smb2_create(tree2, tctx, &(io.smb2));
406 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
407 "Incorrect status");
408 torture_wait_for_oplock_break(tctx);
409 CHECK_VAL(break_info.count, 0);
410 CHECK_VAL(break_info.failures, 0);
412 torture_comment(tctx, "unlink it - should also be no break\n");
413 status = smb2_util_unlink(tree2, fname);
414 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
415 "Incorrect status");
416 torture_wait_for_oplock_break(tctx);
417 CHECK_VAL(break_info.count, 0);
418 CHECK_VAL(break_info.failures, 0);
420 smb2_util_close(tree1, h1);
421 smb2_util_close(tree1, h);
423 smb2_deltree(tree1, BASEDIR);
424 return ret;
427 static bool test_smb2_oplock_exclusive2(struct torture_context *tctx,
428 struct smb2_tree *tree1,
429 struct smb2_tree *tree2)
431 const char *fname = BASEDIR "\\test_exclusive2.dat";
432 NTSTATUS status;
433 bool ret = true;
434 union smb_open io;
435 union smb_unlink unl;
436 struct smb2_handle h, h1, h2;
438 status = torture_smb2_testdir(tree1, BASEDIR, &h);
439 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
441 /* cleanup */
442 smb2_util_unlink(tree1, fname);
444 tree1->session->transport->oplock.handler = torture_oplock_handler;
445 tree1->session->transport->oplock.private_data = tree1;
448 base ntcreatex parms
450 ZERO_STRUCT(io.smb2);
451 io.generic.level = RAW_OPEN_SMB2;
452 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
453 io.smb2.in.alloc_size = 0;
454 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
455 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
456 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
457 io.smb2.in.create_options = 0;
458 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
459 io.smb2.in.security_flags = 0;
460 io.smb2.in.fname = fname;
462 torture_comment(tctx, "EXCLUSIVE2: open a file with an exclusive "
463 "oplock (share mode: all)\n");
464 ZERO_STRUCT(break_info);
465 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
466 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
467 NTCREATEX_SHARE_ACCESS_WRITE|
468 NTCREATEX_SHARE_ACCESS_DELETE;
469 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
471 status = smb2_create(tree1, tctx, &(io.smb2));
472 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
473 h1 = io.smb2.out.file.handle;
474 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
476 torture_comment(tctx, "a 2nd open should cause a break to level 2\n");
477 status = smb2_create(tree2, tctx, &(io.smb2));
478 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
479 h2 = io.smb2.out.file.handle;
480 torture_wait_for_oplock_break(tctx);
481 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
482 CHECK_VAL(break_info.count, 1);
483 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
484 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
485 CHECK_VAL(break_info.failures, 0);
486 ZERO_STRUCT(break_info);
488 /* now we have 2 level II oplocks... */
489 torture_comment(tctx, "try to unlink it - should cause a break\n");
490 unl.unlink.in.pattern = fname;
491 unl.unlink.in.attrib = 0;
492 status = smb2_util_unlink(tree2, fname);
493 torture_assert_ntstatus_ok(tctx, status, "Error unlinking the file");
494 torture_wait_for_oplock_break(tctx);
495 CHECK_VAL(break_info.count, 0);
496 CHECK_VAL(break_info.failures, 0);
498 torture_comment(tctx, "close both handles\n");
499 smb2_util_close(tree1, h1);
500 smb2_util_close(tree1, h2);
501 smb2_util_close(tree1, h);
503 smb2_deltree(tree1, BASEDIR);
504 return ret;
507 static bool test_smb2_oplock_exclusive3(struct torture_context *tctx,
508 struct smb2_tree *tree1,
509 struct smb2_tree *tree2)
511 const char *fname = BASEDIR "\\test_exclusive3.dat";
512 NTSTATUS status;
513 bool ret = true;
514 union smb_open io;
515 union smb_setfileinfo sfi;
516 struct smb2_handle h, h1;
518 status = torture_smb2_testdir(tree1, BASEDIR, &h);
519 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
521 /* cleanup */
522 smb2_util_unlink(tree1, fname);
524 tree1->session->transport->oplock.handler = torture_oplock_handler;
525 tree1->session->transport->oplock.private_data = tree1;
528 base ntcreatex parms
530 ZERO_STRUCT(io.smb2);
531 io.generic.level = RAW_OPEN_SMB2;
532 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
533 io.smb2.in.alloc_size = 0;
534 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
535 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
536 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
537 io.smb2.in.create_options = 0;
538 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
539 io.smb2.in.security_flags = 0;
540 io.smb2.in.fname = fname;
542 torture_comment(tctx, "EXCLUSIVE3: open a file with an exclusive "
543 "oplock (share mode: none)\n");
545 ZERO_STRUCT(break_info);
546 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
547 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
549 status = smb2_create(tree1, tctx, &(io.smb2));
550 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
551 h1 = io.smb2.out.file.handle;
552 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
554 torture_comment(tctx, "setpathinfo EOF should trigger a break to "
555 "none\n");
556 ZERO_STRUCT(sfi);
557 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
558 sfi.generic.in.file.path = fname;
559 sfi.end_of_file_info.in.size = 100;
561 status = smb2_composite_setpathinfo(tree2, &sfi);
563 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
564 "Incorrect status");
565 torture_wait_for_oplock_break(tctx);
566 CHECK_VAL(break_info.count, 0);
567 CHECK_VAL(break_info.failures, 0);
568 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
570 smb2_util_close(tree1, h1);
571 smb2_util_close(tree1, h);
573 smb2_deltree(tree1, BASEDIR);
574 return ret;
577 static bool test_smb2_oplock_exclusive4(struct torture_context *tctx,
578 struct smb2_tree *tree1,
579 struct smb2_tree *tree2)
581 const char *fname = BASEDIR "\\test_exclusive4.dat";
582 NTSTATUS status;
583 bool ret = true;
584 union smb_open io;
585 struct smb2_handle h, h1, h2;
587 status = torture_smb2_testdir(tree1, BASEDIR, &h);
588 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
590 /* cleanup */
591 smb2_util_unlink(tree1, fname);
593 tree1->session->transport->oplock.handler = torture_oplock_handler;
594 tree1->session->transport->oplock.private_data = tree1;
597 base ntcreatex parms
599 ZERO_STRUCT(io.smb2);
600 io.generic.level = RAW_OPEN_SMB2;
601 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
602 io.smb2.in.alloc_size = 0;
603 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
604 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
605 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
606 io.smb2.in.create_options = 0;
607 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
608 io.smb2.in.security_flags = 0;
609 io.smb2.in.fname = fname;
611 torture_comment(tctx, "EXCLUSIVE4: open with exclusive oplock\n");
612 ZERO_STRUCT(break_info);
614 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
615 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
616 status = smb2_create(tree1, tctx, &(io.smb2));
617 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
618 h1 = io.smb2.out.file.handle;
619 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
621 ZERO_STRUCT(break_info);
622 torture_comment(tctx, "second open with attributes only shouldn't "
623 "cause oplock break\n");
625 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
626 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
627 SEC_FILE_WRITE_ATTRIBUTE |
628 SEC_STD_SYNCHRONIZE;
629 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
630 status = smb2_create(tree2, tctx, &(io.smb2));
631 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
632 h2 = io.smb2.out.file.handle;
633 CHECK_VAL(io.smb2.out.oplock_level, NO_OPLOCK_RETURN);
634 torture_wait_for_oplock_break(tctx);
635 CHECK_VAL(break_info.count, 0);
636 CHECK_VAL(break_info.failures, 0);
638 smb2_util_close(tree1, h1);
639 smb2_util_close(tree2, h2);
640 smb2_util_close(tree1, h);
642 smb2_deltree(tree1, BASEDIR);
643 return ret;
646 static bool test_smb2_oplock_exclusive5(struct torture_context *tctx,
647 struct smb2_tree *tree1,
648 struct smb2_tree *tree2)
650 const char *fname = BASEDIR "\\test_exclusive5.dat";
651 NTSTATUS status;
652 bool ret = true;
653 union smb_open io;
654 struct smb2_handle h, h1, h2;
656 status = torture_smb2_testdir(tree1, BASEDIR, &h);
657 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
659 /* cleanup */
660 smb2_util_unlink(tree1, fname);
662 tree1->session->transport->oplock.handler = torture_oplock_handler;
663 tree1->session->transport->oplock.private_data = tree1;
665 tree2->session->transport->oplock.handler = torture_oplock_handler;
666 tree2->session->transport->oplock.private_data = tree2;
669 base ntcreatex parms
671 ZERO_STRUCT(io.smb2);
672 io.generic.level = RAW_OPEN_SMB2;
673 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
674 io.smb2.in.alloc_size = 0;
675 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
676 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
677 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
678 io.smb2.in.create_options = 0;
679 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
680 io.smb2.in.security_flags = 0;
681 io.smb2.in.fname = fname;
683 torture_comment(tctx, "EXCLUSIVE5: open with exclusive oplock\n");
684 ZERO_STRUCT(break_info);
686 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
687 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
688 NTCREATEX_SHARE_ACCESS_WRITE|
689 NTCREATEX_SHARE_ACCESS_DELETE;
690 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
691 status = smb2_create(tree1, tctx, &(io.smb2));
692 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
693 h1 = io.smb2.out.file.handle;
694 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
696 ZERO_STRUCT(break_info);
698 torture_comment(tctx, "second open with attributes only and "
699 "NTCREATEX_DISP_OVERWRITE_IF dispostion causes "
700 "oplock break\n");
702 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
703 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
704 SEC_FILE_WRITE_ATTRIBUTE |
705 SEC_STD_SYNCHRONIZE;
706 io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
707 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
708 status = smb2_create(tree2, tctx, &(io.smb2));
709 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
710 h2 = io.smb2.out.file.handle;
711 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
712 torture_wait_for_oplock_break(tctx);
713 CHECK_VAL(break_info.count, 1);
714 CHECK_VAL(break_info.failures, 0);
716 smb2_util_close(tree1, h1);
717 smb2_util_close(tree2, h2);
718 smb2_util_close(tree1, h);
720 smb2_deltree(tree1, BASEDIR);
721 return ret;
724 static bool test_smb2_oplock_exclusive6(struct torture_context *tctx,
725 struct smb2_tree *tree1,
726 struct smb2_tree *tree2)
728 const char *fname1 = BASEDIR "\\test_exclusive6_1.dat";
729 const char *fname2 = BASEDIR "\\test_exclusive6_2.dat";
730 NTSTATUS status;
731 bool ret = true;
732 union smb_open io;
733 union smb_setfileinfo sinfo;
734 struct smb2_close closeio;
735 struct smb2_handle h, h1;
737 status = torture_smb2_testdir(tree1, BASEDIR, &h);
738 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
740 /* cleanup */
741 smb2_util_unlink(tree1, fname1);
742 smb2_util_unlink(tree2, fname2);
744 tree1->session->transport->oplock.handler = torture_oplock_handler;
745 tree1->session->transport->oplock.private_data = tree1;
748 base ntcreatex parms
750 ZERO_STRUCT(io.smb2);
751 io.generic.level = RAW_OPEN_SMB2;
752 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
753 io.smb2.in.alloc_size = 0;
754 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
755 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
756 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
757 io.smb2.in.create_options = 0;
758 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
759 io.smb2.in.security_flags = 0;
760 io.smb2.in.fname = fname1;
762 torture_comment(tctx, "EXCLUSIVE6: open a file with an exclusive "
763 "oplock (share mode: none)\n");
764 ZERO_STRUCT(break_info);
765 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
766 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
768 status = smb2_create(tree1, tctx, &(io.smb2));
769 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
770 h1 = io.smb2.out.file.handle;
771 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
773 torture_comment(tctx, "rename with the parent directory handle open "
774 "for DELETE should not generate a break but get "
775 "a sharing violation\n");
776 ZERO_STRUCT(sinfo);
777 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
778 sinfo.rename_information.in.file.handle = h1;
779 sinfo.rename_information.in.overwrite = true;
780 sinfo.rename_information.in.new_name = fname2;
781 status = smb2_setinfo_file(tree1, &sinfo);
783 torture_comment(tctx, "trying rename while parent handle open for delete.\n");
784 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
785 "Incorrect status");
786 torture_wait_for_oplock_break(tctx);
787 CHECK_VAL(break_info.count, 0);
788 CHECK_VAL(break_info.failures, 0);
790 /* Close the parent directory handle. */
791 ZERO_STRUCT(closeio);
792 closeio.in.file.handle = h;
793 status = smb2_close(tree1, &closeio);
794 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
795 "Incorrect status");
797 /* Re-open without DELETE access. */
798 ZERO_STRUCT(io);
799 io.smb2.in.oplock_level = 0;
800 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL & (~SEC_STD_DELETE);
801 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
802 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
803 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
804 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
805 io.smb2.in.fname = BASEDIR;
807 status = smb2_create(tree1, tctx, &(io.smb2));
808 torture_assert_ntstatus_ok(tctx, status, "Error opening the base directory");
810 torture_comment(tctx, "rename with the parent directory handle open "
811 "without DELETE should succeed without a break\n");
812 ZERO_STRUCT(sinfo);
813 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
814 sinfo.rename_information.in.file.handle = h1;
815 sinfo.rename_information.in.overwrite = true;
816 sinfo.rename_information.in.new_name = fname2;
817 status = smb2_setinfo_file(tree1, &sinfo);
819 torture_comment(tctx, "trying rename while parent handle open without delete\n");
820 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
821 "Incorrect status");
822 torture_wait_for_oplock_break(tctx);
823 CHECK_VAL(break_info.count, 0);
824 CHECK_VAL(break_info.failures, 0);
826 smb2_util_close(tree1, h1);
827 smb2_util_close(tree1, h);
829 smb2_deltree(tree1, BASEDIR);
830 return ret;
833 static bool test_smb2_oplock_batch1(struct torture_context *tctx,
834 struct smb2_tree *tree1,
835 struct smb2_tree *tree2)
837 const char *fname = BASEDIR "\\test_batch1.dat";
838 NTSTATUS status;
839 bool ret = true;
840 union smb_open io;
841 struct smb2_handle h, h1;
842 char c = 0;
844 status = torture_smb2_testdir(tree1, BASEDIR, &h);
845 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
847 /* cleanup */
848 smb2_util_unlink(tree1, fname);
850 tree1->session->transport->oplock.handler = torture_oplock_handler;
851 tree1->session->transport->oplock.private_data = tree1;
854 base ntcreatex parms
856 ZERO_STRUCT(io.smb2);
857 io.generic.level = RAW_OPEN_SMB2;
858 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
859 io.smb2.in.alloc_size = 0;
860 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
861 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
862 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
863 io.smb2.in.create_options = 0;
864 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
865 io.smb2.in.security_flags = 0;
866 io.smb2.in.fname = fname;
869 with a batch oplock we get a break
871 torture_comment(tctx, "BATCH1: open with batch oplock\n");
872 ZERO_STRUCT(break_info);
873 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
874 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
875 status = smb2_create(tree1, tctx, &(io.smb2));
876 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
877 h1 = io.smb2.out.file.handle;
878 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
880 torture_comment(tctx, "unlink should generate a break\n");
881 status = smb2_util_unlink(tree2, fname);
882 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
883 "Incorrect status");
885 torture_wait_for_oplock_break(tctx);
886 CHECK_VAL(break_info.count, 1);
887 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
888 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
889 CHECK_VAL(break_info.failures, 0);
891 torture_comment(tctx, "2nd unlink should not generate a break\n");
892 ZERO_STRUCT(break_info);
893 status = smb2_util_unlink(tree2, fname);
894 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
895 "Incorrect status");
897 torture_wait_for_oplock_break(tctx);
898 CHECK_VAL(break_info.count, 0);
900 torture_comment(tctx, "writing should generate a self break to none\n");
901 tree1->session->transport->oplock.handler =
902 torture_oplock_handler_level2_to_none;
903 smb2_util_write(tree1, h1, &c, 0, 1);
905 torture_wait_for_oplock_break(tctx);
907 CHECK_VAL(break_info.count, 1);
908 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
909 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
910 CHECK_VAL(break_info.failures, 0);
912 smb2_util_close(tree1, h1);
913 smb2_util_close(tree1, h);
915 smb2_deltree(tree1, BASEDIR);
916 return ret;
919 static bool test_smb2_oplock_batch2(struct torture_context *tctx,
920 struct smb2_tree *tree1,
921 struct smb2_tree *tree2)
923 const char *fname = BASEDIR "\\test_batch2.dat";
924 NTSTATUS status;
925 bool ret = true;
926 union smb_open io;
927 char c = 0;
928 struct smb2_handle h, h1;
930 status = torture_smb2_testdir(tree1, BASEDIR, &h);
931 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
933 /* cleanup */
934 smb2_util_unlink(tree1, fname);
936 tree1->session->transport->oplock.handler = torture_oplock_handler;
937 tree1->session->transport->oplock.private_data = tree1;
940 base ntcreatex parms
942 ZERO_STRUCT(io.smb2);
943 io.generic.level = RAW_OPEN_SMB2;
944 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
945 io.smb2.in.alloc_size = 0;
946 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
947 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
948 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
949 io.smb2.in.create_options = 0;
950 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
951 io.smb2.in.security_flags = 0;
952 io.smb2.in.fname = fname;
954 torture_comment(tctx, "BATCH2: open with batch oplock\n");
955 ZERO_STRUCT(break_info);
956 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
957 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
958 status = smb2_create(tree1, tctx, &(io.smb2));
959 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
960 h1 = io.smb2.out.file.handle;
961 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
963 torture_comment(tctx, "unlink should generate a break, which we ack "
964 "as break to none\n");
965 tree1->session->transport->oplock.handler =
966 torture_oplock_handler_ack_to_none;
967 tree1->session->transport->oplock.private_data = tree1;
968 status = smb2_util_unlink(tree2, fname);
969 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
970 "Incorrect status");
972 torture_wait_for_oplock_break(tctx);
973 CHECK_VAL(break_info.count, 1);
974 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
975 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
976 CHECK_VAL(break_info.failures, 0);
978 torture_comment(tctx, "2nd unlink should not generate a break\n");
979 ZERO_STRUCT(break_info);
980 status = smb2_util_unlink(tree2, fname);
981 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
982 "Incorrect status");
984 torture_wait_for_oplock_break(tctx);
985 CHECK_VAL(break_info.count, 0);
987 torture_comment(tctx, "writing should not generate a break\n");
988 smb2_util_write(tree1, h1, &c, 0, 1);
990 torture_wait_for_oplock_break(tctx);
991 CHECK_VAL(break_info.count, 0);
993 smb2_util_close(tree1, h1);
994 smb2_util_close(tree1, h);
996 smb2_deltree(tree1, BASEDIR);
997 return ret;
1000 static bool test_smb2_oplock_batch3(struct torture_context *tctx,
1001 struct smb2_tree *tree1,
1002 struct smb2_tree *tree2)
1004 const char *fname = BASEDIR "\\test_batch3.dat";
1005 NTSTATUS status;
1006 bool ret = true;
1007 union smb_open io;
1008 struct smb2_handle h, h1;
1010 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1011 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1013 /* cleanup */
1014 smb2_util_unlink(tree1, fname);
1015 tree1->session->transport->oplock.handler = torture_oplock_handler;
1016 tree1->session->transport->oplock.private_data = tree1;
1019 base ntcreatex parms
1021 ZERO_STRUCT(io.smb2);
1022 io.generic.level = RAW_OPEN_SMB2;
1023 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1024 io.smb2.in.alloc_size = 0;
1025 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1026 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1027 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1028 io.smb2.in.create_options = 0;
1029 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1030 io.smb2.in.security_flags = 0;
1031 io.smb2.in.fname = fname;
1033 torture_comment(tctx, "BATCH3: if we close on break then the unlink "
1034 "can succeed\n");
1035 ZERO_STRUCT(break_info);
1036 tree1->session->transport->oplock.handler =
1037 torture_oplock_handler_close;
1038 tree1->session->transport->oplock.private_data = tree1;
1040 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1041 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1042 status = smb2_create(tree1, tctx, &(io.smb2));
1043 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1044 h1 = io.smb2.out.file.handle;
1045 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1047 ZERO_STRUCT(break_info);
1048 status = smb2_util_unlink(tree2, fname);
1049 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1051 torture_wait_for_oplock_break(tctx);
1052 CHECK_VAL(break_info.count, 1);
1053 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1054 CHECK_VAL(break_info.level, 1);
1055 CHECK_VAL(break_info.failures, 0);
1057 smb2_util_close(tree1, h1);
1058 smb2_util_close(tree1, h);
1060 smb2_deltree(tree1, BASEDIR);
1061 return ret;
1064 static bool test_smb2_oplock_batch4(struct torture_context *tctx,
1065 struct smb2_tree *tree1,
1066 struct smb2_tree *tree2)
1068 const char *fname = BASEDIR "\\test_batch4.dat";
1069 NTSTATUS status;
1070 bool ret = true;
1071 union smb_open io;
1072 struct smb2_read r;
1073 struct smb2_handle h, h1;
1075 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1076 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1078 /* cleanup */
1079 smb2_util_unlink(tree1, fname);
1081 tree1->session->transport->oplock.handler = torture_oplock_handler;
1082 tree1->session->transport->oplock.private_data = tree1;
1085 base ntcreatex parms
1087 ZERO_STRUCT(io.smb2);
1088 io.generic.level = RAW_OPEN_SMB2;
1089 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1090 io.smb2.in.alloc_size = 0;
1091 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1092 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1093 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1094 io.smb2.in.create_options = 0;
1095 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1096 io.smb2.in.security_flags = 0;
1097 io.smb2.in.fname = fname;
1099 torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
1100 ZERO_STRUCT(break_info);
1102 tree1->session->transport->oplock.handler = torture_oplock_handler;
1103 tree1->session->transport->oplock.private_data = tree1;
1105 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1106 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1107 status = smb2_create(tree1, tctx, &(io.smb2));
1108 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1109 h1 = io.smb2.out.file.handle;
1110 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1112 ZERO_STRUCT(r);
1113 r.in.file.handle = h1;
1114 r.in.offset = 0;
1116 status = smb2_read(tree1, tree1, &r);
1117 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1118 torture_wait_for_oplock_break(tctx);
1119 CHECK_VAL(break_info.count, 0);
1120 CHECK_VAL(break_info.failures, 0);
1122 smb2_util_close(tree1, h1);
1123 smb2_util_close(tree1, h);
1125 smb2_deltree(tree1, BASEDIR);
1126 return ret;
1129 static bool test_smb2_oplock_batch5(struct torture_context *tctx,
1130 struct smb2_tree *tree1,
1131 struct smb2_tree *tree2)
1133 const char *fname = BASEDIR "\\test_batch5.dat";
1134 NTSTATUS status;
1135 bool ret = true;
1136 union smb_open io;
1137 struct smb2_handle h, h1;
1139 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1140 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1142 /* cleanup */
1143 smb2_util_unlink(tree1, fname);
1145 tree1->session->transport->oplock.handler = torture_oplock_handler;
1146 tree1->session->transport->oplock.private_data = tree1;
1149 base ntcreatex parms
1151 ZERO_STRUCT(io.smb2);
1152 io.generic.level = RAW_OPEN_SMB2;
1153 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1154 io.smb2.in.alloc_size = 0;
1155 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1156 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1157 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1158 io.smb2.in.create_options = 0;
1159 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1160 io.smb2.in.security_flags = 0;
1161 io.smb2.in.fname = fname;
1163 torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
1164 ZERO_STRUCT(break_info);
1166 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1167 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1168 status = smb2_create(tree1, tctx, &(io.smb2));
1169 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1170 h1 = io.smb2.out.file.handle;
1171 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1173 ZERO_STRUCT(break_info);
1175 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1176 status = smb2_create(tree2, tctx, &(io.smb2));
1177 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
1178 "Incorrect status");
1180 torture_wait_for_oplock_break(tctx);
1181 CHECK_VAL(break_info.count, 1);
1182 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1183 CHECK_VAL(break_info.level, 1);
1184 CHECK_VAL(break_info.failures, 0);
1186 smb2_util_close(tree1, h1);
1187 smb2_util_close(tree1, h);
1189 smb2_deltree(tree1, BASEDIR);
1190 return ret;
1193 static bool test_smb2_oplock_batch6(struct torture_context *tctx,
1194 struct smb2_tree *tree1,
1195 struct smb2_tree *tree2)
1197 const char *fname = BASEDIR "\\test_batch6.dat";
1198 NTSTATUS status;
1199 bool ret = true;
1200 union smb_open io;
1201 struct smb2_handle h, h1, h2;
1202 char c = 0;
1204 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1205 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1207 /* cleanup */
1208 smb2_util_unlink(tree1, fname);
1210 tree1->session->transport->oplock.handler = torture_oplock_handler;
1211 tree1->session->transport->oplock.private_data = tree1;
1214 base ntcreatex parms
1216 ZERO_STRUCT(io.smb2);
1217 io.generic.level = RAW_OPEN_SMB2;
1218 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1219 io.smb2.in.alloc_size = 0;
1220 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1221 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1222 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1223 io.smb2.in.create_options = 0;
1224 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1225 io.smb2.in.security_flags = 0;
1226 io.smb2.in.fname = fname;
1228 torture_comment(tctx, "BATCH6: a 2nd open should give a break to "
1229 "level II if the first open allowed shared read\n");
1230 ZERO_STRUCT(break_info);
1231 tree2->session->transport->oplock.handler = torture_oplock_handler;
1232 tree2->session->transport->oplock.private_data = tree2;
1234 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
1235 SEC_RIGHTS_FILE_WRITE;
1236 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1237 NTCREATEX_SHARE_ACCESS_WRITE;
1238 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1239 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1240 status = smb2_create(tree1, tctx, &(io.smb2));
1241 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1242 h1 = io.smb2.out.file.handle;
1243 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1245 ZERO_STRUCT(break_info);
1247 status = smb2_create(tree2, tctx, &(io.smb2));
1248 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1249 h2 = io.smb2.out.file.handle;
1250 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1252 torture_wait_for_oplock_break(tctx);
1253 CHECK_VAL(break_info.count, 1);
1254 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1255 CHECK_VAL(break_info.level, 1);
1256 CHECK_VAL(break_info.failures, 0);
1257 ZERO_STRUCT(break_info);
1259 torture_comment(tctx, "write should trigger a break to none on both\n");
1260 tree1->session->transport->oplock.handler =
1261 torture_oplock_handler_level2_to_none;
1262 tree2->session->transport->oplock.handler =
1263 torture_oplock_handler_level2_to_none;
1264 smb2_util_write(tree1, h1, &c, 0, 1);
1266 /* We expect two breaks */
1267 torture_wait_for_oplock_break(tctx);
1268 torture_wait_for_oplock_break(tctx);
1270 CHECK_VAL(break_info.count, 2);
1271 CHECK_VAL(break_info.level, 0);
1272 CHECK_VAL(break_info.failures, 0);
1274 smb2_util_close(tree1, h1);
1275 smb2_util_close(tree2, h2);
1276 smb2_util_close(tree1, h);
1278 smb2_deltree(tree1, BASEDIR);
1279 return ret;
1282 static bool test_smb2_oplock_batch7(struct torture_context *tctx,
1283 struct smb2_tree *tree1,
1284 struct smb2_tree *tree2)
1286 const char *fname = BASEDIR "\\test_batch7.dat";
1287 NTSTATUS status;
1288 bool ret = true;
1289 union smb_open io;
1290 struct smb2_handle h, h1, h2;
1292 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1293 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1295 /* cleanup */
1296 smb2_util_unlink(tree1, fname);
1298 tree1->session->transport->oplock.handler = torture_oplock_handler;
1299 tree1->session->transport->oplock.private_data = tree1;
1302 base ntcreatex parms
1304 ZERO_STRUCT(io.smb2);
1305 io.generic.level = RAW_OPEN_SMB2;
1306 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1307 io.smb2.in.alloc_size = 0;
1308 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1309 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1310 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1311 io.smb2.in.create_options = 0;
1312 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1313 io.smb2.in.security_flags = 0;
1314 io.smb2.in.fname = fname;
1316 torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when "
1317 "we close instead of ack\n");
1318 ZERO_STRUCT(break_info);
1319 tree1->session->transport->oplock.handler =
1320 torture_oplock_handler_close;
1321 tree1->session->transport->oplock.private_data = tree1;
1323 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1324 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1325 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1326 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1327 status = smb2_create(tree1, tctx, &(io.smb2));
1328 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1329 h2 = io.smb2.out.file.handle;
1330 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1332 ZERO_STRUCT(break_info);
1334 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1335 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1336 status = smb2_create(tree2, tctx, &(io.smb2));
1337 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1338 h1 = io.smb2.out.file.handle;
1339 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1341 torture_wait_for_oplock_break(tctx);
1342 CHECK_VAL(break_info.count, 1);
1343 CHECK_VAL(break_info.handle.data[0], h2.data[0]);
1344 CHECK_VAL(break_info.level, 1);
1345 CHECK_VAL(break_info.failures, 0);
1347 smb2_util_close(tree2, h1);
1348 smb2_util_close(tree2, h);
1350 smb2_deltree(tree1, BASEDIR);
1351 return ret;
1354 static bool test_smb2_oplock_batch8(struct torture_context *tctx,
1355 struct smb2_tree *tree1,
1356 struct smb2_tree *tree2)
1358 const char *fname = BASEDIR "\\test_batch8.dat";
1359 NTSTATUS status;
1360 bool ret = true;
1361 union smb_open io;
1362 struct smb2_handle h, h1, h2;
1364 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1365 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1367 /* cleanup */
1368 smb2_util_unlink(tree1, fname);
1370 tree1->session->transport->oplock.handler = torture_oplock_handler;
1371 tree1->session->transport->oplock.private_data = tree1;
1374 base ntcreatex parms
1376 ZERO_STRUCT(io.smb2);
1377 io.generic.level = RAW_OPEN_SMB2;
1378 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1379 io.smb2.in.alloc_size = 0;
1380 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1381 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1382 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1383 io.smb2.in.create_options = 0;
1384 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1385 io.smb2.in.security_flags = 0;
1386 io.smb2.in.fname = fname;
1388 torture_comment(tctx, "BATCH8: open with batch oplock\n");
1389 ZERO_STRUCT(break_info);
1391 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1392 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1393 status = smb2_create(tree1, tctx, &(io.smb2));
1394 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1395 h1 = io.smb2.out.file.handle;
1396 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1398 ZERO_STRUCT(break_info);
1399 torture_comment(tctx, "second open with attributes only shouldn't "
1400 "cause oplock break\n");
1402 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1403 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1404 SEC_FILE_WRITE_ATTRIBUTE |
1405 SEC_STD_SYNCHRONIZE;
1406 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1407 status = smb2_create(tree2, tctx, &(io.smb2));
1408 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1409 h2 = io.smb2.out.file.handle;
1410 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
1411 torture_wait_for_oplock_break(tctx);
1412 CHECK_VAL(break_info.count, 0);
1413 CHECK_VAL(break_info.failures, 0);
1415 smb2_util_close(tree1, h1);
1416 smb2_util_close(tree2, h2);
1417 smb2_util_close(tree1, h);
1419 smb2_deltree(tree1, BASEDIR);
1420 return ret;
1423 static bool test_smb2_oplock_batch9(struct torture_context *tctx,
1424 struct smb2_tree *tree1,
1425 struct smb2_tree *tree2)
1427 const char *fname = BASEDIR "\\test_batch9.dat";
1428 NTSTATUS status;
1429 bool ret = true;
1430 union smb_open io;
1431 struct smb2_handle h, h1, h2;
1432 char c = 0;
1434 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1435 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1437 /* cleanup */
1438 smb2_util_unlink(tree1, fname);
1440 tree1->session->transport->oplock.handler = torture_oplock_handler;
1441 tree1->session->transport->oplock.private_data = tree1;
1444 base ntcreatex parms
1446 ZERO_STRUCT(io.smb2);
1447 io.generic.level = RAW_OPEN_SMB2;
1448 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1449 io.smb2.in.alloc_size = 0;
1450 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1451 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1452 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1453 io.smb2.in.create_options = 0;
1454 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1455 io.smb2.in.security_flags = 0;
1456 io.smb2.in.fname = fname;
1458 torture_comment(tctx, "BATCH9: open with attributes only can create "
1459 "file\n");
1461 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1462 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1463 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1464 SEC_FILE_WRITE_ATTRIBUTE |
1465 SEC_STD_SYNCHRONIZE;
1466 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1467 status = smb2_create(tree1, tctx, &(io.smb2));
1468 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1469 h1 = io.smb2.out.file.handle;
1470 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1472 torture_comment(tctx, "Subsequent normal open should break oplock on "
1473 "attribute only open to level II\n");
1475 ZERO_STRUCT(break_info);
1477 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1478 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1479 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1480 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1481 status = smb2_create(tree2, tctx, &(io.smb2));
1482 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1483 h2 = io.smb2.out.file.handle;
1484 torture_wait_for_oplock_break(tctx);
1485 CHECK_VAL(break_info.count, 1);
1486 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1487 CHECK_VAL(break_info.failures, 0);
1488 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
1489 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1490 smb2_util_close(tree2, h2);
1492 torture_comment(tctx, "third oplocked open should grant level2 without "
1493 "break\n");
1494 ZERO_STRUCT(break_info);
1496 tree2->session->transport->oplock.handler = torture_oplock_handler;
1497 tree2->session->transport->oplock.private_data = tree2;
1499 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1500 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1501 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1502 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1503 status = smb2_create(tree2, tctx, &(io.smb2));
1504 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1505 h2 = io.smb2.out.file.handle;
1506 torture_wait_for_oplock_break(tctx);
1507 CHECK_VAL(break_info.count, 0);
1508 CHECK_VAL(break_info.failures, 0);
1509 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1511 ZERO_STRUCT(break_info);
1513 torture_comment(tctx, "write should trigger a break to none on both\n");
1514 tree1->session->transport->oplock.handler =
1515 torture_oplock_handler_level2_to_none;
1516 tree2->session->transport->oplock.handler =
1517 torture_oplock_handler_level2_to_none;
1518 smb2_util_write(tree2, h2, &c, 0, 1);
1520 /* We expect two breaks */
1521 torture_wait_for_oplock_break(tctx);
1522 torture_wait_for_oplock_break(tctx);
1524 CHECK_VAL(break_info.count, 2);
1525 CHECK_VAL(break_info.level, 0);
1526 CHECK_VAL(break_info.failures, 0);
1528 smb2_util_close(tree1, h1);
1529 smb2_util_close(tree2, h2);
1530 smb2_util_close(tree1, h);
1532 smb2_deltree(tree1, BASEDIR);
1533 return ret;
1536 static bool test_smb2_oplock_batch10(struct torture_context *tctx,
1537 struct smb2_tree *tree1,
1538 struct smb2_tree *tree2)
1540 const char *fname = BASEDIR "\\test_batch10.dat";
1541 NTSTATUS status;
1542 bool ret = true;
1543 union smb_open io;
1544 struct smb2_handle h, h1, h2;
1546 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1547 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1549 /* cleanup */
1550 smb2_util_unlink(tree1, fname);
1552 tree1->session->transport->oplock.handler = torture_oplock_handler;
1553 tree1->session->transport->oplock.private_data = tree1;
1556 base ntcreatex parms
1558 ZERO_STRUCT(io.smb2);
1559 io.generic.level = RAW_OPEN_SMB2;
1560 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1561 io.smb2.in.alloc_size = 0;
1562 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1563 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1564 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1565 io.smb2.in.create_options = 0;
1566 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1567 io.smb2.in.security_flags = 0;
1568 io.smb2.in.fname = fname;
1570 torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock "
1571 "open should grant level2\n");
1572 ZERO_STRUCT(break_info);
1573 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1574 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1575 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1576 NTCREATEX_SHARE_ACCESS_WRITE|
1577 NTCREATEX_SHARE_ACCESS_DELETE;
1578 status = smb2_create(tree1, tctx, &(io.smb2));
1579 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1580 h1 = io.smb2.out.file.handle;
1581 torture_wait_for_oplock_break(tctx);
1582 CHECK_VAL(break_info.count, 0);
1583 CHECK_VAL(break_info.failures, 0);
1584 CHECK_VAL(io.smb2.out.oplock_level, 0);
1586 tree2->session->transport->oplock.handler =
1587 torture_oplock_handler_level2_to_none;
1588 tree2->session->transport->oplock.private_data = tree2;
1590 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1591 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1592 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1593 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1594 NTCREATEX_SHARE_ACCESS_WRITE|
1595 NTCREATEX_SHARE_ACCESS_DELETE;
1596 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1597 status = smb2_create(tree2, tctx, &(io.smb2));
1598 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1599 h2 = io.smb2.out.file.handle;
1600 torture_wait_for_oplock_break(tctx);
1601 CHECK_VAL(break_info.count, 0);
1602 CHECK_VAL(break_info.failures, 0);
1603 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1605 torture_comment(tctx, "write should trigger a break to none\n");
1607 struct smb2_write wr;
1608 DATA_BLOB data;
1609 data = data_blob_talloc(tree1, NULL, UINT16_MAX);
1610 data.data[0] = (const uint8_t)'x';
1611 ZERO_STRUCT(wr);
1612 wr.in.file.handle = h1;
1613 wr.in.offset = 0;
1614 wr.in.data = data;
1615 status = smb2_write(tree1, &wr);
1616 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1619 torture_wait_for_oplock_break(tctx);
1621 CHECK_VAL(break_info.count, 1);
1622 CHECK_VAL(break_info.handle.data[0], h2.data[0]);
1623 CHECK_VAL(break_info.level, 0);
1624 CHECK_VAL(break_info.failures, 0);
1626 smb2_util_close(tree1, h1);
1627 smb2_util_close(tree2, h2);
1628 smb2_util_close(tree1, h);
1630 smb2_deltree(tree1, BASEDIR);
1631 return ret;
1634 static bool test_smb2_oplock_batch11(struct torture_context *tctx,
1635 struct smb2_tree *tree1,
1636 struct smb2_tree *tree2)
1638 const char *fname = BASEDIR "\\test_batch11.dat";
1639 NTSTATUS status;
1640 bool ret = true;
1641 union smb_open io;
1642 union smb_setfileinfo sfi;
1643 struct smb2_handle h, h1;
1645 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1646 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1648 /* cleanup */
1649 smb2_util_unlink(tree1, fname);
1651 tree1->session->transport->oplock.handler =
1652 torture_oplock_handler_two_notifications;
1653 tree1->session->transport->oplock.private_data = tree1;
1656 base ntcreatex parms
1658 ZERO_STRUCT(io.smb2);
1659 io.generic.level = RAW_OPEN_SMB2;
1660 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1661 io.smb2.in.alloc_size = 0;
1662 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1663 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1664 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1665 io.smb2.in.create_options = 0;
1666 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1667 io.smb2.in.security_flags = 0;
1668 io.smb2.in.fname = fname;
1670 /* Test if a set-eof on pathname breaks an exclusive oplock. */
1671 torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks "
1672 "oplocks.\n");
1674 ZERO_STRUCT(break_info);
1676 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1677 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1678 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1679 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1680 NTCREATEX_SHARE_ACCESS_WRITE|
1681 NTCREATEX_SHARE_ACCESS_DELETE;
1682 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1683 status = smb2_create(tree1, tctx, &(io.smb2));
1684 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1685 h1 = io.smb2.out.file.handle;
1686 torture_wait_for_oplock_break(tctx);
1687 CHECK_VAL(break_info.count, 0);
1688 CHECK_VAL(break_info.failures, 0);
1689 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1691 ZERO_STRUCT(sfi);
1692 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1693 sfi.generic.in.file.path = fname;
1694 sfi.end_of_file_info.in.size = 100;
1696 status = smb2_composite_setpathinfo(tree2, &sfi);
1697 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1699 /* We expect two breaks */
1700 torture_wait_for_oplock_break(tctx);
1701 torture_wait_for_oplock_break(tctx);
1703 CHECK_VAL(break_info.count, 2);
1704 CHECK_VAL(break_info.failures, 0);
1705 CHECK_VAL(break_info.level, 0);
1707 smb2_util_close(tree1, h1);
1708 smb2_util_close(tree1, h);
1710 smb2_deltree(tree1, BASEDIR);
1711 return ret;
1714 static bool test_smb2_oplock_batch12(struct torture_context *tctx,
1715 struct smb2_tree *tree1,
1716 struct smb2_tree *tree2)
1718 const char *fname = BASEDIR "\\test_batch12.dat";
1719 NTSTATUS status;
1720 bool ret = true;
1721 union smb_open io;
1722 union smb_setfileinfo sfi;
1723 struct smb2_handle h, h1;
1725 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1726 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1728 /* cleanup */
1729 smb2_util_unlink(tree1, fname);
1731 tree1->session->transport->oplock.handler =
1732 torture_oplock_handler_two_notifications;
1733 tree1->session->transport->oplock.private_data = tree1;
1736 base ntcreatex parms
1738 ZERO_STRUCT(io.smb2);
1739 io.generic.level = RAW_OPEN_SMB2;
1740 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1741 io.smb2.in.alloc_size = 0;
1742 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1743 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1744 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1745 io.smb2.in.create_options = 0;
1746 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1747 io.smb2.in.security_flags = 0;
1748 io.smb2.in.fname = fname;
1750 /* Test if a set-allocation size on pathname breaks an exclusive
1751 * oplock. */
1752 torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size "
1753 "breaks oplocks.\n");
1755 ZERO_STRUCT(break_info);
1757 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1758 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1759 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1760 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1761 NTCREATEX_SHARE_ACCESS_WRITE|
1762 NTCREATEX_SHARE_ACCESS_DELETE;
1763 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1764 status = smb2_create(tree1, tctx, &(io.smb2));
1765 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1766 h1 = io.smb2.out.file.handle;
1767 torture_wait_for_oplock_break(tctx);
1768 CHECK_VAL(break_info.count, 0);
1769 CHECK_VAL(break_info.failures, 0);
1770 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1772 ZERO_STRUCT(sfi);
1773 sfi.generic.level = RAW_SFILEINFO_ALLOCATION_INFORMATION;
1774 sfi.generic.in.file.path = fname;
1775 sfi.allocation_info.in.alloc_size = 65536 * 8;
1777 status = smb2_composite_setpathinfo(tree2, &sfi);
1778 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1780 /* We expect two breaks */
1781 torture_wait_for_oplock_break(tctx);
1782 torture_wait_for_oplock_break(tctx);
1784 CHECK_VAL(break_info.count, 2);
1785 CHECK_VAL(break_info.failures, 0);
1786 CHECK_VAL(break_info.level, 0);
1788 smb2_util_close(tree1, h1);
1789 smb2_util_close(tree1, h);
1791 smb2_deltree(tree1, BASEDIR);
1792 return ret;
1795 static bool test_smb2_oplock_batch13(struct torture_context *tctx,
1796 struct smb2_tree *tree1,
1797 struct smb2_tree *tree2)
1799 const char *fname = BASEDIR "\\test_batch13.dat";
1800 NTSTATUS status;
1801 bool ret = true;
1802 union smb_open io;
1803 struct smb2_handle h, h1, h2;
1805 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1806 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1808 /* cleanup */
1809 smb2_util_unlink(tree1, fname);
1811 tree1->session->transport->oplock.handler = torture_oplock_handler;
1812 tree1->session->transport->oplock.private_data = tree1;
1814 tree2->session->transport->oplock.handler = torture_oplock_handler;
1815 tree2->session->transport->oplock.private_data = tree2;
1818 base ntcreatex parms
1820 ZERO_STRUCT(io.smb2);
1821 io.generic.level = RAW_OPEN_SMB2;
1822 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1823 io.smb2.in.alloc_size = 0;
1824 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1825 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1826 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1827 io.smb2.in.create_options = 0;
1828 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1829 io.smb2.in.security_flags = 0;
1830 io.smb2.in.fname = fname;
1832 torture_comment(tctx, "BATCH13: open with batch oplock\n");
1833 ZERO_STRUCT(break_info);
1835 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1836 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1837 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1838 NTCREATEX_SHARE_ACCESS_WRITE|
1839 NTCREATEX_SHARE_ACCESS_DELETE;
1840 status = smb2_create(tree1, tctx, &(io.smb2));
1841 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1842 h1 = io.smb2.out.file.handle;
1843 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1845 ZERO_STRUCT(break_info);
1847 torture_comment(tctx, "second open with attributes only and "
1848 "NTCREATEX_DISP_OVERWRITE dispostion causes "
1849 "oplock break\n");
1851 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1852 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1853 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1854 SEC_FILE_WRITE_ATTRIBUTE |
1855 SEC_STD_SYNCHRONIZE;
1856 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1857 NTCREATEX_SHARE_ACCESS_WRITE|
1858 NTCREATEX_SHARE_ACCESS_DELETE;
1859 io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
1860 status = smb2_create(tree2, tctx, &(io.smb2));
1861 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1862 h2 = io.smb2.out.file.handle;
1863 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1864 torture_wait_for_oplock_break(tctx);
1865 CHECK_VAL(break_info.count, 1);
1866 CHECK_VAL(break_info.failures, 0);
1868 smb2_util_close(tree1, h1);
1869 smb2_util_close(tree2, h2);
1870 smb2_util_close(tree1, h);
1872 smb2_deltree(tree1, BASEDIR);
1874 return ret;
1877 static bool test_smb2_oplock_batch14(struct torture_context *tctx,
1878 struct smb2_tree *tree1,
1879 struct smb2_tree *tree2)
1881 const char *fname = BASEDIR "\\test_batch14.dat";
1882 NTSTATUS status;
1883 bool ret = true;
1884 union smb_open io;
1885 struct smb2_handle h, h1, h2;
1887 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1888 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1890 /* cleanup */
1891 smb2_util_unlink(tree1, fname);
1893 tree1->session->transport->oplock.handler = torture_oplock_handler;
1894 tree1->session->transport->oplock.private_data = tree1;
1897 base ntcreatex parms
1899 ZERO_STRUCT(io.smb2);
1900 io.generic.level = RAW_OPEN_SMB2;
1901 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1902 io.smb2.in.alloc_size = 0;
1903 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1904 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1905 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1906 io.smb2.in.create_options = 0;
1907 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1908 io.smb2.in.security_flags = 0;
1909 io.smb2.in.fname = fname;
1911 torture_comment(tctx, "BATCH14: open with batch oplock\n");
1912 ZERO_STRUCT(break_info);
1914 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1915 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1916 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1917 NTCREATEX_SHARE_ACCESS_WRITE|
1918 NTCREATEX_SHARE_ACCESS_DELETE;
1919 status = smb2_create(tree1, tctx, &(io.smb2));
1920 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1921 h1 = io.smb2.out.file.handle;
1922 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1924 ZERO_STRUCT(break_info);
1926 torture_comment(tctx, "second open with attributes only and "
1927 "NTCREATEX_DISP_SUPERSEDE dispostion causes "
1928 "oplock break\n");
1930 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1931 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1932 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1933 SEC_FILE_WRITE_ATTRIBUTE |
1934 SEC_STD_SYNCHRONIZE;
1935 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1936 NTCREATEX_SHARE_ACCESS_WRITE|
1937 NTCREATEX_SHARE_ACCESS_DELETE;
1938 io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
1939 status = smb2_create(tree2, tctx, &(io.smb2));
1940 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1941 h2 = io.smb2.out.file.handle;
1942 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1944 torture_wait_for_oplock_break(tctx);
1945 CHECK_VAL(break_info.count, 1);
1946 CHECK_VAL(break_info.failures, 0);
1948 smb2_util_close(tree1, h1);
1949 smb2_util_close(tree2, h2);
1950 smb2_util_close(tree1, h);
1952 smb2_deltree(tree1, BASEDIR);
1953 return ret;
1956 static bool test_smb2_oplock_batch15(struct torture_context *tctx,
1957 struct smb2_tree *tree1,
1958 struct smb2_tree *tree2)
1960 const char *fname = BASEDIR "\\test_batch15.dat";
1961 NTSTATUS status;
1962 bool ret = true;
1963 union smb_open io;
1964 union smb_fileinfo qfi;
1965 struct smb2_handle h, h1;
1967 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1968 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1970 /* cleanup */
1971 smb2_util_unlink(tree1, fname);
1973 tree1->session->transport->oplock.handler = torture_oplock_handler;
1974 tree1->session->transport->oplock.private_data = tree1;
1977 base ntcreatex parms
1979 ZERO_STRUCT(io.smb2);
1980 io.generic.level = RAW_OPEN_SMB2;
1981 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1982 io.smb2.in.alloc_size = 0;
1983 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1984 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1985 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1986 io.smb2.in.create_options = 0;
1987 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1988 io.smb2.in.security_flags = 0;
1989 io.smb2.in.fname = fname;
1991 /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
1992 torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks "
1993 "a batch oplock (should not).\n");
1995 ZERO_STRUCT(break_info);
1997 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1998 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1999 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2000 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2001 NTCREATEX_SHARE_ACCESS_WRITE|
2002 NTCREATEX_SHARE_ACCESS_DELETE;
2003 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2004 status = smb2_create(tree1, tctx, &(io.smb2));
2005 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2006 h1 = io.smb2.out.file.handle;
2008 torture_wait_for_oplock_break(tctx);
2009 CHECK_VAL(break_info.count, 0);
2010 CHECK_VAL(break_info.failures, 0);
2011 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2013 ZERO_STRUCT(qfi);
2014 qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2015 qfi.generic.in.file.handle = h1;
2016 status = smb2_getinfo_file(tree2, tctx, &qfi);
2018 torture_wait_for_oplock_break(tctx);
2019 CHECK_VAL(break_info.count, 0);
2021 smb2_util_close(tree1, h1);
2022 smb2_util_close(tree1, h);
2024 smb2_deltree(tree1, BASEDIR);
2025 return ret;
2028 static bool test_smb2_oplock_batch16(struct torture_context *tctx,
2029 struct smb2_tree *tree1,
2030 struct smb2_tree *tree2)
2032 const char *fname = BASEDIR "\\test_batch16.dat";
2033 NTSTATUS status;
2034 bool ret = true;
2035 union smb_open io;
2036 struct smb2_handle h, h1, h2;
2038 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2039 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2041 /* cleanup */
2042 smb2_util_unlink(tree1, fname);
2044 tree1->session->transport->oplock.handler = torture_oplock_handler;
2045 tree1->session->transport->oplock.private_data = tree1;
2047 tree2->session->transport->oplock.handler = torture_oplock_handler;
2048 tree2->session->transport->oplock.private_data = tree2;
2051 base ntcreatex parms
2053 ZERO_STRUCT(io.smb2);
2054 io.generic.level = RAW_OPEN_SMB2;
2055 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2056 io.smb2.in.alloc_size = 0;
2057 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2058 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2059 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2060 io.smb2.in.create_options = 0;
2061 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2062 io.smb2.in.security_flags = 0;
2063 io.smb2.in.fname = fname;
2065 torture_comment(tctx, "BATCH16: open with batch oplock\n");
2066 ZERO_STRUCT(break_info);
2068 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2069 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2070 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2071 NTCREATEX_SHARE_ACCESS_WRITE|
2072 NTCREATEX_SHARE_ACCESS_DELETE;
2073 status = smb2_create(tree1, tctx, &(io.smb2));
2074 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2075 h1 = io.smb2.out.file.handle;
2076 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2078 ZERO_STRUCT(break_info);
2080 torture_comment(tctx, "second open with attributes only and "
2081 "NTCREATEX_DISP_OVERWRITE_IF dispostion causes "
2082 "oplock break\n");
2084 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2085 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2086 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
2087 SEC_FILE_WRITE_ATTRIBUTE |
2088 SEC_STD_SYNCHRONIZE;
2089 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2090 NTCREATEX_SHARE_ACCESS_WRITE|
2091 NTCREATEX_SHARE_ACCESS_DELETE;
2092 io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2093 status = smb2_create(tree2, tctx, &(io.smb2));
2094 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2095 h2 = io.smb2.out.file.handle;
2096 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2098 torture_wait_for_oplock_break(tctx);
2099 CHECK_VAL(break_info.count, 1);
2100 CHECK_VAL(break_info.failures, 0);
2102 smb2_util_close(tree1, h1);
2103 smb2_util_close(tree2, h2);
2104 smb2_util_close(tree1, h);
2106 smb2_deltree(tree1, BASEDIR);
2107 return ret;
2110 /* This function is a placeholder for the SMB1 RAW-OPLOCK-BATCH17 test. Since
2111 * SMB2 doesn't have a RENAME command this test isn't applicable. However,
2112 * it's much less confusing, when comparing test, to keep the SMB1 and SMB2
2113 * test numbers in sync. */
2114 #if 0
2115 static bool test_raw_oplock_batch17(struct torture_context *tctx,
2116 struct smb2_tree *tree1,
2117 struct smb2_tree *tree2)
2119 return true;
2121 #endif
2123 /* This function is a placeholder for the SMB1 RAW-OPLOCK-BATCH18 test. Since
2124 * SMB2 doesn't have an NTRENAME command this test isn't applicable. However,
2125 * it's much less confusing, when comparing tests, to keep the SMB1 and SMB2
2126 * test numbers in sync. */
2127 #if 0
2128 static bool test_raw_oplock_batch18(struct torture_context *tctx,
2129 struct smb2_tree *tree1,
2130 struct smb2_tree *tree2)
2132 return true;
2134 #endif
2136 static bool test_smb2_oplock_batch19(struct torture_context *tctx,
2137 struct smb2_tree *tree1)
2139 const char *fname1 = BASEDIR "\\test_batch19_1.dat";
2140 const char *fname2 = BASEDIR "\\test_batch19_2.dat";
2141 NTSTATUS status;
2142 bool ret = true;
2143 union smb_open io;
2144 union smb_fileinfo qfi;
2145 union smb_setfileinfo sfi;
2146 struct smb2_handle h, h1;
2148 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2149 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2151 /* cleanup */
2152 smb2_util_unlink(tree1, fname1);
2153 smb2_util_unlink(tree1, fname2);
2155 tree1->session->transport->oplock.handler = torture_oplock_handler;
2156 tree1->session->transport->oplock.private_data = tree1;
2159 base ntcreatex parms
2161 ZERO_STRUCT(io.smb2);
2162 io.generic.level = RAW_OPEN_SMB2;
2163 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2164 io.smb2.in.alloc_size = 0;
2165 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2166 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2167 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2168 io.smb2.in.create_options = 0;
2169 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2170 io.smb2.in.security_flags = 0;
2171 io.smb2.in.fname = fname1;
2173 torture_comment(tctx, "BATCH19: open a file with an batch oplock "
2174 "(share mode: none)\n");
2175 ZERO_STRUCT(break_info);
2176 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2177 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2178 status = smb2_create(tree1, tctx, &(io.smb2));
2179 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2180 h1 = io.smb2.out.file.handle;
2181 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2183 torture_comment(tctx, "setfileinfo rename info should not trigger "
2184 "a break but should cause a sharing violation\n");
2185 ZERO_STRUCT(sfi);
2186 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2187 sfi.generic.in.file.path = fname1;
2188 sfi.rename_information.in.file.handle = h1;
2189 sfi.rename_information.in.overwrite = 0;
2190 sfi.rename_information.in.root_fid = 0;
2191 sfi.rename_information.in.new_name = fname2;
2193 status = smb2_setinfo_file(tree1, &sfi);
2195 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2196 "Incorrect status");
2198 torture_wait_for_oplock_break(tctx);
2199 CHECK_VAL(break_info.count, 0);
2201 ZERO_STRUCT(qfi);
2202 qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2203 qfi.generic.in.file.handle = h1;
2205 status = smb2_getinfo_file(tree1, tctx, &qfi);
2206 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2207 CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2209 smb2_util_close(tree1, h1);
2210 smb2_util_close(tree1, h);
2212 smb2_deltree(tree1, fname1);
2213 smb2_deltree(tree1, fname2);
2214 return ret;
2217 static bool test_smb2_oplock_batch20(struct torture_context *tctx,
2218 struct smb2_tree *tree1,
2219 struct smb2_tree *tree2)
2221 const char *fname1 = BASEDIR "\\test_batch20_1.dat";
2222 const char *fname2 = BASEDIR "\\test_batch20_2.dat";
2223 NTSTATUS status;
2224 bool ret = true;
2225 union smb_open io;
2226 union smb_fileinfo qfi;
2227 union smb_setfileinfo sfi;
2228 struct smb2_handle h, h1, h2;
2230 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2231 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2233 /* cleanup */
2234 smb2_util_unlink(tree1, fname1);
2235 smb2_util_unlink(tree1, fname2);
2237 tree1->session->transport->oplock.handler = torture_oplock_handler;
2238 tree1->session->transport->oplock.private_data = tree1;
2241 base ntcreatex parms
2243 ZERO_STRUCT(io.smb2);
2244 io.generic.level = RAW_OPEN_SMB2;
2245 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2246 io.smb2.in.alloc_size = 0;
2247 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2248 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2249 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2250 io.smb2.in.create_options = 0;
2251 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2252 io.smb2.in.security_flags = 0;
2253 io.smb2.in.fname = fname1;
2255 torture_comment(tctx, "BATCH20: open a file with an batch oplock "
2256 "(share mode: all)\n");
2257 ZERO_STRUCT(break_info);
2258 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2259 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2260 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2261 NTCREATEX_SHARE_ACCESS_WRITE|
2262 NTCREATEX_SHARE_ACCESS_DELETE;
2263 status = smb2_create(tree1, tctx, &(io.smb2));
2264 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2265 h1 = io.smb2.out.file.handle;
2266 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2268 torture_comment(tctx, "setfileinfo rename info should not trigger "
2269 "a break but should cause a sharing violation\n");
2270 ZERO_STRUCT(sfi);
2271 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2272 sfi.rename_information.in.file.handle = h1;
2273 sfi.rename_information.in.overwrite = 0;
2274 sfi.rename_information.in.new_name = fname2;
2276 status = smb2_setinfo_file(tree1, &sfi);
2277 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2278 "Incorrect status");
2280 torture_wait_for_oplock_break(tctx);
2281 CHECK_VAL(break_info.count, 0);
2283 ZERO_STRUCT(qfi);
2284 qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2285 qfi.generic.in.file.handle = h1;
2287 status = smb2_getinfo_file(tree1, tctx, &qfi);
2288 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2289 CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2291 torture_comment(tctx, "open the file a second time requesting batch "
2292 "(share mode: all)\n");
2293 ZERO_STRUCT(break_info);
2294 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2295 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2296 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2297 NTCREATEX_SHARE_ACCESS_WRITE|
2298 NTCREATEX_SHARE_ACCESS_DELETE;
2299 io.smb2.in.fname = fname1;
2300 status = smb2_create(tree2, tctx, &(io.smb2));
2301 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2302 h2 = io.smb2.out.file.handle;
2303 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2305 torture_wait_for_oplock_break(tctx);
2306 CHECK_VAL(break_info.count, 1);
2307 CHECK_VAL(break_info.failures, 0);
2308 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2310 torture_comment(tctx, "setfileinfo rename info should not trigger "
2311 "a break but should cause a sharing violation\n");
2312 ZERO_STRUCT(break_info);
2313 ZERO_STRUCT(sfi);
2314 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2315 sfi.rename_information.in.file.handle = h2;
2316 sfi.rename_information.in.overwrite = 0;
2317 sfi.rename_information.in.new_name = fname2;
2319 status = smb2_setinfo_file(tree2, &sfi);
2320 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2321 "Incorrect status");
2323 torture_wait_for_oplock_break(tctx);
2324 CHECK_VAL(break_info.count, 0);
2326 ZERO_STRUCT(qfi);
2327 qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2328 qfi.generic.in.file.handle = h1;
2330 status = smb2_getinfo_file(tree1, tctx, &qfi);
2331 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2332 CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2334 ZERO_STRUCT(qfi);
2335 qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2336 qfi.generic.in.file.handle = h2;
2338 status = smb2_getinfo_file(tree2, tctx, &qfi);
2339 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2340 CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2342 smb2_util_close(tree1, h1);
2343 smb2_util_close(tree2, h2);
2344 smb2_util_close(tree1, h);
2346 smb2_deltree(tree1, fname1);
2347 return ret;
2350 static bool test_smb2_oplock_batch21(struct torture_context *tctx,
2351 struct smb2_tree *tree1)
2353 const char *fname = BASEDIR "\\test_batch21.dat";
2354 NTSTATUS status;
2355 bool ret = true;
2356 union smb_open io;
2357 struct smb2_handle h, h1;
2358 char c = 0;
2360 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2361 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2363 /* cleanup */
2364 smb2_util_unlink(tree1, fname);
2366 tree1->session->transport->oplock.handler = torture_oplock_handler;
2367 tree1->session->transport->oplock.private_data = tree1;
2370 base ntcreatex parms
2372 ZERO_STRUCT(io.smb2);
2373 io.generic.level = RAW_OPEN_SMB2;
2374 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2375 io.smb2.in.alloc_size = 0;
2376 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2377 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2378 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2379 io.smb2.in.create_options = 0;
2380 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2381 io.smb2.in.security_flags = 0;
2382 io.smb2.in.fname = fname;
2385 with a batch oplock we get a break
2387 torture_comment(tctx, "BATCH21: open with batch oplock\n");
2388 ZERO_STRUCT(break_info);
2389 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2390 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2391 status = smb2_create(tree1, tctx, &(io.smb2));
2392 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2393 h1 = io.smb2.out.file.handle;
2394 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2396 torture_comment(tctx, "writing should not generate a break\n");
2397 status = smb2_util_write(tree1, h1, &c, 0, 1);
2398 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2400 torture_wait_for_oplock_break(tctx);
2401 CHECK_VAL(break_info.count, 0);
2403 smb2_util_close(tree1, h1);
2404 smb2_util_close(tree1, h);
2406 smb2_deltree(tree1, BASEDIR);
2407 return ret;
2410 static bool test_smb2_oplock_batch22(struct torture_context *tctx,
2411 struct smb2_tree *tree1)
2413 const char *fname = BASEDIR "\\test_batch22.dat";
2414 NTSTATUS status;
2415 bool ret = true;
2416 union smb_open io;
2417 struct smb2_handle h, h1, h2;
2418 struct timeval tv;
2419 int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
2420 int te;
2422 if (torture_setting_bool(tctx, "samba3", false)) {
2423 torture_skip(tctx, "BATCH22 disabled against samba3\n");
2426 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2427 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2429 /* cleanup */
2430 smb2_util_unlink(tree1, fname);
2432 tree1->session->transport->oplock.handler = torture_oplock_handler;
2433 tree1->session->transport->oplock.private_data = tree1;
2435 base ntcreatex parms
2437 ZERO_STRUCT(io.smb2);
2438 io.generic.level = RAW_OPEN_SMB2;
2439 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2440 io.smb2.in.alloc_size = 0;
2441 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2442 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2443 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2444 io.smb2.in.create_options = 0;
2445 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2446 io.smb2.in.security_flags = 0;
2447 io.smb2.in.fname = fname;
2450 with a batch oplock we get a break
2452 torture_comment(tctx, "BATCH22: open with batch oplock\n");
2453 ZERO_STRUCT(break_info);
2454 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2455 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2456 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2457 NTCREATEX_SHARE_ACCESS_WRITE|
2458 NTCREATEX_SHARE_ACCESS_DELETE;
2459 status = smb2_create(tree1, tctx, &(io.smb2));
2460 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2461 h1 = io.smb2.out.file.handle;
2462 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2464 torture_comment(tctx, "a 2nd open should succeed after the oplock "
2465 "break timeout\n");
2466 tv = timeval_current();
2467 tree1->session->transport->oplock.handler =
2468 torture_oplock_handler_timeout;
2469 status = smb2_create(tree1, tctx, &(io.smb2));
2470 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2471 h2 = io.smb2.out.file.handle;
2472 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2474 torture_wait_for_oplock_break(tctx);
2475 te = (int)timeval_elapsed(&tv);
2476 CHECK_RANGE(te, timeout - 1, timeout + 15);
2477 torture_comment(tctx, "waited %d seconds for oplock timeout\n", te);
2479 CHECK_VAL(break_info.count, 1);
2480 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
2481 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2482 CHECK_VAL(break_info.failures, 0);
2484 smb2_util_close(tree1, h1);
2485 smb2_util_close(tree1, h2);
2486 smb2_util_close(tree1, h);
2488 smb2_deltree(tree1, BASEDIR);
2489 return ret;
2492 static bool test_smb2_oplock_batch23(struct torture_context *tctx,
2493 struct smb2_tree *tree1,
2494 struct smb2_tree *tree2)
2496 const char *fname = BASEDIR "\\test_batch23.dat";
2497 NTSTATUS status;
2498 bool ret = true;
2499 union smb_open io;
2500 struct smb2_handle h, h1, h2, h3;
2501 struct smb2_tree *tree3 = NULL;
2503 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2504 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2506 /* cleanup */
2507 smb2_util_unlink(tree1, fname);
2509 ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
2510 CHECK_VAL(ret, true);
2512 tree1->session->transport->oplock.handler = torture_oplock_handler;
2513 tree1->session->transport->oplock.private_data = tree1;
2515 tree2->session->transport->oplock.handler = torture_oplock_handler;
2516 tree2->session->transport->oplock.private_data = tree2;
2518 tree3->session->transport->oplock.handler = torture_oplock_handler;
2519 tree3->session->transport->oplock.private_data = tree3;
2522 base ntcreatex parms
2524 ZERO_STRUCT(io.smb2);
2525 io.generic.level = RAW_OPEN_SMB2;
2526 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2527 io.smb2.in.alloc_size = 0;
2528 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2529 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2530 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2531 io.smb2.in.create_options = 0;
2532 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2533 io.smb2.in.security_flags = 0;
2534 io.smb2.in.fname = fname;
2536 torture_comment(tctx, "BATCH23: an open and ask for a batch oplock\n");
2537 ZERO_STRUCT(break_info);
2539 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
2540 SEC_RIGHTS_FILE_WRITE;
2541 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2542 NTCREATEX_SHARE_ACCESS_WRITE;
2543 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2544 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2545 status = smb2_create(tree1, tctx, &(io.smb2));
2546 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2547 h1 = io.smb2.out.file.handle;
2548 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2550 ZERO_STRUCT(break_info);
2552 torture_comment(tctx, "a 2nd open without level2 oplock support "
2553 "should generate a break to level2\n");
2554 status = smb2_create(tree3, tctx, &(io.smb2));
2555 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2556 h3 = io.smb2.out.file.handle;
2558 torture_wait_for_oplock_break(tctx);
2559 CHECK_VAL(break_info.count, 1);
2560 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
2561 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2562 CHECK_VAL(break_info.failures, 0);
2564 ZERO_STRUCT(break_info);
2566 torture_comment(tctx, "a 3rd open with level2 oplock support should "
2567 "not generate a break\n");
2568 status = smb2_create(tree2, tctx, &(io.smb2));
2569 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2570 h2 = io.smb2.out.file.handle;
2571 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2573 torture_wait_for_oplock_break(tctx);
2574 CHECK_VAL(break_info.count, 0);
2576 smb2_util_close(tree1, h1);
2577 smb2_util_close(tree2, h2);
2578 smb2_util_close(tree3, h3);
2579 smb2_util_close(tree1, h);
2581 smb2_deltree(tree1, BASEDIR);
2582 return ret;
2585 static bool test_smb2_oplock_batch24(struct torture_context *tctx,
2586 struct smb2_tree *tree1,
2587 struct smb2_tree *tree2)
2589 const char *fname = BASEDIR "\\test_batch24.dat";
2590 NTSTATUS status;
2591 bool ret = true;
2592 union smb_open io;
2593 struct smb2_handle h, h1, h2;
2594 struct smb2_tree *tree3 = NULL;
2596 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2597 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2599 /* cleanup */
2600 smb2_util_unlink(tree1, fname);
2602 ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
2603 CHECK_VAL(ret, true);
2605 tree1->session->transport->oplock.handler = torture_oplock_handler;
2606 tree1->session->transport->oplock.private_data = tree1;
2608 tree2->session->transport->oplock.handler = torture_oplock_handler;
2609 tree2->session->transport->oplock.private_data = tree2;
2611 tree3->session->transport->oplock.handler = torture_oplock_handler;
2612 tree3->session->transport->oplock.private_data = tree3;
2615 base ntcreatex parms
2617 ZERO_STRUCT(io.smb2);
2618 io.generic.level = RAW_OPEN_SMB2;
2619 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2620 io.smb2.in.alloc_size = 0;
2621 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2622 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2623 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2624 io.smb2.in.create_options = 0;
2625 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2626 io.smb2.in.security_flags = 0;
2627 io.smb2.in.fname = fname;
2629 torture_comment(tctx, "BATCH24: a open without level support and "
2630 "ask for a batch oplock\n");
2631 ZERO_STRUCT(break_info);
2633 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
2634 SEC_RIGHTS_FILE_WRITE;
2635 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2636 NTCREATEX_SHARE_ACCESS_WRITE;
2637 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2638 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2640 status = smb2_create(tree3, tctx, &(io.smb2));
2641 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2642 h2 = io.smb2.out.file.handle;
2643 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2645 ZERO_STRUCT(break_info);
2647 torture_comment(tctx, "a 2nd open with level2 oplock support should "
2648 "generate a break\n");
2649 status = smb2_create(tree2, tctx, &(io.smb2));
2650 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2651 h1 = io.smb2.out.file.handle;
2652 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2654 torture_wait_for_oplock_break(tctx);
2655 CHECK_VAL(break_info.count, 1);
2656 CHECK_VAL(break_info.handle.data[0], h2.data[0]);
2657 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2658 CHECK_VAL(break_info.failures, 0);
2660 smb2_util_close(tree3, h2);
2661 smb2_util_close(tree2, h1);
2662 smb2_util_close(tree1, h);
2664 smb2_deltree(tree1, BASEDIR);
2665 return ret;
2668 static bool test_smb2_oplock_batch25(struct torture_context *tctx,
2669 struct smb2_tree *tree1)
2671 const char *fname = BASEDIR "\\test_batch25.dat";
2672 NTSTATUS status;
2673 bool ret = true;
2674 union smb_open io;
2675 struct smb2_handle h, h1;
2677 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2678 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2680 /* cleanup */
2681 smb2_util_unlink(tree1, fname);
2683 tree1->session->transport->oplock.handler = torture_oplock_handler;
2684 tree1->session->transport->oplock.private_data = tree1;
2687 base ntcreatex parms
2689 ZERO_STRUCT(io.smb2);
2690 io.generic.level = RAW_OPEN_SMB2;
2691 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2692 io.smb2.in.alloc_size = 0;
2693 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2694 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2695 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2696 io.smb2.in.create_options = 0;
2697 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2698 io.smb2.in.security_flags = 0;
2699 io.smb2.in.fname = fname;
2701 torture_comment(tctx, "BATCH25: open a file with an batch oplock "
2702 "(share mode: none)\n");
2704 ZERO_STRUCT(break_info);
2705 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2706 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2708 status = smb2_create(tree1, tctx, &(io.smb2));
2709 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2710 h1 = io.smb2.out.file.handle;
2711 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2713 torture_comment(tctx, "changing the file attribute info should trigger "
2714 "a break and a violation\n");
2716 status = smb2_util_setatr(tree1, fname, FILE_ATTRIBUTE_HIDDEN);
2717 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2718 "Incorrect status");
2720 torture_wait_for_oplock_break(tctx);
2721 CHECK_VAL(break_info.count, 1);
2723 smb2_util_close(tree1, h1);
2724 smb2_util_close(tree1, h);
2726 smb2_deltree(tree1, fname);
2727 return ret;
2730 /* Test how oplocks work on streams. */
2731 static bool test_raw_oplock_stream1(struct torture_context *tctx,
2732 struct smb2_tree *tree1,
2733 struct smb2_tree *tree2)
2735 NTSTATUS status;
2736 union smb_open io;
2737 const char *fname_base = BASEDIR "\\test_stream1.txt";
2738 const char *fname_stream, *fname_default_stream;
2739 const char *default_stream = "::$DATA";
2740 const char *stream = "Stream One:$DATA";
2741 bool ret = true;
2742 struct smb2_handle h, h_base, h_stream;
2743 int i;
2745 #define NSTREAM_OPLOCK_RESULTS 8
2746 struct {
2747 const char **fname;
2748 bool open_base_file;
2749 uint32_t oplock_req;
2750 uint32_t oplock_granted;
2751 } stream_oplock_results[NSTREAM_OPLOCK_RESULTS] = {
2752 /* Request oplock on stream without the base file open. */
2753 {&fname_stream, false, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
2754 {&fname_default_stream, false, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
2755 {&fname_stream, false, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
2756 {&fname_default_stream, false, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
2758 /* Request oplock on stream with the base file open. */
2759 {&fname_stream, true, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
2760 {&fname_default_stream, true, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_II},
2761 {&fname_stream, true, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
2762 {&fname_default_stream, true, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_II},
2765 /* Only passes against windows at the moment. */
2766 if (torture_setting_bool(tctx, "samba3", false) ||
2767 torture_setting_bool(tctx, "samba4", false)) {
2768 torture_skip(tctx, "STREAM1 disabled against samba3+4\n");
2771 fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
2772 fname_default_stream = talloc_asprintf(tctx, "%s%s", fname_base,
2773 default_stream);
2775 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2776 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2778 /* Initialize handles to "closed". Using -1 in the first 64-bytes
2779 * as the sentry for this */
2780 h_stream.data[0] = -1;
2782 /* cleanup */
2783 smb2_util_unlink(tree1, fname_base);
2785 tree1->session->transport->oplock.handler = torture_oplock_handler;
2786 tree1->session->transport->oplock.private_data = tree1;
2788 tree2->session->transport->oplock.handler = torture_oplock_handler;
2789 tree2->session->transport->oplock.private_data = tree2;
2791 /* Setup generic open parameters. */
2792 ZERO_STRUCT(io.smb2);
2793 io.generic.level = RAW_OPEN_SMB2;
2794 io.smb2.in.desired_access = (SEC_FILE_READ_DATA |
2795 SEC_FILE_WRITE_DATA |
2796 SEC_FILE_APPEND_DATA |
2797 SEC_STD_READ_CONTROL);
2798 io.smb2.in.alloc_size = 0;
2799 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2800 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2801 NTCREATEX_SHARE_ACCESS_WRITE;
2802 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2803 io.smb2.in.create_options = 0;
2804 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2805 io.smb2.in.security_flags = 0;
2807 /* Create the file with a stream */
2808 io.smb2.in.fname = fname_stream;
2809 io.smb2.in.create_flags = 0;
2810 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2811 status = smb2_create(tree1, tctx, &(io.smb2));
2812 torture_assert_ntstatus_ok(tctx, status, "Error creating file");
2813 smb2_util_close(tree1, io.smb2.out.file.handle);
2815 /* Change the disposition to open now that the file has been created. */
2816 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
2818 /* Try some permutations of taking oplocks on streams. */
2819 for (i = 0; i < NSTREAM_OPLOCK_RESULTS; i++) {
2820 const char *fname = *stream_oplock_results[i].fname;
2821 bool open_base_file = stream_oplock_results[i].open_base_file;
2822 uint32_t oplock_req = stream_oplock_results[i].oplock_req;
2823 uint32_t oplock_granted =
2824 stream_oplock_results[i].oplock_granted;
2826 if (open_base_file) {
2827 torture_comment(tctx, "Opening base file: %s with "
2828 "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
2829 io.smb2.in.fname = fname_base;
2830 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2831 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2832 status = smb2_create(tree2, tctx, &(io.smb2));
2833 torture_assert_ntstatus_ok(tctx, status,
2834 "Error opening file");
2835 CHECK_VAL(io.smb2.out.oplock_level,
2836 SMB2_OPLOCK_LEVEL_BATCH);
2837 h_base = io.smb2.out.file.handle;
2840 torture_comment(tctx, "%d: Opening stream: %s with %d\n", i,
2841 fname, oplock_req);
2842 io.smb2.in.fname = fname;
2843 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2844 io.smb2.in.oplock_level = oplock_req;
2846 /* Do the open with the desired oplock on the stream. */
2847 status = smb2_create(tree1, tctx, &(io.smb2));
2848 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
2849 CHECK_VAL(io.smb2.out.oplock_level, oplock_granted);
2850 smb2_util_close(tree1, io.smb2.out.file.handle);
2852 /* Cleanup the base file if it was opened. */
2853 if (open_base_file)
2854 smb2_util_close(tree2, h_base);
2857 /* Open the stream with an exclusive oplock. */
2858 torture_comment(tctx, "Opening stream: %s with %d\n",
2859 fname_stream, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
2860 io.smb2.in.fname = fname_stream;
2861 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2862 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
2863 status = smb2_create(tree1, tctx, &(io.smb2));
2864 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
2865 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
2866 h_stream = io.smb2.out.file.handle;
2868 /* Open the base file and see if it contends. */
2869 ZERO_STRUCT(break_info);
2870 torture_comment(tctx, "Opening base file: %s with %d\n",
2871 fname_base, SMB2_OPLOCK_LEVEL_BATCH);
2872 io.smb2.in.fname = fname_base;
2873 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2874 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2875 status = smb2_create(tree2, tctx, &(io.smb2));
2876 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
2877 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2878 smb2_util_close(tree2, io.smb2.out.file.handle);
2880 torture_wait_for_oplock_break(tctx);
2881 CHECK_VAL(break_info.count, 0);
2882 CHECK_VAL(break_info.failures, 0);
2884 /* Open the stream again to see if it contends. */
2885 ZERO_STRUCT(break_info);
2886 torture_comment(tctx, "Opening stream again: %s with "
2887 "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
2888 io.smb2.in.fname = fname_stream;
2889 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2890 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
2891 status = smb2_create(tree2, tctx, &(io.smb2));
2892 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
2893 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2894 smb2_util_close(tree2, io.smb2.out.file.handle);
2896 torture_wait_for_oplock_break(tctx);
2897 CHECK_VAL(break_info.count, 1);
2898 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2899 CHECK_VAL(break_info.failures, 0);
2901 /* Close the stream. */
2902 if (h_stream.data[0] != -1) {
2903 smb2_util_close(tree1, h_stream);
2906 smb2_util_close(tree1, h);
2908 smb2_deltree(tree1, BASEDIR);
2909 return ret;
2912 static bool test_smb2_oplock_doc(struct torture_context *tctx, struct smb2_tree *tree)
2914 const char *fname = BASEDIR "\\test_oplock_doc.dat";
2915 NTSTATUS status;
2916 bool ret = true;
2917 union smb_open io;
2918 struct smb2_handle h, h1;
2920 status = torture_smb2_testdir(tree, BASEDIR, &h);
2921 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2923 /* cleanup */
2924 smb2_util_unlink(tree, fname);
2925 tree->session->transport->oplock.handler = torture_oplock_handler;
2926 tree->session->transport->oplock.private_data = tree;
2929 base ntcreatex parms
2931 ZERO_STRUCT(io.smb2);
2932 io.generic.level = RAW_OPEN_SMB2;
2933 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2934 io.smb2.in.alloc_size = 0;
2935 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2936 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2937 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2938 io.smb2.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
2939 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2940 io.smb2.in.security_flags = 0;
2941 io.smb2.in.fname = fname;
2943 torture_comment(tctx, "open a delete-on-close file with a batch "
2944 "oplock\n");
2945 ZERO_STRUCT(break_info);
2946 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2947 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2949 status = smb2_create(tree, tctx, &(io.smb2));
2950 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2951 h1 = io.smb2.out.file.handle;
2952 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2954 smb2_util_close(tree, h1);
2956 smb2_util_unlink(tree, fname);
2957 smb2_deltree(tree, BASEDIR);
2958 return ret;
2961 /* Open a file with a batch oplock, then open it again from a second client
2962 * requesting no oplock. Having two open file handles should break our own
2963 * oplock during BRL acquisition.
2965 static bool test_smb2_oplock_brl1(struct torture_context *tctx,
2966 struct smb2_tree *tree1,
2967 struct smb2_tree *tree2)
2969 const char *fname = BASEDIR "\\test_batch_brl.dat";
2970 /*int fname, f;*/
2971 bool ret = true;
2972 uint8_t buf[1000];
2973 bool correct = true;
2974 union smb_open io;
2975 NTSTATUS status;
2976 struct smb2_lock lck;
2977 struct smb2_lock_element lock[1];
2978 struct smb2_handle h, h1, h2;
2980 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2981 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2983 /* cleanup */
2984 smb2_util_unlink(tree1, fname);
2986 tree1->session->transport->oplock.handler =
2987 torture_oplock_handler_two_notifications;
2988 tree1->session->transport->oplock.private_data = tree1;
2991 base ntcreatex parms
2993 ZERO_STRUCT(io.smb2);
2994 io.generic.level = RAW_OPEN_SMB2;
2995 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
2996 SEC_RIGHTS_FILE_WRITE;
2997 io.smb2.in.alloc_size = 0;
2998 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2999 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3000 NTCREATEX_SHARE_ACCESS_WRITE;
3001 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3002 io.smb2.in.create_options = 0;
3003 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3004 io.smb2.in.security_flags = 0;
3005 io.smb2.in.fname = fname;
3008 with a batch oplock we get a break
3010 torture_comment(tctx, "open with batch oplock\n");
3011 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3012 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3014 status = smb2_create(tree1, tctx, &(io.smb2));
3015 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3016 h1 = io.smb2.out.file.handle;
3017 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3019 /* create a file with bogus data */
3020 memset(buf, 0, sizeof(buf));
3022 status = smb2_util_write(tree1, h1,buf, 0, sizeof(buf));
3023 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3024 torture_comment(tctx, "Failed to create file\n");
3025 correct = false;
3026 goto done;
3029 torture_comment(tctx, "a 2nd open should give a break\n");
3030 ZERO_STRUCT(break_info);
3032 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3033 io.smb2.in.oplock_level = 0;
3034 status = smb2_create(tree2, tctx, &(io.smb2));
3035 h2 = io.smb2.out.file.handle;
3036 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3038 torture_wait_for_oplock_break(tctx);
3039 CHECK_VAL(break_info.count, 1);
3040 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
3041 CHECK_VAL(break_info.failures, 0);
3042 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3044 ZERO_STRUCT(break_info);
3046 torture_comment(tctx, "a self BRL acquisition should break to none\n");
3047 lock[0].offset = 0;
3048 lock[0].length = 4;
3049 lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3050 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3052 ZERO_STRUCT(lck);
3053 lck.in.file.handle = h1;
3054 lck.in.locks = &lock[0];
3055 lck.in.lock_count = 1;
3056 status = smb2_lock(tree1, &lck);
3057 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3059 torture_wait_for_oplock_break(tctx);
3060 CHECK_VAL(break_info.count, 1);
3061 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
3062 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3063 CHECK_VAL(break_info.failures, 0);
3065 /* expect no oplock break */
3066 ZERO_STRUCT(break_info);
3067 lock[0].offset = 2;
3068 status = smb2_lock(tree1, &lck);
3069 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3070 "Incorrect status");
3072 torture_wait_for_oplock_break(tctx);
3073 CHECK_VAL(break_info.count, 0);
3074 CHECK_VAL(break_info.level, 0);
3075 CHECK_VAL(break_info.failures, 0);
3077 smb2_util_close(tree1, h1);
3078 smb2_util_close(tree2, h2);
3079 smb2_util_close(tree1, h);
3081 done:
3082 smb2_deltree(tree1, BASEDIR);
3083 return ret;
3087 /* Open a file with a batch oplock on one tree and then acquire a brl.
3088 * We should not contend our own oplock.
3090 static bool test_smb2_oplock_brl2(struct torture_context *tctx, struct smb2_tree *tree1)
3092 const char *fname = BASEDIR "\\test_batch_brl.dat";
3093 /*int fname, f;*/
3094 bool ret = true;
3095 uint8_t buf[1000];
3096 bool correct = true;
3097 union smb_open io;
3098 NTSTATUS status;
3099 struct smb2_handle h, h1;
3100 struct smb2_lock lck;
3101 struct smb2_lock_element lock[1];
3103 status = torture_smb2_testdir(tree1, BASEDIR, &h);
3104 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3106 /* cleanup */
3107 smb2_util_unlink(tree1, fname);
3109 tree1->session->transport->oplock.handler = torture_oplock_handler;
3110 tree1->session->transport->oplock.private_data = tree1;
3113 base ntcreatex parms
3115 ZERO_STRUCT(io.smb2);
3116 io.generic.level = RAW_OPEN_SMB2;
3117 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3118 SEC_RIGHTS_FILE_WRITE;
3119 io.smb2.in.alloc_size = 0;
3120 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3121 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3122 NTCREATEX_SHARE_ACCESS_WRITE;
3123 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3124 io.smb2.in.create_options = 0;
3125 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3126 io.smb2.in.security_flags = 0;
3127 io.smb2.in.fname = fname;
3130 with a batch oplock we get a break
3132 torture_comment(tctx, "open with batch oplock\n");
3133 ZERO_STRUCT(break_info);
3134 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3135 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3137 status = smb2_create(tree1, tctx, &(io.smb2));
3138 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3139 h1 = io.smb2.out.file.handle;
3140 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3142 /* create a file with bogus data */
3143 memset(buf, 0, sizeof(buf));
3145 status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
3146 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3147 torture_comment(tctx, "Failed to create file\n");
3148 correct = false;
3149 goto done;
3152 ZERO_STRUCT(break_info);
3154 torture_comment(tctx, "a self BRL acquisition should not break to "
3155 "none\n");
3157 lock[0].offset = 0;
3158 lock[0].length = 4;
3159 lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3160 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3162 ZERO_STRUCT(lck);
3163 lck.in.file.handle = h1;
3164 lck.in.locks = &lock[0];
3165 lck.in.lock_count = 1;
3166 status = smb2_lock(tree1, &lck);
3167 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3169 lock[0].offset = 2;
3170 status = smb2_lock(tree1, &lck);
3171 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3172 "Incorrect status");
3174 /* With one file handle open a BRL should not contend our oplock.
3175 * Thus, no oplock break will be received and the entire break_info
3176 * struct will be 0 */
3177 torture_wait_for_oplock_break(tctx);
3178 CHECK_VAL(break_info.count, 0);
3179 CHECK_VAL(break_info.level, 0);
3180 CHECK_VAL(break_info.failures, 0);
3182 smb2_util_close(tree1, h1);
3183 smb2_util_close(tree1, h);
3185 done:
3186 smb2_deltree(tree1, BASEDIR);
3187 return ret;
3190 /* Open a file with a batch oplock twice from one tree and then acquire a
3191 * brl. BRL acquisition should break our own oplock.
3193 static bool test_smb2_oplock_brl3(struct torture_context *tctx, struct smb2_tree *tree1)
3195 const char *fname = BASEDIR "\\test_batch_brl.dat";
3196 bool ret = true;
3197 uint8_t buf[1000];
3198 bool correct = true;
3199 union smb_open io;
3200 NTSTATUS status;
3201 struct smb2_handle h, h1, h2;
3202 struct smb2_lock lck;
3203 struct smb2_lock_element lock[1];
3205 status = torture_smb2_testdir(tree1, BASEDIR, &h);
3206 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3208 /* cleanup */
3209 smb2_util_unlink(tree1, fname);
3210 tree1->session->transport->oplock.handler =
3211 torture_oplock_handler_two_notifications;
3212 tree1->session->transport->oplock.private_data = tree1;
3215 base ntcreatex parms
3217 ZERO_STRUCT(io.smb2);
3218 io.generic.level = RAW_OPEN_SMB2;
3219 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3220 SEC_RIGHTS_FILE_WRITE;
3221 io.smb2.in.alloc_size = 0;
3222 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3223 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3224 NTCREATEX_SHARE_ACCESS_WRITE;
3225 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3226 io.smb2.in.create_options = 0;
3227 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3228 io.smb2.in.security_flags = 0;
3229 io.smb2.in.fname = fname;
3232 with a batch oplock we get a break
3234 torture_comment(tctx, "open with batch oplock\n");
3235 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3236 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3238 status = smb2_create(tree1, tctx, &(io.smb2));
3239 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3240 h1 = io.smb2.out.file.handle;
3241 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3243 /* create a file with bogus data */
3244 memset(buf, 0, sizeof(buf));
3245 status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
3247 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3248 torture_comment(tctx, "Failed to create file\n");
3249 correct = false;
3250 goto done;
3253 torture_comment(tctx, "a 2nd open should give a break\n");
3254 ZERO_STRUCT(break_info);
3256 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3257 io.smb2.in.oplock_level = 0;
3258 status = smb2_create(tree1, tctx, &(io.smb2));
3259 h2 = io.smb2.out.file.handle;
3260 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3261 CHECK_VAL(break_info.count, 1);
3262 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
3263 CHECK_VAL(break_info.failures, 0);
3264 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3266 ZERO_STRUCT(break_info);
3268 torture_comment(tctx, "a self BRL acquisition should break to none\n");
3270 lock[0].offset = 0;
3271 lock[0].length = 4;
3272 lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3273 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3275 ZERO_STRUCT(lck);
3276 lck.in.file.handle = h1;
3277 lck.in.locks = &lock[0];
3278 lck.in.lock_count = 1;
3279 status = smb2_lock(tree1, &lck);
3280 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3282 torture_wait_for_oplock_break(tctx);
3283 CHECK_VAL(break_info.count, 1);
3284 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
3285 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3286 CHECK_VAL(break_info.failures, 0);
3288 /* expect no oplock break */
3289 ZERO_STRUCT(break_info);
3290 lock[0].offset = 2;
3291 status = smb2_lock(tree1, &lck);
3292 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3293 "Incorrect status");
3295 torture_wait_for_oplock_break(tctx);
3296 CHECK_VAL(break_info.count, 0);
3297 CHECK_VAL(break_info.level, 0);
3298 CHECK_VAL(break_info.failures, 0);
3300 smb2_util_close(tree1, h1);
3301 smb2_util_close(tree1, h2);
3302 smb2_util_close(tree1, h);
3304 done:
3305 smb2_deltree(tree1, BASEDIR);
3306 return ret;
3310 /* Starting the SMB2 specific oplock tests at 500 so we can keep the SMB1
3311 * tests in sync with an identically numbered SMB2 test */
3313 /* Test whether the server correctly returns an error when we send
3314 * a response to a levelII to none oplock notification. */
3315 static bool test_smb2_oplock_levelII500(struct torture_context *tctx,
3316 struct smb2_tree *tree1)
3318 const char *fname = BASEDIR "\\test_levelII500.dat";
3319 NTSTATUS status;
3320 bool ret = true;
3321 union smb_open io;
3322 struct smb2_handle h, h1;
3323 char c = 0;
3325 status = torture_smb2_testdir(tree1, BASEDIR, &h);
3326 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3328 /* cleanup */
3329 smb2_util_unlink(tree1, fname);
3331 tree1->session->transport->oplock.handler = torture_oplock_handler;
3332 tree1->session->transport->oplock.private_data = tree1;
3335 base ntcreatex parms
3337 ZERO_STRUCT(io.smb2);
3338 io.generic.level = RAW_OPEN_SMB2;
3339 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3340 io.smb2.in.alloc_size = 0;
3341 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3342 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3343 io.smb2.in.create_options = 0;
3344 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3345 io.smb2.in.security_flags = 0;
3346 io.smb2.in.fname = fname;
3348 torture_comment(tctx, "LEVELII500: acknowledging a break from II to "
3349 "none should return an error\n");
3350 ZERO_STRUCT(break_info);
3352 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3353 SEC_RIGHTS_FILE_WRITE;
3354 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3355 NTCREATEX_SHARE_ACCESS_WRITE;
3356 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3357 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
3358 status = smb2_create(tree1, tctx, &(io.smb2));
3359 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3360 h1 = io.smb2.out.file.handle;
3361 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
3363 ZERO_STRUCT(break_info);
3365 torture_comment(tctx, "write should trigger a break to none and when "
3366 "we reply, an oplock break failure\n");
3367 smb2_util_write(tree1, h1, &c, 0, 1);
3369 /* Wait several times to receive both the break notification, and the
3370 * NT_STATUS_INVALID_OPLOCK_PROTOCOL error in the break response */
3371 torture_wait_for_oplock_break(tctx);
3372 torture_wait_for_oplock_break(tctx);
3373 torture_wait_for_oplock_break(tctx);
3374 torture_wait_for_oplock_break(tctx);
3376 /* There appears to be a race condition in W2K8 and W2K8R2 where
3377 * sometimes the server will happily reply to our break response with
3378 * NT_STATUS_OK, and sometimes it will return the OPLOCK_PROTOCOL
3379 * error. As the MS-SMB2 doc states that a client should not reply to
3380 * a level2 to none break notification, I'm leaving the protocol error
3381 * as the expected behavior. */
3382 CHECK_VAL(break_info.count, 1);
3383 CHECK_VAL(break_info.level, 0);
3384 CHECK_VAL(break_info.failures, 1);
3385 torture_assert_ntstatus_equal(tctx, break_info.failure_status,
3386 NT_STATUS_INVALID_OPLOCK_PROTOCOL,
3387 "Incorrect status");
3389 smb2_util_close(tree1, h1);
3390 smb2_util_close(tree1, h);
3392 smb2_deltree(tree1, BASEDIR);
3393 return ret;
3396 struct torture_suite *torture_smb2_oplocks_init(void)
3398 struct torture_suite *suite =
3399 torture_suite_create(talloc_autofree_context(), "oplock");
3401 torture_suite_add_2smb2_test(suite, "exclusive1", test_smb2_oplock_exclusive1);
3402 torture_suite_add_2smb2_test(suite, "exclusive2", test_smb2_oplock_exclusive2);
3403 torture_suite_add_2smb2_test(suite, "exclusive3", test_smb2_oplock_exclusive3);
3404 torture_suite_add_2smb2_test(suite, "exclusive4", test_smb2_oplock_exclusive4);
3405 torture_suite_add_2smb2_test(suite, "exclusive5", test_smb2_oplock_exclusive5);
3406 torture_suite_add_2smb2_test(suite, "exclusive6", test_smb2_oplock_exclusive6);
3407 torture_suite_add_2smb2_test(suite, "batch1", test_smb2_oplock_batch1);
3408 torture_suite_add_2smb2_test(suite, "batch2", test_smb2_oplock_batch2);
3409 torture_suite_add_2smb2_test(suite, "batch3", test_smb2_oplock_batch3);
3410 torture_suite_add_2smb2_test(suite, "batch4", test_smb2_oplock_batch4);
3411 torture_suite_add_2smb2_test(suite, "batch5", test_smb2_oplock_batch5);
3412 torture_suite_add_2smb2_test(suite, "batch6", test_smb2_oplock_batch6);
3413 torture_suite_add_2smb2_test(suite, "batch7", test_smb2_oplock_batch7);
3414 torture_suite_add_2smb2_test(suite, "batch8", test_smb2_oplock_batch8);
3415 torture_suite_add_2smb2_test(suite, "batch9", test_smb2_oplock_batch9);
3416 torture_suite_add_2smb2_test(suite, "batch10", test_smb2_oplock_batch10);
3417 torture_suite_add_2smb2_test(suite, "batch11", test_smb2_oplock_batch11);
3418 torture_suite_add_2smb2_test(suite, "batch12", test_smb2_oplock_batch12);
3419 torture_suite_add_2smb2_test(suite, "batch13", test_smb2_oplock_batch13);
3420 torture_suite_add_2smb2_test(suite, "batch14", test_smb2_oplock_batch14);
3421 torture_suite_add_2smb2_test(suite, "batch15", test_smb2_oplock_batch15);
3422 torture_suite_add_2smb2_test(suite, "batch16", test_smb2_oplock_batch16);
3423 torture_suite_add_1smb2_test(suite, "batch19", test_smb2_oplock_batch19);
3424 torture_suite_add_2smb2_test(suite, "batch20", test_smb2_oplock_batch20);
3425 torture_suite_add_1smb2_test(suite, "batch21", test_smb2_oplock_batch21);
3426 torture_suite_add_1smb2_test(suite, "batch22", test_smb2_oplock_batch22);
3427 torture_suite_add_2smb2_test(suite, "batch23", test_smb2_oplock_batch23);
3428 torture_suite_add_2smb2_test(suite, "batch24", test_smb2_oplock_batch24);
3429 torture_suite_add_1smb2_test(suite, "batch25", test_smb2_oplock_batch25);
3430 torture_suite_add_2smb2_test(suite, "stream1", test_raw_oplock_stream1);
3431 torture_suite_add_1smb2_test(suite, "doc", test_smb2_oplock_doc);
3432 torture_suite_add_2smb2_test(suite, "brl1", test_smb2_oplock_brl1);
3433 torture_suite_add_1smb2_test(suite, "brl2", test_smb2_oplock_brl2);
3434 torture_suite_add_1smb2_test(suite, "brl3", test_smb2_oplock_brl3);
3435 torture_suite_add_1smb2_test(suite, "levelii500", test_smb2_oplock_levelII500);
3437 suite->description = talloc_strdup(suite, "SMB2-OPLOCK tests");
3439 return suite;
3443 stress testing of oplocks
3445 bool test_smb2_bench_oplock(struct torture_context *tctx,
3446 struct smb2_tree *tree)
3448 struct smb2_tree **trees;
3449 bool ret = true;
3450 NTSTATUS status;
3451 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3452 int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
3453 int i, count=0;
3454 int timelimit = torture_setting_int(tctx, "timelimit", 10);
3455 union smb_open io;
3456 struct timeval tv;
3457 struct smb2_handle h;
3459 trees = talloc_array(mem_ctx, struct smb2_tree *, torture_nprocs);
3461 torture_comment(tctx, "Opening %d connections\n", torture_nprocs);
3462 for (i=0;i<torture_nprocs;i++) {
3463 if (!torture_smb2_connection(tctx, &trees[i])) {
3464 return false;
3466 talloc_steal(mem_ctx, trees[i]);
3467 trees[i]->session->transport->oplock.handler =
3468 torture_oplock_handler_close;
3469 trees[i]->session->transport->oplock.private_data = trees[i];
3472 status = torture_smb2_testdir(trees[0], BASEDIR, &h);
3473 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3475 ZERO_STRUCT(io.smb2);
3476 io.smb2.level = RAW_OPEN_SMB2;
3477 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3478 io.smb2.in.alloc_size = 0;
3479 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3480 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3481 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3482 io.smb2.in.create_options = 0;
3483 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3484 io.smb2.in.security_flags = 0;
3485 io.smb2.in.fname = BASEDIR "\\test.dat";
3486 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3487 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3489 tv = timeval_current();
3492 we open the same file with SHARE_ACCESS_NONE from all the
3493 connections in a round robin fashion. Each open causes an
3494 oplock break on the previous connection, which is answered
3495 by the oplock_handler_close() to close the file.
3497 This measures how fast we can pass on oplocks, and stresses
3498 the oplock handling code
3500 torture_comment(tctx, "Running for %d seconds\n", timelimit);
3501 while (timeval_elapsed(&tv) < timelimit) {
3502 for (i=0;i<torture_nprocs;i++) {
3503 status = smb2_create(trees[i], mem_ctx, &(io.smb2));
3504 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3505 count++;
3508 if (torture_setting_bool(tctx, "progress", true)) {
3509 torture_comment(tctx, "%.2f ops/second\r",
3510 count/timeval_elapsed(&tv));
3514 torture_comment(tctx, "%.2f ops/second\n", count/timeval_elapsed(&tv));
3515 smb2_util_close(trees[0], io.smb2.out.file.handle);
3516 smb2_util_unlink(trees[0], BASEDIR "\\test.dat");
3517 smb2_deltree(trees[0], BASEDIR);
3518 talloc_free(mem_ctx);
3519 return ret;
3522 static struct hold_oplock_info {
3523 const char *fname;
3524 bool close_on_break;
3525 uint32_t share_access;
3526 struct smb2_handle handle;
3527 } hold_info[] = {
3528 { BASEDIR "\\notshared_close", true,
3529 NTCREATEX_SHARE_ACCESS_NONE, },
3530 { BASEDIR "\\notshared_noclose", false,
3531 NTCREATEX_SHARE_ACCESS_NONE, },
3532 { BASEDIR "\\shared_close", true,
3533 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
3534 { BASEDIR "\\shared_noclose", false,
3535 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
3538 static bool torture_oplock_handler_hold(struct smb2_transport *transport,
3539 const struct smb2_handle *handle,
3540 uint8_t level, void *private_data)
3542 struct hold_oplock_info *info;
3543 int i;
3545 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
3546 if (smb2_util_handle_equal(hold_info[i].handle, *handle))
3547 break;
3550 if (i == ARRAY_SIZE(hold_info)) {
3551 printf("oplock break for unknown handle 0x%llx%llx\n",
3552 (unsigned long long) handle->data[0],
3553 (unsigned long long) handle->data[1]);
3554 return false;
3557 info = &hold_info[i];
3559 if (info->close_on_break) {
3560 printf("oplock break on %s - closing\n", info->fname);
3561 torture_oplock_handler_close(transport, handle,
3562 level, private_data);
3563 return true;
3566 printf("oplock break on %s - acking break\n", info->fname);
3567 printf("Acking to none in oplock handler\n");
3569 torture_oplock_handler_ack_to_none(transport, handle,
3570 level, private_data);
3571 return true;
3575 used for manual testing of oplocks - especially interaction with
3576 other filesystems (such as NFS and local access)
3578 bool test_smb2_hold_oplock(struct torture_context *tctx,
3579 struct smb2_tree *tree)
3581 struct torture_context *mem_ctx = talloc_new(tctx);
3582 struct tevent_context *ev = tctx->ev;
3583 int i;
3584 struct smb2_handle h;
3585 NTSTATUS status;
3587 torture_comment(tctx, "Setting up open files with oplocks in %s\n",
3588 BASEDIR);
3590 status = torture_smb2_testdir(tree, BASEDIR, &h);
3591 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3593 tree->session->transport->oplock.handler = torture_oplock_handler_hold;
3594 tree->session->transport->oplock.private_data = tree;
3596 /* setup the files */
3597 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
3598 union smb_open io;
3599 char c = 1;
3601 ZERO_STRUCT(io.smb2);
3602 io.generic.level = RAW_OPEN_SMB2;
3603 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3604 io.smb2.in.alloc_size = 0;
3605 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3606 io.smb2.in.share_access = hold_info[i].share_access;
3607 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3608 io.smb2.in.create_options = 0;
3609 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3610 io.smb2.in.security_flags = 0;
3611 io.smb2.in.fname = hold_info[i].fname;
3612 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3613 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3615 torture_comment(tctx, "opening %s\n", hold_info[i].fname);
3617 status = smb2_create(tree, mem_ctx, &(io.smb2));
3618 if (!NT_STATUS_IS_OK(status)) {
3619 torture_comment(tctx, "Failed to open %s - %s\n",
3620 hold_info[i].fname, nt_errstr(status));
3621 return false;
3624 if (io.smb2.out.oplock_level != SMB2_OPLOCK_LEVEL_BATCH) {
3625 torture_comment(tctx, "Oplock not granted for %s - "
3626 "expected %d but got %d\n",
3627 hold_info[i].fname,
3628 SMB2_OPLOCK_LEVEL_BATCH,
3629 io.smb2.out.oplock_level);
3630 return false;
3632 hold_info[i].handle = io.smb2.out.file.handle;
3634 /* make the file non-zero size */
3635 status = smb2_util_write(tree, hold_info[i].handle, &c, 0, 1);
3636 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3637 torture_comment(tctx, "Failed to write to file\n");
3638 return false;
3642 torture_comment(tctx, "Waiting for oplock events\n");
3643 tevent_loop_wait(ev);
3644 smb2_deltree(tree, BASEDIR);
3645 talloc_free(mem_ctx);
3646 return true;