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