s3/docs: Remove reference to nonexistent file.
[Samba/gbeck.git] / source4 / torture / smb2 / lock.c
blob033e12f1fc8d6a78027f93940bbb5e9e3d928be2
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"
26 #include "torture/torture.h"
27 #include "torture/smb2/proto.h"
30 #define TARGET_IS_WINDOWS(_tctx) (torture_setting_bool(_tctx, "win7", false) || torture_setting_bool(torture, "windows", false))
31 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
33 #define CHECK_STATUS(status, correct) do { \
34 if (!NT_STATUS_EQUAL(status, correct)) { \
35 printf("(%s) Incorrect status %s - should be %s\n", \
36 __location__, nt_errstr(status), nt_errstr(correct)); \
37 ret = false; \
38 goto done; \
39 }} while (0)
41 #define CHECK_VALUE(v, correct) do { \
42 if ((v) != (correct)) { \
43 printf("(%s) Incorrect value %s=%d - should be %d\n", \
44 __location__, #v, v, correct); \
45 ret = false; \
46 goto done; \
47 }} while (0)
49 static bool test_valid_request(struct torture_context *torture, struct smb2_tree *tree)
51 bool ret = true;
52 NTSTATUS status;
53 struct smb2_handle h;
54 uint8_t buf[200];
55 struct smb2_lock lck;
56 struct smb2_lock_element el[2];
58 ZERO_STRUCT(buf);
60 status = torture_smb2_testfile(tree, "lock1.txt", &h);
61 CHECK_STATUS(status, NT_STATUS_OK);
63 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
64 CHECK_STATUS(status, NT_STATUS_OK);
66 lck.in.locks = el;
68 lck.in.lock_count = 0x0000;
69 lck.in.reserved = 0x00000000;
70 lck.in.file.handle = h;
71 el[0].offset = 0x0000000000000000;
72 el[0].length = 0x0000000000000000;
73 el[0].reserved = 0x0000000000000000;
74 el[0].flags = 0x00000000;
75 status = smb2_lock(tree, &lck);
76 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
78 lck.in.lock_count = 0x0001;
79 lck.in.reserved = 0x00000000;
80 lck.in.file.handle = h;
81 el[0].offset = 0;
82 el[0].length = 0;
83 el[0].reserved = 0x00000000;
84 el[0].flags = SMB2_LOCK_FLAG_NONE;
85 status = smb2_lock(tree, &lck);
86 CHECK_STATUS(status, NT_STATUS_OK);
87 CHECK_VALUE(lck.out.reserved, 0);
89 lck.in.file.handle.data[0] +=1;
90 status = smb2_lock(tree, &lck);
91 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
92 lck.in.file.handle.data[0] -=1;
94 lck.in.lock_count = 0x0001;
95 lck.in.reserved = 0x123ab1;
96 lck.in.file.handle = h;
97 el[0].offset = UINT64_MAX;
98 el[0].length = UINT64_MAX;
99 el[0].reserved = 0x00000000;
100 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
101 status = smb2_lock(tree, &lck);
102 if (TARGET_IS_WIN7(torture)) {
103 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
104 } else {
105 CHECK_STATUS(status, NT_STATUS_OK);
107 CHECK_VALUE(lck.out.reserved, 0);
109 lck.in.reserved = 0x123ab2;
110 status = smb2_lock(tree, &lck);
111 if (TARGET_IS_WIN7(torture)) {
112 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
113 } else if (TARGET_IS_WINDOWS(torture)) {
114 CHECK_STATUS(status, NT_STATUS_OK);
115 } else {
116 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
118 CHECK_VALUE(lck.out.reserved, 0);
120 lck.in.reserved = 0x123ab3;
121 status = smb2_lock(tree, &lck);
122 if (TARGET_IS_WIN7(torture)) {
123 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
124 } else if (TARGET_IS_WINDOWS(torture)) {
125 CHECK_STATUS(status, NT_STATUS_OK);
126 } else {
127 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
129 CHECK_VALUE(lck.out.reserved, 0);
131 lck.in.reserved = 0x123ab4;
132 status = smb2_lock(tree, &lck);
133 if (TARGET_IS_WIN7(torture)) {
134 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
135 } else if (TARGET_IS_WINDOWS(torture)) {
136 CHECK_STATUS(status, NT_STATUS_OK);
137 } else {
138 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
140 CHECK_VALUE(lck.out.reserved, 0);
142 lck.in.reserved = 0x123ab5;
143 status = smb2_lock(tree, &lck);
144 if (TARGET_IS_WIN7(torture)) {
145 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
146 } else if (TARGET_IS_WINDOWS(torture)) {
147 CHECK_STATUS(status, NT_STATUS_OK);
148 } else {
149 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
151 CHECK_VALUE(lck.out.reserved, 0);
153 lck.in.lock_count = 0x0001;
154 lck.in.reserved = 0x12345678;
155 lck.in.file.handle = h;
156 el[0].offset = UINT32_MAX;
157 el[0].length = UINT32_MAX;
158 el[0].reserved = 0x87654321;
159 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
160 status = smb2_lock(tree, &lck);
161 CHECK_STATUS(status, NT_STATUS_OK);
162 CHECK_VALUE(lck.out.reserved, 0);
164 status = smb2_lock(tree, &lck);
165 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
167 status = smb2_lock(tree, &lck);
168 if (TARGET_IS_WINDOWS(torture)) {
169 CHECK_STATUS(status, NT_STATUS_OK);
170 } else {
171 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
173 CHECK_VALUE(lck.out.reserved, 0);
175 status = smb2_lock(tree, &lck);
176 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
178 status = smb2_lock(tree, &lck);
179 if (TARGET_IS_WINDOWS(torture)) {
180 CHECK_STATUS(status, NT_STATUS_OK);
181 } else {
182 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
184 CHECK_VALUE(lck.out.reserved, 0);
186 el[0].flags = 0x00000000;
187 status = smb2_lock(tree, &lck);
188 CHECK_STATUS(status, NT_STATUS_OK);
189 CHECK_VALUE(lck.out.reserved, 0);
191 status = smb2_lock(tree, &lck);
192 CHECK_STATUS(status, NT_STATUS_OK);
193 CHECK_VALUE(lck.out.reserved, 0);
195 el[0].flags = 0x00000001;
196 status = smb2_lock(tree, &lck);
197 CHECK_STATUS(status, NT_STATUS_OK);
198 CHECK_VALUE(lck.out.reserved, 0);
200 status = smb2_lock(tree, &lck);
201 CHECK_STATUS(status, NT_STATUS_OK);
202 CHECK_VALUE(lck.out.reserved, 0);
204 lck.in.lock_count = 0x0001;
205 lck.in.reserved = 0x87654321;
206 lck.in.file.handle = h;
207 el[0].offset = 0x00000000FFFFFFFF;
208 el[0].length = 0x00000000FFFFFFFF;
209 el[0].reserved = 0x1234567;
210 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
211 status = smb2_lock(tree, &lck);
212 CHECK_STATUS(status, NT_STATUS_OK);
214 lck.in.lock_count = 0x0001;
215 lck.in.reserved = 0x1234567;
216 lck.in.file.handle = h;
217 el[0].offset = 0x00000000FFFFFFFF;
218 el[0].length = 0x00000000FFFFFFFF;
219 el[0].reserved = 0x00000000;
220 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
221 status = smb2_lock(tree, &lck);
222 CHECK_STATUS(status, NT_STATUS_OK);
224 status = smb2_lock(tree, &lck);
225 CHECK_STATUS(status, NT_STATUS_OK);
226 status = smb2_lock(tree, &lck);
227 CHECK_STATUS(status, NT_STATUS_OK);
228 status = smb2_lock(tree, &lck);
229 CHECK_STATUS(status, NT_STATUS_OK);
230 status = smb2_lock(tree, &lck);
231 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
233 lck.in.lock_count = 0x0001;
234 lck.in.reserved = 0;
235 lck.in.file.handle = h;
236 el[0].offset = 1;
237 el[0].length = 1;
238 el[0].reserved = 0x00000000;
239 el[0].flags = ~SMB2_LOCK_FLAG_ALL_MASK;
241 status = smb2_lock(tree, &lck);
242 CHECK_STATUS(status, NT_STATUS_OK);
244 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
245 status = smb2_lock(tree, &lck);
246 CHECK_STATUS(status, NT_STATUS_OK);
248 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
249 status = smb2_lock(tree, &lck);
250 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
252 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_EXCLUSIVE;
253 status = smb2_lock(tree, &lck);
254 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
256 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_SHARED;
257 status = smb2_lock(tree, &lck);
258 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
260 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
261 status = smb2_lock(tree, &lck);
262 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
264 lck.in.lock_count = 2;
265 lck.in.reserved = 0;
266 lck.in.file.handle = h;
267 el[0].offset = 9999;
268 el[0].length = 1;
269 el[0].reserved = 0x00000000;
270 el[1].offset = 9999;
271 el[1].length = 1;
272 el[1].reserved = 0x00000000;
274 lck.in.lock_count = 2;
275 el[0].flags = 0;
276 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
277 status = smb2_lock(tree, &lck);
278 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
280 lck.in.lock_count = 2;
281 el[0].flags = 0;
282 el[1].flags = 0;
283 status = smb2_lock(tree, &lck);
284 CHECK_STATUS(status, NT_STATUS_OK);
286 lck.in.lock_count = 2;
287 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
288 el[1].flags = 0;
289 status = smb2_lock(tree, &lck);
290 CHECK_STATUS(status, NT_STATUS_OK);
292 lck.in.lock_count = 1;
293 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
294 status = smb2_lock(tree, &lck);
295 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
297 lck.in.lock_count = 1;
298 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
299 status = smb2_lock(tree, &lck);
300 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
302 lck.in.lock_count = 1;
303 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
304 status = smb2_lock(tree, &lck);
305 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
307 lck.in.lock_count = 1;
308 el[0].flags = 0;
309 status = smb2_lock(tree, &lck);
310 CHECK_STATUS(status, NT_STATUS_OK);
312 status = smb2_lock(tree, &lck);
313 CHECK_STATUS(status, NT_STATUS_OK);
315 lck.in.lock_count = 2;
316 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
317 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
318 status = smb2_lock(tree, &lck);
319 CHECK_STATUS(status, NT_STATUS_OK);
321 lck.in.lock_count = 1;
322 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
323 status = smb2_lock(tree, &lck);
324 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
327 done:
328 return ret;
331 struct test_lock_read_write_state {
332 const char *fname;
333 uint32_t lock_flags;
334 NTSTATUS write_h1_status;
335 NTSTATUS read_h1_status;
336 NTSTATUS write_h2_status;
337 NTSTATUS read_h2_status;
340 static bool test_lock_read_write(struct torture_context *torture,
341 struct smb2_tree *tree,
342 struct test_lock_read_write_state *s)
344 bool ret = true;
345 NTSTATUS status;
346 struct smb2_handle h1, h2;
347 uint8_t buf[200];
348 struct smb2_lock lck;
349 struct smb2_create cr;
350 struct smb2_write wr;
351 struct smb2_read rd;
352 struct smb2_lock_element el[1];
354 lck.in.locks = el;
356 ZERO_STRUCT(buf);
358 status = torture_smb2_testfile(tree, s->fname, &h1);
359 CHECK_STATUS(status, NT_STATUS_OK);
361 status = smb2_util_write(tree, h1, buf, 0, ARRAY_SIZE(buf));
362 CHECK_STATUS(status, NT_STATUS_OK);
364 lck.in.lock_count = 0x0001;
365 lck.in.reserved = 0x00000000;
366 lck.in.file.handle = h1;
367 el[0].offset = 0;
368 el[0].length = ARRAY_SIZE(buf)/2;
369 el[0].reserved = 0x00000000;
370 el[0].flags = s->lock_flags;
371 status = smb2_lock(tree, &lck);
372 CHECK_STATUS(status, NT_STATUS_OK);
373 CHECK_VALUE(lck.out.reserved, 0);
375 lck.in.lock_count = 0x0001;
376 lck.in.reserved = 0x00000000;
377 lck.in.file.handle = h1;
378 el[0].offset = ARRAY_SIZE(buf)/2;
379 el[0].length = ARRAY_SIZE(buf)/2;
380 el[0].reserved = 0x00000000;
381 el[0].flags = s->lock_flags;
382 status = smb2_lock(tree, &lck);
383 CHECK_STATUS(status, NT_STATUS_OK);
384 CHECK_VALUE(lck.out.reserved, 0);
386 ZERO_STRUCT(cr);
387 cr.in.oplock_level = 0;
388 cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
389 cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
390 cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
391 cr.in.share_access =
392 NTCREATEX_SHARE_ACCESS_DELETE|
393 NTCREATEX_SHARE_ACCESS_READ|
394 NTCREATEX_SHARE_ACCESS_WRITE;
395 cr.in.create_options = 0;
396 cr.in.fname = s->fname;
398 status = smb2_create(tree, tree, &cr);
399 CHECK_STATUS(status, NT_STATUS_OK);
401 h2 = cr.out.file.handle;
403 ZERO_STRUCT(wr);
404 wr.in.file.handle = h1;
405 wr.in.offset = ARRAY_SIZE(buf)/2;
406 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
408 status = smb2_write(tree, &wr);
409 CHECK_STATUS(status, s->write_h1_status);
411 ZERO_STRUCT(rd);
412 rd.in.file.handle = h1;
413 rd.in.offset = ARRAY_SIZE(buf)/2;
414 rd.in.length = ARRAY_SIZE(buf)/2;
416 status = smb2_read(tree, tree, &rd);
417 CHECK_STATUS(status, s->read_h1_status);
419 ZERO_STRUCT(wr);
420 wr.in.file.handle = h2;
421 wr.in.offset = ARRAY_SIZE(buf)/2;
422 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
424 status = smb2_write(tree, &wr);
425 CHECK_STATUS(status, s->write_h2_status);
427 ZERO_STRUCT(rd);
428 rd.in.file.handle = h2;
429 rd.in.offset = ARRAY_SIZE(buf)/2;
430 rd.in.length = ARRAY_SIZE(buf)/2;
432 status = smb2_read(tree, tree, &rd);
433 CHECK_STATUS(status, s->read_h2_status);
435 lck.in.lock_count = 0x0001;
436 lck.in.reserved = 0x00000000;
437 lck.in.file.handle = h1;
438 el[0].offset = ARRAY_SIZE(buf)/2;
439 el[0].length = ARRAY_SIZE(buf)/2;
440 el[0].reserved = 0x00000000;
441 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
442 status = smb2_lock(tree, &lck);
443 CHECK_STATUS(status, NT_STATUS_OK);
444 CHECK_VALUE(lck.out.reserved, 0);
446 ZERO_STRUCT(wr);
447 wr.in.file.handle = h2;
448 wr.in.offset = ARRAY_SIZE(buf)/2;
449 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
451 status = smb2_write(tree, &wr);
452 CHECK_STATUS(status, NT_STATUS_OK);
454 ZERO_STRUCT(rd);
455 rd.in.file.handle = h2;
456 rd.in.offset = ARRAY_SIZE(buf)/2;
457 rd.in.length = ARRAY_SIZE(buf)/2;
459 status = smb2_read(tree, tree, &rd);
460 CHECK_STATUS(status, NT_STATUS_OK);
462 done:
463 return ret;
466 static bool test_lock_rw_none(struct torture_context *torture, struct smb2_tree *tree)
468 struct test_lock_read_write_state s = {
469 .fname = "lock_rw_none.dat",
470 .lock_flags = SMB2_LOCK_FLAG_NONE,
471 .write_h1_status = NT_STATUS_FILE_LOCK_CONFLICT,
472 .read_h1_status = NT_STATUS_OK,
473 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
474 .read_h2_status = NT_STATUS_OK,
477 return test_lock_read_write(torture, tree, &s);
480 static bool test_lock_rw_shared(struct torture_context *torture, struct smb2_tree *tree)
482 struct test_lock_read_write_state s = {
483 .fname = "lock_rw_shared.dat",
484 .lock_flags = SMB2_LOCK_FLAG_SHARED,
485 .write_h1_status = NT_STATUS_FILE_LOCK_CONFLICT,
486 .read_h1_status = NT_STATUS_OK,
487 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
488 .read_h2_status = NT_STATUS_OK,
491 return test_lock_read_write(torture, tree, &s);
494 static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_tree *tree)
496 struct test_lock_read_write_state s = {
497 .fname = "lock_rw_exclusiv.dat",
498 .lock_flags = SMB2_LOCK_FLAG_EXCLUSIVE,
499 .write_h1_status = NT_STATUS_OK,
500 .read_h1_status = NT_STATUS_OK,
501 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
502 .read_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
505 return test_lock_read_write(torture, tree, &s);
508 static bool test_lock_auto_unlock(struct torture_context *torture, struct smb2_tree *tree)
510 bool ret = true;
511 NTSTATUS status;
512 struct smb2_handle h;
513 uint8_t buf[200];
514 struct smb2_lock lck;
515 struct smb2_lock_element el[2];
517 ZERO_STRUCT(buf);
519 status = torture_smb2_testfile(tree, "autounlock.txt", &h);
520 CHECK_STATUS(status, NT_STATUS_OK);
522 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
523 CHECK_STATUS(status, NT_STATUS_OK);
525 ZERO_STRUCT(lck);
526 lck.in.locks = el;
527 lck.in.lock_count = 0x0001;
528 lck.in.file.handle = h;
529 el[0].offset = 0;
530 el[0].length = 1;
531 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
532 status = smb2_lock(tree, &lck);
533 CHECK_STATUS(status, NT_STATUS_OK);
535 status = smb2_lock(tree, &lck);
536 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
538 status = smb2_lock(tree, &lck);
539 if (TARGET_IS_WINDOWS(torture)) {
540 CHECK_STATUS(status, NT_STATUS_OK);
541 } else {
542 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
545 status = smb2_lock(tree, &lck);
546 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
548 done:
549 return ret;
553 /* basic testing of SMB2 locking
555 struct torture_suite *torture_smb2_lock_init(void)
557 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "LOCK");
559 torture_suite_add_1smb2_test(suite, "VALID-REQUEST", test_valid_request);
560 torture_suite_add_1smb2_test(suite, "RW-NONE", test_lock_rw_none);
561 torture_suite_add_1smb2_test(suite, "RW-SHARED", test_lock_rw_shared);
562 torture_suite_add_1smb2_test(suite, "RW-EXCLUSIV", test_lock_rw_exclusiv);
563 torture_suite_add_1smb2_test(suite, "AUTO-UNLOCK", test_lock_auto_unlock);
565 suite->description = talloc_strdup(suite, "SMB2-LOCK tests");
567 return suite;