6051145936b8213beeffeb782142a6e497d23bd6
[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 fname[256];
577         char fname2[256];
578         struct smb2_handle _h1;
579         struct smb2_handle *h1 = NULL;
580         struct smb2_create io1;
581         bool ret = true;
582         union smb_fileinfo qfinfo;
583         union smb_setfileinfo sfinfo;
584         struct cli_credentials *anon_creds = NULL;
585         uint32_t secinfo_flags = SECINFO_OWNER
586                                 | SECINFO_GROUP
587                                 | SECINFO_DACL
588                                 | SECINFO_PROTECTED_DACL
589                                 | SECINFO_UNPROTECTED_DACL;
590         struct security_descriptor *sd1, *sd2;
591         struct security_ace ace;
592         struct dom_sid *extra_sid;
593
594         /* Add some random component to the file name. */
595         snprintf(fname, 256, "session_reauth5_%s.dat",
596                  generate_random_str(tctx, 8));
597
598         smb2_util_unlink(tree, fname);
599
600         smb2_oplock_create_share(&io1, fname,
601                                  smb2_util_share_access(""),
602                                  smb2_util_oplock_level("b"));
603
604         status = smb2_create(tree, mem_ctx, &io1);
605         CHECK_STATUS(status, NT_STATUS_OK);
606         _h1 = io1.out.file.handle;
607         h1 = &_h1;
608         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
609         CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
610
611         /* get the security descriptor */
612
613         ZERO_STRUCT(qfinfo);
614
615         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
616         qfinfo.query_secdesc.in.file.handle = _h1;
617         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
618
619         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
620         CHECK_STATUS(status, NT_STATUS_OK);
621
622         sd1 = qfinfo.query_secdesc.out.sd;
623
624         /* re-authenticate as anonymous */
625
626         anon_creds = cli_credentials_init_anon(mem_ctx);
627         torture_assert(tctx, (anon_creds != NULL), "talloc error");
628
629         status = smb2_session_setup_spnego(tree->session,
630                                            anon_creds,
631                                            0 /* previous_session_id */);
632         CHECK_STATUS(status, NT_STATUS_OK);
633
634         /* try to rename the file: fails */
635
636         snprintf(fname2, 256, "session_reauth5.2_%s.dat",
637                  generate_random_str(tctx, 8));
638
639         smb2_util_unlink(tree, fname2);
640
641         ZERO_STRUCT(sfinfo);
642         sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
643         sfinfo.rename_information.in.file.handle = _h1;
644         sfinfo.rename_information.in.overwrite = true;
645         sfinfo.rename_information.in.new_name = fname2;
646
647         status = smb2_setinfo_file(tree, &sfinfo);
648         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
649
650         /* re-authenticate as original user again */
651
652         status = smb2_session_setup_spnego(tree->session,
653                                            cmdline_credentials,
654                                            0 /* previous_session_id */);
655         CHECK_STATUS(status, NT_STATUS_OK);
656
657         /* give full access on the file to anonymous */
658
659         extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
660
661         ZERO_STRUCT(ace);
662         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
663         ace.flags = 0;
664         ace.access_mask = SEC_STD_ALL | SEC_FILE_ALL;
665         ace.trustee = *extra_sid;
666
667         status = security_descriptor_dacl_add(sd1, &ace);
668         CHECK_STATUS(status, NT_STATUS_OK);
669
670         ZERO_STRUCT(sfinfo);
671         sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
672         sfinfo.set_secdesc.in.file.handle = _h1;
673         sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
674         sfinfo.set_secdesc.in.sd = sd1;
675
676         status = smb2_setinfo_file(tree, &sfinfo);
677         CHECK_STATUS(status, NT_STATUS_OK);
678
679         /* re-get the security descriptor */
680
681         ZERO_STRUCT(qfinfo);
682
683         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
684         qfinfo.query_secdesc.in.file.handle = _h1;
685         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
686
687         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
688         CHECK_STATUS(status, NT_STATUS_OK);
689
690         /* re-authenticate as anonymous - again */
691
692         anon_creds = cli_credentials_init_anon(mem_ctx);
693         torture_assert(tctx, (anon_creds != NULL), "talloc error");
694
695         status = smb2_session_setup_spnego(tree->session,
696                                            anon_creds,
697                                            0 /* previous_session_id */);
698         CHECK_STATUS(status, NT_STATUS_OK);
699
700         /* try to rename the file: fails */
701
702         snprintf(fname2, 256, "session_reauth3.2_%s.dat",
703                  generate_random_str(tctx, 8));
704
705         smb2_util_unlink(tree, fname2);
706
707         ZERO_STRUCT(sfinfo);
708         sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
709         sfinfo.rename_information.in.file.handle = _h1;
710         sfinfo.rename_information.in.overwrite = true;
711         sfinfo.rename_information.in.new_name = fname2;
712
713         status = smb2_setinfo_file(tree, &sfinfo);
714         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
715
716         /* re-authenticate as original user - again */
717
718         status = smb2_session_setup_spnego(tree->session,
719                                            cmdline_credentials,
720                                            0 /* previous_session_id */);
721         CHECK_STATUS(status, NT_STATUS_OK);
722
723         /* rename the file - for verification that it works */
724
725         ZERO_STRUCT(sfinfo);
726         sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
727         sfinfo.rename_information.in.file.handle = _h1;
728         sfinfo.rename_information.in.overwrite = true;
729         sfinfo.rename_information.in.new_name = fname2;
730
731         status = smb2_setinfo_file(tree, &sfinfo);
732         CHECK_STATUS(status, NT_STATUS_OK);
733
734         /* closs the file, check it is gone and reopen under the new name */
735
736         smb2_util_close(tree, _h1);
737
738         ZERO_STRUCT(io1);
739
740         smb2_generic_create_share(&io1,
741                                   NULL /* lease */, false /* dir */,
742                                   fname,
743                                   NTCREATEX_DISP_OPEN,
744                                   smb2_util_share_access(""),
745                                   smb2_util_oplock_level("b"),
746                                   0 /* leasekey */, 0 /* leasestate */);
747
748         status = smb2_create(tree, mem_ctx, &io1);
749         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
750
751         ZERO_STRUCT(io1);
752
753         smb2_generic_create_share(&io1,
754                                   NULL /* lease */, false /* dir */,
755                                   fname2,
756                                   NTCREATEX_DISP_OPEN,
757                                   smb2_util_share_access(""),
758                                   smb2_util_oplock_level("b"),
759                                   0 /* leasekey */, 0 /* leasestate */);
760
761         status = smb2_create(tree, mem_ctx, &io1);
762         CHECK_STATUS(status, NT_STATUS_OK);
763         _h1 = io1.out.file.handle;
764         h1 = &_h1;
765         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
766         CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
767
768         /* try to access the file via the old handle */
769
770         ZERO_STRUCT(qfinfo);
771
772         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
773         qfinfo.query_secdesc.in.file.handle = _h1;
774         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
775
776         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
777         CHECK_STATUS(status, NT_STATUS_OK);
778
779         sd2 = qfinfo.query_secdesc.out.sd;
780
781 done:
782         if (h1 != NULL) {
783                 smb2_util_close(tree, *h1);
784         }
785
786         smb2_util_unlink(tree, fname);
787
788         talloc_free(tree);
789
790         talloc_free(mem_ctx);
791
792         return ret;
793 }
794
795 static bool test_session_expire1(struct torture_context *tctx)
796 {
797         NTSTATUS status;
798         bool ret = false;
799         struct smbcli_options options;
800         const char *host = torture_setting_string(tctx, "host", NULL);
801         const char *share = torture_setting_string(tctx, "share", NULL);
802         struct cli_credentials *credentials = cmdline_credentials;
803         struct smb2_tree *tree;
804         enum credentials_use_kerberos use_kerberos;
805         char fname[256];
806         struct smb2_handle _h1;
807         struct smb2_handle *h1 = NULL;
808         struct smb2_create io1;
809         union smb_fileinfo qfinfo;
810         size_t i;
811
812         use_kerberos = cli_credentials_get_kerberos_state(credentials);
813         if (use_kerberos != CRED_MUST_USE_KERBEROS) {
814                 torture_warning(tctx, "smb2.session.expire1 requires -k yes!");
815                 torture_skip(tctx, "smb2.session.expire1 requires -k yes!");
816         }
817
818         torture_assert_int_equal(tctx, use_kerberos, CRED_MUST_USE_KERBEROS,
819                                  "please use -k yes");
820
821         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
822
823         lpcfg_smbcli_options(tctx->lp_ctx, &options);
824
825         status = smb2_connect(tctx,
826                               host,
827                               lpcfg_smb_ports(tctx->lp_ctx),
828                               share,
829                               lpcfg_resolve_context(tctx->lp_ctx),
830                               credentials,
831                               &tree,
832                               tctx->ev,
833                               &options,
834                               lpcfg_socket_options(tctx->lp_ctx),
835                               lpcfg_gensec_settings(tctx, tctx->lp_ctx)
836                               );
837         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
838                                         "smb2_connect failed");
839
840         /* Add some random component to the file name. */
841         snprintf(fname, 256, "session_expire1_%s.dat",
842                  generate_random_str(tctx, 8));
843
844         smb2_util_unlink(tree, fname);
845
846         smb2_oplock_create_share(&io1, fname,
847                                  smb2_util_share_access(""),
848                                  smb2_util_oplock_level("b"));
849         io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
850
851         status = smb2_create(tree, tctx, &io1);
852         CHECK_STATUS(status, NT_STATUS_OK);
853         _h1 = io1.out.file.handle;
854         h1 = &_h1;
855         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
856         CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
857
858         /* get the security descriptor */
859
860         ZERO_STRUCT(qfinfo);
861
862         qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
863         qfinfo.access_information.in.file.handle = _h1;
864
865         for (i=0; i < 2; i++) {
866                 torture_comment(tctx, "query info => OK\n");
867
868                 ZERO_STRUCT(qfinfo.access_information.out);
869                 status = smb2_getinfo_file(tree, tctx, &qfinfo);
870                 CHECK_STATUS(status, NT_STATUS_OK);
871
872                 torture_comment(tctx, "sleep 5 seconds\n");
873                 smb_msleep(5*1000);
874
875                 torture_comment(tctx, "query info => EXPIRED\n");
876                 ZERO_STRUCT(qfinfo.access_information.out);
877                 status = smb2_getinfo_file(tree, tctx, &qfinfo);
878                 CHECK_STATUS(status, NT_STATUS_NETWORK_SESSION_EXPIRED);
879
880                 /*
881                  * the krb5 library may not handle expired creds
882                  * well, lets start with an empty ccache.
883                  */
884                 cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
885
886                 torture_comment(tctx, "reauth => OK\n");
887                 status = smb2_session_setup_spnego(tree->session,
888                                                    credentials,
889                                                    0 /* previous_session_id */);
890                 CHECK_STATUS(status, NT_STATUS_OK);
891         }
892
893         ZERO_STRUCT(qfinfo.access_information.out);
894         status = smb2_getinfo_file(tree, tctx, &qfinfo);
895         CHECK_STATUS(status, NT_STATUS_OK);
896
897         ret = true;
898 done:
899         if (h1 != NULL) {
900                 smb2_util_close(tree, *h1);
901         }
902
903         talloc_free(tree);
904         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
905         return ret;
906 }
907
908 struct torture_suite *torture_smb2_session_init(void)
909 {
910         struct torture_suite *suite =
911             torture_suite_create(talloc_autofree_context(), "session");
912
913         torture_suite_add_1smb2_test(suite, "reconnect1", test_session_reconnect1);
914         torture_suite_add_1smb2_test(suite, "reconnect2", test_session_reconnect2);
915         torture_suite_add_1smb2_test(suite, "reauth1", test_session_reauth1);
916         torture_suite_add_1smb2_test(suite, "reauth2", test_session_reauth2);
917         torture_suite_add_1smb2_test(suite, "reauth3", test_session_reauth3);
918         torture_suite_add_1smb2_test(suite, "reauth4", test_session_reauth4);
919         torture_suite_add_1smb2_test(suite, "reauth5", test_session_reauth5);
920         torture_suite_add_simple_test(suite, "expire1", test_session_expire1);
921
922         suite->description = talloc_strdup(suite, "SMB2-SESSION tests");
923
924         return suite;
925 }