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 CHECK_STATUS(status, correct) do { \
32 if (!NT_STATUS_EQUAL(status, correct)) { \
33 printf("(%s) Incorrect status %s - should be %s\n", \
34 __location__, nt_errstr(status), nt_errstr(correct)); \
39 #define CHECK_VALUE(v, correct) do { \
40 if ((v) != (correct)) { \
41 printf("(%s) Incorrect value %s=%d - should be %d\n", \
42 __location__, #v, v, correct); \
47 static bool test_valid_request(struct torture_context *torture, struct smb2_tree *tree)
54 struct smb2_lock_element el[2];
58 status = torture_smb2_testfile(tree, "lock1.txt", &h);
59 CHECK_STATUS(status, NT_STATUS_OK);
61 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
62 CHECK_STATUS(status, NT_STATUS_OK);
66 lck.in.lock_count = 0x0000;
67 lck.in.reserved = 0x00000000;
68 lck.in.file.handle = h;
69 el[0].offset = 0x0000000000000000;
70 el[0].length = 0x0000000000000000;
71 el[0].reserved = 0x0000000000000000;
72 el[0].flags = 0x00000000;
73 status = smb2_lock(tree, &lck);
74 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
76 lck.in.lock_count = 0x0001;
77 lck.in.reserved = 0x00000000;
78 lck.in.file.handle = h;
81 el[0].reserved = 0x00000000;
82 el[0].flags = SMB2_LOCK_FLAG_NONE;
83 status = smb2_lock(tree, &lck);
84 CHECK_STATUS(status, NT_STATUS_OK);
85 CHECK_VALUE(lck.out.reserved, 0);
87 lck.in.file.handle.data[0] +=1;
88 status = smb2_lock(tree, &lck);
89 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
90 lck.in.file.handle.data[0] -=1;
92 lck.in.lock_count = 0x0001;
93 lck.in.reserved = 0x123ab1;
94 lck.in.file.handle = h;
95 el[0].offset = UINT64_MAX;
96 el[0].length = UINT64_MAX;
97 el[0].reserved = 0x00000000;
98 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
99 status = smb2_lock(tree, &lck);
100 CHECK_STATUS(status, NT_STATUS_OK);
101 CHECK_VALUE(lck.out.reserved, 0);
103 lck.in.reserved = 0x123ab2;
104 status = smb2_lock(tree, &lck);
105 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
107 lck.in.reserved = 0x123ab3;
108 status = smb2_lock(tree, &lck);
109 if (torture_setting_bool(torture, "windows", false)) {
110 CHECK_STATUS(status, NT_STATUS_OK);
112 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
114 CHECK_VALUE(lck.out.reserved, 0);
116 lck.in.reserved = 0x123ab4;
117 status = smb2_lock(tree, &lck);
118 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
120 lck.in.reserved = 0x123ab5;
121 status = smb2_lock(tree, &lck);
122 if (torture_setting_bool(torture, "windows", false)) {
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.lock_count = 0x0001;
130 lck.in.reserved = 0x12345678;
131 lck.in.file.handle = h;
132 el[0].offset = UINT32_MAX;
133 el[0].length = UINT32_MAX;
134 el[0].reserved = 0x87654321;
135 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
136 status = smb2_lock(tree, &lck);
137 CHECK_STATUS(status, NT_STATUS_OK);
138 CHECK_VALUE(lck.out.reserved, 0);
140 status = smb2_lock(tree, &lck);
141 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
143 status = smb2_lock(tree, &lck);
144 if (torture_setting_bool(torture, "windows", false)) {
145 CHECK_STATUS(status, NT_STATUS_OK);
147 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
149 CHECK_VALUE(lck.out.reserved, 0);
151 status = smb2_lock(tree, &lck);
152 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
154 status = smb2_lock(tree, &lck);
155 if (torture_setting_bool(torture, "windows", false)) {
156 CHECK_STATUS(status, NT_STATUS_OK);
158 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
160 CHECK_VALUE(lck.out.reserved, 0);
162 el[0].flags = 0x00000000;
163 status = smb2_lock(tree, &lck);
164 CHECK_STATUS(status, NT_STATUS_OK);
165 CHECK_VALUE(lck.out.reserved, 0);
167 status = smb2_lock(tree, &lck);
168 CHECK_STATUS(status, NT_STATUS_OK);
169 CHECK_VALUE(lck.out.reserved, 0);
171 el[0].flags = 0x00000001;
172 status = smb2_lock(tree, &lck);
173 CHECK_STATUS(status, NT_STATUS_OK);
174 CHECK_VALUE(lck.out.reserved, 0);
176 status = smb2_lock(tree, &lck);
177 CHECK_STATUS(status, NT_STATUS_OK);
178 CHECK_VALUE(lck.out.reserved, 0);
180 lck.in.lock_count = 0x0001;
181 lck.in.reserved = 0x87654321;
182 lck.in.file.handle = h;
183 el[0].offset = 0x00000000FFFFFFFF;
184 el[0].length = 0x00000000FFFFFFFF;
185 el[0].reserved = 0x1234567;
186 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
187 status = smb2_lock(tree, &lck);
188 CHECK_STATUS(status, NT_STATUS_OK);
190 lck.in.lock_count = 0x0001;
191 lck.in.reserved = 0x1234567;
192 lck.in.file.handle = h;
193 el[0].offset = 0x00000000FFFFFFFF;
194 el[0].length = 0x00000000FFFFFFFF;
195 el[0].reserved = 0x00000000;
196 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
197 status = smb2_lock(tree, &lck);
198 CHECK_STATUS(status, NT_STATUS_OK);
200 status = smb2_lock(tree, &lck);
201 CHECK_STATUS(status, NT_STATUS_OK);
202 status = smb2_lock(tree, &lck);
203 CHECK_STATUS(status, NT_STATUS_OK);
204 status = smb2_lock(tree, &lck);
205 CHECK_STATUS(status, NT_STATUS_OK);
206 status = smb2_lock(tree, &lck);
207 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
209 lck.in.lock_count = 0x0001;
211 lck.in.file.handle = h;
214 el[0].reserved = 0x00000000;
215 el[0].flags = ~SMB2_LOCK_FLAG_ALL_MASK;
217 status = smb2_lock(tree, &lck);
218 CHECK_STATUS(status, NT_STATUS_OK);
220 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
221 status = smb2_lock(tree, &lck);
222 CHECK_STATUS(status, NT_STATUS_OK);
224 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
225 status = smb2_lock(tree, &lck);
226 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
228 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_EXCLUSIVE;
229 status = smb2_lock(tree, &lck);
230 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
232 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_SHARED;
233 status = smb2_lock(tree, &lck);
234 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
236 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
237 status = smb2_lock(tree, &lck);
238 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
240 lck.in.lock_count = 2;
242 lck.in.file.handle = h;
245 el[0].reserved = 0x00000000;
248 el[1].reserved = 0x00000000;
250 lck.in.lock_count = 2;
252 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
253 status = smb2_lock(tree, &lck);
254 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
256 lck.in.lock_count = 2;
259 status = smb2_lock(tree, &lck);
260 CHECK_STATUS(status, NT_STATUS_OK);
262 lck.in.lock_count = 2;
263 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
265 status = smb2_lock(tree, &lck);
266 CHECK_STATUS(status, NT_STATUS_OK);
268 lck.in.lock_count = 1;
269 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
270 status = smb2_lock(tree, &lck);
271 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
273 lck.in.lock_count = 1;
274 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
275 status = smb2_lock(tree, &lck);
276 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
278 lck.in.lock_count = 1;
279 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
280 status = smb2_lock(tree, &lck);
281 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
283 lck.in.lock_count = 1;
285 status = smb2_lock(tree, &lck);
286 CHECK_STATUS(status, NT_STATUS_OK);
288 status = smb2_lock(tree, &lck);
289 CHECK_STATUS(status, NT_STATUS_OK);
291 lck.in.lock_count = 2;
292 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
293 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
294 status = smb2_lock(tree, &lck);
295 CHECK_STATUS(status, NT_STATUS_OK);
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);
307 struct test_lock_read_write_state {
310 NTSTATUS write_h1_status;
311 NTSTATUS read_h1_status;
312 NTSTATUS write_h2_status;
313 NTSTATUS read_h2_status;
316 static bool test_lock_read_write(struct torture_context *torture,
317 struct smb2_tree *tree,
318 struct test_lock_read_write_state *s)
322 struct smb2_handle h1, h2;
324 struct smb2_lock lck;
325 struct smb2_create cr;
326 struct smb2_write wr;
328 struct smb2_lock_element el[1];
334 status = torture_smb2_testfile(tree, s->fname, &h1);
335 CHECK_STATUS(status, NT_STATUS_OK);
337 status = smb2_util_write(tree, h1, buf, 0, ARRAY_SIZE(buf));
338 CHECK_STATUS(status, NT_STATUS_OK);
340 lck.in.lock_count = 0x0001;
341 lck.in.reserved = 0x00000000;
342 lck.in.file.handle = h1;
344 el[0].length = ARRAY_SIZE(buf)/2;
345 el[0].reserved = 0x00000000;
346 el[0].flags = s->lock_flags;
347 status = smb2_lock(tree, &lck);
348 CHECK_STATUS(status, NT_STATUS_OK);
349 CHECK_VALUE(lck.out.reserved, 0);
351 lck.in.lock_count = 0x0001;
352 lck.in.reserved = 0x00000000;
353 lck.in.file.handle = h1;
354 el[0].offset = ARRAY_SIZE(buf)/2;
355 el[0].length = ARRAY_SIZE(buf)/2;
356 el[0].reserved = 0x00000000;
357 el[0].flags = s->lock_flags;
358 status = smb2_lock(tree, &lck);
359 CHECK_STATUS(status, NT_STATUS_OK);
360 CHECK_VALUE(lck.out.reserved, 0);
363 cr.in.oplock_level = 0;
364 cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
365 cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
366 cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
368 NTCREATEX_SHARE_ACCESS_DELETE|
369 NTCREATEX_SHARE_ACCESS_READ|
370 NTCREATEX_SHARE_ACCESS_WRITE;
371 cr.in.create_options = 0;
372 cr.in.fname = s->fname;
374 status = smb2_create(tree, tree, &cr);
375 CHECK_STATUS(status, NT_STATUS_OK);
377 h2 = cr.out.file.handle;
380 wr.in.file.handle = h1;
381 wr.in.offset = ARRAY_SIZE(buf)/2;
382 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
384 status = smb2_write(tree, &wr);
385 CHECK_STATUS(status, s->write_h1_status);
388 rd.in.file.handle = h1;
389 rd.in.offset = ARRAY_SIZE(buf)/2;
390 rd.in.length = ARRAY_SIZE(buf)/2;
392 status = smb2_read(tree, tree, &rd);
393 CHECK_STATUS(status, s->read_h1_status);
396 wr.in.file.handle = h2;
397 wr.in.offset = ARRAY_SIZE(buf)/2;
398 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
400 status = smb2_write(tree, &wr);
401 CHECK_STATUS(status, s->write_h2_status);
404 rd.in.file.handle = h2;
405 rd.in.offset = ARRAY_SIZE(buf)/2;
406 rd.in.length = ARRAY_SIZE(buf)/2;
408 status = smb2_read(tree, tree, &rd);
409 CHECK_STATUS(status, s->read_h2_status);
411 lck.in.lock_count = 0x0001;
412 lck.in.reserved = 0x00000000;
413 lck.in.file.handle = h1;
414 el[0].offset = ARRAY_SIZE(buf)/2;
415 el[0].length = ARRAY_SIZE(buf)/2;
416 el[0].reserved = 0x00000000;
417 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
418 status = smb2_lock(tree, &lck);
419 CHECK_STATUS(status, NT_STATUS_OK);
420 CHECK_VALUE(lck.out.reserved, 0);
423 wr.in.file.handle = h2;
424 wr.in.offset = ARRAY_SIZE(buf)/2;
425 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
427 status = smb2_write(tree, &wr);
428 CHECK_STATUS(status, NT_STATUS_OK);
431 rd.in.file.handle = h2;
432 rd.in.offset = ARRAY_SIZE(buf)/2;
433 rd.in.length = ARRAY_SIZE(buf)/2;
435 status = smb2_read(tree, tree, &rd);
436 CHECK_STATUS(status, NT_STATUS_OK);
442 static bool test_lock_rw_none(struct torture_context *torture, struct smb2_tree *tree)
444 struct test_lock_read_write_state s = {
445 .fname = "lock_rw_none.dat",
446 .lock_flags = SMB2_LOCK_FLAG_NONE,
447 .write_h1_status = NT_STATUS_FILE_LOCK_CONFLICT,
448 .read_h1_status = NT_STATUS_OK,
449 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
450 .read_h2_status = NT_STATUS_OK,
453 return test_lock_read_write(torture, tree, &s);
456 static bool test_lock_rw_shared(struct torture_context *torture, struct smb2_tree *tree)
458 struct test_lock_read_write_state s = {
459 .fname = "lock_rw_shared.dat",
460 .lock_flags = SMB2_LOCK_FLAG_SHARED,
461 .write_h1_status = NT_STATUS_FILE_LOCK_CONFLICT,
462 .read_h1_status = NT_STATUS_OK,
463 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
464 .read_h2_status = NT_STATUS_OK,
467 return test_lock_read_write(torture, tree, &s);
470 static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_tree *tree)
472 struct test_lock_read_write_state s = {
473 .fname = "lock_rw_exclusiv.dat",
474 .lock_flags = SMB2_LOCK_FLAG_EXCLUSIVE,
475 .write_h1_status = NT_STATUS_OK,
476 .read_h1_status = NT_STATUS_OK,
477 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
478 .read_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
481 return test_lock_read_write(torture, tree, &s);
485 static bool test_lock_auto_unlock(struct torture_context *torture, struct smb2_tree *tree)
489 struct smb2_handle h;
491 struct smb2_lock lck;
492 struct smb2_lock_element el[2];
496 status = torture_smb2_testfile(tree, "autounlock.txt", &h);
497 CHECK_STATUS(status, NT_STATUS_OK);
499 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
500 CHECK_STATUS(status, NT_STATUS_OK);
504 lck.in.lock_count = 0x0001;
505 lck.in.file.handle = h;
508 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
509 status = smb2_lock(tree, &lck);
510 CHECK_STATUS(status, NT_STATUS_OK);
512 status = smb2_lock(tree, &lck);
513 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
515 status = smb2_lock(tree, &lck);
516 if (torture_setting_bool(torture, "windows", false)) {
517 CHECK_STATUS(status, NT_STATUS_OK);
519 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
529 /* basic testing of SMB2 locking
531 struct torture_suite *torture_smb2_lock_init(void)
533 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "LOCK");
535 torture_suite_add_1smb2_test(suite, "VALID-REQUEST", test_valid_request);
536 torture_suite_add_1smb2_test(suite, "RW-NONE", test_lock_rw_none);
537 torture_suite_add_1smb2_test(suite, "RW-SHARED", test_lock_rw_shared);
538 torture_suite_add_1smb2_test(suite, "RW-EXCLUSIV", test_lock_rw_exclusiv);
539 torture_suite_add_1smb2_test(suite, "AUTO-UNLOCK", test_lock_auto_unlock);
541 suite->description = talloc_strdup(suite, "SMB2-LOCK tests");