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