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 CHECK_STATUS(status, NT_STATUS_OK);
110 CHECK_VALUE(lck.out.reserved, 0);
112 lck.in.reserved = 0x123ab4;
113 status = smb2_lock(tree, &lck);
114 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
116 lck.in.reserved = 0x123ab5;
117 status = smb2_lock(tree, &lck);
118 CHECK_STATUS(status, NT_STATUS_OK);
119 CHECK_VALUE(lck.out.reserved, 0);
121 lck.in.lock_count = 0x0001;
122 lck.in.reserved = 0x12345678;
123 lck.in.file.handle = h;
124 el[0].offset = UINT32_MAX;
125 el[0].length = UINT32_MAX;
126 el[0].reserved = 0x87654321;
127 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
128 status = smb2_lock(tree, &lck);
129 CHECK_STATUS(status, NT_STATUS_OK);
130 CHECK_VALUE(lck.out.reserved, 0);
132 status = smb2_lock(tree, &lck);
133 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
135 status = smb2_lock(tree, &lck);
136 CHECK_STATUS(status, NT_STATUS_OK);
137 CHECK_VALUE(lck.out.reserved, 0);
139 status = smb2_lock(tree, &lck);
140 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
142 status = smb2_lock(tree, &lck);
143 CHECK_STATUS(status, NT_STATUS_OK);
144 CHECK_VALUE(lck.out.reserved, 0);
146 el[0].flags = 0x00000000;
147 status = smb2_lock(tree, &lck);
148 CHECK_STATUS(status, NT_STATUS_OK);
149 CHECK_VALUE(lck.out.reserved, 0);
151 status = smb2_lock(tree, &lck);
152 CHECK_STATUS(status, NT_STATUS_OK);
153 CHECK_VALUE(lck.out.reserved, 0);
155 el[0].flags = 0x00000001;
156 status = smb2_lock(tree, &lck);
157 CHECK_STATUS(status, NT_STATUS_OK);
158 CHECK_VALUE(lck.out.reserved, 0);
160 status = smb2_lock(tree, &lck);
161 CHECK_STATUS(status, NT_STATUS_OK);
162 CHECK_VALUE(lck.out.reserved, 0);
164 lck.in.lock_count = 0x0001;
165 lck.in.reserved = 0x87654321;
166 lck.in.file.handle = h;
167 el[0].offset = 0x00000000FFFFFFFF;
168 el[0].length = 0x00000000FFFFFFFF;
169 el[0].reserved = 0x1234567;
170 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
171 status = smb2_lock(tree, &lck);
172 CHECK_STATUS(status, NT_STATUS_OK);
174 lck.in.lock_count = 0x0001;
175 lck.in.reserved = 0x1234567;
176 lck.in.file.handle = h;
177 el[0].offset = 0x00000000FFFFFFFF;
178 el[0].length = 0x00000000FFFFFFFF;
179 el[0].reserved = 0x00000000;
180 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
181 status = smb2_lock(tree, &lck);
182 CHECK_STATUS(status, NT_STATUS_OK);
184 status = smb2_lock(tree, &lck);
185 CHECK_STATUS(status, NT_STATUS_OK);
186 status = smb2_lock(tree, &lck);
187 CHECK_STATUS(status, NT_STATUS_OK);
188 status = smb2_lock(tree, &lck);
189 CHECK_STATUS(status, NT_STATUS_OK);
190 status = smb2_lock(tree, &lck);
191 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
193 lck.in.lock_count = 0x0001;
195 lck.in.file.handle = h;
198 el[0].reserved = 0x00000000;
199 el[0].flags = ~SMB2_LOCK_FLAG_ALL_MASK;
201 status = smb2_lock(tree, &lck);
202 CHECK_STATUS(status, NT_STATUS_OK);
204 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
205 status = smb2_lock(tree, &lck);
206 CHECK_STATUS(status, NT_STATUS_OK);
208 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
209 status = smb2_lock(tree, &lck);
210 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
212 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_EXCLUSIVE;
213 status = smb2_lock(tree, &lck);
214 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
216 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_SHARED;
217 status = smb2_lock(tree, &lck);
218 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
220 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
221 status = smb2_lock(tree, &lck);
222 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
224 lck.in.lock_count = 2;
226 lck.in.file.handle = h;
229 el[0].reserved = 0x00000000;
232 el[1].reserved = 0x00000000;
234 lck.in.lock_count = 2;
236 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
237 status = smb2_lock(tree, &lck);
238 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
240 lck.in.lock_count = 2;
243 status = smb2_lock(tree, &lck);
244 CHECK_STATUS(status, NT_STATUS_OK);
246 lck.in.lock_count = 2;
247 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
249 status = smb2_lock(tree, &lck);
250 CHECK_STATUS(status, NT_STATUS_OK);
252 lck.in.lock_count = 1;
253 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
254 status = smb2_lock(tree, &lck);
255 CHECK_STATUS(status, NT_STATUS_OK);
257 lck.in.lock_count = 1;
258 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
259 status = smb2_lock(tree, &lck);
260 CHECK_STATUS(status, NT_STATUS_OK);
262 lck.in.lock_count = 1;
263 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
264 status = smb2_lock(tree, &lck);
265 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
267 lck.in.lock_count = 1;
269 status = smb2_lock(tree, &lck);
270 CHECK_STATUS(status, NT_STATUS_OK);
272 status = smb2_lock(tree, &lck);
273 CHECK_STATUS(status, NT_STATUS_OK);
275 lck.in.lock_count = 2;
276 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
277 el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
278 status = smb2_lock(tree, &lck);
279 CHECK_STATUS(status, NT_STATUS_OK);
281 lck.in.lock_count = 1;
282 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
283 status = smb2_lock(tree, &lck);
284 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
291 struct test_lock_read_write_state {
294 NTSTATUS write_h1_status;
295 NTSTATUS read_h1_status;
296 NTSTATUS write_h2_status;
297 NTSTATUS read_h2_status;
300 static bool test_lock_read_write(struct torture_context *torture,
301 struct smb2_tree *tree,
302 struct test_lock_read_write_state *s)
306 struct smb2_handle h1, h2;
308 struct smb2_lock lck;
309 struct smb2_create cr;
310 struct smb2_write wr;
312 struct smb2_lock_element el[1];
318 status = torture_smb2_testfile(tree, s->fname, &h1);
319 CHECK_STATUS(status, NT_STATUS_OK);
321 status = smb2_util_write(tree, h1, buf, 0, ARRAY_SIZE(buf));
322 CHECK_STATUS(status, NT_STATUS_OK);
324 lck.in.lock_count = 0x0001;
325 lck.in.reserved = 0x00000000;
326 lck.in.file.handle = h1;
328 el[0].length = ARRAY_SIZE(buf)/2;
329 el[0].reserved = 0x00000000;
330 el[0].flags = s->lock_flags;
331 status = smb2_lock(tree, &lck);
332 CHECK_STATUS(status, NT_STATUS_OK);
333 CHECK_VALUE(lck.out.reserved, 0);
335 lck.in.lock_count = 0x0001;
336 lck.in.reserved = 0x00000000;
337 lck.in.file.handle = h1;
338 el[0].offset = ARRAY_SIZE(buf)/2;
339 el[0].length = ARRAY_SIZE(buf)/2;
340 el[0].reserved = 0x00000000;
341 el[0].flags = s->lock_flags;
342 status = smb2_lock(tree, &lck);
343 CHECK_STATUS(status, NT_STATUS_OK);
344 CHECK_VALUE(lck.out.reserved, 0);
347 cr.in.oplock_level = 0;
348 cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
349 cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
350 cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
352 NTCREATEX_SHARE_ACCESS_DELETE|
353 NTCREATEX_SHARE_ACCESS_READ|
354 NTCREATEX_SHARE_ACCESS_WRITE;
355 cr.in.create_options = 0;
356 cr.in.fname = s->fname;
358 status = smb2_create(tree, tree, &cr);
359 CHECK_STATUS(status, NT_STATUS_OK);
361 h2 = cr.out.file.handle;
364 wr.in.file.handle = h1;
365 wr.in.offset = ARRAY_SIZE(buf)/2;
366 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
368 status = smb2_write(tree, &wr);
369 CHECK_STATUS(status, s->write_h1_status);
372 rd.in.file.handle = h1;
373 rd.in.offset = ARRAY_SIZE(buf)/2;
374 rd.in.length = ARRAY_SIZE(buf)/2;
376 status = smb2_read(tree, tree, &rd);
377 CHECK_STATUS(status, s->read_h1_status);
380 wr.in.file.handle = h2;
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_h2_status);
388 rd.in.file.handle = h2;
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_h2_status);
395 lck.in.lock_count = 0x0001;
396 lck.in.reserved = 0x00000000;
397 lck.in.file.handle = h1;
398 el[0].offset = ARRAY_SIZE(buf)/2;
399 el[0].length = ARRAY_SIZE(buf)/2;
400 el[0].reserved = 0x00000000;
401 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
402 status = smb2_lock(tree, &lck);
403 CHECK_STATUS(status, NT_STATUS_OK);
404 CHECK_VALUE(lck.out.reserved, 0);
407 wr.in.file.handle = h2;
408 wr.in.offset = ARRAY_SIZE(buf)/2;
409 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
411 status = smb2_write(tree, &wr);
412 CHECK_STATUS(status, NT_STATUS_OK);
415 rd.in.file.handle = h2;
416 rd.in.offset = ARRAY_SIZE(buf)/2;
417 rd.in.length = ARRAY_SIZE(buf)/2;
419 status = smb2_read(tree, tree, &rd);
420 CHECK_STATUS(status, NT_STATUS_OK);
426 static bool test_lock_rw_none(struct torture_context *torture, struct smb2_tree *tree)
428 struct test_lock_read_write_state s = {
429 .fname = "lock_rw_none.dat",
430 .lock_flags = SMB2_LOCK_FLAG_NONE,
431 .write_h1_status = NT_STATUS_FILE_LOCK_CONFLICT,
432 .read_h1_status = NT_STATUS_OK,
433 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
434 .read_h2_status = NT_STATUS_OK,
437 return test_lock_read_write(torture, tree, &s);
440 static bool test_lock_rw_shared(struct torture_context *torture, struct smb2_tree *tree)
442 struct test_lock_read_write_state s = {
443 .fname = "lock_rw_shared.dat",
444 .lock_flags = SMB2_LOCK_FLAG_SHARED,
445 .write_h1_status = NT_STATUS_FILE_LOCK_CONFLICT,
446 .read_h1_status = NT_STATUS_OK,
447 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
448 .read_h2_status = NT_STATUS_OK,
451 return test_lock_read_write(torture, tree, &s);
454 static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_tree *tree)
456 struct test_lock_read_write_state s = {
457 .fname = "lock_rw_exclusiv.dat",
458 .lock_flags = SMB2_LOCK_FLAG_EXCLUSIVE,
459 .write_h1_status = NT_STATUS_OK,
460 .read_h1_status = NT_STATUS_OK,
461 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
462 .read_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
465 return test_lock_read_write(torture, tree, &s);
468 /* basic testing of SMB2 locking
470 struct torture_suite *torture_smb2_lock_init(void)
472 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "LOCK");
474 torture_suite_add_1smb2_test(suite, "VALID-REQUEST", test_valid_request);
475 torture_suite_add_1smb2_test(suite, "RW-NONE", test_lock_rw_none);
476 torture_suite_add_1smb2_test(suite, "RW-SHARED", test_lock_rw_shared);
477 torture_suite_add_1smb2_test(suite, "RW-EXCLUSIV", test_lock_rw_exclusiv);
479 suite->description = talloc_strdup(suite, "SMB2-LOCK tests");