2 Unix SMB/CIFS implementation.
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/>.
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)); \
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); \
50 static bool test_valid_request(struct torture_context *torture, struct smb2_tree *tree)
57 struct smb2_lock_element el[2];
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);
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;
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_WIN7_INVALID_RANGE);
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_WIN7_INVALID_RANGE);
115 CHECK_STATUS(status, NT_STATUS_OK);
118 lck.in.reserved = 0x123ab3;
119 status = smb2_lock(tree, &lck);
120 if (TARGET_IS_WIN7(torture)) {
121 CHECK_STATUS(status, NT_STATUS_WIN7_INVALID_RANGE);
122 } else if (TARGET_IS_WINDOWS(torture)) {
123 CHECK_STATUS(status, NT_STATUS_OK);
125 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
127 CHECK_VALUE(lck.out.reserved, 0);
129 lck.in.reserved = 0x123ab4;
130 status = smb2_lock(tree, &lck);
131 if (TARGET_IS_WIN7(torture)) {
132 CHECK_STATUS(status, NT_STATUS_WIN7_INVALID_RANGE);
134 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
137 lck.in.reserved = 0x123ab5;
138 status = smb2_lock(tree, &lck);
139 if (TARGET_IS_WIN7(torture)) {
140 CHECK_STATUS(status, NT_STATUS_WIN7_INVALID_RANGE);
141 } else if (TARGET_IS_WINDOWS(torture)) {
142 CHECK_STATUS(status, NT_STATUS_OK);
144 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
146 CHECK_VALUE(lck.out.reserved, 0);
148 lck.in.lock_count = 0x0001;
149 lck.in.reserved = 0x12345678;
150 lck.in.file.handle = h;
151 el[0].offset = UINT32_MAX;
152 el[0].length = UINT32_MAX;
153 el[0].reserved = 0x87654321;
154 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
155 status = smb2_lock(tree, &lck);
156 CHECK_STATUS(status, NT_STATUS_OK);
157 CHECK_VALUE(lck.out.reserved, 0);
159 status = smb2_lock(tree, &lck);
160 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
162 status = smb2_lock(tree, &lck);
163 if (TARGET_IS_WINDOWS(torture)) {
164 CHECK_STATUS(status, NT_STATUS_OK);
166 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
168 CHECK_VALUE(lck.out.reserved, 0);
170 status = smb2_lock(tree, &lck);
171 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
173 status = smb2_lock(tree, &lck);
174 if (TARGET_IS_WINDOWS(torture)) {
175 CHECK_STATUS(status, NT_STATUS_OK);
177 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
179 CHECK_VALUE(lck.out.reserved, 0);
181 el[0].flags = 0x00000000;
182 status = smb2_lock(tree, &lck);
183 CHECK_STATUS(status, NT_STATUS_OK);
184 CHECK_VALUE(lck.out.reserved, 0);
186 status = smb2_lock(tree, &lck);
187 CHECK_STATUS(status, NT_STATUS_OK);
188 CHECK_VALUE(lck.out.reserved, 0);
190 el[0].flags = 0x00000001;
191 status = smb2_lock(tree, &lck);
192 CHECK_STATUS(status, NT_STATUS_OK);
193 CHECK_VALUE(lck.out.reserved, 0);
195 status = smb2_lock(tree, &lck);
196 CHECK_STATUS(status, NT_STATUS_OK);
197 CHECK_VALUE(lck.out.reserved, 0);
199 lck.in.lock_count = 0x0001;
200 lck.in.reserved = 0x87654321;
201 lck.in.file.handle = h;
202 el[0].offset = 0x00000000FFFFFFFF;
203 el[0].length = 0x00000000FFFFFFFF;
204 el[0].reserved = 0x1234567;
205 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
206 status = smb2_lock(tree, &lck);
207 CHECK_STATUS(status, NT_STATUS_OK);
209 lck.in.lock_count = 0x0001;
210 lck.in.reserved = 0x1234567;
211 lck.in.file.handle = h;
212 el[0].offset = 0x00000000FFFFFFFF;
213 el[0].length = 0x00000000FFFFFFFF;
214 el[0].reserved = 0x00000000;
215 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
216 status = smb2_lock(tree, &lck);
217 CHECK_STATUS(status, NT_STATUS_OK);
219 status = smb2_lock(tree, &lck);
220 CHECK_STATUS(status, NT_STATUS_OK);
221 status = smb2_lock(tree, &lck);
222 CHECK_STATUS(status, NT_STATUS_OK);
223 status = smb2_lock(tree, &lck);
224 CHECK_STATUS(status, NT_STATUS_OK);
225 status = smb2_lock(tree, &lck);
226 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
228 lck.in.lock_count = 0x0001;
230 lck.in.file.handle = h;
233 el[0].reserved = 0x00000000;
234 el[0].flags = ~SMB2_LOCK_FLAG_ALL_MASK;
236 status = smb2_lock(tree, &lck);
237 CHECK_STATUS(status, NT_STATUS_OK);
239 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
240 status = smb2_lock(tree, &lck);
241 CHECK_STATUS(status, NT_STATUS_OK);
243 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
244 status = smb2_lock(tree, &lck);
245 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
247 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_EXCLUSIVE;
248 status = smb2_lock(tree, &lck);
249 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
251 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_SHARED;
252 status = smb2_lock(tree, &lck);
253 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
255 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
256 status = smb2_lock(tree, &lck);
257 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
259 lck.in.lock_count = 2;
261 lck.in.file.handle = h;
264 el[0].reserved = 0x00000000;
267 el[1].reserved = 0x00000000;
269 lck.in.lock_count = 2;
271 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
272 status = smb2_lock(tree, &lck);
273 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
275 lck.in.lock_count = 2;
278 status = smb2_lock(tree, &lck);
279 CHECK_STATUS(status, NT_STATUS_OK);
281 lck.in.lock_count = 2;
282 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
284 status = smb2_lock(tree, &lck);
285 CHECK_STATUS(status, NT_STATUS_OK);
287 lck.in.lock_count = 1;
288 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
289 status = smb2_lock(tree, &lck);
290 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
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;
304 status = smb2_lock(tree, &lck);
305 CHECK_STATUS(status, NT_STATUS_OK);
307 status = smb2_lock(tree, &lck);
308 CHECK_STATUS(status, NT_STATUS_OK);
310 lck.in.lock_count = 2;
311 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
312 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
313 status = smb2_lock(tree, &lck);
314 CHECK_STATUS(status, NT_STATUS_OK);
316 lck.in.lock_count = 1;
317 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
318 status = smb2_lock(tree, &lck);
319 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
326 struct test_lock_read_write_state {
329 NTSTATUS write_h1_status;
330 NTSTATUS read_h1_status;
331 NTSTATUS write_h2_status;
332 NTSTATUS read_h2_status;
335 static bool test_lock_read_write(struct torture_context *torture,
336 struct smb2_tree *tree,
337 struct test_lock_read_write_state *s)
341 struct smb2_handle h1, h2;
343 struct smb2_lock lck;
344 struct smb2_create cr;
345 struct smb2_write wr;
347 struct smb2_lock_element el[1];
353 status = torture_smb2_testfile(tree, s->fname, &h1);
354 CHECK_STATUS(status, NT_STATUS_OK);
356 status = smb2_util_write(tree, h1, buf, 0, ARRAY_SIZE(buf));
357 CHECK_STATUS(status, NT_STATUS_OK);
359 lck.in.lock_count = 0x0001;
360 lck.in.reserved = 0x00000000;
361 lck.in.file.handle = h1;
363 el[0].length = ARRAY_SIZE(buf)/2;
364 el[0].reserved = 0x00000000;
365 el[0].flags = s->lock_flags;
366 status = smb2_lock(tree, &lck);
367 CHECK_STATUS(status, NT_STATUS_OK);
368 CHECK_VALUE(lck.out.reserved, 0);
370 lck.in.lock_count = 0x0001;
371 lck.in.reserved = 0x00000000;
372 lck.in.file.handle = h1;
373 el[0].offset = ARRAY_SIZE(buf)/2;
374 el[0].length = ARRAY_SIZE(buf)/2;
375 el[0].reserved = 0x00000000;
376 el[0].flags = s->lock_flags;
377 status = smb2_lock(tree, &lck);
378 CHECK_STATUS(status, NT_STATUS_OK);
379 CHECK_VALUE(lck.out.reserved, 0);
382 cr.in.oplock_level = 0;
383 cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
384 cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
385 cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
387 NTCREATEX_SHARE_ACCESS_DELETE|
388 NTCREATEX_SHARE_ACCESS_READ|
389 NTCREATEX_SHARE_ACCESS_WRITE;
390 cr.in.create_options = 0;
391 cr.in.fname = s->fname;
393 status = smb2_create(tree, tree, &cr);
394 CHECK_STATUS(status, NT_STATUS_OK);
396 h2 = cr.out.file.handle;
399 wr.in.file.handle = h1;
400 wr.in.offset = ARRAY_SIZE(buf)/2;
401 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
403 status = smb2_write(tree, &wr);
404 CHECK_STATUS(status, s->write_h1_status);
407 rd.in.file.handle = h1;
408 rd.in.offset = ARRAY_SIZE(buf)/2;
409 rd.in.length = ARRAY_SIZE(buf)/2;
411 status = smb2_read(tree, tree, &rd);
412 CHECK_STATUS(status, s->read_h1_status);
415 wr.in.file.handle = h2;
416 wr.in.offset = ARRAY_SIZE(buf)/2;
417 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
419 status = smb2_write(tree, &wr);
420 CHECK_STATUS(status, s->write_h2_status);
423 rd.in.file.handle = h2;
424 rd.in.offset = ARRAY_SIZE(buf)/2;
425 rd.in.length = ARRAY_SIZE(buf)/2;
427 status = smb2_read(tree, tree, &rd);
428 CHECK_STATUS(status, s->read_h2_status);
430 lck.in.lock_count = 0x0001;
431 lck.in.reserved = 0x00000000;
432 lck.in.file.handle = h1;
433 el[0].offset = ARRAY_SIZE(buf)/2;
434 el[0].length = ARRAY_SIZE(buf)/2;
435 el[0].reserved = 0x00000000;
436 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
437 status = smb2_lock(tree, &lck);
438 CHECK_STATUS(status, NT_STATUS_OK);
439 CHECK_VALUE(lck.out.reserved, 0);
442 wr.in.file.handle = h2;
443 wr.in.offset = ARRAY_SIZE(buf)/2;
444 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
446 status = smb2_write(tree, &wr);
447 CHECK_STATUS(status, NT_STATUS_OK);
450 rd.in.file.handle = h2;
451 rd.in.offset = ARRAY_SIZE(buf)/2;
452 rd.in.length = ARRAY_SIZE(buf)/2;
454 status = smb2_read(tree, tree, &rd);
455 CHECK_STATUS(status, NT_STATUS_OK);
461 static bool test_lock_rw_none(struct torture_context *torture, struct smb2_tree *tree)
463 struct test_lock_read_write_state s = {
464 .fname = "lock_rw_none.dat",
465 .lock_flags = SMB2_LOCK_FLAG_NONE,
466 .write_h1_status = NT_STATUS_FILE_LOCK_CONFLICT,
467 .read_h1_status = NT_STATUS_OK,
468 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
469 .read_h2_status = NT_STATUS_OK,
472 return test_lock_read_write(torture, tree, &s);
475 static bool test_lock_rw_shared(struct torture_context *torture, struct smb2_tree *tree)
477 struct test_lock_read_write_state s = {
478 .fname = "lock_rw_shared.dat",
479 .lock_flags = SMB2_LOCK_FLAG_SHARED,
480 .write_h1_status = NT_STATUS_FILE_LOCK_CONFLICT,
481 .read_h1_status = NT_STATUS_OK,
482 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
483 .read_h2_status = NT_STATUS_OK,
486 return test_lock_read_write(torture, tree, &s);
489 static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_tree *tree)
491 struct test_lock_read_write_state s = {
492 .fname = "lock_rw_exclusiv.dat",
493 .lock_flags = SMB2_LOCK_FLAG_EXCLUSIVE,
494 .write_h1_status = NT_STATUS_OK,
495 .read_h1_status = NT_STATUS_OK,
496 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
497 .read_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
500 return test_lock_read_write(torture, tree, &s);
503 static bool test_lock_auto_unlock(struct torture_context *torture, struct smb2_tree *tree)
507 struct smb2_handle h;
509 struct smb2_lock lck;
510 struct smb2_lock_element el[2];
514 status = torture_smb2_testfile(tree, "autounlock.txt", &h);
515 CHECK_STATUS(status, NT_STATUS_OK);
517 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
518 CHECK_STATUS(status, NT_STATUS_OK);
522 lck.in.lock_count = 0x0001;
523 lck.in.file.handle = h;
526 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
527 status = smb2_lock(tree, &lck);
528 CHECK_STATUS(status, NT_STATUS_OK);
530 status = smb2_lock(tree, &lck);
531 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
533 status = smb2_lock(tree, &lck);
534 if (TARGET_IS_WINDOWS(torture)) {
535 CHECK_STATUS(status, NT_STATUS_OK);
537 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
540 status = smb2_lock(tree, &lck);
541 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
548 /* basic testing of SMB2 locking
550 struct torture_suite *torture_smb2_lock_init(void)
552 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "LOCK");
554 torture_suite_add_1smb2_test(suite, "VALID-REQUEST", test_valid_request);
555 torture_suite_add_1smb2_test(suite, "RW-NONE", test_lock_rw_none);
556 torture_suite_add_1smb2_test(suite, "RW-SHARED", test_lock_rw_shared);
557 torture_suite_add_1smb2_test(suite, "RW-EXCLUSIV", test_lock_rw_exclusiv);
558 torture_suite_add_1smb2_test(suite, "AUTO-UNLOCK", test_lock_auto_unlock);
560 suite->description = talloc_strdup(suite, "SMB2-LOCK tests");