2
Unix SMB/CIFS implementation.
6
Copyright (C) Stefan Metzmacher 2006
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.
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.
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/>.
23
#include "libcli/smb2/smb2.h"
24
#include "libcli/smb2/smb2_calls.h"
26
#include "torture/torture.h"
27
#include "torture/smb2/proto.h"
29
#include "librpc/gen_ndr/ndr_security.h"
31
#define CHECK_STATUS(status, correct) do { \
32
if (!NT_STATUS_EQUAL(status, correct)) { \
33
printf("(%s) Incorrect status %s - should be %s\n", \
34
__location__, nt_errstr(status), nt_errstr(correct)); \
39
#define CHECK_VALUE(v, correct) do { \
40
if ((v) != (correct)) { \
41
printf("(%s) Incorrect value %s=%d - should be %d\n", \
42
__location__, #v, v, correct); \
47
static bool test_valid_request(struct torture_context *torture, struct smb2_tree *tree)
54
struct smb2_lock_element el[2];
58
status = torture_smb2_testfile(tree, "lock1.txt", &h);
59
CHECK_STATUS(status, NT_STATUS_OK);
61
status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
62
CHECK_STATUS(status, NT_STATUS_OK);
66
lck.in.lock_count = 0x0000;
67
lck.in.reserved = 0x00000000;
68
lck.in.file.handle = h;
69
el[0].offset = 0x0000000000000000;
70
el[0].length = 0x0000000000000000;
71
el[0].reserved = 0x0000000000000000;
72
el[0].flags = 0x00000000;
73
status = smb2_lock(tree, &lck);
74
CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
76
lck.in.lock_count = 0x0001;
77
lck.in.reserved = 0x00000000;
78
lck.in.file.handle = h;
81
el[0].reserved = 0x00000000;
82
el[0].flags = SMB2_LOCK_FLAG_NONE;
83
status = smb2_lock(tree, &lck);
84
CHECK_STATUS(status, NT_STATUS_OK);
85
CHECK_VALUE(lck.out.reserved, 0);
87
lck.in.file.handle.data[0] +=1;
88
status = smb2_lock(tree, &lck);
89
CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
90
lck.in.file.handle.data[0] -=1;
92
lck.in.lock_count = 0x0001;
93
lck.in.reserved = 0x123ab1;
94
lck.in.file.handle = h;
95
el[0].offset = UINT64_MAX;
96
el[0].length = UINT64_MAX;
97
el[0].reserved = 0x00000000;
98
el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
99
status = smb2_lock(tree, &lck);
100
CHECK_STATUS(status, NT_STATUS_OK);
101
CHECK_VALUE(lck.out.reserved, 0);
103
lck.in.reserved = 0x123ab2;
104
status = smb2_lock(tree, &lck);
105
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
107
lck.in.reserved = 0x123ab3;
108
status = smb2_lock(tree, &lck);
109
if (torture_setting_bool(torture, "windows", false)) {
110
CHECK_STATUS(status, NT_STATUS_OK);
112
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
114
CHECK_VALUE(lck.out.reserved, 0);
116
lck.in.reserved = 0x123ab4;
117
status = smb2_lock(tree, &lck);
118
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
120
lck.in.reserved = 0x123ab5;
121
status = smb2_lock(tree, &lck);
122
if (torture_setting_bool(torture, "windows", false)) {
123
CHECK_STATUS(status, NT_STATUS_OK);
125
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
127
CHECK_VALUE(lck.out.reserved, 0);
129
lck.in.lock_count = 0x0001;
130
lck.in.reserved = 0x12345678;
131
lck.in.file.handle = h;
132
el[0].offset = UINT32_MAX;
133
el[0].length = UINT32_MAX;
134
el[0].reserved = 0x87654321;
135
el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
136
status = smb2_lock(tree, &lck);
137
CHECK_STATUS(status, NT_STATUS_OK);
138
CHECK_VALUE(lck.out.reserved, 0);
140
status = smb2_lock(tree, &lck);
141
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
143
status = smb2_lock(tree, &lck);
144
if (torture_setting_bool(torture, "windows", false)) {
145
CHECK_STATUS(status, NT_STATUS_OK);
147
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
149
CHECK_VALUE(lck.out.reserved, 0);
151
status = smb2_lock(tree, &lck);
152
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
154
status = smb2_lock(tree, &lck);
155
if (torture_setting_bool(torture, "windows", false)) {
156
CHECK_STATUS(status, NT_STATUS_OK);
158
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
160
CHECK_VALUE(lck.out.reserved, 0);
162
el[0].flags = 0x00000000;
163
status = smb2_lock(tree, &lck);
164
CHECK_STATUS(status, NT_STATUS_OK);
165
CHECK_VALUE(lck.out.reserved, 0);
167
status = smb2_lock(tree, &lck);
168
CHECK_STATUS(status, NT_STATUS_OK);
169
CHECK_VALUE(lck.out.reserved, 0);
171
el[0].flags = 0x00000001;
172
status = smb2_lock(tree, &lck);
173
CHECK_STATUS(status, NT_STATUS_OK);
174
CHECK_VALUE(lck.out.reserved, 0);
176
status = smb2_lock(tree, &lck);
177
CHECK_STATUS(status, NT_STATUS_OK);
178
CHECK_VALUE(lck.out.reserved, 0);
180
lck.in.lock_count = 0x0001;
181
lck.in.reserved = 0x87654321;
182
lck.in.file.handle = h;
183
el[0].offset = 0x00000000FFFFFFFF;
184
el[0].length = 0x00000000FFFFFFFF;
185
el[0].reserved = 0x1234567;
186
el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
187
status = smb2_lock(tree, &lck);
188
CHECK_STATUS(status, NT_STATUS_OK);
190
lck.in.lock_count = 0x0001;
191
lck.in.reserved = 0x1234567;
192
lck.in.file.handle = h;
193
el[0].offset = 0x00000000FFFFFFFF;
194
el[0].length = 0x00000000FFFFFFFF;
195
el[0].reserved = 0x00000000;
196
el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
197
status = smb2_lock(tree, &lck);
198
CHECK_STATUS(status, NT_STATUS_OK);
200
status = smb2_lock(tree, &lck);
201
CHECK_STATUS(status, NT_STATUS_OK);
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_OK);
206
status = smb2_lock(tree, &lck);
207
CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
209
lck.in.lock_count = 0x0001;
211
lck.in.file.handle = h;
214
el[0].reserved = 0x00000000;
215
el[0].flags = ~SMB2_LOCK_FLAG_ALL_MASK;
217
status = smb2_lock(tree, &lck);
218
CHECK_STATUS(status, NT_STATUS_OK);
220
el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
221
status = smb2_lock(tree, &lck);
222
CHECK_STATUS(status, NT_STATUS_OK);
224
el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
225
status = smb2_lock(tree, &lck);
226
CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
228
el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_EXCLUSIVE;
229
status = smb2_lock(tree, &lck);
230
CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
232
el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_SHARED;
233
status = smb2_lock(tree, &lck);
234
CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
236
el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
237
status = smb2_lock(tree, &lck);
238
CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
240
lck.in.lock_count = 2;
242
lck.in.file.handle = h;
245
el[0].reserved = 0x00000000;
248
el[1].reserved = 0x00000000;
250
lck.in.lock_count = 2;
252
el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
253
status = smb2_lock(tree, &lck);
254
CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
256
lck.in.lock_count = 2;
259
status = smb2_lock(tree, &lck);
260
CHECK_STATUS(status, NT_STATUS_OK);
262
lck.in.lock_count = 2;
263
el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
265
status = smb2_lock(tree, &lck);
266
CHECK_STATUS(status, NT_STATUS_OK);
268
lck.in.lock_count = 1;
269
el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
270
status = smb2_lock(tree, &lck);
271
CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
273
lck.in.lock_count = 1;
274
el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
275
status = smb2_lock(tree, &lck);
276
CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
278
lck.in.lock_count = 1;
279
el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
280
status = smb2_lock(tree, &lck);
281
CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
283
lck.in.lock_count = 1;
285
status = smb2_lock(tree, &lck);
286
CHECK_STATUS(status, NT_STATUS_OK);
288
status = smb2_lock(tree, &lck);
289
CHECK_STATUS(status, NT_STATUS_OK);
291
lck.in.lock_count = 2;
292
el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
293
el[1].flags = SMB2_LOCK_FLAG_UNLOCK;
294
status = smb2_lock(tree, &lck);
295
CHECK_STATUS(status, NT_STATUS_OK);
297
lck.in.lock_count = 1;
298
el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
299
status = smb2_lock(tree, &lck);
300
CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
307
struct test_lock_read_write_state {
310
NTSTATUS write_h1_status;
311
NTSTATUS read_h1_status;
312
NTSTATUS write_h2_status;
313
NTSTATUS read_h2_status;
316
static bool test_lock_read_write(struct torture_context *torture,
317
struct smb2_tree *tree,
318
struct test_lock_read_write_state *s)
322
struct smb2_handle h1, h2;
324
struct smb2_lock lck;
325
struct smb2_create cr;
326
struct smb2_write wr;
328
struct smb2_lock_element el[1];
334
status = torture_smb2_testfile(tree, s->fname, &h1);
335
CHECK_STATUS(status, NT_STATUS_OK);
337
status = smb2_util_write(tree, h1, buf, 0, ARRAY_SIZE(buf));
338
CHECK_STATUS(status, NT_STATUS_OK);
340
lck.in.lock_count = 0x0001;
341
lck.in.reserved = 0x00000000;
342
lck.in.file.handle = h1;
344
el[0].length = ARRAY_SIZE(buf)/2;
345
el[0].reserved = 0x00000000;
346
el[0].flags = s->lock_flags;
347
status = smb2_lock(tree, &lck);
348
CHECK_STATUS(status, NT_STATUS_OK);
349
CHECK_VALUE(lck.out.reserved, 0);
351
lck.in.lock_count = 0x0001;
352
lck.in.reserved = 0x00000000;
353
lck.in.file.handle = h1;
354
el[0].offset = ARRAY_SIZE(buf)/2;
355
el[0].length = ARRAY_SIZE(buf)/2;
356
el[0].reserved = 0x00000000;
357
el[0].flags = s->lock_flags;
358
status = smb2_lock(tree, &lck);
359
CHECK_STATUS(status, NT_STATUS_OK);
360
CHECK_VALUE(lck.out.reserved, 0);
363
cr.in.oplock_level = 0;
364
cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
365
cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
366
cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
368
NTCREATEX_SHARE_ACCESS_DELETE|
369
NTCREATEX_SHARE_ACCESS_READ|
370
NTCREATEX_SHARE_ACCESS_WRITE;
371
cr.in.create_options = 0;
372
cr.in.fname = s->fname;
374
status = smb2_create(tree, tree, &cr);
375
CHECK_STATUS(status, NT_STATUS_OK);
377
h2 = cr.out.file.handle;
380
wr.in.file.handle = h1;
381
wr.in.offset = ARRAY_SIZE(buf)/2;
382
wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
384
status = smb2_write(tree, &wr);
385
CHECK_STATUS(status, s->write_h1_status);
388
rd.in.file.handle = h1;
389
rd.in.offset = ARRAY_SIZE(buf)/2;
390
rd.in.length = ARRAY_SIZE(buf)/2;
392
status = smb2_read(tree, tree, &rd);
393
CHECK_STATUS(status, s->read_h1_status);
396
wr.in.file.handle = h2;
397
wr.in.offset = ARRAY_SIZE(buf)/2;
398
wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
400
status = smb2_write(tree, &wr);
401
CHECK_STATUS(status, s->write_h2_status);
404
rd.in.file.handle = h2;
405
rd.in.offset = ARRAY_SIZE(buf)/2;
406
rd.in.length = ARRAY_SIZE(buf)/2;
408
status = smb2_read(tree, tree, &rd);
409
CHECK_STATUS(status, s->read_h2_status);
411
lck.in.lock_count = 0x0001;
412
lck.in.reserved = 0x00000000;
413
lck.in.file.handle = h1;
414
el[0].offset = ARRAY_SIZE(buf)/2;
415
el[0].length = ARRAY_SIZE(buf)/2;
416
el[0].reserved = 0x00000000;
417
el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
418
status = smb2_lock(tree, &lck);
419
CHECK_STATUS(status, NT_STATUS_OK);
420
CHECK_VALUE(lck.out.reserved, 0);
423
wr.in.file.handle = h2;
424
wr.in.offset = ARRAY_SIZE(buf)/2;
425
wr.in.data = data_blob_const(buf, ARRAY_SIZE(buf)/2);
427
status = smb2_write(tree, &wr);
428
CHECK_STATUS(status, NT_STATUS_OK);
431
rd.in.file.handle = h2;
432
rd.in.offset = ARRAY_SIZE(buf)/2;
433
rd.in.length = ARRAY_SIZE(buf)/2;
435
status = smb2_read(tree, tree, &rd);
436
CHECK_STATUS(status, NT_STATUS_OK);
442
static bool test_lock_rw_none(struct torture_context *torture, struct smb2_tree *tree)
444
struct test_lock_read_write_state s = {
445
.fname = "lock_rw_none.dat",
446
.lock_flags = SMB2_LOCK_FLAG_NONE,
447
.write_h1_status = NT_STATUS_FILE_LOCK_CONFLICT,
448
.read_h1_status = NT_STATUS_OK,
449
.write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
450
.read_h2_status = NT_STATUS_OK,
453
return test_lock_read_write(torture, tree, &s);
456
static bool test_lock_rw_shared(struct torture_context *torture, struct smb2_tree *tree)
458
struct test_lock_read_write_state s = {
459
.fname = "lock_rw_shared.dat",
460
.lock_flags = SMB2_LOCK_FLAG_SHARED,
461
.write_h1_status = NT_STATUS_FILE_LOCK_CONFLICT,
462
.read_h1_status = NT_STATUS_OK,
463
.write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
464
.read_h2_status = NT_STATUS_OK,
467
return test_lock_read_write(torture, tree, &s);
470
static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_tree *tree)
472
struct test_lock_read_write_state s = {
473
.fname = "lock_rw_exclusiv.dat",
474
.lock_flags = SMB2_LOCK_FLAG_EXCLUSIVE,
475
.write_h1_status = NT_STATUS_OK,
476
.read_h1_status = NT_STATUS_OK,
477
.write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
478
.read_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
481
return test_lock_read_write(torture, tree, &s);
485
static bool test_lock_auto_unlock(struct torture_context *torture, struct smb2_tree *tree)
489
struct smb2_handle h;
491
struct smb2_lock lck;
492
struct smb2_lock_element el[2];
496
status = torture_smb2_testfile(tree, "autounlock.txt", &h);
497
CHECK_STATUS(status, NT_STATUS_OK);
499
status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
500
CHECK_STATUS(status, NT_STATUS_OK);
504
lck.in.lock_count = 0x0001;
505
lck.in.file.handle = h;
508
el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
509
status = smb2_lock(tree, &lck);
510
CHECK_STATUS(status, NT_STATUS_OK);
512
status = smb2_lock(tree, &lck);
513
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
515
status = smb2_lock(tree, &lck);
516
if (torture_setting_bool(torture, "windows", false)) {
517
CHECK_STATUS(status, NT_STATUS_OK);
519
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
529
/* basic testing of SMB2 locking
531
struct torture_suite *torture_smb2_lock_init(void)
533
struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "LOCK");
535
torture_suite_add_1smb2_test(suite, "VALID-REQUEST", test_valid_request);
536
torture_suite_add_1smb2_test(suite, "RW-NONE", test_lock_rw_none);
537
torture_suite_add_1smb2_test(suite, "RW-SHARED", test_lock_rw_shared);
538
torture_suite_add_1smb2_test(suite, "RW-EXCLUSIV", test_lock_rw_exclusiv);
539
torture_suite_add_1smb2_test(suite, "AUTO-UNLOCK", test_lock_auto_unlock);
541
suite->description = talloc_strdup(suite, "SMB2-LOCK tests");