Merge commit 'origin/v4-0-test' into v4-0-test
[ira/wip.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         struct smb2_lock_element el[1];
55
56         ZERO_STRUCT(buf);
57
58         status = torture_smb2_testfile(tree, "lock1.txt", &h);
59         CHECK_STATUS(status, NT_STATUS_OK);
60
61         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
62         CHECK_STATUS(status, NT_STATUS_OK);
63
64         lck.in.locks            = el;
65
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);
75
76         lck.in.lock_count       = 0x0001;
77         lck.in.reserved         = 0x00000000;
78         lck.in.file.handle      = h;
79         el[0].offset            = 0;
80         el[0].length            = 0;
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);
86
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;
91
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);
102
103         lck.in.reserved         = 0x123ab2;
104         status = smb2_lock(tree, &lck);
105         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
106
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);
111
112         lck.in.reserved         = 0x123ab4;
113         status = smb2_lock(tree, &lck);
114         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
115
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);
120
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);
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.reserved, 0);
138
139         status = smb2_lock(tree, &lck);
140         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
141
142         status = smb2_lock(tree, &lck);
143         CHECK_STATUS(status, NT_STATUS_OK);
144         CHECK_VALUE(lck.out.reserved, 0);
145
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);
150
151         status = smb2_lock(tree, &lck);
152         CHECK_STATUS(status, NT_STATUS_OK);
153         CHECK_VALUE(lck.out.reserved, 0);
154
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);
159
160         status = smb2_lock(tree, &lck);
161         CHECK_STATUS(status, NT_STATUS_OK);
162         CHECK_VALUE(lck.out.reserved, 0);
163
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);
173
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);
183
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
191 done:
192         return ret;
193 }
194
195 struct test_lock_read_write_state {
196         const char *fname;
197         uint32_t lock_flags;
198         NTSTATUS write_h1_status;
199         NTSTATUS read_h1_status;
200         NTSTATUS write_h2_status;
201         NTSTATUS read_h2_status;
202 };
203
204 static bool test_lock_read_write(struct torture_context *torture,
205                                  struct smb2_tree *tree,
206                                  struct test_lock_read_write_state *s)
207 {
208         bool ret = true;
209         NTSTATUS status;
210         struct smb2_handle h1, h2;
211         uint8_t buf[200];
212         struct smb2_lock lck;
213         struct smb2_create cr;
214         struct smb2_write wr;
215         struct smb2_read rd;
216         struct smb2_lock_element el[1];
217
218         lck.in.locks            = el;
219
220         ZERO_STRUCT(buf);
221
222         status = torture_smb2_testfile(tree, s->fname, &h1);
223         CHECK_STATUS(status, NT_STATUS_OK);
224
225         status = smb2_util_write(tree, h1, buf, 0, ARRAY_SIZE(buf));
226         CHECK_STATUS(status, NT_STATUS_OK);
227
228         lck.in.lock_count       = 0x0001;
229         lck.in.reserved         = 0x00000000;
230         lck.in.file.handle      = h1;
231         el[0].offset            = 0;
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);
238
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);
249
250         ZERO_STRUCT(cr);
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;
255         cr.in.share_access = 
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;
261
262         status = smb2_create(tree, tree, &cr);
263         CHECK_STATUS(status, NT_STATUS_OK);
264
265         h2 = cr.out.file.handle;
266
267         ZERO_STRUCT(wr);
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);
271
272         status = smb2_write(tree, &wr);
273         CHECK_STATUS(status, s->write_h1_status);
274
275         ZERO_STRUCT(rd);
276         rd.in.file.handle = h1;
277         rd.in.offset      = ARRAY_SIZE(buf)/2;
278         rd.in.length      = ARRAY_SIZE(buf)/2;
279
280         status = smb2_read(tree, tree, &rd);
281         CHECK_STATUS(status, s->read_h1_status);
282
283         ZERO_STRUCT(wr);
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);
287
288         status = smb2_write(tree, &wr);
289         CHECK_STATUS(status, s->write_h2_status);
290
291         ZERO_STRUCT(rd);
292         rd.in.file.handle = h2;
293         rd.in.offset      = ARRAY_SIZE(buf)/2;
294         rd.in.length      = ARRAY_SIZE(buf)/2;
295
296         status = smb2_read(tree, tree, &rd);
297         CHECK_STATUS(status, s->read_h2_status);
298
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);
309
310         ZERO_STRUCT(wr);
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);
314
315         status = smb2_write(tree, &wr);
316         CHECK_STATUS(status, NT_STATUS_OK);
317
318         ZERO_STRUCT(rd);
319         rd.in.file.handle = h2;
320         rd.in.offset      = ARRAY_SIZE(buf)/2;
321         rd.in.length      = ARRAY_SIZE(buf)/2;
322
323         status = smb2_read(tree, tree, &rd);
324         CHECK_STATUS(status, NT_STATUS_OK);
325
326 done:
327         return ret;
328 }
329
330 static bool test_lock_rw_none(struct torture_context *torture, struct smb2_tree *tree)
331 {
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,
339         };
340
341         return test_lock_read_write(torture, tree, &s);
342 }
343
344 static bool test_lock_rw_shared(struct torture_context *torture, struct smb2_tree *tree)
345 {
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,
353         };
354
355         return test_lock_read_write(torture, tree, &s);
356 }
357
358 static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_tree *tree)
359 {
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,
367         };
368
369         return test_lock_read_write(torture, tree, &s);
370 }
371
372 /* basic testing of SMB2 locking
373 */
374 struct torture_suite *torture_smb2_lock_init(void)
375 {
376         struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "LOCK");
377
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);
382
383         suite->description = talloc_strdup(suite, "SMB2-LOCK tests");
384
385         return suite;
386 }
387