smbd: Fix crossing automounter mount points
[Samba.git] / source4 / torture / smb2 / lock.c
blobeac0d557fc38659f47a591623bec1e08b26aad8d
1 /*
2 Unix SMB/CIFS implementation.
4 SMB2 lock test suite
6 Copyright (C) Stefan Metzmacher 2006
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25 #include "../libcli/smb/smbXcli_base.h"
27 #include "torture/torture.h"
28 #include "torture/smb2/proto.h"
29 #include "torture/util.h"
31 #include "lib/events/events.h"
32 #include "param/param.h"
34 #define CHECK_STATUS(status, correct) do { \
35 const char *_cmt = "(" __location__ ")"; \
36 torture_assert_ntstatus_equal_goto(torture,status,correct, \
37 ret,done,_cmt); \
38 } while (0)
40 #define CHECK_STATUS_CMT(status, correct, cmt) do { \
41 torture_assert_ntstatus_equal_goto(torture,status,correct, \
42 ret,done,cmt); \
43 } while (0)
45 #define CHECK_STATUS_CONT(status, correct) do { \
46 if (!NT_STATUS_EQUAL(status, correct)) { \
47 torture_result(torture, TORTURE_FAIL, \
48 "(%s) Incorrect status %s - should be %s\n", \
49 __location__, nt_errstr(status), nt_errstr(correct)); \
50 ret = false; \
51 }} while (0)
53 #define CHECK_VALUE(v, correct) do { \
54 const char *_cmt = "(" __location__ ")"; \
55 torture_assert_int_equal_goto(torture,v,correct,ret,done,_cmt); \
56 } while (0)
58 #define BASEDIR "testlock"
60 #define TARGET_SUPPORTS_INVALID_LOCK_RANGE(_tctx) \
61 (torture_setting_bool(_tctx, "invalid_lock_range_support", true))
62 #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false))
64 #define WAIT_FOR_ASYNC_RESPONSE(req) \
65 while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) { \
66 if (tevent_loop_once(torture->ev) != 0) { \
67 break; \
68 } \
71 static bool test_valid_request(struct torture_context *torture,
72 struct smb2_tree *tree)
74 bool ret = true;
75 NTSTATUS status;
76 struct smb2_handle h;
77 uint8_t buf[200];
78 struct smb2_lock lck;
79 struct smb2_lock_element el[2];
81 ZERO_STRUCT(buf);
83 status = torture_smb2_testfile(tree, "lock1.txt", &h);
84 CHECK_STATUS(status, NT_STATUS_OK);
86 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
87 CHECK_STATUS(status, NT_STATUS_OK);
89 lck.in.locks = el;
91 torture_comment(torture, "Test request with 0 locks.\n");
93 lck.in.lock_count = 0x0000;
94 lck.in.lock_sequence = 0x00000000;
95 lck.in.file.handle = h;
96 el[0].offset = 0x0000000000000000;
97 el[0].length = 0x0000000000000000;
98 el[0].reserved = 0x0000000000000000;
99 el[0].flags = 0x00000000;
100 status = smb2_lock(tree, &lck);
101 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
103 lck.in.lock_count = 0x0000;
104 lck.in.lock_sequence = 0x00000000;
105 lck.in.file.handle = h;
106 el[0].offset = 0;
107 el[0].length = 0;
108 el[0].reserved = 0x00000000;
109 el[0].flags = SMB2_LOCK_FLAG_SHARED;
110 status = smb2_lock(tree, &lck);
111 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
113 lck.in.lock_count = 0x0001;
114 lck.in.lock_sequence = 0x00000000;
115 lck.in.file.handle = h;
116 el[0].offset = 0;
117 el[0].length = 0;
118 el[0].reserved = 0x00000000;
119 el[0].flags = SMB2_LOCK_FLAG_NONE;
120 status = smb2_lock(tree, &lck);
121 if (TARGET_IS_W2K8(torture)) {
122 CHECK_STATUS(status, NT_STATUS_OK);
123 torture_warning(torture, "Target has bug validating lock flags "
124 "parameter.\n");
125 } else {
126 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
129 torture_comment(torture, "Test >63-bit lock requests.\n");
131 lck.in.file.handle.data[0] +=1;
132 status = smb2_lock(tree, &lck);
133 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
134 lck.in.file.handle.data[0] -=1;
136 lck.in.lock_count = 0x0001;
137 lck.in.lock_sequence = 0x123ab1;
138 lck.in.file.handle = h;
139 el[0].offset = UINT64_MAX;
140 el[0].length = UINT64_MAX;
141 el[0].reserved = 0x00000000;
142 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
143 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
144 status = smb2_lock(tree, &lck);
145 if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(torture)) {
146 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
147 } else {
148 CHECK_STATUS(status, NT_STATUS_OK);
149 CHECK_VALUE(lck.out.reserved, 0);
152 lck.in.lock_sequence = 0x123ab2;
153 status = smb2_lock(tree, &lck);
154 if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(torture)) {
155 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
156 } else {
157 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
160 torture_comment(torture, "Test basic lock stacking.\n");
162 lck.in.lock_count = 0x0001;
163 lck.in.lock_sequence = 0x12345678;
164 lck.in.file.handle = h;
165 el[0].offset = UINT32_MAX;
166 el[0].length = UINT32_MAX;
167 el[0].reserved = 0x87654321;
168 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
169 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
170 status = smb2_lock(tree, &lck);
171 CHECK_STATUS(status, NT_STATUS_OK);
172 CHECK_VALUE(lck.out.reserved, 0);
174 el[0].flags = SMB2_LOCK_FLAG_SHARED;
175 status = smb2_lock(tree, &lck);
176 CHECK_STATUS(status, NT_STATUS_OK);
177 CHECK_VALUE(lck.out.reserved, 0);
179 status = smb2_lock(tree, &lck);
180 CHECK_STATUS(status, NT_STATUS_OK);
181 CHECK_VALUE(lck.out.reserved, 0);
183 lck.in.lock_count = 0x0001;
184 lck.in.lock_sequence = 0x87654321;
185 lck.in.file.handle = h;
186 el[0].offset = 0x00000000FFFFFFFF;
187 el[0].length = 0x00000000FFFFFFFF;
188 el[0].reserved = 0x1234567;
189 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
190 status = smb2_lock(tree, &lck);
191 CHECK_STATUS(status, NT_STATUS_OK);
193 lck.in.lock_count = 0x0001;
194 lck.in.lock_sequence = 0x1234567;
195 lck.in.file.handle = h;
196 el[0].offset = 0x00000000FFFFFFFF;
197 el[0].length = 0x00000000FFFFFFFF;
198 el[0].reserved = 0x00000000;
199 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
200 status = smb2_lock(tree, &lck);
201 CHECK_STATUS(status, NT_STATUS_OK);
203 status = smb2_lock(tree, &lck);
204 CHECK_STATUS(status, NT_STATUS_OK);
205 status = smb2_lock(tree, &lck);
206 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
208 torture_comment(torture, "Test flags field permutations.\n");
210 lck.in.lock_count = 0x0001;
211 lck.in.lock_sequence = 0;
212 lck.in.file.handle = h;
213 el[0].offset = 1;
214 el[0].length = 1;
215 el[0].reserved = 0x00000000;
216 el[0].flags = ~SMB2_LOCK_FLAG_ALL_MASK;
218 status = smb2_lock(tree, &lck);
219 if (TARGET_IS_W2K8(torture)) {
220 CHECK_STATUS(status, NT_STATUS_OK);
221 torture_warning(torture, "Target has bug validating lock flags "
222 "parameter.\n");
223 } else {
224 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
227 if (TARGET_IS_W2K8(torture)) {
228 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
229 status = smb2_lock(tree, &lck);
230 CHECK_STATUS(status, NT_STATUS_OK);
233 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
234 status = smb2_lock(tree, &lck);
235 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
237 el[0].flags = SMB2_LOCK_FLAG_UNLOCK |
238 SMB2_LOCK_FLAG_EXCLUSIVE;
239 status = smb2_lock(tree, &lck);
240 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
242 el[0].flags = SMB2_LOCK_FLAG_UNLOCK |
243 SMB2_LOCK_FLAG_SHARED;
244 status = smb2_lock(tree, &lck);
245 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
247 el[0].flags = SMB2_LOCK_FLAG_UNLOCK |
248 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
249 status = smb2_lock(tree, &lck);
250 if (TARGET_IS_W2K8(torture)) {
251 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
252 torture_warning(torture, "Target has bug validating lock flags "
253 "parameter.\n");
254 } else {
255 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
258 torture_comment(torture, "Test return error when 2 locks are "
259 "requested\n");
261 lck.in.lock_count = 2;
262 lck.in.lock_sequence = 0;
263 lck.in.file.handle = h;
264 el[0].offset = 9999;
265 el[0].length = 1;
266 el[0].reserved = 0x00000000;
267 el[1].offset = 9999;
268 el[1].length = 1;
269 el[1].reserved = 0x00000000;
271 lck.in.lock_count = 2;
272 el[0].flags = 0;
273 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
274 status = smb2_lock(tree, &lck);
275 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
277 lck.in.lock_count = 2;
278 el[0].flags = SMB2_LOCK_FLAG_SHARED|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
279 el[1].flags = SMB2_LOCK_FLAG_SHARED;
280 status = smb2_lock(tree, &lck);
281 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
283 lck.in.lock_count = 2;
284 el[0].flags = 0;
285 el[1].flags = 0;
286 status = smb2_lock(tree, &lck);
287 if (TARGET_IS_W2K8(torture)) {
288 CHECK_STATUS(status, NT_STATUS_OK);
289 torture_warning(torture, "Target has bug validating lock flags "
290 "parameter.\n");
291 } else {
292 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
295 lck.in.lock_count = 2;
296 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
297 el[1].flags = 0;
298 status = smb2_lock(tree, &lck);
299 if (TARGET_IS_W2K8(torture)) {
300 CHECK_STATUS(status, NT_STATUS_OK);
301 torture_warning(torture, "Target has bug validating lock flags "
302 "parameter.\n");
303 } else {
304 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
307 lck.in.lock_count = 1;
308 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
309 status = smb2_lock(tree, &lck);
310 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
312 lck.in.lock_count = 1;
313 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
314 status = smb2_lock(tree, &lck);
315 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
317 lck.in.lock_count = 1;
318 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
319 status = smb2_lock(tree, &lck);
320 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
322 lck.in.lock_count = 1;
323 el[0].flags = SMB2_LOCK_FLAG_SHARED;
324 status = smb2_lock(tree, &lck);
325 CHECK_STATUS(status, NT_STATUS_OK);
327 status = smb2_lock(tree, &lck);
328 CHECK_STATUS(status, NT_STATUS_OK);
330 lck.in.lock_count = 2;
331 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
332 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
333 status = smb2_lock(tree, &lck);
334 CHECK_STATUS(status, NT_STATUS_OK);
336 lck.in.lock_count = 1;
337 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
338 status = smb2_lock(tree, &lck);
339 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
341 done:
342 return ret;
345 struct test_lock_read_write_state {
346 const char *fname;
347 uint32_t lock_flags;
348 NTSTATUS write_h1_status;
349 NTSTATUS read_h1_status;
350 NTSTATUS write_h2_status;
351 NTSTATUS read_h2_status;
354 static bool test_lock_read_write(struct torture_context *torture,
355 struct smb2_tree *tree,
356 struct test_lock_read_write_state *s)
358 bool ret = true;
359 NTSTATUS status;
360 struct smb2_handle h1, h2;
361 uint8_t buf[200];
362 struct smb2_lock lck;
363 struct smb2_create cr;
364 struct smb2_write wr;
365 struct smb2_read rd;
366 struct smb2_lock_element el[1];
368 lck.in.locks = el;
370 ZERO_STRUCT(buf);
372 status = torture_smb2_testfile(tree, s->fname, &h1);
373 CHECK_STATUS(status, NT_STATUS_OK);
375 status = smb2_util_write(tree, h1, buf, 0, ARRAY_SIZE(buf));
376 CHECK_STATUS(status, NT_STATUS_OK);
378 lck.in.lock_count = 0x0001;
379 lck.in.lock_sequence = 0x00000000;
380 lck.in.file.handle = h1;
381 el[0].offset = 0;
382 el[0].length = ARRAY_SIZE(buf)/2;
383 el[0].reserved = 0x00000000;
384 el[0].flags = s->lock_flags;
385 status = smb2_lock(tree, &lck);
386 CHECK_STATUS(status, NT_STATUS_OK);
387 CHECK_VALUE(lck.out.reserved, 0);
389 lck.in.lock_count = 0x0001;
390 lck.in.lock_sequence = 0x00000000;
391 lck.in.file.handle = h1;
392 el[0].offset = ARRAY_SIZE(buf)/2;
393 el[0].length = ARRAY_SIZE(buf)/2;
394 el[0].reserved = 0x00000000;
395 el[0].flags = s->lock_flags;
396 status = smb2_lock(tree, &lck);
397 CHECK_STATUS(status, NT_STATUS_OK);
398 CHECK_VALUE(lck.out.reserved, 0);
400 ZERO_STRUCT(cr);
401 cr.in.oplock_level = 0;
402 cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
403 cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
404 cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
405 cr.in.share_access =
406 NTCREATEX_SHARE_ACCESS_DELETE|
407 NTCREATEX_SHARE_ACCESS_READ|
408 NTCREATEX_SHARE_ACCESS_WRITE;
409 cr.in.create_options = 0;
410 cr.in.fname = s->fname;
412 status = smb2_create(tree, tree, &cr);
413 CHECK_STATUS(status, NT_STATUS_OK);
415 h2 = cr.out.file.handle;
417 ZERO_STRUCT(wr);
418 wr.in.file.handle = h1;
419 wr.in.offset = ARRAY_SIZE(buf)/2;
420 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
422 status = smb2_write(tree, &wr);
423 CHECK_STATUS(status, s->write_h1_status);
425 ZERO_STRUCT(rd);
426 rd.in.file.handle = h1;
427 rd.in.offset = ARRAY_SIZE(buf)/2;
428 rd.in.length = ARRAY_SIZE(buf)/2;
430 status = smb2_read(tree, tree, &rd);
431 CHECK_STATUS(status, s->read_h1_status);
433 ZERO_STRUCT(wr);
434 wr.in.file.handle = h2;
435 wr.in.offset = ARRAY_SIZE(buf)/2;
436 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
438 status = smb2_write(tree, &wr);
439 CHECK_STATUS(status, s->write_h2_status);
441 ZERO_STRUCT(rd);
442 rd.in.file.handle = h2;
443 rd.in.offset = ARRAY_SIZE(buf)/2;
444 rd.in.length = ARRAY_SIZE(buf)/2;
446 status = smb2_read(tree, tree, &rd);
447 CHECK_STATUS(status, s->read_h2_status);
449 lck.in.lock_count = 0x0001;
450 lck.in.lock_sequence = 0x00000000;
451 lck.in.file.handle = h1;
452 el[0].offset = ARRAY_SIZE(buf)/2;
453 el[0].length = ARRAY_SIZE(buf)/2;
454 el[0].reserved = 0x00000000;
455 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
456 status = smb2_lock(tree, &lck);
457 CHECK_STATUS(status, NT_STATUS_OK);
458 CHECK_VALUE(lck.out.reserved, 0);
460 ZERO_STRUCT(wr);
461 wr.in.file.handle = h2;
462 wr.in.offset = ARRAY_SIZE(buf)/2;
463 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
465 status = smb2_write(tree, &wr);
466 CHECK_STATUS(status, NT_STATUS_OK);
468 ZERO_STRUCT(rd);
469 rd.in.file.handle = h2;
470 rd.in.offset = ARRAY_SIZE(buf)/2;
471 rd.in.length = ARRAY_SIZE(buf)/2;
473 status = smb2_read(tree, tree, &rd);
474 CHECK_STATUS(status, NT_STATUS_OK);
476 done:
477 return ret;
480 static bool test_lock_rw_none(struct torture_context *torture,
481 struct smb2_tree *tree)
483 struct test_lock_read_write_state s = {
484 .fname = "lock_rw_none.dat",
485 .lock_flags = SMB2_LOCK_FLAG_NONE,
486 .write_h1_status = NT_STATUS_FILE_LOCK_CONFLICT,
487 .read_h1_status = NT_STATUS_OK,
488 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
489 .read_h2_status = NT_STATUS_OK,
492 if (!TARGET_IS_W2K8(torture)) {
493 torture_skip(torture, "RW-NONE tests the behavior of a "
494 "NONE-type lock, which is the same as a SHARED "
495 "lock but is granted due to a bug in W2K8. If "
496 "target is not W2K8 we skip this test.\n");
499 return test_lock_read_write(torture, tree, &s);
502 static bool test_lock_rw_shared(struct torture_context *torture,
503 struct smb2_tree *tree)
505 struct test_lock_read_write_state s = {
506 .fname = "lock_rw_shared.dat",
507 .lock_flags = SMB2_LOCK_FLAG_SHARED,
508 .write_h1_status = NT_STATUS_FILE_LOCK_CONFLICT,
509 .read_h1_status = NT_STATUS_OK,
510 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
511 .read_h2_status = NT_STATUS_OK,
514 return test_lock_read_write(torture, tree, &s);
517 static bool test_lock_rw_exclusive(struct torture_context *torture,
518 struct smb2_tree *tree)
520 struct test_lock_read_write_state s = {
521 .fname = "lock_rw_exclusive.dat",
522 .lock_flags = SMB2_LOCK_FLAG_EXCLUSIVE,
523 .write_h1_status = NT_STATUS_OK,
524 .read_h1_status = NT_STATUS_OK,
525 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
526 .read_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
529 return test_lock_read_write(torture, tree, &s);
532 static bool test_lock_auto_unlock(struct torture_context *torture,
533 struct smb2_tree *tree)
535 bool ret = true;
536 NTSTATUS status;
537 struct smb2_handle h;
538 uint8_t buf[200];
539 struct smb2_lock lck;
540 struct smb2_lock_element el[1];
542 ZERO_STRUCT(buf);
544 status = torture_smb2_testfile(tree, "autounlock.txt", &h);
545 CHECK_STATUS(status, NT_STATUS_OK);
547 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
548 CHECK_STATUS(status, NT_STATUS_OK);
550 ZERO_STRUCT(lck);
551 ZERO_STRUCT(el[0]);
552 lck.in.locks = el;
553 lck.in.lock_count = 0x0001;
554 lck.in.file.handle = h;
555 el[0].offset = 0;
556 el[0].length = 1;
557 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
558 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
559 status = smb2_lock(tree, &lck);
560 CHECK_STATUS(status, NT_STATUS_OK);
562 status = smb2_lock(tree, &lck);
563 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
565 status = smb2_lock(tree, &lck);
566 if (TARGET_IS_W2K8(torture)) {
567 CHECK_STATUS(status, NT_STATUS_OK);
568 torture_warning(torture, "Target has \"pretty please\" bug. "
569 "A contending lock request on the same handle "
570 "unlocks the lock.\n");
571 } else {
572 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
575 status = smb2_lock(tree, &lck);
576 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
578 done:
579 return ret;
583 test different lock ranges and see if different handles conflict
585 static bool test_lock(struct torture_context *torture,
586 struct smb2_tree *tree)
588 NTSTATUS status;
589 bool ret = true;
590 struct smb2_handle h = {{0}};
591 struct smb2_handle h2 = {{0}};
592 uint8_t buf[200];
593 struct smb2_lock lck;
594 struct smb2_lock_element el[2];
596 const char *fname = BASEDIR "\\async.txt";
598 status = torture_smb2_testdir(tree, BASEDIR, &h);
599 CHECK_STATUS(status, NT_STATUS_OK);
600 smb2_util_close(tree, h);
602 status = torture_smb2_testfile(tree, fname, &h);
603 CHECK_STATUS(status, NT_STATUS_OK);
605 ZERO_STRUCT(buf);
606 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
607 CHECK_STATUS(status, NT_STATUS_OK);
609 status = torture_smb2_testfile(tree, fname, &h2);
610 CHECK_STATUS(status, NT_STATUS_OK);
612 lck.in.locks = el;
614 lck.in.lock_count = 0x0001;
615 lck.in.lock_sequence = 0x00000000;
616 lck.in.file.handle = h;
617 el[0].reserved = 0x00000000;
618 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
619 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
621 torture_comment(torture, "Trying 0/0 lock\n");
622 el[0].offset = 0x0000000000000000;
623 el[0].length = 0x0000000000000000;
624 status = smb2_lock(tree, &lck);
625 CHECK_STATUS(status, NT_STATUS_OK);
626 lck.in.file.handle = h2;
627 status = smb2_lock(tree, &lck);
628 CHECK_STATUS(status, NT_STATUS_OK);
629 lck.in.file.handle = h;
630 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
631 status = smb2_lock(tree, &lck);
632 CHECK_STATUS(status, NT_STATUS_OK);
634 torture_comment(torture, "Trying 0/1 lock\n");
635 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
636 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
637 el[0].offset = 0x0000000000000000;
638 el[0].length = 0x0000000000000001;
639 status = smb2_lock(tree, &lck);
640 CHECK_STATUS(status, NT_STATUS_OK);
641 lck.in.file.handle = h2;
642 status = smb2_lock(tree, &lck);
643 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
644 lck.in.file.handle = h;
645 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
646 status = smb2_lock(tree, &lck);
647 CHECK_STATUS(status, NT_STATUS_OK);
648 status = smb2_lock(tree, &lck);
649 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
651 torture_comment(torture, "Trying 0xEEFFFFF lock\n");
652 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
653 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
654 el[0].offset = 0xEEFFFFFF;
655 el[0].length = 4000;
656 status = smb2_lock(tree, &lck);
657 CHECK_STATUS(status, NT_STATUS_OK);
658 lck.in.file.handle = h2;
659 status = smb2_lock(tree, &lck);
660 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
661 lck.in.file.handle = h;
662 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
663 status = smb2_lock(tree, &lck);
664 CHECK_STATUS(status, NT_STATUS_OK);
665 status = smb2_lock(tree, &lck);
666 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
668 torture_comment(torture, "Trying 0xEF00000 lock\n");
669 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
670 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
671 el[0].offset = 0xEF000000;
672 el[0].length = 4000;
673 status = smb2_lock(tree, &lck);
674 CHECK_STATUS(status, NT_STATUS_OK);
675 lck.in.file.handle = h2;
676 status = smb2_lock(tree, &lck);
677 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
678 lck.in.file.handle = h;
679 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
680 status = smb2_lock(tree, &lck);
681 CHECK_STATUS(status, NT_STATUS_OK);
682 status = smb2_lock(tree, &lck);
683 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
685 torture_comment(torture, "Trying (2^63 - 1)/1\n");
686 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
687 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
688 el[0].offset = 1;
689 el[0].offset <<= 63;
690 el[0].offset--;
691 el[0].length = 1;
692 status = smb2_lock(tree, &lck);
693 CHECK_STATUS(status, NT_STATUS_OK);
694 lck.in.file.handle = h2;
695 status = smb2_lock(tree, &lck);
696 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
697 lck.in.file.handle = h;
698 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
699 status = smb2_lock(tree, &lck);
700 CHECK_STATUS(status, NT_STATUS_OK);
701 status = smb2_lock(tree, &lck);
702 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
704 torture_comment(torture, "Trying 2^63/1\n");
705 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
706 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
707 el[0].offset = 1;
708 el[0].offset <<= 63;
709 el[0].length = 1;
710 status = smb2_lock(tree, &lck);
711 CHECK_STATUS(status, NT_STATUS_OK);
712 lck.in.file.handle = h2;
713 status = smb2_lock(tree, &lck);
714 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
715 lck.in.file.handle = h;
716 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
717 status = smb2_lock(tree, &lck);
718 CHECK_STATUS(status, NT_STATUS_OK);
719 status = smb2_lock(tree, &lck);
720 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
722 torture_comment(torture, "Trying max/0 lock\n");
723 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
724 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
725 el[0].offset = ~0;
726 el[0].length = 0;
727 status = smb2_lock(tree, &lck);
728 CHECK_STATUS(status, NT_STATUS_OK);
729 lck.in.file.handle = h2;
730 status = smb2_lock(tree, &lck);
731 CHECK_STATUS(status, NT_STATUS_OK);
732 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
733 status = smb2_lock(tree, &lck);
734 CHECK_STATUS(status, NT_STATUS_OK);
735 lck.in.file.handle = h;
736 status = smb2_lock(tree, &lck);
737 CHECK_STATUS(status, NT_STATUS_OK);
738 status = smb2_lock(tree, &lck);
739 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
741 torture_comment(torture, "Trying max/1 lock\n");
742 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
743 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
744 el[0].offset = ~0;
745 el[0].length = 1;
746 status = smb2_lock(tree, &lck);
747 CHECK_STATUS(status, NT_STATUS_OK);
748 lck.in.file.handle = h2;
749 status = smb2_lock(tree, &lck);
750 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
751 lck.in.file.handle = h;
752 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
753 status = smb2_lock(tree, &lck);
754 CHECK_STATUS(status, NT_STATUS_OK);
755 status = smb2_lock(tree, &lck);
756 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
758 torture_comment(torture, "Trying max/2 lock\n");
759 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
760 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
761 el[0].offset = ~0;
762 el[0].length = 2;
763 status = smb2_lock(tree, &lck);
764 if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(torture)) {
765 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
766 } else {
767 CHECK_STATUS(status, NT_STATUS_OK);
768 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
769 status = smb2_lock(tree, &lck);
770 CHECK_STATUS(status, NT_STATUS_OK);
773 torture_comment(torture, "Trying wrong handle unlock\n");
774 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
775 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
776 el[0].offset = 10001;
777 el[0].length = 40002;
778 status = smb2_lock(tree, &lck);
779 CHECK_STATUS(status, NT_STATUS_OK);
780 lck.in.file.handle = h2;
781 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
782 status = smb2_lock(tree, &lck);
783 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
784 lck.in.file.handle = h;
785 status = smb2_lock(tree, &lck);
786 CHECK_STATUS(status, NT_STATUS_OK);
788 done:
789 smb2_util_close(tree, h2);
790 smb2_util_close(tree, h);
791 smb2_deltree(tree, BASEDIR);
792 return ret;
796 test SMB2 LOCK async operation
798 static bool test_async(struct torture_context *torture,
799 struct smb2_tree *tree)
801 NTSTATUS status;
802 bool ret = true;
803 struct smb2_handle h = {{0}};
804 struct smb2_handle h2 = {{0}};
805 uint8_t buf[200];
806 struct smb2_lock lck;
807 struct smb2_lock_element el[2];
808 struct smb2_request *req = NULL;
810 const char *fname = BASEDIR "\\async.txt";
812 status = torture_smb2_testdir(tree, BASEDIR, &h);
813 CHECK_STATUS(status, NT_STATUS_OK);
814 smb2_util_close(tree, h);
816 status = torture_smb2_testfile(tree, fname, &h);
817 CHECK_STATUS(status, NT_STATUS_OK);
819 ZERO_STRUCT(buf);
820 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
821 CHECK_STATUS(status, NT_STATUS_OK);
823 status = torture_smb2_testfile(tree, fname, &h2);
824 CHECK_STATUS(status, NT_STATUS_OK);
826 lck.in.locks = el;
828 lck.in.lock_count = 0x0001;
829 lck.in.lock_sequence = 0x00000000;
830 lck.in.file.handle = h;
831 el[0].offset = 100;
832 el[0].length = 50;
833 el[0].reserved = 0x00000000;
834 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE;
836 torture_comment(torture, " Acquire first lock\n");
837 status = smb2_lock(tree, &lck);
838 CHECK_STATUS(status, NT_STATUS_OK);
840 torture_comment(torture, " Second lock should pend on first\n");
841 lck.in.file.handle = h2;
842 req = smb2_lock_send(tree, &lck);
843 WAIT_FOR_ASYNC_RESPONSE(req);
845 torture_comment(torture, " Unlock first lock\n");
846 lck.in.file.handle = h;
847 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
848 status = smb2_lock(tree, &lck);
849 CHECK_STATUS(status, NT_STATUS_OK);
851 torture_comment(torture, " Second lock should now succeed\n");
852 lck.in.file.handle = h2;
853 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE;
854 status = smb2_lock_recv(req, &lck);
855 CHECK_STATUS(status, NT_STATUS_OK);
857 done:
858 smb2_util_close(tree, h2);
859 smb2_util_close(tree, h);
860 smb2_deltree(tree, BASEDIR);
861 return ret;
865 test SMB2 LOCK Cancel operation
867 static bool test_cancel(struct torture_context *torture,
868 struct smb2_tree *tree)
870 NTSTATUS status;
871 bool ret = true;
872 struct smb2_handle h = {{0}};
873 struct smb2_handle h2 = {{0}};
874 uint8_t buf[200];
875 struct smb2_lock lck;
876 struct smb2_lock_element el[2];
877 struct smb2_request *req = NULL;
879 const char *fname = BASEDIR "\\cancel.txt";
881 status = torture_smb2_testdir(tree, BASEDIR, &h);
882 CHECK_STATUS(status, NT_STATUS_OK);
883 smb2_util_close(tree, h);
885 status = torture_smb2_testfile(tree, fname, &h);
886 CHECK_STATUS(status, NT_STATUS_OK);
888 ZERO_STRUCT(buf);
889 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
890 CHECK_STATUS(status, NT_STATUS_OK);
892 status = torture_smb2_testfile(tree, fname, &h2);
893 CHECK_STATUS(status, NT_STATUS_OK);
895 lck.in.locks = el;
897 lck.in.lock_count = 0x0001;
898 lck.in.lock_sequence = 0x00000000;
899 lck.in.file.handle = h;
900 el[0].offset = 100;
901 el[0].length = 10;
902 el[0].reserved = 0x00000000;
903 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE;
905 torture_comment(torture, "Testing basic cancel\n");
907 torture_comment(torture, " Acquire first lock\n");
908 status = smb2_lock(tree, &lck);
909 CHECK_STATUS(status, NT_STATUS_OK);
911 torture_comment(torture, " Second lock should pend on first\n");
912 lck.in.file.handle = h2;
913 req = smb2_lock_send(tree, &lck);
914 WAIT_FOR_ASYNC_RESPONSE(req);
916 torture_comment(torture, " Cancel the second lock\n");
917 smb2_cancel(req);
918 lck.in.file.handle = h2;
919 status = smb2_lock_recv(req, &lck);
920 CHECK_STATUS(status, NT_STATUS_CANCELLED);
922 torture_comment(torture, " Unlock first lock\n");
923 lck.in.file.handle = h;
924 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
925 status = smb2_lock(tree, &lck);
926 CHECK_STATUS(status, NT_STATUS_OK);
929 torture_comment(torture, "Testing cancel by unlock\n");
931 torture_comment(torture, " Acquire first lock\n");
932 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE;
933 status = smb2_lock(tree, &lck);
934 CHECK_STATUS(status, NT_STATUS_OK);
936 torture_comment(torture, " Second lock should pend on first\n");
937 lck.in.file.handle = h2;
938 req = smb2_lock_send(tree, &lck);
939 WAIT_FOR_ASYNC_RESPONSE(req);
941 torture_comment(torture, " Attempt to unlock pending second lock\n");
942 lck.in.file.handle = h2;
943 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
944 status = smb2_lock(tree, &lck);
945 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
947 torture_comment(torture, " Now cancel the second lock\n");
948 smb2_cancel(req);
949 lck.in.file.handle = h2;
950 status = smb2_lock_recv(req, &lck);
951 CHECK_STATUS(status, NT_STATUS_CANCELLED);
953 torture_comment(torture, " Unlock first lock\n");
954 lck.in.file.handle = h;
955 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
956 status = smb2_lock(tree, &lck);
957 CHECK_STATUS(status, NT_STATUS_OK);
960 torture_comment(torture, "Testing cancel by close\n");
962 torture_comment(torture, " Acquire first lock\n");
963 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE;
964 status = smb2_lock(tree, &lck);
965 CHECK_STATUS(status, NT_STATUS_OK);
967 torture_comment(torture, " Second lock should pend on first\n");
968 lck.in.file.handle = h2;
969 req = smb2_lock_send(tree, &lck);
970 WAIT_FOR_ASYNC_RESPONSE(req);
972 torture_comment(torture, " Close the second lock handle\n");
973 smb2_util_close(tree, h2);
974 CHECK_STATUS(status, NT_STATUS_OK);
976 torture_comment(torture, " Check pending lock reply\n");
977 status = smb2_lock_recv(req, &lck);
978 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
980 torture_comment(torture, " Unlock first lock\n");
981 lck.in.file.handle = h;
982 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
983 status = smb2_lock(tree, &lck);
984 CHECK_STATUS(status, NT_STATUS_OK);
986 done:
987 smb2_util_close(tree, h2);
988 smb2_util_close(tree, h);
989 smb2_deltree(tree, BASEDIR);
990 return ret;
994 test SMB2 LOCK Cancel by tree disconnect
996 static bool test_cancel_tdis(struct torture_context *torture,
997 struct smb2_tree *tree)
999 NTSTATUS status;
1000 bool ret = true;
1001 struct smb2_handle h = {{0}};
1002 struct smb2_handle h2 = {{0}};
1003 uint8_t buf[200];
1004 struct smb2_lock lck;
1005 struct smb2_lock_element el[2];
1006 struct smb2_request *req = NULL;
1008 const char *fname = BASEDIR "\\cancel_tdis.txt";
1010 status = torture_smb2_testdir(tree, BASEDIR, &h);
1011 CHECK_STATUS(status, NT_STATUS_OK);
1012 smb2_util_close(tree, h);
1014 status = torture_smb2_testfile(tree, fname, &h);
1015 CHECK_STATUS(status, NT_STATUS_OK);
1017 ZERO_STRUCT(buf);
1018 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1019 CHECK_STATUS(status, NT_STATUS_OK);
1021 status = torture_smb2_testfile(tree, fname, &h2);
1022 CHECK_STATUS(status, NT_STATUS_OK);
1024 lck.in.locks = el;
1026 lck.in.lock_count = 0x0001;
1027 lck.in.lock_sequence = 0x00000000;
1028 lck.in.file.handle = h;
1029 el[0].offset = 100;
1030 el[0].length = 10;
1031 el[0].reserved = 0x00000000;
1032 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE;
1034 torture_comment(torture, "Testing cancel by tree disconnect\n");
1036 status = torture_smb2_testfile(tree, fname, &h);
1037 CHECK_STATUS(status, NT_STATUS_OK);
1039 status = torture_smb2_testfile(tree, fname, &h2);
1040 CHECK_STATUS(status, NT_STATUS_OK);
1042 torture_comment(torture, " Acquire first lock\n");
1043 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE;
1044 status = smb2_lock(tree, &lck);
1045 CHECK_STATUS(status, NT_STATUS_OK);
1047 torture_comment(torture, " Second lock should pend on first\n");
1048 lck.in.file.handle = h2;
1049 req = smb2_lock_send(tree, &lck);
1050 WAIT_FOR_ASYNC_RESPONSE(req);
1052 torture_comment(torture, " Disconnect the tree\n");
1053 smb2_tdis(tree);
1054 CHECK_STATUS(status, NT_STATUS_OK);
1056 torture_comment(torture, " Check pending lock reply\n");
1057 status = smb2_lock_recv(req, &lck);
1058 if (!NT_STATUS_EQUAL(status, NT_STATUS_RANGE_NOT_LOCKED)) {
1060 * The status depends on the server internals
1061 * the order in which the files are closed
1062 * by smb2_tdis().
1064 CHECK_STATUS(status, NT_STATUS_OK);
1067 torture_comment(torture, " Attempt to unlock first lock\n");
1068 lck.in.file.handle = h;
1069 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1070 status = smb2_lock(tree, &lck);
1072 * Most Windows versions have a strange order to
1073 * verify the session id, tree id and file id.
1074 * (They should be checked in that order, but windows
1075 * seems to check the file id before the others).
1077 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED)) {
1078 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
1081 done:
1082 smb2_util_close(tree, h2);
1083 smb2_util_close(tree, h);
1084 smb2_deltree(tree, BASEDIR);
1085 return ret;
1089 test SMB2 LOCK Cancel by user logoff
1091 static bool test_cancel_logoff(struct torture_context *torture,
1092 struct smb2_tree *tree)
1094 NTSTATUS status;
1095 bool ret = true;
1096 struct smb2_handle h = {{0}};
1097 struct smb2_handle h2 = {{0}};
1098 uint8_t buf[200];
1099 struct smb2_lock lck;
1100 struct smb2_lock_element el[2];
1101 struct smb2_request *req = NULL;
1103 const char *fname = BASEDIR "\\cancel_logoff.txt";
1105 status = torture_smb2_testdir(tree, BASEDIR, &h);
1106 CHECK_STATUS(status, NT_STATUS_OK);
1107 smb2_util_close(tree, h);
1109 status = torture_smb2_testfile(tree, fname, &h);
1110 CHECK_STATUS(status, NT_STATUS_OK);
1112 ZERO_STRUCT(buf);
1113 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1114 CHECK_STATUS(status, NT_STATUS_OK);
1116 status = torture_smb2_testfile(tree, fname, &h2);
1117 CHECK_STATUS(status, NT_STATUS_OK);
1119 lck.in.locks = el;
1121 lck.in.lock_count = 0x0001;
1122 lck.in.lock_sequence = 0x00000000;
1123 lck.in.file.handle = h;
1124 el[0].offset = 100;
1125 el[0].length = 10;
1126 el[0].reserved = 0x00000000;
1127 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE;
1129 torture_comment(torture, "Testing cancel by ulogoff\n");
1131 torture_comment(torture, " Acquire first lock\n");
1132 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE;
1133 status = smb2_lock(tree, &lck);
1134 CHECK_STATUS(status, NT_STATUS_OK);
1136 torture_comment(torture, " Second lock should pend on first\n");
1137 lck.in.file.handle = h2;
1138 req = smb2_lock_send(tree, &lck);
1139 WAIT_FOR_ASYNC_RESPONSE(req);
1141 torture_comment(torture, " Logoff user\n");
1142 smb2_logoff(tree->session);
1144 torture_comment(torture, " Check pending lock reply\n");
1145 status = smb2_lock_recv(req, &lck);
1146 if (!NT_STATUS_EQUAL(status, NT_STATUS_RANGE_NOT_LOCKED)) {
1148 * The status depends on the server internals
1149 * the order in which the files are closed
1150 * by smb2_logoff().
1152 CHECK_STATUS(status, NT_STATUS_OK);
1155 torture_comment(torture, " Attempt to unlock first lock\n");
1156 lck.in.file.handle = h;
1157 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1158 status = smb2_lock(tree, &lck);
1160 * Most Windows versions have a strange order to
1161 * verify the session id, tree id and file id.
1162 * (They should be checked in that order, but windows
1163 * seems to check the file id before the others).
1165 if (!NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
1166 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
1169 done:
1170 smb2_util_close(tree, h2);
1171 smb2_util_close(tree, h);
1172 smb2_deltree(tree, BASEDIR);
1173 return ret;
1177 * Test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
1179 * The SMBv1 protocol returns a different error code on lock acquisition
1180 * failure depending on a number of parameters, including what error code
1181 * was returned to the previous failure.
1183 * SMBv2 has cleaned up these semantics and should always return
1184 * NT_STATUS_LOCK_NOT_GRANTED to failed lock requests, and
1185 * NT_STATUS_FILE_LOCK_CONFLICT to failed read/write requests due to a lock
1186 * being held on that range.
1188 static bool test_errorcode(struct torture_context *torture,
1189 struct smb2_tree *tree)
1191 NTSTATUS status;
1192 bool ret = true;
1193 struct smb2_handle h = {{0}};
1194 struct smb2_handle h2 = {{0}};
1195 uint8_t buf[200];
1196 struct smb2_lock lck;
1197 struct smb2_lock_element el[2];
1199 const char *fname = BASEDIR "\\errorcode.txt";
1201 status = torture_smb2_testdir(tree, BASEDIR, &h);
1202 CHECK_STATUS(status, NT_STATUS_OK);
1203 smb2_util_close(tree, h);
1205 status = torture_smb2_testfile(tree, fname, &h);
1206 CHECK_STATUS(status, NT_STATUS_OK);
1208 ZERO_STRUCT(buf);
1209 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1210 CHECK_STATUS(status, NT_STATUS_OK);
1212 status = torture_smb2_testfile(tree, fname, &h2);
1213 CHECK_STATUS(status, NT_STATUS_OK);
1215 lck.in.locks = el;
1217 lck.in.lock_count = 0x0001;
1218 lck.in.lock_sequence = 0x00000000;
1219 lck.in.file.handle = h;
1220 el[0].offset = 100;
1221 el[0].length = 10;
1222 el[0].reserved = 0x00000000;
1223 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1224 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1226 torture_comment(torture, "Testing LOCK_NOT_GRANTED vs. "
1227 "FILE_LOCK_CONFLICT\n");
1229 if (TARGET_IS_W2K8(torture)) {
1230 torture_result(torture, TORTURE_SKIP,
1231 "Target has \"pretty please\" bug. A contending lock "
1232 "request on the same handle unlocks the lock.");
1233 goto done;
1236 status = smb2_lock(tree, &lck);
1237 CHECK_STATUS(status, NT_STATUS_OK);
1239 /* Demonstrate that the first conflicting lock on each handle gives
1240 * LOCK_NOT_GRANTED. */
1241 lck.in.file.handle = h;
1242 status = smb2_lock(tree, &lck);
1243 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1245 lck.in.file.handle = h2;
1246 status = smb2_lock(tree, &lck);
1247 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1249 /* Demonstrate that each following conflict also gives
1250 * LOCK_NOT_GRANTED */
1251 lck.in.file.handle = h;
1252 status = smb2_lock(tree, &lck);
1253 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1255 lck.in.file.handle = h2;
1256 status = smb2_lock(tree, &lck);
1257 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1259 lck.in.file.handle = h;
1260 status = smb2_lock(tree, &lck);
1261 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1263 lck.in.file.handle = h2;
1264 status = smb2_lock(tree, &lck);
1265 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1267 /* Demonstrate that the smbpid doesn't matter */
1268 lck.in.file.handle = h;
1269 status = smb2_lock(tree, &lck);
1270 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1272 lck.in.file.handle = h2;
1273 status = smb2_lock(tree, &lck);
1274 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1276 /* Demonstrate that a 0-byte lock inside the locked range still
1277 * gives the same error. */
1279 el[0].offset = 102;
1280 el[0].length = 0;
1281 lck.in.file.handle = h;
1282 status = smb2_lock(tree, &lck);
1283 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1285 lck.in.file.handle = h2;
1286 status = smb2_lock(tree, &lck);
1287 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1289 /* Demonstrate that a lock inside the locked range still gives the
1290 * same error. */
1292 el[0].offset = 102;
1293 el[0].length = 5;
1294 lck.in.file.handle = h;
1295 status = smb2_lock(tree, &lck);
1296 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1298 lck.in.file.handle = h2;
1299 status = smb2_lock(tree, &lck);
1300 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1302 done:
1303 smb2_util_close(tree, h2);
1304 smb2_util_close(tree, h);
1305 smb2_deltree(tree, BASEDIR);
1306 return ret;
1310 * Tests zero byte locks.
1313 struct double_lock_test {
1314 struct smb2_lock_element lock1;
1315 struct smb2_lock_element lock2;
1316 NTSTATUS status;
1319 static struct double_lock_test zero_byte_tests[] = {
1320 /* {offset, count, reserved, flags},
1321 * {offset, count, reserved, flags},
1322 * status */
1324 /** First, takes a zero byte lock at offset 10. Then:
1325 * - Taking 0 byte lock at 10 should succeed.
1326 * - Taking 1 byte locks at 9,10,11 should succeed.
1327 * - Taking 2 byte lock at 9 should fail.
1328 * - Taking 2 byte lock at 10 should succeed.
1329 * - Taking 3 byte lock at 9 should fail.
1331 {{10, 0, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1332 {{10, 0, 0, 0}, {9, 1, 0, 0}, NT_STATUS_OK},
1333 {{10, 0, 0, 0}, {10, 1, 0, 0}, NT_STATUS_OK},
1334 {{10, 0, 0, 0}, {11, 1, 0, 0}, NT_STATUS_OK},
1335 {{10, 0, 0, 0}, {9, 2, 0, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1336 {{10, 0, 0, 0}, {10, 2, 0, 0}, NT_STATUS_OK},
1337 {{10, 0, 0, 0}, {9, 3, 0, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1339 /** Same, but opposite order. */
1340 {{10, 0, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1341 {{9, 1, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1342 {{10, 1, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1343 {{11, 1, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1344 {{9, 2, 0, 0}, {10, 0, 0, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1345 {{10, 2, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1346 {{9, 3, 0, 0}, {10, 0, 0, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1348 /** Zero zero case. */
1349 {{0, 0, 0, 0}, {0, 0, 0, 0}, NT_STATUS_OK},
1352 static bool test_zerobytelength(struct torture_context *torture,
1353 struct smb2_tree *tree)
1355 NTSTATUS status;
1356 bool ret = true;
1357 struct smb2_handle h = {{0}};
1358 struct smb2_handle h2 = {{0}};
1359 uint8_t buf[200];
1360 struct smb2_lock lck;
1361 int i;
1363 const char *fname = BASEDIR "\\zero.txt";
1365 torture_comment(torture, "Testing zero length byte range locks:\n");
1367 status = torture_smb2_testdir(tree, BASEDIR, &h);
1368 CHECK_STATUS(status, NT_STATUS_OK);
1369 smb2_util_close(tree, h);
1371 status = torture_smb2_testfile(tree, fname, &h);
1372 CHECK_STATUS(status, NT_STATUS_OK);
1374 ZERO_STRUCT(buf);
1375 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1376 CHECK_STATUS(status, NT_STATUS_OK);
1378 status = torture_smb2_testfile(tree, fname, &h2);
1379 CHECK_STATUS(status, NT_STATUS_OK);
1381 /* Setup initial parameters */
1382 lck.in.lock_count = 0x0001;
1383 lck.in.lock_sequence = 0x00000000;
1384 lck.in.file.handle = h;
1386 /* Try every combination of locks in zero_byte_tests, using the same
1387 * handle for both locks. The first lock is assumed to succeed. The
1388 * second lock may contend, depending on the expected status. */
1389 for (i = 0; i < ARRAY_SIZE(zero_byte_tests); i++) {
1390 torture_comment(torture,
1391 " ... {%llu, %llu} + {%llu, %llu} = %s\n",
1392 (unsigned long long) zero_byte_tests[i].lock1.offset,
1393 (unsigned long long) zero_byte_tests[i].lock1.length,
1394 (unsigned long long) zero_byte_tests[i].lock2.offset,
1395 (unsigned long long) zero_byte_tests[i].lock2.length,
1396 nt_errstr(zero_byte_tests[i].status));
1398 /* Lock both locks. */
1399 lck.in.locks = &zero_byte_tests[i].lock1;
1400 lck.in.locks[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1401 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1402 status = smb2_lock(tree, &lck);
1403 CHECK_STATUS(status, NT_STATUS_OK);
1405 lck.in.locks = &zero_byte_tests[i].lock2;
1406 lck.in.locks[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1407 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1408 status = smb2_lock(tree, &lck);
1409 CHECK_STATUS_CONT(status, zero_byte_tests[i].status);
1411 /* Unlock both locks in reverse order. */
1412 lck.in.locks[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1413 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1414 status = smb2_lock(tree, &lck);
1415 CHECK_STATUS(status, NT_STATUS_OK);
1418 lck.in.locks = &zero_byte_tests[i].lock1;
1419 lck.in.locks[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1420 status = smb2_lock(tree, &lck);
1421 CHECK_STATUS(status, NT_STATUS_OK);
1424 /* Try every combination of locks in zero_byte_tests, using two
1425 * different handles. */
1426 for (i = 0; i < ARRAY_SIZE(zero_byte_tests); i++) {
1427 torture_comment(torture,
1428 " ... {%llu, %llu} + {%llu, %llu} = %s\n",
1429 (unsigned long long) zero_byte_tests[i].lock1.offset,
1430 (unsigned long long) zero_byte_tests[i].lock1.length,
1431 (unsigned long long) zero_byte_tests[i].lock2.offset,
1432 (unsigned long long) zero_byte_tests[i].lock2.length,
1433 nt_errstr(zero_byte_tests[i].status));
1435 /* Lock both locks. */
1436 lck.in.file.handle = h;
1437 lck.in.locks = &zero_byte_tests[i].lock1;
1438 lck.in.locks[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1439 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1440 status = smb2_lock(tree, &lck);
1441 CHECK_STATUS(status, NT_STATUS_OK);
1443 lck.in.file.handle = h2;
1444 lck.in.locks = &zero_byte_tests[i].lock2;
1445 lck.in.locks[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1446 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1447 status = smb2_lock(tree, &lck);
1448 CHECK_STATUS_CONT(status, zero_byte_tests[i].status);
1450 /* Unlock both locks in reverse order. */
1451 lck.in.file.handle = h2;
1452 lck.in.locks[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1453 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1454 status = smb2_lock(tree, &lck);
1455 CHECK_STATUS(status, NT_STATUS_OK);
1458 lck.in.file.handle = h;
1459 lck.in.locks = &zero_byte_tests[i].lock1;
1460 lck.in.locks[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1461 status = smb2_lock(tree, &lck);
1462 CHECK_STATUS(status, NT_STATUS_OK);
1465 done:
1466 smb2_util_close(tree, h2);
1467 smb2_util_close(tree, h);
1468 smb2_deltree(tree, BASEDIR);
1469 return ret;
1472 static bool test_zerobyteread(struct torture_context *torture,
1473 struct smb2_tree *tree)
1475 NTSTATUS status;
1476 bool ret = true;
1477 struct smb2_handle h = {{0}};
1478 struct smb2_handle h2 = {{0}};
1479 uint8_t buf[200];
1480 struct smb2_lock lck;
1481 struct smb2_lock_element el[1];
1482 struct smb2_read rd;
1484 const char *fname = BASEDIR "\\zerobyteread.txt";
1486 status = torture_smb2_testdir(tree, BASEDIR, &h);
1487 CHECK_STATUS(status, NT_STATUS_OK);
1488 smb2_util_close(tree, h);
1490 status = torture_smb2_testfile(tree, fname, &h);
1491 CHECK_STATUS(status, NT_STATUS_OK);
1493 ZERO_STRUCT(buf);
1494 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1495 CHECK_STATUS(status, NT_STATUS_OK);
1497 status = torture_smb2_testfile(tree, fname, &h2);
1498 CHECK_STATUS(status, NT_STATUS_OK);
1500 /* Setup initial parameters */
1501 lck.in.locks = el;
1502 lck.in.lock_count = 0x0001;
1503 lck.in.lock_sequence = 0x00000000;
1504 lck.in.file.handle = h;
1506 ZERO_STRUCT(rd);
1507 rd.in.file.handle = h2;
1509 torture_comment(torture, "Testing zero byte read on lock range:\n");
1511 /* Take an exclusive lock */
1512 torture_comment(torture, " taking exclusive lock.\n");
1513 el[0].offset = 0;
1514 el[0].length = 10;
1515 el[0].reserved = 0x00000000;
1516 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1517 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1518 status = smb2_lock(tree, &lck);
1519 CHECK_STATUS(status, NT_STATUS_OK);
1520 CHECK_VALUE(lck.out.reserved, 0);
1522 /* Try a zero byte read */
1523 torture_comment(torture, " reading 0 bytes.\n");
1524 rd.in.offset = 5;
1525 rd.in.length = 0;
1526 status = smb2_read(tree, tree, &rd);
1527 torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done,
1528 "zero byte read did not return 0 bytes");
1529 CHECK_STATUS(status, NT_STATUS_OK);
1531 /* Unlock lock */
1532 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1533 status = smb2_lock(tree, &lck);
1534 CHECK_STATUS(status, NT_STATUS_OK);
1535 CHECK_VALUE(lck.out.reserved, 0);
1537 torture_comment(torture, "Testing zero byte read on zero byte lock "
1538 "range:\n");
1540 /* Take an exclusive lock */
1541 torture_comment(torture, " taking exclusive 0-byte lock.\n");
1542 el[0].offset = 5;
1543 el[0].length = 0;
1544 el[0].reserved = 0x00000000;
1545 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1546 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1547 status = smb2_lock(tree, &lck);
1548 CHECK_STATUS(status, NT_STATUS_OK);
1549 CHECK_VALUE(lck.out.reserved, 0);
1551 /* Try a zero byte read before the lock */
1552 torture_comment(torture, " reading 0 bytes before the lock.\n");
1553 rd.in.offset = 4;
1554 rd.in.length = 0;
1555 status = smb2_read(tree, tree, &rd);
1556 torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done,
1557 "zero byte read did not return 0 bytes");
1558 CHECK_STATUS(status, NT_STATUS_OK);
1560 /* Try a zero byte read on the lock */
1561 torture_comment(torture, " reading 0 bytes on the lock.\n");
1562 rd.in.offset = 5;
1563 rd.in.length = 0;
1564 status = smb2_read(tree, tree, &rd);
1565 torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done,
1566 "zero byte read did not return 0 bytes");
1567 CHECK_STATUS(status, NT_STATUS_OK);
1569 /* Try a zero byte read after the lock */
1570 torture_comment(torture, " reading 0 bytes after the lock.\n");
1571 rd.in.offset = 6;
1572 rd.in.length = 0;
1573 status = smb2_read(tree, tree, &rd);
1574 torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done,
1575 "zero byte read did not return 0 bytes");
1576 CHECK_STATUS(status, NT_STATUS_OK);
1578 /* Unlock lock */
1579 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1580 status = smb2_lock(tree, &lck);
1581 CHECK_STATUS(status, NT_STATUS_OK);
1582 CHECK_VALUE(lck.out.reserved, 0);
1584 done:
1585 smb2_util_close(tree, h2);
1586 smb2_util_close(tree, h);
1587 smb2_deltree(tree, BASEDIR);
1588 return ret;
1591 static bool test_unlock(struct torture_context *torture,
1592 struct smb2_tree *tree)
1594 NTSTATUS status;
1595 bool ret = true;
1596 struct smb2_handle h = {{0}};
1597 struct smb2_handle h2 = {{0}};
1598 uint8_t buf[200];
1599 struct smb2_lock lck;
1600 struct smb2_lock_element el1[1];
1601 struct smb2_lock_element el2[1];
1603 const char *fname = BASEDIR "\\unlock.txt";
1605 status = torture_smb2_testdir(tree, BASEDIR, &h);
1606 CHECK_STATUS(status, NT_STATUS_OK);
1607 smb2_util_close(tree, h);
1609 status = torture_smb2_testfile(tree, fname, &h);
1610 CHECK_STATUS(status, NT_STATUS_OK);
1612 ZERO_STRUCT(buf);
1613 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1614 CHECK_STATUS(status, NT_STATUS_OK);
1616 status = torture_smb2_testfile(tree, fname, &h2);
1617 CHECK_STATUS(status, NT_STATUS_OK);
1619 /* Setup initial parameters */
1620 lck.in.locks = el1;
1621 lck.in.lock_count = 0x0001;
1622 lck.in.lock_sequence = 0x00000000;
1623 el1[0].offset = 0;
1624 el1[0].length = 10;
1625 el1[0].reserved = 0x00000000;
1627 /* Take exclusive lock, then unlock it with a shared-unlock call. */
1629 torture_comment(torture, "Testing unlock exclusive with shared\n");
1631 torture_comment(torture, " taking exclusive lock.\n");
1632 lck.in.file.handle = h;
1633 el1[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE;
1634 status = smb2_lock(tree, &lck);
1635 CHECK_STATUS(status, NT_STATUS_OK);
1637 torture_comment(torture, " try to unlock the exclusive with a shared "
1638 "unlock call.\n");
1639 el1[0].flags = SMB2_LOCK_FLAG_SHARED |
1640 SMB2_LOCK_FLAG_UNLOCK;
1641 status = smb2_lock(tree, &lck);
1642 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1644 torture_comment(torture, " try shared lock on h2, to test the "
1645 "unlock.\n");
1646 lck.in.file.handle = h2;
1647 el1[0].flags = SMB2_LOCK_FLAG_SHARED |
1648 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1649 status = smb2_lock(tree, &lck);
1650 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1652 torture_comment(torture, " unlock the exclusive lock\n");
1653 lck.in.file.handle = h;
1654 el1[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1655 status = smb2_lock(tree, &lck);
1656 CHECK_STATUS(status, NT_STATUS_OK);
1658 /* Unlock a shared lock with an exclusive-unlock call. */
1660 torture_comment(torture, "Testing unlock shared with exclusive\n");
1662 torture_comment(torture, " taking shared lock.\n");
1663 lck.in.file.handle = h;
1664 el1[0].flags = SMB2_LOCK_FLAG_SHARED;
1665 status = smb2_lock(tree, &lck);
1666 CHECK_STATUS(status, NT_STATUS_OK);
1668 torture_comment(torture, " try to unlock the shared with an exclusive "
1669 "unlock call.\n");
1670 el1[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1671 SMB2_LOCK_FLAG_UNLOCK;
1672 status = smb2_lock(tree, &lck);
1673 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1675 torture_comment(torture, " try exclusive lock on h2, to test the "
1676 "unlock.\n");
1677 lck.in.file.handle = h2;
1678 el1[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1679 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1680 status = smb2_lock(tree, &lck);
1681 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1683 torture_comment(torture, " unlock the exclusive lock\n");
1684 lck.in.file.handle = h;
1685 el1[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1686 status = smb2_lock(tree, &lck);
1687 CHECK_STATUS(status, NT_STATUS_OK);
1689 /* Test unlocking of stacked 0-byte locks. SMB2 0-byte lock behavior
1690 * should be the same as >0-byte behavior. Exclusive locks should be
1691 * unlocked before shared. */
1693 torture_comment(torture, "Test unlocking stacked 0-byte locks\n");
1695 lck.in.locks = el1;
1696 lck.in.file.handle = h;
1697 el1[0].offset = 10;
1698 el1[0].length = 0;
1699 el1[0].reserved = 0x00000000;
1700 el2[0].offset = 5;
1701 el2[0].length = 10;
1702 el2[0].reserved = 0x00000000;
1704 /* lock 0-byte exclusive */
1705 el1[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1706 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1707 status = smb2_lock(tree, &lck);
1708 CHECK_STATUS(status, NT_STATUS_OK);
1710 /* lock 0-byte shared */
1711 el1[0].flags = SMB2_LOCK_FLAG_SHARED |
1712 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1713 status = smb2_lock(tree, &lck);
1714 CHECK_STATUS(status, NT_STATUS_OK);
1716 /* test contention */
1717 lck.in.locks = el2;
1718 lck.in.file.handle = h2;
1719 el2[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1720 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1721 status = smb2_lock(tree, &lck);
1722 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1724 lck.in.locks = el2;
1725 lck.in.file.handle = h2;
1726 el2[0].flags = SMB2_LOCK_FLAG_SHARED |
1727 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1728 status = smb2_lock(tree, &lck);
1729 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1731 /* unlock */
1732 lck.in.locks = el1;
1733 lck.in.file.handle = h;
1734 el1[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1735 status = smb2_lock(tree, &lck);
1736 CHECK_STATUS(status, NT_STATUS_OK);
1738 /* test - can we take a shared lock? */
1739 lck.in.locks = el2;
1740 lck.in.file.handle = h2;
1741 el2[0].flags = SMB2_LOCK_FLAG_SHARED |
1742 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1743 status = smb2_lock(tree, &lck);
1744 CHECK_STATUS(status, NT_STATUS_OK);
1746 el2[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1747 status = smb2_lock(tree, &lck);
1748 CHECK_STATUS(status, NT_STATUS_OK);
1750 /* cleanup */
1751 lck.in.locks = el1;
1752 lck.in.file.handle = h;
1753 el1[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1754 status = smb2_lock(tree, &lck);
1755 CHECK_STATUS(status, NT_STATUS_OK);
1757 /* Test unlocking of stacked exclusive, shared locks. Exclusive
1758 * should be unlocked before any shared. */
1760 torture_comment(torture, "Test unlocking stacked exclusive/shared "
1761 "locks\n");
1763 lck.in.locks = el1;
1764 lck.in.file.handle = h;
1765 el1[0].offset = 10;
1766 el1[0].length = 10;
1767 el1[0].reserved = 0x00000000;
1768 el2[0].offset = 5;
1769 el2[0].length = 10;
1770 el2[0].reserved = 0x00000000;
1772 /* lock exclusive */
1773 el1[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1774 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1775 status = smb2_lock(tree, &lck);
1776 CHECK_STATUS(status, NT_STATUS_OK);
1778 /* lock shared */
1779 el1[0].flags = SMB2_LOCK_FLAG_SHARED |
1780 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1781 status = smb2_lock(tree, &lck);
1782 CHECK_STATUS(status, NT_STATUS_OK);
1784 /* test contention */
1785 lck.in.locks = el2;
1786 lck.in.file.handle = h2;
1787 el2[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1788 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1789 status = smb2_lock(tree, &lck);
1790 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1792 lck.in.locks = el2;
1793 lck.in.file.handle = h2;
1794 el2[0].flags = SMB2_LOCK_FLAG_SHARED |
1795 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1796 status = smb2_lock(tree, &lck);
1797 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1799 /* unlock */
1800 lck.in.locks = el1;
1801 lck.in.file.handle = h;
1802 el1[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1803 status = smb2_lock(tree, &lck);
1804 CHECK_STATUS(status, NT_STATUS_OK);
1806 /* test - can we take a shared lock? */
1807 lck.in.locks = el2;
1808 lck.in.file.handle = h2;
1809 el2[0].flags = SMB2_LOCK_FLAG_SHARED |
1810 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1811 status = smb2_lock(tree, &lck);
1812 CHECK_STATUS(status, NT_STATUS_OK);
1814 el2[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1815 status = smb2_lock(tree, &lck);
1816 CHECK_STATUS(status, NT_STATUS_OK);
1818 /* cleanup */
1819 lck.in.locks = el1;
1820 lck.in.file.handle = h;
1821 el1[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1822 status = smb2_lock(tree, &lck);
1823 CHECK_STATUS(status, NT_STATUS_OK);
1825 done:
1826 smb2_util_close(tree, h2);
1827 smb2_util_close(tree, h);
1828 smb2_deltree(tree, BASEDIR);
1829 return ret;
1832 static bool test_multiple_unlock(struct torture_context *torture,
1833 struct smb2_tree *tree)
1835 NTSTATUS status;
1836 bool ret = true;
1837 struct smb2_handle h;
1838 uint8_t buf[200];
1839 struct smb2_lock lck;
1840 struct smb2_lock_element el[2];
1842 const char *fname = BASEDIR "\\unlock_multiple.txt";
1844 status = torture_smb2_testdir(tree, BASEDIR, &h);
1845 CHECK_STATUS(status, NT_STATUS_OK);
1846 smb2_util_close(tree, h);
1848 status = torture_smb2_testfile(tree, fname, &h);
1849 CHECK_STATUS(status, NT_STATUS_OK);
1851 ZERO_STRUCT(buf);
1852 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1853 CHECK_STATUS(status, NT_STATUS_OK);
1855 torture_comment(torture, "Testing multiple unlocks:\n");
1857 /* Setup initial parameters */
1858 lck.in.lock_count = 0x0002;
1859 lck.in.lock_sequence = 0x00000000;
1860 lck.in.file.handle = h;
1861 el[0].offset = 0;
1862 el[0].length = 10;
1863 el[0].reserved = 0x00000000;
1864 el[1].offset = 10;
1865 el[1].length = 10;
1866 el[1].reserved = 0x00000000;
1868 /* Test1: Acquire second lock, but not first. */
1869 torture_comment(torture, " unlock 2 locks, first one not locked. "
1870 "Expect no locks unlocked. \n");
1872 lck.in.lock_count = 0x0001;
1873 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1874 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1875 lck.in.locks = &el[1];
1876 status = smb2_lock(tree, &lck);
1877 CHECK_STATUS(status, NT_STATUS_OK);
1879 /* Try to unlock both locks */
1880 lck.in.lock_count = 0x0002;
1881 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1882 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
1883 lck.in.locks = el;
1884 status = smb2_lock(tree, &lck);
1885 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1887 /* Second lock should not be unlocked. */
1888 lck.in.lock_count = 0x0001;
1889 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1890 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1891 lck.in.locks = &el[1];
1892 status = smb2_lock(tree, &lck);
1893 if (TARGET_IS_W2K8(torture)) {
1894 CHECK_STATUS(status, NT_STATUS_OK);
1895 torture_warning(torture, "Target has \"pretty please\" bug. "
1896 "A contending lock request on the same handle "
1897 "unlocks the lock.\n");
1898 } else {
1899 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1902 /* cleanup */
1903 lck.in.lock_count = 0x0001;
1904 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
1905 lck.in.locks = &el[1];
1906 status = smb2_lock(tree, &lck);
1907 CHECK_STATUS(status, NT_STATUS_OK);
1909 /* Test2: Acquire first lock, but not second. */
1910 torture_comment(torture, " unlock 2 locks, second one not locked. "
1911 "Expect first lock unlocked.\n");
1913 lck.in.lock_count = 0x0001;
1914 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1915 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1916 lck.in.locks = &el[0];
1917 status = smb2_lock(tree, &lck);
1918 CHECK_STATUS(status, NT_STATUS_OK);
1920 /* Try to unlock both locks */
1921 lck.in.lock_count = 0x0002;
1922 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1923 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
1924 lck.in.locks = el;
1925 status = smb2_lock(tree, &lck);
1926 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1928 /* First lock should be unlocked. */
1929 lck.in.lock_count = 0x0001;
1930 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1931 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1932 lck.in.locks = &el[0];
1933 status = smb2_lock(tree, &lck);
1934 CHECK_STATUS(status, NT_STATUS_OK);
1936 /* cleanup */
1937 lck.in.lock_count = 0x0001;
1938 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1939 lck.in.locks = &el[0];
1940 status = smb2_lock(tree, &lck);
1941 CHECK_STATUS(status, NT_STATUS_OK);
1943 /* Test3: Request 2 locks, second will contend. What happens to the
1944 * first? */
1945 torture_comment(torture, " request 2 locks, second one will contend. "
1946 "Expect both to fail.\n");
1948 /* Lock the second range */
1949 lck.in.lock_count = 0x0001;
1950 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1951 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1952 lck.in.locks = &el[1];
1953 status = smb2_lock(tree, &lck);
1954 CHECK_STATUS(status, NT_STATUS_OK);
1956 /* Request both locks */
1957 lck.in.lock_count = 0x0002;
1958 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1959 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1960 lck.in.locks = el;
1961 status = smb2_lock(tree, &lck);
1962 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1964 /* First lock should be unlocked. */
1965 lck.in.lock_count = 0x0001;
1966 lck.in.locks = &el[0];
1967 status = smb2_lock(tree, &lck);
1968 CHECK_STATUS(status, NT_STATUS_OK);
1970 /* cleanup */
1971 if (TARGET_IS_W2K8(torture)) {
1972 lck.in.lock_count = 0x0001;
1973 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1974 lck.in.locks = &el[0];
1975 status = smb2_lock(tree, &lck);
1976 CHECK_STATUS(status, NT_STATUS_OK);
1977 torture_warning(torture, "Target has \"pretty please\" bug. "
1978 "A contending lock request on the same handle "
1979 "unlocks the lock.\n");
1980 } else {
1981 lck.in.lock_count = 0x0002;
1982 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
1983 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
1984 lck.in.locks = el;
1985 status = smb2_lock(tree, &lck);
1986 CHECK_STATUS(status, NT_STATUS_OK);
1989 /* Test4: Request unlock and lock. The lock contends, is the unlock
1990 * then relocked? SMB2 doesn't like the lock and unlock requests in the
1991 * same packet. The unlock will succeed, but the lock will return
1992 * INVALID_PARAMETER. This behavior is described in MS-SMB2
1993 * 3.3.5.14.1 */
1994 torture_comment(torture, " request unlock and lock, second one will "
1995 "error. Expect the unlock to succeed.\n");
1997 /* Lock both ranges */
1998 lck.in.lock_count = 0x0002;
1999 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2000 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2001 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2002 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2003 lck.in.locks = el;
2004 status = smb2_lock(tree, &lck);
2005 CHECK_STATUS(status, NT_STATUS_OK);
2007 /* Attempt to unlock the first range and lock the second. The lock
2008 * request will error. */
2009 lck.in.lock_count = 0x0002;
2010 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2011 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2012 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2013 lck.in.locks = el;
2014 status = smb2_lock(tree, &lck);
2015 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
2017 /* The first lock should've been unlocked */
2018 lck.in.lock_count = 0x0001;
2019 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2020 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2021 lck.in.locks = &el[0];
2022 status = smb2_lock(tree, &lck);
2023 CHECK_STATUS(status, NT_STATUS_OK);
2025 /* cleanup */
2026 lck.in.lock_count = 0x0002;
2027 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2028 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
2029 lck.in.locks = el;
2030 status = smb2_lock(tree, &lck);
2031 CHECK_STATUS(status, NT_STATUS_OK);
2033 /* Test10: SMB2 only test. Request unlock and lock in same packet.
2034 * Neither contend. SMB2 doesn't like lock and unlock requests in the
2035 * same packet. The unlock will succeed, but the lock will return
2036 * INVALID_PARAMETER. */
2037 torture_comment(torture, " request unlock and lock. Unlock will "
2038 "succeed, but lock will fail.\n");
2040 /* Lock first range */
2041 lck.in.lock_count = 0x0001;
2042 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2043 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2044 lck.in.locks = &el[0];
2045 status = smb2_lock(tree, &lck);
2046 CHECK_STATUS(status, NT_STATUS_OK);
2048 /* Attempt to unlock the first range and lock the second */
2049 lck.in.lock_count = 0x0002;
2050 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2051 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2052 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2053 lck.in.locks = el;
2054 status = smb2_lock(tree, &lck);
2055 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
2057 /* Neither lock should still be locked */
2058 lck.in.lock_count = 0x0002;
2059 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2060 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2061 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2062 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2063 lck.in.locks = el;
2064 status = smb2_lock(tree, &lck);
2065 CHECK_STATUS(status, NT_STATUS_OK);
2067 /* cleanup */
2068 lck.in.lock_count = 0x0002;
2069 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2070 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
2071 lck.in.locks = el;
2072 status = smb2_lock(tree, &lck);
2073 CHECK_STATUS(status, NT_STATUS_OK);
2075 /* Test11: SMB2 only test. Request lock and unlock in same packet.
2076 * Neither contend. SMB2 doesn't like lock and unlock requests in the
2077 * same packet. The lock will succeed, the unlock will fail with
2078 * INVALID_PARAMETER, and the lock will be unlocked before return. */
2079 torture_comment(torture, " request lock and unlock. Both will "
2080 "fail.\n");
2082 /* Lock second range */
2083 lck.in.lock_count = 0x0001;
2084 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2085 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2086 lck.in.locks = &el[1];
2087 status = smb2_lock(tree, &lck);
2088 CHECK_STATUS(status, NT_STATUS_OK);
2090 /* Attempt to lock the first range and unlock the second */
2091 lck.in.lock_count = 0x0002;
2092 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2093 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2094 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
2095 lck.in.locks = el;
2096 status = smb2_lock(tree, &lck);
2097 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
2099 /* First range should be unlocked, second locked. */
2100 lck.in.lock_count = 0x0001;
2101 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2102 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2103 lck.in.locks = &el[0];
2104 status = smb2_lock(tree, &lck);
2105 CHECK_STATUS(status, NT_STATUS_OK);
2107 lck.in.lock_count = 0x0001;
2108 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2109 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2110 lck.in.locks = &el[1];
2111 status = smb2_lock(tree, &lck);
2112 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
2114 /* cleanup */
2115 if (TARGET_IS_W2K8(torture)) {
2116 lck.in.lock_count = 0x0001;
2117 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2118 lck.in.locks = &el[0];
2119 status = smb2_lock(tree, &lck);
2120 CHECK_STATUS(status, NT_STATUS_OK);
2121 torture_warning(torture, "Target has \"pretty please\" bug. "
2122 "A contending lock request on the same handle "
2123 "unlocks the lock.\n");
2124 } else {
2125 lck.in.lock_count = 0x0002;
2126 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2127 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
2128 lck.in.locks = el;
2129 status = smb2_lock(tree, &lck);
2130 CHECK_STATUS(status, NT_STATUS_OK);
2133 done:
2134 smb2_util_close(tree, h);
2135 smb2_deltree(tree, BASEDIR);
2136 return ret;
2140 * Test lock stacking
2141 * - some tests ported from BASE-LOCK-LOCK5
2143 static bool test_stacking(struct torture_context *torture,
2144 struct smb2_tree *tree)
2146 NTSTATUS status;
2147 bool ret = true;
2148 struct smb2_handle h = {{0}};
2149 struct smb2_handle h2 = {{0}};
2150 uint8_t buf[200];
2151 struct smb2_lock lck;
2152 struct smb2_lock_element el[1];
2154 const char *fname = BASEDIR "\\stacking.txt";
2156 status = torture_smb2_testdir(tree, BASEDIR, &h);
2157 CHECK_STATUS(status, NT_STATUS_OK);
2158 smb2_util_close(tree, h);
2160 status = torture_smb2_testfile(tree, fname, &h);
2161 CHECK_STATUS(status, NT_STATUS_OK);
2163 ZERO_STRUCT(buf);
2164 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2165 CHECK_STATUS(status, NT_STATUS_OK);
2167 status = torture_smb2_testfile(tree, fname, &h2);
2168 CHECK_STATUS(status, NT_STATUS_OK);
2170 torture_comment(torture, "Testing lock stacking:\n");
2172 /* Setup initial parameters */
2173 lck.in.locks = el;
2174 lck.in.lock_count = 0x0001;
2175 lck.in.lock_sequence = 0x00000000;
2176 lck.in.file.handle = h;
2177 el[0].offset = 0;
2178 el[0].length = 10;
2179 el[0].reserved = 0x00000000;
2181 /* Try to take a shared lock, then a shared lock on same handle */
2182 torture_comment(torture, " stacking a shared on top of a shared"
2183 "lock succeeds.\n");
2185 el[0].flags = SMB2_LOCK_FLAG_SHARED |
2186 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2187 status = smb2_lock(tree, &lck);
2188 CHECK_STATUS(status, NT_STATUS_OK);
2190 el[0].flags = SMB2_LOCK_FLAG_SHARED |
2191 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2192 status = smb2_lock(tree, &lck);
2193 CHECK_STATUS(status, NT_STATUS_OK);
2195 /* cleanup */
2196 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2197 status = smb2_lock(tree, &lck);
2198 CHECK_STATUS(status, NT_STATUS_OK);
2200 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2201 status = smb2_lock(tree, &lck);
2202 CHECK_STATUS(status, NT_STATUS_OK);
2205 /* Try to take an exclusive lock, then a shared lock on same handle */
2206 torture_comment(torture, " stacking a shared on top of an exclusive "
2207 "lock succeeds.\n");
2209 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2210 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2211 status = smb2_lock(tree, &lck);
2212 CHECK_STATUS(status, NT_STATUS_OK);
2214 el[0].flags = SMB2_LOCK_FLAG_SHARED |
2215 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2216 status = smb2_lock(tree, &lck);
2217 CHECK_STATUS(status, NT_STATUS_OK);
2219 el[0].flags = SMB2_LOCK_FLAG_SHARED |
2220 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2221 status = smb2_lock(tree, &lck);
2222 CHECK_STATUS(status, NT_STATUS_OK);
2224 /* stacking a shared from a different handle should fail */
2225 lck.in.file.handle = h2;
2226 el[0].flags = SMB2_LOCK_FLAG_SHARED |
2227 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2228 status = smb2_lock(tree, &lck);
2229 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
2231 /* cleanup */
2232 lck.in.file.handle = h;
2233 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2234 status = smb2_lock(tree, &lck);
2235 CHECK_STATUS(status, NT_STATUS_OK);
2237 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2238 status = smb2_lock(tree, &lck);
2239 CHECK_STATUS(status, NT_STATUS_OK);
2241 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2242 status = smb2_lock(tree, &lck);
2243 CHECK_STATUS(status, NT_STATUS_OK);
2245 /* ensure the 4th unlock fails */
2246 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2247 status = smb2_lock(tree, &lck);
2248 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
2250 /* ensure a second handle can now take an exclusive lock */
2251 lck.in.file.handle = h2;
2252 el[0].flags = SMB2_LOCK_FLAG_SHARED |
2253 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2254 status = smb2_lock(tree, &lck);
2255 CHECK_STATUS(status, NT_STATUS_OK);
2257 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2258 status = smb2_lock(tree, &lck);
2259 CHECK_STATUS(status, NT_STATUS_OK);
2261 /* Try to take an exclusive lock, then a shared lock on a
2262 * different handle */
2263 torture_comment(torture, " stacking a shared on top of an exclusive "
2264 "lock with different handles fails.\n");
2266 lck.in.file.handle = h;
2267 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2268 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2269 status = smb2_lock(tree, &lck);
2270 CHECK_STATUS(status, NT_STATUS_OK);
2272 lck.in.file.handle = h2;
2273 el[0].flags = SMB2_LOCK_FLAG_SHARED |
2274 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2275 status = smb2_lock(tree, &lck);
2276 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
2278 /* cleanup */
2279 lck.in.file.handle = h;
2280 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2281 status = smb2_lock(tree, &lck);
2282 CHECK_STATUS(status, NT_STATUS_OK);
2284 /* Try to take a shared lock, then stack an exclusive with same
2285 * handle. */
2286 torture_comment(torture, " stacking an exclusive on top of a shared "
2287 "lock fails.\n");
2289 el[0].flags = SMB2_LOCK_FLAG_SHARED |
2290 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2291 status = smb2_lock(tree, &lck);
2292 CHECK_STATUS(status, NT_STATUS_OK);
2294 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2295 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2296 status = smb2_lock(tree, &lck);
2297 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
2299 /* cleanup */
2300 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2301 status = smb2_lock(tree, &lck);
2302 if (TARGET_IS_W2K8(torture)) {
2303 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
2304 torture_warning(torture, "Target has \"pretty please\" bug. "
2305 "A contending lock request on the same handle "
2306 "unlocks the lock.\n");
2307 } else {
2308 CHECK_STATUS(status, NT_STATUS_OK);
2311 /* Prove that two exclusive locks do not stack on the same handle. */
2312 torture_comment(torture, " two exclusive locks do not stack.\n");
2314 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2315 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2316 status = smb2_lock(tree, &lck);
2317 CHECK_STATUS(status, NT_STATUS_OK);
2319 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2320 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2321 status = smb2_lock(tree, &lck);
2322 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
2324 /* cleanup */
2325 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2326 status = smb2_lock(tree, &lck);
2327 if (TARGET_IS_W2K8(torture)) {
2328 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
2329 torture_warning(torture, "Target has \"pretty please\" bug. "
2330 "A contending lock request on the same handle "
2331 "unlocks the lock.\n");
2332 } else {
2333 CHECK_STATUS(status, NT_STATUS_OK);
2336 done:
2337 smb2_util_close(tree, h2);
2338 smb2_util_close(tree, h);
2339 smb2_deltree(tree, BASEDIR);
2340 return ret;
2344 * Test lock contention
2345 * - shared lock should contend with exclusive lock on different handle
2347 static bool test_contend(struct torture_context *torture,
2348 struct smb2_tree *tree)
2350 NTSTATUS status;
2351 bool ret = true;
2352 struct smb2_handle h = {{0}};
2353 struct smb2_handle h2 = {{0}};
2354 uint8_t buf[200];
2355 struct smb2_lock lck;
2356 struct smb2_lock_element el[1];
2358 const char *fname = BASEDIR "\\contend.txt";
2360 status = torture_smb2_testdir(tree, BASEDIR, &h);
2361 CHECK_STATUS(status, NT_STATUS_OK);
2362 smb2_util_close(tree, h);
2364 status = torture_smb2_testfile(tree, fname, &h);
2365 CHECK_STATUS(status, NT_STATUS_OK);
2367 ZERO_STRUCT(buf);
2368 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2369 CHECK_STATUS(status, NT_STATUS_OK);
2371 status = torture_smb2_testfile(tree, fname, &h2);
2372 CHECK_STATUS(status, NT_STATUS_OK);
2374 torture_comment(torture, "Testing lock contention:\n");
2376 /* Setup initial parameters */
2377 lck.in.locks = el;
2378 lck.in.lock_count = 0x0001;
2379 lck.in.lock_sequence = 0x00000000;
2380 lck.in.file.handle = h;
2381 el[0].offset = 0;
2382 el[0].length = 10;
2383 el[0].reserved = 0x00000000;
2385 /* Take an exclusive lock, then a shared lock on different handle */
2386 torture_comment(torture, " shared should contend on exclusive on "
2387 "different handle.\n");
2389 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2390 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2391 status = smb2_lock(tree, &lck);
2392 CHECK_STATUS(status, NT_STATUS_OK);
2394 lck.in.file.handle = h2;
2395 el[0].flags = SMB2_LOCK_FLAG_SHARED |
2396 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2397 status = smb2_lock(tree, &lck);
2398 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
2400 /* cleanup */
2401 lck.in.file.handle = h;
2402 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2403 status = smb2_lock(tree, &lck);
2404 CHECK_STATUS(status, NT_STATUS_OK);
2406 done:
2407 smb2_util_close(tree, h2);
2408 smb2_util_close(tree, h);
2409 smb2_deltree(tree, BASEDIR);
2410 return ret;
2414 * Test locker context
2415 * - test that pid does not affect the locker context
2417 static bool test_context(struct torture_context *torture,
2418 struct smb2_tree *tree)
2420 NTSTATUS status;
2421 bool ret = true;
2422 struct smb2_handle h = {{0}};
2423 struct smb2_handle h2 = {{0}};
2424 uint8_t buf[200];
2425 struct smb2_lock lck;
2426 struct smb2_lock_element el[1];
2428 const char *fname = BASEDIR "\\context.txt";
2430 status = torture_smb2_testdir(tree, BASEDIR, &h);
2431 CHECK_STATUS(status, NT_STATUS_OK);
2432 smb2_util_close(tree, h);
2434 status = torture_smb2_testfile(tree, fname, &h);
2435 CHECK_STATUS(status, NT_STATUS_OK);
2437 ZERO_STRUCT(buf);
2438 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2439 CHECK_STATUS(status, NT_STATUS_OK);
2441 status = torture_smb2_testfile(tree, fname, &h2);
2442 CHECK_STATUS(status, NT_STATUS_OK);
2444 torture_comment(torture, "Testing locker context:\n");
2446 /* Setup initial parameters */
2447 lck.in.locks = el;
2448 lck.in.lock_count = 0x0001;
2449 lck.in.lock_sequence = 0x00000000;
2450 lck.in.file.handle = h;
2451 el[0].offset = 0;
2452 el[0].length = 10;
2453 el[0].reserved = 0x00000000;
2455 /* Take an exclusive lock, then try to unlock with a different pid,
2456 * same handle. This shows that the pid doesn't affect the locker
2457 * context in SMB2. */
2458 torture_comment(torture, " pid shouldn't affect locker context\n");
2460 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2461 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2462 status = smb2_lock(tree, &lck);
2463 CHECK_STATUS(status, NT_STATUS_OK);
2465 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2466 status = smb2_lock(tree, &lck);
2467 CHECK_STATUS(status, NT_STATUS_OK);
2469 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2470 status = smb2_lock(tree, &lck);
2471 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
2473 done:
2474 smb2_util_close(tree, h2);
2475 smb2_util_close(tree, h);
2476 smb2_deltree(tree, BASEDIR);
2477 return ret;
2481 * Test as much of the potential lock range as possible
2482 * - test ported from BASE-LOCK-LOCK3
2484 static bool test_range(struct torture_context *torture,
2485 struct smb2_tree *tree)
2487 NTSTATUS status;
2488 bool ret = true;
2489 struct smb2_handle h = {{0}};
2490 struct smb2_handle h2 = {{0}};
2491 uint8_t buf[200];
2492 struct smb2_lock lck;
2493 struct smb2_lock_element el[1];
2494 uint64_t offset, i;
2495 extern int torture_numops;
2497 const char *fname = BASEDIR "\\range.txt";
2499 #define NEXT_OFFSET offset += (~(uint64_t)0) / torture_numops
2501 status = torture_smb2_testdir(tree, BASEDIR, &h);
2502 CHECK_STATUS(status, NT_STATUS_OK);
2503 smb2_util_close(tree, h);
2505 status = torture_smb2_testfile(tree, fname, &h);
2506 CHECK_STATUS(status, NT_STATUS_OK);
2508 ZERO_STRUCT(buf);
2509 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2510 CHECK_STATUS(status, NT_STATUS_OK);
2512 status = torture_smb2_testfile(tree, fname, &h2);
2513 CHECK_STATUS(status, NT_STATUS_OK);
2515 torture_comment(torture, "Testing locks spread across the 64-bit "
2516 "offset range\n");
2518 if (TARGET_IS_W2K8(torture)) {
2519 torture_result(torture, TORTURE_SKIP,
2520 "Target has \"pretty please\" bug. A contending lock "
2521 "request on the same handle unlocks the lock.");
2522 goto done;
2525 /* Setup initial parameters */
2526 lck.in.locks = el;
2527 lck.in.lock_count = 0x0001;
2528 lck.in.lock_sequence = 0x00000000;
2529 lck.in.file.handle = h;
2530 el[0].offset = 0;
2531 el[0].length = 1;
2532 el[0].reserved = 0x00000000;
2533 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2534 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2536 torture_comment(torture, " establishing %d locks\n", torture_numops);
2538 for (offset=i=0; i<torture_numops; i++) {
2539 NEXT_OFFSET;
2541 lck.in.file.handle = h;
2542 el[0].offset = offset - 1;
2543 status = smb2_lock(tree, &lck);
2544 CHECK_STATUS_CMT(status, NT_STATUS_OK,
2545 talloc_asprintf(torture,
2546 "lock h failed at offset %#llx ",
2547 (unsigned long long) el[0].offset));
2549 lck.in.file.handle = h2;
2550 el[0].offset = offset - 2;
2551 status = smb2_lock(tree, &lck);
2552 CHECK_STATUS_CMT(status, NT_STATUS_OK,
2553 talloc_asprintf(torture,
2554 "lock h2 failed at offset %#llx ",
2555 (unsigned long long) el[0].offset));
2558 torture_comment(torture, " testing %d locks\n", torture_numops);
2560 for (offset=i=0; i<torture_numops; i++) {
2561 NEXT_OFFSET;
2563 lck.in.file.handle = h;
2564 el[0].offset = offset - 1;
2565 status = smb2_lock(tree, &lck);
2566 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
2567 talloc_asprintf(torture,
2568 "lock h at offset %#llx should not have "
2569 "succeeded ",
2570 (unsigned long long) el[0].offset));
2572 lck.in.file.handle = h;
2573 el[0].offset = offset - 2;
2574 status = smb2_lock(tree, &lck);
2575 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
2576 talloc_asprintf(torture,
2577 "lock h2 at offset %#llx should not have "
2578 "succeeded ",
2579 (unsigned long long) el[0].offset));
2581 lck.in.file.handle = h2;
2582 el[0].offset = offset - 1;
2583 status = smb2_lock(tree, &lck);
2584 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
2585 talloc_asprintf(torture,
2586 "lock h at offset %#llx should not have "
2587 "succeeded ",
2588 (unsigned long long) el[0].offset));
2590 lck.in.file.handle = h2;
2591 el[0].offset = offset - 2;
2592 status = smb2_lock(tree, &lck);
2593 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
2594 talloc_asprintf(torture,
2595 "lock h2 at offset %#llx should not have "
2596 "succeeded ",
2597 (unsigned long long) el[0].offset));
2600 torture_comment(torture, " removing %d locks\n", torture_numops);
2602 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2604 for (offset=i=0; i<torture_numops; i++) {
2605 NEXT_OFFSET;
2607 lck.in.file.handle = h;
2608 el[0].offset = offset - 1;
2609 status = smb2_lock(tree, &lck);
2610 CHECK_STATUS_CMT(status, NT_STATUS_OK,
2611 talloc_asprintf(torture,
2612 "unlock from h failed at offset %#llx ",
2613 (unsigned long long) el[0].offset));
2615 lck.in.file.handle = h2;
2616 el[0].offset = offset - 2;
2617 status = smb2_lock(tree, &lck);
2618 CHECK_STATUS_CMT(status, NT_STATUS_OK,
2619 talloc_asprintf(torture,
2620 "unlock from h2 failed at offset %#llx ",
2621 (unsigned long long) el[0].offset));
2624 done:
2625 smb2_util_close(tree, h2);
2626 smb2_util_close(tree, h);
2627 smb2_deltree(tree, BASEDIR);
2628 return ret;
2631 static NTSTATUS test_smb2_lock(struct smb2_tree *tree, struct smb2_handle h,
2632 uint64_t offset, uint64_t length, bool exclusive)
2634 struct smb2_lock lck;
2635 struct smb2_lock_element el[1];
2636 NTSTATUS status;
2638 lck.in.locks = el;
2639 lck.in.lock_count = 0x0001;
2640 lck.in.lock_sequence = 0x00000000;
2641 lck.in.file.handle = h;
2642 el[0].offset = offset;
2643 el[0].length = length;
2644 el[0].reserved = 0x00000000;
2645 el[0].flags = (exclusive ?
2646 SMB2_LOCK_FLAG_EXCLUSIVE :
2647 SMB2_LOCK_FLAG_SHARED) |
2648 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2650 status = smb2_lock(tree, &lck);
2652 return status;
2655 static NTSTATUS test_smb2_unlock(struct smb2_tree *tree, struct smb2_handle h,
2656 uint64_t offset, uint64_t length)
2658 struct smb2_lock lck;
2659 struct smb2_lock_element el[1];
2660 NTSTATUS status;
2662 lck.in.locks = el;
2663 lck.in.lock_count = 0x0001;
2664 lck.in.lock_sequence = 0x00000000;
2665 lck.in.file.handle = h;
2666 el[0].offset = offset;
2667 el[0].length = length;
2668 el[0].reserved = 0x00000000;
2669 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2671 status = smb2_lock(tree, &lck);
2673 return status;
2676 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2677 torture_result(torture, TORTURE_FAIL, __location__": subtest failed");\
2678 torture_comment(torture, "** "); correct = false; \
2682 * Test overlapping lock ranges from various lockers
2683 * - some tests ported from BASE-LOCK-LOCK4
2685 static bool test_overlap(struct torture_context *torture,
2686 struct smb2_tree *tree,
2687 struct smb2_tree *tree2)
2689 NTSTATUS status;
2690 bool ret = true;
2691 struct smb2_handle h = {{0}};
2692 struct smb2_handle h2 = {{0}};
2693 struct smb2_handle h3 = {{0}};
2694 uint8_t buf[200];
2695 bool correct = true;
2697 const char *fname = BASEDIR "\\overlap.txt";
2699 status = torture_smb2_testdir(tree, BASEDIR, &h);
2700 CHECK_STATUS(status, NT_STATUS_OK);
2701 smb2_util_close(tree, h);
2703 status = torture_smb2_testfile(tree, fname, &h);
2704 CHECK_STATUS(status, NT_STATUS_OK);
2706 ZERO_STRUCT(buf);
2707 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2708 CHECK_STATUS(status, NT_STATUS_OK);
2710 status = torture_smb2_testfile(tree, fname, &h2);
2711 CHECK_STATUS(status, NT_STATUS_OK);
2713 status = torture_smb2_testfile(tree2, fname, &h3);
2714 CHECK_STATUS(status, NT_STATUS_OK);
2716 torture_comment(torture, "Testing overlapping locks:\n");
2718 ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 0, 4, true)) &&
2719 NT_STATUS_IS_OK(test_smb2_lock(tree, h, 2, 4, true));
2720 EXPECTED(ret, false);
2721 torture_comment(torture, "the same session/handle %s set overlapping "
2722 "exclusive locks\n", ret?"can":"cannot");
2724 ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 10, 4, false)) &&
2725 NT_STATUS_IS_OK(test_smb2_lock(tree, h, 12, 4, false));
2726 EXPECTED(ret, true);
2727 torture_comment(torture, "the same session/handle %s set overlapping "
2728 "shared locks\n", ret?"can":"cannot");
2730 ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 20, 4, true)) &&
2731 NT_STATUS_IS_OK(test_smb2_lock(tree2, h3, 22, 4, true));
2732 EXPECTED(ret, false);
2733 torture_comment(torture, "a different session %s set overlapping "
2734 "exclusive locks\n", ret?"can":"cannot");
2736 ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 30, 4, false)) &&
2737 NT_STATUS_IS_OK(test_smb2_lock(tree2, h3, 32, 4, false));
2738 EXPECTED(ret, true);
2739 torture_comment(torture, "a different session %s set overlapping "
2740 "shared locks\n", ret?"can":"cannot");
2742 ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 40, 4, true)) &&
2743 NT_STATUS_IS_OK(test_smb2_lock(tree, h2, 42, 4, true));
2744 EXPECTED(ret, false);
2745 torture_comment(torture, "a different handle %s set overlapping "
2746 "exclusive locks\n", ret?"can":"cannot");
2748 ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 50, 4, false)) &&
2749 NT_STATUS_IS_OK(test_smb2_lock(tree, h2, 52, 4, false));
2750 EXPECTED(ret, true);
2751 torture_comment(torture, "a different handle %s set overlapping "
2752 "shared locks\n", ret?"can":"cannot");
2754 ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 110, 4, false)) &&
2755 NT_STATUS_IS_OK(test_smb2_lock(tree, h, 112, 4, false)) &&
2756 NT_STATUS_IS_OK(test_smb2_unlock(tree, h, 110, 6));
2757 EXPECTED(ret, false);
2758 torture_comment(torture, "the same handle %s coalesce read locks\n",
2759 ret?"can":"cannot");
2761 smb2_util_close(tree, h2);
2762 smb2_util_close(tree, h);
2763 status = torture_smb2_testfile(tree, fname, &h);
2764 CHECK_STATUS(status, NT_STATUS_OK);
2765 status = torture_smb2_testfile(tree, fname, &h2);
2766 CHECK_STATUS(status, NT_STATUS_OK);
2767 ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 0, 8, false)) &&
2768 NT_STATUS_IS_OK(test_smb2_lock(tree, h2, 0, 1, false)) &&
2769 NT_STATUS_IS_OK(smb2_util_close(tree, h)) &&
2770 NT_STATUS_IS_OK(torture_smb2_testfile(tree, fname, &h)) &&
2771 NT_STATUS_IS_OK(test_smb2_lock(tree, h, 7, 1, true));
2772 EXPECTED(ret, true);
2773 torture_comment(torture, "the server %s have the NT byte range lock "
2774 "bug\n", !ret?"does":"doesn't");
2776 done:
2777 smb2_util_close(tree2, h3);
2778 smb2_util_close(tree, h2);
2779 smb2_util_close(tree, h);
2780 smb2_deltree(tree, BASEDIR);
2781 return correct;
2785 * Test truncation of locked file
2786 * - some tests ported from BASE-LOCK-LOCK7
2788 static bool test_truncate(struct torture_context *torture,
2789 struct smb2_tree *tree)
2791 NTSTATUS status;
2792 bool ret = true;
2793 struct smb2_handle h = {{0}};
2794 struct smb2_handle h2 = {{0}};
2795 uint8_t buf[200];
2796 struct smb2_lock lck;
2797 struct smb2_lock_element el[1];
2798 struct smb2_create io;
2800 const char *fname = BASEDIR "\\truncate.txt";
2802 status = torture_smb2_testdir(tree, BASEDIR, &h);
2803 CHECK_STATUS(status, NT_STATUS_OK);
2804 smb2_util_close(tree, h);
2806 status = torture_smb2_testfile(tree, fname, &h);
2807 CHECK_STATUS(status, NT_STATUS_OK);
2809 ZERO_STRUCT(buf);
2810 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2811 CHECK_STATUS(status, NT_STATUS_OK);
2813 torture_comment(torture, "Testing truncation of locked file:\n");
2815 /* Setup initial parameters */
2816 lck.in.locks = el;
2817 lck.in.lock_count = 0x0001;
2818 lck.in.lock_sequence = 0x00000000;
2819 lck.in.file.handle = h;
2820 el[0].offset = 0;
2821 el[0].length = 10;
2822 el[0].reserved = 0x00000000;
2824 ZERO_STRUCT(io);
2825 io.in.oplock_level = 0;
2826 io.in.desired_access = SEC_RIGHTS_FILE_ALL;
2827 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2828 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2829 io.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
2830 NTCREATEX_SHARE_ACCESS_READ |
2831 NTCREATEX_SHARE_ACCESS_WRITE;
2832 io.in.create_options = 0;
2833 io.in.fname = fname;
2835 /* Take an exclusive lock */
2836 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
2837 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2838 status = smb2_lock(tree, &lck);
2839 CHECK_STATUS(status, NT_STATUS_OK);
2841 /* On second handle open the file with OVERWRITE disposition */
2842 torture_comment(torture, " overwrite disposition is allowed on a "
2843 "locked file.\n");
2845 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2846 status = smb2_create(tree, tree, &io);
2847 CHECK_STATUS(status, NT_STATUS_OK);
2848 h2 = io.out.file.handle;
2849 smb2_util_close(tree, h2);
2851 /* On second handle open the file with SUPERSEDE disposition */
2852 torture_comment(torture, " supersede disposition is allowed on a "
2853 "locked file.\n");
2855 io.in.create_disposition = NTCREATEX_DISP_SUPERSEDE;
2856 status = smb2_create(tree, tree, &io);
2857 CHECK_STATUS(status, NT_STATUS_OK);
2858 h2 = io.out.file.handle;
2859 smb2_util_close(tree, h2);
2861 /* cleanup */
2862 lck.in.file.handle = h;
2863 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
2864 status = smb2_lock(tree, &lck);
2865 CHECK_STATUS(status, NT_STATUS_OK);
2867 done:
2868 smb2_util_close(tree, h2);
2869 smb2_util_close(tree, h);
2870 smb2_deltree(tree, BASEDIR);
2871 return ret;
2875 * Test lock replay detection
2877 * This test checks the SMB 2.1.0 behaviour of lock sequence checking,
2878 * which is only turned on for resilient handles.
2880 * Make it clear that this test is supposed to pass against the legacy
2881 * Windows servers which violate the specification:
2883 * [MS-SMB2] 3.3.5.14 Receiving an SMB2 LOCK Request
2885 * ...
2887 * ... if Open.IsResilient or Open.IsDurable or Open.IsPersistent is
2888 * TRUE or if Connection.Dialect belongs to the SMB 3.x dialect family
2889 * and Connection.ServerCapabilities includes
2890 * SMB2_GLOBAL_CAP_MULTI_CHANNEL bit, the server SHOULD<314>
2891 * perform lock sequence verification ...
2893 * ...
2895 * <314> Section 3.3.5.14: Windows 7 and Windows Server 2008 R2 perform
2896 * lock sequence verification only when Open.IsResilient is TRUE.
2897 * Windows 8 through Windows 10 v1909 and Windows Server 2012 through
2898 * Windows Server v1909 perform lock sequence verification only when
2899 * Open.IsResilient or Open.IsPersistent is TRUE.
2901 * Note <314> also applies to all versions (at least) up to Windows Server v2004.
2903 * Hopefully this will be fixed in future Windows versions and they
2904 * will avoid Note <314>.
2906 static bool test_replay_broken_windows(struct torture_context *torture,
2907 struct smb2_tree *tree)
2909 NTSTATUS status;
2910 bool ret = true;
2911 struct smb2_handle h;
2912 struct smb2_ioctl ioctl;
2913 struct smb2_lock lck;
2914 struct smb2_lock_element el;
2915 uint8_t res_req[8];
2916 const char *fname = BASEDIR "\\replay_broken_windows.txt";
2917 struct smb2_transport *transport = tree->session->transport;
2919 if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB2_10) {
2920 torture_skip(torture, "SMB 2.1.0 Dialect family or above \
2921 required for Lock Replay tests\n");
2924 status = torture_smb2_testdir(tree, BASEDIR, &h);
2925 CHECK_STATUS(status, NT_STATUS_OK);
2926 smb2_util_close(tree, h);
2928 torture_comment(torture, "Testing Open File:\n");
2929 status = torture_smb2_testfile(tree, fname, &h);
2930 CHECK_STATUS(status, NT_STATUS_OK);
2933 * Setup initial parameters
2935 el = (struct smb2_lock_element) {
2936 .length = 100,
2937 .offset = 100,
2939 lck = (struct smb2_lock) {
2940 .in.locks = &el,
2941 .in.lock_count = 0x0001,
2942 .in.file.handle = h
2945 torture_comment(torture, "Testing Lock Replay detection [ignored]:\n");
2946 lck.in.lock_sequence = 0x010 + 0x1;
2947 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2948 status = smb2_lock(tree, &lck);
2949 CHECK_STATUS(status, NT_STATUS_OK);
2950 status = smb2_lock(tree, &lck);
2951 if (NT_STATUS_IS_OK(status)) {
2952 lck.in.lock_sequence = 0x020 + 0x2;
2953 status = smb2_lock(tree, &lck);
2954 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
2955 lck.in.lock_sequence = 0x010 + 0x1;
2956 status = smb2_lock(tree, &lck);
2957 CHECK_STATUS(status, NT_STATUS_OK);
2958 if (smbXcli_conn_protocol(transport->conn) > PROTOCOL_SMB2_10) {
2959 torture_skip_goto(torture, done,
2960 "SMB3 Server implements LockSequence "
2961 "for all handles\n");
2964 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
2965 if (smbXcli_conn_protocol(transport->conn) > PROTOCOL_SMB2_10) {
2966 torture_comment(torture,
2967 "\nSMB3 Server implements LockSequence as SMB 2.1.0"
2968 " LEGACY BROKEN Windows!!!\n\n");
2970 torture_comment(torture,
2971 "Testing SMB 2.1.0 LockSequence for ResilientHandles\n");
2973 el.flags = SMB2_LOCK_FLAG_UNLOCK;
2974 status = smb2_lock(tree, &lck);
2975 CHECK_STATUS(status, NT_STATUS_OK);
2976 status = smb2_lock(tree, &lck);
2977 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
2979 torture_comment(torture, "Testing Set Resiliency:\n");
2980 SIVAL(res_req, 0, 1000); /* timeout */
2981 SIVAL(res_req, 4, 0); /* reserved */
2982 ioctl = (struct smb2_ioctl) {
2983 .level = RAW_IOCTL_SMB2,
2984 .in.file.handle = h,
2985 .in.function = FSCTL_LMR_REQ_RESILIENCY,
2986 .in.max_output_response = 0,
2987 .in.flags = SMB2_IOCTL_FLAG_IS_FSCTL,
2988 .in.out.data = res_req,
2989 .in.out.length = sizeof(res_req)
2991 status = smb2_ioctl(tree, torture, &ioctl);
2992 CHECK_STATUS(status, NT_STATUS_OK);
2995 * Test with an invalid bucket number (only 1..64 are valid).
2996 * With an invalid number, lock replay detection is not performed.
2998 torture_comment(torture, "Testing Lock (ignored) Replay detection "
2999 "(Bucket No: 0 (invalid)) [ignored]:\n");
3000 lck.in.lock_sequence = 0x000 + 0x1;
3001 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3002 status = smb2_lock(tree, &lck);
3003 CHECK_STATUS(status, NT_STATUS_OK);
3004 status = smb2_lock(tree, &lck);
3005 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3007 el.flags = SMB2_LOCK_FLAG_UNLOCK;
3008 status = smb2_lock(tree, &lck);
3009 CHECK_STATUS(status, NT_STATUS_OK);
3010 status = smb2_lock(tree, &lck);
3011 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
3013 torture_comment(torture, "Testing Lock Replay detection "
3014 "(Bucket No: 1):\n");
3017 * Obtain Exclusive Lock of length 100 bytes using Bucket Num 1
3018 * and Bucket Seq 1.
3020 lck.in.lock_sequence = 0x010 + 0x1;
3021 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3022 status = smb2_lock(tree, &lck);
3023 CHECK_STATUS(status, NT_STATUS_OK);
3026 * Server detects Replay of Byte Range locks using the Lock Sequence
3027 * Numbers. And ignores the requests completely.
3029 status = smb2_lock(tree, &lck);
3030 CHECK_STATUS(status, NT_STATUS_OK);
3031 el.flags = SMB2_LOCK_FLAG_UNLOCK;
3032 status = smb2_lock(tree, &lck);
3033 CHECK_STATUS(status, NT_STATUS_OK);
3034 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3035 status = smb2_lock(tree, &lck);
3036 CHECK_STATUS(status, NT_STATUS_OK);
3037 el.flags = SMB2_LOCK_FLAG_UNLOCK;
3038 status = smb2_lock(tree, &lck);
3039 CHECK_STATUS(status, NT_STATUS_OK);
3040 status = smb2_lock(tree, &lck);
3041 CHECK_STATUS(status, NT_STATUS_OK);
3043 /* status: still locked */
3046 * Server will not grant same Byte Range using a different Bucket Seq
3048 lck.in.lock_sequence = 0x010 + 0x2;
3049 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3050 status = smb2_lock(tree, &lck);
3051 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3052 status = smb2_lock(tree, &lck);
3053 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3055 torture_comment(torture, "Testing Lock Replay detection "
3056 "(Bucket No: 2):\n");
3059 * Server will not grant same Byte Range using a different Bucket Num
3061 lck.in.lock_sequence = 0x020 + 0x1;
3062 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3063 status = smb2_lock(tree, &lck);
3064 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3065 status = smb2_lock(tree, &lck);
3066 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3068 /* status: still locked */
3070 /* test with invalid bucket when file is locked */
3072 torture_comment(torture, "Testing Lock Replay detection "
3073 "(Bucket No: 65 (invalid)) [ignored]:\n");
3075 lck.in.lock_sequence = 0x410 + 0x1;
3076 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3077 status = smb2_lock(tree, &lck);
3078 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3079 status = smb2_lock(tree, &lck);
3080 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3082 el.flags = SMB2_LOCK_FLAG_UNLOCK;
3083 status = smb2_lock(tree, &lck);
3084 CHECK_STATUS(status, NT_STATUS_OK);
3085 status = smb2_lock(tree, &lck);
3086 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
3088 /* status: unlocked */
3091 * Lock again for the unlock replay test
3093 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3094 status = smb2_lock(tree, &lck);
3095 CHECK_STATUS(status, NT_STATUS_OK);
3097 torture_comment(torture, "Testing Lock Replay detection "
3098 "(Bucket No: 64):\n");
3101 * Server will not grant same Byte Range using a different Bucket Num
3103 lck.in.lock_sequence = 0x400 + 0x1;
3104 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3105 status = smb2_lock(tree, &lck);
3106 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3107 status = smb2_lock(tree, &lck);
3108 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3111 * Test Unlock replay detection
3113 lck.in.lock_sequence = 0x400 + 0x2;
3114 el.flags = SMB2_LOCK_FLAG_UNLOCK;
3115 status = smb2_lock(tree, &lck);
3116 CHECK_STATUS(status, NT_STATUS_OK); /* new seq num ==> unlocked */
3117 status = smb2_lock(tree, &lck);
3118 CHECK_STATUS(status, NT_STATUS_OK); /* replay detected ==> ignored */
3120 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3121 status = smb2_lock(tree, &lck); /* same seq num ==> ignored */
3122 CHECK_STATUS(status, NT_STATUS_OK);
3124 /* verify it's unlocked: */
3125 lck.in.lock_sequence = 0x400 + 0x3;
3126 el.flags = SMB2_LOCK_FLAG_UNLOCK;
3127 status = smb2_lock(tree, &lck);
3128 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
3130 /* status: not locked */
3132 done:
3133 smb2_util_close(tree, h);
3134 smb2_deltree(tree, BASEDIR);
3135 return ret;
3139 * Test lock replay detection
3141 * This test check the SMB 3 behaviour of lock sequence checking,
3142 * which should be implemented for all handles.
3144 * Make it clear that this test is supposed to pass a
3145 * server implementing the specification:
3147 * [MS-SMB2] 3.3.5.14 Receiving an SMB2 LOCK Request
3149 * ...
3151 * ... if Open.IsResilient or Open.IsDurable or Open.IsPersistent is
3152 * TRUE or if Connection.Dialect belongs to the SMB 3.x dialect family
3153 * and Connection.ServerCapabilities includes
3154 * SMB2_GLOBAL_CAP_MULTI_CHANNEL bit, the server SHOULD<314>
3155 * perform lock sequence verification ...
3157 * ...
3159 * <314> Section 3.3.5.14: Windows 7 and Windows Server 2008 R2 perform
3160 * lock sequence verification only when Open.IsResilient is TRUE.
3161 * Windows 8 through Windows 10 v1909 and Windows Server 2012 through
3162 * Windows Server v1909 perform lock sequence verification only when
3163 * Open.IsResilient or Open.IsPersistent is TRUE.
3165 * Note <314> also applies to all versions (at least) up to Windows Server v2004.
3167 * Hopefully this will be fixed in future Windows versions and they
3168 * will avoid Note <314>.
3170 static bool _test_replay_smb3_specification(struct torture_context *torture,
3171 struct smb2_tree *tree,
3172 const char *testname,
3173 bool use_durable)
3175 NTSTATUS status;
3176 bool ret = true;
3177 struct smb2_create io;
3178 struct smb2_handle h;
3179 struct smb2_lock lck;
3180 struct smb2_lock_element el;
3181 char fname[256];
3182 struct smb2_transport *transport = tree->session->transport;
3184 if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
3185 torture_skip(torture, "SMB 3.0.0 Dialect family or above \
3186 required for Lock Replay tests\n");
3189 snprintf(fname, sizeof(fname), "%s\\%s.dat", BASEDIR, testname);
3191 status = torture_smb2_testdir(tree, BASEDIR, &h);
3192 CHECK_STATUS(status, NT_STATUS_OK);
3193 smb2_util_close(tree, h);
3195 torture_comment(torture, "%s: Testing Open File:\n", testname);
3197 smb2_oplock_create_share(&io, fname,
3198 smb2_util_share_access(""),
3199 smb2_util_oplock_level("b"));
3200 io.in.durable_open = use_durable;
3202 status = smb2_create(tree, torture, &io);
3203 CHECK_STATUS(status, NT_STATUS_OK);
3204 h = io.out.file.handle;
3205 CHECK_VALUE(io.out.oplock_level, smb2_util_oplock_level("b"));
3206 CHECK_VALUE(io.out.durable_open, use_durable);
3207 CHECK_VALUE(io.out.durable_open_v2, false);
3208 CHECK_VALUE(io.out.persistent_open, false);
3211 * Setup initial parameters
3213 el = (struct smb2_lock_element) {
3214 .length = 100,
3215 .offset = 100,
3217 lck = (struct smb2_lock) {
3218 .in.locks = &el,
3219 .in.lock_count = 0x0001,
3220 .in.file.handle = h
3223 torture_comment(torture,
3224 "Testing SMB 3 LockSequence for all Handles\n");
3227 * Test with an invalid bucket number (only 1..64 are valid).
3228 * With an invalid number, lock replay detection is not performed.
3230 torture_comment(torture, "Testing Lock (ignored) Replay detection "
3231 "(Bucket No: 0 (invalid)) [ignored]:\n");
3232 lck.in.lock_sequence = 0x000 + 0x1;
3233 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3234 status = smb2_lock(tree, &lck);
3235 CHECK_STATUS(status, NT_STATUS_OK);
3236 status = smb2_lock(tree, &lck);
3237 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3239 el.flags = SMB2_LOCK_FLAG_UNLOCK;
3240 status = smb2_lock(tree, &lck);
3241 CHECK_STATUS(status, NT_STATUS_OK);
3242 status = smb2_lock(tree, &lck);
3243 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
3245 torture_comment(torture, "Testing Lock Replay detection "
3246 "(Bucket No: 1):\n");
3249 * Obtain Exclusive Lock of length 100 bytes using Bucket Num 1
3250 * and Bucket Seq 1.
3252 lck.in.lock_sequence = 0x010 + 0x1;
3253 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3254 status = smb2_lock(tree, &lck);
3255 CHECK_STATUS(status, NT_STATUS_OK);
3258 * Server detects Replay of Byte Range locks using the Lock Sequence
3259 * Numbers. And ignores the requests completely.
3261 status = smb2_lock(tree, &lck);
3262 CHECK_STATUS(status, NT_STATUS_OK);
3263 el.flags = SMB2_LOCK_FLAG_UNLOCK;
3264 status = smb2_lock(tree, &lck);
3265 CHECK_STATUS(status, NT_STATUS_OK);
3266 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3267 status = smb2_lock(tree, &lck);
3268 CHECK_STATUS(status, NT_STATUS_OK);
3269 el.flags = SMB2_LOCK_FLAG_UNLOCK;
3270 status = smb2_lock(tree, &lck);
3271 CHECK_STATUS(status, NT_STATUS_OK);
3272 status = smb2_lock(tree, &lck);
3273 CHECK_STATUS(status, NT_STATUS_OK);
3275 /* status: still locked */
3278 * Server will not grant same Byte Range using a different Bucket Seq
3280 lck.in.lock_sequence = 0x010 + 0x2;
3281 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3282 status = smb2_lock(tree, &lck);
3283 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3284 status = smb2_lock(tree, &lck);
3285 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3287 torture_comment(torture, "Testing Lock Replay detection "
3288 "(Bucket No: 2):\n");
3291 * Server will not grant same Byte Range using a different Bucket Num
3293 lck.in.lock_sequence = 0x020 + 0x1;
3294 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3295 status = smb2_lock(tree, &lck);
3296 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3297 status = smb2_lock(tree, &lck);
3298 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3300 /* status: still locked */
3302 /* test with invalid bucket when file is locked */
3304 torture_comment(torture, "Testing Lock Replay detection "
3305 "(Bucket No: 65 (invalid)) [ignored]:\n");
3307 lck.in.lock_sequence = 0x410 + 0x1;
3308 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3309 status = smb2_lock(tree, &lck);
3310 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3311 status = smb2_lock(tree, &lck);
3312 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3314 el.flags = SMB2_LOCK_FLAG_UNLOCK;
3315 status = smb2_lock(tree, &lck);
3316 CHECK_STATUS(status, NT_STATUS_OK);
3317 status = smb2_lock(tree, &lck);
3318 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
3320 /* status: unlocked */
3323 * Lock again for the unlock replay test
3325 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3326 status = smb2_lock(tree, &lck);
3327 CHECK_STATUS(status, NT_STATUS_OK);
3329 torture_comment(torture, "Testing Lock Replay detection "
3330 "(Bucket No: 64):\n");
3333 * Server will not grant same Byte Range using a different Bucket Num
3335 lck.in.lock_sequence = 0x400 + 0x1;
3336 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3337 status = smb2_lock(tree, &lck);
3338 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3339 status = smb2_lock(tree, &lck);
3340 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
3343 * Test Unlock replay detection
3345 lck.in.lock_sequence = 0x400 + 0x2;
3346 el.flags = SMB2_LOCK_FLAG_UNLOCK;
3347 status = smb2_lock(tree, &lck);
3348 CHECK_STATUS(status, NT_STATUS_OK); /* new seq num ==> unlocked */
3349 status = smb2_lock(tree, &lck);
3350 CHECK_STATUS(status, NT_STATUS_OK); /* replay detected ==> ignored */
3352 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3353 status = smb2_lock(tree, &lck); /* same seq num ==> ignored */
3354 CHECK_STATUS(status, NT_STATUS_OK);
3356 /* verify it's unlocked: */
3357 lck.in.lock_sequence = 0x400 + 0x3;
3358 el.flags = SMB2_LOCK_FLAG_UNLOCK;
3359 status = smb2_lock(tree, &lck);
3360 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
3362 /* status: not locked */
3364 done:
3365 smb2_util_close(tree, h);
3366 smb2_deltree(tree, BASEDIR);
3367 return ret;
3370 static bool test_replay_smb3_specification_durable(struct torture_context *torture,
3371 struct smb2_tree *tree)
3373 const char *testname = "replay_smb3_specification_durable";
3374 struct smb2_transport *transport = tree->session->transport;
3376 if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB2_10) {
3377 torture_skip(torture, "SMB 2.1.0 Dialect family or above \
3378 required for Lock Replay tests on durable handles\n");
3381 return _test_replay_smb3_specification(torture, tree, testname, true);
3384 static bool test_replay_smb3_specification_multi(struct torture_context *torture,
3385 struct smb2_tree *tree)
3387 const char *testname = "replay_smb3_specification_multi";
3388 struct smb2_transport *transport = tree->session->transport;
3389 uint32_t server_capabilities;
3391 if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
3392 torture_skip(torture, "SMB 3.0.0 Dialect family or above \
3393 required for Lock Replay tests on without durable handles\n");
3396 server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
3397 if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
3398 torture_skip(torture, "MULTI_CHANNEL is \
3399 required for Lock Replay tests on without durable handles\n");
3402 return _test_replay_smb3_specification(torture, tree, testname, false);
3406 * Test lock interaction between smbd and ctdb with tombstone records.
3408 * Re-locking an unlocked record could lead to a deadlock between
3409 * smbd and ctdb. Make sure we don't regress.
3411 * https://bugzilla.samba.org/show_bug.cgi?id=12005
3412 * https://bugzilla.samba.org/show_bug.cgi?id=10008
3414 static bool test_deadlock(struct torture_context *torture,
3415 struct smb2_tree *tree)
3417 NTSTATUS status;
3418 bool ret = true;
3419 struct smb2_handle _h;
3420 struct smb2_handle *h = NULL;
3421 uint8_t buf[200];
3422 const char *fname = BASEDIR "\\deadlock.txt";
3424 if (!lpcfg_clustering(torture->lp_ctx)) {
3425 torture_skip(torture, "Test must be run on a ctdb cluster\n");
3426 return true;
3429 status = torture_smb2_testdir(tree, BASEDIR, &_h);
3430 torture_assert_ntstatus_ok(torture, status,
3431 "torture_smb2_testdir failed");
3432 smb2_util_close(tree, _h);
3434 status = torture_smb2_testfile(tree, fname, &_h);
3435 torture_assert_ntstatus_ok_goto(torture, status, ret, done,
3436 "torture_smb2_testfile failed");
3437 h = &_h;
3439 ZERO_STRUCT(buf);
3440 status = smb2_util_write(tree, *h, buf, 0, ARRAY_SIZE(buf));
3441 torture_assert_ntstatus_ok_goto(torture, status, ret, done,
3442 "smb2_util_write failed");
3444 status = test_smb2_lock(tree, *h, 0, 1, true);
3445 torture_assert_ntstatus_ok_goto(torture, status, ret, done,
3446 "test_smb2_lock failed");
3448 status = test_smb2_unlock(tree, *h, 0, 1);
3449 torture_assert_ntstatus_ok_goto(torture, status, ret, done,
3450 "test_smb2_unlock failed");
3452 status = test_smb2_lock(tree, *h, 0, 1, true);
3453 torture_assert_ntstatus_ok_goto(torture, status, ret, done,
3454 "test_smb2_lock failed");
3456 status = test_smb2_unlock(tree, *h, 0, 1);
3457 torture_assert_ntstatus_ok_goto(torture, status, ret, done,
3458 "test_smb2_unlock failed");
3460 done:
3461 if (h != NULL) {
3462 smb2_util_close(tree, *h);
3464 smb2_deltree(tree, BASEDIR);
3465 return ret;
3468 /* basic testing of SMB2 locking
3470 struct torture_suite *torture_smb2_lock_init(TALLOC_CTX *ctx)
3472 struct torture_suite *suite =
3473 torture_suite_create(ctx, "lock");
3474 torture_suite_add_1smb2_test(suite, "valid-request",
3475 test_valid_request);
3476 torture_suite_add_1smb2_test(suite, "rw-none", test_lock_rw_none);
3477 torture_suite_add_1smb2_test(suite, "rw-shared", test_lock_rw_shared);
3478 torture_suite_add_1smb2_test(suite, "rw-exclusive",
3479 test_lock_rw_exclusive);
3480 torture_suite_add_1smb2_test(suite, "auto-unlock",
3481 test_lock_auto_unlock);
3482 torture_suite_add_1smb2_test(suite, "lock", test_lock);
3483 torture_suite_add_1smb2_test(suite, "async", test_async);
3484 torture_suite_add_1smb2_test(suite, "cancel", test_cancel);
3485 torture_suite_add_1smb2_test(suite, "cancel-tdis", test_cancel_tdis);
3486 torture_suite_add_1smb2_test(suite, "cancel-logoff",
3487 test_cancel_logoff);
3488 torture_suite_add_1smb2_test(suite, "errorcode", test_errorcode);
3489 torture_suite_add_1smb2_test(suite, "zerobytelength",
3490 test_zerobytelength);
3491 torture_suite_add_1smb2_test(suite, "zerobyteread",
3492 test_zerobyteread);
3493 torture_suite_add_1smb2_test(suite, "unlock", test_unlock);
3494 torture_suite_add_1smb2_test(suite, "multiple-unlock",
3495 test_multiple_unlock);
3496 torture_suite_add_1smb2_test(suite, "stacking", test_stacking);
3497 torture_suite_add_1smb2_test(suite, "contend", test_contend);
3498 torture_suite_add_1smb2_test(suite, "context", test_context);
3499 torture_suite_add_1smb2_test(suite, "range", test_range);
3500 torture_suite_add_2smb2_test(suite, "overlap", test_overlap);
3501 torture_suite_add_1smb2_test(suite, "truncate", test_truncate);
3502 torture_suite_add_1smb2_test(suite, "replay_broken_windows",
3503 test_replay_broken_windows);
3504 torture_suite_add_1smb2_test(suite, "replay_smb3_specification_durable",
3505 test_replay_smb3_specification_durable);
3506 torture_suite_add_1smb2_test(suite, "replay_smb3_specification_multi",
3507 test_replay_smb3_specification_multi);
3508 torture_suite_add_1smb2_test(suite, "ctdb-delrec-deadlock", test_deadlock);
3510 suite->description = talloc_strdup(suite, "SMB2-LOCK tests");
3512 return suite;