s4:torture/smb2: run smb2.session.reauth5 in a subdirectory
[ddiss/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, &tree2)) {
98                 torture_warning(tctx, "session reconnect failed\n");
99                 ret = false;
100                 goto done;
101         }
102
103         /* try to access the file via the old handle */
104
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;
111
112         smb2_oplock_create_share(&io2, fname,
113                                  smb2_util_share_access(""),
114                                  smb2_util_oplock_level("b"));
115
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;
122
123 done:
124         if (h1 != NULL) {
125                 smb2_util_close(tree, *h1);
126         }
127         if (h2 != NULL) {
128                 smb2_util_close(tree2, *h2);
129         }
130
131         smb2_util_unlink(tree2, fname);
132
133         talloc_free(tree);
134         talloc_free(tree2);
135
136         talloc_free(mem_ctx);
137
138         return ret;
139 }
140
141 /**
142  * basic test for doing a session reconnect on one connection
143  */
144 bool test_session_reconnect2(struct torture_context *tctx, struct smb2_tree *tree)
145 {
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;
156
157         /* Add some random component to the file name. */
158         snprintf(fname, 256, "session_reconnect_%s.dat",
159                  generate_random_str(tctx, 8));
160
161         smb2_util_unlink(tree, fname);
162
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;
167
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"));
174
175         /* disconnect, reconnect and then do durable reopen */
176         previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
177
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");
181
182         /* try to access the file via the old handle */
183
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;
190
191 done:
192         if (h1 != NULL) {
193                 smb2_util_close(tree, *h1);
194         }
195
196         talloc_free(tree);
197         talloc_free(session2);
198
199         talloc_free(mem_ctx);
200
201         return ret;
202 }
203
204 bool test_session_reauth1(struct torture_context *tctx, struct smb2_tree *tree)
205 {
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;
214
215         /* Add some random component to the file name. */
216         snprintf(fname, 256, "session_reauth1_%s.dat",
217                  generate_random_str(tctx, 8));
218
219         smb2_util_unlink(tree, fname);
220
221         smb2_oplock_create_share(&io1, fname,
222                                  smb2_util_share_access(""),
223                                  smb2_util_oplock_level("b"));
224
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"));
231
232         status = smb2_session_setup_spnego(tree->session,
233                                            cmdline_credentials,
234                                            0 /* previous_session_id */);
235         CHECK_STATUS(status, NT_STATUS_OK);
236
237         /* try to access the file via the old handle */
238
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);
244
245         status = smb2_session_setup_spnego(tree->session,
246                                            cmdline_credentials,
247                                            0 /* previous_session_id */);
248         CHECK_STATUS(status, NT_STATUS_OK);
249
250         /* try to access the file via the old handle */
251
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);
257
258 done:
259         if (h1 != NULL) {
260                 smb2_util_close(tree, *h1);
261         }
262
263         smb2_util_unlink(tree, fname);
264
265         talloc_free(tree);
266
267         talloc_free(mem_ctx);
268
269         return ret;
270 }
271
272 bool test_session_reauth2(struct torture_context *tctx, struct smb2_tree *tree)
273 {
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;
283
284         /* Add some random component to the file name. */
285         snprintf(fname, 256, "session_reauth2_%s.dat",
286                  generate_random_str(tctx, 8));
287
288         smb2_util_unlink(tree, fname);
289
290         smb2_oplock_create_share(&io1, fname,
291                                  smb2_util_share_access(""),
292                                  smb2_util_oplock_level("b"));
293
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"));
300
301         /* re-authenticate as anonymous */
302
303         anon_creds = cli_credentials_init_anon(mem_ctx);
304         torture_assert(tctx, (anon_creds != NULL), "talloc error");
305
306         status = smb2_session_setup_spnego(tree->session,
307                                            anon_creds,
308                                            0 /* previous_session_id */);
309         CHECK_STATUS(status, NT_STATUS_OK);
310
311         /* try to access the file via the old handle */
312
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);
318
319         /* re-authenticate as original user again */
320
321         status = smb2_session_setup_spnego(tree->session,
322                                            cmdline_credentials,
323                                            0 /* previous_session_id */);
324         CHECK_STATUS(status, NT_STATUS_OK);
325
326         /* try to access the file via the old handle */
327
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);
333
334 done:
335         if (h1 != NULL) {
336                 smb2_util_close(tree, *h1);
337         }
338
339         smb2_util_unlink(tree, fname);
340
341         talloc_free(tree);
342
343         talloc_free(mem_ctx);
344
345         return ret;
346 }
347
348 /**
349  * test getting security descriptor after reauth
350  */
351 bool test_session_reauth3(struct torture_context *tctx, struct smb2_tree *tree)
352 {
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;
367
368         /* Add some random component to the file name. */
369         snprintf(fname, 256, "session_reauth3_%s.dat",
370                  generate_random_str(tctx, 8));
371
372         smb2_util_unlink(tree, fname);
373
374         smb2_oplock_create_share(&io1, fname,
375                                  smb2_util_share_access(""),
376                                  smb2_util_oplock_level("b"));
377
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"));
384
385         /* get the security descriptor */
386
387         ZERO_STRUCT(qfinfo);
388
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;
392
393         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
394         CHECK_STATUS(status, NT_STATUS_OK);
395         /* re-authenticate as anonymous */
396
397         anon_creds = cli_credentials_init_anon(mem_ctx);
398         torture_assert(tctx, (anon_creds != NULL), "talloc error");
399
400         status = smb2_session_setup_spnego(tree->session,
401                                            anon_creds,
402                                            0 /* previous_session_id */);
403         CHECK_STATUS(status, NT_STATUS_OK);
404
405         /* try to access the file via the old handle */
406
407         ZERO_STRUCT(qfinfo);
408
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;
412
413         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
414         CHECK_STATUS(status, NT_STATUS_OK);
415
416         /* re-authenticate as original user again */
417
418         status = smb2_session_setup_spnego(tree->session,
419                                            cmdline_credentials,
420                                            0 /* previous_session_id */);
421         CHECK_STATUS(status, NT_STATUS_OK);
422
423         /* try to access the file via the old handle */
424
425         ZERO_STRUCT(qfinfo);
426
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;
430
431         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
432         CHECK_STATUS(status, NT_STATUS_OK);
433
434 done:
435         if (h1 != NULL) {
436                 smb2_util_close(tree, *h1);
437         }
438
439         smb2_util_unlink(tree, fname);
440
441         talloc_free(tree);
442
443         talloc_free(mem_ctx);
444
445         return ret;
446 }
447
448 /**
449  * test setting security descriptor after reauth.
450  */
451 bool test_session_reauth4(struct torture_context *tctx, struct smb2_tree *tree)
452 {
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;
471
472         /* Add some random component to the file name. */
473         snprintf(fname, 256, "session_reauth4_%s.dat",
474                  generate_random_str(tctx, 8));
475
476         smb2_util_unlink(tree, fname);
477
478         smb2_oplock_create_share(&io1, fname,
479                                  smb2_util_share_access(""),
480                                  smb2_util_oplock_level("b"));
481
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"));
488
489         /* get the security descriptor */
490
491         ZERO_STRUCT(qfinfo);
492
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;
496
497         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
498         CHECK_STATUS(status, NT_STATUS_OK);
499
500         sd1 = qfinfo.query_secdesc.out.sd;
501
502         /* re-authenticate as anonymous */
503
504         anon_creds = cli_credentials_init_anon(mem_ctx);
505         torture_assert(tctx, (anon_creds != NULL), "talloc error");
506
507         status = smb2_session_setup_spnego(tree->session,
508                                            anon_creds,
509                                            0 /* previous_session_id */);
510         CHECK_STATUS(status, NT_STATUS_OK);
511
512         /* give full access on the file to anonymous */
513
514         extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
515
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;
521
522         status = security_descriptor_dacl_add(sd1, &ace);
523         CHECK_STATUS(status, NT_STATUS_OK);
524
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;
530
531         status = smb2_setinfo_file(tree, &sfinfo);
532         CHECK_STATUS(status, NT_STATUS_OK);
533
534         /* re-authenticate as original user again */
535
536         status = smb2_session_setup_spnego(tree->session,
537                                            cmdline_credentials,
538                                            0 /* previous_session_id */);
539         CHECK_STATUS(status, NT_STATUS_OK);
540
541         /* re-get the security descriptor */
542
543         ZERO_STRUCT(qfinfo);
544
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;
548
549         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
550         CHECK_STATUS(status, NT_STATUS_OK);
551
552         ret = true;
553
554 done:
555         if (h1 != NULL) {
556                 smb2_util_close(tree, *h1);
557         }
558
559         smb2_util_unlink(tree, fname);
560
561         talloc_free(tree);
562
563         talloc_free(mem_ctx);
564
565         return ret;
566 }
567
568 /**
569  * test renaming after reauth.
570  * compare security descriptors before and after rename/reauth
571  */
572 bool test_session_reauth5(struct torture_context *tctx, struct smb2_tree *tree)
573 {
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;
598
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);
603
604         ok = smb2_util_setup_dir(tctx, tree, dname);
605         CHECK_VAL(ok, true);
606
607         status = torture_smb2_testdir(tree, dname, &_dh1);
608         CHECK_STATUS(status, NT_STATUS_OK);
609         dh1 = &_dh1;
610
611         smb2_oplock_create_share(&io1, fname,
612                                  smb2_util_share_access(""),
613                                  smb2_util_oplock_level("b"));
614
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"));
621
622         /* get the security descriptor */
623
624         ZERO_STRUCT(qfinfo);
625
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;
629
630         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
631         CHECK_STATUS(status, NT_STATUS_OK);
632
633         f_sd1 = qfinfo.query_secdesc.out.sd;
634
635         /* re-authenticate as anonymous */
636
637         anon_creds = cli_credentials_init_anon(mem_ctx);
638         torture_assert(tctx, (anon_creds != NULL), "talloc error");
639
640         status = smb2_session_setup_spnego(tree->session,
641                                            anon_creds,
642                                            0 /* previous_session_id */);
643         CHECK_STATUS(status, NT_STATUS_OK);
644
645         /* try to rename the file: fails */
646
647         snprintf(fname2, 256, "%s\\file2.dat", dname);
648
649         smb2_util_unlink(tree, fname2);
650
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;
656
657         status = smb2_setinfo_file(tree, &sfinfo);
658         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
659
660         /* re-authenticate as original user again */
661
662         status = smb2_session_setup_spnego(tree->session,
663                                            cmdline_credentials,
664                                            0 /* previous_session_id */);
665         CHECK_STATUS(status, NT_STATUS_OK);
666
667         /* give full access on the file to anonymous */
668
669         extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
670
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;
676
677         status = security_descriptor_dacl_add(f_sd1, &ace);
678         CHECK_STATUS(status, NT_STATUS_OK);
679
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;
685
686         status = smb2_setinfo_file(tree, &sfinfo);
687         CHECK_STATUS(status, NT_STATUS_OK);
688
689         /* re-get the security descriptor */
690
691         ZERO_STRUCT(qfinfo);
692
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;
696
697         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
698         CHECK_STATUS(status, NT_STATUS_OK);
699
700         /* re-authenticate as anonymous - again */
701
702         anon_creds = cli_credentials_init_anon(mem_ctx);
703         torture_assert(tctx, (anon_creds != NULL), "talloc error");
704
705         status = smb2_session_setup_spnego(tree->session,
706                                            anon_creds,
707                                            0 /* previous_session_id */);
708         CHECK_STATUS(status, NT_STATUS_OK);
709
710         /* try to rename the file: fails */
711
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;
717
718         status = smb2_setinfo_file(tree, &sfinfo);
719         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
720
721         /* give full access on the parent dir to anonymous */
722
723         ZERO_STRUCT(qfinfo);
724
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;
728
729         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
730         CHECK_STATUS(status, NT_STATUS_OK);
731
732         d_sd1 = qfinfo.query_secdesc.out.sd;
733
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;
739
740         status = security_descriptor_dacl_add(d_sd1, &ace);
741         CHECK_STATUS(status, NT_STATUS_OK);
742
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;
749
750         status = smb2_setinfo_file(tree, &sfinfo);
751         CHECK_STATUS(status, NT_STATUS_OK);
752
753         ZERO_STRUCT(qfinfo);
754
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;
758
759         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
760         CHECK_STATUS(status, NT_STATUS_OK);
761
762         smb2_util_close(tree, _dh1);
763         dh1 = NULL;
764
765         /* try to rename the file: still fails */
766
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;
772
773         status = smb2_setinfo_file(tree, &sfinfo);
774         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
775
776         /* re-authenticate as original user - again */
777
778         status = smb2_session_setup_spnego(tree->session,
779                                            cmdline_credentials,
780                                            0 /* previous_session_id */);
781         CHECK_STATUS(status, NT_STATUS_OK);
782
783         /* rename the file - for verification that it works */
784
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;
790
791         status = smb2_setinfo_file(tree, &sfinfo);
792         CHECK_STATUS(status, NT_STATUS_OK);
793
794         /* closs the file, check it is gone and reopen under the new name */
795
796         smb2_util_close(tree, _h1);
797
798         ZERO_STRUCT(io1);
799
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 */);
807
808         status = smb2_create(tree, mem_ctx, &io1);
809         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
810
811         ZERO_STRUCT(io1);
812
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 */);
820
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"));
827
828         /* try to access the file via the old handle */
829
830         ZERO_STRUCT(qfinfo);
831
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;
835
836         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
837         CHECK_STATUS(status, NT_STATUS_OK);
838
839         f_sd2 = qfinfo.query_secdesc.out.sd;
840
841 done:
842         if (dh1 != NULL) {
843                 smb2_util_close(tree, *dh1);
844         }
845         if (h1 != NULL) {
846                 smb2_util_close(tree, *h1);
847         }
848
849         smb2_deltree(tree, dname);
850
851         talloc_free(tree);
852
853         talloc_free(mem_ctx);
854
855         return ret;
856 }
857
858 static bool test_session_expire1(struct torture_context *tctx)
859 {
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;
874
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!");
879         }
880
881         torture_assert_int_equal(tctx, use_kerberos, CRED_MUST_USE_KERBEROS,
882                                  "please use -k yes");
883
884         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
885
886         lpcfg_smbcli_options(tctx->lp_ctx, &options);
887
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)
899                               );
900         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
901                                         "smb2_connect failed");
902
903         /* Add some random component to the file name. */
904         snprintf(fname, 256, "session_expire1_%s.dat",
905                  generate_random_str(tctx, 8));
906
907         smb2_util_unlink(tree, fname);
908
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;
913
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"));
920
921         /* get the security descriptor */
922
923         ZERO_STRUCT(qfinfo);
924
925         qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
926         qfinfo.access_information.in.file.handle = _h1;
927
928         for (i=0; i < 2; i++) {
929                 torture_comment(tctx, "query info => OK\n");
930
931                 ZERO_STRUCT(qfinfo.access_information.out);
932                 status = smb2_getinfo_file(tree, tctx, &qfinfo);
933                 CHECK_STATUS(status, NT_STATUS_OK);
934
935                 torture_comment(tctx, "sleep 5 seconds\n");
936                 smb_msleep(5*1000);
937
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);
942
943                 /*
944                  * the krb5 library may not handle expired creds
945                  * well, lets start with an empty ccache.
946                  */
947                 cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
948
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);
954         }
955
956         ZERO_STRUCT(qfinfo.access_information.out);
957         status = smb2_getinfo_file(tree, tctx, &qfinfo);
958         CHECK_STATUS(status, NT_STATUS_OK);
959
960         ret = true;
961 done:
962         if (h1 != NULL) {
963                 smb2_util_close(tree, *h1);
964         }
965
966         talloc_free(tree);
967         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
968         return ret;
969 }
970
971 struct torture_suite *torture_smb2_session_init(void)
972 {
973         struct torture_suite *suite =
974             torture_suite_create(talloc_autofree_context(), "session");
975
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);
984
985         suite->description = talloc_strdup(suite, "SMB2-SESSION tests");
986
987         return suite;
988 }