Fix typo.
[ab/samba.git/.git] / source4 / torture / smb2 / lock.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    SMB2 lock test suite
5
6    Copyright (C) Stefan Metzmacher 2006
7    
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.
12    
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.
17    
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/>.
20 */
21
22 #include "includes.h"
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25
26 #include "torture/torture.h"
27 #include "torture/smb2/proto.h"
28
29 #include "librpc/gen_ndr/ndr_security.h"
30
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)); \
35                 ret = false; \
36                 goto done; \
37         }} while (0)
38
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); \
43                 ret = false; \
44                 goto done; \
45         }} while (0)
46
47 static bool test_valid_request(struct torture_context *torture, struct smb2_tree *tree)
48 {
49         bool ret = true;
50         NTSTATUS status;
51         struct smb2_handle h;
52         uint8_t buf[200];
53         struct smb2_lock lck;
54
55         ZERO_STRUCT(buf);
56
57         status = torture_smb2_testfile(tree, "lock1.txt", &h);
58         CHECK_STATUS(status, NT_STATUS_OK);
59
60         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
61         CHECK_STATUS(status, NT_STATUS_OK);
62
63         lck.in.unknown1         = 0x0000;
64         lck.in.unknown2         = 0x00000000;
65         lck.in.file.handle      = h;
66         lck.in.offset           = 0x0000000000000000;
67         lck.in.count            = 0x0000000000000000;
68         lck.in.unknown5         = 0x0000000000000000;
69         lck.in.flags            = 0x00000000;
70         status = smb2_lock(tree, &lck);
71         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
72
73         lck.in.unknown1         = 0x0001;
74         lck.in.unknown2         = 0x00000000;
75         lck.in.file.handle      = h;
76         lck.in.offset           = 0;
77         lck.in.count            = 0;
78         lck.in.unknown5         = 0x00000000;
79         lck.in.flags            = SMB2_LOCK_FLAG_NONE;
80         status = smb2_lock(tree, &lck);
81         CHECK_STATUS(status, NT_STATUS_OK);
82         CHECK_VALUE(lck.out.unknown1, 0);
83
84         lck.in.file.handle.data[0] +=1;
85         status = smb2_lock(tree, &lck);
86         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
87         lck.in.file.handle.data[0] -=1;
88
89         lck.in.unknown1         = 0x0001;
90         lck.in.unknown2         = 0xFFFFFFFF;
91         lck.in.file.handle      = h;
92         lck.in.offset           = UINT64_MAX;
93         lck.in.count            = UINT64_MAX;
94         lck.in.unknown5         = 0x00000000;
95         lck.in.flags            = SMB2_LOCK_FLAG_EXCLUSIV|SMB2_LOCK_FLAG_NO_PENDING;
96         status = smb2_lock(tree, &lck);
97         CHECK_STATUS(status, NT_STATUS_OK);
98         CHECK_VALUE(lck.out.unknown1, 0);
99
100         status = smb2_lock(tree, &lck);
101         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
102
103         status = smb2_lock(tree, &lck);
104         CHECK_STATUS(status, NT_STATUS_OK);
105         CHECK_VALUE(lck.out.unknown1, 0);
106
107         status = smb2_lock(tree, &lck);
108         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
109
110         status = smb2_lock(tree, &lck);
111         CHECK_STATUS(status, NT_STATUS_OK);
112         CHECK_VALUE(lck.out.unknown1, 0);
113
114         lck.in.unknown1         = 0x0001;
115         lck.in.unknown2         = 0x12345678;
116         lck.in.file.handle      = h;
117         lck.in.offset           = UINT32_MAX;
118         lck.in.count            = UINT32_MAX;
119         lck.in.unknown5         = 0x87654321;
120         lck.in.flags            = SMB2_LOCK_FLAG_EXCLUSIV|SMB2_LOCK_FLAG_NO_PENDING;
121         status = smb2_lock(tree, &lck);
122         CHECK_STATUS(status, NT_STATUS_OK);
123         CHECK_VALUE(lck.out.unknown1, 0);
124
125         status = smb2_lock(tree, &lck);
126         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
127
128         status = smb2_lock(tree, &lck);
129         CHECK_STATUS(status, NT_STATUS_OK);
130         CHECK_VALUE(lck.out.unknown1, 0);
131
132         status = smb2_lock(tree, &lck);
133         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
134
135         status = smb2_lock(tree, &lck);
136         CHECK_STATUS(status, NT_STATUS_OK);
137         CHECK_VALUE(lck.out.unknown1, 0);
138
139         lck.in.flags            = 0x00000000;
140         status = smb2_lock(tree, &lck);
141         CHECK_STATUS(status, NT_STATUS_OK);
142         CHECK_VALUE(lck.out.unknown1, 0);
143
144         status = smb2_lock(tree, &lck);
145         CHECK_STATUS(status, NT_STATUS_OK);
146         CHECK_VALUE(lck.out.unknown1, 0);
147
148         lck.in.flags            = 0x00000001;
149         status = smb2_lock(tree, &lck);
150         CHECK_STATUS(status, NT_STATUS_OK);
151         CHECK_VALUE(lck.out.unknown1, 0);
152
153         status = smb2_lock(tree, &lck);
154         CHECK_STATUS(status, NT_STATUS_OK);
155         CHECK_VALUE(lck.out.unknown1, 0);
156
157         lck.in.unknown1         = 0x0001;
158         lck.in.unknown2         = 0x87654321;
159         lck.in.file.handle      = h;
160         lck.in.offset           = 0x00000000FFFFFFFF;
161         lck.in.count            = 0x00000000FFFFFFFF;
162         lck.in.unknown5         = 0x12345678;
163         lck.in.flags            = SMB2_LOCK_FLAG_UNLOCK;
164         status = smb2_lock(tree, &lck);
165         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
166
167         lck.in.unknown1         = 0x0001;
168         lck.in.unknown2         = 0x12345678;
169         lck.in.file.handle      = h;
170         lck.in.offset           = 0x00000000FFFFFFFF;
171         lck.in.count            = 0x00000000FFFFFFFF;
172         lck.in.unknown5         = 0x00000000;
173         lck.in.flags            = SMB2_LOCK_FLAG_UNLOCK;
174         status = smb2_lock(tree, &lck);
175         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
176
177         status = smb2_lock(tree, &lck);
178         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
179         status = smb2_lock(tree, &lck);
180         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
181         status = smb2_lock(tree, &lck);
182         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
183
184 done:
185         return ret;
186 }
187
188 struct test_lock_read_write_state {
189         const char *fname;
190         uint32_t lock_flags;
191         NTSTATUS write_h1_status;
192         NTSTATUS read_h1_status;
193         NTSTATUS write_h2_status;
194         NTSTATUS read_h2_status;
195 };
196
197 static bool test_lock_read_write(struct torture_context *torture,
198                                  struct smb2_tree *tree,
199                                  struct test_lock_read_write_state *s)
200 {
201         bool ret = true;
202         NTSTATUS status;
203         struct smb2_handle h1, h2;
204         uint8_t buf[200];
205         struct smb2_lock lck;
206         struct smb2_create cr;
207         struct smb2_write wr;
208         struct smb2_read rd;
209
210         ZERO_STRUCT(buf);
211
212         status = torture_smb2_testfile(tree, s->fname, &h1);
213         CHECK_STATUS(status, NT_STATUS_OK);
214
215         status = smb2_util_write(tree, h1, buf, 0, ARRAY_SIZE(buf));
216         CHECK_STATUS(status, NT_STATUS_OK);
217
218         lck.in.unknown1         = 0x0001;
219         lck.in.unknown2         = 0x00000000;
220         lck.in.file.handle      = h1;
221         lck.in.offset           = 0;
222         lck.in.count            = ARRAY_SIZE(buf)/2;
223         lck.in.unknown5         = 0x00000000;
224         lck.in.flags            = s->lock_flags;
225         status = smb2_lock(tree, &lck);
226         CHECK_STATUS(status, NT_STATUS_OK);
227         CHECK_VALUE(lck.out.unknown1, 0);
228
229         lck.in.unknown1         = 0x0001;
230         lck.in.unknown2         = 0x00000000;
231         lck.in.file.handle      = h1;
232         lck.in.offset           = ARRAY_SIZE(buf)/2;
233         lck.in.count            = ARRAY_SIZE(buf)/2;
234         lck.in.unknown5         = 0x00000000;
235         lck.in.flags            = s->lock_flags;
236         status = smb2_lock(tree, &lck);
237         CHECK_STATUS(status, NT_STATUS_OK);
238         CHECK_VALUE(lck.out.unknown1, 0);
239
240         ZERO_STRUCT(cr);
241         cr.in.oplock_level = 0;
242         cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
243         cr.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
244         cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
245         cr.in.share_access = 
246                 NTCREATEX_SHARE_ACCESS_DELETE|
247                 NTCREATEX_SHARE_ACCESS_READ|
248                 NTCREATEX_SHARE_ACCESS_WRITE;
249         cr.in.create_options = 0;
250         cr.in.fname = s->fname;
251
252         status = smb2_create(tree, tree, &cr);
253         CHECK_STATUS(status, NT_STATUS_OK);
254
255         h2 = cr.out.file.handle;
256
257         ZERO_STRUCT(wr);
258         wr.in.file.handle = h1;
259         wr.in.offset      = ARRAY_SIZE(buf)/2;
260         wr.in.data        = data_blob_const(buf, ARRAY_SIZE(buf)/2);
261
262         status = smb2_write(tree, &wr);
263         CHECK_STATUS(status, s->write_h1_status);
264
265         ZERO_STRUCT(rd);
266         rd.in.file.handle = h1;
267         rd.in.offset      = ARRAY_SIZE(buf)/2;
268         rd.in.length      = ARRAY_SIZE(buf)/2;
269
270         status = smb2_read(tree, tree, &rd);
271         CHECK_STATUS(status, s->read_h1_status);
272
273         ZERO_STRUCT(wr);
274         wr.in.file.handle = h2;
275         wr.in.offset      = ARRAY_SIZE(buf)/2;
276         wr.in.data        = data_blob_const(buf, ARRAY_SIZE(buf)/2);
277
278         status = smb2_write(tree, &wr);
279         CHECK_STATUS(status, s->write_h2_status);
280
281         ZERO_STRUCT(rd);
282         rd.in.file.handle = h2;
283         rd.in.offset      = ARRAY_SIZE(buf)/2;
284         rd.in.length      = ARRAY_SIZE(buf)/2;
285
286         status = smb2_read(tree, tree, &rd);
287         CHECK_STATUS(status, s->read_h2_status);
288
289         lck.in.unknown1         = 0x0001;
290         lck.in.unknown2         = 0x00000000;
291         lck.in.file.handle      = h1;
292         lck.in.offset           = ARRAY_SIZE(buf)/2;
293         lck.in.count            = ARRAY_SIZE(buf)/2;
294         lck.in.unknown5         = 0x00000000;
295         lck.in.flags            = SMB2_LOCK_FLAG_UNLOCK;
296         status = smb2_lock(tree, &lck);
297         CHECK_STATUS(status, NT_STATUS_OK);
298         CHECK_VALUE(lck.out.unknown1, 0);
299
300         ZERO_STRUCT(wr);
301         wr.in.file.handle = h2;
302         wr.in.offset      = ARRAY_SIZE(buf)/2;
303         wr.in.data        = data_blob_const(buf, ARRAY_SIZE(buf)/2);
304
305         status = smb2_write(tree, &wr);
306         CHECK_STATUS(status, NT_STATUS_OK);
307
308         ZERO_STRUCT(rd);
309         rd.in.file.handle = h2;
310         rd.in.offset      = ARRAY_SIZE(buf)/2;
311         rd.in.length      = ARRAY_SIZE(buf)/2;
312
313         status = smb2_read(tree, tree, &rd);
314         CHECK_STATUS(status, NT_STATUS_OK);
315
316 done:
317         return ret;
318 }
319
320 static bool test_lock_rw_none(struct torture_context *torture, struct smb2_tree *tree)
321 {
322         struct test_lock_read_write_state s = {
323                 .fname                  = "lock_rw_none.dat",
324                 .lock_flags             = SMB2_LOCK_FLAG_NONE,
325                 .write_h1_status        = NT_STATUS_FILE_LOCK_CONFLICT,
326                 .read_h1_status         = NT_STATUS_OK,
327                 .write_h2_status        = NT_STATUS_FILE_LOCK_CONFLICT,
328                 .read_h2_status         = NT_STATUS_OK,
329         };
330
331         return test_lock_read_write(torture, tree, &s);
332 }
333
334 static bool test_lock_rw_shared(struct torture_context *torture, struct smb2_tree *tree)
335 {
336         struct test_lock_read_write_state s = {
337                 .fname                  = "lock_rw_shared.dat",
338                 .lock_flags             = SMB2_LOCK_FLAG_SHARED,
339                 .write_h1_status        = NT_STATUS_FILE_LOCK_CONFLICT,
340                 .read_h1_status         = NT_STATUS_OK,
341                 .write_h2_status        = NT_STATUS_FILE_LOCK_CONFLICT,
342                 .read_h2_status         = NT_STATUS_OK,
343         };
344
345         return test_lock_read_write(torture, tree, &s);
346 }
347
348 static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_tree *tree)
349 {
350         struct test_lock_read_write_state s = {
351                 .fname                  = "lock_rw_exclusiv.dat",
352                 .lock_flags             = SMB2_LOCK_FLAG_EXCLUSIV,
353                 .write_h1_status        = NT_STATUS_OK,
354                 .read_h1_status         = NT_STATUS_OK,
355                 .write_h2_status        = NT_STATUS_FILE_LOCK_CONFLICT,
356                 .read_h2_status         = NT_STATUS_FILE_LOCK_CONFLICT,
357         };
358
359         return test_lock_read_write(torture, tree, &s);
360 }
361
362 /* basic testing of SMB2 locking
363 */
364 struct torture_suite *torture_smb2_lock_init(void)
365 {
366         struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "LOCK");
367
368         torture_suite_add_1smb2_test(suite, "VALID-REQUEST", test_valid_request);
369         torture_suite_add_1smb2_test(suite, "RW-NONE", test_lock_rw_none);
370         torture_suite_add_1smb2_test(suite, "RW-SHARED", test_lock_rw_shared);
371         torture_suite_add_1smb2_test(suite, "RW-EXCLUSIV", test_lock_rw_exclusiv);
372
373         suite->description = talloc_strdup(suite, "SMB2-LOCK tests");
374
375         return suite;
376 }
377