s3: smbd: kernel oplocks. Replace retry_open() with setup_kernel_oplock_poll_open().
[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         break_info.handle = *handle;
172         break_info.level = level;
173         break_info.count++;
174
175         printf("Break from level II to none in oplock handler\n");
176
177         return true;
178 }
179
180 /* A handler function for oplock break notifications.  This should be used when
181  * test expects two break notifications, first to level II, then to none. */
182 static bool torture_oplock_handler_two_notifications(
183                                         struct smb2_transport *transport,
184                                         const struct smb2_handle *handle,
185                                         uint8_t level,
186                                         void *private_data)
187 {
188         struct smb2_tree *tree = private_data;
189         const char *name;
190         struct smb2_request *req;
191         ZERO_STRUCT(break_info.br);
192
193         break_info.handle       = *handle;
194         break_info.level        = level;
195         break_info.count++;
196
197         switch (level) {
198         case SMB2_OPLOCK_LEVEL_II:
199                 name = "level II";
200                 break;
201         case SMB2_OPLOCK_LEVEL_NONE:
202                 name = "none";
203                 break;
204         default:
205                 name = "unknown";
206                 break_info.failures++;
207         }
208         printf("Breaking to %s [0x%02X] in oplock handler\n", name, level);
209
210         if (level == SMB2_OPLOCK_LEVEL_NONE)
211                 return true;
212
213         break_info.br.in.file.handle    = *handle;
214         break_info.br.in.oplock_level   = level;
215         break_info.br.in.reserved       = 0;
216         break_info.br.in.reserved2      = 0;
217
218         req = smb2_break_send(tree, &break_info.br);
219         req->async.fn = torture_oplock_break_callback;
220         req->async.private_data = NULL;
221         return true;
222 }
223 static void torture_oplock_handler_close_recv(struct smb2_request *req)
224 {
225         if (!smb2_request_receive(req)) {
226                 printf("close failed in oplock_handler_close\n");
227                 break_info.failures++;
228         }
229 }
230
231 /*
232   a handler function for oplock break requests - close the file
233 */
234 static bool torture_oplock_handler_close(struct smb2_transport *transport,
235                                          const struct smb2_handle *handle,
236                                          uint8_t level,
237                                          void *private_data)
238 {
239         struct smb2_close io;
240         struct smb2_tree *tree = private_data;
241         struct smb2_request *req;
242
243         break_info.handle = *handle;
244         break_info.level = level;
245         break_info.count++;
246
247         ZERO_STRUCT(io);
248         io.in.file.handle       = *handle;
249         io.in.flags          = RAW_CLOSE_SMB2;
250         req = smb2_close_send(tree, &io);
251         if (req == NULL) {
252                 printf("failed to send close in oplock_handler_close\n");
253                 return false;
254         }
255
256         req->async.fn = torture_oplock_handler_close_recv;
257         req->async.private_data = NULL;
258
259         return true;
260 }
261
262 /*
263   a handler function for oplock break requests. Let it timeout
264 */
265 static bool torture_oplock_handler_timeout(struct smb2_transport *transport,
266                                            const struct smb2_handle *handle,
267                                            uint8_t level,
268                                            void *private_data)
269 {
270         break_info.handle = *handle;
271         break_info.level = level;
272         break_info.count++;
273
274         printf("Let oplock break timeout\n");
275         return true;
276 }
277
278 static bool open_smb2_connection_no_level2_oplocks(struct torture_context *tctx,
279                                                    struct smb2_tree **tree)
280 {
281         NTSTATUS status;
282         const char *host = torture_setting_string(tctx, "host", NULL);
283         const char *share = torture_setting_string(tctx, "share", NULL);
284         struct smbcli_options options;
285
286         lpcfg_smbcli_options(tctx->lp_ctx, &options);
287         options.use_level2_oplocks = false;
288
289         status = smb2_connect(tctx, host,
290                               lpcfg_smb_ports(tctx->lp_ctx), share,
291                               lpcfg_resolve_context(tctx->lp_ctx),
292                               popt_get_cmdline_credentials(),
293                               tree, tctx->ev, &options,
294                               lpcfg_socket_options(tctx->lp_ctx),
295                               lpcfg_gensec_settings(tctx, tctx->lp_ctx));
296         if (!NT_STATUS_IS_OK(status)) {
297                 torture_comment(tctx, "Failed to connect to SMB2 share "
298                                 "\\\\%s\\%s - %s\n", host, share,
299                                 nt_errstr(status));
300                 return false;
301         }
302         return true;
303 }
304
305 /*
306    Timer handler function notifies the registering function that time is up
307 */
308 static void timeout_cb(struct tevent_context *ev,
309                        struct tevent_timer *te,
310                        struct timeval current_time,
311                        void *private_data)
312 {
313         bool *timesup = (bool *)private_data;
314         *timesup = true;
315         return;
316 }
317
318 /*
319    Wait a short period of time to receive a single oplock break request
320 */
321 static void torture_wait_for_oplock_break(struct torture_context *tctx)
322 {
323         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
324         struct tevent_timer *te = NULL;
325         struct timeval ne;
326         bool timesup = false;
327         int old_count = break_info.count;
328
329         /* Wait .1 seconds for an oplock break */
330         ne = tevent_timeval_current_ofs(0, 100000);
331
332         if ((te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, &timesup))
333             == NULL)
334         {
335                 torture_comment(tctx, "Failed to wait for an oplock break. "
336                                       "test results may not be accurate.");
337                 goto done;
338         }
339
340         while (!timesup && break_info.count < old_count + 1) {
341                 if (tevent_loop_once(tctx->ev) != 0) {
342                         torture_comment(tctx, "Failed to wait for an oplock "
343                                               "break. test results may not be "
344                                               "accurate.");
345                         goto done;
346                 }
347         }
348
349 done:
350         /* We don't know if the timed event fired and was freed, we received
351          * our oplock break, or some other event triggered the loop.  Thus,
352          * we create a tmp_ctx to be able to safely free/remove the timed
353          * event in all 3 cases. */
354         talloc_free(tmp_ctx);
355
356         return;
357 }
358
359 static bool test_smb2_oplock_exclusive1(struct torture_context *tctx,
360                                         struct smb2_tree *tree1,
361                                         struct smb2_tree *tree2)
362 {
363         const char *fname = BASEDIR "\\test_exclusive1.dat";
364         NTSTATUS status;
365         bool ret = true;
366         union smb_open io;
367         struct smb2_handle h1;
368         struct smb2_handle h;
369
370         status = torture_smb2_testdir(tree1, BASEDIR, &h);
371         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
372
373         /* cleanup */
374         smb2_util_unlink(tree1, fname);
375
376         tree1->session->transport->oplock.handler = torture_oplock_handler;
377         tree1->session->transport->oplock.private_data = tree1;
378
379         /*
380           base ntcreatex parms
381         */
382         ZERO_STRUCT(io.smb2);
383         io.generic.level = RAW_OPEN_SMB2;
384         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
385         io.smb2.in.alloc_size = 0;
386         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
387         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
388         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
389         io.smb2.in.create_options = 0;
390         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
391         io.smb2.in.security_flags = 0;
392         io.smb2.in.fname = fname;
393
394         torture_comment(tctx, "EXCLUSIVE1: open a file with an exclusive "
395                         "oplock (share mode: none)\n");
396         ZERO_STRUCT(break_info);
397         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
398
399         status = smb2_create(tree1, tctx, &(io.smb2));
400         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
401         h1 = io.smb2.out.file.handle;
402         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
403
404         torture_comment(tctx, "a 2nd open should not cause a break\n");
405         status = smb2_create(tree2, tctx, &(io.smb2));
406         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
407                                       "Incorrect status");
408         torture_wait_for_oplock_break(tctx);
409         CHECK_VAL(break_info.count, 0);
410         CHECK_VAL(break_info.failures, 0);
411
412         torture_comment(tctx, "unlink it - should also be no break\n");
413         status = smb2_util_unlink(tree2, fname);
414         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
415                                       "Incorrect status");
416         torture_wait_for_oplock_break(tctx);
417         CHECK_VAL(break_info.count, 0);
418         CHECK_VAL(break_info.failures, 0);
419
420         smb2_util_close(tree1, h1);
421         smb2_util_close(tree1, h);
422
423         smb2_deltree(tree1, BASEDIR);
424         return ret;
425 }
426
427 static bool test_smb2_oplock_exclusive2(struct torture_context *tctx,
428                                         struct smb2_tree *tree1,
429                                         struct smb2_tree *tree2)
430 {
431         const char *fname = BASEDIR "\\test_exclusive2.dat";
432         NTSTATUS status;
433         bool ret = true;
434         union smb_open io;
435         struct smb2_handle h, h1, h2;
436
437         status = torture_smb2_testdir(tree1, BASEDIR, &h);
438         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
439
440         /* cleanup */
441         smb2_util_unlink(tree1, fname);
442
443         tree1->session->transport->oplock.handler = torture_oplock_handler;
444         tree1->session->transport->oplock.private_data = tree1;
445
446         /*
447           base ntcreatex parms
448         */
449         ZERO_STRUCT(io.smb2);
450         io.generic.level = RAW_OPEN_SMB2;
451         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
452         io.smb2.in.alloc_size = 0;
453         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
454         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
455         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
456         io.smb2.in.create_options = 0;
457         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
458         io.smb2.in.security_flags = 0;
459         io.smb2.in.fname = fname;
460
461         torture_comment(tctx, "EXCLUSIVE2: open a file with an exclusive "
462                         "oplock (share mode: all)\n");
463         ZERO_STRUCT(break_info);
464         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
465         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
466                 NTCREATEX_SHARE_ACCESS_WRITE|
467                 NTCREATEX_SHARE_ACCESS_DELETE;
468         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
469
470         status = smb2_create(tree1, tctx, &(io.smb2));
471         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
472         h1 = io.smb2.out.file.handle;
473         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
474
475         torture_comment(tctx, "a 2nd open should cause a break to level 2\n");
476         status = smb2_create(tree2, tctx, &(io.smb2));
477         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
478         h2 = io.smb2.out.file.handle;
479         torture_wait_for_oplock_break(tctx);
480         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
481         CHECK_VAL(break_info.count, 1);
482         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
483         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
484         CHECK_VAL(break_info.failures, 0);
485         ZERO_STRUCT(break_info);
486
487         /* now we have 2 level II oplocks... */
488         torture_comment(tctx, "try to unlink it - should cause a break\n");
489         status = smb2_util_unlink(tree2, fname);
490         torture_assert_ntstatus_ok(tctx, status, "Error unlinking the file");
491         torture_wait_for_oplock_break(tctx);
492         CHECK_VAL(break_info.count, 0);
493         CHECK_VAL(break_info.failures, 0);
494
495         torture_comment(tctx, "close both handles\n");
496         smb2_util_close(tree1, h1);
497         smb2_util_close(tree1, h2);
498         smb2_util_close(tree1, h);
499
500         smb2_deltree(tree1, BASEDIR);
501         return ret;
502 }
503
504 static bool test_smb2_oplock_exclusive3(struct torture_context *tctx,
505                                         struct smb2_tree *tree1,
506                                         struct smb2_tree *tree2)
507 {
508         const char *fname = BASEDIR "\\test_exclusive3.dat";
509         NTSTATUS status;
510         bool ret = true;
511         union smb_open io;
512         union smb_setfileinfo sfi;
513         struct smb2_handle h, h1;
514
515         status = torture_smb2_testdir(tree1, BASEDIR, &h);
516         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
517
518         /* cleanup */
519         smb2_util_unlink(tree1, fname);
520
521         tree1->session->transport->oplock.handler = torture_oplock_handler;
522         tree1->session->transport->oplock.private_data = tree1;
523
524         /*
525           base ntcreatex parms
526         */
527         ZERO_STRUCT(io.smb2);
528         io.generic.level = RAW_OPEN_SMB2;
529         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
530         io.smb2.in.alloc_size = 0;
531         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
532         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
533         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
534         io.smb2.in.create_options = 0;
535         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
536         io.smb2.in.security_flags = 0;
537         io.smb2.in.fname = fname;
538
539         torture_comment(tctx, "EXCLUSIVE3: open a file with an exclusive "
540                         "oplock (share mode: none)\n");
541
542         ZERO_STRUCT(break_info);
543         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
544         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
545
546         status = smb2_create(tree1, tctx, &(io.smb2));
547         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
548         h1 = io.smb2.out.file.handle;
549         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
550
551         torture_comment(tctx, "setpathinfo EOF should trigger a break to "
552                         "none\n");
553         ZERO_STRUCT(sfi);
554         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
555         sfi.generic.in.file.path = fname;
556         sfi.end_of_file_info.in.size = 100;
557
558         status = smb2_composite_setpathinfo(tree2, &sfi);
559
560         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
561                                       "Incorrect status");
562         torture_wait_for_oplock_break(tctx);
563         CHECK_VAL(break_info.count, 0);
564         CHECK_VAL(break_info.failures, 0);
565         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
566
567         smb2_util_close(tree1, h1);
568         smb2_util_close(tree1, h);
569
570         smb2_deltree(tree1, BASEDIR);
571         return ret;
572 }
573
574 static bool test_smb2_oplock_exclusive4(struct torture_context *tctx,
575                                         struct smb2_tree *tree1,
576                                         struct smb2_tree *tree2)
577 {
578         const char *fname = BASEDIR "\\test_exclusive4.dat";
579         NTSTATUS status;
580         bool ret = true;
581         union smb_open io;
582         struct smb2_handle h, h1, h2;
583
584         status = torture_smb2_testdir(tree1, BASEDIR, &h);
585         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
586
587         /* cleanup */
588         smb2_util_unlink(tree1, fname);
589
590         tree1->session->transport->oplock.handler = torture_oplock_handler;
591         tree1->session->transport->oplock.private_data = tree1;
592
593         /*
594           base ntcreatex parms
595         */
596         ZERO_STRUCT(io.smb2);
597         io.generic.level = RAW_OPEN_SMB2;
598         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
599         io.smb2.in.alloc_size = 0;
600         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
601         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
602         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
603         io.smb2.in.create_options = 0;
604         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
605         io.smb2.in.security_flags = 0;
606         io.smb2.in.fname = fname;
607
608         torture_comment(tctx, "EXCLUSIVE4: open with exclusive oplock\n");
609         ZERO_STRUCT(break_info);
610
611         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
612         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
613         status = smb2_create(tree1, tctx, &(io.smb2));
614         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
615         h1 = io.smb2.out.file.handle;
616         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
617
618         ZERO_STRUCT(break_info);
619         torture_comment(tctx, "second open with attributes only shouldn't "
620                         "cause oplock break\n");
621
622         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
623         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
624                                 SEC_FILE_WRITE_ATTRIBUTE |
625                                 SEC_STD_SYNCHRONIZE;
626         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
627         status = smb2_create(tree2, tctx, &(io.smb2));
628         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
629         h2 = io.smb2.out.file.handle;
630         CHECK_VAL(io.smb2.out.oplock_level, NO_OPLOCK_RETURN);
631         torture_wait_for_oplock_break(tctx);
632         CHECK_VAL(break_info.count, 0);
633         CHECK_VAL(break_info.failures, 0);
634
635         smb2_util_close(tree1, h1);
636         smb2_util_close(tree2, h2);
637         smb2_util_close(tree1, h);
638
639         smb2_deltree(tree1, BASEDIR);
640         return ret;
641 }
642
643 static bool test_smb2_oplock_exclusive5(struct torture_context *tctx,
644                                         struct smb2_tree *tree1,
645                                         struct smb2_tree *tree2)
646 {
647         const char *fname = BASEDIR "\\test_exclusive5.dat";
648         NTSTATUS status;
649         bool ret = true;
650         union smb_open io;
651         struct smb2_handle h, h1, h2;
652
653         status = torture_smb2_testdir(tree1, BASEDIR, &h);
654         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
655
656         /* cleanup */
657         smb2_util_unlink(tree1, fname);
658
659         tree1->session->transport->oplock.handler = torture_oplock_handler;
660         tree1->session->transport->oplock.private_data = tree1;
661
662         tree2->session->transport->oplock.handler = torture_oplock_handler;
663         tree2->session->transport->oplock.private_data = tree2;
664
665         /*
666           base ntcreatex parms
667         */
668         ZERO_STRUCT(io.smb2);
669         io.generic.level = RAW_OPEN_SMB2;
670         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
671         io.smb2.in.alloc_size = 0;
672         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
673         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
674         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
675         io.smb2.in.create_options = 0;
676         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
677         io.smb2.in.security_flags = 0;
678         io.smb2.in.fname = fname;
679
680         torture_comment(tctx, "EXCLUSIVE5: open with exclusive oplock\n");
681         ZERO_STRUCT(break_info);
682
683         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
684         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
685                 NTCREATEX_SHARE_ACCESS_WRITE|
686                 NTCREATEX_SHARE_ACCESS_DELETE;
687         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
688         status = smb2_create(tree1, tctx, &(io.smb2));
689         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
690         h1 = io.smb2.out.file.handle;
691         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
692
693         ZERO_STRUCT(break_info);
694
695         torture_comment(tctx, "second open with attributes only and "
696                         "NTCREATEX_DISP_OVERWRITE_IF dispostion causes "
697                         "oplock break\n");
698
699         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
700         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
701                                 SEC_FILE_WRITE_ATTRIBUTE |
702                                 SEC_STD_SYNCHRONIZE;
703         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
704         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
705         status = smb2_create(tree2, tctx, &(io.smb2));
706         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
707         h2 = io.smb2.out.file.handle;
708         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
709         torture_wait_for_oplock_break(tctx);
710         CHECK_VAL(break_info.count, 1);
711         CHECK_VAL(break_info.failures, 0);
712
713         smb2_util_close(tree1, h1);
714         smb2_util_close(tree2, h2);
715         smb2_util_close(tree1, h);
716
717         smb2_deltree(tree1, BASEDIR);
718         return ret;
719 }
720
721 static bool test_smb2_oplock_exclusive6(struct torture_context *tctx,
722                                         struct smb2_tree *tree1,
723                                         struct smb2_tree *tree2)
724 {
725         const char *fname1 = BASEDIR "\\test_exclusive6_1.dat";
726         const char *fname2 = BASEDIR "\\test_exclusive6_2.dat";
727         NTSTATUS status;
728         bool ret = true;
729         union smb_open io;
730         union smb_setfileinfo sinfo;
731         struct smb2_close closeio;
732         struct smb2_handle h, h1;
733
734         status = torture_smb2_testdir(tree1, BASEDIR, &h);
735         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
736
737         /* cleanup */
738         smb2_util_unlink(tree1, fname1);
739         smb2_util_unlink(tree2, fname2);
740
741         tree1->session->transport->oplock.handler = torture_oplock_handler;
742         tree1->session->transport->oplock.private_data = tree1;
743
744         /*
745           base ntcreatex parms
746         */
747         ZERO_STRUCT(io.smb2);
748         io.generic.level = RAW_OPEN_SMB2;
749         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
750         io.smb2.in.alloc_size = 0;
751         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
752         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
753         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
754         io.smb2.in.create_options = 0;
755         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
756         io.smb2.in.security_flags = 0;
757         io.smb2.in.fname = fname1;
758
759         torture_comment(tctx, "EXCLUSIVE6: open a file with an exclusive "
760                         "oplock (share mode: none)\n");
761         ZERO_STRUCT(break_info);
762         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
763         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
764
765         status = smb2_create(tree1, tctx, &(io.smb2));
766         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
767         h1 = io.smb2.out.file.handle;
768         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
769
770         torture_comment(tctx, "rename with the parent directory handle open "
771                         "for DELETE should not generate a break but get "
772                         "a sharing violation\n");
773         ZERO_STRUCT(sinfo);
774         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
775         sinfo.rename_information.in.file.handle = h1;
776         sinfo.rename_information.in.overwrite = true;
777         sinfo.rename_information.in.new_name = fname2;
778         status = smb2_setinfo_file(tree1, &sinfo);
779
780         torture_comment(tctx, "trying rename while parent handle open for delete.\n");
781         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
782                                       "Incorrect status");
783         torture_wait_for_oplock_break(tctx);
784         CHECK_VAL(break_info.count, 0);
785         CHECK_VAL(break_info.failures, 0);
786
787         /* Close the parent directory handle. */
788         ZERO_STRUCT(closeio);
789         closeio.in.file.handle = h;
790         status = smb2_close(tree1, &closeio);
791         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
792                                       "Incorrect status");
793
794         /* Re-open without DELETE access. */
795         ZERO_STRUCT(io);
796         io.smb2.in.oplock_level = 0;
797         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL & (~SEC_STD_DELETE);
798         io.smb2.in.file_attributes   = FILE_ATTRIBUTE_DIRECTORY;
799         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
800         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
801         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
802         io.smb2.in.fname = BASEDIR;
803
804         status = smb2_create(tree1, tctx, &(io.smb2));
805         torture_assert_ntstatus_ok(tctx, status, "Error opening the base directory");
806
807         torture_comment(tctx, "rename with the parent directory handle open "
808                         "without DELETE should succeed without a break\n");
809         ZERO_STRUCT(sinfo);
810         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
811         sinfo.rename_information.in.file.handle = h1;
812         sinfo.rename_information.in.overwrite = true;
813         sinfo.rename_information.in.new_name = fname2;
814         status = smb2_setinfo_file(tree1, &sinfo);
815
816         torture_comment(tctx, "trying rename while parent handle open without delete\n");
817         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
818                                       "Incorrect status");
819         torture_wait_for_oplock_break(tctx);
820         CHECK_VAL(break_info.count, 0);
821         CHECK_VAL(break_info.failures, 0);
822
823         smb2_util_close(tree1, h1);
824         smb2_util_close(tree1, h);
825
826         smb2_deltree(tree1, BASEDIR);
827         return ret;
828 }
829
830 static bool test_smb2_oplock_exclusive9(struct torture_context *tctx,
831                                         struct smb2_tree *tree1,
832                                         struct smb2_tree *tree2)
833 {
834         const char *fname = BASEDIR "\\test_exclusive9.dat";
835         NTSTATUS status;
836         bool ret = true;
837         union smb_open io;
838         struct smb2_handle h1, h2;
839         int i;
840
841         struct {
842                 uint32_t create_disposition;
843                 uint32_t break_level;
844         } levels[] = {
845                 { NTCREATEX_DISP_SUPERSEDE, SMB2_OPLOCK_LEVEL_NONE },
846                 { NTCREATEX_DISP_OPEN, SMB2_OPLOCK_LEVEL_II },
847                 { NTCREATEX_DISP_OVERWRITE_IF, SMB2_OPLOCK_LEVEL_NONE },
848                 { NTCREATEX_DISP_OPEN_IF, SMB2_OPLOCK_LEVEL_II },
849         };
850
851
852         status = torture_smb2_testdir(tree1, BASEDIR, &h1);
853         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
854         smb2_util_close(tree1, h1);
855
856         /* cleanup */
857         smb2_util_unlink(tree1, fname);
858
859         tree1->session->transport->oplock.handler = torture_oplock_handler;
860         tree1->session->transport->oplock.private_data = tree1;
861
862         /*
863           base ntcreatex parms
864         */
865         ZERO_STRUCT(io.smb2);
866         io.generic.level = RAW_OPEN_SMB2;
867         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
868         io.smb2.in.alloc_size = 0;
869         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
870         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
871                 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
872         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
873         io.smb2.in.create_options = 0;
874         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
875         io.smb2.in.security_flags = 0;
876         io.smb2.in.fname = fname;
877
878         for (i=0; i<ARRAY_SIZE(levels); i++) {
879
880                 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
881                 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
882
883                 status = smb2_create(tree1, tctx, &(io.smb2));
884                 torture_assert_ntstatus_ok(tctx, status,
885                                            "Error opening the file");
886                 h1 = io.smb2.out.file.handle;
887                 CHECK_VAL(io.smb2.out.oplock_level,
888                           SMB2_OPLOCK_LEVEL_EXCLUSIVE);
889
890                 ZERO_STRUCT(break_info);
891
892                 io.smb2.in.create_disposition = levels[i].create_disposition;
893                 status = smb2_create(tree2, tctx, &(io.smb2));
894                 torture_assert_ntstatus_ok(tctx, status,
895                                            "Error opening the file");
896                 h2 = io.smb2.out.file.handle;
897                 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
898
899                 CHECK_VAL(break_info.count, 1);
900                 CHECK_VAL(break_info.level, levels[i].break_level);
901                 CHECK_VAL(break_info.failures, 0);
902
903                 smb2_util_close(tree2, h2);
904                 smb2_util_close(tree1, h1);
905         }
906
907         smb2_deltree(tree1, BASEDIR);
908         return ret;
909 }
910
911 static bool test_smb2_oplock_batch1(struct torture_context *tctx,
912                                     struct smb2_tree *tree1,
913                                     struct smb2_tree *tree2)
914 {
915         const char *fname = BASEDIR "\\test_batch1.dat";
916         NTSTATUS status;
917         bool ret = true;
918         union smb_open io;
919         struct smb2_handle h, h1;
920         char c = 0;
921
922         status = torture_smb2_testdir(tree1, BASEDIR, &h);
923         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
924
925         /* cleanup */
926         smb2_util_unlink(tree1, fname);
927
928         tree1->session->transport->oplock.handler = torture_oplock_handler;
929         tree1->session->transport->oplock.private_data = tree1;
930
931         /*
932           base ntcreatex parms
933         */
934         ZERO_STRUCT(io.smb2);
935         io.generic.level = RAW_OPEN_SMB2;
936         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
937         io.smb2.in.alloc_size = 0;
938         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
939         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
940         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
941         io.smb2.in.create_options = 0;
942         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
943         io.smb2.in.security_flags = 0;
944         io.smb2.in.fname = fname;
945
946         /*
947           with a batch oplock we get a break
948         */
949         torture_comment(tctx, "BATCH1: open with batch oplock\n");
950         ZERO_STRUCT(break_info);
951         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
952         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
953         status = smb2_create(tree1, tctx, &(io.smb2));
954         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
955         h1 = io.smb2.out.file.handle;
956         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
957
958         torture_comment(tctx, "unlink should generate a break\n");
959         status = smb2_util_unlink(tree2, fname);
960         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
961                                       "Incorrect status");
962
963         torture_wait_for_oplock_break(tctx);
964         CHECK_VAL(break_info.count, 1);
965         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
966         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
967         CHECK_VAL(break_info.failures, 0);
968
969         torture_comment(tctx, "2nd unlink should not generate a break\n");
970         ZERO_STRUCT(break_info);
971         status = smb2_util_unlink(tree2, fname);
972         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
973                                       "Incorrect status");
974
975         torture_wait_for_oplock_break(tctx);
976         CHECK_VAL(break_info.count, 0);
977
978         torture_comment(tctx, "writing should generate a self break to none\n");
979         tree1->session->transport->oplock.handler =
980             torture_oplock_handler_level2_to_none;
981         smb2_util_write(tree1, h1, &c, 0, 1);
982
983         torture_wait_for_oplock_break(tctx);
984
985         CHECK_VAL(break_info.count, 1);
986         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
987         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
988         CHECK_VAL(break_info.failures, 0);
989
990         smb2_util_close(tree1, h1);
991         smb2_util_close(tree1, h);
992
993         smb2_deltree(tree1, BASEDIR);
994         return ret;
995 }
996
997 static bool test_smb2_oplock_batch2(struct torture_context *tctx,
998                                     struct smb2_tree *tree1,
999                                     struct smb2_tree *tree2)
1000 {
1001         const char *fname = BASEDIR "\\test_batch2.dat";
1002         NTSTATUS status;
1003         bool ret = true;
1004         union smb_open io;
1005         char c = 0;
1006         struct smb2_handle h, h1;
1007
1008         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1009         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1010
1011         /* cleanup */
1012         smb2_util_unlink(tree1, fname);
1013
1014         tree1->session->transport->oplock.handler = torture_oplock_handler;
1015         tree1->session->transport->oplock.private_data = tree1;
1016
1017         /*
1018           base ntcreatex parms
1019         */
1020         ZERO_STRUCT(io.smb2);
1021         io.generic.level = RAW_OPEN_SMB2;
1022         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1023         io.smb2.in.alloc_size = 0;
1024         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1025         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1026         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1027         io.smb2.in.create_options = 0;
1028         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1029         io.smb2.in.security_flags = 0;
1030         io.smb2.in.fname = fname;
1031
1032         torture_comment(tctx, "BATCH2: open with batch oplock\n");
1033         ZERO_STRUCT(break_info);
1034         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1035         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1036         status = smb2_create(tree1, tctx, &(io.smb2));
1037         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1038         h1 = io.smb2.out.file.handle;
1039         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1040
1041         torture_comment(tctx, "unlink should generate a break, which we ack "
1042                         "as break to none\n");
1043         tree1->session->transport->oplock.handler =
1044                                 torture_oplock_handler_ack_to_none;
1045         tree1->session->transport->oplock.private_data = tree1;
1046         status = smb2_util_unlink(tree2, fname);
1047         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
1048                                      "Incorrect status");
1049
1050         torture_wait_for_oplock_break(tctx);
1051         CHECK_VAL(break_info.count, 1);
1052         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1053         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
1054         CHECK_VAL(break_info.failures, 0);
1055
1056         torture_comment(tctx, "2nd unlink should not generate a break\n");
1057         ZERO_STRUCT(break_info);
1058         status = smb2_util_unlink(tree2, fname);
1059         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
1060                                       "Incorrect status");
1061
1062         torture_wait_for_oplock_break(tctx);
1063         CHECK_VAL(break_info.count, 0);
1064
1065         torture_comment(tctx, "writing should not generate a break\n");
1066         smb2_util_write(tree1, h1, &c, 0, 1);
1067
1068         torture_wait_for_oplock_break(tctx);
1069         CHECK_VAL(break_info.count, 0);
1070
1071         smb2_util_close(tree1, h1);
1072         smb2_util_close(tree1, h);
1073
1074         smb2_deltree(tree1, BASEDIR);
1075         return ret;
1076 }
1077
1078 static bool test_smb2_oplock_batch3(struct torture_context *tctx,
1079                                     struct smb2_tree *tree1,
1080                                     struct smb2_tree *tree2)
1081 {
1082         const char *fname = BASEDIR "\\test_batch3.dat";
1083         NTSTATUS status;
1084         bool ret = true;
1085         union smb_open io;
1086         struct smb2_handle h, h1;
1087
1088         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1089         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1090
1091         /* cleanup */
1092         smb2_util_unlink(tree1, fname);
1093         tree1->session->transport->oplock.handler = torture_oplock_handler;
1094         tree1->session->transport->oplock.private_data = tree1;
1095
1096         /*
1097           base ntcreatex parms
1098         */
1099         ZERO_STRUCT(io.smb2);
1100         io.generic.level = RAW_OPEN_SMB2;
1101         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1102         io.smb2.in.alloc_size = 0;
1103         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1104         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1105         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1106         io.smb2.in.create_options = 0;
1107         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1108         io.smb2.in.security_flags = 0;
1109         io.smb2.in.fname = fname;
1110
1111         torture_comment(tctx, "BATCH3: if we close on break then the unlink "
1112                         "can succeed\n");
1113         ZERO_STRUCT(break_info);
1114         tree1->session->transport->oplock.handler =
1115                                         torture_oplock_handler_close;
1116         tree1->session->transport->oplock.private_data = tree1;
1117
1118         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1119         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1120         status = smb2_create(tree1, tctx, &(io.smb2));
1121         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1122         h1 = io.smb2.out.file.handle;
1123         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1124
1125         ZERO_STRUCT(break_info);
1126         status = smb2_util_unlink(tree2, fname);
1127         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1128
1129         torture_wait_for_oplock_break(tctx);
1130         CHECK_VAL(break_info.count, 1);
1131         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1132         CHECK_VAL(break_info.level, 1);
1133         CHECK_VAL(break_info.failures, 0);
1134
1135         smb2_util_close(tree1, h1);
1136         smb2_util_close(tree1, h);
1137
1138         smb2_deltree(tree1, BASEDIR);
1139         return ret;
1140 }
1141
1142 static bool test_smb2_oplock_batch4(struct torture_context *tctx,
1143                                     struct smb2_tree *tree1,
1144                                     struct smb2_tree *tree2)
1145 {
1146         const char *fname = BASEDIR "\\test_batch4.dat";
1147         NTSTATUS status;
1148         bool ret = true;
1149         union smb_open io;
1150         struct smb2_read r;
1151         struct smb2_handle h, h1;
1152
1153         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1154         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1155
1156         /* cleanup */
1157         smb2_util_unlink(tree1, fname);
1158
1159         tree1->session->transport->oplock.handler = torture_oplock_handler;
1160         tree1->session->transport->oplock.private_data = tree1;
1161
1162         /*
1163           base ntcreatex parms
1164         */
1165         ZERO_STRUCT(io.smb2);
1166         io.generic.level = RAW_OPEN_SMB2;
1167         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1168         io.smb2.in.alloc_size = 0;
1169         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1170         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1171         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1172         io.smb2.in.create_options = 0;
1173         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1174         io.smb2.in.security_flags = 0;
1175         io.smb2.in.fname = fname;
1176
1177         torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
1178         ZERO_STRUCT(break_info);
1179
1180         tree1->session->transport->oplock.handler = torture_oplock_handler;
1181         tree1->session->transport->oplock.private_data = tree1;
1182
1183         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1184         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1185         status = smb2_create(tree1, tctx, &(io.smb2));
1186         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1187         h1 = io.smb2.out.file.handle;
1188         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1189
1190         ZERO_STRUCT(r);
1191         r.in.file.handle = h1;
1192         r.in.offset      = 0;
1193
1194         status = smb2_read(tree1, tree1, &r);
1195         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1196         torture_wait_for_oplock_break(tctx);
1197         CHECK_VAL(break_info.count, 0);
1198         CHECK_VAL(break_info.failures, 0);
1199
1200         smb2_util_close(tree1, h1);
1201         smb2_util_close(tree1, h);
1202
1203         smb2_deltree(tree1, BASEDIR);
1204         return ret;
1205 }
1206
1207 static bool test_smb2_oplock_batch5(struct torture_context *tctx,
1208                                     struct smb2_tree *tree1,
1209                                     struct smb2_tree *tree2)
1210 {
1211         const char *fname = BASEDIR "\\test_batch5.dat";
1212         NTSTATUS status;
1213         bool ret = true;
1214         union smb_open io;
1215         struct smb2_handle h, h1;
1216
1217         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1218         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1219
1220         /* cleanup */
1221         smb2_util_unlink(tree1, fname);
1222
1223         tree1->session->transport->oplock.handler = torture_oplock_handler;
1224         tree1->session->transport->oplock.private_data = tree1;
1225
1226         /*
1227           base ntcreatex parms
1228         */
1229         ZERO_STRUCT(io.smb2);
1230         io.generic.level = RAW_OPEN_SMB2;
1231         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1232         io.smb2.in.alloc_size = 0;
1233         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1234         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1235         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1236         io.smb2.in.create_options = 0;
1237         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1238         io.smb2.in.security_flags = 0;
1239         io.smb2.in.fname = fname;
1240
1241         torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
1242         ZERO_STRUCT(break_info);
1243
1244         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1245         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1246         status = smb2_create(tree1, tctx, &(io.smb2));
1247         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1248         h1 = io.smb2.out.file.handle;
1249         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1250
1251         ZERO_STRUCT(break_info);
1252
1253         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1254         status = smb2_create(tree2, tctx, &(io.smb2));
1255         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
1256                                       "Incorrect status");
1257
1258         torture_wait_for_oplock_break(tctx);
1259         CHECK_VAL(break_info.count, 1);
1260         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1261         CHECK_VAL(break_info.level, 1);
1262         CHECK_VAL(break_info.failures, 0);
1263
1264         smb2_util_close(tree1, h1);
1265         smb2_util_close(tree1, h);
1266
1267         smb2_deltree(tree1, BASEDIR);
1268         return ret;
1269 }
1270
1271 static bool test_smb2_oplock_batch6(struct torture_context *tctx,
1272                                     struct smb2_tree *tree1,
1273                                     struct smb2_tree *tree2)
1274 {
1275         const char *fname = BASEDIR "\\test_batch6.dat";
1276         NTSTATUS status;
1277         bool ret = true;
1278         union smb_open io;
1279         struct smb2_handle h, h1, h2;
1280         char c = 0;
1281
1282         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1283         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1284
1285         /* cleanup */
1286         smb2_util_unlink(tree1, fname);
1287
1288         tree1->session->transport->oplock.handler = torture_oplock_handler;
1289         tree1->session->transport->oplock.private_data = tree1;
1290
1291         /*
1292           base ntcreatex parms
1293         */
1294         ZERO_STRUCT(io.smb2);
1295         io.generic.level = RAW_OPEN_SMB2;
1296         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1297         io.smb2.in.alloc_size = 0;
1298         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1299         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1300         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1301         io.smb2.in.create_options = 0;
1302         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1303         io.smb2.in.security_flags = 0;
1304         io.smb2.in.fname = fname;
1305
1306         torture_comment(tctx, "BATCH6: a 2nd open should give a break to "
1307                         "level II if the first open allowed shared read\n");
1308         ZERO_STRUCT(break_info);
1309         tree2->session->transport->oplock.handler = torture_oplock_handler;
1310         tree2->session->transport->oplock.private_data = tree2;
1311
1312         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
1313                                 SEC_RIGHTS_FILE_WRITE;
1314         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1315                                 NTCREATEX_SHARE_ACCESS_WRITE;
1316         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1317         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1318         status = smb2_create(tree1, tctx, &(io.smb2));
1319         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1320         h1 = io.smb2.out.file.handle;
1321         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1322
1323         ZERO_STRUCT(break_info);
1324
1325         status = smb2_create(tree2, tctx, &(io.smb2));
1326         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1327         h2 = io.smb2.out.file.handle;
1328         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1329
1330         torture_wait_for_oplock_break(tctx);
1331         CHECK_VAL(break_info.count, 1);
1332         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1333         CHECK_VAL(break_info.level, 1);
1334         CHECK_VAL(break_info.failures, 0);
1335         ZERO_STRUCT(break_info);
1336
1337         torture_comment(tctx, "write should trigger a break to none on both\n");
1338         tree1->session->transport->oplock.handler =
1339             torture_oplock_handler_level2_to_none;
1340         tree2->session->transport->oplock.handler =
1341             torture_oplock_handler_level2_to_none;
1342         smb2_util_write(tree1, h1, &c, 0, 1);
1343
1344         /* We expect two breaks */
1345         torture_wait_for_oplock_break(tctx);
1346         torture_wait_for_oplock_break(tctx);
1347
1348         CHECK_VAL(break_info.count, 2);
1349         CHECK_VAL(break_info.level, 0);
1350         CHECK_VAL(break_info.failures, 0);
1351
1352         smb2_util_close(tree1, h1);
1353         smb2_util_close(tree2, h2);
1354         smb2_util_close(tree1, h);
1355
1356         smb2_deltree(tree1, BASEDIR);
1357         return ret;
1358 }
1359
1360 static bool test_smb2_oplock_batch7(struct torture_context *tctx,
1361                                     struct smb2_tree *tree1,
1362                                     struct smb2_tree *tree2)
1363 {
1364         const char *fname = BASEDIR "\\test_batch7.dat";
1365         NTSTATUS status;
1366         bool ret = true;
1367         union smb_open io;
1368         struct smb2_handle h, h1, h2;
1369
1370         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1371         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1372
1373         /* cleanup */
1374         smb2_util_unlink(tree1, fname);
1375
1376         tree1->session->transport->oplock.handler = torture_oplock_handler;
1377         tree1->session->transport->oplock.private_data = tree1;
1378
1379         /*
1380           base ntcreatex parms
1381         */
1382         ZERO_STRUCT(io.smb2);
1383         io.generic.level = RAW_OPEN_SMB2;
1384         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1385         io.smb2.in.alloc_size = 0;
1386         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1387         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1388         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1389         io.smb2.in.create_options = 0;
1390         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1391         io.smb2.in.security_flags = 0;
1392         io.smb2.in.fname = fname;
1393
1394         torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when "
1395                         "we close instead of ack\n");
1396         ZERO_STRUCT(break_info);
1397         tree1->session->transport->oplock.handler =
1398                         torture_oplock_handler_close;
1399         tree1->session->transport->oplock.private_data = tree1;
1400
1401         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1402         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1403         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1404         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1405         status = smb2_create(tree1, tctx, &(io.smb2));
1406         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1407         h2 = io.smb2.out.file.handle;
1408         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1409
1410         ZERO_STRUCT(break_info);
1411
1412         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1413         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1414         status = smb2_create(tree2, tctx, &(io.smb2));
1415         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1416         h1 = io.smb2.out.file.handle;
1417         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1418
1419         torture_wait_for_oplock_break(tctx);
1420         CHECK_VAL(break_info.count, 1);
1421         CHECK_VAL(break_info.handle.data[0], h2.data[0]);
1422         CHECK_VAL(break_info.level, 1);
1423         CHECK_VAL(break_info.failures, 0);
1424
1425         smb2_util_close(tree2, h1);
1426         smb2_util_close(tree2, h);
1427
1428         smb2_deltree(tree1, BASEDIR);
1429         return ret;
1430 }
1431
1432 static bool test_smb2_oplock_batch8(struct torture_context *tctx,
1433                                     struct smb2_tree *tree1,
1434                                     struct smb2_tree *tree2)
1435 {
1436         const char *fname = BASEDIR "\\test_batch8.dat";
1437         NTSTATUS status;
1438         bool ret = true;
1439         union smb_open io;
1440         struct smb2_handle h, h1, h2;
1441
1442         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1443         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1444
1445         /* cleanup */
1446         smb2_util_unlink(tree1, fname);
1447
1448         tree1->session->transport->oplock.handler = torture_oplock_handler;
1449         tree1->session->transport->oplock.private_data = tree1;
1450
1451         /*
1452           base ntcreatex parms
1453         */
1454         ZERO_STRUCT(io.smb2);
1455         io.generic.level = RAW_OPEN_SMB2;
1456         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1457         io.smb2.in.alloc_size = 0;
1458         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1459         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1460         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1461         io.smb2.in.create_options = 0;
1462         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1463         io.smb2.in.security_flags = 0;
1464         io.smb2.in.fname = fname;
1465
1466         torture_comment(tctx, "BATCH8: open with batch oplock\n");
1467         ZERO_STRUCT(break_info);
1468
1469         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1470         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1471         status = smb2_create(tree1, tctx, &(io.smb2));
1472         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1473         h1 = io.smb2.out.file.handle;
1474         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1475
1476         ZERO_STRUCT(break_info);
1477         torture_comment(tctx, "second open with attributes only shouldn't "
1478                         "cause oplock break\n");
1479
1480         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1481         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1482                                 SEC_FILE_WRITE_ATTRIBUTE |
1483                                 SEC_STD_SYNCHRONIZE;
1484         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1485         status = smb2_create(tree2, tctx, &(io.smb2));
1486         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1487         h2 = io.smb2.out.file.handle;
1488         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
1489         torture_wait_for_oplock_break(tctx);
1490         CHECK_VAL(break_info.count, 0);
1491         CHECK_VAL(break_info.failures, 0);
1492
1493         smb2_util_close(tree1, h1);
1494         smb2_util_close(tree2, h2);
1495         smb2_util_close(tree1, h);
1496
1497         smb2_deltree(tree1, BASEDIR);
1498         return ret;
1499 }
1500
1501 static bool test_smb2_oplock_batch9(struct torture_context *tctx,
1502                                      struct smb2_tree *tree1,
1503                                      struct smb2_tree *tree2)
1504 {
1505         const char *fname = BASEDIR "\\test_batch9.dat";
1506         NTSTATUS status;
1507         bool ret = true;
1508         union smb_open io;
1509         struct smb2_handle h, h1, h2;
1510         char c = 0;
1511
1512         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1513         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1514
1515         /* cleanup */
1516         smb2_util_unlink(tree1, fname);
1517
1518         tree1->session->transport->oplock.handler = torture_oplock_handler;
1519         tree1->session->transport->oplock.private_data = tree1;
1520
1521         /*
1522           base ntcreatex parms
1523         */
1524         ZERO_STRUCT(io.smb2);
1525         io.generic.level = RAW_OPEN_SMB2;
1526         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1527         io.smb2.in.alloc_size = 0;
1528         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1529         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1530         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1531         io.smb2.in.create_options = 0;
1532         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1533         io.smb2.in.security_flags = 0;
1534         io.smb2.in.fname = fname;
1535
1536         torture_comment(tctx, "BATCH9: open with attributes only can create "
1537                         "file\n");
1538
1539         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1540         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1541         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1542                                 SEC_FILE_WRITE_ATTRIBUTE |
1543                                 SEC_STD_SYNCHRONIZE;
1544         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
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         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1549
1550         torture_comment(tctx, "Subsequent normal open should break oplock on "
1551                         "attribute only open to level II\n");
1552
1553         ZERO_STRUCT(break_info);
1554
1555         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1556         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1557         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1558         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1559         status = smb2_create(tree2, tctx, &(io.smb2));
1560         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1561         h2 = io.smb2.out.file.handle;
1562         torture_wait_for_oplock_break(tctx);
1563         CHECK_VAL(break_info.count, 1);
1564         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1565         CHECK_VAL(break_info.failures, 0);
1566         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
1567         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1568         smb2_util_close(tree2, h2);
1569
1570         torture_comment(tctx, "third oplocked open should grant level2 without "
1571                         "break\n");
1572         ZERO_STRUCT(break_info);
1573
1574         tree2->session->transport->oplock.handler = torture_oplock_handler;
1575         tree2->session->transport->oplock.private_data = tree2;
1576
1577         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1578         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1579         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1580         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1581         status = smb2_create(tree2, tctx, &(io.smb2));
1582         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1583         h2 = io.smb2.out.file.handle;
1584         torture_wait_for_oplock_break(tctx);
1585         CHECK_VAL(break_info.count, 0);
1586         CHECK_VAL(break_info.failures, 0);
1587         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1588
1589         ZERO_STRUCT(break_info);
1590
1591         torture_comment(tctx, "write should trigger a break to none on both\n");
1592         tree1->session->transport->oplock.handler =
1593             torture_oplock_handler_level2_to_none;
1594         tree2->session->transport->oplock.handler =
1595             torture_oplock_handler_level2_to_none;
1596         smb2_util_write(tree2, h2, &c, 0, 1);
1597
1598         /* We expect two breaks */
1599         torture_wait_for_oplock_break(tctx);
1600         torture_wait_for_oplock_break(tctx);
1601
1602         CHECK_VAL(break_info.count, 2);
1603         CHECK_VAL(break_info.level, 0);
1604         CHECK_VAL(break_info.failures, 0);
1605
1606         smb2_util_close(tree1, h1);
1607         smb2_util_close(tree2, h2);
1608         smb2_util_close(tree1, h);
1609
1610         smb2_deltree(tree1, BASEDIR);
1611         return ret;
1612 }
1613
1614 static bool test_smb2_oplock_batch9a(struct torture_context *tctx,
1615                                      struct smb2_tree *tree1,
1616                                      struct smb2_tree *tree2)
1617 {
1618         const char *fname = BASEDIR "\\test_batch9a.dat";
1619         NTSTATUS status;
1620         bool ret = true;
1621         union smb_open io;
1622         struct smb2_handle h, h1, h2, h3;
1623         char c = 0;
1624
1625         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1626         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1627
1628         /* cleanup */
1629         smb2_util_unlink(tree1, fname);
1630
1631         tree1->session->transport->oplock.handler = torture_oplock_handler;
1632         tree1->session->transport->oplock.private_data = tree1;
1633
1634         /*
1635           base ntcreatex parms
1636         */
1637         ZERO_STRUCT(io.smb2);
1638         io.generic.level = RAW_OPEN_SMB2;
1639         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1640         io.smb2.in.alloc_size = 0;
1641         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1642         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1643         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1644         io.smb2.in.create_options = 0;
1645         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1646         io.smb2.in.security_flags = 0;
1647         io.smb2.in.fname = fname;
1648
1649         torture_comment(tctx, "BATCH9: open with attributes only can create "
1650                         "file\n");
1651
1652         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1653         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1654         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1655                                 SEC_FILE_WRITE_ATTRIBUTE |
1656                                 SEC_STD_SYNCHRONIZE;
1657         status = smb2_create(tree1, tctx, &(io.smb2));
1658         torture_assert_ntstatus_ok(tctx, status, "Error creating the file");
1659         h1 = io.smb2.out.file.handle;
1660         CHECK_VAL(io.smb2.out.create_action, FILE_WAS_CREATED);
1661         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1662
1663         torture_comment(tctx, "Subsequent attributes open should not break\n");
1664
1665         ZERO_STRUCT(break_info);
1666
1667         status = smb2_create(tree2, tctx, &(io.smb2));
1668         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1669         h3 = io.smb2.out.file.handle;
1670         torture_wait_for_oplock_break(tctx);
1671         CHECK_VAL(break_info.count, 0);
1672         CHECK_VAL(io.smb2.out.create_action, FILE_WAS_OPENED);
1673         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
1674         smb2_util_close(tree2, h3);
1675
1676         torture_comment(tctx, "Subsequent normal open should break oplock on "
1677                         "attribute only open to level II\n");
1678
1679         ZERO_STRUCT(break_info);
1680
1681         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1682         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1683         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1684         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1685         status = smb2_create(tree2, tctx, &(io.smb2));
1686         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1687         h2 = io.smb2.out.file.handle;
1688         torture_wait_for_oplock_break(tctx);
1689         CHECK_VAL(break_info.count, 1);
1690         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1691         CHECK_VAL(break_info.failures, 0);
1692         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
1693         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1694         smb2_util_close(tree2, h2);
1695
1696         torture_comment(tctx, "third oplocked open should grant level2 without "
1697                         "break\n");
1698         ZERO_STRUCT(break_info);
1699
1700         tree2->session->transport->oplock.handler = torture_oplock_handler;
1701         tree2->session->transport->oplock.private_data = tree2;
1702
1703         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1704         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1705         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1706         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1707         status = smb2_create(tree2, tctx, &(io.smb2));
1708         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1709         h2 = io.smb2.out.file.handle;
1710         torture_wait_for_oplock_break(tctx);
1711         CHECK_VAL(break_info.count, 0);
1712         CHECK_VAL(break_info.failures, 0);
1713         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1714
1715         ZERO_STRUCT(break_info);
1716
1717         torture_comment(tctx, "write should trigger a break to none on both\n");
1718         tree1->session->transport->oplock.handler =
1719             torture_oplock_handler_level2_to_none;
1720         tree2->session->transport->oplock.handler =
1721             torture_oplock_handler_level2_to_none;
1722         smb2_util_write(tree2, h2, &c, 0, 1);
1723
1724         /* We expect two breaks */
1725         torture_wait_for_oplock_break(tctx);
1726         torture_wait_for_oplock_break(tctx);
1727
1728         CHECK_VAL(break_info.count, 2);
1729         CHECK_VAL(break_info.level, 0);
1730         CHECK_VAL(break_info.failures, 0);
1731
1732         smb2_util_close(tree1, h1);
1733         smb2_util_close(tree2, h2);
1734         smb2_util_close(tree1, h);
1735
1736         smb2_deltree(tree1, BASEDIR);
1737         return ret;
1738 }
1739
1740
1741 static bool test_smb2_oplock_batch10(struct torture_context *tctx,
1742                                      struct smb2_tree *tree1,
1743                                      struct smb2_tree *tree2)
1744 {
1745         const char *fname = BASEDIR "\\test_batch10.dat";
1746         NTSTATUS status;
1747         bool ret = true;
1748         union smb_open io;
1749         struct smb2_handle h, h1, h2;
1750
1751         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1752         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1753
1754         /* cleanup */
1755         smb2_util_unlink(tree1, fname);
1756
1757         tree1->session->transport->oplock.handler = torture_oplock_handler;
1758         tree1->session->transport->oplock.private_data = tree1;
1759
1760         /*
1761           base ntcreatex parms
1762         */
1763         ZERO_STRUCT(io.smb2);
1764         io.generic.level = RAW_OPEN_SMB2;
1765         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1766         io.smb2.in.alloc_size = 0;
1767         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1768         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1769         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1770         io.smb2.in.create_options = 0;
1771         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1772         io.smb2.in.security_flags = 0;
1773         io.smb2.in.fname = fname;
1774
1775         torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock "
1776                         "open should grant level2\n");
1777         ZERO_STRUCT(break_info);
1778         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1779         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1780         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1781                 NTCREATEX_SHARE_ACCESS_WRITE|
1782                 NTCREATEX_SHARE_ACCESS_DELETE;
1783         status = smb2_create(tree1, tctx, &(io.smb2));
1784         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1785         h1 = io.smb2.out.file.handle;
1786         torture_wait_for_oplock_break(tctx);
1787         CHECK_VAL(break_info.count, 0);
1788         CHECK_VAL(break_info.failures, 0);
1789         CHECK_VAL(io.smb2.out.oplock_level, 0);
1790
1791         tree2->session->transport->oplock.handler =
1792             torture_oplock_handler_level2_to_none;
1793         tree2->session->transport->oplock.private_data = tree2;
1794
1795         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1796         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1797         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1798         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1799                 NTCREATEX_SHARE_ACCESS_WRITE|
1800                 NTCREATEX_SHARE_ACCESS_DELETE;
1801         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1802         status = smb2_create(tree2, tctx, &(io.smb2));
1803         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1804         h2 = io.smb2.out.file.handle;
1805         torture_wait_for_oplock_break(tctx);
1806         CHECK_VAL(break_info.count, 0);
1807         CHECK_VAL(break_info.failures, 0);
1808         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1809
1810         torture_comment(tctx, "write should trigger a break to none\n");
1811         {
1812                 struct smb2_write wr;
1813                 DATA_BLOB data;
1814                 data = data_blob_talloc_zero(tree1, UINT16_MAX);
1815                 data.data[0] = (const uint8_t)'x';
1816                 ZERO_STRUCT(wr);
1817                 wr.in.file.handle = h1;
1818                 wr.in.offset      = 0;
1819                 wr.in.data        = data;
1820                 status = smb2_write(tree1, &wr);
1821                 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1822         }
1823
1824         torture_wait_for_oplock_break(tctx);
1825
1826         CHECK_VAL(break_info.count, 1);
1827         CHECK_VAL(break_info.handle.data[0], h2.data[0]);
1828         CHECK_VAL(break_info.level, 0);
1829         CHECK_VAL(break_info.failures, 0);
1830
1831         smb2_util_close(tree1, h1);
1832         smb2_util_close(tree2, h2);
1833         smb2_util_close(tree1, h);
1834
1835         smb2_deltree(tree1, BASEDIR);
1836         return ret;
1837 }
1838
1839 static bool test_smb2_oplock_batch11(struct torture_context *tctx,
1840                                      struct smb2_tree *tree1,
1841                                      struct smb2_tree *tree2)
1842 {
1843         const char *fname = BASEDIR "\\test_batch11.dat";
1844         NTSTATUS status;
1845         bool ret = true;
1846         union smb_open io;
1847         union smb_setfileinfo sfi;
1848         struct smb2_handle h, h1;
1849
1850         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1851         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1852
1853         /* cleanup */
1854         smb2_util_unlink(tree1, fname);
1855
1856         tree1->session->transport->oplock.handler =
1857             torture_oplock_handler_two_notifications;
1858         tree1->session->transport->oplock.private_data = tree1;
1859
1860         /*
1861           base ntcreatex parms
1862         */
1863         ZERO_STRUCT(io.smb2);
1864         io.generic.level = RAW_OPEN_SMB2;
1865         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1866         io.smb2.in.alloc_size = 0;
1867         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1868         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1869         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1870         io.smb2.in.create_options = 0;
1871         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1872         io.smb2.in.security_flags = 0;
1873         io.smb2.in.fname = fname;
1874
1875         /* Test if a set-eof on pathname breaks an exclusive oplock. */
1876         torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks "
1877                         "oplocks.\n");
1878
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.desired_access = SEC_RIGHTS_FILE_ALL;
1884         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1885                                 NTCREATEX_SHARE_ACCESS_WRITE|
1886                                 NTCREATEX_SHARE_ACCESS_DELETE;
1887         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1888         status = smb2_create(tree1, tctx, &(io.smb2));
1889         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1890         h1 = io.smb2.out.file.handle;
1891         torture_wait_for_oplock_break(tctx);
1892         CHECK_VAL(break_info.count, 0);
1893         CHECK_VAL(break_info.failures, 0);
1894         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1895
1896         ZERO_STRUCT(sfi);
1897         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1898         sfi.generic.in.file.path = fname;
1899         sfi.end_of_file_info.in.size = 100;
1900
1901         status = smb2_composite_setpathinfo(tree2, &sfi);
1902         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1903
1904         /* We expect two breaks */
1905         torture_wait_for_oplock_break(tctx);
1906         torture_wait_for_oplock_break(tctx);
1907
1908         CHECK_VAL(break_info.count, 2);
1909         CHECK_VAL(break_info.failures, 0);
1910         CHECK_VAL(break_info.level, 0);
1911
1912         smb2_util_close(tree1, h1);
1913         smb2_util_close(tree1, h);
1914
1915         smb2_deltree(tree1, BASEDIR);
1916         return ret;
1917 }
1918
1919 static bool test_smb2_oplock_batch12(struct torture_context *tctx,
1920                                      struct smb2_tree *tree1,
1921                                      struct smb2_tree *tree2)
1922 {
1923         const char *fname = BASEDIR "\\test_batch12.dat";
1924         NTSTATUS status;
1925         bool ret = true;
1926         union smb_open io;
1927         union smb_setfileinfo sfi;
1928         struct smb2_handle h, h1;
1929
1930         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1931         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1932
1933         /* cleanup */
1934         smb2_util_unlink(tree1, fname);
1935
1936         tree1->session->transport->oplock.handler =
1937             torture_oplock_handler_two_notifications;
1938         tree1->session->transport->oplock.private_data = tree1;
1939
1940         /*
1941           base ntcreatex parms
1942         */
1943         ZERO_STRUCT(io.smb2);
1944         io.generic.level = RAW_OPEN_SMB2;
1945         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1946         io.smb2.in.alloc_size = 0;
1947         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1948         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1949         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1950         io.smb2.in.create_options = 0;
1951         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1952         io.smb2.in.security_flags = 0;
1953         io.smb2.in.fname = fname;
1954
1955         /* Test if a set-allocation size on pathname breaks an exclusive
1956          * oplock. */
1957         torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size "
1958                         "breaks oplocks.\n");
1959
1960         ZERO_STRUCT(break_info);
1961
1962         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1963         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1964         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1965         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1966                                 NTCREATEX_SHARE_ACCESS_WRITE|
1967                                 NTCREATEX_SHARE_ACCESS_DELETE;
1968         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1969         status = smb2_create(tree1, tctx, &(io.smb2));
1970         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1971         h1 = io.smb2.out.file.handle;
1972         torture_wait_for_oplock_break(tctx);
1973         CHECK_VAL(break_info.count, 0);
1974         CHECK_VAL(break_info.failures, 0);
1975         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1976
1977         ZERO_STRUCT(sfi);
1978         sfi.generic.level = RAW_SFILEINFO_ALLOCATION_INFORMATION;
1979         sfi.generic.in.file.path = fname;
1980         sfi.allocation_info.in.alloc_size = 65536 * 8;
1981
1982         status = smb2_composite_setpathinfo(tree2, &sfi);
1983         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1984
1985         /* We expect two breaks */
1986         torture_wait_for_oplock_break(tctx);
1987         torture_wait_for_oplock_break(tctx);
1988
1989         CHECK_VAL(break_info.count, 2);
1990         CHECK_VAL(break_info.failures, 0);
1991         CHECK_VAL(break_info.level, 0);
1992
1993         smb2_util_close(tree1, h1);
1994         smb2_util_close(tree1, h);
1995
1996         smb2_deltree(tree1, BASEDIR);
1997         return ret;
1998 }
1999
2000 static bool test_smb2_oplock_batch13(struct torture_context *tctx,
2001                                      struct smb2_tree *tree1,
2002                                      struct smb2_tree *tree2)
2003 {
2004         const char *fname = BASEDIR "\\test_batch13.dat";
2005         NTSTATUS status;
2006         bool ret = true;
2007         union smb_open io;
2008         struct smb2_handle h, h1, h2;
2009
2010         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2011         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2012
2013         /* cleanup */
2014         smb2_util_unlink(tree1, fname);
2015
2016         tree1->session->transport->oplock.handler = torture_oplock_handler;
2017         tree1->session->transport->oplock.private_data = tree1;
2018
2019         tree2->session->transport->oplock.handler = torture_oplock_handler;
2020         tree2->session->transport->oplock.private_data = tree2;
2021
2022         /*
2023           base ntcreatex parms
2024         */
2025         ZERO_STRUCT(io.smb2);
2026         io.generic.level = RAW_OPEN_SMB2;
2027         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2028         io.smb2.in.alloc_size = 0;
2029         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2030         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2031         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2032         io.smb2.in.create_options = 0;
2033         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2034         io.smb2.in.security_flags = 0;
2035         io.smb2.in.fname = fname;
2036
2037         torture_comment(tctx, "BATCH13: open with batch oplock\n");
2038         ZERO_STRUCT(break_info);
2039
2040         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2041         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2042         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2043                 NTCREATEX_SHARE_ACCESS_WRITE|
2044                 NTCREATEX_SHARE_ACCESS_DELETE;
2045         status = smb2_create(tree1, tctx, &(io.smb2));
2046         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2047         h1 = io.smb2.out.file.handle;
2048         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2049
2050         ZERO_STRUCT(break_info);
2051
2052         torture_comment(tctx, "second open with attributes only and "
2053                         "NTCREATEX_DISP_OVERWRITE dispostion causes "
2054                         "oplock break\n");
2055
2056         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2057         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2058         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
2059                                 SEC_FILE_WRITE_ATTRIBUTE |
2060                                 SEC_STD_SYNCHRONIZE;
2061         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2062                                 NTCREATEX_SHARE_ACCESS_WRITE|
2063                                 NTCREATEX_SHARE_ACCESS_DELETE;
2064         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2065         status = smb2_create(tree2, tctx, &(io.smb2));
2066         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2067         h2 = io.smb2.out.file.handle;
2068         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2069         torture_wait_for_oplock_break(tctx);
2070         CHECK_VAL(break_info.count, 1);
2071         CHECK_VAL(break_info.failures, 0);
2072
2073         smb2_util_close(tree1, h1);
2074         smb2_util_close(tree2, h2);
2075         smb2_util_close(tree1, h);
2076
2077         smb2_deltree(tree1, BASEDIR);
2078
2079         return ret;
2080 }
2081
2082 static bool test_smb2_oplock_batch14(struct torture_context *tctx,
2083                                      struct smb2_tree *tree1,
2084                                      struct smb2_tree *tree2)
2085 {
2086         const char *fname = BASEDIR "\\test_batch14.dat";
2087         NTSTATUS status;
2088         bool ret = true;
2089         union smb_open io;
2090         struct smb2_handle h, h1, h2;
2091
2092         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2093         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2094
2095         /* cleanup */
2096         smb2_util_unlink(tree1, fname);
2097
2098         tree1->session->transport->oplock.handler = torture_oplock_handler;
2099         tree1->session->transport->oplock.private_data = tree1;
2100
2101         /*
2102           base ntcreatex parms
2103         */
2104         ZERO_STRUCT(io.smb2);
2105         io.generic.level = RAW_OPEN_SMB2;
2106         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2107         io.smb2.in.alloc_size = 0;
2108         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2109         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2110         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2111         io.smb2.in.create_options = 0;
2112         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2113         io.smb2.in.security_flags = 0;
2114         io.smb2.in.fname = fname;
2115
2116         torture_comment(tctx, "BATCH14: open with batch oplock\n");
2117         ZERO_STRUCT(break_info);
2118
2119         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2120         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2121         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2122                 NTCREATEX_SHARE_ACCESS_WRITE|
2123                 NTCREATEX_SHARE_ACCESS_DELETE;
2124         status = smb2_create(tree1, tctx, &(io.smb2));
2125         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2126         h1 = io.smb2.out.file.handle;
2127         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2128
2129         ZERO_STRUCT(break_info);
2130
2131         torture_comment(tctx, "second open with attributes only and "
2132                         "NTCREATEX_DISP_SUPERSEDE dispostion causes "
2133                         "oplock break\n");
2134
2135         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2136         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2137         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
2138                                 SEC_FILE_WRITE_ATTRIBUTE |
2139                                 SEC_STD_SYNCHRONIZE;
2140         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2141                                 NTCREATEX_SHARE_ACCESS_WRITE|
2142                                 NTCREATEX_SHARE_ACCESS_DELETE;
2143         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2144         status = smb2_create(tree2, tctx, &(io.smb2));
2145         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2146         h2 = io.smb2.out.file.handle;
2147         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2148
2149         torture_wait_for_oplock_break(tctx);
2150         CHECK_VAL(break_info.count, 1);
2151         CHECK_VAL(break_info.failures, 0);
2152
2153         smb2_util_close(tree1, h1);
2154         smb2_util_close(tree2, h2);
2155         smb2_util_close(tree1, h);
2156
2157         smb2_deltree(tree1, BASEDIR);
2158         return ret;
2159 }
2160
2161 static bool test_smb2_oplock_batch15(struct torture_context *tctx,
2162                                      struct smb2_tree *tree1,
2163                                      struct smb2_tree *tree2)
2164 {
2165         const char *fname = BASEDIR "\\test_batch15.dat";
2166         NTSTATUS status;
2167         bool ret = true;
2168         union smb_open io;
2169         union smb_fileinfo qfi;
2170         struct smb2_handle h, h1;
2171
2172         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2173         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2174
2175         /* cleanup */
2176         smb2_util_unlink(tree1, fname);
2177
2178         tree1->session->transport->oplock.handler = torture_oplock_handler;
2179         tree1->session->transport->oplock.private_data = tree1;
2180
2181         /*
2182           base ntcreatex parms
2183         */
2184         ZERO_STRUCT(io.smb2);
2185         io.generic.level = RAW_OPEN_SMB2;
2186         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2187         io.smb2.in.alloc_size = 0;
2188         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2189         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2190         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2191         io.smb2.in.create_options = 0;
2192         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2193         io.smb2.in.security_flags = 0;
2194         io.smb2.in.fname = fname;
2195
2196         /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
2197         torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks "
2198                         "a batch oplock (should not).\n");
2199
2200         ZERO_STRUCT(break_info);
2201
2202         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2203         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2204         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2205         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2206                                 NTCREATEX_SHARE_ACCESS_WRITE|
2207                                 NTCREATEX_SHARE_ACCESS_DELETE;
2208         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2209         status = smb2_create(tree1, tctx, &(io.smb2));
2210         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2211         h1 = io.smb2.out.file.handle;
2212
2213         torture_wait_for_oplock_break(tctx);
2214         CHECK_VAL(break_info.count, 0);
2215         CHECK_VAL(break_info.failures, 0);
2216         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2217
2218         ZERO_STRUCT(qfi);
2219         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2220         qfi.generic.in.file.handle = h1;
2221         status = smb2_getinfo_file(tree2, tctx, &qfi);
2222
2223         torture_wait_for_oplock_break(tctx);
2224         CHECK_VAL(break_info.count, 0);
2225
2226         smb2_util_close(tree1, h1);
2227         smb2_util_close(tree1, h);
2228
2229         smb2_deltree(tree1, BASEDIR);
2230         return ret;
2231 }
2232
2233 static bool test_smb2_oplock_batch16(struct torture_context *tctx,
2234                                      struct smb2_tree *tree1,
2235                                      struct smb2_tree *tree2)
2236 {
2237         const char *fname = BASEDIR "\\test_batch16.dat";
2238         NTSTATUS status;
2239         bool ret = true;
2240         union smb_open io;
2241         struct smb2_handle h, h1, h2;
2242
2243         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2244         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2245
2246         /* cleanup */
2247         smb2_util_unlink(tree1, fname);
2248
2249         tree1->session->transport->oplock.handler = torture_oplock_handler;
2250         tree1->session->transport->oplock.private_data = tree1;
2251
2252         tree2->session->transport->oplock.handler = torture_oplock_handler;
2253         tree2->session->transport->oplock.private_data = tree2;
2254
2255         /*
2256           base ntcreatex parms
2257         */
2258         ZERO_STRUCT(io.smb2);
2259         io.generic.level = RAW_OPEN_SMB2;
2260         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2261         io.smb2.in.alloc_size = 0;
2262         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2263         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2264         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2265         io.smb2.in.create_options = 0;
2266         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2267         io.smb2.in.security_flags = 0;
2268         io.smb2.in.fname = fname;
2269
2270         torture_comment(tctx, "BATCH16: open with batch oplock\n");
2271         ZERO_STRUCT(break_info);
2272
2273         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2274         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2275         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2276                 NTCREATEX_SHARE_ACCESS_WRITE|
2277                 NTCREATEX_SHARE_ACCESS_DELETE;
2278         status = smb2_create(tree1, tctx, &(io.smb2));
2279         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2280         h1 = io.smb2.out.file.handle;
2281         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2282
2283         ZERO_STRUCT(break_info);
2284
2285         torture_comment(tctx, "second open with attributes only and "
2286                         "NTCREATEX_DISP_OVERWRITE_IF dispostion causes "
2287                         "oplock break\n");
2288
2289         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2290         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2291         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
2292                                 SEC_FILE_WRITE_ATTRIBUTE |
2293                                 SEC_STD_SYNCHRONIZE;
2294         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2295                                 NTCREATEX_SHARE_ACCESS_WRITE|
2296                                 NTCREATEX_SHARE_ACCESS_DELETE;
2297         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2298         status = smb2_create(tree2, tctx, &(io.smb2));
2299         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2300         h2 = io.smb2.out.file.handle;
2301         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2302
2303         torture_wait_for_oplock_break(tctx);
2304         CHECK_VAL(break_info.count, 1);
2305         CHECK_VAL(break_info.failures, 0);
2306
2307         smb2_util_close(tree1, h1);
2308         smb2_util_close(tree2, h2);
2309         smb2_util_close(tree1, h);
2310
2311         smb2_deltree(tree1, BASEDIR);
2312         return ret;
2313 }
2314
2315 /* This function is a placeholder for the SMB1 RAW-OPLOCK-BATCH17 test.  Since
2316  * SMB2 doesn't have a RENAME command this test isn't applicable.  However,
2317  * it's much less confusing, when comparing test, to keep the SMB1 and SMB2
2318  * test numbers in sync. */
2319 #if 0
2320 static bool test_raw_oplock_batch17(struct torture_context *tctx,
2321                                     struct smb2_tree *tree1,
2322                                     struct smb2_tree *tree2)
2323 {
2324         return true;
2325 }
2326 #endif
2327
2328 /* This function is a placeholder for the SMB1 RAW-OPLOCK-BATCH18 test.  Since
2329  * SMB2 doesn't have an NTRENAME command this test isn't applicable.  However,
2330  * it's much less confusing, when comparing tests, to keep the SMB1 and SMB2
2331  * test numbers in sync. */
2332 #if 0
2333 static bool test_raw_oplock_batch18(struct torture_context *tctx,
2334                                     struct smb2_tree *tree1,
2335                                     struct smb2_tree *tree2)
2336 {
2337         return true;
2338 }
2339 #endif
2340
2341 static bool test_smb2_oplock_batch19(struct torture_context *tctx,
2342                                      struct smb2_tree *tree1)
2343 {
2344         const char *fname1 = BASEDIR "\\test_batch19_1.dat";
2345         const char *fname2 = BASEDIR "\\test_batch19_2.dat";
2346         NTSTATUS status;
2347         bool ret = true;
2348         union smb_open io;
2349         union smb_fileinfo qfi;
2350         union smb_setfileinfo sfi;
2351         struct smb2_handle h, h1;
2352
2353         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2354         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2355
2356         /* cleanup */
2357         smb2_util_unlink(tree1, fname1);
2358         smb2_util_unlink(tree1, fname2);
2359
2360         tree1->session->transport->oplock.handler = torture_oplock_handler;
2361         tree1->session->transport->oplock.private_data = tree1;
2362
2363         /*
2364           base ntcreatex parms
2365         */
2366         ZERO_STRUCT(io.smb2);
2367         io.generic.level = RAW_OPEN_SMB2;
2368         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2369         io.smb2.in.alloc_size = 0;
2370         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2371         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2372         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2373         io.smb2.in.create_options = 0;
2374         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2375         io.smb2.in.security_flags = 0;
2376         io.smb2.in.fname = fname1;
2377
2378         torture_comment(tctx, "BATCH19: open a file with an batch oplock "
2379                         "(share mode: none)\n");
2380         ZERO_STRUCT(break_info);
2381         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2382         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2383         status = smb2_create(tree1, tctx, &(io.smb2));
2384         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2385         h1 = io.smb2.out.file.handle;
2386         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2387
2388         torture_comment(tctx, "setfileinfo rename info should not trigger "
2389                         "a break but should cause a sharing violation\n");
2390         ZERO_STRUCT(sfi);
2391         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2392         sfi.generic.in.file.path = fname1;
2393         sfi.rename_information.in.file.handle   = h1;
2394         sfi.rename_information.in.overwrite     = 0;
2395         sfi.rename_information.in.root_fid      = 0;
2396         sfi.rename_information.in.new_name      = fname2;
2397
2398         status = smb2_setinfo_file(tree1, &sfi);
2399
2400         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2401                                       "Incorrect status");
2402
2403         torture_wait_for_oplock_break(tctx);
2404         CHECK_VAL(break_info.count, 0);
2405
2406         ZERO_STRUCT(qfi);
2407         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2408         qfi.generic.in.file.handle = h1;
2409
2410         status = smb2_getinfo_file(tree1, tctx, &qfi);
2411         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2412         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2413
2414         smb2_util_close(tree1, h1);
2415         smb2_util_close(tree1, h);
2416
2417         smb2_deltree(tree1, fname1);
2418         smb2_deltree(tree1, fname2);
2419         return ret;
2420 }
2421
2422 static bool test_smb2_oplock_batch20(struct torture_context *tctx,
2423                                      struct smb2_tree *tree1,
2424                                      struct smb2_tree *tree2)
2425 {
2426         const char *fname1 = BASEDIR "\\test_batch20_1.dat";
2427         const char *fname2 = BASEDIR "\\test_batch20_2.dat";
2428         NTSTATUS status;
2429         bool ret = true;
2430         union smb_open io;
2431         union smb_fileinfo qfi;
2432         union smb_setfileinfo sfi;
2433         struct smb2_handle h, h1, h2;
2434
2435         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2436         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2437
2438         /* cleanup */
2439         smb2_util_unlink(tree1, fname1);
2440         smb2_util_unlink(tree1, fname2);
2441
2442         tree1->session->transport->oplock.handler = torture_oplock_handler;
2443         tree1->session->transport->oplock.private_data = tree1;
2444
2445         /*
2446           base ntcreatex parms
2447         */
2448         ZERO_STRUCT(io.smb2);
2449         io.generic.level = RAW_OPEN_SMB2;
2450         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2451         io.smb2.in.alloc_size = 0;
2452         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2453         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2454         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2455         io.smb2.in.create_options = 0;
2456         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2457         io.smb2.in.security_flags = 0;
2458         io.smb2.in.fname = fname1;
2459
2460         torture_comment(tctx, "BATCH20: open a file with an batch oplock "
2461                         "(share mode: all)\n");
2462         ZERO_STRUCT(break_info);
2463         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2464         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2465         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2466                                 NTCREATEX_SHARE_ACCESS_WRITE|
2467                                 NTCREATEX_SHARE_ACCESS_DELETE;
2468         status = smb2_create(tree1, tctx, &(io.smb2));
2469         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2470         h1 = io.smb2.out.file.handle;
2471         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2472
2473         torture_comment(tctx, "setfileinfo rename info should not trigger "
2474                         "a break but should cause a sharing violation\n");
2475         ZERO_STRUCT(sfi);
2476         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2477         sfi.rename_information.in.file.handle   = h1;
2478         sfi.rename_information.in.overwrite     = 0;
2479         sfi.rename_information.in.new_name      = fname2;
2480
2481         status = smb2_setinfo_file(tree1, &sfi);
2482         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2483                                       "Incorrect status");
2484
2485         torture_wait_for_oplock_break(tctx);
2486         CHECK_VAL(break_info.count, 0);
2487
2488         ZERO_STRUCT(qfi);
2489         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2490         qfi.generic.in.file.handle = h1;
2491
2492         status = smb2_getinfo_file(tree1, tctx, &qfi);
2493         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2494         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2495
2496         torture_comment(tctx, "open the file a second time requesting batch "
2497                         "(share mode: all)\n");
2498         ZERO_STRUCT(break_info);
2499         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2500         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2501         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2502                                 NTCREATEX_SHARE_ACCESS_WRITE|
2503                                 NTCREATEX_SHARE_ACCESS_DELETE;
2504         io.smb2.in.fname = fname1;
2505         status = smb2_create(tree2, tctx, &(io.smb2));
2506         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2507         h2 = io.smb2.out.file.handle;
2508         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2509
2510         torture_wait_for_oplock_break(tctx);
2511         CHECK_VAL(break_info.count, 1);
2512         CHECK_VAL(break_info.failures, 0);
2513         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2514
2515         torture_comment(tctx, "setfileinfo rename info should not trigger "
2516                         "a break but should cause a sharing violation\n");
2517         ZERO_STRUCT(break_info);
2518         ZERO_STRUCT(sfi);
2519         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2520         sfi.rename_information.in.file.handle   = h2;
2521         sfi.rename_information.in.overwrite     = 0;
2522         sfi.rename_information.in.new_name      = fname2;
2523
2524         status = smb2_setinfo_file(tree2, &sfi);
2525         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2526                                       "Incorrect status");
2527
2528         torture_wait_for_oplock_break(tctx);
2529         CHECK_VAL(break_info.count, 0);
2530
2531         ZERO_STRUCT(qfi);
2532         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2533         qfi.generic.in.file.handle = h1;
2534
2535         status = smb2_getinfo_file(tree1, tctx, &qfi);
2536         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2537         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2538
2539         ZERO_STRUCT(qfi);
2540         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2541         qfi.generic.in.file.handle = h2;
2542
2543         status = smb2_getinfo_file(tree2, tctx, &qfi);
2544         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2545         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2546
2547         smb2_util_close(tree1, h1);
2548         smb2_util_close(tree2, h2);
2549         smb2_util_close(tree1, h);
2550
2551         smb2_deltree(tree1, fname1);
2552         return ret;
2553 }
2554
2555 static bool test_smb2_oplock_batch21(struct torture_context *tctx,
2556                                      struct smb2_tree *tree1)
2557 {
2558         const char *fname = BASEDIR "\\test_batch21.dat";
2559         NTSTATUS status;
2560         bool ret = true;
2561         union smb_open io;
2562         struct smb2_handle h, h1;
2563         char c = 0;
2564
2565         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2566         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2567
2568         /* cleanup */
2569         smb2_util_unlink(tree1, fname);
2570
2571         tree1->session->transport->oplock.handler = torture_oplock_handler;
2572         tree1->session->transport->oplock.private_data = tree1;
2573
2574         /*
2575           base ntcreatex parms
2576         */
2577         ZERO_STRUCT(io.smb2);
2578         io.generic.level = RAW_OPEN_SMB2;
2579         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2580         io.smb2.in.alloc_size = 0;
2581         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2582         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2583         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2584         io.smb2.in.create_options = 0;
2585         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2586         io.smb2.in.security_flags = 0;
2587         io.smb2.in.fname = fname;
2588
2589         /*
2590           with a batch oplock we get a break
2591         */
2592         torture_comment(tctx, "BATCH21: open with batch oplock\n");
2593         ZERO_STRUCT(break_info);
2594         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2595         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2596         status = smb2_create(tree1, tctx, &(io.smb2));
2597         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2598         h1 = io.smb2.out.file.handle;
2599         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2600
2601         torture_comment(tctx, "writing should not generate a break\n");
2602         status = smb2_util_write(tree1, h1, &c, 0, 1);
2603         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2604
2605         torture_wait_for_oplock_break(tctx);
2606         CHECK_VAL(break_info.count, 0);
2607
2608         smb2_util_close(tree1, h1);
2609         smb2_util_close(tree1, h);
2610
2611         smb2_deltree(tree1, BASEDIR);
2612         return ret;
2613 }
2614
2615 static bool test_smb2_oplock_batch22(struct torture_context *tctx,
2616                                      struct smb2_tree *tree1)
2617 {
2618         const char *fname = BASEDIR "\\test_batch22.dat";
2619         NTSTATUS status;
2620         bool ret = true;
2621         union smb_open io;
2622         struct smb2_handle h, h1, h2;
2623         struct timeval tv;
2624         int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
2625         int te;
2626
2627         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2628         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2629
2630         /* cleanup */
2631         smb2_util_unlink(tree1, fname);
2632
2633         tree1->session->transport->oplock.handler = torture_oplock_handler;
2634         tree1->session->transport->oplock.private_data = tree1;
2635         /*
2636           base ntcreatex parms
2637         */
2638         ZERO_STRUCT(io.smb2);
2639         io.generic.level = RAW_OPEN_SMB2;
2640         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2641         io.smb2.in.alloc_size = 0;
2642         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2643         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2644         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2645         io.smb2.in.create_options = 0;
2646         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2647         io.smb2.in.security_flags = 0;
2648         io.smb2.in.fname = fname;
2649
2650         /*
2651           with a batch oplock we get a break
2652         */
2653         torture_comment(tctx, "BATCH22: open with batch oplock\n");
2654         ZERO_STRUCT(break_info);
2655         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2656         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2657         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2658                 NTCREATEX_SHARE_ACCESS_WRITE|
2659                 NTCREATEX_SHARE_ACCESS_DELETE;
2660         status = smb2_create(tree1, tctx, &(io.smb2));
2661         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2662         h1 = io.smb2.out.file.handle;
2663         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2664
2665         torture_comment(tctx, "a 2nd open should succeed after the oplock "
2666                         "break timeout\n");
2667         tv = timeval_current();
2668         tree1->session->transport->oplock.handler =
2669                                 torture_oplock_handler_timeout;
2670         status = smb2_create(tree1, tctx, &(io.smb2));
2671         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2672         h2 = io.smb2.out.file.handle;
2673         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2674
2675         torture_wait_for_oplock_break(tctx);
2676         te = (int)timeval_elapsed(&tv);
2677         CHECK_RANGE(te, timeout - 1, timeout + 15);
2678         torture_comment(tctx, "waited %d seconds for oplock timeout\n", te);
2679
2680         CHECK_VAL(break_info.count, 1);
2681         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
2682         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2683         CHECK_VAL(break_info.failures, 0);
2684
2685         smb2_util_close(tree1, h1);
2686         smb2_util_close(tree1, h2);
2687         smb2_util_close(tree1, h);
2688
2689         smb2_deltree(tree1, BASEDIR);
2690         return ret;
2691 }
2692
2693 static bool test_smb2_oplock_batch23(struct torture_context *tctx,
2694                                      struct smb2_tree *tree1,
2695                                      struct smb2_tree *tree2)
2696 {
2697         const char *fname = BASEDIR "\\test_batch23.dat";
2698         NTSTATUS status;
2699         bool ret = true;
2700         union smb_open io;
2701         struct smb2_handle h, h1, h2, h3;
2702         struct smb2_tree *tree3 = NULL;
2703
2704         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2705         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2706
2707         /* cleanup */
2708         smb2_util_unlink(tree1, fname);
2709
2710         ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
2711         CHECK_VAL(ret, true);
2712
2713         tree1->session->transport->oplock.handler = torture_oplock_handler;
2714         tree1->session->transport->oplock.private_data = tree1;
2715
2716         tree2->session->transport->oplock.handler = torture_oplock_handler;
2717         tree2->session->transport->oplock.private_data = tree2;
2718
2719         tree3->session->transport->oplock.handler = torture_oplock_handler;
2720         tree3->session->transport->oplock.private_data = tree3;
2721
2722         /*
2723           base ntcreatex parms
2724         */
2725         ZERO_STRUCT(io.smb2);
2726         io.generic.level = RAW_OPEN_SMB2;
2727         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2728         io.smb2.in.alloc_size = 0;
2729         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2730         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2731         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2732         io.smb2.in.create_options = 0;
2733         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2734         io.smb2.in.security_flags = 0;
2735         io.smb2.in.fname = fname;
2736
2737         torture_comment(tctx, "BATCH23: an open and ask for a batch oplock\n");
2738         ZERO_STRUCT(break_info);
2739
2740         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
2741                                 SEC_RIGHTS_FILE_WRITE;
2742         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2743                                 NTCREATEX_SHARE_ACCESS_WRITE;
2744         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2745         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2746         status = smb2_create(tree1, tctx, &(io.smb2));
2747         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2748         h1 = io.smb2.out.file.handle;
2749         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2750
2751         ZERO_STRUCT(break_info);
2752
2753         torture_comment(tctx, "a 2nd open without level2 oplock support "
2754                         "should generate a break to level2\n");
2755         status = smb2_create(tree3, tctx, &(io.smb2));
2756         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2757         h3 = io.smb2.out.file.handle;
2758
2759         torture_wait_for_oplock_break(tctx);
2760         CHECK_VAL(break_info.count, 1);
2761         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
2762         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2763         CHECK_VAL(break_info.failures, 0);
2764
2765         ZERO_STRUCT(break_info);
2766
2767         torture_comment(tctx, "a 3rd open with level2 oplock support should "
2768                         "not generate a break\n");
2769         status = smb2_create(tree2, tctx, &(io.smb2));
2770         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2771         h2 = io.smb2.out.file.handle;
2772         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2773
2774         torture_wait_for_oplock_break(tctx);
2775         CHECK_VAL(break_info.count, 0);
2776
2777         smb2_util_close(tree1, h1);
2778         smb2_util_close(tree2, h2);
2779         smb2_util_close(tree3, h3);
2780         smb2_util_close(tree1, h);
2781
2782         smb2_deltree(tree1, BASEDIR);
2783         return ret;
2784 }
2785
2786 static bool test_smb2_oplock_batch24(struct torture_context *tctx,
2787                                      struct smb2_tree *tree1,
2788                                      struct smb2_tree *tree2)
2789 {
2790         const char *fname = BASEDIR "\\test_batch24.dat";
2791         NTSTATUS status;
2792         bool ret = true;
2793         union smb_open io;
2794         struct smb2_handle h, h1, h2;
2795         struct smb2_tree *tree3 = NULL;
2796
2797         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2798         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2799
2800         /* cleanup */
2801         smb2_util_unlink(tree1, fname);
2802
2803         ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
2804         CHECK_VAL(ret, true);
2805
2806         tree1->session->transport->oplock.handler = torture_oplock_handler;
2807         tree1->session->transport->oplock.private_data = tree1;
2808
2809         tree2->session->transport->oplock.handler = torture_oplock_handler;
2810         tree2->session->transport->oplock.private_data = tree2;
2811
2812         tree3->session->transport->oplock.handler = torture_oplock_handler;
2813         tree3->session->transport->oplock.private_data = tree3;
2814
2815         /*
2816           base ntcreatex parms
2817         */
2818         ZERO_STRUCT(io.smb2);
2819         io.generic.level = RAW_OPEN_SMB2;
2820         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2821         io.smb2.in.alloc_size = 0;
2822         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2823         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2824         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2825         io.smb2.in.create_options = 0;
2826         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2827         io.smb2.in.security_flags = 0;
2828         io.smb2.in.fname = fname;
2829
2830         torture_comment(tctx, "BATCH24: a open without level support and "
2831                         "ask for a batch oplock\n");
2832         ZERO_STRUCT(break_info);
2833
2834         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
2835                                 SEC_RIGHTS_FILE_WRITE;
2836         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2837                                 NTCREATEX_SHARE_ACCESS_WRITE;
2838         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2839         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2840
2841         status = smb2_create(tree3, tctx, &(io.smb2));
2842         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2843         h2 = io.smb2.out.file.handle;
2844         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2845
2846         ZERO_STRUCT(break_info);
2847
2848         torture_comment(tctx, "a 2nd open with level2 oplock support should "
2849                         "generate a break\n");
2850         status = smb2_create(tree2, tctx, &(io.smb2));
2851         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2852         h1 = io.smb2.out.file.handle;
2853         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2854
2855         torture_wait_for_oplock_break(tctx);
2856         CHECK_VAL(break_info.count, 1);
2857         CHECK_VAL(break_info.handle.data[0], h2.data[0]);
2858         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2859         CHECK_VAL(break_info.failures, 0);
2860
2861         smb2_util_close(tree3, h2);
2862         smb2_util_close(tree2, h1);
2863         smb2_util_close(tree1, h);
2864
2865         smb2_deltree(tree1, BASEDIR);
2866         return ret;
2867 }
2868
2869 static bool test_smb2_oplock_batch25(struct torture_context *tctx,
2870                                      struct smb2_tree *tree1)
2871 {
2872         const char *fname = BASEDIR "\\test_batch25.dat";
2873         NTSTATUS status;
2874         bool ret = true;
2875         union smb_open io;
2876         struct smb2_handle h, h1;
2877
2878         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2879         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2880
2881         /* cleanup */
2882         smb2_util_unlink(tree1, fname);
2883
2884         tree1->session->transport->oplock.handler = torture_oplock_handler;
2885         tree1->session->transport->oplock.private_data = tree1;
2886
2887         /*
2888           base ntcreatex parms
2889         */
2890         ZERO_STRUCT(io.smb2);
2891         io.generic.level = RAW_OPEN_SMB2;
2892         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2893         io.smb2.in.alloc_size = 0;
2894         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2895         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2896         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2897         io.smb2.in.create_options = 0;
2898         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2899         io.smb2.in.security_flags = 0;
2900         io.smb2.in.fname = fname;
2901
2902         torture_comment(tctx, "BATCH25: open a file with an batch oplock "
2903                         "(share mode: none)\n");
2904
2905         ZERO_STRUCT(break_info);
2906         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2907         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2908
2909         status = smb2_create(tree1, tctx, &(io.smb2));
2910         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2911         h1 = io.smb2.out.file.handle;
2912         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2913
2914         torture_comment(tctx, "changing the file attribute info should trigger "
2915                         "a break and a violation\n");
2916
2917         status = smb2_util_setatr(tree1, fname, FILE_ATTRIBUTE_HIDDEN);
2918         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2919                                       "Incorrect status");
2920
2921         torture_wait_for_oplock_break(tctx);
2922         CHECK_VAL(break_info.count, 1);
2923
2924         smb2_util_close(tree1, h1);
2925         smb2_util_close(tree1, h);
2926
2927         smb2_deltree(tree1, fname);
2928         return ret;
2929 }
2930
2931 static bool test_smb2_oplock_batch26(struct torture_context *tctx,
2932                                         struct smb2_tree *tree1)
2933 {
2934
2935         NTSTATUS status;
2936         bool ret = true;
2937         union smb_open io;
2938         struct smb2_handle h, h1, h2, h3;
2939         const char *fname_base = BASEDIR "\\test_oplock.txt";
2940         const char *stream = "Stream One:$DATA";
2941         const char *fname_stream;
2942
2943         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2944         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2945
2946         tree1->session->transport->oplock.handler = torture_oplock_handler;
2947         tree1->session->transport->oplock.private_data = tree1;
2948
2949         fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
2950
2951         /*
2952           base ntcreatex parms
2953         */
2954         ZERO_STRUCT(io.smb2);
2955         io.generic.level = RAW_OPEN_SMB2;
2956         io.smb2.in.desired_access = 0x120089;
2957         io.smb2.in.alloc_size = 0;
2958         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2959         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_DELETE |
2960                                   NTCREATEX_SHARE_ACCESS_WRITE;
2961         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2962         io.smb2.in.create_options = 0;
2963         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2964         io.smb2.in.security_flags = 0;
2965         io.smb2.in.fname = fname_base;
2966
2967         /*
2968           Open base file with a batch oplock.
2969         */
2970         torture_comment(tctx, "Open the base file with batch oplock\n");
2971         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2972         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2973
2974         status = smb2_create(tree1, tctx, &(io.smb2));
2975         torture_assert_ntstatus_ok(tctx, status, "Error opening base file");
2976         h1 = io.smb2.out.file.handle;
2977         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2978
2979         torture_comment(tctx, "Got batch oplock on base file\n");
2980
2981         torture_comment(tctx, "Opening stream file with batch oplock..\n");
2982
2983         io.smb2.in.fname = fname_stream;
2984
2985         status = smb2_create(tree1, tctx, &(io.smb2));
2986         torture_assert_ntstatus_ok(tctx, status, "Error opening stream file");
2987         h2 = io.smb2.out.file.handle;
2988         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2989
2990         torture_comment(tctx, "Got batch oplock on stream file\n");
2991
2992         torture_comment(tctx, "Open base file again with batch oplock\n");
2993
2994         io.smb2.in.fname = fname_base;
2995
2996         status = smb2_create(tree1, tctx, &(io.smb2));
2997         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2998         h3 = io.smb2.out.file.handle;
2999         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
3000
3001         smb2_util_close(tree1, h1);
3002         smb2_util_close(tree1, h2);
3003         smb2_util_close(tree1, h3);
3004         smb2_util_close(tree1, h);
3005         smb2_deltree(tree1, BASEDIR);
3006         return ret;
3007
3008 }
3009
3010 /* Test how oplocks work on streams. */
3011 static bool test_raw_oplock_stream1(struct torture_context *tctx,
3012                                     struct smb2_tree *tree1,
3013                                     struct smb2_tree *tree2)
3014 {
3015         NTSTATUS status;
3016         union smb_open io;
3017         const char *fname_base = BASEDIR "\\test_stream1.txt";
3018         const char *fname_stream, *fname_default_stream;
3019         const char *default_stream = "::$DATA";
3020         const char *stream = "Stream One:$DATA";
3021         bool ret = true;
3022         struct smb2_handle h, h_base, h_stream;
3023         int i;
3024
3025 #define NSTREAM_OPLOCK_RESULTS 8
3026         struct {
3027                 const char **fname;
3028                 bool open_base_file;
3029                 uint32_t oplock_req;
3030                 uint32_t oplock_granted;
3031         } stream_oplock_results[NSTREAM_OPLOCK_RESULTS] = {
3032                 /* Request oplock on stream without the base file open. */
3033                 {&fname_stream, false, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
3034                 {&fname_default_stream, false, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
3035                 {&fname_stream, false, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
3036                 {&fname_default_stream, false,  SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
3037
3038                 /* Request oplock on stream with the base file open. */
3039                 {&fname_stream, true, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
3040                 {&fname_default_stream, true, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_II},
3041                 {&fname_stream, true, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
3042                 {&fname_default_stream, true,  SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_II},
3043         };
3044
3045         fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
3046         fname_default_stream = talloc_asprintf(tctx, "%s%s", fname_base,
3047                                                default_stream);
3048
3049         status = torture_smb2_testdir(tree1, BASEDIR, &h);
3050         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3051
3052         /* Initialize handles to "closed".  Using -1 in the first 64-bytes
3053          * as the sentry for this */
3054         h_stream.data[0] = -1;
3055
3056         /* cleanup */
3057         smb2_util_unlink(tree1, fname_base);
3058
3059         tree1->session->transport->oplock.handler = torture_oplock_handler;
3060         tree1->session->transport->oplock.private_data = tree1;
3061
3062         tree2->session->transport->oplock.handler = torture_oplock_handler;
3063         tree2->session->transport->oplock.private_data = tree2;
3064
3065         /* Setup generic open parameters. */
3066         ZERO_STRUCT(io.smb2);
3067         io.generic.level = RAW_OPEN_SMB2;
3068         io.smb2.in.desired_access = (SEC_FILE_READ_DATA |
3069                                      SEC_FILE_WRITE_DATA |
3070                                      SEC_FILE_APPEND_DATA |
3071                                      SEC_STD_READ_CONTROL);
3072         io.smb2.in.alloc_size = 0;
3073         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3074         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3075                                   NTCREATEX_SHARE_ACCESS_WRITE;
3076         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3077         io.smb2.in.create_options = 0;
3078         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3079         io.smb2.in.security_flags = 0;
3080
3081         /* Create the file with a stream */
3082         io.smb2.in.fname = fname_stream;
3083         io.smb2.in.create_flags = 0;
3084         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
3085         status = smb2_create(tree1, tctx, &(io.smb2));
3086         torture_assert_ntstatus_ok(tctx, status, "Error creating file");
3087         smb2_util_close(tree1, io.smb2.out.file.handle);
3088
3089         /* Change the disposition to open now that the file has been created. */
3090         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
3091
3092         /* Try some permutations of taking oplocks on streams. */
3093         for (i = 0; i < NSTREAM_OPLOCK_RESULTS; i++) {
3094                 const char *fname = *stream_oplock_results[i].fname;
3095                 bool open_base_file = stream_oplock_results[i].open_base_file;
3096                 uint32_t oplock_req = stream_oplock_results[i].oplock_req;
3097                 uint32_t oplock_granted =
3098                     stream_oplock_results[i].oplock_granted;
3099
3100                 if (open_base_file) {
3101                         torture_comment(tctx, "Opening base file: %s with "
3102                             "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
3103                         io.smb2.in.fname = fname_base;
3104                         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3105                         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3106                         status = smb2_create(tree2, tctx, &(io.smb2));
3107                         torture_assert_ntstatus_ok(tctx, status,
3108                             "Error opening file");
3109                         CHECK_VAL(io.smb2.out.oplock_level,
3110                             SMB2_OPLOCK_LEVEL_BATCH);
3111                         h_base = io.smb2.out.file.handle;
3112                 }
3113
3114                 torture_comment(tctx, "%d: Opening stream: %s with %d\n", i,
3115                     fname, oplock_req);
3116                 io.smb2.in.fname = fname;
3117                 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3118                 io.smb2.in.oplock_level = oplock_req;
3119
3120                 /* Do the open with the desired oplock on the stream. */
3121                 status = smb2_create(tree1, tctx, &(io.smb2));
3122                 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
3123                 CHECK_VAL(io.smb2.out.oplock_level, oplock_granted);
3124                 smb2_util_close(tree1, io.smb2.out.file.handle);
3125
3126                 /* Cleanup the base file if it was opened. */
3127                 if (open_base_file)
3128                         smb2_util_close(tree2, h_base);
3129         }
3130
3131         /* Open the stream with an exclusive oplock. */
3132         torture_comment(tctx, "Opening stream: %s with %d\n",
3133             fname_stream, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
3134         io.smb2.in.fname = fname_stream;
3135         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3136         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
3137         status = smb2_create(tree1, tctx, &(io.smb2));
3138         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
3139         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
3140         h_stream = io.smb2.out.file.handle;
3141
3142         /* Open the base file and see if it contends. */
3143         ZERO_STRUCT(break_info);
3144         torture_comment(tctx, "Opening base file: %s with %d\n",
3145             fname_base, SMB2_OPLOCK_LEVEL_BATCH);
3146         io.smb2.in.fname = fname_base;
3147         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3148         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3149         status = smb2_create(tree2, tctx, &(io.smb2));
3150         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
3151         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3152         smb2_util_close(tree2, io.smb2.out.file.handle);
3153
3154         torture_wait_for_oplock_break(tctx);
3155         CHECK_VAL(break_info.count, 0);
3156         CHECK_VAL(break_info.failures, 0);
3157
3158         /* Open the stream again to see if it contends. */
3159         ZERO_STRUCT(break_info);
3160         torture_comment(tctx, "Opening stream again: %s with "
3161             "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
3162         io.smb2.in.fname = fname_stream;
3163         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3164         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
3165         status = smb2_create(tree2, tctx, &(io.smb2));
3166         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
3167         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
3168         smb2_util_close(tree2, io.smb2.out.file.handle);
3169
3170         torture_wait_for_oplock_break(tctx);
3171         CHECK_VAL(break_info.count, 1);
3172         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3173         CHECK_VAL(break_info.failures, 0);
3174
3175         /* Close the stream. */
3176         if (h_stream.data[0] != -1) {
3177                 smb2_util_close(tree1, h_stream);
3178         }
3179
3180         smb2_util_close(tree1, h);
3181
3182         smb2_deltree(tree1, BASEDIR);
3183         return ret;
3184 }
3185
3186 static bool test_smb2_oplock_doc(struct torture_context *tctx, struct smb2_tree *tree,
3187                                  struct smb2_tree *tree2)
3188 {
3189         const char *fname = BASEDIR "\\test_oplock_doc.dat";
3190         NTSTATUS status;
3191         bool ret = true;
3192         union smb_open io;
3193         struct smb2_handle h, h1;
3194         union smb_setfileinfo sfinfo;
3195
3196         status = torture_smb2_testdir(tree, BASEDIR, &h);
3197         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3198         smb2_util_close(tree, h);
3199
3200         /* cleanup */
3201         smb2_util_unlink(tree, fname);
3202         tree->session->transport->oplock.handler = torture_oplock_handler;
3203         tree->session->transport->oplock.private_data = tree;
3204
3205         /*
3206           base ntcreatex parms
3207         */
3208         ZERO_STRUCT(io.smb2);
3209         io.generic.level = RAW_OPEN_SMB2;
3210         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3211         io.smb2.in.alloc_size = 0;
3212         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3213         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
3214                 NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
3215         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3216         io.smb2.in.create_options = 0;
3217         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3218         io.smb2.in.security_flags = 0;
3219         io.smb2.in.fname = fname;
3220
3221         torture_comment(tctx, "open a file with a batch oplock\n");
3222         ZERO_STRUCT(break_info);
3223         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3224         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3225
3226         status = smb2_create(tree, tctx, &(io.smb2));
3227         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3228         h1 = io.smb2.out.file.handle;
3229         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3230
3231         torture_comment(tctx, "Set delete on close\n");
3232         ZERO_STRUCT(sfinfo);
3233         sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3234         sfinfo.generic.in.file.handle = h1;
3235         sfinfo.disposition_info.in.delete_on_close = 1;
3236         status = smb2_setinfo_file(tree, &sfinfo);
3237         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3238
3239         torture_comment(tctx, "2nd open should not break and get "
3240                         "DELETE_PENDING\n");
3241         ZERO_STRUCT(break_info);
3242         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
3243         io.smb2.in.create_options = 0;
3244         io.smb2.in.desired_access = SEC_FILE_READ_DATA;
3245         status = smb2_create(tree2, tctx, &io.smb2);
3246         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DELETE_PENDING,
3247                                       "Incorrect status");
3248         CHECK_VAL(break_info.count, 0);
3249
3250         smb2_util_close(tree, h1);
3251
3252         smb2_util_unlink(tree, fname);
3253         smb2_deltree(tree, BASEDIR);
3254         return ret;
3255 }
3256
3257 /* Open a file with a batch oplock, then open it again from a second client
3258  * requesting no oplock. Having two open file handles should break our own
3259  * oplock during BRL acquisition.
3260  */
3261 static bool test_smb2_oplock_brl1(struct torture_context *tctx,
3262                                 struct smb2_tree *tree1,
3263                                 struct smb2_tree *tree2)
3264 {
3265         const char *fname = BASEDIR "\\test_batch_brl.dat";
3266         /*int fname, f;*/
3267         bool ret = true;
3268         uint8_t buf[1000];
3269         union smb_open io;
3270         NTSTATUS status;
3271         struct smb2_lock lck;
3272         struct smb2_lock_element lock[1];
3273         struct smb2_handle h, h1, h2;
3274
3275         status = torture_smb2_testdir(tree1, BASEDIR, &h);
3276         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3277
3278         /* cleanup */
3279         smb2_util_unlink(tree1, fname);
3280
3281         tree1->session->transport->oplock.handler =
3282             torture_oplock_handler_two_notifications;
3283         tree1->session->transport->oplock.private_data = tree1;
3284
3285         /*
3286           base ntcreatex parms
3287         */
3288         ZERO_STRUCT(io.smb2);
3289         io.generic.level = RAW_OPEN_SMB2;
3290         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3291                                     SEC_RIGHTS_FILE_WRITE;
3292         io.smb2.in.alloc_size = 0;
3293         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3294         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3295                                   NTCREATEX_SHARE_ACCESS_WRITE;
3296         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3297         io.smb2.in.create_options = 0;
3298         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3299         io.smb2.in.security_flags = 0;
3300         io.smb2.in.fname = fname;
3301
3302         /*
3303           with a batch oplock we get a break
3304         */
3305         torture_comment(tctx, "open with batch oplock\n");
3306         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3307         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3308
3309         status = smb2_create(tree1, tctx, &(io.smb2));
3310         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3311         h1 = io.smb2.out.file.handle;
3312         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3313
3314         /* create a file with bogus data */
3315         memset(buf, 0, sizeof(buf));
3316
3317         status = smb2_util_write(tree1, h1,buf, 0, sizeof(buf));
3318         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3319                 torture_comment(tctx, "Failed to create file\n");
3320                 ret = false;
3321                 goto done;
3322         }
3323
3324         torture_comment(tctx, "a 2nd open should give a break\n");
3325         ZERO_STRUCT(break_info);
3326
3327         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3328         io.smb2.in.oplock_level = 0;
3329         status = smb2_create(tree2, tctx, &(io.smb2));
3330         h2 = io.smb2.out.file.handle;
3331         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3332
3333         torture_wait_for_oplock_break(tctx);
3334         CHECK_VAL(break_info.count, 1);
3335         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
3336         CHECK_VAL(break_info.failures, 0);
3337         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3338
3339         ZERO_STRUCT(break_info);
3340
3341         torture_comment(tctx, "a self BRL acquisition should break to none\n");
3342
3343         ZERO_STRUCT(lock);
3344
3345         lock[0].offset = 0;
3346         lock[0].length = 4;
3347         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3348                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3349
3350         ZERO_STRUCT(lck);
3351         lck.in.file.handle = h1;
3352         lck.in.locks = &lock[0];
3353         lck.in.lock_count = 1;
3354         status = smb2_lock(tree1, &lck);
3355         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3356
3357         torture_wait_for_oplock_break(tctx);
3358         CHECK_VAL(break_info.count, 1);
3359         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
3360         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3361         CHECK_VAL(break_info.failures, 0);
3362
3363         /* expect no oplock break */
3364         ZERO_STRUCT(break_info);
3365         lock[0].offset = 2;
3366         status = smb2_lock(tree1, &lck);
3367         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3368                                       "Incorrect status");
3369
3370         torture_wait_for_oplock_break(tctx);
3371         CHECK_VAL(break_info.count, 0);
3372         CHECK_VAL(break_info.level, 0);
3373         CHECK_VAL(break_info.failures, 0);
3374
3375         smb2_util_close(tree1, h1);
3376         smb2_util_close(tree2, h2);
3377         smb2_util_close(tree1, h);
3378
3379 done:
3380         smb2_deltree(tree1, BASEDIR);
3381         return ret;
3382
3383 }
3384
3385 /* Open a file with a batch oplock on one tree and then acquire a brl.
3386  * We should not contend our own oplock.
3387  */
3388 static bool test_smb2_oplock_brl2(struct torture_context *tctx, struct smb2_tree *tree1)
3389 {
3390         const char *fname = BASEDIR "\\test_batch_brl.dat";
3391         /*int fname, f;*/
3392         bool ret = true;
3393         uint8_t buf[1000];
3394         union smb_open io;
3395         NTSTATUS status;
3396         struct smb2_handle h, h1;
3397         struct smb2_lock lck;
3398         struct smb2_lock_element lock[1];
3399
3400         status = torture_smb2_testdir(tree1, BASEDIR, &h);
3401         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3402
3403         /* cleanup */
3404         smb2_util_unlink(tree1, fname);
3405
3406         tree1->session->transport->oplock.handler = torture_oplock_handler;
3407         tree1->session->transport->oplock.private_data = tree1;
3408
3409         /*
3410           base ntcreatex parms
3411         */
3412         ZERO_STRUCT(io.smb2);
3413         io.generic.level = RAW_OPEN_SMB2;
3414         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3415                                     SEC_RIGHTS_FILE_WRITE;
3416         io.smb2.in.alloc_size = 0;
3417         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3418         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3419                                   NTCREATEX_SHARE_ACCESS_WRITE;
3420         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3421         io.smb2.in.create_options = 0;
3422         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3423         io.smb2.in.security_flags = 0;
3424         io.smb2.in.fname = fname;
3425
3426         /*
3427           with a batch oplock we get a break
3428         */
3429         torture_comment(tctx, "open with batch oplock\n");
3430         ZERO_STRUCT(break_info);
3431         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3432         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3433
3434         status = smb2_create(tree1, tctx, &(io.smb2));
3435         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3436         h1 = io.smb2.out.file.handle;
3437         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3438
3439         /* create a file with bogus data */
3440         memset(buf, 0, sizeof(buf));
3441
3442         status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
3443         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3444                 torture_comment(tctx, "Failed to create file\n");
3445                 ret = false;
3446                 goto done;
3447         }
3448
3449         ZERO_STRUCT(break_info);
3450
3451         torture_comment(tctx, "a self BRL acquisition should not break to "
3452                         "none\n");
3453
3454         ZERO_STRUCT(lock);
3455
3456         lock[0].offset = 0;
3457         lock[0].length = 4;
3458         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3459                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3460
3461         ZERO_STRUCT(lck);
3462         lck.in.file.handle = h1;
3463         lck.in.locks = &lock[0];
3464         lck.in.lock_count = 1;
3465         status = smb2_lock(tree1, &lck);
3466         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3467
3468         lock[0].offset = 2;
3469         status = smb2_lock(tree1, &lck);
3470         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3471                                       "Incorrect status");
3472
3473         /* With one file handle open a BRL should not contend our oplock.
3474          * Thus, no oplock break will be received and the entire break_info
3475          * struct will be 0 */
3476         torture_wait_for_oplock_break(tctx);
3477         CHECK_VAL(break_info.count, 0);
3478         CHECK_VAL(break_info.level, 0);
3479         CHECK_VAL(break_info.failures, 0);
3480
3481         smb2_util_close(tree1, h1);
3482         smb2_util_close(tree1, h);
3483
3484 done:
3485         smb2_deltree(tree1, BASEDIR);
3486         return ret;
3487 }
3488
3489 /* Open a file with a batch oplock twice from one tree and then acquire a
3490  * brl. BRL acquisition should break our own oplock.
3491  */
3492 static bool test_smb2_oplock_brl3(struct torture_context *tctx, struct smb2_tree *tree1)
3493 {
3494         const char *fname = BASEDIR "\\test_batch_brl.dat";
3495         bool ret = true;
3496         uint8_t buf[1000];
3497         union smb_open io;
3498         NTSTATUS status;
3499         struct smb2_handle h, h1, h2;
3500         struct smb2_lock lck;
3501         struct smb2_lock_element lock[1];
3502
3503         status = torture_smb2_testdir(tree1, BASEDIR, &h);
3504         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3505
3506         /* cleanup */
3507         smb2_util_unlink(tree1, fname);
3508         tree1->session->transport->oplock.handler =
3509             torture_oplock_handler_two_notifications;
3510         tree1->session->transport->oplock.private_data = tree1;
3511
3512         /*
3513           base ntcreatex parms
3514         */
3515         ZERO_STRUCT(io.smb2);
3516         io.generic.level = RAW_OPEN_SMB2;
3517         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3518                                     SEC_RIGHTS_FILE_WRITE;
3519         io.smb2.in.alloc_size = 0;
3520         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3521         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3522                                   NTCREATEX_SHARE_ACCESS_WRITE;
3523         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3524         io.smb2.in.create_options = 0;
3525         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3526         io.smb2.in.security_flags = 0;
3527         io.smb2.in.fname = fname;
3528
3529         /*
3530           with a batch oplock we get a break
3531         */
3532         torture_comment(tctx, "open with batch oplock\n");
3533         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3534         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3535
3536         status = smb2_create(tree1, tctx, &(io.smb2));
3537         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3538         h1 = io.smb2.out.file.handle;
3539         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3540
3541         /* create a file with bogus data */
3542         memset(buf, 0, sizeof(buf));
3543         status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
3544
3545         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3546                 torture_comment(tctx, "Failed to create file\n");
3547                 ret = false;
3548                 goto done;
3549         }
3550
3551         torture_comment(tctx, "a 2nd open should give a break\n");
3552         ZERO_STRUCT(break_info);
3553
3554         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3555         io.smb2.in.oplock_level = 0;
3556         status = smb2_create(tree1, tctx, &(io.smb2));
3557         h2 = io.smb2.out.file.handle;
3558         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3559         CHECK_VAL(break_info.count, 1);
3560         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
3561         CHECK_VAL(break_info.failures, 0);
3562         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3563
3564         ZERO_STRUCT(break_info);
3565
3566         torture_comment(tctx, "a self BRL acquisition should break to none\n");
3567
3568         ZERO_STRUCT(lock);
3569
3570         lock[0].offset = 0;
3571         lock[0].length = 4;
3572         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3573                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3574
3575         ZERO_STRUCT(lck);
3576         lck.in.file.handle = h1;
3577         lck.in.locks = &lock[0];
3578         lck.in.lock_count = 1;
3579         status = smb2_lock(tree1, &lck);
3580         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3581
3582         torture_wait_for_oplock_break(tctx);
3583         CHECK_VAL(break_info.count, 1);
3584         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
3585         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3586         CHECK_VAL(break_info.failures, 0);
3587
3588         /* expect no oplock break */
3589         ZERO_STRUCT(break_info);
3590         lock[0].offset = 2;
3591         status = smb2_lock(tree1, &lck);
3592         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3593                                       "Incorrect status");
3594
3595         torture_wait_for_oplock_break(tctx);
3596         CHECK_VAL(break_info.count, 0);
3597         CHECK_VAL(break_info.level, 0);
3598         CHECK_VAL(break_info.failures, 0);
3599
3600         smb2_util_close(tree1, h1);
3601         smb2_util_close(tree1, h2);
3602         smb2_util_close(tree1, h);
3603
3604 done:
3605         smb2_deltree(tree1, BASEDIR);
3606         return ret;
3607
3608 }
3609
3610 /* Starting the SMB2 specific oplock tests at 500 so we can keep the SMB1
3611  * tests in sync with an identically numbered SMB2 test */
3612
3613 /* Test whether the server correctly returns an error when we send
3614  * a response to a levelII to none oplock notification. */
3615 static bool test_smb2_oplock_levelII500(struct torture_context *tctx,
3616                                       struct smb2_tree *tree1)
3617 {
3618         const char *fname = BASEDIR "\\test_levelII500.dat";
3619         NTSTATUS status;
3620         bool ret = true;
3621         union smb_open io;
3622         struct smb2_handle h, h1;
3623         char c = 0;
3624
3625         status = torture_smb2_testdir(tree1, BASEDIR, &h);
3626         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3627
3628         /* cleanup */
3629         smb2_util_unlink(tree1, fname);
3630
3631         tree1->session->transport->oplock.handler = torture_oplock_handler;
3632         tree1->session->transport->oplock.private_data = tree1;
3633
3634         /*
3635           base ntcreatex parms
3636         */
3637         ZERO_STRUCT(io.smb2);
3638         io.generic.level = RAW_OPEN_SMB2;
3639         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3640         io.smb2.in.alloc_size = 0;
3641         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3642         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3643         io.smb2.in.create_options = 0;
3644         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3645         io.smb2.in.security_flags = 0;
3646         io.smb2.in.fname = fname;
3647
3648         torture_comment(tctx, "LEVELII500: acknowledging a break from II to "
3649                         "none should return an error\n");
3650         ZERO_STRUCT(break_info);
3651
3652         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3653                                 SEC_RIGHTS_FILE_WRITE;
3654         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3655                                 NTCREATEX_SHARE_ACCESS_WRITE;
3656         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3657         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
3658         status = smb2_create(tree1, tctx, &(io.smb2));
3659         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3660         h1 = io.smb2.out.file.handle;
3661         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
3662
3663         ZERO_STRUCT(break_info);
3664
3665         torture_comment(tctx, "write should trigger a break to none and when "
3666                         "we reply, an oplock break failure\n");
3667         smb2_util_write(tree1, h1, &c, 0, 1);
3668
3669         /* Wait several times to receive both the break notification, and the
3670          * NT_STATUS_INVALID_OPLOCK_PROTOCOL error in the break response */
3671         torture_wait_for_oplock_break(tctx);
3672         torture_wait_for_oplock_break(tctx);
3673         torture_wait_for_oplock_break(tctx);
3674         torture_wait_for_oplock_break(tctx);
3675
3676         /* There appears to be a race condition in W2K8 and W2K8R2 where
3677          * sometimes the server will happily reply to our break response with
3678          * NT_STATUS_OK, and sometimes it will return the OPLOCK_PROTOCOL
3679          * error.  As the MS-SMB2 doc states that a client should not reply to
3680          * a level2 to none break notification, I'm leaving the protocol error
3681          * as the expected behavior. */
3682         CHECK_VAL(break_info.count, 1);
3683         CHECK_VAL(break_info.level, 0);
3684         CHECK_VAL(break_info.failures, 1);
3685         torture_assert_ntstatus_equal(tctx, break_info.failure_status,
3686                                       NT_STATUS_INVALID_OPLOCK_PROTOCOL,
3687                                       "Incorrect status");
3688
3689         smb2_util_close(tree1, h1);
3690         smb2_util_close(tree1, h);
3691
3692         smb2_deltree(tree1, BASEDIR);
3693         return ret;
3694 }
3695
3696 /*
3697  * Test a double-break. Open a file with exclusive. Send off a second open
3698  * request with OPEN_IF, triggering a break to level2. This should respond
3699  * with level2. Before replying to the break to level2, fire off a third open
3700  * with OVERWRITE_IF. The expected sequence would be that the 3rd opener gets
3701  * a level2 immediately triggered by a break to none, but that seems not the
3702  * case. Still investigating what the right behaviour should be.
3703  */
3704
3705 struct levelII501_state {
3706         struct torture_context *tctx;
3707         struct smb2_tree *tree1;
3708         struct smb2_tree *tree2;
3709         struct smb2_tree *tree3;
3710         struct smb2_handle h;
3711         struct smb2_handle h1;
3712         union smb_open io;
3713
3714         struct smb2_handle break_handle;
3715         uint8_t break_to;
3716         struct smb2_break br;
3717
3718         bool done;
3719 };
3720
3721 static bool torture_oplock_break_delay(struct smb2_transport *transport,
3722                                        const struct smb2_handle *handle,
3723                                        uint8_t level, void *private_data);
3724 static void levelII501_break_done(struct smb2_request *req);
3725 static void levelII501_open1_done(struct smb2_request *req);
3726 static void levelII501_open2_done(struct smb2_request *req);
3727 static void levelII501_2ndopen_cb(struct tevent_context *ev,
3728                                   struct tevent_timer *te,
3729                                   struct timeval current_time,
3730                                   void *private_data);
3731 static void levelII501_break_timeout_cb(struct tevent_context *ev,
3732                                         struct tevent_timer *te,
3733                                         struct timeval current_time,
3734                                         void *private_data);
3735 static void levelII501_timeout_cb(struct tevent_context *ev,
3736                                   struct tevent_timer *te,
3737                                   struct timeval current_time,
3738                                   void *private_data);
3739
3740 static bool test_smb2_oplock_levelII501(struct torture_context *tctx,
3741                                         struct smb2_tree *tree1,
3742                                         struct smb2_tree *tree2)
3743 {
3744         const char *fname = BASEDIR "\\test_levelII501.dat";
3745         NTSTATUS status;
3746         bool ret = true;
3747         struct levelII501_state *state;
3748         struct smb2_request *req;
3749         struct tevent_timer *te;
3750
3751         state = talloc(tctx, struct levelII501_state);
3752         state->tctx = tctx;
3753         state->done = false;
3754         state->tree1 = tree1;
3755         state->tree2 = tree2;
3756
3757         if (!torture_smb2_connection(tctx, &state->tree3)) {
3758                 torture_fail(tctx, "Establishing SMB2 connection failed\n");
3759                 return false;
3760         }
3761
3762         status = torture_smb2_testdir(tree1, BASEDIR, &state->h);
3763         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3764
3765         /* cleanup */
3766         smb2_util_unlink(tree1, fname);
3767
3768         /*
3769           base ntcreatex parms
3770         */
3771         ZERO_STRUCT(state->io.smb2);
3772         state->io.generic.level = RAW_OPEN_SMB2;
3773         state->io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3774         state->io.smb2.in.alloc_size = 0;
3775         state->io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3776         state->io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3777         state->io.smb2.in.create_options = 0;
3778         state->io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3779         state->io.smb2.in.security_flags = 0;
3780         state->io.smb2.in.fname = fname;
3781
3782         torture_comment(tctx, "LEVELII501: Test double break sequence\n");
3783         ZERO_STRUCT(break_info);
3784
3785         state->io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3786                                 SEC_RIGHTS_FILE_WRITE;
3787         state->io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3788                                 NTCREATEX_SHARE_ACCESS_WRITE;
3789         state->io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3790         state->io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
3791
3792         tree1->session->transport->oplock.handler = torture_oplock_break_delay;
3793         tree1->session->transport->oplock.private_data = state;
3794
3795         status = smb2_create(tree1, tctx, &(state->io.smb2));
3796         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3797         state->h1 = state->io.smb2.out.file.handle;
3798         CHECK_VAL(state->io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
3799
3800         /*
3801          * Trigger a break to level2
3802          */
3803
3804         req = smb2_create_send(tree2, &state->io.smb2);
3805         req->async.fn = levelII501_open1_done;
3806         req->async.private_data = state;
3807
3808         te = tevent_add_timer(
3809                 tctx->ev, tctx, tevent_timeval_current_ofs(0, 200000),
3810                 levelII501_2ndopen_cb, state);
3811         torture_assert(tctx, te != NULL, "tevent_add_timer failed\n");
3812
3813         te = tevent_add_timer(
3814                 tctx->ev, tctx, tevent_timeval_current_ofs(2, 0),
3815                 levelII501_timeout_cb, state);
3816         torture_assert(tctx, te != NULL, "tevent_add_timer failed\n");
3817
3818         while (!state->done) {
3819                 if (tevent_loop_once(tctx->ev) != 0) {
3820                         torture_comment(tctx, "tevent_loop_once failed\n");
3821                 }
3822         }
3823
3824         return ret;
3825 }
3826
3827 /*
3828  * Fire off a second open after a little timeout
3829  */
3830
3831 static void levelII501_2ndopen_cb(struct tevent_context *ev,
3832                                   struct tevent_timer *te,
3833                                   struct timeval current_time,
3834                                   void *private_data)
3835 {
3836         struct levelII501_state *state = talloc_get_type_abort(
3837                 private_data, struct levelII501_state);
3838         struct smb2_request *req;
3839
3840         state->io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
3841         req = smb2_create_send(state->tree3, &state->io.smb2);
3842         req->async.fn = levelII501_open2_done;
3843         req->async.private_data = state;
3844 }
3845
3846 /*
3847  * Postpone the break response by 500 msec
3848  */
3849 static bool torture_oplock_break_delay(struct smb2_transport *transport,
3850                                        const struct smb2_handle *handle,
3851                                        uint8_t level, void *private_data)
3852 {
3853         struct levelII501_state *state = talloc_get_type_abort(
3854                 private_data, struct levelII501_state);
3855         const char *name;
3856         struct tevent_timer *te;
3857
3858         break_info.handle       = *handle;
3859         break_info.level        = level;
3860         break_info.count++;
3861
3862         state->break_handle = *handle;
3863         state->break_to = level;
3864
3865         switch(level) {
3866         case SMB2_OPLOCK_LEVEL_II:
3867                 name = "level II";
3868                 break;
3869         case SMB2_OPLOCK_LEVEL_NONE:
3870                 name = "none";
3871                 break;
3872         default:
3873                 name = "unknown";
3874                 break;
3875         }
3876         printf("Got break to %s [0x%02X] in oplock handler, postponing "
3877                "break response for 500msec\n", name, level);
3878
3879         te = tevent_add_timer(
3880                 state->tctx->ev, state->tctx,
3881                 tevent_timeval_current_ofs(0, 500000),
3882                 levelII501_break_timeout_cb, state);
3883         torture_assert(state->tctx, te != NULL, "tevent_add_timer failed\n");
3884
3885         return true;
3886 }
3887
3888 static void levelII501_break_timeout_cb(struct tevent_context *ev,
3889                                         struct tevent_timer *te,
3890                                         struct timeval current_time,
3891                                         void *private_data)
3892 {
3893         struct levelII501_state *state = talloc_get_type_abort(
3894                 private_data, struct levelII501_state);
3895         struct smb2_request *req;
3896
3897         talloc_free(te);
3898
3899         ZERO_STRUCT(state->br);
3900         state->br.in.file.handle = state->break_handle;
3901         state->br.in.oplock_level = state->break_to;
3902
3903         req = smb2_break_send(state->tree1, &state->br);
3904         req->async.fn = levelII501_break_done;
3905         req->async.private_data = state;
3906 }
3907
3908 static void levelII501_break_done(struct smb2_request *req)
3909 {
3910         struct smb2_break io;
3911         NTSTATUS status;
3912
3913         status = smb2_break_recv(req, &io);
3914         printf("break done: %s\n", nt_errstr(status));
3915 }
3916
3917 static void levelII501_open1_done(struct smb2_request *req)
3918 {
3919         struct levelII501_state *state = talloc_get_type_abort(
3920                 req->async.private_data, struct levelII501_state);
3921         struct smb2_create io;
3922         NTSTATUS status;
3923
3924         status = smb2_create_recv(req, state, &io);
3925         printf("open1 done: %s\n", nt_errstr(status));
3926 }
3927
3928 static void levelII501_open2_done(struct smb2_request *req)
3929 {
3930         struct levelII501_state *state = talloc_get_type_abort(
3931                 req->async.private_data, struct levelII501_state);
3932         struct smb2_create io;
3933         NTSTATUS status;
3934
3935         status = smb2_create_recv(req, state, &io);
3936         printf("open2 done: %s\n", nt_errstr(status));
3937 }
3938
3939 static void levelII501_timeout_cb(struct tevent_context *ev,
3940                                   struct tevent_timer *te,
3941                                   struct timeval current_time,
3942                                   void *private_data)
3943 {
3944         struct levelII501_state *state = talloc_get_type_abort(
3945                 private_data, struct levelII501_state);
3946         talloc_free(te);
3947         state->done = true;
3948 }
3949
3950 struct torture_suite *torture_smb2_oplocks_init(TALLOC_CTX *ctx)
3951 {
3952         struct torture_suite *suite =
3953             torture_suite_create(ctx, "oplock");
3954
3955         torture_suite_add_2smb2_test(suite, "exclusive1", test_smb2_oplock_exclusive1);
3956         torture_suite_add_2smb2_test(suite, "exclusive2", test_smb2_oplock_exclusive2);
3957         torture_suite_add_2smb2_test(suite, "exclusive3", test_smb2_oplock_exclusive3);
3958         torture_suite_add_2smb2_test(suite, "exclusive4", test_smb2_oplock_exclusive4);
3959         torture_suite_add_2smb2_test(suite, "exclusive5", test_smb2_oplock_exclusive5);
3960         torture_suite_add_2smb2_test(suite, "exclusive6", test_smb2_oplock_exclusive6);
3961         torture_suite_add_2smb2_test(suite, "exclusive9",
3962                                      test_smb2_oplock_exclusive9);
3963         torture_suite_add_2smb2_test(suite, "batch1", test_smb2_oplock_batch1);
3964         torture_suite_add_2smb2_test(suite, "batch2", test_smb2_oplock_batch2);
3965         torture_suite_add_2smb2_test(suite, "batch3", test_smb2_oplock_batch3);
3966         torture_suite_add_2smb2_test(suite, "batch4", test_smb2_oplock_batch4);
3967         torture_suite_add_2smb2_test(suite, "batch5", test_smb2_oplock_batch5);
3968         torture_suite_add_2smb2_test(suite, "batch6", test_smb2_oplock_batch6);
3969         torture_suite_add_2smb2_test(suite, "batch7", test_smb2_oplock_batch7);
3970         torture_suite_add_2smb2_test(suite, "batch8", test_smb2_oplock_batch8);
3971         torture_suite_add_2smb2_test(suite, "batch9", test_smb2_oplock_batch9);
3972         torture_suite_add_2smb2_test(suite, "batch9a", test_smb2_oplock_batch9a);
3973         torture_suite_add_2smb2_test(suite, "batch10", test_smb2_oplock_batch10);
3974         torture_suite_add_2smb2_test(suite, "batch11", test_smb2_oplock_batch11);
3975         torture_suite_add_2smb2_test(suite, "batch12", test_smb2_oplock_batch12);
3976         torture_suite_add_2smb2_test(suite, "batch13", test_smb2_oplock_batch13);
3977         torture_suite_add_2smb2_test(suite, "batch14", test_smb2_oplock_batch14);
3978         torture_suite_add_2smb2_test(suite, "batch15", test_smb2_oplock_batch15);
3979         torture_suite_add_2smb2_test(suite, "batch16", test_smb2_oplock_batch16);
3980         torture_suite_add_1smb2_test(suite, "batch19", test_smb2_oplock_batch19);
3981         torture_suite_add_2smb2_test(suite, "batch20", test_smb2_oplock_batch20);
3982         torture_suite_add_1smb2_test(suite, "batch21", test_smb2_oplock_batch21);
3983         torture_suite_add_1smb2_test(suite, "batch22", test_smb2_oplock_batch22);
3984         torture_suite_add_2smb2_test(suite, "batch23", test_smb2_oplock_batch23);
3985         torture_suite_add_2smb2_test(suite, "batch24", test_smb2_oplock_batch24);
3986         torture_suite_add_1smb2_test(suite, "batch25", test_smb2_oplock_batch25);
3987         torture_suite_add_1smb2_test(suite, "batch26", test_smb2_oplock_batch26);
3988         torture_suite_add_2smb2_test(suite, "stream1", test_raw_oplock_stream1);
3989         torture_suite_add_2smb2_test(suite, "doc", test_smb2_oplock_doc);
3990         torture_suite_add_2smb2_test(suite, "brl1", test_smb2_oplock_brl1);
3991         torture_suite_add_1smb2_test(suite, "brl2", test_smb2_oplock_brl2);
3992         torture_suite_add_1smb2_test(suite, "brl3", test_smb2_oplock_brl3);
3993         torture_suite_add_1smb2_test(suite, "levelii500", test_smb2_oplock_levelII500);
3994         torture_suite_add_2smb2_test(suite, "levelii501",
3995                                      test_smb2_oplock_levelII501);
3996         suite->description = talloc_strdup(suite, "SMB2-OPLOCK tests");
3997
3998         return suite;
3999 }
4000
4001 /*
4002    stress testing of oplocks
4003 */
4004 bool test_smb2_bench_oplock(struct torture_context *tctx,
4005                                    struct smb2_tree *tree)
4006 {
4007         struct smb2_tree **trees;
4008         bool ret = true;
4009         NTSTATUS status;
4010         TALLOC_CTX *mem_ctx = talloc_new(tctx);
4011         int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
4012         int i, count=0;
4013         int timelimit = torture_setting_int(tctx, "timelimit", 10);
4014         union smb_open io;
4015         struct timeval tv;
4016         struct smb2_handle h;
4017
4018         trees = talloc_array(mem_ctx, struct smb2_tree *, torture_nprocs);
4019
4020         torture_comment(tctx, "Opening %d connections\n", torture_nprocs);
4021         for (i=0;i<torture_nprocs;i++) {
4022                 if (!torture_smb2_connection(tctx, &trees[i])) {
4023                         return false;
4024                 }
4025                 talloc_steal(mem_ctx, trees[i]);
4026                 trees[i]->session->transport->oplock.handler =
4027                                         torture_oplock_handler_close;
4028                 trees[i]->session->transport->oplock.private_data = trees[i];
4029         }
4030
4031         status = torture_smb2_testdir(trees[0], BASEDIR, &h);
4032         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
4033
4034         ZERO_STRUCT(io.smb2);
4035         io.smb2.level = RAW_OPEN_SMB2;
4036         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
4037         io.smb2.in.alloc_size = 0;
4038         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4039         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
4040         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4041         io.smb2.in.create_options = 0;
4042         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4043         io.smb2.in.security_flags = 0;
4044         io.smb2.in.fname = BASEDIR "\\test.dat";
4045         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
4046         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
4047
4048         tv = timeval_current();
4049
4050         /*
4051           we open the same file with SHARE_ACCESS_NONE from all the
4052           connections in a round robin fashion. Each open causes an
4053           oplock break on the previous connection, which is answered
4054           by the oplock_handler_close() to close the file.
4055
4056           This measures how fast we can pass on oplocks, and stresses
4057           the oplock handling code
4058         */
4059         torture_comment(tctx, "Running for %d seconds\n", timelimit);
4060         while (timeval_elapsed(&tv) < timelimit) {
4061                 for (i=0;i<torture_nprocs;i++) {
4062                         status = smb2_create(trees[i], mem_ctx, &(io.smb2));
4063                         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
4064                         count++;
4065                 }
4066
4067                 if (torture_setting_bool(tctx, "progress", true)) {
4068                         torture_comment(tctx, "%.2f ops/second\r",
4069                                         count/timeval_elapsed(&tv));
4070                 }
4071         }
4072
4073         torture_comment(tctx, "%.2f ops/second\n", count/timeval_elapsed(&tv));
4074         smb2_util_close(trees[0], io.smb2.out.file.handle);
4075         smb2_util_unlink(trees[0], BASEDIR "\\test.dat");
4076         smb2_deltree(trees[0], BASEDIR);
4077         talloc_free(mem_ctx);
4078         return ret;
4079 }
4080
4081 static struct hold_oplock_info {
4082         const char *fname;
4083         bool close_on_break;
4084         uint32_t share_access;
4085         struct smb2_handle handle;
4086 } hold_info[] = {
4087         { BASEDIR "\\notshared_close", true,
4088           NTCREATEX_SHARE_ACCESS_NONE, },
4089         { BASEDIR "\\notshared_noclose", false,
4090           NTCREATEX_SHARE_ACCESS_NONE, },
4091         { BASEDIR "\\shared_close", true,
4092           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
4093         { BASEDIR "\\shared_noclose", false,
4094           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
4095 };
4096
4097 static bool torture_oplock_handler_hold(struct smb2_transport *transport,
4098                                         const struct smb2_handle *handle,
4099                                         uint8_t level, void *private_data)
4100 {
4101         struct hold_oplock_info *info;
4102         int i;
4103
4104         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
4105                 if (smb2_util_handle_equal(hold_info[i].handle, *handle))
4106                         break;
4107         }
4108
4109         if (i == ARRAY_SIZE(hold_info)) {
4110                 printf("oplock break for unknown handle 0x%llx%llx\n",
4111                        (unsigned long long) handle->data[0],
4112                        (unsigned long long) handle->data[1]);
4113                 return false;
4114         }
4115
4116         info = &hold_info[i];
4117
4118         if (info->close_on_break) {
4119                 printf("oplock break on %s - closing\n", info->fname);
4120                 torture_oplock_handler_close(transport, handle,
4121                                              level, private_data);
4122                 return true;
4123         }
4124
4125         printf("oplock break on %s - acking break\n", info->fname);
4126         printf("Acking to none in oplock handler\n");
4127
4128         torture_oplock_handler_ack_to_none(transport, handle,
4129                                            level, private_data);
4130         return true;
4131 }
4132
4133 /*
4134    used for manual testing of oplocks - especially interaction with
4135    other filesystems (such as NFS and local access)
4136 */
4137 bool test_smb2_hold_oplock(struct torture_context *tctx,
4138                            struct smb2_tree *tree)
4139 {
4140         struct torture_context *mem_ctx = talloc_new(tctx);
4141         struct tevent_context *ev = tctx->ev;
4142         int i;
4143         struct smb2_handle h;
4144         NTSTATUS status;
4145
4146         torture_comment(tctx, "Setting up open files with oplocks in %s\n",
4147                         BASEDIR);
4148
4149         status = torture_smb2_testdir(tree, BASEDIR, &h);
4150         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
4151
4152         tree->session->transport->oplock.handler = torture_oplock_handler_hold;
4153         tree->session->transport->oplock.private_data = tree;
4154
4155         /* setup the files */
4156         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
4157                 union smb_open io;
4158                 char c = 1;
4159
4160                 ZERO_STRUCT(io.smb2);
4161                 io.generic.level = RAW_OPEN_SMB2;
4162                 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
4163                 io.smb2.in.alloc_size = 0;
4164                 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4165                 io.smb2.in.share_access = hold_info[i].share_access;
4166                 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4167                 io.smb2.in.create_options = 0;
4168                 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4169                 io.smb2.in.security_flags = 0;
4170                 io.smb2.in.fname = hold_info[i].fname;
4171                 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
4172                 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
4173
4174                 torture_comment(tctx, "opening %s\n", hold_info[i].fname);
4175
4176                 status = smb2_create(tree, mem_ctx, &(io.smb2));
4177                 if (!NT_STATUS_IS_OK(status)) {
4178                         torture_comment(tctx, "Failed to open %s - %s\n",
4179                                hold_info[i].fname, nt_errstr(status));
4180                         return false;
4181                 }
4182
4183                 if (io.smb2.out.oplock_level != SMB2_OPLOCK_LEVEL_BATCH) {
4184                         torture_comment(tctx, "Oplock not granted for %s - "
4185                                         "expected %d but got %d\n",
4186                                         hold_info[i].fname,
4187                                         SMB2_OPLOCK_LEVEL_BATCH,
4188                                         io.smb2.out.oplock_level);
4189                         return false;
4190                 }
4191                 hold_info[i].handle = io.smb2.out.file.handle;
4192
4193                 /* make the file non-zero size */
4194                 status = smb2_util_write(tree, hold_info[i].handle, &c, 0, 1);
4195                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
4196                         torture_comment(tctx, "Failed to write to file\n");
4197                         return false;
4198                 }
4199         }
4200
4201         torture_comment(tctx, "Waiting for oplock events\n");
4202         tevent_loop_wait(ev);
4203         smb2_deltree(tree, BASEDIR);
4204         talloc_free(mem_ctx);
4205         return true;
4206 }
4207
4208
4209 static bool test_smb2_kernel_oplocks1(struct torture_context *tctx,
4210                                       struct smb2_tree *tree)
4211 {
4212         const char *fname = "test_kernel_oplock1.dat";
4213         NTSTATUS status;
4214         bool ret = true;
4215         struct smb2_create create;
4216         struct smb2_handle h1 = {{0}}, h2 = {{0}};
4217
4218         smb2_util_unlink(tree, fname);
4219
4220         tree->session->transport->oplock.handler = torture_oplock_handler;
4221         tree->session->transport->oplock.private_data = tree;
4222         ZERO_STRUCT(break_info);
4223
4224         ZERO_STRUCT(create);
4225         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4226         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4227         create.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
4228         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4229         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4230         create.in.fname = fname;
4231         create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
4232
4233         status = smb2_create(tree, tctx, &create);
4234         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4235         h1 = create.out.file.handle;
4236
4237         torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE, ret, done,
4238                             "Oplock level is not SMB2_OPLOCK_LEVEL_EXCLUSIVE\n");
4239
4240         ZERO_STRUCT(create);
4241         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4242         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4243         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4244         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4245         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4246         create.in.fname = fname;
4247
4248         status = smb2_create(tree, tctx, &create);
4249         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_SHARING_VIOLATION, ret, done,
4250                                            "Open didn't return NT_STATUS_SHARING_VIOLATION\n");
4251         h2 = create.out.file.handle;
4252
4253         torture_wait_for_oplock_break(tctx);
4254         if (break_info.count != 0) {
4255                 torture_warning(tctx, "Open caused oplock break\n");
4256         }
4257
4258         smb2_util_close(tree, h1);
4259         smb2_util_close(tree, h2);
4260
4261 done:
4262         if (!smb2_util_handle_empty(h1)) {
4263                 smb2_util_close(tree, h1);
4264         }
4265         if (!smb2_util_handle_empty(h2)) {
4266                 smb2_util_close(tree, h2);
4267         }
4268         smb2_util_unlink(tree, fname);
4269         return ret;
4270 }
4271
4272 static bool test_smb2_kernel_oplocks2(struct torture_context *tctx,
4273                                       struct smb2_tree *tree)
4274 {
4275         const char *fname = "test_kernel_oplock2.dat";
4276         const char *sname = "test_kernel_oplock2.dat:foo";
4277         NTSTATUS status;
4278         bool ret = true;
4279         struct smb2_create create;
4280         struct smb2_handle h1 = {{0}}, h2 = {{0}};
4281
4282         smb2_util_unlink(tree, fname);
4283
4284         tree->session->transport->oplock.handler = torture_oplock_handler;
4285         tree->session->transport->oplock.private_data = tree;
4286         ZERO_STRUCT(break_info);
4287
4288         ZERO_STRUCT(create);
4289         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4290         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4291         create.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
4292         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4293         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4294         create.in.fname = fname;
4295         create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
4296
4297         status = smb2_create(tree, tctx, &create);
4298         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4299         h1 = create.out.file.handle;
4300
4301         torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE, ret, done,
4302                             "Oplock level is not SMB2_OPLOCK_LEVEL_EXCLUSIVE\n");
4303
4304         ZERO_STRUCT(create);
4305         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4306         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4307         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4308         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4309         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4310         create.in.fname = sname;
4311
4312         status = smb2_create(tree, tctx, &create);
4313         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4314         h2 = create.out.file.handle;
4315
4316         torture_wait_for_oplock_break(tctx);
4317         if (break_info.count != 0) {
4318                 torture_warning(tctx, "Stream open caused oplock break\n");
4319         }
4320
4321         smb2_util_close(tree, h1);
4322         smb2_util_close(tree, h2);
4323
4324 done:
4325         if (!smb2_util_handle_empty(h1)) {
4326                 smb2_util_close(tree, h1);
4327         }
4328         if (!smb2_util_handle_empty(h2)) {
4329                 smb2_util_close(tree, h2);
4330         }
4331         smb2_util_unlink(tree, fname);
4332         return ret;
4333 }
4334
4335 /**
4336  * 1. 1st client opens file with oplock
4337  * 2. 2nd client opens file
4338  *
4339  * Verify 2 triggers an oplock break
4340  **/
4341 static bool test_smb2_kernel_oplocks3(struct torture_context *tctx,
4342                                       struct smb2_tree *tree,
4343                                       struct smb2_tree *tree2)
4344 {
4345         const char *fname = "test_kernel_oplock3.dat";
4346         NTSTATUS status;
4347         bool ret = true;
4348         struct smb2_create create;
4349         struct smb2_handle h1 = {{0}}, h2 = {{0}};
4350
4351         smb2_util_unlink(tree, fname);
4352         status = torture_smb2_testfile(tree, fname, &h1);
4353         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4354                                         "Error creating testfile\n");
4355         smb2_util_close(tree, h1);
4356         ZERO_STRUCT(h1);
4357
4358         tree->session->transport->oplock.handler = torture_oplock_handler;
4359         tree->session->transport->oplock.private_data = tree;
4360         ZERO_STRUCT(break_info);
4361
4362         /* 1 */
4363         ZERO_STRUCT(create);
4364         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4365         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4366         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4367         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4368         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4369         create.in.fname = fname;
4370         create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
4371
4372         status = smb2_create(tree, tctx, &create);
4373         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4374         h1 = create.out.file.handle;
4375
4376         torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE, ret, done,
4377                             "Oplock level is not SMB2_OPLOCK_LEVEL_EXCLUSIVE\n");
4378
4379         /* 2 */
4380         ZERO_STRUCT(create);
4381         create.in.desired_access = SEC_RIGHTS_FILE_READ;
4382         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4383         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4384         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4385         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4386         create.in.fname = fname;
4387
4388         status = smb2_create(tree2, tctx, &create);
4389         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4390         h2 = create.out.file.handle;
4391
4392         torture_wait_for_oplock_break(tctx);
4393         torture_assert_goto(tctx, break_info.count == 1, ret, done, "Expected 1 oplock break\n");
4394
4395 done:
4396         if (!smb2_util_handle_empty(h1)) {
4397                 smb2_util_close(tree, h1);
4398         }
4399         if (!smb2_util_handle_empty(h2)) {
4400                 smb2_util_close(tree, h2);
4401         }
4402         smb2_util_unlink(tree, fname);
4403         return ret;
4404 }
4405
4406 /**
4407  * 1) create testfile with stream
4408  * 2) open file r/w with batch oplock, sharing read/delete
4409  * 3) open stream on file for reading
4410  *
4411  * Verify 3) doesn't trigger an oplock break
4412  **/
4413 static bool test_smb2_kernel_oplocks4(struct torture_context *tctx,
4414                                       struct smb2_tree *tree)
4415 {
4416         const char *fname = "test_kernel_oplock4.dat";
4417         const char *sname = "test_kernel_oplock4.dat:foo";
4418         NTSTATUS status;
4419         bool ret = true;
4420         struct smb2_create create;
4421         struct smb2_handle h1 = {{0}}, h2 = {{0}};
4422
4423         tree->session->transport->oplock.handler = torture_oplock_handler;
4424         tree->session->transport->oplock.private_data = tree;
4425         ZERO_STRUCT(break_info);
4426         smb2_util_unlink(tree, fname);
4427
4428         /* 1 */
4429         status = torture_smb2_testfile(tree, fname, &h1);
4430         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4431                                         "Error creating testfile\n");
4432         smb2_util_close(tree, h1);
4433         ZERO_STRUCT(h1);
4434
4435         ZERO_STRUCT(create);
4436         create.in.desired_access = SEC_RIGHTS_FILE_READ;
4437         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4438         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4439         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4440         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4441         create.in.fname = sname;
4442
4443         status = smb2_create(tree, tctx, &create);
4444         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4445         h1 = create.out.file.handle;
4446         smb2_util_close(tree, h1);
4447         ZERO_STRUCT(h1);
4448
4449         /* 2 */
4450         ZERO_STRUCT(create);
4451         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4452         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4453         create.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE;
4454         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4455         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4456         create.in.fname = fname;
4457         create.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
4458
4459         status = smb2_create(tree, tctx, &create);
4460         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4461         h1 = create.out.file.handle;
4462
4463         torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_BATCH, ret, done,
4464                             "Oplock level is not SMB2_OPLOCK_LEVEL_BATCH\n");
4465
4466         ZERO_STRUCT(create);
4467         create.in.desired_access = SEC_RIGHTS_FILE_READ;
4468         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4469         create.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE;
4470         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4471         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4472         create.in.fname = sname;
4473
4474         status = smb2_create(tree, tctx, &create);
4475         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4476         h2 = create.out.file.handle;
4477
4478         torture_wait_for_oplock_break(tctx);
4479         if (break_info.count != 0) {
4480                 torture_warning(tctx, "Stream open caused oplock break\n");
4481         }
4482
4483 done:
4484         if (!smb2_util_handle_empty(h1)) {
4485                 smb2_util_close(tree, h1);
4486         }
4487         if (!smb2_util_handle_empty(h2)) {
4488                 smb2_util_close(tree, h2);
4489         }
4490         smb2_util_unlink(tree, fname);
4491         return ret;
4492 }
4493
4494 /**
4495  * 1) create testfile with stream
4496  * 2) open stream r/w with batch oplock -> batch oplock granted
4497  * 3) open stream r/o with batch oplock
4498  *
4499  * Verify 3) does trigger an oplock break
4500  **/
4501 static bool test_smb2_kernel_oplocks5(struct torture_context *tctx,
4502                                       struct smb2_tree *tree)
4503 {
4504         const char *fname = "test_kernel_oplock4.dat";
4505         const char *sname = "test_kernel_oplock4.dat:foo";
4506         NTSTATUS status;
4507         bool ret = true;
4508         struct smb2_create create;
4509         struct smb2_handle h1 = {{0}}, h2 = {{0}};
4510
4511         tree->session->transport->oplock.handler = torture_oplock_handler;
4512         tree->session->transport->oplock.private_data = tree;
4513         ZERO_STRUCT(break_info);
4514         smb2_util_unlink(tree, fname);
4515
4516         /* 1 */
4517         status = torture_smb2_testfile(tree, fname, &h1);
4518         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4519                                         "Error creating testfile\n");
4520         smb2_util_close(tree, h1);
4521         ZERO_STRUCT(h1);
4522
4523         ZERO_STRUCT(create);
4524         create.in.desired_access = SEC_RIGHTS_FILE_READ;
4525         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4526         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4527         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4528         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4529         create.in.fname = sname;
4530
4531         status = smb2_create(tree, tctx, &create);
4532         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4533         h1 = create.out.file.handle;
4534         smb2_util_close(tree, h1);
4535         ZERO_STRUCT(h1);
4536
4537         /* 2 */
4538         ZERO_STRUCT(create);
4539         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4540         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4541         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4542         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4543         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4544         create.in.fname = sname;
4545         create.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
4546
4547         status = smb2_create(tree, tctx, &create);
4548         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4549         h1 = create.out.file.handle;
4550
4551         torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_BATCH, ret, done,
4552                             "Oplock level is not SMB2_OPLOCK_LEVEL_BATCH\n");
4553
4554         ZERO_STRUCT(create);
4555         create.in.desired_access = SEC_RIGHTS_FILE_READ;
4556         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4557         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4558         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4559         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4560         create.in.fname = sname;
4561         create.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
4562
4563         status = smb2_create(tree, tctx, &create);
4564         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4565         h2 = create.out.file.handle;
4566
4567         torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_NONE, ret, done,
4568                             "Oplock level is not SMB2_OPLOCK_LEVEL_NONE\n");
4569
4570         torture_wait_for_oplock_break(tctx);
4571         if (break_info.count != 1) {
4572                 torture_warning(tctx, "Stream open didn't cause oplock break\n");
4573         }
4574
4575 done:
4576         if (!smb2_util_handle_empty(h1)) {
4577                 smb2_util_close(tree, h1);
4578         }
4579         if (!smb2_util_handle_empty(h2)) {
4580                 smb2_util_close(tree, h2);
4581         }
4582         smb2_util_unlink(tree, fname);
4583         return ret;
4584 }
4585
4586 /**
4587  * 1) create testfile with stream
4588  * 2) 1st client opens stream r/w with batch oplock -> batch oplock granted
4589  * 3) 2nd client opens stream r/o with batch oplock
4590  *
4591  * Verify 3) does trigger an oplock break
4592  **/
4593 static bool test_smb2_kernel_oplocks6(struct torture_context *tctx,
4594                                       struct smb2_tree *tree,
4595                                       struct smb2_tree *tree2)
4596 {
4597         const char *fname = "test_kernel_oplock6.dat";
4598         const char *sname = "test_kernel_oplock6.dat:foo";
4599         NTSTATUS status;
4600         bool ret = true;
4601         struct smb2_create create;
4602         struct smb2_handle h1 = {{0}}, h2 = {{0}};
4603
4604         smb2_util_unlink(tree, fname);
4605         status = torture_smb2_testfile(tree, fname, &h1);
4606         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4607                                         "Error creating testfile\n");
4608         smb2_util_close(tree, h1);
4609         ZERO_STRUCT(h1);
4610
4611         tree->session->transport->oplock.handler = torture_oplock_handler;
4612         tree->session->transport->oplock.private_data = tree;
4613         ZERO_STRUCT(break_info);
4614
4615         /* 1 */
4616         ZERO_STRUCT(create);
4617         create.in.desired_access = SEC_RIGHTS_FILE_READ;
4618         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4619         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4620         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4621         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4622         create.in.fname = sname;
4623
4624         status = smb2_create(tree, tctx, &create);
4625         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4626         h1 = create.out.file.handle;
4627         smb2_util_close(tree, h1);
4628         ZERO_STRUCT(h1);
4629
4630         /* 2 */
4631         ZERO_STRUCT(create);
4632         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4633         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4634         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4635         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4636         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4637         create.in.fname = fname;
4638         create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
4639
4640         status = smb2_create(tree, tctx, &create);
4641         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4642         h1 = create.out.file.handle;
4643
4644         torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE, ret, done,
4645                             "Oplock level is not SMB2_OPLOCK_LEVEL_EXCLUSIVE\n");
4646
4647         /* 3 */
4648         ZERO_STRUCT(create);
4649         create.in.desired_access = SEC_RIGHTS_FILE_READ;
4650         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4651         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4652         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4653         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4654         create.in.fname = fname;
4655
4656         status = smb2_create(tree2, tctx, &create);
4657         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4658         h2 = create.out.file.handle;
4659
4660         torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_NONE, ret, done,
4661                             "Oplock level is not SMB2_OPLOCK_LEVEL_NONE\n");
4662
4663         torture_wait_for_oplock_break(tctx);
4664         torture_assert_goto(tctx, break_info.count == 1, ret, done, "Expected 1 oplock break\n");
4665
4666 done:
4667         if (!smb2_util_handle_empty(h1)) {
4668                 smb2_util_close(tree, h1);
4669         }
4670         if (!smb2_util_handle_empty(h2)) {
4671                 smb2_util_close(tree, h2);
4672         }
4673         smb2_util_unlink(tree, fname);
4674         return ret;
4675 }
4676
4677 /**
4678  * Recreate regression test from bug:
4679  *
4680  * https://bugzilla.samba.org/show_bug.cgi?id=13058
4681  *
4682  * 1. smbd-1 opens the file and sets the oplock
4683  * 2. smbd-2 tries to open the file. open() fails(EAGAIN) and open is deferred.
4684  * 3. smbd-1 sends oplock break request to the client.
4685  * 4. smbd-1 closes the file.
4686  * 5. smbd-1 opens the file and sets the oplock.
4687  * 6. smbd-2 calls defer_open_done(), and should re-break the oplock.
4688  **/
4689
4690 static bool test_smb2_kernel_oplocks7(struct torture_context *tctx,
4691                                       struct smb2_tree *tree,
4692                                       struct smb2_tree *tree2)
4693 {
4694         const char *fname = "test_kernel_oplock7.dat";
4695         NTSTATUS status;
4696         bool ret = true;
4697         struct smb2_create create;
4698         struct smb2_handle h1 = {{0}}, h2 = {{0}};
4699         struct smb2_create create_2;
4700         struct smb2_create io;
4701         struct smb2_request *req;
4702
4703         smb2_util_unlink(tree, fname);
4704         status = torture_smb2_testfile(tree, fname, &h1);
4705         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4706                                         "Error creating testfile\n");
4707         smb2_util_close(tree, h1);
4708         ZERO_STRUCT(h1);
4709
4710         /* Close the open file on break. */
4711         tree->session->transport->oplock.handler = torture_oplock_handler_close;
4712         tree->session->transport->oplock.private_data = tree;
4713         ZERO_STRUCT(break_info);
4714
4715         /* 1 - open file with oplock */
4716         ZERO_STRUCT(create);
4717         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4718         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4719         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4720         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4721         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4722         create.in.fname = fname;
4723         create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
4724
4725         status = smb2_create(tree, tctx, &create);
4726         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4727                         "Error opening the file\n");
4728         CHECK_VAL(create.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
4729
4730         /* 2 - open file to break oplock */
4731         ZERO_STRUCT(create_2);
4732         create_2.in.desired_access = SEC_RIGHTS_FILE_ALL;
4733         create_2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4734         create_2.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4735         create_2.in.create_disposition = NTCREATEX_DISP_OPEN;
4736         create_2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4737         create_2.in.fname = fname;
4738         create_2.in.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
4739
4740         /* Open on tree2 - should cause a break on tree */
4741         req = smb2_create_send(tree2, &create_2);
4742         torture_assert(tctx, req != NULL, "smb2_create_send");
4743
4744         /* The oplock break handler should close the file. */
4745         /* Steps 3 & 4. */
4746         torture_wait_for_oplock_break(tctx);
4747
4748         tree->session->transport->oplock.handler = torture_oplock_handler;
4749
4750         /*
4751          * 5 - re-open on tree. NB. There is a race here
4752          * depending on which smbd goes first. We either get
4753          * an oplock level of SMB2_OPLOCK_LEVEL_EXCLUSIVE if
4754          * the close and re-open on tree is processed first, or
4755          * SMB2_OPLOCK_LEVEL_NONE if the pending create on
4756          * tree2 is processed first.
4757          */
4758         status = smb2_create(tree, tctx, &create);
4759         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4760                         "Error opening the file\n");
4761
4762         h1 = create.out.file.handle;
4763         if (create.out.oplock_level != SMB2_OPLOCK_LEVEL_EXCLUSIVE &&
4764             create.out.oplock_level != SMB2_OPLOCK_LEVEL_NONE) {
4765                 torture_result(tctx,
4766                         TORTURE_FAIL,
4767                         "(%s): wrong value for oplock got 0x%x\n",
4768                         __location__,
4769                         (unsigned int)create.out.oplock_level);
4770                 ret = false;
4771                 goto done;
4772
4773         }
4774
4775         /* 6 - retrieve the second open. */
4776         status = smb2_create_recv(req, tctx, &io);
4777         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4778                         "Error opening the file\n");
4779         h2 = io.out.file.handle;
4780         CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
4781
4782 done:
4783         if (!smb2_util_handle_empty(h1)) {
4784                 smb2_util_close(tree, h1);
4785         }
4786         if (!smb2_util_handle_empty(h2)) {
4787                 smb2_util_close(tree2, h2);
4788         }
4789         smb2_util_unlink(tree, fname);
4790         return ret;
4791 }
4792
4793 struct torture_suite *torture_smb2_kernel_oplocks_init(TALLOC_CTX *ctx)
4794 {
4795         struct torture_suite *suite =
4796             torture_suite_create(ctx, "kernel-oplocks");
4797
4798         torture_suite_add_1smb2_test(suite, "kernel_oplocks1", test_smb2_kernel_oplocks1);
4799         torture_suite_add_1smb2_test(suite, "kernel_oplocks2", test_smb2_kernel_oplocks2);
4800         torture_suite_add_2smb2_test(suite, "kernel_oplocks3", test_smb2_kernel_oplocks3);
4801         torture_suite_add_1smb2_test(suite, "kernel_oplocks4", test_smb2_kernel_oplocks4);
4802         torture_suite_add_1smb2_test(suite, "kernel_oplocks5", test_smb2_kernel_oplocks5);
4803         torture_suite_add_2smb2_test(suite, "kernel_oplocks6", test_smb2_kernel_oplocks6);
4804         torture_suite_add_2smb2_test(suite, "kernel_oplocks7", test_smb2_kernel_oplocks7);
4805
4806         suite->description = talloc_strdup(suite, "SMB2-KERNEL-OPLOCK tests");
4807
4808         return suite;
4809 }