s4: popt: Global replace of cmdline_credentials -> popt_get_cmdline_credentials().
[gd/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
35 #define CHECK_CREATED(tctx, __io, __created, __attribute)                       \
36         do {                                                                    \
37                 torture_assert_int_equal(tctx, (__io)->out.create_action,       \
38                                                 NTCREATEX_ACTION_ ## __created, \
39                                                 "out.create_action incorrect"); \
40                 torture_assert_int_equal(tctx, (__io)->out.alloc_size, 0,       \
41                                                 "out.alloc_size incorrect");    \
42                 torture_assert_int_equal(tctx, (__io)->out.size, 0,             \
43                                                 "out.size incorrect");          \
44                 torture_assert_int_equal(tctx, (__io)->out.file_attr,           \
45                                                 (__attribute),                  \
46                                                 "out.file_attr incorrect");     \
47                 torture_assert_int_equal(tctx, (__io)->out.reserved2, 0,        \
48                                 "out.reserverd2 incorrect");                    \
49         } while(0)
50
51 /**
52  * basic test for doing a session reconnect
53  */
54 bool test_session_reconnect1(struct torture_context *tctx, struct smb2_tree *tree)
55 {
56         NTSTATUS status;
57         TALLOC_CTX *mem_ctx = talloc_new(tctx);
58         char fname[256];
59         struct smb2_handle _h1;
60         struct smb2_handle *h1 = NULL;
61         struct smb2_handle _h2;
62         struct smb2_handle *h2 = NULL;
63         struct smb2_create io1, io2;
64         uint64_t previous_session_id;
65         bool ret = true;
66         struct smb2_tree *tree2 = NULL;
67         union smb_fileinfo qfinfo;
68
69         /* Add some random component to the file name. */
70         snprintf(fname, sizeof(fname), "session_reconnect_%s.dat",
71                  generate_random_str(tctx, 8));
72
73         smb2_util_unlink(tree, fname);
74
75         smb2_oplock_create_share(&io1, fname,
76                                  smb2_util_share_access(""),
77                                  smb2_util_oplock_level("b"));
78
79         status = smb2_create(tree, mem_ctx, &io1);
80         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
81                                         "smb2_create failed");
82         _h1 = io1.out.file.handle;
83         h1 = &_h1;
84         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
85         torture_assert_int_equal(tctx, io1.out.oplock_level,
86                                         smb2_util_oplock_level("b"),
87                                         "oplock_level incorrect");
88
89         /* disconnect, reconnect and then do durable reopen */
90         previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
91
92         torture_assert_goto(tctx, torture_smb2_connection_ext(tctx, previous_session_id,
93                             &tree->session->transport->options, &tree2),
94                             ret, done,
95                             "session reconnect failed\n");
96
97         /* try to access the file via the old handle */
98
99         ZERO_STRUCT(qfinfo);
100         qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
101         qfinfo.generic.in.file.handle = _h1;
102         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
103         torture_assert_ntstatus_equal_goto(tctx, status,
104                                            NT_STATUS_USER_SESSION_DELETED,
105                                            ret, done, "smb2_getinfo_file "
106                                            "returned unexpected status");
107         h1 = NULL;
108
109         smb2_oplock_create_share(&io2, fname,
110                                  smb2_util_share_access(""),
111                                  smb2_util_oplock_level("b"));
112
113         status = smb2_create(tree2, mem_ctx, &io2);
114         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
115                                         "smb2_create failed");
116
117         CHECK_CREATED(tctx, &io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
118         torture_assert_int_equal(tctx, io1.out.oplock_level,
119                                         smb2_util_oplock_level("b"),
120                                         "oplock_level incorrect");
121         _h2 = io2.out.file.handle;
122         h2 = &_h2;
123
124 done:
125         if (h1 != NULL) {
126                 smb2_util_close(tree, *h1);
127         }
128         if (h2 != NULL) {
129                 smb2_util_close(tree2, *h2);
130         }
131
132         if (tree2 != NULL) {
133                 smb2_util_unlink(tree2, fname);
134         }
135         smb2_util_unlink(tree, fname);
136
137         talloc_free(tree);
138         talloc_free(tree2);
139
140         talloc_free(mem_ctx);
141
142         return ret;
143 }
144
145 /**
146  * basic test for doing a session reconnect on one connection
147  */
148 bool test_session_reconnect2(struct torture_context *tctx, struct smb2_tree *tree)
149 {
150         NTSTATUS status;
151         TALLOC_CTX *mem_ctx = talloc_new(tctx);
152         char fname[256];
153         struct smb2_handle _h1;
154         struct smb2_handle *h1 = NULL;
155         struct smb2_create io1;
156         uint64_t previous_session_id;
157         bool ret = true;
158         struct smb2_session *session2 = NULL;
159         union smb_fileinfo qfinfo;
160
161         /* Add some random component to the file name. */
162         snprintf(fname, sizeof(fname), "session_reconnect_%s.dat",
163                  generate_random_str(tctx, 8));
164
165         smb2_util_unlink(tree, fname);
166
167         smb2_oplock_create_share(&io1, fname,
168                                  smb2_util_share_access(""),
169                                  smb2_util_oplock_level("b"));
170         io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
171
172         status = smb2_create(tree, mem_ctx, &io1);
173         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
174                                         "smb2_create failed");
175         _h1 = io1.out.file.handle;
176         h1 = &_h1;
177         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
178         torture_assert_int_equal(tctx, io1.out.oplock_level,
179                                         smb2_util_oplock_level("b"),
180                                         "oplock_level incorrect");
181
182         /* disconnect, reconnect and then do durable reopen */
183         previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
184
185         torture_assert(tctx, torture_smb2_session_setup(tctx, tree->session->transport,
186                                 previous_session_id, tctx, &session2),
187                                 "session reconnect (on the same connection) failed");
188
189         /* try to access the file via the old handle */
190
191         ZERO_STRUCT(qfinfo);
192         qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
193         qfinfo.generic.in.file.handle = _h1;
194         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
195         torture_assert_ntstatus_equal_goto(tctx, status,
196                                            NT_STATUS_USER_SESSION_DELETED,
197                                            ret, done, "smb2_getinfo_file "
198                                            "returned unexpected status");
199         h1 = NULL;
200
201 done:
202         if (h1 != NULL) {
203                 smb2_util_close(tree, *h1);
204         }
205
206         talloc_free(tree);
207         talloc_free(session2);
208
209         talloc_free(mem_ctx);
210
211         return ret;
212 }
213
214 bool test_session_reauth1(struct torture_context *tctx, struct smb2_tree *tree)
215 {
216         NTSTATUS status;
217         TALLOC_CTX *mem_ctx = talloc_new(tctx);
218         char fname[256];
219         struct smb2_handle _h1;
220         struct smb2_handle *h1 = NULL;
221         struct smb2_create io1;
222         bool ret = true;
223         union smb_fileinfo qfinfo;
224
225         /* Add some random component to the file name. */
226         snprintf(fname, sizeof(fname), "session_reauth1_%s.dat",
227                  generate_random_str(tctx, 8));
228
229         smb2_util_unlink(tree, fname);
230
231         smb2_oplock_create_share(&io1, fname,
232                                  smb2_util_share_access(""),
233                                  smb2_util_oplock_level("b"));
234
235         status = smb2_create(tree, mem_ctx, &io1);
236         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
237                                         "smb2_create failed");
238         _h1 = io1.out.file.handle;
239         h1 = &_h1;
240         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
241         torture_assert_int_equal(tctx, io1.out.oplock_level,
242                                         smb2_util_oplock_level("b"),
243                                         "oplock_level incorrect");
244
245         status = smb2_session_setup_spnego(tree->session,
246                                            popt_get_cmdline_credentials(),
247                                            0 /* previous_session_id */);
248         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
249                                         "smb2_session_setup_spnego failed");
250
251         /* try to access the file via the old handle */
252
253         ZERO_STRUCT(qfinfo);
254         qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
255         qfinfo.generic.in.file.handle = _h1;
256         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
257         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
258                                         "smb2_getinfo_file failed");
259
260         status = smb2_session_setup_spnego(tree->session,
261                                            popt_get_cmdline_credentials(),
262                                            0 /* previous_session_id */);
263         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
264                                         "smb2_session_setup_spnego failed");
265
266         /* try to access the file via the old handle */
267
268         ZERO_STRUCT(qfinfo);
269         qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
270         qfinfo.generic.in.file.handle = _h1;
271         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
272         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
273                                         "smb2_getinfo_file failed");
274
275 done:
276         if (h1 != NULL) {
277                 smb2_util_close(tree, *h1);
278         }
279
280         smb2_util_unlink(tree, fname);
281
282         talloc_free(tree);
283
284         talloc_free(mem_ctx);
285
286         return ret;
287 }
288
289 bool test_session_reauth2(struct torture_context *tctx, struct smb2_tree *tree)
290 {
291         NTSTATUS status;
292         TALLOC_CTX *mem_ctx = talloc_new(tctx);
293         char fname[256];
294         struct smb2_handle _h1;
295         struct smb2_handle *h1 = NULL;
296         struct smb2_create io1;
297         bool ret = true;
298         union smb_fileinfo qfinfo;
299         struct cli_credentials *anon_creds = NULL;
300
301         /* Add some random component to the file name. */
302         snprintf(fname, sizeof(fname), "session_reauth2_%s.dat",
303                  generate_random_str(tctx, 8));
304
305         smb2_util_unlink(tree, fname);
306
307         smb2_oplock_create_share(&io1, fname,
308                                  smb2_util_share_access(""),
309                                  smb2_util_oplock_level("b"));
310
311         status = smb2_create(tree, mem_ctx, &io1);
312         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
313                                         "smb2_create failed");
314         _h1 = io1.out.file.handle;
315         h1 = &_h1;
316         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
317         torture_assert_int_equal(tctx, io1.out.oplock_level,
318                                         smb2_util_oplock_level("b"),
319                                         "oplock_level incorrect");
320
321         /* re-authenticate as anonymous */
322
323         anon_creds = cli_credentials_init_anon(mem_ctx);
324         torture_assert(tctx, (anon_creds != NULL), "talloc error");
325
326         status = smb2_session_setup_spnego(tree->session,
327                                            anon_creds,
328                                            0 /* previous_session_id */);
329         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
330                                         "smb2_session_setup_spnego failed");
331
332         /* try to access the file via the old handle */
333
334         ZERO_STRUCT(qfinfo);
335         qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
336         qfinfo.generic.in.file.handle = _h1;
337         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
338         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
339                                         "smb2_getinfo_file failed");
340
341         /* re-authenticate as original user again */
342
343         status = smb2_session_setup_spnego(tree->session,
344                                            popt_get_cmdline_credentials(),
345                                            0 /* previous_session_id */);
346         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
347                                         "smb2_session_setup_spnego failed");
348
349         /* try to access the file via the old handle */
350
351         ZERO_STRUCT(qfinfo);
352         qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
353         qfinfo.generic.in.file.handle = _h1;
354         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
355         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
356                                         "smb2_getinfo_file failed");
357
358 done:
359         if (h1 != NULL) {
360                 smb2_util_close(tree, *h1);
361         }
362
363         smb2_util_unlink(tree, fname);
364
365         talloc_free(tree);
366
367         talloc_free(mem_ctx);
368
369         return ret;
370 }
371
372 /**
373  * test getting security descriptor after reauth
374  */
375 bool test_session_reauth3(struct torture_context *tctx, struct smb2_tree *tree)
376 {
377         NTSTATUS status;
378         TALLOC_CTX *mem_ctx = talloc_new(tctx);
379         char fname[256];
380         struct smb2_handle _h1;
381         struct smb2_handle *h1 = NULL;
382         struct smb2_create io1;
383         bool ret = true;
384         union smb_fileinfo qfinfo;
385         struct cli_credentials *anon_creds = NULL;
386         uint32_t secinfo_flags = SECINFO_OWNER
387                                 | SECINFO_GROUP
388                                 | SECINFO_DACL
389                                 | SECINFO_PROTECTED_DACL
390                                 | SECINFO_UNPROTECTED_DACL;
391
392         /* Add some random component to the file name. */
393         snprintf(fname, sizeof(fname), "session_reauth3_%s.dat",
394                  generate_random_str(tctx, 8));
395
396         smb2_util_unlink(tree, fname);
397
398         smb2_oplock_create_share(&io1, fname,
399                                  smb2_util_share_access(""),
400                                  smb2_util_oplock_level("b"));
401
402         status = smb2_create(tree, mem_ctx, &io1);
403         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
404                                         "smb2_create failed");
405         _h1 = io1.out.file.handle;
406         h1 = &_h1;
407         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
408         torture_assert_int_equal(tctx, io1.out.oplock_level,
409                                         smb2_util_oplock_level("b"),
410                                         "oplock_level incorrect");
411
412         /* get the security descriptor */
413
414         ZERO_STRUCT(qfinfo);
415
416         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
417         qfinfo.query_secdesc.in.file.handle = _h1;
418         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
419
420         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
421         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
422                                         "smb2_getinfo_file failed");
423
424         /* re-authenticate as anonymous */
425
426         anon_creds = cli_credentials_init_anon(mem_ctx);
427         torture_assert(tctx, (anon_creds != NULL), "talloc error");
428
429         status = smb2_session_setup_spnego(tree->session,
430                                            anon_creds,
431                                            0 /* previous_session_id */);
432         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
433                                         "smb2_session_setup_spnego failed");
434
435         /* try to access the file via the old handle */
436
437         ZERO_STRUCT(qfinfo);
438
439         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
440         qfinfo.query_secdesc.in.file.handle = _h1;
441         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
442
443         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
444         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
445                                         "smb2_getinfo_file failed");
446
447         /* re-authenticate as original user again */
448
449         status = smb2_session_setup_spnego(tree->session,
450                                            popt_get_cmdline_credentials(),
451                                            0 /* previous_session_id */);
452         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
453                                         "smb2_session_setup_spnego failed");
454
455         /* try to access the file via the old handle */
456
457         ZERO_STRUCT(qfinfo);
458
459         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
460         qfinfo.query_secdesc.in.file.handle = _h1;
461         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
462
463         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
464         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
465                                         "smb2_getinfo_file failed");
466
467 done:
468         if (h1 != NULL) {
469                 smb2_util_close(tree, *h1);
470         }
471
472         smb2_util_unlink(tree, fname);
473
474         talloc_free(tree);
475
476         talloc_free(mem_ctx);
477
478         return ret;
479 }
480
481 /**
482  * test setting security descriptor after reauth.
483  */
484 bool test_session_reauth4(struct torture_context *tctx, struct smb2_tree *tree)
485 {
486         NTSTATUS status;
487         TALLOC_CTX *mem_ctx = talloc_new(tctx);
488         char fname[256];
489         struct smb2_handle _h1;
490         struct smb2_handle *h1 = NULL;
491         struct smb2_create io1;
492         bool ret = true;
493         union smb_fileinfo qfinfo;
494         union smb_setfileinfo sfinfo;
495         struct cli_credentials *anon_creds = NULL;
496         uint32_t secinfo_flags = SECINFO_OWNER
497                                 | SECINFO_GROUP
498                                 | SECINFO_DACL
499                                 | SECINFO_PROTECTED_DACL
500                                 | SECINFO_UNPROTECTED_DACL;
501         struct security_descriptor *sd1;
502         struct security_ace ace;
503         struct dom_sid *extra_sid;
504
505         /* Add some random component to the file name. */
506         snprintf(fname, sizeof(fname), "session_reauth4_%s.dat",
507                  generate_random_str(tctx, 8));
508
509         smb2_util_unlink(tree, fname);
510
511         smb2_oplock_create_share(&io1, fname,
512                                  smb2_util_share_access(""),
513                                  smb2_util_oplock_level("b"));
514
515         status = smb2_create(tree, mem_ctx, &io1);
516         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
517                                         "smb2_create failed");
518         _h1 = io1.out.file.handle;
519         h1 = &_h1;
520         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
521         torture_assert_int_equal(tctx, io1.out.oplock_level,
522                                         smb2_util_oplock_level("b"),
523                                         "oplock_level incorrect");
524
525         /* get the security descriptor */
526
527         ZERO_STRUCT(qfinfo);
528
529         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
530         qfinfo.query_secdesc.in.file.handle = _h1;
531         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
532
533         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
534         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
535                                         "smb2_getinfo_file failed");
536
537         sd1 = qfinfo.query_secdesc.out.sd;
538
539         /* re-authenticate as anonymous */
540
541         anon_creds = cli_credentials_init_anon(mem_ctx);
542         torture_assert(tctx, (anon_creds != NULL), "talloc error");
543
544         status = smb2_session_setup_spnego(tree->session,
545                                            anon_creds,
546                                            0 /* previous_session_id */);
547         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
548                                         "smb2_session_setup_spnego failed");
549
550         /* give full access on the file to anonymous */
551
552         extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
553
554         ZERO_STRUCT(ace);
555         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
556         ace.flags = 0;
557         ace.access_mask = SEC_STD_ALL | SEC_FILE_ALL;
558         ace.trustee = *extra_sid;
559
560         status = security_descriptor_dacl_add(sd1, &ace);
561         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
562                                         "security_descriptor_dacl_add failed");
563
564         ZERO_STRUCT(sfinfo);
565         sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
566         sfinfo.set_secdesc.in.file.handle = _h1;
567         sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
568         sfinfo.set_secdesc.in.sd = sd1;
569
570         status = smb2_setinfo_file(tree, &sfinfo);
571         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
572                                         "smb2_setinfo_file failed");
573
574         /* re-authenticate as original user again */
575
576         status = smb2_session_setup_spnego(tree->session,
577                                            popt_get_cmdline_credentials(),
578                                            0 /* previous_session_id */);
579         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
580                                         "smb2_session_setup_spnego failed");
581
582         /* re-get the security descriptor */
583
584         ZERO_STRUCT(qfinfo);
585
586         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
587         qfinfo.query_secdesc.in.file.handle = _h1;
588         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
589
590         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
591         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
592                                         "smb2_getinfo_file failed");
593
594         ret = true;
595
596 done:
597         if (h1 != NULL) {
598                 smb2_util_close(tree, *h1);
599         }
600
601         smb2_util_unlink(tree, fname);
602
603         talloc_free(tree);
604
605         talloc_free(mem_ctx);
606
607         return ret;
608 }
609
610 /**
611  * test renaming after reauth.
612  * compare security descriptors before and after rename/reauth
613  */
614 bool test_session_reauth5(struct torture_context *tctx, struct smb2_tree *tree)
615 {
616         NTSTATUS status;
617         TALLOC_CTX *mem_ctx = talloc_new(tctx);
618         char dname[256];
619         char fname[256];
620         char fname2[256];
621         struct smb2_handle _dh1;
622         struct smb2_handle *dh1 = NULL;
623         struct smb2_handle _h1;
624         struct smb2_handle *h1 = NULL;
625         struct smb2_create io1;
626         bool ret = true;
627         bool ok;
628         union smb_fileinfo qfinfo;
629         union smb_setfileinfo sfinfo;
630         struct cli_credentials *anon_creds = NULL;
631         uint32_t secinfo_flags = SECINFO_OWNER
632                                 | SECINFO_GROUP
633                                 | SECINFO_DACL
634                                 | SECINFO_PROTECTED_DACL
635                                 | SECINFO_UNPROTECTED_DACL;
636         struct security_descriptor *f_sd1;
637         struct security_descriptor *d_sd1 = NULL;
638         struct security_ace ace;
639         struct dom_sid *extra_sid;
640
641         /* Add some random component to the file name. */
642         snprintf(dname, sizeof(dname), "session_reauth5_%s.d",
643                  generate_random_str(tctx, 8));
644         snprintf(fname, sizeof(fname), "%s\\file.dat", dname);
645
646         ok = smb2_util_setup_dir(tctx, tree, dname);
647         torture_assert(tctx, ok, "smb2_util_setup_dir not ok");
648
649         status = torture_smb2_testdir(tree, dname, &_dh1);
650         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
651                                         "torture_smb2_testdir failed");
652         dh1 = &_dh1;
653
654         smb2_oplock_create_share(&io1, fname,
655                                  smb2_util_share_access(""),
656                                  smb2_util_oplock_level("b"));
657
658         status = smb2_create(tree, mem_ctx, &io1);
659         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
660                                         "smb2_create failed");
661         _h1 = io1.out.file.handle;
662         h1 = &_h1;
663         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
664         torture_assert_int_equal(tctx, io1.out.oplock_level,
665                                         smb2_util_oplock_level("b"),
666                                         "oplock_level incorrect");
667
668         /* get the security descriptor */
669
670         ZERO_STRUCT(qfinfo);
671
672         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
673         qfinfo.query_secdesc.in.file.handle = _h1;
674         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
675
676         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
677         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
678                                         "smb2_getinfo_file failed");
679
680         f_sd1 = qfinfo.query_secdesc.out.sd;
681
682         /* re-authenticate as anonymous */
683
684         anon_creds = cli_credentials_init_anon(mem_ctx);
685         torture_assert(tctx, (anon_creds != NULL), "talloc error");
686
687         status = smb2_session_setup_spnego(tree->session,
688                                            anon_creds,
689                                            0 /* previous_session_id */);
690         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
691                                         "smb2_session_setup_spnego failed");
692
693         /* try to rename the file: fails */
694
695         snprintf(fname2, sizeof(fname2), "%s\\file2.dat", dname);
696
697         status = smb2_util_unlink(tree, fname2);
698         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
699                                         "smb2_util_unlink failed");
700
701
702         ZERO_STRUCT(sfinfo);
703         sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
704         sfinfo.rename_information.in.file.handle = _h1;
705         sfinfo.rename_information.in.overwrite = true;
706         sfinfo.rename_information.in.new_name = fname2;
707
708         status = smb2_setinfo_file(tree, &sfinfo);
709         torture_assert_ntstatus_equal_goto(tctx, status,
710                                            NT_STATUS_ACCESS_DENIED,
711                                            ret, done, "smb2_setinfo_file "
712                                            "returned unexpected status");
713
714         /* re-authenticate as original user again */
715
716         status = smb2_session_setup_spnego(tree->session,
717                                            popt_get_cmdline_credentials(),
718                                            0 /* previous_session_id */);
719         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
720                                         "smb2_session_setup_spnego failed");
721
722         /* give full access on the file to anonymous */
723
724         extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);
725
726         ZERO_STRUCT(ace);
727         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
728         ace.flags = 0;
729         ace.access_mask = SEC_RIGHTS_FILE_ALL;
730         ace.trustee = *extra_sid;
731
732         status = security_descriptor_dacl_add(f_sd1, &ace);
733         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
734                                         "security_descriptor_dacl_add failed");
735
736         ZERO_STRUCT(sfinfo);
737         sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
738         sfinfo.set_secdesc.in.file.handle = _h1;
739         sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
740         sfinfo.set_secdesc.in.sd = f_sd1;
741
742         status = smb2_setinfo_file(tree, &sfinfo);
743         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
744                                         "smb2_setinfo_file failed");
745
746         /* re-get the security descriptor */
747
748         ZERO_STRUCT(qfinfo);
749
750         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
751         qfinfo.query_secdesc.in.file.handle = _h1;
752         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
753
754         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
755         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
756                                         "smb2_getinfo_file failed");
757
758         /* re-authenticate as anonymous - again */
759
760         anon_creds = cli_credentials_init_anon(mem_ctx);
761         torture_assert(tctx, (anon_creds != NULL), "talloc error");
762
763         status = smb2_session_setup_spnego(tree->session,
764                                            anon_creds,
765                                            0 /* previous_session_id */);
766         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
767                                         "smb2_session_setup_spnego failed");
768
769         /* try to rename the file: fails */
770
771         ZERO_STRUCT(sfinfo);
772         sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
773         sfinfo.rename_information.in.file.handle = _h1;
774         sfinfo.rename_information.in.overwrite = true;
775         sfinfo.rename_information.in.new_name = fname2;
776
777         status = smb2_setinfo_file(tree, &sfinfo);
778         torture_assert_ntstatus_equal_goto(tctx, status,
779                                            NT_STATUS_ACCESS_DENIED,
780                                            ret, done, "smb2_setinfo_file "
781                                            "returned unexpected status");
782
783         /* give full access on the parent dir to anonymous */
784
785         ZERO_STRUCT(qfinfo);
786
787         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
788         qfinfo.query_secdesc.in.file.handle = _dh1;
789         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
790
791         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
792         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
793                                         "smb2_getinfo_file failed");
794
795         d_sd1 = qfinfo.query_secdesc.out.sd;
796
797         ZERO_STRUCT(ace);
798         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
799         ace.flags = 0;
800         ace.access_mask = SEC_RIGHTS_FILE_ALL;
801         ace.trustee = *extra_sid;
802
803         status = security_descriptor_dacl_add(d_sd1, &ace);
804         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
805                                         "security_descriptor_dacl_add failed");
806
807         ZERO_STRUCT(sfinfo);
808         sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
809         sfinfo.set_secdesc.in.file.handle = _dh1;
810         sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
811         sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
812         sfinfo.set_secdesc.in.sd = d_sd1;
813
814         status = smb2_setinfo_file(tree, &sfinfo);
815         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
816                                         "smb2_setinfo_file failed");
817
818         ZERO_STRUCT(qfinfo);
819
820         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
821         qfinfo.query_secdesc.in.file.handle = _dh1;
822         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
823
824         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
825         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
826                                         "smb2_getinfo_file failed");
827
828         status = smb2_util_close(tree, _dh1);
829         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
830                                         "smb2_util_close failed");
831         dh1 = NULL;
832
833         /* try to rename the file: still fails */
834
835         ZERO_STRUCT(sfinfo);
836         sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
837         sfinfo.rename_information.in.file.handle = _h1;
838         sfinfo.rename_information.in.overwrite = true;
839         sfinfo.rename_information.in.new_name = fname2;
840
841         status = smb2_setinfo_file(tree, &sfinfo);
842         torture_assert_ntstatus_equal_goto(tctx, status,
843                                         NT_STATUS_ACCESS_DENIED,
844                                         ret, done, "smb2_setinfo_file "
845                                         "returned unexpected status");
846
847         /* re-authenticate as original user - again */
848
849         status = smb2_session_setup_spnego(tree->session,
850                                            popt_get_cmdline_credentials(),
851                                            0 /* previous_session_id */);
852         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
853                                         "smb2_session_setup_spnego failed");
854
855         /* rename the file - for verification that it works */
856
857         ZERO_STRUCT(sfinfo);
858         sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
859         sfinfo.rename_information.in.file.handle = _h1;
860         sfinfo.rename_information.in.overwrite = true;
861         sfinfo.rename_information.in.new_name = fname2;
862
863         status = smb2_setinfo_file(tree, &sfinfo);
864         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
865                                         "smb2_setinfo_file failed");
866
867         /* closs the file, check it is gone and reopen under the new name */
868
869         status = smb2_util_close(tree, _h1);
870         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
871                                         "smb2_util_close failed");
872         ZERO_STRUCT(io1);
873
874         smb2_generic_create_share(&io1,
875                                   NULL /* lease */, false /* dir */,
876                                   fname,
877                                   NTCREATEX_DISP_OPEN,
878                                   smb2_util_share_access(""),
879                                   smb2_util_oplock_level("b"),
880                                   0 /* leasekey */, 0 /* leasestate */);
881
882         status = smb2_create(tree, mem_ctx, &io1);
883         torture_assert_ntstatus_equal_goto(tctx, status,
884                                         NT_STATUS_OBJECT_NAME_NOT_FOUND,
885                                         ret, done, "smb2_create "
886                                         "returned unexpected status");
887
888         ZERO_STRUCT(io1);
889
890         smb2_generic_create_share(&io1,
891                                   NULL /* lease */, false /* dir */,
892                                   fname2,
893                                   NTCREATEX_DISP_OPEN,
894                                   smb2_util_share_access(""),
895                                   smb2_util_oplock_level("b"),
896                                   0 /* leasekey */, 0 /* leasestate */);
897
898         status = smb2_create(tree, mem_ctx, &io1);
899         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
900                                         "smb2_create failed");
901         _h1 = io1.out.file.handle;
902         h1 = &_h1;
903         CHECK_CREATED(tctx, &io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
904         torture_assert_int_equal(tctx, io1.out.oplock_level,
905                                         smb2_util_oplock_level("b"),
906                                         "oplock_level incorrect");
907
908         /* try to access the file via the old handle */
909
910         ZERO_STRUCT(qfinfo);
911
912         qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
913         qfinfo.query_secdesc.in.file.handle = _h1;
914         qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;
915
916         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
917         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
918                                         "smb2_getinfo_file failed");
919
920 done:
921         if (dh1 != NULL) {
922                 smb2_util_close(tree, *dh1);
923         }
924         if (h1 != NULL) {
925                 smb2_util_close(tree, *h1);
926         }
927
928         smb2_deltree(tree, dname);
929
930         talloc_free(tree);
931
932         talloc_free(mem_ctx);
933
934         return ret;
935 }
936
937 /**
938  * do reauth with wrong credentials,
939  * hence triggering the error path in reauth.
940  * The invalid reauth deletes the session.
941  */
942 bool test_session_reauth6(struct torture_context *tctx, struct smb2_tree *tree)
943 {
944         NTSTATUS status;
945         TALLOC_CTX *mem_ctx = talloc_new(tctx);
946         char fname[256];
947         struct smb2_handle _h1;
948         struct smb2_handle *h1 = NULL;
949         struct smb2_create io1;
950         bool ret = true;
951         char *corrupted_password;
952         struct cli_credentials *broken_creds;
953         bool ok;
954         bool encrypted;
955         NTSTATUS expected;
956         enum credentials_use_kerberos krb_state;
957
958         krb_state = cli_credentials_get_kerberos_state(
959                         popt_get_cmdline_credentials());
960         if (krb_state == CRED_MUST_USE_KERBEROS) {
961                 torture_skip(tctx,
962                              "Can't test failing session setup with kerberos.");
963         }
964
965         encrypted = smb2cli_tcon_is_encryption_on(tree->smbXcli);
966
967         /* Add some random component to the file name. */
968         snprintf(fname, sizeof(fname), "session_reauth1_%s.dat",
969                  generate_random_str(tctx, 8));
970
971         smb2_util_unlink(tree, fname);
972
973         smb2_oplock_create_share(&io1, fname,
974                                  smb2_util_share_access(""),
975                                  smb2_util_oplock_level("b"));
976         io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
977
978         status = smb2_create(tree, mem_ctx, &io1);
979         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
980                                         "smb2_create failed");
981         _h1 = io1.out.file.handle;
982         h1 = &_h1;
983         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
984         torture_assert_int_equal(tctx, io1.out.oplock_level,
985                                         smb2_util_oplock_level("b"),
986                                         "oplock_level incorrect");
987
988         /*
989          * reauthentication with invalid credentials:
990          */
991
992         broken_creds = cli_credentials_shallow_copy(mem_ctx,
993                                             popt_get_cmdline_credentials());
994         torture_assert(tctx, (broken_creds != NULL), "talloc error");
995
996         corrupted_password = talloc_asprintf(mem_ctx, "%s%s",
997                                 cli_credentials_get_password(broken_creds),
998                                 "corrupt");
999         torture_assert(tctx, (corrupted_password != NULL), "talloc error");
1000
1001         ok = cli_credentials_set_password(broken_creds, corrupted_password,
1002                                           CRED_SPECIFIED);
1003         torture_assert(tctx, ok, "cli_credentials_set_password not ok");
1004
1005         status = smb2_session_setup_spnego(tree->session,
1006                                            broken_creds,
1007                                            0 /* previous_session_id */);
1008         torture_assert_ntstatus_equal_goto(tctx, status,
1009                                         NT_STATUS_LOGON_FAILURE, ret, done,
1010                                         "smb2_session_setup_spnego "
1011                                         "returned unexpected status");
1012
1013         torture_comment(tctx, "did failed reauth\n");
1014         /*
1015          * now verify that the invalid session reauth has closed our session
1016          */
1017
1018         if (encrypted) {
1019                 expected = NT_STATUS_CONNECTION_DISCONNECTED;
1020         } else {
1021                 expected = NT_STATUS_USER_SESSION_DELETED;
1022         }
1023
1024         smb2_oplock_create_share(&io1, fname,
1025                                  smb2_util_share_access(""),
1026                                  smb2_util_oplock_level("b"));
1027
1028         status = smb2_create(tree, mem_ctx, &io1);
1029         torture_assert_ntstatus_equal_goto(tctx, status, expected,
1030                                         ret, done, "smb2_create "
1031                                         "returned unexpected status");
1032
1033 done:
1034         if (h1 != NULL) {
1035                 smb2_util_close(tree, *h1);
1036         }
1037
1038         smb2_util_unlink(tree, fname);
1039
1040         talloc_free(tree);
1041
1042         talloc_free(mem_ctx);
1043
1044         return ret;
1045 }
1046
1047
1048 static bool test_session_expire1(struct torture_context *tctx)
1049 {
1050         NTSTATUS status;
1051         bool ret = false;
1052         struct smbcli_options options;
1053         const char *host = torture_setting_string(tctx, "host", NULL);
1054         const char *share = torture_setting_string(tctx, "share", NULL);
1055         struct cli_credentials *credentials = popt_get_cmdline_credentials();
1056         struct smb2_tree *tree = NULL;
1057         enum credentials_use_kerberos use_kerberos;
1058         char fname[256];
1059         struct smb2_handle _h1;
1060         struct smb2_handle *h1 = NULL;
1061         struct smb2_create io1;
1062         union smb_fileinfo qfinfo;
1063         size_t i;
1064
1065         use_kerberos = cli_credentials_get_kerberos_state(credentials);
1066         if (use_kerberos != CRED_MUST_USE_KERBEROS) {
1067                 torture_warning(tctx, "smb2.session.expire1 requires -k yes!");
1068                 torture_skip(tctx, "smb2.session.expire1 requires -k yes!");
1069         }
1070
1071         torture_assert_int_equal(tctx, use_kerberos, CRED_MUST_USE_KERBEROS,
1072                                  "please use -k yes");
1073
1074         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
1075
1076         lpcfg_smbcli_options(tctx->lp_ctx, &options);
1077
1078         status = smb2_connect(tctx,
1079                               host,
1080                               lpcfg_smb_ports(tctx->lp_ctx),
1081                               share,
1082                               lpcfg_resolve_context(tctx->lp_ctx),
1083                               credentials,
1084                               &tree,
1085                               tctx->ev,
1086                               &options,
1087                               lpcfg_socket_options(tctx->lp_ctx),
1088                               lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1089                               );
1090         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1091                                         "smb2_connect failed");
1092
1093         /* Add some random component to the file name. */
1094         snprintf(fname, sizeof(fname), "session_expire1_%s.dat",
1095                  generate_random_str(tctx, 8));
1096
1097         smb2_util_unlink(tree, fname);
1098
1099         smb2_oplock_create_share(&io1, fname,
1100                                  smb2_util_share_access(""),
1101                                  smb2_util_oplock_level("b"));
1102         io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1103
1104         status = smb2_create(tree, tctx, &io1);
1105         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1106                                         "smb2_create failed");
1107         _h1 = io1.out.file.handle;
1108         h1 = &_h1;
1109         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1110         torture_assert_int_equal(tctx, io1.out.oplock_level,
1111                                         smb2_util_oplock_level("b"),
1112                                         "oplock_level incorrect");
1113
1114         /* get the security descriptor */
1115
1116         ZERO_STRUCT(qfinfo);
1117
1118         qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
1119         qfinfo.access_information.in.file.handle = _h1;
1120
1121         for (i=0; i < 2; i++) {
1122                 torture_comment(tctx, "query info => OK\n");
1123
1124                 ZERO_STRUCT(qfinfo.access_information.out);
1125                 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1126                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1127                                                 "smb2_getinfo_file failed");
1128
1129                 torture_comment(tctx, "sleep 10 seconds\n");
1130                 smb_msleep(10*1000);
1131
1132                 torture_comment(tctx, "query info => EXPIRED\n");
1133                 ZERO_STRUCT(qfinfo.access_information.out);
1134                 status = smb2_getinfo_file(tree, tctx, &qfinfo);
1135                 torture_assert_ntstatus_equal_goto(tctx, status,
1136                                         NT_STATUS_NETWORK_SESSION_EXPIRED,
1137                                         ret, done, "smb2_getinfo_file "
1138                                         "returned unexpected status");
1139
1140                 /*
1141                  * the krb5 library may not handle expired creds
1142                  * well, lets start with an empty ccache.
1143                  */
1144                 cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
1145
1146                 torture_comment(tctx, "reauth => OK\n");
1147                 status = smb2_session_setup_spnego(tree->session,
1148                                                    credentials,
1149                                                    0 /* previous_session_id */);
1150                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1151                                         "smb2_session_seutup_spnego failed");
1152         }
1153
1154         ZERO_STRUCT(qfinfo.access_information.out);
1155         status = smb2_getinfo_file(tree, tctx, &qfinfo);
1156         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1157                                         "smb2_getinfo_file failed");
1158
1159         ret = true;
1160 done:
1161         if (h1 != NULL) {
1162                 smb2_util_close(tree, *h1);
1163         }
1164
1165         talloc_free(tree);
1166         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
1167         return ret;
1168 }
1169
1170 bool test_session_bind1(struct torture_context *tctx, struct smb2_tree *tree1)
1171 {
1172         const char *host = torture_setting_string(tctx, "host", NULL);
1173         const char *share = torture_setting_string(tctx, "share", NULL);
1174         struct cli_credentials *credentials = popt_get_cmdline_credentials();
1175         NTSTATUS status;
1176         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1177         char fname[256];
1178         struct smb2_handle _h1;
1179         struct smb2_handle *h1 = NULL;
1180         struct smb2_create io1;
1181         union smb_fileinfo qfinfo;
1182         bool ret = false;
1183         struct smb2_tree *tree2 = NULL;
1184         struct smb2_transport *transport1 = tree1->session->transport;
1185         struct smb2_transport *transport2 = NULL;
1186         struct smb2_session *session1_1 = tree1->session;
1187         struct smb2_session *session1_2 = NULL;
1188         struct smb2_session *session2_1 = NULL;
1189         struct smb2_session *session2_2 = NULL;
1190         uint32_t caps;
1191
1192         caps = smb2cli_conn_server_capabilities(transport1->conn);
1193         if (!(caps & SMB2_CAP_MULTI_CHANNEL)) {
1194                 torture_skip(tctx, "server doesn't support SMB2_CAP_MULTI_CHANNEL\n");
1195         }
1196
1197         /* Add some random component to the file name. */
1198         snprintf(fname, sizeof(fname), "session_bind1_%s.dat",
1199                  generate_random_str(tctx, 8));
1200
1201         smb2_util_unlink(tree1, fname);
1202
1203         smb2_oplock_create_share(&io1, fname,
1204                                  smb2_util_share_access(""),
1205                                  smb2_util_oplock_level("b"));
1206
1207         status = smb2_create(tree1, mem_ctx, &io1);
1208         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1209                                         "smb2_create failed");
1210         _h1 = io1.out.file.handle;
1211         h1 = &_h1;
1212         CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1213         torture_assert_int_equal(tctx, io1.out.oplock_level,
1214                                         smb2_util_oplock_level("b"),
1215                                         "oplock_level incorrect");
1216
1217         status = smb2_connect(tctx,
1218                               host,
1219                               lpcfg_smb_ports(tctx->lp_ctx),
1220                               share,
1221                               lpcfg_resolve_context(tctx->lp_ctx),
1222                               credentials,
1223                               &tree2,
1224                               tctx->ev,
1225                               &transport1->options,
1226                               lpcfg_socket_options(tctx->lp_ctx),
1227                               lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1228                               );
1229         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1230                                         "smb2_connect failed");
1231         session2_2 = tree2->session;
1232         transport2 = tree2->session->transport;
1233
1234         /*
1235          * Now bind the 2nd transport connection to the 1st session
1236          */
1237         session1_2 = smb2_session_channel(transport2,
1238                                           lpcfg_gensec_settings(tctx, tctx->lp_ctx),
1239                                           tree2,
1240                                           session1_1);
1241         torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
1242
1243         status = smb2_session_setup_spnego(session1_2,
1244                                            popt_get_cmdline_credentials(),
1245                                            0 /* previous_session_id */);
1246         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1247                                         "smb2_session_setup_spnego failed");
1248
1249         /* use the 1st connection, 1st session */
1250         ZERO_STRUCT(qfinfo);
1251         qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
1252         qfinfo.generic.in.file.handle = _h1;
1253         tree1->session = session1_1;
1254         status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
1255         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1256                                         "smb2_getinfo_file failed");
1257
1258         /* use the 2nd connection, 1st session */
1259         ZERO_STRUCT(qfinfo);
1260         qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
1261         qfinfo.generic.in.file.handle = _h1;
1262         tree1->session = session1_2;
1263         status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
1264         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1265                                         "smb2_getinfo_file failed");
1266
1267         tree1->session = session1_1;
1268         status = smb2_util_close(tree1, *h1);
1269         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1270                                         "smb2_util_close failed");
1271         h1 = NULL;
1272
1273         /*
1274          * Now bind the 1st transport connection to the 2nd session
1275          */
1276         session2_1 = smb2_session_channel(transport1,
1277                                           lpcfg_gensec_settings(tctx, tctx->lp_ctx),
1278                                           tree1,
1279                                           session2_2);
1280         torture_assert(tctx, session2_1 != NULL, "smb2_session_channel failed");
1281
1282         status = smb2_session_setup_spnego(session2_1,
1283                                            popt_get_cmdline_credentials(),
1284                                            0 /* previous_session_id */);
1285         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1286                                         "smb2_session_setup_spnego failed");
1287
1288         tree2->session = session2_1;
1289         status = smb2_util_unlink(tree2, fname);
1290         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1291                                         "smb2_util_unlink failed");
1292         ret = true;
1293 done:
1294         talloc_free(tree2);
1295         tree1->session = session1_1;
1296
1297         if (h1 != NULL) {
1298                 smb2_util_close(tree1, *h1);
1299         }
1300
1301         smb2_util_unlink(tree1, fname);
1302
1303         talloc_free(tree1);
1304
1305         talloc_free(mem_ctx);
1306
1307         return ret;
1308 }
1309
1310 struct torture_suite *torture_smb2_session_init(TALLOC_CTX *ctx)
1311 {
1312         struct torture_suite *suite =
1313             torture_suite_create(ctx, "session");
1314
1315         torture_suite_add_1smb2_test(suite, "reconnect1", test_session_reconnect1);
1316         torture_suite_add_1smb2_test(suite, "reconnect2", test_session_reconnect2);
1317         torture_suite_add_1smb2_test(suite, "reauth1", test_session_reauth1);
1318         torture_suite_add_1smb2_test(suite, "reauth2", test_session_reauth2);
1319         torture_suite_add_1smb2_test(suite, "reauth3", test_session_reauth3);
1320         torture_suite_add_1smb2_test(suite, "reauth4", test_session_reauth4);
1321         torture_suite_add_1smb2_test(suite, "reauth5", test_session_reauth5);
1322         torture_suite_add_1smb2_test(suite, "reauth6", test_session_reauth6);
1323         torture_suite_add_simple_test(suite, "expire1", test_session_expire1);
1324         torture_suite_add_1smb2_test(suite, "bind1", test_session_bind1);
1325
1326         suite->description = talloc_strdup(suite, "SMB2-SESSION tests");
1327
1328         return suite;
1329 }