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