torture: fixed SMB2-LOCK valgrind error
[ira/wip.git] / source4 / torture / smb2 / lock.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    SMB2 lock test suite
5
6    Copyright (C) Stefan Metzmacher 2006
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25
26 #include "torture/torture.h"
27 #include "torture/smb2/proto.h"
28 #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         CHECK_STATUS(status, NT_STATUS_OK);
1048
1049         torture_comment(torture, "  Attempt to unlock first lock\n");
1050         lck.in.file.handle      = h;
1051         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1052         status = smb2_lock(tree, &lck);
1053         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
1054
1055 done:
1056         smb2_util_close(tree, h2);
1057         smb2_util_close(tree, h);
1058         smb2_deltree(tree, BASEDIR);
1059         return ret;
1060 }
1061
1062 /*
1063   test SMB2 LOCK Cancel by user logoff
1064 */
1065 static bool test_cancel_logoff(struct torture_context *torture,
1066                                struct smb2_tree *tree)
1067 {
1068         NTSTATUS status;
1069         bool ret = true;
1070         struct smb2_handle h, h2;
1071         uint8_t buf[200];
1072         struct smb2_lock lck;
1073         struct smb2_lock_element el[2];
1074         struct smb2_request *req = NULL;
1075
1076         const char *fname = BASEDIR "\\cancel_tdis.txt";
1077
1078         status = torture_smb2_testdir(tree, BASEDIR, &h);
1079         CHECK_STATUS(status, NT_STATUS_OK);
1080         smb2_util_close(tree, h);
1081
1082         status = torture_smb2_testfile(tree, fname, &h);
1083         CHECK_STATUS(status, NT_STATUS_OK);
1084
1085         ZERO_STRUCT(buf);
1086         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1087         CHECK_STATUS(status, NT_STATUS_OK);
1088
1089         status = torture_smb2_testfile(tree, fname, &h2);
1090         CHECK_STATUS(status, NT_STATUS_OK);
1091
1092         lck.in.locks            = el;
1093
1094         lck.in.lock_count       = 0x0001;
1095         lck.in.lock_sequence    = 0x00000000;
1096         lck.in.file.handle      = h;
1097         el[0].offset            = 100;
1098         el[0].length            = 10;
1099         el[0].reserved          = 0x00000000;
1100         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
1101
1102         torture_comment(torture, "Testing cancel by ulogoff\n");
1103
1104         torture_comment(torture, "  Acquire first lock\n");
1105         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
1106         status = smb2_lock(tree, &lck);
1107         CHECK_STATUS(status, NT_STATUS_OK);
1108
1109         torture_comment(torture, "  Second lock should pend on first\n");
1110         lck.in.file.handle      = h2;
1111         req = smb2_lock_send(tree, &lck);
1112         WAIT_FOR_ASYNC_RESPONSE(req);
1113
1114         torture_comment(torture, "  Logoff user\n");
1115         smb2_logoff(tree->session);
1116
1117         torture_comment(torture, "  Check pending lock reply\n");
1118         status = smb2_lock_recv(req, &lck);
1119         CHECK_STATUS(status, NT_STATUS_OK);
1120
1121         torture_comment(torture, "  Attempt to unlock first lock\n");
1122         lck.in.file.handle      = h;
1123         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1124         status = smb2_lock(tree, &lck);
1125         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
1126
1127 done:
1128         smb2_util_close(tree, h2);
1129         smb2_util_close(tree, h);
1130         smb2_deltree(tree, BASEDIR);
1131         return ret;
1132 }
1133
1134 /*
1135  * Test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
1136  *
1137  * The SMBv1 protocol returns a different error code on lock acquisition
1138  * failure depending on a number of parameters, including what error code
1139  * was returned to the previous failure.
1140  *
1141  * SMBv2 has cleaned up these semantics and should always return
1142  * NT_STATUS_LOCK_NOT_GRANTED to failed lock requests, and
1143  * NT_STATUS_FILE_LOCK_CONFLICT to failed read/write requests due to a lock
1144  * being held on that range.
1145 */
1146 static bool test_errorcode(struct torture_context *torture,
1147                            struct smb2_tree *tree)
1148 {
1149         NTSTATUS status;
1150         bool ret = true;
1151         struct smb2_handle h, h2;
1152         uint8_t buf[200];
1153         struct smb2_lock lck;
1154         struct smb2_lock_element el[2];
1155
1156         const char *fname = BASEDIR "\\errorcode.txt";
1157
1158         status = torture_smb2_testdir(tree, BASEDIR, &h);
1159         CHECK_STATUS(status, NT_STATUS_OK);
1160         smb2_util_close(tree, h);
1161
1162         status = torture_smb2_testfile(tree, fname, &h);
1163         CHECK_STATUS(status, NT_STATUS_OK);
1164
1165         ZERO_STRUCT(buf);
1166         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1167         CHECK_STATUS(status, NT_STATUS_OK);
1168
1169         status = torture_smb2_testfile(tree, fname, &h2);
1170         CHECK_STATUS(status, NT_STATUS_OK);
1171
1172         lck.in.locks            = el;
1173
1174         lck.in.lock_count       = 0x0001;
1175         lck.in.lock_sequence    = 0x00000000;
1176         lck.in.file.handle      = h;
1177         el[0].offset            = 100;
1178         el[0].length            = 10;
1179         el[0].reserved          = 0x00000000;
1180         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1181                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1182
1183         torture_comment(torture, "Testing LOCK_NOT_GRANTED vs. "
1184                                  "FILE_LOCK_CONFLICT\n");
1185
1186         if (TARGET_IS_W2K8(torture)) {
1187                 torture_result(torture, TORTURE_SKIP,
1188                     "Target has \"pretty please\" bug. A contending lock "
1189                     "request on the same handle unlocks the lock.");
1190                 goto done;
1191         }
1192
1193         status = smb2_lock(tree, &lck);
1194         CHECK_STATUS(status, NT_STATUS_OK);
1195
1196         /* Demonstrate that the first conflicting lock on each handle gives
1197          * LOCK_NOT_GRANTED. */
1198         lck.in.file.handle      = h;
1199         status = smb2_lock(tree, &lck);
1200         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1201
1202         lck.in.file.handle      = h2;
1203         status = smb2_lock(tree, &lck);
1204         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1205
1206         /* Demonstrate that each following conflict also gives
1207          * LOCK_NOT_GRANTED */
1208         lck.in.file.handle      = h;
1209         status = smb2_lock(tree, &lck);
1210         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1211
1212         lck.in.file.handle      = h2;
1213         status = smb2_lock(tree, &lck);
1214         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1215
1216         lck.in.file.handle      = h;
1217         status = smb2_lock(tree, &lck);
1218         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1219
1220         lck.in.file.handle      = h2;
1221         status = smb2_lock(tree, &lck);
1222         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1223
1224         /* Demonstrate that the smbpid doesn't matter */
1225         tree->session->pid++;
1226         lck.in.file.handle      = h;
1227         status = smb2_lock(tree, &lck);
1228         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1229
1230         lck.in.file.handle      = h2;
1231         status = smb2_lock(tree, &lck);
1232         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1233         tree->session->pid--;
1234
1235         /* Demonstrate that a 0-byte lock inside the locked range still
1236          * gives the same error. */
1237
1238         el[0].offset            = 102;
1239         el[0].length            = 0;
1240         lck.in.file.handle      = h;
1241         status = smb2_lock(tree, &lck);
1242         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1243
1244         lck.in.file.handle      = h2;
1245         status = smb2_lock(tree, &lck);
1246         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1247
1248         /* Demonstrate that a lock inside the locked range still gives the
1249          * same error. */
1250
1251         el[0].offset            = 102;
1252         el[0].length            = 5;
1253         lck.in.file.handle      = h;
1254         status = smb2_lock(tree, &lck);
1255         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1256
1257         lck.in.file.handle      = h2;
1258         status = smb2_lock(tree, &lck);
1259         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1260
1261 done:
1262         smb2_util_close(tree, h2);
1263         smb2_util_close(tree, h);
1264         smb2_deltree(tree, BASEDIR);
1265         return ret;
1266 }
1267
1268 /**
1269  * Tests zero byte locks.
1270  */
1271
1272 struct double_lock_test {
1273         struct smb2_lock_element lock1;
1274         struct smb2_lock_element lock2;
1275         NTSTATUS status;
1276 };
1277
1278 static struct double_lock_test zero_byte_tests[] = {
1279         /* {offset, count, reserved, flags},
1280          * {offset, count, reserved, flags},
1281          * status */
1282
1283         /** First, takes a zero byte lock at offset 10. Then:
1284         *   - Taking 0 byte lock at 10 should succeed.
1285         *   - Taking 1 byte locks at 9,10,11 should succeed.
1286         *   - Taking 2 byte lock at 9 should fail.
1287         *   - Taking 2 byte lock at 10 should succeed.
1288         *   - Taking 3 byte lock at 9 should fail.
1289         */
1290         {{10, 0, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1291         {{10, 0, 0, 0}, {9, 1, 0, 0},  NT_STATUS_OK},
1292         {{10, 0, 0, 0}, {10, 1, 0, 0}, NT_STATUS_OK},
1293         {{10, 0, 0, 0}, {11, 1, 0, 0}, NT_STATUS_OK},
1294         {{10, 0, 0, 0}, {9, 2, 0, 0},  NT_STATUS_LOCK_NOT_GRANTED},
1295         {{10, 0, 0, 0}, {10, 2, 0, 0}, NT_STATUS_OK},
1296         {{10, 0, 0, 0}, {9, 3, 0, 0},  NT_STATUS_LOCK_NOT_GRANTED},
1297
1298         /** Same, but opposite order. */
1299         {{10, 0, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1300         {{9, 1, 0, 0},  {10, 0, 0, 0}, NT_STATUS_OK},
1301         {{10, 1, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1302         {{11, 1, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1303         {{9, 2, 0, 0},  {10, 0, 0, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1304         {{10, 2, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1305         {{9, 3, 0, 0},  {10, 0, 0, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1306
1307         /** Zero zero case. */
1308         {{0, 0, 0, 0},  {0, 0, 0, 0},  NT_STATUS_OK},
1309 };
1310
1311 static bool test_zerobytelength(struct torture_context *torture,
1312                                 struct smb2_tree *tree)
1313 {
1314         NTSTATUS status;
1315         bool ret = true;
1316         struct smb2_handle h, h2;
1317         uint8_t buf[200];
1318         struct smb2_lock lck;
1319         int i;
1320
1321         const char *fname = BASEDIR "\\zero.txt";
1322
1323         torture_comment(torture, "Testing zero length byte range locks:\n");
1324
1325         status = torture_smb2_testdir(tree, BASEDIR, &h);
1326         CHECK_STATUS(status, NT_STATUS_OK);
1327         smb2_util_close(tree, h);
1328
1329         status = torture_smb2_testfile(tree, fname, &h);
1330         CHECK_STATUS(status, NT_STATUS_OK);
1331
1332         ZERO_STRUCT(buf);
1333         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1334         CHECK_STATUS(status, NT_STATUS_OK);
1335
1336         status = torture_smb2_testfile(tree, fname, &h2);
1337         CHECK_STATUS(status, NT_STATUS_OK);
1338
1339         /* Setup initial parameters */
1340         lck.in.lock_count       = 0x0001;
1341         lck.in.lock_sequence    = 0x00000000;
1342         lck.in.file.handle      = h;
1343
1344         /* Try every combination of locks in zero_byte_tests, using the same
1345          * handle for both locks. The first lock is assumed to succeed. The
1346          * second lock may contend, depending on the expected status. */
1347         for (i = 0; i < ARRAY_SIZE(zero_byte_tests); i++) {
1348                 torture_comment(torture,
1349                     "  ... {%llu, %llu} + {%llu, %llu} = %s\n",
1350                     zero_byte_tests[i].lock1.offset,
1351                     zero_byte_tests[i].lock1.length,
1352                     zero_byte_tests[i].lock2.offset,
1353                     zero_byte_tests[i].lock2.length,
1354                     nt_errstr(zero_byte_tests[i].status));
1355
1356                 /* Lock both locks. */
1357                 lck.in.locks            = &zero_byte_tests[i].lock1;
1358                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_EXCLUSIVE |
1359                                           SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1360                 status = smb2_lock(tree, &lck);
1361                 CHECK_STATUS(status, NT_STATUS_OK);
1362
1363                 lck.in.locks            = &zero_byte_tests[i].lock2;
1364                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_EXCLUSIVE |
1365                                           SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1366                 status = smb2_lock(tree, &lck);
1367                 CHECK_STATUS_CONT(status, zero_byte_tests[i].status);
1368
1369                 /* Unlock both locks in reverse order. */
1370                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_UNLOCK;
1371                 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1372                         status = smb2_lock(tree, &lck);
1373                         CHECK_STATUS(status, NT_STATUS_OK);
1374                 }
1375
1376                 lck.in.locks            = &zero_byte_tests[i].lock1;
1377                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_UNLOCK;
1378                 status = smb2_lock(tree, &lck);
1379                 CHECK_STATUS(status, NT_STATUS_OK);
1380         }
1381
1382         /* Try every combination of locks in zero_byte_tests, using two
1383          * different handles. */
1384         for (i = 0; i < ARRAY_SIZE(zero_byte_tests); i++) {
1385                 torture_comment(torture,
1386                     "  ... {%llu, %llu} + {%llu, %llu} = %s\n",
1387                     zero_byte_tests[i].lock1.offset,
1388                     zero_byte_tests[i].lock1.length,
1389                     zero_byte_tests[i].lock2.offset,
1390                     zero_byte_tests[i].lock2.length,
1391                     nt_errstr(zero_byte_tests[i].status));
1392
1393                 /* Lock both locks. */
1394                 lck.in.file.handle      = h;
1395                 lck.in.locks            = &zero_byte_tests[i].lock1;
1396                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_EXCLUSIVE |
1397                                           SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1398                 status = smb2_lock(tree, &lck);
1399                 CHECK_STATUS(status, NT_STATUS_OK);
1400
1401                 lck.in.file.handle      = h2;
1402                 lck.in.locks            = &zero_byte_tests[i].lock2;
1403                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_EXCLUSIVE |
1404                                           SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1405                 status = smb2_lock(tree, &lck);
1406                 CHECK_STATUS_CONT(status, zero_byte_tests[i].status);
1407
1408                 /* Unlock both locks in reverse order. */
1409                 lck.in.file.handle      = h2;
1410                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_UNLOCK;
1411                 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1412                         status = smb2_lock(tree, &lck);
1413                         CHECK_STATUS(status, NT_STATUS_OK);
1414                 }
1415
1416                 lck.in.file.handle      = h;
1417                 lck.in.locks            = &zero_byte_tests[i].lock1;
1418                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_UNLOCK;
1419                 status = smb2_lock(tree, &lck);
1420                 CHECK_STATUS(status, NT_STATUS_OK);
1421         }
1422
1423 done:
1424         smb2_util_close(tree, h2);
1425         smb2_util_close(tree, h);
1426         smb2_deltree(tree, BASEDIR);
1427         return ret;
1428 }
1429
1430 static bool test_unlock(struct torture_context *torture,
1431                         struct smb2_tree *tree)
1432 {
1433         NTSTATUS status;
1434         bool ret = true;
1435         struct smb2_handle h, h2;
1436         uint8_t buf[200];
1437         struct smb2_lock lck;
1438         struct smb2_lock_element el1[1];
1439         struct smb2_lock_element el2[1];
1440
1441         const char *fname = BASEDIR "\\unlock.txt";
1442
1443         status = torture_smb2_testdir(tree, BASEDIR, &h);
1444         CHECK_STATUS(status, NT_STATUS_OK);
1445         smb2_util_close(tree, h);
1446
1447         status = torture_smb2_testfile(tree, fname, &h);
1448         CHECK_STATUS(status, NT_STATUS_OK);
1449
1450         ZERO_STRUCT(buf);
1451         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1452         CHECK_STATUS(status, NT_STATUS_OK);
1453
1454         status = torture_smb2_testfile(tree, fname, &h2);
1455         CHECK_STATUS(status, NT_STATUS_OK);
1456
1457         /* Setup initial parameters */
1458         lck.in.locks            = el1;
1459         lck.in.lock_count       = 0x0001;
1460         lck.in.lock_sequence    = 0x00000000;
1461         el1[0].offset           = 0;
1462         el1[0].length           = 10;
1463         el1[0].reserved         = 0x00000000;
1464
1465         /* Take exclusive lock, then unlock it with a shared-unlock call. */
1466
1467         torture_comment(torture, "Testing unlock exclusive with shared\n");
1468
1469         torture_comment(torture, "  taking exclusive lock.\n");
1470         lck.in.file.handle      = h;
1471         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE;
1472         status = smb2_lock(tree, &lck);
1473         CHECK_STATUS(status, NT_STATUS_OK);
1474
1475         torture_comment(torture, "  try to unlock the exclusive with a shared "
1476                                  "unlock call.\n");
1477         el1[0].flags            = SMB2_LOCK_FLAG_SHARED |
1478                                   SMB2_LOCK_FLAG_UNLOCK;
1479         status = smb2_lock(tree, &lck);
1480         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1481
1482         torture_comment(torture, "  try shared lock on h2, to test the "
1483                                  "unlock.\n");
1484         lck.in.file.handle      = h2;
1485         el1[0].flags            = SMB2_LOCK_FLAG_SHARED |
1486                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1487         status = smb2_lock(tree, &lck);
1488         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1489
1490         torture_comment(torture, "  unlock the exclusive lock\n");
1491         lck.in.file.handle      = h;
1492         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1493         status = smb2_lock(tree, &lck);
1494         CHECK_STATUS(status, NT_STATUS_OK);
1495
1496         /* Unlock a shared lock with an exclusive-unlock call. */
1497
1498         torture_comment(torture, "Testing unlock shared with exclusive\n");
1499
1500         torture_comment(torture, "  taking shared lock.\n");
1501         lck.in.file.handle      = h;
1502         el1[0].flags            = SMB2_LOCK_FLAG_SHARED;
1503         status = smb2_lock(tree, &lck);
1504         CHECK_STATUS(status, NT_STATUS_OK);
1505
1506         torture_comment(torture, "  try to unlock the shared with an exclusive "
1507                                  "unlock call.\n");
1508         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1509                                   SMB2_LOCK_FLAG_UNLOCK;
1510         status = smb2_lock(tree, &lck);
1511         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1512
1513         torture_comment(torture, "  try exclusive lock on h2, to test the "
1514                                  "unlock.\n");
1515         lck.in.file.handle      = h2;
1516         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1517                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1518         status = smb2_lock(tree, &lck);
1519         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1520
1521         torture_comment(torture, "  unlock the exclusive lock\n");
1522         lck.in.file.handle      = h;
1523         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1524         status = smb2_lock(tree, &lck);
1525         CHECK_STATUS(status, NT_STATUS_OK);
1526
1527         /* Test unlocking of stacked 0-byte locks. SMB2 0-byte lock behavior
1528          * should be the same as >0-byte behavior.  Exclusive locks should be
1529          * unlocked before shared. */
1530
1531         torture_comment(torture, "Test unlocking stacked 0-byte locks\n");
1532
1533         lck.in.locks            = el1;
1534         lck.in.file.handle      = h;
1535         el1[0].offset           = 10;
1536         el1[0].length           = 0;
1537         el1[0].reserved         = 0x00000000;
1538         el2[0].offset           = 5;
1539         el2[0].length           = 10;
1540         el2[0].reserved         = 0x00000000;
1541
1542         /* lock 0-byte exclusive */
1543         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1544                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1545         status = smb2_lock(tree, &lck);
1546         CHECK_STATUS(status, NT_STATUS_OK);
1547
1548         /* lock 0-byte shared */
1549         el1[0].flags            = SMB2_LOCK_FLAG_SHARED |
1550                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1551         status = smb2_lock(tree, &lck);
1552         CHECK_STATUS(status, NT_STATUS_OK);
1553
1554         /* test contention */
1555         lck.in.locks            = el2;
1556         lck.in.file.handle      = h2;
1557         el2[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1558                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1559         status = smb2_lock(tree, &lck);
1560         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1561
1562         lck.in.locks            = el2;
1563         lck.in.file.handle      = h2;
1564         el2[0].flags            = SMB2_LOCK_FLAG_SHARED |
1565                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1566         status = smb2_lock(tree, &lck);
1567         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1568
1569         /* unlock */
1570         lck.in.locks            = el1;
1571         lck.in.file.handle      = h;
1572         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1573         status = smb2_lock(tree, &lck);
1574         CHECK_STATUS(status, NT_STATUS_OK);
1575
1576         /* test - can we take a shared lock? */
1577         lck.in.locks            = el2;
1578         lck.in.file.handle      = h2;
1579         el2[0].flags            = SMB2_LOCK_FLAG_SHARED |
1580                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1581         status = smb2_lock(tree, &lck);
1582         CHECK_STATUS(status, NT_STATUS_OK);
1583
1584         el2[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1585         status = smb2_lock(tree, &lck);
1586         CHECK_STATUS(status, NT_STATUS_OK);
1587
1588         /* cleanup */
1589         lck.in.locks            = el1;
1590         lck.in.file.handle      = h;
1591         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1592         status = smb2_lock(tree, &lck);
1593         CHECK_STATUS(status, NT_STATUS_OK);
1594
1595         /* Test unlocking of stacked exclusive, shared locks. Exclusive
1596          * should be unlocked before any shared. */
1597
1598         torture_comment(torture, "Test unlocking stacked exclusive/shared "
1599                                  "locks\n");
1600
1601         lck.in.locks            = el1;
1602         lck.in.file.handle      = h;
1603         el1[0].offset           = 10;
1604         el1[0].length           = 10;
1605         el1[0].reserved         = 0x00000000;
1606         el2[0].offset           = 5;
1607         el2[0].length           = 10;
1608         el2[0].reserved         = 0x00000000;
1609
1610         /* lock exclusive */
1611         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1612                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1613         status = smb2_lock(tree, &lck);
1614         CHECK_STATUS(status, NT_STATUS_OK);
1615
1616         /* lock shared */
1617         el1[0].flags            = SMB2_LOCK_FLAG_SHARED |
1618                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1619         status = smb2_lock(tree, &lck);
1620         CHECK_STATUS(status, NT_STATUS_OK);
1621
1622         /* test contention */
1623         lck.in.locks            = el2;
1624         lck.in.file.handle      = h2;
1625         el2[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1626                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1627         status = smb2_lock(tree, &lck);
1628         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1629
1630         lck.in.locks            = el2;
1631         lck.in.file.handle      = h2;
1632         el2[0].flags            = SMB2_LOCK_FLAG_SHARED |
1633                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1634         status = smb2_lock(tree, &lck);
1635         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1636
1637         /* unlock */
1638         lck.in.locks            = el1;
1639         lck.in.file.handle      = h;
1640         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1641         status = smb2_lock(tree, &lck);
1642         CHECK_STATUS(status, NT_STATUS_OK);
1643
1644         /* test - can we take a shared lock? */
1645         lck.in.locks            = el2;
1646         lck.in.file.handle      = h2;
1647         el2[0].flags            = SMB2_LOCK_FLAG_SHARED |
1648                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1649         status = smb2_lock(tree, &lck);
1650         CHECK_STATUS(status, NT_STATUS_OK);
1651
1652         el2[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1653         status = smb2_lock(tree, &lck);
1654         CHECK_STATUS(status, NT_STATUS_OK);
1655
1656         /* cleanup */
1657         lck.in.locks            = el1;
1658         lck.in.file.handle      = h;
1659         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1660         status = smb2_lock(tree, &lck);
1661         CHECK_STATUS(status, NT_STATUS_OK);
1662
1663 done:
1664         smb2_util_close(tree, h2);
1665         smb2_util_close(tree, h);
1666         smb2_deltree(tree, BASEDIR);
1667         return ret;
1668 }
1669
1670 static bool test_multiple_unlock(struct torture_context *torture,
1671                                  struct smb2_tree *tree)
1672 {
1673         NTSTATUS status;
1674         bool ret = true;
1675         struct smb2_handle h;
1676         uint8_t buf[200];
1677         struct smb2_lock lck;
1678         struct smb2_lock_element el[2];
1679         struct smb2_lock_element el0, el1;
1680
1681         const char *fname = BASEDIR "\\unlock_multiple.txt";
1682
1683         status = torture_smb2_testdir(tree, BASEDIR, &h);
1684         CHECK_STATUS(status, NT_STATUS_OK);
1685         smb2_util_close(tree, h);
1686
1687         status = torture_smb2_testfile(tree, fname, &h);
1688         CHECK_STATUS(status, NT_STATUS_OK);
1689
1690         ZERO_STRUCT(buf);
1691         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1692         CHECK_STATUS(status, NT_STATUS_OK);
1693
1694         torture_comment(torture, "Testing multiple unlocks:\n");
1695
1696         /* Setup initial parameters */
1697         lck.in.lock_count       = 0x0002;
1698         lck.in.lock_sequence    = 0x00000000;
1699         lck.in.file.handle      = h;
1700         el0.offset              = 0;
1701         el0.length              = 10;
1702         el0.reserved            = 0x00000000;
1703         el1.offset              = 10;
1704         el1.length              = 10;
1705         el1.reserved            = 0x00000000;
1706         el[0]                   = el0;
1707         el[1]                   = el1;
1708
1709         /* Test1: Acquire second lock, but not first. */
1710         torture_comment(torture, "  unlock 2 locks, first one not locked. "
1711                                  "Expect no locks unlocked. \n");
1712
1713         lck.in.lock_count       = 0x0001;
1714         el1.flags               = SMB2_LOCK_FLAG_EXCLUSIVE |
1715                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1716         lck.in.locks            = &el1;
1717         status = smb2_lock(tree, &lck);
1718         CHECK_STATUS(status, NT_STATUS_OK);
1719
1720         /* Try to unlock both locks */
1721         lck.in.lock_count       = 0x0002;
1722         el0.flags               = SMB2_LOCK_FLAG_UNLOCK;
1723         el1.flags               = SMB2_LOCK_FLAG_UNLOCK;
1724         el[0]                   = el0;
1725         el[1]                   = el1;
1726         lck.in.locks            = el;
1727         status = smb2_lock(tree, &lck);
1728         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1729
1730         /* Second lock should not be unlocked. */
1731         lck.in.lock_count       = 0x0001;
1732         el1.flags               = SMB2_LOCK_FLAG_EXCLUSIVE |
1733                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1734         lck.in.locks            = &el1;
1735         status = smb2_lock(tree, &lck);
1736         if (TARGET_IS_W2K8(torture)) {
1737                 CHECK_STATUS(status, NT_STATUS_OK);
1738                 torture_warning(torture, "Target has \"pretty please\" bug. "
1739                                 "A contending lock request on the same handle "
1740                                 "unlocks the lock.\n");
1741         } else {
1742                 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1743         }
1744
1745         /* cleanup */
1746         lck.in.lock_count       = 0x0001;
1747         el1.flags               = SMB2_LOCK_FLAG_UNLOCK;
1748         lck.in.locks            = &el1;
1749         status = smb2_lock(tree, &lck);
1750         CHECK_STATUS(status, NT_STATUS_OK);
1751
1752         /* Test2: Acquire first lock, but not second. */
1753         torture_comment(torture, "  unlock 2 locks, second one not locked. "
1754                                  "Expect first lock unlocked.\n");
1755
1756         lck.in.lock_count       = 0x0001;
1757         el0.flags               = SMB2_LOCK_FLAG_EXCLUSIVE |
1758                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1759         lck.in.locks            = &el0;
1760         status = smb2_lock(tree, &lck);
1761         CHECK_STATUS(status, NT_STATUS_OK);
1762
1763         /* Try to unlock both locks */
1764         lck.in.lock_count       = 0x0002;
1765         el0.flags               = SMB2_LOCK_FLAG_UNLOCK;
1766         el1.flags               = SMB2_LOCK_FLAG_UNLOCK;
1767         el[0]                   = el0;
1768         el[1]                   = el1;
1769         lck.in.locks            = el;
1770         status = smb2_lock(tree, &lck);
1771         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1772
1773         /* First lock should be unlocked. */
1774         lck.in.lock_count       = 0x0001;
1775         el0.flags               = SMB2_LOCK_FLAG_EXCLUSIVE |
1776                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1777         lck.in.locks            = &el0;
1778         status = smb2_lock(tree, &lck);
1779         CHECK_STATUS(status, NT_STATUS_OK);
1780
1781         /* cleanup */
1782         lck.in.lock_count       = 0x0001;
1783         el0.flags               = SMB2_LOCK_FLAG_UNLOCK;
1784         lck.in.locks            = &el0;
1785         status = smb2_lock(tree, &lck);
1786         CHECK_STATUS(status, NT_STATUS_OK);
1787
1788 done:
1789         smb2_util_close(tree, h);
1790         smb2_deltree(tree, BASEDIR);
1791         return ret;
1792 }
1793
1794 /**
1795  * Test lock stacking
1796  *  - some tests ported from BASE-LOCK-LOCK5
1797  */
1798 static bool test_stacking(struct torture_context *torture,
1799                           struct smb2_tree *tree)
1800 {
1801         NTSTATUS status;
1802         bool ret = true;
1803         struct smb2_handle h, h2;
1804         uint8_t buf[200];
1805         struct smb2_lock lck;
1806         struct smb2_lock_element el[1];
1807
1808         const char *fname = BASEDIR "\\stacking.txt";
1809
1810         status = torture_smb2_testdir(tree, BASEDIR, &h);
1811         CHECK_STATUS(status, NT_STATUS_OK);
1812         smb2_util_close(tree, h);
1813
1814         status = torture_smb2_testfile(tree, fname, &h);
1815         CHECK_STATUS(status, NT_STATUS_OK);
1816
1817         ZERO_STRUCT(buf);
1818         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1819         CHECK_STATUS(status, NT_STATUS_OK);
1820
1821         status = torture_smb2_testfile(tree, fname, &h2);
1822         CHECK_STATUS(status, NT_STATUS_OK);
1823
1824         torture_comment(torture, "Testing lock stacking:\n");
1825
1826         /* Setup initial parameters */
1827         lck.in.locks            = el;
1828         lck.in.lock_count       = 0x0001;
1829         lck.in.lock_sequence    = 0x00000000;
1830         lck.in.file.handle      = h;
1831         el[0].offset            = 0;
1832         el[0].length            = 10;
1833         el[0].reserved          = 0x00000000;
1834
1835         /* Try to take a shared lock, then a shared lock on same handle */
1836         torture_comment(torture, "  stacking a shared on top of a shared"
1837                                  "lock succeeds.\n");
1838
1839         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
1840                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1841         status = smb2_lock(tree, &lck);
1842         CHECK_STATUS(status, NT_STATUS_OK);
1843
1844         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
1845                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1846         status = smb2_lock(tree, &lck);
1847         CHECK_STATUS(status, NT_STATUS_OK);
1848
1849         /* cleanup */
1850         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1851         status = smb2_lock(tree, &lck);
1852         CHECK_STATUS(status, NT_STATUS_OK);
1853
1854         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1855         status = smb2_lock(tree, &lck);
1856         CHECK_STATUS(status, NT_STATUS_OK);
1857
1858
1859         /* Try to take an exclusive lock, then a shared lock on same handle */
1860         torture_comment(torture, "  stacking a shared on top of an exclusive "
1861                                  "lock succeeds.\n");
1862
1863         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1864                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1865         status = smb2_lock(tree, &lck);
1866         CHECK_STATUS(status, NT_STATUS_OK);
1867
1868         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
1869                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1870         status = smb2_lock(tree, &lck);
1871         CHECK_STATUS(status, NT_STATUS_OK);
1872
1873         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
1874                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1875         status = smb2_lock(tree, &lck);
1876         CHECK_STATUS(status, NT_STATUS_OK);
1877
1878         /* stacking a shared from a different handle should fail */
1879         lck.in.file.handle      = h2;
1880         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
1881                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1882         status = smb2_lock(tree, &lck);
1883         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1884
1885         /* cleanup */
1886         lck.in.file.handle      = h;
1887         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1888         status = smb2_lock(tree, &lck);
1889         CHECK_STATUS(status, NT_STATUS_OK);
1890
1891         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1892         status = smb2_lock(tree, &lck);
1893         CHECK_STATUS(status, NT_STATUS_OK);
1894
1895         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1896         status = smb2_lock(tree, &lck);
1897         CHECK_STATUS(status, NT_STATUS_OK);
1898
1899         /* ensure the 4th unlock fails */
1900         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1901         status = smb2_lock(tree, &lck);
1902         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1903
1904         /* ensure a second handle can now take an exclusive lock */
1905         lck.in.file.handle      = h2;
1906         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
1907                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1908         status = smb2_lock(tree, &lck);
1909         CHECK_STATUS(status, NT_STATUS_OK);
1910
1911         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1912         status = smb2_lock(tree, &lck);
1913         CHECK_STATUS(status, NT_STATUS_OK);
1914
1915         /* Try to take an exclusive lock, then a shared lock on a
1916          * different handle */
1917         torture_comment(torture, "  stacking a shared on top of an exclusive "
1918                                  "lock with different handles fails.\n");
1919
1920         lck.in.file.handle      = h;
1921         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1922                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1923         status = smb2_lock(tree, &lck);
1924         CHECK_STATUS(status, NT_STATUS_OK);
1925
1926         lck.in.file.handle      = h2;
1927         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
1928                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1929         status = smb2_lock(tree, &lck);
1930         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1931
1932         /* cleanup */
1933         lck.in.file.handle      = h;
1934         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1935         status = smb2_lock(tree, &lck);
1936         CHECK_STATUS(status, NT_STATUS_OK);
1937
1938         /* Try to take a shared lock, then stack an exclusive with same
1939          * handle.  */
1940         torture_comment(torture, "  stacking an exclusive on top of a shared "
1941                                  "lock fails.\n");
1942
1943         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
1944                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1945         status = smb2_lock(tree, &lck);
1946         CHECK_STATUS(status, NT_STATUS_OK);
1947
1948         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1949                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1950         status = smb2_lock(tree, &lck);
1951         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1952
1953         /* cleanup */
1954         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1955         status = smb2_lock(tree, &lck);
1956         if (TARGET_IS_W2K8(torture)) {
1957                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1958                 torture_warning(torture, "Target has \"pretty please\" bug. "
1959                                 "A contending lock request on the same handle "
1960                                 "unlocks the lock.\n");
1961         } else {
1962                 CHECK_STATUS(status, NT_STATUS_OK);
1963         }
1964
1965         /* Prove that two exclusive locks do not stack on the same handle. */
1966         torture_comment(torture, "  two exclusive locks do not stack.\n");
1967
1968         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1969                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1970         status = smb2_lock(tree, &lck);
1971         CHECK_STATUS(status, NT_STATUS_OK);
1972
1973         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1974                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1975         status = smb2_lock(tree, &lck);
1976         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1977
1978         /* cleanup */
1979         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1980         status = smb2_lock(tree, &lck);
1981         if (TARGET_IS_W2K8(torture)) {
1982                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1983                 torture_warning(torture, "Target has \"pretty please\" bug. "
1984                                 "A contending lock request on the same handle "
1985                                 "unlocks the lock.\n");
1986         } else {
1987                 CHECK_STATUS(status, NT_STATUS_OK);
1988         }
1989
1990 done:
1991         smb2_util_close(tree, h2);
1992         smb2_util_close(tree, h);
1993         smb2_deltree(tree, BASEDIR);
1994         return ret;
1995 }
1996
1997 /**
1998  * Test lock contention
1999  * - shared lock should contend with exclusive lock on different handle
2000  */
2001 static bool test_contend(struct torture_context *torture,
2002                          struct smb2_tree *tree)
2003 {
2004         NTSTATUS status;
2005         bool ret = true;
2006         struct smb2_handle h, h2;
2007         uint8_t buf[200];
2008         struct smb2_lock lck;
2009         struct smb2_lock_element el[1];
2010
2011         const char *fname = BASEDIR "\\contend.txt";
2012
2013         status = torture_smb2_testdir(tree, BASEDIR, &h);
2014         CHECK_STATUS(status, NT_STATUS_OK);
2015         smb2_util_close(tree, h);
2016
2017         status = torture_smb2_testfile(tree, fname, &h);
2018         CHECK_STATUS(status, NT_STATUS_OK);
2019
2020         ZERO_STRUCT(buf);
2021         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2022         CHECK_STATUS(status, NT_STATUS_OK);
2023
2024         status = torture_smb2_testfile(tree, fname, &h2);
2025         CHECK_STATUS(status, NT_STATUS_OK);
2026
2027         torture_comment(torture, "Testing lock contention:\n");
2028
2029         /* Setup initial parameters */
2030         lck.in.locks            = el;
2031         lck.in.lock_count       = 0x0001;
2032         lck.in.lock_sequence    = 0x00000000;
2033         lck.in.file.handle      = h;
2034         el[0].offset            = 0;
2035         el[0].length            = 10;
2036         el[0].reserved          = 0x00000000;
2037
2038         /* Take an exclusive lock, then a shared lock on different handle */
2039         torture_comment(torture, "  shared should contend on exclusive on "
2040                                  "different handle.\n");
2041
2042         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2043                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2044         status = smb2_lock(tree, &lck);
2045         CHECK_STATUS(status, NT_STATUS_OK);
2046
2047         lck.in.file.handle      = h2;
2048         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
2049                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2050         status = smb2_lock(tree, &lck);
2051         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
2052
2053         /* cleanup */
2054         lck.in.file.handle      = h;
2055         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2056         status = smb2_lock(tree, &lck);
2057         CHECK_STATUS(status, NT_STATUS_OK);
2058
2059 done:
2060         smb2_util_close(tree, h2);
2061         smb2_util_close(tree, h);
2062         smb2_deltree(tree, BASEDIR);
2063         return ret;
2064 }
2065
2066 /**
2067  * Test locker context
2068  * - test that pid does not affect the locker context
2069  */
2070 static bool test_context(struct torture_context *torture,
2071                          struct smb2_tree *tree)
2072 {
2073         NTSTATUS status;
2074         bool ret = true;
2075         struct smb2_handle h, h2;
2076         uint8_t buf[200];
2077         struct smb2_lock lck;
2078         struct smb2_lock_element el[1];
2079
2080         const char *fname = BASEDIR "\\context.txt";
2081
2082         status = torture_smb2_testdir(tree, BASEDIR, &h);
2083         CHECK_STATUS(status, NT_STATUS_OK);
2084         smb2_util_close(tree, h);
2085
2086         status = torture_smb2_testfile(tree, fname, &h);
2087         CHECK_STATUS(status, NT_STATUS_OK);
2088
2089         ZERO_STRUCT(buf);
2090         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2091         CHECK_STATUS(status, NT_STATUS_OK);
2092
2093         status = torture_smb2_testfile(tree, fname, &h2);
2094         CHECK_STATUS(status, NT_STATUS_OK);
2095
2096         torture_comment(torture, "Testing locker context:\n");
2097
2098         /* Setup initial parameters */
2099         lck.in.locks            = el;
2100         lck.in.lock_count       = 0x0001;
2101         lck.in.lock_sequence    = 0x00000000;
2102         lck.in.file.handle      = h;
2103         el[0].offset            = 0;
2104         el[0].length            = 10;
2105         el[0].reserved          = 0x00000000;
2106
2107         /* Take an exclusive lock, then try to unlock with a different pid,
2108          * same handle.  This shows that the pid doesn't affect the locker
2109          * context in SMB2. */
2110         torture_comment(torture, "  pid shouldn't affect locker context\n");
2111
2112         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2113                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2114         status = smb2_lock(tree, &lck);
2115         CHECK_STATUS(status, NT_STATUS_OK);
2116
2117         tree->session->pid++;
2118         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2119         status = smb2_lock(tree, &lck);
2120         CHECK_STATUS(status, NT_STATUS_OK);
2121
2122         tree->session->pid--;
2123         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2124         status = smb2_lock(tree, &lck);
2125         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
2126
2127 done:
2128         smb2_util_close(tree, h2);
2129         smb2_util_close(tree, h);
2130         smb2_deltree(tree, BASEDIR);
2131         return ret;
2132 }
2133
2134 /**
2135  * Test as much of the potential lock range as possible
2136  *  - test ported from BASE-LOCK-LOCK3
2137  */
2138 static bool test_range(struct torture_context *torture,
2139                        struct smb2_tree *tree)
2140 {
2141         NTSTATUS status;
2142         bool ret = true;
2143         struct smb2_handle h, h2;
2144         uint8_t buf[200];
2145         struct smb2_lock lck;
2146         struct smb2_lock_element el[1];
2147         uint64_t offset, i;
2148         extern int torture_numops;
2149
2150         const char *fname = BASEDIR "\\range.txt";
2151
2152 #define NEXT_OFFSET offset += (~(uint64_t)0) / torture_numops
2153
2154         status = torture_smb2_testdir(tree, BASEDIR, &h);
2155         CHECK_STATUS(status, NT_STATUS_OK);
2156         smb2_util_close(tree, h);
2157
2158         status = torture_smb2_testfile(tree, fname, &h);
2159         CHECK_STATUS(status, NT_STATUS_OK);
2160
2161         ZERO_STRUCT(buf);
2162         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2163         CHECK_STATUS(status, NT_STATUS_OK);
2164
2165         status = torture_smb2_testfile(tree, fname, &h2);
2166         CHECK_STATUS(status, NT_STATUS_OK);
2167
2168         torture_comment(torture, "Testing locks spread across the 64-bit "
2169                                  "offset range\n");
2170
2171         if (TARGET_IS_W2K8(torture)) {
2172                 torture_result(torture, TORTURE_SKIP,
2173                     "Target has \"pretty please\" bug. A contending lock "
2174                     "request on the same handle unlocks the lock.");
2175                 goto done;
2176         }
2177
2178         /* Setup initial parameters */
2179         lck.in.locks            = el;
2180         lck.in.lock_count       = 0x0001;
2181         lck.in.lock_sequence    = 0x00000000;
2182         lck.in.file.handle      = h;
2183         el[0].offset            = 0;
2184         el[0].length            = 1;
2185         el[0].reserved          = 0x00000000;
2186         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2187                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2188
2189         torture_comment(torture, "  establishing %d locks\n", torture_numops);
2190
2191         for (offset=i=0; i<torture_numops; i++) {
2192                 NEXT_OFFSET;
2193
2194                 lck.in.file.handle      = h;
2195                 el[0].offset            = offset - 1;
2196                 status = smb2_lock(tree, &lck);
2197                 CHECK_STATUS_CMT(status, NT_STATUS_OK,
2198                                  talloc_asprintf(torture,
2199                                      "lock h failed at offset %#llx ",
2200                                      el[0].offset));
2201
2202                 lck.in.file.handle      = h2;
2203                 el[0].offset            = offset - 2;
2204                 status = smb2_lock(tree, &lck);
2205                 CHECK_STATUS_CMT(status, NT_STATUS_OK,
2206                                  talloc_asprintf(torture,
2207                                      "lock h2 failed at offset %#llx ",
2208                                      el[0].offset));
2209         }
2210
2211         torture_comment(torture, "  testing %d locks\n", torture_numops);
2212
2213         for (offset=i=0; i<torture_numops; i++) {
2214                 NEXT_OFFSET;
2215
2216                 lck.in.file.handle      = h;
2217                 el[0].offset            = offset - 1;
2218                 status = smb2_lock(tree, &lck);
2219                 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
2220                                  talloc_asprintf(torture,
2221                                      "lock h at offset %#llx should not have "
2222                                      "succeeded ", el[0].offset));
2223
2224                 lck.in.file.handle      = h;
2225                 el[0].offset            = offset - 2;
2226                 status = smb2_lock(tree, &lck);
2227                 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
2228                                  talloc_asprintf(torture,
2229                                      "lock h2 at offset %#llx should not have "
2230                                      "succeeded ", el[0].offset));
2231
2232                 lck.in.file.handle      = h2;
2233                 el[0].offset            = offset - 1;
2234                 status = smb2_lock(tree, &lck);
2235                 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
2236                                  talloc_asprintf(torture,
2237                                      "lock h at offset %#llx should not have "
2238                                      "succeeded ", el[0].offset));
2239
2240                 lck.in.file.handle      = h2;
2241                 el[0].offset            = offset - 2;
2242                 status = smb2_lock(tree, &lck);
2243                 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
2244                                  talloc_asprintf(torture,
2245                                      "lock h2 at offset %#llx should not have "
2246                                      "succeeded ", el[0].offset));
2247         }
2248
2249         torture_comment(torture, "  removing %d locks\n", torture_numops);
2250
2251         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2252
2253         for (offset=i=0; i<torture_numops; i++) {
2254                 NEXT_OFFSET;
2255
2256                 lck.in.file.handle      = h;
2257                 el[0].offset            = offset - 1;
2258                 status = smb2_lock(tree, &lck);
2259                 CHECK_STATUS_CMT(status, NT_STATUS_OK,
2260                                  talloc_asprintf(torture,
2261                                      "unlock from h failed at offset %#llx ",
2262                                      el[0].offset));
2263
2264                 lck.in.file.handle      = h2;
2265                 el[0].offset            = offset - 2;
2266                 status = smb2_lock(tree, &lck);
2267                 CHECK_STATUS_CMT(status, NT_STATUS_OK,
2268                                  talloc_asprintf(torture,
2269                                      "unlock from h2 failed at offset %#llx ",
2270                                      el[0].offset));
2271         }
2272
2273 done:
2274         smb2_util_close(tree, h2);
2275         smb2_util_close(tree, h);
2276         smb2_deltree(tree, BASEDIR);
2277         return ret;
2278 }
2279
2280 static NTSTATUS smb2cli_lock(struct smb2_tree *tree, struct smb2_handle h,
2281                              uint64_t offset, uint64_t length, bool exclusive)
2282 {
2283         struct smb2_lock lck;
2284         struct smb2_lock_element el[1];
2285         NTSTATUS status;
2286
2287         lck.in.locks            = el;
2288         lck.in.lock_count       = 0x0001;
2289         lck.in.lock_sequence    = 0x00000000;
2290         lck.in.file.handle      = h;
2291         el[0].offset            = offset;
2292         el[0].length            = length;
2293         el[0].reserved          = 0x00000000;
2294         el[0].flags             = (exclusive ?
2295                                   SMB2_LOCK_FLAG_EXCLUSIVE :
2296                                   SMB2_LOCK_FLAG_SHARED) |
2297                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2298
2299         status = smb2_lock(tree, &lck);
2300
2301         return status;
2302 }
2303
2304 static NTSTATUS smb2cli_unlock(struct smb2_tree *tree, struct smb2_handle h,
2305                                uint64_t offset, uint64_t length)
2306 {
2307         struct smb2_lock lck;
2308         struct smb2_lock_element el[1];
2309         NTSTATUS status;
2310
2311         lck.in.locks            = el;
2312         lck.in.lock_count       = 0x0001;
2313         lck.in.lock_sequence    = 0x00000000;
2314         lck.in.file.handle      = h;
2315         el[0].offset            = offset;
2316         el[0].length            = length;
2317         el[0].reserved          = 0x00000000;
2318         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2319
2320         status = smb2_lock(tree, &lck);
2321
2322         return status;
2323 }
2324
2325 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2326         torture_result(torture, TORTURE_FAIL, __location__": subtest failed");\
2327         torture_comment(torture, "** "); correct = false; \
2328         }
2329
2330 /**
2331  * Test overlapping lock ranges from various lockers
2332  *  - some tests ported from BASE-LOCK-LOCK4
2333  */
2334 static bool test_overlap(struct torture_context *torture,
2335                          struct smb2_tree *tree,
2336                          struct smb2_tree *tree2)
2337 {
2338         NTSTATUS status;
2339         bool ret = true;
2340         struct smb2_handle h, h2, h3;
2341         uint8_t buf[200];
2342         bool correct = true;
2343
2344         const char *fname = BASEDIR "\\overlap.txt";
2345
2346         status = torture_smb2_testdir(tree, BASEDIR, &h);
2347         CHECK_STATUS(status, NT_STATUS_OK);
2348         smb2_util_close(tree, h);
2349
2350         status = torture_smb2_testfile(tree, fname, &h);
2351         CHECK_STATUS(status, NT_STATUS_OK);
2352
2353         ZERO_STRUCT(buf);
2354         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2355         CHECK_STATUS(status, NT_STATUS_OK);
2356
2357         status = torture_smb2_testfile(tree, fname, &h2);
2358         CHECK_STATUS(status, NT_STATUS_OK);
2359
2360         status = torture_smb2_testfile(tree2, fname, &h3);
2361         CHECK_STATUS(status, NT_STATUS_OK);
2362
2363         torture_comment(torture, "Testing overlapping locks:\n");
2364
2365         ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 0, 4, true)) &&
2366               NT_STATUS_IS_OK(smb2cli_lock(tree, h, 2, 4, true));
2367         EXPECTED(ret, false);
2368         torture_comment(torture, "the same session/handle %s set overlapping "
2369                                  "exclusive locks\n", ret?"can":"cannot");
2370
2371         ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 10, 4, false)) &&
2372               NT_STATUS_IS_OK(smb2cli_lock(tree, h, 12, 4, false));
2373         EXPECTED(ret, true);
2374         torture_comment(torture, "the same session/handle %s set overlapping "
2375                                  "shared locks\n", ret?"can":"cannot");
2376
2377         ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 20, 4, true)) &&
2378               NT_STATUS_IS_OK(smb2cli_lock(tree2, h3, 22, 4, true));
2379         EXPECTED(ret, false);
2380         torture_comment(torture, "a different session %s set overlapping "
2381                                  "exclusive locks\n", ret?"can":"cannot");
2382
2383         ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 30, 4, false)) &&
2384               NT_STATUS_IS_OK(smb2cli_lock(tree2, h3, 32, 4, false));
2385         EXPECTED(ret, true);
2386         torture_comment(torture, "a different session %s set overlapping "
2387                                  "shared locks\n", ret?"can":"cannot");
2388
2389         ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 40, 4, true)) &&
2390               NT_STATUS_IS_OK(smb2cli_lock(tree, h2, 42, 4, true));
2391         EXPECTED(ret, false);
2392         torture_comment(torture, "a different handle %s set overlapping "
2393                                  "exclusive locks\n", ret?"can":"cannot");
2394
2395         ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 50, 4, false)) &&
2396               NT_STATUS_IS_OK(smb2cli_lock(tree, h2, 52, 4, false));
2397         EXPECTED(ret, true);
2398         torture_comment(torture, "a different handle %s set overlapping "
2399                                  "shared locks\n", ret?"can":"cannot");
2400
2401         ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 110, 4, false)) &&
2402               NT_STATUS_IS_OK(smb2cli_lock(tree, h, 112, 4, false)) &&
2403               NT_STATUS_IS_OK(smb2cli_unlock(tree, h, 110, 6));
2404         EXPECTED(ret, false);
2405         torture_comment(torture, "the same handle %s coalesce read locks\n",
2406                                  ret?"can":"cannot");
2407
2408         smb2_util_close(tree, h2);
2409         smb2_util_close(tree, h);
2410         status = torture_smb2_testfile(tree, fname, &h);
2411         CHECK_STATUS(status, NT_STATUS_OK);
2412         status = torture_smb2_testfile(tree, fname, &h2);
2413         CHECK_STATUS(status, NT_STATUS_OK);
2414         ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 0, 8, false)) &&
2415               NT_STATUS_IS_OK(smb2cli_lock(tree, h2, 0, 1, false)) &&
2416               NT_STATUS_IS_OK(smb2_util_close(tree, h)) &&
2417               NT_STATUS_IS_OK(torture_smb2_testfile(tree, fname, &h)) &&
2418               NT_STATUS_IS_OK(smb2cli_lock(tree, h, 7, 1, true));
2419         EXPECTED(ret, true);
2420         torture_comment(torture, "the server %s have the NT byte range lock bug\n",
2421                                  !ret?"does":"doesn't");
2422
2423 done:
2424         smb2_util_close(tree2, h3);
2425         smb2_util_close(tree, h2);
2426         smb2_util_close(tree, h);
2427         smb2_deltree(tree, BASEDIR);
2428         return correct;
2429 }
2430
2431 /**
2432  * Test truncation of locked file
2433  *  - some tests ported from BASE-LOCK-LOCK7
2434  */
2435 static bool test_truncate(struct torture_context *torture,
2436                           struct smb2_tree *tree)
2437 {
2438         NTSTATUS status;
2439         bool ret = true;
2440         struct smb2_handle h, h2;
2441         uint8_t buf[200];
2442         struct smb2_lock lck;
2443         struct smb2_lock_element el[1];
2444         struct smb2_create io;
2445
2446         const char *fname = BASEDIR "\\truncate.txt";
2447
2448         status = torture_smb2_testdir(tree, BASEDIR, &h);
2449         CHECK_STATUS(status, NT_STATUS_OK);
2450         smb2_util_close(tree, h);
2451
2452         status = torture_smb2_testfile(tree, fname, &h);
2453         CHECK_STATUS(status, NT_STATUS_OK);
2454
2455         ZERO_STRUCT(buf);
2456         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2457         CHECK_STATUS(status, NT_STATUS_OK);
2458
2459         torture_comment(torture, "Testing truncation of locked file:\n");
2460
2461         /* Setup initial parameters */
2462         lck.in.locks            = el;
2463         lck.in.lock_count       = 0x0001;
2464         lck.in.lock_sequence    = 0x00000000;
2465         lck.in.file.handle      = h;
2466         el[0].offset            = 0;
2467         el[0].length            = 10;
2468         el[0].reserved          = 0x00000000;
2469
2470         ZERO_STRUCT(io);
2471         io.in.oplock_level = 0;
2472         io.in.desired_access = SEC_RIGHTS_FILE_ALL;
2473         io.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
2474         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2475         io.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
2476                              NTCREATEX_SHARE_ACCESS_READ |
2477                              NTCREATEX_SHARE_ACCESS_WRITE;
2478         io.in.create_options = 0;
2479         io.in.fname = fname;
2480
2481         /* Take an exclusive lock */
2482         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2483                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2484         status = smb2_lock(tree, &lck);
2485         CHECK_STATUS(status, NT_STATUS_OK);
2486
2487         /* On second handle open the file with OVERWRITE disposition */
2488         torture_comment(torture, "  overwrite disposition is allowed on a locked "
2489                                  "file.\n");
2490
2491         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2492         status = smb2_create(tree, tree, &io);
2493         CHECK_STATUS(status, NT_STATUS_OK);
2494         h2 = io.out.file.handle;
2495         smb2_util_close(tree, h2);
2496
2497         /* On second handle open the file with SUPERSEDE disposition */
2498         torture_comment(torture, "  supersede disposition is allowed on a locked "
2499                                  "file.\n");
2500
2501         io.in.create_disposition = NTCREATEX_DISP_SUPERSEDE;
2502         status = smb2_create(tree, tree, &io);
2503         CHECK_STATUS(status, NT_STATUS_OK);
2504         h2 = io.out.file.handle;
2505         smb2_util_close(tree, h2);
2506
2507         /* cleanup */
2508         lck.in.file.handle      = h;
2509         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2510         status = smb2_lock(tree, &lck);
2511         CHECK_STATUS(status, NT_STATUS_OK);
2512
2513 done:
2514         smb2_util_close(tree, h2);
2515         smb2_util_close(tree, h);
2516         smb2_deltree(tree, BASEDIR);
2517         return ret;
2518 }
2519
2520 /* basic testing of SMB2 locking
2521 */
2522 struct torture_suite *torture_smb2_lock_init(void)
2523 {
2524         struct torture_suite *suite =
2525             torture_suite_create(talloc_autofree_context(), "LOCK");
2526
2527         torture_suite_add_1smb2_test(suite, "VALID-REQUEST",
2528             test_valid_request);
2529         torture_suite_add_1smb2_test(suite, "RW-NONE", test_lock_rw_none);
2530         torture_suite_add_1smb2_test(suite, "RW-SHARED", test_lock_rw_shared);
2531         torture_suite_add_1smb2_test(suite, "RW-EXCLUSIVE",
2532             test_lock_rw_exclusive);
2533         torture_suite_add_1smb2_test(suite, "AUTO-UNLOCK",
2534             test_lock_auto_unlock);
2535         torture_suite_add_1smb2_test(suite, "LOCK", test_lock);
2536         torture_suite_add_1smb2_test(suite, "ASYNC", test_async);
2537         torture_suite_add_1smb2_test(suite, "CANCEL", test_cancel);
2538         torture_suite_add_1smb2_test(suite, "CANCEL-TDIS", test_cancel_tdis);
2539         torture_suite_add_1smb2_test(suite, "CANCEL-LOGOFF",
2540             test_cancel_logoff);
2541         torture_suite_add_1smb2_test(suite, "ERRORCODE", test_errorcode);
2542         torture_suite_add_1smb2_test(suite, "ZEROBYTELENGTH",
2543             test_zerobytelength);
2544         torture_suite_add_1smb2_test(suite, "UNLOCK", test_unlock);
2545         torture_suite_add_1smb2_test(suite, "MULTIPLE-UNLOCK",
2546             test_multiple_unlock);
2547         torture_suite_add_1smb2_test(suite, "STACKING", test_stacking);
2548         torture_suite_add_1smb2_test(suite, "CONTEND", test_contend);
2549         torture_suite_add_1smb2_test(suite, "CONTEXT", test_context);
2550         torture_suite_add_1smb2_test(suite, "RANGE", test_range);
2551         torture_suite_add_2smb2_test(suite, "OVERLAP", test_overlap);
2552         torture_suite_add_1smb2_test(suite, "TRUNCATE", test_truncate);
2553
2554         suite->description = talloc_strdup(suite, "SMB2-LOCK tests");
2555
2556         return suite;
2557 }