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"
35 #define CHECK_CREATED(tctx, __io, __created, __attribute) \
37 torture_assert_int_equal(tctx, (__io)->out.create_action, \
38 NTCREATEX_ACTION_ ## __created, \
39 "out.create_action incorrect"); \
40 torture_assert_int_equal(tctx, (__io)->out.alloc_size, 0, \
41 "out.alloc_size incorrect"); \
42 torture_assert_int_equal(tctx, (__io)->out.size, 0, \
43 "out.size incorrect"); \
44 torture_assert_int_equal(tctx, (__io)->out.file_attr, \
46 "out.file_attr incorrect"); \
47 torture_assert_int_equal(tctx, (__io)->out.reserved2, 0, \
48 "out.reserverd2 incorrect"); \
52 * basic test for doing a session reconnect
54 bool test_session_reconnect1(struct torture_context *tctx, struct smb2_tree *tree)
57 TALLOC_CTX *mem_ctx = talloc_new(tctx);
59 struct smb2_handle _h1;
60 struct smb2_handle *h1 = NULL;
61 struct smb2_handle _h2;
62 struct smb2_handle *h2 = NULL;
63 struct smb2_create io1, io2;
64 uint64_t previous_session_id;
66 struct smb2_tree *tree2 = NULL;
67 union smb_fileinfo qfinfo;
69 /* Add some random component to the file name. */
70 snprintf(fname, sizeof(fname), "session_reconnect_%s.dat",
71 generate_random_str(tctx, 8));
73 smb2_util_unlink(tree, fname);
75 smb2_oplock_create_share(&io1, fname,
76 smb2_util_share_access(""),
77 smb2_util_oplock_level("b"));
79 status = smb2_create(tree, mem_ctx, &io1);
80 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
81 "smb2_create failed");
82 _h1 = io1.out.file.handle;
84 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
85 torture_assert_int_equal(tctx, io1.out.oplock_level,
86 smb2_util_oplock_level("b"),
87 "oplock_level incorrect");
89 /* disconnect, reconnect and then do durable reopen */
90 previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
92 torture_assert_goto(tctx, torture_smb2_connection_ext(tctx, previous_session_id,
93 &tree->session->transport->options, &tree2),
95 "session reconnect failed\n");
97 /* try to access the file via the old handle */
100 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
101 qfinfo.generic.in.file.handle = _h1;
102 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
103 torture_assert_ntstatus_equal_goto(tctx, status,
104 NT_STATUS_USER_SESSION_DELETED,
105 ret, done, "smb2_getinfo_file "
106 "returned unexpected status");
109 smb2_oplock_create_share(&io2, fname,
110 smb2_util_share_access(""),
111 smb2_util_oplock_level("b"));
113 status = smb2_create(tree2, mem_ctx, &io2);
114 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
115 "smb2_create failed");
117 CHECK_CREATED(tctx, &io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
118 torture_assert_int_equal(tctx, io1.out.oplock_level,
119 smb2_util_oplock_level("b"),
120 "oplock_level incorrect");
121 _h2 = io2.out.file.handle;
126 smb2_util_close(tree, *h1);
129 smb2_util_close(tree2, *h2);
133 smb2_util_unlink(tree2, fname);
135 smb2_util_unlink(tree, fname);
140 talloc_free(mem_ctx);
146 * basic test for doing a session reconnect on one connection
148 bool test_session_reconnect2(struct torture_context *tctx, struct smb2_tree *tree)
151 TALLOC_CTX *mem_ctx = talloc_new(tctx);
153 struct smb2_handle _h1;
154 struct smb2_handle *h1 = NULL;
155 struct smb2_create io1;
156 uint64_t previous_session_id;
158 struct smb2_session *session2 = NULL;
159 union smb_fileinfo qfinfo;
161 /* Add some random component to the file name. */
162 snprintf(fname, sizeof(fname), "session_reconnect_%s.dat",
163 generate_random_str(tctx, 8));
165 smb2_util_unlink(tree, fname);
167 smb2_oplock_create_share(&io1, fname,
168 smb2_util_share_access(""),
169 smb2_util_oplock_level("b"));
170 io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
172 status = smb2_create(tree, mem_ctx, &io1);
173 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
174 "smb2_create failed");
175 _h1 = io1.out.file.handle;
177 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
178 torture_assert_int_equal(tctx, io1.out.oplock_level,
179 smb2_util_oplock_level("b"),
180 "oplock_level incorrect");
182 /* disconnect, reconnect and then do durable reopen */
183 previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
185 torture_assert(tctx, torture_smb2_session_setup(tctx, tree->session->transport,
186 previous_session_id, tctx, &session2),
187 "session reconnect (on the same connection) failed");
189 /* try to access the file via the old handle */
192 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
193 qfinfo.generic.in.file.handle = _h1;
194 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
195 torture_assert_ntstatus_equal_goto(tctx, status,
196 NT_STATUS_USER_SESSION_DELETED,
197 ret, done, "smb2_getinfo_file "
198 "returned unexpected status");
203 smb2_util_close(tree, *h1);
207 talloc_free(session2);
209 talloc_free(mem_ctx);
214 bool test_session_reauth1(struct torture_context *tctx, struct smb2_tree *tree)
217 TALLOC_CTX *mem_ctx = talloc_new(tctx);
219 struct smb2_handle _h1;
220 struct smb2_handle *h1 = NULL;
221 struct smb2_create io1;
223 union smb_fileinfo qfinfo;
225 /* Add some random component to the file name. */
226 snprintf(fname, sizeof(fname), "session_reauth1_%s.dat",
227 generate_random_str(tctx, 8));
229 smb2_util_unlink(tree, fname);
231 smb2_oplock_create_share(&io1, fname,
232 smb2_util_share_access(""),
233 smb2_util_oplock_level("b"));
235 status = smb2_create(tree, mem_ctx, &io1);
236 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
237 "smb2_create failed");
238 _h1 = io1.out.file.handle;
240 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
241 torture_assert_int_equal(tctx, io1.out.oplock_level,
242 smb2_util_oplock_level("b"),
243 "oplock_level incorrect");
245 status = smb2_session_setup_spnego(tree->session,
247 0 /* previous_session_id */);
248 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
249 "smb2_session_setup_spnego failed");
251 /* try to access the file via the old handle */
254 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
255 qfinfo.generic.in.file.handle = _h1;
256 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
257 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
258 "smb2_getinfo_file failed");
260 status = smb2_session_setup_spnego(tree->session,
262 0 /* previous_session_id */);
263 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
264 "smb2_session_setup_spnego failed");
266 /* try to access the file via the old handle */
269 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
270 qfinfo.generic.in.file.handle = _h1;
271 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
272 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
273 "smb2_getinfo_file failed");
277 smb2_util_close(tree, *h1);
280 smb2_util_unlink(tree, fname);
284 talloc_free(mem_ctx);
289 bool test_session_reauth2(struct torture_context *tctx, struct smb2_tree *tree)
292 TALLOC_CTX *mem_ctx = talloc_new(tctx);
294 struct smb2_handle _h1;
295 struct smb2_handle *h1 = NULL;
296 struct smb2_create io1;
298 union smb_fileinfo qfinfo;
299 struct cli_credentials *anon_creds = NULL;
301 /* Add some random component to the file name. */
302 snprintf(fname, sizeof(fname), "session_reauth2_%s.dat",
303 generate_random_str(tctx, 8));
305 smb2_util_unlink(tree, fname);
307 smb2_oplock_create_share(&io1, fname,
308 smb2_util_share_access(""),
309 smb2_util_oplock_level("b"));
311 status = smb2_create(tree, mem_ctx, &io1);
312 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
313 "smb2_create failed");
314 _h1 = io1.out.file.handle;
316 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
317 torture_assert_int_equal(tctx, io1.out.oplock_level,
318 smb2_util_oplock_level("b"),
319 "oplock_level incorrect");
321 /* re-authenticate as anonymous */
323 anon_creds = cli_credentials_init_anon(mem_ctx);
324 torture_assert(tctx, (anon_creds != NULL), "talloc error");
326 status = smb2_session_setup_spnego(tree->session,
328 0 /* previous_session_id */);
329 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
330 "smb2_session_setup_spnego failed");
332 /* try to access the file via the old handle */
335 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
336 qfinfo.generic.in.file.handle = _h1;
337 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
338 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
339 "smb2_getinfo_file failed");
341 /* re-authenticate as original user again */
343 status = smb2_session_setup_spnego(tree->session,
345 0 /* previous_session_id */);
346 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
347 "smb2_session_setup_spnego failed");
349 /* try to access the file via the old handle */
352 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
353 qfinfo.generic.in.file.handle = _h1;
354 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
355 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
356 "smb2_getinfo_file failed");
360 smb2_util_close(tree, *h1);
363 smb2_util_unlink(tree, fname);
367 talloc_free(mem_ctx);
373 * test getting security descriptor after reauth
375 bool test_session_reauth3(struct torture_context *tctx, struct smb2_tree *tree)
378 TALLOC_CTX *mem_ctx = talloc_new(tctx);
380 struct smb2_handle _h1;
381 struct smb2_handle *h1 = NULL;
382 struct smb2_create io1;
384 union smb_fileinfo qfinfo;
385 struct cli_credentials *anon_creds = NULL;
386 uint32_t secinfo_flags = SECINFO_OWNER
389 | SECINFO_PROTECTED_DACL
390 | SECINFO_UNPROTECTED_DACL;
392 /* Add some random component to the file name. */
393 snprintf(fname, sizeof(fname), "session_reauth3_%s.dat",
394 generate_random_str(tctx, 8));
396 smb2_util_unlink(tree, fname);
398 smb2_oplock_create_share(&io1, fname,
399 smb2_util_share_access(""),
400 smb2_util_oplock_level("b"));
402 status = smb2_create(tree, mem_ctx, &io1);
403 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
404 "smb2_create failed");
405 _h1 = io1.out.file.handle;
407 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
408 torture_assert_int_equal(tctx, io1.out.oplock_level,
409 smb2_util_oplock_level("b"),
410 "oplock_level incorrect");
412 /* get the security descriptor */
416 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
417 qfinfo.query_secdesc.in.file.handle = _h1;
418 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
420 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
421 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
422 "smb2_getinfo_file failed");
424 /* re-authenticate as anonymous */
426 anon_creds = cli_credentials_init_anon(mem_ctx);
427 torture_assert(tctx, (anon_creds != NULL), "talloc error");
429 status = smb2_session_setup_spnego(tree->session,
431 0 /* previous_session_id */);
432 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
433 "smb2_session_setup_spnego failed");
435 /* try to access the file via the old handle */
439 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
440 qfinfo.query_secdesc.in.file.handle = _h1;
441 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
443 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
444 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
445 "smb2_getinfo_file failed");
447 /* re-authenticate as original user again */
449 status = smb2_session_setup_spnego(tree->session,
451 0 /* previous_session_id */);
452 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
453 "smb2_session_setup_spnego failed");
455 /* try to access the file via the old handle */
459 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
460 qfinfo.query_secdesc.in.file.handle = _h1;
461 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
463 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
464 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
465 "smb2_getinfo_file failed");
469 smb2_util_close(tree, *h1);
472 smb2_util_unlink(tree, fname);
476 talloc_free(mem_ctx);
482 * test setting security descriptor after reauth.
484 bool test_session_reauth4(struct torture_context *tctx, struct smb2_tree *tree)
487 TALLOC_CTX *mem_ctx = talloc_new(tctx);
489 struct smb2_handle _h1;
490 struct smb2_handle *h1 = NULL;
491 struct smb2_create io1;
493 union smb_fileinfo qfinfo;
494 union smb_setfileinfo sfinfo;
495 struct cli_credentials *anon_creds = NULL;
496 uint32_t secinfo_flags = SECINFO_OWNER
499 | SECINFO_PROTECTED_DACL
500 | SECINFO_UNPROTECTED_DACL;
501 struct security_descriptor *sd1;
502 struct security_ace ace;
503 struct dom_sid *extra_sid;
505 /* Add some random component to the file name. */
506 snprintf(fname, sizeof(fname), "session_reauth4_%s.dat",
507 generate_random_str(tctx, 8));
509 smb2_util_unlink(tree, fname);
511 smb2_oplock_create_share(&io1, fname,
512 smb2_util_share_access(""),
513 smb2_util_oplock_level("b"));
515 status = smb2_create(tree, mem_ctx, &io1);
516 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
517 "smb2_create failed");
518 _h1 = io1.out.file.handle;
520 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
521 torture_assert_int_equal(tctx, io1.out.oplock_level,
522 smb2_util_oplock_level("b"),
523 "oplock_level incorrect");
525 /* get the security descriptor */
529 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
530 qfinfo.query_secdesc.in.file.handle = _h1;
531 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
533 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
534 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
535 "smb2_getinfo_file failed");
537 sd1 = qfinfo.query_secdesc.out.sd;
539 /* re-authenticate as anonymous */
541 anon_creds = cli_credentials_init_anon(mem_ctx);
542 torture_assert(tctx, (anon_creds != NULL), "talloc error");
544 status = smb2_session_setup_spnego(tree->session,
546 0 /* previous_session_id */);
547 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
548 "smb2_session_setup_spnego failed");
550 /* give full access on the file to anonymous */
552 extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
555 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
557 ace.access_mask = SEC_STD_ALL | SEC_FILE_ALL;
558 ace.trustee = *extra_sid;
560 status = security_descriptor_dacl_add(sd1, &ace);
561 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
562 "security_descriptor_dacl_add failed");
565 sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
566 sfinfo.set_secdesc.in.file.handle = _h1;
567 sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
568 sfinfo.set_secdesc.in.sd = sd1;
570 status = smb2_setinfo_file(tree, &sfinfo);
571 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
572 "smb2_setinfo_file failed");
574 /* re-authenticate as original user again */
576 status = smb2_session_setup_spnego(tree->session,
578 0 /* previous_session_id */);
579 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
580 "smb2_session_setup_spnego failed");
582 /* re-get the security descriptor */
586 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
587 qfinfo.query_secdesc.in.file.handle = _h1;
588 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
590 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
591 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
592 "smb2_getinfo_file failed");
598 smb2_util_close(tree, *h1);
601 smb2_util_unlink(tree, fname);
605 talloc_free(mem_ctx);
611 * test renaming after reauth.
612 * compare security descriptors before and after rename/reauth
614 bool test_session_reauth5(struct torture_context *tctx, struct smb2_tree *tree)
617 TALLOC_CTX *mem_ctx = talloc_new(tctx);
621 struct smb2_handle _dh1;
622 struct smb2_handle *dh1 = NULL;
623 struct smb2_handle _h1;
624 struct smb2_handle *h1 = NULL;
625 struct smb2_create io1;
628 union smb_fileinfo qfinfo;
629 union smb_setfileinfo sfinfo;
630 struct cli_credentials *anon_creds = NULL;
631 uint32_t secinfo_flags = SECINFO_OWNER
634 | SECINFO_PROTECTED_DACL
635 | SECINFO_UNPROTECTED_DACL;
636 struct security_descriptor *f_sd1;
637 struct security_descriptor *d_sd1 = NULL;
638 struct security_ace ace;
639 struct dom_sid *extra_sid;
641 /* Add some random component to the file name. */
642 snprintf(dname, sizeof(dname), "session_reauth5_%s.d",
643 generate_random_str(tctx, 8));
644 snprintf(fname, sizeof(fname), "%s\\file.dat", dname);
646 ok = smb2_util_setup_dir(tctx, tree, dname);
647 torture_assert(tctx, ok, "smb2_util_setup_dir not ok");
649 status = torture_smb2_testdir(tree, dname, &_dh1);
650 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
651 "torture_smb2_testdir failed");
654 smb2_oplock_create_share(&io1, fname,
655 smb2_util_share_access(""),
656 smb2_util_oplock_level("b"));
658 status = smb2_create(tree, mem_ctx, &io1);
659 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
660 "smb2_create failed");
661 _h1 = io1.out.file.handle;
663 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
664 torture_assert_int_equal(tctx, io1.out.oplock_level,
665 smb2_util_oplock_level("b"),
666 "oplock_level incorrect");
668 /* get the security descriptor */
672 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
673 qfinfo.query_secdesc.in.file.handle = _h1;
674 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
676 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
677 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
678 "smb2_getinfo_file failed");
680 f_sd1 = qfinfo.query_secdesc.out.sd;
682 /* re-authenticate as anonymous */
684 anon_creds = cli_credentials_init_anon(mem_ctx);
685 torture_assert(tctx, (anon_creds != NULL), "talloc error");
687 status = smb2_session_setup_spnego(tree->session,
689 0 /* previous_session_id */);
690 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
691 "smb2_session_setup_spnego failed");
693 /* try to rename the file: fails */
695 snprintf(fname2, sizeof(fname2), "%s\\file2.dat", dname);
697 status = smb2_util_unlink(tree, fname2);
698 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
699 "smb2_util_unlink failed");
703 sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
704 sfinfo.rename_information.in.file.handle = _h1;
705 sfinfo.rename_information.in.overwrite = true;
706 sfinfo.rename_information.in.new_name = fname2;
708 status = smb2_setinfo_file(tree, &sfinfo);
709 torture_assert_ntstatus_equal_goto(tctx, status,
710 NT_STATUS_ACCESS_DENIED,
711 ret, done, "smb2_setinfo_file "
712 "returned unexpected status");
714 /* re-authenticate as original user again */
716 status = smb2_session_setup_spnego(tree->session,
718 0 /* previous_session_id */);
719 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
720 "smb2_session_setup_spnego failed");
722 /* give full access on the file to anonymous */
724 extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
727 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
729 ace.access_mask = SEC_RIGHTS_FILE_ALL;
730 ace.trustee = *extra_sid;
732 status = security_descriptor_dacl_add(f_sd1, &ace);
733 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
734 "security_descriptor_dacl_add failed");
737 sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
738 sfinfo.set_secdesc.in.file.handle = _h1;
739 sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
740 sfinfo.set_secdesc.in.sd = f_sd1;
742 status = smb2_setinfo_file(tree, &sfinfo);
743 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
744 "smb2_setinfo_file failed");
746 /* re-get the security descriptor */
750 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
751 qfinfo.query_secdesc.in.file.handle = _h1;
752 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
754 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
755 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
756 "smb2_getinfo_file failed");
758 /* re-authenticate as anonymous - again */
760 anon_creds = cli_credentials_init_anon(mem_ctx);
761 torture_assert(tctx, (anon_creds != NULL), "talloc error");
763 status = smb2_session_setup_spnego(tree->session,
765 0 /* previous_session_id */);
766 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
767 "smb2_session_setup_spnego failed");
769 /* try to rename the file: fails */
772 sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
773 sfinfo.rename_information.in.file.handle = _h1;
774 sfinfo.rename_information.in.overwrite = true;
775 sfinfo.rename_information.in.new_name = fname2;
777 status = smb2_setinfo_file(tree, &sfinfo);
778 torture_assert_ntstatus_equal_goto(tctx, status,
779 NT_STATUS_ACCESS_DENIED,
780 ret, done, "smb2_setinfo_file "
781 "returned unexpected status");
783 /* give full access on the parent dir to anonymous */
787 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
788 qfinfo.query_secdesc.in.file.handle = _dh1;
789 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
791 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
792 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
793 "smb2_getinfo_file failed");
795 d_sd1 = qfinfo.query_secdesc.out.sd;
798 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
800 ace.access_mask = SEC_RIGHTS_FILE_ALL;
801 ace.trustee = *extra_sid;
803 status = security_descriptor_dacl_add(d_sd1, &ace);
804 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
805 "security_descriptor_dacl_add failed");
808 sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
809 sfinfo.set_secdesc.in.file.handle = _dh1;
810 sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
811 sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
812 sfinfo.set_secdesc.in.sd = d_sd1;
814 status = smb2_setinfo_file(tree, &sfinfo);
815 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
816 "smb2_setinfo_file failed");
820 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
821 qfinfo.query_secdesc.in.file.handle = _dh1;
822 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
824 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
825 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
826 "smb2_getinfo_file failed");
828 status = smb2_util_close(tree, _dh1);
829 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
830 "smb2_util_close failed");
833 /* try to rename the file: still fails */
836 sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
837 sfinfo.rename_information.in.file.handle = _h1;
838 sfinfo.rename_information.in.overwrite = true;
839 sfinfo.rename_information.in.new_name = fname2;
841 status = smb2_setinfo_file(tree, &sfinfo);
842 torture_assert_ntstatus_equal_goto(tctx, status,
843 NT_STATUS_ACCESS_DENIED,
844 ret, done, "smb2_setinfo_file "
845 "returned unexpected status");
847 /* re-authenticate as original user - again */
849 status = smb2_session_setup_spnego(tree->session,
851 0 /* previous_session_id */);
852 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
853 "smb2_session_setup_spnego failed");
855 /* rename the file - for verification that it works */
858 sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
859 sfinfo.rename_information.in.file.handle = _h1;
860 sfinfo.rename_information.in.overwrite = true;
861 sfinfo.rename_information.in.new_name = fname2;
863 status = smb2_setinfo_file(tree, &sfinfo);
864 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
865 "smb2_setinfo_file failed");
867 /* closs the file, check it is gone and reopen under the new name */
869 status = smb2_util_close(tree, _h1);
870 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
871 "smb2_util_close failed");
874 smb2_generic_create_share(&io1,
875 NULL /* lease */, false /* dir */,
878 smb2_util_share_access(""),
879 smb2_util_oplock_level("b"),
880 0 /* leasekey */, 0 /* leasestate */);
882 status = smb2_create(tree, mem_ctx, &io1);
883 torture_assert_ntstatus_equal_goto(tctx, status,
884 NT_STATUS_OBJECT_NAME_NOT_FOUND,
885 ret, done, "smb2_create "
886 "returned unexpected status");
890 smb2_generic_create_share(&io1,
891 NULL /* lease */, false /* dir */,
894 smb2_util_share_access(""),
895 smb2_util_oplock_level("b"),
896 0 /* leasekey */, 0 /* leasestate */);
898 status = smb2_create(tree, mem_ctx, &io1);
899 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
900 "smb2_create failed");
901 _h1 = io1.out.file.handle;
903 CHECK_CREATED(tctx, &io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
904 torture_assert_int_equal(tctx, io1.out.oplock_level,
905 smb2_util_oplock_level("b"),
906 "oplock_level incorrect");
908 /* try to access the file via the old handle */
912 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
913 qfinfo.query_secdesc.in.file.handle = _h1;
914 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
916 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
917 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
918 "smb2_getinfo_file failed");
922 smb2_util_close(tree, *dh1);
925 smb2_util_close(tree, *h1);
928 smb2_deltree(tree, dname);
932 talloc_free(mem_ctx);
938 * do reauth with wrong credentials,
939 * hence triggering the error path in reauth.
940 * The invalid reauth deletes the session.
942 bool test_session_reauth6(struct torture_context *tctx, struct smb2_tree *tree)
945 TALLOC_CTX *mem_ctx = talloc_new(tctx);
947 struct smb2_handle _h1;
948 struct smb2_handle *h1 = NULL;
949 struct smb2_create io1;
951 char *corrupted_password;
952 struct cli_credentials *broken_creds;
956 enum credentials_use_kerberos krb_state;
958 krb_state = cli_credentials_get_kerberos_state(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 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_expire1(struct torture_context *tctx)
1051 struct smbcli_options options;
1052 const char *host = torture_setting_string(tctx, "host", NULL);
1053 const char *share = torture_setting_string(tctx, "share", NULL);
1054 struct cli_credentials *credentials = cmdline_credentials;
1055 struct smb2_tree *tree = NULL;
1056 enum credentials_use_kerberos use_kerberos;
1058 struct smb2_handle _h1;
1059 struct smb2_handle *h1 = NULL;
1060 struct smb2_create io1;
1061 union smb_fileinfo qfinfo;
1064 use_kerberos = cli_credentials_get_kerberos_state(credentials);
1065 if (use_kerberos != CRED_MUST_USE_KERBEROS) {
1066 torture_warning(tctx, "smb2.session.expire1 requires -k yes!");
1067 torture_skip(tctx, "smb2.session.expire1 requires -k yes!");
1070 torture_assert_int_equal(tctx, use_kerberos, CRED_MUST_USE_KERBEROS,
1071 "please use -k yes");
1073 lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
1075 lpcfg_smbcli_options(tctx->lp_ctx, &options);
1077 status = smb2_connect(tctx,
1079 lpcfg_smb_ports(tctx->lp_ctx),
1081 lpcfg_resolve_context(tctx->lp_ctx),
1086 lpcfg_socket_options(tctx->lp_ctx),
1087 lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1089 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1090 "smb2_connect failed");
1092 /* Add some random component to the file name. */
1093 snprintf(fname, sizeof(fname), "session_expire1_%s.dat",
1094 generate_random_str(tctx, 8));
1096 smb2_util_unlink(tree, fname);
1098 smb2_oplock_create_share(&io1, fname,
1099 smb2_util_share_access(""),
1100 smb2_util_oplock_level("b"));
1101 io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1103 status = smb2_create(tree, tctx, &io1);
1104 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1105 "smb2_create failed");
1106 _h1 = io1.out.file.handle;
1108 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1109 torture_assert_int_equal(tctx, io1.out.oplock_level,
1110 smb2_util_oplock_level("b"),
1111 "oplock_level incorrect");
1113 /* get the security descriptor */
1115 ZERO_STRUCT(qfinfo);
1117 qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
1118 qfinfo.access_information.in.file.handle = _h1;
1120 for (i=0; i < 2; i++) {
1121 torture_comment(tctx, "query info => OK\n");
1123 ZERO_STRUCT(qfinfo.access_information.out);
1124 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1125 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1126 "smb2_getinfo_file failed");
1128 torture_comment(tctx, "sleep 5 seconds\n");
1131 torture_comment(tctx, "query info => EXPIRED\n");
1132 ZERO_STRUCT(qfinfo.access_information.out);
1133 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1134 torture_assert_ntstatus_equal_goto(tctx, status,
1135 NT_STATUS_NETWORK_SESSION_EXPIRED,
1136 ret, done, "smb2_getinfo_file "
1137 "returned unexpected status");
1140 * the krb5 library may not handle expired creds
1141 * well, lets start with an empty ccache.
1143 cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
1145 torture_comment(tctx, "reauth => OK\n");
1146 status = smb2_session_setup_spnego(tree->session,
1148 0 /* previous_session_id */);
1149 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1150 "smb2_session_seutup_spnego failed");
1153 ZERO_STRUCT(qfinfo.access_information.out);
1154 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1155 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1156 "smb2_getinfo_file failed");
1161 smb2_util_close(tree, *h1);
1165 lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
1169 bool test_session_bind1(struct torture_context *tctx, struct smb2_tree *tree1)
1171 const char *host = torture_setting_string(tctx, "host", NULL);
1172 const char *share = torture_setting_string(tctx, "share", NULL);
1173 struct cli_credentials *credentials = cmdline_credentials;
1175 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1177 struct smb2_handle _h1;
1178 struct smb2_handle *h1 = NULL;
1179 struct smb2_create io1;
1180 union smb_fileinfo qfinfo;
1182 struct smb2_tree *tree2 = NULL;
1183 struct smb2_transport *transport1 = tree1->session->transport;
1184 struct smb2_transport *transport2 = NULL;
1185 struct smb2_session *session1_1 = tree1->session;
1186 struct smb2_session *session1_2 = NULL;
1187 struct smb2_session *session2_1 = NULL;
1188 struct smb2_session *session2_2 = NULL;
1191 caps = smb2cli_conn_server_capabilities(transport1->conn);
1192 if (!(caps & SMB2_CAP_MULTI_CHANNEL)) {
1193 torture_skip(tctx, "server doesn't support SMB2_CAP_MULTI_CHANNEL\n");
1196 /* Add some random component to the file name. */
1197 snprintf(fname, sizeof(fname), "session_bind1_%s.dat",
1198 generate_random_str(tctx, 8));
1200 smb2_util_unlink(tree1, fname);
1202 smb2_oplock_create_share(&io1, fname,
1203 smb2_util_share_access(""),
1204 smb2_util_oplock_level("b"));
1206 status = smb2_create(tree1, mem_ctx, &io1);
1207 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1208 "smb2_create failed");
1209 _h1 = io1.out.file.handle;
1211 CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1212 torture_assert_int_equal(tctx, io1.out.oplock_level,
1213 smb2_util_oplock_level("b"),
1214 "oplock_level incorrect");
1216 status = smb2_connect(tctx,
1218 lpcfg_smb_ports(tctx->lp_ctx),
1220 lpcfg_resolve_context(tctx->lp_ctx),
1224 &transport1->options,
1225 lpcfg_socket_options(tctx->lp_ctx),
1226 lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1228 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1229 "smb2_connect failed");
1230 session2_2 = tree2->session;
1231 transport2 = tree2->session->transport;
1234 * Now bind the 2nd transport connection to the 1st session
1236 session1_2 = smb2_session_channel(transport2,
1237 lpcfg_gensec_settings(tctx, tctx->lp_ctx),
1240 torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
1242 status = smb2_session_setup_spnego(session1_2,
1243 cmdline_credentials,
1244 0 /* previous_session_id */);
1245 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1246 "smb2_session_setup_spnego failed");
1248 /* use the 1st connection, 1st session */
1249 ZERO_STRUCT(qfinfo);
1250 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
1251 qfinfo.generic.in.file.handle = _h1;
1252 tree1->session = session1_1;
1253 status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
1254 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1255 "smb2_getinfo_file failed");
1257 /* use the 2nd connection, 1st session */
1258 ZERO_STRUCT(qfinfo);
1259 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
1260 qfinfo.generic.in.file.handle = _h1;
1261 tree1->session = session1_2;
1262 status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
1263 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1264 "smb2_getinfo_file failed");
1266 tree1->session = session1_1;
1267 status = smb2_util_close(tree1, *h1);
1268 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1269 "smb2_util_close failed");
1273 * Now bind the 1st transport connection to the 2nd session
1275 session2_1 = smb2_session_channel(transport1,
1276 lpcfg_gensec_settings(tctx, tctx->lp_ctx),
1279 torture_assert(tctx, session2_1 != NULL, "smb2_session_channel failed");
1281 status = smb2_session_setup_spnego(session2_1,
1282 cmdline_credentials,
1283 0 /* previous_session_id */);
1284 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1285 "smb2_session_setup_spnego failed");
1287 tree2->session = session2_1;
1288 status = smb2_util_unlink(tree2, fname);
1289 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1290 "smb2_util_unlink failed");
1294 tree1->session = session1_1;
1297 smb2_util_close(tree1, *h1);
1300 smb2_util_unlink(tree1, fname);
1304 talloc_free(mem_ctx);
1309 struct torture_suite *torture_smb2_session_init(void)
1311 struct torture_suite *suite =
1312 torture_suite_create(talloc_autofree_context(), "session");
1314 torture_suite_add_1smb2_test(suite, "reconnect1", test_session_reconnect1);
1315 torture_suite_add_1smb2_test(suite, "reconnect2", test_session_reconnect2);
1316 torture_suite_add_1smb2_test(suite, "reauth1", test_session_reauth1);
1317 torture_suite_add_1smb2_test(suite, "reauth2", test_session_reauth2);
1318 torture_suite_add_1smb2_test(suite, "reauth3", test_session_reauth3);
1319 torture_suite_add_1smb2_test(suite, "reauth4", test_session_reauth4);
1320 torture_suite_add_1smb2_test(suite, "reauth5", test_session_reauth5);
1321 torture_suite_add_1smb2_test(suite, "reauth6", test_session_reauth6);
1322 torture_suite_add_simple_test(suite, "expire1", test_session_expire1);
1323 torture_suite_add_1smb2_test(suite, "bind1", test_session_bind1);
1325 suite->description = talloc_strdup(suite, "SMB2-SESSION tests");