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[1];
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 = 0xFFFFFFFF;
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 status = smb2_lock(tree, &lck);
104 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
106 status = smb2_lock(tree, &lck);
107 CHECK_STATUS(status, NT_STATUS_OK);
108 CHECK_VALUE(lck.out.reserved, 0);
110 status = smb2_lock(tree, &lck);
111 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
113 status = smb2_lock(tree, &lck);
114 CHECK_STATUS(status, NT_STATUS_OK);
115 CHECK_VALUE(lck.out.reserved, 0);
117 lck.in.lock_count = 0x0001;
118 lck.in.reserved = 0x12345678;
119 lck.in.file.handle = h;
120 el[0].offset = UINT32_MAX;
121 el[0].length = UINT32_MAX;
122 el[0].reserved = 0x87654321;
123 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
124 status = smb2_lock(tree, &lck);
125 CHECK_STATUS(status, NT_STATUS_OK);
126 CHECK_VALUE(lck.out.reserved, 0);
128 status = smb2_lock(tree, &lck);
129 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
131 status = smb2_lock(tree, &lck);
132 CHECK_STATUS(status, NT_STATUS_OK);
133 CHECK_VALUE(lck.out.reserved, 0);
135 status = smb2_lock(tree, &lck);
136 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
138 status = smb2_lock(tree, &lck);
139 CHECK_STATUS(status, NT_STATUS_OK);
140 CHECK_VALUE(lck.out.reserved, 0);
142 el[0].flags = 0x00000000;
143 status = smb2_lock(tree, &lck);
144 CHECK_STATUS(status, NT_STATUS_OK);
145 CHECK_VALUE(lck.out.reserved, 0);
147 status = smb2_lock(tree, &lck);
148 CHECK_STATUS(status, NT_STATUS_OK);
149 CHECK_VALUE(lck.out.reserved, 0);
151 el[0].flags = 0x00000001;
152 status = smb2_lock(tree, &lck);
153 CHECK_STATUS(status, NT_STATUS_OK);
154 CHECK_VALUE(lck.out.reserved, 0);
156 status = smb2_lock(tree, &lck);
157 CHECK_STATUS(status, NT_STATUS_OK);
158 CHECK_VALUE(lck.out.reserved, 0);
160 lck.in.lock_count = 0x0001;
161 lck.in.reserved = 0x87654321;
162 lck.in.file.handle = h;
163 el[0].offset = 0x00000000FFFFFFFF;
164 el[0].length = 0x00000000FFFFFFFF;
165 el[0].reserved = 0x12345678;
166 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
167 status = smb2_lock(tree, &lck);
168 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
170 lck.in.lock_count = 0x0001;
171 lck.in.reserved = 0x12345678;
172 lck.in.file.handle = h;
173 el[0].offset = 0x00000000FFFFFFFF;
174 el[0].length = 0x00000000FFFFFFFF;
175 el[0].reserved = 0x00000000;
176 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
177 status = smb2_lock(tree, &lck);
178 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
180 status = smb2_lock(tree, &lck);
181 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
182 status = smb2_lock(tree, &lck);
183 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
184 status = smb2_lock(tree, &lck);
185 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
191 struct test_lock_read_write_state {
194 NTSTATUS write_h1_status;
195 NTSTATUS read_h1_status;
196 NTSTATUS write_h2_status;
197 NTSTATUS read_h2_status;
200 static bool test_lock_read_write(struct torture_context *torture,
201 struct smb2_tree *tree,
202 struct test_lock_read_write_state *s)
206 struct smb2_handle h1, h2;
208 struct smb2_lock lck;
209 struct smb2_create cr;
210 struct smb2_write wr;
212 struct smb2_lock_element el[1];
218 status = torture_smb2_testfile(tree, s->fname, &h1);
219 CHECK_STATUS(status, NT_STATUS_OK);
221 status = smb2_util_write(tree, h1, buf, 0, ARRAY_SIZE(buf));
222 CHECK_STATUS(status, NT_STATUS_OK);
224 lck.in.lock_count = 0x0001;
225 lck.in.reserved = 0x00000000;
226 lck.in.file.handle = h1;
228 el[0].length = ARRAY_SIZE(buf)/2;
229 el[0].reserved = 0x00000000;
230 el[0].flags = s->lock_flags;
231 status = smb2_lock(tree, &lck);
232 CHECK_STATUS(status, NT_STATUS_OK);
233 CHECK_VALUE(lck.out.reserved, 0);
235 lck.in.lock_count = 0x0001;
236 lck.in.reserved = 0x00000000;
237 lck.in.file.handle = h1;
238 el[0].offset = ARRAY_SIZE(buf)/2;
239 el[0].length = ARRAY_SIZE(buf)/2;
240 el[0].reserved = 0x00000000;
241 el[0].flags = s->lock_flags;
242 status = smb2_lock(tree, &lck);
243 CHECK_STATUS(status, NT_STATUS_OK);
244 CHECK_VALUE(lck.out.reserved, 0);
247 cr.in.oplock_level = 0;
248 cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
249 cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
250 cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
252 NTCREATEX_SHARE_ACCESS_DELETE|
253 NTCREATEX_SHARE_ACCESS_READ|
254 NTCREATEX_SHARE_ACCESS_WRITE;
255 cr.in.create_options = 0;
256 cr.in.fname = s->fname;
258 status = smb2_create(tree, tree, &cr);
259 CHECK_STATUS(status, NT_STATUS_OK);
261 h2 = cr.out.file.handle;
264 wr.in.file.handle = h1;
265 wr.in.offset = ARRAY_SIZE(buf)/2;
266 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
268 status = smb2_write(tree, &wr);
269 CHECK_STATUS(status, s->write_h1_status);
272 rd.in.file.handle = h1;
273 rd.in.offset = ARRAY_SIZE(buf)/2;
274 rd.in.length = ARRAY_SIZE(buf)/2;
276 status = smb2_read(tree, tree, &rd);
277 CHECK_STATUS(status, s->read_h1_status);
280 wr.in.file.handle = h2;
281 wr.in.offset = ARRAY_SIZE(buf)/2;
282 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
284 status = smb2_write(tree, &wr);
285 CHECK_STATUS(status, s->write_h2_status);
288 rd.in.file.handle = h2;
289 rd.in.offset = ARRAY_SIZE(buf)/2;
290 rd.in.length = ARRAY_SIZE(buf)/2;
292 status = smb2_read(tree, tree, &rd);
293 CHECK_STATUS(status, s->read_h2_status);
295 lck.in.lock_count = 0x0001;
296 lck.in.reserved = 0x00000000;
297 lck.in.file.handle = h1;
298 el[0].offset = ARRAY_SIZE(buf)/2;
299 el[0].length = ARRAY_SIZE(buf)/2;
300 el[0].reserved = 0x00000000;
301 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
302 status = smb2_lock(tree, &lck);
303 CHECK_STATUS(status, NT_STATUS_OK);
304 CHECK_VALUE(lck.out.reserved, 0);
307 wr.in.file.handle = h2;
308 wr.in.offset = ARRAY_SIZE(buf)/2;
309 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
311 status = smb2_write(tree, &wr);
312 CHECK_STATUS(status, NT_STATUS_OK);
315 rd.in.file.handle = h2;
316 rd.in.offset = ARRAY_SIZE(buf)/2;
317 rd.in.length = ARRAY_SIZE(buf)/2;
319 status = smb2_read(tree, tree, &rd);
320 CHECK_STATUS(status, NT_STATUS_OK);
326 static bool test_lock_rw_none(struct torture_context *torture, struct smb2_tree *tree)
328 struct test_lock_read_write_state s = {
329 .fname = "lock_rw_none.dat",
330 .lock_flags = SMB2_LOCK_FLAG_NONE,
331 .write_h1_status = NT_STATUS_FILE_LOCK_CONFLICT,
332 .read_h1_status = NT_STATUS_OK,
333 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
334 .read_h2_status = NT_STATUS_OK,
337 return test_lock_read_write(torture, tree, &s);
340 static bool test_lock_rw_shared(struct torture_context *torture, struct smb2_tree *tree)
342 struct test_lock_read_write_state s = {
343 .fname = "lock_rw_shared.dat",
344 .lock_flags = SMB2_LOCK_FLAG_SHARED,
345 .write_h1_status = NT_STATUS_FILE_LOCK_CONFLICT,
346 .read_h1_status = NT_STATUS_OK,
347 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
348 .read_h2_status = NT_STATUS_OK,
351 return test_lock_read_write(torture, tree, &s);
354 static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_tree *tree)
356 struct test_lock_read_write_state s = {
357 .fname = "lock_rw_exclusiv.dat",
358 .lock_flags = SMB2_LOCK_FLAG_EXCLUSIVE,
359 .write_h1_status = NT_STATUS_OK,
360 .read_h1_status = NT_STATUS_OK,
361 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
362 .read_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
365 return test_lock_read_write(torture, tree, &s);
368 /* basic testing of SMB2 locking
370 struct torture_suite *torture_smb2_lock_init(void)
372 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "LOCK");
374 torture_suite_add_1smb2_test(suite, "VALID-REQUEST", test_valid_request);
375 torture_suite_add_1smb2_test(suite, "RW-NONE", test_lock_rw_none);
376 torture_suite_add_1smb2_test(suite, "RW-SHARED", test_lock_rw_shared);
377 torture_suite_add_1smb2_test(suite, "RW-EXCLUSIV", test_lock_rw_exclusiv);
379 suite->description = talloc_strdup(suite, "SMB2-LOCK tests");