6d5f7b8594ec24e5317971c68fbb44f09b70a6be
[nivanova/samba-autobuild/.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 "auth/credentials/credentials_krb5.h"
31 #include "libcli/security/security.h"
32 #include "libcli/resolve/resolve.h"
33 #include "lib/param/param.h"
34 #include "lib/util/tevent_ntstatus.h"
35
36 #define CHECK_CREATED(tctx, __io, __created, __attribute)                       \
37         do {                                                                    \
38                 torture_assert_int_equal(tctx, (__io)->out.create_action,       \
39                                                 NTCREATEX_ACTION_ ## __created, \
40                                                 "out.create_action incorrect"); \
41                 torture_assert_int_equal(tctx, (__io)->out.size, 0,             \
42                                                 "out.size incorrect");          \
43                 torture_assert_int_equal(tctx, (__io)->out.file_attr,           \
44                                                 (__attribute),                  \
45                                                 "out.file_attr incorrect");     \
46                 torture_assert_int_equal(tctx, (__io)->out.reserved2, 0,        \
47                                 "out.reserverd2 incorrect");                    \
48         } while(0)
49
50 /**
51  * basic test for doing a session reconnect
52  */
53 bool test_session_reconnect1(struct torture_context *tctx, struct smb2_tree *tree)
54 {
55         NTSTATUS status;
56         TALLOC_CTX *mem_ctx = talloc_new(tctx);
57         char fname[256];
58         struct smb2_handle _h1;
59         struct smb2_handle *h1 = NULL;
60         struct smb2_handle _h2;
61         struct smb2_handle *h2 = NULL;
62         struct smb2_create io1, io2;
63         uint64_t previous_session_id;
64         bool ret = true;
65         struct smb2_tree *tree2 = NULL;
66         union smb_fileinfo qfinfo;
67
68         /* Add some random component to the file name. */
69         snprintf(fname, sizeof(fname), "session_reconnect_%s.dat",
70                  generate_random_str(tctx, 8));
71
72         smb2_util_unlink(tree, fname);
73
74         smb2_oplock_create_share(&io1, fname,
75                                  smb2_util_share_access(""),
76                                  smb2_util_oplock_level("b"));
77
78         status = smb2_create(tree, mem_ctx, &io1);
79         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
80                                         "smb2_create failed");
81         _h1 = io1.out.file.handle;
82         h1 = &_h1;
83         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
84         torture_assert_int_equal(tctx, io1.out.oplock_level,
85                                         smb2_util_oplock_level("b"),
86                                         "oplock_level incorrect");
87
88         /* disconnect, reconnect and then do durable reopen */
89         previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
90
91         torture_assert_goto(tctx, torture_smb2_connection_ext(tctx, previous_session_id,
92                             &tree->session->transport->options, &tree2),
93                             ret, done,
94                             "session reconnect failed\n");
95
96         /* try to access the file via the old handle */
97
98         ZERO_STRUCT(qfinfo);
99         qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
100         qfinfo.generic.in.file.handle = _h1;
101         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
102         torture_assert_ntstatus_equal_goto(tctx, status,
103                                            NT_STATUS_USER_SESSION_DELETED,
104                                            ret, done, "smb2_getinfo_file "
105                                            "returned unexpected status");
106         h1 = NULL;
107
108         smb2_oplock_create_share(&io2, fname,
109                                  smb2_util_share_access(""),
110                                  smb2_util_oplock_level("b"));
111
112         status = smb2_create(tree2, mem_ctx, &io2);
113         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
114                                         "smb2_create failed");
115
116         CHECK_CREATED(tctx, &io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
117         torture_assert_int_equal(tctx, io1.out.oplock_level,
118                                         smb2_util_oplock_level("b"),
119                                         "oplock_level incorrect");
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         if (tree2 != NULL) {
132                 smb2_util_unlink(tree2, fname);
133         }
134         smb2_util_unlink(tree, 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 = NULL;
158         union smb_fileinfo qfinfo;
159
160         /* Add some random component to the file name. */
161         snprintf(fname, sizeof(fname), "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         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
173                                         "smb2_create failed");
174         _h1 = io1.out.file.handle;
175         h1 = &_h1;
176         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
177         torture_assert_int_equal(tctx, io1.out.oplock_level,
178                                         smb2_util_oplock_level("b"),
179                                         "oplock_level incorrect");
180
181         /* disconnect, reconnect and then do durable reopen */
182         previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
183
184         torture_assert(tctx, torture_smb2_session_setup(tctx, tree->session->transport,
185                                 previous_session_id, tctx, &session2),
186                                 "session reconnect (on the same connection) failed");
187
188         /* try to access the file via the old handle */
189
190         ZERO_STRUCT(qfinfo);
191         qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
192         qfinfo.generic.in.file.handle = _h1;
193         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
194         torture_assert_ntstatus_equal_goto(tctx, status,
195                                            NT_STATUS_USER_SESSION_DELETED,
196                                            ret, done, "smb2_getinfo_file "
197                                            "returned unexpected status");
198         h1 = NULL;
199
200 done:
201         if (h1 != NULL) {
202                 smb2_util_close(tree, *h1);
203         }
204
205         talloc_free(tree);
206         talloc_free(session2);
207
208         talloc_free(mem_ctx);
209
210         return ret;
211 }
212
213 bool test_session_reauth1(struct torture_context *tctx, struct smb2_tree *tree)
214 {
215         NTSTATUS status;
216         TALLOC_CTX *mem_ctx = talloc_new(tctx);
217         char fname[256];
218         struct smb2_handle _h1;
219         struct smb2_handle *h1 = NULL;
220         struct smb2_create io1;
221         bool ret = true;
222         union smb_fileinfo qfinfo;
223
224         /* Add some random component to the file name. */
225         snprintf(fname, sizeof(fname), "session_reauth1_%s.dat",
226                  generate_random_str(tctx, 8));
227
228         smb2_util_unlink(tree, fname);
229
230         smb2_oplock_create_share(&io1, fname,
231                                  smb2_util_share_access(""),
232                                  smb2_util_oplock_level("b"));
233
234         status = smb2_create(tree, mem_ctx, &io1);
235         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
236                                         "smb2_create failed");
237         _h1 = io1.out.file.handle;
238         h1 = &_h1;
239         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
240         torture_assert_int_equal(tctx, io1.out.oplock_level,
241                                         smb2_util_oplock_level("b"),
242                                         "oplock_level incorrect");
243
244         status = smb2_session_setup_spnego(tree->session,
245                                            popt_get_cmdline_credentials(),
246                                            0 /* previous_session_id */);
247         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
248                                         "smb2_session_setup_spnego failed");
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         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
257                                         "smb2_getinfo_file failed");
258
259         status = smb2_session_setup_spnego(tree->session,
260                                            popt_get_cmdline_credentials(),
261                                            0 /* previous_session_id */);
262         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
263                                         "smb2_session_setup_spnego failed");
264
265         /* try to access the file via the old handle */
266
267         ZERO_STRUCT(qfinfo);
268         qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
269         qfinfo.generic.in.file.handle = _h1;
270         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
271         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
272                                         "smb2_getinfo_file failed");
273
274 done:
275         if (h1 != NULL) {
276                 smb2_util_close(tree, *h1);
277         }
278
279         smb2_util_unlink(tree, fname);
280
281         talloc_free(tree);
282
283         talloc_free(mem_ctx);
284
285         return ret;
286 }
287
288 bool test_session_reauth2(struct torture_context *tctx, struct smb2_tree *tree)
289 {
290         NTSTATUS status;
291         TALLOC_CTX *mem_ctx = talloc_new(tctx);
292         char fname[256];
293         struct smb2_handle _h1;
294         struct smb2_handle *h1 = NULL;
295         struct smb2_create io1;
296         bool ret = true;
297         union smb_fileinfo qfinfo;
298         struct cli_credentials *anon_creds = NULL;
299
300         /* Add some random component to the file name. */
301         snprintf(fname, sizeof(fname), "session_reauth2_%s.dat",
302                  generate_random_str(tctx, 8));
303
304         smb2_util_unlink(tree, fname);
305
306         smb2_oplock_create_share(&io1, fname,
307                                  smb2_util_share_access(""),
308                                  smb2_util_oplock_level("b"));
309
310         status = smb2_create(tree, mem_ctx, &io1);
311         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
312                                         "smb2_create failed");
313         _h1 = io1.out.file.handle;
314         h1 = &_h1;
315         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
316         torture_assert_int_equal(tctx, io1.out.oplock_level,
317                                         smb2_util_oplock_level("b"),
318                                         "oplock_level incorrect");
319
320         /* re-authenticate as anonymous */
321
322         anon_creds = cli_credentials_init_anon(mem_ctx);
323         torture_assert(tctx, (anon_creds != NULL), "talloc error");
324
325         status = smb2_session_setup_spnego(tree->session,
326                                            anon_creds,
327                                            0 /* previous_session_id */);
328         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
329                                         "smb2_session_setup_spnego failed");
330
331         /* try to access the file via the old handle */
332
333         ZERO_STRUCT(qfinfo);
334         qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
335         qfinfo.generic.in.file.handle = _h1;
336         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
337         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
338                                         "smb2_getinfo_file failed");
339
340         /* re-authenticate as original user again */
341
342         status = smb2_session_setup_spnego(tree->session,
343                                            popt_get_cmdline_credentials(),
344                                            0 /* previous_session_id */);
345         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
346                                         "smb2_session_setup_spnego failed");
347
348         /* try to access the file via the old handle */
349
350         ZERO_STRUCT(qfinfo);
351         qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
352         qfinfo.generic.in.file.handle = _h1;
353         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
354         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
355                                         "smb2_getinfo_file failed");
356
357 done:
358         if (h1 != NULL) {
359                 smb2_util_close(tree, *h1);
360         }
361
362         smb2_util_unlink(tree, fname);
363
364         talloc_free(tree);
365
366         talloc_free(mem_ctx);
367
368         return ret;
369 }
370
371 /**
372  * test getting security descriptor after reauth
373  */
374 bool test_session_reauth3(struct torture_context *tctx, struct smb2_tree *tree)
375 {
376         NTSTATUS status;
377         TALLOC_CTX *mem_ctx = talloc_new(tctx);
378         char fname[256];
379         struct smb2_handle _h1;
380         struct smb2_handle *h1 = NULL;
381         struct smb2_create io1;
382         bool ret = true;
383         union smb_fileinfo qfinfo;
384         struct cli_credentials *anon_creds = NULL;
385         uint32_t secinfo_flags = SECINFO_OWNER
386                                 | SECINFO_GROUP
387                                 | SECINFO_DACL
388                                 | SECINFO_PROTECTED_DACL
389                                 | SECINFO_UNPROTECTED_DACL;
390
391         /* Add some random component to the file name. */
392         snprintf(fname, sizeof(fname), "session_reauth3_%s.dat",
393                  generate_random_str(tctx, 8));
394
395         smb2_util_unlink(tree, fname);
396
397         smb2_oplock_create_share(&io1, fname,
398                                  smb2_util_share_access(""),
399                                  smb2_util_oplock_level("b"));
400
401         status = smb2_create(tree, mem_ctx, &io1);
402         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
403                                         "smb2_create failed");
404         _h1 = io1.out.file.handle;
405         h1 = &_h1;
406         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
407         torture_assert_int_equal(tctx, io1.out.oplock_level,
408                                         smb2_util_oplock_level("b"),
409                                         "oplock_level incorrect");
410
411         /* get the security descriptor */
412
413         ZERO_STRUCT(qfinfo);
414
415         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
416         qfinfo.query_secdesc.in.file.handle = _h1;
417         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
418
419         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
420         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
421                                         "smb2_getinfo_file failed");
422
423         /* re-authenticate as anonymous */
424
425         anon_creds = cli_credentials_init_anon(mem_ctx);
426         torture_assert(tctx, (anon_creds != NULL), "talloc error");
427
428         status = smb2_session_setup_spnego(tree->session,
429                                            anon_creds,
430                                            0 /* previous_session_id */);
431         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
432                                         "smb2_session_setup_spnego failed");
433
434         /* try to access the file via the old handle */
435
436         ZERO_STRUCT(qfinfo);
437
438         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
439         qfinfo.query_secdesc.in.file.handle = _h1;
440         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
441
442         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
443         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
444                                         "smb2_getinfo_file failed");
445
446         /* re-authenticate as original user again */
447
448         status = smb2_session_setup_spnego(tree->session,
449                                            popt_get_cmdline_credentials(),
450                                            0 /* previous_session_id */);
451         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
452                                         "smb2_session_setup_spnego failed");
453
454         /* try to access the file via the old handle */
455
456         ZERO_STRUCT(qfinfo);
457
458         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
459         qfinfo.query_secdesc.in.file.handle = _h1;
460         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
461
462         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
463         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
464                                         "smb2_getinfo_file failed");
465
466 done:
467         if (h1 != NULL) {
468                 smb2_util_close(tree, *h1);
469         }
470
471         smb2_util_unlink(tree, fname);
472
473         talloc_free(tree);
474
475         talloc_free(mem_ctx);
476
477         return ret;
478 }
479
480 /**
481  * test setting security descriptor after reauth.
482  */
483 bool test_session_reauth4(struct torture_context *tctx, struct smb2_tree *tree)
484 {
485         NTSTATUS status;
486         TALLOC_CTX *mem_ctx = talloc_new(tctx);
487         char fname[256];
488         struct smb2_handle _h1;
489         struct smb2_handle *h1 = NULL;
490         struct smb2_create io1;
491         bool ret = true;
492         union smb_fileinfo qfinfo;
493         union smb_setfileinfo sfinfo;
494         struct cli_credentials *anon_creds = NULL;
495         uint32_t secinfo_flags = SECINFO_OWNER
496                                 | SECINFO_GROUP
497                                 | SECINFO_DACL
498                                 | SECINFO_PROTECTED_DACL
499                                 | SECINFO_UNPROTECTED_DACL;
500         struct security_descriptor *sd1;
501         struct security_ace ace;
502         struct dom_sid *extra_sid;
503
504         /* Add some random component to the file name. */
505         snprintf(fname, sizeof(fname), "session_reauth4_%s.dat",
506                  generate_random_str(tctx, 8));
507
508         smb2_util_unlink(tree, fname);
509
510         smb2_oplock_create_share(&io1, fname,
511                                  smb2_util_share_access(""),
512                                  smb2_util_oplock_level("b"));
513
514         status = smb2_create(tree, mem_ctx, &io1);
515         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
516                                         "smb2_create failed");
517         _h1 = io1.out.file.handle;
518         h1 = &_h1;
519         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
520         torture_assert_int_equal(tctx, io1.out.oplock_level,
521                                         smb2_util_oplock_level("b"),
522                                         "oplock_level incorrect");
523
524         /* get the security descriptor */
525
526         ZERO_STRUCT(qfinfo);
527
528         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
529         qfinfo.query_secdesc.in.file.handle = _h1;
530         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
531
532         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
533         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
534                                         "smb2_getinfo_file failed");
535
536         sd1 = qfinfo.query_secdesc.out.sd;
537
538         /* re-authenticate as anonymous */
539
540         anon_creds = cli_credentials_init_anon(mem_ctx);
541         torture_assert(tctx, (anon_creds != NULL), "talloc error");
542
543         status = smb2_session_setup_spnego(tree->session,
544                                            anon_creds,
545                                            0 /* previous_session_id */);
546         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
547                                         "smb2_session_setup_spnego failed");
548
549         /* give full access on the file to anonymous */
550
551         extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
552
553         ZERO_STRUCT(ace);
554         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
555         ace.flags = 0;
556         ace.access_mask = SEC_STD_ALL | SEC_FILE_ALL;
557         ace.trustee = *extra_sid;
558
559         status = security_descriptor_dacl_add(sd1, &ace);
560         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
561                                         "security_descriptor_dacl_add failed");
562
563         ZERO_STRUCT(sfinfo);
564         sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
565         sfinfo.set_secdesc.in.file.handle = _h1;
566         sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
567         sfinfo.set_secdesc.in.sd = sd1;
568
569         status = smb2_setinfo_file(tree, &sfinfo);
570         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
571                                         "smb2_setinfo_file failed");
572
573         /* re-authenticate as original user again */
574
575         status = smb2_session_setup_spnego(tree->session,
576                                            popt_get_cmdline_credentials(),
577                                            0 /* previous_session_id */);
578         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
579                                         "smb2_session_setup_spnego failed");
580
581         /* re-get the security descriptor */
582
583         ZERO_STRUCT(qfinfo);
584
585         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
586         qfinfo.query_secdesc.in.file.handle = _h1;
587         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
588
589         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
590         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
591                                         "smb2_getinfo_file failed");
592
593         ret = true;
594
595 done:
596         if (h1 != NULL) {
597                 smb2_util_close(tree, *h1);
598         }
599
600         smb2_util_unlink(tree, fname);
601
602         talloc_free(tree);
603
604         talloc_free(mem_ctx);
605
606         return ret;
607 }
608
609 /**
610  * test renaming after reauth.
611  * compare security descriptors before and after rename/reauth
612  */
613 bool test_session_reauth5(struct torture_context *tctx, struct smb2_tree *tree)
614 {
615         NTSTATUS status;
616         TALLOC_CTX *mem_ctx = talloc_new(tctx);
617         char dname[128];
618         char fname[256];
619         char fname2[256];
620         struct smb2_handle _dh1;
621         struct smb2_handle *dh1 = NULL;
622         struct smb2_handle _h1;
623         struct smb2_handle *h1 = NULL;
624         struct smb2_create io1;
625         bool ret = true;
626         bool ok;
627         union smb_fileinfo qfinfo;
628         union smb_setfileinfo sfinfo;
629         struct cli_credentials *anon_creds = NULL;
630         uint32_t secinfo_flags = SECINFO_OWNER
631                                 | SECINFO_GROUP
632                                 | SECINFO_DACL
633                                 | SECINFO_PROTECTED_DACL
634                                 | SECINFO_UNPROTECTED_DACL;
635         struct security_descriptor *f_sd1;
636         struct security_descriptor *d_sd1 = NULL;
637         struct security_ace ace;
638         struct dom_sid *extra_sid;
639
640         /* Add some random component to the file name. */
641         snprintf(dname, sizeof(dname), "session_reauth5_%s.d",
642                  generate_random_str(tctx, 8));
643         snprintf(fname, sizeof(fname), "%s\\file.dat", dname);
644
645         ok = smb2_util_setup_dir(tctx, tree, dname);
646         torture_assert(tctx, ok, "smb2_util_setup_dir not ok");
647
648         status = torture_smb2_testdir(tree, dname, &_dh1);
649         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
650                                         "torture_smb2_testdir failed");
651         dh1 = &_dh1;
652
653         smb2_oplock_create_share(&io1, fname,
654                                  smb2_util_share_access(""),
655                                  smb2_util_oplock_level("b"));
656
657         status = smb2_create(tree, mem_ctx, &io1);
658         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
659                                         "smb2_create failed");
660         _h1 = io1.out.file.handle;
661         h1 = &_h1;
662         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
663         torture_assert_int_equal(tctx, io1.out.oplock_level,
664                                         smb2_util_oplock_level("b"),
665                                         "oplock_level incorrect");
666
667         /* get the security descriptor */
668
669         ZERO_STRUCT(qfinfo);
670
671         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
672         qfinfo.query_secdesc.in.file.handle = _h1;
673         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
674
675         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
676         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
677                                         "smb2_getinfo_file failed");
678
679         f_sd1 = qfinfo.query_secdesc.out.sd;
680
681         /* re-authenticate as anonymous */
682
683         anon_creds = cli_credentials_init_anon(mem_ctx);
684         torture_assert(tctx, (anon_creds != NULL), "talloc error");
685
686         status = smb2_session_setup_spnego(tree->session,
687                                            anon_creds,
688                                            0 /* previous_session_id */);
689         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
690                                         "smb2_session_setup_spnego failed");
691
692         /* try to rename the file: fails */
693
694         snprintf(fname2, sizeof(fname2), "%s\\file2.dat", dname);
695
696         status = smb2_util_unlink(tree, fname2);
697         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
698                                         "smb2_util_unlink failed");
699
700
701         ZERO_STRUCT(sfinfo);
702         sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
703         sfinfo.rename_information.in.file.handle = _h1;
704         sfinfo.rename_information.in.overwrite = true;
705         sfinfo.rename_information.in.new_name = fname2;
706
707         status = smb2_setinfo_file(tree, &sfinfo);
708         torture_assert_ntstatus_equal_goto(tctx, status,
709                                            NT_STATUS_ACCESS_DENIED,
710                                            ret, done, "smb2_setinfo_file "
711                                            "returned unexpected status");
712
713         /* re-authenticate as original user again */
714
715         status = smb2_session_setup_spnego(tree->session,
716                                            popt_get_cmdline_credentials(),
717                                            0 /* previous_session_id */);
718         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
719                                         "smb2_session_setup_spnego failed");
720
721         /* give full access on the file to anonymous */
722
723         extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
724
725         ZERO_STRUCT(ace);
726         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
727         ace.flags = 0;
728         ace.access_mask = SEC_RIGHTS_FILE_ALL;
729         ace.trustee = *extra_sid;
730
731         status = security_descriptor_dacl_add(f_sd1, &ace);
732         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
733                                         "security_descriptor_dacl_add failed");
734
735         ZERO_STRUCT(sfinfo);
736         sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
737         sfinfo.set_secdesc.in.file.handle = _h1;
738         sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
739         sfinfo.set_secdesc.in.sd = f_sd1;
740
741         status = smb2_setinfo_file(tree, &sfinfo);
742         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
743                                         "smb2_setinfo_file failed");
744
745         /* re-get the security descriptor */
746
747         ZERO_STRUCT(qfinfo);
748
749         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
750         qfinfo.query_secdesc.in.file.handle = _h1;
751         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
752
753         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
754         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
755                                         "smb2_getinfo_file failed");
756
757         /* re-authenticate as anonymous - again */
758
759         anon_creds = cli_credentials_init_anon(mem_ctx);
760         torture_assert(tctx, (anon_creds != NULL), "talloc error");
761
762         status = smb2_session_setup_spnego(tree->session,
763                                            anon_creds,
764                                            0 /* previous_session_id */);
765         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
766                                         "smb2_session_setup_spnego failed");
767
768         /* try to rename the file: 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         torture_assert_ntstatus_equal_goto(tctx, status,
778                                            NT_STATUS_ACCESS_DENIED,
779                                            ret, done, "smb2_setinfo_file "
780                                            "returned unexpected status");
781
782         /* give full access on the parent dir to anonymous */
783
784         ZERO_STRUCT(qfinfo);
785
786         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
787         qfinfo.query_secdesc.in.file.handle = _dh1;
788         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
789
790         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
791         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
792                                         "smb2_getinfo_file failed");
793
794         d_sd1 = qfinfo.query_secdesc.out.sd;
795
796         ZERO_STRUCT(ace);
797         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
798         ace.flags = 0;
799         ace.access_mask = SEC_RIGHTS_FILE_ALL;
800         ace.trustee = *extra_sid;
801
802         status = security_descriptor_dacl_add(d_sd1, &ace);
803         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
804                                         "security_descriptor_dacl_add failed");
805
806         ZERO_STRUCT(sfinfo);
807         sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
808         sfinfo.set_secdesc.in.file.handle = _dh1;
809         sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
810         sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
811         sfinfo.set_secdesc.in.sd = d_sd1;
812
813         status = smb2_setinfo_file(tree, &sfinfo);
814         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
815                                         "smb2_setinfo_file failed");
816
817         ZERO_STRUCT(qfinfo);
818
819         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
820         qfinfo.query_secdesc.in.file.handle = _dh1;
821         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
822
823         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
824         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
825                                         "smb2_getinfo_file failed");
826
827         status = smb2_util_close(tree, _dh1);
828         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
829                                         "smb2_util_close failed");
830         dh1 = NULL;
831
832         /* try to rename the file: still fails */
833
834         ZERO_STRUCT(sfinfo);
835         sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
836         sfinfo.rename_information.in.file.handle = _h1;
837         sfinfo.rename_information.in.overwrite = true;
838         sfinfo.rename_information.in.new_name = fname2;
839
840         status = smb2_setinfo_file(tree, &sfinfo);
841         torture_assert_ntstatus_equal_goto(tctx, status,
842                                         NT_STATUS_ACCESS_DENIED,
843                                         ret, done, "smb2_setinfo_file "
844                                         "returned unexpected status");
845
846         /* re-authenticate as original user - again */
847
848         status = smb2_session_setup_spnego(tree->session,
849                                            popt_get_cmdline_credentials(),
850                                            0 /* previous_session_id */);
851         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
852                                         "smb2_session_setup_spnego failed");
853
854         /* rename the file - for verification that it works */
855
856         ZERO_STRUCT(sfinfo);
857         sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
858         sfinfo.rename_information.in.file.handle = _h1;
859         sfinfo.rename_information.in.overwrite = true;
860         sfinfo.rename_information.in.new_name = fname2;
861
862         status = smb2_setinfo_file(tree, &sfinfo);
863         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
864                                         "smb2_setinfo_file failed");
865
866         /* closs the file, check it is gone and reopen under the new name */
867
868         status = smb2_util_close(tree, _h1);
869         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
870                                         "smb2_util_close failed");
871         ZERO_STRUCT(io1);
872
873         smb2_generic_create_share(&io1,
874                                   NULL /* lease */, false /* dir */,
875                                   fname,
876                                   NTCREATEX_DISP_OPEN,
877                                   smb2_util_share_access(""),
878                                   smb2_util_oplock_level("b"),
879                                   0 /* leasekey */, 0 /* leasestate */);
880
881         status = smb2_create(tree, mem_ctx, &io1);
882         torture_assert_ntstatus_equal_goto(tctx, status,
883                                         NT_STATUS_OBJECT_NAME_NOT_FOUND,
884                                         ret, done, "smb2_create "
885                                         "returned unexpected status");
886
887         ZERO_STRUCT(io1);
888
889         smb2_generic_create_share(&io1,
890                                   NULL /* lease */, false /* dir */,
891                                   fname2,
892                                   NTCREATEX_DISP_OPEN,
893                                   smb2_util_share_access(""),
894                                   smb2_util_oplock_level("b"),
895                                   0 /* leasekey */, 0 /* leasestate */);
896
897         status = smb2_create(tree, mem_ctx, &io1);
898         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
899                                         "smb2_create failed");
900         _h1 = io1.out.file.handle;
901         h1 = &_h1;
902         CHECK_CREATED(tctx, &io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
903         torture_assert_int_equal(tctx, io1.out.oplock_level,
904                                         smb2_util_oplock_level("b"),
905                                         "oplock_level incorrect");
906
907         /* try to access the file via the old handle */
908
909         ZERO_STRUCT(qfinfo);
910
911         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
912         qfinfo.query_secdesc.in.file.handle = _h1;
913         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
914
915         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
916         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
917                                         "smb2_getinfo_file failed");
918
919 done:
920         if (dh1 != NULL) {
921                 smb2_util_close(tree, *dh1);
922         }
923         if (h1 != NULL) {
924                 smb2_util_close(tree, *h1);
925         }
926
927         smb2_deltree(tree, dname);
928
929         talloc_free(tree);
930
931         talloc_free(mem_ctx);
932
933         return ret;
934 }
935
936 /**
937  * do reauth with wrong credentials,
938  * hence triggering the error path in reauth.
939  * The invalid reauth deletes the session.
940  */
941 bool test_session_reauth6(struct torture_context *tctx, struct smb2_tree *tree)
942 {
943         NTSTATUS status;
944         TALLOC_CTX *mem_ctx = talloc_new(tctx);
945         char fname[256];
946         struct smb2_handle _h1;
947         struct smb2_handle *h1 = NULL;
948         struct smb2_create io1;
949         bool ret = true;
950         char *corrupted_password;
951         struct cli_credentials *broken_creds;
952         bool ok;
953         bool encrypted;
954         NTSTATUS expected;
955         enum credentials_use_kerberos krb_state;
956
957         krb_state = cli_credentials_get_kerberos_state(
958                         popt_get_cmdline_credentials());
959         if (krb_state == CRED_MUST_USE_KERBEROS) {
960                 torture_skip(tctx,
961                              "Can't test failing session setup with kerberos.");
962         }
963
964         encrypted = smb2cli_tcon_is_encryption_on(tree->smbXcli);
965
966         /* Add some random component to the file name. */
967         snprintf(fname, sizeof(fname), "session_reauth1_%s.dat",
968                  generate_random_str(tctx, 8));
969
970         smb2_util_unlink(tree, fname);
971
972         smb2_oplock_create_share(&io1, fname,
973                                  smb2_util_share_access(""),
974                                  smb2_util_oplock_level("b"));
975         io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
976
977         status = smb2_create(tree, mem_ctx, &io1);
978         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
979                                         "smb2_create failed");
980         _h1 = io1.out.file.handle;
981         h1 = &_h1;
982         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
983         torture_assert_int_equal(tctx, io1.out.oplock_level,
984                                         smb2_util_oplock_level("b"),
985                                         "oplock_level incorrect");
986
987         /*
988          * reauthentication with invalid credentials:
989          */
990
991         broken_creds = cli_credentials_shallow_copy(mem_ctx,
992                                             popt_get_cmdline_credentials());
993         torture_assert(tctx, (broken_creds != NULL), "talloc error");
994
995         corrupted_password = talloc_asprintf(mem_ctx, "%s%s",
996                                 cli_credentials_get_password(broken_creds),
997                                 "corrupt");
998         torture_assert(tctx, (corrupted_password != NULL), "talloc error");
999
1000         ok = cli_credentials_set_password(broken_creds, corrupted_password,
1001                                           CRED_SPECIFIED);
1002         torture_assert(tctx, ok, "cli_credentials_set_password not ok");
1003
1004         status = smb2_session_setup_spnego(tree->session,
1005                                            broken_creds,
1006                                            0 /* previous_session_id */);
1007         torture_assert_ntstatus_equal_goto(tctx, status,
1008                                         NT_STATUS_LOGON_FAILURE, ret, done,
1009                                         "smb2_session_setup_spnego "
1010                                         "returned unexpected status");
1011
1012         torture_comment(tctx, "did failed reauth\n");
1013         /*
1014          * now verify that the invalid session reauth has closed our session
1015          */
1016
1017         if (encrypted) {
1018                 expected = NT_STATUS_CONNECTION_DISCONNECTED;
1019         } else {
1020                 expected = NT_STATUS_USER_SESSION_DELETED;
1021         }
1022
1023         smb2_oplock_create_share(&io1, fname,
1024                                  smb2_util_share_access(""),
1025                                  smb2_util_oplock_level("b"));
1026
1027         status = smb2_create(tree, mem_ctx, &io1);
1028         torture_assert_ntstatus_equal_goto(tctx, status, expected,
1029                                         ret, done, "smb2_create "
1030                                         "returned unexpected status");
1031
1032 done:
1033         if (h1 != NULL) {
1034                 smb2_util_close(tree, *h1);
1035         }
1036
1037         smb2_util_unlink(tree, fname);
1038
1039         talloc_free(tree);
1040
1041         talloc_free(mem_ctx);
1042
1043         return ret;
1044 }
1045
1046
1047 static bool test_session_expire1i(struct torture_context *tctx,
1048                                   bool force_signing,
1049                                   bool force_encryption)
1050 {
1051         NTSTATUS status;
1052         bool ret = false;
1053         struct smbcli_options options;
1054         const char *host = torture_setting_string(tctx, "host", NULL);
1055         const char *share = torture_setting_string(tctx, "share", NULL);
1056         struct cli_credentials *credentials = popt_get_cmdline_credentials();
1057         struct smb2_tree *tree = NULL;
1058         enum credentials_use_kerberos use_kerberos;
1059         char fname[256];
1060         struct smb2_handle _h1;
1061         struct smb2_handle *h1 = NULL;
1062         struct smb2_create io1;
1063         union smb_fileinfo qfinfo;
1064         size_t i;
1065
1066         use_kerberos = cli_credentials_get_kerberos_state(credentials);
1067         if (use_kerberos != CRED_MUST_USE_KERBEROS) {
1068                 torture_warning(tctx, "smb2.session.expire1 requires -k yes!");
1069                 torture_skip(tctx, "smb2.session.expire1 requires -k yes!");
1070         }
1071
1072         torture_assert_int_equal(tctx, use_kerberos, CRED_MUST_USE_KERBEROS,
1073                                  "please use -k yes");
1074
1075         cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
1076
1077         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
1078
1079         lpcfg_smbcli_options(tctx->lp_ctx, &options);
1080         if (force_signing) {
1081                 options.signing = SMB_SIGNING_REQUIRED;
1082         }
1083
1084         status = smb2_connect(tctx,
1085                               host,
1086                               lpcfg_smb_ports(tctx->lp_ctx),
1087                               share,
1088                               lpcfg_resolve_context(tctx->lp_ctx),
1089                               credentials,
1090                               &tree,
1091                               tctx->ev,
1092                               &options,
1093                               lpcfg_socket_options(tctx->lp_ctx),
1094                               lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1095                               );
1096         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1097                                         "smb2_connect failed");
1098
1099         if (force_encryption) {
1100                 status = smb2cli_session_encryption_on(tree->session->smbXcli);
1101                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1102                                         "smb2cli_session_encryption_on failed");
1103         }
1104
1105         /* Add some random component to the file name. */
1106         snprintf(fname, sizeof(fname), "session_expire1_%s.dat",
1107                  generate_random_str(tctx, 8));
1108
1109         smb2_util_unlink(tree, fname);
1110
1111         smb2_oplock_create_share(&io1, fname,
1112                                  smb2_util_share_access(""),
1113                                  smb2_util_oplock_level("b"));
1114         io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1115
1116         status = smb2_create(tree, tctx, &io1);
1117         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1118                                         "smb2_create failed");
1119         _h1 = io1.out.file.handle;
1120         h1 = &_h1;
1121         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1122         torture_assert_int_equal(tctx, io1.out.oplock_level,
1123                                         smb2_util_oplock_level("b"),
1124                                         "oplock_level incorrect");
1125
1126         /* get the security descriptor */
1127
1128         ZERO_STRUCT(qfinfo);
1129
1130         qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
1131         qfinfo.access_information.in.file.handle = _h1;
1132
1133         for (i=0; i < 2; i++) {
1134                 torture_comment(tctx, "query info => OK\n");
1135
1136                 ZERO_STRUCT(qfinfo.access_information.out);
1137                 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1138                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1139                                                 "smb2_getinfo_file failed");
1140
1141                 torture_comment(tctx, "sleep 10 seconds\n");
1142                 smb_msleep(10*1000);
1143
1144                 torture_comment(tctx, "query info => EXPIRED\n");
1145                 ZERO_STRUCT(qfinfo.access_information.out);
1146                 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1147                 torture_assert_ntstatus_equal_goto(tctx, status,
1148                                         NT_STATUS_NETWORK_SESSION_EXPIRED,
1149                                         ret, done, "smb2_getinfo_file "
1150                                         "returned unexpected status");
1151
1152                 /*
1153                  * the krb5 library may not handle expired creds
1154                  * well, lets start with an empty ccache.
1155                  */
1156                 cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
1157
1158                 if (!force_encryption) {
1159                         smb2cli_session_require_signed_response(
1160                                 tree->session->smbXcli, true);
1161                 }
1162
1163                 torture_comment(tctx, "reauth => OK\n");
1164                 status = smb2_session_setup_spnego(tree->session,
1165                                                    credentials,
1166                                                    0 /* previous_session_id */);
1167                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1168                                         "smb2_session_setup_spnego failed");
1169
1170                 smb2cli_session_require_signed_response(
1171                         tree->session->smbXcli, false);
1172         }
1173
1174         ZERO_STRUCT(qfinfo.access_information.out);
1175         status = smb2_getinfo_file(tree, tctx, &qfinfo);
1176         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1177                                         "smb2_getinfo_file failed");
1178
1179         ret = true;
1180 done:
1181         cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
1182
1183         if (h1 != NULL) {
1184                 smb2_util_close(tree, *h1);
1185         }
1186
1187         talloc_free(tree);
1188         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
1189         return ret;
1190 }
1191
1192 static bool test_session_expire1n(struct torture_context *tctx)
1193 {
1194         return test_session_expire1i(tctx,
1195                                      false,   /* force_signing */
1196                                      false); /* force_encryption */
1197 }
1198
1199 static bool test_session_expire1s(struct torture_context *tctx)
1200 {
1201         return test_session_expire1i(tctx,
1202                                      true,   /* force_signing */
1203                                      false); /* force_encryption */
1204 }
1205
1206 static bool test_session_expire1e(struct torture_context *tctx)
1207 {
1208         return test_session_expire1i(tctx,
1209                                      true,   /* force_signing */
1210                                      true); /* force_encryption */
1211 }
1212
1213 static bool test_session_expire2i(struct torture_context *tctx,
1214                                   bool force_encryption)
1215 {
1216         NTSTATUS status;
1217         bool ret = false;
1218         struct smbcli_options options;
1219         const char *host = torture_setting_string(tctx, "host", NULL);
1220         const char *share = torture_setting_string(tctx, "share", NULL);
1221         struct cli_credentials *credentials = popt_get_cmdline_credentials();
1222         struct smb2_tree *tree = NULL;
1223         const char *unc = NULL;
1224         struct smb2_tree *tree2 = NULL;
1225         struct tevent_req *subreq = NULL;
1226         uint32_t timeout_msec;
1227         enum credentials_use_kerberos use_kerberos;
1228         uint32_t caps;
1229         char fname[256];
1230         struct smb2_handle dh;
1231         struct smb2_handle dh2;
1232         struct smb2_handle _h1;
1233         struct smb2_handle *h1 = NULL;
1234         struct smb2_create io1;
1235         union smb_fileinfo qfinfo;
1236         union smb_setfileinfo sfinfo;
1237         struct smb2_flush flsh;
1238         struct smb2_read rd;
1239         const uint8_t wd = 0;
1240         struct smb2_lock lck;
1241         struct smb2_lock_element el;
1242         struct smb2_ioctl ctl;
1243         struct smb2_break oack;
1244         struct smb2_lease_break_ack lack;
1245         struct smb2_find fnd;
1246         union smb_search_data *d = NULL;
1247         unsigned int count;
1248         struct smb2_request *req = NULL;
1249         struct smb2_notify ntf1;
1250         struct smb2_notify ntf2;
1251
1252         use_kerberos = cli_credentials_get_kerberos_state(credentials);
1253         if (use_kerberos != CRED_MUST_USE_KERBEROS) {
1254                 torture_warning(tctx, "smb2.session.expire2 requires -k yes!");
1255                 torture_skip(tctx, "smb2.session.expire2 requires -k yes!");
1256         }
1257
1258         torture_assert_int_equal(tctx, use_kerberos, CRED_MUST_USE_KERBEROS,
1259                                  "please use -k yes");
1260
1261         cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
1262
1263         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
1264
1265         lpcfg_smbcli_options(tctx->lp_ctx, &options);
1266         options.signing = SMB_SIGNING_REQUIRED;
1267
1268         unc = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
1269         torture_assert(tctx, unc != NULL, "talloc_asprintf");
1270
1271         status = smb2_connect(tctx,
1272                               host,
1273                               lpcfg_smb_ports(tctx->lp_ctx),
1274                               share,
1275                               lpcfg_resolve_context(tctx->lp_ctx),
1276                               credentials,
1277                               &tree,
1278                               tctx->ev,
1279                               &options,
1280                               lpcfg_socket_options(tctx->lp_ctx),
1281                               lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1282                               );
1283         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1284                                         "smb2_connect failed");
1285
1286         if (force_encryption) {
1287                 status = smb2cli_session_encryption_on(tree->session->smbXcli);
1288                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1289                                         "smb2cli_session_encryption_on failed");
1290         }
1291
1292         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1293
1294         /* Add some random component to the file name. */
1295         snprintf(fname, sizeof(fname), "session_expire2_%s.dat",
1296                  generate_random_str(tctx, 8));
1297
1298         smb2_util_unlink(tree, fname);
1299
1300         status = smb2_util_roothandle(tree, &dh);
1301         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1302                                         "smb2_util_roothandle failed");
1303
1304         smb2_oplock_create_share(&io1, fname,
1305                                  smb2_util_share_access(""),
1306                                  smb2_util_oplock_level("b"));
1307         io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1308
1309         status = smb2_create(tree, tctx, &io1);
1310         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1311                                         "smb2_create failed");
1312         _h1 = io1.out.file.handle;
1313         h1 = &_h1;
1314         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1315         torture_assert_int_equal(tctx, io1.out.oplock_level,
1316                                         smb2_util_oplock_level("b"),
1317                                         "oplock_level incorrect");
1318
1319         /* get the security descriptor */
1320
1321         ZERO_STRUCT(qfinfo);
1322
1323         qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
1324         qfinfo.access_information.in.file.handle = _h1;
1325
1326         torture_comment(tctx, "query info => OK\n");
1327
1328         ZERO_STRUCT(qfinfo.access_information.out);
1329         status = smb2_getinfo_file(tree, tctx, &qfinfo);
1330         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1331                                         "smb2_getinfo_file failed");
1332
1333         torture_comment(tctx, "lock => OK\n");
1334         ZERO_STRUCT(lck);
1335         lck.in.locks            = &el;
1336         lck.in.lock_count       = 0x0001;
1337         lck.in.lock_sequence    = 0x00000000;
1338         lck.in.file.handle      = *h1;
1339         ZERO_STRUCT(el);
1340         el.flags                = SMB2_LOCK_FLAG_EXCLUSIVE |
1341                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1342         el.offset               = 0x0000000000000000;
1343         el.length               = 0x0000000000000001;
1344         status = smb2_lock(tree, &lck);
1345         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1346                                         "smb2_lock lock failed");
1347
1348         torture_comment(tctx, "1st notify => PENDING\n");
1349         ZERO_STRUCT(ntf1);
1350         ntf1.in.file.handle     = dh;
1351         ntf1.in.recursive       = 0x0000;
1352         ntf1.in.buffer_size     = 128;
1353         ntf1.in.completion_filter= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1354         ntf1.in.unknown         = 0x00000000;
1355         req = smb2_notify_send(tree, &ntf1);
1356
1357         while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
1358                 if (tevent_loop_once(tctx->ev) != 0) {
1359                         break;
1360                 }
1361         }
1362
1363         torture_assert_goto(tctx, req->state <= SMB2_REQUEST_RECV, ret, done,
1364                             "smb2_notify finished");
1365
1366         torture_comment(tctx, "sleep 10 seconds\n");
1367         smb_msleep(10*1000);
1368
1369         torture_comment(tctx, "query info => EXPIRED\n");
1370         ZERO_STRUCT(qfinfo.access_information.out);
1371         status = smb2_getinfo_file(tree, tctx, &qfinfo);
1372         torture_assert_ntstatus_equal_goto(tctx, status,
1373                                 NT_STATUS_NETWORK_SESSION_EXPIRED,
1374                                 ret, done, "smb2_getinfo_file "
1375                                 "returned unexpected status");
1376
1377
1378         torture_comment(tctx, "set info => EXPIRED\n");
1379         ZERO_STRUCT(sfinfo);
1380         sfinfo.end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1381         sfinfo.end_of_file_info.in.file.handle = *h1;
1382         sfinfo.end_of_file_info.in.size = 1;
1383         status = smb2_setinfo_file(tree, &sfinfo);
1384         torture_assert_ntstatus_equal_goto(tctx, status,
1385                                 NT_STATUS_NETWORK_SESSION_EXPIRED,
1386                                 ret, done, "smb2_setinfo_file "
1387                                 "returned unexpected status");
1388
1389         torture_comment(tctx, "flush => EXPIRED\n");
1390         ZERO_STRUCT(flsh);
1391         flsh.in.file.handle = *h1;
1392         status = smb2_flush(tree, &flsh);
1393         torture_assert_ntstatus_equal_goto(tctx, status,
1394                                 NT_STATUS_NETWORK_SESSION_EXPIRED,
1395                                 ret, done, "smb2_flush "
1396                                 "returned unexpected status");
1397
1398         torture_comment(tctx, "read => EXPIRED\n");
1399         ZERO_STRUCT(rd);
1400         rd.in.file.handle = *h1;
1401         rd.in.length      = 5;
1402         rd.in.offset      = 0;
1403         status = smb2_read(tree, tctx, &rd);
1404         torture_assert_ntstatus_equal_goto(tctx, status,
1405                                 NT_STATUS_NETWORK_SESSION_EXPIRED,
1406                                 ret, done, "smb2_read "
1407                                 "returned unexpected status");
1408
1409         torture_comment(tctx, "write => EXPIRED\n");
1410         status = smb2_util_write(tree, *h1, &wd, 0, 1);
1411         torture_assert_ntstatus_equal_goto(tctx, status,
1412                                 NT_STATUS_NETWORK_SESSION_EXPIRED,
1413                                 ret, done, "smb2_util_write "
1414                                 "returned unexpected status");
1415
1416         torture_comment(tctx, "ioctl => EXPIRED\n");
1417         ZERO_STRUCT(ctl);
1418         ctl.in.file.handle = *h1;
1419         ctl.in.function = FSCTL_SRV_ENUM_SNAPS;
1420         ctl.in.max_response_size = 16;
1421         ctl.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
1422         status = smb2_ioctl(tree, tctx, &ctl);
1423         torture_assert_ntstatus_equal_goto(tctx, status,
1424                                 NT_STATUS_NETWORK_SESSION_EXPIRED,
1425                                 ret, done, "smb2_ioctl "
1426                                 "returned unexpected status");
1427
1428         torture_comment(tctx, "oplock ack => EXPIRED\n");
1429         ZERO_STRUCT(oack);
1430         oack.in.file.handle = *h1;
1431         status = smb2_break(tree, &oack);
1432         torture_assert_ntstatus_equal_goto(tctx, status,
1433                                 NT_STATUS_NETWORK_SESSION_EXPIRED,
1434                                 ret, done, "smb2_break "
1435                                 "returned unexpected status");
1436
1437         if (caps & SMB2_CAP_LEASING) {
1438                 torture_comment(tctx, "lease ack => EXPIRED\n");
1439                 ZERO_STRUCT(lack);
1440                 lack.in.lease.lease_version = 1;
1441                 lack.in.lease.lease_key.data[0] = 1;
1442                 lack.in.lease.lease_key.data[1] = 2;
1443                 status = smb2_lease_break_ack(tree, &lack);
1444                 torture_assert_ntstatus_equal_goto(tctx, status,
1445                                         NT_STATUS_NETWORK_SESSION_EXPIRED,
1446                                         ret, done, "smb2_break "
1447                                         "returned unexpected status");
1448         }
1449
1450         torture_comment(tctx, "query directory => EXPIRED\n");
1451         ZERO_STRUCT(fnd);
1452         fnd.in.file.handle      = dh;
1453         fnd.in.pattern          = "*";
1454         fnd.in.continue_flags   = SMB2_CONTINUE_FLAG_SINGLE;
1455         fnd.in.max_response_size= 0x100;
1456         fnd.in.level            = SMB2_FIND_BOTH_DIRECTORY_INFO;
1457         status = smb2_find_level(tree, tree, &fnd, &count, &d);
1458         torture_assert_ntstatus_equal_goto(tctx, status,
1459                                 NT_STATUS_NETWORK_SESSION_EXPIRED,
1460                                 ret, done, "smb2_find_level "
1461                                 "returned unexpected status");
1462
1463         torture_comment(tctx, "1st notify => CANCEL\n");
1464         smb2_cancel(req);
1465
1466         torture_comment(tctx, "2nd notify => EXPIRED\n");
1467         ZERO_STRUCT(ntf2);
1468         ntf2.in.file.handle     = dh;
1469         ntf2.in.recursive       = 0x0000;
1470         ntf2.in.buffer_size     = 128;
1471         ntf2.in.completion_filter= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1472         ntf2.in.unknown         = 0x00000000;
1473         status = smb2_notify(tree, tctx, &ntf2);
1474         torture_assert_ntstatus_equal_goto(tctx, status,
1475                                 NT_STATUS_NETWORK_SESSION_EXPIRED,
1476                                 ret, done, "smb2_notify "
1477                                 "returned unexpected status");
1478
1479         torture_assert_goto(tctx, req->state > SMB2_REQUEST_RECV, ret, done,
1480                             "smb2_notify (1st) not finished");
1481
1482         status = smb2_notify_recv(req, tctx, &ntf1);
1483         torture_assert_ntstatus_equal_goto(tctx, status,
1484                                 NT_STATUS_CANCELLED,
1485                                 ret, done, "smb2_notify cancelled"
1486                                 "returned unexpected status");
1487
1488         torture_comment(tctx, "tcon => EXPIRED\n");
1489         tree2 = smb2_tree_init(tree->session, tctx, false);
1490         torture_assert(tctx, tree2 != NULL, "smb2_tree_init");
1491         timeout_msec = tree->session->transport->options.request_timeout * 1000;
1492         subreq = smb2cli_tcon_send(tree2, tctx->ev,
1493                                    tree2->session->transport->conn,
1494                                    timeout_msec,
1495                                    tree2->session->smbXcli,
1496                                    tree2->smbXcli,
1497                                    0, /* flags */
1498                                    unc);
1499         torture_assert(tctx, subreq != NULL, "smb2cli_tcon_send");
1500         torture_assert(tctx,
1501                        tevent_req_poll_ntstatus(subreq, tctx->ev, &status),
1502                        "tevent_req_poll_ntstatus");
1503         status = smb2cli_tcon_recv(subreq);
1504         TALLOC_FREE(subreq);
1505         torture_assert_ntstatus_equal_goto(tctx, status,
1506                                 NT_STATUS_NETWORK_SESSION_EXPIRED,
1507                                 ret, done, "smb2cli_tcon"
1508                                 "returned unexpected status");
1509
1510         torture_comment(tctx, "create => EXPIRED\n");
1511         status = smb2_util_roothandle(tree, &dh2);
1512         torture_assert_ntstatus_equal_goto(tctx, status,
1513                                 NT_STATUS_NETWORK_SESSION_EXPIRED,
1514                                 ret, done, "smb2_util_roothandle"
1515                                 "returned unexpected status");
1516
1517         torture_comment(tctx, "tdis => EXPIRED\n");
1518         status = smb2_tdis(tree);
1519         torture_assert_ntstatus_equal_goto(tctx, status,
1520                                 NT_STATUS_NETWORK_SESSION_EXPIRED,
1521                                 ret, done, "smb2cli_tdis"
1522                                 "returned unexpected status");
1523
1524         /*
1525          * (Un)Lock, Close and Logoff are still possible
1526          */
1527
1528         torture_comment(tctx, "1st unlock => OK\n");
1529         el.flags                = SMB2_LOCK_FLAG_UNLOCK;
1530         status = smb2_lock(tree, &lck);
1531         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1532                                         "smb2_lock unlock failed");
1533
1534         torture_comment(tctx, "2nd unlock => RANGE_NOT_LOCKED\n");
1535         status = smb2_lock(tree, &lck);
1536         torture_assert_ntstatus_equal_goto(tctx, status,
1537                                 NT_STATUS_RANGE_NOT_LOCKED,
1538                                 ret, done, "smb2_lock 2nd unlock"
1539                                 "returned unexpected status");
1540
1541         torture_comment(tctx, "lock => EXPIRED\n");
1542         el.flags                = SMB2_LOCK_FLAG_EXCLUSIVE |
1543                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
1544         status = smb2_lock(tree, &lck);
1545         torture_assert_ntstatus_equal_goto(tctx, status,
1546                                 NT_STATUS_NETWORK_SESSION_EXPIRED,
1547                                 ret, done, "smb2_util_roothandle"
1548                                 "returned unexpected status");
1549
1550         torture_comment(tctx, "close => OK\n");
1551         status = smb2_util_close(tree, *h1);
1552         h1 = NULL;
1553         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1554                                         "smb2_close failed");
1555
1556         torture_comment(tctx, "echo without session => OK\n");
1557         status = smb2_keepalive(tree->session->transport);
1558         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1559                                         "smb2_keepalive without session failed");
1560
1561         torture_comment(tctx, "echo with session => OK\n");
1562         req = smb2_keepalive_send(tree->session->transport, tree->session);
1563         status = smb2_keepalive_recv(req);
1564         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1565                                         "smb2_keepalive with session failed");
1566
1567         torture_comment(tctx, "logoff => OK\n");
1568         status = smb2_logoff(tree->session);
1569         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1570                                         "smb2_logoff failed");
1571
1572         ret = true;
1573 done:
1574         cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
1575
1576         if (h1 != NULL) {
1577                 smb2_util_close(tree, *h1);
1578         }
1579
1580         talloc_free(tree);
1581         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
1582         return ret;
1583 }
1584
1585 static bool test_session_expire2s(struct torture_context *tctx)
1586 {
1587         return test_session_expire2i(tctx,
1588                                      false); /* force_encryption */
1589 }
1590
1591 static bool test_session_expire2e(struct torture_context *tctx)
1592 {
1593         return test_session_expire2i(tctx,
1594                                      true); /* force_encryption */
1595 }
1596
1597 static bool test_session_expire_disconnect(struct torture_context *tctx)
1598 {
1599         NTSTATUS status;
1600         bool ret = false;
1601         struct smbcli_options options;
1602         const char *host = torture_setting_string(tctx, "host", NULL);
1603         const char *share = torture_setting_string(tctx, "share", NULL);
1604         struct cli_credentials *credentials = popt_get_cmdline_credentials();
1605         struct smb2_tree *tree = NULL;
1606         enum credentials_use_kerberos use_kerberos;
1607         char fname[256];
1608         struct smb2_handle _h1;
1609         struct smb2_handle *h1 = NULL;
1610         struct smb2_create io1;
1611         union smb_fileinfo qfinfo;
1612         bool connected;
1613
1614         use_kerberos = cli_credentials_get_kerberos_state(credentials);
1615         if (use_kerberos != CRED_MUST_USE_KERBEROS) {
1616                 torture_warning(tctx, "smb2.session.expire1 requires -k yes!");
1617                 torture_skip(tctx, "smb2.session.expire1 requires -k yes!");
1618         }
1619
1620         cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
1621
1622         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
1623         lpcfg_smbcli_options(tctx->lp_ctx, &options);
1624         options.signing = SMB_SIGNING_REQUIRED;
1625
1626         status = smb2_connect(tctx,
1627                               host,
1628                               lpcfg_smb_ports(tctx->lp_ctx),
1629                               share,
1630                               lpcfg_resolve_context(tctx->lp_ctx),
1631                               credentials,
1632                               &tree,
1633                               tctx->ev,
1634                               &options,
1635                               lpcfg_socket_options(tctx->lp_ctx),
1636                               lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1637                               );
1638         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1639                                         "smb2_connect failed");
1640
1641         smbXcli_session_set_disconnect_expired(tree->session->smbXcli);
1642
1643         /* Add some random component to the file name. */
1644         snprintf(fname, sizeof(fname), "session_expire1_%s.dat",
1645                  generate_random_str(tctx, 8));
1646
1647         smb2_util_unlink(tree, fname);
1648
1649         smb2_oplock_create_share(&io1, fname,
1650                                  smb2_util_share_access(""),
1651                                  smb2_util_oplock_level("b"));
1652         io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1653
1654         status = smb2_create(tree, tctx, &io1);
1655         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1656                                         "smb2_create failed");
1657         _h1 = io1.out.file.handle;
1658         h1 = &_h1;
1659         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1660         torture_assert_int_equal(tctx, io1.out.oplock_level,
1661                                         smb2_util_oplock_level("b"),
1662                                         "oplock_level incorrect");
1663
1664         /* get the security descriptor */
1665
1666         ZERO_STRUCT(qfinfo);
1667
1668         qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
1669         qfinfo.access_information.in.file.handle = _h1;
1670
1671         torture_comment(tctx, "query info => OK\n");
1672
1673         ZERO_STRUCT(qfinfo.access_information.out);
1674         status = smb2_getinfo_file(tree, tctx, &qfinfo);
1675         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1676                                         "smb2_getinfo_file failed");
1677
1678         torture_comment(tctx, "sleep 10 seconds\n");
1679         smb_msleep(10*1000);
1680
1681         torture_comment(tctx, "query info => EXPIRED\n");
1682         ZERO_STRUCT(qfinfo.access_information.out);
1683         status = smb2_getinfo_file(tree, tctx, &qfinfo);
1684         torture_assert_ntstatus_equal_goto(tctx, status,
1685                                            NT_STATUS_NETWORK_SESSION_EXPIRED,
1686                                            ret, done, "smb2_getinfo_file "
1687                                            "returned unexpected status");
1688
1689         connected = smbXcli_conn_is_connected(tree->session->transport->conn);
1690         torture_assert_goto(tctx, !connected, ret, done, "connected\n");
1691
1692         ret = true;
1693 done:
1694         cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
1695
1696         if (h1 != NULL) {
1697                 smb2_util_close(tree, *h1);
1698         }
1699
1700         talloc_free(tree);
1701         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
1702         return ret;
1703 }
1704
1705 bool test_session_bind1(struct torture_context *tctx, struct smb2_tree *tree1)
1706 {
1707         const char *host = torture_setting_string(tctx, "host", NULL);
1708         const char *share = torture_setting_string(tctx, "share", NULL);
1709         struct cli_credentials *credentials = popt_get_cmdline_credentials();
1710         NTSTATUS status;
1711         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1712         char fname[256];
1713         struct smb2_handle _h1;
1714         struct smb2_handle *h1 = NULL;
1715         struct smb2_create io1;
1716         union smb_fileinfo qfinfo;
1717         bool ret = false;
1718         struct smb2_tree *tree2 = NULL;
1719         struct smb2_transport *transport1 = tree1->session->transport;
1720         struct smb2_transport *transport2 = NULL;
1721         struct smb2_session *session1_1 = tree1->session;
1722         struct smb2_session *session1_2 = NULL;
1723         struct smb2_session *session2_1 = NULL;
1724         struct smb2_session *session2_2 = NULL;
1725         uint32_t caps;
1726
1727         caps = smb2cli_conn_server_capabilities(transport1->conn);
1728         if (!(caps & SMB2_CAP_MULTI_CHANNEL)) {
1729                 torture_skip(tctx, "server doesn't support SMB2_CAP_MULTI_CHANNEL\n");
1730         }
1731
1732         /* Add some random component to the file name. */
1733         snprintf(fname, sizeof(fname), "session_bind1_%s.dat",
1734                  generate_random_str(tctx, 8));
1735
1736         smb2_util_unlink(tree1, fname);
1737
1738         smb2_oplock_create_share(&io1, fname,
1739                                  smb2_util_share_access(""),
1740                                  smb2_util_oplock_level("b"));
1741
1742         status = smb2_create(tree1, mem_ctx, &io1);
1743         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1744                                         "smb2_create failed");
1745         _h1 = io1.out.file.handle;
1746         h1 = &_h1;
1747         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1748         torture_assert_int_equal(tctx, io1.out.oplock_level,
1749                                         smb2_util_oplock_level("b"),
1750                                         "oplock_level incorrect");
1751
1752         status = smb2_connect(tctx,
1753                               host,
1754                               lpcfg_smb_ports(tctx->lp_ctx),
1755                               share,
1756                               lpcfg_resolve_context(tctx->lp_ctx),
1757                               credentials,
1758                               &tree2,
1759                               tctx->ev,
1760                               &transport1->options,
1761                               lpcfg_socket_options(tctx->lp_ctx),
1762                               lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1763                               );
1764         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1765                                         "smb2_connect failed");
1766         session2_2 = tree2->session;
1767         transport2 = tree2->session->transport;
1768
1769         /*
1770          * Now bind the 2nd transport connection to the 1st session
1771          */
1772         session1_2 = smb2_session_channel(transport2,
1773                                           lpcfg_gensec_settings(tctx, tctx->lp_ctx),
1774                                           tree2,
1775                                           session1_1);
1776         torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
1777
1778         status = smb2_session_setup_spnego(session1_2,
1779                                            popt_get_cmdline_credentials(),
1780                                            0 /* previous_session_id */);
1781         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1782                                         "smb2_session_setup_spnego failed");
1783
1784         /* use the 1st connection, 1st session */
1785         ZERO_STRUCT(qfinfo);
1786         qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
1787         qfinfo.generic.in.file.handle = _h1;
1788         tree1->session = session1_1;
1789         status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
1790         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1791                                         "smb2_getinfo_file failed");
1792
1793         /* use the 2nd connection, 1st session */
1794         ZERO_STRUCT(qfinfo);
1795         qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
1796         qfinfo.generic.in.file.handle = _h1;
1797         tree1->session = session1_2;
1798         status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
1799         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1800                                         "smb2_getinfo_file failed");
1801
1802         tree1->session = session1_1;
1803         status = smb2_util_close(tree1, *h1);
1804         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1805                                         "smb2_util_close failed");
1806         h1 = NULL;
1807
1808         /*
1809          * Now bind the 1st transport connection to the 2nd session
1810          */
1811         session2_1 = smb2_session_channel(transport1,
1812                                           lpcfg_gensec_settings(tctx, tctx->lp_ctx),
1813                                           tree1,
1814                                           session2_2);
1815         torture_assert(tctx, session2_1 != NULL, "smb2_session_channel failed");
1816
1817         status = smb2_session_setup_spnego(session2_1,
1818                                            popt_get_cmdline_credentials(),
1819                                            0 /* previous_session_id */);
1820         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1821                                         "smb2_session_setup_spnego failed");
1822
1823         tree2->session = session2_1;
1824         status = smb2_util_unlink(tree2, fname);
1825         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1826                                         "smb2_util_unlink failed");
1827         ret = true;
1828 done:
1829         talloc_free(tree2);
1830         tree1->session = session1_1;
1831
1832         if (h1 != NULL) {
1833                 smb2_util_close(tree1, *h1);
1834         }
1835
1836         smb2_util_unlink(tree1, fname);
1837
1838         talloc_free(tree1);
1839
1840         talloc_free(mem_ctx);
1841
1842         return ret;
1843 }
1844
1845 struct torture_suite *torture_smb2_session_init(TALLOC_CTX *ctx)
1846 {
1847         struct torture_suite *suite =
1848             torture_suite_create(ctx, "session");
1849
1850         torture_suite_add_1smb2_test(suite, "reconnect1", test_session_reconnect1);
1851         torture_suite_add_1smb2_test(suite, "reconnect2", test_session_reconnect2);
1852         torture_suite_add_1smb2_test(suite, "reauth1", test_session_reauth1);
1853         torture_suite_add_1smb2_test(suite, "reauth2", test_session_reauth2);
1854         torture_suite_add_1smb2_test(suite, "reauth3", test_session_reauth3);
1855         torture_suite_add_1smb2_test(suite, "reauth4", test_session_reauth4);
1856         torture_suite_add_1smb2_test(suite, "reauth5", test_session_reauth5);
1857         torture_suite_add_1smb2_test(suite, "reauth6", test_session_reauth6);
1858         torture_suite_add_simple_test(suite, "expire1n", test_session_expire1n);
1859         torture_suite_add_simple_test(suite, "expire1s", test_session_expire1s);
1860         torture_suite_add_simple_test(suite, "expire1e", test_session_expire1e);
1861         torture_suite_add_simple_test(suite, "expire2s", test_session_expire2s);
1862         torture_suite_add_simple_test(suite, "expire2e", test_session_expire2e);
1863         torture_suite_add_simple_test(suite, "expire_disconnect",
1864                                       test_session_expire_disconnect);
1865         torture_suite_add_1smb2_test(suite, "bind1", test_session_bind1);
1866
1867         suite->description = talloc_strdup(suite, "SMB2-SESSION tests");
1868
1869         return suite;
1870 }