6bba7bd0e4787ae984e4bd13a197bcab366b5096
[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[2];
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         lck.in.locks            = el;
545         lck.in.lock_count       = 0x0001;
546         lck.in.file.handle      = h;
547         el[0].offset            = 0;
548         el[0].length            = 1;
549         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
550                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
551         status = smb2_lock(tree, &lck);
552         CHECK_STATUS(status, NT_STATUS_OK);
553
554         status = smb2_lock(tree, &lck);
555         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
556
557         status = smb2_lock(tree, &lck);
558         if (TARGET_IS_W2K8(torture)) {
559                 CHECK_STATUS(status, NT_STATUS_OK);
560                 torture_warning(torture, "Target has \"pretty please\" bug. "
561                                 "A contending lock request on the same handle "
562                                 "unlocks the lock.\n");
563         } else {
564                 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
565         }
566
567         status = smb2_lock(tree, &lck);
568         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
569
570 done:
571         return ret;
572 }
573
574 /*
575   test different lock ranges and see if different handles conflict
576 */
577 static bool test_lock(struct torture_context *torture,
578                       struct smb2_tree *tree)
579 {
580         NTSTATUS status;
581         bool ret = true;
582         struct smb2_handle h, h2;
583         uint8_t buf[200];
584         struct smb2_lock lck;
585         struct smb2_lock_element el[2];
586
587         const char *fname = BASEDIR "\\async.txt";
588
589         status = torture_smb2_testdir(tree, BASEDIR, &h);
590         CHECK_STATUS(status, NT_STATUS_OK);
591         smb2_util_close(tree, h);
592
593         status = torture_smb2_testfile(tree, fname, &h);
594         CHECK_STATUS(status, NT_STATUS_OK);
595
596         ZERO_STRUCT(buf);
597         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
598         CHECK_STATUS(status, NT_STATUS_OK);
599
600         status = torture_smb2_testfile(tree, fname, &h2);
601         CHECK_STATUS(status, NT_STATUS_OK);
602
603         lck.in.locks            = el;
604
605         lck.in.lock_count       = 0x0001;
606         lck.in.lock_sequence    = 0x00000000;
607         lck.in.file.handle      = h;
608         el[0].reserved          = 0x00000000;
609         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
610                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
611
612         torture_comment(torture, "Trying 0/0 lock\n");
613         el[0].offset            = 0x0000000000000000;
614         el[0].length            = 0x0000000000000000;
615         status = smb2_lock(tree, &lck);
616         CHECK_STATUS(status, NT_STATUS_OK);
617         lck.in.file.handle      = h2;
618         status = smb2_lock(tree, &lck);
619         CHECK_STATUS(status, NT_STATUS_OK);
620         lck.in.file.handle      = h;
621         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
622         status = smb2_lock(tree, &lck);
623         CHECK_STATUS(status, NT_STATUS_OK);
624
625         torture_comment(torture, "Trying 0/1 lock\n");
626         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
627                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
628         el[0].offset            = 0x0000000000000000;
629         el[0].length            = 0x0000000000000001;
630         status = smb2_lock(tree, &lck);
631         CHECK_STATUS(status, NT_STATUS_OK);
632         lck.in.file.handle      = h2;
633         status = smb2_lock(tree, &lck);
634         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
635         lck.in.file.handle      = h;
636         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
637         status = smb2_lock(tree, &lck);
638         CHECK_STATUS(status, NT_STATUS_OK);
639         status = smb2_lock(tree, &lck);
640         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
641
642         torture_comment(torture, "Trying 0xEEFFFFF lock\n");
643         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
644                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
645         el[0].offset            = 0xEEFFFFFF;
646         el[0].length            = 4000;
647         status = smb2_lock(tree, &lck);
648         CHECK_STATUS(status, NT_STATUS_OK);
649         lck.in.file.handle      = h2;
650         status = smb2_lock(tree, &lck);
651         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
652         lck.in.file.handle      = h;
653         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
654         status = smb2_lock(tree, &lck);
655         CHECK_STATUS(status, NT_STATUS_OK);
656         status = smb2_lock(tree, &lck);
657         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
658
659         torture_comment(torture, "Trying 0xEF00000 lock\n");
660         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
661                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
662         el[0].offset            = 0xEF000000;
663         el[0].length            = 4000;
664         status = smb2_lock(tree, &lck);
665         CHECK_STATUS(status, NT_STATUS_OK);
666         lck.in.file.handle      = h2;
667         status = smb2_lock(tree, &lck);
668         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
669         lck.in.file.handle      = h;
670         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
671         status = smb2_lock(tree, &lck);
672         CHECK_STATUS(status, NT_STATUS_OK);
673         status = smb2_lock(tree, &lck);
674         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
675
676         torture_comment(torture, "Trying (2^63 - 1)/1\n");
677         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
678                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
679         el[0].offset            = 1;
680         el[0].offset          <<= 63;
681         el[0].offset--;
682         el[0].length            = 1;
683         status = smb2_lock(tree, &lck);
684         CHECK_STATUS(status, NT_STATUS_OK);
685         lck.in.file.handle      = h2;
686         status = smb2_lock(tree, &lck);
687         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
688         lck.in.file.handle      = h;
689         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
690         status = smb2_lock(tree, &lck);
691         CHECK_STATUS(status, NT_STATUS_OK);
692         status = smb2_lock(tree, &lck);
693         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
694
695         torture_comment(torture, "Trying 2^63/1\n");
696         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
697                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
698         el[0].offset            = 1;
699         el[0].offset          <<= 63;
700         el[0].length            = 1;
701         status = smb2_lock(tree, &lck);
702         CHECK_STATUS(status, NT_STATUS_OK);
703         lck.in.file.handle      = h2;
704         status = smb2_lock(tree, &lck);
705         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
706         lck.in.file.handle      = h;
707         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
708         status = smb2_lock(tree, &lck);
709         CHECK_STATUS(status, NT_STATUS_OK);
710         status = smb2_lock(tree, &lck);
711         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
712
713         torture_comment(torture, "Trying max/0 lock\n");
714         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
715                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
716         el[0].offset            = ~0;
717         el[0].length            = 0;
718         status = smb2_lock(tree, &lck);
719         CHECK_STATUS(status, NT_STATUS_OK);
720         lck.in.file.handle      = h2;
721         status = smb2_lock(tree, &lck);
722         CHECK_STATUS(status, NT_STATUS_OK);
723         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
724         status = smb2_lock(tree, &lck);
725         CHECK_STATUS(status, NT_STATUS_OK);
726         lck.in.file.handle      = h;
727         status = smb2_lock(tree, &lck);
728         CHECK_STATUS(status, NT_STATUS_OK);
729         status = smb2_lock(tree, &lck);
730         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
731
732         torture_comment(torture, "Trying max/1 lock\n");
733         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
734                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
735         el[0].offset            = ~0;
736         el[0].length            = 1;
737         status = smb2_lock(tree, &lck);
738         CHECK_STATUS(status, NT_STATUS_OK);
739         lck.in.file.handle      = h2;
740         status = smb2_lock(tree, &lck);
741         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
742         lck.in.file.handle      = h;
743         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
744         status = smb2_lock(tree, &lck);
745         CHECK_STATUS(status, NT_STATUS_OK);
746         status = smb2_lock(tree, &lck);
747         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
748
749         torture_comment(torture, "Trying max/2 lock\n");
750         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
751                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
752         el[0].offset            = ~0;
753         el[0].length            = 2;
754         status = smb2_lock(tree, &lck);
755         if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(torture)) {
756                 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
757         } else {
758                 CHECK_STATUS(status, NT_STATUS_OK);
759                 el[0].flags     = SMB2_LOCK_FLAG_UNLOCK;
760                 status = smb2_lock(tree, &lck);
761                 CHECK_STATUS(status, NT_STATUS_OK);
762         }
763
764         torture_comment(torture, "Trying wrong handle unlock\n");
765         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
766                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
767         el[0].offset            = 10001;
768         el[0].length            = 40002;
769         status = smb2_lock(tree, &lck);
770         CHECK_STATUS(status, NT_STATUS_OK);
771         lck.in.file.handle      = h2;
772         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
773         status = smb2_lock(tree, &lck);
774         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
775         lck.in.file.handle      = h;
776         status = smb2_lock(tree, &lck);
777         CHECK_STATUS(status, NT_STATUS_OK);
778
779 done:
780         smb2_util_close(tree, h2);
781         smb2_util_close(tree, h);
782         smb2_deltree(tree, BASEDIR);
783         return ret;
784 }
785
786 /*
787   test SMB2 LOCK async operation
788 */
789 static bool test_async(struct torture_context *torture,
790                        struct smb2_tree *tree)
791 {
792         NTSTATUS status;
793         bool ret = true;
794         struct smb2_handle h, h2;
795         uint8_t buf[200];
796         struct smb2_lock lck;
797         struct smb2_lock_element el[2];
798         struct smb2_request *req = NULL;
799
800         const char *fname = BASEDIR "\\async.txt";
801
802         status = torture_smb2_testdir(tree, BASEDIR, &h);
803         CHECK_STATUS(status, NT_STATUS_OK);
804         smb2_util_close(tree, h);
805
806         status = torture_smb2_testfile(tree, fname, &h);
807         CHECK_STATUS(status, NT_STATUS_OK);
808
809         ZERO_STRUCT(buf);
810         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
811         CHECK_STATUS(status, NT_STATUS_OK);
812
813         status = torture_smb2_testfile(tree, fname, &h2);
814         CHECK_STATUS(status, NT_STATUS_OK);
815
816         lck.in.locks            = el;
817
818         lck.in.lock_count       = 0x0001;
819         lck.in.lock_sequence    = 0x00000000;
820         lck.in.file.handle      = h;
821         el[0].offset            = 100;
822         el[0].length            = 50;
823         el[0].reserved          = 0x00000000;
824         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
825
826         torture_comment(torture, "  Acquire first lock\n");
827         status = smb2_lock(tree, &lck);
828         CHECK_STATUS(status, NT_STATUS_OK);
829
830         torture_comment(torture, "  Second lock should pend on first\n");
831         lck.in.file.handle      = h2;
832         req = smb2_lock_send(tree, &lck);
833         WAIT_FOR_ASYNC_RESPONSE(req);
834
835         torture_comment(torture, "  Unlock first lock\n");
836         lck.in.file.handle      = h;
837         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
838         status = smb2_lock(tree, &lck);
839         CHECK_STATUS(status, NT_STATUS_OK);
840
841         torture_comment(torture, "  Second lock should now succeed\n");
842         lck.in.file.handle      = h2;
843         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
844         status = smb2_lock_recv(req, &lck);
845         CHECK_STATUS(status, NT_STATUS_OK);
846
847 done:
848         smb2_util_close(tree, h2);
849         smb2_util_close(tree, h);
850         smb2_deltree(tree, BASEDIR);
851         return ret;
852 }
853
854 /*
855   test SMB2 LOCK Cancel operation
856 */
857 static bool test_cancel(struct torture_context *torture,
858                         struct smb2_tree *tree)
859 {
860         NTSTATUS status;
861         bool ret = true;
862         struct smb2_handle h, h2;
863         uint8_t buf[200];
864         struct smb2_lock lck;
865         struct smb2_lock_element el[2];
866         struct smb2_request *req = NULL;
867
868         const char *fname = BASEDIR "\\cancel.txt";
869
870         status = torture_smb2_testdir(tree, BASEDIR, &h);
871         CHECK_STATUS(status, NT_STATUS_OK);
872         smb2_util_close(tree, h);
873
874         status = torture_smb2_testfile(tree, fname, &h);
875         CHECK_STATUS(status, NT_STATUS_OK);
876
877         ZERO_STRUCT(buf);
878         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
879         CHECK_STATUS(status, NT_STATUS_OK);
880
881         status = torture_smb2_testfile(tree, fname, &h2);
882         CHECK_STATUS(status, NT_STATUS_OK);
883
884         lck.in.locks            = el;
885
886         lck.in.lock_count       = 0x0001;
887         lck.in.lock_sequence    = 0x00000000;
888         lck.in.file.handle      = h;
889         el[0].offset            = 100;
890         el[0].length            = 10;
891         el[0].reserved          = 0x00000000;
892         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
893
894         torture_comment(torture, "Testing basic cancel\n");
895
896         torture_comment(torture, "  Acquire first lock\n");
897         status = smb2_lock(tree, &lck);
898         CHECK_STATUS(status, NT_STATUS_OK);
899
900         torture_comment(torture, "  Second lock should pend on first\n");
901         lck.in.file.handle      = h2;
902         req = smb2_lock_send(tree, &lck);
903         WAIT_FOR_ASYNC_RESPONSE(req);
904
905         torture_comment(torture, "  Cancel the second lock\n");
906         smb2_cancel(req);
907         lck.in.file.handle      = h2;
908         status = smb2_lock_recv(req, &lck);
909         CHECK_STATUS(status, NT_STATUS_CANCELLED);
910
911         torture_comment(torture, "  Unlock first lock\n");
912         lck.in.file.handle      = h;
913         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
914         status = smb2_lock(tree, &lck);
915         CHECK_STATUS(status, NT_STATUS_OK);
916
917
918         torture_comment(torture, "Testing cancel by unlock\n");
919
920         torture_comment(torture, "  Acquire first lock\n");
921         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
922         status = smb2_lock(tree, &lck);
923         CHECK_STATUS(status, NT_STATUS_OK);
924
925         torture_comment(torture, "  Second lock should pend on first\n");
926         lck.in.file.handle      = h2;
927         req = smb2_lock_send(tree, &lck);
928         WAIT_FOR_ASYNC_RESPONSE(req);
929
930         torture_comment(torture, "  Attempt to unlock pending second lock\n");
931         lck.in.file.handle      = h2;
932         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
933         status = smb2_lock(tree, &lck);
934         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
935
936         torture_comment(torture, "  Now cancel the second lock\n");
937         smb2_cancel(req);
938         lck.in.file.handle      = h2;
939         status = smb2_lock_recv(req, &lck);
940         CHECK_STATUS(status, NT_STATUS_CANCELLED);
941
942         torture_comment(torture, "  Unlock first lock\n");
943         lck.in.file.handle      = h;
944         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
945         status = smb2_lock(tree, &lck);
946         CHECK_STATUS(status, NT_STATUS_OK);
947
948
949         torture_comment(torture, "Testing cancel by close\n");
950
951         torture_comment(torture, "  Acquire first lock\n");
952         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
953         status = smb2_lock(tree, &lck);
954         CHECK_STATUS(status, NT_STATUS_OK);
955
956         torture_comment(torture, "  Second lock should pend on first\n");
957         lck.in.file.handle      = h2;
958         req = smb2_lock_send(tree, &lck);
959         WAIT_FOR_ASYNC_RESPONSE(req);
960
961         torture_comment(torture, "  Close the second lock handle\n");
962         smb2_util_close(tree, h2);
963         CHECK_STATUS(status, NT_STATUS_OK);
964
965         torture_comment(torture, "  Check pending lock reply\n");
966         status = smb2_lock_recv(req, &lck);
967         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
968
969         torture_comment(torture, "  Unlock first lock\n");
970         lck.in.file.handle      = h;
971         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
972         status = smb2_lock(tree, &lck);
973         CHECK_STATUS(status, NT_STATUS_OK);
974
975 done:
976         smb2_util_close(tree, h2);
977         smb2_util_close(tree, h);
978         smb2_deltree(tree, BASEDIR);
979         return ret;
980 }
981
982 /*
983   test SMB2 LOCK Cancel by tree disconnect
984 */
985 static bool test_cancel_tdis(struct torture_context *torture,
986                              struct smb2_tree *tree)
987 {
988         NTSTATUS status;
989         bool ret = true;
990         struct smb2_handle h, h2;
991         uint8_t buf[200];
992         struct smb2_lock lck;
993         struct smb2_lock_element el[2];
994         struct smb2_request *req = NULL;
995
996         const char *fname = BASEDIR "\\cancel_tdis.txt";
997
998         status = torture_smb2_testdir(tree, BASEDIR, &h);
999         CHECK_STATUS(status, NT_STATUS_OK);
1000         smb2_util_close(tree, h);
1001
1002         status = torture_smb2_testfile(tree, fname, &h);
1003         CHECK_STATUS(status, NT_STATUS_OK);
1004
1005         ZERO_STRUCT(buf);
1006         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1007         CHECK_STATUS(status, NT_STATUS_OK);
1008
1009         status = torture_smb2_testfile(tree, fname, &h2);
1010         CHECK_STATUS(status, NT_STATUS_OK);
1011
1012         lck.in.locks            = el;
1013
1014         lck.in.lock_count       = 0x0001;
1015         lck.in.lock_sequence    = 0x00000000;
1016         lck.in.file.handle      = h;
1017         el[0].offset            = 100;
1018         el[0].length            = 10;
1019         el[0].reserved          = 0x00000000;
1020         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
1021
1022         torture_comment(torture, "Testing cancel by tree disconnect\n");
1023
1024         status = torture_smb2_testfile(tree, fname, &h);
1025         CHECK_STATUS(status, NT_STATUS_OK);
1026
1027         status = torture_smb2_testfile(tree, fname, &h2);
1028         CHECK_STATUS(status, NT_STATUS_OK);
1029
1030         torture_comment(torture, "  Acquire first lock\n");
1031         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
1032         status = smb2_lock(tree, &lck);
1033         CHECK_STATUS(status, NT_STATUS_OK);
1034
1035         torture_comment(torture, "  Second lock should pend on first\n");
1036         lck.in.file.handle      = h2;
1037         req = smb2_lock_send(tree, &lck);
1038         WAIT_FOR_ASYNC_RESPONSE(req);
1039
1040         torture_comment(torture, "  Disconnect the tree\n");
1041         smb2_tdis(tree);
1042         CHECK_STATUS(status, NT_STATUS_OK);
1043
1044         torture_comment(torture, "  Check pending lock reply\n");
1045         status = smb2_lock_recv(req, &lck);
1046         CHECK_STATUS(status, NT_STATUS_OK);
1047
1048         torture_comment(torture, "  Attempt to unlock first lock\n");
1049         lck.in.file.handle      = h;
1050         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1051         status = smb2_lock(tree, &lck);
1052         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
1053
1054 done:
1055         smb2_util_close(tree, h2);
1056         smb2_util_close(tree, h);
1057         smb2_deltree(tree, BASEDIR);
1058         return ret;
1059 }
1060
1061 /*
1062   test SMB2 LOCK Cancel by user logoff
1063 */
1064 static bool test_cancel_logoff(struct torture_context *torture,
1065                                struct smb2_tree *tree)
1066 {
1067         NTSTATUS status;
1068         bool ret = true;
1069         struct smb2_handle h, h2;
1070         uint8_t buf[200];
1071         struct smb2_lock lck;
1072         struct smb2_lock_element el[2];
1073         struct smb2_request *req = NULL;
1074
1075         const char *fname = BASEDIR "\\cancel_tdis.txt";
1076
1077         status = torture_smb2_testdir(tree, BASEDIR, &h);
1078         CHECK_STATUS(status, NT_STATUS_OK);
1079         smb2_util_close(tree, h);
1080
1081         status = torture_smb2_testfile(tree, fname, &h);
1082         CHECK_STATUS(status, NT_STATUS_OK);
1083
1084         ZERO_STRUCT(buf);
1085         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1086         CHECK_STATUS(status, NT_STATUS_OK);
1087
1088         status = torture_smb2_testfile(tree, fname, &h2);
1089         CHECK_STATUS(status, NT_STATUS_OK);
1090
1091         lck.in.locks            = el;
1092
1093         lck.in.lock_count       = 0x0001;
1094         lck.in.lock_sequence    = 0x00000000;
1095         lck.in.file.handle      = h;
1096         el[0].offset            = 100;
1097         el[0].length            = 10;
1098         el[0].reserved          = 0x00000000;
1099         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
1100
1101         torture_comment(torture, "Testing cancel by ulogoff\n");
1102
1103         torture_comment(torture, "  Acquire first lock\n");
1104         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
1105         status = smb2_lock(tree, &lck);
1106         CHECK_STATUS(status, NT_STATUS_OK);
1107
1108         torture_comment(torture, "  Second lock should pend on first\n");
1109         lck.in.file.handle      = h2;
1110         req = smb2_lock_send(tree, &lck);
1111         WAIT_FOR_ASYNC_RESPONSE(req);
1112
1113         torture_comment(torture, "  Logoff user\n");
1114         smb2_logoff(tree->session);
1115
1116         torture_comment(torture, "  Check pending lock reply\n");
1117         status = smb2_lock_recv(req, &lck);
1118         CHECK_STATUS(status, NT_STATUS_OK);
1119
1120         torture_comment(torture, "  Attempt to unlock first lock\n");
1121         lck.in.file.handle      = h;
1122         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1123         status = smb2_lock(tree, &lck);
1124         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
1125
1126 done:
1127         smb2_util_close(tree, h2);
1128         smb2_util_close(tree, h);
1129         smb2_deltree(tree, BASEDIR);
1130         return ret;
1131 }
1132
1133 /*
1134  * Test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
1135  *
1136  * The SMBv1 protocol returns a different error code on lock acquisition
1137  * failure depending on a number of parameters, including what error code
1138  * was returned to the previous failure.
1139  *
1140  * SMBv2 has cleaned up these semantics and should always return
1141  * NT_STATUS_LOCK_NOT_GRANTED to failed lock requests, and
1142  * NT_STATUS_FILE_LOCK_CONFLICT to failed read/write requests due to a lock
1143  * being held on that range.
1144 */
1145 static bool test_errorcode(struct torture_context *torture,
1146                            struct smb2_tree *tree)
1147 {
1148         NTSTATUS status;
1149         bool ret = true;
1150         struct smb2_handle h, h2;
1151         uint8_t buf[200];
1152         struct smb2_lock lck;
1153         struct smb2_lock_element el[2];
1154
1155         const char *fname = BASEDIR "\\errorcode.txt";
1156
1157         status = torture_smb2_testdir(tree, BASEDIR, &h);
1158         CHECK_STATUS(status, NT_STATUS_OK);
1159         smb2_util_close(tree, h);
1160
1161         status = torture_smb2_testfile(tree, fname, &h);
1162         CHECK_STATUS(status, NT_STATUS_OK);
1163
1164         ZERO_STRUCT(buf);
1165         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1166         CHECK_STATUS(status, NT_STATUS_OK);
1167
1168         status = torture_smb2_testfile(tree, fname, &h2);
1169         CHECK_STATUS(status, NT_STATUS_OK);
1170
1171         lck.in.locks            = el;
1172
1173         lck.in.lock_count       = 0x0001;
1174         lck.in.lock_sequence    = 0x00000000;
1175         lck.in.file.handle      = h;
1176         el[0].offset            = 100;
1177         el[0].length            = 10;
1178         el[0].reserved          = 0x00000000;
1179         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1180                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1181
1182         torture_comment(torture, "Testing LOCK_NOT_GRANTED vs. "
1183                                  "FILE_LOCK_CONFLICT\n");
1184
1185         if (TARGET_IS_W2K8(torture)) {
1186                 torture_result(torture, TORTURE_SKIP,
1187                     "Target has \"pretty please\" bug. A contending lock "
1188                     "request on the same handle unlocks the lock.");
1189                 goto done;
1190         }
1191
1192         status = smb2_lock(tree, &lck);
1193         CHECK_STATUS(status, NT_STATUS_OK);
1194
1195         /* Demonstrate that the first conflicting lock on each handle gives
1196          * LOCK_NOT_GRANTED. */
1197         lck.in.file.handle      = h;
1198         status = smb2_lock(tree, &lck);
1199         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1200
1201         lck.in.file.handle      = h2;
1202         status = smb2_lock(tree, &lck);
1203         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1204
1205         /* Demonstrate that each following conflict also gives
1206          * LOCK_NOT_GRANTED */
1207         lck.in.file.handle      = h;
1208         status = smb2_lock(tree, &lck);
1209         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1210
1211         lck.in.file.handle      = h2;
1212         status = smb2_lock(tree, &lck);
1213         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1214
1215         lck.in.file.handle      = h;
1216         status = smb2_lock(tree, &lck);
1217         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1218
1219         lck.in.file.handle      = h2;
1220         status = smb2_lock(tree, &lck);
1221         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1222
1223         /* Demonstrate that the smbpid doesn't matter */
1224         tree->session->pid++;
1225         lck.in.file.handle      = h;
1226         status = smb2_lock(tree, &lck);
1227         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1228
1229         lck.in.file.handle      = h2;
1230         status = smb2_lock(tree, &lck);
1231         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1232         tree->session->pid--;
1233
1234         /* Demonstrate that a 0-byte lock inside the locked range still
1235          * gives the same error. */
1236
1237         el[0].offset            = 102;
1238         el[0].length            = 0;
1239         lck.in.file.handle      = h;
1240         status = smb2_lock(tree, &lck);
1241         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1242
1243         lck.in.file.handle      = h2;
1244         status = smb2_lock(tree, &lck);
1245         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1246
1247         /* Demonstrate that a lock inside the locked range still gives the
1248          * same error. */
1249
1250         el[0].offset            = 102;
1251         el[0].length            = 5;
1252         lck.in.file.handle      = h;
1253         status = smb2_lock(tree, &lck);
1254         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1255
1256         lck.in.file.handle      = h2;
1257         status = smb2_lock(tree, &lck);
1258         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1259
1260 done:
1261         smb2_util_close(tree, h2);
1262         smb2_util_close(tree, h);
1263         smb2_deltree(tree, BASEDIR);
1264         return ret;
1265 }
1266
1267 /**
1268  * Tests zero byte locks.
1269  */
1270
1271 struct double_lock_test {
1272         struct smb2_lock_element lock1;
1273         struct smb2_lock_element lock2;
1274         NTSTATUS status;
1275 };
1276
1277 static struct double_lock_test zero_byte_tests[] = {
1278         /* {offset, count, reserved, flags},
1279          * {offset, count, reserved, flags},
1280          * status */
1281
1282         /** First, takes a zero byte lock at offset 10. Then:
1283         *   - Taking 0 byte lock at 10 should succeed.
1284         *   - Taking 1 byte locks at 9,10,11 should succeed.
1285         *   - Taking 2 byte lock at 9 should fail.
1286         *   - Taking 2 byte lock at 10 should succeed.
1287         *   - Taking 3 byte lock at 9 should fail.
1288         */
1289         {{10, 0, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1290         {{10, 0, 0, 0}, {9, 1, 0, 0},  NT_STATUS_OK},
1291         {{10, 0, 0, 0}, {10, 1, 0, 0}, NT_STATUS_OK},
1292         {{10, 0, 0, 0}, {11, 1, 0, 0}, NT_STATUS_OK},
1293         {{10, 0, 0, 0}, {9, 2, 0, 0},  NT_STATUS_LOCK_NOT_GRANTED},
1294         {{10, 0, 0, 0}, {10, 2, 0, 0}, NT_STATUS_OK},
1295         {{10, 0, 0, 0}, {9, 3, 0, 0},  NT_STATUS_LOCK_NOT_GRANTED},
1296
1297         /** Same, but opposite order. */
1298         {{10, 0, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1299         {{9, 1, 0, 0},  {10, 0, 0, 0}, NT_STATUS_OK},
1300         {{10, 1, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1301         {{11, 1, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1302         {{9, 2, 0, 0},  {10, 0, 0, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1303         {{10, 2, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
1304         {{9, 3, 0, 0},  {10, 0, 0, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1305
1306         /** Zero zero case. */
1307         {{0, 0, 0, 0},  {0, 0, 0, 0},  NT_STATUS_OK},
1308 };
1309
1310 static bool test_zerobytelength(struct torture_context *torture,
1311                                 struct smb2_tree *tree)
1312 {
1313         NTSTATUS status;
1314         bool ret = true;
1315         struct smb2_handle h, h2;
1316         uint8_t buf[200];
1317         struct smb2_lock lck;
1318         int i;
1319
1320         const char *fname = BASEDIR "\\zero.txt";
1321
1322         torture_comment(torture, "Testing zero length byte range locks:\n");
1323
1324         status = torture_smb2_testdir(tree, BASEDIR, &h);
1325         CHECK_STATUS(status, NT_STATUS_OK);
1326         smb2_util_close(tree, h);
1327
1328         status = torture_smb2_testfile(tree, fname, &h);
1329         CHECK_STATUS(status, NT_STATUS_OK);
1330
1331         ZERO_STRUCT(buf);
1332         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1333         CHECK_STATUS(status, NT_STATUS_OK);
1334
1335         status = torture_smb2_testfile(tree, fname, &h2);
1336         CHECK_STATUS(status, NT_STATUS_OK);
1337
1338         /* Setup initial parameters */
1339         lck.in.lock_count       = 0x0001;
1340         lck.in.lock_sequence    = 0x00000000;
1341         lck.in.file.handle      = h;
1342
1343         /* Try every combination of locks in zero_byte_tests, using the same
1344          * handle for both locks. The first lock is assumed to succeed. The
1345          * second lock may contend, depending on the expected status. */
1346         for (i = 0; i < ARRAY_SIZE(zero_byte_tests); i++) {
1347                 torture_comment(torture,
1348                     "  ... {%llu, %llu} + {%llu, %llu} = %s\n",
1349                     zero_byte_tests[i].lock1.offset,
1350                     zero_byte_tests[i].lock1.length,
1351                     zero_byte_tests[i].lock2.offset,
1352                     zero_byte_tests[i].lock2.length,
1353                     nt_errstr(zero_byte_tests[i].status));
1354
1355                 /* Lock both locks. */
1356                 lck.in.locks            = &zero_byte_tests[i].lock1;
1357                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_EXCLUSIVE |
1358                                           SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1359                 status = smb2_lock(tree, &lck);
1360                 CHECK_STATUS(status, NT_STATUS_OK);
1361
1362                 lck.in.locks            = &zero_byte_tests[i].lock2;
1363                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_EXCLUSIVE |
1364                                           SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1365                 status = smb2_lock(tree, &lck);
1366                 CHECK_STATUS_CONT(status, zero_byte_tests[i].status);
1367
1368                 /* Unlock both locks in reverse order. */
1369                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_UNLOCK;
1370                 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1371                         status = smb2_lock(tree, &lck);
1372                         CHECK_STATUS(status, NT_STATUS_OK);
1373                 }
1374
1375                 lck.in.locks            = &zero_byte_tests[i].lock1;
1376                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_UNLOCK;
1377                 status = smb2_lock(tree, &lck);
1378                 CHECK_STATUS(status, NT_STATUS_OK);
1379         }
1380
1381         /* Try every combination of locks in zero_byte_tests, using two
1382          * different handles. */
1383         for (i = 0; i < ARRAY_SIZE(zero_byte_tests); i++) {
1384                 torture_comment(torture,
1385                     "  ... {%llu, %llu} + {%llu, %llu} = %s\n",
1386                     zero_byte_tests[i].lock1.offset,
1387                     zero_byte_tests[i].lock1.length,
1388                     zero_byte_tests[i].lock2.offset,
1389                     zero_byte_tests[i].lock2.length,
1390                     nt_errstr(zero_byte_tests[i].status));
1391
1392                 /* Lock both locks. */
1393                 lck.in.file.handle      = h;
1394                 lck.in.locks            = &zero_byte_tests[i].lock1;
1395                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_EXCLUSIVE |
1396                                           SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1397                 status = smb2_lock(tree, &lck);
1398                 CHECK_STATUS(status, NT_STATUS_OK);
1399
1400                 lck.in.file.handle      = h2;
1401                 lck.in.locks            = &zero_byte_tests[i].lock2;
1402                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_EXCLUSIVE |
1403                                           SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1404                 status = smb2_lock(tree, &lck);
1405                 CHECK_STATUS_CONT(status, zero_byte_tests[i].status);
1406
1407                 /* Unlock both locks in reverse order. */
1408                 lck.in.file.handle      = h2;
1409                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_UNLOCK;
1410                 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1411                         status = smb2_lock(tree, &lck);
1412                         CHECK_STATUS(status, NT_STATUS_OK);
1413                 }
1414
1415                 lck.in.file.handle      = h;
1416                 lck.in.locks            = &zero_byte_tests[i].lock1;
1417                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_UNLOCK;
1418                 status = smb2_lock(tree, &lck);
1419                 CHECK_STATUS(status, NT_STATUS_OK);
1420         }
1421
1422 done:
1423         smb2_util_close(tree, h2);
1424         smb2_util_close(tree, h);
1425         smb2_deltree(tree, BASEDIR);
1426         return ret;
1427 }
1428
1429 static bool test_unlock(struct torture_context *torture,
1430                         struct smb2_tree *tree)
1431 {
1432         NTSTATUS status;
1433         bool ret = true;
1434         struct smb2_handle h, h2;
1435         uint8_t buf[200];
1436         struct smb2_lock lck;
1437         struct smb2_lock_element el1[1];
1438         struct smb2_lock_element el2[1];
1439
1440         const char *fname = BASEDIR "\\unlock.txt";
1441
1442         status = torture_smb2_testdir(tree, BASEDIR, &h);
1443         CHECK_STATUS(status, NT_STATUS_OK);
1444         smb2_util_close(tree, h);
1445
1446         status = torture_smb2_testfile(tree, fname, &h);
1447         CHECK_STATUS(status, NT_STATUS_OK);
1448
1449         ZERO_STRUCT(buf);
1450         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1451         CHECK_STATUS(status, NT_STATUS_OK);
1452
1453         status = torture_smb2_testfile(tree, fname, &h2);
1454         CHECK_STATUS(status, NT_STATUS_OK);
1455
1456         /* Setup initial parameters */
1457         lck.in.locks            = el1;
1458         lck.in.lock_count       = 0x0001;
1459         lck.in.lock_sequence    = 0x00000000;
1460         el1[0].offset           = 0;
1461         el1[0].length           = 10;
1462         el1[0].reserved         = 0x00000000;
1463
1464         /* Take exclusive lock, then unlock it with a shared-unlock call. */
1465
1466         torture_comment(torture, "Testing unlock exclusive with shared\n");
1467
1468         torture_comment(torture, "  taking exclusive lock.\n");
1469         lck.in.file.handle      = h;
1470         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE;
1471         status = smb2_lock(tree, &lck);
1472         CHECK_STATUS(status, NT_STATUS_OK);
1473
1474         torture_comment(torture, "  try to unlock the exclusive with a shared "
1475                                  "unlock call.\n");
1476         el1[0].flags            = SMB2_LOCK_FLAG_SHARED |
1477                                   SMB2_LOCK_FLAG_UNLOCK;
1478         status = smb2_lock(tree, &lck);
1479         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1480
1481         torture_comment(torture, "  try shared lock on h2, to test the "
1482                                  "unlock.\n");
1483         lck.in.file.handle      = h2;
1484         el1[0].flags            = SMB2_LOCK_FLAG_SHARED |
1485                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1486         status = smb2_lock(tree, &lck);
1487         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1488
1489         torture_comment(torture, "  unlock the exclusive lock\n");
1490         lck.in.file.handle      = h;
1491         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1492         status = smb2_lock(tree, &lck);
1493         CHECK_STATUS(status, NT_STATUS_OK);
1494
1495         /* Unlock a shared lock with an exclusive-unlock call. */
1496
1497         torture_comment(torture, "Testing unlock shared with exclusive\n");
1498
1499         torture_comment(torture, "  taking shared lock.\n");
1500         lck.in.file.handle      = h;
1501         el1[0].flags            = SMB2_LOCK_FLAG_SHARED;
1502         status = smb2_lock(tree, &lck);
1503         CHECK_STATUS(status, NT_STATUS_OK);
1504
1505         torture_comment(torture, "  try to unlock the shared with an exclusive "
1506                                  "unlock call.\n");
1507         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1508                                   SMB2_LOCK_FLAG_UNLOCK;
1509         status = smb2_lock(tree, &lck);
1510         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1511
1512         torture_comment(torture, "  try exclusive lock on h2, to test the "
1513                                  "unlock.\n");
1514         lck.in.file.handle      = h2;
1515         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1516                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1517         status = smb2_lock(tree, &lck);
1518         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1519
1520         torture_comment(torture, "  unlock the exclusive lock\n");
1521         lck.in.file.handle      = h;
1522         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1523         status = smb2_lock(tree, &lck);
1524         CHECK_STATUS(status, NT_STATUS_OK);
1525
1526         /* Test unlocking of stacked 0-byte locks. SMB2 0-byte lock behavior
1527          * should be the same as >0-byte behavior.  Exclusive locks should be
1528          * unlocked before shared. */
1529
1530         torture_comment(torture, "Test unlocking stacked 0-byte locks\n");
1531
1532         lck.in.locks            = el1;
1533         lck.in.file.handle      = h;
1534         el1[0].offset           = 10;
1535         el1[0].length           = 0;
1536         el1[0].reserved         = 0x00000000;
1537         el2[0].offset           = 5;
1538         el2[0].length           = 10;
1539         el2[0].reserved         = 0x00000000;
1540
1541         /* lock 0-byte exclusive */
1542         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1543                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1544         status = smb2_lock(tree, &lck);
1545         CHECK_STATUS(status, NT_STATUS_OK);
1546
1547         /* lock 0-byte shared */
1548         el1[0].flags            = SMB2_LOCK_FLAG_SHARED |
1549                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1550         status = smb2_lock(tree, &lck);
1551         CHECK_STATUS(status, NT_STATUS_OK);
1552
1553         /* test contention */
1554         lck.in.locks            = el2;
1555         lck.in.file.handle      = h2;
1556         el2[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1557                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1558         status = smb2_lock(tree, &lck);
1559         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1560
1561         lck.in.locks            = el2;
1562         lck.in.file.handle      = h2;
1563         el2[0].flags            = SMB2_LOCK_FLAG_SHARED |
1564                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1565         status = smb2_lock(tree, &lck);
1566         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1567
1568         /* unlock */
1569         lck.in.locks            = el1;
1570         lck.in.file.handle      = h;
1571         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1572         status = smb2_lock(tree, &lck);
1573         CHECK_STATUS(status, NT_STATUS_OK);
1574
1575         /* test - can we take a shared lock? */
1576         lck.in.locks            = el2;
1577         lck.in.file.handle      = h2;
1578         el2[0].flags            = SMB2_LOCK_FLAG_SHARED |
1579                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1580         status = smb2_lock(tree, &lck);
1581         CHECK_STATUS(status, NT_STATUS_OK);
1582
1583         el2[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1584         status = smb2_lock(tree, &lck);
1585         CHECK_STATUS(status, NT_STATUS_OK);
1586
1587         /* cleanup */
1588         lck.in.locks            = el1;
1589         lck.in.file.handle      = h;
1590         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1591         status = smb2_lock(tree, &lck);
1592         CHECK_STATUS(status, NT_STATUS_OK);
1593
1594         /* Test unlocking of stacked exclusive, shared locks. Exclusive
1595          * should be unlocked before any shared. */
1596
1597         torture_comment(torture, "Test unlocking stacked exclusive/shared "
1598                                  "locks\n");
1599
1600         lck.in.locks            = el1;
1601         lck.in.file.handle      = h;
1602         el1[0].offset           = 10;
1603         el1[0].length           = 10;
1604         el1[0].reserved         = 0x00000000;
1605         el2[0].offset           = 5;
1606         el2[0].length           = 10;
1607         el2[0].reserved         = 0x00000000;
1608
1609         /* lock exclusive */
1610         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1611                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1612         status = smb2_lock(tree, &lck);
1613         CHECK_STATUS(status, NT_STATUS_OK);
1614
1615         /* lock shared */
1616         el1[0].flags            = SMB2_LOCK_FLAG_SHARED |
1617                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1618         status = smb2_lock(tree, &lck);
1619         CHECK_STATUS(status, NT_STATUS_OK);
1620
1621         /* test contention */
1622         lck.in.locks            = el2;
1623         lck.in.file.handle      = h2;
1624         el2[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
1625                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1626         status = smb2_lock(tree, &lck);
1627         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1628
1629         lck.in.locks            = el2;
1630         lck.in.file.handle      = h2;
1631         el2[0].flags            = SMB2_LOCK_FLAG_SHARED |
1632                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1633         status = smb2_lock(tree, &lck);
1634         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1635
1636         /* unlock */
1637         lck.in.locks            = el1;
1638         lck.in.file.handle      = h;
1639         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1640         status = smb2_lock(tree, &lck);
1641         CHECK_STATUS(status, NT_STATUS_OK);
1642
1643         /* test - can we take a shared lock? */
1644         lck.in.locks            = el2;
1645         lck.in.file.handle      = h2;
1646         el2[0].flags            = SMB2_LOCK_FLAG_SHARED |
1647                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1648         status = smb2_lock(tree, &lck);
1649         CHECK_STATUS(status, NT_STATUS_OK);
1650
1651         el2[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1652         status = smb2_lock(tree, &lck);
1653         CHECK_STATUS(status, NT_STATUS_OK);
1654
1655         /* cleanup */
1656         lck.in.locks            = el1;
1657         lck.in.file.handle      = h;
1658         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
1659         status = smb2_lock(tree, &lck);
1660         CHECK_STATUS(status, NT_STATUS_OK);
1661
1662 done:
1663         smb2_util_close(tree, h2);
1664         smb2_util_close(tree, h);
1665         smb2_deltree(tree, BASEDIR);
1666         return ret;
1667 }
1668
1669 static bool test_multiple_unlock(struct torture_context *torture,
1670                                  struct smb2_tree *tree)
1671 {
1672         NTSTATUS status;
1673         bool ret = true;
1674         struct smb2_handle h;
1675         uint8_t buf[200];
1676         struct smb2_lock lck;
1677         struct smb2_lock_element el[2];
1678         struct smb2_lock_element el0, el1;
1679
1680         const char *fname = BASEDIR "\\unlock_multiple.txt";
1681
1682         status = torture_smb2_testdir(tree, BASEDIR, &h);
1683         CHECK_STATUS(status, NT_STATUS_OK);
1684         smb2_util_close(tree, h);
1685
1686         status = torture_smb2_testfile(tree, fname, &h);
1687         CHECK_STATUS(status, NT_STATUS_OK);
1688
1689         ZERO_STRUCT(buf);
1690         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1691         CHECK_STATUS(status, NT_STATUS_OK);
1692
1693         torture_comment(torture, "Testing multiple unlocks:\n");
1694
1695         /* Setup initial parameters */
1696         lck.in.lock_count       = 0x0002;
1697         lck.in.lock_sequence    = 0x00000000;
1698         lck.in.file.handle      = h;
1699         el0.offset              = 0;
1700         el0.length              = 10;
1701         el0.reserved            = 0x00000000;
1702         el1.offset              = 10;
1703         el1.length              = 10;
1704         el1.reserved            = 0x00000000;
1705         el[0]                   = el0;
1706         el[1]                   = el1;
1707
1708         /* Test1: Acquire second lock, but not first. */
1709         torture_comment(torture, "  unlock 2 locks, first one not locked. "
1710                                  "Expect no locks unlocked. \n");
1711
1712         lck.in.lock_count       = 0x0001;
1713         el1.flags               = SMB2_LOCK_FLAG_EXCLUSIVE |
1714                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1715         lck.in.locks            = &el1;
1716         status = smb2_lock(tree, &lck);
1717         CHECK_STATUS(status, NT_STATUS_OK);
1718
1719         /* Try to unlock both locks */
1720         lck.in.lock_count       = 0x0002;
1721         el0.flags               = SMB2_LOCK_FLAG_UNLOCK;
1722         el1.flags               = SMB2_LOCK_FLAG_UNLOCK;
1723         el[0]                   = el0;
1724         el[1]                   = el1;
1725         lck.in.locks            = el;
1726         status = smb2_lock(tree, &lck);
1727         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1728
1729         /* Second lock should not be unlocked. */
1730         lck.in.lock_count       = 0x0001;
1731         el1.flags               = SMB2_LOCK_FLAG_EXCLUSIVE |
1732                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1733         lck.in.locks            = &el1;
1734         status = smb2_lock(tree, &lck);
1735         if (TARGET_IS_W2K8(torture)) {
1736                 CHECK_STATUS(status, NT_STATUS_OK);
1737                 torture_warning(torture, "Target has \"pretty please\" bug. "
1738                                 "A contending lock request on the same handle "
1739                                 "unlocks the lock.\n");
1740         } else {
1741                 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1742         }
1743
1744         /* cleanup */
1745         lck.in.lock_count       = 0x0001;
1746         el1.flags               = SMB2_LOCK_FLAG_UNLOCK;
1747         lck.in.locks            = &el1;
1748         status = smb2_lock(tree, &lck);
1749         CHECK_STATUS(status, NT_STATUS_OK);
1750
1751         /* Test2: Acquire first lock, but not second. */
1752         torture_comment(torture, "  unlock 2 locks, second one not locked. "
1753                                  "Expect first lock unlocked.\n");
1754
1755         lck.in.lock_count       = 0x0001;
1756         el0.flags               = SMB2_LOCK_FLAG_EXCLUSIVE |
1757                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1758         lck.in.locks            = &el0;
1759         status = smb2_lock(tree, &lck);
1760         CHECK_STATUS(status, NT_STATUS_OK);
1761
1762         /* Try to unlock both locks */
1763         lck.in.lock_count       = 0x0002;
1764         el0.flags               = SMB2_LOCK_FLAG_UNLOCK;
1765         el1.flags               = SMB2_LOCK_FLAG_UNLOCK;
1766         el[0]                   = el0;
1767         el[1]                   = el1;
1768         lck.in.locks            = el;
1769         status = smb2_lock(tree, &lck);
1770         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1771
1772         /* First lock should be unlocked. */
1773         lck.in.lock_count       = 0x0001;
1774         el0.flags               = SMB2_LOCK_FLAG_EXCLUSIVE |
1775                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1776         lck.in.locks            = &el0;
1777         status = smb2_lock(tree, &lck);
1778         CHECK_STATUS(status, NT_STATUS_OK);
1779
1780         /* cleanup */
1781         lck.in.lock_count       = 0x0001;
1782         el0.flags               = SMB2_LOCK_FLAG_UNLOCK;
1783         lck.in.locks            = &el0;
1784         status = smb2_lock(tree, &lck);
1785         CHECK_STATUS(status, NT_STATUS_OK);
1786
1787 done:
1788         smb2_util_close(tree, h);
1789         smb2_deltree(tree, BASEDIR);
1790         return ret;
1791 }
1792
1793 /**
1794  * Test lock stacking
1795  *  - some tests ported from BASE-LOCK-LOCK5
1796  */
1797 static bool test_stacking(struct torture_context *torture,
1798                           struct smb2_tree *tree)
1799 {
1800         NTSTATUS status;
1801         bool ret = true;
1802         struct smb2_handle h, h2;
1803         uint8_t buf[200];
1804         struct smb2_lock lck;
1805         struct smb2_lock_element el[1];
1806
1807         const char *fname = BASEDIR "\\stacking.txt";
1808
1809         status = torture_smb2_testdir(tree, BASEDIR, &h);
1810         CHECK_STATUS(status, NT_STATUS_OK);
1811         smb2_util_close(tree, h);
1812
1813         status = torture_smb2_testfile(tree, fname, &h);
1814         CHECK_STATUS(status, NT_STATUS_OK);
1815
1816         ZERO_STRUCT(buf);
1817         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
1818         CHECK_STATUS(status, NT_STATUS_OK);
1819
1820         status = torture_smb2_testfile(tree, fname, &h2);
1821         CHECK_STATUS(status, NT_STATUS_OK);
1822
1823         torture_comment(torture, "Testing lock stacking:\n");
1824
1825         /* Setup initial parameters */
1826         lck.in.locks            = el;
1827         lck.in.lock_count       = 0x0001;
1828         lck.in.lock_sequence    = 0x00000000;
1829         lck.in.file.handle      = h;
1830         el[0].offset            = 0;
1831         el[0].length            = 10;
1832         el[0].reserved          = 0x00000000;
1833
1834         /* Try to take a shared lock, then a shared lock on same handle */
1835         torture_comment(torture, "  stacking a shared on top of a shared"
1836                                  "lock succeeds.\n");
1837
1838         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
1839                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1840         status = smb2_lock(tree, &lck);
1841         CHECK_STATUS(status, NT_STATUS_OK);
1842
1843         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
1844                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1845         status = smb2_lock(tree, &lck);
1846         CHECK_STATUS(status, NT_STATUS_OK);
1847
1848         /* cleanup */
1849         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1850         status = smb2_lock(tree, &lck);
1851         CHECK_STATUS(status, NT_STATUS_OK);
1852
1853         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1854         status = smb2_lock(tree, &lck);
1855         CHECK_STATUS(status, NT_STATUS_OK);
1856
1857
1858         /* Try to take an exclusive lock, then a shared lock on same handle */
1859         torture_comment(torture, "  stacking a shared on top of an exclusive "
1860                                  "lock succeeds.\n");
1861
1862         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1863                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1864         status = smb2_lock(tree, &lck);
1865         CHECK_STATUS(status, NT_STATUS_OK);
1866
1867         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
1868                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1869         status = smb2_lock(tree, &lck);
1870         CHECK_STATUS(status, NT_STATUS_OK);
1871
1872         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
1873                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1874         status = smb2_lock(tree, &lck);
1875         CHECK_STATUS(status, NT_STATUS_OK);
1876
1877         /* stacking a shared from a different handle should fail */
1878         lck.in.file.handle      = h2;
1879         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
1880                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1881         status = smb2_lock(tree, &lck);
1882         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1883
1884         /* cleanup */
1885         lck.in.file.handle      = h;
1886         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1887         status = smb2_lock(tree, &lck);
1888         CHECK_STATUS(status, NT_STATUS_OK);
1889
1890         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1891         status = smb2_lock(tree, &lck);
1892         CHECK_STATUS(status, NT_STATUS_OK);
1893
1894         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1895         status = smb2_lock(tree, &lck);
1896         CHECK_STATUS(status, NT_STATUS_OK);
1897
1898         /* ensure the 4th unlock fails */
1899         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1900         status = smb2_lock(tree, &lck);
1901         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1902
1903         /* ensure a second handle can now take an exclusive lock */
1904         lck.in.file.handle      = h2;
1905         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
1906                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1907         status = smb2_lock(tree, &lck);
1908         CHECK_STATUS(status, NT_STATUS_OK);
1909
1910         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1911         status = smb2_lock(tree, &lck);
1912         CHECK_STATUS(status, NT_STATUS_OK);
1913
1914         /* Try to take an exclusive lock, then a shared lock on a
1915          * different handle */
1916         torture_comment(torture, "  stacking a shared on top of an exclusive "
1917                                  "lock with different handles fails.\n");
1918
1919         lck.in.file.handle      = h;
1920         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1921                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1922         status = smb2_lock(tree, &lck);
1923         CHECK_STATUS(status, NT_STATUS_OK);
1924
1925         lck.in.file.handle      = h2;
1926         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
1927                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1928         status = smb2_lock(tree, &lck);
1929         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1930
1931         /* cleanup */
1932         lck.in.file.handle      = h;
1933         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1934         status = smb2_lock(tree, &lck);
1935         CHECK_STATUS(status, NT_STATUS_OK);
1936
1937         /* Try to take a shared lock, then stack an exclusive with same
1938          * handle.  */
1939         torture_comment(torture, "  stacking an exclusive on top of a shared "
1940                                  "lock fails.\n");
1941
1942         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
1943                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1944         status = smb2_lock(tree, &lck);
1945         CHECK_STATUS(status, NT_STATUS_OK);
1946
1947         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1948                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1949         status = smb2_lock(tree, &lck);
1950         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1951
1952         /* cleanup */
1953         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1954         status = smb2_lock(tree, &lck);
1955         if (TARGET_IS_W2K8(torture)) {
1956                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1957                 torture_warning(torture, "Target has \"pretty please\" bug. "
1958                                 "A contending lock request on the same handle "
1959                                 "unlocks the lock.\n");
1960         } else {
1961                 CHECK_STATUS(status, NT_STATUS_OK);
1962         }
1963
1964         /* Prove that two exclusive locks do not stack on the same handle. */
1965         torture_comment(torture, "  two exclusive locks do not stack.\n");
1966
1967         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1968                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1969         status = smb2_lock(tree, &lck);
1970         CHECK_STATUS(status, NT_STATUS_OK);
1971
1972         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
1973                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1974         status = smb2_lock(tree, &lck);
1975         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1976
1977         /* cleanup */
1978         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
1979         status = smb2_lock(tree, &lck);
1980         if (TARGET_IS_W2K8(torture)) {
1981                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1982                 torture_warning(torture, "Target has \"pretty please\" bug. "
1983                                 "A contending lock request on the same handle "
1984                                 "unlocks the lock.\n");
1985         } else {
1986                 CHECK_STATUS(status, NT_STATUS_OK);
1987         }
1988
1989 done:
1990         smb2_util_close(tree, h2);
1991         smb2_util_close(tree, h);
1992         smb2_deltree(tree, BASEDIR);
1993         return ret;
1994 }
1995
1996 /**
1997  * Test lock contention
1998  * - shared lock should contend with exclusive lock on different handle
1999  */
2000 static bool test_contend(struct torture_context *torture,
2001                          struct smb2_tree *tree)
2002 {
2003         NTSTATUS status;
2004         bool ret = true;
2005         struct smb2_handle h, h2;
2006         uint8_t buf[200];
2007         struct smb2_lock lck;
2008         struct smb2_lock_element el[1];
2009
2010         const char *fname = BASEDIR "\\contend.txt";
2011
2012         status = torture_smb2_testdir(tree, BASEDIR, &h);
2013         CHECK_STATUS(status, NT_STATUS_OK);
2014         smb2_util_close(tree, h);
2015
2016         status = torture_smb2_testfile(tree, fname, &h);
2017         CHECK_STATUS(status, NT_STATUS_OK);
2018
2019         ZERO_STRUCT(buf);
2020         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2021         CHECK_STATUS(status, NT_STATUS_OK);
2022
2023         status = torture_smb2_testfile(tree, fname, &h2);
2024         CHECK_STATUS(status, NT_STATUS_OK);
2025
2026         torture_comment(torture, "Testing lock contention:\n");
2027
2028         /* Setup initial parameters */
2029         lck.in.locks            = el;
2030         lck.in.lock_count       = 0x0001;
2031         lck.in.lock_sequence    = 0x00000000;
2032         lck.in.file.handle      = h;
2033         el[0].offset            = 0;
2034         el[0].length            = 10;
2035         el[0].reserved          = 0x00000000;
2036
2037         /* Take an exclusive lock, then a shared lock on different handle */
2038         torture_comment(torture, "  shared should contend on exclusive on "
2039                                  "different handle.\n");
2040
2041         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2042                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2043         status = smb2_lock(tree, &lck);
2044         CHECK_STATUS(status, NT_STATUS_OK);
2045
2046         lck.in.file.handle      = h2;
2047         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
2048                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2049         status = smb2_lock(tree, &lck);
2050         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
2051
2052         /* cleanup */
2053         lck.in.file.handle      = h;
2054         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2055         status = smb2_lock(tree, &lck);
2056         CHECK_STATUS(status, NT_STATUS_OK);
2057
2058 done:
2059         smb2_util_close(tree, h2);
2060         smb2_util_close(tree, h);
2061         smb2_deltree(tree, BASEDIR);
2062         return ret;
2063 }
2064
2065 /**
2066  * Test locker context
2067  * - test that pid does not affect the locker context
2068  */
2069 static bool test_context(struct torture_context *torture,
2070                          struct smb2_tree *tree)
2071 {
2072         NTSTATUS status;
2073         bool ret = true;
2074         struct smb2_handle h, h2;
2075         uint8_t buf[200];
2076         struct smb2_lock lck;
2077         struct smb2_lock_element el[1];
2078
2079         const char *fname = BASEDIR "\\context.txt";
2080
2081         status = torture_smb2_testdir(tree, BASEDIR, &h);
2082         CHECK_STATUS(status, NT_STATUS_OK);
2083         smb2_util_close(tree, h);
2084
2085         status = torture_smb2_testfile(tree, fname, &h);
2086         CHECK_STATUS(status, NT_STATUS_OK);
2087
2088         ZERO_STRUCT(buf);
2089         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2090         CHECK_STATUS(status, NT_STATUS_OK);
2091
2092         status = torture_smb2_testfile(tree, fname, &h2);
2093         CHECK_STATUS(status, NT_STATUS_OK);
2094
2095         torture_comment(torture, "Testing locker context:\n");
2096
2097         /* Setup initial parameters */
2098         lck.in.locks            = el;
2099         lck.in.lock_count       = 0x0001;
2100         lck.in.lock_sequence    = 0x00000000;
2101         lck.in.file.handle      = h;
2102         el[0].offset            = 0;
2103         el[0].length            = 10;
2104         el[0].reserved          = 0x00000000;
2105
2106         /* Take an exclusive lock, then try to unlock with a different pid,
2107          * same handle.  This shows that the pid doesn't affect the locker
2108          * context in SMB2. */
2109         torture_comment(torture, "  pid shouldn't affect locker context\n");
2110
2111         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2112                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2113         status = smb2_lock(tree, &lck);
2114         CHECK_STATUS(status, NT_STATUS_OK);
2115
2116         tree->session->pid++;
2117         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2118         status = smb2_lock(tree, &lck);
2119         CHECK_STATUS(status, NT_STATUS_OK);
2120
2121         tree->session->pid--;
2122         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2123         status = smb2_lock(tree, &lck);
2124         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
2125
2126 done:
2127         smb2_util_close(tree, h2);
2128         smb2_util_close(tree, h);
2129         smb2_deltree(tree, BASEDIR);
2130         return ret;
2131 }
2132
2133 /**
2134  * Test as much of the potential lock range as possible
2135  *  - test ported from BASE-LOCK-LOCK3
2136  */
2137 static bool test_range(struct torture_context *torture,
2138                        struct smb2_tree *tree)
2139 {
2140         NTSTATUS status;
2141         bool ret = true;
2142         struct smb2_handle h, h2;
2143         uint8_t buf[200];
2144         struct smb2_lock lck;
2145         struct smb2_lock_element el[1];
2146         uint64_t offset, i;
2147         extern int torture_numops;
2148
2149         const char *fname = BASEDIR "\\range.txt";
2150
2151 #define NEXT_OFFSET offset += (~(uint64_t)0) / torture_numops
2152
2153         status = torture_smb2_testdir(tree, BASEDIR, &h);
2154         CHECK_STATUS(status, NT_STATUS_OK);
2155         smb2_util_close(tree, h);
2156
2157         status = torture_smb2_testfile(tree, fname, &h);
2158         CHECK_STATUS(status, NT_STATUS_OK);
2159
2160         ZERO_STRUCT(buf);
2161         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2162         CHECK_STATUS(status, NT_STATUS_OK);
2163
2164         status = torture_smb2_testfile(tree, fname, &h2);
2165         CHECK_STATUS(status, NT_STATUS_OK);
2166
2167         torture_comment(torture, "Testing locks spread across the 64-bit "
2168                                  "offset range\n");
2169
2170         if (TARGET_IS_W2K8(torture)) {
2171                 torture_result(torture, TORTURE_SKIP,
2172                     "Target has \"pretty please\" bug. A contending lock "
2173                     "request on the same handle unlocks the lock.");
2174                 goto done;
2175         }
2176
2177         /* Setup initial parameters */
2178         lck.in.locks            = el;
2179         lck.in.lock_count       = 0x0001;
2180         lck.in.lock_sequence    = 0x00000000;
2181         lck.in.file.handle      = h;
2182         el[0].offset            = 0;
2183         el[0].length            = 1;
2184         el[0].reserved          = 0x00000000;
2185         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2186                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2187
2188         torture_comment(torture, "  establishing %d locks\n", torture_numops);
2189
2190         for (offset=i=0; i<torture_numops; i++) {
2191                 NEXT_OFFSET;
2192
2193                 lck.in.file.handle      = h;
2194                 el[0].offset            = offset - 1;
2195                 status = smb2_lock(tree, &lck);
2196                 CHECK_STATUS_CMT(status, NT_STATUS_OK,
2197                                  talloc_asprintf(torture,
2198                                      "lock h failed at offset %#llx ",
2199                                      el[0].offset));
2200
2201                 lck.in.file.handle      = h2;
2202                 el[0].offset            = offset - 2;
2203                 status = smb2_lock(tree, &lck);
2204                 CHECK_STATUS_CMT(status, NT_STATUS_OK,
2205                                  talloc_asprintf(torture,
2206                                      "lock h2 failed at offset %#llx ",
2207                                      el[0].offset));
2208         }
2209
2210         torture_comment(torture, "  testing %d locks\n", torture_numops);
2211
2212         for (offset=i=0; i<torture_numops; i++) {
2213                 NEXT_OFFSET;
2214
2215                 lck.in.file.handle      = h;
2216                 el[0].offset            = offset - 1;
2217                 status = smb2_lock(tree, &lck);
2218                 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
2219                                  talloc_asprintf(torture,
2220                                      "lock h at offset %#llx should not have "
2221                                      "succeeded ", el[0].offset));
2222
2223                 lck.in.file.handle      = h;
2224                 el[0].offset            = offset - 2;
2225                 status = smb2_lock(tree, &lck);
2226                 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
2227                                  talloc_asprintf(torture,
2228                                      "lock h2 at offset %#llx should not have "
2229                                      "succeeded ", el[0].offset));
2230
2231                 lck.in.file.handle      = h2;
2232                 el[0].offset            = offset - 1;
2233                 status = smb2_lock(tree, &lck);
2234                 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
2235                                  talloc_asprintf(torture,
2236                                      "lock h at offset %#llx should not have "
2237                                      "succeeded ", el[0].offset));
2238
2239                 lck.in.file.handle      = h2;
2240                 el[0].offset            = offset - 2;
2241                 status = smb2_lock(tree, &lck);
2242                 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
2243                                  talloc_asprintf(torture,
2244                                      "lock h2 at offset %#llx should not have "
2245                                      "succeeded ", el[0].offset));
2246         }
2247
2248         torture_comment(torture, "  removing %d locks\n", torture_numops);
2249
2250         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2251
2252         for (offset=i=0; i<torture_numops; i++) {
2253                 NEXT_OFFSET;
2254
2255                 lck.in.file.handle      = h;
2256                 el[0].offset            = offset - 1;
2257                 status = smb2_lock(tree, &lck);
2258                 CHECK_STATUS_CMT(status, NT_STATUS_OK,
2259                                  talloc_asprintf(torture,
2260                                      "unlock from h failed at offset %#llx ",
2261                                      el[0].offset));
2262
2263                 lck.in.file.handle      = h2;
2264                 el[0].offset            = offset - 2;
2265                 status = smb2_lock(tree, &lck);
2266                 CHECK_STATUS_CMT(status, NT_STATUS_OK,
2267                                  talloc_asprintf(torture,
2268                                      "unlock from h2 failed at offset %#llx ",
2269                                      el[0].offset));
2270         }
2271
2272 done:
2273         smb2_util_close(tree, h2);
2274         smb2_util_close(tree, h);
2275         smb2_deltree(tree, BASEDIR);
2276         return ret;
2277 }
2278
2279 static NTSTATUS smb2cli_lock(struct smb2_tree *tree, struct smb2_handle h,
2280                              uint64_t offset, uint64_t length, bool exclusive)
2281 {
2282         struct smb2_lock lck;
2283         struct smb2_lock_element el[1];
2284         NTSTATUS status;
2285
2286         lck.in.locks            = el;
2287         lck.in.lock_count       = 0x0001;
2288         lck.in.lock_sequence    = 0x00000000;
2289         lck.in.file.handle      = h;
2290         el[0].offset            = offset;
2291         el[0].length            = length;
2292         el[0].reserved          = 0x00000000;
2293         el[0].flags             = (exclusive ?
2294                                   SMB2_LOCK_FLAG_EXCLUSIVE :
2295                                   SMB2_LOCK_FLAG_SHARED) |
2296                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2297
2298         status = smb2_lock(tree, &lck);
2299
2300         return status;
2301 }
2302
2303 static NTSTATUS smb2cli_unlock(struct smb2_tree *tree, struct smb2_handle h,
2304                                uint64_t offset, uint64_t length)
2305 {
2306         struct smb2_lock lck;
2307         struct smb2_lock_element el[1];
2308         NTSTATUS status;
2309
2310         lck.in.locks            = el;
2311         lck.in.lock_count       = 0x0001;
2312         lck.in.lock_sequence    = 0x00000000;
2313         lck.in.file.handle      = h;
2314         el[0].offset            = offset;
2315         el[0].length            = length;
2316         el[0].reserved          = 0x00000000;
2317         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2318
2319         status = smb2_lock(tree, &lck);
2320
2321         return status;
2322 }
2323
2324 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2325         torture_result(torture, TORTURE_FAIL, __location__": subtest failed");\
2326         torture_comment(torture, "** "); correct = false; \
2327         }
2328
2329 /**
2330  * Test overlapping lock ranges from various lockers
2331  *  - some tests ported from BASE-LOCK-LOCK4
2332  */
2333 static bool test_overlap(struct torture_context *torture,
2334                          struct smb2_tree *tree,
2335                          struct smb2_tree *tree2)
2336 {
2337         NTSTATUS status;
2338         bool ret = true;
2339         struct smb2_handle h, h2, h3;
2340         uint8_t buf[200];
2341         bool correct = true;
2342
2343         const char *fname = BASEDIR "\\overlap.txt";
2344
2345         status = torture_smb2_testdir(tree, BASEDIR, &h);
2346         CHECK_STATUS(status, NT_STATUS_OK);
2347         smb2_util_close(tree, h);
2348
2349         status = torture_smb2_testfile(tree, fname, &h);
2350         CHECK_STATUS(status, NT_STATUS_OK);
2351
2352         ZERO_STRUCT(buf);
2353         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2354         CHECK_STATUS(status, NT_STATUS_OK);
2355
2356         status = torture_smb2_testfile(tree, fname, &h2);
2357         CHECK_STATUS(status, NT_STATUS_OK);
2358
2359         status = torture_smb2_testfile(tree2, fname, &h3);
2360         CHECK_STATUS(status, NT_STATUS_OK);
2361
2362         torture_comment(torture, "Testing overlapping locks:\n");
2363
2364         ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 0, 4, true)) &&
2365               NT_STATUS_IS_OK(smb2cli_lock(tree, h, 2, 4, true));
2366         EXPECTED(ret, false);
2367         torture_comment(torture, "the same session/handle %s set overlapping "
2368                                  "exclusive locks\n", ret?"can":"cannot");
2369
2370         ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 10, 4, false)) &&
2371               NT_STATUS_IS_OK(smb2cli_lock(tree, h, 12, 4, false));
2372         EXPECTED(ret, true);
2373         torture_comment(torture, "the same session/handle %s set overlapping "
2374                                  "shared locks\n", ret?"can":"cannot");
2375
2376         ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 20, 4, true)) &&
2377               NT_STATUS_IS_OK(smb2cli_lock(tree2, h3, 22, 4, true));
2378         EXPECTED(ret, false);
2379         torture_comment(torture, "a different session %s set overlapping "
2380                                  "exclusive locks\n", ret?"can":"cannot");
2381
2382         ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 30, 4, false)) &&
2383               NT_STATUS_IS_OK(smb2cli_lock(tree2, h3, 32, 4, false));
2384         EXPECTED(ret, true);
2385         torture_comment(torture, "a different session %s set overlapping "
2386                                  "shared locks\n", ret?"can":"cannot");
2387
2388         ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 40, 4, true)) &&
2389               NT_STATUS_IS_OK(smb2cli_lock(tree, h2, 42, 4, true));
2390         EXPECTED(ret, false);
2391         torture_comment(torture, "a different handle %s set overlapping "
2392                                  "exclusive locks\n", ret?"can":"cannot");
2393
2394         ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 50, 4, false)) &&
2395               NT_STATUS_IS_OK(smb2cli_lock(tree, h2, 52, 4, false));
2396         EXPECTED(ret, true);
2397         torture_comment(torture, "a different handle %s set overlapping "
2398                                  "shared locks\n", ret?"can":"cannot");
2399
2400         ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 110, 4, false)) &&
2401               NT_STATUS_IS_OK(smb2cli_lock(tree, h, 112, 4, false)) &&
2402               NT_STATUS_IS_OK(smb2cli_unlock(tree, h, 110, 6));
2403         EXPECTED(ret, false);
2404         torture_comment(torture, "the same handle %s coalesce read locks\n",
2405                                  ret?"can":"cannot");
2406
2407         smb2_util_close(tree, h2);
2408         smb2_util_close(tree, h);
2409         status = torture_smb2_testfile(tree, fname, &h);
2410         CHECK_STATUS(status, NT_STATUS_OK);
2411         status = torture_smb2_testfile(tree, fname, &h2);
2412         CHECK_STATUS(status, NT_STATUS_OK);
2413         ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 0, 8, false)) &&
2414               NT_STATUS_IS_OK(smb2cli_lock(tree, h2, 0, 1, false)) &&
2415               NT_STATUS_IS_OK(smb2_util_close(tree, h)) &&
2416               NT_STATUS_IS_OK(torture_smb2_testfile(tree, fname, &h)) &&
2417               NT_STATUS_IS_OK(smb2cli_lock(tree, h, 7, 1, true));
2418         EXPECTED(ret, true);
2419         torture_comment(torture, "the server %s have the NT byte range lock bug\n",
2420                                  !ret?"does":"doesn't");
2421
2422 done:
2423         smb2_util_close(tree2, h3);
2424         smb2_util_close(tree, h2);
2425         smb2_util_close(tree, h);
2426         smb2_deltree(tree, BASEDIR);
2427         return correct;
2428 }
2429
2430 /**
2431  * Test truncation of locked file
2432  *  - some tests ported from BASE-LOCK-LOCK7
2433  */
2434 static bool test_truncate(struct torture_context *torture,
2435                           struct smb2_tree *tree)
2436 {
2437         NTSTATUS status;
2438         bool ret = true;
2439         struct smb2_handle h, h2;
2440         uint8_t buf[200];
2441         struct smb2_lock lck;
2442         struct smb2_lock_element el[1];
2443         struct smb2_create io;
2444
2445         const char *fname = BASEDIR "\\truncate.txt";
2446
2447         status = torture_smb2_testdir(tree, BASEDIR, &h);
2448         CHECK_STATUS(status, NT_STATUS_OK);
2449         smb2_util_close(tree, h);
2450
2451         status = torture_smb2_testfile(tree, fname, &h);
2452         CHECK_STATUS(status, NT_STATUS_OK);
2453
2454         ZERO_STRUCT(buf);
2455         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
2456         CHECK_STATUS(status, NT_STATUS_OK);
2457
2458         torture_comment(torture, "Testing truncation of locked file:\n");
2459
2460         /* Setup initial parameters */
2461         lck.in.locks            = el;
2462         lck.in.lock_count       = 0x0001;
2463         lck.in.lock_sequence    = 0x00000000;
2464         lck.in.file.handle      = h;
2465         el[0].offset            = 0;
2466         el[0].length            = 10;
2467         el[0].reserved          = 0x00000000;
2468
2469         ZERO_STRUCT(io);
2470         io.in.oplock_level = 0;
2471         io.in.desired_access = SEC_RIGHTS_FILE_ALL;
2472         io.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
2473         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2474         io.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
2475                              NTCREATEX_SHARE_ACCESS_READ |
2476                              NTCREATEX_SHARE_ACCESS_WRITE;
2477         io.in.create_options = 0;
2478         io.in.fname = fname;
2479
2480         /* Take an exclusive lock */
2481         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
2482                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2483         status = smb2_lock(tree, &lck);
2484         CHECK_STATUS(status, NT_STATUS_OK);
2485
2486         /* On second handle open the file with OVERWRITE disposition */
2487         torture_comment(torture, "  overwrite disposition is allowed on a locked "
2488                                  "file.\n");
2489
2490         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2491         status = smb2_create(tree, tree, &io);
2492         CHECK_STATUS(status, NT_STATUS_OK);
2493         h2 = io.out.file.handle;
2494         smb2_util_close(tree, h2);
2495
2496         /* On second handle open the file with SUPERSEDE disposition */
2497         torture_comment(torture, "  supersede disposition is allowed on a locked "
2498                                  "file.\n");
2499
2500         io.in.create_disposition = NTCREATEX_DISP_SUPERSEDE;
2501         status = smb2_create(tree, tree, &io);
2502         CHECK_STATUS(status, NT_STATUS_OK);
2503         h2 = io.out.file.handle;
2504         smb2_util_close(tree, h2);
2505
2506         /* cleanup */
2507         lck.in.file.handle      = h;
2508         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
2509         status = smb2_lock(tree, &lck);
2510         CHECK_STATUS(status, NT_STATUS_OK);
2511
2512 done:
2513         smb2_util_close(tree, h2);
2514         smb2_util_close(tree, h);
2515         smb2_deltree(tree, BASEDIR);
2516         return ret;
2517 }
2518
2519 /* basic testing of SMB2 locking
2520 */
2521 struct torture_suite *torture_smb2_lock_init(void)
2522 {
2523         struct torture_suite *suite =
2524             torture_suite_create(talloc_autofree_context(), "LOCK");
2525
2526         torture_suite_add_1smb2_test(suite, "VALID-REQUEST",
2527             test_valid_request);
2528         torture_suite_add_1smb2_test(suite, "RW-NONE", test_lock_rw_none);
2529         torture_suite_add_1smb2_test(suite, "RW-SHARED", test_lock_rw_shared);
2530         torture_suite_add_1smb2_test(suite, "RW-EXCLUSIVE",
2531             test_lock_rw_exclusive);
2532         torture_suite_add_1smb2_test(suite, "AUTO-UNLOCK",
2533             test_lock_auto_unlock);
2534         torture_suite_add_1smb2_test(suite, "LOCK", test_lock);
2535         torture_suite_add_1smb2_test(suite, "ASYNC", test_async);
2536         torture_suite_add_1smb2_test(suite, "CANCEL", test_cancel);
2537         torture_suite_add_1smb2_test(suite, "CANCEL-TDIS", test_cancel_tdis);
2538         torture_suite_add_1smb2_test(suite, "CANCEL-LOGOFF",
2539             test_cancel_logoff);
2540         torture_suite_add_1smb2_test(suite, "ERRORCODE", test_errorcode);
2541         torture_suite_add_1smb2_test(suite, "ZEROBYTELENGTH",
2542             test_zerobytelength);
2543         torture_suite_add_1smb2_test(suite, "UNLOCK", test_unlock);
2544         torture_suite_add_1smb2_test(suite, "MULTIPLE-UNLOCK",
2545             test_multiple_unlock);
2546         torture_suite_add_1smb2_test(suite, "STACKING", test_stacking);
2547         torture_suite_add_1smb2_test(suite, "CONTEND", test_contend);
2548         torture_suite_add_1smb2_test(suite, "CONTEXT", test_context);
2549         torture_suite_add_1smb2_test(suite, "RANGE", test_range);
2550         torture_suite_add_2smb2_test(suite, "OVERLAP", test_overlap);
2551         torture_suite_add_1smb2_test(suite, "TRUNCATE", test_truncate);
2552
2553         suite->description = talloc_strdup(suite, "SMB2-LOCK tests");
2554
2555         return suite;
2556 }