Adding new oplock test 'batch26'.
[metze/samba/wip.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 cli_credentials *credentials = cmdline_credentials;
285         struct smbcli_options options;
286
287         lpcfg_smbcli_options(tctx->lp_ctx, &options);
288         options.use_level2_oplocks = false;
289
290         status = smb2_connect(tctx, host,
291                               lpcfg_smb_ports(tctx->lp_ctx), share,
292                               lpcfg_resolve_context(tctx->lp_ctx),
293                               credentials, tree, tctx->ev, &options,
294                               lpcfg_socket_options(tctx->lp_ctx),
295                               lpcfg_gensec_settings(tctx, tctx->lp_ctx));
296         if (!NT_STATUS_IS_OK(status)) {
297                 torture_comment(tctx, "Failed to connect to SMB2 share "
298                                 "\\\\%s\\%s - %s\n", host, share,
299                                 nt_errstr(status));
300                 return false;
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_batch10(struct torture_context *tctx,
1615                                      struct smb2_tree *tree1,
1616                                      struct smb2_tree *tree2)
1617 {
1618         const char *fname = BASEDIR "\\test_batch10.dat";
1619         NTSTATUS status;
1620         bool ret = true;
1621         union smb_open io;
1622         struct smb2_handle h, h1, h2;
1623
1624         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1625         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1626
1627         /* cleanup */
1628         smb2_util_unlink(tree1, fname);
1629
1630         tree1->session->transport->oplock.handler = torture_oplock_handler;
1631         tree1->session->transport->oplock.private_data = tree1;
1632
1633         /*
1634           base ntcreatex parms
1635         */
1636         ZERO_STRUCT(io.smb2);
1637         io.generic.level = RAW_OPEN_SMB2;
1638         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1639         io.smb2.in.alloc_size = 0;
1640         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1641         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1642         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1643         io.smb2.in.create_options = 0;
1644         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1645         io.smb2.in.security_flags = 0;
1646         io.smb2.in.fname = fname;
1647
1648         torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock "
1649                         "open should grant level2\n");
1650         ZERO_STRUCT(break_info);
1651         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1652         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1653         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1654                 NTCREATEX_SHARE_ACCESS_WRITE|
1655                 NTCREATEX_SHARE_ACCESS_DELETE;
1656         status = smb2_create(tree1, tctx, &(io.smb2));
1657         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1658         h1 = io.smb2.out.file.handle;
1659         torture_wait_for_oplock_break(tctx);
1660         CHECK_VAL(break_info.count, 0);
1661         CHECK_VAL(break_info.failures, 0);
1662         CHECK_VAL(io.smb2.out.oplock_level, 0);
1663
1664         tree2->session->transport->oplock.handler =
1665             torture_oplock_handler_level2_to_none;
1666         tree2->session->transport->oplock.private_data = tree2;
1667
1668         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1669         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1670         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1671         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1672                 NTCREATEX_SHARE_ACCESS_WRITE|
1673                 NTCREATEX_SHARE_ACCESS_DELETE;
1674         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1675         status = smb2_create(tree2, tctx, &(io.smb2));
1676         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1677         h2 = io.smb2.out.file.handle;
1678         torture_wait_for_oplock_break(tctx);
1679         CHECK_VAL(break_info.count, 0);
1680         CHECK_VAL(break_info.failures, 0);
1681         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1682
1683         torture_comment(tctx, "write should trigger a break to none\n");
1684         {
1685                 struct smb2_write wr;
1686                 DATA_BLOB data;
1687                 data = data_blob_talloc(tree1, NULL, UINT16_MAX);
1688                 data.data[0] = (const uint8_t)'x';
1689                 ZERO_STRUCT(wr);
1690                 wr.in.file.handle = h1;
1691                 wr.in.offset      = 0;
1692                 wr.in.data        = data;
1693                 status = smb2_write(tree1, &wr);
1694                 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1695         }
1696
1697         torture_wait_for_oplock_break(tctx);
1698
1699         CHECK_VAL(break_info.count, 1);
1700         CHECK_VAL(break_info.handle.data[0], h2.data[0]);
1701         CHECK_VAL(break_info.level, 0);
1702         CHECK_VAL(break_info.failures, 0);
1703
1704         smb2_util_close(tree1, h1);
1705         smb2_util_close(tree2, h2);
1706         smb2_util_close(tree1, h);
1707
1708         smb2_deltree(tree1, BASEDIR);
1709         return ret;
1710 }
1711
1712 static bool test_smb2_oplock_batch11(struct torture_context *tctx,
1713                                      struct smb2_tree *tree1,
1714                                      struct smb2_tree *tree2)
1715 {
1716         const char *fname = BASEDIR "\\test_batch11.dat";
1717         NTSTATUS status;
1718         bool ret = true;
1719         union smb_open io;
1720         union smb_setfileinfo sfi;
1721         struct smb2_handle h, h1;
1722
1723         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1724         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1725
1726         /* cleanup */
1727         smb2_util_unlink(tree1, fname);
1728
1729         tree1->session->transport->oplock.handler =
1730             torture_oplock_handler_two_notifications;
1731         tree1->session->transport->oplock.private_data = tree1;
1732
1733         /*
1734           base ntcreatex parms
1735         */
1736         ZERO_STRUCT(io.smb2);
1737         io.generic.level = RAW_OPEN_SMB2;
1738         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1739         io.smb2.in.alloc_size = 0;
1740         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1741         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1742         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1743         io.smb2.in.create_options = 0;
1744         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1745         io.smb2.in.security_flags = 0;
1746         io.smb2.in.fname = fname;
1747
1748         /* Test if a set-eof on pathname breaks an exclusive oplock. */
1749         torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks "
1750                         "oplocks.\n");
1751
1752         ZERO_STRUCT(break_info);
1753
1754         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1755         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1756         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1757         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1758                                 NTCREATEX_SHARE_ACCESS_WRITE|
1759                                 NTCREATEX_SHARE_ACCESS_DELETE;
1760         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1761         status = smb2_create(tree1, tctx, &(io.smb2));
1762         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1763         h1 = io.smb2.out.file.handle;
1764         torture_wait_for_oplock_break(tctx);
1765         CHECK_VAL(break_info.count, 0);
1766         CHECK_VAL(break_info.failures, 0);
1767         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1768
1769         ZERO_STRUCT(sfi);
1770         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1771         sfi.generic.in.file.path = fname;
1772         sfi.end_of_file_info.in.size = 100;
1773
1774         status = smb2_composite_setpathinfo(tree2, &sfi);
1775         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1776
1777         /* We expect two breaks */
1778         torture_wait_for_oplock_break(tctx);
1779         torture_wait_for_oplock_break(tctx);
1780
1781         CHECK_VAL(break_info.count, 2);
1782         CHECK_VAL(break_info.failures, 0);
1783         CHECK_VAL(break_info.level, 0);
1784
1785         smb2_util_close(tree1, h1);
1786         smb2_util_close(tree1, h);
1787
1788         smb2_deltree(tree1, BASEDIR);
1789         return ret;
1790 }
1791
1792 static bool test_smb2_oplock_batch12(struct torture_context *tctx,
1793                                      struct smb2_tree *tree1,
1794                                      struct smb2_tree *tree2)
1795 {
1796         const char *fname = BASEDIR "\\test_batch12.dat";
1797         NTSTATUS status;
1798         bool ret = true;
1799         union smb_open io;
1800         union smb_setfileinfo sfi;
1801         struct smb2_handle h, h1;
1802
1803         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1804         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1805
1806         /* cleanup */
1807         smb2_util_unlink(tree1, fname);
1808
1809         tree1->session->transport->oplock.handler =
1810             torture_oplock_handler_two_notifications;
1811         tree1->session->transport->oplock.private_data = tree1;
1812
1813         /*
1814           base ntcreatex parms
1815         */
1816         ZERO_STRUCT(io.smb2);
1817         io.generic.level = RAW_OPEN_SMB2;
1818         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1819         io.smb2.in.alloc_size = 0;
1820         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1821         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1822         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1823         io.smb2.in.create_options = 0;
1824         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1825         io.smb2.in.security_flags = 0;
1826         io.smb2.in.fname = fname;
1827
1828         /* Test if a set-allocation size on pathname breaks an exclusive
1829          * oplock. */
1830         torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size "
1831                         "breaks oplocks.\n");
1832
1833         ZERO_STRUCT(break_info);
1834
1835         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1836         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1837         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1838         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1839                                 NTCREATEX_SHARE_ACCESS_WRITE|
1840                                 NTCREATEX_SHARE_ACCESS_DELETE;
1841         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1842         status = smb2_create(tree1, tctx, &(io.smb2));
1843         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1844         h1 = io.smb2.out.file.handle;
1845         torture_wait_for_oplock_break(tctx);
1846         CHECK_VAL(break_info.count, 0);
1847         CHECK_VAL(break_info.failures, 0);
1848         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1849
1850         ZERO_STRUCT(sfi);
1851         sfi.generic.level = RAW_SFILEINFO_ALLOCATION_INFORMATION;
1852         sfi.generic.in.file.path = fname;
1853         sfi.allocation_info.in.alloc_size = 65536 * 8;
1854
1855         status = smb2_composite_setpathinfo(tree2, &sfi);
1856         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1857
1858         /* We expect two breaks */
1859         torture_wait_for_oplock_break(tctx);
1860         torture_wait_for_oplock_break(tctx);
1861
1862         CHECK_VAL(break_info.count, 2);
1863         CHECK_VAL(break_info.failures, 0);
1864         CHECK_VAL(break_info.level, 0);
1865
1866         smb2_util_close(tree1, h1);
1867         smb2_util_close(tree1, h);
1868
1869         smb2_deltree(tree1, BASEDIR);
1870         return ret;
1871 }
1872
1873 static bool test_smb2_oplock_batch13(struct torture_context *tctx,
1874                                      struct smb2_tree *tree1,
1875                                      struct smb2_tree *tree2)
1876 {
1877         const char *fname = BASEDIR "\\test_batch13.dat";
1878         NTSTATUS status;
1879         bool ret = true;
1880         union smb_open io;
1881         struct smb2_handle h, h1, h2;
1882
1883         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1884         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1885
1886         /* cleanup */
1887         smb2_util_unlink(tree1, fname);
1888
1889         tree1->session->transport->oplock.handler = torture_oplock_handler;
1890         tree1->session->transport->oplock.private_data = tree1;
1891
1892         tree2->session->transport->oplock.handler = torture_oplock_handler;
1893         tree2->session->transport->oplock.private_data = tree2;
1894
1895         /*
1896           base ntcreatex parms
1897         */
1898         ZERO_STRUCT(io.smb2);
1899         io.generic.level = RAW_OPEN_SMB2;
1900         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1901         io.smb2.in.alloc_size = 0;
1902         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1903         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1904         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1905         io.smb2.in.create_options = 0;
1906         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1907         io.smb2.in.security_flags = 0;
1908         io.smb2.in.fname = fname;
1909
1910         torture_comment(tctx, "BATCH13: open with batch oplock\n");
1911         ZERO_STRUCT(break_info);
1912
1913         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1914         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1915         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1916                 NTCREATEX_SHARE_ACCESS_WRITE|
1917                 NTCREATEX_SHARE_ACCESS_DELETE;
1918         status = smb2_create(tree1, tctx, &(io.smb2));
1919         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1920         h1 = io.smb2.out.file.handle;
1921         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1922
1923         ZERO_STRUCT(break_info);
1924
1925         torture_comment(tctx, "second open with attributes only and "
1926                         "NTCREATEX_DISP_OVERWRITE dispostion causes "
1927                         "oplock break\n");
1928
1929         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1930         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1931         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1932                                 SEC_FILE_WRITE_ATTRIBUTE |
1933                                 SEC_STD_SYNCHRONIZE;
1934         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1935                                 NTCREATEX_SHARE_ACCESS_WRITE|
1936                                 NTCREATEX_SHARE_ACCESS_DELETE;
1937         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
1938         status = smb2_create(tree2, tctx, &(io.smb2));
1939         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1940         h2 = io.smb2.out.file.handle;
1941         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1942         torture_wait_for_oplock_break(tctx);
1943         CHECK_VAL(break_info.count, 1);
1944         CHECK_VAL(break_info.failures, 0);
1945
1946         smb2_util_close(tree1, h1);
1947         smb2_util_close(tree2, h2);
1948         smb2_util_close(tree1, h);
1949
1950         smb2_deltree(tree1, BASEDIR);
1951
1952         return ret;
1953 }
1954
1955 static bool test_smb2_oplock_batch14(struct torture_context *tctx,
1956                                      struct smb2_tree *tree1,
1957                                      struct smb2_tree *tree2)
1958 {
1959         const char *fname = BASEDIR "\\test_batch14.dat";
1960         NTSTATUS status;
1961         bool ret = true;
1962         union smb_open io;
1963         struct smb2_handle h, h1, h2;
1964
1965         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1966         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1967
1968         /* cleanup */
1969         smb2_util_unlink(tree1, fname);
1970
1971         tree1->session->transport->oplock.handler = torture_oplock_handler;
1972         tree1->session->transport->oplock.private_data = tree1;
1973
1974         /*
1975           base ntcreatex parms
1976         */
1977         ZERO_STRUCT(io.smb2);
1978         io.generic.level = RAW_OPEN_SMB2;
1979         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1980         io.smb2.in.alloc_size = 0;
1981         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1982         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1983         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1984         io.smb2.in.create_options = 0;
1985         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1986         io.smb2.in.security_flags = 0;
1987         io.smb2.in.fname = fname;
1988
1989         torture_comment(tctx, "BATCH14: open with batch oplock\n");
1990         ZERO_STRUCT(break_info);
1991
1992         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1993         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1994         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1995                 NTCREATEX_SHARE_ACCESS_WRITE|
1996                 NTCREATEX_SHARE_ACCESS_DELETE;
1997         status = smb2_create(tree1, tctx, &(io.smb2));
1998         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1999         h1 = io.smb2.out.file.handle;
2000         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2001
2002         ZERO_STRUCT(break_info);
2003
2004         torture_comment(tctx, "second open with attributes only and "
2005                         "NTCREATEX_DISP_SUPERSEDE dispostion causes "
2006                         "oplock break\n");
2007
2008         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2009         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2010         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
2011                                 SEC_FILE_WRITE_ATTRIBUTE |
2012                                 SEC_STD_SYNCHRONIZE;
2013         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2014                                 NTCREATEX_SHARE_ACCESS_WRITE|
2015                                 NTCREATEX_SHARE_ACCESS_DELETE;
2016         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2017         status = smb2_create(tree2, tctx, &(io.smb2));
2018         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2019         h2 = io.smb2.out.file.handle;
2020         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2021
2022         torture_wait_for_oplock_break(tctx);
2023         CHECK_VAL(break_info.count, 1);
2024         CHECK_VAL(break_info.failures, 0);
2025
2026         smb2_util_close(tree1, h1);
2027         smb2_util_close(tree2, h2);
2028         smb2_util_close(tree1, h);
2029
2030         smb2_deltree(tree1, BASEDIR);
2031         return ret;
2032 }
2033
2034 static bool test_smb2_oplock_batch15(struct torture_context *tctx,
2035                                      struct smb2_tree *tree1,
2036                                      struct smb2_tree *tree2)
2037 {
2038         const char *fname = BASEDIR "\\test_batch15.dat";
2039         NTSTATUS status;
2040         bool ret = true;
2041         union smb_open io;
2042         union smb_fileinfo qfi;
2043         struct smb2_handle h, h1;
2044
2045         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2046         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2047
2048         /* cleanup */
2049         smb2_util_unlink(tree1, fname);
2050
2051         tree1->session->transport->oplock.handler = torture_oplock_handler;
2052         tree1->session->transport->oplock.private_data = tree1;
2053
2054         /*
2055           base ntcreatex parms
2056         */
2057         ZERO_STRUCT(io.smb2);
2058         io.generic.level = RAW_OPEN_SMB2;
2059         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2060         io.smb2.in.alloc_size = 0;
2061         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2062         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2063         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2064         io.smb2.in.create_options = 0;
2065         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2066         io.smb2.in.security_flags = 0;
2067         io.smb2.in.fname = fname;
2068
2069         /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
2070         torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks "
2071                         "a batch oplock (should not).\n");
2072
2073         ZERO_STRUCT(break_info);
2074
2075         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2076         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2077         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2078         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2079                                 NTCREATEX_SHARE_ACCESS_WRITE|
2080                                 NTCREATEX_SHARE_ACCESS_DELETE;
2081         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2082         status = smb2_create(tree1, tctx, &(io.smb2));
2083         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2084         h1 = io.smb2.out.file.handle;
2085
2086         torture_wait_for_oplock_break(tctx);
2087         CHECK_VAL(break_info.count, 0);
2088         CHECK_VAL(break_info.failures, 0);
2089         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2090
2091         ZERO_STRUCT(qfi);
2092         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2093         qfi.generic.in.file.handle = h1;
2094         status = smb2_getinfo_file(tree2, tctx, &qfi);
2095
2096         torture_wait_for_oplock_break(tctx);
2097         CHECK_VAL(break_info.count, 0);
2098
2099         smb2_util_close(tree1, h1);
2100         smb2_util_close(tree1, h);
2101
2102         smb2_deltree(tree1, BASEDIR);
2103         return ret;
2104 }
2105
2106 static bool test_smb2_oplock_batch16(struct torture_context *tctx,
2107                                      struct smb2_tree *tree1,
2108                                      struct smb2_tree *tree2)
2109 {
2110         const char *fname = BASEDIR "\\test_batch16.dat";
2111         NTSTATUS status;
2112         bool ret = true;
2113         union smb_open io;
2114         struct smb2_handle h, h1, h2;
2115
2116         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2117         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2118
2119         /* cleanup */
2120         smb2_util_unlink(tree1, fname);
2121
2122         tree1->session->transport->oplock.handler = torture_oplock_handler;
2123         tree1->session->transport->oplock.private_data = tree1;
2124
2125         tree2->session->transport->oplock.handler = torture_oplock_handler;
2126         tree2->session->transport->oplock.private_data = tree2;
2127
2128         /*
2129           base ntcreatex parms
2130         */
2131         ZERO_STRUCT(io.smb2);
2132         io.generic.level = RAW_OPEN_SMB2;
2133         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2134         io.smb2.in.alloc_size = 0;
2135         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2136         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2137         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2138         io.smb2.in.create_options = 0;
2139         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2140         io.smb2.in.security_flags = 0;
2141         io.smb2.in.fname = fname;
2142
2143         torture_comment(tctx, "BATCH16: open with batch oplock\n");
2144         ZERO_STRUCT(break_info);
2145
2146         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2147         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2148         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2149                 NTCREATEX_SHARE_ACCESS_WRITE|
2150                 NTCREATEX_SHARE_ACCESS_DELETE;
2151         status = smb2_create(tree1, tctx, &(io.smb2));
2152         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2153         h1 = io.smb2.out.file.handle;
2154         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2155
2156         ZERO_STRUCT(break_info);
2157
2158         torture_comment(tctx, "second open with attributes only and "
2159                         "NTCREATEX_DISP_OVERWRITE_IF dispostion causes "
2160                         "oplock break\n");
2161
2162         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2163         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2164         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
2165                                 SEC_FILE_WRITE_ATTRIBUTE |
2166                                 SEC_STD_SYNCHRONIZE;
2167         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2168                                 NTCREATEX_SHARE_ACCESS_WRITE|
2169                                 NTCREATEX_SHARE_ACCESS_DELETE;
2170         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2171         status = smb2_create(tree2, tctx, &(io.smb2));
2172         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2173         h2 = io.smb2.out.file.handle;
2174         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2175
2176         torture_wait_for_oplock_break(tctx);
2177         CHECK_VAL(break_info.count, 1);
2178         CHECK_VAL(break_info.failures, 0);
2179
2180         smb2_util_close(tree1, h1);
2181         smb2_util_close(tree2, h2);
2182         smb2_util_close(tree1, h);
2183
2184         smb2_deltree(tree1, BASEDIR);
2185         return ret;
2186 }
2187
2188 /* This function is a placeholder for the SMB1 RAW-OPLOCK-BATCH17 test.  Since
2189  * SMB2 doesn't have a RENAME command this test isn't applicable.  However,
2190  * it's much less confusing, when comparing test, to keep the SMB1 and SMB2
2191  * test numbers in sync. */
2192 #if 0
2193 static bool test_raw_oplock_batch17(struct torture_context *tctx,
2194                                     struct smb2_tree *tree1,
2195                                     struct smb2_tree *tree2)
2196 {
2197         return true;
2198 }
2199 #endif
2200
2201 /* This function is a placeholder for the SMB1 RAW-OPLOCK-BATCH18 test.  Since
2202  * SMB2 doesn't have an NTRENAME command this test isn't applicable.  However,
2203  * it's much less confusing, when comparing tests, to keep the SMB1 and SMB2
2204  * test numbers in sync. */
2205 #if 0
2206 static bool test_raw_oplock_batch18(struct torture_context *tctx,
2207                                     struct smb2_tree *tree1,
2208                                     struct smb2_tree *tree2)
2209 {
2210         return true;
2211 }
2212 #endif
2213
2214 static bool test_smb2_oplock_batch19(struct torture_context *tctx,
2215                                      struct smb2_tree *tree1)
2216 {
2217         const char *fname1 = BASEDIR "\\test_batch19_1.dat";
2218         const char *fname2 = BASEDIR "\\test_batch19_2.dat";
2219         NTSTATUS status;
2220         bool ret = true;
2221         union smb_open io;
2222         union smb_fileinfo qfi;
2223         union smb_setfileinfo sfi;
2224         struct smb2_handle h, h1;
2225
2226         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2227         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2228
2229         /* cleanup */
2230         smb2_util_unlink(tree1, fname1);
2231         smb2_util_unlink(tree1, fname2);
2232
2233         tree1->session->transport->oplock.handler = torture_oplock_handler;
2234         tree1->session->transport->oplock.private_data = tree1;
2235
2236         /*
2237           base ntcreatex parms
2238         */
2239         ZERO_STRUCT(io.smb2);
2240         io.generic.level = RAW_OPEN_SMB2;
2241         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2242         io.smb2.in.alloc_size = 0;
2243         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2244         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2245         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2246         io.smb2.in.create_options = 0;
2247         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2248         io.smb2.in.security_flags = 0;
2249         io.smb2.in.fname = fname1;
2250
2251         torture_comment(tctx, "BATCH19: open a file with an batch oplock "
2252                         "(share mode: none)\n");
2253         ZERO_STRUCT(break_info);
2254         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2255         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2256         status = smb2_create(tree1, tctx, &(io.smb2));
2257         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2258         h1 = io.smb2.out.file.handle;
2259         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2260
2261         torture_comment(tctx, "setfileinfo rename info should not trigger "
2262                         "a break but should cause a sharing violation\n");
2263         ZERO_STRUCT(sfi);
2264         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2265         sfi.generic.in.file.path = fname1;
2266         sfi.rename_information.in.file.handle   = h1;
2267         sfi.rename_information.in.overwrite     = 0;
2268         sfi.rename_information.in.root_fid      = 0;
2269         sfi.rename_information.in.new_name      = fname2;
2270
2271         status = smb2_setinfo_file(tree1, &sfi);
2272
2273         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2274                                       "Incorrect status");
2275
2276         torture_wait_for_oplock_break(tctx);
2277         CHECK_VAL(break_info.count, 0);
2278
2279         ZERO_STRUCT(qfi);
2280         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2281         qfi.generic.in.file.handle = h1;
2282
2283         status = smb2_getinfo_file(tree1, tctx, &qfi);
2284         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2285         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2286
2287         smb2_util_close(tree1, h1);
2288         smb2_util_close(tree1, h);
2289
2290         smb2_deltree(tree1, fname1);
2291         smb2_deltree(tree1, fname2);
2292         return ret;
2293 }
2294
2295 static bool test_smb2_oplock_batch20(struct torture_context *tctx,
2296                                      struct smb2_tree *tree1,
2297                                      struct smb2_tree *tree2)
2298 {
2299         const char *fname1 = BASEDIR "\\test_batch20_1.dat";
2300         const char *fname2 = BASEDIR "\\test_batch20_2.dat";
2301         NTSTATUS status;
2302         bool ret = true;
2303         union smb_open io;
2304         union smb_fileinfo qfi;
2305         union smb_setfileinfo sfi;
2306         struct smb2_handle h, h1, h2;
2307
2308         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2309         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2310
2311         /* cleanup */
2312         smb2_util_unlink(tree1, fname1);
2313         smb2_util_unlink(tree1, fname2);
2314
2315         tree1->session->transport->oplock.handler = torture_oplock_handler;
2316         tree1->session->transport->oplock.private_data = tree1;
2317
2318         /*
2319           base ntcreatex parms
2320         */
2321         ZERO_STRUCT(io.smb2);
2322         io.generic.level = RAW_OPEN_SMB2;
2323         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2324         io.smb2.in.alloc_size = 0;
2325         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2326         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2327         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2328         io.smb2.in.create_options = 0;
2329         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2330         io.smb2.in.security_flags = 0;
2331         io.smb2.in.fname = fname1;
2332
2333         torture_comment(tctx, "BATCH20: open a file with an batch oplock "
2334                         "(share mode: all)\n");
2335         ZERO_STRUCT(break_info);
2336         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2337         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2338         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2339                                 NTCREATEX_SHARE_ACCESS_WRITE|
2340                                 NTCREATEX_SHARE_ACCESS_DELETE;
2341         status = smb2_create(tree1, tctx, &(io.smb2));
2342         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2343         h1 = io.smb2.out.file.handle;
2344         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2345
2346         torture_comment(tctx, "setfileinfo rename info should not trigger "
2347                         "a break but should cause a sharing violation\n");
2348         ZERO_STRUCT(sfi);
2349         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2350         sfi.rename_information.in.file.handle   = h1;
2351         sfi.rename_information.in.overwrite     = 0;
2352         sfi.rename_information.in.new_name      = fname2;
2353
2354         status = smb2_setinfo_file(tree1, &sfi);
2355         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2356                                       "Incorrect status");
2357
2358         torture_wait_for_oplock_break(tctx);
2359         CHECK_VAL(break_info.count, 0);
2360
2361         ZERO_STRUCT(qfi);
2362         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2363         qfi.generic.in.file.handle = h1;
2364
2365         status = smb2_getinfo_file(tree1, tctx, &qfi);
2366         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2367         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2368
2369         torture_comment(tctx, "open the file a second time requesting batch "
2370                         "(share mode: all)\n");
2371         ZERO_STRUCT(break_info);
2372         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2373         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2374         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2375                                 NTCREATEX_SHARE_ACCESS_WRITE|
2376                                 NTCREATEX_SHARE_ACCESS_DELETE;
2377         io.smb2.in.fname = fname1;
2378         status = smb2_create(tree2, tctx, &(io.smb2));
2379         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2380         h2 = io.smb2.out.file.handle;
2381         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2382
2383         torture_wait_for_oplock_break(tctx);
2384         CHECK_VAL(break_info.count, 1);
2385         CHECK_VAL(break_info.failures, 0);
2386         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2387
2388         torture_comment(tctx, "setfileinfo rename info should not trigger "
2389                         "a break but should cause a sharing violation\n");
2390         ZERO_STRUCT(break_info);
2391         ZERO_STRUCT(sfi);
2392         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2393         sfi.rename_information.in.file.handle   = h2;
2394         sfi.rename_information.in.overwrite     = 0;
2395         sfi.rename_information.in.new_name      = fname2;
2396
2397         status = smb2_setinfo_file(tree2, &sfi);
2398         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2399                                       "Incorrect status");
2400
2401         torture_wait_for_oplock_break(tctx);
2402         CHECK_VAL(break_info.count, 0);
2403
2404         ZERO_STRUCT(qfi);
2405         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2406         qfi.generic.in.file.handle = h1;
2407
2408         status = smb2_getinfo_file(tree1, tctx, &qfi);
2409         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2410         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2411
2412         ZERO_STRUCT(qfi);
2413         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2414         qfi.generic.in.file.handle = h2;
2415
2416         status = smb2_getinfo_file(tree2, tctx, &qfi);
2417         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2418         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2419
2420         smb2_util_close(tree1, h1);
2421         smb2_util_close(tree2, h2);
2422         smb2_util_close(tree1, h);
2423
2424         smb2_deltree(tree1, fname1);
2425         return ret;
2426 }
2427
2428 static bool test_smb2_oplock_batch21(struct torture_context *tctx,
2429                                      struct smb2_tree *tree1)
2430 {
2431         const char *fname = BASEDIR "\\test_batch21.dat";
2432         NTSTATUS status;
2433         bool ret = true;
2434         union smb_open io;
2435         struct smb2_handle h, h1;
2436         char c = 0;
2437
2438         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2439         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2440
2441         /* cleanup */
2442         smb2_util_unlink(tree1, fname);
2443
2444         tree1->session->transport->oplock.handler = torture_oplock_handler;
2445         tree1->session->transport->oplock.private_data = tree1;
2446
2447         /*
2448           base ntcreatex parms
2449         */
2450         ZERO_STRUCT(io.smb2);
2451         io.generic.level = RAW_OPEN_SMB2;
2452         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2453         io.smb2.in.alloc_size = 0;
2454         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2455         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2456         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2457         io.smb2.in.create_options = 0;
2458         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2459         io.smb2.in.security_flags = 0;
2460         io.smb2.in.fname = fname;
2461
2462         /*
2463           with a batch oplock we get a break
2464         */
2465         torture_comment(tctx, "BATCH21: open with batch oplock\n");
2466         ZERO_STRUCT(break_info);
2467         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2468         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2469         status = smb2_create(tree1, tctx, &(io.smb2));
2470         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2471         h1 = io.smb2.out.file.handle;
2472         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2473
2474         torture_comment(tctx, "writing should not generate a break\n");
2475         status = smb2_util_write(tree1, h1, &c, 0, 1);
2476         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2477
2478         torture_wait_for_oplock_break(tctx);
2479         CHECK_VAL(break_info.count, 0);
2480
2481         smb2_util_close(tree1, h1);
2482         smb2_util_close(tree1, h);
2483
2484         smb2_deltree(tree1, BASEDIR);
2485         return ret;
2486 }
2487
2488 static bool test_smb2_oplock_batch22(struct torture_context *tctx,
2489                                      struct smb2_tree *tree1)
2490 {
2491         const char *fname = BASEDIR "\\test_batch22.dat";
2492         NTSTATUS status;
2493         bool ret = true;
2494         union smb_open io;
2495         struct smb2_handle h, h1, h2;
2496         struct timeval tv;
2497         int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
2498         int te;
2499
2500         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2501         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2502
2503         /* cleanup */
2504         smb2_util_unlink(tree1, fname);
2505
2506         tree1->session->transport->oplock.handler = torture_oplock_handler;
2507         tree1->session->transport->oplock.private_data = tree1;
2508         /*
2509           base ntcreatex parms
2510         */
2511         ZERO_STRUCT(io.smb2);
2512         io.generic.level = RAW_OPEN_SMB2;
2513         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2514         io.smb2.in.alloc_size = 0;
2515         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2516         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2517         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2518         io.smb2.in.create_options = 0;
2519         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2520         io.smb2.in.security_flags = 0;
2521         io.smb2.in.fname = fname;
2522
2523         /*
2524           with a batch oplock we get a break
2525         */
2526         torture_comment(tctx, "BATCH22: open with batch oplock\n");
2527         ZERO_STRUCT(break_info);
2528         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2529         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2530         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2531                 NTCREATEX_SHARE_ACCESS_WRITE|
2532                 NTCREATEX_SHARE_ACCESS_DELETE;
2533         status = smb2_create(tree1, tctx, &(io.smb2));
2534         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2535         h1 = io.smb2.out.file.handle;
2536         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2537
2538         torture_comment(tctx, "a 2nd open should succeed after the oplock "
2539                         "break timeout\n");
2540         tv = timeval_current();
2541         tree1->session->transport->oplock.handler =
2542                                 torture_oplock_handler_timeout;
2543         status = smb2_create(tree1, tctx, &(io.smb2));
2544         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2545         h2 = io.smb2.out.file.handle;
2546         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2547
2548         torture_wait_for_oplock_break(tctx);
2549         te = (int)timeval_elapsed(&tv);
2550         CHECK_RANGE(te, timeout - 1, timeout + 15);
2551         torture_comment(tctx, "waited %d seconds for oplock timeout\n", te);
2552
2553         CHECK_VAL(break_info.count, 1);
2554         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
2555         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2556         CHECK_VAL(break_info.failures, 0);
2557
2558         smb2_util_close(tree1, h1);
2559         smb2_util_close(tree1, h2);
2560         smb2_util_close(tree1, h);
2561
2562         smb2_deltree(tree1, BASEDIR);
2563         return ret;
2564 }
2565
2566 static bool test_smb2_oplock_batch23(struct torture_context *tctx,
2567                                      struct smb2_tree *tree1,
2568                                      struct smb2_tree *tree2)
2569 {
2570         const char *fname = BASEDIR "\\test_batch23.dat";
2571         NTSTATUS status;
2572         bool ret = true;
2573         union smb_open io;
2574         struct smb2_handle h, h1, h2, h3;
2575         struct smb2_tree *tree3 = NULL;
2576
2577         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2578         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2579
2580         /* cleanup */
2581         smb2_util_unlink(tree1, fname);
2582
2583         ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
2584         CHECK_VAL(ret, true);
2585
2586         tree1->session->transport->oplock.handler = torture_oplock_handler;
2587         tree1->session->transport->oplock.private_data = tree1;
2588
2589         tree2->session->transport->oplock.handler = torture_oplock_handler;
2590         tree2->session->transport->oplock.private_data = tree2;
2591
2592         tree3->session->transport->oplock.handler = torture_oplock_handler;
2593         tree3->session->transport->oplock.private_data = tree3;
2594
2595         /*
2596           base ntcreatex parms
2597         */
2598         ZERO_STRUCT(io.smb2);
2599         io.generic.level = RAW_OPEN_SMB2;
2600         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2601         io.smb2.in.alloc_size = 0;
2602         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2603         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2604         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2605         io.smb2.in.create_options = 0;
2606         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2607         io.smb2.in.security_flags = 0;
2608         io.smb2.in.fname = fname;
2609
2610         torture_comment(tctx, "BATCH23: an open and ask for a batch oplock\n");
2611         ZERO_STRUCT(break_info);
2612
2613         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
2614                                 SEC_RIGHTS_FILE_WRITE;
2615         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2616                                 NTCREATEX_SHARE_ACCESS_WRITE;
2617         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2618         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2619         status = smb2_create(tree1, tctx, &(io.smb2));
2620         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2621         h1 = io.smb2.out.file.handle;
2622         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2623
2624         ZERO_STRUCT(break_info);
2625
2626         torture_comment(tctx, "a 2nd open without level2 oplock support "
2627                         "should generate a break to level2\n");
2628         status = smb2_create(tree3, tctx, &(io.smb2));
2629         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2630         h3 = io.smb2.out.file.handle;
2631
2632         torture_wait_for_oplock_break(tctx);
2633         CHECK_VAL(break_info.count, 1);
2634         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
2635         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2636         CHECK_VAL(break_info.failures, 0);
2637
2638         ZERO_STRUCT(break_info);
2639
2640         torture_comment(tctx, "a 3rd open with level2 oplock support should "
2641                         "not generate a break\n");
2642         status = smb2_create(tree2, tctx, &(io.smb2));
2643         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2644         h2 = io.smb2.out.file.handle;
2645         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2646
2647         torture_wait_for_oplock_break(tctx);
2648         CHECK_VAL(break_info.count, 0);
2649
2650         smb2_util_close(tree1, h1);
2651         smb2_util_close(tree2, h2);
2652         smb2_util_close(tree3, h3);
2653         smb2_util_close(tree1, h);
2654
2655         smb2_deltree(tree1, BASEDIR);
2656         return ret;
2657 }
2658
2659 static bool test_smb2_oplock_batch24(struct torture_context *tctx,
2660                                      struct smb2_tree *tree1,
2661                                      struct smb2_tree *tree2)
2662 {
2663         const char *fname = BASEDIR "\\test_batch24.dat";
2664         NTSTATUS status;
2665         bool ret = true;
2666         union smb_open io;
2667         struct smb2_handle h, h1, h2;
2668         struct smb2_tree *tree3 = NULL;
2669
2670         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2671         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2672
2673         /* cleanup */
2674         smb2_util_unlink(tree1, fname);
2675
2676         ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
2677         CHECK_VAL(ret, true);
2678
2679         tree1->session->transport->oplock.handler = torture_oplock_handler;
2680         tree1->session->transport->oplock.private_data = tree1;
2681
2682         tree2->session->transport->oplock.handler = torture_oplock_handler;
2683         tree2->session->transport->oplock.private_data = tree2;
2684
2685         tree3->session->transport->oplock.handler = torture_oplock_handler;
2686         tree3->session->transport->oplock.private_data = tree3;
2687
2688         /*
2689           base ntcreatex parms
2690         */
2691         ZERO_STRUCT(io.smb2);
2692         io.generic.level = RAW_OPEN_SMB2;
2693         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2694         io.smb2.in.alloc_size = 0;
2695         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2696         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2697         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2698         io.smb2.in.create_options = 0;
2699         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2700         io.smb2.in.security_flags = 0;
2701         io.smb2.in.fname = fname;
2702
2703         torture_comment(tctx, "BATCH24: a open without level support and "
2704                         "ask for a batch oplock\n");
2705         ZERO_STRUCT(break_info);
2706
2707         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
2708                                 SEC_RIGHTS_FILE_WRITE;
2709         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2710                                 NTCREATEX_SHARE_ACCESS_WRITE;
2711         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2712         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2713
2714         status = smb2_create(tree3, tctx, &(io.smb2));
2715         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2716         h2 = io.smb2.out.file.handle;
2717         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2718
2719         ZERO_STRUCT(break_info);
2720
2721         torture_comment(tctx, "a 2nd open with level2 oplock support should "
2722                         "generate a break\n");
2723         status = smb2_create(tree2, tctx, &(io.smb2));
2724         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2725         h1 = io.smb2.out.file.handle;
2726         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2727
2728         torture_wait_for_oplock_break(tctx);
2729         CHECK_VAL(break_info.count, 1);
2730         CHECK_VAL(break_info.handle.data[0], h2.data[0]);
2731         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2732         CHECK_VAL(break_info.failures, 0);
2733
2734         smb2_util_close(tree3, h2);
2735         smb2_util_close(tree2, h1);
2736         smb2_util_close(tree1, h);
2737
2738         smb2_deltree(tree1, BASEDIR);
2739         return ret;
2740 }
2741
2742 static bool test_smb2_oplock_batch25(struct torture_context *tctx,
2743                                      struct smb2_tree *tree1)
2744 {
2745         const char *fname = BASEDIR "\\test_batch25.dat";
2746         NTSTATUS status;
2747         bool ret = true;
2748         union smb_open io;
2749         struct smb2_handle h, h1;
2750
2751         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2752         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2753
2754         /* cleanup */
2755         smb2_util_unlink(tree1, fname);
2756
2757         tree1->session->transport->oplock.handler = torture_oplock_handler;
2758         tree1->session->transport->oplock.private_data = tree1;
2759
2760         /*
2761           base ntcreatex parms
2762         */
2763         ZERO_STRUCT(io.smb2);
2764         io.generic.level = RAW_OPEN_SMB2;
2765         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2766         io.smb2.in.alloc_size = 0;
2767         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2768         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2769         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2770         io.smb2.in.create_options = 0;
2771         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2772         io.smb2.in.security_flags = 0;
2773         io.smb2.in.fname = fname;
2774
2775         torture_comment(tctx, "BATCH25: open a file with an batch oplock "
2776                         "(share mode: none)\n");
2777
2778         ZERO_STRUCT(break_info);
2779         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2780         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2781
2782         status = smb2_create(tree1, tctx, &(io.smb2));
2783         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2784         h1 = io.smb2.out.file.handle;
2785         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2786
2787         torture_comment(tctx, "changing the file attribute info should trigger "
2788                         "a break and a violation\n");
2789
2790         status = smb2_util_setatr(tree1, fname, FILE_ATTRIBUTE_HIDDEN);
2791         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2792                                       "Incorrect status");
2793
2794         torture_wait_for_oplock_break(tctx);
2795         CHECK_VAL(break_info.count, 1);
2796
2797         smb2_util_close(tree1, h1);
2798         smb2_util_close(tree1, h);
2799
2800         smb2_deltree(tree1, fname);
2801         return ret;
2802 }
2803
2804 static bool test_smb2_oplock_batch26(struct torture_context *tctx,
2805                                         struct smb2_tree *tree1)
2806 {
2807
2808         NTSTATUS status;
2809         bool ret = true;
2810         union smb_open io;
2811         struct smb2_handle h, h1, h2, h3;
2812         const char *fname_base = BASEDIR "\\test_oplock.txt";
2813         const char *stream = "Stream One:$DATA";
2814         const char *fname_stream;
2815
2816         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2817         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2818
2819         tree1->session->transport->oplock.handler = torture_oplock_handler;
2820         tree1->session->transport->oplock.private_data = tree1;
2821
2822         fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
2823
2824         /*
2825           base ntcreatex parms
2826         */
2827         ZERO_STRUCT(io.smb2);
2828         io.generic.level = RAW_OPEN_SMB2;
2829         io.smb2.in.desired_access = 0x120089;
2830         io.smb2.in.alloc_size = 0;
2831         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2832         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_DELETE |
2833                                   NTCREATEX_SHARE_ACCESS_WRITE;
2834         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2835         io.smb2.in.create_options = 0;
2836         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2837         io.smb2.in.security_flags = 0;
2838         io.smb2.in.fname = fname_base;
2839
2840         /*
2841           Open base file with a batch oplock.
2842         */
2843         torture_comment(tctx, "Open the base file with batch oplock\n");
2844         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2845         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2846
2847         status = smb2_create(tree1, tctx, &(io.smb2));
2848         torture_assert_ntstatus_ok(tctx, status, "Error opening base file");
2849         h1 = io.smb2.out.file.handle;
2850         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2851
2852         torture_comment(tctx, "Got batch oplock on base file\n");
2853
2854         torture_comment(tctx, "Opening stream file with batch oplock..\n");
2855
2856         io.smb2.in.fname = fname_stream;
2857
2858         status = smb2_create(tree1, tctx, &(io.smb2));
2859         torture_assert_ntstatus_ok(tctx, status, "Error opening stream file");
2860         h2 = io.smb2.out.file.handle;
2861         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2862
2863         torture_comment(tctx, "Got batch oplock on stream file\n");
2864
2865         torture_comment(tctx, "Open base file again with batch oplock\n");
2866
2867         io.smb2.in.fname = fname_base;
2868
2869         status = smb2_create(tree1, tctx, &(io.smb2));
2870         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2871         h3 = io.smb2.out.file.handle;
2872         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2873
2874         smb2_util_close(tree1, h1);
2875         smb2_util_close(tree1, h2);
2876         smb2_util_close(tree1, h3);
2877         smb2_util_close(tree1, h);
2878 done:
2879         smb2_deltree(tree1, BASEDIR);
2880         return ret;
2881
2882 }
2883
2884 /* Test how oplocks work on streams. */
2885 static bool test_raw_oplock_stream1(struct torture_context *tctx,
2886                                     struct smb2_tree *tree1,
2887                                     struct smb2_tree *tree2)
2888 {
2889         NTSTATUS status;
2890         union smb_open io;
2891         const char *fname_base = BASEDIR "\\test_stream1.txt";
2892         const char *fname_stream, *fname_default_stream;
2893         const char *default_stream = "::$DATA";
2894         const char *stream = "Stream One:$DATA";
2895         bool ret = true;
2896         struct smb2_handle h, h_base, h_stream;
2897         int i;
2898
2899 #define NSTREAM_OPLOCK_RESULTS 8
2900         struct {
2901                 const char **fname;
2902                 bool open_base_file;
2903                 uint32_t oplock_req;
2904                 uint32_t oplock_granted;
2905         } stream_oplock_results[NSTREAM_OPLOCK_RESULTS] = {
2906                 /* Request oplock on stream without the base file open. */
2907                 {&fname_stream, false, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
2908                 {&fname_default_stream, false, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
2909                 {&fname_stream, false, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
2910                 {&fname_default_stream, false,  SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
2911
2912                 /* Request oplock on stream with the base file open. */
2913                 {&fname_stream, true, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
2914                 {&fname_default_stream, true, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_II},
2915                 {&fname_stream, true, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
2916                 {&fname_default_stream, true,  SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_II},
2917         };
2918
2919         fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
2920         fname_default_stream = talloc_asprintf(tctx, "%s%s", fname_base,
2921                                                default_stream);
2922
2923         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2924         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2925
2926         /* Initialize handles to "closed".  Using -1 in the first 64-bytes
2927          * as the sentry for this */
2928         h_stream.data[0] = -1;
2929
2930         /* cleanup */
2931         smb2_util_unlink(tree1, fname_base);
2932
2933         tree1->session->transport->oplock.handler = torture_oplock_handler;
2934         tree1->session->transport->oplock.private_data = tree1;
2935
2936         tree2->session->transport->oplock.handler = torture_oplock_handler;
2937         tree2->session->transport->oplock.private_data = tree2;
2938
2939         /* Setup generic open parameters. */
2940         ZERO_STRUCT(io.smb2);
2941         io.generic.level = RAW_OPEN_SMB2;
2942         io.smb2.in.desired_access = (SEC_FILE_READ_DATA |
2943                                      SEC_FILE_WRITE_DATA |
2944                                      SEC_FILE_APPEND_DATA |
2945                                      SEC_STD_READ_CONTROL);
2946         io.smb2.in.alloc_size = 0;
2947         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2948         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2949                                   NTCREATEX_SHARE_ACCESS_WRITE;
2950         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2951         io.smb2.in.create_options = 0;
2952         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2953         io.smb2.in.security_flags = 0;
2954
2955         /* Create the file with a stream */
2956         io.smb2.in.fname = fname_stream;
2957         io.smb2.in.create_flags = 0;
2958         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2959         status = smb2_create(tree1, tctx, &(io.smb2));
2960         torture_assert_ntstatus_ok(tctx, status, "Error creating file");
2961         smb2_util_close(tree1, io.smb2.out.file.handle);
2962
2963         /* Change the disposition to open now that the file has been created. */
2964         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
2965
2966         /* Try some permutations of taking oplocks on streams. */
2967         for (i = 0; i < NSTREAM_OPLOCK_RESULTS; i++) {
2968                 const char *fname = *stream_oplock_results[i].fname;
2969                 bool open_base_file = stream_oplock_results[i].open_base_file;
2970                 uint32_t oplock_req = stream_oplock_results[i].oplock_req;
2971                 uint32_t oplock_granted =
2972                     stream_oplock_results[i].oplock_granted;
2973
2974                 if (open_base_file) {
2975                         torture_comment(tctx, "Opening base file: %s with "
2976                             "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
2977                         io.smb2.in.fname = fname_base;
2978                         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2979                         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2980                         status = smb2_create(tree2, tctx, &(io.smb2));
2981                         torture_assert_ntstatus_ok(tctx, status,
2982                             "Error opening file");
2983                         CHECK_VAL(io.smb2.out.oplock_level,
2984                             SMB2_OPLOCK_LEVEL_BATCH);
2985                         h_base = io.smb2.out.file.handle;
2986                 }
2987
2988                 torture_comment(tctx, "%d: Opening stream: %s with %d\n", i,
2989                     fname, oplock_req);
2990                 io.smb2.in.fname = fname;
2991                 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2992                 io.smb2.in.oplock_level = oplock_req;
2993
2994                 /* Do the open with the desired oplock on the stream. */
2995                 status = smb2_create(tree1, tctx, &(io.smb2));
2996                 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
2997                 CHECK_VAL(io.smb2.out.oplock_level, oplock_granted);
2998                 smb2_util_close(tree1, io.smb2.out.file.handle);
2999
3000                 /* Cleanup the base file if it was opened. */
3001                 if (open_base_file)
3002                         smb2_util_close(tree2, h_base);
3003         }
3004
3005         /* Open the stream with an exclusive oplock. */
3006         torture_comment(tctx, "Opening stream: %s with %d\n",
3007             fname_stream, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
3008         io.smb2.in.fname = fname_stream;
3009         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3010         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
3011         status = smb2_create(tree1, tctx, &(io.smb2));
3012         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
3013         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
3014         h_stream = io.smb2.out.file.handle;
3015
3016         /* Open the base file and see if it contends. */
3017         ZERO_STRUCT(break_info);
3018         torture_comment(tctx, "Opening base file: %s with %d\n",
3019             fname_base, SMB2_OPLOCK_LEVEL_BATCH);
3020         io.smb2.in.fname = fname_base;
3021         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3022         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3023         status = smb2_create(tree2, tctx, &(io.smb2));
3024         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
3025         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3026         smb2_util_close(tree2, io.smb2.out.file.handle);
3027
3028         torture_wait_for_oplock_break(tctx);
3029         CHECK_VAL(break_info.count, 0);
3030         CHECK_VAL(break_info.failures, 0);
3031
3032         /* Open the stream again to see if it contends. */
3033         ZERO_STRUCT(break_info);
3034         torture_comment(tctx, "Opening stream again: %s with "
3035             "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
3036         io.smb2.in.fname = fname_stream;
3037         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3038         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
3039         status = smb2_create(tree2, tctx, &(io.smb2));
3040         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
3041         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
3042         smb2_util_close(tree2, io.smb2.out.file.handle);
3043
3044         torture_wait_for_oplock_break(tctx);
3045         CHECK_VAL(break_info.count, 1);
3046         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3047         CHECK_VAL(break_info.failures, 0);
3048
3049         /* Close the stream. */
3050         if (h_stream.data[0] != -1) {
3051                 smb2_util_close(tree1, h_stream);
3052         }
3053
3054         smb2_util_close(tree1, h);
3055
3056         smb2_deltree(tree1, BASEDIR);
3057         return ret;
3058 }
3059
3060 static bool test_smb2_oplock_doc(struct torture_context *tctx, struct smb2_tree *tree,
3061                                  struct smb2_tree *tree2)
3062 {
3063         const char *fname = BASEDIR "\\test_oplock_doc.dat";
3064         NTSTATUS status;
3065         bool ret = true;
3066         union smb_open io;
3067         struct smb2_handle h, h1;
3068         union smb_setfileinfo sfinfo;
3069
3070         status = torture_smb2_testdir(tree, BASEDIR, &h);
3071         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3072         smb2_util_close(tree, h);
3073
3074         /* cleanup */
3075         smb2_util_unlink(tree, fname);
3076         tree->session->transport->oplock.handler = torture_oplock_handler;
3077         tree->session->transport->oplock.private_data = tree;
3078
3079         /*
3080           base ntcreatex parms
3081         */
3082         ZERO_STRUCT(io.smb2);
3083         io.generic.level = RAW_OPEN_SMB2;
3084         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3085         io.smb2.in.alloc_size = 0;
3086         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3087         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
3088                 NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
3089         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3090         io.smb2.in.create_options = 0;
3091         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3092         io.smb2.in.security_flags = 0;
3093         io.smb2.in.fname = fname;
3094
3095         torture_comment(tctx, "open a file with a batch oplock\n");
3096         ZERO_STRUCT(break_info);
3097         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3098         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3099
3100         status = smb2_create(tree, tctx, &(io.smb2));
3101         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3102         h1 = io.smb2.out.file.handle;
3103         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3104
3105         torture_comment(tctx, "Set delete on close\n");
3106         ZERO_STRUCT(sfinfo);
3107         sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3108         sfinfo.generic.in.file.handle = h1;
3109         sfinfo.disposition_info.in.delete_on_close = 1;
3110         status = smb2_setinfo_file(tree, &sfinfo);
3111         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3112
3113         torture_comment(tctx, "2nd open should not break and get "
3114                         "DELETE_PENDING\n");
3115         ZERO_STRUCT(break_info);
3116         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
3117         io.smb2.in.create_options = 0;
3118         io.smb2.in.desired_access = SEC_FILE_READ_DATA;
3119         status = smb2_create(tree2, tctx, &io.smb2);
3120         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DELETE_PENDING,
3121                                       "Incorrect status");
3122         CHECK_VAL(break_info.count, 0);
3123
3124         smb2_util_close(tree, h1);
3125
3126         smb2_util_unlink(tree, fname);
3127         smb2_deltree(tree, BASEDIR);
3128         return ret;
3129 }
3130
3131 /* Open a file with a batch oplock, then open it again from a second client
3132  * requesting no oplock. Having two open file handles should break our own
3133  * oplock during BRL acquisition.
3134  */
3135 static bool test_smb2_oplock_brl1(struct torture_context *tctx,
3136                                 struct smb2_tree *tree1,
3137                                 struct smb2_tree *tree2)
3138 {
3139         const char *fname = BASEDIR "\\test_batch_brl.dat";
3140         /*int fname, f;*/
3141         bool ret = true;
3142         uint8_t buf[1000];
3143         union smb_open io;
3144         NTSTATUS status;
3145         struct smb2_lock lck;
3146         struct smb2_lock_element lock[1];
3147         struct smb2_handle h, h1, h2;
3148
3149         status = torture_smb2_testdir(tree1, BASEDIR, &h);
3150         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3151
3152         /* cleanup */
3153         smb2_util_unlink(tree1, fname);
3154
3155         tree1->session->transport->oplock.handler =
3156             torture_oplock_handler_two_notifications;
3157         tree1->session->transport->oplock.private_data = tree1;
3158
3159         /*
3160           base ntcreatex parms
3161         */
3162         ZERO_STRUCT(io.smb2);
3163         io.generic.level = RAW_OPEN_SMB2;
3164         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3165                                     SEC_RIGHTS_FILE_WRITE;
3166         io.smb2.in.alloc_size = 0;
3167         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3168         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3169                                   NTCREATEX_SHARE_ACCESS_WRITE;
3170         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3171         io.smb2.in.create_options = 0;
3172         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3173         io.smb2.in.security_flags = 0;
3174         io.smb2.in.fname = fname;
3175
3176         /*
3177           with a batch oplock we get a break
3178         */
3179         torture_comment(tctx, "open with batch oplock\n");
3180         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3181         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3182
3183         status = smb2_create(tree1, tctx, &(io.smb2));
3184         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3185         h1 = io.smb2.out.file.handle;
3186         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3187
3188         /* create a file with bogus data */
3189         memset(buf, 0, sizeof(buf));
3190
3191         status = smb2_util_write(tree1, h1,buf, 0, sizeof(buf));
3192         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3193                 torture_comment(tctx, "Failed to create file\n");
3194                 ret = false;
3195                 goto done;
3196         }
3197
3198         torture_comment(tctx, "a 2nd open should give a break\n");
3199         ZERO_STRUCT(break_info);
3200
3201         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3202         io.smb2.in.oplock_level = 0;
3203         status = smb2_create(tree2, tctx, &(io.smb2));
3204         h2 = io.smb2.out.file.handle;
3205         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3206
3207         torture_wait_for_oplock_break(tctx);
3208         CHECK_VAL(break_info.count, 1);
3209         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
3210         CHECK_VAL(break_info.failures, 0);
3211         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3212
3213         ZERO_STRUCT(break_info);
3214
3215         torture_comment(tctx, "a self BRL acquisition should break to none\n");
3216         lock[0].offset = 0;
3217         lock[0].length = 4;
3218         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3219                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3220
3221         ZERO_STRUCT(lck);
3222         lck.in.file.handle = h1;
3223         lck.in.locks = &lock[0];
3224         lck.in.lock_count = 1;
3225         status = smb2_lock(tree1, &lck);
3226         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3227
3228         torture_wait_for_oplock_break(tctx);
3229         CHECK_VAL(break_info.count, 1);
3230         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
3231         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3232         CHECK_VAL(break_info.failures, 0);
3233
3234         /* expect no oplock break */
3235         ZERO_STRUCT(break_info);
3236         lock[0].offset = 2;
3237         status = smb2_lock(tree1, &lck);
3238         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3239                                       "Incorrect status");
3240
3241         torture_wait_for_oplock_break(tctx);
3242         CHECK_VAL(break_info.count, 0);
3243         CHECK_VAL(break_info.level, 0);
3244         CHECK_VAL(break_info.failures, 0);
3245
3246         smb2_util_close(tree1, h1);
3247         smb2_util_close(tree2, h2);
3248         smb2_util_close(tree1, h);
3249
3250 done:
3251         smb2_deltree(tree1, BASEDIR);
3252         return ret;
3253
3254 }
3255
3256 /* Open a file with a batch oplock on one tree and then acquire a brl.
3257  * We should not contend our own oplock.
3258  */
3259 static bool test_smb2_oplock_brl2(struct torture_context *tctx, struct smb2_tree *tree1)
3260 {
3261         const char *fname = BASEDIR "\\test_batch_brl.dat";
3262         /*int fname, f;*/
3263         bool ret = true;
3264         uint8_t buf[1000];
3265         union smb_open io;
3266         NTSTATUS status;
3267         struct smb2_handle h, h1;
3268         struct smb2_lock lck;
3269         struct smb2_lock_element lock[1];
3270
3271         status = torture_smb2_testdir(tree1, BASEDIR, &h);
3272         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3273
3274         /* cleanup */
3275         smb2_util_unlink(tree1, fname);
3276
3277         tree1->session->transport->oplock.handler = torture_oplock_handler;
3278         tree1->session->transport->oplock.private_data = tree1;
3279
3280         /*
3281           base ntcreatex parms
3282         */
3283         ZERO_STRUCT(io.smb2);
3284         io.generic.level = RAW_OPEN_SMB2;
3285         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3286                                     SEC_RIGHTS_FILE_WRITE;
3287         io.smb2.in.alloc_size = 0;
3288         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3289         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3290                                   NTCREATEX_SHARE_ACCESS_WRITE;
3291         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3292         io.smb2.in.create_options = 0;
3293         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3294         io.smb2.in.security_flags = 0;
3295         io.smb2.in.fname = fname;
3296
3297         /*
3298           with a batch oplock we get a break
3299         */
3300         torture_comment(tctx, "open with batch oplock\n");
3301         ZERO_STRUCT(break_info);
3302         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3303         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3304
3305         status = smb2_create(tree1, tctx, &(io.smb2));
3306         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3307         h1 = io.smb2.out.file.handle;
3308         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3309
3310         /* create a file with bogus data */
3311         memset(buf, 0, sizeof(buf));
3312
3313         status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
3314         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3315                 torture_comment(tctx, "Failed to create file\n");
3316                 ret = false;
3317                 goto done;
3318         }
3319
3320         ZERO_STRUCT(break_info);
3321
3322         torture_comment(tctx, "a self BRL acquisition should not break to "
3323                         "none\n");
3324
3325         lock[0].offset = 0;
3326         lock[0].length = 4;
3327         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3328                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3329
3330         ZERO_STRUCT(lck);
3331         lck.in.file.handle = h1;
3332         lck.in.locks = &lock[0];
3333         lck.in.lock_count = 1;
3334         status = smb2_lock(tree1, &lck);
3335         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3336
3337         lock[0].offset = 2;
3338         status = smb2_lock(tree1, &lck);
3339         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3340                                       "Incorrect status");
3341
3342         /* With one file handle open a BRL should not contend our oplock.
3343          * Thus, no oplock break will be received and the entire break_info
3344          * struct will be 0 */
3345         torture_wait_for_oplock_break(tctx);
3346         CHECK_VAL(break_info.count, 0);
3347         CHECK_VAL(break_info.level, 0);
3348         CHECK_VAL(break_info.failures, 0);
3349
3350         smb2_util_close(tree1, h1);
3351         smb2_util_close(tree1, h);
3352
3353 done:
3354         smb2_deltree(tree1, BASEDIR);
3355         return ret;
3356 }
3357
3358 /* Open a file with a batch oplock twice from one tree and then acquire a
3359  * brl. BRL acquisition should break our own oplock.
3360  */
3361 static bool test_smb2_oplock_brl3(struct torture_context *tctx, struct smb2_tree *tree1)
3362 {
3363         const char *fname = BASEDIR "\\test_batch_brl.dat";
3364         bool ret = true;
3365         uint8_t buf[1000];
3366         union smb_open io;
3367         NTSTATUS status;
3368         struct smb2_handle h, h1, h2;
3369         struct smb2_lock lck;
3370         struct smb2_lock_element lock[1];
3371
3372         status = torture_smb2_testdir(tree1, BASEDIR, &h);
3373         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3374
3375         /* cleanup */
3376         smb2_util_unlink(tree1, fname);
3377         tree1->session->transport->oplock.handler =
3378             torture_oplock_handler_two_notifications;
3379         tree1->session->transport->oplock.private_data = tree1;
3380
3381         /*
3382           base ntcreatex parms
3383         */
3384         ZERO_STRUCT(io.smb2);
3385         io.generic.level = RAW_OPEN_SMB2;
3386         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3387                                     SEC_RIGHTS_FILE_WRITE;
3388         io.smb2.in.alloc_size = 0;
3389         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3390         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3391                                   NTCREATEX_SHARE_ACCESS_WRITE;
3392         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3393         io.smb2.in.create_options = 0;
3394         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3395         io.smb2.in.security_flags = 0;
3396         io.smb2.in.fname = fname;
3397
3398         /*
3399           with a batch oplock we get a break
3400         */
3401         torture_comment(tctx, "open with batch oplock\n");
3402         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3403         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3404
3405         status = smb2_create(tree1, tctx, &(io.smb2));
3406         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3407         h1 = io.smb2.out.file.handle;
3408         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3409
3410         /* create a file with bogus data */
3411         memset(buf, 0, sizeof(buf));
3412         status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
3413
3414         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3415                 torture_comment(tctx, "Failed to create file\n");
3416                 ret = false;
3417                 goto done;
3418         }
3419
3420         torture_comment(tctx, "a 2nd open should give a break\n");
3421         ZERO_STRUCT(break_info);
3422
3423         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3424         io.smb2.in.oplock_level = 0;
3425         status = smb2_create(tree1, tctx, &(io.smb2));
3426         h2 = io.smb2.out.file.handle;
3427         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3428         CHECK_VAL(break_info.count, 1);
3429         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
3430         CHECK_VAL(break_info.failures, 0);
3431         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3432
3433         ZERO_STRUCT(break_info);
3434
3435         torture_comment(tctx, "a self BRL acquisition should break to none\n");
3436
3437         lock[0].offset = 0;
3438         lock[0].length = 4;
3439         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3440                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3441
3442         ZERO_STRUCT(lck);
3443         lck.in.file.handle = h1;
3444         lck.in.locks = &lock[0];
3445         lck.in.lock_count = 1;
3446         status = smb2_lock(tree1, &lck);
3447         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3448
3449         torture_wait_for_oplock_break(tctx);
3450         CHECK_VAL(break_info.count, 1);
3451         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
3452         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3453         CHECK_VAL(break_info.failures, 0);
3454
3455         /* expect no oplock break */
3456         ZERO_STRUCT(break_info);
3457         lock[0].offset = 2;
3458         status = smb2_lock(tree1, &lck);
3459         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3460                                       "Incorrect status");
3461
3462         torture_wait_for_oplock_break(tctx);
3463         CHECK_VAL(break_info.count, 0);
3464         CHECK_VAL(break_info.level, 0);
3465         CHECK_VAL(break_info.failures, 0);
3466
3467         smb2_util_close(tree1, h1);
3468         smb2_util_close(tree1, h2);
3469         smb2_util_close(tree1, h);
3470
3471 done:
3472         smb2_deltree(tree1, BASEDIR);
3473         return ret;
3474
3475 }
3476
3477 /* Starting the SMB2 specific oplock tests at 500 so we can keep the SMB1
3478  * tests in sync with an identically numbered SMB2 test */
3479
3480 /* Test whether the server correctly returns an error when we send
3481  * a response to a levelII to none oplock notification. */
3482 static bool test_smb2_oplock_levelII500(struct torture_context *tctx,
3483                                       struct smb2_tree *tree1)
3484 {
3485         const char *fname = BASEDIR "\\test_levelII500.dat";
3486         NTSTATUS status;
3487         bool ret = true;
3488         union smb_open io;
3489         struct smb2_handle h, h1;
3490         char c = 0;
3491
3492         status = torture_smb2_testdir(tree1, BASEDIR, &h);
3493         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3494
3495         /* cleanup */
3496         smb2_util_unlink(tree1, fname);
3497
3498         tree1->session->transport->oplock.handler = torture_oplock_handler;
3499         tree1->session->transport->oplock.private_data = tree1;
3500
3501         /*
3502           base ntcreatex parms
3503         */
3504         ZERO_STRUCT(io.smb2);
3505         io.generic.level = RAW_OPEN_SMB2;
3506         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3507         io.smb2.in.alloc_size = 0;
3508         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3509         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3510         io.smb2.in.create_options = 0;
3511         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3512         io.smb2.in.security_flags = 0;
3513         io.smb2.in.fname = fname;
3514
3515         torture_comment(tctx, "LEVELII500: acknowledging a break from II to "
3516                         "none should return an error\n");
3517         ZERO_STRUCT(break_info);
3518
3519         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3520                                 SEC_RIGHTS_FILE_WRITE;
3521         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3522                                 NTCREATEX_SHARE_ACCESS_WRITE;
3523         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3524         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
3525         status = smb2_create(tree1, tctx, &(io.smb2));
3526         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3527         h1 = io.smb2.out.file.handle;
3528         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
3529
3530         ZERO_STRUCT(break_info);
3531
3532         torture_comment(tctx, "write should trigger a break to none and when "
3533                         "we reply, an oplock break failure\n");
3534         smb2_util_write(tree1, h1, &c, 0, 1);
3535
3536         /* Wait several times to receive both the break notification, and the
3537          * NT_STATUS_INVALID_OPLOCK_PROTOCOL error in the break response */
3538         torture_wait_for_oplock_break(tctx);
3539         torture_wait_for_oplock_break(tctx);
3540         torture_wait_for_oplock_break(tctx);
3541         torture_wait_for_oplock_break(tctx);
3542
3543         /* There appears to be a race condition in W2K8 and W2K8R2 where
3544          * sometimes the server will happily reply to our break response with
3545          * NT_STATUS_OK, and sometimes it will return the OPLOCK_PROTOCOL
3546          * error.  As the MS-SMB2 doc states that a client should not reply to
3547          * a level2 to none break notification, I'm leaving the protocol error
3548          * as the expected behavior. */
3549         CHECK_VAL(break_info.count, 1);
3550         CHECK_VAL(break_info.level, 0);
3551         CHECK_VAL(break_info.failures, 1);
3552         torture_assert_ntstatus_equal(tctx, break_info.failure_status,
3553                                       NT_STATUS_INVALID_OPLOCK_PROTOCOL,
3554                                       "Incorrect status");
3555
3556         smb2_util_close(tree1, h1);
3557         smb2_util_close(tree1, h);
3558
3559         smb2_deltree(tree1, BASEDIR);
3560         return ret;
3561 }
3562
3563 /*
3564  * Test a double-break. Open a file with exclusive. Send off a second open
3565  * request with OPEN_IF, triggering a break to level2. This should respond
3566  * with level2. Before replying to the break to level2, fire off a third open
3567  * with OVERWRITE_IF. The expected sequence would be that the 3rd opener gets
3568  * a level2 immediately triggered by a break to none, but that seems not the
3569  * case. Still investigating what the right behaviour should be.
3570  */
3571
3572 struct levelII501_state {
3573         struct torture_context *tctx;
3574         struct smb2_tree *tree1;
3575         struct smb2_tree *tree2;
3576         struct smb2_tree *tree3;
3577         struct smb2_handle h;
3578         struct smb2_handle h1;
3579         union smb_open io;
3580
3581         struct smb2_handle break_handle;
3582         uint8_t break_to;
3583         struct smb2_break br;
3584
3585         bool done;
3586 };
3587
3588 static bool torture_oplock_break_delay(struct smb2_transport *transport,
3589                                        const struct smb2_handle *handle,
3590                                        uint8_t level, void *private_data);
3591 static void levelII501_break_done(struct smb2_request *req);
3592 static void levelII501_open1_done(struct smb2_request *req);
3593 static void levelII501_open2_done(struct smb2_request *req);
3594 static void levelII501_2ndopen_cb(struct tevent_context *ev,
3595                                   struct tevent_timer *te,
3596                                   struct timeval current_time,
3597                                   void *private_data);
3598 static void levelII501_break_timeout_cb(struct tevent_context *ev,
3599                                         struct tevent_timer *te,
3600                                         struct timeval current_time,
3601                                         void *private_data);
3602 static void levelII501_timeout_cb(struct tevent_context *ev,
3603                                   struct tevent_timer *te,
3604                                   struct timeval current_time,
3605                                   void *private_data);
3606
3607 static bool test_smb2_oplock_levelII501(struct torture_context *tctx,
3608                                         struct smb2_tree *tree1,
3609                                         struct smb2_tree *tree2)
3610 {
3611         const char *fname = BASEDIR "\\test_levelII501.dat";
3612         NTSTATUS status;
3613         bool ret = true;
3614         struct levelII501_state *state;
3615         struct smb2_request *req;
3616         struct tevent_timer *te;
3617
3618         state = talloc(tctx, struct levelII501_state);
3619         state->tctx = tctx;
3620         state->done = false;
3621         state->tree1 = tree1;
3622         state->tree2 = tree2;
3623
3624         if (!torture_smb2_connection(tctx, &state->tree3)) {
3625                 torture_fail(tctx, "Establishing SMB2 connection failed\n");
3626                 return false;
3627         }
3628
3629         status = torture_smb2_testdir(tree1, BASEDIR, &state->h);
3630         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3631
3632         /* cleanup */
3633         smb2_util_unlink(tree1, fname);
3634
3635         /*
3636           base ntcreatex parms
3637         */
3638         ZERO_STRUCT(state->io.smb2);
3639         state->io.generic.level = RAW_OPEN_SMB2;
3640         state->io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3641         state->io.smb2.in.alloc_size = 0;
3642         state->io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3643         state->io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3644         state->io.smb2.in.create_options = 0;
3645         state->io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3646         state->io.smb2.in.security_flags = 0;
3647         state->io.smb2.in.fname = fname;
3648
3649         torture_comment(tctx, "LEVELII501: Test double break sequence\n");
3650         ZERO_STRUCT(break_info);
3651
3652         state->io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3653                                 SEC_RIGHTS_FILE_WRITE;
3654         state->io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3655                                 NTCREATEX_SHARE_ACCESS_WRITE;
3656         state->io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3657         state->io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
3658
3659         tree1->session->transport->oplock.handler = torture_oplock_break_delay;
3660         tree1->session->transport->oplock.private_data = state;
3661
3662         status = smb2_create(tree1, tctx, &(state->io.smb2));
3663         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3664         state->h1 = state->io.smb2.out.file.handle;
3665         CHECK_VAL(state->io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
3666
3667         /*
3668          * Trigger a break to level2
3669          */
3670
3671         req = smb2_create_send(tree2, &state->io.smb2);
3672         req->async.fn = levelII501_open1_done;
3673         req->async.private_data = state;
3674
3675         te = tevent_add_timer(
3676                 tctx->ev, tctx, tevent_timeval_current_ofs(0, 200000),
3677                 levelII501_2ndopen_cb, state);
3678         torture_assert(tctx, te != NULL, "tevent_add_timer failed\n");
3679
3680         te = tevent_add_timer(
3681                 tctx->ev, tctx, tevent_timeval_current_ofs(2, 0),
3682                 levelII501_timeout_cb, state);
3683         torture_assert(tctx, te != NULL, "tevent_add_timer failed\n");
3684
3685         while (!state->done) {
3686                 if (tevent_loop_once(tctx->ev) != 0) {
3687                         torture_comment(tctx, "tevent_loop_once failed\n");
3688                 }
3689         }
3690
3691         return ret;
3692 }
3693
3694 /*
3695  * Fire off a second open after a little timeout
3696  */
3697
3698 static void levelII501_2ndopen_cb(struct tevent_context *ev,
3699                                   struct tevent_timer *te,
3700                                   struct timeval current_time,
3701                                   void *private_data)
3702 {
3703         struct levelII501_state *state = talloc_get_type_abort(
3704                 private_data, struct levelII501_state);
3705         struct smb2_request *req;
3706
3707         state->io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
3708         req = smb2_create_send(state->tree3, &state->io.smb2);
3709         req->async.fn = levelII501_open2_done;
3710         req->async.private_data = state;
3711 }
3712
3713 /*
3714  * Postpone the break response by 500 msec
3715  */
3716 static bool torture_oplock_break_delay(struct smb2_transport *transport,
3717                                        const struct smb2_handle *handle,
3718                                        uint8_t level, void *private_data)
3719 {
3720         struct levelII501_state *state = talloc_get_type_abort(
3721                 private_data, struct levelII501_state);
3722         const char *name;
3723         struct tevent_timer *te;
3724
3725         break_info.handle       = *handle;
3726         break_info.level        = level;
3727         break_info.count++;
3728
3729         state->break_handle = *handle;
3730         state->break_to = level;
3731
3732         switch(level) {
3733         case SMB2_OPLOCK_LEVEL_II:
3734                 name = "level II";
3735                 break;
3736         case SMB2_OPLOCK_LEVEL_NONE:
3737                 name = "none";
3738                 break;
3739         default:
3740                 name = "unknown";
3741                 break;
3742         }
3743         printf("Got break to %s [0x%02X] in oplock handler, postponing "
3744                "break response for 500msec\n", name, level);
3745
3746         te = tevent_add_timer(
3747                 state->tctx->ev, state->tctx,
3748                 tevent_timeval_current_ofs(0, 500000),
3749                 levelII501_break_timeout_cb, state);
3750         torture_assert(state->tctx, te != NULL, "tevent_add_timer failed\n");
3751
3752         return true;
3753 }
3754
3755 static void levelII501_break_timeout_cb(struct tevent_context *ev,
3756                                         struct tevent_timer *te,
3757                                         struct timeval current_time,
3758                                         void *private_data)
3759 {
3760         struct levelII501_state *state = talloc_get_type_abort(
3761                 private_data, struct levelII501_state);
3762         struct smb2_request *req;
3763
3764         talloc_free(te);
3765
3766         ZERO_STRUCT(state->br);
3767         state->br.in.file.handle = state->break_handle;
3768         state->br.in.oplock_level = state->break_to;
3769
3770         req = smb2_break_send(state->tree1, &state->br);
3771         req->async.fn = levelII501_break_done;
3772         req->async.private_data = state;
3773 }
3774
3775 static void levelII501_break_done(struct smb2_request *req)
3776 {
3777         struct smb2_break io;
3778         NTSTATUS status;
3779
3780         status = smb2_break_recv(req, &io);
3781         printf("break done: %s\n", nt_errstr(status));
3782 }
3783
3784 static void levelII501_open1_done(struct smb2_request *req)
3785 {
3786         struct levelII501_state *state = talloc_get_type_abort(
3787                 req->async.private_data, struct levelII501_state);
3788         struct smb2_create io;
3789         NTSTATUS status;
3790
3791         status = smb2_create_recv(req, state, &io);
3792         printf("open1 done: %s\n", nt_errstr(status));
3793 }
3794
3795 static void levelII501_open2_done(struct smb2_request *req)
3796 {
3797         struct levelII501_state *state = talloc_get_type_abort(
3798                 req->async.private_data, struct levelII501_state);
3799         struct smb2_create io;
3800         NTSTATUS status;
3801
3802         status = smb2_create_recv(req, state, &io);
3803         printf("open2 done: %s\n", nt_errstr(status));
3804 }
3805
3806 static void levelII501_timeout_cb(struct tevent_context *ev,
3807                                   struct tevent_timer *te,
3808                                   struct timeval current_time,
3809                                   void *private_data)
3810 {
3811         struct levelII501_state *state = talloc_get_type_abort(
3812                 private_data, struct levelII501_state);
3813         talloc_free(te);
3814         state->done = true;
3815 }
3816
3817 struct torture_suite *torture_smb2_oplocks_init(void)
3818 {
3819         struct torture_suite *suite =
3820             torture_suite_create(talloc_autofree_context(), "oplock");
3821
3822         torture_suite_add_2smb2_test(suite, "exclusive1", test_smb2_oplock_exclusive1);
3823         torture_suite_add_2smb2_test(suite, "exclusive2", test_smb2_oplock_exclusive2);
3824         torture_suite_add_2smb2_test(suite, "exclusive3", test_smb2_oplock_exclusive3);
3825         torture_suite_add_2smb2_test(suite, "exclusive4", test_smb2_oplock_exclusive4);
3826         torture_suite_add_2smb2_test(suite, "exclusive5", test_smb2_oplock_exclusive5);
3827         torture_suite_add_2smb2_test(suite, "exclusive6", test_smb2_oplock_exclusive6);
3828         torture_suite_add_2smb2_test(suite, "exclusive9",
3829                                      test_smb2_oplock_exclusive9);
3830         torture_suite_add_2smb2_test(suite, "batch1", test_smb2_oplock_batch1);
3831         torture_suite_add_2smb2_test(suite, "batch2", test_smb2_oplock_batch2);
3832         torture_suite_add_2smb2_test(suite, "batch3", test_smb2_oplock_batch3);
3833         torture_suite_add_2smb2_test(suite, "batch4", test_smb2_oplock_batch4);
3834         torture_suite_add_2smb2_test(suite, "batch5", test_smb2_oplock_batch5);
3835         torture_suite_add_2smb2_test(suite, "batch6", test_smb2_oplock_batch6);
3836         torture_suite_add_2smb2_test(suite, "batch7", test_smb2_oplock_batch7);
3837         torture_suite_add_2smb2_test(suite, "batch8", test_smb2_oplock_batch8);
3838         torture_suite_add_2smb2_test(suite, "batch9", test_smb2_oplock_batch9);
3839         torture_suite_add_2smb2_test(suite, "batch10", test_smb2_oplock_batch10);
3840         torture_suite_add_2smb2_test(suite, "batch11", test_smb2_oplock_batch11);
3841         torture_suite_add_2smb2_test(suite, "batch12", test_smb2_oplock_batch12);
3842         torture_suite_add_2smb2_test(suite, "batch13", test_smb2_oplock_batch13);
3843         torture_suite_add_2smb2_test(suite, "batch14", test_smb2_oplock_batch14);
3844         torture_suite_add_2smb2_test(suite, "batch15", test_smb2_oplock_batch15);
3845         torture_suite_add_2smb2_test(suite, "batch16", test_smb2_oplock_batch16);
3846         torture_suite_add_1smb2_test(suite, "batch19", test_smb2_oplock_batch19);
3847         torture_suite_add_2smb2_test(suite, "batch20", test_smb2_oplock_batch20);
3848         torture_suite_add_1smb2_test(suite, "batch21", test_smb2_oplock_batch21);
3849         torture_suite_add_1smb2_test(suite, "batch22", test_smb2_oplock_batch22);
3850         torture_suite_add_2smb2_test(suite, "batch23", test_smb2_oplock_batch23);
3851         torture_suite_add_2smb2_test(suite, "batch24", test_smb2_oplock_batch24);
3852         torture_suite_add_1smb2_test(suite, "batch25", test_smb2_oplock_batch25);
3853         torture_suite_add_1smb2_test(suite, "batch26", test_smb2_oplock_batch26);
3854         torture_suite_add_2smb2_test(suite, "stream1", test_raw_oplock_stream1);
3855         torture_suite_add_2smb2_test(suite, "doc", test_smb2_oplock_doc);
3856         torture_suite_add_2smb2_test(suite, "brl1", test_smb2_oplock_brl1);
3857         torture_suite_add_1smb2_test(suite, "brl2", test_smb2_oplock_brl2);
3858         torture_suite_add_1smb2_test(suite, "brl3", test_smb2_oplock_brl3);
3859         torture_suite_add_1smb2_test(suite, "levelii500", test_smb2_oplock_levelII500);
3860         torture_suite_add_2smb2_test(suite, "levelii501",
3861                                      test_smb2_oplock_levelII501);
3862         suite->description = talloc_strdup(suite, "SMB2-OPLOCK tests");
3863
3864         return suite;
3865 }
3866
3867 /*
3868    stress testing of oplocks
3869 */
3870 bool test_smb2_bench_oplock(struct torture_context *tctx,
3871                                    struct smb2_tree *tree)
3872 {
3873         struct smb2_tree **trees;
3874         bool ret = true;
3875         NTSTATUS status;
3876         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3877         int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
3878         int i, count=0;
3879         int timelimit = torture_setting_int(tctx, "timelimit", 10);
3880         union smb_open io;
3881         struct timeval tv;
3882         struct smb2_handle h;
3883
3884         trees = talloc_array(mem_ctx, struct smb2_tree *, torture_nprocs);
3885
3886         torture_comment(tctx, "Opening %d connections\n", torture_nprocs);
3887         for (i=0;i<torture_nprocs;i++) {
3888                 if (!torture_smb2_connection(tctx, &trees[i])) {
3889                         return false;
3890                 }
3891                 talloc_steal(mem_ctx, trees[i]);
3892                 trees[i]->session->transport->oplock.handler =
3893                                         torture_oplock_handler_close;
3894                 trees[i]->session->transport->oplock.private_data = trees[i];
3895         }
3896
3897         status = torture_smb2_testdir(trees[0], BASEDIR, &h);
3898         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3899
3900         ZERO_STRUCT(io.smb2);
3901         io.smb2.level = RAW_OPEN_SMB2;
3902         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3903         io.smb2.in.alloc_size = 0;
3904         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3905         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3906         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3907         io.smb2.in.create_options = 0;
3908         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3909         io.smb2.in.security_flags = 0;
3910         io.smb2.in.fname = BASEDIR "\\test.dat";
3911         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3912         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3913
3914         tv = timeval_current();
3915
3916         /*
3917           we open the same file with SHARE_ACCESS_NONE from all the
3918           connections in a round robin fashion. Each open causes an
3919           oplock break on the previous connection, which is answered
3920           by the oplock_handler_close() to close the file.
3921
3922           This measures how fast we can pass on oplocks, and stresses
3923           the oplock handling code
3924         */
3925         torture_comment(tctx, "Running for %d seconds\n", timelimit);
3926         while (timeval_elapsed(&tv) < timelimit) {
3927                 for (i=0;i<torture_nprocs;i++) {
3928                         status = smb2_create(trees[i], mem_ctx, &(io.smb2));
3929                         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3930                         count++;
3931                 }
3932
3933                 if (torture_setting_bool(tctx, "progress", true)) {
3934                         torture_comment(tctx, "%.2f ops/second\r",
3935                                         count/timeval_elapsed(&tv));
3936                 }
3937         }
3938
3939         torture_comment(tctx, "%.2f ops/second\n", count/timeval_elapsed(&tv));
3940         smb2_util_close(trees[0], io.smb2.out.file.handle);
3941         smb2_util_unlink(trees[0], BASEDIR "\\test.dat");
3942         smb2_deltree(trees[0], BASEDIR);
3943         talloc_free(mem_ctx);
3944         return ret;
3945 }
3946
3947 static struct hold_oplock_info {
3948         const char *fname;
3949         bool close_on_break;
3950         uint32_t share_access;
3951         struct smb2_handle handle;
3952 } hold_info[] = {
3953         { BASEDIR "\\notshared_close", true,
3954           NTCREATEX_SHARE_ACCESS_NONE, },
3955         { BASEDIR "\\notshared_noclose", false,
3956           NTCREATEX_SHARE_ACCESS_NONE, },
3957         { BASEDIR "\\shared_close", true,
3958           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
3959         { BASEDIR "\\shared_noclose", false,
3960           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
3961 };
3962
3963 static bool torture_oplock_handler_hold(struct smb2_transport *transport,
3964                                         const struct smb2_handle *handle,
3965                                         uint8_t level, void *private_data)
3966 {
3967         struct hold_oplock_info *info;
3968         int i;
3969
3970         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
3971                 if (smb2_util_handle_equal(hold_info[i].handle, *handle))
3972                         break;
3973         }
3974
3975         if (i == ARRAY_SIZE(hold_info)) {
3976                 printf("oplock break for unknown handle 0x%llx%llx\n",
3977                        (unsigned long long) handle->data[0],
3978                        (unsigned long long) handle->data[1]);
3979                 return false;
3980         }
3981
3982         info = &hold_info[i];
3983
3984         if (info->close_on_break) {
3985                 printf("oplock break on %s - closing\n", info->fname);
3986                 torture_oplock_handler_close(transport, handle,
3987                                              level, private_data);
3988                 return true;
3989         }
3990
3991         printf("oplock break on %s - acking break\n", info->fname);
3992         printf("Acking to none in oplock handler\n");
3993
3994         torture_oplock_handler_ack_to_none(transport, handle,
3995                                            level, private_data);
3996         return true;
3997 }
3998
3999 /*
4000    used for manual testing of oplocks - especially interaction with
4001    other filesystems (such as NFS and local access)
4002 */
4003 bool test_smb2_hold_oplock(struct torture_context *tctx,
4004                            struct smb2_tree *tree)
4005 {
4006         struct torture_context *mem_ctx = talloc_new(tctx);
4007         struct tevent_context *ev = tctx->ev;
4008         int i;
4009         struct smb2_handle h;
4010         NTSTATUS status;
4011
4012         torture_comment(tctx, "Setting up open files with oplocks in %s\n",
4013                         BASEDIR);
4014
4015         status = torture_smb2_testdir(tree, BASEDIR, &h);
4016         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
4017
4018         tree->session->transport->oplock.handler = torture_oplock_handler_hold;
4019         tree->session->transport->oplock.private_data = tree;
4020
4021         /* setup the files */
4022         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
4023                 union smb_open io;
4024                 char c = 1;
4025
4026                 ZERO_STRUCT(io.smb2);
4027                 io.generic.level = RAW_OPEN_SMB2;
4028                 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
4029                 io.smb2.in.alloc_size = 0;
4030                 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4031                 io.smb2.in.share_access = hold_info[i].share_access;
4032                 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4033                 io.smb2.in.create_options = 0;
4034                 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4035                 io.smb2.in.security_flags = 0;
4036                 io.smb2.in.fname = hold_info[i].fname;
4037                 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
4038                 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
4039
4040                 torture_comment(tctx, "opening %s\n", hold_info[i].fname);
4041
4042                 status = smb2_create(tree, mem_ctx, &(io.smb2));
4043                 if (!NT_STATUS_IS_OK(status)) {
4044                         torture_comment(tctx, "Failed to open %s - %s\n",
4045                                hold_info[i].fname, nt_errstr(status));
4046                         return false;
4047                 }
4048
4049                 if (io.smb2.out.oplock_level != SMB2_OPLOCK_LEVEL_BATCH) {
4050                         torture_comment(tctx, "Oplock not granted for %s - "
4051                                         "expected %d but got %d\n",
4052                                         hold_info[i].fname,
4053                                         SMB2_OPLOCK_LEVEL_BATCH,
4054                                         io.smb2.out.oplock_level);
4055                         return false;
4056                 }
4057                 hold_info[i].handle = io.smb2.out.file.handle;
4058
4059                 /* make the file non-zero size */
4060                 status = smb2_util_write(tree, hold_info[i].handle, &c, 0, 1);
4061                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
4062                         torture_comment(tctx, "Failed to write to file\n");
4063                         return false;
4064                 }
4065         }
4066
4067         torture_comment(tctx, "Waiting for oplock events\n");
4068         tevent_loop_wait(ev);
4069         smb2_deltree(tree, BASEDIR);
4070         talloc_free(mem_ctx);
4071         return true;
4072 }