Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into v4-0-defs
[garming/samba-autobuild/.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         if (torture_setting_bool(torture, "windows", false)) {
110                 CHECK_STATUS(status, NT_STATUS_OK);
111         } else {
112                 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
113         }
114         CHECK_VALUE(lck.out.reserved, 0);
115
116         lck.in.reserved         = 0x123ab4;
117         status = smb2_lock(tree, &lck);
118         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
119
120         lck.in.reserved         = 0x123ab5;
121         status = smb2_lock(tree, &lck);
122         if (torture_setting_bool(torture, "windows", false)) {
123                 CHECK_STATUS(status, NT_STATUS_OK);
124         } else {
125                 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
126         }
127         CHECK_VALUE(lck.out.reserved, 0);
128
129         lck.in.lock_count       = 0x0001;
130         lck.in.reserved         = 0x12345678;
131         lck.in.file.handle      = h;
132         el[0].offset            = UINT32_MAX;
133         el[0].length            = UINT32_MAX;
134         el[0].reserved          = 0x87654321;
135         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
136         status = smb2_lock(tree, &lck);
137         CHECK_STATUS(status, NT_STATUS_OK);
138         CHECK_VALUE(lck.out.reserved, 0);
139
140         status = smb2_lock(tree, &lck);
141         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
142
143         status = smb2_lock(tree, &lck);
144         if (torture_setting_bool(torture, "windows", false)) {
145                 CHECK_STATUS(status, NT_STATUS_OK);
146         } else {
147                 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
148         }
149         CHECK_VALUE(lck.out.reserved, 0);
150
151         status = smb2_lock(tree, &lck);
152         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
153
154         status = smb2_lock(tree, &lck);
155         if (torture_setting_bool(torture, "windows", false)) {
156                 CHECK_STATUS(status, NT_STATUS_OK);
157         } else {
158                 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
159         }
160         CHECK_VALUE(lck.out.reserved, 0);
161
162         el[0].flags             = 0x00000000;
163         status = smb2_lock(tree, &lck);
164         CHECK_STATUS(status, NT_STATUS_OK);
165         CHECK_VALUE(lck.out.reserved, 0);
166
167         status = smb2_lock(tree, &lck);
168         CHECK_STATUS(status, NT_STATUS_OK);
169         CHECK_VALUE(lck.out.reserved, 0);
170
171         el[0].flags             = 0x00000001;
172         status = smb2_lock(tree, &lck);
173         CHECK_STATUS(status, NT_STATUS_OK);
174         CHECK_VALUE(lck.out.reserved, 0);
175
176         status = smb2_lock(tree, &lck);
177         CHECK_STATUS(status, NT_STATUS_OK);
178         CHECK_VALUE(lck.out.reserved, 0);
179
180         lck.in.lock_count       = 0x0001;
181         lck.in.reserved         = 0x87654321;
182         lck.in.file.handle      = h;
183         el[0].offset            = 0x00000000FFFFFFFF;
184         el[0].length            = 0x00000000FFFFFFFF;
185         el[0].reserved          = 0x1234567;
186         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
187         status = smb2_lock(tree, &lck);
188         CHECK_STATUS(status, NT_STATUS_OK);
189
190         lck.in.lock_count       = 0x0001;
191         lck.in.reserved         = 0x1234567;
192         lck.in.file.handle      = h;
193         el[0].offset            = 0x00000000FFFFFFFF;
194         el[0].length            = 0x00000000FFFFFFFF;
195         el[0].reserved          = 0x00000000;
196         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
197         status = smb2_lock(tree, &lck);
198         CHECK_STATUS(status, NT_STATUS_OK);
199
200         status = smb2_lock(tree, &lck);
201         CHECK_STATUS(status, NT_STATUS_OK);
202         status = smb2_lock(tree, &lck);
203         CHECK_STATUS(status, NT_STATUS_OK);
204         status = smb2_lock(tree, &lck);
205         CHECK_STATUS(status, NT_STATUS_OK);
206         status = smb2_lock(tree, &lck);
207         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
208
209         lck.in.lock_count       = 0x0001;
210         lck.in.reserved         = 0;
211         lck.in.file.handle      = h;
212         el[0].offset            = 1;
213         el[0].length            = 1;
214         el[0].reserved          = 0x00000000;
215         el[0].flags             = ~SMB2_LOCK_FLAG_ALL_MASK;
216
217         status = smb2_lock(tree, &lck);
218         CHECK_STATUS(status, NT_STATUS_OK);
219
220         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
221         status = smb2_lock(tree, &lck);
222         CHECK_STATUS(status, NT_STATUS_OK);
223
224         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
225         status = smb2_lock(tree, &lck);
226         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
227
228         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_EXCLUSIVE;
229         status = smb2_lock(tree, &lck);
230         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
231
232         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_SHARED;
233         status = smb2_lock(tree, &lck);
234         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
235
236         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
237         status = smb2_lock(tree, &lck);
238         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
239
240         lck.in.lock_count       = 2;
241         lck.in.reserved         = 0;
242         lck.in.file.handle      = h;
243         el[0].offset            = 9999;
244         el[0].length            = 1;
245         el[0].reserved          = 0x00000000;
246         el[1].offset            = 9999;
247         el[1].length            = 1;
248         el[1].reserved          = 0x00000000;
249
250         lck.in.lock_count       = 2;
251         el[0].flags             = 0;
252         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
253         status = smb2_lock(tree, &lck);
254         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
255
256         lck.in.lock_count       = 2;
257         el[0].flags             = 0;
258         el[1].flags             = 0;
259         status = smb2_lock(tree, &lck);
260         CHECK_STATUS(status, NT_STATUS_OK);
261
262         lck.in.lock_count       = 2;
263         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
264         el[1].flags             = 0;
265         status = smb2_lock(tree, &lck);
266         CHECK_STATUS(status, NT_STATUS_OK);
267
268         lck.in.lock_count       = 1;
269         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
270         status = smb2_lock(tree, &lck);
271         if (torture_setting_bool(torture, "windows", false)) {
272                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
273         } else {
274                 CHECK_STATUS(status, NT_STATUS_OK);
275         }
276
277         lck.in.lock_count       = 1;
278         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
279         status = smb2_lock(tree, &lck);
280         if (torture_setting_bool(torture, "windows", false)) {
281                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
282         } else {
283                 CHECK_STATUS(status, NT_STATUS_OK);
284         }
285
286         lck.in.lock_count       = 1;
287         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
288         status = smb2_lock(tree, &lck);
289         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
290
291         lck.in.lock_count       = 1;
292         el[0].flags             = 0;
293         status = smb2_lock(tree, &lck);
294         CHECK_STATUS(status, NT_STATUS_OK);
295
296         status = smb2_lock(tree, &lck);
297         CHECK_STATUS(status, NT_STATUS_OK);
298
299         lck.in.lock_count       = 2;
300         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
301         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
302         status = smb2_lock(tree, &lck);
303         CHECK_STATUS(status, NT_STATUS_OK);
304
305         lck.in.lock_count       = 1;
306         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
307         status = smb2_lock(tree, &lck);
308         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
309         
310
311 done:
312         return ret;
313 }
314
315 struct test_lock_read_write_state {
316         const char *fname;
317         uint32_t lock_flags;
318         NTSTATUS write_h1_status;
319         NTSTATUS read_h1_status;
320         NTSTATUS write_h2_status;
321         NTSTATUS read_h2_status;
322 };
323
324 static bool test_lock_read_write(struct torture_context *torture,
325                                  struct smb2_tree *tree,
326                                  struct test_lock_read_write_state *s)
327 {
328         bool ret = true;
329         NTSTATUS status;
330         struct smb2_handle h1, h2;
331         uint8_t buf[200];
332         struct smb2_lock lck;
333         struct smb2_create cr;
334         struct smb2_write wr;
335         struct smb2_read rd;
336         struct smb2_lock_element el[1];
337
338         lck.in.locks            = el;
339
340         ZERO_STRUCT(buf);
341
342         status = torture_smb2_testfile(tree, s->fname, &h1);
343         CHECK_STATUS(status, NT_STATUS_OK);
344
345         status = smb2_util_write(tree, h1, buf, 0, ARRAY_SIZE(buf));
346         CHECK_STATUS(status, NT_STATUS_OK);
347
348         lck.in.lock_count       = 0x0001;
349         lck.in.reserved         = 0x00000000;
350         lck.in.file.handle      = h1;
351         el[0].offset            = 0;
352         el[0].length            = ARRAY_SIZE(buf)/2;
353         el[0].reserved          = 0x00000000;
354         el[0].flags             = s->lock_flags;
355         status = smb2_lock(tree, &lck);
356         CHECK_STATUS(status, NT_STATUS_OK);
357         CHECK_VALUE(lck.out.reserved, 0);
358
359         lck.in.lock_count       = 0x0001;
360         lck.in.reserved         = 0x00000000;
361         lck.in.file.handle      = h1;
362         el[0].offset            = ARRAY_SIZE(buf)/2;
363         el[0].length            = ARRAY_SIZE(buf)/2;
364         el[0].reserved          = 0x00000000;
365         el[0].flags             = s->lock_flags;
366         status = smb2_lock(tree, &lck);
367         CHECK_STATUS(status, NT_STATUS_OK);
368         CHECK_VALUE(lck.out.reserved, 0);
369
370         ZERO_STRUCT(cr);
371         cr.in.oplock_level = 0;
372         cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
373         cr.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
374         cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
375         cr.in.share_access = 
376                 NTCREATEX_SHARE_ACCESS_DELETE|
377                 NTCREATEX_SHARE_ACCESS_READ|
378                 NTCREATEX_SHARE_ACCESS_WRITE;
379         cr.in.create_options = 0;
380         cr.in.fname = s->fname;
381
382         status = smb2_create(tree, tree, &cr);
383         CHECK_STATUS(status, NT_STATUS_OK);
384
385         h2 = cr.out.file.handle;
386
387         ZERO_STRUCT(wr);
388         wr.in.file.handle = h1;
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_h1_status);
394
395         ZERO_STRUCT(rd);
396         rd.in.file.handle = h1;
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_h1_status);
402
403         ZERO_STRUCT(wr);
404         wr.in.file.handle = h2;
405         wr.in.offset      = ARRAY_SIZE(buf)/2;
406         wr.in.data        = data_blob_const(buf, ARRAY_SIZE(buf)/2);
407
408         status = smb2_write(tree, &wr);
409         CHECK_STATUS(status, s->write_h2_status);
410
411         ZERO_STRUCT(rd);
412         rd.in.file.handle = h2;
413         rd.in.offset      = ARRAY_SIZE(buf)/2;
414         rd.in.length      = ARRAY_SIZE(buf)/2;
415
416         status = smb2_read(tree, tree, &rd);
417         CHECK_STATUS(status, s->read_h2_status);
418
419         lck.in.lock_count       = 0x0001;
420         lck.in.reserved         = 0x00000000;
421         lck.in.file.handle      = h1;
422         el[0].offset            = ARRAY_SIZE(buf)/2;
423         el[0].length            = ARRAY_SIZE(buf)/2;
424         el[0].reserved          = 0x00000000;
425         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
426         status = smb2_lock(tree, &lck);
427         CHECK_STATUS(status, NT_STATUS_OK);
428         CHECK_VALUE(lck.out.reserved, 0);
429
430         ZERO_STRUCT(wr);
431         wr.in.file.handle = h2;
432         wr.in.offset      = ARRAY_SIZE(buf)/2;
433         wr.in.data        = data_blob_const(buf, ARRAY_SIZE(buf)/2);
434
435         status = smb2_write(tree, &wr);
436         CHECK_STATUS(status, NT_STATUS_OK);
437
438         ZERO_STRUCT(rd);
439         rd.in.file.handle = h2;
440         rd.in.offset      = ARRAY_SIZE(buf)/2;
441         rd.in.length      = ARRAY_SIZE(buf)/2;
442
443         status = smb2_read(tree, tree, &rd);
444         CHECK_STATUS(status, NT_STATUS_OK);
445
446 done:
447         return ret;
448 }
449
450 static bool test_lock_rw_none(struct torture_context *torture, struct smb2_tree *tree)
451 {
452         struct test_lock_read_write_state s = {
453                 .fname                  = "lock_rw_none.dat",
454                 .lock_flags             = SMB2_LOCK_FLAG_NONE,
455                 .write_h1_status        = NT_STATUS_FILE_LOCK_CONFLICT,
456                 .read_h1_status         = NT_STATUS_OK,
457                 .write_h2_status        = NT_STATUS_FILE_LOCK_CONFLICT,
458                 .read_h2_status         = NT_STATUS_OK,
459         };
460
461         return test_lock_read_write(torture, tree, &s);
462 }
463
464 static bool test_lock_rw_shared(struct torture_context *torture, struct smb2_tree *tree)
465 {
466         struct test_lock_read_write_state s = {
467                 .fname                  = "lock_rw_shared.dat",
468                 .lock_flags             = SMB2_LOCK_FLAG_SHARED,
469                 .write_h1_status        = NT_STATUS_FILE_LOCK_CONFLICT,
470                 .read_h1_status         = NT_STATUS_OK,
471                 .write_h2_status        = NT_STATUS_FILE_LOCK_CONFLICT,
472                 .read_h2_status         = NT_STATUS_OK,
473         };
474
475         return test_lock_read_write(torture, tree, &s);
476 }
477
478 static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_tree *tree)
479 {
480         struct test_lock_read_write_state s = {
481                 .fname                  = "lock_rw_exclusiv.dat",
482                 .lock_flags             = SMB2_LOCK_FLAG_EXCLUSIVE,
483                 .write_h1_status        = NT_STATUS_OK,
484                 .read_h1_status         = NT_STATUS_OK,
485                 .write_h2_status        = NT_STATUS_FILE_LOCK_CONFLICT,
486                 .read_h2_status         = NT_STATUS_FILE_LOCK_CONFLICT,
487         };
488
489         return test_lock_read_write(torture, tree, &s);
490 }
491
492
493 static bool test_lock_auto_unlock(struct torture_context *torture, struct smb2_tree *tree)
494 {
495         bool ret = true;
496         NTSTATUS status;
497         struct smb2_handle h;
498         uint8_t buf[200];
499         struct smb2_lock lck;
500         struct smb2_lock_element el[2];
501
502         ZERO_STRUCT(buf);
503
504         status = torture_smb2_testfile(tree, "autounlock.txt", &h);
505         CHECK_STATUS(status, NT_STATUS_OK);
506
507         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
508         CHECK_STATUS(status, NT_STATUS_OK);
509
510         ZERO_STRUCT(lck);
511         lck.in.locks            = el;
512         lck.in.lock_count       = 0x0001;
513         lck.in.file.handle      = h;
514         el[0].offset            = 0;
515         el[0].length            = 1;
516         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
517         status = smb2_lock(tree, &lck);
518         CHECK_STATUS(status, NT_STATUS_OK);
519
520         status = smb2_lock(tree, &lck);
521         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
522
523         status = smb2_lock(tree, &lck);
524         if (torture_setting_bool(torture, "windows", false)) {
525                 CHECK_STATUS(status, NT_STATUS_OK);
526         } else {
527                 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
528         }
529
530         
531
532 done:
533         return ret;
534 }
535
536
537 /* basic testing of SMB2 locking
538 */
539 struct torture_suite *torture_smb2_lock_init(void)
540 {
541         struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "LOCK");
542
543         torture_suite_add_1smb2_test(suite, "VALID-REQUEST", test_valid_request);
544         torture_suite_add_1smb2_test(suite, "RW-NONE", test_lock_rw_none);
545         torture_suite_add_1smb2_test(suite, "RW-SHARED", test_lock_rw_shared);
546         torture_suite_add_1smb2_test(suite, "RW-EXCLUSIV", test_lock_rw_exclusiv);
547         torture_suite_add_1smb2_test(suite, "AUTO-UNLOCK", test_lock_auto_unlock);
548
549         suite->description = talloc_strdup(suite, "SMB2-LOCK tests");
550
551         return suite;
552 }
553