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