s3-spoolss: fix _spoolss_GetPrinterDataEx after IDL change.
[Samba/nascimento.git] / source4 / torture / smb2 / durable_open.c
blobd182744b3554fa2a438dc70252b3d511f38e19d8
1 /*
2 Unix SMB/CIFS implementation.
4 test suite for SMB2 durable opens
6 Copyright (C) Stefan Metzmacher 2008
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/>.
22 #include "includes.h"
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25 #include "torture/torture.h"
26 #include "torture/smb2/proto.h"
28 #define CHECK_VAL(v, correct) do { \
29 if ((v) != (correct)) { \
30 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
31 __location__, #v, (int)v, (int)correct); \
32 ret = false; \
33 }} while (0)
35 #define CHECK_STATUS(status, correct) do { \
36 if (!NT_STATUS_EQUAL(status, correct)) { \
37 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
38 nt_errstr(status), nt_errstr(correct)); \
39 ret = false; \
40 goto done; \
41 }} while (0)
43 #define CHECK_CREATED(__io, __created, __attribute) \
44 do { \
45 CHECK_VAL((__io)->out.create_action, NTCREATEX_ACTION_ ## __created); \
46 CHECK_VAL((__io)->out.alloc_size, 0); \
47 CHECK_VAL((__io)->out.size, 0); \
48 CHECK_VAL((__io)->out.file_attr, (__attribute)); \
49 CHECK_VAL((__io)->out.reserved2, 0); \
50 } while(0)
53 basic testing of SMB2 durable opens
54 regarding the position information on the handle
56 bool test_durable_open_file_position(struct torture_context *tctx,
57 struct smb2_tree *tree1,
58 struct smb2_tree *tree2)
60 TALLOC_CTX *mem_ctx = talloc_new(tctx);
61 struct smb2_handle h1, h2;
62 struct smb2_create io1, io2;
63 NTSTATUS status;
64 const char *fname = "durable_open_position.dat";
65 union smb_fileinfo qfinfo;
66 union smb_setfileinfo sfinfo;
67 bool ret = true;
68 uint64_t pos;
70 smb2_util_unlink(tree1, fname);
72 ZERO_STRUCT(io1);
73 io1.in.security_flags = 0x00;
74 io1.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
75 io1.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
76 io1.in.create_flags = 0x00000000;
77 io1.in.reserved = 0x00000000;
78 io1.in.desired_access = SEC_RIGHTS_FILE_ALL;
79 io1.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
80 io1.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
81 NTCREATEX_SHARE_ACCESS_WRITE |
82 NTCREATEX_SHARE_ACCESS_DELETE;
83 io1.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
84 io1.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
85 NTCREATEX_OPTIONS_ASYNC_ALERT |
86 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
87 0x00200000;
88 io1.in.durable_open = true;
89 io1.in.fname = fname;
91 status = smb2_create(tree1, mem_ctx, &io1);
92 CHECK_STATUS(status, NT_STATUS_OK);
93 h1 = io1.out.file.handle;
94 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
95 CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
97 /* TODO: check extra blob content */
99 ZERO_STRUCT(qfinfo);
100 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
101 qfinfo.generic.in.file.handle = h1;
102 status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
103 CHECK_STATUS(status, NT_STATUS_OK);
104 CHECK_VAL(qfinfo.position_information.out.position, 0);
105 pos = qfinfo.position_information.out.position;
106 torture_comment(tctx, "position: %llu\n",
107 (unsigned long long)pos);
109 ZERO_STRUCT(sfinfo);
110 sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
111 sfinfo.generic.in.file.handle = h1;
112 sfinfo.position_information.in.position = 0x1000;
113 status = smb2_setinfo_file(tree1, &sfinfo);
114 CHECK_STATUS(status, NT_STATUS_OK);
116 ZERO_STRUCT(qfinfo);
117 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
118 qfinfo.generic.in.file.handle = h1;
119 status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
120 CHECK_STATUS(status, NT_STATUS_OK);
121 CHECK_VAL(qfinfo.position_information.out.position, 0x1000);
122 pos = qfinfo.position_information.out.position;
123 torture_comment(tctx, "position: %llu\n",
124 (unsigned long long)pos);
126 talloc_free(tree1);
127 tree1 = NULL;
129 ZERO_STRUCT(qfinfo);
130 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
131 qfinfo.generic.in.file.handle = h1;
132 status = smb2_getinfo_file(tree2, mem_ctx, &qfinfo);
133 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
135 ZERO_STRUCT(io2);
136 io2.in.fname = fname;
137 io2.in.durable_handle = &h1;
139 status = smb2_create(tree2, mem_ctx, &io2);
140 CHECK_STATUS(status, NT_STATUS_OK);
141 CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
142 CHECK_VAL(io2.out.reserved, 0x00);
143 CHECK_VAL(io2.out.create_action, NTCREATEX_ACTION_EXISTED);
144 CHECK_VAL(io2.out.alloc_size, 0);
145 CHECK_VAL(io2.out.size, 0);
146 CHECK_VAL(io2.out.file_attr, FILE_ATTRIBUTE_ARCHIVE);
147 CHECK_VAL(io2.out.reserved2, 0);
149 h2 = io2.out.file.handle;
151 ZERO_STRUCT(qfinfo);
152 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
153 qfinfo.generic.in.file.handle = h2;
154 status = smb2_getinfo_file(tree2, mem_ctx, &qfinfo);
155 CHECK_STATUS(status, NT_STATUS_OK);
156 CHECK_VAL(qfinfo.position_information.out.position, 0x1000);
157 pos = qfinfo.position_information.out.position;
158 torture_comment(tctx, "position: %llu\n",
159 (unsigned long long)pos);
161 smb2_util_close(tree2, h2);
163 talloc_free(mem_ctx);
165 smb2_util_unlink(tree2, fname);
166 done:
167 return ret;
171 Open, disconnect, oplock break, reconnect.
173 bool test_durable_open_oplock(struct torture_context *tctx,
174 struct smb2_tree *tree1,
175 struct smb2_tree *tree2)
177 TALLOC_CTX *mem_ctx = talloc_new(tctx);
178 struct smb2_create io1, io2;
179 struct smb2_handle h1, h2;
180 NTSTATUS status;
181 char fname[256];
182 bool ret = true;
184 /* Choose a random name in case the state is left a little funky. */
185 snprintf(fname, 256, "durable_open_lease_%s.dat", generate_random_str(tctx, 8));
187 /* Clean slate */
188 smb2_util_unlink(tree1, fname);
190 /* Create with batch oplock */
191 ZERO_STRUCT(io1);
192 io1.in.security_flags = 0x00;
193 io1.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
194 io1.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
195 io1.in.create_flags = 0x00000000;
196 io1.in.reserved = 0x00000000;
197 io1.in.desired_access = SEC_RIGHTS_FILE_ALL;
198 io1.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
199 io1.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
200 NTCREATEX_SHARE_ACCESS_WRITE |
201 NTCREATEX_SHARE_ACCESS_DELETE;
202 io1.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
203 io1.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
204 NTCREATEX_OPTIONS_ASYNC_ALERT |
205 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
206 0x00200000;
207 io1.in.fname = fname;
208 io1.in.durable_open = true;
210 io2 = io1;
211 io2.in.create_disposition = NTCREATEX_DISP_OPEN;
213 status = smb2_create(tree1, mem_ctx, &io1);
214 CHECK_STATUS(status, NT_STATUS_OK);
215 h1 = io1.out.file.handle;
216 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
217 CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
219 /* Disconnect after getting the batch */
220 talloc_free(tree1);
221 tree1 = NULL;
224 * Windows7 (build 7000) will break a batch oplock immediately if the
225 * original client is gone. (ZML: This seems like a bug. It should give
226 * some time for the client to reconnect!)
228 status = smb2_create(tree2, mem_ctx, &io2);
229 CHECK_STATUS(status, NT_STATUS_OK);
230 h2 = io2.out.file.handle;
231 CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
232 CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
234 /* What if tree1 tries to come back and reclaim? */
235 if (!torture_smb2_connection(tctx, &tree1)) {
236 torture_warning(tctx, "couldn't reconnect, bailing\n");
237 ret = false;
238 goto done;
241 ZERO_STRUCT(io1);
242 io1.in.fname = fname;
243 io1.in.durable_handle = &h1;
245 status = smb2_create(tree1, mem_ctx, &io1);
246 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
248 done:
249 smb2_util_close(tree2, h2);
250 smb2_util_unlink(tree2, fname);
252 return ret;
256 Open, disconnect, lease break, reconnect.
258 bool test_durable_open_lease(struct torture_context *tctx,
259 struct smb2_tree *tree1,
260 struct smb2_tree *tree2)
262 TALLOC_CTX *mem_ctx = talloc_new(tctx);
263 struct smb2_create io1, io2;
264 struct smb2_lease ls1, ls2;
265 struct smb2_handle h1, h2;
266 NTSTATUS status;
267 char fname[256];
268 bool ret = true;
269 uint64_t lease1, lease2;
272 * Choose a random name and random lease in case the state is left a
273 * little funky.
275 lease1 = random();
276 lease2 = random();
277 snprintf(fname, 256, "durable_open_lease_%s.dat", generate_random_str(tctx, 8));
279 /* Clean slate */
280 smb2_util_unlink(tree1, fname);
282 /* Create with lease */
283 ZERO_STRUCT(io1);
284 io1.in.security_flags = 0x00;
285 io1.in.oplock_level = SMB2_OPLOCK_LEVEL_LEASE;
286 io1.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
287 io1.in.create_flags = 0x00000000;
288 io1.in.reserved = 0x00000000;
289 io1.in.desired_access = SEC_RIGHTS_FILE_ALL;
290 io1.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
291 io1.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
292 NTCREATEX_SHARE_ACCESS_WRITE |
293 NTCREATEX_SHARE_ACCESS_DELETE;
294 io1.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
295 io1.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
296 NTCREATEX_OPTIONS_ASYNC_ALERT |
297 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
298 0x00200000;
299 io1.in.fname = fname;
300 io1.in.durable_open = true;
302 ZERO_STRUCT(ls1);
303 ls1.lease_key.data[0] = lease1;
304 ls1.lease_key.data[1] = ~lease1;
305 ls1.lease_state = SMB2_LEASE_READ|SMB2_LEASE_HANDLE|SMB2_LEASE_WRITE;
306 io1.in.lease_request = &ls1;
308 io2 = io1;
309 ls2 = ls1;
310 ls2.lease_key.data[0] = lease2;
311 ls2.lease_key.data[1] = ~lease2;
312 io2.in.lease_request = &ls2;
313 io2.in.create_disposition = NTCREATEX_DISP_OPEN;
315 status = smb2_create(tree1, mem_ctx, &io1);
316 CHECK_STATUS(status, NT_STATUS_OK);
317 h1 = io1.out.file.handle;
318 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
320 CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
321 CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease1);
322 CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease1);
323 CHECK_VAL(io1.out.lease_response.lease_state,
324 SMB2_LEASE_READ|SMB2_LEASE_HANDLE|SMB2_LEASE_WRITE);
326 /* Disconnect after getting the lease */
327 talloc_free(tree1);
328 tree1 = NULL;
331 * Windows7 (build 7000) will grant an RH lease immediate (not an RHW?)
332 * even if the original client is gone. (ZML: This seems like a bug. It
333 * should give some time for the client to reconnect! And why RH?)
335 status = smb2_create(tree2, mem_ctx, &io2);
336 CHECK_STATUS(status, NT_STATUS_OK);
337 h2 = io2.out.file.handle;
338 CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
340 CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
341 CHECK_VAL(io2.out.lease_response.lease_key.data[0], lease2);
342 CHECK_VAL(io2.out.lease_response.lease_key.data[1], ~lease2);
343 CHECK_VAL(io2.out.lease_response.lease_state,
344 SMB2_LEASE_READ|SMB2_LEASE_HANDLE);
346 /* What if tree1 tries to come back and reclaim? */
347 if (!torture_smb2_connection(tctx, &tree1)) {
348 torture_warning(tctx, "couldn't reconnect, bailing\n");
349 ret = false;
350 goto done;
353 ZERO_STRUCT(io1);
354 io1.in.fname = fname;
355 io1.in.durable_handle = &h1;
356 io1.in.lease_request = &ls1;
358 status = smb2_create(tree1, mem_ctx, &io1);
359 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
361 done:
362 smb2_util_close(tree2, h2);
363 smb2_util_unlink(tree2, fname);
365 return ret;
369 Open, take BRL, disconnect, reconnect.
371 bool test_durable_open_lock(struct torture_context *tctx,
372 struct smb2_tree *tree)
374 TALLOC_CTX *mem_ctx = talloc_new(tctx);
375 struct smb2_create io;
376 struct smb2_lease ls;
377 struct smb2_handle h;
378 struct smb2_lock lck;
379 struct smb2_lock_element el[2];
380 NTSTATUS status;
381 char fname[256];
382 bool ret = true;
383 uint64_t lease;
386 * Choose a random name and random lease in case the state is left a
387 * little funky.
389 lease = random();
390 snprintf(fname, 256, "durable_open_lock_%s.dat", generate_random_str(tctx, 8));
392 /* Clean slate */
393 smb2_util_unlink(tree, fname);
395 /* Create with lease */
396 ZERO_STRUCT(io);
397 io.in.security_flags = 0x00;
398 io.in.oplock_level = SMB2_OPLOCK_LEVEL_LEASE;
399 io.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
400 io.in.create_flags = 0x00000000;
401 io.in.reserved = 0x00000000;
402 io.in.desired_access = SEC_RIGHTS_FILE_ALL;
403 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
404 io.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
405 NTCREATEX_SHARE_ACCESS_WRITE |
406 NTCREATEX_SHARE_ACCESS_DELETE;
407 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
408 io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
409 NTCREATEX_OPTIONS_ASYNC_ALERT |
410 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
411 0x00200000;
412 io.in.fname = fname;
413 io.in.durable_open = true;
415 ZERO_STRUCT(ls);
416 ls.lease_key.data[0] = lease;
417 ls.lease_key.data[1] = ~lease;
418 ls.lease_state = SMB2_LEASE_READ|SMB2_LEASE_HANDLE|SMB2_LEASE_WRITE;
419 io.in.lease_request = &ls;
421 status = smb2_create(tree, mem_ctx, &io);
422 CHECK_STATUS(status, NT_STATUS_OK);
423 h = io.out.file.handle;
424 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
426 CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
427 CHECK_VAL(io.out.lease_response.lease_key.data[0], lease);
428 CHECK_VAL(io.out.lease_response.lease_key.data[1], ~lease);
429 CHECK_VAL(io.out.lease_response.lease_state,
430 SMB2_LEASE_READ|SMB2_LEASE_HANDLE|SMB2_LEASE_WRITE);
432 ZERO_STRUCT(lck);
433 ZERO_STRUCT(el);
434 lck.in.locks = el;
435 lck.in.lock_count = 0x0001;
436 lck.in.lock_sequence = 0x00000000;
437 lck.in.file.handle = h;
438 el[0].offset = 0;
439 el[0].length = 1;
440 el[0].reserved = 0x00000000;
441 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE;
442 status = smb2_lock(tree, &lck);
443 CHECK_STATUS(status, NT_STATUS_OK);
445 /* Disconnect/Reconnect. */
446 talloc_free(tree);
447 tree = NULL;
449 if (!torture_smb2_connection(tctx, &tree)) {
450 torture_warning(tctx, "couldn't reconnect, bailing\n");
451 ret = false;
452 goto done;
455 ZERO_STRUCT(io);
456 io.in.fname = fname;
457 io.in.durable_handle = &h;
458 io.in.lease_request = &ls;
460 status = smb2_create(tree, mem_ctx, &io);
461 CHECK_STATUS(status, NT_STATUS_OK);
462 h = io.out.file.handle;
464 lck.in.file.handle = h;
465 el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
466 status = smb2_lock(tree, &lck);
467 CHECK_STATUS(status, NT_STATUS_OK);
469 done:
470 smb2_util_close(tree, h);
471 smb2_util_unlink(tree, fname);
473 return ret;
477 Open, disconnect, open in another tree, reconnect.
479 This test actually demonstrates a minimum level of respect for the durable
480 open in the face of another open. As long as this test shows an inability to
481 reconnect after an open, the oplock/lease tests above will certainly
482 demonstrate an error on reconnect.
484 bool test_durable_open_open(struct torture_context *tctx,
485 struct smb2_tree *tree1,
486 struct smb2_tree *tree2)
488 TALLOC_CTX *mem_ctx = talloc_new(tctx);
489 struct smb2_create io1, io2;
490 struct smb2_lease ls;
491 struct smb2_handle h1, h2;
492 NTSTATUS status;
493 char fname[256];
494 bool ret = true;
495 uint64_t lease;
498 * Choose a random name and random lease in case the state is left a
499 * little funky.
501 lease = random();
502 snprintf(fname, 256, "durable_open_lock_%s.dat", generate_random_str(tctx, 8));
504 /* Clean slate */
505 smb2_util_unlink(tree1, fname);
507 /* Create with lease */
508 ZERO_STRUCT(io1);
509 io1.in.security_flags = 0x00;
510 io1.in.oplock_level = SMB2_OPLOCK_LEVEL_LEASE;
511 io1.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
512 io1.in.create_flags = 0x00000000;
513 io1.in.reserved = 0x00000000;
514 io1.in.desired_access = SEC_RIGHTS_FILE_ALL;
515 io1.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
516 io1.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
517 io1.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
518 io1.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
519 NTCREATEX_OPTIONS_ASYNC_ALERT |
520 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
521 0x00200000;
522 io1.in.fname = fname;
523 io1.in.durable_open = true;
525 io2 = io1;
526 io2.in.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
527 io2.in.durable_open = false;
529 ZERO_STRUCT(ls);
530 ls.lease_key.data[0] = lease;
531 ls.lease_key.data[1] = ~lease;
532 ls.lease_state = SMB2_LEASE_READ|SMB2_LEASE_HANDLE;
533 io1.in.lease_request = &ls;
535 status = smb2_create(tree1, mem_ctx, &io1);
536 CHECK_STATUS(status, NT_STATUS_OK);
537 h1 = io1.out.file.handle;
538 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
540 CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
541 CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease);
542 CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease);
543 CHECK_VAL(io1.out.lease_response.lease_state,
544 SMB2_LEASE_READ|SMB2_LEASE_HANDLE);
546 /* Disconnect */
547 talloc_free(tree1);
548 tree1 = NULL;
550 /* Open the file in tree2 */
551 status = smb2_create(tree2, mem_ctx, &io2);
552 CHECK_STATUS(status, NT_STATUS_OK);
553 h2 = io2.out.file.handle;
554 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
556 /* Reconnect */
557 if (!torture_smb2_connection(tctx, &tree1)) {
558 torture_warning(tctx, "couldn't reconnect, bailing\n");
559 ret = false;
560 goto done;
563 ZERO_STRUCT(io1);
564 io1.in.fname = fname;
565 io1.in.durable_handle = &h1;
566 io1.in.lease_request = &ls;
569 * Windows7 (build 7000) will give away an open immediately if the
570 * original client is gone. (ZML: This seems like a bug. It should give
571 * some time for the client to reconnect!)
573 status = smb2_create(tree1, mem_ctx, &io1);
574 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
575 h1 = io1.out.file.handle;
577 done:
578 smb2_util_close(tree2, h2);
579 smb2_util_unlink(tree2, fname);
580 smb2_util_close(tree1, h1);
581 smb2_util_unlink(tree1, fname);
583 return ret;
586 struct torture_suite *torture_smb2_durable_open_init(void)
588 struct torture_suite *suite =
589 torture_suite_create(talloc_autofree_context(), "DURABLE-OPEN");
591 torture_suite_add_2smb2_test(suite, "FILE-POSITION",
592 test_durable_open_file_position);
593 torture_suite_add_2smb2_test(suite, "OPLOCK", test_durable_open_oplock);
594 torture_suite_add_2smb2_test(suite, "LEASE", test_durable_open_lease);
595 torture_suite_add_1smb2_test(suite, "LOCK", test_durable_open_lock);
596 torture_suite_add_2smb2_test(suite, "OPEN", test_durable_open_open);
598 suite->description = talloc_strdup(suite, "SMB2-DURABLE-OPEN tests");
600 return suite;