Make sure reason for skipping is output.
[kai/samba-autobuild/.git] / source / 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         if (torture_setting_bool(torture, "windows", false)) {
256                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
257         } else {
258                 CHECK_STATUS(status, NT_STATUS_OK);
259         }
260
261         lck.in.lock_count       = 1;
262         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
263         status = smb2_lock(tree, &lck);
264         if (torture_setting_bool(torture, "windows", false)) {
265                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
266         } else {
267                 CHECK_STATUS(status, NT_STATUS_OK);
268         }
269
270         lck.in.lock_count       = 1;
271         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
272         status = smb2_lock(tree, &lck);
273         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
274
275         lck.in.lock_count       = 1;
276         el[0].flags             = 0;
277         status = smb2_lock(tree, &lck);
278         CHECK_STATUS(status, NT_STATUS_OK);
279
280         status = smb2_lock(tree, &lck);
281         CHECK_STATUS(status, NT_STATUS_OK);
282
283         lck.in.lock_count       = 2;
284         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
285         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
286         status = smb2_lock(tree, &lck);
287         CHECK_STATUS(status, NT_STATUS_OK);
288
289         lck.in.lock_count       = 1;
290         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
291         status = smb2_lock(tree, &lck);
292         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
293         
294
295 done:
296         return ret;
297 }
298
299 struct test_lock_read_write_state {
300         const char *fname;
301         uint32_t lock_flags;
302         NTSTATUS write_h1_status;
303         NTSTATUS read_h1_status;
304         NTSTATUS write_h2_status;
305         NTSTATUS read_h2_status;
306 };
307
308 static bool test_lock_read_write(struct torture_context *torture,
309                                  struct smb2_tree *tree,
310                                  struct test_lock_read_write_state *s)
311 {
312         bool ret = true;
313         NTSTATUS status;
314         struct smb2_handle h1, h2;
315         uint8_t buf[200];
316         struct smb2_lock lck;
317         struct smb2_create cr;
318         struct smb2_write wr;
319         struct smb2_read rd;
320         struct smb2_lock_element el[1];
321
322         lck.in.locks            = el;
323
324         ZERO_STRUCT(buf);
325
326         status = torture_smb2_testfile(tree, s->fname, &h1);
327         CHECK_STATUS(status, NT_STATUS_OK);
328
329         status = smb2_util_write(tree, h1, buf, 0, ARRAY_SIZE(buf));
330         CHECK_STATUS(status, NT_STATUS_OK);
331
332         lck.in.lock_count       = 0x0001;
333         lck.in.reserved         = 0x00000000;
334         lck.in.file.handle      = h1;
335         el[0].offset            = 0;
336         el[0].length            = ARRAY_SIZE(buf)/2;
337         el[0].reserved          = 0x00000000;
338         el[0].flags             = s->lock_flags;
339         status = smb2_lock(tree, &lck);
340         CHECK_STATUS(status, NT_STATUS_OK);
341         CHECK_VALUE(lck.out.reserved, 0);
342
343         lck.in.lock_count       = 0x0001;
344         lck.in.reserved         = 0x00000000;
345         lck.in.file.handle      = h1;
346         el[0].offset            = ARRAY_SIZE(buf)/2;
347         el[0].length            = ARRAY_SIZE(buf)/2;
348         el[0].reserved          = 0x00000000;
349         el[0].flags             = s->lock_flags;
350         status = smb2_lock(tree, &lck);
351         CHECK_STATUS(status, NT_STATUS_OK);
352         CHECK_VALUE(lck.out.reserved, 0);
353
354         ZERO_STRUCT(cr);
355         cr.in.oplock_level = 0;
356         cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
357         cr.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
358         cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
359         cr.in.share_access = 
360                 NTCREATEX_SHARE_ACCESS_DELETE|
361                 NTCREATEX_SHARE_ACCESS_READ|
362                 NTCREATEX_SHARE_ACCESS_WRITE;
363         cr.in.create_options = 0;
364         cr.in.fname = s->fname;
365
366         status = smb2_create(tree, tree, &cr);
367         CHECK_STATUS(status, NT_STATUS_OK);
368
369         h2 = cr.out.file.handle;
370
371         ZERO_STRUCT(wr);
372         wr.in.file.handle = h1;
373         wr.in.offset      = ARRAY_SIZE(buf)/2;
374         wr.in.data        = data_blob_const(buf, ARRAY_SIZE(buf)/2);
375
376         status = smb2_write(tree, &wr);
377         CHECK_STATUS(status, s->write_h1_status);
378
379         ZERO_STRUCT(rd);
380         rd.in.file.handle = h1;
381         rd.in.offset      = ARRAY_SIZE(buf)/2;
382         rd.in.length      = ARRAY_SIZE(buf)/2;
383
384         status = smb2_read(tree, tree, &rd);
385         CHECK_STATUS(status, s->read_h1_status);
386
387         ZERO_STRUCT(wr);
388         wr.in.file.handle = h2;
389         wr.in.offset      = ARRAY_SIZE(buf)/2;
390         wr.in.data        = data_blob_const(buf, ARRAY_SIZE(buf)/2);
391
392         status = smb2_write(tree, &wr);
393         CHECK_STATUS(status, s->write_h2_status);
394
395         ZERO_STRUCT(rd);
396         rd.in.file.handle = h2;
397         rd.in.offset      = ARRAY_SIZE(buf)/2;
398         rd.in.length      = ARRAY_SIZE(buf)/2;
399
400         status = smb2_read(tree, tree, &rd);
401         CHECK_STATUS(status, s->read_h2_status);
402
403         lck.in.lock_count       = 0x0001;
404         lck.in.reserved         = 0x00000000;
405         lck.in.file.handle      = h1;
406         el[0].offset            = ARRAY_SIZE(buf)/2;
407         el[0].length            = ARRAY_SIZE(buf)/2;
408         el[0].reserved          = 0x00000000;
409         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
410         status = smb2_lock(tree, &lck);
411         CHECK_STATUS(status, NT_STATUS_OK);
412         CHECK_VALUE(lck.out.reserved, 0);
413
414         ZERO_STRUCT(wr);
415         wr.in.file.handle = h2;
416         wr.in.offset      = ARRAY_SIZE(buf)/2;
417         wr.in.data        = data_blob_const(buf, ARRAY_SIZE(buf)/2);
418
419         status = smb2_write(tree, &wr);
420         CHECK_STATUS(status, NT_STATUS_OK);
421
422         ZERO_STRUCT(rd);
423         rd.in.file.handle = h2;
424         rd.in.offset      = ARRAY_SIZE(buf)/2;
425         rd.in.length      = ARRAY_SIZE(buf)/2;
426
427         status = smb2_read(tree, tree, &rd);
428         CHECK_STATUS(status, NT_STATUS_OK);
429
430 done:
431         return ret;
432 }
433
434 static bool test_lock_rw_none(struct torture_context *torture, struct smb2_tree *tree)
435 {
436         struct test_lock_read_write_state s = {
437                 .fname                  = "lock_rw_none.dat",
438                 .lock_flags             = SMB2_LOCK_FLAG_NONE,
439                 .write_h1_status        = NT_STATUS_FILE_LOCK_CONFLICT,
440                 .read_h1_status         = NT_STATUS_OK,
441                 .write_h2_status        = NT_STATUS_FILE_LOCK_CONFLICT,
442                 .read_h2_status         = NT_STATUS_OK,
443         };
444
445         return test_lock_read_write(torture, tree, &s);
446 }
447
448 static bool test_lock_rw_shared(struct torture_context *torture, struct smb2_tree *tree)
449 {
450         struct test_lock_read_write_state s = {
451                 .fname                  = "lock_rw_shared.dat",
452                 .lock_flags             = SMB2_LOCK_FLAG_SHARED,
453                 .write_h1_status        = NT_STATUS_FILE_LOCK_CONFLICT,
454                 .read_h1_status         = NT_STATUS_OK,
455                 .write_h2_status        = NT_STATUS_FILE_LOCK_CONFLICT,
456                 .read_h2_status         = NT_STATUS_OK,
457         };
458
459         return test_lock_read_write(torture, tree, &s);
460 }
461
462 static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_tree *tree)
463 {
464         struct test_lock_read_write_state s = {
465                 .fname                  = "lock_rw_exclusiv.dat",
466                 .lock_flags             = SMB2_LOCK_FLAG_EXCLUSIVE,
467                 .write_h1_status        = NT_STATUS_OK,
468                 .read_h1_status         = NT_STATUS_OK,
469                 .write_h2_status        = NT_STATUS_FILE_LOCK_CONFLICT,
470                 .read_h2_status         = NT_STATUS_FILE_LOCK_CONFLICT,
471         };
472
473         return test_lock_read_write(torture, tree, &s);
474 }
475
476 /* basic testing of SMB2 locking
477 */
478 struct torture_suite *torture_smb2_lock_init(void)
479 {
480         struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "LOCK");
481
482         torture_suite_add_1smb2_test(suite, "VALID-REQUEST", test_valid_request);
483         torture_suite_add_1smb2_test(suite, "RW-NONE", test_lock_rw_none);
484         torture_suite_add_1smb2_test(suite, "RW-SHARED", test_lock_rw_shared);
485         torture_suite_add_1smb2_test(suite, "RW-EXCLUSIV", test_lock_rw_exclusiv);
486
487         suite->description = talloc_strdup(suite, "SMB2-LOCK tests");
488
489         return suite;
490 }
491