Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into 4-0-abartlet
[kai/samba.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[2];
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         status = smb2_lock(tree, &lck);
191         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
192
193         lck.in.lock_count       = 0x0001;
194         lck.in.reserved         = 0;
195         lck.in.file.handle      = h;
196         el[0].offset            = 1;
197         el[0].length            = 1;
198         el[0].reserved          = 0x00000000;
199         el[0].flags             = ~SMB2_LOCK_FLAG_ALL_MASK;
200
201         status = smb2_lock(tree, &lck);
202         CHECK_STATUS(status, NT_STATUS_OK);
203
204         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
205         status = smb2_lock(tree, &lck);
206         CHECK_STATUS(status, NT_STATUS_OK);
207
208         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
209         status = smb2_lock(tree, &lck);
210         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
211
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);
215
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);
219
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);
223
224         lck.in.lock_count       = 2;
225         lck.in.reserved         = 0;
226         lck.in.file.handle      = h;
227         el[0].offset            = 9999;
228         el[0].length            = 1;
229         el[0].reserved          = 0x00000000;
230         el[1].offset            = 9999;
231         el[1].length            = 1;
232         el[1].reserved          = 0x00000000;
233
234         lck.in.lock_count       = 2;
235         el[0].flags             = 0;
236         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
237         status = smb2_lock(tree, &lck);
238         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
239
240         lck.in.lock_count       = 2;
241         el[0].flags             = 0;
242         el[1].flags             = 0;
243         status = smb2_lock(tree, &lck);
244         CHECK_STATUS(status, NT_STATUS_OK);
245
246         lck.in.lock_count       = 2;
247         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
248         el[1].flags             = 0;
249         status = smb2_lock(tree, &lck);
250         CHECK_STATUS(status, NT_STATUS_OK);
251
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);
256
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);
261
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);
266
267         lck.in.lock_count       = 1;
268         el[0].flags             = 0;
269         status = smb2_lock(tree, &lck);
270         CHECK_STATUS(status, NT_STATUS_OK);
271
272         status = smb2_lock(tree, &lck);
273         CHECK_STATUS(status, NT_STATUS_OK);
274
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);
280
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);
285         
286
287 done:
288         return ret;
289 }
290
291 struct test_lock_read_write_state {
292         const char *fname;
293         uint32_t lock_flags;
294         NTSTATUS write_h1_status;
295         NTSTATUS read_h1_status;
296         NTSTATUS write_h2_status;
297         NTSTATUS read_h2_status;
298 };
299
300 static bool test_lock_read_write(struct torture_context *torture,
301                                  struct smb2_tree *tree,
302                                  struct test_lock_read_write_state *s)
303 {
304         bool ret = true;
305         NTSTATUS status;
306         struct smb2_handle h1, h2;
307         uint8_t buf[200];
308         struct smb2_lock lck;
309         struct smb2_create cr;
310         struct smb2_write wr;
311         struct smb2_read rd;
312         struct smb2_lock_element el[1];
313
314         lck.in.locks            = el;
315
316         ZERO_STRUCT(buf);
317
318         status = torture_smb2_testfile(tree, s->fname, &h1);
319         CHECK_STATUS(status, NT_STATUS_OK);
320
321         status = smb2_util_write(tree, h1, buf, 0, ARRAY_SIZE(buf));
322         CHECK_STATUS(status, NT_STATUS_OK);
323
324         lck.in.lock_count       = 0x0001;
325         lck.in.reserved         = 0x00000000;
326         lck.in.file.handle      = h1;
327         el[0].offset            = 0;
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);
334
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);
345
346         ZERO_STRUCT(cr);
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;
351         cr.in.share_access = 
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;
357
358         status = smb2_create(tree, tree, &cr);
359         CHECK_STATUS(status, NT_STATUS_OK);
360
361         h2 = cr.out.file.handle;
362
363         ZERO_STRUCT(wr);
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);
367
368         status = smb2_write(tree, &wr);
369         CHECK_STATUS(status, s->write_h1_status);
370
371         ZERO_STRUCT(rd);
372         rd.in.file.handle = h1;
373         rd.in.offset      = ARRAY_SIZE(buf)/2;
374         rd.in.length      = ARRAY_SIZE(buf)/2;
375
376         status = smb2_read(tree, tree, &rd);
377         CHECK_STATUS(status, s->read_h1_status);
378
379         ZERO_STRUCT(wr);
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);
383
384         status = smb2_write(tree, &wr);
385         CHECK_STATUS(status, s->write_h2_status);
386
387         ZERO_STRUCT(rd);
388         rd.in.file.handle = h2;
389         rd.in.offset      = ARRAY_SIZE(buf)/2;
390         rd.in.length      = ARRAY_SIZE(buf)/2;
391
392         status = smb2_read(tree, tree, &rd);
393         CHECK_STATUS(status, s->read_h2_status);
394
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);
405
406         ZERO_STRUCT(wr);
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);
410
411         status = smb2_write(tree, &wr);
412         CHECK_STATUS(status, NT_STATUS_OK);
413
414         ZERO_STRUCT(rd);
415         rd.in.file.handle = h2;
416         rd.in.offset      = ARRAY_SIZE(buf)/2;
417         rd.in.length      = ARRAY_SIZE(buf)/2;
418
419         status = smb2_read(tree, tree, &rd);
420         CHECK_STATUS(status, NT_STATUS_OK);
421
422 done:
423         return ret;
424 }
425
426 static bool test_lock_rw_none(struct torture_context *torture, struct smb2_tree *tree)
427 {
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,
435         };
436
437         return test_lock_read_write(torture, tree, &s);
438 }
439
440 static bool test_lock_rw_shared(struct torture_context *torture, struct smb2_tree *tree)
441 {
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,
449         };
450
451         return test_lock_read_write(torture, tree, &s);
452 }
453
454 static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_tree *tree)
455 {
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,
463         };
464
465         return test_lock_read_write(torture, tree, &s);
466 }
467
468 /* basic testing of SMB2 locking
469 */
470 struct torture_suite *torture_smb2_lock_init(void)
471 {
472         struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "LOCK");
473
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);
478
479         suite->description = talloc_strdup(suite, "SMB2-LOCK tests");
480
481         return suite;
482 }
483