f686de6a2f761a3f771ce7c5aa82b313fcf12708
[gd/samba/.git] / source4 / torture / smb2 / oplock.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    test suite for SMB2 oplocks
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Stefan Metzmacher 2008
8
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.
13
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.
18
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/>.
21 */
22
23 #include "includes.h"
24
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"
29
30 #include "lib/cmdline/popt_common.h"
31 #include "lib/events/events.h"
32
33 #include "param/param.h"
34 #include "system/filesys.h"
35
36 #include "torture/torture.h"
37 #include "torture/smb2/proto.h"
38
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)
46
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)
54
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)
62
63 #define BASEDIR "oplock_test"
64
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;
73
74 static void torture_oplock_break_callback(struct smb2_request *req)
75 {
76         NTSTATUS status;
77         struct smb2_break br;
78
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;
84         }
85
86         return;
87 }
88
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)
95 {
96         struct smb2_tree *tree = private_data;
97         const char *name;
98         struct smb2_request *req;
99         ZERO_STRUCT(break_info.br);
100
101         break_info.handle       = *handle;
102         break_info.level        = level;
103         break_info.count++;
104
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++;
115         }
116         printf("Acking to %s [0x%02X] in oplock handler\n", name, level);
117
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;
122
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;
127 }
128
129 /*
130   A handler function for oplock break notifications. Send a break to none
131   request.
132 */
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)
137 {
138         struct smb2_tree *tree = private_data;
139         struct smb2_request *req;
140
141         break_info.handle = *handle;
142         break_info.level = level;
143         break_info.count++;
144
145         printf("Acking to none in oplock handler\n");
146
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;
152
153         req = smb2_break_send(tree, &break_info.br);
154         req->async.fn = torture_oplock_break_callback;
155         req->async.private_data = NULL;
156
157         return true;
158 }
159
160 /*
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.
164 */
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)
170 {
171         struct smb2_tree *tree = private_data;
172
173         break_info.handle = *handle;
174         break_info.level = level;
175         break_info.count++;
176
177         printf("Break from level II to none in oplock handler\n");
178
179         return true;
180 }
181
182 /* A handler function for oplock break notifications.  This should be used when
183  * test expects two break notifications, first to level II, then to none. */
184 static bool torture_oplock_handler_two_notifications(
185                                         struct smb2_transport *transport,
186                                         const struct smb2_handle *handle,
187                                         uint8_t level,
188                                         void *private_data)
189 {
190         struct smb2_tree *tree = private_data;
191         const char *name;
192         struct smb2_request *req;
193         ZERO_STRUCT(break_info.br);
194
195         break_info.handle       = *handle;
196         break_info.level        = level;
197         break_info.count++;
198
199         switch (level) {
200         case SMB2_OPLOCK_LEVEL_II:
201                 name = "level II";
202                 break;
203         case SMB2_OPLOCK_LEVEL_NONE:
204                 name = "none";
205                 break;
206         default:
207                 name = "unknown";
208                 break_info.failures++;
209         }
210         printf("Breaking to %s [0x%02X] in oplock handler\n", name, level);
211
212         if (level == SMB2_OPLOCK_LEVEL_NONE)
213                 return true;
214
215         break_info.br.in.file.handle    = *handle;
216         break_info.br.in.oplock_level   = level;
217         break_info.br.in.reserved       = 0;
218         break_info.br.in.reserved2      = 0;
219
220         req = smb2_break_send(tree, &break_info.br);
221         req->async.fn = torture_oplock_break_callback;
222         req->async.private_data = NULL;
223         return true;
224 }
225 static void torture_oplock_handler_close_recv(struct smb2_request *req)
226 {
227         if (!smb2_request_receive(req)) {
228                 printf("close failed in oplock_handler_close\n");
229                 break_info.failures++;
230         }
231 }
232
233 /*
234   a handler function for oplock break requests - close the file
235 */
236 static bool torture_oplock_handler_close(struct smb2_transport *transport,
237                                          const struct smb2_handle *handle,
238                                          uint8_t level,
239                                          void *private_data)
240 {
241         struct smb2_close io;
242         struct smb2_tree *tree = private_data;
243         struct smb2_request *req;
244
245         break_info.handle = *handle;
246         break_info.level = level;
247         break_info.count++;
248
249         ZERO_STRUCT(io);
250         io.in.file.handle       = *handle;
251         io.in.flags          = RAW_CLOSE_SMB2;
252         req = smb2_close_send(tree, &io);
253         if (req == NULL) {
254                 printf("failed to send close in oplock_handler_close\n");
255                 return false;
256         }
257
258         req->async.fn = torture_oplock_handler_close_recv;
259         req->async.private_data = NULL;
260
261         return true;
262 }
263
264 /*
265   a handler function for oplock break requests. Let it timeout
266 */
267 static bool torture_oplock_handler_timeout(struct smb2_transport *transport,
268                                            const struct smb2_handle *handle,
269                                            uint8_t level,
270                                            void *private_data)
271 {
272         break_info.handle = *handle;
273         break_info.level = level;
274         break_info.count++;
275
276         printf("Let oplock break timeout\n");
277         return true;
278 }
279
280 static bool open_smb2_connection_no_level2_oplocks(struct torture_context *tctx,
281                                                    struct smb2_tree **tree)
282 {
283         NTSTATUS status;
284         const char *host = torture_setting_string(tctx, "host", NULL);
285         const char *share = torture_setting_string(tctx, "share", NULL);
286         struct cli_credentials *credentials = cmdline_credentials;
287         struct smbcli_options options;
288
289         lp_smbcli_options(tctx->lp_ctx, &options);
290         options.use_level2_oplocks = false;
291
292         status = smb2_connect(tctx, host,
293                               lp_smb_ports(tctx->lp_ctx), share,
294                               lp_resolve_context(tctx->lp_ctx),
295                               credentials, tree, tctx->ev, &options,
296                               lp_socket_options(tctx->lp_ctx),
297                               lp_gensec_settings(tctx, tctx->lp_ctx));
298         if (!NT_STATUS_IS_OK(status)) {
299                 torture_comment(tctx, "Failed to connect to SMB2 share "
300                                 "\\\\%s\\%s - %s\n", host, share,
301                                 nt_errstr(status));
302                 return false;
303         }
304         return true;
305 }
306
307 /*
308    Timer handler function notifies the registering function that time is up
309 */
310 static void timeout_cb(struct tevent_context *ev,
311                        struct tevent_timer *te,
312                        struct timeval current_time,
313                        void *private_data)
314 {
315         bool *timesup = (bool *)private_data;
316         *timesup = true;
317         return;
318 }
319
320 /*
321    Wait a short period of time to receive a single oplock break request
322 */
323 static void torture_wait_for_oplock_break(struct torture_context *tctx)
324 {
325         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
326         struct tevent_timer *te = NULL;
327         struct timeval ne;
328         bool timesup = false;
329         int old_count = break_info.count;
330
331         /* Wait .1 seconds for an oplock break */
332         ne = tevent_timeval_current_ofs(0, 100000);
333
334         if ((te = event_add_timed(tctx->ev, tmp_ctx, ne, timeout_cb, &timesup))
335             == NULL)
336         {
337                 torture_comment(tctx, "Failed to wait for an oplock break. "
338                                       "test results may not be accurate.");
339                 goto done;
340         }
341
342         while (!timesup && break_info.count < old_count + 1) {
343                 if (event_loop_once(tctx->ev) != 0) {
344                         torture_comment(tctx, "Failed to wait for an oplock "
345                                               "break. test results may not be "
346                                               "accurate.");
347                         goto done;
348                 }
349         }
350
351 done:
352         /* We don't know if the timed event fired and was freed, we received
353          * our oplock break, or some other event triggered the loop.  Thus,
354          * we create a tmp_ctx to be able to safely free/remove the timed
355          * event in all 3 cases. */
356         talloc_free(tmp_ctx);
357
358         return;
359 }
360
361 static bool test_smb2_oplock_exclusive1(struct torture_context *tctx,
362                                         struct smb2_tree *tree1,
363                                         struct smb2_tree *tree2)
364 {
365         const char *fname = BASEDIR "\\test_exclusive1.dat";
366         NTSTATUS status;
367         bool ret = true;
368         union smb_open io;
369         union smb_unlink unl;
370         struct smb2_handle h1;
371         struct smb2_handle h;
372
373         status = torture_smb2_testdir(tree1, BASEDIR, &h);
374         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
375
376         /* cleanup */
377         smb2_util_unlink(tree1, fname);
378
379         tree1->session->transport->oplock.handler = torture_oplock_handler;
380         tree1->session->transport->oplock.private_data = tree1;
381
382         /*
383           base ntcreatex parms
384         */
385         ZERO_STRUCT(io.smb2);
386         io.generic.level = RAW_OPEN_SMB2;
387         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
388         io.smb2.in.alloc_size = 0;
389         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
390         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
391         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
392         io.smb2.in.create_options = 0;
393         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
394         io.smb2.in.security_flags = 0;
395         io.smb2.in.fname = fname;
396
397         torture_comment(tctx, "EXCLUSIVE1: open a file with an exclusive "
398                         "oplock (share mode: none)\n");
399         ZERO_STRUCT(break_info);
400         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
401
402         status = smb2_create(tree1, tctx, &(io.smb2));
403         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
404         h1 = io.smb2.out.file.handle;
405         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
406
407         torture_comment(tctx, "a 2nd open should not cause a break\n");
408         status = smb2_create(tree2, tctx, &(io.smb2));
409         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
410                                       "Incorrect status");
411         torture_wait_for_oplock_break(tctx);
412         CHECK_VAL(break_info.count, 0);
413         CHECK_VAL(break_info.failures, 0);
414
415         torture_comment(tctx, "unlink it - should also be no break\n");
416         unl.unlink.in.pattern = fname;
417         unl.unlink.in.attrib = 0;
418         status = smb2_util_unlink(tree2, fname);
419         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
420                                       "Incorrect status");
421         torture_wait_for_oplock_break(tctx);
422         CHECK_VAL(break_info.count, 0);
423         CHECK_VAL(break_info.failures, 0);
424
425         smb2_util_close(tree1, h1);
426         smb2_util_close(tree1, h);
427
428         smb2_deltree(tree1, BASEDIR);
429         return ret;
430 }
431
432 static bool test_smb2_oplock_exclusive2(struct torture_context *tctx,
433                                         struct smb2_tree *tree1,
434                                         struct smb2_tree *tree2)
435 {
436         const char *fname = BASEDIR "\\test_exclusive2.dat";
437         NTSTATUS status;
438         bool ret = true;
439         union smb_open io;
440         union smb_unlink unl;
441         struct smb2_handle h, h1, h2;
442
443         status = torture_smb2_testdir(tree1, BASEDIR, &h);
444         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
445
446         /* cleanup */
447         smb2_util_unlink(tree1, fname);
448
449         tree1->session->transport->oplock.handler = torture_oplock_handler;
450         tree1->session->transport->oplock.private_data = tree1;
451
452         /*
453           base ntcreatex parms
454         */
455         ZERO_STRUCT(io.smb2);
456         io.generic.level = RAW_OPEN_SMB2;
457         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
458         io.smb2.in.alloc_size = 0;
459         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
460         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
461         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
462         io.smb2.in.create_options = 0;
463         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
464         io.smb2.in.security_flags = 0;
465         io.smb2.in.fname = fname;
466
467         torture_comment(tctx, "EXCLUSIVE2: open a file with an exclusive "
468                         "oplock (share mode: all)\n");
469         ZERO_STRUCT(break_info);
470         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
471         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
472                 NTCREATEX_SHARE_ACCESS_WRITE|
473                 NTCREATEX_SHARE_ACCESS_DELETE;
474         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
475
476         status = smb2_create(tree1, tctx, &(io.smb2));
477         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
478         h1 = io.smb2.out.file.handle;
479         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
480
481         torture_comment(tctx, "a 2nd open should cause a break to level 2\n");
482         status = smb2_create(tree2, tctx, &(io.smb2));
483         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
484         h2 = io.smb2.out.file.handle;
485         torture_wait_for_oplock_break(tctx);
486         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
487         CHECK_VAL(break_info.count, 1);
488         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
489         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
490         CHECK_VAL(break_info.failures, 0);
491         ZERO_STRUCT(break_info);
492
493         /* now we have 2 level II oplocks... */
494         torture_comment(tctx, "try to unlink it - should cause a break\n");
495         unl.unlink.in.pattern = fname;
496         unl.unlink.in.attrib = 0;
497         status = smb2_util_unlink(tree2, fname);
498         torture_assert_ntstatus_ok(tctx, status, "Error unlinking the file");
499         torture_wait_for_oplock_break(tctx);
500         CHECK_VAL(break_info.count, 0);
501         CHECK_VAL(break_info.failures, 0);
502
503         torture_comment(tctx, "close both handles\n");
504         smb2_util_close(tree1, h1);
505         smb2_util_close(tree1, h2);
506         smb2_util_close(tree1, h);
507
508         smb2_deltree(tree1, BASEDIR);
509         return ret;
510 }
511
512 static bool test_smb2_oplock_exclusive3(struct torture_context *tctx,
513                                         struct smb2_tree *tree1,
514                                         struct smb2_tree *tree2)
515 {
516         const char *fname = BASEDIR "\\test_exclusive3.dat";
517         NTSTATUS status;
518         bool ret = true;
519         union smb_open io;
520         union smb_setfileinfo sfi;
521         struct smb2_handle h, h1;
522
523         status = torture_smb2_testdir(tree1, BASEDIR, &h);
524         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
525
526         /* cleanup */
527         smb2_util_unlink(tree1, fname);
528
529         tree1->session->transport->oplock.handler = torture_oplock_handler;
530         tree1->session->transport->oplock.private_data = tree1;
531
532         /*
533           base ntcreatex parms
534         */
535         ZERO_STRUCT(io.smb2);
536         io.generic.level = RAW_OPEN_SMB2;
537         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
538         io.smb2.in.alloc_size = 0;
539         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
540         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
541         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
542         io.smb2.in.create_options = 0;
543         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
544         io.smb2.in.security_flags = 0;
545         io.smb2.in.fname = fname;
546
547         torture_comment(tctx, "EXCLUSIVE3: open a file with an exclusive "
548                         "oplock (share mode: none)\n");
549
550         ZERO_STRUCT(break_info);
551         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
552         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
553
554         status = smb2_create(tree1, tctx, &(io.smb2));
555         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
556         h1 = io.smb2.out.file.handle;
557         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
558
559         torture_comment(tctx, "setpathinfo EOF should trigger a break to "
560                         "none\n");
561         ZERO_STRUCT(sfi);
562         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
563         sfi.generic.in.file.path = fname;
564         sfi.end_of_file_info.in.size = 100;
565
566         status = smb2_composite_setpathinfo(tree2, &sfi);
567
568         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
569                                       "Incorrect status");
570         torture_wait_for_oplock_break(tctx);
571         CHECK_VAL(break_info.count, 0);
572         CHECK_VAL(break_info.failures, 0);
573         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
574
575         smb2_util_close(tree1, h1);
576         smb2_util_close(tree1, h);
577
578         smb2_deltree(tree1, BASEDIR);
579         return ret;
580 }
581
582 static bool test_smb2_oplock_exclusive4(struct torture_context *tctx,
583                                         struct smb2_tree *tree1,
584                                         struct smb2_tree *tree2)
585 {
586         const char *fname = BASEDIR "\\test_exclusive4.dat";
587         NTSTATUS status;
588         bool ret = true;
589         union smb_open io;
590         struct smb2_handle h, h1, h2;
591
592         status = torture_smb2_testdir(tree1, BASEDIR, &h);
593         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
594
595         /* cleanup */
596         smb2_util_unlink(tree1, fname);
597
598         tree1->session->transport->oplock.handler = torture_oplock_handler;
599         tree1->session->transport->oplock.private_data = tree1;
600
601         /*
602           base ntcreatex parms
603         */
604         ZERO_STRUCT(io.smb2);
605         io.generic.level = RAW_OPEN_SMB2;
606         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
607         io.smb2.in.alloc_size = 0;
608         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
609         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
610         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
611         io.smb2.in.create_options = 0;
612         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
613         io.smb2.in.security_flags = 0;
614         io.smb2.in.fname = fname;
615
616         torture_comment(tctx, "EXCLUSIVE4: open with exclusive oplock\n");
617         ZERO_STRUCT(break_info);
618
619         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
620         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
621         status = smb2_create(tree1, tctx, &(io.smb2));
622         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
623         h1 = io.smb2.out.file.handle;
624         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
625
626         ZERO_STRUCT(break_info);
627         torture_comment(tctx, "second open with attributes only shouldn't "
628                         "cause oplock break\n");
629
630         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
631         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
632                                 SEC_FILE_WRITE_ATTRIBUTE |
633                                 SEC_STD_SYNCHRONIZE;
634         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
635         status = smb2_create(tree2, tctx, &(io.smb2));
636         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
637         h2 = io.smb2.out.file.handle;
638         CHECK_VAL(io.smb2.out.oplock_level, NO_OPLOCK_RETURN);
639         torture_wait_for_oplock_break(tctx);
640         CHECK_VAL(break_info.count, 0);
641         CHECK_VAL(break_info.failures, 0);
642
643         smb2_util_close(tree1, h1);
644         smb2_util_close(tree2, h2);
645         smb2_util_close(tree1, h);
646
647         smb2_deltree(tree1, BASEDIR);
648         return ret;
649 }
650
651 static bool test_smb2_oplock_exclusive5(struct torture_context *tctx,
652                                         struct smb2_tree *tree1,
653                                         struct smb2_tree *tree2)
654 {
655         const char *fname = BASEDIR "\\test_exclusive5.dat";
656         NTSTATUS status;
657         bool ret = true;
658         union smb_open io;
659         struct smb2_handle h, h1, h2;
660
661         status = torture_smb2_testdir(tree1, BASEDIR, &h);
662         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
663
664         /* cleanup */
665         smb2_util_unlink(tree1, fname);
666
667         tree1->session->transport->oplock.handler = torture_oplock_handler;
668         tree1->session->transport->oplock.private_data = tree1;
669
670         tree2->session->transport->oplock.handler = torture_oplock_handler;
671         tree2->session->transport->oplock.private_data = tree2;
672
673         /*
674           base ntcreatex parms
675         */
676         ZERO_STRUCT(io.smb2);
677         io.generic.level = RAW_OPEN_SMB2;
678         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
679         io.smb2.in.alloc_size = 0;
680         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
681         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
682         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
683         io.smb2.in.create_options = 0;
684         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
685         io.smb2.in.security_flags = 0;
686         io.smb2.in.fname = fname;
687
688         torture_comment(tctx, "EXCLUSIVE5: open with exclusive oplock\n");
689         ZERO_STRUCT(break_info);
690
691         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
692         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
693                 NTCREATEX_SHARE_ACCESS_WRITE|
694                 NTCREATEX_SHARE_ACCESS_DELETE;
695         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
696         status = smb2_create(tree1, tctx, &(io.smb2));
697         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
698         h1 = io.smb2.out.file.handle;
699         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
700
701         ZERO_STRUCT(break_info);
702
703         torture_comment(tctx, "second open with attributes only and "
704                         "NTCREATEX_DISP_OVERWRITE_IF dispostion causes "
705                         "oplock break\n");
706
707         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
708         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
709                                 SEC_FILE_WRITE_ATTRIBUTE |
710                                 SEC_STD_SYNCHRONIZE;
711         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
712         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
713         status = smb2_create(tree2, tctx, &(io.smb2));
714         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
715         h2 = io.smb2.out.file.handle;
716         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
717         torture_wait_for_oplock_break(tctx);
718         CHECK_VAL(break_info.count, 1);
719         CHECK_VAL(break_info.failures, 0);
720
721         smb2_util_close(tree1, h1);
722         smb2_util_close(tree2, h2);
723         smb2_util_close(tree1, h);
724
725         smb2_deltree(tree1, BASEDIR);
726         return ret;
727 }
728
729 static bool test_smb2_oplock_exclusive6(struct torture_context *tctx,
730                                         struct smb2_tree *tree1,
731                                         struct smb2_tree *tree2)
732 {
733         const char *fname1 = BASEDIR "\\test_exclusive6_1.dat";
734         const char *fname2 = BASEDIR "\\test_exclusive6_2.dat";
735         NTSTATUS status;
736         bool ret = true;
737         union smb_open io;
738         union smb_setfileinfo sinfo;
739         struct smb2_handle h, h1;
740
741         status = torture_smb2_testdir(tree1, BASEDIR, &h);
742         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
743
744         /* cleanup */
745         smb2_util_unlink(tree1, fname1);
746         smb2_util_unlink(tree2, fname2);
747
748         tree1->session->transport->oplock.handler = torture_oplock_handler;
749         tree1->session->transport->oplock.private_data = tree1;
750
751         /*
752           base ntcreatex parms
753         */
754         ZERO_STRUCT(io.smb2);
755         io.generic.level = RAW_OPEN_SMB2;
756         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
757         io.smb2.in.alloc_size = 0;
758         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
759         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
760         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
761         io.smb2.in.create_options = 0;
762         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
763         io.smb2.in.security_flags = 0;
764         io.smb2.in.fname = fname1;
765
766         torture_comment(tctx, "EXCLUSIVE6: open a file with an exclusive "
767                         "oplock (share mode: none)\n");
768         ZERO_STRUCT(break_info);
769         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
770         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
771
772         status = smb2_create(tree1, tctx, &(io.smb2));
773         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
774         h1 = io.smb2.out.file.handle;
775         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
776
777         torture_comment(tctx, "rename should not generate a break but get "
778                         "a sharing violation\n");
779         ZERO_STRUCT(sinfo);
780         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
781         sinfo.rename_information.in.file.handle = h1;
782         sinfo.rename_information.in.overwrite = true;
783         sinfo.rename_information.in.new_name = fname2;
784         status = smb2_setinfo_file(tree1, &sinfo);
785
786         torture_comment(tctx, "trying rename while first file open\n");
787         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
788                                       "Incorrect status");
789         torture_wait_for_oplock_break(tctx);
790         CHECK_VAL(break_info.count, 0);
791         CHECK_VAL(break_info.failures, 0);
792
793         smb2_util_close(tree1, h1);
794         smb2_util_close(tree1, h);
795
796         smb2_deltree(tree1, BASEDIR);
797         return ret;
798 }
799
800 static bool test_smb2_oplock_batch1(struct torture_context *tctx,
801                                     struct smb2_tree *tree1,
802                                     struct smb2_tree *tree2)
803 {
804         const char *fname = BASEDIR "\\test_batch1.dat";
805         NTSTATUS status;
806         bool ret = true;
807         union smb_open io;
808         struct smb2_handle h, h1;
809         char c = 0;
810
811         status = torture_smb2_testdir(tree1, BASEDIR, &h);
812         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
813
814         /* cleanup */
815         smb2_util_unlink(tree1, fname);
816
817         tree1->session->transport->oplock.handler = torture_oplock_handler;
818         tree1->session->transport->oplock.private_data = tree1;
819
820         /*
821           base ntcreatex parms
822         */
823         ZERO_STRUCT(io.smb2);
824         io.generic.level = RAW_OPEN_SMB2;
825         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
826         io.smb2.in.alloc_size = 0;
827         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
828         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
829         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
830         io.smb2.in.create_options = 0;
831         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
832         io.smb2.in.security_flags = 0;
833         io.smb2.in.fname = fname;
834
835         /*
836           with a batch oplock we get a break
837         */
838         torture_comment(tctx, "BATCH1: open with batch oplock\n");
839         ZERO_STRUCT(break_info);
840         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
841         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
842         status = smb2_create(tree1, tctx, &(io.smb2));
843         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
844         h1 = io.smb2.out.file.handle;
845         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
846
847         torture_comment(tctx, "unlink should generate a break\n");
848         status = smb2_util_unlink(tree2, fname);
849         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
850                                       "Incorrect status");
851
852         torture_wait_for_oplock_break(tctx);
853         CHECK_VAL(break_info.count, 1);
854         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
855         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
856         CHECK_VAL(break_info.failures, 0);
857
858         torture_comment(tctx, "2nd unlink should not generate a break\n");
859         ZERO_STRUCT(break_info);
860         status = smb2_util_unlink(tree2, fname);
861         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
862                                       "Incorrect status");
863
864         torture_wait_for_oplock_break(tctx);
865         CHECK_VAL(break_info.count, 0);
866
867         torture_comment(tctx, "writing should generate a self break to none\n");
868         tree1->session->transport->oplock.handler =
869             torture_oplock_handler_level2_to_none;
870         smb2_util_write(tree1, h1, &c, 0, 1);
871
872         torture_wait_for_oplock_break(tctx);
873
874         CHECK_VAL(break_info.count, 1);
875         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
876         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
877         CHECK_VAL(break_info.failures, 0);
878
879         smb2_util_close(tree1, h1);
880         smb2_util_close(tree1, h);
881
882         smb2_deltree(tree1, BASEDIR);
883         return ret;
884 }
885
886 static bool test_smb2_oplock_batch2(struct torture_context *tctx,
887                                     struct smb2_tree *tree1,
888                                     struct smb2_tree *tree2)
889 {
890         const char *fname = BASEDIR "\\test_batch2.dat";
891         NTSTATUS status;
892         bool ret = true;
893         union smb_open io;
894         char c = 0;
895         struct smb2_handle h, h1;
896
897         status = torture_smb2_testdir(tree1, BASEDIR, &h);
898         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
899
900         /* cleanup */
901         smb2_util_unlink(tree1, fname);
902
903         tree1->session->transport->oplock.handler = torture_oplock_handler;
904         tree1->session->transport->oplock.private_data = tree1;
905
906         /*
907           base ntcreatex parms
908         */
909         ZERO_STRUCT(io.smb2);
910         io.generic.level = RAW_OPEN_SMB2;
911         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
912         io.smb2.in.alloc_size = 0;
913         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
914         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
915         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
916         io.smb2.in.create_options = 0;
917         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
918         io.smb2.in.security_flags = 0;
919         io.smb2.in.fname = fname;
920
921         torture_comment(tctx, "BATCH2: open with batch oplock\n");
922         ZERO_STRUCT(break_info);
923         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
924         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
925         status = smb2_create(tree1, tctx, &(io.smb2));
926         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
927         h1 = io.smb2.out.file.handle;
928         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
929
930         torture_comment(tctx, "unlink should generate a break, which we ack "
931                         "as break to none\n");
932         tree1->session->transport->oplock.handler =
933                                 torture_oplock_handler_ack_to_none;
934         tree1->session->transport->oplock.private_data = tree1;
935         status = smb2_util_unlink(tree2, fname);
936         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
937                                      "Incorrect status");
938
939         torture_wait_for_oplock_break(tctx);
940         CHECK_VAL(break_info.count, 1);
941         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
942         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
943         CHECK_VAL(break_info.failures, 0);
944
945         torture_comment(tctx, "2nd unlink should not generate a break\n");
946         ZERO_STRUCT(break_info);
947         status = smb2_util_unlink(tree2, fname);
948         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
949                                       "Incorrect status");
950
951         torture_wait_for_oplock_break(tctx);
952         CHECK_VAL(break_info.count, 0);
953
954         torture_comment(tctx, "writing should not generate a break\n");
955         smb2_util_write(tree1, h1, &c, 0, 1);
956
957         torture_wait_for_oplock_break(tctx);
958         CHECK_VAL(break_info.count, 0);
959
960         smb2_util_close(tree1, h1);
961         smb2_util_close(tree1, h);
962
963         smb2_deltree(tree1, BASEDIR);
964         return ret;
965 }
966
967 static bool test_smb2_oplock_batch3(struct torture_context *tctx,
968                                     struct smb2_tree *tree1,
969                                     struct smb2_tree *tree2)
970 {
971         const char *fname = BASEDIR "\\test_batch3.dat";
972         NTSTATUS status;
973         bool ret = true;
974         union smb_open io;
975         struct smb2_handle h, h1;
976
977         status = torture_smb2_testdir(tree1, BASEDIR, &h);
978         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
979
980         /* cleanup */
981         smb2_util_unlink(tree1, fname);
982         tree1->session->transport->oplock.handler = torture_oplock_handler;
983         tree1->session->transport->oplock.private_data = tree1;
984
985         /*
986           base ntcreatex parms
987         */
988         ZERO_STRUCT(io.smb2);
989         io.generic.level = RAW_OPEN_SMB2;
990         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
991         io.smb2.in.alloc_size = 0;
992         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
993         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
994         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
995         io.smb2.in.create_options = 0;
996         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
997         io.smb2.in.security_flags = 0;
998         io.smb2.in.fname = fname;
999
1000         torture_comment(tctx, "BATCH3: if we close on break then the unlink "
1001                         "can succeed\n");
1002         ZERO_STRUCT(break_info);
1003         tree1->session->transport->oplock.handler =
1004                                         torture_oplock_handler_close;
1005         tree1->session->transport->oplock.private_data = tree1;
1006
1007         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1008         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1009         status = smb2_create(tree1, tctx, &(io.smb2));
1010         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1011         h1 = io.smb2.out.file.handle;
1012         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1013
1014         ZERO_STRUCT(break_info);
1015         status = smb2_util_unlink(tree2, fname);
1016         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1017
1018         torture_wait_for_oplock_break(tctx);
1019         CHECK_VAL(break_info.count, 1);
1020         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1021         CHECK_VAL(break_info.level, 1);
1022         CHECK_VAL(break_info.failures, 0);
1023
1024         smb2_util_close(tree1, h1);
1025         smb2_util_close(tree1, h);
1026
1027         smb2_deltree(tree1, BASEDIR);
1028         return ret;
1029 }
1030
1031 static bool test_smb2_oplock_batch4(struct torture_context *tctx,
1032                                     struct smb2_tree *tree1,
1033                                     struct smb2_tree *tree2)
1034 {
1035         const char *fname = BASEDIR "\\test_batch4.dat";
1036         NTSTATUS status;
1037         bool ret = true;
1038         union smb_open io;
1039         struct smb2_read r;
1040         struct smb2_handle h, h1;
1041
1042         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1043         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1044
1045         /* cleanup */
1046         smb2_util_unlink(tree1, fname);
1047
1048         tree1->session->transport->oplock.handler = torture_oplock_handler;
1049         tree1->session->transport->oplock.private_data = tree1;
1050
1051         /*
1052           base ntcreatex parms
1053         */
1054         ZERO_STRUCT(io.smb2);
1055         io.generic.level = RAW_OPEN_SMB2;
1056         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1057         io.smb2.in.alloc_size = 0;
1058         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1059         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1060         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1061         io.smb2.in.create_options = 0;
1062         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1063         io.smb2.in.security_flags = 0;
1064         io.smb2.in.fname = fname;
1065
1066         torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
1067         ZERO_STRUCT(break_info);
1068
1069         tree1->session->transport->oplock.handler = torture_oplock_handler;
1070         tree1->session->transport->oplock.private_data = tree1;
1071
1072         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1073         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1074         status = smb2_create(tree1, tctx, &(io.smb2));
1075         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1076         h1 = io.smb2.out.file.handle;
1077         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1078
1079         ZERO_STRUCT(r);
1080         r.in.file.handle = h1;
1081         r.in.offset      = 0;
1082
1083         status = smb2_read(tree1, tree1, &r);
1084         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1085         torture_wait_for_oplock_break(tctx);
1086         CHECK_VAL(break_info.count, 0);
1087         CHECK_VAL(break_info.failures, 0);
1088
1089         smb2_util_close(tree1, h1);
1090         smb2_util_close(tree1, h);
1091
1092         smb2_deltree(tree1, BASEDIR);
1093         return ret;
1094 }
1095
1096 static bool test_smb2_oplock_batch5(struct torture_context *tctx,
1097                                     struct smb2_tree *tree1,
1098                                     struct smb2_tree *tree2)
1099 {
1100         const char *fname = BASEDIR "\\test_batch5.dat";
1101         NTSTATUS status;
1102         bool ret = true;
1103         union smb_open io;
1104         struct smb2_handle h, h1;
1105
1106         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1107         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1108
1109         /* cleanup */
1110         smb2_util_unlink(tree1, fname);
1111
1112         tree1->session->transport->oplock.handler = torture_oplock_handler;
1113         tree1->session->transport->oplock.private_data = tree1;
1114
1115         /*
1116           base ntcreatex parms
1117         */
1118         ZERO_STRUCT(io.smb2);
1119         io.generic.level = RAW_OPEN_SMB2;
1120         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1121         io.smb2.in.alloc_size = 0;
1122         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1123         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1124         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1125         io.smb2.in.create_options = 0;
1126         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1127         io.smb2.in.security_flags = 0;
1128         io.smb2.in.fname = fname;
1129
1130         torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
1131         ZERO_STRUCT(break_info);
1132
1133         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1134         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1135         status = smb2_create(tree1, tctx, &(io.smb2));
1136         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1137         h1 = io.smb2.out.file.handle;
1138         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1139
1140         ZERO_STRUCT(break_info);
1141
1142         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1143         status = smb2_create(tree2, tctx, &(io.smb2));
1144         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
1145                                       "Incorrect status");
1146
1147         torture_wait_for_oplock_break(tctx);
1148         CHECK_VAL(break_info.count, 1);
1149         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1150         CHECK_VAL(break_info.level, 1);
1151         CHECK_VAL(break_info.failures, 0);
1152
1153         smb2_util_close(tree1, h1);
1154         smb2_util_close(tree1, h);
1155
1156         smb2_deltree(tree1, BASEDIR);
1157         return ret;
1158 }
1159
1160 static bool test_smb2_oplock_batch6(struct torture_context *tctx,
1161                                     struct smb2_tree *tree1,
1162                                     struct smb2_tree *tree2)
1163 {
1164         const char *fname = BASEDIR "\\test_batch6.dat";
1165         NTSTATUS status;
1166         bool ret = true;
1167         union smb_open io;
1168         struct smb2_handle h, h1, h2;
1169         char c = 0;
1170
1171         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1172         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1173
1174         /* cleanup */
1175         smb2_util_unlink(tree1, fname);
1176
1177         tree1->session->transport->oplock.handler = torture_oplock_handler;
1178         tree1->session->transport->oplock.private_data = tree1;
1179
1180         /*
1181           base ntcreatex parms
1182         */
1183         ZERO_STRUCT(io.smb2);
1184         io.generic.level = RAW_OPEN_SMB2;
1185         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1186         io.smb2.in.alloc_size = 0;
1187         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1188         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1189         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1190         io.smb2.in.create_options = 0;
1191         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1192         io.smb2.in.security_flags = 0;
1193         io.smb2.in.fname = fname;
1194
1195         torture_comment(tctx, "BATCH6: a 2nd open should give a break to "
1196                         "level II if the first open allowed shared read\n");
1197         ZERO_STRUCT(break_info);
1198         tree2->session->transport->oplock.handler = torture_oplock_handler;
1199         tree2->session->transport->oplock.private_data = tree2;
1200
1201         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
1202                                 SEC_RIGHTS_FILE_WRITE;
1203         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1204                                 NTCREATEX_SHARE_ACCESS_WRITE;
1205         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1206         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1207         status = smb2_create(tree1, tctx, &(io.smb2));
1208         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1209         h1 = io.smb2.out.file.handle;
1210         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1211
1212         ZERO_STRUCT(break_info);
1213
1214         status = smb2_create(tree2, tctx, &(io.smb2));
1215         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1216         h2 = io.smb2.out.file.handle;
1217         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1218
1219         torture_wait_for_oplock_break(tctx);
1220         CHECK_VAL(break_info.count, 1);
1221         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1222         CHECK_VAL(break_info.level, 1);
1223         CHECK_VAL(break_info.failures, 0);
1224         ZERO_STRUCT(break_info);
1225
1226         torture_comment(tctx, "write should trigger a break to none on both\n");
1227         tree1->session->transport->oplock.handler =
1228             torture_oplock_handler_level2_to_none;
1229         tree2->session->transport->oplock.handler =
1230             torture_oplock_handler_level2_to_none;
1231         smb2_util_write(tree1, h1, &c, 0, 1);
1232
1233         /* We expect two breaks */
1234         torture_wait_for_oplock_break(tctx);
1235         torture_wait_for_oplock_break(tctx);
1236
1237         CHECK_VAL(break_info.count, 2);
1238         CHECK_VAL(break_info.level, 0);
1239         CHECK_VAL(break_info.failures, 0);
1240
1241         smb2_util_close(tree1, h1);
1242         smb2_util_close(tree2, h2);
1243         smb2_util_close(tree1, h);
1244
1245         smb2_deltree(tree1, BASEDIR);
1246         return ret;
1247 }
1248
1249 static bool test_smb2_oplock_batch7(struct torture_context *tctx,
1250                                     struct smb2_tree *tree1,
1251                                     struct smb2_tree *tree2)
1252 {
1253         const char *fname = BASEDIR "\\test_batch7.dat";
1254         NTSTATUS status;
1255         bool ret = true;
1256         union smb_open io;
1257         struct smb2_handle h, h1, h2;
1258
1259         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1260         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1261
1262         /* cleanup */
1263         smb2_util_unlink(tree1, fname);
1264
1265         tree1->session->transport->oplock.handler = torture_oplock_handler;
1266         tree1->session->transport->oplock.private_data = tree1;
1267
1268         /*
1269           base ntcreatex parms
1270         */
1271         ZERO_STRUCT(io.smb2);
1272         io.generic.level = RAW_OPEN_SMB2;
1273         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1274         io.smb2.in.alloc_size = 0;
1275         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1276         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1277         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1278         io.smb2.in.create_options = 0;
1279         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1280         io.smb2.in.security_flags = 0;
1281         io.smb2.in.fname = fname;
1282
1283         torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when "
1284                         "we close instead of ack\n");
1285         ZERO_STRUCT(break_info);
1286         tree1->session->transport->oplock.handler =
1287                         torture_oplock_handler_close;
1288         tree1->session->transport->oplock.private_data = tree1;
1289
1290         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1291         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1292         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1293         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1294         status = smb2_create(tree1, tctx, &(io.smb2));
1295         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1296         h2 = io.smb2.out.file.handle;
1297         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1298
1299         ZERO_STRUCT(break_info);
1300
1301         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1302         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1303         status = smb2_create(tree2, tctx, &(io.smb2));
1304         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1305         h1 = io.smb2.out.file.handle;
1306         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1307
1308         torture_wait_for_oplock_break(tctx);
1309         CHECK_VAL(break_info.count, 1);
1310         CHECK_VAL(break_info.handle.data[0], h2.data[0]);
1311         CHECK_VAL(break_info.level, 1);
1312         CHECK_VAL(break_info.failures, 0);
1313
1314         smb2_util_close(tree2, h1);
1315         smb2_util_close(tree2, h);
1316
1317         smb2_deltree(tree1, BASEDIR);
1318         return ret;
1319 }
1320
1321 static bool test_smb2_oplock_batch8(struct torture_context *tctx,
1322                                     struct smb2_tree *tree1,
1323                                     struct smb2_tree *tree2)
1324 {
1325         const char *fname = BASEDIR "\\test_batch8.dat";
1326         NTSTATUS status;
1327         bool ret = true;
1328         union smb_open io;
1329         struct smb2_handle h, h1, h2;
1330
1331         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1332         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1333
1334         /* cleanup */
1335         smb2_util_unlink(tree1, fname);
1336
1337         tree1->session->transport->oplock.handler = torture_oplock_handler;
1338         tree1->session->transport->oplock.private_data = tree1;
1339
1340         /*
1341           base ntcreatex parms
1342         */
1343         ZERO_STRUCT(io.smb2);
1344         io.generic.level = RAW_OPEN_SMB2;
1345         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1346         io.smb2.in.alloc_size = 0;
1347         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1348         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1349         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1350         io.smb2.in.create_options = 0;
1351         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1352         io.smb2.in.security_flags = 0;
1353         io.smb2.in.fname = fname;
1354
1355         torture_comment(tctx, "BATCH8: open with batch oplock\n");
1356         ZERO_STRUCT(break_info);
1357
1358         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1359         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1360         status = smb2_create(tree1, tctx, &(io.smb2));
1361         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1362         h1 = io.smb2.out.file.handle;
1363         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1364
1365         ZERO_STRUCT(break_info);
1366         torture_comment(tctx, "second open with attributes only shouldn't "
1367                         "cause oplock break\n");
1368
1369         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1370         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1371                                 SEC_FILE_WRITE_ATTRIBUTE |
1372                                 SEC_STD_SYNCHRONIZE;
1373         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1374         status = smb2_create(tree2, tctx, &(io.smb2));
1375         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1376         h2 = io.smb2.out.file.handle;
1377         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
1378         torture_wait_for_oplock_break(tctx);
1379         CHECK_VAL(break_info.count, 0);
1380         CHECK_VAL(break_info.failures, 0);
1381
1382         smb2_util_close(tree1, h1);
1383         smb2_util_close(tree2, h2);
1384         smb2_util_close(tree1, h);
1385
1386         smb2_deltree(tree1, BASEDIR);
1387         return ret;
1388 }
1389
1390 static bool test_smb2_oplock_batch9(struct torture_context *tctx,
1391                                      struct smb2_tree *tree1,
1392                                      struct smb2_tree *tree2)
1393 {
1394         const char *fname = BASEDIR "\\test_batch9.dat";
1395         NTSTATUS status;
1396         bool ret = true;
1397         union smb_open io;
1398         struct smb2_handle h, h1, h2;
1399         char c = 0;
1400
1401         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1402         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1403
1404         /* cleanup */
1405         smb2_util_unlink(tree1, fname);
1406
1407         tree1->session->transport->oplock.handler = torture_oplock_handler;
1408         tree1->session->transport->oplock.private_data = tree1;
1409
1410         /*
1411           base ntcreatex parms
1412         */
1413         ZERO_STRUCT(io.smb2);
1414         io.generic.level = RAW_OPEN_SMB2;
1415         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1416         io.smb2.in.alloc_size = 0;
1417         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1418         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1419         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1420         io.smb2.in.create_options = 0;
1421         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1422         io.smb2.in.security_flags = 0;
1423         io.smb2.in.fname = fname;
1424
1425         torture_comment(tctx, "BATCH9: open with attributes only can create "
1426                         "file\n");
1427
1428         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1429         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1430         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1431                                 SEC_FILE_WRITE_ATTRIBUTE |
1432                                 SEC_STD_SYNCHRONIZE;
1433         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1434         status = smb2_create(tree1, tctx, &(io.smb2));
1435         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1436         h1 = io.smb2.out.file.handle;
1437         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1438
1439         torture_comment(tctx, "Subsequent normal open should break oplock on "
1440                         "attribute only open to level II\n");
1441
1442         ZERO_STRUCT(break_info);
1443
1444         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1445         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1446         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1447         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1448         status = smb2_create(tree2, tctx, &(io.smb2));
1449         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1450         h2 = io.smb2.out.file.handle;
1451         torture_wait_for_oplock_break(tctx);
1452         CHECK_VAL(break_info.count, 1);
1453         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1454         CHECK_VAL(break_info.failures, 0);
1455         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
1456         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1457         smb2_util_close(tree2, h2);
1458
1459         torture_comment(tctx, "third oplocked open should grant level2 without "
1460                         "break\n");
1461         ZERO_STRUCT(break_info);
1462
1463         tree2->session->transport->oplock.handler = torture_oplock_handler;
1464         tree2->session->transport->oplock.private_data = tree2;
1465
1466         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1467         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1468         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1469         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1470         status = smb2_create(tree2, tctx, &(io.smb2));
1471         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1472         h2 = io.smb2.out.file.handle;
1473         torture_wait_for_oplock_break(tctx);
1474         CHECK_VAL(break_info.count, 0);
1475         CHECK_VAL(break_info.failures, 0);
1476         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1477
1478         ZERO_STRUCT(break_info);
1479
1480         torture_comment(tctx, "write should trigger a break to none on both\n");
1481         tree1->session->transport->oplock.handler =
1482             torture_oplock_handler_level2_to_none;
1483         tree2->session->transport->oplock.handler =
1484             torture_oplock_handler_level2_to_none;
1485         smb2_util_write(tree2, h2, &c, 0, 1);
1486
1487         /* We expect two breaks */
1488         torture_wait_for_oplock_break(tctx);
1489         torture_wait_for_oplock_break(tctx);
1490
1491         CHECK_VAL(break_info.count, 2);
1492         CHECK_VAL(break_info.level, 0);
1493         CHECK_VAL(break_info.failures, 0);
1494
1495         smb2_util_close(tree1, h1);
1496         smb2_util_close(tree2, h2);
1497         smb2_util_close(tree1, h);
1498
1499         smb2_deltree(tree1, BASEDIR);
1500         return ret;
1501 }
1502
1503 static bool test_smb2_oplock_batch10(struct torture_context *tctx,
1504                                      struct smb2_tree *tree1,
1505                                      struct smb2_tree *tree2)
1506 {
1507         const char *fname = BASEDIR "\\test_batch10.dat";
1508         NTSTATUS status;
1509         bool ret = true;
1510         union smb_open io;
1511         struct smb2_handle h, h1, h2;
1512
1513         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1514         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1515
1516         /* cleanup */
1517         smb2_util_unlink(tree1, fname);
1518
1519         tree1->session->transport->oplock.handler = torture_oplock_handler;
1520         tree1->session->transport->oplock.private_data = tree1;
1521
1522         /*
1523           base ntcreatex parms
1524         */
1525         ZERO_STRUCT(io.smb2);
1526         io.generic.level = RAW_OPEN_SMB2;
1527         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1528         io.smb2.in.alloc_size = 0;
1529         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1530         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1531         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1532         io.smb2.in.create_options = 0;
1533         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1534         io.smb2.in.security_flags = 0;
1535         io.smb2.in.fname = fname;
1536
1537         torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock "
1538                         "open should grant level2\n");
1539         ZERO_STRUCT(break_info);
1540         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1541         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1542         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1543                 NTCREATEX_SHARE_ACCESS_WRITE|
1544                 NTCREATEX_SHARE_ACCESS_DELETE;
1545         status = smb2_create(tree1, tctx, &(io.smb2));
1546         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1547         h1 = io.smb2.out.file.handle;
1548         torture_wait_for_oplock_break(tctx);
1549         CHECK_VAL(break_info.count, 0);
1550         CHECK_VAL(break_info.failures, 0);
1551         CHECK_VAL(io.smb2.out.oplock_level, 0);
1552
1553         tree2->session->transport->oplock.handler =
1554             torture_oplock_handler_level2_to_none;
1555         tree2->session->transport->oplock.private_data = tree2;
1556
1557         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1558         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1559         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1560         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1561                 NTCREATEX_SHARE_ACCESS_WRITE|
1562                 NTCREATEX_SHARE_ACCESS_DELETE;
1563         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1564         status = smb2_create(tree2, tctx, &(io.smb2));
1565         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1566         h2 = io.smb2.out.file.handle;
1567         torture_wait_for_oplock_break(tctx);
1568         CHECK_VAL(break_info.count, 0);
1569         CHECK_VAL(break_info.failures, 0);
1570         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1571
1572         torture_comment(tctx, "write should trigger a break to none\n");
1573         {
1574                 struct smb2_write wr;
1575                 DATA_BLOB data;
1576                 data = data_blob_talloc(tree1, NULL, UINT16_MAX);
1577                 data.data[0] = (const uint8_t)'x';
1578                 ZERO_STRUCT(wr);
1579                 wr.in.file.handle = h1;
1580                 wr.in.offset      = 0;
1581                 wr.in.data        = data;
1582                 status = smb2_write(tree1, &wr);
1583                 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1584         }
1585
1586         torture_wait_for_oplock_break(tctx);
1587
1588         CHECK_VAL(break_info.count, 1);
1589         CHECK_VAL(break_info.handle.data[0], h2.data[0]);
1590         CHECK_VAL(break_info.level, 0);
1591         CHECK_VAL(break_info.failures, 0);
1592
1593         smb2_util_close(tree1, h1);
1594         smb2_util_close(tree2, h2);
1595         smb2_util_close(tree1, h);
1596
1597         smb2_deltree(tree1, BASEDIR);
1598         return ret;
1599 }
1600
1601 static bool test_smb2_oplock_batch11(struct torture_context *tctx,
1602                                      struct smb2_tree *tree1,
1603                                      struct smb2_tree *tree2)
1604 {
1605         const char *fname = BASEDIR "\\test_batch11.dat";
1606         NTSTATUS status;
1607         bool ret = true;
1608         union smb_open io;
1609         union smb_setfileinfo sfi;
1610         struct smb2_handle h, h1;
1611
1612         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1613         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1614
1615         /* cleanup */
1616         smb2_util_unlink(tree1, fname);
1617
1618         tree1->session->transport->oplock.handler =
1619             torture_oplock_handler_two_notifications;
1620         tree1->session->transport->oplock.private_data = tree1;
1621
1622         /*
1623           base ntcreatex parms
1624         */
1625         ZERO_STRUCT(io.smb2);
1626         io.generic.level = RAW_OPEN_SMB2;
1627         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1628         io.smb2.in.alloc_size = 0;
1629         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1630         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1631         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1632         io.smb2.in.create_options = 0;
1633         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1634         io.smb2.in.security_flags = 0;
1635         io.smb2.in.fname = fname;
1636
1637         /* Test if a set-eof on pathname breaks an exclusive oplock. */
1638         torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks "
1639                         "oplocks.\n");
1640
1641         ZERO_STRUCT(break_info);
1642
1643         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1644         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1645         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1646         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1647                                 NTCREATEX_SHARE_ACCESS_WRITE|
1648                                 NTCREATEX_SHARE_ACCESS_DELETE;
1649         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1650         status = smb2_create(tree1, tctx, &(io.smb2));
1651         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1652         h1 = io.smb2.out.file.handle;
1653         torture_wait_for_oplock_break(tctx);
1654         CHECK_VAL(break_info.count, 0);
1655         CHECK_VAL(break_info.failures, 0);
1656         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1657
1658         ZERO_STRUCT(sfi);
1659         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1660         sfi.generic.in.file.path = fname;
1661         sfi.end_of_file_info.in.size = 100;
1662
1663         status = smb2_composite_setpathinfo(tree2, &sfi);
1664         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1665
1666         /* We expect two breaks */
1667         torture_wait_for_oplock_break(tctx);
1668         torture_wait_for_oplock_break(tctx);
1669
1670         CHECK_VAL(break_info.count, 2);
1671         CHECK_VAL(break_info.failures, 0);
1672         CHECK_VAL(break_info.level, 0);
1673
1674         smb2_util_close(tree1, h1);
1675         smb2_util_close(tree1, h);
1676
1677         smb2_deltree(tree1, BASEDIR);
1678         return ret;
1679 }
1680
1681 static bool test_smb2_oplock_batch12(struct torture_context *tctx,
1682                                      struct smb2_tree *tree1,
1683                                      struct smb2_tree *tree2)
1684 {
1685         const char *fname = BASEDIR "\\test_batch12.dat";
1686         NTSTATUS status;
1687         bool ret = true;
1688         union smb_open io;
1689         union smb_setfileinfo sfi;
1690         struct smb2_handle h, h1;
1691
1692         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1693         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1694
1695         /* cleanup */
1696         smb2_util_unlink(tree1, fname);
1697
1698         tree1->session->transport->oplock.handler =
1699             torture_oplock_handler_two_notifications;
1700         tree1->session->transport->oplock.private_data = tree1;
1701
1702         /*
1703           base ntcreatex parms
1704         */
1705         ZERO_STRUCT(io.smb2);
1706         io.generic.level = RAW_OPEN_SMB2;
1707         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1708         io.smb2.in.alloc_size = 0;
1709         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1710         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1711         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1712         io.smb2.in.create_options = 0;
1713         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1714         io.smb2.in.security_flags = 0;
1715         io.smb2.in.fname = fname;
1716
1717         /* Test if a set-allocation size on pathname breaks an exclusive
1718          * oplock. */
1719         torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size "
1720                         "breaks oplocks.\n");
1721
1722         ZERO_STRUCT(break_info);
1723
1724         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1725         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1726         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1727         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1728                                 NTCREATEX_SHARE_ACCESS_WRITE|
1729                                 NTCREATEX_SHARE_ACCESS_DELETE;
1730         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1731         status = smb2_create(tree1, tctx, &(io.smb2));
1732         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1733         h1 = io.smb2.out.file.handle;
1734         torture_wait_for_oplock_break(tctx);
1735         CHECK_VAL(break_info.count, 0);
1736         CHECK_VAL(break_info.failures, 0);
1737         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1738
1739         ZERO_STRUCT(sfi);
1740         sfi.generic.level = RAW_SFILEINFO_ALLOCATION_INFORMATION;
1741         sfi.generic.in.file.path = fname;
1742         sfi.allocation_info.in.alloc_size = 65536 * 8;
1743
1744         status = smb2_composite_setpathinfo(tree2, &sfi);
1745         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1746
1747         /* We expect two breaks */
1748         torture_wait_for_oplock_break(tctx);
1749         torture_wait_for_oplock_break(tctx);
1750
1751         CHECK_VAL(break_info.count, 2);
1752         CHECK_VAL(break_info.failures, 0);
1753         CHECK_VAL(break_info.level, 0);
1754
1755         smb2_util_close(tree1, h1);
1756         smb2_util_close(tree1, h);
1757
1758         smb2_deltree(tree1, BASEDIR);
1759         return ret;
1760 }
1761
1762 static bool test_smb2_oplock_batch13(struct torture_context *tctx,
1763                                      struct smb2_tree *tree1,
1764                                      struct smb2_tree *tree2)
1765 {
1766         const char *fname = BASEDIR "\\test_batch13.dat";
1767         NTSTATUS status;
1768         bool ret = true;
1769         union smb_open io;
1770         struct smb2_handle h, h1, h2;
1771
1772         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1773         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1774
1775         /* cleanup */
1776         smb2_util_unlink(tree1, fname);
1777
1778         tree1->session->transport->oplock.handler = torture_oplock_handler;
1779         tree1->session->transport->oplock.private_data = tree1;
1780
1781         tree2->session->transport->oplock.handler = torture_oplock_handler;
1782         tree2->session->transport->oplock.private_data = tree2;
1783
1784         /*
1785           base ntcreatex parms
1786         */
1787         ZERO_STRUCT(io.smb2);
1788         io.generic.level = RAW_OPEN_SMB2;
1789         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1790         io.smb2.in.alloc_size = 0;
1791         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1792         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1793         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1794         io.smb2.in.create_options = 0;
1795         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1796         io.smb2.in.security_flags = 0;
1797         io.smb2.in.fname = fname;
1798
1799         torture_comment(tctx, "BATCH13: open with batch oplock\n");
1800         ZERO_STRUCT(break_info);
1801
1802         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1803         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1804         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1805                 NTCREATEX_SHARE_ACCESS_WRITE|
1806                 NTCREATEX_SHARE_ACCESS_DELETE;
1807         status = smb2_create(tree1, tctx, &(io.smb2));
1808         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1809         h1 = io.smb2.out.file.handle;
1810         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1811
1812         ZERO_STRUCT(break_info);
1813
1814         torture_comment(tctx, "second open with attributes only and "
1815                         "NTCREATEX_DISP_OVERWRITE dispostion causes "
1816                         "oplock break\n");
1817
1818         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1819         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1820         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1821                                 SEC_FILE_WRITE_ATTRIBUTE |
1822                                 SEC_STD_SYNCHRONIZE;
1823         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1824                                 NTCREATEX_SHARE_ACCESS_WRITE|
1825                                 NTCREATEX_SHARE_ACCESS_DELETE;
1826         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
1827         status = smb2_create(tree2, tctx, &(io.smb2));
1828         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1829         h2 = io.smb2.out.file.handle;
1830         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1831         torture_wait_for_oplock_break(tctx);
1832         CHECK_VAL(break_info.count, 1);
1833         CHECK_VAL(break_info.failures, 0);
1834
1835         smb2_util_close(tree1, h1);
1836         smb2_util_close(tree2, h2);
1837         smb2_util_close(tree1, h);
1838
1839         smb2_deltree(tree1, BASEDIR);
1840
1841         return ret;
1842 }
1843
1844 static bool test_smb2_oplock_batch14(struct torture_context *tctx,
1845                                      struct smb2_tree *tree1,
1846                                      struct smb2_tree *tree2)
1847 {
1848         const char *fname = BASEDIR "\\test_batch14.dat";
1849         NTSTATUS status;
1850         bool ret = true;
1851         union smb_open io;
1852         struct smb2_handle h, h1, h2;
1853
1854         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1855         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1856
1857         /* cleanup */
1858         smb2_util_unlink(tree1, fname);
1859
1860         tree1->session->transport->oplock.handler = torture_oplock_handler;
1861         tree1->session->transport->oplock.private_data = tree1;
1862
1863         /*
1864           base ntcreatex parms
1865         */
1866         ZERO_STRUCT(io.smb2);
1867         io.generic.level = RAW_OPEN_SMB2;
1868         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1869         io.smb2.in.alloc_size = 0;
1870         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1871         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1872         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1873         io.smb2.in.create_options = 0;
1874         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1875         io.smb2.in.security_flags = 0;
1876         io.smb2.in.fname = fname;
1877
1878         torture_comment(tctx, "BATCH14: open with batch oplock\n");
1879         ZERO_STRUCT(break_info);
1880
1881         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1882         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1883         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1884                 NTCREATEX_SHARE_ACCESS_WRITE|
1885                 NTCREATEX_SHARE_ACCESS_DELETE;
1886         status = smb2_create(tree1, tctx, &(io.smb2));
1887         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1888         h1 = io.smb2.out.file.handle;
1889         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1890
1891         ZERO_STRUCT(break_info);
1892
1893         torture_comment(tctx, "second open with attributes only and "
1894                         "NTCREATEX_DISP_SUPERSEDE dispostion causes "
1895                         "oplock break\n");
1896
1897         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1898         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1899         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1900                                 SEC_FILE_WRITE_ATTRIBUTE |
1901                                 SEC_STD_SYNCHRONIZE;
1902         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1903                                 NTCREATEX_SHARE_ACCESS_WRITE|
1904                                 NTCREATEX_SHARE_ACCESS_DELETE;
1905         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
1906         status = smb2_create(tree2, tctx, &(io.smb2));
1907         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1908         h2 = io.smb2.out.file.handle;
1909         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1910
1911         torture_wait_for_oplock_break(tctx);
1912         CHECK_VAL(break_info.count, 1);
1913         CHECK_VAL(break_info.failures, 0);
1914
1915         smb2_util_close(tree1, h1);
1916         smb2_util_close(tree2, h2);
1917         smb2_util_close(tree1, h);
1918
1919         smb2_deltree(tree1, BASEDIR);
1920         return ret;
1921 }
1922
1923 static bool test_smb2_oplock_batch15(struct torture_context *tctx,
1924                                      struct smb2_tree *tree1,
1925                                      struct smb2_tree *tree2)
1926 {
1927         const char *fname = BASEDIR "\\test_batch15.dat";
1928         NTSTATUS status;
1929         bool ret = true;
1930         union smb_open io;
1931         union smb_fileinfo qfi;
1932         struct smb2_handle h, h1;
1933
1934         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1935         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1936
1937         /* cleanup */
1938         smb2_util_unlink(tree1, fname);
1939
1940         tree1->session->transport->oplock.handler = torture_oplock_handler;
1941         tree1->session->transport->oplock.private_data = tree1;
1942
1943         /*
1944           base ntcreatex parms
1945         */
1946         ZERO_STRUCT(io.smb2);
1947         io.generic.level = RAW_OPEN_SMB2;
1948         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1949         io.smb2.in.alloc_size = 0;
1950         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1951         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1952         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1953         io.smb2.in.create_options = 0;
1954         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1955         io.smb2.in.security_flags = 0;
1956         io.smb2.in.fname = fname;
1957
1958         /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
1959         torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks "
1960                         "a batch oplock (should not).\n");
1961
1962         ZERO_STRUCT(break_info);
1963
1964         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1965         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1966         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1967         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1968                                 NTCREATEX_SHARE_ACCESS_WRITE|
1969                                 NTCREATEX_SHARE_ACCESS_DELETE;
1970         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1971         status = smb2_create(tree1, tctx, &(io.smb2));
1972         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1973         h1 = io.smb2.out.file.handle;
1974
1975         torture_wait_for_oplock_break(tctx);
1976         CHECK_VAL(break_info.count, 0);
1977         CHECK_VAL(break_info.failures, 0);
1978         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1979
1980         ZERO_STRUCT(qfi);
1981         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
1982         qfi.generic.in.file.handle = h1;
1983         status = smb2_getinfo_file(tree2, tctx, &qfi);
1984
1985         torture_wait_for_oplock_break(tctx);
1986         CHECK_VAL(break_info.count, 0);
1987
1988         smb2_util_close(tree1, h1);
1989         smb2_util_close(tree1, h);
1990
1991         smb2_deltree(tree1, BASEDIR);
1992         return ret;
1993 }
1994
1995 static bool test_smb2_oplock_batch16(struct torture_context *tctx,
1996                                      struct smb2_tree *tree1,
1997                                      struct smb2_tree *tree2)
1998 {
1999         const char *fname = BASEDIR "\\test_batch16.dat";
2000         NTSTATUS status;
2001         bool ret = true;
2002         union smb_open io;
2003         struct smb2_handle h, h1, h2;
2004
2005         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2006         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2007
2008         /* cleanup */
2009         smb2_util_unlink(tree1, fname);
2010
2011         tree1->session->transport->oplock.handler = torture_oplock_handler;
2012         tree1->session->transport->oplock.private_data = tree1;
2013
2014         tree2->session->transport->oplock.handler = torture_oplock_handler;
2015         tree2->session->transport->oplock.private_data = tree2;
2016
2017         /*
2018           base ntcreatex parms
2019         */
2020         ZERO_STRUCT(io.smb2);
2021         io.generic.level = RAW_OPEN_SMB2;
2022         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2023         io.smb2.in.alloc_size = 0;
2024         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2025         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2026         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2027         io.smb2.in.create_options = 0;
2028         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2029         io.smb2.in.security_flags = 0;
2030         io.smb2.in.fname = fname;
2031
2032         torture_comment(tctx, "BATCH16: open with batch oplock\n");
2033         ZERO_STRUCT(break_info);
2034
2035         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2036         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2037         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2038                 NTCREATEX_SHARE_ACCESS_WRITE|
2039                 NTCREATEX_SHARE_ACCESS_DELETE;
2040         status = smb2_create(tree1, tctx, &(io.smb2));
2041         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2042         h1 = io.smb2.out.file.handle;
2043         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2044
2045         ZERO_STRUCT(break_info);
2046
2047         torture_comment(tctx, "second open with attributes only and "
2048                         "NTCREATEX_DISP_OVERWRITE_IF dispostion causes "
2049                         "oplock break\n");
2050
2051         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2052         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2053         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
2054                                 SEC_FILE_WRITE_ATTRIBUTE |
2055                                 SEC_STD_SYNCHRONIZE;
2056         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2057                                 NTCREATEX_SHARE_ACCESS_WRITE|
2058                                 NTCREATEX_SHARE_ACCESS_DELETE;
2059         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2060         status = smb2_create(tree2, tctx, &(io.smb2));
2061         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2062         h2 = io.smb2.out.file.handle;
2063         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2064
2065         torture_wait_for_oplock_break(tctx);
2066         CHECK_VAL(break_info.count, 1);
2067         CHECK_VAL(break_info.failures, 0);
2068
2069         smb2_util_close(tree1, h1);
2070         smb2_util_close(tree2, h2);
2071         smb2_util_close(tree1, h);
2072
2073         smb2_deltree(tree1, BASEDIR);
2074         return ret;
2075 }
2076
2077 /* This function is a placeholder for the SMB1 RAW-OPLOCK-BATCH17 test.  Since
2078  * SMB2 doesn't have a RENAME command this test isn't applicable.  However,
2079  * it's much less confusing, when comparing test, to keep the SMB1 and SMB2
2080  * test numbers in sync. */
2081 #if 0
2082 static bool test_raw_oplock_batch17(struct torture_context *tctx,
2083                                     struct smb2_tree *tree1,
2084                                     struct smb2_tree *tree2)
2085 {
2086         return true;
2087 }
2088 #endif
2089
2090 /* This function is a placeholder for the SMB1 RAW-OPLOCK-BATCH18 test.  Since
2091  * SMB2 doesn't have an NTRENAME command this test isn't applicable.  However,
2092  * it's much less confusing, when comparing tests, to keep the SMB1 and SMB2
2093  * test numbers in sync. */
2094 #if 0
2095 static bool test_raw_oplock_batch18(struct torture_context *tctx,
2096                                     struct smb2_tree *tree1,
2097                                     struct smb2_tree *tree2)
2098 {
2099         return true;
2100 }
2101 #endif
2102
2103 static bool test_smb2_oplock_batch19(struct torture_context *tctx,
2104                                      struct smb2_tree *tree1)
2105 {
2106         const char *fname1 = BASEDIR "\\test_batch19_1.dat";
2107         const char *fname2 = BASEDIR "\\test_batch19_2.dat";
2108         NTSTATUS status;
2109         bool ret = true;
2110         union smb_open io;
2111         union smb_fileinfo qfi;
2112         union smb_setfileinfo sfi;
2113         struct smb2_handle h, h1;
2114
2115         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2116         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2117
2118         /* cleanup */
2119         smb2_util_unlink(tree1, fname1);
2120         smb2_util_unlink(tree1, fname2);
2121
2122         tree1->session->transport->oplock.handler = torture_oplock_handler;
2123         tree1->session->transport->oplock.private_data = tree1;
2124
2125         /*
2126           base ntcreatex parms
2127         */
2128         ZERO_STRUCT(io.smb2);
2129         io.generic.level = RAW_OPEN_SMB2;
2130         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2131         io.smb2.in.alloc_size = 0;
2132         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2133         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2134         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2135         io.smb2.in.create_options = 0;
2136         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2137         io.smb2.in.security_flags = 0;
2138         io.smb2.in.fname = fname1;
2139
2140         torture_comment(tctx, "BATCH19: open a file with an batch oplock "
2141                         "(share mode: none)\n");
2142         ZERO_STRUCT(break_info);
2143         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2144         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2145         status = smb2_create(tree1, tctx, &(io.smb2));
2146         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2147         h1 = io.smb2.out.file.handle;
2148         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2149
2150         torture_comment(tctx, "setfileinfo rename info should not trigger "
2151                         "a break but should cause a sharing violation\n");
2152         ZERO_STRUCT(sfi);
2153         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2154         sfi.generic.in.file.path = fname1;
2155         sfi.rename_information.in.file.handle   = h1;
2156         sfi.rename_information.in.overwrite     = 0;
2157         sfi.rename_information.in.root_fid      = 0;
2158         sfi.rename_information.in.new_name      = fname2;
2159
2160         status = smb2_setinfo_file(tree1, &sfi);
2161
2162         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2163                                       "Incorrect status");
2164
2165         torture_wait_for_oplock_break(tctx);
2166         CHECK_VAL(break_info.count, 0);
2167
2168         ZERO_STRUCT(qfi);
2169         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2170         qfi.generic.in.file.handle = h1;
2171
2172         status = smb2_getinfo_file(tree1, tctx, &qfi);
2173         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2174         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2175
2176         smb2_util_close(tree1, h1);
2177         smb2_util_close(tree1, h);
2178
2179         smb2_deltree(tree1, fname1);
2180         smb2_deltree(tree1, fname2);
2181         return ret;
2182 }
2183
2184 static bool test_smb2_oplock_batch20(struct torture_context *tctx,
2185                                      struct smb2_tree *tree1,
2186                                      struct smb2_tree *tree2)
2187 {
2188         const char *fname1 = BASEDIR "\\test_batch20_1.dat";
2189         const char *fname2 = BASEDIR "\\test_batch20_2.dat";
2190         NTSTATUS status;
2191         bool ret = true;
2192         union smb_open io;
2193         union smb_fileinfo qfi;
2194         union smb_setfileinfo sfi;
2195         struct smb2_handle h, h1, h2;
2196
2197         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2198         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2199
2200         /* cleanup */
2201         smb2_util_unlink(tree1, fname1);
2202         smb2_util_unlink(tree1, fname2);
2203
2204         tree1->session->transport->oplock.handler = torture_oplock_handler;
2205         tree1->session->transport->oplock.private_data = tree1;
2206
2207         /*
2208           base ntcreatex parms
2209         */
2210         ZERO_STRUCT(io.smb2);
2211         io.generic.level = RAW_OPEN_SMB2;
2212         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2213         io.smb2.in.alloc_size = 0;
2214         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2215         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2216         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2217         io.smb2.in.create_options = 0;
2218         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2219         io.smb2.in.security_flags = 0;
2220         io.smb2.in.fname = fname1;
2221
2222         torture_comment(tctx, "BATCH20: open a file with an batch oplock "
2223                         "(share mode: all)\n");
2224         ZERO_STRUCT(break_info);
2225         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2226         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2227         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2228                                 NTCREATEX_SHARE_ACCESS_WRITE|
2229                                 NTCREATEX_SHARE_ACCESS_DELETE;
2230         status = smb2_create(tree1, tctx, &(io.smb2));
2231         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2232         h1 = io.smb2.out.file.handle;
2233         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2234
2235         torture_comment(tctx, "setfileinfo rename info should not trigger "
2236                         "a break but should cause a sharing violation\n");
2237         ZERO_STRUCT(sfi);
2238         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2239         sfi.rename_information.in.file.handle   = h1;
2240         sfi.rename_information.in.overwrite     = 0;
2241         sfi.rename_information.in.new_name      = fname2;
2242
2243         status = smb2_setinfo_file(tree1, &sfi);
2244         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2245                                       "Incorrect status");
2246
2247         torture_wait_for_oplock_break(tctx);
2248         CHECK_VAL(break_info.count, 0);
2249
2250         ZERO_STRUCT(qfi);
2251         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2252         qfi.generic.in.file.handle = h1;
2253
2254         status = smb2_getinfo_file(tree1, tctx, &qfi);
2255         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2256         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2257
2258         torture_comment(tctx, "open the file a second time requesting batch "
2259                         "(share mode: all)\n");
2260         ZERO_STRUCT(break_info);
2261         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2262         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2263         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2264                                 NTCREATEX_SHARE_ACCESS_WRITE|
2265                                 NTCREATEX_SHARE_ACCESS_DELETE;
2266         io.smb2.in.fname = fname1;
2267         status = smb2_create(tree2, tctx, &(io.smb2));
2268         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2269         h2 = io.smb2.out.file.handle;
2270         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2271
2272         torture_wait_for_oplock_break(tctx);
2273         CHECK_VAL(break_info.count, 1);
2274         CHECK_VAL(break_info.failures, 0);
2275         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2276
2277         torture_comment(tctx, "setfileinfo rename info should not trigger "
2278                         "a break but should cause a sharing violation\n");
2279         ZERO_STRUCT(break_info);
2280         ZERO_STRUCT(sfi);
2281         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2282         sfi.rename_information.in.file.handle   = h2;
2283         sfi.rename_information.in.overwrite     = 0;
2284         sfi.rename_information.in.new_name      = fname2;
2285
2286         status = smb2_setinfo_file(tree2, &sfi);
2287         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2288                                       "Incorrect status");
2289
2290         torture_wait_for_oplock_break(tctx);
2291         CHECK_VAL(break_info.count, 0);
2292
2293         ZERO_STRUCT(qfi);
2294         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2295         qfi.generic.in.file.handle = h1;
2296
2297         status = smb2_getinfo_file(tree1, tctx, &qfi);
2298         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2299         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2300
2301         ZERO_STRUCT(qfi);
2302         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2303         qfi.generic.in.file.handle = h2;
2304
2305         status = smb2_getinfo_file(tree2, tctx, &qfi);
2306         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2307         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2308
2309         smb2_util_close(tree1, h1);
2310         smb2_util_close(tree2, h2);
2311         smb2_util_close(tree1, h);
2312
2313         smb2_deltree(tree1, fname1);
2314         return ret;
2315 }
2316
2317 static bool test_smb2_oplock_batch21(struct torture_context *tctx,
2318                                      struct smb2_tree *tree1)
2319 {
2320         const char *fname = BASEDIR "\\test_batch21.dat";
2321         NTSTATUS status;
2322         bool ret = true;
2323         union smb_open io;
2324         struct smb2_handle h, h1;
2325         char c = 0;
2326
2327         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2328         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2329
2330         /* cleanup */
2331         smb2_util_unlink(tree1, fname);
2332
2333         tree1->session->transport->oplock.handler = torture_oplock_handler;
2334         tree1->session->transport->oplock.private_data = tree1;
2335
2336         /*
2337           base ntcreatex parms
2338         */
2339         ZERO_STRUCT(io.smb2);
2340         io.generic.level = RAW_OPEN_SMB2;
2341         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2342         io.smb2.in.alloc_size = 0;
2343         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2344         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2345         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2346         io.smb2.in.create_options = 0;
2347         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2348         io.smb2.in.security_flags = 0;
2349         io.smb2.in.fname = fname;
2350
2351         /*
2352           with a batch oplock we get a break
2353         */
2354         torture_comment(tctx, "BATCH21: open with batch oplock\n");
2355         ZERO_STRUCT(break_info);
2356         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2357         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2358         status = smb2_create(tree1, tctx, &(io.smb2));
2359         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2360         h1 = io.smb2.out.file.handle;
2361         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2362
2363         torture_comment(tctx, "writing should not generate a break\n");
2364         status = smb2_util_write(tree1, h1, &c, 0, 1);
2365         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2366
2367         torture_wait_for_oplock_break(tctx);
2368         CHECK_VAL(break_info.count, 0);
2369
2370         smb2_util_close(tree1, h1);
2371         smb2_util_close(tree1, h);
2372
2373         smb2_deltree(tree1, BASEDIR);
2374         return ret;
2375 }
2376
2377 static bool test_smb2_oplock_batch22(struct torture_context *tctx,
2378                                      struct smb2_tree *tree1)
2379 {
2380         const char *fname = BASEDIR "\\test_batch22.dat";
2381         NTSTATUS status;
2382         bool ret = true;
2383         union smb_open io;
2384         struct smb2_handle h, h1, h2;
2385         struct timeval tv;
2386         int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
2387         int te;
2388
2389         if (torture_setting_bool(tctx, "samba3", false)) {
2390                 torture_skip(tctx, "BATCH22 disabled against samba3\n");
2391         }
2392
2393         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2394         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2395
2396         /* cleanup */
2397         smb2_util_unlink(tree1, fname);
2398
2399         tree1->session->transport->oplock.handler = torture_oplock_handler;
2400         tree1->session->transport->oplock.private_data = tree1;
2401         /*
2402           base ntcreatex parms
2403         */
2404         ZERO_STRUCT(io.smb2);
2405         io.generic.level = RAW_OPEN_SMB2;
2406         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2407         io.smb2.in.alloc_size = 0;
2408         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2409         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2410         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2411         io.smb2.in.create_options = 0;
2412         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2413         io.smb2.in.security_flags = 0;
2414         io.smb2.in.fname = fname;
2415
2416         /*
2417           with a batch oplock we get a break
2418         */
2419         torture_comment(tctx, "BATCH22: open with batch oplock\n");
2420         ZERO_STRUCT(break_info);
2421         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2422         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2423         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2424                 NTCREATEX_SHARE_ACCESS_WRITE|
2425                 NTCREATEX_SHARE_ACCESS_DELETE;
2426         status = smb2_create(tree1, tctx, &(io.smb2));
2427         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2428         h1 = io.smb2.out.file.handle;
2429         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2430
2431         torture_comment(tctx, "a 2nd open should succeed after the oplock "
2432                         "break timeout\n");
2433         tv = timeval_current();
2434         tree1->session->transport->oplock.handler =
2435                                 torture_oplock_handler_timeout;
2436         status = smb2_create(tree1, tctx, &(io.smb2));
2437         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2438         h2 = io.smb2.out.file.handle;
2439         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2440
2441         torture_wait_for_oplock_break(tctx);
2442         te = (int)timeval_elapsed(&tv);
2443         CHECK_RANGE(te, timeout - 1, timeout + 15);
2444         torture_comment(tctx, "waited %d seconds for oplock timeout\n", te);
2445
2446         CHECK_VAL(break_info.count, 1);
2447         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
2448         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2449         CHECK_VAL(break_info.failures, 0);
2450
2451         smb2_util_close(tree1, h1);
2452         smb2_util_close(tree1, h2);
2453         smb2_util_close(tree1, h);
2454
2455         smb2_deltree(tree1, BASEDIR);
2456         return ret;
2457 }
2458
2459 static bool test_smb2_oplock_batch23(struct torture_context *tctx,
2460                                      struct smb2_tree *tree1,
2461                                      struct smb2_tree *tree2)
2462 {
2463         const char *fname = BASEDIR "\\test_batch23.dat";
2464         NTSTATUS status;
2465         bool ret = true;
2466         union smb_open io;
2467         struct smb2_handle h, h1, h2, h3;
2468         struct smb2_tree *tree3 = NULL;
2469
2470         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2471         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2472
2473         /* cleanup */
2474         smb2_util_unlink(tree1, fname);
2475
2476         ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
2477         CHECK_VAL(ret, true);
2478
2479         tree1->session->transport->oplock.handler = torture_oplock_handler;
2480         tree1->session->transport->oplock.private_data = tree1;
2481
2482         tree2->session->transport->oplock.handler = torture_oplock_handler;
2483         tree2->session->transport->oplock.private_data = tree2;
2484
2485         tree3->session->transport->oplock.handler = torture_oplock_handler;
2486         tree3->session->transport->oplock.private_data = tree3;
2487
2488         /*
2489           base ntcreatex parms
2490         */
2491         ZERO_STRUCT(io.smb2);
2492         io.generic.level = RAW_OPEN_SMB2;
2493         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2494         io.smb2.in.alloc_size = 0;
2495         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2496         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2497         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2498         io.smb2.in.create_options = 0;
2499         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2500         io.smb2.in.security_flags = 0;
2501         io.smb2.in.fname = fname;
2502
2503         torture_comment(tctx, "BATCH23: an open and ask for a batch oplock\n");
2504         ZERO_STRUCT(break_info);
2505
2506         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
2507                                 SEC_RIGHTS_FILE_WRITE;
2508         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2509                                 NTCREATEX_SHARE_ACCESS_WRITE;
2510         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2511         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2512         status = smb2_create(tree1, tctx, &(io.smb2));
2513         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2514         h1 = io.smb2.out.file.handle;
2515         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2516
2517         ZERO_STRUCT(break_info);
2518
2519         torture_comment(tctx, "a 2nd open without level2 oplock support "
2520                         "should generate a break to level2\n");
2521         status = smb2_create(tree3, tctx, &(io.smb2));
2522         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2523         h3 = io.smb2.out.file.handle;
2524
2525         torture_wait_for_oplock_break(tctx);
2526         CHECK_VAL(break_info.count, 1);
2527         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
2528         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2529         CHECK_VAL(break_info.failures, 0);
2530
2531         ZERO_STRUCT(break_info);
2532
2533         torture_comment(tctx, "a 3rd open with level2 oplock support should "
2534                         "not generate a break\n");
2535         status = smb2_create(tree2, tctx, &(io.smb2));
2536         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2537         h2 = io.smb2.out.file.handle;
2538         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2539
2540         torture_wait_for_oplock_break(tctx);
2541         CHECK_VAL(break_info.count, 0);
2542
2543         smb2_util_close(tree1, h1);
2544         smb2_util_close(tree2, h2);
2545         smb2_util_close(tree3, h3);
2546         smb2_util_close(tree1, h);
2547
2548         smb2_deltree(tree1, BASEDIR);
2549         return ret;
2550 }
2551
2552 static bool test_smb2_oplock_batch24(struct torture_context *tctx,
2553                                      struct smb2_tree *tree1,
2554                                      struct smb2_tree *tree2)
2555 {
2556         const char *fname = BASEDIR "\\test_batch24.dat";
2557         NTSTATUS status;
2558         bool ret = true;
2559         union smb_open io;
2560         struct smb2_handle h, h1, h2;
2561         struct smb2_tree *tree3 = NULL;
2562
2563         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2564         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2565
2566         /* cleanup */
2567         smb2_util_unlink(tree1, fname);
2568
2569         ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
2570         CHECK_VAL(ret, true);
2571
2572         tree1->session->transport->oplock.handler = torture_oplock_handler;
2573         tree1->session->transport->oplock.private_data = tree1;
2574
2575         tree2->session->transport->oplock.handler = torture_oplock_handler;
2576         tree2->session->transport->oplock.private_data = tree2;
2577
2578         tree3->session->transport->oplock.handler = torture_oplock_handler;
2579         tree3->session->transport->oplock.private_data = tree3;
2580
2581         /*
2582           base ntcreatex parms
2583         */
2584         ZERO_STRUCT(io.smb2);
2585         io.generic.level = RAW_OPEN_SMB2;
2586         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2587         io.smb2.in.alloc_size = 0;
2588         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2589         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2590         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2591         io.smb2.in.create_options = 0;
2592         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2593         io.smb2.in.security_flags = 0;
2594         io.smb2.in.fname = fname;
2595
2596         torture_comment(tctx, "BATCH24: a open without level support and "
2597                         "ask for a batch oplock\n");
2598         ZERO_STRUCT(break_info);
2599
2600         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
2601                                 SEC_RIGHTS_FILE_WRITE;
2602         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2603                                 NTCREATEX_SHARE_ACCESS_WRITE;
2604         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2605         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2606
2607         status = smb2_create(tree3, tctx, &(io.smb2));
2608         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2609         h2 = io.smb2.out.file.handle;
2610         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2611
2612         ZERO_STRUCT(break_info);
2613
2614         torture_comment(tctx, "a 2nd open with level2 oplock support should "
2615                         "generate a break\n");
2616         status = smb2_create(tree2, tctx, &(io.smb2));
2617         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2618         h1 = io.smb2.out.file.handle;
2619         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2620
2621         torture_wait_for_oplock_break(tctx);
2622         CHECK_VAL(break_info.count, 1);
2623         CHECK_VAL(break_info.handle.data[0], h2.data[0]);
2624         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2625         CHECK_VAL(break_info.failures, 0);
2626
2627         smb2_util_close(tree3, h2);
2628         smb2_util_close(tree2, h1);
2629         smb2_util_close(tree1, h);
2630
2631         smb2_deltree(tree1, BASEDIR);
2632         return ret;
2633 }
2634
2635 static bool test_smb2_oplock_batch25(struct torture_context *tctx,
2636                                      struct smb2_tree *tree1)
2637 {
2638         const char *fname = BASEDIR "\\test_batch25.dat";
2639         NTSTATUS status;
2640         bool ret = true;
2641         union smb_open io;
2642         struct smb2_handle h, h1;
2643
2644         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2645         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2646
2647         /* cleanup */
2648         smb2_util_unlink(tree1, fname);
2649
2650         tree1->session->transport->oplock.handler = torture_oplock_handler;
2651         tree1->session->transport->oplock.private_data = tree1;
2652
2653         /*
2654           base ntcreatex parms
2655         */
2656         ZERO_STRUCT(io.smb2);
2657         io.generic.level = RAW_OPEN_SMB2;
2658         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2659         io.smb2.in.alloc_size = 0;
2660         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2661         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2662         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2663         io.smb2.in.create_options = 0;
2664         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2665         io.smb2.in.security_flags = 0;
2666         io.smb2.in.fname = fname;
2667
2668         torture_comment(tctx, "BATCH25: open a file with an batch oplock "
2669                         "(share mode: none)\n");
2670
2671         ZERO_STRUCT(break_info);
2672         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2673         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2674
2675         status = smb2_create(tree1, tctx, &(io.smb2));
2676         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2677         h1 = io.smb2.out.file.handle;
2678         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2679
2680         torture_comment(tctx, "changing the file attribute info should trigger "
2681                         "a break and a violation\n");
2682
2683         status = smb2_util_setatr(tree1, fname, FILE_ATTRIBUTE_HIDDEN);
2684         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2685                                       "Incorrect status");
2686
2687         torture_wait_for_oplock_break(tctx);
2688         CHECK_VAL(break_info.count, 1);
2689
2690         smb2_util_close(tree1, h1);
2691         smb2_util_close(tree1, h);
2692
2693         smb2_deltree(tree1, fname);
2694         return ret;
2695 }
2696
2697 /* Test how oplocks work on streams. */
2698 static bool test_raw_oplock_stream1(struct torture_context *tctx,
2699                                     struct smb2_tree *tree1,
2700                                     struct smb2_tree *tree2)
2701 {
2702         NTSTATUS status;
2703         union smb_open io;
2704         const char *fname_base = BASEDIR "\\test_stream1.txt";
2705         const char *fname_stream, *fname_default_stream;
2706         const char *default_stream = "::$DATA";
2707         const char *stream = "Stream One:$DATA";
2708         bool ret = true;
2709         struct smb2_handle h, h_base, h_stream;
2710         int i;
2711
2712 #define NSTREAM_OPLOCK_RESULTS 8
2713         struct {
2714                 const char **fname;
2715                 bool open_base_file;
2716                 uint32_t oplock_req;
2717                 uint32_t oplock_granted;
2718         } stream_oplock_results[NSTREAM_OPLOCK_RESULTS] = {
2719                 /* Request oplock on stream without the base file open. */
2720                 {&fname_stream, false, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
2721                 {&fname_default_stream, false, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
2722                 {&fname_stream, false, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
2723                 {&fname_default_stream, false,  SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
2724
2725                 /* Request oplock on stream with the base file open. */
2726                 {&fname_stream, true, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
2727                 {&fname_default_stream, true, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_II},
2728                 {&fname_stream, true, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
2729                 {&fname_default_stream, true,  SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_II},
2730         };
2731
2732         /* Only passes against windows at the moment. */
2733         if (torture_setting_bool(tctx, "samba3", false) ||
2734             torture_setting_bool(tctx, "samba4", false)) {
2735                 torture_skip(tctx, "STREAM1 disabled against samba3+4\n");
2736         }
2737
2738         fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
2739         fname_default_stream = talloc_asprintf(tctx, "%s%s", fname_base,
2740                                                default_stream);
2741
2742         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2743         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2744
2745         /* Initialize handles to "closed".  Using -1 in the first 64-bytes
2746          * as the sentry for this */
2747         h_stream.data[0] = -1;
2748
2749         /* cleanup */
2750         smb2_util_unlink(tree1, fname_base);
2751
2752         tree1->session->transport->oplock.handler = torture_oplock_handler;
2753         tree1->session->transport->oplock.private_data = tree1;
2754
2755         tree2->session->transport->oplock.handler = torture_oplock_handler;
2756         tree2->session->transport->oplock.private_data = tree2;
2757
2758         /* Setup generic open parameters. */
2759         ZERO_STRUCT(io.smb2);
2760         io.generic.level = RAW_OPEN_SMB2;
2761         io.smb2.in.desired_access = (SEC_FILE_READ_DATA |
2762                                      SEC_FILE_WRITE_DATA |
2763                                      SEC_FILE_APPEND_DATA |
2764                                      SEC_STD_READ_CONTROL);
2765         io.smb2.in.alloc_size = 0;
2766         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2767         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2768                                   NTCREATEX_SHARE_ACCESS_WRITE;
2769         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2770         io.smb2.in.create_options = 0;
2771         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2772         io.smb2.in.security_flags = 0;
2773
2774         /* Create the file with a stream */
2775         io.smb2.in.fname = fname_stream;
2776         io.smb2.in.create_flags = 0;
2777         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2778         status = smb2_create(tree1, tctx, &(io.smb2));
2779         torture_assert_ntstatus_ok(tctx, status, "Error creating file");
2780         smb2_util_close(tree1, io.smb2.out.file.handle);
2781
2782         /* Change the disposition to open now that the file has been created. */
2783         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
2784
2785         /* Try some permutations of taking oplocks on streams. */
2786         for (i = 0; i < NSTREAM_OPLOCK_RESULTS; i++) {
2787                 const char *fname = *stream_oplock_results[i].fname;
2788                 bool open_base_file = stream_oplock_results[i].open_base_file;
2789                 uint32_t oplock_req = stream_oplock_results[i].oplock_req;
2790                 uint32_t oplock_granted =
2791                     stream_oplock_results[i].oplock_granted;
2792
2793                 if (open_base_file) {
2794                         torture_comment(tctx, "Opening base file: %s with "
2795                             "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
2796                         io.smb2.in.fname = fname_base;
2797                         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2798                         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2799                         status = smb2_create(tree2, tctx, &(io.smb2));
2800                         torture_assert_ntstatus_ok(tctx, status,
2801                             "Error opening file");
2802                         CHECK_VAL(io.smb2.out.oplock_level,
2803                             SMB2_OPLOCK_LEVEL_BATCH);
2804                         h_base = io.smb2.out.file.handle;
2805                 }
2806
2807                 torture_comment(tctx, "%d: Opening stream: %s with %d\n", i,
2808                     fname, oplock_req);
2809                 io.smb2.in.fname = fname;
2810                 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2811                 io.smb2.in.oplock_level = oplock_req;
2812
2813                 /* Do the open with the desired oplock on the stream. */
2814                 status = smb2_create(tree1, tctx, &(io.smb2));
2815                 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
2816                 CHECK_VAL(io.smb2.out.oplock_level, oplock_granted);
2817                 smb2_util_close(tree1, io.smb2.out.file.handle);
2818
2819                 /* Cleanup the base file if it was opened. */
2820                 if (open_base_file)
2821                         smb2_util_close(tree2, h_base);
2822         }
2823
2824         /* Open the stream with an exclusive oplock. */
2825         torture_comment(tctx, "Opening stream: %s with %d\n",
2826             fname_stream, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
2827         io.smb2.in.fname = fname_stream;
2828         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2829         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
2830         status = smb2_create(tree1, tctx, &(io.smb2));
2831         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
2832         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
2833         h_stream = io.smb2.out.file.handle;
2834
2835         /* Open the base file and see if it contends. */
2836         ZERO_STRUCT(break_info);
2837         torture_comment(tctx, "Opening base file: %s with %d\n",
2838             fname_base, SMB2_OPLOCK_LEVEL_BATCH);
2839         io.smb2.in.fname = fname_base;
2840         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2841         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2842         status = smb2_create(tree2, tctx, &(io.smb2));
2843         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
2844         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2845         smb2_util_close(tree2, io.smb2.out.file.handle);
2846
2847         torture_wait_for_oplock_break(tctx);
2848         CHECK_VAL(break_info.count, 0);
2849         CHECK_VAL(break_info.failures, 0);
2850
2851         /* Open the stream again to see if it contends. */
2852         ZERO_STRUCT(break_info);
2853         torture_comment(tctx, "Opening stream again: %s with "
2854             "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
2855         io.smb2.in.fname = fname_stream;
2856         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2857         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
2858         status = smb2_create(tree2, tctx, &(io.smb2));
2859         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
2860         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2861         smb2_util_close(tree2, io.smb2.out.file.handle);
2862
2863         torture_wait_for_oplock_break(tctx);
2864         CHECK_VAL(break_info.count, 1);
2865         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2866         CHECK_VAL(break_info.failures, 0);
2867
2868         /* Close the stream. */
2869         if (h_stream.data[0] != -1) {
2870                 smb2_util_close(tree1, h_stream);
2871         }
2872
2873         smb2_util_close(tree1, h);
2874
2875         smb2_deltree(tree1, BASEDIR);
2876         return ret;
2877 }
2878
2879 static bool test_smb2_oplock_doc(struct torture_context *tctx, struct smb2_tree *tree)
2880 {
2881         const char *fname = BASEDIR "\\test_oplock_doc.dat";
2882         NTSTATUS status;
2883         bool ret = true;
2884         union smb_open io;
2885         struct smb2_handle h, h1;
2886
2887         status = torture_smb2_testdir(tree, BASEDIR, &h);
2888         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2889
2890         /* cleanup */
2891         smb2_util_unlink(tree, fname);
2892         tree->session->transport->oplock.handler = torture_oplock_handler;
2893         tree->session->transport->oplock.private_data = tree;
2894
2895         /*
2896           base ntcreatex parms
2897         */
2898         ZERO_STRUCT(io.smb2);
2899         io.generic.level = RAW_OPEN_SMB2;
2900         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2901         io.smb2.in.alloc_size = 0;
2902         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2903         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2904         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2905         io.smb2.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
2906         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2907         io.smb2.in.security_flags = 0;
2908         io.smb2.in.fname = fname;
2909
2910         torture_comment(tctx, "open a delete-on-close file with a batch "
2911                         "oplock\n");
2912         ZERO_STRUCT(break_info);
2913         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2914         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2915
2916         status = smb2_create(tree, tctx, &(io.smb2));
2917         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2918         h1 = io.smb2.out.file.handle;
2919         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2920
2921         smb2_util_close(tree, h1);
2922
2923         smb2_util_unlink(tree, fname);
2924         smb2_deltree(tree, BASEDIR);
2925         return ret;
2926 }
2927
2928 /* Open a file with a batch oplock, then open it again from a second client
2929  * requesting no oplock. Having two open file handles should break our own
2930  * oplock during BRL acquisition.
2931  */
2932 static bool test_smb2_oplock_brl1(struct torture_context *tctx,
2933                                 struct smb2_tree *tree1,
2934                                 struct smb2_tree *tree2)
2935 {
2936         const char *fname = BASEDIR "\\test_batch_brl.dat";
2937         /*int fname, f;*/
2938         bool ret = true;
2939         uint8_t buf[1000];
2940         bool correct = true;
2941         union smb_open io;
2942         NTSTATUS status;
2943         struct smb2_lock lck;
2944         struct smb2_lock_element lock[1];
2945         struct smb2_handle h, h1, h2;
2946
2947         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2948         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2949
2950         /* cleanup */
2951         smb2_util_unlink(tree1, fname);
2952
2953         tree1->session->transport->oplock.handler =
2954             torture_oplock_handler_two_notifications;
2955         tree1->session->transport->oplock.private_data = tree1;
2956
2957         /*
2958           base ntcreatex parms
2959         */
2960         ZERO_STRUCT(io.smb2);
2961         io.generic.level = RAW_OPEN_SMB2;
2962         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
2963                                     SEC_RIGHTS_FILE_WRITE;
2964         io.smb2.in.alloc_size = 0;
2965         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2966         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2967                                   NTCREATEX_SHARE_ACCESS_WRITE;
2968         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2969         io.smb2.in.create_options = 0;
2970         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2971         io.smb2.in.security_flags = 0;
2972         io.smb2.in.fname = fname;
2973
2974         /*
2975           with a batch oplock we get a break
2976         */
2977         torture_comment(tctx, "open with batch oplock\n");
2978         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2979         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2980
2981         status = smb2_create(tree1, tctx, &(io.smb2));
2982         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2983         h1 = io.smb2.out.file.handle;
2984         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2985
2986         /* create a file with bogus data */
2987         memset(buf, 0, sizeof(buf));
2988
2989         status = smb2_util_write(tree1, h1,buf, 0, sizeof(buf));
2990         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
2991                 torture_comment(tctx, "Failed to create file\n");
2992                 correct = false;
2993                 goto done;
2994         }
2995
2996         torture_comment(tctx, "a 2nd open should give a break\n");
2997         ZERO_STRUCT(break_info);
2998
2999         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3000         io.smb2.in.oplock_level = 0;
3001         status = smb2_create(tree2, tctx, &(io.smb2));
3002         h2 = io.smb2.out.file.handle;
3003         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3004
3005         torture_wait_for_oplock_break(tctx);
3006         CHECK_VAL(break_info.count, 1);
3007         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
3008         CHECK_VAL(break_info.failures, 0);
3009         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3010
3011         ZERO_STRUCT(break_info);
3012
3013         torture_comment(tctx, "a self BRL acquisition should break to none\n");
3014         lock[0].offset = 0;
3015         lock[0].length = 4;
3016         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3017                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3018
3019         ZERO_STRUCT(lck);
3020         lck.in.file.handle = h1;
3021         lck.in.locks = &lock[0];
3022         lck.in.lock_count = 1;
3023         status = smb2_lock(tree1, &lck);
3024         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3025
3026         torture_wait_for_oplock_break(tctx);
3027         CHECK_VAL(break_info.count, 1);
3028         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
3029         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3030         CHECK_VAL(break_info.failures, 0);
3031
3032         /* expect no oplock break */
3033         ZERO_STRUCT(break_info);
3034         lock[0].offset = 2;
3035         status = smb2_lock(tree1, &lck);
3036         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3037                                       "Incorrect status");
3038
3039         torture_wait_for_oplock_break(tctx);
3040         CHECK_VAL(break_info.count, 0);
3041         CHECK_VAL(break_info.level, 0);
3042         CHECK_VAL(break_info.failures, 0);
3043
3044         smb2_util_close(tree1, h1);
3045         smb2_util_close(tree2, h2);
3046         smb2_util_close(tree1, h);
3047
3048 done:
3049         smb2_deltree(tree1, BASEDIR);
3050         return ret;
3051
3052 }
3053
3054 /* Open a file with a batch oplock on one tree and then acquire a brl.
3055  * We should not contend our own oplock.
3056  */
3057 static bool test_smb2_oplock_brl2(struct torture_context *tctx, struct smb2_tree *tree1)
3058 {
3059         const char *fname = BASEDIR "\\test_batch_brl.dat";
3060         /*int fname, f;*/
3061         bool ret = true;
3062         uint8_t buf[1000];
3063         bool correct = true;
3064         union smb_open io;
3065         NTSTATUS status;
3066         struct smb2_handle h, h1;
3067         struct smb2_lock lck;
3068         struct smb2_lock_element lock[1];
3069
3070         status = torture_smb2_testdir(tree1, BASEDIR, &h);
3071         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3072
3073         /* cleanup */
3074         smb2_util_unlink(tree1, fname);
3075
3076         tree1->session->transport->oplock.handler = torture_oplock_handler;
3077         tree1->session->transport->oplock.private_data = tree1;
3078
3079         /*
3080           base ntcreatex parms
3081         */
3082         ZERO_STRUCT(io.smb2);
3083         io.generic.level = RAW_OPEN_SMB2;
3084         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3085                                     SEC_RIGHTS_FILE_WRITE;
3086         io.smb2.in.alloc_size = 0;
3087         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3088         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3089                                   NTCREATEX_SHARE_ACCESS_WRITE;
3090         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3091         io.smb2.in.create_options = 0;
3092         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3093         io.smb2.in.security_flags = 0;
3094         io.smb2.in.fname = fname;
3095
3096         /*
3097           with a batch oplock we get a break
3098         */
3099         torture_comment(tctx, "open with batch oplock\n");
3100         ZERO_STRUCT(break_info);
3101         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3102         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3103
3104         status = smb2_create(tree1, tctx, &(io.smb2));
3105         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3106         h1 = io.smb2.out.file.handle;
3107         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3108
3109         /* create a file with bogus data */
3110         memset(buf, 0, sizeof(buf));
3111
3112         status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
3113         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3114                 torture_comment(tctx, "Failed to create file\n");
3115                 correct = false;
3116                 goto done;
3117         }
3118
3119         ZERO_STRUCT(break_info);
3120
3121         torture_comment(tctx, "a self BRL acquisition should not break to "
3122                         "none\n");
3123
3124         lock[0].offset = 0;
3125         lock[0].length = 4;
3126         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3127                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3128
3129         ZERO_STRUCT(lck);
3130         lck.in.file.handle = h1;
3131         lck.in.locks = &lock[0];
3132         lck.in.lock_count = 1;
3133         status = smb2_lock(tree1, &lck);
3134         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3135
3136         lock[0].offset = 2;
3137         status = smb2_lock(tree1, &lck);
3138         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3139                                       "Incorrect status");
3140
3141         /* With one file handle open a BRL should not contend our oplock.
3142          * Thus, no oplock break will be received and the entire break_info
3143          * struct will be 0 */
3144         torture_wait_for_oplock_break(tctx);
3145         CHECK_VAL(break_info.count, 0);
3146         CHECK_VAL(break_info.level, 0);
3147         CHECK_VAL(break_info.failures, 0);
3148
3149         smb2_util_close(tree1, h1);
3150         smb2_util_close(tree1, h);
3151
3152 done:
3153         smb2_deltree(tree1, BASEDIR);
3154         return ret;
3155 }
3156
3157 /* Open a file with a batch oplock twice from one tree and then acquire a
3158  * brl. BRL acquisition should break our own oplock.
3159  */
3160 static bool test_smb2_oplock_brl3(struct torture_context *tctx, struct smb2_tree *tree1)
3161 {
3162         const char *fname = BASEDIR "\\test_batch_brl.dat";
3163         bool ret = true;
3164         uint8_t buf[1000];
3165         bool correct = true;
3166         union smb_open io;
3167         NTSTATUS status;
3168         struct smb2_handle h, h1, h2;
3169         struct smb2_lock lck;
3170         struct smb2_lock_element lock[1];
3171
3172         status = torture_smb2_testdir(tree1, BASEDIR, &h);
3173         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3174
3175         /* cleanup */
3176         smb2_util_unlink(tree1, fname);
3177         tree1->session->transport->oplock.handler =
3178             torture_oplock_handler_two_notifications;
3179         tree1->session->transport->oplock.private_data = tree1;
3180
3181         /*
3182           base ntcreatex parms
3183         */
3184         ZERO_STRUCT(io.smb2);
3185         io.generic.level = RAW_OPEN_SMB2;
3186         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3187                                     SEC_RIGHTS_FILE_WRITE;
3188         io.smb2.in.alloc_size = 0;
3189         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3190         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3191                                   NTCREATEX_SHARE_ACCESS_WRITE;
3192         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3193         io.smb2.in.create_options = 0;
3194         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3195         io.smb2.in.security_flags = 0;
3196         io.smb2.in.fname = fname;
3197
3198         /*
3199           with a batch oplock we get a break
3200         */
3201         torture_comment(tctx, "open with batch oplock\n");
3202         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3203         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3204
3205         status = smb2_create(tree1, tctx, &(io.smb2));
3206         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3207         h1 = io.smb2.out.file.handle;
3208         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3209
3210         /* create a file with bogus data */
3211         memset(buf, 0, sizeof(buf));
3212         status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
3213
3214         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3215                 torture_comment(tctx, "Failed to create file\n");
3216                 correct = false;
3217                 goto done;
3218         }
3219
3220         torture_comment(tctx, "a 2nd open should give a break\n");
3221         ZERO_STRUCT(break_info);
3222
3223         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3224         io.smb2.in.oplock_level = 0;
3225         status = smb2_create(tree1, tctx, &(io.smb2));
3226         h2 = io.smb2.out.file.handle;
3227         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3228         CHECK_VAL(break_info.count, 1);
3229         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
3230         CHECK_VAL(break_info.failures, 0);
3231         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3232
3233         ZERO_STRUCT(break_info);
3234
3235         torture_comment(tctx, "a self BRL acquisition should break to none\n");
3236
3237         lock[0].offset = 0;
3238         lock[0].length = 4;
3239         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3240                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3241
3242         ZERO_STRUCT(lck);
3243         lck.in.file.handle = h1;
3244         lck.in.locks = &lock[0];
3245         lck.in.lock_count = 1;
3246         status = smb2_lock(tree1, &lck);
3247         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3248
3249         torture_wait_for_oplock_break(tctx);
3250         CHECK_VAL(break_info.count, 1);
3251         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
3252         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3253         CHECK_VAL(break_info.failures, 0);
3254
3255         /* expect no oplock break */
3256         ZERO_STRUCT(break_info);
3257         lock[0].offset = 2;
3258         status = smb2_lock(tree1, &lck);
3259         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3260                                       "Incorrect status");
3261
3262         torture_wait_for_oplock_break(tctx);
3263         CHECK_VAL(break_info.count, 0);
3264         CHECK_VAL(break_info.level, 0);
3265         CHECK_VAL(break_info.failures, 0);
3266
3267         smb2_util_close(tree1, h1);
3268         smb2_util_close(tree1, h2);
3269         smb2_util_close(tree1, h);
3270
3271 done:
3272         smb2_deltree(tree1, BASEDIR);
3273         return ret;
3274
3275 }
3276
3277 /* Starting the SMB2 specific oplock tests at 500 so we can keep the SMB1
3278  * tests in sync with an identically numbered SMB2 test */
3279
3280 /* Test whether the server correctly returns an error when we send
3281  * a response to a levelII to none oplock notification. */
3282 static bool test_smb2_oplock_levelII500(struct torture_context *tctx,
3283                                       struct smb2_tree *tree1)
3284 {
3285         const char *fname = BASEDIR "\\test_levelII500.dat";
3286         NTSTATUS status;
3287         bool ret = true;
3288         union smb_open io;
3289         struct smb2_handle h, h1;
3290         char c = 0;
3291
3292         status = torture_smb2_testdir(tree1, BASEDIR, &h);
3293         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3294
3295         /* cleanup */
3296         smb2_util_unlink(tree1, fname);
3297
3298         tree1->session->transport->oplock.handler = torture_oplock_handler;
3299         tree1->session->transport->oplock.private_data = tree1;
3300
3301         /*
3302           base ntcreatex parms
3303         */
3304         ZERO_STRUCT(io.smb2);
3305         io.generic.level = RAW_OPEN_SMB2;
3306         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3307         io.smb2.in.alloc_size = 0;
3308         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3309         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3310         io.smb2.in.create_options = 0;
3311         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3312         io.smb2.in.security_flags = 0;
3313         io.smb2.in.fname = fname;
3314
3315         torture_comment(tctx, "LEVELII500: acknowledging a break from II to "
3316                         "none should return an error\n");
3317         ZERO_STRUCT(break_info);
3318
3319         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3320                                 SEC_RIGHTS_FILE_WRITE;
3321         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3322                                 NTCREATEX_SHARE_ACCESS_WRITE;
3323         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3324         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
3325         status = smb2_create(tree1, tctx, &(io.smb2));
3326         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3327         h1 = io.smb2.out.file.handle;
3328         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
3329
3330         ZERO_STRUCT(break_info);
3331
3332         torture_comment(tctx, "write should trigger a break to none and when "
3333                         "we reply, an oplock break failure\n");
3334         smb2_util_write(tree1, h1, &c, 0, 1);
3335
3336         /* Wait several times to receive both the break notification, and the
3337          * NT_STATUS_INVALID_OPLOCK_PROTOCOL error in the break response */
3338         torture_wait_for_oplock_break(tctx);
3339         torture_wait_for_oplock_break(tctx);
3340         torture_wait_for_oplock_break(tctx);
3341         torture_wait_for_oplock_break(tctx);
3342
3343         /* There appears to be a race condition in W2K8 and W2K8R2 where
3344          * sometimes the server will happily reply to our break response with
3345          * NT_STATUS_OK, and sometimes it will return the OPLOCK_PROTOCOL
3346          * error.  As the MS-SMB2 doc states that a client should not reply to
3347          * a level2 to none break notification, I'm leaving the protocol error
3348          * as the expected behavior. */
3349         CHECK_VAL(break_info.count, 1);
3350         CHECK_VAL(break_info.level, 0);
3351         CHECK_VAL(break_info.failures, 1);
3352         torture_assert_ntstatus_equal(tctx, break_info.failure_status,
3353                                       NT_STATUS_INVALID_OPLOCK_PROTOCOL,
3354                                       "Incorrect status");
3355
3356         smb2_util_close(tree1, h1);
3357         smb2_util_close(tree1, h);
3358
3359         smb2_deltree(tree1, BASEDIR);
3360         return ret;
3361 }
3362
3363 struct torture_suite *torture_smb2_oplocks_init(void)
3364 {
3365         struct torture_suite *suite =
3366             torture_suite_create(talloc_autofree_context(), "OPLOCK");
3367
3368         torture_suite_add_2smb2_test(suite, "EXCLUSIVE1", test_smb2_oplock_exclusive1);
3369         torture_suite_add_2smb2_test(suite, "EXCLUSIVE2", test_smb2_oplock_exclusive2);
3370         torture_suite_add_2smb2_test(suite, "EXCLUSIVE3", test_smb2_oplock_exclusive3);
3371         torture_suite_add_2smb2_test(suite, "EXCLUSIVE4", test_smb2_oplock_exclusive4);
3372         torture_suite_add_2smb2_test(suite, "EXCLUSIVE5", test_smb2_oplock_exclusive5);
3373         torture_suite_add_2smb2_test(suite, "EXCLUSIVE6", test_smb2_oplock_exclusive6);
3374         torture_suite_add_2smb2_test(suite, "BATCH1", test_smb2_oplock_batch1);
3375         torture_suite_add_2smb2_test(suite, "BATCH2", test_smb2_oplock_batch2);
3376         torture_suite_add_2smb2_test(suite, "BATCH3", test_smb2_oplock_batch3);
3377         torture_suite_add_2smb2_test(suite, "BATCH4", test_smb2_oplock_batch4);
3378         torture_suite_add_2smb2_test(suite, "BATCH5", test_smb2_oplock_batch5);
3379         torture_suite_add_2smb2_test(suite, "BATCH6", test_smb2_oplock_batch6);
3380         torture_suite_add_2smb2_test(suite, "BATCH7", test_smb2_oplock_batch7);
3381         torture_suite_add_2smb2_test(suite, "BATCH8", test_smb2_oplock_batch8);
3382         torture_suite_add_2smb2_test(suite, "BATCH9", test_smb2_oplock_batch9);
3383         torture_suite_add_2smb2_test(suite, "BATCH10", test_smb2_oplock_batch10);
3384         torture_suite_add_2smb2_test(suite, "BATCH11", test_smb2_oplock_batch11);
3385         torture_suite_add_2smb2_test(suite, "BATCH12", test_smb2_oplock_batch12);
3386         torture_suite_add_2smb2_test(suite, "BATCH13", test_smb2_oplock_batch13);
3387         torture_suite_add_2smb2_test(suite, "BATCH14", test_smb2_oplock_batch14);
3388         torture_suite_add_2smb2_test(suite, "BATCH15", test_smb2_oplock_batch15);
3389         torture_suite_add_2smb2_test(suite, "BATCH16", test_smb2_oplock_batch16);
3390         torture_suite_add_1smb2_test(suite, "BATCH19", test_smb2_oplock_batch19);
3391         torture_suite_add_2smb2_test(suite, "BATCH20", test_smb2_oplock_batch20);
3392         torture_suite_add_1smb2_test(suite, "BATCH21", test_smb2_oplock_batch21);
3393         torture_suite_add_1smb2_test(suite, "BATCH22", test_smb2_oplock_batch22);
3394         torture_suite_add_2smb2_test(suite, "BATCH23", test_smb2_oplock_batch23);
3395         torture_suite_add_2smb2_test(suite, "BATCH24", test_smb2_oplock_batch24);
3396         torture_suite_add_1smb2_test(suite, "BATCH25", test_smb2_oplock_batch25);
3397         torture_suite_add_2smb2_test(suite, "STREAM1", test_raw_oplock_stream1);
3398         torture_suite_add_1smb2_test(suite, "DOC", test_smb2_oplock_doc);
3399         torture_suite_add_2smb2_test(suite, "BRL1", test_smb2_oplock_brl1);
3400         torture_suite_add_1smb2_test(suite, "BRL2", test_smb2_oplock_brl2);
3401         torture_suite_add_1smb2_test(suite, "BRL3", test_smb2_oplock_brl3);
3402         torture_suite_add_1smb2_test(suite, "LEVELII500", test_smb2_oplock_levelII500);
3403
3404         suite->description = talloc_strdup(suite, "SMB2-OPLOCK tests");
3405
3406         return suite;
3407 }
3408
3409 /*
3410    stress testing of oplocks
3411 */
3412 bool test_smb2_bench_oplock(struct torture_context *tctx,
3413                                    struct smb2_tree *tree)
3414 {
3415         struct smb2_tree **trees;
3416         bool ret = true;
3417         NTSTATUS status;
3418         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3419         int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
3420         int i, count=0;
3421         int timelimit = torture_setting_int(tctx, "timelimit", 10);
3422         union smb_open io;
3423         struct timeval tv;
3424         struct smb2_handle h;
3425
3426         trees = talloc_array(mem_ctx, struct smb2_tree *, torture_nprocs);
3427
3428         torture_comment(tctx, "Opening %d connections\n", torture_nprocs);
3429         for (i=0;i<torture_nprocs;i++) {
3430                 if (!torture_smb2_connection(tctx, &trees[i])) {
3431                         return false;
3432                 }
3433                 talloc_steal(mem_ctx, trees[i]);
3434                 trees[i]->session->transport->oplock.handler =
3435                                         torture_oplock_handler_close;
3436                 trees[i]->session->transport->oplock.private_data = trees[i];
3437         }
3438
3439         status = torture_smb2_testdir(trees[0], BASEDIR, &h);
3440         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3441
3442         ZERO_STRUCT(io.smb2);
3443         io.smb2.level = RAW_OPEN_SMB2;
3444         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3445         io.smb2.in.alloc_size = 0;
3446         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3447         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3448         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3449         io.smb2.in.create_options = 0;
3450         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3451         io.smb2.in.security_flags = 0;
3452         io.smb2.in.fname = BASEDIR "\\test.dat";
3453         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3454         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3455
3456         tv = timeval_current();
3457
3458         /*
3459           we open the same file with SHARE_ACCESS_NONE from all the
3460           connections in a round robin fashion. Each open causes an
3461           oplock break on the previous connection, which is answered
3462           by the oplock_handler_close() to close the file.
3463
3464           This measures how fast we can pass on oplocks, and stresses
3465           the oplock handling code
3466         */
3467         torture_comment(tctx, "Running for %d seconds\n", timelimit);
3468         while (timeval_elapsed(&tv) < timelimit) {
3469                 for (i=0;i<torture_nprocs;i++) {
3470                         NTSTATUS status;
3471
3472                         status = smb2_create(trees[i], mem_ctx, &(io.smb2));
3473                         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3474                         count++;
3475                 }
3476
3477                 if (torture_setting_bool(tctx, "progress", true)) {
3478                         torture_comment(tctx, "%.2f ops/second\r",
3479                                         count/timeval_elapsed(&tv));
3480                 }
3481         }
3482
3483         torture_comment(tctx, "%.2f ops/second\n", count/timeval_elapsed(&tv));
3484         smb2_util_close(trees[0], io.smb2.out.file.handle);
3485         smb2_util_unlink(trees[0], BASEDIR "\\test.dat");
3486         smb2_deltree(trees[0], BASEDIR);
3487         talloc_free(mem_ctx);
3488         return ret;
3489 }
3490
3491 static struct hold_oplock_info {
3492         const char *fname;
3493         bool close_on_break;
3494         uint32_t share_access;
3495         struct smb2_handle handle;
3496 } hold_info[] = {
3497         { BASEDIR "\\notshared_close", true,
3498           NTCREATEX_SHARE_ACCESS_NONE, },
3499         { BASEDIR "\\notshared_noclose", false,
3500           NTCREATEX_SHARE_ACCESS_NONE, },
3501         { BASEDIR "\\shared_close", true,
3502           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
3503         { BASEDIR "\\shared_noclose", false,
3504           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
3505 };
3506
3507 static bool torture_oplock_handler_hold(struct smb2_transport *transport,
3508                                         const struct smb2_handle *handle,
3509                                         uint8_t level, void *private_data)
3510 {
3511         struct hold_oplock_info *info;
3512         int i;
3513
3514         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
3515                 if (smb2_util_handle_equal(hold_info[i].handle, *handle))
3516                         break;
3517         }
3518
3519         if (i == ARRAY_SIZE(hold_info)) {
3520                 printf("oplock break for unknown handle 0x%llx%llx\n",
3521                        handle->data[0], handle->data[1]);
3522                 return false;
3523         }
3524
3525         info = &hold_info[i];
3526
3527         if (info->close_on_break) {
3528                 printf("oplock break on %s - closing\n", info->fname);
3529                 torture_oplock_handler_close(transport, handle,
3530                                              level, private_data);
3531                 return true;
3532         }
3533
3534         printf("oplock break on %s - acking break\n", info->fname);
3535         printf("Acking to none in oplock handler\n");
3536
3537         torture_oplock_handler_ack_to_none(transport, handle,
3538                                            level, private_data);
3539         return true;
3540 }
3541
3542 /*
3543    used for manual testing of oplocks - especially interaction with
3544    other filesystems (such as NFS and local access)
3545 */
3546 bool test_smb2_hold_oplock(struct torture_context *tctx,
3547                            struct smb2_tree *tree)
3548 {
3549         struct torture_context *mem_ctx = talloc_new(tctx);
3550         struct tevent_context *ev =
3551                 (struct tevent_context *)tree->session->transport->socket->event.ctx;
3552         int i;
3553         struct smb2_handle h;
3554         NTSTATUS status;
3555
3556         torture_comment(tctx, "Setting up open files with oplocks in %s\n",
3557                         BASEDIR);
3558
3559         status = torture_smb2_testdir(tree, BASEDIR, &h);
3560         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3561
3562         tree->session->transport->oplock.handler = torture_oplock_handler_hold;
3563         tree->session->transport->oplock.private_data = tree;
3564
3565         /* setup the files */
3566         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
3567                 union smb_open io;
3568                 NTSTATUS status;
3569                 char c = 1;
3570
3571                 ZERO_STRUCT(io.smb2);
3572                 io.generic.level = RAW_OPEN_SMB2;
3573                 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3574                 io.smb2.in.alloc_size = 0;
3575                 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3576                 io.smb2.in.share_access = hold_info[i].share_access;
3577                 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3578                 io.smb2.in.create_options = 0;
3579                 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3580                 io.smb2.in.security_flags = 0;
3581                 io.smb2.in.fname = hold_info[i].fname;
3582                 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3583                 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3584
3585                 torture_comment(tctx, "opening %s\n", hold_info[i].fname);
3586
3587                 status = smb2_create(tree, mem_ctx, &(io.smb2));
3588                 if (!NT_STATUS_IS_OK(status)) {
3589                         torture_comment(tctx, "Failed to open %s - %s\n",
3590                                hold_info[i].fname, nt_errstr(status));
3591                         return false;
3592                 }
3593
3594                 if (io.smb2.out.oplock_level != SMB2_OPLOCK_LEVEL_BATCH) {
3595                         torture_comment(tctx, "Oplock not granted for %s - "
3596                                         "expected %d but got %d\n",
3597                                         hold_info[i].fname,
3598                                         SMB2_OPLOCK_LEVEL_BATCH,
3599                                         io.smb2.out.oplock_level);
3600                         return false;
3601                 }
3602                 hold_info[i].handle = io.smb2.out.file.handle;
3603
3604                 /* make the file non-zero size */
3605                 status = smb2_util_write(tree, hold_info[i].handle, &c, 0, 1);
3606                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3607                         torture_comment(tctx, "Failed to write to file\n");
3608                         return false;
3609                 }
3610         }
3611
3612         torture_comment(tctx, "Waiting for oplock events\n");
3613         event_loop_wait(ev);
3614         smb2_deltree(tree, BASEDIR);
3615         talloc_free(mem_ctx);
3616         return true;
3617 }