libcli/security: implement object_in_list()
[Samba/gebeck_regimport.git] / source4 / torture / smb2 / session.c
blob9592b5ef8dcf4d30fcb390c8217a8a644dceec7c
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, &tree2)) {
98 torture_warning(tctx, "session reconnect failed\n");
99 ret = false;
100 goto done;
103 /* try to access the file via the old handle */
105 ZERO_STRUCT(qfinfo);
106 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
107 qfinfo.generic.in.file.handle = _h1;
108 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
109 CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
110 h1 = NULL;
112 smb2_oplock_create_share(&io2, fname,
113 smb2_util_share_access(""),
114 smb2_util_oplock_level("b"));
116 status = smb2_create(tree2, mem_ctx, &io2);
117 CHECK_STATUS(status, NT_STATUS_OK);
118 CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
119 CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("b"));
120 _h2 = io2.out.file.handle;
121 h2 = &_h2;
123 done:
124 if (h1 != NULL) {
125 smb2_util_close(tree, *h1);
127 if (h2 != NULL) {
128 smb2_util_close(tree2, *h2);
131 smb2_util_unlink(tree2, fname);
133 talloc_free(tree);
134 talloc_free(tree2);
136 talloc_free(mem_ctx);
138 return ret;
142 * basic test for doing a session reconnect on one connection
144 bool test_session_reconnect2(struct torture_context *tctx, struct smb2_tree *tree)
146 NTSTATUS status;
147 TALLOC_CTX *mem_ctx = talloc_new(tctx);
148 char fname[256];
149 struct smb2_handle _h1;
150 struct smb2_handle *h1 = NULL;
151 struct smb2_create io1;
152 uint64_t previous_session_id;
153 bool ret = true;
154 struct smb2_session *session2;
155 union smb_fileinfo qfinfo;
157 /* Add some random component to the file name. */
158 snprintf(fname, 256, "session_reconnect_%s.dat",
159 generate_random_str(tctx, 8));
161 smb2_util_unlink(tree, fname);
163 smb2_oplock_create_share(&io1, fname,
164 smb2_util_share_access(""),
165 smb2_util_oplock_level("b"));
166 io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
168 status = smb2_create(tree, mem_ctx, &io1);
169 CHECK_STATUS(status, NT_STATUS_OK);
170 _h1 = io1.out.file.handle;
171 h1 = &_h1;
172 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
173 CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
175 /* disconnect, reconnect and then do durable reopen */
176 previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
178 torture_assert(tctx, torture_smb2_session_setup(tctx, tree->session->transport,
179 previous_session_id, tctx, &session2),
180 "session reconnect (on the same connection) failed");
182 /* try to access the file via the old handle */
184 ZERO_STRUCT(qfinfo);
185 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
186 qfinfo.generic.in.file.handle = _h1;
187 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
188 CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
189 h1 = NULL;
191 done:
192 if (h1 != NULL) {
193 smb2_util_close(tree, *h1);
196 talloc_free(tree);
197 talloc_free(session2);
199 talloc_free(mem_ctx);
201 return ret;
204 bool test_session_reauth1(struct torture_context *tctx, struct smb2_tree *tree)
206 NTSTATUS status;
207 TALLOC_CTX *mem_ctx = talloc_new(tctx);
208 char fname[256];
209 struct smb2_handle _h1;
210 struct smb2_handle *h1 = NULL;
211 struct smb2_create io1;
212 bool ret = true;
213 union smb_fileinfo qfinfo;
215 /* Add some random component to the file name. */
216 snprintf(fname, 256, "session_reauth1_%s.dat",
217 generate_random_str(tctx, 8));
219 smb2_util_unlink(tree, fname);
221 smb2_oplock_create_share(&io1, fname,
222 smb2_util_share_access(""),
223 smb2_util_oplock_level("b"));
225 status = smb2_create(tree, mem_ctx, &io1);
226 CHECK_STATUS(status, NT_STATUS_OK);
227 _h1 = io1.out.file.handle;
228 h1 = &_h1;
229 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
230 CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
232 status = smb2_session_setup_spnego(tree->session,
233 cmdline_credentials,
234 0 /* previous_session_id */);
235 CHECK_STATUS(status, NT_STATUS_OK);
237 /* try to access the file via the old handle */
239 ZERO_STRUCT(qfinfo);
240 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
241 qfinfo.generic.in.file.handle = _h1;
242 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
243 CHECK_STATUS(status, NT_STATUS_OK);
245 status = smb2_session_setup_spnego(tree->session,
246 cmdline_credentials,
247 0 /* previous_session_id */);
248 CHECK_STATUS(status, NT_STATUS_OK);
250 /* try to access the file via the old handle */
252 ZERO_STRUCT(qfinfo);
253 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
254 qfinfo.generic.in.file.handle = _h1;
255 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
256 CHECK_STATUS(status, NT_STATUS_OK);
258 done:
259 if (h1 != NULL) {
260 smb2_util_close(tree, *h1);
263 smb2_util_unlink(tree, fname);
265 talloc_free(tree);
267 talloc_free(mem_ctx);
269 return ret;
272 bool test_session_reauth2(struct torture_context *tctx, struct smb2_tree *tree)
274 NTSTATUS status;
275 TALLOC_CTX *mem_ctx = talloc_new(tctx);
276 char fname[256];
277 struct smb2_handle _h1;
278 struct smb2_handle *h1 = NULL;
279 struct smb2_create io1;
280 bool ret = true;
281 union smb_fileinfo qfinfo;
282 struct cli_credentials *anon_creds = NULL;
284 /* Add some random component to the file name. */
285 snprintf(fname, 256, "session_reauth2_%s.dat",
286 generate_random_str(tctx, 8));
288 smb2_util_unlink(tree, fname);
290 smb2_oplock_create_share(&io1, fname,
291 smb2_util_share_access(""),
292 smb2_util_oplock_level("b"));
294 status = smb2_create(tree, mem_ctx, &io1);
295 CHECK_STATUS(status, NT_STATUS_OK);
296 _h1 = io1.out.file.handle;
297 h1 = &_h1;
298 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
299 CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
301 /* re-authenticate as anonymous */
303 anon_creds = cli_credentials_init_anon(mem_ctx);
304 torture_assert(tctx, (anon_creds != NULL), "talloc error");
306 status = smb2_session_setup_spnego(tree->session,
307 anon_creds,
308 0 /* previous_session_id */);
309 CHECK_STATUS(status, NT_STATUS_OK);
311 /* try to access the file via the old handle */
313 ZERO_STRUCT(qfinfo);
314 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
315 qfinfo.generic.in.file.handle = _h1;
316 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
317 CHECK_STATUS(status, NT_STATUS_OK);
319 /* re-authenticate as original user again */
321 status = smb2_session_setup_spnego(tree->session,
322 cmdline_credentials,
323 0 /* previous_session_id */);
324 CHECK_STATUS(status, NT_STATUS_OK);
326 /* try to access the file via the old handle */
328 ZERO_STRUCT(qfinfo);
329 qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
330 qfinfo.generic.in.file.handle = _h1;
331 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
332 CHECK_STATUS(status, NT_STATUS_OK);
334 done:
335 if (h1 != NULL) {
336 smb2_util_close(tree, *h1);
339 smb2_util_unlink(tree, fname);
341 talloc_free(tree);
343 talloc_free(mem_ctx);
345 return ret;
349 * test getting security descriptor after reauth
351 bool test_session_reauth3(struct torture_context *tctx, struct smb2_tree *tree)
353 NTSTATUS status;
354 TALLOC_CTX *mem_ctx = talloc_new(tctx);
355 char fname[256];
356 struct smb2_handle _h1;
357 struct smb2_handle *h1 = NULL;
358 struct smb2_create io1;
359 bool ret = true;
360 union smb_fileinfo qfinfo;
361 struct cli_credentials *anon_creds = NULL;
362 uint32_t secinfo_flags = SECINFO_OWNER
363 | SECINFO_GROUP
364 | SECINFO_DACL
365 | SECINFO_PROTECTED_DACL
366 | SECINFO_UNPROTECTED_DACL;
368 /* Add some random component to the file name. */
369 snprintf(fname, 256, "session_reauth3_%s.dat",
370 generate_random_str(tctx, 8));
372 smb2_util_unlink(tree, fname);
374 smb2_oplock_create_share(&io1, fname,
375 smb2_util_share_access(""),
376 smb2_util_oplock_level("b"));
378 status = smb2_create(tree, mem_ctx, &io1);
379 CHECK_STATUS(status, NT_STATUS_OK);
380 _h1 = io1.out.file.handle;
381 h1 = &_h1;
382 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
383 CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
385 /* get the security descriptor */
387 ZERO_STRUCT(qfinfo);
389 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
390 qfinfo.query_secdesc.in.file.handle = _h1;
391 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
393 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
394 CHECK_STATUS(status, NT_STATUS_OK);
395 /* re-authenticate as anonymous */
397 anon_creds = cli_credentials_init_anon(mem_ctx);
398 torture_assert(tctx, (anon_creds != NULL), "talloc error");
400 status = smb2_session_setup_spnego(tree->session,
401 anon_creds,
402 0 /* previous_session_id */);
403 CHECK_STATUS(status, NT_STATUS_OK);
405 /* try to access the file via the old handle */
407 ZERO_STRUCT(qfinfo);
409 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
410 qfinfo.query_secdesc.in.file.handle = _h1;
411 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
413 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
414 CHECK_STATUS(status, NT_STATUS_OK);
416 /* re-authenticate as original user again */
418 status = smb2_session_setup_spnego(tree->session,
419 cmdline_credentials,
420 0 /* previous_session_id */);
421 CHECK_STATUS(status, NT_STATUS_OK);
423 /* try to access the file via the old handle */
425 ZERO_STRUCT(qfinfo);
427 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
428 qfinfo.query_secdesc.in.file.handle = _h1;
429 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
431 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
432 CHECK_STATUS(status, NT_STATUS_OK);
434 done:
435 if (h1 != NULL) {
436 smb2_util_close(tree, *h1);
439 smb2_util_unlink(tree, fname);
441 talloc_free(tree);
443 talloc_free(mem_ctx);
445 return ret;
449 * test setting security descriptor after reauth.
451 bool test_session_reauth4(struct torture_context *tctx, struct smb2_tree *tree)
453 NTSTATUS status;
454 TALLOC_CTX *mem_ctx = talloc_new(tctx);
455 char fname[256];
456 struct smb2_handle _h1;
457 struct smb2_handle *h1 = NULL;
458 struct smb2_create io1;
459 bool ret = true;
460 union smb_fileinfo qfinfo;
461 union smb_setfileinfo sfinfo;
462 struct cli_credentials *anon_creds = NULL;
463 uint32_t secinfo_flags = SECINFO_OWNER
464 | SECINFO_GROUP
465 | SECINFO_DACL
466 | SECINFO_PROTECTED_DACL
467 | SECINFO_UNPROTECTED_DACL;
468 struct security_descriptor *sd1;
469 struct security_ace ace;
470 struct dom_sid *extra_sid;
472 /* Add some random component to the file name. */
473 snprintf(fname, 256, "session_reauth4_%s.dat",
474 generate_random_str(tctx, 8));
476 smb2_util_unlink(tree, fname);
478 smb2_oplock_create_share(&io1, fname,
479 smb2_util_share_access(""),
480 smb2_util_oplock_level("b"));
482 status = smb2_create(tree, mem_ctx, &io1);
483 CHECK_STATUS(status, NT_STATUS_OK);
484 _h1 = io1.out.file.handle;
485 h1 = &_h1;
486 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
487 CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
489 /* get the security descriptor */
491 ZERO_STRUCT(qfinfo);
493 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
494 qfinfo.query_secdesc.in.file.handle = _h1;
495 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
497 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
498 CHECK_STATUS(status, NT_STATUS_OK);
500 sd1 = qfinfo.query_secdesc.out.sd;
502 /* re-authenticate as anonymous */
504 anon_creds = cli_credentials_init_anon(mem_ctx);
505 torture_assert(tctx, (anon_creds != NULL), "talloc error");
507 status = smb2_session_setup_spnego(tree->session,
508 anon_creds,
509 0 /* previous_session_id */);
510 CHECK_STATUS(status, NT_STATUS_OK);
512 /* give full access on the file to anonymous */
514 extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
516 ZERO_STRUCT(ace);
517 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
518 ace.flags = 0;
519 ace.access_mask = SEC_STD_ALL | SEC_FILE_ALL;
520 ace.trustee = *extra_sid;
522 status = security_descriptor_dacl_add(sd1, &ace);
523 CHECK_STATUS(status, NT_STATUS_OK);
525 ZERO_STRUCT(sfinfo);
526 sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
527 sfinfo.set_secdesc.in.file.handle = _h1;
528 sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
529 sfinfo.set_secdesc.in.sd = sd1;
531 status = smb2_setinfo_file(tree, &sfinfo);
532 CHECK_STATUS(status, NT_STATUS_OK);
534 /* re-authenticate as original user again */
536 status = smb2_session_setup_spnego(tree->session,
537 cmdline_credentials,
538 0 /* previous_session_id */);
539 CHECK_STATUS(status, NT_STATUS_OK);
541 /* re-get the security descriptor */
543 ZERO_STRUCT(qfinfo);
545 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
546 qfinfo.query_secdesc.in.file.handle = _h1;
547 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
549 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
550 CHECK_STATUS(status, NT_STATUS_OK);
552 ret = true;
554 done:
555 if (h1 != NULL) {
556 smb2_util_close(tree, *h1);
559 smb2_util_unlink(tree, fname);
561 talloc_free(tree);
563 talloc_free(mem_ctx);
565 return ret;
569 * test renaming after reauth.
570 * compare security descriptors before and after rename/reauth
572 bool test_session_reauth5(struct torture_context *tctx, struct smb2_tree *tree)
574 NTSTATUS status;
575 TALLOC_CTX *mem_ctx = talloc_new(tctx);
576 char dname[256];
577 char fname[256];
578 char fname2[256];
579 struct smb2_handle _dh1;
580 struct smb2_handle *dh1 = NULL;
581 struct smb2_handle _h1;
582 struct smb2_handle *h1 = NULL;
583 struct smb2_create io1;
584 bool ret = true;
585 bool ok;
586 union smb_fileinfo qfinfo;
587 union smb_setfileinfo sfinfo;
588 struct cli_credentials *anon_creds = NULL;
589 uint32_t secinfo_flags = SECINFO_OWNER
590 | SECINFO_GROUP
591 | SECINFO_DACL
592 | SECINFO_PROTECTED_DACL
593 | SECINFO_UNPROTECTED_DACL;
594 struct security_descriptor *f_sd1, *f_sd2;
595 struct security_descriptor *d_sd1 = NULL;
596 struct security_ace ace;
597 struct dom_sid *extra_sid;
599 /* Add some random component to the file name. */
600 snprintf(dname, 256, "session_reauth5_%s.d",
601 generate_random_str(tctx, 8));
602 snprintf(fname, 256, "%s\\file.dat", dname);
604 ok = smb2_util_setup_dir(tctx, tree, dname);
605 CHECK_VAL(ok, true);
607 status = torture_smb2_testdir(tree, dname, &_dh1);
608 CHECK_STATUS(status, NT_STATUS_OK);
609 dh1 = &_dh1;
611 smb2_oplock_create_share(&io1, fname,
612 smb2_util_share_access(""),
613 smb2_util_oplock_level("b"));
615 status = smb2_create(tree, mem_ctx, &io1);
616 CHECK_STATUS(status, NT_STATUS_OK);
617 _h1 = io1.out.file.handle;
618 h1 = &_h1;
619 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
620 CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
622 /* get the security descriptor */
624 ZERO_STRUCT(qfinfo);
626 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
627 qfinfo.query_secdesc.in.file.handle = _h1;
628 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
630 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
631 CHECK_STATUS(status, NT_STATUS_OK);
633 f_sd1 = qfinfo.query_secdesc.out.sd;
635 /* re-authenticate as anonymous */
637 anon_creds = cli_credentials_init_anon(mem_ctx);
638 torture_assert(tctx, (anon_creds != NULL), "talloc error");
640 status = smb2_session_setup_spnego(tree->session,
641 anon_creds,
642 0 /* previous_session_id */);
643 CHECK_STATUS(status, NT_STATUS_OK);
645 /* try to rename the file: fails */
647 snprintf(fname2, 256, "%s\\file2.dat", dname);
649 smb2_util_unlink(tree, fname2);
651 ZERO_STRUCT(sfinfo);
652 sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
653 sfinfo.rename_information.in.file.handle = _h1;
654 sfinfo.rename_information.in.overwrite = true;
655 sfinfo.rename_information.in.new_name = fname2;
657 status = smb2_setinfo_file(tree, &sfinfo);
658 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
660 /* re-authenticate as original user again */
662 status = smb2_session_setup_spnego(tree->session,
663 cmdline_credentials,
664 0 /* previous_session_id */);
665 CHECK_STATUS(status, NT_STATUS_OK);
667 /* give full access on the file to anonymous */
669 extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
671 ZERO_STRUCT(ace);
672 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
673 ace.flags = 0;
674 ace.access_mask = SEC_RIGHTS_FILE_ALL;
675 ace.trustee = *extra_sid;
677 status = security_descriptor_dacl_add(f_sd1, &ace);
678 CHECK_STATUS(status, NT_STATUS_OK);
680 ZERO_STRUCT(sfinfo);
681 sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
682 sfinfo.set_secdesc.in.file.handle = _h1;
683 sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
684 sfinfo.set_secdesc.in.sd = f_sd1;
686 status = smb2_setinfo_file(tree, &sfinfo);
687 CHECK_STATUS(status, NT_STATUS_OK);
689 /* re-get the security descriptor */
691 ZERO_STRUCT(qfinfo);
693 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
694 qfinfo.query_secdesc.in.file.handle = _h1;
695 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
697 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
698 CHECK_STATUS(status, NT_STATUS_OK);
700 /* re-authenticate as anonymous - again */
702 anon_creds = cli_credentials_init_anon(mem_ctx);
703 torture_assert(tctx, (anon_creds != NULL), "talloc error");
705 status = smb2_session_setup_spnego(tree->session,
706 anon_creds,
707 0 /* previous_session_id */);
708 CHECK_STATUS(status, NT_STATUS_OK);
710 /* try to rename the file: fails */
712 ZERO_STRUCT(sfinfo);
713 sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
714 sfinfo.rename_information.in.file.handle = _h1;
715 sfinfo.rename_information.in.overwrite = true;
716 sfinfo.rename_information.in.new_name = fname2;
718 status = smb2_setinfo_file(tree, &sfinfo);
719 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
721 /* give full access on the parent dir to anonymous */
723 ZERO_STRUCT(qfinfo);
725 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
726 qfinfo.query_secdesc.in.file.handle = _dh1;
727 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
729 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
730 CHECK_STATUS(status, NT_STATUS_OK);
732 d_sd1 = qfinfo.query_secdesc.out.sd;
734 ZERO_STRUCT(ace);
735 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
736 ace.flags = 0;
737 ace.access_mask = SEC_RIGHTS_FILE_ALL;
738 ace.trustee = *extra_sid;
740 status = security_descriptor_dacl_add(d_sd1, &ace);
741 CHECK_STATUS(status, NT_STATUS_OK);
743 ZERO_STRUCT(sfinfo);
744 sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
745 sfinfo.set_secdesc.in.file.handle = _dh1;
746 sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
747 sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
748 sfinfo.set_secdesc.in.sd = d_sd1;
750 status = smb2_setinfo_file(tree, &sfinfo);
751 CHECK_STATUS(status, NT_STATUS_OK);
753 ZERO_STRUCT(qfinfo);
755 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
756 qfinfo.query_secdesc.in.file.handle = _dh1;
757 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
759 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
760 CHECK_STATUS(status, NT_STATUS_OK);
762 smb2_util_close(tree, _dh1);
763 dh1 = NULL;
765 /* try to rename the file: still fails */
767 ZERO_STRUCT(sfinfo);
768 sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
769 sfinfo.rename_information.in.file.handle = _h1;
770 sfinfo.rename_information.in.overwrite = true;
771 sfinfo.rename_information.in.new_name = fname2;
773 status = smb2_setinfo_file(tree, &sfinfo);
774 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
776 /* re-authenticate as original user - again */
778 status = smb2_session_setup_spnego(tree->session,
779 cmdline_credentials,
780 0 /* previous_session_id */);
781 CHECK_STATUS(status, NT_STATUS_OK);
783 /* rename the file - for verification that it works */
785 ZERO_STRUCT(sfinfo);
786 sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
787 sfinfo.rename_information.in.file.handle = _h1;
788 sfinfo.rename_information.in.overwrite = true;
789 sfinfo.rename_information.in.new_name = fname2;
791 status = smb2_setinfo_file(tree, &sfinfo);
792 CHECK_STATUS(status, NT_STATUS_OK);
794 /* closs the file, check it is gone and reopen under the new name */
796 smb2_util_close(tree, _h1);
798 ZERO_STRUCT(io1);
800 smb2_generic_create_share(&io1,
801 NULL /* lease */, false /* dir */,
802 fname,
803 NTCREATEX_DISP_OPEN,
804 smb2_util_share_access(""),
805 smb2_util_oplock_level("b"),
806 0 /* leasekey */, 0 /* leasestate */);
808 status = smb2_create(tree, mem_ctx, &io1);
809 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
811 ZERO_STRUCT(io1);
813 smb2_generic_create_share(&io1,
814 NULL /* lease */, false /* dir */,
815 fname2,
816 NTCREATEX_DISP_OPEN,
817 smb2_util_share_access(""),
818 smb2_util_oplock_level("b"),
819 0 /* leasekey */, 0 /* leasestate */);
821 status = smb2_create(tree, mem_ctx, &io1);
822 CHECK_STATUS(status, NT_STATUS_OK);
823 _h1 = io1.out.file.handle;
824 h1 = &_h1;
825 CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
826 CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
828 /* try to access the file via the old handle */
830 ZERO_STRUCT(qfinfo);
832 qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
833 qfinfo.query_secdesc.in.file.handle = _h1;
834 qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
836 status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
837 CHECK_STATUS(status, NT_STATUS_OK);
839 f_sd2 = qfinfo.query_secdesc.out.sd;
841 done:
842 if (dh1 != NULL) {
843 smb2_util_close(tree, *dh1);
845 if (h1 != NULL) {
846 smb2_util_close(tree, *h1);
849 smb2_deltree(tree, dname);
851 talloc_free(tree);
853 talloc_free(mem_ctx);
855 return ret;
858 static bool test_session_expire1(struct torture_context *tctx)
860 NTSTATUS status;
861 bool ret = false;
862 struct smbcli_options options;
863 const char *host = torture_setting_string(tctx, "host", NULL);
864 const char *share = torture_setting_string(tctx, "share", NULL);
865 struct cli_credentials *credentials = cmdline_credentials;
866 struct smb2_tree *tree;
867 enum credentials_use_kerberos use_kerberos;
868 char fname[256];
869 struct smb2_handle _h1;
870 struct smb2_handle *h1 = NULL;
871 struct smb2_create io1;
872 union smb_fileinfo qfinfo;
873 size_t i;
875 use_kerberos = cli_credentials_get_kerberos_state(credentials);
876 if (use_kerberos != CRED_MUST_USE_KERBEROS) {
877 torture_warning(tctx, "smb2.session.expire1 requires -k yes!");
878 torture_skip(tctx, "smb2.session.expire1 requires -k yes!");
881 torture_assert_int_equal(tctx, use_kerberos, CRED_MUST_USE_KERBEROS,
882 "please use -k yes");
884 lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
886 lpcfg_smbcli_options(tctx->lp_ctx, &options);
888 status = smb2_connect(tctx,
889 host,
890 lpcfg_smb_ports(tctx->lp_ctx),
891 share,
892 lpcfg_resolve_context(tctx->lp_ctx),
893 credentials,
894 &tree,
895 tctx->ev,
896 &options,
897 lpcfg_socket_options(tctx->lp_ctx),
898 lpcfg_gensec_settings(tctx, tctx->lp_ctx)
900 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
901 "smb2_connect failed");
903 /* Add some random component to the file name. */
904 snprintf(fname, 256, "session_expire1_%s.dat",
905 generate_random_str(tctx, 8));
907 smb2_util_unlink(tree, fname);
909 smb2_oplock_create_share(&io1, fname,
910 smb2_util_share_access(""),
911 smb2_util_oplock_level("b"));
912 io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
914 status = smb2_create(tree, tctx, &io1);
915 CHECK_STATUS(status, NT_STATUS_OK);
916 _h1 = io1.out.file.handle;
917 h1 = &_h1;
918 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
919 CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
921 /* get the security descriptor */
923 ZERO_STRUCT(qfinfo);
925 qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
926 qfinfo.access_information.in.file.handle = _h1;
928 for (i=0; i < 2; i++) {
929 torture_comment(tctx, "query info => OK\n");
931 ZERO_STRUCT(qfinfo.access_information.out);
932 status = smb2_getinfo_file(tree, tctx, &qfinfo);
933 CHECK_STATUS(status, NT_STATUS_OK);
935 torture_comment(tctx, "sleep 5 seconds\n");
936 smb_msleep(5*1000);
938 torture_comment(tctx, "query info => EXPIRED\n");
939 ZERO_STRUCT(qfinfo.access_information.out);
940 status = smb2_getinfo_file(tree, tctx, &qfinfo);
941 CHECK_STATUS(status, NT_STATUS_NETWORK_SESSION_EXPIRED);
944 * the krb5 library may not handle expired creds
945 * well, lets start with an empty ccache.
947 cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
949 torture_comment(tctx, "reauth => OK\n");
950 status = smb2_session_setup_spnego(tree->session,
951 credentials,
952 0 /* previous_session_id */);
953 CHECK_STATUS(status, NT_STATUS_OK);
956 ZERO_STRUCT(qfinfo.access_information.out);
957 status = smb2_getinfo_file(tree, tctx, &qfinfo);
958 CHECK_STATUS(status, NT_STATUS_OK);
960 ret = true;
961 done:
962 if (h1 != NULL) {
963 smb2_util_close(tree, *h1);
966 talloc_free(tree);
967 lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
968 return ret;
971 struct torture_suite *torture_smb2_session_init(void)
973 struct torture_suite *suite =
974 torture_suite_create(talloc_autofree_context(), "session");
976 torture_suite_add_1smb2_test(suite, "reconnect1", test_session_reconnect1);
977 torture_suite_add_1smb2_test(suite, "reconnect2", test_session_reconnect2);
978 torture_suite_add_1smb2_test(suite, "reauth1", test_session_reauth1);
979 torture_suite_add_1smb2_test(suite, "reauth2", test_session_reauth2);
980 torture_suite_add_1smb2_test(suite, "reauth3", test_session_reauth3);
981 torture_suite_add_1smb2_test(suite, "reauth4", test_session_reauth4);
982 torture_suite_add_1smb2_test(suite, "reauth5", test_session_reauth5);
983 torture_suite_add_simple_test(suite, "expire1", test_session_expire1);
985 suite->description = talloc_strdup(suite, "SMB2-SESSION tests");
987 return suite;