vfs_ceph: add fake async pwrite/pread send/recv hooks
[Samba.git] / source4 / torture / smb2 / session.c
blob15a11e235d6099bbde3d9bfa4c14dabf71f4e68d
1 /*
2 Unix SMB/CIFS implementation.
4 test suite for SMB2 session setups
6 Copyright (C) Michael Adam 2012
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"
27 #include "../libcli/smb/smbXcli_base.h"
28 #include "lib/cmdline/popt_common.h"
29 #include "auth/credentials/credentials.h"
30 #include "auth/credentials/credentials_krb5.h"
31 #include "libcli/security/security.h"
32 #include "libcli/resolve/resolve.h"
33 #include "lib/param/param.h"
34 #include "lib/util/tevent_ntstatus.h"
36 #define CHECK_CREATED(tctx, __io, __created, __attribute) \
37 do { \
38 torture_assert_int_equal(tctx, (__io)->out.create_action, \
39 NTCREATEX_ACTION_ ## __created, \
40 "out.create_action incorrect"); \
41 torture_assert_int_equal(tctx, (__io)->out.alloc_size, 0, \
42 "out.alloc_size incorrect"); \
43 torture_assert_int_equal(tctx, (__io)->out.size, 0, \
44 "out.size incorrect"); \
45 torture_assert_int_equal(tctx, (__io)->out.file_attr, \
46 (__attribute), \
47 "out.file_attr incorrect"); \
48 torture_assert_int_equal(tctx, (__io)->out.reserved2, 0, \
49 "out.reserverd2 incorrect"); \
50 } while(0)
52 /**
53 * basic test for doing a session reconnect
55 bool test_session_reconnect1(struct torture_context *tctx, struct smb2_tree *tree)
57 NTSTATUS status;
58 TALLOC_CTX *mem_ctx = talloc_new(tctx);
59 char fname[256];
60 struct smb2_handle _h1;
61 struct smb2_handle *h1 = NULL;
62 struct smb2_handle _h2;
63 struct smb2_handle *h2 = NULL;
64 struct smb2_create io1, io2;
65 uint64_t previous_session_id;
66 bool ret = true;
67 struct smb2_tree *tree2 = NULL;
68 union smb_fileinfo qfinfo;
70 /* Add some random component to the file name. */
71 snprintf(fname, sizeof(fname), "session_reconnect_%s.dat",
72 generate_random_str(tctx, 8));
74 smb2_util_unlink(tree, fname);
76 smb2_oplock_create_share(&io1, fname,
77 smb2_util_share_access(""),
78 smb2_util_oplock_level("b"));
80 status = smb2_create(tree, mem_ctx, &io1);
81 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
82 "smb2_create failed");
83 _h1 = io1.out.file.handle;
84 h1 = &_h1;
85 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
86 torture_assert_int_equal(tctx, io1.out.oplock_level,
87 smb2_util_oplock_level("b"),
88 "oplock_level incorrect");
90 /* disconnect, reconnect and then do durable reopen */
91 previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
93 torture_assert_goto(tctx, torture_smb2_connection_ext(tctx, previous_session_id,
94 &tree->session->transport->options, &tree2),
95 ret, done,
96 "session reconnect failed\n");
98 /* try to access the file via the old handle */
100 ZERO_STRUCT(qfinfo);
101 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
102 qfinfo.generic.in.file.handle = _h1;
103 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
104 torture_assert_ntstatus_equal_goto(tctx, status,
105 NT_STATUS_USER_SESSION_DELETED,
106 ret, done, "smb2_getinfo_file "
107 "returned unexpected status");
108 h1 = NULL;
110 smb2_oplock_create_share(&io2, fname,
111 smb2_util_share_access(""),
112 smb2_util_oplock_level("b"));
114 status = smb2_create(tree2, mem_ctx, &io2);
115 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
116 "smb2_create failed");
118 CHECK_CREATED(tctx, &io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
119 torture_assert_int_equal(tctx, io1.out.oplock_level,
120 smb2_util_oplock_level("b"),
121 "oplock_level incorrect");
122 _h2 = io2.out.file.handle;
123 h2 = &_h2;
125 done:
126 if (h1 != NULL) {
127 smb2_util_close(tree, *h1);
129 if (h2 != NULL) {
130 smb2_util_close(tree2, *h2);
133 if (tree2 != NULL) {
134 smb2_util_unlink(tree2, fname);
136 smb2_util_unlink(tree, fname);
138 talloc_free(tree);
139 talloc_free(tree2);
141 talloc_free(mem_ctx);
143 return ret;
147 * basic test for doing a session reconnect on one connection
149 bool test_session_reconnect2(struct torture_context *tctx, struct smb2_tree *tree)
151 NTSTATUS status;
152 TALLOC_CTX *mem_ctx = talloc_new(tctx);
153 char fname[256];
154 struct smb2_handle _h1;
155 struct smb2_handle *h1 = NULL;
156 struct smb2_create io1;
157 uint64_t previous_session_id;
158 bool ret = true;
159 struct smb2_session *session2 = NULL;
160 union smb_fileinfo qfinfo;
162 /* Add some random component to the file name. */
163 snprintf(fname, sizeof(fname), "session_reconnect_%s.dat",
164 generate_random_str(tctx, 8));
166 smb2_util_unlink(tree, fname);
168 smb2_oplock_create_share(&io1, fname,
169 smb2_util_share_access(""),
170 smb2_util_oplock_level("b"));
171 io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
173 status = smb2_create(tree, mem_ctx, &io1);
174 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
175 "smb2_create failed");
176 _h1 = io1.out.file.handle;
177 h1 = &_h1;
178 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
179 torture_assert_int_equal(tctx, io1.out.oplock_level,
180 smb2_util_oplock_level("b"),
181 "oplock_level incorrect");
183 /* disconnect, reconnect and then do durable reopen */
184 previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
186 torture_assert(tctx, torture_smb2_session_setup(tctx, tree->session->transport,
187 previous_session_id, tctx, &session2),
188 "session reconnect (on the same connection) failed");
190 /* try to access the file via the old handle */
192 ZERO_STRUCT(qfinfo);
193 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
194 qfinfo.generic.in.file.handle = _h1;
195 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
196 torture_assert_ntstatus_equal_goto(tctx, status,
197 NT_STATUS_USER_SESSION_DELETED,
198 ret, done, "smb2_getinfo_file "
199 "returned unexpected status");
200 h1 = NULL;
202 done:
203 if (h1 != NULL) {
204 smb2_util_close(tree, *h1);
207 talloc_free(tree);
208 talloc_free(session2);
210 talloc_free(mem_ctx);
212 return ret;
215 bool test_session_reauth1(struct torture_context *tctx, struct smb2_tree *tree)
217 NTSTATUS status;
218 TALLOC_CTX *mem_ctx = talloc_new(tctx);
219 char fname[256];
220 struct smb2_handle _h1;
221 struct smb2_handle *h1 = NULL;
222 struct smb2_create io1;
223 bool ret = true;
224 union smb_fileinfo qfinfo;
226 /* Add some random component to the file name. */
227 snprintf(fname, sizeof(fname), "session_reauth1_%s.dat",
228 generate_random_str(tctx, 8));
230 smb2_util_unlink(tree, fname);
232 smb2_oplock_create_share(&io1, fname,
233 smb2_util_share_access(""),
234 smb2_util_oplock_level("b"));
236 status = smb2_create(tree, mem_ctx, &io1);
237 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
238 "smb2_create failed");
239 _h1 = io1.out.file.handle;
240 h1 = &_h1;
241 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
242 torture_assert_int_equal(tctx, io1.out.oplock_level,
243 smb2_util_oplock_level("b"),
244 "oplock_level incorrect");
246 status = smb2_session_setup_spnego(tree->session,
247 popt_get_cmdline_credentials(),
248 0 /* previous_session_id */);
249 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
250 "smb2_session_setup_spnego failed");
252 /* try to access the file via the old handle */
254 ZERO_STRUCT(qfinfo);
255 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
256 qfinfo.generic.in.file.handle = _h1;
257 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
258 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
259 "smb2_getinfo_file failed");
261 status = smb2_session_setup_spnego(tree->session,
262 popt_get_cmdline_credentials(),
263 0 /* previous_session_id */);
264 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
265 "smb2_session_setup_spnego failed");
267 /* try to access the file via the old handle */
269 ZERO_STRUCT(qfinfo);
270 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
271 qfinfo.generic.in.file.handle = _h1;
272 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
273 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
274 "smb2_getinfo_file failed");
276 done:
277 if (h1 != NULL) {
278 smb2_util_close(tree, *h1);
281 smb2_util_unlink(tree, fname);
283 talloc_free(tree);
285 talloc_free(mem_ctx);
287 return ret;
290 bool test_session_reauth2(struct torture_context *tctx, struct smb2_tree *tree)
292 NTSTATUS status;
293 TALLOC_CTX *mem_ctx = talloc_new(tctx);
294 char fname[256];
295 struct smb2_handle _h1;
296 struct smb2_handle *h1 = NULL;
297 struct smb2_create io1;
298 bool ret = true;
299 union smb_fileinfo qfinfo;
300 struct cli_credentials *anon_creds = NULL;
302 /* Add some random component to the file name. */
303 snprintf(fname, sizeof(fname), "session_reauth2_%s.dat",
304 generate_random_str(tctx, 8));
306 smb2_util_unlink(tree, fname);
308 smb2_oplock_create_share(&io1, fname,
309 smb2_util_share_access(""),
310 smb2_util_oplock_level("b"));
312 status = smb2_create(tree, mem_ctx, &io1);
313 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
314 "smb2_create failed");
315 _h1 = io1.out.file.handle;
316 h1 = &_h1;
317 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
318 torture_assert_int_equal(tctx, io1.out.oplock_level,
319 smb2_util_oplock_level("b"),
320 "oplock_level incorrect");
322 /* re-authenticate as anonymous */
324 anon_creds = cli_credentials_init_anon(mem_ctx);
325 torture_assert(tctx, (anon_creds != NULL), "talloc error");
327 status = smb2_session_setup_spnego(tree->session,
328 anon_creds,
329 0 /* previous_session_id */);
330 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
331 "smb2_session_setup_spnego failed");
333 /* try to access the file via the old handle */
335 ZERO_STRUCT(qfinfo);
336 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
337 qfinfo.generic.in.file.handle = _h1;
338 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
339 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
340 "smb2_getinfo_file failed");
342 /* re-authenticate as original user again */
344 status = smb2_session_setup_spnego(tree->session,
345 popt_get_cmdline_credentials(),
346 0 /* previous_session_id */);
347 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
348 "smb2_session_setup_spnego failed");
350 /* try to access the file via the old handle */
352 ZERO_STRUCT(qfinfo);
353 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
354 qfinfo.generic.in.file.handle = _h1;
355 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
356 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
357 "smb2_getinfo_file failed");
359 done:
360 if (h1 != NULL) {
361 smb2_util_close(tree, *h1);
364 smb2_util_unlink(tree, fname);
366 talloc_free(tree);
368 talloc_free(mem_ctx);
370 return ret;
374 * test getting security descriptor after reauth
376 bool test_session_reauth3(struct torture_context *tctx, struct smb2_tree *tree)
378 NTSTATUS status;
379 TALLOC_CTX *mem_ctx = talloc_new(tctx);
380 char fname[256];
381 struct smb2_handle _h1;
382 struct smb2_handle *h1 = NULL;
383 struct smb2_create io1;
384 bool ret = true;
385 union smb_fileinfo qfinfo;
386 struct cli_credentials *anon_creds = NULL;
387 uint32_t secinfo_flags = SECINFO_OWNER
388 | SECINFO_GROUP
389 | SECINFO_DACL
390 | SECINFO_PROTECTED_DACL
391 | SECINFO_UNPROTECTED_DACL;
393 /* Add some random component to the file name. */
394 snprintf(fname, sizeof(fname), "session_reauth3_%s.dat",
395 generate_random_str(tctx, 8));
397 smb2_util_unlink(tree, fname);
399 smb2_oplock_create_share(&io1, fname,
400 smb2_util_share_access(""),
401 smb2_util_oplock_level("b"));
403 status = smb2_create(tree, mem_ctx, &io1);
404 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
405 "smb2_create failed");
406 _h1 = io1.out.file.handle;
407 h1 = &_h1;
408 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
409 torture_assert_int_equal(tctx, io1.out.oplock_level,
410 smb2_util_oplock_level("b"),
411 "oplock_level incorrect");
413 /* get the security descriptor */
415 ZERO_STRUCT(qfinfo);
417 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
418 qfinfo.query_secdesc.in.file.handle = _h1;
419 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
421 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
422 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
423 "smb2_getinfo_file failed");
425 /* re-authenticate as anonymous */
427 anon_creds = cli_credentials_init_anon(mem_ctx);
428 torture_assert(tctx, (anon_creds != NULL), "talloc error");
430 status = smb2_session_setup_spnego(tree->session,
431 anon_creds,
432 0 /* previous_session_id */);
433 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
434 "smb2_session_setup_spnego failed");
436 /* try to access the file via the old handle */
438 ZERO_STRUCT(qfinfo);
440 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
441 qfinfo.query_secdesc.in.file.handle = _h1;
442 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
444 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
445 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
446 "smb2_getinfo_file failed");
448 /* re-authenticate as original user again */
450 status = smb2_session_setup_spnego(tree->session,
451 popt_get_cmdline_credentials(),
452 0 /* previous_session_id */);
453 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
454 "smb2_session_setup_spnego failed");
456 /* try to access the file via the old handle */
458 ZERO_STRUCT(qfinfo);
460 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
461 qfinfo.query_secdesc.in.file.handle = _h1;
462 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
464 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
465 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
466 "smb2_getinfo_file failed");
468 done:
469 if (h1 != NULL) {
470 smb2_util_close(tree, *h1);
473 smb2_util_unlink(tree, fname);
475 talloc_free(tree);
477 talloc_free(mem_ctx);
479 return ret;
483 * test setting security descriptor after reauth.
485 bool test_session_reauth4(struct torture_context *tctx, struct smb2_tree *tree)
487 NTSTATUS status;
488 TALLOC_CTX *mem_ctx = talloc_new(tctx);
489 char fname[256];
490 struct smb2_handle _h1;
491 struct smb2_handle *h1 = NULL;
492 struct smb2_create io1;
493 bool ret = true;
494 union smb_fileinfo qfinfo;
495 union smb_setfileinfo sfinfo;
496 struct cli_credentials *anon_creds = NULL;
497 uint32_t secinfo_flags = SECINFO_OWNER
498 | SECINFO_GROUP
499 | SECINFO_DACL
500 | SECINFO_PROTECTED_DACL
501 | SECINFO_UNPROTECTED_DACL;
502 struct security_descriptor *sd1;
503 struct security_ace ace;
504 struct dom_sid *extra_sid;
506 /* Add some random component to the file name. */
507 snprintf(fname, sizeof(fname), "session_reauth4_%s.dat",
508 generate_random_str(tctx, 8));
510 smb2_util_unlink(tree, fname);
512 smb2_oplock_create_share(&io1, fname,
513 smb2_util_share_access(""),
514 smb2_util_oplock_level("b"));
516 status = smb2_create(tree, mem_ctx, &io1);
517 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
518 "smb2_create failed");
519 _h1 = io1.out.file.handle;
520 h1 = &_h1;
521 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
522 torture_assert_int_equal(tctx, io1.out.oplock_level,
523 smb2_util_oplock_level("b"),
524 "oplock_level incorrect");
526 /* get the security descriptor */
528 ZERO_STRUCT(qfinfo);
530 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
531 qfinfo.query_secdesc.in.file.handle = _h1;
532 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
534 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
535 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
536 "smb2_getinfo_file failed");
538 sd1 = qfinfo.query_secdesc.out.sd;
540 /* re-authenticate as anonymous */
542 anon_creds = cli_credentials_init_anon(mem_ctx);
543 torture_assert(tctx, (anon_creds != NULL), "talloc error");
545 status = smb2_session_setup_spnego(tree->session,
546 anon_creds,
547 0 /* previous_session_id */);
548 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
549 "smb2_session_setup_spnego failed");
551 /* give full access on the file to anonymous */
553 extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
555 ZERO_STRUCT(ace);
556 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
557 ace.flags = 0;
558 ace.access_mask = SEC_STD_ALL | SEC_FILE_ALL;
559 ace.trustee = *extra_sid;
561 status = security_descriptor_dacl_add(sd1, &ace);
562 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
563 "security_descriptor_dacl_add failed");
565 ZERO_STRUCT(sfinfo);
566 sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
567 sfinfo.set_secdesc.in.file.handle = _h1;
568 sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
569 sfinfo.set_secdesc.in.sd = sd1;
571 status = smb2_setinfo_file(tree, &sfinfo);
572 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
573 "smb2_setinfo_file failed");
575 /* re-authenticate as original user again */
577 status = smb2_session_setup_spnego(tree->session,
578 popt_get_cmdline_credentials(),
579 0 /* previous_session_id */);
580 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
581 "smb2_session_setup_spnego failed");
583 /* re-get the security descriptor */
585 ZERO_STRUCT(qfinfo);
587 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
588 qfinfo.query_secdesc.in.file.handle = _h1;
589 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
591 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
592 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
593 "smb2_getinfo_file failed");
595 ret = true;
597 done:
598 if (h1 != NULL) {
599 smb2_util_close(tree, *h1);
602 smb2_util_unlink(tree, fname);
604 talloc_free(tree);
606 talloc_free(mem_ctx);
608 return ret;
612 * test renaming after reauth.
613 * compare security descriptors before and after rename/reauth
615 bool test_session_reauth5(struct torture_context *tctx, struct smb2_tree *tree)
617 NTSTATUS status;
618 TALLOC_CTX *mem_ctx = talloc_new(tctx);
619 char dname[256];
620 char fname[256];
621 char fname2[256];
622 struct smb2_handle _dh1;
623 struct smb2_handle *dh1 = NULL;
624 struct smb2_handle _h1;
625 struct smb2_handle *h1 = NULL;
626 struct smb2_create io1;
627 bool ret = true;
628 bool ok;
629 union smb_fileinfo qfinfo;
630 union smb_setfileinfo sfinfo;
631 struct cli_credentials *anon_creds = NULL;
632 uint32_t secinfo_flags = SECINFO_OWNER
633 | SECINFO_GROUP
634 | SECINFO_DACL
635 | SECINFO_PROTECTED_DACL
636 | SECINFO_UNPROTECTED_DACL;
637 struct security_descriptor *f_sd1;
638 struct security_descriptor *d_sd1 = NULL;
639 struct security_ace ace;
640 struct dom_sid *extra_sid;
642 /* Add some random component to the file name. */
643 snprintf(dname, sizeof(dname), "session_reauth5_%s.d",
644 generate_random_str(tctx, 8));
645 snprintf(fname, sizeof(fname), "%s\\file.dat", dname);
647 ok = smb2_util_setup_dir(tctx, tree, dname);
648 torture_assert(tctx, ok, "smb2_util_setup_dir not ok");
650 status = torture_smb2_testdir(tree, dname, &_dh1);
651 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
652 "torture_smb2_testdir failed");
653 dh1 = &_dh1;
655 smb2_oplock_create_share(&io1, fname,
656 smb2_util_share_access(""),
657 smb2_util_oplock_level("b"));
659 status = smb2_create(tree, mem_ctx, &io1);
660 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
661 "smb2_create failed");
662 _h1 = io1.out.file.handle;
663 h1 = &_h1;
664 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
665 torture_assert_int_equal(tctx, io1.out.oplock_level,
666 smb2_util_oplock_level("b"),
667 "oplock_level incorrect");
669 /* get the security descriptor */
671 ZERO_STRUCT(qfinfo);
673 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
674 qfinfo.query_secdesc.in.file.handle = _h1;
675 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
677 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
678 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
679 "smb2_getinfo_file failed");
681 f_sd1 = qfinfo.query_secdesc.out.sd;
683 /* re-authenticate as anonymous */
685 anon_creds = cli_credentials_init_anon(mem_ctx);
686 torture_assert(tctx, (anon_creds != NULL), "talloc error");
688 status = smb2_session_setup_spnego(tree->session,
689 anon_creds,
690 0 /* previous_session_id */);
691 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
692 "smb2_session_setup_spnego failed");
694 /* try to rename the file: fails */
696 snprintf(fname2, sizeof(fname2), "%s\\file2.dat", dname);
698 status = smb2_util_unlink(tree, fname2);
699 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
700 "smb2_util_unlink failed");
703 ZERO_STRUCT(sfinfo);
704 sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
705 sfinfo.rename_information.in.file.handle = _h1;
706 sfinfo.rename_information.in.overwrite = true;
707 sfinfo.rename_information.in.new_name = fname2;
709 status = smb2_setinfo_file(tree, &sfinfo);
710 torture_assert_ntstatus_equal_goto(tctx, status,
711 NT_STATUS_ACCESS_DENIED,
712 ret, done, "smb2_setinfo_file "
713 "returned unexpected status");
715 /* re-authenticate as original user again */
717 status = smb2_session_setup_spnego(tree->session,
718 popt_get_cmdline_credentials(),
719 0 /* previous_session_id */);
720 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
721 "smb2_session_setup_spnego failed");
723 /* give full access on the file to anonymous */
725 extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
727 ZERO_STRUCT(ace);
728 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
729 ace.flags = 0;
730 ace.access_mask = SEC_RIGHTS_FILE_ALL;
731 ace.trustee = *extra_sid;
733 status = security_descriptor_dacl_add(f_sd1, &ace);
734 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
735 "security_descriptor_dacl_add failed");
737 ZERO_STRUCT(sfinfo);
738 sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
739 sfinfo.set_secdesc.in.file.handle = _h1;
740 sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
741 sfinfo.set_secdesc.in.sd = f_sd1;
743 status = smb2_setinfo_file(tree, &sfinfo);
744 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
745 "smb2_setinfo_file failed");
747 /* re-get the security descriptor */
749 ZERO_STRUCT(qfinfo);
751 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
752 qfinfo.query_secdesc.in.file.handle = _h1;
753 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
755 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
756 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
757 "smb2_getinfo_file failed");
759 /* re-authenticate as anonymous - again */
761 anon_creds = cli_credentials_init_anon(mem_ctx);
762 torture_assert(tctx, (anon_creds != NULL), "talloc error");
764 status = smb2_session_setup_spnego(tree->session,
765 anon_creds,
766 0 /* previous_session_id */);
767 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
768 "smb2_session_setup_spnego failed");
770 /* try to rename the file: fails */
772 ZERO_STRUCT(sfinfo);
773 sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
774 sfinfo.rename_information.in.file.handle = _h1;
775 sfinfo.rename_information.in.overwrite = true;
776 sfinfo.rename_information.in.new_name = fname2;
778 status = smb2_setinfo_file(tree, &sfinfo);
779 torture_assert_ntstatus_equal_goto(tctx, status,
780 NT_STATUS_ACCESS_DENIED,
781 ret, done, "smb2_setinfo_file "
782 "returned unexpected status");
784 /* give full access on the parent dir to anonymous */
786 ZERO_STRUCT(qfinfo);
788 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
789 qfinfo.query_secdesc.in.file.handle = _dh1;
790 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
792 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
793 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
794 "smb2_getinfo_file failed");
796 d_sd1 = qfinfo.query_secdesc.out.sd;
798 ZERO_STRUCT(ace);
799 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
800 ace.flags = 0;
801 ace.access_mask = SEC_RIGHTS_FILE_ALL;
802 ace.trustee = *extra_sid;
804 status = security_descriptor_dacl_add(d_sd1, &ace);
805 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
806 "security_descriptor_dacl_add failed");
808 ZERO_STRUCT(sfinfo);
809 sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
810 sfinfo.set_secdesc.in.file.handle = _dh1;
811 sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
812 sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
813 sfinfo.set_secdesc.in.sd = d_sd1;
815 status = smb2_setinfo_file(tree, &sfinfo);
816 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
817 "smb2_setinfo_file failed");
819 ZERO_STRUCT(qfinfo);
821 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
822 qfinfo.query_secdesc.in.file.handle = _dh1;
823 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
825 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
826 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
827 "smb2_getinfo_file failed");
829 status = smb2_util_close(tree, _dh1);
830 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
831 "smb2_util_close failed");
832 dh1 = NULL;
834 /* try to rename the file: still fails */
836 ZERO_STRUCT(sfinfo);
837 sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
838 sfinfo.rename_information.in.file.handle = _h1;
839 sfinfo.rename_information.in.overwrite = true;
840 sfinfo.rename_information.in.new_name = fname2;
842 status = smb2_setinfo_file(tree, &sfinfo);
843 torture_assert_ntstatus_equal_goto(tctx, status,
844 NT_STATUS_ACCESS_DENIED,
845 ret, done, "smb2_setinfo_file "
846 "returned unexpected status");
848 /* re-authenticate as original user - again */
850 status = smb2_session_setup_spnego(tree->session,
851 popt_get_cmdline_credentials(),
852 0 /* previous_session_id */);
853 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
854 "smb2_session_setup_spnego failed");
856 /* rename the file - for verification that it works */
858 ZERO_STRUCT(sfinfo);
859 sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
860 sfinfo.rename_information.in.file.handle = _h1;
861 sfinfo.rename_information.in.overwrite = true;
862 sfinfo.rename_information.in.new_name = fname2;
864 status = smb2_setinfo_file(tree, &sfinfo);
865 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
866 "smb2_setinfo_file failed");
868 /* closs the file, check it is gone and reopen under the new name */
870 status = smb2_util_close(tree, _h1);
871 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
872 "smb2_util_close failed");
873 ZERO_STRUCT(io1);
875 smb2_generic_create_share(&io1,
876 NULL /* lease */, false /* dir */,
877 fname,
878 NTCREATEX_DISP_OPEN,
879 smb2_util_share_access(""),
880 smb2_util_oplock_level("b"),
881 0 /* leasekey */, 0 /* leasestate */);
883 status = smb2_create(tree, mem_ctx, &io1);
884 torture_assert_ntstatus_equal_goto(tctx, status,
885 NT_STATUS_OBJECT_NAME_NOT_FOUND,
886 ret, done, "smb2_create "
887 "returned unexpected status");
889 ZERO_STRUCT(io1);
891 smb2_generic_create_share(&io1,
892 NULL /* lease */, false /* dir */,
893 fname2,
894 NTCREATEX_DISP_OPEN,
895 smb2_util_share_access(""),
896 smb2_util_oplock_level("b"),
897 0 /* leasekey */, 0 /* leasestate */);
899 status = smb2_create(tree, mem_ctx, &io1);
900 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
901 "smb2_create failed");
902 _h1 = io1.out.file.handle;
903 h1 = &_h1;
904 CHECK_CREATED(tctx, &io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
905 torture_assert_int_equal(tctx, io1.out.oplock_level,
906 smb2_util_oplock_level("b"),
907 "oplock_level incorrect");
909 /* try to access the file via the old handle */
911 ZERO_STRUCT(qfinfo);
913 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
914 qfinfo.query_secdesc.in.file.handle = _h1;
915 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
917 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
918 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
919 "smb2_getinfo_file failed");
921 done:
922 if (dh1 != NULL) {
923 smb2_util_close(tree, *dh1);
925 if (h1 != NULL) {
926 smb2_util_close(tree, *h1);
929 smb2_deltree(tree, dname);
931 talloc_free(tree);
933 talloc_free(mem_ctx);
935 return ret;
939 * do reauth with wrong credentials,
940 * hence triggering the error path in reauth.
941 * The invalid reauth deletes the session.
943 bool test_session_reauth6(struct torture_context *tctx, struct smb2_tree *tree)
945 NTSTATUS status;
946 TALLOC_CTX *mem_ctx = talloc_new(tctx);
947 char fname[256];
948 struct smb2_handle _h1;
949 struct smb2_handle *h1 = NULL;
950 struct smb2_create io1;
951 bool ret = true;
952 char *corrupted_password;
953 struct cli_credentials *broken_creds;
954 bool ok;
955 bool encrypted;
956 NTSTATUS expected;
957 enum credentials_use_kerberos krb_state;
959 krb_state = cli_credentials_get_kerberos_state(
960 popt_get_cmdline_credentials());
961 if (krb_state == CRED_MUST_USE_KERBEROS) {
962 torture_skip(tctx,
963 "Can't test failing session setup with kerberos.");
966 encrypted = smb2cli_tcon_is_encryption_on(tree->smbXcli);
968 /* Add some random component to the file name. */
969 snprintf(fname, sizeof(fname), "session_reauth1_%s.dat",
970 generate_random_str(tctx, 8));
972 smb2_util_unlink(tree, fname);
974 smb2_oplock_create_share(&io1, fname,
975 smb2_util_share_access(""),
976 smb2_util_oplock_level("b"));
977 io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
979 status = smb2_create(tree, mem_ctx, &io1);
980 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
981 "smb2_create failed");
982 _h1 = io1.out.file.handle;
983 h1 = &_h1;
984 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
985 torture_assert_int_equal(tctx, io1.out.oplock_level,
986 smb2_util_oplock_level("b"),
987 "oplock_level incorrect");
990 * reauthentication with invalid credentials:
993 broken_creds = cli_credentials_shallow_copy(mem_ctx,
994 popt_get_cmdline_credentials());
995 torture_assert(tctx, (broken_creds != NULL), "talloc error");
997 corrupted_password = talloc_asprintf(mem_ctx, "%s%s",
998 cli_credentials_get_password(broken_creds),
999 "corrupt");
1000 torture_assert(tctx, (corrupted_password != NULL), "talloc error");
1002 ok = cli_credentials_set_password(broken_creds, corrupted_password,
1003 CRED_SPECIFIED);
1004 torture_assert(tctx, ok, "cli_credentials_set_password not ok");
1006 status = smb2_session_setup_spnego(tree->session,
1007 broken_creds,
1008 0 /* previous_session_id */);
1009 torture_assert_ntstatus_equal_goto(tctx, status,
1010 NT_STATUS_LOGON_FAILURE, ret, done,
1011 "smb2_session_setup_spnego "
1012 "returned unexpected status");
1014 torture_comment(tctx, "did failed reauth\n");
1016 * now verify that the invalid session reauth has closed our session
1019 if (encrypted) {
1020 expected = NT_STATUS_CONNECTION_DISCONNECTED;
1021 } else {
1022 expected = NT_STATUS_USER_SESSION_DELETED;
1025 smb2_oplock_create_share(&io1, fname,
1026 smb2_util_share_access(""),
1027 smb2_util_oplock_level("b"));
1029 status = smb2_create(tree, mem_ctx, &io1);
1030 torture_assert_ntstatus_equal_goto(tctx, status, expected,
1031 ret, done, "smb2_create "
1032 "returned unexpected status");
1034 done:
1035 if (h1 != NULL) {
1036 smb2_util_close(tree, *h1);
1039 smb2_util_unlink(tree, fname);
1041 talloc_free(tree);
1043 talloc_free(mem_ctx);
1045 return ret;
1049 static bool test_session_expire1(struct torture_context *tctx)
1051 NTSTATUS status;
1052 bool ret = false;
1053 struct smbcli_options options;
1054 const char *host = torture_setting_string(tctx, "host", NULL);
1055 const char *share = torture_setting_string(tctx, "share", NULL);
1056 struct cli_credentials *credentials = popt_get_cmdline_credentials();
1057 struct smb2_tree *tree = NULL;
1058 enum credentials_use_kerberos use_kerberos;
1059 char fname[256];
1060 struct smb2_handle _h1;
1061 struct smb2_handle *h1 = NULL;
1062 struct smb2_create io1;
1063 union smb_fileinfo qfinfo;
1064 size_t i;
1066 use_kerberos = cli_credentials_get_kerberos_state(credentials);
1067 if (use_kerberos != CRED_MUST_USE_KERBEROS) {
1068 torture_warning(tctx, "smb2.session.expire1 requires -k yes!");
1069 torture_skip(tctx, "smb2.session.expire1 requires -k yes!");
1072 torture_assert_int_equal(tctx, use_kerberos, CRED_MUST_USE_KERBEROS,
1073 "please use -k yes");
1075 lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
1077 lpcfg_smbcli_options(tctx->lp_ctx, &options);
1079 status = smb2_connect(tctx,
1080 host,
1081 lpcfg_smb_ports(tctx->lp_ctx),
1082 share,
1083 lpcfg_resolve_context(tctx->lp_ctx),
1084 credentials,
1085 &tree,
1086 tctx->ev,
1087 &options,
1088 lpcfg_socket_options(tctx->lp_ctx),
1089 lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1091 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1092 "smb2_connect failed");
1094 /* Add some random component to the file name. */
1095 snprintf(fname, sizeof(fname), "session_expire1_%s.dat",
1096 generate_random_str(tctx, 8));
1098 smb2_util_unlink(tree, fname);
1100 smb2_oplock_create_share(&io1, fname,
1101 smb2_util_share_access(""),
1102 smb2_util_oplock_level("b"));
1103 io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1105 status = smb2_create(tree, tctx, &io1);
1106 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1107 "smb2_create failed");
1108 _h1 = io1.out.file.handle;
1109 h1 = &_h1;
1110 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1111 torture_assert_int_equal(tctx, io1.out.oplock_level,
1112 smb2_util_oplock_level("b"),
1113 "oplock_level incorrect");
1115 /* get the security descriptor */
1117 ZERO_STRUCT(qfinfo);
1119 qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
1120 qfinfo.access_information.in.file.handle = _h1;
1122 for (i=0; i < 2; i++) {
1123 torture_comment(tctx, "query info => OK\n");
1125 ZERO_STRUCT(qfinfo.access_information.out);
1126 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1127 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1128 "smb2_getinfo_file failed");
1130 torture_comment(tctx, "sleep 10 seconds\n");
1131 smb_msleep(10*1000);
1133 torture_comment(tctx, "query info => EXPIRED\n");
1134 ZERO_STRUCT(qfinfo.access_information.out);
1135 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1136 torture_assert_ntstatus_equal_goto(tctx, status,
1137 NT_STATUS_NETWORK_SESSION_EXPIRED,
1138 ret, done, "smb2_getinfo_file "
1139 "returned unexpected status");
1142 * the krb5 library may not handle expired creds
1143 * well, lets start with an empty ccache.
1145 cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
1147 torture_comment(tctx, "reauth => OK\n");
1148 status = smb2_session_setup_spnego(tree->session,
1149 credentials,
1150 0 /* previous_session_id */);
1151 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1152 "smb2_session_setup_spnego failed");
1155 ZERO_STRUCT(qfinfo.access_information.out);
1156 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1157 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1158 "smb2_getinfo_file failed");
1160 ret = true;
1161 done:
1162 if (h1 != NULL) {
1163 smb2_util_close(tree, *h1);
1166 talloc_free(tree);
1167 lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
1168 return ret;
1171 static bool test_session_expire2(struct torture_context *tctx)
1173 NTSTATUS status;
1174 bool ret = false;
1175 struct smbcli_options options;
1176 const char *host = torture_setting_string(tctx, "host", NULL);
1177 const char *share = torture_setting_string(tctx, "share", NULL);
1178 struct cli_credentials *credentials = popt_get_cmdline_credentials();
1179 struct smb2_tree *tree = NULL;
1180 const char *unc = NULL;
1181 struct smb2_tree *tree2 = NULL;
1182 struct tevent_req *subreq = NULL;
1183 uint32_t timeout_msec;
1184 enum credentials_use_kerberos use_kerberos;
1185 uint32_t caps;
1186 char fname[256];
1187 struct smb2_handle dh;
1188 struct smb2_handle dh2;
1189 struct smb2_handle _h1;
1190 struct smb2_handle *h1 = NULL;
1191 struct smb2_create io1;
1192 union smb_fileinfo qfinfo;
1193 union smb_setfileinfo sfinfo;
1194 struct smb2_flush flsh;
1195 struct smb2_read rd;
1196 const uint8_t wd = 0;
1197 struct smb2_lock lck;
1198 struct smb2_lock_element el;
1199 struct smb2_ioctl ctl;
1200 struct smb2_break oack;
1201 struct smb2_lease_break_ack lack;
1202 struct smb2_find fnd;
1203 union smb_search_data *d = NULL;
1204 unsigned int count;
1205 struct smb2_request *req = NULL;
1206 struct smb2_notify ntf1;
1207 struct smb2_notify ntf2;
1209 use_kerberos = cli_credentials_get_kerberos_state(credentials);
1210 if (use_kerberos != CRED_MUST_USE_KERBEROS) {
1211 torture_warning(tctx, "smb2.session.expire2 requires -k yes!");
1212 torture_skip(tctx, "smb2.session.expire2 requires -k yes!");
1215 torture_assert_int_equal(tctx, use_kerberos, CRED_MUST_USE_KERBEROS,
1216 "please use -k yes");
1218 lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
1220 lpcfg_smbcli_options(tctx->lp_ctx, &options);
1222 unc = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
1223 torture_assert(tctx, unc != NULL, "talloc_asprintf");
1225 status = smb2_connect(tctx,
1226 host,
1227 lpcfg_smb_ports(tctx->lp_ctx),
1228 share,
1229 lpcfg_resolve_context(tctx->lp_ctx),
1230 credentials,
1231 &tree,
1232 tctx->ev,
1233 &options,
1234 lpcfg_socket_options(tctx->lp_ctx),
1235 lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1237 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1238 "smb2_connect failed");
1240 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1242 /* Add some random component to the file name. */
1243 snprintf(fname, sizeof(fname), "session_expire2_%s.dat",
1244 generate_random_str(tctx, 8));
1246 smb2_util_unlink(tree, fname);
1248 status = smb2_util_roothandle(tree, &dh);
1249 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1250 "smb2_util_roothandle failed");
1252 smb2_oplock_create_share(&io1, fname,
1253 smb2_util_share_access(""),
1254 smb2_util_oplock_level("b"));
1255 io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1257 status = smb2_create(tree, tctx, &io1);
1258 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1259 "smb2_create failed");
1260 _h1 = io1.out.file.handle;
1261 h1 = &_h1;
1262 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1263 torture_assert_int_equal(tctx, io1.out.oplock_level,
1264 smb2_util_oplock_level("b"),
1265 "oplock_level incorrect");
1267 /* get the security descriptor */
1269 ZERO_STRUCT(qfinfo);
1271 qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
1272 qfinfo.access_information.in.file.handle = _h1;
1274 torture_comment(tctx, "query info => OK\n");
1276 ZERO_STRUCT(qfinfo.access_information.out);
1277 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1278 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1279 "smb2_getinfo_file failed");
1281 torture_comment(tctx, "lock => OK\n");
1282 ZERO_STRUCT(lck);
1283 lck.in.locks = &el;
1284 lck.in.lock_count = 0x0001;
1285 lck.in.lock_sequence = 0x00000000;
1286 lck.in.file.handle = *h1;
1287 ZERO_STRUCT(el);
1288 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1289 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1290 el.offset = 0x0000000000000000;
1291 el.length = 0x0000000000000001;
1292 status = smb2_lock(tree, &lck);
1293 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1294 "smb2_lock lock failed");
1296 torture_comment(tctx, "1st notify => PENDING\n");
1297 ZERO_STRUCT(ntf1);
1298 ntf1.in.file.handle = dh;
1299 ntf1.in.recursive = 0x0000;
1300 ntf1.in.buffer_size = 128;
1301 ntf1.in.completion_filter= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1302 ntf1.in.unknown = 0x00000000;
1303 req = smb2_notify_send(tree, &ntf1);
1305 while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
1306 if (tevent_loop_once(tctx->ev) != 0) {
1307 break;
1311 torture_assert_goto(tctx, req->state <= SMB2_REQUEST_RECV, ret, done,
1312 "smb2_notify finished");
1314 torture_comment(tctx, "sleep 10 seconds\n");
1315 smb_msleep(10*1000);
1317 torture_comment(tctx, "query info => EXPIRED\n");
1318 ZERO_STRUCT(qfinfo.access_information.out);
1319 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1320 torture_assert_ntstatus_equal_goto(tctx, status,
1321 NT_STATUS_NETWORK_SESSION_EXPIRED,
1322 ret, done, "smb2_getinfo_file "
1323 "returned unexpected status");
1326 torture_comment(tctx, "set info => EXPIRED\n");
1327 ZERO_STRUCT(sfinfo);
1328 sfinfo.end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1329 sfinfo.end_of_file_info.in.file.handle = *h1;
1330 sfinfo.end_of_file_info.in.size = 1;
1331 status = smb2_setinfo_file(tree, &sfinfo);
1332 torture_assert_ntstatus_equal_goto(tctx, status,
1333 NT_STATUS_NETWORK_SESSION_EXPIRED,
1334 ret, done, "smb2_setinfo_file "
1335 "returned unexpected status");
1337 torture_comment(tctx, "flush => EXPIRED\n");
1338 ZERO_STRUCT(flsh);
1339 flsh.in.file.handle = *h1;
1340 status = smb2_flush(tree, &flsh);
1341 torture_assert_ntstatus_equal_goto(tctx, status,
1342 NT_STATUS_NETWORK_SESSION_EXPIRED,
1343 ret, done, "smb2_flush "
1344 "returned unexpected status");
1346 torture_comment(tctx, "read => EXPIRED\n");
1347 ZERO_STRUCT(rd);
1348 rd.in.file.handle = *h1;
1349 rd.in.length = 5;
1350 rd.in.offset = 0;
1351 status = smb2_read(tree, tctx, &rd);
1352 torture_assert_ntstatus_equal_goto(tctx, status,
1353 NT_STATUS_NETWORK_SESSION_EXPIRED,
1354 ret, done, "smb2_read "
1355 "returned unexpected status");
1357 torture_comment(tctx, "write => EXPIRED\n");
1358 status = smb2_util_write(tree, *h1, &wd, 0, 1);
1359 torture_assert_ntstatus_equal_goto(tctx, status,
1360 NT_STATUS_NETWORK_SESSION_EXPIRED,
1361 ret, done, "smb2_util_write "
1362 "returned unexpected status");
1364 torture_comment(tctx, "ioctl => EXPIRED\n");
1365 ZERO_STRUCT(ctl);
1366 ctl.in.file.handle = *h1;
1367 ctl.in.function = FSCTL_SRV_ENUM_SNAPS;
1368 ctl.in.max_response_size = 16;
1369 ctl.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
1370 status = smb2_ioctl(tree, tctx, &ctl);
1371 torture_assert_ntstatus_equal_goto(tctx, status,
1372 NT_STATUS_NETWORK_SESSION_EXPIRED,
1373 ret, done, "smb2_ioctl "
1374 "returned unexpected status");
1376 torture_comment(tctx, "oplock ack => EXPIRED\n");
1377 ZERO_STRUCT(oack);
1378 oack.in.file.handle = *h1;
1379 status = smb2_break(tree, &oack);
1380 torture_assert_ntstatus_equal_goto(tctx, status,
1381 NT_STATUS_NETWORK_SESSION_EXPIRED,
1382 ret, done, "smb2_break "
1383 "returned unexpected status");
1385 if (caps & SMB2_CAP_LEASING) {
1386 torture_comment(tctx, "lease ack => EXPIRED\n");
1387 ZERO_STRUCT(lack);
1388 lack.in.lease.lease_version = 1;
1389 lack.in.lease.lease_key.data[0] = 1;
1390 lack.in.lease.lease_key.data[1] = 2;
1391 status = smb2_lease_break_ack(tree, &lack);
1392 torture_assert_ntstatus_equal_goto(tctx, status,
1393 NT_STATUS_NETWORK_SESSION_EXPIRED,
1394 ret, done, "smb2_break "
1395 "returned unexpected status");
1398 torture_comment(tctx, "query directory => EXPIRED\n");
1399 ZERO_STRUCT(fnd);
1400 fnd.in.file.handle = dh;
1401 fnd.in.pattern = "*";
1402 fnd.in.continue_flags = SMB2_CONTINUE_FLAG_SINGLE;
1403 fnd.in.max_response_size= 0x100;
1404 fnd.in.level = SMB2_FIND_BOTH_DIRECTORY_INFO;
1405 status = smb2_find_level(tree, tree, &fnd, &count, &d);
1406 torture_assert_ntstatus_equal_goto(tctx, status,
1407 NT_STATUS_NETWORK_SESSION_EXPIRED,
1408 ret, done, "smb2_find_level "
1409 "returned unexpected status");
1411 torture_comment(tctx, "1st notify => CANCEL\n");
1412 smb2_cancel(req);
1414 torture_comment(tctx, "2nd notify => EXPIRED\n");
1415 ZERO_STRUCT(ntf2);
1416 ntf2.in.file.handle = dh;
1417 ntf2.in.recursive = 0x0000;
1418 ntf2.in.buffer_size = 128;
1419 ntf2.in.completion_filter= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1420 ntf2.in.unknown = 0x00000000;
1421 status = smb2_notify(tree, tctx, &ntf2);
1422 torture_assert_ntstatus_equal_goto(tctx, status,
1423 NT_STATUS_NETWORK_SESSION_EXPIRED,
1424 ret, done, "smb2_notify "
1425 "returned unexpected status");
1427 torture_assert_goto(tctx, req->state > SMB2_REQUEST_RECV, ret, done,
1428 "smb2_notify (1st) not finished");
1430 status = smb2_notify_recv(req, tctx, &ntf1);
1431 torture_assert_ntstatus_equal_goto(tctx, status,
1432 NT_STATUS_CANCELLED,
1433 ret, done, "smb2_notify cancelled"
1434 "returned unexpected status");
1436 torture_comment(tctx, "tcon => EXPIRED\n");
1437 tree2 = smb2_tree_init(tree->session, tctx, false);
1438 torture_assert(tctx, tree2 != NULL, "smb2_tree_init");
1439 timeout_msec = tree->session->transport->options.request_timeout * 1000;
1440 subreq = smb2cli_tcon_send(tree2, tctx->ev,
1441 tree2->session->transport->conn,
1442 timeout_msec,
1443 tree2->session->smbXcli,
1444 tree2->smbXcli,
1445 0, /* flags */
1446 unc);
1447 torture_assert(tctx, subreq != NULL, "smb2cli_tcon_send");
1448 torture_assert(tctx,
1449 tevent_req_poll_ntstatus(subreq, tctx->ev, &status),
1450 "tevent_req_poll_ntstatus");
1451 status = smb2cli_tcon_recv(subreq);
1452 TALLOC_FREE(subreq);
1453 torture_assert_ntstatus_equal_goto(tctx, status,
1454 NT_STATUS_NETWORK_SESSION_EXPIRED,
1455 ret, done, "smb2cli_tcon"
1456 "returned unexpected status");
1458 torture_comment(tctx, "create => EXPIRED\n");
1459 status = smb2_util_roothandle(tree, &dh2);
1460 torture_assert_ntstatus_equal_goto(tctx, status,
1461 NT_STATUS_NETWORK_SESSION_EXPIRED,
1462 ret, done, "smb2_util_roothandle"
1463 "returned unexpected status");
1465 torture_comment(tctx, "tdis => EXPIRED\n");
1466 status = smb2_tdis(tree);
1467 torture_assert_ntstatus_equal_goto(tctx, status,
1468 NT_STATUS_NETWORK_SESSION_EXPIRED,
1469 ret, done, "smb2cli_tdis"
1470 "returned unexpected status");
1473 * (Un)Lock, Close and Logoff are still possible
1476 torture_comment(tctx, "1st unlock => OK\n");
1477 el.flags = SMB2_LOCK_FLAG_UNLOCK;
1478 status = smb2_lock(tree, &lck);
1479 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1480 "smb2_lock unlock failed");
1482 torture_comment(tctx, "2nd unlock => RANGE_NOT_LOCKED\n");
1483 status = smb2_lock(tree, &lck);
1484 torture_assert_ntstatus_equal_goto(tctx, status,
1485 NT_STATUS_RANGE_NOT_LOCKED,
1486 ret, done, "smb2_lock 2nd unlock"
1487 "returned unexpected status");
1489 torture_comment(tctx, "lock => EXPIRED\n");
1490 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1491 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1492 status = smb2_lock(tree, &lck);
1493 torture_assert_ntstatus_equal_goto(tctx, status,
1494 NT_STATUS_NETWORK_SESSION_EXPIRED,
1495 ret, done, "smb2_util_roothandle"
1496 "returned unexpected status");
1498 torture_comment(tctx, "close => OK\n");
1499 status = smb2_util_close(tree, *h1);
1500 h1 = NULL;
1501 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1502 "smb2_close failed");
1504 torture_comment(tctx, "echo without session => OK\n");
1505 status = smb2_keepalive(tree->session->transport);
1506 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1507 "smb2_keepalive without session failed");
1509 torture_comment(tctx, "echo with session => OK\n");
1510 req = smb2_keepalive_send(tree->session->transport, tree->session);
1511 status = smb2_keepalive_recv(req);
1512 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1513 "smb2_keepalive with session failed");
1515 torture_comment(tctx, "logoff => OK\n");
1516 status = smb2_logoff(tree->session);
1517 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1518 "smb2_logoff failed");
1520 ret = true;
1521 done:
1522 if (h1 != NULL) {
1523 smb2_util_close(tree, *h1);
1526 talloc_free(tree);
1527 lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
1528 return ret;
1531 bool test_session_bind1(struct torture_context *tctx, struct smb2_tree *tree1)
1533 const char *host = torture_setting_string(tctx, "host", NULL);
1534 const char *share = torture_setting_string(tctx, "share", NULL);
1535 struct cli_credentials *credentials = popt_get_cmdline_credentials();
1536 NTSTATUS status;
1537 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1538 char fname[256];
1539 struct smb2_handle _h1;
1540 struct smb2_handle *h1 = NULL;
1541 struct smb2_create io1;
1542 union smb_fileinfo qfinfo;
1543 bool ret = false;
1544 struct smb2_tree *tree2 = NULL;
1545 struct smb2_transport *transport1 = tree1->session->transport;
1546 struct smb2_transport *transport2 = NULL;
1547 struct smb2_session *session1_1 = tree1->session;
1548 struct smb2_session *session1_2 = NULL;
1549 struct smb2_session *session2_1 = NULL;
1550 struct smb2_session *session2_2 = NULL;
1551 uint32_t caps;
1553 caps = smb2cli_conn_server_capabilities(transport1->conn);
1554 if (!(caps & SMB2_CAP_MULTI_CHANNEL)) {
1555 torture_skip(tctx, "server doesn't support SMB2_CAP_MULTI_CHANNEL\n");
1558 /* Add some random component to the file name. */
1559 snprintf(fname, sizeof(fname), "session_bind1_%s.dat",
1560 generate_random_str(tctx, 8));
1562 smb2_util_unlink(tree1, fname);
1564 smb2_oplock_create_share(&io1, fname,
1565 smb2_util_share_access(""),
1566 smb2_util_oplock_level("b"));
1568 status = smb2_create(tree1, mem_ctx, &io1);
1569 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1570 "smb2_create failed");
1571 _h1 = io1.out.file.handle;
1572 h1 = &_h1;
1573 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1574 torture_assert_int_equal(tctx, io1.out.oplock_level,
1575 smb2_util_oplock_level("b"),
1576 "oplock_level incorrect");
1578 status = smb2_connect(tctx,
1579 host,
1580 lpcfg_smb_ports(tctx->lp_ctx),
1581 share,
1582 lpcfg_resolve_context(tctx->lp_ctx),
1583 credentials,
1584 &tree2,
1585 tctx->ev,
1586 &transport1->options,
1587 lpcfg_socket_options(tctx->lp_ctx),
1588 lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1590 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1591 "smb2_connect failed");
1592 session2_2 = tree2->session;
1593 transport2 = tree2->session->transport;
1596 * Now bind the 2nd transport connection to the 1st session
1598 session1_2 = smb2_session_channel(transport2,
1599 lpcfg_gensec_settings(tctx, tctx->lp_ctx),
1600 tree2,
1601 session1_1);
1602 torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
1604 status = smb2_session_setup_spnego(session1_2,
1605 popt_get_cmdline_credentials(),
1606 0 /* previous_session_id */);
1607 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1608 "smb2_session_setup_spnego failed");
1610 /* use the 1st connection, 1st session */
1611 ZERO_STRUCT(qfinfo);
1612 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
1613 qfinfo.generic.in.file.handle = _h1;
1614 tree1->session = session1_1;
1615 status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
1616 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1617 "smb2_getinfo_file failed");
1619 /* use the 2nd connection, 1st session */
1620 ZERO_STRUCT(qfinfo);
1621 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
1622 qfinfo.generic.in.file.handle = _h1;
1623 tree1->session = session1_2;
1624 status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
1625 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1626 "smb2_getinfo_file failed");
1628 tree1->session = session1_1;
1629 status = smb2_util_close(tree1, *h1);
1630 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1631 "smb2_util_close failed");
1632 h1 = NULL;
1635 * Now bind the 1st transport connection to the 2nd session
1637 session2_1 = smb2_session_channel(transport1,
1638 lpcfg_gensec_settings(tctx, tctx->lp_ctx),
1639 tree1,
1640 session2_2);
1641 torture_assert(tctx, session2_1 != NULL, "smb2_session_channel failed");
1643 status = smb2_session_setup_spnego(session2_1,
1644 popt_get_cmdline_credentials(),
1645 0 /* previous_session_id */);
1646 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1647 "smb2_session_setup_spnego failed");
1649 tree2->session = session2_1;
1650 status = smb2_util_unlink(tree2, fname);
1651 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1652 "smb2_util_unlink failed");
1653 ret = true;
1654 done:
1655 talloc_free(tree2);
1656 tree1->session = session1_1;
1658 if (h1 != NULL) {
1659 smb2_util_close(tree1, *h1);
1662 smb2_util_unlink(tree1, fname);
1664 talloc_free(tree1);
1666 talloc_free(mem_ctx);
1668 return ret;
1671 struct torture_suite *torture_smb2_session_init(TALLOC_CTX *ctx)
1673 struct torture_suite *suite =
1674 torture_suite_create(ctx, "session");
1676 torture_suite_add_1smb2_test(suite, "reconnect1", test_session_reconnect1);
1677 torture_suite_add_1smb2_test(suite, "reconnect2", test_session_reconnect2);
1678 torture_suite_add_1smb2_test(suite, "reauth1", test_session_reauth1);
1679 torture_suite_add_1smb2_test(suite, "reauth2", test_session_reauth2);
1680 torture_suite_add_1smb2_test(suite, "reauth3", test_session_reauth3);
1681 torture_suite_add_1smb2_test(suite, "reauth4", test_session_reauth4);
1682 torture_suite_add_1smb2_test(suite, "reauth5", test_session_reauth5);
1683 torture_suite_add_1smb2_test(suite, "reauth6", test_session_reauth6);
1684 torture_suite_add_simple_test(suite, "expire1", test_session_expire1);
1685 torture_suite_add_simple_test(suite, "expire2", test_session_expire2);
1686 torture_suite_add_1smb2_test(suite, "bind1", test_session_bind1);
1688 suite->description = talloc_strdup(suite, "SMB2-SESSION tests");
1690 return suite;