s4:torture/smb2: add smb2.session.bind1
[Samba.git] / source4 / torture / smb2 / session.c
blob3a4b3bd80d85aec635c4373f98838982ee29db45
1 /*
2 Unix SMB/CIFS implementation.
4 test suite for SMB2 session setups
6 Copyright (C) Michael Adam 2012
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25 #include "torture/torture.h"
26 #include "torture/smb2/proto.h"
27 #include "../libcli/smb/smbXcli_base.h"
28 #include "lib/cmdline/popt_common.h"
29 #include "auth/credentials/credentials.h"
30 #include "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); \
38 ret = false; \
39 }} while (0)
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)); \
45 ret = false; \
46 goto done; \
47 }} while (0)
49 #define CHECK_CREATED(__io, __created, __attribute) \
50 do { \
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); \
56 } while(0)
59 /**
60 * basic test for doing a session reconnect
62 bool test_session_reconnect1(struct torture_context *tctx, struct smb2_tree *tree)
64 NTSTATUS status;
65 TALLOC_CTX *mem_ctx = talloc_new(tctx);
66 char fname[256];
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;
73 bool ret = true;
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;
90 h1 = &_h1;
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,
99 &tree2))
101 torture_warning(tctx, "session reconnect failed\n");
102 ret = false;
103 goto done;
106 /* try to access the file via the old handle */
108 ZERO_STRUCT(qfinfo);
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);
113 h1 = NULL;
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;
124 h2 = &_h2;
126 done:
127 if (h1 != NULL) {
128 smb2_util_close(tree, *h1);
130 if (h2 != NULL) {
131 smb2_util_close(tree2, *h2);
134 smb2_util_unlink(tree2, fname);
136 talloc_free(tree);
137 talloc_free(tree2);
139 talloc_free(mem_ctx);
141 return ret;
145 * basic test for doing a session reconnect on one connection
147 bool test_session_reconnect2(struct torture_context *tctx, struct smb2_tree *tree)
149 NTSTATUS status;
150 TALLOC_CTX *mem_ctx = talloc_new(tctx);
151 char fname[256];
152 struct smb2_handle _h1;
153 struct smb2_handle *h1 = NULL;
154 struct smb2_create io1;
155 uint64_t previous_session_id;
156 bool ret = true;
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;
174 h1 = &_h1;
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 */
187 ZERO_STRUCT(qfinfo);
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);
192 h1 = NULL;
194 done:
195 if (h1 != NULL) {
196 smb2_util_close(tree, *h1);
199 talloc_free(tree);
200 talloc_free(session2);
202 talloc_free(mem_ctx);
204 return ret;
207 bool test_session_reauth1(struct torture_context *tctx, struct smb2_tree *tree)
209 NTSTATUS status;
210 TALLOC_CTX *mem_ctx = talloc_new(tctx);
211 char fname[256];
212 struct smb2_handle _h1;
213 struct smb2_handle *h1 = NULL;
214 struct smb2_create io1;
215 bool ret = true;
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;
231 h1 = &_h1;
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,
236 cmdline_credentials,
237 0 /* previous_session_id */);
238 CHECK_STATUS(status, NT_STATUS_OK);
240 /* try to access the file via the old handle */
242 ZERO_STRUCT(qfinfo);
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,
249 cmdline_credentials,
250 0 /* previous_session_id */);
251 CHECK_STATUS(status, NT_STATUS_OK);
253 /* try to access the file via the old handle */
255 ZERO_STRUCT(qfinfo);
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);
261 done:
262 if (h1 != NULL) {
263 smb2_util_close(tree, *h1);
266 smb2_util_unlink(tree, fname);
268 talloc_free(tree);
270 talloc_free(mem_ctx);
272 return ret;
275 bool test_session_reauth2(struct torture_context *tctx, struct smb2_tree *tree)
277 NTSTATUS status;
278 TALLOC_CTX *mem_ctx = talloc_new(tctx);
279 char fname[256];
280 struct smb2_handle _h1;
281 struct smb2_handle *h1 = NULL;
282 struct smb2_create io1;
283 bool ret = true;
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;
300 h1 = &_h1;
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,
310 anon_creds,
311 0 /* previous_session_id */);
312 CHECK_STATUS(status, NT_STATUS_OK);
314 /* try to access the file via the old handle */
316 ZERO_STRUCT(qfinfo);
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,
325 cmdline_credentials,
326 0 /* previous_session_id */);
327 CHECK_STATUS(status, NT_STATUS_OK);
329 /* try to access the file via the old handle */
331 ZERO_STRUCT(qfinfo);
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);
337 done:
338 if (h1 != NULL) {
339 smb2_util_close(tree, *h1);
342 smb2_util_unlink(tree, fname);
344 talloc_free(tree);
346 talloc_free(mem_ctx);
348 return ret;
352 * test getting security descriptor after reauth
354 bool test_session_reauth3(struct torture_context *tctx, struct smb2_tree *tree)
356 NTSTATUS status;
357 TALLOC_CTX *mem_ctx = talloc_new(tctx);
358 char fname[256];
359 struct smb2_handle _h1;
360 struct smb2_handle *h1 = NULL;
361 struct smb2_create io1;
362 bool ret = true;
363 union smb_fileinfo qfinfo;
364 struct cli_credentials *anon_creds = NULL;
365 uint32_t secinfo_flags = SECINFO_OWNER
366 | SECINFO_GROUP
367 | SECINFO_DACL
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;
384 h1 = &_h1;
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 */
390 ZERO_STRUCT(qfinfo);
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,
404 anon_creds,
405 0 /* previous_session_id */);
406 CHECK_STATUS(status, NT_STATUS_OK);
408 /* try to access the file via the old handle */
410 ZERO_STRUCT(qfinfo);
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,
422 cmdline_credentials,
423 0 /* previous_session_id */);
424 CHECK_STATUS(status, NT_STATUS_OK);
426 /* try to access the file via the old handle */
428 ZERO_STRUCT(qfinfo);
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);
437 done:
438 if (h1 != NULL) {
439 smb2_util_close(tree, *h1);
442 smb2_util_unlink(tree, fname);
444 talloc_free(tree);
446 talloc_free(mem_ctx);
448 return ret;
452 * test setting security descriptor after reauth.
454 bool test_session_reauth4(struct torture_context *tctx, struct smb2_tree *tree)
456 NTSTATUS status;
457 TALLOC_CTX *mem_ctx = talloc_new(tctx);
458 char fname[256];
459 struct smb2_handle _h1;
460 struct smb2_handle *h1 = NULL;
461 struct smb2_create io1;
462 bool ret = true;
463 union smb_fileinfo qfinfo;
464 union smb_setfileinfo sfinfo;
465 struct cli_credentials *anon_creds = NULL;
466 uint32_t secinfo_flags = SECINFO_OWNER
467 | SECINFO_GROUP
468 | SECINFO_DACL
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;
488 h1 = &_h1;
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 */
494 ZERO_STRUCT(qfinfo);
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,
511 anon_creds,
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);
519 ZERO_STRUCT(ace);
520 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
521 ace.flags = 0;
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);
528 ZERO_STRUCT(sfinfo);
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,
540 cmdline_credentials,
541 0 /* previous_session_id */);
542 CHECK_STATUS(status, NT_STATUS_OK);
544 /* re-get the security descriptor */
546 ZERO_STRUCT(qfinfo);
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);
555 ret = true;
557 done:
558 if (h1 != NULL) {
559 smb2_util_close(tree, *h1);
562 smb2_util_unlink(tree, fname);
564 talloc_free(tree);
566 talloc_free(mem_ctx);
568 return ret;
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)
577 NTSTATUS status;
578 TALLOC_CTX *mem_ctx = talloc_new(tctx);
579 char dname[256];
580 char fname[256];
581 char fname2[256];
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;
587 bool ret = true;
588 bool ok;
589 union smb_fileinfo qfinfo;
590 union smb_setfileinfo sfinfo;
591 struct cli_credentials *anon_creds = NULL;
592 uint32_t secinfo_flags = SECINFO_OWNER
593 | SECINFO_GROUP
594 | SECINFO_DACL
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);
608 CHECK_VAL(ok, true);
610 status = torture_smb2_testdir(tree, dname, &_dh1);
611 CHECK_STATUS(status, NT_STATUS_OK);
612 dh1 = &_dh1;
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;
621 h1 = &_h1;
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 */
627 ZERO_STRUCT(qfinfo);
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,
644 anon_creds,
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);
654 ZERO_STRUCT(sfinfo);
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,
666 cmdline_credentials,
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);
674 ZERO_STRUCT(ace);
675 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
676 ace.flags = 0;
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);
683 ZERO_STRUCT(sfinfo);
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 */
694 ZERO_STRUCT(qfinfo);
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,
709 anon_creds,
710 0 /* previous_session_id */);
711 CHECK_STATUS(status, NT_STATUS_OK);
713 /* try to rename the file: fails */
715 ZERO_STRUCT(sfinfo);
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 */
726 ZERO_STRUCT(qfinfo);
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;
737 ZERO_STRUCT(ace);
738 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
739 ace.flags = 0;
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);
746 ZERO_STRUCT(sfinfo);
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);
756 ZERO_STRUCT(qfinfo);
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);
766 dh1 = NULL;
768 /* try to rename the file: still fails */
770 ZERO_STRUCT(sfinfo);
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,
782 cmdline_credentials,
783 0 /* previous_session_id */);
784 CHECK_STATUS(status, NT_STATUS_OK);
786 /* rename the file - for verification that it works */
788 ZERO_STRUCT(sfinfo);
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);
801 ZERO_STRUCT(io1);
803 smb2_generic_create_share(&io1,
804 NULL /* lease */, false /* dir */,
805 fname,
806 NTCREATEX_DISP_OPEN,
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);
814 ZERO_STRUCT(io1);
816 smb2_generic_create_share(&io1,
817 NULL /* lease */, false /* dir */,
818 fname2,
819 NTCREATEX_DISP_OPEN,
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;
827 h1 = &_h1;
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 */
833 ZERO_STRUCT(qfinfo);
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);
842 done:
843 if (dh1 != NULL) {
844 smb2_util_close(tree, *dh1);
846 if (h1 != NULL) {
847 smb2_util_close(tree, *h1);
850 smb2_deltree(tree, dname);
852 talloc_free(tree);
854 talloc_free(mem_ctx);
856 return ret;
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)
866 NTSTATUS status;
867 TALLOC_CTX *mem_ctx = talloc_new(tctx);
868 char fname[256];
869 struct smb2_handle _h1;
870 struct smb2_handle *h1 = NULL;
871 struct smb2_create io1;
872 bool ret = true;
873 char *corrupted_password;
874 struct cli_credentials *broken_creds;
875 bool ok;
876 bool encrypted;
877 NTSTATUS expected;
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) {
882 torture_skip(tctx,
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;
902 h1 = &_h1;
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),
916 "corrupt");
917 torture_assert(tctx, (corrupted_password != NULL), "talloc error");
919 ok = cli_credentials_set_password(broken_creds, corrupted_password,
920 CRED_SPECIFIED);
921 CHECK_VAL(ok, true);
923 status = smb2_session_setup_spnego(tree->session,
924 broken_creds,
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
933 if (encrypted) {
934 expected = NT_STATUS_CONNECTION_DISCONNECTED;
935 } else {
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);
946 done:
947 if (h1 != NULL) {
948 smb2_util_close(tree, *h1);
951 smb2_util_unlink(tree, fname);
953 talloc_free(tree);
955 talloc_free(mem_ctx);
957 return ret;
961 static bool test_session_expire1(struct torture_context *tctx)
963 NTSTATUS status;
964 bool ret = false;
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;
971 char fname[256];
972 struct smb2_handle _h1;
973 struct smb2_handle *h1 = NULL;
974 struct smb2_create io1;
975 union smb_fileinfo qfinfo;
976 size_t i;
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,
992 host,
993 lpcfg_smb_ports(tctx->lp_ctx),
994 share,
995 lpcfg_resolve_context(tctx->lp_ctx),
996 credentials,
997 &tree,
998 tctx->ev,
999 &options,
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;
1020 h1 = &_h1;
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");
1039 smb_msleep(5*1000);
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,
1054 credentials,
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);
1063 ret = true;
1064 done:
1065 if (h1 != NULL) {
1066 smb2_util_close(tree, *h1);
1069 talloc_free(tree);
1070 lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
1071 return ret;
1074 bool test_session_bind1(struct torture_context *tctx, struct smb2_tree *tree1)
1076 const char *host = torture_setting_string(tctx, "host", NULL);
1077 const char *share = torture_setting_string(tctx, "share", NULL);
1078 struct cli_credentials *credentials = cmdline_credentials;
1079 NTSTATUS status;
1080 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1081 char fname[256];
1082 struct smb2_handle _h1;
1083 struct smb2_handle *h1 = NULL;
1084 struct smb2_create io1;
1085 union smb_fileinfo qfinfo;
1086 bool ret = false;
1087 struct smb2_tree *tree2 = NULL;
1088 struct smb2_transport *transport1 = tree1->session->transport;
1089 struct smb2_transport *transport2 = NULL;
1090 struct smb2_session *session1_1 = tree1->session;
1091 struct smb2_session *session1_2 = NULL;
1092 struct smb2_session *session2_1 = NULL;
1093 struct smb2_session *session2_2 = NULL;
1094 uint32_t caps;
1096 caps = smb2cli_conn_server_capabilities(transport1->conn);
1097 if (!(caps & SMB2_CAP_MULTI_CHANNEL)) {
1098 torture_skip(tctx, "server doesn't support SMB2_CAP_MULTI_CHANNEL\n");
1101 /* Add some random component to the file name. */
1102 snprintf(fname, 256, "session_bind1_%s.dat",
1103 generate_random_str(tctx, 8));
1105 smb2_util_unlink(tree1, fname);
1107 smb2_oplock_create_share(&io1, fname,
1108 smb2_util_share_access(""),
1109 smb2_util_oplock_level("b"));
1111 status = smb2_create(tree1, mem_ctx, &io1);
1112 CHECK_STATUS(status, NT_STATUS_OK);
1113 _h1 = io1.out.file.handle;
1114 h1 = &_h1;
1115 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1116 CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
1118 status = smb2_connect(tctx,
1119 host,
1120 lpcfg_smb_ports(tctx->lp_ctx),
1121 share,
1122 lpcfg_resolve_context(tctx->lp_ctx),
1123 credentials,
1124 &tree2,
1125 tctx->ev,
1126 &transport1->options,
1127 lpcfg_socket_options(tctx->lp_ctx),
1128 lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1130 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1131 "smb2_connect failed");
1132 session2_2 = tree2->session;
1133 transport2 = tree2->session->transport;
1136 * Now bind the 2nd transport connection to the 1st session
1138 session1_2 = smb2_session_channel(transport2,
1139 lpcfg_gensec_settings(tctx, tctx->lp_ctx),
1140 tree2,
1141 session1_1);
1142 torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
1144 status = smb2_session_setup_spnego(session1_2,
1145 cmdline_credentials,
1146 0 /* previous_session_id */);
1147 CHECK_STATUS(status, NT_STATUS_OK);
1149 /* use the 1st connection, 1st session */
1150 ZERO_STRUCT(qfinfo);
1151 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
1152 qfinfo.generic.in.file.handle = _h1;
1153 tree1->session = session1_1;
1154 status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
1155 CHECK_STATUS(status, NT_STATUS_OK);
1157 /* use the 2nd connection, 1st session */
1158 ZERO_STRUCT(qfinfo);
1159 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
1160 qfinfo.generic.in.file.handle = _h1;
1161 tree1->session = session1_2;
1162 status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
1163 CHECK_STATUS(status, NT_STATUS_OK);
1165 tree1->session = session1_1;
1166 smb2_util_close(tree1, *h1);
1167 h1 = NULL;
1170 * Now bind the 1st transport connection to the 2nd session
1172 session2_1 = smb2_session_channel(transport1,
1173 lpcfg_gensec_settings(tctx, tctx->lp_ctx),
1174 tree1,
1175 session2_2);
1176 torture_assert(tctx, session2_1 != NULL, "smb2_session_channel failed");
1178 status = smb2_session_setup_spnego(session2_1,
1179 cmdline_credentials,
1180 0 /* previous_session_id */);
1181 CHECK_STATUS(status, NT_STATUS_OK);
1183 tree2->session = session2_1;
1184 status = smb2_util_unlink(tree2, fname);
1185 CHECK_STATUS(status, NT_STATUS_OK);
1187 ret = true;
1188 done:
1189 talloc_free(tree2);
1190 tree1->session = session1_1;
1192 if (h1 != NULL) {
1193 smb2_util_close(tree1, *h1);
1196 smb2_util_unlink(tree1, fname);
1198 talloc_free(tree1);
1200 talloc_free(mem_ctx);
1202 return ret;
1205 struct torture_suite *torture_smb2_session_init(void)
1207 struct torture_suite *suite =
1208 torture_suite_create(talloc_autofree_context(), "session");
1210 torture_suite_add_1smb2_test(suite, "reconnect1", test_session_reconnect1);
1211 torture_suite_add_1smb2_test(suite, "reconnect2", test_session_reconnect2);
1212 torture_suite_add_1smb2_test(suite, "reauth1", test_session_reauth1);
1213 torture_suite_add_1smb2_test(suite, "reauth2", test_session_reauth2);
1214 torture_suite_add_1smb2_test(suite, "reauth3", test_session_reauth3);
1215 torture_suite_add_1smb2_test(suite, "reauth4", test_session_reauth4);
1216 torture_suite_add_1smb2_test(suite, "reauth5", test_session_reauth5);
1217 torture_suite_add_1smb2_test(suite, "reauth6", test_session_reauth6);
1218 torture_suite_add_simple_test(suite, "expire1", test_session_expire1);
1219 torture_suite_add_1smb2_test(suite, "bind1", test_session_bind1);
1221 suite->description = talloc_strdup(suite, "SMB2-SESSION tests");
1223 return suite;