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 = 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);
195 struct test_lock_read_write_state {
198 NTSTATUS write_h1_status;
199 NTSTATUS read_h1_status;
200 NTSTATUS write_h2_status;
201 NTSTATUS read_h2_status;
204 static bool test_lock_read_write(struct torture_context *torture,
205 struct smb2_tree *tree,
206 struct test_lock_read_write_state *s)
210 struct smb2_handle h1, h2;
212 struct smb2_lock lck;
213 struct smb2_create cr;
214 struct smb2_write wr;
216 struct smb2_lock_element el[1];
222 status = torture_smb2_testfile(tree, s->fname, &h1);
223 CHECK_STATUS(status, NT_STATUS_OK);
225 status = smb2_util_write(tree, h1, buf, 0, ARRAY_SIZE(buf));
226 CHECK_STATUS(status, NT_STATUS_OK);
228 lck.in.lock_count = 0x0001;
229 lck.in.reserved = 0x00000000;
230 lck.in.file.handle = h1;
232 el[0].length = ARRAY_SIZE(buf)/2;
233 el[0].reserved = 0x00000000;
234 el[0].flags = s->lock_flags;
235 status = smb2_lock(tree, &lck);
236 CHECK_STATUS(status, NT_STATUS_OK);
237 CHECK_VALUE(lck.out.reserved, 0);
239 lck.in.lock_count = 0x0001;
240 lck.in.reserved = 0x00000000;
241 lck.in.file.handle = h1;
242 el[0].offset = ARRAY_SIZE(buf)/2;
243 el[0].length = ARRAY_SIZE(buf)/2;
244 el[0].reserved = 0x00000000;
245 el[0].flags = s->lock_flags;
246 status = smb2_lock(tree, &lck);
247 CHECK_STATUS(status, NT_STATUS_OK);
248 CHECK_VALUE(lck.out.reserved, 0);
251 cr.in.oplock_level = 0;
252 cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
253 cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
254 cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
256 NTCREATEX_SHARE_ACCESS_DELETE|
257 NTCREATEX_SHARE_ACCESS_READ|
258 NTCREATEX_SHARE_ACCESS_WRITE;
259 cr.in.create_options = 0;
260 cr.in.fname = s->fname;
262 status = smb2_create(tree, tree, &cr);
263 CHECK_STATUS(status, NT_STATUS_OK);
265 h2 = cr.out.file.handle;
268 wr.in.file.handle = h1;
269 wr.in.offset = ARRAY_SIZE(buf)/2;
270 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
272 status = smb2_write(tree, &wr);
273 CHECK_STATUS(status, s->write_h1_status);
276 rd.in.file.handle = h1;
277 rd.in.offset = ARRAY_SIZE(buf)/2;
278 rd.in.length = ARRAY_SIZE(buf)/2;
280 status = smb2_read(tree, tree, &rd);
281 CHECK_STATUS(status, s->read_h1_status);
284 wr.in.file.handle = h2;
285 wr.in.offset = ARRAY_SIZE(buf)/2;
286 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
288 status = smb2_write(tree, &wr);
289 CHECK_STATUS(status, s->write_h2_status);
292 rd.in.file.handle = h2;
293 rd.in.offset = ARRAY_SIZE(buf)/2;
294 rd.in.length = ARRAY_SIZE(buf)/2;
296 status = smb2_read(tree, tree, &rd);
297 CHECK_STATUS(status, s->read_h2_status);
299 lck.in.lock_count = 0x0001;
300 lck.in.reserved = 0x00000000;
301 lck.in.file.handle = h1;
302 el[0].offset = ARRAY_SIZE(buf)/2;
303 el[0].length = ARRAY_SIZE(buf)/2;
304 el[0].reserved = 0x00000000;
305 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
306 status = smb2_lock(tree, &lck);
307 CHECK_STATUS(status, NT_STATUS_OK);
308 CHECK_VALUE(lck.out.reserved, 0);
311 wr.in.file.handle = h2;
312 wr.in.offset = ARRAY_SIZE(buf)/2;
313 wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
315 status = smb2_write(tree, &wr);
316 CHECK_STATUS(status, NT_STATUS_OK);
319 rd.in.file.handle = h2;
320 rd.in.offset = ARRAY_SIZE(buf)/2;
321 rd.in.length = ARRAY_SIZE(buf)/2;
323 status = smb2_read(tree, tree, &rd);
324 CHECK_STATUS(status, NT_STATUS_OK);
330 static bool test_lock_rw_none(struct torture_context *torture, struct smb2_tree *tree)
332 struct test_lock_read_write_state s = {
333 .fname = "lock_rw_none.dat",
334 .lock_flags = SMB2_LOCK_FLAG_NONE,
335 .write_h1_status = NT_STATUS_FILE_LOCK_CONFLICT,
336 .read_h1_status = NT_STATUS_OK,
337 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
338 .read_h2_status = NT_STATUS_OK,
341 return test_lock_read_write(torture, tree, &s);
344 static bool test_lock_rw_shared(struct torture_context *torture, struct smb2_tree *tree)
346 struct test_lock_read_write_state s = {
347 .fname = "lock_rw_shared.dat",
348 .lock_flags = SMB2_LOCK_FLAG_SHARED,
349 .write_h1_status = NT_STATUS_FILE_LOCK_CONFLICT,
350 .read_h1_status = NT_STATUS_OK,
351 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
352 .read_h2_status = NT_STATUS_OK,
355 return test_lock_read_write(torture, tree, &s);
358 static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_tree *tree)
360 struct test_lock_read_write_state s = {
361 .fname = "lock_rw_exclusiv.dat",
362 .lock_flags = SMB2_LOCK_FLAG_EXCLUSIVE,
363 .write_h1_status = NT_STATUS_OK,
364 .read_h1_status = NT_STATUS_OK,
365 .write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
366 .read_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
369 return test_lock_read_write(torture, tree, &s);
372 /* basic testing of SMB2 locking
374 struct torture_suite *torture_smb2_lock_init(void)
376 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "LOCK");
378 torture_suite_add_1smb2_test(suite, "VALID-REQUEST", test_valid_request);
379 torture_suite_add_1smb2_test(suite, "RW-NONE", test_lock_rw_none);
380 torture_suite_add_1smb2_test(suite, "RW-SHARED", test_lock_rw_shared);
381 torture_suite_add_1smb2_test(suite, "RW-EXCLUSIV", test_lock_rw_exclusiv);
383 suite->description = talloc_strdup(suite, "SMB2-LOCK tests");