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