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/>.
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) \
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.size, 0, \
42 "out.size incorrect"); \
43 torture_assert_int_equal(tctx, (__io)->out.file_attr, \
45 "out.file_attr incorrect"); \
46 torture_assert_int_equal(tctx, (__io)->out.reserved2, 0, \
47 "out.reserverd2 incorrect"); \
51 * basic test for doing a session reconnect
53 bool test_session_reconnect1(struct torture_context *tctx, struct smb2_tree *tree)
56 TALLOC_CTX *mem_ctx = talloc_new(tctx);
58 struct smb2_handle _h1;
59 struct smb2_handle *h1 = NULL;
60 struct smb2_handle _h2;
61 struct smb2_handle *h2 = NULL;
62 struct smb2_create io1, io2;
63 uint64_t previous_session_id;
65 struct smb2_tree *tree2 = NULL;
66 union smb_fileinfo qfinfo;
68 /* Add some random component to the file name. */
69 snprintf(fname, sizeof(fname), "session_reconnect_%s.dat",
70 generate_random_str(tctx, 8));
72 smb2_util_unlink(tree, fname);
74 smb2_oplock_create_share(&io1, fname,
75 smb2_util_share_access(""),
76 smb2_util_oplock_level("b"));
78 status = smb2_create(tree, mem_ctx, &io1);
79 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
80 "smb2_create failed");
81 _h1 = io1.out.file.handle;
83 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
84 torture_assert_int_equal(tctx, io1.out.oplock_level,
85 smb2_util_oplock_level("b"),
86 "oplock_level incorrect");
88 /* disconnect, reconnect and then do durable reopen */
89 previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
91 torture_assert_goto(tctx, torture_smb2_connection_ext(tctx, previous_session_id,
92 &tree->session->transport->options, &tree2),
94 "session reconnect failed\n");
96 /* try to access the file via the old handle */
99 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
100 qfinfo.generic.in.file.handle = _h1;
101 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
102 torture_assert_ntstatus_equal_goto(tctx, status,
103 NT_STATUS_USER_SESSION_DELETED,
104 ret, done, "smb2_getinfo_file "
105 "returned unexpected status");
108 smb2_oplock_create_share(&io2, fname,
109 smb2_util_share_access(""),
110 smb2_util_oplock_level("b"));
112 status = smb2_create(tree2, mem_ctx, &io2);
113 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
114 "smb2_create failed");
116 CHECK_CREATED(tctx, &io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
117 torture_assert_int_equal(tctx, io1.out.oplock_level,
118 smb2_util_oplock_level("b"),
119 "oplock_level incorrect");
120 _h2 = io2.out.file.handle;
125 smb2_util_close(tree, *h1);
128 smb2_util_close(tree2, *h2);
132 smb2_util_unlink(tree2, fname);
134 smb2_util_unlink(tree, fname);
139 talloc_free(mem_ctx);
145 * basic test for doing a session reconnect on one connection
147 bool test_session_reconnect2(struct torture_context *tctx, struct smb2_tree *tree)
150 TALLOC_CTX *mem_ctx = talloc_new(tctx);
152 struct smb2_handle _h1;
153 struct smb2_handle *h1 = NULL;
154 struct smb2_create io1;
155 uint64_t previous_session_id;
157 struct smb2_session *session2 = NULL;
158 union smb_fileinfo qfinfo;
160 /* Add some random component to the file name. */
161 snprintf(fname, sizeof(fname), "session_reconnect_%s.dat",
162 generate_random_str(tctx, 8));
164 smb2_util_unlink(tree, fname);
166 smb2_oplock_create_share(&io1, fname,
167 smb2_util_share_access(""),
168 smb2_util_oplock_level("b"));
169 io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
171 status = smb2_create(tree, mem_ctx, &io1);
172 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
173 "smb2_create failed");
174 _h1 = io1.out.file.handle;
176 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
177 torture_assert_int_equal(tctx, io1.out.oplock_level,
178 smb2_util_oplock_level("b"),
179 "oplock_level incorrect");
181 /* disconnect, reconnect and then do durable reopen */
182 previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
184 torture_assert(tctx, torture_smb2_session_setup(tctx, tree->session->transport,
185 previous_session_id, tctx, &session2),
186 "session reconnect (on the same connection) failed");
188 /* try to access the file via the old handle */
191 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
192 qfinfo.generic.in.file.handle = _h1;
193 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
194 torture_assert_ntstatus_equal_goto(tctx, status,
195 NT_STATUS_USER_SESSION_DELETED,
196 ret, done, "smb2_getinfo_file "
197 "returned unexpected status");
202 smb2_util_close(tree, *h1);
206 talloc_free(session2);
208 talloc_free(mem_ctx);
213 bool test_session_reauth1(struct torture_context *tctx, struct smb2_tree *tree)
216 TALLOC_CTX *mem_ctx = talloc_new(tctx);
218 struct smb2_handle _h1;
219 struct smb2_handle *h1 = NULL;
220 struct smb2_create io1;
222 union smb_fileinfo qfinfo;
224 /* Add some random component to the file name. */
225 snprintf(fname, sizeof(fname), "session_reauth1_%s.dat",
226 generate_random_str(tctx, 8));
228 smb2_util_unlink(tree, fname);
230 smb2_oplock_create_share(&io1, fname,
231 smb2_util_share_access(""),
232 smb2_util_oplock_level("b"));
234 status = smb2_create(tree, mem_ctx, &io1);
235 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
236 "smb2_create failed");
237 _h1 = io1.out.file.handle;
239 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
240 torture_assert_int_equal(tctx, io1.out.oplock_level,
241 smb2_util_oplock_level("b"),
242 "oplock_level incorrect");
244 status = smb2_session_setup_spnego(tree->session,
245 popt_get_cmdline_credentials(),
246 0 /* previous_session_id */);
247 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
248 "smb2_session_setup_spnego failed");
250 /* try to access the file via the old handle */
253 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
254 qfinfo.generic.in.file.handle = _h1;
255 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
256 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
257 "smb2_getinfo_file failed");
259 status = smb2_session_setup_spnego(tree->session,
260 popt_get_cmdline_credentials(),
261 0 /* previous_session_id */);
262 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
263 "smb2_session_setup_spnego failed");
265 /* try to access the file via the old handle */
268 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
269 qfinfo.generic.in.file.handle = _h1;
270 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
271 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
272 "smb2_getinfo_file failed");
276 smb2_util_close(tree, *h1);
279 smb2_util_unlink(tree, fname);
283 talloc_free(mem_ctx);
288 bool test_session_reauth2(struct torture_context *tctx, struct smb2_tree *tree)
291 TALLOC_CTX *mem_ctx = talloc_new(tctx);
293 struct smb2_handle _h1;
294 struct smb2_handle *h1 = NULL;
295 struct smb2_create io1;
297 union smb_fileinfo qfinfo;
298 struct cli_credentials *anon_creds = NULL;
300 /* Add some random component to the file name. */
301 snprintf(fname, sizeof(fname), "session_reauth2_%s.dat",
302 generate_random_str(tctx, 8));
304 smb2_util_unlink(tree, fname);
306 smb2_oplock_create_share(&io1, fname,
307 smb2_util_share_access(""),
308 smb2_util_oplock_level("b"));
310 status = smb2_create(tree, mem_ctx, &io1);
311 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
312 "smb2_create failed");
313 _h1 = io1.out.file.handle;
315 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
316 torture_assert_int_equal(tctx, io1.out.oplock_level,
317 smb2_util_oplock_level("b"),
318 "oplock_level incorrect");
320 /* re-authenticate as anonymous */
322 anon_creds = cli_credentials_init_anon(mem_ctx);
323 torture_assert(tctx, (anon_creds != NULL), "talloc error");
325 status = smb2_session_setup_spnego(tree->session,
327 0 /* previous_session_id */);
328 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
329 "smb2_session_setup_spnego failed");
331 /* try to access the file via the old handle */
334 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
335 qfinfo.generic.in.file.handle = _h1;
336 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
337 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
338 "smb2_getinfo_file failed");
340 /* re-authenticate as original user again */
342 status = smb2_session_setup_spnego(tree->session,
343 popt_get_cmdline_credentials(),
344 0 /* previous_session_id */);
345 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
346 "smb2_session_setup_spnego failed");
348 /* try to access the file via the old handle */
351 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
352 qfinfo.generic.in.file.handle = _h1;
353 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
354 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
355 "smb2_getinfo_file failed");
359 smb2_util_close(tree, *h1);
362 smb2_util_unlink(tree, fname);
366 talloc_free(mem_ctx);
372 * test getting security descriptor after reauth
374 bool test_session_reauth3(struct torture_context *tctx, struct smb2_tree *tree)
377 TALLOC_CTX *mem_ctx = talloc_new(tctx);
379 struct smb2_handle _h1;
380 struct smb2_handle *h1 = NULL;
381 struct smb2_create io1;
383 union smb_fileinfo qfinfo;
384 struct cli_credentials *anon_creds = NULL;
385 uint32_t secinfo_flags = SECINFO_OWNER
388 | SECINFO_PROTECTED_DACL
389 | SECINFO_UNPROTECTED_DACL;
391 /* Add some random component to the file name. */
392 snprintf(fname, sizeof(fname), "session_reauth3_%s.dat",
393 generate_random_str(tctx, 8));
395 smb2_util_unlink(tree, fname);
397 smb2_oplock_create_share(&io1, fname,
398 smb2_util_share_access(""),
399 smb2_util_oplock_level("b"));
401 status = smb2_create(tree, mem_ctx, &io1);
402 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
403 "smb2_create failed");
404 _h1 = io1.out.file.handle;
406 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
407 torture_assert_int_equal(tctx, io1.out.oplock_level,
408 smb2_util_oplock_level("b"),
409 "oplock_level incorrect");
411 /* get the security descriptor */
415 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
416 qfinfo.query_secdesc.in.file.handle = _h1;
417 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
419 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
420 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
421 "smb2_getinfo_file failed");
423 /* re-authenticate as anonymous */
425 anon_creds = cli_credentials_init_anon(mem_ctx);
426 torture_assert(tctx, (anon_creds != NULL), "talloc error");
428 status = smb2_session_setup_spnego(tree->session,
430 0 /* previous_session_id */);
431 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
432 "smb2_session_setup_spnego failed");
434 /* try to access the file via the old handle */
438 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
439 qfinfo.query_secdesc.in.file.handle = _h1;
440 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
442 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
443 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
444 "smb2_getinfo_file failed");
446 /* re-authenticate as original user again */
448 status = smb2_session_setup_spnego(tree->session,
449 popt_get_cmdline_credentials(),
450 0 /* previous_session_id */);
451 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
452 "smb2_session_setup_spnego failed");
454 /* try to access the file via the old handle */
458 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
459 qfinfo.query_secdesc.in.file.handle = _h1;
460 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
462 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
463 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
464 "smb2_getinfo_file failed");
468 smb2_util_close(tree, *h1);
471 smb2_util_unlink(tree, fname);
475 talloc_free(mem_ctx);
481 * test setting security descriptor after reauth.
483 bool test_session_reauth4(struct torture_context *tctx, struct smb2_tree *tree)
486 TALLOC_CTX *mem_ctx = talloc_new(tctx);
488 struct smb2_handle _h1;
489 struct smb2_handle *h1 = NULL;
490 struct smb2_create io1;
492 union smb_fileinfo qfinfo;
493 union smb_setfileinfo sfinfo;
494 struct cli_credentials *anon_creds = NULL;
495 uint32_t secinfo_flags = SECINFO_OWNER
498 | SECINFO_PROTECTED_DACL
499 | SECINFO_UNPROTECTED_DACL;
500 struct security_descriptor *sd1;
501 struct security_ace ace;
502 struct dom_sid *extra_sid;
504 /* Add some random component to the file name. */
505 snprintf(fname, sizeof(fname), "session_reauth4_%s.dat",
506 generate_random_str(tctx, 8));
508 smb2_util_unlink(tree, fname);
510 smb2_oplock_create_share(&io1, fname,
511 smb2_util_share_access(""),
512 smb2_util_oplock_level("b"));
514 status = smb2_create(tree, mem_ctx, &io1);
515 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
516 "smb2_create failed");
517 _h1 = io1.out.file.handle;
519 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
520 torture_assert_int_equal(tctx, io1.out.oplock_level,
521 smb2_util_oplock_level("b"),
522 "oplock_level incorrect");
524 /* get the security descriptor */
528 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
529 qfinfo.query_secdesc.in.file.handle = _h1;
530 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
532 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
533 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
534 "smb2_getinfo_file failed");
536 sd1 = qfinfo.query_secdesc.out.sd;
538 /* re-authenticate as anonymous */
540 anon_creds = cli_credentials_init_anon(mem_ctx);
541 torture_assert(tctx, (anon_creds != NULL), "talloc error");
543 status = smb2_session_setup_spnego(tree->session,
545 0 /* previous_session_id */);
546 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
547 "smb2_session_setup_spnego failed");
549 /* give full access on the file to anonymous */
551 extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
554 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
556 ace.access_mask = SEC_STD_ALL | SEC_FILE_ALL;
557 ace.trustee = *extra_sid;
559 status = security_descriptor_dacl_add(sd1, &ace);
560 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
561 "security_descriptor_dacl_add failed");
564 sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
565 sfinfo.set_secdesc.in.file.handle = _h1;
566 sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
567 sfinfo.set_secdesc.in.sd = sd1;
569 status = smb2_setinfo_file(tree, &sfinfo);
570 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
571 "smb2_setinfo_file failed");
573 /* re-authenticate as original user again */
575 status = smb2_session_setup_spnego(tree->session,
576 popt_get_cmdline_credentials(),
577 0 /* previous_session_id */);
578 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
579 "smb2_session_setup_spnego failed");
581 /* re-get the security descriptor */
585 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
586 qfinfo.query_secdesc.in.file.handle = _h1;
587 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
589 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
590 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
591 "smb2_getinfo_file failed");
597 smb2_util_close(tree, *h1);
600 smb2_util_unlink(tree, fname);
604 talloc_free(mem_ctx);
610 * test renaming after reauth.
611 * compare security descriptors before and after rename/reauth
613 bool test_session_reauth5(struct torture_context *tctx, struct smb2_tree *tree)
616 TALLOC_CTX *mem_ctx = talloc_new(tctx);
620 struct smb2_handle _dh1;
621 struct smb2_handle *dh1 = NULL;
622 struct smb2_handle _h1;
623 struct smb2_handle *h1 = NULL;
624 struct smb2_create io1;
627 union smb_fileinfo qfinfo;
628 union smb_setfileinfo sfinfo;
629 struct cli_credentials *anon_creds = NULL;
630 uint32_t secinfo_flags = SECINFO_OWNER
633 | SECINFO_PROTECTED_DACL
634 | SECINFO_UNPROTECTED_DACL;
635 struct security_descriptor *f_sd1;
636 struct security_descriptor *d_sd1 = NULL;
637 struct security_ace ace;
638 struct dom_sid *extra_sid;
640 /* Add some random component to the file name. */
641 snprintf(dname, sizeof(dname), "session_reauth5_%s.d",
642 generate_random_str(tctx, 8));
643 snprintf(fname, sizeof(fname), "%s\\file.dat", dname);
645 ok = smb2_util_setup_dir(tctx, tree, dname);
646 torture_assert(tctx, ok, "smb2_util_setup_dir not ok");
648 status = torture_smb2_testdir(tree, dname, &_dh1);
649 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
650 "torture_smb2_testdir failed");
653 smb2_oplock_create_share(&io1, fname,
654 smb2_util_share_access(""),
655 smb2_util_oplock_level("b"));
657 status = smb2_create(tree, mem_ctx, &io1);
658 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
659 "smb2_create failed");
660 _h1 = io1.out.file.handle;
662 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
663 torture_assert_int_equal(tctx, io1.out.oplock_level,
664 smb2_util_oplock_level("b"),
665 "oplock_level incorrect");
667 /* get the security descriptor */
671 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
672 qfinfo.query_secdesc.in.file.handle = _h1;
673 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
675 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
676 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
677 "smb2_getinfo_file failed");
679 f_sd1 = qfinfo.query_secdesc.out.sd;
681 /* re-authenticate as anonymous */
683 anon_creds = cli_credentials_init_anon(mem_ctx);
684 torture_assert(tctx, (anon_creds != NULL), "talloc error");
686 status = smb2_session_setup_spnego(tree->session,
688 0 /* previous_session_id */);
689 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
690 "smb2_session_setup_spnego failed");
692 /* try to rename the file: fails */
694 snprintf(fname2, sizeof(fname2), "%s\\file2.dat", dname);
696 status = smb2_util_unlink(tree, fname2);
697 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
698 "smb2_util_unlink failed");
702 sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
703 sfinfo.rename_information.in.file.handle = _h1;
704 sfinfo.rename_information.in.overwrite = true;
705 sfinfo.rename_information.in.new_name = fname2;
707 status = smb2_setinfo_file(tree, &sfinfo);
708 torture_assert_ntstatus_equal_goto(tctx, status,
709 NT_STATUS_ACCESS_DENIED,
710 ret, done, "smb2_setinfo_file "
711 "returned unexpected status");
713 /* re-authenticate as original user again */
715 status = smb2_session_setup_spnego(tree->session,
716 popt_get_cmdline_credentials(),
717 0 /* previous_session_id */);
718 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
719 "smb2_session_setup_spnego failed");
721 /* give full access on the file to anonymous */
723 extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
726 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
728 ace.access_mask = SEC_RIGHTS_FILE_ALL;
729 ace.trustee = *extra_sid;
731 status = security_descriptor_dacl_add(f_sd1, &ace);
732 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
733 "security_descriptor_dacl_add failed");
736 sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
737 sfinfo.set_secdesc.in.file.handle = _h1;
738 sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
739 sfinfo.set_secdesc.in.sd = f_sd1;
741 status = smb2_setinfo_file(tree, &sfinfo);
742 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
743 "smb2_setinfo_file failed");
745 /* re-get the security descriptor */
749 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
750 qfinfo.query_secdesc.in.file.handle = _h1;
751 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
753 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
754 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
755 "smb2_getinfo_file failed");
757 /* re-authenticate as anonymous - again */
759 anon_creds = cli_credentials_init_anon(mem_ctx);
760 torture_assert(tctx, (anon_creds != NULL), "talloc error");
762 status = smb2_session_setup_spnego(tree->session,
764 0 /* previous_session_id */);
765 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
766 "smb2_session_setup_spnego failed");
768 /* try to rename the file: fails */
771 sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
772 sfinfo.rename_information.in.file.handle = _h1;
773 sfinfo.rename_information.in.overwrite = true;
774 sfinfo.rename_information.in.new_name = fname2;
776 status = smb2_setinfo_file(tree, &sfinfo);
777 torture_assert_ntstatus_equal_goto(tctx, status,
778 NT_STATUS_ACCESS_DENIED,
779 ret, done, "smb2_setinfo_file "
780 "returned unexpected status");
782 /* give full access on the parent dir to anonymous */
786 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
787 qfinfo.query_secdesc.in.file.handle = _dh1;
788 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
790 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
791 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
792 "smb2_getinfo_file failed");
794 d_sd1 = qfinfo.query_secdesc.out.sd;
797 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
799 ace.access_mask = SEC_RIGHTS_FILE_ALL;
800 ace.trustee = *extra_sid;
802 status = security_descriptor_dacl_add(d_sd1, &ace);
803 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
804 "security_descriptor_dacl_add failed");
807 sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
808 sfinfo.set_secdesc.in.file.handle = _dh1;
809 sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
810 sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
811 sfinfo.set_secdesc.in.sd = d_sd1;
813 status = smb2_setinfo_file(tree, &sfinfo);
814 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
815 "smb2_setinfo_file failed");
819 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
820 qfinfo.query_secdesc.in.file.handle = _dh1;
821 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
823 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
824 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
825 "smb2_getinfo_file failed");
827 status = smb2_util_close(tree, _dh1);
828 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
829 "smb2_util_close failed");
832 /* try to rename the file: still fails */
835 sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
836 sfinfo.rename_information.in.file.handle = _h1;
837 sfinfo.rename_information.in.overwrite = true;
838 sfinfo.rename_information.in.new_name = fname2;
840 status = smb2_setinfo_file(tree, &sfinfo);
841 torture_assert_ntstatus_equal_goto(tctx, status,
842 NT_STATUS_ACCESS_DENIED,
843 ret, done, "smb2_setinfo_file "
844 "returned unexpected status");
846 /* re-authenticate as original user - again */
848 status = smb2_session_setup_spnego(tree->session,
849 popt_get_cmdline_credentials(),
850 0 /* previous_session_id */);
851 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
852 "smb2_session_setup_spnego failed");
854 /* rename the file - for verification that it works */
857 sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
858 sfinfo.rename_information.in.file.handle = _h1;
859 sfinfo.rename_information.in.overwrite = true;
860 sfinfo.rename_information.in.new_name = fname2;
862 status = smb2_setinfo_file(tree, &sfinfo);
863 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
864 "smb2_setinfo_file failed");
866 /* closs the file, check it is gone and reopen under the new name */
868 status = smb2_util_close(tree, _h1);
869 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
870 "smb2_util_close failed");
873 smb2_generic_create_share(&io1,
874 NULL /* lease */, false /* dir */,
877 smb2_util_share_access(""),
878 smb2_util_oplock_level("b"),
879 0 /* leasekey */, 0 /* leasestate */);
881 status = smb2_create(tree, mem_ctx, &io1);
882 torture_assert_ntstatus_equal_goto(tctx, status,
883 NT_STATUS_OBJECT_NAME_NOT_FOUND,
884 ret, done, "smb2_create "
885 "returned unexpected status");
889 smb2_generic_create_share(&io1,
890 NULL /* lease */, false /* dir */,
893 smb2_util_share_access(""),
894 smb2_util_oplock_level("b"),
895 0 /* leasekey */, 0 /* leasestate */);
897 status = smb2_create(tree, mem_ctx, &io1);
898 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
899 "smb2_create failed");
900 _h1 = io1.out.file.handle;
902 CHECK_CREATED(tctx, &io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
903 torture_assert_int_equal(tctx, io1.out.oplock_level,
904 smb2_util_oplock_level("b"),
905 "oplock_level incorrect");
907 /* try to access the file via the old handle */
911 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
912 qfinfo.query_secdesc.in.file.handle = _h1;
913 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
915 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
916 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
917 "smb2_getinfo_file failed");
921 smb2_util_close(tree, *dh1);
924 smb2_util_close(tree, *h1);
927 smb2_deltree(tree, dname);
931 talloc_free(mem_ctx);
937 * do reauth with wrong credentials,
938 * hence triggering the error path in reauth.
939 * The invalid reauth deletes the session.
941 bool test_session_reauth6(struct torture_context *tctx, struct smb2_tree *tree)
944 TALLOC_CTX *mem_ctx = talloc_new(tctx);
946 struct smb2_handle _h1;
947 struct smb2_handle *h1 = NULL;
948 struct smb2_create io1;
950 char *corrupted_password;
951 struct cli_credentials *broken_creds;
955 enum credentials_use_kerberos krb_state;
957 krb_state = cli_credentials_get_kerberos_state(
958 popt_get_cmdline_credentials());
959 if (krb_state == CRED_MUST_USE_KERBEROS) {
961 "Can't test failing session setup with kerberos.");
964 encrypted = smb2cli_tcon_is_encryption_on(tree->smbXcli);
966 /* Add some random component to the file name. */
967 snprintf(fname, sizeof(fname), "session_reauth1_%s.dat",
968 generate_random_str(tctx, 8));
970 smb2_util_unlink(tree, fname);
972 smb2_oplock_create_share(&io1, fname,
973 smb2_util_share_access(""),
974 smb2_util_oplock_level("b"));
975 io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
977 status = smb2_create(tree, mem_ctx, &io1);
978 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
979 "smb2_create failed");
980 _h1 = io1.out.file.handle;
982 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
983 torture_assert_int_equal(tctx, io1.out.oplock_level,
984 smb2_util_oplock_level("b"),
985 "oplock_level incorrect");
988 * reauthentication with invalid credentials:
991 broken_creds = cli_credentials_shallow_copy(mem_ctx,
992 popt_get_cmdline_credentials());
993 torture_assert(tctx, (broken_creds != NULL), "talloc error");
995 corrupted_password = talloc_asprintf(mem_ctx, "%s%s",
996 cli_credentials_get_password(broken_creds),
998 torture_assert(tctx, (corrupted_password != NULL), "talloc error");
1000 ok = cli_credentials_set_password(broken_creds, corrupted_password,
1002 torture_assert(tctx, ok, "cli_credentials_set_password not ok");
1004 status = smb2_session_setup_spnego(tree->session,
1006 0 /* previous_session_id */);
1007 torture_assert_ntstatus_equal_goto(tctx, status,
1008 NT_STATUS_LOGON_FAILURE, ret, done,
1009 "smb2_session_setup_spnego "
1010 "returned unexpected status");
1012 torture_comment(tctx, "did failed reauth\n");
1014 * now verify that the invalid session reauth has closed our session
1018 expected = NT_STATUS_CONNECTION_DISCONNECTED;
1020 expected = NT_STATUS_USER_SESSION_DELETED;
1023 smb2_oplock_create_share(&io1, fname,
1024 smb2_util_share_access(""),
1025 smb2_util_oplock_level("b"));
1027 status = smb2_create(tree, mem_ctx, &io1);
1028 torture_assert_ntstatus_equal_goto(tctx, status, expected,
1029 ret, done, "smb2_create "
1030 "returned unexpected status");
1034 smb2_util_close(tree, *h1);
1037 smb2_util_unlink(tree, fname);
1041 talloc_free(mem_ctx);
1047 static bool test_session_expire1i(struct torture_context *tctx,
1049 bool force_encryption)
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;
1060 struct smb2_handle _h1;
1061 struct smb2_handle *h1 = NULL;
1062 struct smb2_create io1;
1063 union smb_fileinfo qfinfo;
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 cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
1077 lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
1079 lpcfg_smbcli_options(tctx->lp_ctx, &options);
1080 if (force_signing) {
1081 options.signing = SMB_SIGNING_REQUIRED;
1084 status = smb2_connect(tctx,
1086 lpcfg_smb_ports(tctx->lp_ctx),
1088 lpcfg_resolve_context(tctx->lp_ctx),
1093 lpcfg_socket_options(tctx->lp_ctx),
1094 lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1096 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1097 "smb2_connect failed");
1099 if (force_encryption) {
1100 status = smb2cli_session_encryption_on(tree->session->smbXcli);
1101 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1102 "smb2cli_session_encryption_on failed");
1105 /* Add some random component to the file name. */
1106 snprintf(fname, sizeof(fname), "session_expire1_%s.dat",
1107 generate_random_str(tctx, 8));
1109 smb2_util_unlink(tree, fname);
1111 smb2_oplock_create_share(&io1, fname,
1112 smb2_util_share_access(""),
1113 smb2_util_oplock_level("b"));
1114 io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1116 status = smb2_create(tree, tctx, &io1);
1117 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1118 "smb2_create failed");
1119 _h1 = io1.out.file.handle;
1121 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1122 torture_assert_int_equal(tctx, io1.out.oplock_level,
1123 smb2_util_oplock_level("b"),
1124 "oplock_level incorrect");
1126 /* get the security descriptor */
1128 ZERO_STRUCT(qfinfo);
1130 qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
1131 qfinfo.access_information.in.file.handle = _h1;
1133 for (i=0; i < 2; i++) {
1134 torture_comment(tctx, "query info => OK\n");
1136 ZERO_STRUCT(qfinfo.access_information.out);
1137 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1138 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1139 "smb2_getinfo_file failed");
1141 torture_comment(tctx, "sleep 10 seconds\n");
1142 smb_msleep(10*1000);
1144 torture_comment(tctx, "query info => EXPIRED\n");
1145 ZERO_STRUCT(qfinfo.access_information.out);
1146 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1147 torture_assert_ntstatus_equal_goto(tctx, status,
1148 NT_STATUS_NETWORK_SESSION_EXPIRED,
1149 ret, done, "smb2_getinfo_file "
1150 "returned unexpected status");
1153 * the krb5 library may not handle expired creds
1154 * well, lets start with an empty ccache.
1156 cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
1158 if (!force_encryption) {
1159 smb2cli_session_require_signed_response(
1160 tree->session->smbXcli, true);
1163 torture_comment(tctx, "reauth => OK\n");
1164 status = smb2_session_setup_spnego(tree->session,
1166 0 /* previous_session_id */);
1167 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1168 "smb2_session_setup_spnego failed");
1170 smb2cli_session_require_signed_response(
1171 tree->session->smbXcli, false);
1174 ZERO_STRUCT(qfinfo.access_information.out);
1175 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1176 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1177 "smb2_getinfo_file failed");
1181 cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
1184 smb2_util_close(tree, *h1);
1188 lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
1192 static bool test_session_expire1n(struct torture_context *tctx)
1194 return test_session_expire1i(tctx,
1195 false, /* force_signing */
1196 false); /* force_encryption */
1199 static bool test_session_expire1s(struct torture_context *tctx)
1201 return test_session_expire1i(tctx,
1202 true, /* force_signing */
1203 false); /* force_encryption */
1206 static bool test_session_expire1e(struct torture_context *tctx)
1208 return test_session_expire1i(tctx,
1209 true, /* force_signing */
1210 true); /* force_encryption */
1213 static bool test_session_expire2i(struct torture_context *tctx,
1214 bool force_encryption)
1218 struct smbcli_options options;
1219 const char *host = torture_setting_string(tctx, "host", NULL);
1220 const char *share = torture_setting_string(tctx, "share", NULL);
1221 struct cli_credentials *credentials = popt_get_cmdline_credentials();
1222 struct smb2_tree *tree = NULL;
1223 const char *unc = NULL;
1224 struct smb2_tree *tree2 = NULL;
1225 struct tevent_req *subreq = NULL;
1226 uint32_t timeout_msec;
1227 enum credentials_use_kerberos use_kerberos;
1230 struct smb2_handle dh;
1231 struct smb2_handle dh2;
1232 struct smb2_handle _h1;
1233 struct smb2_handle *h1 = NULL;
1234 struct smb2_create io1;
1235 union smb_fileinfo qfinfo;
1236 union smb_setfileinfo sfinfo;
1237 struct smb2_flush flsh;
1238 struct smb2_read rd;
1239 const uint8_t wd = 0;
1240 struct smb2_lock lck;
1241 struct smb2_lock_element el;
1242 struct smb2_ioctl ctl;
1243 struct smb2_break oack;
1244 struct smb2_lease_break_ack lack;
1245 struct smb2_find fnd;
1246 union smb_search_data *d = NULL;
1248 struct smb2_request *req = NULL;
1249 struct smb2_notify ntf1;
1250 struct smb2_notify ntf2;
1252 use_kerberos = cli_credentials_get_kerberos_state(credentials);
1253 if (use_kerberos != CRED_MUST_USE_KERBEROS) {
1254 torture_warning(tctx, "smb2.session.expire2 requires -k yes!");
1255 torture_skip(tctx, "smb2.session.expire2 requires -k yes!");
1258 torture_assert_int_equal(tctx, use_kerberos, CRED_MUST_USE_KERBEROS,
1259 "please use -k yes");
1261 cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
1263 lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
1265 lpcfg_smbcli_options(tctx->lp_ctx, &options);
1266 options.signing = SMB_SIGNING_REQUIRED;
1268 unc = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
1269 torture_assert(tctx, unc != NULL, "talloc_asprintf");
1271 status = smb2_connect(tctx,
1273 lpcfg_smb_ports(tctx->lp_ctx),
1275 lpcfg_resolve_context(tctx->lp_ctx),
1280 lpcfg_socket_options(tctx->lp_ctx),
1281 lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1283 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1284 "smb2_connect failed");
1286 if (force_encryption) {
1287 status = smb2cli_session_encryption_on(tree->session->smbXcli);
1288 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1289 "smb2cli_session_encryption_on failed");
1292 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1294 /* Add some random component to the file name. */
1295 snprintf(fname, sizeof(fname), "session_expire2_%s.dat",
1296 generate_random_str(tctx, 8));
1298 smb2_util_unlink(tree, fname);
1300 status = smb2_util_roothandle(tree, &dh);
1301 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1302 "smb2_util_roothandle failed");
1304 smb2_oplock_create_share(&io1, fname,
1305 smb2_util_share_access(""),
1306 smb2_util_oplock_level("b"));
1307 io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1309 status = smb2_create(tree, tctx, &io1);
1310 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1311 "smb2_create failed");
1312 _h1 = io1.out.file.handle;
1314 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1315 torture_assert_int_equal(tctx, io1.out.oplock_level,
1316 smb2_util_oplock_level("b"),
1317 "oplock_level incorrect");
1319 /* get the security descriptor */
1321 ZERO_STRUCT(qfinfo);
1323 qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
1324 qfinfo.access_information.in.file.handle = _h1;
1326 torture_comment(tctx, "query info => OK\n");
1328 ZERO_STRUCT(qfinfo.access_information.out);
1329 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1330 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1331 "smb2_getinfo_file failed");
1333 torture_comment(tctx, "lock => OK\n");
1336 lck.in.lock_count = 0x0001;
1337 lck.in.lock_sequence = 0x00000000;
1338 lck.in.file.handle = *h1;
1340 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1341 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1342 el.offset = 0x0000000000000000;
1343 el.length = 0x0000000000000001;
1344 status = smb2_lock(tree, &lck);
1345 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1346 "smb2_lock lock failed");
1348 torture_comment(tctx, "1st notify => PENDING\n");
1350 ntf1.in.file.handle = dh;
1351 ntf1.in.recursive = 0x0000;
1352 ntf1.in.buffer_size = 128;
1353 ntf1.in.completion_filter= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1354 ntf1.in.unknown = 0x00000000;
1355 req = smb2_notify_send(tree, &ntf1);
1357 while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
1358 if (tevent_loop_once(tctx->ev) != 0) {
1363 torture_assert_goto(tctx, req->state <= SMB2_REQUEST_RECV, ret, done,
1364 "smb2_notify finished");
1366 torture_comment(tctx, "sleep 10 seconds\n");
1367 smb_msleep(10*1000);
1369 torture_comment(tctx, "query info => EXPIRED\n");
1370 ZERO_STRUCT(qfinfo.access_information.out);
1371 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1372 torture_assert_ntstatus_equal_goto(tctx, status,
1373 NT_STATUS_NETWORK_SESSION_EXPIRED,
1374 ret, done, "smb2_getinfo_file "
1375 "returned unexpected status");
1378 torture_comment(tctx, "set info => EXPIRED\n");
1379 ZERO_STRUCT(sfinfo);
1380 sfinfo.end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1381 sfinfo.end_of_file_info.in.file.handle = *h1;
1382 sfinfo.end_of_file_info.in.size = 1;
1383 status = smb2_setinfo_file(tree, &sfinfo);
1384 torture_assert_ntstatus_equal_goto(tctx, status,
1385 NT_STATUS_NETWORK_SESSION_EXPIRED,
1386 ret, done, "smb2_setinfo_file "
1387 "returned unexpected status");
1389 torture_comment(tctx, "flush => EXPIRED\n");
1391 flsh.in.file.handle = *h1;
1392 status = smb2_flush(tree, &flsh);
1393 torture_assert_ntstatus_equal_goto(tctx, status,
1394 NT_STATUS_NETWORK_SESSION_EXPIRED,
1395 ret, done, "smb2_flush "
1396 "returned unexpected status");
1398 torture_comment(tctx, "read => EXPIRED\n");
1400 rd.in.file.handle = *h1;
1403 status = smb2_read(tree, tctx, &rd);
1404 torture_assert_ntstatus_equal_goto(tctx, status,
1405 NT_STATUS_NETWORK_SESSION_EXPIRED,
1406 ret, done, "smb2_read "
1407 "returned unexpected status");
1409 torture_comment(tctx, "write => EXPIRED\n");
1410 status = smb2_util_write(tree, *h1, &wd, 0, 1);
1411 torture_assert_ntstatus_equal_goto(tctx, status,
1412 NT_STATUS_NETWORK_SESSION_EXPIRED,
1413 ret, done, "smb2_util_write "
1414 "returned unexpected status");
1416 torture_comment(tctx, "ioctl => EXPIRED\n");
1418 ctl.in.file.handle = *h1;
1419 ctl.in.function = FSCTL_SRV_ENUM_SNAPS;
1420 ctl.in.max_response_size = 16;
1421 ctl.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
1422 status = smb2_ioctl(tree, tctx, &ctl);
1423 torture_assert_ntstatus_equal_goto(tctx, status,
1424 NT_STATUS_NETWORK_SESSION_EXPIRED,
1425 ret, done, "smb2_ioctl "
1426 "returned unexpected status");
1428 torture_comment(tctx, "oplock ack => EXPIRED\n");
1430 oack.in.file.handle = *h1;
1431 status = smb2_break(tree, &oack);
1432 torture_assert_ntstatus_equal_goto(tctx, status,
1433 NT_STATUS_NETWORK_SESSION_EXPIRED,
1434 ret, done, "smb2_break "
1435 "returned unexpected status");
1437 if (caps & SMB2_CAP_LEASING) {
1438 torture_comment(tctx, "lease ack => EXPIRED\n");
1440 lack.in.lease.lease_version = 1;
1441 lack.in.lease.lease_key.data[0] = 1;
1442 lack.in.lease.lease_key.data[1] = 2;
1443 status = smb2_lease_break_ack(tree, &lack);
1444 torture_assert_ntstatus_equal_goto(tctx, status,
1445 NT_STATUS_NETWORK_SESSION_EXPIRED,
1446 ret, done, "smb2_break "
1447 "returned unexpected status");
1450 torture_comment(tctx, "query directory => EXPIRED\n");
1452 fnd.in.file.handle = dh;
1453 fnd.in.pattern = "*";
1454 fnd.in.continue_flags = SMB2_CONTINUE_FLAG_SINGLE;
1455 fnd.in.max_response_size= 0x100;
1456 fnd.in.level = SMB2_FIND_BOTH_DIRECTORY_INFO;
1457 status = smb2_find_level(tree, tree, &fnd, &count, &d);
1458 torture_assert_ntstatus_equal_goto(tctx, status,
1459 NT_STATUS_NETWORK_SESSION_EXPIRED,
1460 ret, done, "smb2_find_level "
1461 "returned unexpected status");
1463 torture_comment(tctx, "1st notify => CANCEL\n");
1466 torture_comment(tctx, "2nd notify => EXPIRED\n");
1468 ntf2.in.file.handle = dh;
1469 ntf2.in.recursive = 0x0000;
1470 ntf2.in.buffer_size = 128;
1471 ntf2.in.completion_filter= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1472 ntf2.in.unknown = 0x00000000;
1473 status = smb2_notify(tree, tctx, &ntf2);
1474 torture_assert_ntstatus_equal_goto(tctx, status,
1475 NT_STATUS_NETWORK_SESSION_EXPIRED,
1476 ret, done, "smb2_notify "
1477 "returned unexpected status");
1479 torture_assert_goto(tctx, req->state > SMB2_REQUEST_RECV, ret, done,
1480 "smb2_notify (1st) not finished");
1482 status = smb2_notify_recv(req, tctx, &ntf1);
1483 torture_assert_ntstatus_equal_goto(tctx, status,
1484 NT_STATUS_CANCELLED,
1485 ret, done, "smb2_notify cancelled"
1486 "returned unexpected status");
1488 torture_comment(tctx, "tcon => EXPIRED\n");
1489 tree2 = smb2_tree_init(tree->session, tctx, false);
1490 torture_assert(tctx, tree2 != NULL, "smb2_tree_init");
1491 timeout_msec = tree->session->transport->options.request_timeout * 1000;
1492 subreq = smb2cli_tcon_send(tree2, tctx->ev,
1493 tree2->session->transport->conn,
1495 tree2->session->smbXcli,
1499 torture_assert(tctx, subreq != NULL, "smb2cli_tcon_send");
1500 torture_assert(tctx,
1501 tevent_req_poll_ntstatus(subreq, tctx->ev, &status),
1502 "tevent_req_poll_ntstatus");
1503 status = smb2cli_tcon_recv(subreq);
1504 TALLOC_FREE(subreq);
1505 torture_assert_ntstatus_equal_goto(tctx, status,
1506 NT_STATUS_NETWORK_SESSION_EXPIRED,
1507 ret, done, "smb2cli_tcon"
1508 "returned unexpected status");
1510 torture_comment(tctx, "create => EXPIRED\n");
1511 status = smb2_util_roothandle(tree, &dh2);
1512 torture_assert_ntstatus_equal_goto(tctx, status,
1513 NT_STATUS_NETWORK_SESSION_EXPIRED,
1514 ret, done, "smb2_util_roothandle"
1515 "returned unexpected status");
1517 torture_comment(tctx, "tdis => EXPIRED\n");
1518 status = smb2_tdis(tree);
1519 torture_assert_ntstatus_equal_goto(tctx, status,
1520 NT_STATUS_NETWORK_SESSION_EXPIRED,
1521 ret, done, "smb2cli_tdis"
1522 "returned unexpected status");
1525 * (Un)Lock, Close and Logoff are still possible
1528 torture_comment(tctx, "1st unlock => OK\n");
1529 el.flags = SMB2_LOCK_FLAG_UNLOCK;
1530 status = smb2_lock(tree, &lck);
1531 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1532 "smb2_lock unlock failed");
1534 torture_comment(tctx, "2nd unlock => RANGE_NOT_LOCKED\n");
1535 status = smb2_lock(tree, &lck);
1536 torture_assert_ntstatus_equal_goto(tctx, status,
1537 NT_STATUS_RANGE_NOT_LOCKED,
1538 ret, done, "smb2_lock 2nd unlock"
1539 "returned unexpected status");
1541 torture_comment(tctx, "lock => EXPIRED\n");
1542 el.flags = SMB2_LOCK_FLAG_EXCLUSIVE |
1543 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1544 status = smb2_lock(tree, &lck);
1545 torture_assert_ntstatus_equal_goto(tctx, status,
1546 NT_STATUS_NETWORK_SESSION_EXPIRED,
1547 ret, done, "smb2_util_roothandle"
1548 "returned unexpected status");
1550 torture_comment(tctx, "close => OK\n");
1551 status = smb2_util_close(tree, *h1);
1553 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1554 "smb2_close failed");
1556 torture_comment(tctx, "echo without session => OK\n");
1557 status = smb2_keepalive(tree->session->transport);
1558 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1559 "smb2_keepalive without session failed");
1561 torture_comment(tctx, "echo with session => OK\n");
1562 req = smb2_keepalive_send(tree->session->transport, tree->session);
1563 status = smb2_keepalive_recv(req);
1564 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1565 "smb2_keepalive with session failed");
1567 torture_comment(tctx, "logoff => OK\n");
1568 status = smb2_logoff(tree->session);
1569 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1570 "smb2_logoff failed");
1574 cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
1577 smb2_util_close(tree, *h1);
1581 lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
1585 static bool test_session_expire2s(struct torture_context *tctx)
1587 return test_session_expire2i(tctx,
1588 false); /* force_encryption */
1591 static bool test_session_expire2e(struct torture_context *tctx)
1593 return test_session_expire2i(tctx,
1594 true); /* force_encryption */
1597 static bool test_session_expire_disconnect(struct torture_context *tctx)
1601 struct smbcli_options options;
1602 const char *host = torture_setting_string(tctx, "host", NULL);
1603 const char *share = torture_setting_string(tctx, "share", NULL);
1604 struct cli_credentials *credentials = popt_get_cmdline_credentials();
1605 struct smb2_tree *tree = NULL;
1606 enum credentials_use_kerberos use_kerberos;
1608 struct smb2_handle _h1;
1609 struct smb2_handle *h1 = NULL;
1610 struct smb2_create io1;
1611 union smb_fileinfo qfinfo;
1614 use_kerberos = cli_credentials_get_kerberos_state(credentials);
1615 if (use_kerberos != CRED_MUST_USE_KERBEROS) {
1616 torture_warning(tctx, "smb2.session.expire1 requires -k yes!");
1617 torture_skip(tctx, "smb2.session.expire1 requires -k yes!");
1620 cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
1622 lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
1623 lpcfg_smbcli_options(tctx->lp_ctx, &options);
1624 options.signing = SMB_SIGNING_REQUIRED;
1626 status = smb2_connect(tctx,
1628 lpcfg_smb_ports(tctx->lp_ctx),
1630 lpcfg_resolve_context(tctx->lp_ctx),
1635 lpcfg_socket_options(tctx->lp_ctx),
1636 lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1638 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1639 "smb2_connect failed");
1641 smbXcli_session_set_disconnect_expired(tree->session->smbXcli);
1643 /* Add some random component to the file name. */
1644 snprintf(fname, sizeof(fname), "session_expire1_%s.dat",
1645 generate_random_str(tctx, 8));
1647 smb2_util_unlink(tree, fname);
1649 smb2_oplock_create_share(&io1, fname,
1650 smb2_util_share_access(""),
1651 smb2_util_oplock_level("b"));
1652 io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1654 status = smb2_create(tree, tctx, &io1);
1655 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1656 "smb2_create failed");
1657 _h1 = io1.out.file.handle;
1659 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1660 torture_assert_int_equal(tctx, io1.out.oplock_level,
1661 smb2_util_oplock_level("b"),
1662 "oplock_level incorrect");
1664 /* get the security descriptor */
1666 ZERO_STRUCT(qfinfo);
1668 qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
1669 qfinfo.access_information.in.file.handle = _h1;
1671 torture_comment(tctx, "query info => OK\n");
1673 ZERO_STRUCT(qfinfo.access_information.out);
1674 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1675 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1676 "smb2_getinfo_file failed");
1678 torture_comment(tctx, "sleep 10 seconds\n");
1679 smb_msleep(10*1000);
1681 torture_comment(tctx, "query info => EXPIRED\n");
1682 ZERO_STRUCT(qfinfo.access_information.out);
1683 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1684 torture_assert_ntstatus_equal_goto(tctx, status,
1685 NT_STATUS_NETWORK_SESSION_EXPIRED,
1686 ret, done, "smb2_getinfo_file "
1687 "returned unexpected status");
1689 connected = smbXcli_conn_is_connected(tree->session->transport->conn);
1690 torture_assert_goto(tctx, !connected, ret, done, "connected\n");
1694 cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
1697 smb2_util_close(tree, *h1);
1701 lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
1705 bool test_session_bind1(struct torture_context *tctx, struct smb2_tree *tree1)
1707 const char *host = torture_setting_string(tctx, "host", NULL);
1708 const char *share = torture_setting_string(tctx, "share", NULL);
1709 struct cli_credentials *credentials = popt_get_cmdline_credentials();
1711 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1713 struct smb2_handle _h1;
1714 struct smb2_handle *h1 = NULL;
1715 struct smb2_create io1;
1716 union smb_fileinfo qfinfo;
1718 struct smb2_tree *tree2 = NULL;
1719 struct smb2_transport *transport1 = tree1->session->transport;
1720 struct smb2_transport *transport2 = NULL;
1721 struct smb2_session *session1_1 = tree1->session;
1722 struct smb2_session *session1_2 = NULL;
1723 struct smb2_session *session2_1 = NULL;
1724 struct smb2_session *session2_2 = NULL;
1727 caps = smb2cli_conn_server_capabilities(transport1->conn);
1728 if (!(caps & SMB2_CAP_MULTI_CHANNEL)) {
1729 torture_skip(tctx, "server doesn't support SMB2_CAP_MULTI_CHANNEL\n");
1732 /* Add some random component to the file name. */
1733 snprintf(fname, sizeof(fname), "session_bind1_%s.dat",
1734 generate_random_str(tctx, 8));
1736 smb2_util_unlink(tree1, fname);
1738 smb2_oplock_create_share(&io1, fname,
1739 smb2_util_share_access(""),
1740 smb2_util_oplock_level("b"));
1742 status = smb2_create(tree1, mem_ctx, &io1);
1743 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1744 "smb2_create failed");
1745 _h1 = io1.out.file.handle;
1747 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1748 torture_assert_int_equal(tctx, io1.out.oplock_level,
1749 smb2_util_oplock_level("b"),
1750 "oplock_level incorrect");
1752 status = smb2_connect(tctx,
1754 lpcfg_smb_ports(tctx->lp_ctx),
1756 lpcfg_resolve_context(tctx->lp_ctx),
1760 &transport1->options,
1761 lpcfg_socket_options(tctx->lp_ctx),
1762 lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1764 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1765 "smb2_connect failed");
1766 session2_2 = tree2->session;
1767 transport2 = tree2->session->transport;
1770 * Now bind the 2nd transport connection to the 1st session
1772 session1_2 = smb2_session_channel(transport2,
1773 lpcfg_gensec_settings(tctx, tctx->lp_ctx),
1776 torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
1778 status = smb2_session_setup_spnego(session1_2,
1779 popt_get_cmdline_credentials(),
1780 0 /* previous_session_id */);
1781 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1782 "smb2_session_setup_spnego failed");
1784 /* use the 1st connection, 1st session */
1785 ZERO_STRUCT(qfinfo);
1786 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
1787 qfinfo.generic.in.file.handle = _h1;
1788 tree1->session = session1_1;
1789 status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
1790 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1791 "smb2_getinfo_file failed");
1793 /* use the 2nd connection, 1st session */
1794 ZERO_STRUCT(qfinfo);
1795 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
1796 qfinfo.generic.in.file.handle = _h1;
1797 tree1->session = session1_2;
1798 status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
1799 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1800 "smb2_getinfo_file failed");
1802 tree1->session = session1_1;
1803 status = smb2_util_close(tree1, *h1);
1804 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1805 "smb2_util_close failed");
1809 * Now bind the 1st transport connection to the 2nd session
1811 session2_1 = smb2_session_channel(transport1,
1812 lpcfg_gensec_settings(tctx, tctx->lp_ctx),
1815 torture_assert(tctx, session2_1 != NULL, "smb2_session_channel failed");
1817 status = smb2_session_setup_spnego(session2_1,
1818 popt_get_cmdline_credentials(),
1819 0 /* previous_session_id */);
1820 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1821 "smb2_session_setup_spnego failed");
1823 tree2->session = session2_1;
1824 status = smb2_util_unlink(tree2, fname);
1825 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1826 "smb2_util_unlink failed");
1830 tree1->session = session1_1;
1833 smb2_util_close(tree1, *h1);
1836 smb2_util_unlink(tree1, fname);
1840 talloc_free(mem_ctx);
1845 struct torture_suite *torture_smb2_session_init(TALLOC_CTX *ctx)
1847 struct torture_suite *suite =
1848 torture_suite_create(ctx, "session");
1850 torture_suite_add_1smb2_test(suite, "reconnect1", test_session_reconnect1);
1851 torture_suite_add_1smb2_test(suite, "reconnect2", test_session_reconnect2);
1852 torture_suite_add_1smb2_test(suite, "reauth1", test_session_reauth1);
1853 torture_suite_add_1smb2_test(suite, "reauth2", test_session_reauth2);
1854 torture_suite_add_1smb2_test(suite, "reauth3", test_session_reauth3);
1855 torture_suite_add_1smb2_test(suite, "reauth4", test_session_reauth4);
1856 torture_suite_add_1smb2_test(suite, "reauth5", test_session_reauth5);
1857 torture_suite_add_1smb2_test(suite, "reauth6", test_session_reauth6);
1858 torture_suite_add_simple_test(suite, "expire1n", test_session_expire1n);
1859 torture_suite_add_simple_test(suite, "expire1s", test_session_expire1s);
1860 torture_suite_add_simple_test(suite, "expire1e", test_session_expire1e);
1861 torture_suite_add_simple_test(suite, "expire2s", test_session_expire2s);
1862 torture_suite_add_simple_test(suite, "expire2e", test_session_expire2e);
1863 torture_suite_add_simple_test(suite, "expire_disconnect",
1864 test_session_expire_disconnect);
1865 torture_suite_add_1smb2_test(suite, "bind1", test_session_bind1);
1867 suite->description = talloc_strdup(suite, "SMB2-SESSION tests");