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