348312657b43ac58a6f2e767047a0aee95a4c820
[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 #include "torture/util.h"
29
30 #include "lib/events/events.h"
31 #include "param/param.h"
32
33 #define CHECK_STATUS(status, correct) do { \
34         const char *_cmt = "(" __location__ ")"; \
35         torture_assert_ntstatus_equal_goto(torture,status,correct, \
36                                            ret,done,_cmt); \
37         } while (0)
38
39 #define CHECK_STATUS_CMT(status, correct, cmt) do { \
40         torture_assert_ntstatus_equal_goto(torture,status,correct, \
41                                            ret,done,cmt); \
42         } while (0)
43
44 #define CHECK_STATUS_CONT(status, correct) do { \
45         if (!NT_STATUS_EQUAL(status, correct)) { \
46                 torture_result(torture, TORTURE_FAIL, \
47                         "(%s) Incorrect status %s - should be %s\n", \
48                         __location__, nt_errstr(status), nt_errstr(correct)); \
49                 ret = false; \
50         }} while (0)
51
52 #define CHECK_VALUE(v, correct) do { \
53         const char *_cmt = "(" __location__ ")"; \
54         torture_assert_int_equal_goto(torture,v,correct,ret,done,_cmt); \
55         } while (0)
56
57 #define BASEDIR "testlock"
58
59 #define TARGET_SUPPORTS_INVALID_LOCK_RANGE(_tctx) \
60     (torture_setting_bool(_tctx, "invalid_lock_range_support", true))
61 #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false))
62
63 #define WAIT_FOR_ASYNC_RESPONSE(req) \
64         while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) { \
65                 if (event_loop_once(req->transport->socket->event.ctx) != 0) { \
66                         break; \
67                 } \
68         }
69
70 static bool test_valid_request(struct torture_context *torture,
71                                struct smb2_tree *tree)
72 {
73         bool ret = true;
74         NTSTATUS status;
75         struct smb2_handle h;
76         uint8_t buf[200];
77         struct smb2_lock lck;
78         struct smb2_lock_element el[2];
79
80         ZERO_STRUCT(buf);
81
82         status = torture_smb2_testfile(tree, "lock1.txt", &h);
83         CHECK_STATUS(status, NT_STATUS_OK);
84
85         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
86         CHECK_STATUS(status, NT_STATUS_OK);
87
88         lck.in.locks            = el;
89
90         torture_comment(torture, "Test request with 0 locks.\n");
91
92         lck.in.lock_count       = 0x0000;
93         lck.in.lock_sequence    = 0x00000000;
94         lck.in.file.handle      = h;
95         el[0].offset            = 0x0000000000000000;
96         el[0].length            = 0x0000000000000000;
97         el[0].reserved          = 0x0000000000000000;
98         el[0].flags             = 0x00000000;
99         status = smb2_lock(tree, &lck);
100         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
101
102         lck.in.lock_count       = 0x0000;
103         lck.in.lock_sequence    = 0x00000000;
104         lck.in.file.handle      = h;
105         el[0].offset            = 0;
106         el[0].length            = 0;
107         el[0].reserved          = 0x00000000;
108         el[0].flags             = SMB2_LOCK_FLAG_SHARED;
109         status = smb2_lock(tree, &lck);
110         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
111
112         lck.in.lock_count       = 0x0001;
113         lck.in.lock_sequence    = 0x00000000;
114         lck.in.file.handle      = h;
115         el[0].offset            = 0;
116         el[0].length            = 0;
117         el[0].reserved          = 0x00000000;
118         el[0].flags             = SMB2_LOCK_FLAG_NONE;
119         status = smb2_lock(tree, &lck);
120         if (TARGET_IS_W2K8(torture)) {
121                 CHECK_STATUS(status, NT_STATUS_OK);
122                 torture_warning(torture, "Target has bug validating lock flags "
123                                          "parameter.\n");
124         } else {
125                 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
126         }
127
128         torture_comment(torture, "Test >63-bit lock requests.\n");
129
130         lck.in.file.handle.data[0] +=1;
131         status = smb2_lock(tree, &lck);
132         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
133         lck.in.file.handle.data[0] -=1;
134
135         lck.in.lock_count       = 0x0001;
136         lck.in.lock_sequence    = 0x123ab1;
137         lck.in.file.handle      = h;
138         el[0].offset            = UINT64_MAX;
139         el[0].length            = UINT64_MAX;
140         el[0].reserved          = 0x00000000;
141         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
142                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
143         status = smb2_lock(tree, &lck);
144         if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(torture)) {
145                 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
146         } else {
147                 CHECK_STATUS(status, NT_STATUS_OK);
148                 CHECK_VALUE(lck.out.reserved, 0);
149         }
150
151         lck.in.lock_sequence    = 0x123ab2;
152         status = smb2_lock(tree, &lck);
153         if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(torture)) {
154                 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
155         } else {
156                 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
157         }
158
159         torture_comment(torture, "Test basic lock stacking.\n");
160
161         lck.in.lock_count       = 0x0001;
162         lck.in.lock_sequence    = 0x12345678;
163         lck.in.file.handle      = h;
164         el[0].offset            = UINT32_MAX;
165         el[0].length            = UINT32_MAX;
166         el[0].reserved          = 0x87654321;
167         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
168                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
169         status = smb2_lock(tree, &lck);
170         CHECK_STATUS(status, NT_STATUS_OK);
171         CHECK_VALUE(lck.out.reserved, 0);
172
173         el[0].flags             = SMB2_LOCK_FLAG_SHARED;
174         status = smb2_lock(tree, &lck);
175         CHECK_STATUS(status, NT_STATUS_OK);
176         CHECK_VALUE(lck.out.reserved, 0);
177
178         status = smb2_lock(tree, &lck);
179         CHECK_STATUS(status, NT_STATUS_OK);
180         CHECK_VALUE(lck.out.reserved, 0);
181
182         lck.in.lock_count       = 0x0001;
183         lck.in.lock_sequence    = 0x87654321;
184         lck.in.file.handle      = h;
185         el[0].offset            = 0x00000000FFFFFFFF;
186         el[0].length            = 0x00000000FFFFFFFF;
187         el[0].reserved          = 0x1234567;
188         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
189         status = smb2_lock(tree, &lck);
190         CHECK_STATUS(status, NT_STATUS_OK);
191
192         lck.in.lock_count       = 0x0001;
193         lck.in.lock_sequence    = 0x1234567;
194         lck.in.file.handle      = h;
195         el[0].offset            = 0x00000000FFFFFFFF;
196         el[0].length            = 0x00000000FFFFFFFF;
197         el[0].reserved          = 0x00000000;
198         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
199         status = smb2_lock(tree, &lck);
200         CHECK_STATUS(status, NT_STATUS_OK);
201
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_RANGE_NOT_LOCKED);
206
207         torture_comment(torture, "Test flags field permutations.\n");
208
209         lck.in.lock_count       = 0x0001;
210         lck.in.lock_sequence    = 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         if (TARGET_IS_W2K8(torture)) {
219                 CHECK_STATUS(status, NT_STATUS_OK);
220                 torture_warning(torture, "Target has bug validating lock flags "
221                                          "parameter.\n");
222         } else {
223                 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
224         }
225
226         if (TARGET_IS_W2K8(torture)) {
227                 el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
228                 status = smb2_lock(tree, &lck);
229                 CHECK_STATUS(status, NT_STATUS_OK);
230         }
231
232         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
233         status = smb2_lock(tree, &lck);
234         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
235
236         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK |
237                                   SMB2_LOCK_FLAG_EXCLUSIVE;
238         status = smb2_lock(tree, &lck);
239         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
240
241         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK |
242                                   SMB2_LOCK_FLAG_SHARED;
243         status = smb2_lock(tree, &lck);
244         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
245
246         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK |
247                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
248         status = smb2_lock(tree, &lck);
249         if (TARGET_IS_W2K8(torture)) {
250                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
251                 torture_warning(torture, "Target has bug validating lock flags "
252                                          "parameter.\n");
253         } else {
254                 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
255         }
256
257         torture_comment(torture, "Test return error when 2 locks are "
258                                  "requested\n");
259
260         lck.in.lock_count       = 2;
261         lck.in.lock_sequence    = 0;
262         lck.in.file.handle      = h;
263         el[0].offset            = 9999;
264         el[0].length            = 1;
265         el[0].reserved          = 0x00000000;
266         el[1].offset            = 9999;
267         el[1].length            = 1;
268         el[1].reserved          = 0x00000000;
269
270         lck.in.lock_count       = 2;
271         el[0].flags             = 0;
272         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
273         status = smb2_lock(tree, &lck);
274         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
275
276         lck.in.lock_count       = 2;
277         el[0].flags             = 0;
278         el[1].flags             = 0;
279         status = smb2_lock(tree, &lck);
280         if (TARGET_IS_W2K8(torture)) {
281                 CHECK_STATUS(status, NT_STATUS_OK);
282                 torture_warning(torture, "Target has bug validating lock flags "
283                                          "parameter.\n");
284         } else {
285                 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
286         }
287
288         lck.in.lock_count       = 2;
289         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
290         el[1].flags             = 0;
291         status = smb2_lock(tree, &lck);
292         if (TARGET_IS_W2K8(torture)) {
293                 CHECK_STATUS(status, NT_STATUS_OK);
294                 torture_warning(torture, "Target has bug validating lock flags "
295                                          "parameter.\n");
296         } else {
297                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
298         }
299
300         lck.in.lock_count       = 1;
301         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
302         status = smb2_lock(tree, &lck);
303         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
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         lck.in.lock_count       = 1;
311         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
312         status = smb2_lock(tree, &lck);
313         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
314
315         lck.in.lock_count       = 1;
316         el[0].flags             = SMB2_LOCK_FLAG_SHARED;
317         status = smb2_lock(tree, &lck);
318         CHECK_STATUS(status, NT_STATUS_OK);
319
320         status = smb2_lock(tree, &lck);
321         CHECK_STATUS(status, NT_STATUS_OK);
322
323         lck.in.lock_count       = 2;
324         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
325         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
326         status = smb2_lock(tree, &lck);
327         CHECK_STATUS(status, NT_STATUS_OK);
328
329         lck.in.lock_count       = 1;
330         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
331         status = smb2_lock(tree, &lck);
332         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
333
334 done:
335         return ret;
336 }
337
338 struct test_lock_read_write_state {
339         const char *fname;
340         uint32_t lock_flags;
341         NTSTATUS write_h1_status;
342         NTSTATUS read_h1_status;
343         NTSTATUS write_h2_status;
344         NTSTATUS read_h2_status;
345 };
346
347 static bool test_lock_read_write(struct torture_context *torture,
348                                  struct smb2_tree *tree,
349                                  struct test_lock_read_write_state *s)
350 {
351         bool ret = true;
352         NTSTATUS status;
353         struct smb2_handle h1, h2;
354         uint8_t buf[200];
355         struct smb2_lock lck;
356         struct smb2_create cr;
357         struct smb2_write wr;
358         struct smb2_read rd;
359         struct smb2_lock_element el[1];
360
361         lck.in.locks            = el;
362
363         ZERO_STRUCT(buf);
364
365         status = torture_smb2_testfile(tree, s->fname, &h1);
366         CHECK_STATUS(status, NT_STATUS_OK);
367
368         status = smb2_util_write(tree, h1, buf, 0, ARRAY_SIZE(buf));
369         CHECK_STATUS(status, NT_STATUS_OK);
370
371         lck.in.lock_count       = 0x0001;
372         lck.in.lock_sequence    = 0x00000000;
373         lck.in.file.handle      = h1;
374         el[0].offset            = 0;
375         el[0].length            = ARRAY_SIZE(buf)/2;
376         el[0].reserved          = 0x00000000;
377         el[0].flags             = s->lock_flags;
378         status = smb2_lock(tree, &lck);
379         CHECK_STATUS(status, NT_STATUS_OK);
380         CHECK_VALUE(lck.out.reserved, 0);
381
382         lck.in.lock_count       = 0x0001;
383         lck.in.lock_sequence    = 0x00000000;
384         lck.in.file.handle      = h1;
385         el[0].offset            = ARRAY_SIZE(buf)/2;
386         el[0].length            = ARRAY_SIZE(buf)/2;
387         el[0].reserved          = 0x00000000;
388         el[0].flags             = s->lock_flags;
389         status = smb2_lock(tree, &lck);
390         CHECK_STATUS(status, NT_STATUS_OK);
391         CHECK_VALUE(lck.out.reserved, 0);
392
393         ZERO_STRUCT(cr);
394         cr.in.oplock_level = 0;
395         cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
396         cr.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
397         cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
398         cr.in.share_access =
399                 NTCREATEX_SHARE_ACCESS_DELETE|
400                 NTCREATEX_SHARE_ACCESS_READ|
401                 NTCREATEX_SHARE_ACCESS_WRITE;
402         cr.in.create_options = 0;
403         cr.in.fname = s->fname;
404
405         status = smb2_create(tree, tree, &cr);
406         CHECK_STATUS(status, NT_STATUS_OK);
407
408         h2 = cr.out.file.handle;
409
410         ZERO_STRUCT(wr);
411         wr.in.file.handle = h1;
412         wr.in.offset      = ARRAY_SIZE(buf)/2;
413         wr.in.data        = data_blob_const(buf, ARRAY_SIZE(buf)/2);
414
415         status = smb2_write(tree, &wr);
416         CHECK_STATUS(status, s->write_h1_status);
417
418         ZERO_STRUCT(rd);
419         rd.in.file.handle = h1;
420         rd.in.offset      = ARRAY_SIZE(buf)/2;
421         rd.in.length      = ARRAY_SIZE(buf)/2;
422
423         status = smb2_read(tree, tree, &rd);
424         CHECK_STATUS(status, s->read_h1_status);
425
426         ZERO_STRUCT(wr);
427         wr.in.file.handle = h2;
428         wr.in.offset      = ARRAY_SIZE(buf)/2;
429         wr.in.data        = data_blob_const(buf, ARRAY_SIZE(buf)/2);
430
431         status = smb2_write(tree, &wr);
432         CHECK_STATUS(status, s->write_h2_status);
433
434         ZERO_STRUCT(rd);
435         rd.in.file.handle = h2;
436         rd.in.offset      = ARRAY_SIZE(buf)/2;
437         rd.in.length      = ARRAY_SIZE(buf)/2;
438
439         status = smb2_read(tree, tree, &rd);
440         CHECK_STATUS(status, s->read_h2_status);
441
442         lck.in.lock_count       = 0x0001;
443         lck.in.lock_sequence    = 0x00000000;
444         lck.in.file.handle      = h1;
445         el[0].offset            = ARRAY_SIZE(buf)/2;
446         el[0].length            = ARRAY_SIZE(buf)/2;
447         el[0].reserved          = 0x00000000;
448         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
449         status = smb2_lock(tree, &lck);
450         CHECK_STATUS(status, NT_STATUS_OK);
451         CHECK_VALUE(lck.out.reserved, 0);
452
453         ZERO_STRUCT(wr);
454         wr.in.file.handle = h2;
455         wr.in.offset      = ARRAY_SIZE(buf)/2;
456         wr.in.data        = data_blob_const(buf, ARRAY_SIZE(buf)/2);
457
458         status = smb2_write(tree, &wr);
459         CHECK_STATUS(status, NT_STATUS_OK);
460
461         ZERO_STRUCT(rd);
462         rd.in.file.handle = h2;
463         rd.in.offset      = ARRAY_SIZE(buf)/2;
464         rd.in.length      = ARRAY_SIZE(buf)/2;
465
466         status = smb2_read(tree, tree, &rd);
467         CHECK_STATUS(status, NT_STATUS_OK);
468
469 done:
470         return ret;
471 }
472
473 static bool test_lock_rw_none(struct torture_context *torture,
474                               struct smb2_tree *tree)
475 {
476         struct test_lock_read_write_state s = {
477                 .fname                  = "lock_rw_none.dat",
478                 .lock_flags             = SMB2_LOCK_FLAG_NONE,
479                 .write_h1_status        = NT_STATUS_FILE_LOCK_CONFLICT,
480                 .read_h1_status         = NT_STATUS_OK,
481                 .write_h2_status        = NT_STATUS_FILE_LOCK_CONFLICT,
482                 .read_h2_status         = NT_STATUS_OK,
483         };
484
485         if (!TARGET_IS_W2K8(torture)) {
486                 torture_skip(torture, "RW-NONE tests the behavior of a "
487                              "NONE-type lock, which is the same as a SHARED "
488                              "lock but is granted due to a bug in W2K8.  If "
489                              "target is not W2K8 we skip this test.\n");
490         }
491
492         return test_lock_read_write(torture, tree, &s);
493 }
494
495 static bool test_lock_rw_shared(struct torture_context *torture,
496                                 struct smb2_tree *tree)
497 {
498         struct test_lock_read_write_state s = {
499                 .fname                  = "lock_rw_shared.dat",
500                 .lock_flags             = SMB2_LOCK_FLAG_SHARED,
501                 .write_h1_status        = NT_STATUS_FILE_LOCK_CONFLICT,
502                 .read_h1_status         = NT_STATUS_OK,
503                 .write_h2_status        = NT_STATUS_FILE_LOCK_CONFLICT,
504                 .read_h2_status         = NT_STATUS_OK,
505         };
506
507         return test_lock_read_write(torture, tree, &s);
508 }
509
510 static bool test_lock_rw_exclusive(struct torture_context *torture,
511                                    struct smb2_tree *tree)
512 {
513         struct test_lock_read_write_state s = {
514                 .fname                  = "lock_rw_exclusive.dat",
515                 .lock_flags             = SMB2_LOCK_FLAG_EXCLUSIVE,
516                 .write_h1_status        = NT_STATUS_OK,
517                 .read_h1_status         = NT_STATUS_OK,
518                 .write_h2_status        = NT_STATUS_FILE_LOCK_CONFLICT,
519                 .read_h2_status         = NT_STATUS_FILE_LOCK_CONFLICT,
520         };
521
522         return test_lock_read_write(torture, tree, &s);
523 }
524
525 static bool test_lock_auto_unlock(struct torture_context *torture,
526                                   struct smb2_tree *tree)
527 {
528         bool ret = true;
529         NTSTATUS status;
530         struct smb2_handle h;
531         uint8_t buf[200];
532         struct smb2_lock lck;
533         struct smb2_lock_element el[1];
534
535         ZERO_STRUCT(buf);
536
537         status = torture_smb2_testfile(tree, "autounlock.txt", &h);
538         CHECK_STATUS(status, NT_STATUS_OK);
539
540         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
541         CHECK_STATUS(status, NT_STATUS_OK);
542
543         ZERO_STRUCT(lck);
544         ZERO_STRUCT(el[0]);
545         lck.in.locks            = el;
546         lck.in.lock_count       = 0x0001;
547         lck.in.file.handle      = h;
548         el[0].offset            = 0;
549         el[0].length            = 1;
550         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
551                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
552         status = smb2_lock(tree, &lck);
553         CHECK_STATUS(status, NT_STATUS_OK);
554
555         status = smb2_lock(tree, &lck);
556         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
557
558         status = smb2_lock(tree, &lck);
559         if (TARGET_IS_W2K8(torture)) {
560                 CHECK_STATUS(status, NT_STATUS_OK);
561                 torture_warning(torture, "Target has \"pretty please\" bug. "
562                                 "A contending lock request on the same handle "
563                                 "unlocks the lock.\n");
564         } else {
565                 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
566         }
567
568         status = smb2_lock(tree, &lck);
569         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
570
571 done:
572         return ret;
573 }
574
575 /*
576   test different lock ranges and see if different handles conflict
577 */
578 static bool test_lock(struct torture_context *torture,
579                       struct smb2_tree *tree)
580 {
581         NTSTATUS status;
582         bool ret = true;
583         struct smb2_handle h, h2;
584         uint8_t buf[200];
585         struct smb2_lock lck;
586         struct smb2_lock_element el[2];
587
588         const char *fname = BASEDIR "\\async.txt";
589
590         status = torture_smb2_testdir(tree, BASEDIR, &h);
591         CHECK_STATUS(status, NT_STATUS_OK);
592         smb2_util_close(tree, h);
593
594         status = torture_smb2_testfile(tree, fname, &h);
595         CHECK_STATUS(status, NT_STATUS_OK);
596
597         ZERO_STRUCT(buf);
598         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
599         CHECK_STATUS(status, NT_STATUS_OK);
600
601         status = torture_smb2_testfile(tree, fname, &h2);
602         CHECK_STATUS(status, NT_STATUS_OK);
603
604         lck.in.locks            = el;
605
606         lck.in.lock_count       = 0x0001;
607         lck.in.lock_sequence    = 0x00000000;
608         lck.in.file.handle      = h;
609         el[0].reserved          = 0x00000000;
610         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
611                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
612
613         torture_comment(torture, "Trying 0/0 lock\n");
614         el[0].offset            = 0x0000000000000000;
615         el[0].length            = 0x0000000000000000;
616         status = smb2_lock(tree, &lck);
617         CHECK_STATUS(status, NT_STATUS_OK);
618         lck.in.file.handle      = h2;
619         status = smb2_lock(tree, &lck);
620         CHECK_STATUS(status, NT_STATUS_OK);
621         lck.in.file.handle      = h;
622         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
623         status = smb2_lock(tree, &lck);
624         CHECK_STATUS(status, NT_STATUS_OK);
625
626         torture_comment(torture, "Trying 0/1 lock\n");
627         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
628                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
629         el[0].offset            = 0x0000000000000000;
630         el[0].length            = 0x0000000000000001;
631         status = smb2_lock(tree, &lck);
632         CHECK_STATUS(status, NT_STATUS_OK);
633         lck.in.file.handle      = h2;
634         status = smb2_lock(tree, &lck);
635         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
636         lck.in.file.handle      = h;
637         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
638         status = smb2_lock(tree, &lck);
639         CHECK_STATUS(status, NT_STATUS_OK);
640         status = smb2_lock(tree, &lck);
641         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
642
643         torture_comment(torture, "Trying 0xEEFFFFF lock\n");
644         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
645                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
646         el[0].offset            = 0xEEFFFFFF;
647         el[0].length            = 4000;
648         status = smb2_lock(tree, &lck);
649         CHECK_STATUS(status, NT_STATUS_OK);
650         lck.in.file.handle      = h2;
651         status = smb2_lock(tree, &lck);
652         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
653         lck.in.file.handle      = h;
654         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
655         status = smb2_lock(tree, &lck);
656         CHECK_STATUS(status, NT_STATUS_OK);
657         status = smb2_lock(tree, &lck);
658         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
659
660         torture_comment(torture, "Trying 0xEF00000 lock\n");
661         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
662                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
663         el[0].offset            = 0xEF000000;
664         el[0].length            = 4000;
665         status = smb2_lock(tree, &lck);
666         CHECK_STATUS(status, NT_STATUS_OK);
667         lck.in.file.handle      = h2;
668         status = smb2_lock(tree, &lck);
669         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
670         lck.in.file.handle      = h;
671         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
672         status = smb2_lock(tree, &lck);
673         CHECK_STATUS(status, NT_STATUS_OK);
674         status = smb2_lock(tree, &lck);
675         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
676
677         torture_comment(torture, "Trying (2^63 - 1)/1\n");
678         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
679                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
680         el[0].offset            = 1;
681         el[0].offset          <<= 63;
682         el[0].offset--;
683         el[0].length            = 1;
684         status = smb2_lock(tree, &lck);
685         CHECK_STATUS(status, NT_STATUS_OK);
686         lck.in.file.handle      = h2;
687         status = smb2_lock(tree, &lck);
688         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
689         lck.in.file.handle      = h;
690         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
691         status = smb2_lock(tree, &lck);
692         CHECK_STATUS(status, NT_STATUS_OK);
693         status = smb2_lock(tree, &lck);
694         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
695
696         torture_comment(torture, "Trying 2^63/1\n");
697         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
698                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
699         el[0].offset            = 1;
700         el[0].offset          <<= 63;
701         el[0].length            = 1;
702         status = smb2_lock(tree, &lck);
703         CHECK_STATUS(status, NT_STATUS_OK);
704         lck.in.file.handle      = h2;
705         status = smb2_lock(tree, &lck);
706         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
707         lck.in.file.handle      = h;
708         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
709         status = smb2_lock(tree, &lck);
710         CHECK_STATUS(status, NT_STATUS_OK);
711         status = smb2_lock(tree, &lck);
712         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
713
714         torture_comment(torture, "Trying max/0 lock\n");
715         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
716                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
717         el[0].offset            = ~0;
718         el[0].length            = 0;
719         status = smb2_lock(tree, &lck);
720         CHECK_STATUS(status, NT_STATUS_OK);
721         lck.in.file.handle      = h2;
722         status = smb2_lock(tree, &lck);
723         CHECK_STATUS(status, NT_STATUS_OK);
724         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
725         status = smb2_lock(tree, &lck);
726         CHECK_STATUS(status, NT_STATUS_OK);
727         lck.in.file.handle      = h;
728         status = smb2_lock(tree, &lck);
729         CHECK_STATUS(status, NT_STATUS_OK);
730         status = smb2_lock(tree, &lck);
731         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
732
733         torture_comment(torture, "Trying max/1 lock\n");
734         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
735                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
736         el[0].offset            = ~0;
737         el[0].length            = 1;
738         status = smb2_lock(tree, &lck);
739         CHECK_STATUS(status, NT_STATUS_OK);
740         lck.in.file.handle      = h2;
741         status = smb2_lock(tree, &lck);
742         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
743         lck.in.file.handle      = h;
744         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
745         status = smb2_lock(tree, &lck);
746         CHECK_STATUS(status, NT_STATUS_OK);
747         status = smb2_lock(tree, &lck);
748         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
749
750         torture_comment(torture, "Trying max/2 lock\n");
751         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
752                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
753         el[0].offset            = ~0;
754         el[0].length            = 2;
755         status = smb2_lock(tree, &lck);
756         if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(torture)) {
757                 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
758         } else {
759                 CHECK_STATUS(status, NT_STATUS_OK);
760                 el[0].flags     = SMB2_LOCK_FLAG_UNLOCK;
761                 status = smb2_lock(tree, &lck);
762                 CHECK_STATUS(status, NT_STATUS_OK);
763         }
764
765         torture_comment(torture, "Trying wrong handle unlock\n");
766         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
767                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
768         el[0].offset            = 10001;
769         el[0].length            = 40002;
770         status = smb2_lock(tree, &lck);
771         CHECK_STATUS(status, NT_STATUS_OK);
772         lck.in.file.handle      = h2;
773         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
774         status = smb2_lock(tree, &lck);
775         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
776         lck.in.file.handle      = h;
777         status = smb2_lock(tree, &lck);
778         CHECK_STATUS(status, NT_STATUS_OK);
779
780 done:
781         smb2_util_close(tree, h2);
782         smb2_util_close(tree, h);
783         smb2_deltree(tree, BASEDIR);
784         return ret;
785 }
786
787 /*
788   test SMB2 LOCK async operation
789 */
790 static bool test_async(struct torture_context *torture,
791                        struct smb2_tree *tree)
792 {
793         NTSTATUS status;
794         bool ret = true;
795         struct smb2_handle h, h2;
796         uint8_t buf[200];
797         struct smb2_lock lck;
798         struct smb2_lock_element el[2];
799         struct smb2_request *req = NULL;
800
801         const char *fname = BASEDIR "\\async.txt";
802
803         status = torture_smb2_testdir(tree, BASEDIR, &h);
804         CHECK_STATUS(status, NT_STATUS_OK);
805         smb2_util_close(tree, h);
806
807         status = torture_smb2_testfile(tree, fname, &h);
808         CHECK_STATUS(status, NT_STATUS_OK);
809
810         ZERO_STRUCT(buf);
811         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
812         CHECK_STATUS(status, NT_STATUS_OK);
813
814         status = torture_smb2_testfile(tree, fname, &h2);
815         CHECK_STATUS(status, NT_STATUS_OK);
816
817         lck.in.locks            = el;
818
819         lck.in.lock_count       = 0x0001;
820         lck.in.lock_sequence    = 0x00000000;
821         lck.in.file.handle      = h;
822         el[0].offset            = 100;
823         el[0].length            = 50;
824         el[0].reserved          = 0x00000000;
825         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
826
827         torture_comment(torture, "  Acquire first lock\n");
828         status = smb2_lock(tree, &lck);
829         CHECK_STATUS(status, NT_STATUS_OK);
830
831         torture_comment(torture, "  Second lock should pend on first\n");
832         lck.in.file.handle      = h2;
833         req = smb2_lock_send(tree, &lck);
834         WAIT_FOR_ASYNC_RESPONSE(req);
835
836         torture_comment(torture, "  Unlock first lock\n");
837         lck.in.file.handle      = h;
838         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
839         status = smb2_lock(tree, &lck);
840         CHECK_STATUS(status, NT_STATUS_OK);
841
842         torture_comment(torture, "  Second lock should now succeed\n");
843         lck.in.file.handle      = h2;
844         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
845         status = smb2_lock_recv(req, &lck);
846         CHECK_STATUS(status, NT_STATUS_OK);
847
848 done:
849         smb2_util_close(tree, h2);
850         smb2_util_close(tree, h);
851         smb2_deltree(tree, BASEDIR);
852         return ret;
853 }
854
855 /*
856   test SMB2 LOCK Cancel operation
857 */
858 static bool test_cancel(struct torture_context *torture,
859                         struct smb2_tree *tree)
860 {
861         NTSTATUS status;
862         bool ret = true;
863         struct smb2_handle h, h2;
864         uint8_t buf[200];
865         struct smb2_lock lck;
866         struct smb2_lock_element el[2];
867         struct smb2_request *req = NULL;
868
869         const char *fname = BASEDIR "\\cancel.txt";
870
871         status = torture_smb2_testdir(tree, BASEDIR, &h);
872         CHECK_STATUS(status, NT_STATUS_OK);
873         smb2_util_close(tree, h);
874
875         status = torture_smb2_testfile(tree, fname, &h);
876         CHECK_STATUS(status, NT_STATUS_OK);
877
878         ZERO_STRUCT(buf);
879         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
880         CHECK_STATUS(status, NT_STATUS_OK);
881
882         status = torture_smb2_testfile(tree, fname, &h2);
883         CHECK_STATUS(status, NT_STATUS_OK);
884
885         lck.in.locks            = el;
886
887         lck.in.lock_count       = 0x0001;
888         lck.in.lock_sequence    = 0x00000000;
889         lck.in.file.handle      = h;
890         el[0].offset            = 100;
891         el[0].length            = 10;
892         el[0].reserved          = 0x00000000;
893         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
894
895         torture_comment(torture, "Testing basic cancel\n");
896
897         torture_comment(torture, "  Acquire first lock\n");
898         status = smb2_lock(tree, &lck);
899         CHECK_STATUS(status, NT_STATUS_OK);
900
901         torture_comment(torture, "  Second lock should pend on first\n");
902         lck.in.file.handle      = h2;
903         req = smb2_lock_send(tree, &lck);
904         WAIT_FOR_ASYNC_RESPONSE(req);
905
906         torture_comment(torture, "  Cancel the second lock\n");
907         smb2_cancel(req);
908         lck.in.file.handle      = h2;
909         status = smb2_lock_recv(req, &lck);
910         CHECK_STATUS(status, NT_STATUS_CANCELLED);
911
912         torture_comment(torture, "  Unlock first lock\n");
913         lck.in.file.handle      = h;
914         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
915         status = smb2_lock(tree, &lck);
916         CHECK_STATUS(status, NT_STATUS_OK);
917
918
919         torture_comment(torture, "Testing cancel by unlock\n");
920
921         torture_comment(torture, "  Acquire first lock\n");
922         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
923         status = smb2_lock(tree, &lck);
924         CHECK_STATUS(status, NT_STATUS_OK);
925
926         torture_comment(torture, "  Second lock should pend on first\n");
927         lck.in.file.handle      = h2;
928         req = smb2_lock_send(tree, &lck);
929         WAIT_FOR_ASYNC_RESPONSE(req);
930
931         torture_comment(torture, "  Attempt to unlock pending second lock\n");
932         lck.in.file.handle      = h2;
933         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
934         status = smb2_lock(tree, &lck);
935         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
936
937         torture_comment(torture, "  Now cancel the second lock\n");
938         smb2_cancel(req);
939         lck.in.file.handle      = h2;
940         status = smb2_lock_recv(req, &lck);
941         CHECK_STATUS(status, NT_STATUS_CANCELLED);
942
943         torture_comment(torture, "  Unlock first lock\n");
944         lck.in.file.handle      = h;
945         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
946         status = smb2_lock(tree, &lck);
947         CHECK_STATUS(status, NT_STATUS_OK);
948
949
950         torture_comment(torture, "Testing cancel by close\n");
951
952         torture_comment(torture, "  Acquire first lock\n");
953         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
954         status = smb2_lock(tree, &lck);
955         CHECK_STATUS(status, NT_STATUS_OK);
956
957         torture_comment(torture, "  Second lock should pend on first\n");
958         lck.in.file.handle      = h2;
959         req = smb2_lock_send(tree, &lck);
960         WAIT_FOR_ASYNC_RESPONSE(req);
961
962         torture_comment(torture, "  Close the second lock handle\n");
963         smb2_util_close(tree, h2);
964         CHECK_STATUS(status, NT_STATUS_OK);
965
966         torture_comment(torture, "  Check pending lock reply\n");
967         status = smb2_lock_recv(req, &lck);
968         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
969
970         torture_comment(torture, "  Unlock first lock\n");
971         lck.in.file.handle      = h;
972         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
973         status = smb2_lock(tree, &lck);
974         CHECK_STATUS(status, NT_STATUS_OK);
975
976 done:
977         smb2_util_close(tree, h2);
978         smb2_util_close(tree, h);
979         smb2_deltree(tree, BASEDIR);
980         return ret;
981 }
982
983 /*
984   test SMB2 LOCK Cancel by tree disconnect
985 */
986 static bool test_cancel_tdis(struct torture_context *torture,
987                              struct smb2_tree *tree)
988 {
989         NTSTATUS status;
990         bool ret = true;
991         struct smb2_handle h, h2;
992         uint8_t buf[200];
993         struct smb2_lock lck;
994         struct smb2_lock_element el[2];
995         struct smb2_request *req = NULL;
996
997         const char *fname = BASEDIR "\\cancel_tdis.txt";
998
999         status = torture_smb2_testdir(tree, BASEDIR, &h);
1000         CHECK_STATUS(status, NT_STATUS_OK);
1001         smb2_util_close(tree, h);
1002
1003         status = torture_smb2_testfile(tree, fname, &h);
1004         CHECK_STATUS(status, NT_STATUS_OK);
1005
1006         ZERO_STRUCT(buf);
1007         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1008         CHECK_STATUS(status, NT_STATUS_OK);
1009
1010         status = torture_smb2_testfile(tree, fname, &h2);
1011         CHECK_STATUS(status, NT_STATUS_OK);
1012
1013         lck.in.locks            = el;
1014
1015         lck.in.lock_count       = 0x0001;
1016         lck.in.lock_sequence    = 0x00000000;
1017         lck.in.file.handle      = h;
1018         el[0].offset            = 100;
1019         el[0].length            = 10;
1020         el[0].reserved          = 0x00000000;
1021         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
1022
1023         torture_comment(torture, "Testing cancel by tree disconnect\n");
1024
1025         status = torture_smb2_testfile(tree, fname, &h);
1026         CHECK_STATUS(status, NT_STATUS_OK);
1027
1028         status = torture_smb2_testfile(tree, fname, &h2);
1029         CHECK_STATUS(status, NT_STATUS_OK);
1030
1031         torture_comment(torture, "  Acquire first lock\n");
1032         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
1033         status = smb2_lock(tree, &lck);
1034         CHECK_STATUS(status, NT_STATUS_OK);
1035
1036         torture_comment(torture, "  Second lock should pend on first\n");
1037         lck.in.file.handle      = h2;
1038         req = smb2_lock_send(tree, &lck);
1039         WAIT_FOR_ASYNC_RESPONSE(req);
1040
1041         torture_comment(torture, "  Disconnect the tree\n");
1042         smb2_tdis(tree);
1043         CHECK_STATUS(status, NT_STATUS_OK);
1044
1045         torture_comment(torture, "  Check pending lock reply\n");
1046         status = smb2_lock_recv(req, &lck);
1047         if (torture_setting_bool(torture, "samba4", false)) {
1048                 /* saying that this lock succeeded is nonsense - the
1049                  * tree is gone!! */
1050                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1051         } else {
1052                 CHECK_STATUS(status, NT_STATUS_OK);
1053         }
1054
1055         torture_comment(torture, "  Attempt to unlock first lock\n");
1056         lck.in.file.handle      = h;
1057         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1058         status = smb2_lock(tree, &lck);
1059         if (torture_setting_bool(torture, "samba4", false)) {
1060                 /* checking if the tcon supplied are still valid
1061                  * should happen before you validate a file handle,
1062                  * so we should return USER_SESSION_DELETED */
1063                 CHECK_STATUS(status, NT_STATUS_NETWORK_NAME_DELETED);
1064         } else {
1065                 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
1066         }
1067
1068 done:
1069         smb2_util_close(tree, h2);
1070         smb2_util_close(tree, h);
1071         smb2_deltree(tree, BASEDIR);
1072         return ret;
1073 }
1074
1075 /*
1076   test SMB2 LOCK Cancel by user logoff
1077 */
1078 static bool test_cancel_logoff(struct torture_context *torture,
1079                                struct smb2_tree *tree)
1080 {
1081         NTSTATUS status;
1082         bool ret = true;
1083         struct smb2_handle h, h2;
1084         uint8_t buf[200];
1085         struct smb2_lock lck;
1086         struct smb2_lock_element el[2];
1087         struct smb2_request *req = NULL;
1088
1089         const char *fname = BASEDIR "\\cancel_tdis.txt";
1090
1091         status = torture_smb2_testdir(tree, BASEDIR, &h);
1092         CHECK_STATUS(status, NT_STATUS_OK);
1093         smb2_util_close(tree, h);
1094
1095         status = torture_smb2_testfile(tree, fname, &h);
1096         CHECK_STATUS(status, NT_STATUS_OK);
1097
1098         ZERO_STRUCT(buf);
1099         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1100         CHECK_STATUS(status, NT_STATUS_OK);
1101
1102         status = torture_smb2_testfile(tree, fname, &h2);
1103         CHECK_STATUS(status, NT_STATUS_OK);
1104
1105         lck.in.locks            = el;
1106
1107         lck.in.lock_count       = 0x0001;
1108         lck.in.lock_sequence    = 0x00000000;
1109         lck.in.file.handle      = h;
1110         el[0].offset            = 100;
1111         el[0].length            = 10;
1112         el[0].reserved          = 0x00000000;
1113         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
1114
1115         torture_comment(torture, "Testing cancel by ulogoff\n");
1116
1117         torture_comment(torture, "  Acquire first lock\n");
1118         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
1119         status = smb2_lock(tree, &lck);
1120         CHECK_STATUS(status, NT_STATUS_OK);
1121
1122         torture_comment(torture, "  Second lock should pend on first\n");
1123         lck.in.file.handle      = h2;
1124         req = smb2_lock_send(tree, &lck);
1125         WAIT_FOR_ASYNC_RESPONSE(req);
1126
1127         torture_comment(torture, "  Logoff user\n");
1128         smb2_logoff(tree->session);
1129
1130         torture_comment(torture, "  Check pending lock reply\n");
1131         status = smb2_lock_recv(req, &lck);
1132         if (torture_setting_bool(torture, "samba4", false)) {
1133                 /* another bogus 'success' code from windows. The lock
1134                  * cannot have succeeded, as we are now logged off */
1135                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1136         } else {
1137                 CHECK_STATUS(status, NT_STATUS_OK);
1138         }
1139
1140         torture_comment(torture, "  Attempt to unlock first lock\n");
1141         lck.in.file.handle      = h;
1142         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1143         status = smb2_lock(tree, &lck);
1144         if (torture_setting_bool(torture, "samba4", false)) {
1145                 /* checking if the credential supplied are still valid
1146                  * should happen before you validate a file handle,
1147                  * so we should return USER_SESSION_DELETED */
1148                 CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
1149         } else {
1150                 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
1151         }
1152
1153 done:
1154         smb2_util_close(tree, h2);
1155         smb2_util_close(tree, h);
1156         smb2_deltree(tree, BASEDIR);
1157         return ret;
1158 }
1159
1160 /*
1161  * Test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
1162  *
1163  * The SMBv1 protocol returns a different error code on lock acquisition
1164  * failure depending on a number of parameters, including what error code
1165  * was returned to the previous failure.
1166  *
1167  * SMBv2 has cleaned up these semantics and should always return
1168  * NT_STATUS_LOCK_NOT_GRANTED to failed lock requests, and
1169  * NT_STATUS_FILE_LOCK_CONFLICT to failed read/write requests due to a lock
1170  * being held on that range.
1171 */
1172 static bool test_errorcode(struct torture_context *torture,
1173                            struct smb2_tree *tree)
1174 {
1175         NTSTATUS status;
1176         bool ret = true;
1177         struct smb2_handle h, h2;
1178         uint8_t buf[200];
1179         struct smb2_lock lck;
1180         struct smb2_lock_element el[2];
1181
1182         const char *fname = BASEDIR "\\errorcode.txt";
1183
1184         status = torture_smb2_testdir(tree, BASEDIR, &h);
1185         CHECK_STATUS(status, NT_STATUS_OK);
1186         smb2_util_close(tree, h);
1187
1188         status = torture_smb2_testfile(tree, fname, &h);
1189         CHECK_STATUS(status, NT_STATUS_OK);
1190
1191         ZERO_STRUCT(buf);
1192         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1193         CHECK_STATUS(status, NT_STATUS_OK);
1194
1195         status = torture_smb2_testfile(tree, fname, &h2);
1196         CHECK_STATUS(status, NT_STATUS_OK);
1197
1198         lck.in.locks            = el;
1199
1200         lck.in.lock_count       = 0x0001;
1201         lck.in.lock_sequence    = 0x00000000;
1202         lck.in.file.handle      = h;
1203         el[0].offset            = 100;
1204         el[0].length            = 10;
1205         el[0].reserved          = 0x00000000;
1206         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1207                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1208
1209         torture_comment(torture, "Testing LOCK_NOT_GRANTED vs. "
1210                                  "FILE_LOCK_CONFLICT\n");
1211
1212         if (TARGET_IS_W2K8(torture)) {
1213                 torture_result(torture, TORTURE_SKIP,
1214                     "Target has \"pretty please\" bug. A contending lock "
1215                     "request on the same handle unlocks the lock.");
1216                 goto done;
1217         }
1218
1219         status = smb2_lock(tree, &lck);
1220         CHECK_STATUS(status, NT_STATUS_OK);
1221
1222         /* Demonstrate that the first conflicting lock on each handle gives
1223          * LOCK_NOT_GRANTED. */
1224         lck.in.file.handle      = h;
1225         status = smb2_lock(tree, &lck);
1226         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1227
1228         lck.in.file.handle      = h2;
1229         status = smb2_lock(tree, &lck);
1230         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1231
1232         /* Demonstrate that each following conflict also gives
1233          * LOCK_NOT_GRANTED */
1234         lck.in.file.handle      = h;
1235         status = smb2_lock(tree, &lck);
1236         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1237
1238         lck.in.file.handle      = h2;
1239         status = smb2_lock(tree, &lck);
1240         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1241
1242         lck.in.file.handle      = h;
1243         status = smb2_lock(tree, &lck);
1244         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1245
1246         lck.in.file.handle      = h2;
1247         status = smb2_lock(tree, &lck);
1248         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1249
1250         /* Demonstrate that the smbpid doesn't matter */
1251         tree->session->pid++;
1252         lck.in.file.handle      = h;
1253         status = smb2_lock(tree, &lck);
1254         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1255
1256         lck.in.file.handle      = h2;
1257         status = smb2_lock(tree, &lck);
1258         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1259         tree->session->pid--;
1260
1261         /* Demonstrate that a 0-byte lock inside the locked range still
1262          * gives the same error. */
1263
1264         el[0].offset            = 102;
1265         el[0].length            = 0;
1266         lck.in.file.handle      = h;
1267         status = smb2_lock(tree, &lck);
1268         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1269
1270         lck.in.file.handle      = h2;
1271         status = smb2_lock(tree, &lck);
1272         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1273
1274         /* Demonstrate that a lock inside the locked range still gives the
1275          * same error. */
1276
1277         el[0].offset            = 102;
1278         el[0].length            = 5;
1279         lck.in.file.handle      = h;
1280         status = smb2_lock(tree, &lck);
1281         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1282
1283         lck.in.file.handle      = h2;
1284         status = smb2_lock(tree, &lck);
1285         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1286
1287 done:
1288         smb2_util_close(tree, h2);
1289         smb2_util_close(tree, h);
1290         smb2_deltree(tree, BASEDIR);
1291         return ret;
1292 }
1293
1294 /**
1295  * Tests zero byte locks.
1296  */
1297
1298 struct double_lock_test {
1299         struct smb2_lock_element lock1;
1300         struct smb2_lock_element lock2;
1301         NTSTATUS status;
1302 };
1303
1304 static struct double_lock_test zero_byte_tests[] = {
1305         /* {offset, count, reserved, flags},
1306          * {offset, count, reserved, flags},
1307          * status */
1308
1309         /** First, takes a zero byte lock at offset 10. Then:
1310         *   - Taking 0 byte lock at 10 should succeed.
1311         *   - Taking 1 byte locks at 9,10,11 should succeed.
1312         *   - Taking 2 byte lock at 9 should fail.
1313         *   - Taking 2 byte lock at 10 should succeed.
1314         *   - Taking 3 byte lock at 9 should fail.
1315         */
1316         {{10, 0, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1317         {{10, 0, 0, 0}, {9, 1, 0, 0},  NT_STATUS_OK},
1318         {{10, 0, 0, 0}, {10, 1, 0, 0}, NT_STATUS_OK},
1319         {{10, 0, 0, 0}, {11, 1, 0, 0}, NT_STATUS_OK},
1320         {{10, 0, 0, 0}, {9, 2, 0, 0},  NT_STATUS_LOCK_NOT_GRANTED},
1321         {{10, 0, 0, 0}, {10, 2, 0, 0}, NT_STATUS_OK},
1322         {{10, 0, 0, 0}, {9, 3, 0, 0},  NT_STATUS_LOCK_NOT_GRANTED},
1323
1324         /** Same, but opposite order. */
1325         {{10, 0, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1326         {{9, 1, 0, 0},  {10, 0, 0, 0}, NT_STATUS_OK},
1327         {{10, 1, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1328         {{11, 1, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1329         {{9, 2, 0, 0},  {10, 0, 0, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1330         {{10, 2, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1331         {{9, 3, 0, 0},  {10, 0, 0, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1332
1333         /** Zero zero case. */
1334         {{0, 0, 0, 0},  {0, 0, 0, 0},  NT_STATUS_OK},
1335 };
1336
1337 static bool test_zerobytelength(struct torture_context *torture,
1338                                 struct smb2_tree *tree)
1339 {
1340         NTSTATUS status;
1341         bool ret = true;
1342         struct smb2_handle h, h2;
1343         uint8_t buf[200];
1344         struct smb2_lock lck;
1345         int i;
1346
1347         const char *fname = BASEDIR "\\zero.txt";
1348
1349         torture_comment(torture, "Testing zero length byte range locks:\n");
1350
1351         status = torture_smb2_testdir(tree, BASEDIR, &h);
1352         CHECK_STATUS(status, NT_STATUS_OK);
1353         smb2_util_close(tree, h);
1354
1355         status = torture_smb2_testfile(tree, fname, &h);
1356         CHECK_STATUS(status, NT_STATUS_OK);
1357
1358         ZERO_STRUCT(buf);
1359         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1360         CHECK_STATUS(status, NT_STATUS_OK);
1361
1362         status = torture_smb2_testfile(tree, fname, &h2);
1363         CHECK_STATUS(status, NT_STATUS_OK);
1364
1365         /* Setup initial parameters */
1366         lck.in.lock_count       = 0x0001;
1367         lck.in.lock_sequence    = 0x00000000;
1368         lck.in.file.handle      = h;
1369
1370         /* Try every combination of locks in zero_byte_tests, using the same
1371          * handle for both locks. The first lock is assumed to succeed. The
1372          * second lock may contend, depending on the expected status. */
1373         for (i = 0; i < ARRAY_SIZE(zero_byte_tests); i++) {
1374                 torture_comment(torture,
1375                     "  ... {%llu, %llu} + {%llu, %llu} = %s\n",
1376                     (unsigned long long) zero_byte_tests[i].lock1.offset,
1377                     (unsigned long long) zero_byte_tests[i].lock1.length,
1378                     (unsigned long long) zero_byte_tests[i].lock2.offset,
1379                     (unsigned long long) zero_byte_tests[i].lock2.length,
1380                     nt_errstr(zero_byte_tests[i].status));
1381
1382                 /* Lock both locks. */
1383                 lck.in.locks            = &zero_byte_tests[i].lock1;
1384                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_EXCLUSIVE |
1385                                           SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1386                 status = smb2_lock(tree, &lck);
1387                 CHECK_STATUS(status, NT_STATUS_OK);
1388
1389                 lck.in.locks            = &zero_byte_tests[i].lock2;
1390                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_EXCLUSIVE |
1391                                           SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1392                 status = smb2_lock(tree, &lck);
1393                 CHECK_STATUS_CONT(status, zero_byte_tests[i].status);
1394
1395                 /* Unlock both locks in reverse order. */
1396                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_UNLOCK;
1397                 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1398                         status = smb2_lock(tree, &lck);
1399                         CHECK_STATUS(status, NT_STATUS_OK);
1400                 }
1401
1402                 lck.in.locks            = &zero_byte_tests[i].lock1;
1403                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_UNLOCK;
1404                 status = smb2_lock(tree, &lck);
1405                 CHECK_STATUS(status, NT_STATUS_OK);
1406         }
1407
1408         /* Try every combination of locks in zero_byte_tests, using two
1409          * different handles. */
1410         for (i = 0; i < ARRAY_SIZE(zero_byte_tests); i++) {
1411                 torture_comment(torture,
1412                     "  ... {%llu, %llu} + {%llu, %llu} = %s\n",
1413                     (unsigned long long) zero_byte_tests[i].lock1.offset,
1414                     (unsigned long long) zero_byte_tests[i].lock1.length,
1415                     (unsigned long long) zero_byte_tests[i].lock2.offset,
1416                     (unsigned long long) zero_byte_tests[i].lock2.length,
1417                     nt_errstr(zero_byte_tests[i].status));
1418
1419                 /* Lock both locks. */
1420                 lck.in.file.handle      = h;
1421                 lck.in.locks            = &zero_byte_tests[i].lock1;
1422                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_EXCLUSIVE |
1423                                           SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1424                 status = smb2_lock(tree, &lck);
1425                 CHECK_STATUS(status, NT_STATUS_OK);
1426
1427                 lck.in.file.handle      = h2;
1428                 lck.in.locks            = &zero_byte_tests[i].lock2;
1429                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_EXCLUSIVE |
1430                                           SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1431                 status = smb2_lock(tree, &lck);
1432                 CHECK_STATUS_CONT(status, zero_byte_tests[i].status);
1433
1434                 /* Unlock both locks in reverse order. */
1435                 lck.in.file.handle      = h2;
1436                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_UNLOCK;
1437                 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1438                         status = smb2_lock(tree, &lck);
1439                         CHECK_STATUS(status, NT_STATUS_OK);
1440                 }
1441
1442                 lck.in.file.handle      = h;
1443                 lck.in.locks            = &zero_byte_tests[i].lock1;
1444                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_UNLOCK;
1445                 status = smb2_lock(tree, &lck);
1446                 CHECK_STATUS(status, NT_STATUS_OK);
1447         }
1448
1449 done:
1450         smb2_util_close(tree, h2);
1451         smb2_util_close(tree, h);
1452         smb2_deltree(tree, BASEDIR);
1453         return ret;
1454 }
1455
1456 static bool test_zerobyteread(struct torture_context *torture,
1457                               struct smb2_tree *tree)
1458 {
1459         NTSTATUS status;
1460         bool ret = true;
1461         struct smb2_handle h, h2;
1462         uint8_t buf[200];
1463         struct smb2_lock lck;
1464         struct smb2_lock_element el[1];
1465         struct smb2_read rd;
1466
1467         const char *fname = BASEDIR "\\zerobyteread.txt";
1468
1469         status = torture_smb2_testdir(tree, BASEDIR, &h);
1470         CHECK_STATUS(status, NT_STATUS_OK);
1471         smb2_util_close(tree, h);
1472
1473         status = torture_smb2_testfile(tree, fname, &h);
1474         CHECK_STATUS(status, NT_STATUS_OK);
1475
1476         ZERO_STRUCT(buf);
1477         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1478         CHECK_STATUS(status, NT_STATUS_OK);
1479
1480         status = torture_smb2_testfile(tree, fname, &h2);
1481         CHECK_STATUS(status, NT_STATUS_OK);
1482
1483         /* Setup initial parameters */
1484         lck.in.locks            = el;
1485         lck.in.lock_count       = 0x0001;
1486         lck.in.lock_sequence    = 0x00000000;
1487         lck.in.file.handle      = h;
1488
1489         ZERO_STRUCT(rd);
1490         rd.in.file.handle = h2;
1491
1492         torture_comment(torture, "Testing zero byte read on lock range:\n");
1493
1494         /* Take an exclusive lock */
1495         torture_comment(torture, "  taking exclusive lock.\n");
1496         el[0].offset            = 0;
1497         el[0].length            = 10;
1498         el[0].reserved          = 0x00000000;
1499         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1500                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1501         status = smb2_lock(tree, &lck);
1502         CHECK_STATUS(status, NT_STATUS_OK);
1503         CHECK_VALUE(lck.out.reserved, 0);
1504
1505         /* Try a zero byte read */
1506         torture_comment(torture, "  reading 0 bytes.\n");
1507         rd.in.offset      = 5;
1508         rd.in.length      = 0;
1509         status = smb2_read(tree, tree, &rd);
1510         torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done,
1511                                       "zero byte read did not return 0 bytes");
1512         CHECK_STATUS(status, NT_STATUS_OK);
1513
1514         /* Unlock lock */
1515         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1516         status = smb2_lock(tree, &lck);
1517         CHECK_STATUS(status, NT_STATUS_OK);
1518         CHECK_VALUE(lck.out.reserved, 0);
1519
1520         torture_comment(torture, "Testing zero byte read on zero byte lock "
1521                                  "range:\n");
1522
1523         /* Take an exclusive lock */
1524         torture_comment(torture, "  taking exclusive 0-byte lock.\n");
1525         el[0].offset            = 5;
1526         el[0].length            = 0;
1527         el[0].reserved          = 0x00000000;
1528         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1529                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1530         status = smb2_lock(tree, &lck);
1531         CHECK_STATUS(status, NT_STATUS_OK);
1532         CHECK_VALUE(lck.out.reserved, 0);
1533
1534         /* Try a zero byte read before the lock */
1535         torture_comment(torture, "  reading 0 bytes before the lock.\n");
1536         rd.in.offset      = 4;
1537         rd.in.length      = 0;
1538         status = smb2_read(tree, tree, &rd);
1539         torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done,
1540                                       "zero byte read did not return 0 bytes");
1541         CHECK_STATUS(status, NT_STATUS_OK);
1542
1543         /* Try a zero byte read on the lock */
1544         torture_comment(torture, "  reading 0 bytes on the lock.\n");
1545         rd.in.offset      = 5;
1546         rd.in.length      = 0;
1547         status = smb2_read(tree, tree, &rd);
1548         torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done,
1549                                       "zero byte read did not return 0 bytes");
1550         CHECK_STATUS(status, NT_STATUS_OK);
1551
1552         /* Try a zero byte read after the lock */
1553         torture_comment(torture, "  reading 0 bytes after the lock.\n");
1554         rd.in.offset      = 6;
1555         rd.in.length      = 0;
1556         status = smb2_read(tree, tree, &rd);
1557         torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done,
1558                                       "zero byte read did not return 0 bytes");
1559         CHECK_STATUS(status, NT_STATUS_OK);
1560
1561         /* Unlock lock */
1562         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1563         status = smb2_lock(tree, &lck);
1564         CHECK_STATUS(status, NT_STATUS_OK);
1565         CHECK_VALUE(lck.out.reserved, 0);
1566
1567 done:
1568         smb2_util_close(tree, h2);
1569         smb2_util_close(tree, h);
1570         smb2_deltree(tree, BASEDIR);
1571         return ret;
1572 }
1573
1574 static bool test_unlock(struct torture_context *torture,
1575                         struct smb2_tree *tree)
1576 {
1577         NTSTATUS status;
1578         bool ret = true;
1579         struct smb2_handle h, h2;
1580         uint8_t buf[200];
1581         struct smb2_lock lck;
1582         struct smb2_lock_element el1[1];
1583         struct smb2_lock_element el2[1];
1584
1585         const char *fname = BASEDIR "\\unlock.txt";
1586
1587         status = torture_smb2_testdir(tree, BASEDIR, &h);
1588         CHECK_STATUS(status, NT_STATUS_OK);
1589         smb2_util_close(tree, h);
1590
1591         status = torture_smb2_testfile(tree, fname, &h);
1592         CHECK_STATUS(status, NT_STATUS_OK);
1593
1594         ZERO_STRUCT(buf);
1595         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1596         CHECK_STATUS(status, NT_STATUS_OK);
1597
1598         status = torture_smb2_testfile(tree, fname, &h2);
1599         CHECK_STATUS(status, NT_STATUS_OK);
1600
1601         /* Setup initial parameters */
1602         lck.in.locks            = el1;
1603         lck.in.lock_count       = 0x0001;
1604         lck.in.lock_sequence    = 0x00000000;
1605         el1[0].offset           = 0;
1606         el1[0].length           = 10;
1607         el1[0].reserved         = 0x00000000;
1608
1609         /* Take exclusive lock, then unlock it with a shared-unlock call. */
1610
1611         torture_comment(torture, "Testing unlock exclusive with shared\n");
1612
1613         torture_comment(torture, "  taking exclusive lock.\n");
1614         lck.in.file.handle      = h;
1615         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE;
1616         status = smb2_lock(tree, &lck);
1617         CHECK_STATUS(status, NT_STATUS_OK);
1618
1619         torture_comment(torture, "  try to unlock the exclusive with a shared "
1620                                  "unlock call.\n");
1621         el1[0].flags            = SMB2_LOCK_FLAG_SHARED |
1622                                   SMB2_LOCK_FLAG_UNLOCK;
1623         status = smb2_lock(tree, &lck);
1624         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1625
1626         torture_comment(torture, "  try shared lock on h2, to test the "
1627                                  "unlock.\n");
1628         lck.in.file.handle      = h2;
1629         el1[0].flags            = SMB2_LOCK_FLAG_SHARED |
1630                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1631         status = smb2_lock(tree, &lck);
1632         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1633
1634         torture_comment(torture, "  unlock the exclusive lock\n");
1635         lck.in.file.handle      = h;
1636         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1637         status = smb2_lock(tree, &lck);
1638         CHECK_STATUS(status, NT_STATUS_OK);
1639
1640         /* Unlock a shared lock with an exclusive-unlock call. */
1641
1642         torture_comment(torture, "Testing unlock shared with exclusive\n");
1643
1644         torture_comment(torture, "  taking shared lock.\n");
1645         lck.in.file.handle      = h;
1646         el1[0].flags            = SMB2_LOCK_FLAG_SHARED;
1647         status = smb2_lock(tree, &lck);
1648         CHECK_STATUS(status, NT_STATUS_OK);
1649
1650         torture_comment(torture, "  try to unlock the shared with an exclusive "
1651                                  "unlock call.\n");
1652         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1653                                   SMB2_LOCK_FLAG_UNLOCK;
1654         status = smb2_lock(tree, &lck);
1655         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1656
1657         torture_comment(torture, "  try exclusive lock on h2, to test the "
1658                                  "unlock.\n");
1659         lck.in.file.handle      = h2;
1660         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1661                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1662         status = smb2_lock(tree, &lck);
1663         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1664
1665         torture_comment(torture, "  unlock the exclusive lock\n");
1666         lck.in.file.handle      = h;
1667         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1668         status = smb2_lock(tree, &lck);
1669         CHECK_STATUS(status, NT_STATUS_OK);
1670
1671         /* Test unlocking of stacked 0-byte locks. SMB2 0-byte lock behavior
1672          * should be the same as >0-byte behavior.  Exclusive locks should be
1673          * unlocked before shared. */
1674
1675         torture_comment(torture, "Test unlocking stacked 0-byte locks\n");
1676
1677         lck.in.locks            = el1;
1678         lck.in.file.handle      = h;
1679         el1[0].offset           = 10;
1680         el1[0].length           = 0;
1681         el1[0].reserved         = 0x00000000;
1682         el2[0].offset           = 5;
1683         el2[0].length           = 10;
1684         el2[0].reserved         = 0x00000000;
1685
1686         /* lock 0-byte exclusive */
1687         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1688                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1689         status = smb2_lock(tree, &lck);
1690         CHECK_STATUS(status, NT_STATUS_OK);
1691
1692         /* lock 0-byte shared */
1693         el1[0].flags            = SMB2_LOCK_FLAG_SHARED |
1694                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1695         status = smb2_lock(tree, &lck);
1696         CHECK_STATUS(status, NT_STATUS_OK);
1697
1698         /* test contention */
1699         lck.in.locks            = el2;
1700         lck.in.file.handle      = h2;
1701         el2[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1702                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1703         status = smb2_lock(tree, &lck);
1704         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1705
1706         lck.in.locks            = el2;
1707         lck.in.file.handle      = h2;
1708         el2[0].flags            = SMB2_LOCK_FLAG_SHARED |
1709                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1710         status = smb2_lock(tree, &lck);
1711         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1712
1713         /* unlock */
1714         lck.in.locks            = el1;
1715         lck.in.file.handle      = h;
1716         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1717         status = smb2_lock(tree, &lck);
1718         CHECK_STATUS(status, NT_STATUS_OK);
1719
1720         /* test - can we take a shared lock? */
1721         lck.in.locks            = el2;
1722         lck.in.file.handle      = h2;
1723         el2[0].flags            = SMB2_LOCK_FLAG_SHARED |
1724                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1725         status = smb2_lock(tree, &lck);
1726         CHECK_STATUS(status, NT_STATUS_OK);
1727
1728         el2[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1729         status = smb2_lock(tree, &lck);
1730         CHECK_STATUS(status, NT_STATUS_OK);
1731
1732         /* cleanup */
1733         lck.in.locks            = el1;
1734         lck.in.file.handle      = h;
1735         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1736         status = smb2_lock(tree, &lck);
1737         CHECK_STATUS(status, NT_STATUS_OK);
1738
1739         /* Test unlocking of stacked exclusive, shared locks. Exclusive
1740          * should be unlocked before any shared. */
1741
1742         torture_comment(torture, "Test unlocking stacked exclusive/shared "
1743                                  "locks\n");
1744
1745         lck.in.locks            = el1;
1746         lck.in.file.handle      = h;
1747         el1[0].offset           = 10;
1748         el1[0].length           = 10;
1749         el1[0].reserved         = 0x00000000;
1750         el2[0].offset           = 5;
1751         el2[0].length           = 10;
1752         el2[0].reserved         = 0x00000000;
1753
1754         /* lock exclusive */
1755         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1756                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1757         status = smb2_lock(tree, &lck);
1758         CHECK_STATUS(status, NT_STATUS_OK);
1759
1760         /* lock shared */
1761         el1[0].flags            = SMB2_LOCK_FLAG_SHARED |
1762                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1763         status = smb2_lock(tree, &lck);
1764         CHECK_STATUS(status, NT_STATUS_OK);
1765
1766         /* test contention */
1767         lck.in.locks            = el2;
1768         lck.in.file.handle      = h2;
1769         el2[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1770                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1771         status = smb2_lock(tree, &lck);
1772         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1773
1774         lck.in.locks            = el2;
1775         lck.in.file.handle      = h2;
1776         el2[0].flags            = SMB2_LOCK_FLAG_SHARED |
1777                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1778         status = smb2_lock(tree, &lck);
1779         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1780
1781         /* unlock */
1782         lck.in.locks            = el1;
1783         lck.in.file.handle      = h;
1784         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1785         status = smb2_lock(tree, &lck);
1786         CHECK_STATUS(status, NT_STATUS_OK);
1787
1788         /* test - can we take a shared lock? */
1789         lck.in.locks            = el2;
1790         lck.in.file.handle      = h2;
1791         el2[0].flags            = SMB2_LOCK_FLAG_SHARED |
1792                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1793         status = smb2_lock(tree, &lck);
1794         CHECK_STATUS(status, NT_STATUS_OK);
1795
1796         el2[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1797         status = smb2_lock(tree, &lck);
1798         CHECK_STATUS(status, NT_STATUS_OK);
1799
1800         /* cleanup */
1801         lck.in.locks            = el1;
1802         lck.in.file.handle      = h;
1803         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1804         status = smb2_lock(tree, &lck);
1805         CHECK_STATUS(status, NT_STATUS_OK);
1806
1807 done:
1808         smb2_util_close(tree, h2);
1809         smb2_util_close(tree, h);
1810         smb2_deltree(tree, BASEDIR);
1811         return ret;
1812 }
1813
1814 static bool test_multiple_unlock(struct torture_context *torture,
1815                                  struct smb2_tree *tree)
1816 {
1817         NTSTATUS status;
1818         bool ret = true;
1819         struct smb2_handle h;
1820         uint8_t buf[200];
1821         struct smb2_lock lck;
1822         struct smb2_lock_element el[2];
1823
1824         const char *fname = BASEDIR "\\unlock_multiple.txt";
1825
1826         status = torture_smb2_testdir(tree, BASEDIR, &h);
1827         CHECK_STATUS(status, NT_STATUS_OK);
1828         smb2_util_close(tree, h);
1829
1830         status = torture_smb2_testfile(tree, fname, &h);
1831         CHECK_STATUS(status, NT_STATUS_OK);
1832
1833         ZERO_STRUCT(buf);
1834         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1835         CHECK_STATUS(status, NT_STATUS_OK);
1836
1837         torture_comment(torture, "Testing multiple unlocks:\n");
1838
1839         /* Setup initial parameters */
1840         lck.in.lock_count       = 0x0002;
1841         lck.in.lock_sequence    = 0x00000000;
1842         lck.in.file.handle      = h;
1843         el[0].offset            = 0;
1844         el[0].length            = 10;
1845         el[0].reserved          = 0x00000000;
1846         el[1].offset            = 10;
1847         el[1].length            = 10;
1848         el[1].reserved          = 0x00000000;
1849
1850         /* Test1: Acquire second lock, but not first. */
1851         torture_comment(torture, "  unlock 2 locks, first one not locked. "
1852                                  "Expect no locks unlocked. \n");
1853
1854         lck.in.lock_count       = 0x0001;
1855         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1856                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1857         lck.in.locks            = &el[1];
1858         status = smb2_lock(tree, &lck);
1859         CHECK_STATUS(status, NT_STATUS_OK);
1860
1861         /* Try to unlock both locks */
1862         lck.in.lock_count       = 0x0002;
1863         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1864         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
1865         lck.in.locks            = el;
1866         status = smb2_lock(tree, &lck);
1867         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1868
1869         /* Second lock should not be unlocked. */
1870         lck.in.lock_count       = 0x0001;
1871         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1872                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1873         lck.in.locks            = &el[1];
1874         status = smb2_lock(tree, &lck);
1875         if (TARGET_IS_W2K8(torture)) {
1876                 CHECK_STATUS(status, NT_STATUS_OK);
1877                 torture_warning(torture, "Target has \"pretty please\" bug. "
1878                                 "A contending lock request on the same handle "
1879                                 "unlocks the lock.\n");
1880         } else {
1881                 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1882         }
1883
1884         /* cleanup */
1885         lck.in.lock_count       = 0x0001;
1886         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
1887         lck.in.locks            = &el[1];
1888         status = smb2_lock(tree, &lck);
1889         CHECK_STATUS(status, NT_STATUS_OK);
1890
1891         /* Test2: Acquire first lock, but not second. */
1892         torture_comment(torture, "  unlock 2 locks, second one not locked. "
1893                                  "Expect first lock unlocked.\n");
1894
1895         lck.in.lock_count       = 0x0001;
1896         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1897                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1898         lck.in.locks            = &el[0];
1899         status = smb2_lock(tree, &lck);
1900         CHECK_STATUS(status, NT_STATUS_OK);
1901
1902         /* Try to unlock both locks */
1903         lck.in.lock_count       = 0x0002;
1904         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1905         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
1906         lck.in.locks            = el;
1907         status = smb2_lock(tree, &lck);
1908         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1909
1910         /* First lock should be unlocked. */
1911         lck.in.lock_count       = 0x0001;
1912         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1913                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1914         lck.in.locks            = &el[0];
1915         status = smb2_lock(tree, &lck);
1916         CHECK_STATUS(status, NT_STATUS_OK);
1917
1918         /* cleanup */
1919         lck.in.lock_count       = 0x0001;
1920         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1921         lck.in.locks            = &el[0];
1922         status = smb2_lock(tree, &lck);
1923         CHECK_STATUS(status, NT_STATUS_OK);
1924
1925         /* Test3: Request 2 locks, second will contend.  What happens to the
1926          * first? */
1927         torture_comment(torture, "  request 2 locks, second one will contend. "
1928                                  "Expect both to fail.\n");
1929
1930         /* Lock the second range */
1931         lck.in.lock_count       = 0x0001;
1932         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1933                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1934         lck.in.locks            = &el[1];
1935         status = smb2_lock(tree, &lck);
1936         CHECK_STATUS(status, NT_STATUS_OK);
1937
1938         /* Request both locks */
1939         lck.in.lock_count       = 0x0002;
1940         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1941                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1942         lck.in.locks            = el;
1943         status = smb2_lock(tree, &lck);
1944         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1945
1946         /* First lock should be unlocked. */
1947         lck.in.lock_count       = 0x0001;
1948         lck.in.locks            = &el[0];
1949         status = smb2_lock(tree, &lck);
1950         CHECK_STATUS(status, NT_STATUS_OK);
1951
1952         /* cleanup */
1953         if (TARGET_IS_W2K8(torture)) {
1954                 lck.in.lock_count       = 0x0001;
1955                 el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1956                 lck.in.locks            = &el[0];
1957                 status = smb2_lock(tree, &lck);
1958                 CHECK_STATUS(status, NT_STATUS_OK);
1959                 torture_warning(torture, "Target has \"pretty please\" bug. "
1960                                 "A contending lock request on the same handle "
1961                                 "unlocks the lock.\n");
1962         } else {
1963                 lck.in.lock_count       = 0x0002;
1964                 el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1965                 el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
1966                 lck.in.locks            = el;
1967                 status = smb2_lock(tree, &lck);
1968                 CHECK_STATUS(status, NT_STATUS_OK);
1969         }
1970
1971         /* Test4: Request unlock and lock.  The lock contends, is the unlock
1972          * then relocked?  SMB2 doesn't like the lock and unlock requests in the
1973          * same packet. The unlock will succeed, but the lock will return
1974          * INVALID_PARAMETER.  This behavior is described in MS-SMB2
1975          * 3.3.5.14.1 */
1976         torture_comment(torture, "  request unlock and lock, second one will "
1977                                  "error. Expect the unlock to succeed.\n");
1978
1979         /* Lock both ranges */
1980         lck.in.lock_count       = 0x0002;
1981         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1982                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1983         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1984                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1985         lck.in.locks            = el;
1986         status = smb2_lock(tree, &lck);
1987         CHECK_STATUS(status, NT_STATUS_OK);
1988
1989         /* Attempt to unlock the first range and lock the second. The lock
1990          * request will error. */
1991         lck.in.lock_count       = 0x0002;
1992         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1993         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1994                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1995         lck.in.locks            = el;
1996         status = smb2_lock(tree, &lck);
1997         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1998
1999         /* The first lock should've been unlocked */
2000         lck.in.lock_count       = 0x0001;
2001         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2002                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2003         lck.in.locks            = &el[0];
2004         status = smb2_lock(tree, &lck);
2005         CHECK_STATUS(status, NT_STATUS_OK);
2006
2007         /* cleanup */
2008         lck.in.lock_count       = 0x0002;
2009         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2010         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
2011         lck.in.locks            = el;
2012         status = smb2_lock(tree, &lck);
2013         CHECK_STATUS(status, NT_STATUS_OK);
2014
2015         /* Test10: SMB2 only test. Request unlock and lock in same packet.
2016          * Neither contend. SMB2 doesn't like lock and unlock requests in the
2017          * same packet.  The unlock will succeed, but the lock will return
2018          * INVALID_PARAMETER. */
2019         torture_comment(torture, "  request unlock and lock.  Unlock will "
2020                                  "succeed, but lock will fail.\n");
2021
2022         /* Lock first range */
2023         lck.in.lock_count       = 0x0001;
2024         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2025                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2026         lck.in.locks            = &el[0];
2027         status = smb2_lock(tree, &lck);
2028         CHECK_STATUS(status, NT_STATUS_OK);
2029
2030         /* Attempt to unlock the first range and lock the second */
2031         lck.in.lock_count       = 0x0002;
2032         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2033         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2034                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2035         lck.in.locks            = el;
2036         status = smb2_lock(tree, &lck);
2037         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
2038
2039         /* Neither lock should still be locked */
2040         lck.in.lock_count       = 0x0002;
2041         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2042                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2043         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2044                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2045         lck.in.locks            = el;
2046         status = smb2_lock(tree, &lck);
2047         CHECK_STATUS(status, NT_STATUS_OK);
2048
2049         /* cleanup */
2050         lck.in.lock_count       = 0x0002;
2051         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2052         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
2053         lck.in.locks            = el;
2054         status = smb2_lock(tree, &lck);
2055         CHECK_STATUS(status, NT_STATUS_OK);
2056
2057         /* Test11: SMB2 only test. Request lock and unlock in same packet.
2058          * Neither contend. SMB2 doesn't like lock and unlock requests in the
2059          * same packet.  The lock will succeed, the unlock will fail with
2060          * INVALID_PARAMETER, and the lock will be unlocked before return. */
2061         torture_comment(torture, "  request lock and unlock.  Both will "
2062                                  "fail.\n");
2063
2064         /* Lock second range */
2065         lck.in.lock_count       = 0x0001;
2066         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2067                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2068         lck.in.locks            = &el[1];
2069         status = smb2_lock(tree, &lck);
2070         CHECK_STATUS(status, NT_STATUS_OK);
2071
2072         /* Attempt to lock the first range and unlock the second */
2073         lck.in.lock_count       = 0x0002;
2074         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2075                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2076         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
2077         lck.in.locks            = el;
2078         status = smb2_lock(tree, &lck);
2079         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
2080
2081         /* First range should be unlocked, second locked. */
2082         lck.in.lock_count       = 0x0001;
2083         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2084                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2085         lck.in.locks            = &el[0];
2086         status = smb2_lock(tree, &lck);
2087         CHECK_STATUS(status, NT_STATUS_OK);
2088
2089         lck.in.lock_count       = 0x0001;
2090         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2091                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2092         lck.in.locks            = &el[1];
2093         status = smb2_lock(tree, &lck);
2094         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
2095
2096         /* cleanup */
2097         if (TARGET_IS_W2K8(torture)) {
2098                 lck.in.lock_count       = 0x0001;
2099                 el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2100                 lck.in.locks            = &el[0];
2101                 status = smb2_lock(tree, &lck);
2102                 CHECK_STATUS(status, NT_STATUS_OK);
2103                 torture_warning(torture, "Target has \"pretty please\" bug. "
2104                                 "A contending lock request on the same handle "
2105                                 "unlocks the lock.\n");
2106         } else {
2107                 lck.in.lock_count       = 0x0002;
2108                 el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2109                 el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
2110                 lck.in.locks            = el;
2111                 status = smb2_lock(tree, &lck);
2112                 CHECK_STATUS(status, NT_STATUS_OK);
2113         }
2114
2115 done:
2116         smb2_util_close(tree, h);
2117         smb2_deltree(tree, BASEDIR);
2118         return ret;
2119 }
2120
2121 /**
2122  * Test lock stacking
2123  *  - some tests ported from BASE-LOCK-LOCK5
2124  */
2125 static bool test_stacking(struct torture_context *torture,
2126                           struct smb2_tree *tree)
2127 {
2128         NTSTATUS status;
2129         bool ret = true;
2130         struct smb2_handle h, h2;
2131         uint8_t buf[200];
2132         struct smb2_lock lck;
2133         struct smb2_lock_element el[1];
2134
2135         const char *fname = BASEDIR "\\stacking.txt";
2136
2137         status = torture_smb2_testdir(tree, BASEDIR, &h);
2138         CHECK_STATUS(status, NT_STATUS_OK);
2139         smb2_util_close(tree, h);
2140
2141         status = torture_smb2_testfile(tree, fname, &h);
2142         CHECK_STATUS(status, NT_STATUS_OK);
2143
2144         ZERO_STRUCT(buf);
2145         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2146         CHECK_STATUS(status, NT_STATUS_OK);
2147
2148         status = torture_smb2_testfile(tree, fname, &h2);
2149         CHECK_STATUS(status, NT_STATUS_OK);
2150
2151         torture_comment(torture, "Testing lock stacking:\n");
2152
2153         /* Setup initial parameters */
2154         lck.in.locks            = el;
2155         lck.in.lock_count       = 0x0001;
2156         lck.in.lock_sequence    = 0x00000000;
2157         lck.in.file.handle      = h;
2158         el[0].offset            = 0;
2159         el[0].length            = 10;
2160         el[0].reserved          = 0x00000000;
2161
2162         /* Try to take a shared lock, then a shared lock on same handle */
2163         torture_comment(torture, "  stacking a shared on top of a shared"
2164                                  "lock succeeds.\n");
2165
2166         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
2167                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2168         status = smb2_lock(tree, &lck);
2169         CHECK_STATUS(status, NT_STATUS_OK);
2170
2171         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
2172                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2173         status = smb2_lock(tree, &lck);
2174         CHECK_STATUS(status, NT_STATUS_OK);
2175
2176         /* cleanup */
2177         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2178         status = smb2_lock(tree, &lck);
2179         CHECK_STATUS(status, NT_STATUS_OK);
2180
2181         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2182         status = smb2_lock(tree, &lck);
2183         CHECK_STATUS(status, NT_STATUS_OK);
2184
2185
2186         /* Try to take an exclusive lock, then a shared lock on same handle */
2187         torture_comment(torture, "  stacking a shared on top of an exclusive "
2188                                  "lock succeeds.\n");
2189
2190         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2191                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2192         status = smb2_lock(tree, &lck);
2193         CHECK_STATUS(status, NT_STATUS_OK);
2194
2195         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
2196                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2197         status = smb2_lock(tree, &lck);
2198         CHECK_STATUS(status, NT_STATUS_OK);
2199
2200         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
2201                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2202         status = smb2_lock(tree, &lck);
2203         CHECK_STATUS(status, NT_STATUS_OK);
2204
2205         /* stacking a shared from a different handle should fail */
2206         lck.in.file.handle      = h2;
2207         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
2208                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2209         status = smb2_lock(tree, &lck);
2210         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
2211
2212         /* cleanup */
2213         lck.in.file.handle      = h;
2214         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2215         status = smb2_lock(tree, &lck);
2216         CHECK_STATUS(status, NT_STATUS_OK);
2217
2218         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2219         status = smb2_lock(tree, &lck);
2220         CHECK_STATUS(status, NT_STATUS_OK);
2221
2222         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2223         status = smb2_lock(tree, &lck);
2224         CHECK_STATUS(status, NT_STATUS_OK);
2225
2226         /* ensure the 4th unlock fails */
2227         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2228         status = smb2_lock(tree, &lck);
2229         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
2230
2231         /* ensure a second handle can now take an exclusive lock */
2232         lck.in.file.handle      = h2;
2233         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
2234                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2235         status = smb2_lock(tree, &lck);
2236         CHECK_STATUS(status, NT_STATUS_OK);
2237
2238         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2239         status = smb2_lock(tree, &lck);
2240         CHECK_STATUS(status, NT_STATUS_OK);
2241
2242         /* Try to take an exclusive lock, then a shared lock on a
2243          * different handle */
2244         torture_comment(torture, "  stacking a shared on top of an exclusive "
2245                                  "lock with different handles fails.\n");
2246
2247         lck.in.file.handle      = h;
2248         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2249                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2250         status = smb2_lock(tree, &lck);
2251         CHECK_STATUS(status, NT_STATUS_OK);
2252
2253         lck.in.file.handle      = h2;
2254         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
2255                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2256         status = smb2_lock(tree, &lck);
2257         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
2258
2259         /* cleanup */
2260         lck.in.file.handle      = h;
2261         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2262         status = smb2_lock(tree, &lck);
2263         CHECK_STATUS(status, NT_STATUS_OK);
2264
2265         /* Try to take a shared lock, then stack an exclusive with same
2266          * handle.  */
2267         torture_comment(torture, "  stacking an exclusive on top of a shared "
2268                                  "lock fails.\n");
2269
2270         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
2271                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2272         status = smb2_lock(tree, &lck);
2273         CHECK_STATUS(status, NT_STATUS_OK);
2274
2275         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2276                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2277         status = smb2_lock(tree, &lck);
2278         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
2279
2280         /* cleanup */
2281         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2282         status = smb2_lock(tree, &lck);
2283         if (TARGET_IS_W2K8(torture)) {
2284                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
2285                 torture_warning(torture, "Target has \"pretty please\" bug. "
2286                                 "A contending lock request on the same handle "
2287                                 "unlocks the lock.\n");
2288         } else {
2289                 CHECK_STATUS(status, NT_STATUS_OK);
2290         }
2291
2292         /* Prove that two exclusive locks do not stack on the same handle. */
2293         torture_comment(torture, "  two exclusive locks do not stack.\n");
2294
2295         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2296                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2297         status = smb2_lock(tree, &lck);
2298         CHECK_STATUS(status, NT_STATUS_OK);
2299
2300         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2301                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2302         status = smb2_lock(tree, &lck);
2303         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
2304
2305         /* cleanup */
2306         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2307         status = smb2_lock(tree, &lck);
2308         if (TARGET_IS_W2K8(torture)) {
2309                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
2310                 torture_warning(torture, "Target has \"pretty please\" bug. "
2311                                 "A contending lock request on the same handle "
2312                                 "unlocks the lock.\n");
2313         } else {
2314                 CHECK_STATUS(status, NT_STATUS_OK);
2315         }
2316
2317 done:
2318         smb2_util_close(tree, h2);
2319         smb2_util_close(tree, h);
2320         smb2_deltree(tree, BASEDIR);
2321         return ret;
2322 }
2323
2324 /**
2325  * Test lock contention
2326  * - shared lock should contend with exclusive lock on different handle
2327  */
2328 static bool test_contend(struct torture_context *torture,
2329                          struct smb2_tree *tree)
2330 {
2331         NTSTATUS status;
2332         bool ret = true;
2333         struct smb2_handle h, h2;
2334         uint8_t buf[200];
2335         struct smb2_lock lck;
2336         struct smb2_lock_element el[1];
2337
2338         const char *fname = BASEDIR "\\contend.txt";
2339
2340         status = torture_smb2_testdir(tree, BASEDIR, &h);
2341         CHECK_STATUS(status, NT_STATUS_OK);
2342         smb2_util_close(tree, h);
2343
2344         status = torture_smb2_testfile(tree, fname, &h);
2345         CHECK_STATUS(status, NT_STATUS_OK);
2346
2347         ZERO_STRUCT(buf);
2348         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2349         CHECK_STATUS(status, NT_STATUS_OK);
2350
2351         status = torture_smb2_testfile(tree, fname, &h2);
2352         CHECK_STATUS(status, NT_STATUS_OK);
2353
2354         torture_comment(torture, "Testing lock contention:\n");
2355
2356         /* Setup initial parameters */
2357         lck.in.locks            = el;
2358         lck.in.lock_count       = 0x0001;
2359         lck.in.lock_sequence    = 0x00000000;
2360         lck.in.file.handle      = h;
2361         el[0].offset            = 0;
2362         el[0].length            = 10;
2363         el[0].reserved          = 0x00000000;
2364
2365         /* Take an exclusive lock, then a shared lock on different handle */
2366         torture_comment(torture, "  shared should contend on exclusive on "
2367                                  "different handle.\n");
2368
2369         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2370                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2371         status = smb2_lock(tree, &lck);
2372         CHECK_STATUS(status, NT_STATUS_OK);
2373
2374         lck.in.file.handle      = h2;
2375         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
2376                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2377         status = smb2_lock(tree, &lck);
2378         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
2379
2380         /* cleanup */
2381         lck.in.file.handle      = h;
2382         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2383         status = smb2_lock(tree, &lck);
2384         CHECK_STATUS(status, NT_STATUS_OK);
2385
2386 done:
2387         smb2_util_close(tree, h2);
2388         smb2_util_close(tree, h);
2389         smb2_deltree(tree, BASEDIR);
2390         return ret;
2391 }
2392
2393 /**
2394  * Test locker context
2395  * - test that pid does not affect the locker context
2396  */
2397 static bool test_context(struct torture_context *torture,
2398                          struct smb2_tree *tree)
2399 {
2400         NTSTATUS status;
2401         bool ret = true;
2402         struct smb2_handle h, h2;
2403         uint8_t buf[200];
2404         struct smb2_lock lck;
2405         struct smb2_lock_element el[1];
2406
2407         const char *fname = BASEDIR "\\context.txt";
2408
2409         status = torture_smb2_testdir(tree, BASEDIR, &h);
2410         CHECK_STATUS(status, NT_STATUS_OK);
2411         smb2_util_close(tree, h);
2412
2413         status = torture_smb2_testfile(tree, fname, &h);
2414         CHECK_STATUS(status, NT_STATUS_OK);
2415
2416         ZERO_STRUCT(buf);
2417         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2418         CHECK_STATUS(status, NT_STATUS_OK);
2419
2420         status = torture_smb2_testfile(tree, fname, &h2);
2421         CHECK_STATUS(status, NT_STATUS_OK);
2422
2423         torture_comment(torture, "Testing locker context:\n");
2424
2425         /* Setup initial parameters */
2426         lck.in.locks            = el;
2427         lck.in.lock_count       = 0x0001;
2428         lck.in.lock_sequence    = 0x00000000;
2429         lck.in.file.handle      = h;
2430         el[0].offset            = 0;
2431         el[0].length            = 10;
2432         el[0].reserved          = 0x00000000;
2433
2434         /* Take an exclusive lock, then try to unlock with a different pid,
2435          * same handle.  This shows that the pid doesn't affect the locker
2436          * context in SMB2. */
2437         torture_comment(torture, "  pid shouldn't affect locker context\n");
2438
2439         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2440                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2441         status = smb2_lock(tree, &lck);
2442         CHECK_STATUS(status, NT_STATUS_OK);
2443
2444         tree->session->pid++;
2445         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2446         status = smb2_lock(tree, &lck);
2447         CHECK_STATUS(status, NT_STATUS_OK);
2448
2449         tree->session->pid--;
2450         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2451         status = smb2_lock(tree, &lck);
2452         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
2453
2454 done:
2455         smb2_util_close(tree, h2);
2456         smb2_util_close(tree, h);
2457         smb2_deltree(tree, BASEDIR);
2458         return ret;
2459 }
2460
2461 /**
2462  * Test as much of the potential lock range as possible
2463  *  - test ported from BASE-LOCK-LOCK3
2464  */
2465 static bool test_range(struct torture_context *torture,
2466                        struct smb2_tree *tree)
2467 {
2468         NTSTATUS status;
2469         bool ret = true;
2470         struct smb2_handle h, h2;
2471         uint8_t buf[200];
2472         struct smb2_lock lck;
2473         struct smb2_lock_element el[1];
2474         uint64_t offset, i;
2475         extern int torture_numops;
2476
2477         const char *fname = BASEDIR "\\range.txt";
2478
2479 #define NEXT_OFFSET offset += (~(uint64_t)0) / torture_numops
2480
2481         status = torture_smb2_testdir(tree, BASEDIR, &h);
2482         CHECK_STATUS(status, NT_STATUS_OK);
2483         smb2_util_close(tree, h);
2484
2485         status = torture_smb2_testfile(tree, fname, &h);
2486         CHECK_STATUS(status, NT_STATUS_OK);
2487
2488         ZERO_STRUCT(buf);
2489         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2490         CHECK_STATUS(status, NT_STATUS_OK);
2491
2492         status = torture_smb2_testfile(tree, fname, &h2);
2493         CHECK_STATUS(status, NT_STATUS_OK);
2494
2495         torture_comment(torture, "Testing locks spread across the 64-bit "
2496                                  "offset range\n");
2497
2498         if (TARGET_IS_W2K8(torture)) {
2499                 torture_result(torture, TORTURE_SKIP,
2500                     "Target has \"pretty please\" bug. A contending lock "
2501                     "request on the same handle unlocks the lock.");
2502                 goto done;
2503         }
2504
2505         /* Setup initial parameters */
2506         lck.in.locks            = el;
2507         lck.in.lock_count       = 0x0001;
2508         lck.in.lock_sequence    = 0x00000000;
2509         lck.in.file.handle      = h;
2510         el[0].offset            = 0;
2511         el[0].length            = 1;
2512         el[0].reserved          = 0x00000000;
2513         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2514                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2515
2516         torture_comment(torture, "  establishing %d locks\n", torture_numops);
2517
2518         for (offset=i=0; i<torture_numops; i++) {
2519                 NEXT_OFFSET;
2520
2521                 lck.in.file.handle      = h;
2522                 el[0].offset            = offset - 1;
2523                 status = smb2_lock(tree, &lck);
2524                 CHECK_STATUS_CMT(status, NT_STATUS_OK,
2525                                  talloc_asprintf(torture,
2526                                      "lock h failed at offset %#llx ",
2527                                      (unsigned long long) el[0].offset));
2528
2529                 lck.in.file.handle      = h2;
2530                 el[0].offset            = offset - 2;
2531                 status = smb2_lock(tree, &lck);
2532                 CHECK_STATUS_CMT(status, NT_STATUS_OK,
2533                                  talloc_asprintf(torture,
2534                                      "lock h2 failed at offset %#llx ",
2535                                      (unsigned long long) el[0].offset));
2536         }
2537
2538         torture_comment(torture, "  testing %d locks\n", torture_numops);
2539
2540         for (offset=i=0; i<torture_numops; i++) {
2541                 NEXT_OFFSET;
2542
2543                 lck.in.file.handle      = h;
2544                 el[0].offset            = offset - 1;
2545                 status = smb2_lock(tree, &lck);
2546                 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
2547                                  talloc_asprintf(torture,
2548                                      "lock h at offset %#llx should not have "
2549                                      "succeeded ",
2550                                      (unsigned long long) el[0].offset));
2551
2552                 lck.in.file.handle      = h;
2553                 el[0].offset            = offset - 2;
2554                 status = smb2_lock(tree, &lck);
2555                 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
2556                                  talloc_asprintf(torture,
2557                                      "lock h2 at offset %#llx should not have "
2558                                      "succeeded ",
2559                                      (unsigned long long) el[0].offset));
2560
2561                 lck.in.file.handle      = h2;
2562                 el[0].offset            = offset - 1;
2563                 status = smb2_lock(tree, &lck);
2564                 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
2565                                  talloc_asprintf(torture,
2566                                      "lock h at offset %#llx should not have "
2567                                      "succeeded ",
2568                                      (unsigned long long) el[0].offset));
2569
2570                 lck.in.file.handle      = h2;
2571                 el[0].offset            = offset - 2;
2572                 status = smb2_lock(tree, &lck);
2573                 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
2574                                  talloc_asprintf(torture,
2575                                      "lock h2 at offset %#llx should not have "
2576                                      "succeeded ",
2577                                      (unsigned long long) el[0].offset));
2578         }
2579
2580         torture_comment(torture, "  removing %d locks\n", torture_numops);
2581
2582         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2583
2584         for (offset=i=0; i<torture_numops; i++) {
2585                 NEXT_OFFSET;
2586
2587                 lck.in.file.handle      = h;
2588                 el[0].offset            = offset - 1;
2589                 status = smb2_lock(tree, &lck);
2590                 CHECK_STATUS_CMT(status, NT_STATUS_OK,
2591                                  talloc_asprintf(torture,
2592                                      "unlock from h failed at offset %#llx ",
2593                                      (unsigned long long) el[0].offset));
2594
2595                 lck.in.file.handle      = h2;
2596                 el[0].offset            = offset - 2;
2597                 status = smb2_lock(tree, &lck);
2598                 CHECK_STATUS_CMT(status, NT_STATUS_OK,
2599                                  talloc_asprintf(torture,
2600                                      "unlock from h2 failed at offset %#llx ",
2601                                      (unsigned long long) el[0].offset));
2602         }
2603
2604 done:
2605         smb2_util_close(tree, h2);
2606         smb2_util_close(tree, h);
2607         smb2_deltree(tree, BASEDIR);
2608         return ret;
2609 }
2610
2611 static NTSTATUS test_smb2_lock(struct smb2_tree *tree, struct smb2_handle h,
2612                                uint64_t offset, uint64_t length, bool exclusive)
2613 {
2614         struct smb2_lock lck;
2615         struct smb2_lock_element el[1];
2616         NTSTATUS status;
2617
2618         lck.in.locks            = el;
2619         lck.in.lock_count       = 0x0001;
2620         lck.in.lock_sequence    = 0x00000000;
2621         lck.in.file.handle      = h;
2622         el[0].offset            = offset;
2623         el[0].length            = length;
2624         el[0].reserved          = 0x00000000;
2625         el[0].flags             = (exclusive ?
2626                                   SMB2_LOCK_FLAG_EXCLUSIVE :
2627                                   SMB2_LOCK_FLAG_SHARED) |
2628                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2629
2630         status = smb2_lock(tree, &lck);
2631
2632         return status;
2633 }
2634
2635 static NTSTATUS test_smb2_unlock(struct smb2_tree *tree, struct smb2_handle h,
2636                                  uint64_t offset, uint64_t length)
2637 {
2638         struct smb2_lock lck;
2639         struct smb2_lock_element el[1];
2640         NTSTATUS status;
2641
2642         lck.in.locks            = el;
2643         lck.in.lock_count       = 0x0001;
2644         lck.in.lock_sequence    = 0x00000000;
2645         lck.in.file.handle      = h;
2646         el[0].offset            = offset;
2647         el[0].length            = length;
2648         el[0].reserved          = 0x00000000;
2649         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2650
2651         status = smb2_lock(tree, &lck);
2652
2653         return status;
2654 }
2655
2656 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2657         torture_result(torture, TORTURE_FAIL, __location__": subtest failed");\
2658         torture_comment(torture, "** "); correct = false; \
2659         }
2660
2661 /**
2662  * Test overlapping lock ranges from various lockers
2663  *  - some tests ported from BASE-LOCK-LOCK4
2664  */
2665 static bool test_overlap(struct torture_context *torture,
2666                          struct smb2_tree *tree,
2667                          struct smb2_tree *tree2)
2668 {
2669         NTSTATUS status;
2670         bool ret = true;
2671         struct smb2_handle h, h2, h3;
2672         uint8_t buf[200];
2673         bool correct = true;
2674
2675         const char *fname = BASEDIR "\\overlap.txt";
2676
2677         status = torture_smb2_testdir(tree, BASEDIR, &h);
2678         CHECK_STATUS(status, NT_STATUS_OK);
2679         smb2_util_close(tree, h);
2680
2681         status = torture_smb2_testfile(tree, fname, &h);
2682         CHECK_STATUS(status, NT_STATUS_OK);
2683
2684         ZERO_STRUCT(buf);
2685         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2686         CHECK_STATUS(status, NT_STATUS_OK);
2687
2688         status = torture_smb2_testfile(tree, fname, &h2);
2689         CHECK_STATUS(status, NT_STATUS_OK);
2690
2691         status = torture_smb2_testfile(tree2, fname, &h3);
2692         CHECK_STATUS(status, NT_STATUS_OK);
2693
2694         torture_comment(torture, "Testing overlapping locks:\n");
2695
2696         ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 0, 4, true)) &&
2697               NT_STATUS_IS_OK(test_smb2_lock(tree, h, 2, 4, true));
2698         EXPECTED(ret, false);
2699         torture_comment(torture, "the same session/handle %s set overlapping "
2700                                  "exclusive locks\n", ret?"can":"cannot");
2701
2702         ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 10, 4, false)) &&
2703               NT_STATUS_IS_OK(test_smb2_lock(tree, h, 12, 4, false));
2704         EXPECTED(ret, true);
2705         torture_comment(torture, "the same session/handle %s set overlapping "
2706                                  "shared locks\n", ret?"can":"cannot");
2707
2708         ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 20, 4, true)) &&
2709               NT_STATUS_IS_OK(test_smb2_lock(tree2, h3, 22, 4, true));
2710         EXPECTED(ret, false);
2711         torture_comment(torture, "a different session %s set overlapping "
2712                                  "exclusive locks\n", ret?"can":"cannot");
2713
2714         ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 30, 4, false)) &&
2715               NT_STATUS_IS_OK(test_smb2_lock(tree2, h3, 32, 4, false));
2716         EXPECTED(ret, true);
2717         torture_comment(torture, "a different session %s set overlapping "
2718                                  "shared locks\n", ret?"can":"cannot");
2719
2720         ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 40, 4, true)) &&
2721               NT_STATUS_IS_OK(test_smb2_lock(tree, h2, 42, 4, true));
2722         EXPECTED(ret, false);
2723         torture_comment(torture, "a different handle %s set overlapping "
2724                                  "exclusive locks\n", ret?"can":"cannot");
2725
2726         ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 50, 4, false)) &&
2727               NT_STATUS_IS_OK(test_smb2_lock(tree, h2, 52, 4, false));
2728         EXPECTED(ret, true);
2729         torture_comment(torture, "a different handle %s set overlapping "
2730                                  "shared locks\n", ret?"can":"cannot");
2731
2732         ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 110, 4, false)) &&
2733               NT_STATUS_IS_OK(test_smb2_lock(tree, h, 112, 4, false)) &&
2734               NT_STATUS_IS_OK(test_smb2_unlock(tree, h, 110, 6));
2735         EXPECTED(ret, false);
2736         torture_comment(torture, "the same handle %s coalesce read locks\n",
2737                                  ret?"can":"cannot");
2738
2739         smb2_util_close(tree, h2);
2740         smb2_util_close(tree, h);
2741         status = torture_smb2_testfile(tree, fname, &h);
2742         CHECK_STATUS(status, NT_STATUS_OK);
2743         status = torture_smb2_testfile(tree, fname, &h2);
2744         CHECK_STATUS(status, NT_STATUS_OK);
2745         ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 0, 8, false)) &&
2746               NT_STATUS_IS_OK(test_smb2_lock(tree, h2, 0, 1, false)) &&
2747               NT_STATUS_IS_OK(smb2_util_close(tree, h)) &&
2748               NT_STATUS_IS_OK(torture_smb2_testfile(tree, fname, &h)) &&
2749               NT_STATUS_IS_OK(test_smb2_lock(tree, h, 7, 1, true));
2750         EXPECTED(ret, true);
2751         torture_comment(torture, "the server %s have the NT byte range lock "
2752                                  "bug\n", !ret?"does":"doesn't");
2753
2754 done:
2755         smb2_util_close(tree2, h3);
2756         smb2_util_close(tree, h2);
2757         smb2_util_close(tree, h);
2758         smb2_deltree(tree, BASEDIR);
2759         return correct;
2760 }
2761
2762 /**
2763  * Test truncation of locked file
2764  *  - some tests ported from BASE-LOCK-LOCK7
2765  */
2766 static bool test_truncate(struct torture_context *torture,
2767                           struct smb2_tree *tree)
2768 {
2769         NTSTATUS status;
2770         bool ret = true;
2771         struct smb2_handle h, h2;
2772         uint8_t buf[200];
2773         struct smb2_lock lck;
2774         struct smb2_lock_element el[1];
2775         struct smb2_create io;
2776
2777         const char *fname = BASEDIR "\\truncate.txt";
2778
2779         status = torture_smb2_testdir(tree, BASEDIR, &h);
2780         CHECK_STATUS(status, NT_STATUS_OK);
2781         smb2_util_close(tree, h);
2782
2783         status = torture_smb2_testfile(tree, fname, &h);
2784         CHECK_STATUS(status, NT_STATUS_OK);
2785
2786         ZERO_STRUCT(buf);
2787         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2788         CHECK_STATUS(status, NT_STATUS_OK);
2789
2790         torture_comment(torture, "Testing truncation of locked file:\n");
2791
2792         /* Setup initial parameters */
2793         lck.in.locks            = el;
2794         lck.in.lock_count       = 0x0001;
2795         lck.in.lock_sequence    = 0x00000000;
2796         lck.in.file.handle      = h;
2797         el[0].offset            = 0;
2798         el[0].length            = 10;
2799         el[0].reserved          = 0x00000000;
2800
2801         ZERO_STRUCT(io);
2802         io.in.oplock_level = 0;
2803         io.in.desired_access = SEC_RIGHTS_FILE_ALL;
2804         io.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
2805         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2806         io.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
2807                              NTCREATEX_SHARE_ACCESS_READ |
2808                              NTCREATEX_SHARE_ACCESS_WRITE;
2809         io.in.create_options = 0;
2810         io.in.fname = fname;
2811
2812         /* Take an exclusive lock */
2813         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2814                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2815         status = smb2_lock(tree, &lck);
2816         CHECK_STATUS(status, NT_STATUS_OK);
2817
2818         /* On second handle open the file with OVERWRITE disposition */
2819         torture_comment(torture, "  overwrite disposition is allowed on a "
2820                                  "locked file.\n");
2821
2822         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2823         status = smb2_create(tree, tree, &io);
2824         CHECK_STATUS(status, NT_STATUS_OK);
2825         h2 = io.out.file.handle;
2826         smb2_util_close(tree, h2);
2827
2828         /* On second handle open the file with SUPERSEDE disposition */
2829         torture_comment(torture, "  supersede disposition is allowed on a "
2830                                  "locked file.\n");
2831
2832         io.in.create_disposition = NTCREATEX_DISP_SUPERSEDE;
2833         status = smb2_create(tree, tree, &io);
2834         CHECK_STATUS(status, NT_STATUS_OK);
2835         h2 = io.out.file.handle;
2836         smb2_util_close(tree, h2);
2837
2838         /* cleanup */
2839         lck.in.file.handle      = h;
2840         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2841         status = smb2_lock(tree, &lck);
2842         CHECK_STATUS(status, NT_STATUS_OK);
2843
2844 done:
2845         smb2_util_close(tree, h2);
2846         smb2_util_close(tree, h);
2847         smb2_deltree(tree, BASEDIR);
2848         return ret;
2849 }
2850
2851 /* basic testing of SMB2 locking
2852 */
2853 struct torture_suite *torture_smb2_lock_init(void)
2854 {
2855         struct torture_suite *suite =
2856             torture_suite_create(talloc_autofree_context(), "lock");
2857
2858         torture_suite_add_1smb2_test(suite, "valid-request",
2859             test_valid_request);
2860         torture_suite_add_1smb2_test(suite, "rw-none", test_lock_rw_none);
2861         torture_suite_add_1smb2_test(suite, "rw-shared", test_lock_rw_shared);
2862         torture_suite_add_1smb2_test(suite, "rw-exclusive",
2863             test_lock_rw_exclusive);
2864         torture_suite_add_1smb2_test(suite, "auto-unlock",
2865             test_lock_auto_unlock);
2866         torture_suite_add_1smb2_test(suite, "lock", test_lock);
2867         torture_suite_add_1smb2_test(suite, "async", test_async);
2868         torture_suite_add_1smb2_test(suite, "cancel", test_cancel);
2869         torture_suite_add_1smb2_test(suite, "cancel-tdis", test_cancel_tdis);
2870         torture_suite_add_1smb2_test(suite, "cancel-logoff",
2871             test_cancel_logoff);
2872         torture_suite_add_1smb2_test(suite, "errorcode", test_errorcode);
2873         torture_suite_add_1smb2_test(suite, "zerobytelength",
2874             test_zerobytelength);
2875         torture_suite_add_1smb2_test(suite, "zerobyteread",
2876             test_zerobyteread);
2877         torture_suite_add_1smb2_test(suite, "unlock", test_unlock);
2878         torture_suite_add_1smb2_test(suite, "multiple-unlock",
2879             test_multiple_unlock);
2880         torture_suite_add_1smb2_test(suite, "stacking", test_stacking);
2881         torture_suite_add_1smb2_test(suite, "contend", test_contend);
2882         torture_suite_add_1smb2_test(suite, "context", test_context);
2883         torture_suite_add_1smb2_test(suite, "range", test_range);
2884         torture_suite_add_2smb2_test(suite, "overlap", test_overlap);
2885         torture_suite_add_1smb2_test(suite, "truncate", test_truncate);
2886
2887         suite->description = talloc_strdup(suite, "SMB2-LOCK tests");
2888
2889         return suite;
2890 }