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
;
75 union smb_fileinfo qfinfo
;
77 /* Add some random component to the file name. */
78 snprintf(fname
, 256, "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 if (!torture_smb2_connection_ext(tctx
, previous_session_id
,
98 &tree
->session
->transport
->options
,
101 torture_warning(tctx
, "session reconnect failed\n");
106 /* try to access the file via the old handle */
109 qfinfo
.generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
;
110 qfinfo
.generic
.in
.file
.handle
= _h1
;
111 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
112 CHECK_STATUS(status
, NT_STATUS_USER_SESSION_DELETED
);
115 smb2_oplock_create_share(&io2
, fname
,
116 smb2_util_share_access(""),
117 smb2_util_oplock_level("b"));
119 status
= smb2_create(tree2
, mem_ctx
, &io2
);
120 CHECK_STATUS(status
, NT_STATUS_OK
);
121 CHECK_CREATED(&io2
, EXISTED
, FILE_ATTRIBUTE_ARCHIVE
);
122 CHECK_VAL(io2
.out
.oplock_level
, smb2_util_oplock_level("b"));
123 _h2
= io2
.out
.file
.handle
;
128 smb2_util_close(tree
, *h1
);
131 smb2_util_close(tree2
, *h2
);
134 smb2_util_unlink(tree2
, 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
;
158 union smb_fileinfo qfinfo
;
160 /* Add some random component to the file name. */
161 snprintf(fname
, 256, "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 CHECK_STATUS(status
, NT_STATUS_OK
);
173 _h1
= io1
.out
.file
.handle
;
175 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
176 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
178 /* disconnect, reconnect and then do durable reopen */
179 previous_session_id
= smb2cli_session_current_id(tree
->session
->smbXcli
);
181 torture_assert(tctx
, torture_smb2_session_setup(tctx
, tree
->session
->transport
,
182 previous_session_id
, tctx
, &session2
),
183 "session reconnect (on the same connection) failed");
185 /* try to access the file via the old handle */
188 qfinfo
.generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
;
189 qfinfo
.generic
.in
.file
.handle
= _h1
;
190 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
191 CHECK_STATUS(status
, NT_STATUS_USER_SESSION_DELETED
);
196 smb2_util_close(tree
, *h1
);
200 talloc_free(session2
);
202 talloc_free(mem_ctx
);
207 bool test_session_reauth1(struct torture_context
*tctx
, struct smb2_tree
*tree
)
210 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
212 struct smb2_handle _h1
;
213 struct smb2_handle
*h1
= NULL
;
214 struct smb2_create io1
;
216 union smb_fileinfo qfinfo
;
218 /* Add some random component to the file name. */
219 snprintf(fname
, 256, "session_reauth1_%s.dat",
220 generate_random_str(tctx
, 8));
222 smb2_util_unlink(tree
, fname
);
224 smb2_oplock_create_share(&io1
, fname
,
225 smb2_util_share_access(""),
226 smb2_util_oplock_level("b"));
228 status
= smb2_create(tree
, mem_ctx
, &io1
);
229 CHECK_STATUS(status
, NT_STATUS_OK
);
230 _h1
= io1
.out
.file
.handle
;
232 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
233 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
235 status
= smb2_session_setup_spnego(tree
->session
,
237 0 /* previous_session_id */);
238 CHECK_STATUS(status
, NT_STATUS_OK
);
240 /* try to access the file via the old handle */
243 qfinfo
.generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
;
244 qfinfo
.generic
.in
.file
.handle
= _h1
;
245 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
246 CHECK_STATUS(status
, NT_STATUS_OK
);
248 status
= smb2_session_setup_spnego(tree
->session
,
250 0 /* previous_session_id */);
251 CHECK_STATUS(status
, NT_STATUS_OK
);
253 /* try to access the file via the old handle */
256 qfinfo
.generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
;
257 qfinfo
.generic
.in
.file
.handle
= _h1
;
258 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
259 CHECK_STATUS(status
, NT_STATUS_OK
);
263 smb2_util_close(tree
, *h1
);
266 smb2_util_unlink(tree
, fname
);
270 talloc_free(mem_ctx
);
275 bool test_session_reauth2(struct torture_context
*tctx
, struct smb2_tree
*tree
)
278 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
280 struct smb2_handle _h1
;
281 struct smb2_handle
*h1
= NULL
;
282 struct smb2_create io1
;
284 union smb_fileinfo qfinfo
;
285 struct cli_credentials
*anon_creds
= NULL
;
287 /* Add some random component to the file name. */
288 snprintf(fname
, 256, "session_reauth2_%s.dat",
289 generate_random_str(tctx
, 8));
291 smb2_util_unlink(tree
, fname
);
293 smb2_oplock_create_share(&io1
, fname
,
294 smb2_util_share_access(""),
295 smb2_util_oplock_level("b"));
297 status
= smb2_create(tree
, mem_ctx
, &io1
);
298 CHECK_STATUS(status
, NT_STATUS_OK
);
299 _h1
= io1
.out
.file
.handle
;
301 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
302 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
304 /* re-authenticate as anonymous */
306 anon_creds
= cli_credentials_init_anon(mem_ctx
);
307 torture_assert(tctx
, (anon_creds
!= NULL
), "talloc error");
309 status
= smb2_session_setup_spnego(tree
->session
,
311 0 /* previous_session_id */);
312 CHECK_STATUS(status
, NT_STATUS_OK
);
314 /* try to access the file via the old handle */
317 qfinfo
.generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
;
318 qfinfo
.generic
.in
.file
.handle
= _h1
;
319 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
320 CHECK_STATUS(status
, NT_STATUS_OK
);
322 /* re-authenticate as original user again */
324 status
= smb2_session_setup_spnego(tree
->session
,
326 0 /* previous_session_id */);
327 CHECK_STATUS(status
, NT_STATUS_OK
);
329 /* try to access the file via the old handle */
332 qfinfo
.generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
;
333 qfinfo
.generic
.in
.file
.handle
= _h1
;
334 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
335 CHECK_STATUS(status
, NT_STATUS_OK
);
339 smb2_util_close(tree
, *h1
);
342 smb2_util_unlink(tree
, fname
);
346 talloc_free(mem_ctx
);
352 * test getting security descriptor after reauth
354 bool test_session_reauth3(struct torture_context
*tctx
, struct smb2_tree
*tree
)
357 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
359 struct smb2_handle _h1
;
360 struct smb2_handle
*h1
= NULL
;
361 struct smb2_create io1
;
363 union smb_fileinfo qfinfo
;
364 struct cli_credentials
*anon_creds
= NULL
;
365 uint32_t secinfo_flags
= SECINFO_OWNER
368 | SECINFO_PROTECTED_DACL
369 | SECINFO_UNPROTECTED_DACL
;
371 /* Add some random component to the file name. */
372 snprintf(fname
, 256, "session_reauth3_%s.dat",
373 generate_random_str(tctx
, 8));
375 smb2_util_unlink(tree
, fname
);
377 smb2_oplock_create_share(&io1
, fname
,
378 smb2_util_share_access(""),
379 smb2_util_oplock_level("b"));
381 status
= smb2_create(tree
, mem_ctx
, &io1
);
382 CHECK_STATUS(status
, NT_STATUS_OK
);
383 _h1
= io1
.out
.file
.handle
;
385 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
386 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
388 /* get the security descriptor */
392 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
393 qfinfo
.query_secdesc
.in
.file
.handle
= _h1
;
394 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
396 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
397 CHECK_STATUS(status
, NT_STATUS_OK
);
398 /* re-authenticate as anonymous */
400 anon_creds
= cli_credentials_init_anon(mem_ctx
);
401 torture_assert(tctx
, (anon_creds
!= NULL
), "talloc error");
403 status
= smb2_session_setup_spnego(tree
->session
,
405 0 /* previous_session_id */);
406 CHECK_STATUS(status
, NT_STATUS_OK
);
408 /* try to access the file via the old handle */
412 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
413 qfinfo
.query_secdesc
.in
.file
.handle
= _h1
;
414 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
416 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
417 CHECK_STATUS(status
, NT_STATUS_OK
);
419 /* re-authenticate as original user again */
421 status
= smb2_session_setup_spnego(tree
->session
,
423 0 /* previous_session_id */);
424 CHECK_STATUS(status
, NT_STATUS_OK
);
426 /* try to access the file via the old handle */
430 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
431 qfinfo
.query_secdesc
.in
.file
.handle
= _h1
;
432 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
434 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
435 CHECK_STATUS(status
, NT_STATUS_OK
);
439 smb2_util_close(tree
, *h1
);
442 smb2_util_unlink(tree
, fname
);
446 talloc_free(mem_ctx
);
452 * test setting security descriptor after reauth.
454 bool test_session_reauth4(struct torture_context
*tctx
, struct smb2_tree
*tree
)
457 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
459 struct smb2_handle _h1
;
460 struct smb2_handle
*h1
= NULL
;
461 struct smb2_create io1
;
463 union smb_fileinfo qfinfo
;
464 union smb_setfileinfo sfinfo
;
465 struct cli_credentials
*anon_creds
= NULL
;
466 uint32_t secinfo_flags
= SECINFO_OWNER
469 | SECINFO_PROTECTED_DACL
470 | SECINFO_UNPROTECTED_DACL
;
471 struct security_descriptor
*sd1
;
472 struct security_ace ace
;
473 struct dom_sid
*extra_sid
;
475 /* Add some random component to the file name. */
476 snprintf(fname
, 256, "session_reauth4_%s.dat",
477 generate_random_str(tctx
, 8));
479 smb2_util_unlink(tree
, fname
);
481 smb2_oplock_create_share(&io1
, fname
,
482 smb2_util_share_access(""),
483 smb2_util_oplock_level("b"));
485 status
= smb2_create(tree
, mem_ctx
, &io1
);
486 CHECK_STATUS(status
, NT_STATUS_OK
);
487 _h1
= io1
.out
.file
.handle
;
489 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
490 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
492 /* get the security descriptor */
496 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
497 qfinfo
.query_secdesc
.in
.file
.handle
= _h1
;
498 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
500 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
501 CHECK_STATUS(status
, NT_STATUS_OK
);
503 sd1
= qfinfo
.query_secdesc
.out
.sd
;
505 /* re-authenticate as anonymous */
507 anon_creds
= cli_credentials_init_anon(mem_ctx
);
508 torture_assert(tctx
, (anon_creds
!= NULL
), "talloc error");
510 status
= smb2_session_setup_spnego(tree
->session
,
512 0 /* previous_session_id */);
513 CHECK_STATUS(status
, NT_STATUS_OK
);
515 /* give full access on the file to anonymous */
517 extra_sid
= dom_sid_parse_talloc(tctx
, SID_NT_ANONYMOUS
);
520 ace
.type
= SEC_ACE_TYPE_ACCESS_ALLOWED
;
522 ace
.access_mask
= SEC_STD_ALL
| SEC_FILE_ALL
;
523 ace
.trustee
= *extra_sid
;
525 status
= security_descriptor_dacl_add(sd1
, &ace
);
526 CHECK_STATUS(status
, NT_STATUS_OK
);
529 sfinfo
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
530 sfinfo
.set_secdesc
.in
.file
.handle
= _h1
;
531 sfinfo
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
532 sfinfo
.set_secdesc
.in
.sd
= sd1
;
534 status
= smb2_setinfo_file(tree
, &sfinfo
);
535 CHECK_STATUS(status
, NT_STATUS_OK
);
537 /* re-authenticate as original user again */
539 status
= smb2_session_setup_spnego(tree
->session
,
541 0 /* previous_session_id */);
542 CHECK_STATUS(status
, NT_STATUS_OK
);
544 /* re-get the security descriptor */
548 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
549 qfinfo
.query_secdesc
.in
.file
.handle
= _h1
;
550 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
552 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
553 CHECK_STATUS(status
, NT_STATUS_OK
);
559 smb2_util_close(tree
, *h1
);
562 smb2_util_unlink(tree
, fname
);
566 talloc_free(mem_ctx
);
572 * test renaming after reauth.
573 * compare security descriptors before and after rename/reauth
575 bool test_session_reauth5(struct torture_context
*tctx
, struct smb2_tree
*tree
)
578 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
582 struct smb2_handle _dh1
;
583 struct smb2_handle
*dh1
= NULL
;
584 struct smb2_handle _h1
;
585 struct smb2_handle
*h1
= NULL
;
586 struct smb2_create io1
;
589 union smb_fileinfo qfinfo
;
590 union smb_setfileinfo sfinfo
;
591 struct cli_credentials
*anon_creds
= NULL
;
592 uint32_t secinfo_flags
= SECINFO_OWNER
595 | SECINFO_PROTECTED_DACL
596 | SECINFO_UNPROTECTED_DACL
;
597 struct security_descriptor
*f_sd1
;
598 struct security_descriptor
*d_sd1
= NULL
;
599 struct security_ace ace
;
600 struct dom_sid
*extra_sid
;
602 /* Add some random component to the file name. */
603 snprintf(dname
, 256, "session_reauth5_%s.d",
604 generate_random_str(tctx
, 8));
605 snprintf(fname
, 256, "%s\\file.dat", dname
);
607 ok
= smb2_util_setup_dir(tctx
, tree
, dname
);
610 status
= torture_smb2_testdir(tree
, dname
, &_dh1
);
611 CHECK_STATUS(status
, NT_STATUS_OK
);
614 smb2_oplock_create_share(&io1
, fname
,
615 smb2_util_share_access(""),
616 smb2_util_oplock_level("b"));
618 status
= smb2_create(tree
, mem_ctx
, &io1
);
619 CHECK_STATUS(status
, NT_STATUS_OK
);
620 _h1
= io1
.out
.file
.handle
;
622 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
623 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
625 /* get the security descriptor */
629 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
630 qfinfo
.query_secdesc
.in
.file
.handle
= _h1
;
631 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
633 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
634 CHECK_STATUS(status
, NT_STATUS_OK
);
636 f_sd1
= qfinfo
.query_secdesc
.out
.sd
;
638 /* re-authenticate as anonymous */
640 anon_creds
= cli_credentials_init_anon(mem_ctx
);
641 torture_assert(tctx
, (anon_creds
!= NULL
), "talloc error");
643 status
= smb2_session_setup_spnego(tree
->session
,
645 0 /* previous_session_id */);
646 CHECK_STATUS(status
, NT_STATUS_OK
);
648 /* try to rename the file: fails */
650 snprintf(fname2
, 256, "%s\\file2.dat", dname
);
652 smb2_util_unlink(tree
, fname2
);
655 sfinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
656 sfinfo
.rename_information
.in
.file
.handle
= _h1
;
657 sfinfo
.rename_information
.in
.overwrite
= true;
658 sfinfo
.rename_information
.in
.new_name
= fname2
;
660 status
= smb2_setinfo_file(tree
, &sfinfo
);
661 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
663 /* re-authenticate as original user again */
665 status
= smb2_session_setup_spnego(tree
->session
,
667 0 /* previous_session_id */);
668 CHECK_STATUS(status
, NT_STATUS_OK
);
670 /* give full access on the file to anonymous */
672 extra_sid
= dom_sid_parse_talloc(tctx
, SID_NT_ANONYMOUS
);
675 ace
.type
= SEC_ACE_TYPE_ACCESS_ALLOWED
;
677 ace
.access_mask
= SEC_RIGHTS_FILE_ALL
;
678 ace
.trustee
= *extra_sid
;
680 status
= security_descriptor_dacl_add(f_sd1
, &ace
);
681 CHECK_STATUS(status
, NT_STATUS_OK
);
684 sfinfo
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
685 sfinfo
.set_secdesc
.in
.file
.handle
= _h1
;
686 sfinfo
.set_secdesc
.in
.secinfo_flags
= secinfo_flags
;
687 sfinfo
.set_secdesc
.in
.sd
= f_sd1
;
689 status
= smb2_setinfo_file(tree
, &sfinfo
);
690 CHECK_STATUS(status
, NT_STATUS_OK
);
692 /* re-get the security descriptor */
696 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
697 qfinfo
.query_secdesc
.in
.file
.handle
= _h1
;
698 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
700 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
701 CHECK_STATUS(status
, NT_STATUS_OK
);
703 /* re-authenticate as anonymous - again */
705 anon_creds
= cli_credentials_init_anon(mem_ctx
);
706 torture_assert(tctx
, (anon_creds
!= NULL
), "talloc error");
708 status
= smb2_session_setup_spnego(tree
->session
,
710 0 /* previous_session_id */);
711 CHECK_STATUS(status
, NT_STATUS_OK
);
713 /* try to rename the file: fails */
716 sfinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
717 sfinfo
.rename_information
.in
.file
.handle
= _h1
;
718 sfinfo
.rename_information
.in
.overwrite
= true;
719 sfinfo
.rename_information
.in
.new_name
= fname2
;
721 status
= smb2_setinfo_file(tree
, &sfinfo
);
722 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
724 /* give full access on the parent dir to anonymous */
728 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
729 qfinfo
.query_secdesc
.in
.file
.handle
= _dh1
;
730 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
732 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
733 CHECK_STATUS(status
, NT_STATUS_OK
);
735 d_sd1
= qfinfo
.query_secdesc
.out
.sd
;
738 ace
.type
= SEC_ACE_TYPE_ACCESS_ALLOWED
;
740 ace
.access_mask
= SEC_RIGHTS_FILE_ALL
;
741 ace
.trustee
= *extra_sid
;
743 status
= security_descriptor_dacl_add(d_sd1
, &ace
);
744 CHECK_STATUS(status
, NT_STATUS_OK
);
747 sfinfo
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
748 sfinfo
.set_secdesc
.in
.file
.handle
= _dh1
;
749 sfinfo
.set_secdesc
.in
.secinfo_flags
= secinfo_flags
;
750 sfinfo
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
751 sfinfo
.set_secdesc
.in
.sd
= d_sd1
;
753 status
= smb2_setinfo_file(tree
, &sfinfo
);
754 CHECK_STATUS(status
, NT_STATUS_OK
);
758 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
759 qfinfo
.query_secdesc
.in
.file
.handle
= _dh1
;
760 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
762 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
763 CHECK_STATUS(status
, NT_STATUS_OK
);
765 smb2_util_close(tree
, _dh1
);
768 /* try to rename the file: still 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 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
779 /* re-authenticate as original user - again */
781 status
= smb2_session_setup_spnego(tree
->session
,
783 0 /* previous_session_id */);
784 CHECK_STATUS(status
, NT_STATUS_OK
);
786 /* rename the file - for verification that it works */
789 sfinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
790 sfinfo
.rename_information
.in
.file
.handle
= _h1
;
791 sfinfo
.rename_information
.in
.overwrite
= true;
792 sfinfo
.rename_information
.in
.new_name
= fname2
;
794 status
= smb2_setinfo_file(tree
, &sfinfo
);
795 CHECK_STATUS(status
, NT_STATUS_OK
);
797 /* closs the file, check it is gone and reopen under the new name */
799 smb2_util_close(tree
, _h1
);
803 smb2_generic_create_share(&io1
,
804 NULL
/* lease */, false /* dir */,
807 smb2_util_share_access(""),
808 smb2_util_oplock_level("b"),
809 0 /* leasekey */, 0 /* leasestate */);
811 status
= smb2_create(tree
, mem_ctx
, &io1
);
812 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
816 smb2_generic_create_share(&io1
,
817 NULL
/* lease */, false /* dir */,
820 smb2_util_share_access(""),
821 smb2_util_oplock_level("b"),
822 0 /* leasekey */, 0 /* leasestate */);
824 status
= smb2_create(tree
, mem_ctx
, &io1
);
825 CHECK_STATUS(status
, NT_STATUS_OK
);
826 _h1
= io1
.out
.file
.handle
;
828 CHECK_CREATED(&io1
, EXISTED
, FILE_ATTRIBUTE_ARCHIVE
);
829 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
831 /* try to access the file via the old handle */
835 qfinfo
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
836 qfinfo
.query_secdesc
.in
.file
.handle
= _h1
;
837 qfinfo
.query_secdesc
.in
.secinfo_flags
= secinfo_flags
;
839 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
840 CHECK_STATUS(status
, NT_STATUS_OK
);
844 smb2_util_close(tree
, *dh1
);
847 smb2_util_close(tree
, *h1
);
850 smb2_deltree(tree
, dname
);
854 talloc_free(mem_ctx
);
860 * do reauth with wrong credentials,
861 * hence triggering the error path in reauth.
862 * The invalid reauth deletes the session.
864 bool test_session_reauth6(struct torture_context
*tctx
, struct smb2_tree
*tree
)
867 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
869 struct smb2_handle _h1
;
870 struct smb2_handle
*h1
= NULL
;
871 struct smb2_create io1
;
873 char *corrupted_password
;
874 struct cli_credentials
*broken_creds
;
878 enum credentials_use_kerberos krb_state
;
880 krb_state
= cli_credentials_get_kerberos_state(cmdline_credentials
);
881 if (krb_state
== CRED_MUST_USE_KERBEROS
) {
883 "Can't test failing session setup with kerberos.");
886 encrypted
= smb2cli_tcon_is_encryption_on(tree
->smbXcli
);
888 /* Add some random component to the file name. */
889 snprintf(fname
, 256, "session_reauth1_%s.dat",
890 generate_random_str(tctx
, 8));
892 smb2_util_unlink(tree
, fname
);
894 smb2_oplock_create_share(&io1
, fname
,
895 smb2_util_share_access(""),
896 smb2_util_oplock_level("b"));
897 io1
.in
.create_options
|= NTCREATEX_OPTIONS_DELETE_ON_CLOSE
;
899 status
= smb2_create(tree
, mem_ctx
, &io1
);
900 CHECK_STATUS(status
, NT_STATUS_OK
);
901 _h1
= io1
.out
.file
.handle
;
903 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
904 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
907 * reauthentication with invalid credentials:
910 broken_creds
= cli_credentials_shallow_copy(mem_ctx
,
911 cmdline_credentials
);
912 torture_assert(tctx
, (broken_creds
!= NULL
), "talloc error");
914 corrupted_password
= talloc_asprintf(mem_ctx
, "%s%s",
915 cli_credentials_get_password(broken_creds
),
917 torture_assert(tctx
, (corrupted_password
!= NULL
), "talloc error");
919 ok
= cli_credentials_set_password(broken_creds
, corrupted_password
,
923 status
= smb2_session_setup_spnego(tree
->session
,
925 0 /* previous_session_id */);
926 CHECK_STATUS(status
, NT_STATUS_LOGON_FAILURE
);
928 torture_comment(tctx
, "did failed reauth\n");
930 * now verify that the invalid session reauth has closed our session
934 expected
= NT_STATUS_CONNECTION_DISCONNECTED
;
936 expected
= NT_STATUS_USER_SESSION_DELETED
;
939 smb2_oplock_create_share(&io1
, fname
,
940 smb2_util_share_access(""),
941 smb2_util_oplock_level("b"));
943 status
= smb2_create(tree
, mem_ctx
, &io1
);
944 CHECK_STATUS(status
, expected
);
948 smb2_util_close(tree
, *h1
);
951 smb2_util_unlink(tree
, fname
);
955 talloc_free(mem_ctx
);
961 static bool test_session_expire1(struct torture_context
*tctx
)
965 struct smbcli_options options
;
966 const char *host
= torture_setting_string(tctx
, "host", NULL
);
967 const char *share
= torture_setting_string(tctx
, "share", NULL
);
968 struct cli_credentials
*credentials
= cmdline_credentials
;
969 struct smb2_tree
*tree
= NULL
;
970 enum credentials_use_kerberos use_kerberos
;
972 struct smb2_handle _h1
;
973 struct smb2_handle
*h1
= NULL
;
974 struct smb2_create io1
;
975 union smb_fileinfo qfinfo
;
978 use_kerberos
= cli_credentials_get_kerberos_state(credentials
);
979 if (use_kerberos
!= CRED_MUST_USE_KERBEROS
) {
980 torture_warning(tctx
, "smb2.session.expire1 requires -k yes!");
981 torture_skip(tctx
, "smb2.session.expire1 requires -k yes!");
984 torture_assert_int_equal(tctx
, use_kerberos
, CRED_MUST_USE_KERBEROS
,
985 "please use -k yes");
987 lpcfg_set_option(tctx
->lp_ctx
, "gensec_gssapi:requested_life_time=4");
989 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
991 status
= smb2_connect(tctx
,
993 lpcfg_smb_ports(tctx
->lp_ctx
),
995 lpcfg_resolve_context(tctx
->lp_ctx
),
1000 lpcfg_socket_options(tctx
->lp_ctx
),
1001 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)
1003 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1004 "smb2_connect failed");
1006 /* Add some random component to the file name. */
1007 snprintf(fname
, 256, "session_expire1_%s.dat",
1008 generate_random_str(tctx
, 8));
1010 smb2_util_unlink(tree
, fname
);
1012 smb2_oplock_create_share(&io1
, fname
,
1013 smb2_util_share_access(""),
1014 smb2_util_oplock_level("b"));
1015 io1
.in
.create_options
|= NTCREATEX_OPTIONS_DELETE_ON_CLOSE
;
1017 status
= smb2_create(tree
, tctx
, &io1
);
1018 CHECK_STATUS(status
, NT_STATUS_OK
);
1019 _h1
= io1
.out
.file
.handle
;
1021 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
1022 CHECK_VAL(io1
.out
.oplock_level
, smb2_util_oplock_level("b"));
1024 /* get the security descriptor */
1026 ZERO_STRUCT(qfinfo
);
1028 qfinfo
.access_information
.level
= RAW_FILEINFO_ACCESS_INFORMATION
;
1029 qfinfo
.access_information
.in
.file
.handle
= _h1
;
1031 for (i
=0; i
< 2; i
++) {
1032 torture_comment(tctx
, "query info => OK\n");
1034 ZERO_STRUCT(qfinfo
.access_information
.out
);
1035 status
= smb2_getinfo_file(tree
, tctx
, &qfinfo
);
1036 CHECK_STATUS(status
, NT_STATUS_OK
);
1038 torture_comment(tctx
, "sleep 5 seconds\n");
1041 torture_comment(tctx
, "query info => EXPIRED\n");
1042 ZERO_STRUCT(qfinfo
.access_information
.out
);
1043 status
= smb2_getinfo_file(tree
, tctx
, &qfinfo
);
1044 CHECK_STATUS(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
);
1047 * the krb5 library may not handle expired creds
1048 * well, lets start with an empty ccache.
1050 cli_credentials_invalidate_ccache(credentials
, CRED_SPECIFIED
);
1052 torture_comment(tctx
, "reauth => OK\n");
1053 status
= smb2_session_setup_spnego(tree
->session
,
1055 0 /* previous_session_id */);
1056 CHECK_STATUS(status
, NT_STATUS_OK
);
1059 ZERO_STRUCT(qfinfo
.access_information
.out
);
1060 status
= smb2_getinfo_file(tree
, tctx
, &qfinfo
);
1061 CHECK_STATUS(status
, NT_STATUS_OK
);
1066 smb2_util_close(tree
, *h1
);
1070 lpcfg_set_option(tctx
->lp_ctx
, "gensec_gssapi:requested_life_time=0");
1074 struct torture_suite
*torture_smb2_session_init(void)
1076 struct torture_suite
*suite
=
1077 torture_suite_create(talloc_autofree_context(), "session");
1079 torture_suite_add_1smb2_test(suite
, "reconnect1", test_session_reconnect1
);
1080 torture_suite_add_1smb2_test(suite
, "reconnect2", test_session_reconnect2
);
1081 torture_suite_add_1smb2_test(suite
, "reauth1", test_session_reauth1
);
1082 torture_suite_add_1smb2_test(suite
, "reauth2", test_session_reauth2
);
1083 torture_suite_add_1smb2_test(suite
, "reauth3", test_session_reauth3
);
1084 torture_suite_add_1smb2_test(suite
, "reauth4", test_session_reauth4
);
1085 torture_suite_add_1smb2_test(suite
, "reauth5", test_session_reauth5
);
1086 torture_suite_add_1smb2_test(suite
, "reauth6", test_session_reauth6
);
1087 torture_suite_add_simple_test(suite
, "expire1", test_session_expire1
);
1089 suite
->description
= talloc_strdup(suite
, "SMB2-SESSION tests");