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 "libcli/security/security.h"
31 #include "libcli/resolve/resolve.h"
32 #include "lib/param/param.h"
34 #define CHECK_VAL(v, correct) do { \
35 if ((v) != (correct)) { \
36 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
37 __location__, #v, (int)v, (int)correct); \
41 #define CHECK_STATUS(status, correct) do { \
42 if (!NT_STATUS_EQUAL(status, correct)) { \
43 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
44 nt_errstr(status), nt_errstr(correct)); \
49 #define CHECK_CREATED(__io, __created, __attribute) \
51 CHECK_VAL((__io)->out.create_action, NTCREATEX_ACTION_ ## __created); \
52 CHECK_VAL((__io)->out.alloc_size, 0); \
53 CHECK_VAL((__io)->out.size, 0); \
54 CHECK_VAL((__io)->out.file_attr, (__attribute)); \
55 CHECK_VAL((__io)->out.reserved2, 0); \
60 * basic test for doing a session reconnect
62 bool test_session_reconnect1(struct torture_context
*tctx
, struct smb2_tree
*tree
)
65 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
67 struct smb2_handle _h1
;
68 struct smb2_handle
*h1
= NULL
;
69 struct smb2_handle _h2
;
70 struct smb2_handle
*h2
= NULL
;
71 struct smb2_create io1
, io2
;
72 uint64_t previous_session_id
;
74 struct smb2_tree
*tree2
= NULL
;
75 union smb_fileinfo qfinfo
;
77 /* Add some random component to the file name. */
78 snprintf(fname
, sizeof(fname
), "session_reconnect_%s.dat",
79 generate_random_str(tctx
, 8));
81 smb2_util_unlink(tree
, fname
);
83 smb2_oplock_create_share(&io1
, fname
,
84 smb2_util_share_access(""),
85 smb2_util_oplock_level("b"));
87 status
= smb2_create(tree
, mem_ctx
, &io1
);
88 CHECK_STATUS(status
, NT_STATUS_OK
);
89 _h1
= io1
.out
.file
.handle
;
91 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
92 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
94 /* disconnect, reconnect and then do durable reopen */
95 previous_session_id
= smb2cli_session_current_id(tree
->session
->smbXcli
);
97 torture_assert_goto(tctx
, torture_smb2_connection_ext(tctx
, previous_session_id
,
98 &tree
->session
->transport
->options
, &tree2
),
100 "session reconnect failed\n");
102 /* try to access the file via the old handle */
105 qfinfo
.generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
;
106 qfinfo
.generic
.in
.file
.handle
= _h1
;
107 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
108 CHECK_STATUS(status
, NT_STATUS_USER_SESSION_DELETED
);
111 smb2_oplock_create_share(&io2
, fname
,
112 smb2_util_share_access(""),
113 smb2_util_oplock_level("b"));
115 status
= smb2_create(tree2
, mem_ctx
, &io2
);
116 CHECK_STATUS(status
, NT_STATUS_OK
);
117 CHECK_CREATED(&io2
, EXISTED
, FILE_ATTRIBUTE_ARCHIVE
);
118 CHECK_VAL(io2
.out
.oplock_level
, smb2_util_oplock_level("b"));
119 _h2
= io2
.out
.file
.handle
;
124 smb2_util_close(tree
, *h1
);
127 smb2_util_close(tree2
, *h2
);
131 smb2_util_unlink(tree2
, fname
);
133 smb2_util_unlink(tree
, fname
);
138 talloc_free(mem_ctx
);
144 * basic test for doing a session reconnect on one connection
146 bool test_session_reconnect2(struct torture_context
*tctx
, struct smb2_tree
*tree
)
149 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
151 struct smb2_handle _h1
;
152 struct smb2_handle
*h1
= NULL
;
153 struct smb2_create io1
;
154 uint64_t previous_session_id
;
156 struct smb2_session
*session2
= NULL
;
157 union smb_fileinfo qfinfo
;
159 /* Add some random component to the file name. */
160 snprintf(fname
, sizeof(fname
), "session_reconnect_%s.dat",
161 generate_random_str(tctx
, 8));
163 smb2_util_unlink(tree
, fname
);
165 smb2_oplock_create_share(&io1
, fname
,
166 smb2_util_share_access(""),
167 smb2_util_oplock_level("b"));
168 io1
.in
.create_options
|= NTCREATEX_OPTIONS_DELETE_ON_CLOSE
;
170 status
= smb2_create(tree
, mem_ctx
, &io1
);
171 CHECK_STATUS(status
, NT_STATUS_OK
);
172 _h1
= io1
.out
.file
.handle
;
174 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
175 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
177 /* disconnect, reconnect and then do durable reopen */
178 previous_session_id
= smb2cli_session_current_id(tree
->session
->smbXcli
);
180 torture_assert(tctx
, torture_smb2_session_setup(tctx
, tree
->session
->transport
,
181 previous_session_id
, tctx
, &session2
),
182 "session reconnect (on the same connection) failed");
184 /* try to access the file via the old handle */
187 qfinfo
.generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
;
188 qfinfo
.generic
.in
.file
.handle
= _h1
;
189 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
190 CHECK_STATUS(status
, NT_STATUS_USER_SESSION_DELETED
);
195 smb2_util_close(tree
, *h1
);
199 talloc_free(session2
);
201 talloc_free(mem_ctx
);
206 bool test_session_reauth1(struct torture_context
*tctx
, struct smb2_tree
*tree
)
209 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
211 struct smb2_handle _h1
;
212 struct smb2_handle
*h1
= NULL
;
213 struct smb2_create io1
;
215 union smb_fileinfo qfinfo
;
217 /* Add some random component to the file name. */
218 snprintf(fname
, sizeof(fname
), "session_reauth1_%s.dat",
219 generate_random_str(tctx
, 8));
221 smb2_util_unlink(tree
, fname
);
223 smb2_oplock_create_share(&io1
, fname
,
224 smb2_util_share_access(""),
225 smb2_util_oplock_level("b"));
227 status
= smb2_create(tree
, mem_ctx
, &io1
);
228 CHECK_STATUS(status
, NT_STATUS_OK
);
229 _h1
= io1
.out
.file
.handle
;
231 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
232 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
234 status
= smb2_session_setup_spnego(tree
->session
,
236 0 /* previous_session_id */);
237 CHECK_STATUS(status
, NT_STATUS_OK
);
239 /* try to access the file via the old handle */
242 qfinfo
.generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
;
243 qfinfo
.generic
.in
.file
.handle
= _h1
;
244 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
245 CHECK_STATUS(status
, NT_STATUS_OK
);
247 status
= smb2_session_setup_spnego(tree
->session
,
249 0 /* previous_session_id */);
250 CHECK_STATUS(status
, NT_STATUS_OK
);
252 /* try to access the file via the old handle */
255 qfinfo
.generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
;
256 qfinfo
.generic
.in
.file
.handle
= _h1
;
257 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
258 CHECK_STATUS(status
, NT_STATUS_OK
);
262 smb2_util_close(tree
, *h1
);
265 smb2_util_unlink(tree
, fname
);
269 talloc_free(mem_ctx
);
274 bool test_session_reauth2(struct torture_context
*tctx
, struct smb2_tree
*tree
)
277 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
279 struct smb2_handle _h1
;
280 struct smb2_handle
*h1
= NULL
;
281 struct smb2_create io1
;
283 union smb_fileinfo qfinfo
;
284 struct cli_credentials
*anon_creds
= NULL
;
286 /* Add some random component to the file name. */
287 snprintf(fname
, sizeof(fname
), "session_reauth2_%s.dat",
288 generate_random_str(tctx
, 8));
290 smb2_util_unlink(tree
, fname
);
292 smb2_oplock_create_share(&io1
, fname
,
293 smb2_util_share_access(""),
294 smb2_util_oplock_level("b"));
296 status
= smb2_create(tree
, mem_ctx
, &io1
);
297 CHECK_STATUS(status
, NT_STATUS_OK
);
298 _h1
= io1
.out
.file
.handle
;
300 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
301 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
303 /* re-authenticate as anonymous */
305 anon_creds
= cli_credentials_init_anon(mem_ctx
);
306 torture_assert(tctx
, (anon_creds
!= NULL
), "talloc error");
308 status
= smb2_session_setup_spnego(tree
->session
,
310 0 /* previous_session_id */);
311 CHECK_STATUS(status
, NT_STATUS_OK
);
313 /* try to access the file via the old handle */
316 qfinfo
.generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
;
317 qfinfo
.generic
.in
.file
.handle
= _h1
;
318 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
319 CHECK_STATUS(status
, NT_STATUS_OK
);
321 /* re-authenticate as original user again */
323 status
= smb2_session_setup_spnego(tree
->session
,
325 0 /* previous_session_id */);
326 CHECK_STATUS(status
, NT_STATUS_OK
);
328 /* try to access the file via the old handle */
331 qfinfo
.generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
;
332 qfinfo
.generic
.in
.file
.handle
= _h1
;
333 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
334 CHECK_STATUS(status
, NT_STATUS_OK
);
338 smb2_util_close(tree
, *h1
);
341 smb2_util_unlink(tree
, fname
);
345 talloc_free(mem_ctx
);
351 * test getting security descriptor after reauth
353 bool test_session_reauth3(struct torture_context
*tctx
, struct smb2_tree
*tree
)
356 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
358 struct smb2_handle _h1
;
359 struct smb2_handle
*h1
= NULL
;
360 struct smb2_create io1
;
362 union smb_fileinfo qfinfo
;
363 struct cli_credentials
*anon_creds
= NULL
;
364 uint32_t secinfo_flags
= SECINFO_OWNER
367 | SECINFO_PROTECTED_DACL
368 | SECINFO_UNPROTECTED_DACL
;
370 /* Add some random component to the file name. */
371 snprintf(fname
, sizeof(fname
), "session_reauth3_%s.dat",
372 generate_random_str(tctx
, 8));
374 smb2_util_unlink(tree
, fname
);
376 smb2_oplock_create_share(&io1
, fname
,
377 smb2_util_share_access(""),
378 smb2_util_oplock_level("b"));
380 status
= smb2_create(tree
, mem_ctx
, &io1
);
381 CHECK_STATUS(status
, NT_STATUS_OK
);
382 _h1
= io1
.out
.file
.handle
;
384 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
385 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
387 /* get the security descriptor */
391 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
392 qfinfo
.query_secdesc
.in
.file
.handle
= _h1
;
393 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
395 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
396 CHECK_STATUS(status
, NT_STATUS_OK
);
397 /* re-authenticate as anonymous */
399 anon_creds
= cli_credentials_init_anon(mem_ctx
);
400 torture_assert(tctx
, (anon_creds
!= NULL
), "talloc error");
402 status
= smb2_session_setup_spnego(tree
->session
,
404 0 /* previous_session_id */);
405 CHECK_STATUS(status
, NT_STATUS_OK
);
407 /* try to access the file via the old handle */
411 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
412 qfinfo
.query_secdesc
.in
.file
.handle
= _h1
;
413 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
415 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
416 CHECK_STATUS(status
, NT_STATUS_OK
);
418 /* re-authenticate as original user again */
420 status
= smb2_session_setup_spnego(tree
->session
,
422 0 /* previous_session_id */);
423 CHECK_STATUS(status
, NT_STATUS_OK
);
425 /* try to access the file via the old handle */
429 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
430 qfinfo
.query_secdesc
.in
.file
.handle
= _h1
;
431 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
433 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
434 CHECK_STATUS(status
, NT_STATUS_OK
);
438 smb2_util_close(tree
, *h1
);
441 smb2_util_unlink(tree
, fname
);
445 talloc_free(mem_ctx
);
451 * test setting security descriptor after reauth.
453 bool test_session_reauth4(struct torture_context
*tctx
, struct smb2_tree
*tree
)
456 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
458 struct smb2_handle _h1
;
459 struct smb2_handle
*h1
= NULL
;
460 struct smb2_create io1
;
462 union smb_fileinfo qfinfo
;
463 union smb_setfileinfo sfinfo
;
464 struct cli_credentials
*anon_creds
= NULL
;
465 uint32_t secinfo_flags
= SECINFO_OWNER
468 | SECINFO_PROTECTED_DACL
469 | SECINFO_UNPROTECTED_DACL
;
470 struct security_descriptor
*sd1
;
471 struct security_ace ace
;
472 struct dom_sid
*extra_sid
;
474 /* Add some random component to the file name. */
475 snprintf(fname
, sizeof(fname
), "session_reauth4_%s.dat",
476 generate_random_str(tctx
, 8));
478 smb2_util_unlink(tree
, fname
);
480 smb2_oplock_create_share(&io1
, fname
,
481 smb2_util_share_access(""),
482 smb2_util_oplock_level("b"));
484 status
= smb2_create(tree
, mem_ctx
, &io1
);
485 CHECK_STATUS(status
, NT_STATUS_OK
);
486 _h1
= io1
.out
.file
.handle
;
488 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
489 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
491 /* get the security descriptor */
495 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
496 qfinfo
.query_secdesc
.in
.file
.handle
= _h1
;
497 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
499 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
500 CHECK_STATUS(status
, NT_STATUS_OK
);
502 sd1
= qfinfo
.query_secdesc
.out
.sd
;
504 /* re-authenticate as anonymous */
506 anon_creds
= cli_credentials_init_anon(mem_ctx
);
507 torture_assert(tctx
, (anon_creds
!= NULL
), "talloc error");
509 status
= smb2_session_setup_spnego(tree
->session
,
511 0 /* previous_session_id */);
512 CHECK_STATUS(status
, NT_STATUS_OK
);
514 /* give full access on the file to anonymous */
516 extra_sid
= dom_sid_parse_talloc(tctx
, SID_NT_ANONYMOUS
);
519 ace
.type
= SEC_ACE_TYPE_ACCESS_ALLOWED
;
521 ace
.access_mask
= SEC_STD_ALL
| SEC_FILE_ALL
;
522 ace
.trustee
= *extra_sid
;
524 status
= security_descriptor_dacl_add(sd1
, &ace
);
525 CHECK_STATUS(status
, NT_STATUS_OK
);
528 sfinfo
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
529 sfinfo
.set_secdesc
.in
.file
.handle
= _h1
;
530 sfinfo
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
531 sfinfo
.set_secdesc
.in
.sd
= sd1
;
533 status
= smb2_setinfo_file(tree
, &sfinfo
);
534 CHECK_STATUS(status
, NT_STATUS_OK
);
536 /* re-authenticate as original user again */
538 status
= smb2_session_setup_spnego(tree
->session
,
540 0 /* previous_session_id */);
541 CHECK_STATUS(status
, NT_STATUS_OK
);
543 /* re-get the security descriptor */
547 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
548 qfinfo
.query_secdesc
.in
.file
.handle
= _h1
;
549 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
551 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
552 CHECK_STATUS(status
, NT_STATUS_OK
);
558 smb2_util_close(tree
, *h1
);
561 smb2_util_unlink(tree
, fname
);
565 talloc_free(mem_ctx
);
571 * test renaming after reauth.
572 * compare security descriptors before and after rename/reauth
574 bool test_session_reauth5(struct torture_context
*tctx
, struct smb2_tree
*tree
)
577 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
581 struct smb2_handle _dh1
;
582 struct smb2_handle
*dh1
= NULL
;
583 struct smb2_handle _h1
;
584 struct smb2_handle
*h1
= NULL
;
585 struct smb2_create io1
;
588 union smb_fileinfo qfinfo
;
589 union smb_setfileinfo sfinfo
;
590 struct cli_credentials
*anon_creds
= NULL
;
591 uint32_t secinfo_flags
= SECINFO_OWNER
594 | SECINFO_PROTECTED_DACL
595 | SECINFO_UNPROTECTED_DACL
;
596 struct security_descriptor
*f_sd1
;
597 struct security_descriptor
*d_sd1
= NULL
;
598 struct security_ace ace
;
599 struct dom_sid
*extra_sid
;
601 /* Add some random component to the file name. */
602 snprintf(dname
, sizeof(dname
), "session_reauth5_%s.d",
603 generate_random_str(tctx
, 8));
604 snprintf(fname
, sizeof(fname
), "%s\\file.dat", dname
);
606 ok
= smb2_util_setup_dir(tctx
, tree
, dname
);
609 status
= torture_smb2_testdir(tree
, dname
, &_dh1
);
610 CHECK_STATUS(status
, NT_STATUS_OK
);
613 smb2_oplock_create_share(&io1
, fname
,
614 smb2_util_share_access(""),
615 smb2_util_oplock_level("b"));
617 status
= smb2_create(tree
, mem_ctx
, &io1
);
618 CHECK_STATUS(status
, NT_STATUS_OK
);
619 _h1
= io1
.out
.file
.handle
;
621 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
622 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
624 /* get the security descriptor */
628 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
629 qfinfo
.query_secdesc
.in
.file
.handle
= _h1
;
630 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
632 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
633 CHECK_STATUS(status
, NT_STATUS_OK
);
635 f_sd1
= qfinfo
.query_secdesc
.out
.sd
;
637 /* re-authenticate as anonymous */
639 anon_creds
= cli_credentials_init_anon(mem_ctx
);
640 torture_assert(tctx
, (anon_creds
!= NULL
), "talloc error");
642 status
= smb2_session_setup_spnego(tree
->session
,
644 0 /* previous_session_id */);
645 CHECK_STATUS(status
, NT_STATUS_OK
);
647 /* try to rename the file: fails */
649 snprintf(fname2
, sizeof(fname2
), "%s\\file2.dat", dname
);
651 smb2_util_unlink(tree
, fname2
);
654 sfinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
655 sfinfo
.rename_information
.in
.file
.handle
= _h1
;
656 sfinfo
.rename_information
.in
.overwrite
= true;
657 sfinfo
.rename_information
.in
.new_name
= fname2
;
659 status
= smb2_setinfo_file(tree
, &sfinfo
);
660 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
662 /* re-authenticate as original user again */
664 status
= smb2_session_setup_spnego(tree
->session
,
666 0 /* previous_session_id */);
667 CHECK_STATUS(status
, NT_STATUS_OK
);
669 /* give full access on the file to anonymous */
671 extra_sid
= dom_sid_parse_talloc(tctx
, SID_NT_ANONYMOUS
);
674 ace
.type
= SEC_ACE_TYPE_ACCESS_ALLOWED
;
676 ace
.access_mask
= SEC_RIGHTS_FILE_ALL
;
677 ace
.trustee
= *extra_sid
;
679 status
= security_descriptor_dacl_add(f_sd1
, &ace
);
680 CHECK_STATUS(status
, NT_STATUS_OK
);
683 sfinfo
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
684 sfinfo
.set_secdesc
.in
.file
.handle
= _h1
;
685 sfinfo
.set_secdesc
.in
.secinfo_flags
= secinfo_flags
;
686 sfinfo
.set_secdesc
.in
.sd
= f_sd1
;
688 status
= smb2_setinfo_file(tree
, &sfinfo
);
689 CHECK_STATUS(status
, NT_STATUS_OK
);
691 /* re-get the security descriptor */
695 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
696 qfinfo
.query_secdesc
.in
.file
.handle
= _h1
;
697 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
699 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
700 CHECK_STATUS(status
, NT_STATUS_OK
);
702 /* re-authenticate as anonymous - again */
704 anon_creds
= cli_credentials_init_anon(mem_ctx
);
705 torture_assert(tctx
, (anon_creds
!= NULL
), "talloc error");
707 status
= smb2_session_setup_spnego(tree
->session
,
709 0 /* previous_session_id */);
710 CHECK_STATUS(status
, NT_STATUS_OK
);
712 /* try to rename the file: fails */
715 sfinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
716 sfinfo
.rename_information
.in
.file
.handle
= _h1
;
717 sfinfo
.rename_information
.in
.overwrite
= true;
718 sfinfo
.rename_information
.in
.new_name
= fname2
;
720 status
= smb2_setinfo_file(tree
, &sfinfo
);
721 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
723 /* give full access on the parent dir to anonymous */
727 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
728 qfinfo
.query_secdesc
.in
.file
.handle
= _dh1
;
729 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
731 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
732 CHECK_STATUS(status
, NT_STATUS_OK
);
734 d_sd1
= qfinfo
.query_secdesc
.out
.sd
;
737 ace
.type
= SEC_ACE_TYPE_ACCESS_ALLOWED
;
739 ace
.access_mask
= SEC_RIGHTS_FILE_ALL
;
740 ace
.trustee
= *extra_sid
;
742 status
= security_descriptor_dacl_add(d_sd1
, &ace
);
743 CHECK_STATUS(status
, NT_STATUS_OK
);
746 sfinfo
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
747 sfinfo
.set_secdesc
.in
.file
.handle
= _dh1
;
748 sfinfo
.set_secdesc
.in
.secinfo_flags
= secinfo_flags
;
749 sfinfo
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
750 sfinfo
.set_secdesc
.in
.sd
= d_sd1
;
752 status
= smb2_setinfo_file(tree
, &sfinfo
);
753 CHECK_STATUS(status
, NT_STATUS_OK
);
757 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
758 qfinfo
.query_secdesc
.in
.file
.handle
= _dh1
;
759 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
761 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
762 CHECK_STATUS(status
, NT_STATUS_OK
);
764 smb2_util_close(tree
, _dh1
);
767 /* try to rename the file: still fails */
770 sfinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
771 sfinfo
.rename_information
.in
.file
.handle
= _h1
;
772 sfinfo
.rename_information
.in
.overwrite
= true;
773 sfinfo
.rename_information
.in
.new_name
= fname2
;
775 status
= smb2_setinfo_file(tree
, &sfinfo
);
776 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
778 /* re-authenticate as original user - again */
780 status
= smb2_session_setup_spnego(tree
->session
,
782 0 /* previous_session_id */);
783 CHECK_STATUS(status
, NT_STATUS_OK
);
785 /* rename the file - for verification that it works */
788 sfinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
789 sfinfo
.rename_information
.in
.file
.handle
= _h1
;
790 sfinfo
.rename_information
.in
.overwrite
= true;
791 sfinfo
.rename_information
.in
.new_name
= fname2
;
793 status
= smb2_setinfo_file(tree
, &sfinfo
);
794 CHECK_STATUS(status
, NT_STATUS_OK
);
796 /* closs the file, check it is gone and reopen under the new name */
798 smb2_util_close(tree
, _h1
);
802 smb2_generic_create_share(&io1
,
803 NULL
/* lease */, false /* dir */,
806 smb2_util_share_access(""),
807 smb2_util_oplock_level("b"),
808 0 /* leasekey */, 0 /* leasestate */);
810 status
= smb2_create(tree
, mem_ctx
, &io1
);
811 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
815 smb2_generic_create_share(&io1
,
816 NULL
/* lease */, false /* dir */,
819 smb2_util_share_access(""),
820 smb2_util_oplock_level("b"),
821 0 /* leasekey */, 0 /* leasestate */);
823 status
= smb2_create(tree
, mem_ctx
, &io1
);
824 CHECK_STATUS(status
, NT_STATUS_OK
);
825 _h1
= io1
.out
.file
.handle
;
827 CHECK_CREATED(&io1
, EXISTED
, FILE_ATTRIBUTE_ARCHIVE
);
828 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
830 /* try to access the file via the old handle */
834 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
835 qfinfo
.query_secdesc
.in
.file
.handle
= _h1
;
836 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
838 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
839 CHECK_STATUS(status
, NT_STATUS_OK
);
843 smb2_util_close(tree
, *dh1
);
846 smb2_util_close(tree
, *h1
);
849 smb2_deltree(tree
, dname
);
853 talloc_free(mem_ctx
);
859 * do reauth with wrong credentials,
860 * hence triggering the error path in reauth.
861 * The invalid reauth deletes the session.
863 bool test_session_reauth6(struct torture_context
*tctx
, struct smb2_tree
*tree
)
866 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
868 struct smb2_handle _h1
;
869 struct smb2_handle
*h1
= NULL
;
870 struct smb2_create io1
;
872 char *corrupted_password
;
873 struct cli_credentials
*broken_creds
;
877 enum credentials_use_kerberos krb_state
;
879 krb_state
= cli_credentials_get_kerberos_state(cmdline_credentials
);
880 if (krb_state
== CRED_MUST_USE_KERBEROS
) {
882 "Can't test failing session setup with kerberos.");
885 encrypted
= smb2cli_tcon_is_encryption_on(tree
->smbXcli
);
887 /* Add some random component to the file name. */
888 snprintf(fname
, sizeof(fname
), "session_reauth1_%s.dat",
889 generate_random_str(tctx
, 8));
891 smb2_util_unlink(tree
, fname
);
893 smb2_oplock_create_share(&io1
, fname
,
894 smb2_util_share_access(""),
895 smb2_util_oplock_level("b"));
896 io1
.in
.create_options
|= NTCREATEX_OPTIONS_DELETE_ON_CLOSE
;
898 status
= smb2_create(tree
, mem_ctx
, &io1
);
899 CHECK_STATUS(status
, NT_STATUS_OK
);
900 _h1
= io1
.out
.file
.handle
;
902 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
903 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
906 * reauthentication with invalid credentials:
909 broken_creds
= cli_credentials_shallow_copy(mem_ctx
,
910 cmdline_credentials
);
911 torture_assert(tctx
, (broken_creds
!= NULL
), "talloc error");
913 corrupted_password
= talloc_asprintf(mem_ctx
, "%s%s",
914 cli_credentials_get_password(broken_creds
),
916 torture_assert(tctx
, (corrupted_password
!= NULL
), "talloc error");
918 ok
= cli_credentials_set_password(broken_creds
, corrupted_password
,
922 status
= smb2_session_setup_spnego(tree
->session
,
924 0 /* previous_session_id */);
925 CHECK_STATUS(status
, NT_STATUS_LOGON_FAILURE
);
927 torture_comment(tctx
, "did failed reauth\n");
929 * now verify that the invalid session reauth has closed our session
933 expected
= NT_STATUS_CONNECTION_DISCONNECTED
;
935 expected
= NT_STATUS_USER_SESSION_DELETED
;
938 smb2_oplock_create_share(&io1
, fname
,
939 smb2_util_share_access(""),
940 smb2_util_oplock_level("b"));
942 status
= smb2_create(tree
, mem_ctx
, &io1
);
943 CHECK_STATUS(status
, expected
);
947 smb2_util_close(tree
, *h1
);
950 smb2_util_unlink(tree
, fname
);
954 talloc_free(mem_ctx
);
960 static bool test_session_expire1(struct torture_context
*tctx
)
964 struct smbcli_options options
;
965 const char *host
= torture_setting_string(tctx
, "host", NULL
);
966 const char *share
= torture_setting_string(tctx
, "share", NULL
);
967 struct cli_credentials
*credentials
= cmdline_credentials
;
968 struct smb2_tree
*tree
= NULL
;
969 enum credentials_use_kerberos use_kerberos
;
971 struct smb2_handle _h1
;
972 struct smb2_handle
*h1
= NULL
;
973 struct smb2_create io1
;
974 union smb_fileinfo qfinfo
;
977 use_kerberos
= cli_credentials_get_kerberos_state(credentials
);
978 if (use_kerberos
!= CRED_MUST_USE_KERBEROS
) {
979 torture_warning(tctx
, "smb2.session.expire1 requires -k yes!");
980 torture_skip(tctx
, "smb2.session.expire1 requires -k yes!");
983 torture_assert_int_equal(tctx
, use_kerberos
, CRED_MUST_USE_KERBEROS
,
984 "please use -k yes");
986 lpcfg_set_option(tctx
->lp_ctx
, "gensec_gssapi:requested_life_time=4");
988 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
990 status
= smb2_connect(tctx
,
992 lpcfg_smb_ports(tctx
->lp_ctx
),
994 lpcfg_resolve_context(tctx
->lp_ctx
),
999 lpcfg_socket_options(tctx
->lp_ctx
),
1000 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)
1002 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1003 "smb2_connect failed");
1005 /* Add some random component to the file name. */
1006 snprintf(fname
, sizeof(fname
), "session_expire1_%s.dat",
1007 generate_random_str(tctx
, 8));
1009 smb2_util_unlink(tree
, fname
);
1011 smb2_oplock_create_share(&io1
, fname
,
1012 smb2_util_share_access(""),
1013 smb2_util_oplock_level("b"));
1014 io1
.in
.create_options
|= NTCREATEX_OPTIONS_DELETE_ON_CLOSE
;
1016 status
= smb2_create(tree
, tctx
, &io1
);
1017 CHECK_STATUS(status
, NT_STATUS_OK
);
1018 _h1
= io1
.out
.file
.handle
;
1020 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
1021 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
1023 /* get the security descriptor */
1025 ZERO_STRUCT(qfinfo
);
1027 qfinfo
.access_information
.level
= RAW_FILEINFO_ACCESS_INFORMATION
;
1028 qfinfo
.access_information
.in
.file
.handle
= _h1
;
1030 for (i
=0; i
< 2; i
++) {
1031 torture_comment(tctx
, "query info => OK\n");
1033 ZERO_STRUCT(qfinfo
.access_information
.out
);
1034 status
= smb2_getinfo_file(tree
, tctx
, &qfinfo
);
1035 CHECK_STATUS(status
, NT_STATUS_OK
);
1037 torture_comment(tctx
, "sleep 5 seconds\n");
1040 torture_comment(tctx
, "query info => EXPIRED\n");
1041 ZERO_STRUCT(qfinfo
.access_information
.out
);
1042 status
= smb2_getinfo_file(tree
, tctx
, &qfinfo
);
1043 CHECK_STATUS(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
);
1046 * the krb5 library may not handle expired creds
1047 * well, lets start with an empty ccache.
1049 cli_credentials_invalidate_ccache(credentials
, CRED_SPECIFIED
);
1051 torture_comment(tctx
, "reauth => OK\n");
1052 status
= smb2_session_setup_spnego(tree
->session
,
1054 0 /* previous_session_id */);
1055 CHECK_STATUS(status
, NT_STATUS_OK
);
1058 ZERO_STRUCT(qfinfo
.access_information
.out
);
1059 status
= smb2_getinfo_file(tree
, tctx
, &qfinfo
);
1060 CHECK_STATUS(status
, NT_STATUS_OK
);
1065 smb2_util_close(tree
, *h1
);
1069 lpcfg_set_option(tctx
->lp_ctx
, "gensec_gssapi:requested_life_time=0");
1073 bool test_session_bind1(struct torture_context
*tctx
, struct smb2_tree
*tree1
)
1075 const char *host
= torture_setting_string(tctx
, "host", NULL
);
1076 const char *share
= torture_setting_string(tctx
, "share", NULL
);
1077 struct cli_credentials
*credentials
= cmdline_credentials
;
1079 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
1081 struct smb2_handle _h1
;
1082 struct smb2_handle
*h1
= NULL
;
1083 struct smb2_create io1
;
1084 union smb_fileinfo qfinfo
;
1086 struct smb2_tree
*tree2
= NULL
;
1087 struct smb2_transport
*transport1
= tree1
->session
->transport
;
1088 struct smb2_transport
*transport2
= NULL
;
1089 struct smb2_session
*session1_1
= tree1
->session
;
1090 struct smb2_session
*session1_2
= NULL
;
1091 struct smb2_session
*session2_1
= NULL
;
1092 struct smb2_session
*session2_2
= NULL
;
1095 caps
= smb2cli_conn_server_capabilities(transport1
->conn
);
1096 if (!(caps
& SMB2_CAP_MULTI_CHANNEL
)) {
1097 torture_skip(tctx
, "server doesn't support SMB2_CAP_MULTI_CHANNEL\n");
1100 /* Add some random component to the file name. */
1101 snprintf(fname
, sizeof(fname
), "session_bind1_%s.dat",
1102 generate_random_str(tctx
, 8));
1104 smb2_util_unlink(tree1
, fname
);
1106 smb2_oplock_create_share(&io1
, fname
,
1107 smb2_util_share_access(""),
1108 smb2_util_oplock_level("b"));
1110 status
= smb2_create(tree1
, mem_ctx
, &io1
);
1111 CHECK_STATUS(status
, NT_STATUS_OK
);
1112 _h1
= io1
.out
.file
.handle
;
1114 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
1115 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
1117 status
= smb2_connect(tctx
,
1119 lpcfg_smb_ports(tctx
->lp_ctx
),
1121 lpcfg_resolve_context(tctx
->lp_ctx
),
1125 &transport1
->options
,
1126 lpcfg_socket_options(tctx
->lp_ctx
),
1127 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)
1129 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1130 "smb2_connect failed");
1131 session2_2
= tree2
->session
;
1132 transport2
= tree2
->session
->transport
;
1135 * Now bind the 2nd transport connection to the 1st session
1137 session1_2
= smb2_session_channel(transport2
,
1138 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
),
1141 torture_assert(tctx
, session1_2
!= NULL
, "smb2_session_channel failed");
1143 status
= smb2_session_setup_spnego(session1_2
,
1144 cmdline_credentials
,
1145 0 /* previous_session_id */);
1146 CHECK_STATUS(status
, NT_STATUS_OK
);
1148 /* use the 1st connection, 1st session */
1149 ZERO_STRUCT(qfinfo
);
1150 qfinfo
.generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
;
1151 qfinfo
.generic
.in
.file
.handle
= _h1
;
1152 tree1
->session
= session1_1
;
1153 status
= smb2_getinfo_file(tree1
, mem_ctx
, &qfinfo
);
1154 CHECK_STATUS(status
, NT_STATUS_OK
);
1156 /* use the 2nd connection, 1st session */
1157 ZERO_STRUCT(qfinfo
);
1158 qfinfo
.generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
;
1159 qfinfo
.generic
.in
.file
.handle
= _h1
;
1160 tree1
->session
= session1_2
;
1161 status
= smb2_getinfo_file(tree1
, mem_ctx
, &qfinfo
);
1162 CHECK_STATUS(status
, NT_STATUS_OK
);
1164 tree1
->session
= session1_1
;
1165 smb2_util_close(tree1
, *h1
);
1169 * Now bind the 1st transport connection to the 2nd session
1171 session2_1
= smb2_session_channel(transport1
,
1172 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
),
1175 torture_assert(tctx
, session2_1
!= NULL
, "smb2_session_channel failed");
1177 status
= smb2_session_setup_spnego(session2_1
,
1178 cmdline_credentials
,
1179 0 /* previous_session_id */);
1180 CHECK_STATUS(status
, NT_STATUS_OK
);
1182 tree2
->session
= session2_1
;
1183 status
= smb2_util_unlink(tree2
, fname
);
1184 CHECK_STATUS(status
, NT_STATUS_OK
);
1189 tree1
->session
= session1_1
;
1192 smb2_util_close(tree1
, *h1
);
1195 smb2_util_unlink(tree1
, fname
);
1199 talloc_free(mem_ctx
);
1204 struct torture_suite
*torture_smb2_session_init(void)
1206 struct torture_suite
*suite
=
1207 torture_suite_create(talloc_autofree_context(), "session");
1209 torture_suite_add_1smb2_test(suite
, "reconnect1", test_session_reconnect1
);
1210 torture_suite_add_1smb2_test(suite
, "reconnect2", test_session_reconnect2
);
1211 torture_suite_add_1smb2_test(suite
, "reauth1", test_session_reauth1
);
1212 torture_suite_add_1smb2_test(suite
, "reauth2", test_session_reauth2
);
1213 torture_suite_add_1smb2_test(suite
, "reauth3", test_session_reauth3
);
1214 torture_suite_add_1smb2_test(suite
, "reauth4", test_session_reauth4
);
1215 torture_suite_add_1smb2_test(suite
, "reauth5", test_session_reauth5
);
1216 torture_suite_add_1smb2_test(suite
, "reauth6", test_session_reauth6
);
1217 torture_suite_add_simple_test(suite
, "expire1", test_session_expire1
);
1218 torture_suite_add_1smb2_test(suite
, "bind1", test_session_bind1
);
1220 suite
->description
= talloc_strdup(suite
, "SMB2-SESSION tests");