Fix bug 7950 - Samba 3.5.x fails BASE-CREATEX_SHAREMODES_DIR smbtorture4 test
[Samba.git] / source4 / torture / smb2 / lock.c
blobb97233ef66139dcfc054aea636c7fda7c0c38248
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"
29 #include "librpc/gen_ndr/ndr_security.h"
31 #define TARGET_IS_WINDOWS(_tctx) (torture_setting_bool(_tctx, "win7", false) || torture_setting_bool(torture, "windows", false))
32 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
34 #define CHECK_STATUS(status, correct) do { \
35 if (!NT_STATUS_EQUAL(status, correct)) { \
36 printf("(%s) Incorrect status %s - should be %s\n", \
37 __location__, nt_errstr(status), nt_errstr(correct)); \
38 ret = false; \
39 goto done; \
40 }} while (0)
42 #define CHECK_VALUE(v, correct) do { \
43 if ((v) != (correct)) { \
44 printf("(%s) Incorrect value %s=%d - should be %d\n", \
45 __location__, #v, v, correct); \
46 ret = false; \
47 goto done; \
48 }} while (0)
50 static bool test_valid_request(struct torture_context *torture, struct smb2_tree *tree)
52 bool ret = true;
53 NTSTATUS status;
54 struct smb2_handle h;
55 uint8_t buf[200];
56 struct smb2_lock lck;
57 struct smb2_lock_element el[2];
59 ZERO_STRUCT(buf);
61 status = torture_smb2_testfile(tree, "lock1.txt", &h);
62 CHECK_STATUS(status, NT_STATUS_OK);
64 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
65 CHECK_STATUS(status, NT_STATUS_OK);
67 lck.in.locks = el;
69 lck.in.lock_count = 0x0000;
70 lck.in.reserved = 0x00000000;
71 lck.in.file.handle = h;
72 el[0].offset = 0x0000000000000000;
73 el[0].length = 0x0000000000000000;
74 el[0].reserved = 0x0000000000000000;
75 el[0].flags = 0x00000000;
76 status = smb2_lock(tree, &lck);
77 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
79 lck.in.lock_count = 0x0001;
80 lck.in.reserved = 0x00000000;
81 lck.in.file.handle = h;
82 el[0].offset = 0;
83 el[0].length = 0;
84 el[0].reserved = 0x00000000;
85 el[0].flags = SMB2_LOCK_FLAG_NONE;
86 status = smb2_lock(tree, &lck);
87 CHECK_STATUS(status, NT_STATUS_OK);
88 CHECK_VALUE(lck.out.reserved, 0);
90 lck.in.file.handle.data[0] +=1;
91 status = smb2_lock(tree, &lck);
92 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
93 lck.in.file.handle.data[0] -=1;
95 lck.in.lock_count = 0x0001;
96 lck.in.reserved = 0x123ab1;
97 lck.in.file.handle = h;
98 el[0].offset = UINT64_MAX;
99 el[0].length = UINT64_MAX;
100 el[0].reserved = 0x00000000;
101 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
102 status = smb2_lock(tree, &lck);
103 if (TARGET_IS_WIN7(torture)) {
104 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
105 } else {
106 CHECK_STATUS(status, NT_STATUS_OK);
108 CHECK_VALUE(lck.out.reserved, 0);
110 lck.in.reserved = 0x123ab2;
111 status = smb2_lock(tree, &lck);
112 if (TARGET_IS_WIN7(torture)) {
113 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
114 } else if (TARGET_IS_WINDOWS(torture)) {
115 CHECK_STATUS(status, NT_STATUS_OK);
116 } else {
117 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
119 CHECK_VALUE(lck.out.reserved, 0);
121 lck.in.reserved = 0x123ab3;
122 status = smb2_lock(tree, &lck);
123 if (TARGET_IS_WIN7(torture)) {
124 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
125 } else if (TARGET_IS_WINDOWS(torture)) {
126 CHECK_STATUS(status, NT_STATUS_OK);
127 } else {
128 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
130 CHECK_VALUE(lck.out.reserved, 0);
132 lck.in.reserved = 0x123ab4;
133 status = smb2_lock(tree, &lck);
134 if (TARGET_IS_WIN7(torture)) {
135 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
136 } else if (TARGET_IS_WINDOWS(torture)) {
137 CHECK_STATUS(status, NT_STATUS_OK);
138 } else {
139 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
141 CHECK_VALUE(lck.out.reserved, 0);
143 lck.in.reserved = 0x123ab5;
144 status = smb2_lock(tree, &lck);
145 if (TARGET_IS_WIN7(torture)) {
146 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
147 } else if (TARGET_IS_WINDOWS(torture)) {
148 CHECK_STATUS(status, NT_STATUS_OK);
149 } else {
150 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
152 CHECK_VALUE(lck.out.reserved, 0);
154 lck.in.lock_count = 0x0001;
155 lck.in.reserved = 0x12345678;
156 lck.in.file.handle = h;
157 el[0].offset = UINT32_MAX;
158 el[0].length = UINT32_MAX;
159 el[0].reserved = 0x87654321;
160 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
161 status = smb2_lock(tree, &lck);
162 CHECK_STATUS(status, NT_STATUS_OK);
163 CHECK_VALUE(lck.out.reserved, 0);
165 status = smb2_lock(tree, &lck);
166 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
168 status = smb2_lock(tree, &lck);
169 if (TARGET_IS_WINDOWS(torture)) {
170 CHECK_STATUS(status, NT_STATUS_OK);
171 } else {
172 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
174 CHECK_VALUE(lck.out.reserved, 0);
176 status = smb2_lock(tree, &lck);
177 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
179 status = smb2_lock(tree, &lck);
180 if (TARGET_IS_WINDOWS(torture)) {
181 CHECK_STATUS(status, NT_STATUS_OK);
182 } else {
183 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
185 CHECK_VALUE(lck.out.reserved, 0);
187 el[0].flags = 0x00000000;
188 status = smb2_lock(tree, &lck);
189 CHECK_STATUS(status, NT_STATUS_OK);
190 CHECK_VALUE(lck.out.reserved, 0);
192 status = smb2_lock(tree, &lck);
193 CHECK_STATUS(status, NT_STATUS_OK);
194 CHECK_VALUE(lck.out.reserved, 0);
196 el[0].flags = 0x00000001;
197 status = smb2_lock(tree, &lck);
198 CHECK_STATUS(status, NT_STATUS_OK);
199 CHECK_VALUE(lck.out.reserved, 0);
201 status = smb2_lock(tree, &lck);
202 CHECK_STATUS(status, NT_STATUS_OK);
203 CHECK_VALUE(lck.out.reserved, 0);
205 lck.in.lock_count = 0x0001;
206 lck.in.reserved = 0x87654321;
207 lck.in.file.handle = h;
208 el[0].offset = 0x00000000FFFFFFFF;
209 el[0].length = 0x00000000FFFFFFFF;
210 el[0].reserved = 0x1234567;
211 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
212 status = smb2_lock(tree, &lck);
213 CHECK_STATUS(status, NT_STATUS_OK);
215 lck.in.lock_count = 0x0001;
216 lck.in.reserved = 0x1234567;
217 lck.in.file.handle = h;
218 el[0].offset = 0x00000000FFFFFFFF;
219 el[0].length = 0x00000000FFFFFFFF;
220 el[0].reserved = 0x00000000;
221 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
222 status = smb2_lock(tree, &lck);
223 CHECK_STATUS(status, NT_STATUS_OK);
225 status = smb2_lock(tree, &lck);
226 CHECK_STATUS(status, NT_STATUS_OK);
227 status = smb2_lock(tree, &lck);
228 CHECK_STATUS(status, NT_STATUS_OK);
229 status = smb2_lock(tree, &lck);
230 CHECK_STATUS(status, NT_STATUS_OK);
231 status = smb2_lock(tree, &lck);
232 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
234 lck.in.lock_count = 0x0001;
235 lck.in.reserved = 0;
236 lck.in.file.handle = h;
237 el[0].offset = 1;
238 el[0].length = 1;
239 el[0].reserved = 0x00000000;
240 el[0].flags = ~SMB2_LOCK_FLAG_ALL_MASK;
242 status = smb2_lock(tree, &lck);
243 CHECK_STATUS(status, NT_STATUS_OK);
245 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
246 status = smb2_lock(tree, &lck);
247 CHECK_STATUS(status, NT_STATUS_OK);
249 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
250 status = smb2_lock(tree, &lck);
251 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
253 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_EXCLUSIVE;
254 status = smb2_lock(tree, &lck);
255 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
257 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_SHARED;
258 status = smb2_lock(tree, &lck);
259 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
261 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
262 status = smb2_lock(tree, &lck);
263 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
265 lck.in.lock_count = 2;
266 lck.in.reserved = 0;
267 lck.in.file.handle = h;
268 el[0].offset = 9999;
269 el[0].length = 1;
270 el[0].reserved = 0x00000000;
271 el[1].offset = 9999;
272 el[1].length = 1;
273 el[1].reserved = 0x00000000;
275 lck.in.lock_count = 2;
276 el[0].flags = 0;
277 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
278 status = smb2_lock(tree, &lck);
279 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
281 lck.in.lock_count = 2;
282 el[0].flags = 0;
283 el[1].flags = 0;
284 status = smb2_lock(tree, &lck);
285 CHECK_STATUS(status, NT_STATUS_OK);
287 lck.in.lock_count = 2;
288 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
289 el[1].flags = 0;
290 status = smb2_lock(tree, &lck);
291 CHECK_STATUS(status, NT_STATUS_OK);
293 lck.in.lock_count = 1;
294 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
295 status = smb2_lock(tree, &lck);
296 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
298 lck.in.lock_count = 1;
299 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
300 status = smb2_lock(tree, &lck);
301 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
303 lck.in.lock_count = 1;
304 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
305 status = smb2_lock(tree, &lck);
306 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
308 lck.in.lock_count = 1;
309 el[0].flags = 0;
310 status = smb2_lock(tree, &lck);
311 CHECK_STATUS(status, NT_STATUS_OK);
313 status = smb2_lock(tree, &lck);
314 CHECK_STATUS(status, NT_STATUS_OK);
316 lck.in.lock_count = 2;
317 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
318 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
319 status = smb2_lock(tree, &lck);
320 CHECK_STATUS(status, NT_STATUS_OK);
322 lck.in.lock_count = 1;
323 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
324 status = smb2_lock(tree, &lck);
325 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
328 done:
329 return ret;
332 struct test_lock_read_write_state {
333 const char *fname;
334 uint32_t lock_flags;
335 NTSTATUS write_h1_status;
336 NTSTATUS read_h1_status;
337 NTSTATUS write_h2_status;
338 NTSTATUS read_h2_status;
341 static bool test_lock_read_write(struct torture_context *torture,
342 struct smb2_tree *tree,
343 struct test_lock_read_write_state *s)
345 bool ret = true;
346 NTSTATUS status;
347 struct smb2_handle h1, h2;
348 uint8_t buf[200];
349 struct smb2_lock lck;
350 struct smb2_create cr;
351 struct smb2_write wr;
352 struct smb2_read rd;
353 struct smb2_lock_element el[1];
355 lck.in.locks = el;
357 ZERO_STRUCT(buf);
359 status = torture_smb2_testfile(tree, s->fname, &h1);
360 CHECK_STATUS(status, NT_STATUS_OK);
362 status = smb2_util_write(tree, h1, buf, 0, ARRAY_SIZE(buf));
363 CHECK_STATUS(status, NT_STATUS_OK);
365 lck.in.lock_count = 0x0001;
366 lck.in.reserved = 0x00000000;
367 lck.in.file.handle = h1;
368 el[0].offset = 0;
369 el[0].length = ARRAY_SIZE(buf)/2;
370 el[0].reserved = 0x00000000;
371 el[0].flags = s->lock_flags;
372 status = smb2_lock(tree, &lck);
373 CHECK_STATUS(status, NT_STATUS_OK);
374 CHECK_VALUE(lck.out.reserved, 0);
376 lck.in.lock_count = 0x0001;
377 lck.in.reserved = 0x00000000;
378 lck.in.file.handle = h1;
379 el[0].offset = ARRAY_SIZE(buf)/2;
380 el[0].length = ARRAY_SIZE(buf)/2;
381 el[0].reserved = 0x00000000;
382 el[0].flags = s->lock_flags;
383 status = smb2_lock(tree, &lck);
384 CHECK_STATUS(status, NT_STATUS_OK);
385 CHECK_VALUE(lck.out.reserved, 0);
387 ZERO_STRUCT(cr);
388 cr.in.oplock_level = 0;
389 cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
390 cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
391 cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
392 cr.in.share_access =
393 NTCREATEX_SHARE_ACCESS_DELETE|
394 NTCREATEX_SHARE_ACCESS_READ|
395 NTCREATEX_SHARE_ACCESS_WRITE;
396 cr.in.create_options = 0;
397 cr.in.fname = s->fname;
399 status = smb2_create(tree, tree, &cr);
400 CHECK_STATUS(status, NT_STATUS_OK);
402 h2 = cr.out.file.handle;
404 ZERO_STRUCT(wr);
405 wr.in.file.handle = h1;
406 wr.in.offset = ARRAY_SIZE(buf)/2;
407 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
409 status = smb2_write(tree, &wr);
410 CHECK_STATUS(status, s->write_h1_status);
412 ZERO_STRUCT(rd);
413 rd.in.file.handle = h1;
414 rd.in.offset = ARRAY_SIZE(buf)/2;
415 rd.in.length = ARRAY_SIZE(buf)/2;
417 status = smb2_read(tree, tree, &rd);
418 CHECK_STATUS(status, s->read_h1_status);
420 ZERO_STRUCT(wr);
421 wr.in.file.handle = h2;
422 wr.in.offset = ARRAY_SIZE(buf)/2;
423 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
425 status = smb2_write(tree, &wr);
426 CHECK_STATUS(status, s->write_h2_status);
428 ZERO_STRUCT(rd);
429 rd.in.file.handle = h2;
430 rd.in.offset = ARRAY_SIZE(buf)/2;
431 rd.in.length = ARRAY_SIZE(buf)/2;
433 status = smb2_read(tree, tree, &rd);
434 CHECK_STATUS(status, s->read_h2_status);
436 lck.in.lock_count = 0x0001;
437 lck.in.reserved = 0x00000000;
438 lck.in.file.handle = h1;
439 el[0].offset = ARRAY_SIZE(buf)/2;
440 el[0].length = ARRAY_SIZE(buf)/2;
441 el[0].reserved = 0x00000000;
442 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
443 status = smb2_lock(tree, &lck);
444 CHECK_STATUS(status, NT_STATUS_OK);
445 CHECK_VALUE(lck.out.reserved, 0);
447 ZERO_STRUCT(wr);
448 wr.in.file.handle = h2;
449 wr.in.offset = ARRAY_SIZE(buf)/2;
450 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
452 status = smb2_write(tree, &wr);
453 CHECK_STATUS(status, NT_STATUS_OK);
455 ZERO_STRUCT(rd);
456 rd.in.file.handle = h2;
457 rd.in.offset = ARRAY_SIZE(buf)/2;
458 rd.in.length = ARRAY_SIZE(buf)/2;
460 status = smb2_read(tree, tree, &rd);
461 CHECK_STATUS(status, NT_STATUS_OK);
463 done:
464 return ret;
467 static bool test_lock_rw_none(struct torture_context *torture, struct smb2_tree *tree)
469 struct test_lock_read_write_state s = {
470 .fname = "lock_rw_none.dat",
471 .lock_flags = SMB2_LOCK_FLAG_NONE,
472 .write_h1_status = NT_STATUS_FILE_LOCK_CONFLICT,
473 .read_h1_status = NT_STATUS_OK,
474 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
475 .read_h2_status = NT_STATUS_OK,
478 return test_lock_read_write(torture, tree, &s);
481 static bool test_lock_rw_shared(struct torture_context *torture, struct smb2_tree *tree)
483 struct test_lock_read_write_state s = {
484 .fname = "lock_rw_shared.dat",
485 .lock_flags = SMB2_LOCK_FLAG_SHARED,
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 return test_lock_read_write(torture, tree, &s);
495 static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_tree *tree)
497 struct test_lock_read_write_state s = {
498 .fname = "lock_rw_exclusiv.dat",
499 .lock_flags = SMB2_LOCK_FLAG_EXCLUSIVE,
500 .write_h1_status = NT_STATUS_OK,
501 .read_h1_status = NT_STATUS_OK,
502 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
503 .read_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
506 return test_lock_read_write(torture, tree, &s);
509 static bool test_lock_auto_unlock(struct torture_context *torture, struct smb2_tree *tree)
511 bool ret = true;
512 NTSTATUS status;
513 struct smb2_handle h;
514 uint8_t buf[200];
515 struct smb2_lock lck;
516 struct smb2_lock_element el[2];
518 ZERO_STRUCT(buf);
520 status = torture_smb2_testfile(tree, "autounlock.txt", &h);
521 CHECK_STATUS(status, NT_STATUS_OK);
523 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
524 CHECK_STATUS(status, NT_STATUS_OK);
526 ZERO_STRUCT(lck);
527 lck.in.locks = el;
528 lck.in.lock_count = 0x0001;
529 lck.in.file.handle = h;
530 el[0].offset = 0;
531 el[0].length = 1;
532 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
533 status = smb2_lock(tree, &lck);
534 CHECK_STATUS(status, NT_STATUS_OK);
536 status = smb2_lock(tree, &lck);
537 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
539 status = smb2_lock(tree, &lck);
540 if (TARGET_IS_WINDOWS(torture)) {
541 CHECK_STATUS(status, NT_STATUS_OK);
542 } else {
543 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
546 status = smb2_lock(tree, &lck);
547 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
549 done:
550 return ret;
554 /* basic testing of SMB2 locking
556 struct torture_suite *torture_smb2_lock_init(void)
558 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "LOCK");
560 torture_suite_add_1smb2_test(suite, "VALID-REQUEST", test_valid_request);
561 torture_suite_add_1smb2_test(suite, "RW-NONE", test_lock_rw_none);
562 torture_suite_add_1smb2_test(suite, "RW-SHARED", test_lock_rw_shared);
563 torture_suite_add_1smb2_test(suite, "RW-EXCLUSIV", test_lock_rw_exclusiv);
564 torture_suite_add_1smb2_test(suite, "AUTO-UNLOCK", test_lock_auto_unlock);
566 suite->description = talloc_strdup(suite, "SMB2-LOCK tests");
568 return suite;