d076bb6d186defbe554a7a8088b5113575e14439
[mat/samba.git] / source4 / torture / smb2 / session.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    test suite for SMB2 session setups
5
6    Copyright (C) Michael Adam 2012
7
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.
12
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.
17
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/>.
20 */
21
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"
33
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)
40
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)
48
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)
57
58
59 /**
60  * basic test for doing a session reconnect
61  */
62 bool test_session_reconnect1(struct torture_context *tctx, struct smb2_tree *tree)
63 {
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;
76
77         /* Add some random component to the file name. */
78         snprintf(fname, 256, "session_reconnect_%s.dat",
79                  generate_random_str(tctx, 8));
80
81         smb2_util_unlink(tree, fname);
82
83         smb2_oplock_create_share(&io1, fname,
84                                  smb2_util_share_access(""),
85                                  smb2_util_oplock_level("b"));
86
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"));
93
94         /* disconnect, reconnect and then do durable reopen */
95         previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
96
97         if (!torture_smb2_connection_ext(tctx, previous_session_id,
98                                          &tree->session->transport->options,
99                                          &tree2))
100         {
101                 torture_warning(tctx, "session reconnect failed\n");
102                 ret = false;
103                 goto done;
104         }
105
106         /* try to access the file via the old handle */
107
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;
114
115         smb2_oplock_create_share(&io2, fname,
116                                  smb2_util_share_access(""),
117                                  smb2_util_oplock_level("b"));
118
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;
125
126 done:
127         if (h1 != NULL) {
128                 smb2_util_close(tree, *h1);
129         }
130         if (h2 != NULL) {
131                 smb2_util_close(tree2, *h2);
132         }
133
134         smb2_util_unlink(tree2, fname);
135
136         talloc_free(tree);
137         talloc_free(tree2);
138
139         talloc_free(mem_ctx);
140
141         return ret;
142 }
143
144 /**
145  * basic test for doing a session reconnect on one connection
146  */
147 bool test_session_reconnect2(struct torture_context *tctx, struct smb2_tree *tree)
148 {
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;
159
160         /* Add some random component to the file name. */
161         snprintf(fname, 256, "session_reconnect_%s.dat",
162                  generate_random_str(tctx, 8));
163
164         smb2_util_unlink(tree, fname);
165
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;
170
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"));
177
178         /* disconnect, reconnect and then do durable reopen */
179         previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
180
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");
184
185         /* try to access the file via the old handle */
186
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;
193
194 done:
195         if (h1 != NULL) {
196                 smb2_util_close(tree, *h1);
197         }
198
199         talloc_free(tree);
200         talloc_free(session2);
201
202         talloc_free(mem_ctx);
203
204         return ret;
205 }
206
207 bool test_session_reauth1(struct torture_context *tctx, struct smb2_tree *tree)
208 {
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;
217
218         /* Add some random component to the file name. */
219         snprintf(fname, 256, "session_reauth1_%s.dat",
220                  generate_random_str(tctx, 8));
221
222         smb2_util_unlink(tree, fname);
223
224         smb2_oplock_create_share(&io1, fname,
225                                  smb2_util_share_access(""),
226                                  smb2_util_oplock_level("b"));
227
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"));
234
235         status = smb2_session_setup_spnego(tree->session,
236                                            cmdline_credentials,
237                                            0 /* previous_session_id */);
238         CHECK_STATUS(status, NT_STATUS_OK);
239
240         /* try to access the file via the old handle */
241
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);
247
248         status = smb2_session_setup_spnego(tree->session,
249                                            cmdline_credentials,
250                                            0 /* previous_session_id */);
251         CHECK_STATUS(status, NT_STATUS_OK);
252
253         /* try to access the file via the old handle */
254
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);
260
261 done:
262         if (h1 != NULL) {
263                 smb2_util_close(tree, *h1);
264         }
265
266         smb2_util_unlink(tree, fname);
267
268         talloc_free(tree);
269
270         talloc_free(mem_ctx);
271
272         return ret;
273 }
274
275 bool test_session_reauth2(struct torture_context *tctx, struct smb2_tree *tree)
276 {
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;
286
287         /* Add some random component to the file name. */
288         snprintf(fname, 256, "session_reauth2_%s.dat",
289                  generate_random_str(tctx, 8));
290
291         smb2_util_unlink(tree, fname);
292
293         smb2_oplock_create_share(&io1, fname,
294                                  smb2_util_share_access(""),
295                                  smb2_util_oplock_level("b"));
296
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"));
303
304         /* re-authenticate as anonymous */
305
306         anon_creds = cli_credentials_init_anon(mem_ctx);
307         torture_assert(tctx, (anon_creds != NULL), "talloc error");
308
309         status = smb2_session_setup_spnego(tree->session,
310                                            anon_creds,
311                                            0 /* previous_session_id */);
312         CHECK_STATUS(status, NT_STATUS_OK);
313
314         /* try to access the file via the old handle */
315
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);
321
322         /* re-authenticate as original user again */
323
324         status = smb2_session_setup_spnego(tree->session,
325                                            cmdline_credentials,
326                                            0 /* previous_session_id */);
327         CHECK_STATUS(status, NT_STATUS_OK);
328
329         /* try to access the file via the old handle */
330
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);
336
337 done:
338         if (h1 != NULL) {
339                 smb2_util_close(tree, *h1);
340         }
341
342         smb2_util_unlink(tree, fname);
343
344         talloc_free(tree);
345
346         talloc_free(mem_ctx);
347
348         return ret;
349 }
350
351 /**
352  * test getting security descriptor after reauth
353  */
354 bool test_session_reauth3(struct torture_context *tctx, struct smb2_tree *tree)
355 {
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;
370
371         /* Add some random component to the file name. */
372         snprintf(fname, 256, "session_reauth3_%s.dat",
373                  generate_random_str(tctx, 8));
374
375         smb2_util_unlink(tree, fname);
376
377         smb2_oplock_create_share(&io1, fname,
378                                  smb2_util_share_access(""),
379                                  smb2_util_oplock_level("b"));
380
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"));
387
388         /* get the security descriptor */
389
390         ZERO_STRUCT(qfinfo);
391
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;
395
396         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
397         CHECK_STATUS(status, NT_STATUS_OK);
398         /* re-authenticate as anonymous */
399
400         anon_creds = cli_credentials_init_anon(mem_ctx);
401         torture_assert(tctx, (anon_creds != NULL), "talloc error");
402
403         status = smb2_session_setup_spnego(tree->session,
404                                            anon_creds,
405                                            0 /* previous_session_id */);
406         CHECK_STATUS(status, NT_STATUS_OK);
407
408         /* try to access the file via the old handle */
409
410         ZERO_STRUCT(qfinfo);
411
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;
415
416         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
417         CHECK_STATUS(status, NT_STATUS_OK);
418
419         /* re-authenticate as original user again */
420
421         status = smb2_session_setup_spnego(tree->session,
422                                            cmdline_credentials,
423                                            0 /* previous_session_id */);
424         CHECK_STATUS(status, NT_STATUS_OK);
425
426         /* try to access the file via the old handle */
427
428         ZERO_STRUCT(qfinfo);
429
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;
433
434         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
435         CHECK_STATUS(status, NT_STATUS_OK);
436
437 done:
438         if (h1 != NULL) {
439                 smb2_util_close(tree, *h1);
440         }
441
442         smb2_util_unlink(tree, fname);
443
444         talloc_free(tree);
445
446         talloc_free(mem_ctx);
447
448         return ret;
449 }
450
451 /**
452  * test setting security descriptor after reauth.
453  */
454 bool test_session_reauth4(struct torture_context *tctx, struct smb2_tree *tree)
455 {
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;
474
475         /* Add some random component to the file name. */
476         snprintf(fname, 256, "session_reauth4_%s.dat",
477                  generate_random_str(tctx, 8));
478
479         smb2_util_unlink(tree, fname);
480
481         smb2_oplock_create_share(&io1, fname,
482                                  smb2_util_share_access(""),
483                                  smb2_util_oplock_level("b"));
484
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"));
491
492         /* get the security descriptor */
493
494         ZERO_STRUCT(qfinfo);
495
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;
499
500         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
501         CHECK_STATUS(status, NT_STATUS_OK);
502
503         sd1 = qfinfo.query_secdesc.out.sd;
504
505         /* re-authenticate as anonymous */
506
507         anon_creds = cli_credentials_init_anon(mem_ctx);
508         torture_assert(tctx, (anon_creds != NULL), "talloc error");
509
510         status = smb2_session_setup_spnego(tree->session,
511                                            anon_creds,
512                                            0 /* previous_session_id */);
513         CHECK_STATUS(status, NT_STATUS_OK);
514
515         /* give full access on the file to anonymous */
516
517         extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
518
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;
524
525         status = security_descriptor_dacl_add(sd1, &ace);
526         CHECK_STATUS(status, NT_STATUS_OK);
527
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;
533
534         status = smb2_setinfo_file(tree, &sfinfo);
535         CHECK_STATUS(status, NT_STATUS_OK);
536
537         /* re-authenticate as original user again */
538
539         status = smb2_session_setup_spnego(tree->session,
540                                            cmdline_credentials,
541                                            0 /* previous_session_id */);
542         CHECK_STATUS(status, NT_STATUS_OK);
543
544         /* re-get the security descriptor */
545
546         ZERO_STRUCT(qfinfo);
547
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;
551
552         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
553         CHECK_STATUS(status, NT_STATUS_OK);
554
555         ret = true;
556
557 done:
558         if (h1 != NULL) {
559                 smb2_util_close(tree, *h1);
560         }
561
562         smb2_util_unlink(tree, fname);
563
564         talloc_free(tree);
565
566         talloc_free(mem_ctx);
567
568         return ret;
569 }
570
571 /**
572  * test renaming after reauth.
573  * compare security descriptors before and after rename/reauth
574  */
575 bool test_session_reauth5(struct torture_context *tctx, struct smb2_tree *tree)
576 {
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;
601
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);
606
607         ok = smb2_util_setup_dir(tctx, tree, dname);
608         CHECK_VAL(ok, true);
609
610         status = torture_smb2_testdir(tree, dname, &_dh1);
611         CHECK_STATUS(status, NT_STATUS_OK);
612         dh1 = &_dh1;
613
614         smb2_oplock_create_share(&io1, fname,
615                                  smb2_util_share_access(""),
616                                  smb2_util_oplock_level("b"));
617
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"));
624
625         /* get the security descriptor */
626
627         ZERO_STRUCT(qfinfo);
628
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;
632
633         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
634         CHECK_STATUS(status, NT_STATUS_OK);
635
636         f_sd1 = qfinfo.query_secdesc.out.sd;
637
638         /* re-authenticate as anonymous */
639
640         anon_creds = cli_credentials_init_anon(mem_ctx);
641         torture_assert(tctx, (anon_creds != NULL), "talloc error");
642
643         status = smb2_session_setup_spnego(tree->session,
644                                            anon_creds,
645                                            0 /* previous_session_id */);
646         CHECK_STATUS(status, NT_STATUS_OK);
647
648         /* try to rename the file: fails */
649
650         snprintf(fname2, 256, "%s\\file2.dat", dname);
651
652         smb2_util_unlink(tree, fname2);
653
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;
659
660         status = smb2_setinfo_file(tree, &sfinfo);
661         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
662
663         /* re-authenticate as original user again */
664
665         status = smb2_session_setup_spnego(tree->session,
666                                            cmdline_credentials,
667                                            0 /* previous_session_id */);
668         CHECK_STATUS(status, NT_STATUS_OK);
669
670         /* give full access on the file to anonymous */
671
672         extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
673
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;
679
680         status = security_descriptor_dacl_add(f_sd1, &ace);
681         CHECK_STATUS(status, NT_STATUS_OK);
682
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;
688
689         status = smb2_setinfo_file(tree, &sfinfo);
690         CHECK_STATUS(status, NT_STATUS_OK);
691
692         /* re-get the security descriptor */
693
694         ZERO_STRUCT(qfinfo);
695
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;
699
700         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
701         CHECK_STATUS(status, NT_STATUS_OK);
702
703         /* re-authenticate as anonymous - again */
704
705         anon_creds = cli_credentials_init_anon(mem_ctx);
706         torture_assert(tctx, (anon_creds != NULL), "talloc error");
707
708         status = smb2_session_setup_spnego(tree->session,
709                                            anon_creds,
710                                            0 /* previous_session_id */);
711         CHECK_STATUS(status, NT_STATUS_OK);
712
713         /* try to rename the file: fails */
714
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;
720
721         status = smb2_setinfo_file(tree, &sfinfo);
722         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
723
724         /* give full access on the parent dir to anonymous */
725
726         ZERO_STRUCT(qfinfo);
727
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;
731
732         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
733         CHECK_STATUS(status, NT_STATUS_OK);
734
735         d_sd1 = qfinfo.query_secdesc.out.sd;
736
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;
742
743         status = security_descriptor_dacl_add(d_sd1, &ace);
744         CHECK_STATUS(status, NT_STATUS_OK);
745
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;
752
753         status = smb2_setinfo_file(tree, &sfinfo);
754         CHECK_STATUS(status, NT_STATUS_OK);
755
756         ZERO_STRUCT(qfinfo);
757
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;
761
762         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
763         CHECK_STATUS(status, NT_STATUS_OK);
764
765         smb2_util_close(tree, _dh1);
766         dh1 = NULL;
767
768         /* try to rename the file: still fails */
769
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;
775
776         status = smb2_setinfo_file(tree, &sfinfo);
777         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
778
779         /* re-authenticate as original user - again */
780
781         status = smb2_session_setup_spnego(tree->session,
782                                            cmdline_credentials,
783                                            0 /* previous_session_id */);
784         CHECK_STATUS(status, NT_STATUS_OK);
785
786         /* rename the file - for verification that it works */
787
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;
793
794         status = smb2_setinfo_file(tree, &sfinfo);
795         CHECK_STATUS(status, NT_STATUS_OK);
796
797         /* closs the file, check it is gone and reopen under the new name */
798
799         smb2_util_close(tree, _h1);
800
801         ZERO_STRUCT(io1);
802
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 */);
810
811         status = smb2_create(tree, mem_ctx, &io1);
812         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
813
814         ZERO_STRUCT(io1);
815
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 */);
823
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"));
830
831         /* try to access the file via the old handle */
832
833         ZERO_STRUCT(qfinfo);
834
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;
838
839         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
840         CHECK_STATUS(status, NT_STATUS_OK);
841
842 done:
843         if (dh1 != NULL) {
844                 smb2_util_close(tree, *dh1);
845         }
846         if (h1 != NULL) {
847                 smb2_util_close(tree, *h1);
848         }
849
850         smb2_deltree(tree, dname);
851
852         talloc_free(tree);
853
854         talloc_free(mem_ctx);
855
856         return ret;
857 }
858
859 static bool test_session_expire1(struct torture_context *tctx)
860 {
861         NTSTATUS status;
862         bool ret = false;
863         struct smbcli_options options;
864         const char *host = torture_setting_string(tctx, "host", NULL);
865         const char *share = torture_setting_string(tctx, "share", NULL);
866         struct cli_credentials *credentials = cmdline_credentials;
867         struct smb2_tree *tree = NULL;
868         enum credentials_use_kerberos use_kerberos;
869         char fname[256];
870         struct smb2_handle _h1;
871         struct smb2_handle *h1 = NULL;
872         struct smb2_create io1;
873         union smb_fileinfo qfinfo;
874         size_t i;
875
876         use_kerberos = cli_credentials_get_kerberos_state(credentials);
877         if (use_kerberos != CRED_MUST_USE_KERBEROS) {
878                 torture_warning(tctx, "smb2.session.expire1 requires -k yes!");
879                 torture_skip(tctx, "smb2.session.expire1 requires -k yes!");
880         }
881
882         torture_assert_int_equal(tctx, use_kerberos, CRED_MUST_USE_KERBEROS,
883                                  "please use -k yes");
884
885         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
886
887         lpcfg_smbcli_options(tctx->lp_ctx, &options);
888
889         status = smb2_connect(tctx,
890                               host,
891                               lpcfg_smb_ports(tctx->lp_ctx),
892                               share,
893                               lpcfg_resolve_context(tctx->lp_ctx),
894                               credentials,
895                               &tree,
896                               tctx->ev,
897                               &options,
898                               lpcfg_socket_options(tctx->lp_ctx),
899                               lpcfg_gensec_settings(tctx, tctx->lp_ctx)
900                               );
901         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
902                                         "smb2_connect failed");
903
904         /* Add some random component to the file name. */
905         snprintf(fname, 256, "session_expire1_%s.dat",
906                  generate_random_str(tctx, 8));
907
908         smb2_util_unlink(tree, fname);
909
910         smb2_oplock_create_share(&io1, fname,
911                                  smb2_util_share_access(""),
912                                  smb2_util_oplock_level("b"));
913         io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
914
915         status = smb2_create(tree, tctx, &io1);
916         CHECK_STATUS(status, NT_STATUS_OK);
917         _h1 = io1.out.file.handle;
918         h1 = &_h1;
919         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
920         CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
921
922         /* get the security descriptor */
923
924         ZERO_STRUCT(qfinfo);
925
926         qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
927         qfinfo.access_information.in.file.handle = _h1;
928
929         for (i=0; i < 2; i++) {
930                 torture_comment(tctx, "query info => OK\n");
931
932                 ZERO_STRUCT(qfinfo.access_information.out);
933                 status = smb2_getinfo_file(tree, tctx, &qfinfo);
934                 CHECK_STATUS(status, NT_STATUS_OK);
935
936                 torture_comment(tctx, "sleep 5 seconds\n");
937                 smb_msleep(5*1000);
938
939                 torture_comment(tctx, "query info => EXPIRED\n");
940                 ZERO_STRUCT(qfinfo.access_information.out);
941                 status = smb2_getinfo_file(tree, tctx, &qfinfo);
942                 CHECK_STATUS(status, NT_STATUS_NETWORK_SESSION_EXPIRED);
943
944                 /*
945                  * the krb5 library may not handle expired creds
946                  * well, lets start with an empty ccache.
947                  */
948                 cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
949
950                 torture_comment(tctx, "reauth => OK\n");
951                 status = smb2_session_setup_spnego(tree->session,
952                                                    credentials,
953                                                    0 /* previous_session_id */);
954                 CHECK_STATUS(status, NT_STATUS_OK);
955         }
956
957         ZERO_STRUCT(qfinfo.access_information.out);
958         status = smb2_getinfo_file(tree, tctx, &qfinfo);
959         CHECK_STATUS(status, NT_STATUS_OK);
960
961         ret = true;
962 done:
963         if (h1 != NULL) {
964                 smb2_util_close(tree, *h1);
965         }
966
967         talloc_free(tree);
968         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
969         return ret;
970 }
971
972 struct torture_suite *torture_smb2_session_init(void)
973 {
974         struct torture_suite *suite =
975             torture_suite_create(talloc_autofree_context(), "session");
976
977         torture_suite_add_1smb2_test(suite, "reconnect1", test_session_reconnect1);
978         torture_suite_add_1smb2_test(suite, "reconnect2", test_session_reconnect2);
979         torture_suite_add_1smb2_test(suite, "reauth1", test_session_reauth1);
980         torture_suite_add_1smb2_test(suite, "reauth2", test_session_reauth2);
981         torture_suite_add_1smb2_test(suite, "reauth3", test_session_reauth3);
982         torture_suite_add_1smb2_test(suite, "reauth4", test_session_reauth4);
983         torture_suite_add_1smb2_test(suite, "reauth5", test_session_reauth5);
984         torture_suite_add_simple_test(suite, "expire1", test_session_expire1);
985
986         suite->description = talloc_strdup(suite, "SMB2-SESSION tests");
987
988         return suite;
989 }