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