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