s4:torture/smb2: remove useless 'smb2.multichannel.leases.test4'
[samba.git] / source4 / torture / smb2 / multichannel.c
1 /*
2  * Unix SMB/CIFS implementation.
3  *
4  * test SMB2 multichannel operations
5  *
6  * Copyright (C) Guenther Deschner, 2016
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/security/security.h"
28 #include "librpc/gen_ndr/ndr_security.h"
29 #include "librpc/gen_ndr/ndr_ioctl.h"
30 #include "../libcli/smb/smbXcli_base.h"
31 #include "lib/cmdline/popt_common.h"
32 #include "libcli/security/security.h"
33 #include "libcli/resolve/resolve.h"
34 #include "lib/param/param.h"
35 #include "lib/events/events.h"
36 #include "oplock_break_handler.h"
37 #include "lease_break_handler.h"
38 #include "torture/smb2/block.h"
39
40 #define BASEDIR "multichanneltestdir"
41
42 #define CHECK_STATUS(status, correct) \
43         torture_assert_ntstatus_equal_goto(tctx, status, correct,\
44                                            ret, done, "")
45
46 #define CHECK_VAL(v, correct) do { \
47         if ((v) != (correct)) { \
48                 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s" \
49                                 " got 0x%x - should be 0x%x\n", \
50                                 __location__, #v, (int)v, (int)correct); \
51                 ret = false; \
52                 goto done; \
53         } } while (0)
54
55 #define CHECK_VAL_GREATER_THAN(v, gt_val) do { \
56         if ((v) <= (gt_val)) { \
57                 torture_result(tctx, TORTURE_FAIL, \
58                                 "(%s): wrong value for %s got 0x%x - " \
59                                 "should be greater than 0x%x\n", \
60                                 __location__, #v, (int)v, (int)gt_val); \
61                 ret = false; \
62                 goto done; \
63         } } while (0)
64
65 #define CHECK_CREATED(__io, __created, __attribute)                     \
66         do {                                                            \
67                 CHECK_VAL((__io)->out.create_action,                    \
68                                 NTCREATEX_ACTION_ ## __created);        \
69                 CHECK_VAL((__io)->out.alloc_size, 0);                   \
70                 CHECK_VAL((__io)->out.size, 0);                         \
71                 CHECK_VAL((__io)->out.file_attr, (__attribute));        \
72                 CHECK_VAL((__io)->out.reserved2, 0);                    \
73         } while (0)
74
75 #define CHECK_PTR(ptr, correct) do { \
76         if ((ptr) != (correct)) { \
77                 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s " \
78                                 "got 0x%p - should be 0x%p\n", \
79                                 __location__, #ptr, ptr, correct); \
80                 ret = false; \
81                 goto done; \
82         } } while (0)
83
84 #define CHECK_LEASE(__io, __state, __oplevel, __key, __flags)           \
85         do {                                                            \
86                 CHECK_VAL((__io)->out.lease_response.lease_version, 1); \
87                 if (__oplevel) {                                        \
88                         CHECK_VAL((__io)->out.oplock_level, \
89                                         SMB2_OPLOCK_LEVEL_LEASE); \
90                         CHECK_VAL((__io)->out.lease_response.lease_key.data[0],\
91                                   (__key)); \
92                         CHECK_VAL((__io)->out.lease_response.lease_key.data[1],\
93                                   ~(__key)); \
94                         CHECK_VAL((__io)->out.lease_response.lease_state,\
95                                   smb2_util_lease_state(__state)); \
96                 } else {                                                \
97                         CHECK_VAL((__io)->out.oplock_level,\
98                                   SMB2_OPLOCK_LEVEL_NONE); \
99                         CHECK_VAL((__io)->out.lease_response.lease_key.data[0],\
100                                   0); \
101                         CHECK_VAL((__io)->out.lease_response.lease_key.data[1],\
102                                   0); \
103                         CHECK_VAL((__io)->out.lease_response.lease_state, 0); \
104                 }                                                       \
105                                                                         \
106                 CHECK_VAL((__io)->out.lease_response.lease_flags, (__flags)); \
107                 CHECK_VAL((__io)->out.lease_response.lease_duration, 0); \
108                 CHECK_VAL((__io)->out.lease_response.lease_epoch, 0); \
109         } while (0)
110
111 static bool test_ioctl_network_interface_info(struct torture_context *tctx,
112                                               struct smb2_tree *tree,
113                                               struct fsctl_net_iface_info *info)
114 {
115         union smb_ioctl ioctl;
116         struct smb2_handle fh;
117         uint32_t caps;
118
119         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
120         if (!(caps & SMB2_CAP_MULTI_CHANNEL)) {
121                 torture_skip(tctx,
122                             "server doesn't support SMB2_CAP_MULTI_CHANNEL\n");
123         }
124
125         ZERO_STRUCT(ioctl);
126
127         ioctl.smb2.level = RAW_IOCTL_SMB2;
128
129         fh.data[0] = UINT64_MAX;
130         fh.data[1] = UINT64_MAX;
131
132         ioctl.smb2.in.file.handle = fh;
133         ioctl.smb2.in.function = FSCTL_QUERY_NETWORK_INTERFACE_INFO;
134         /* Windows client sets this to 64KiB */
135         ioctl.smb2.in.max_output_response = 0x10000;
136         ioctl.smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
137
138         torture_assert_ntstatus_ok(tctx,
139                 smb2_ioctl(tree, tctx, &ioctl.smb2),
140                 "FSCTL_QUERY_NETWORK_INTERFACE_INFO failed");
141
142         torture_assert(tctx,
143                 (ioctl.smb2.out.out.length != 0),
144                 "no interface info returned???");
145
146         torture_assert_ndr_success(tctx,
147                 ndr_pull_struct_blob(&ioctl.smb2.out.out, tctx, info,
148                         (ndr_pull_flags_fn_t)ndr_pull_fsctl_net_iface_info),
149                 "failed to ndr pull");
150
151         if (DEBUGLVL(1)) {
152                 NDR_PRINT_DEBUG(fsctl_net_iface_info, info);
153         }
154
155         return true;
156 }
157
158 static bool test_multichannel_interface_info(struct torture_context *tctx,
159                                              struct smb2_tree *tree)
160 {
161         struct fsctl_net_iface_info info;
162
163         return test_ioctl_network_interface_info(tctx, tree, &info);
164 }
165
166 static struct smb2_tree *test_multichannel_create_channel(
167                                 struct torture_context *tctx,
168                                 const char *host,
169                                 const char *share,
170                                 struct cli_credentials *credentials,
171                                 const struct smbcli_options *_transport_options,
172                                 struct smb2_tree *parent_tree
173                                 )
174 {
175         struct smbcli_options transport_options = *_transport_options;
176         NTSTATUS status;
177         struct smb2_transport *transport;
178         struct smb2_session *session;
179         bool ret = true;
180         struct smb2_tree *tree;
181
182         if (parent_tree) {
183                 transport_options.only_negprot = true;
184         }
185
186         status = smb2_connect(tctx,
187                         host,
188                         lpcfg_smb_ports(tctx->lp_ctx),
189                         share,
190                         lpcfg_resolve_context(tctx->lp_ctx),
191                         credentials,
192                         &tree,
193                         tctx->ev,
194                         &transport_options,
195                         lpcfg_socket_options(tctx->lp_ctx),
196                         lpcfg_gensec_settings(tctx, tctx->lp_ctx)
197                         );
198         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
199                         "smb2_connect failed");
200         transport = tree->session->transport;
201         transport->oplock.handler = torture_oplock_ack_handler;
202         transport->oplock.private_data = tree;
203         transport->lease.handler = torture_lease_handler;
204         transport->lease.private_data = tree;
205         torture_comment(tctx, "established transport [%p]\n", transport);
206
207         /*
208          * If parent tree is set, bind the session to the parent transport
209          */
210         if (parent_tree) {
211                 session = smb2_session_channel(transport,
212                                 lpcfg_gensec_settings(tctx, tctx->lp_ctx),
213                                 parent_tree, parent_tree->session);
214                 torture_assert_goto(tctx, session != NULL, ret, done,
215                                 "smb2_session_channel failed");
216
217                 tree->smbXcli = parent_tree->smbXcli;
218                 tree->session = session;
219                 status = smb2_session_setup_spnego(session,
220                                                 credentials,
221                                                 0 /* previous_session_id */);
222                 CHECK_STATUS(status, NT_STATUS_OK);
223                 torture_comment(tctx, "bound new session to parent\n");
224         }
225         /*
226          * We absolutely need to make sure to send something over this
227          * connection to register the oplock break handler with the smb client
228          * connection. If we do not send something (at least a keepalive), we
229          * will *NEVER* receive anything over this transport.
230          */
231         smb2_keepalive(transport);
232
233 done:
234         if (ret) {
235                 return tree;
236         } else {
237                 return NULL;
238         }
239 }
240
241 bool test_multichannel_create_channel_array(
242                                 struct torture_context *tctx,
243                                 const char *host,
244                                 const char *share,
245                                 struct cli_credentials *credentials,
246                                 struct smbcli_options *transport_options,
247                                 uint8_t num_trees,
248                                 struct smb2_tree **trees)
249 {
250         uint8_t i;
251
252         transport_options->client_guid = GUID_random();
253
254         for (i = 0; i < num_trees; i++) {
255                 struct smb2_tree *parent_tree = NULL;
256                 struct smb2_tree *tree = NULL;
257                 struct smb2_transport *transport = NULL;
258                 uint16_t local_port = 0;
259
260                 if (i > 0) {
261                         parent_tree = trees[0];
262                 }
263
264                 torture_comment(tctx, "Setting up connection %d\n", i);
265                 tree = test_multichannel_create_channel(tctx, host, share,
266                                         credentials, transport_options,
267                                         parent_tree);
268                 torture_assert(tctx, tree, "failed to created new channel");
269
270                 trees[i] = tree;
271                 transport = tree->session->transport;
272                 local_port = torture_get_local_port_from_transport(transport);
273                 torture_comment(tctx, "transport[%d] uses tcp port: %d\n",
274                                 i, local_port);
275         }
276
277         return true;
278 }
279
280 bool test_multichannel_create_channels(
281                                 struct torture_context *tctx,
282                                 const char *host,
283                                 const char *share,
284                                 struct cli_credentials *credentials,
285                                 struct smbcli_options *transport_options,
286                                 struct smb2_tree **tree2A,
287                                 struct smb2_tree **tree2B,
288                                 struct smb2_tree **tree2C
289                                 )
290 {
291         struct smb2_tree **trees = NULL;
292         size_t num_trees = 0;
293         bool ret;
294
295         torture_assert(tctx, tree2A, "tree2A required!");
296         num_trees += 1;
297         torture_assert(tctx, tree2B, "tree2B required!");
298         num_trees += 1;
299         if (tree2C != NULL) {
300                 num_trees += 1;
301         }
302         trees = talloc_zero_array(tctx, struct smb2_tree *, num_trees);
303         torture_assert(tctx, trees, "out of memory");
304
305         ret = test_multichannel_create_channel_array(tctx, host, share, credentials,
306                                                      transport_options,
307                                                      num_trees, trees);
308         if (!ret) {
309                 return false;
310         }
311
312         *tree2A = trees[0];
313         *tree2B = trees[1];
314         if (tree2C != NULL) {
315                 *tree2C = trees[2];
316         }
317
318         return true;
319 }
320
321 static void test_multichannel_free_channels(struct smb2_tree *tree2A,
322                                              struct smb2_tree *tree2B,
323                                              struct smb2_tree *tree2C)
324 {
325         TALLOC_FREE(tree2A);
326         TALLOC_FREE(tree2B);
327         TALLOC_FREE(tree2C);
328 }
329
330 static bool test_multichannel_initial_checks(struct torture_context *tctx,
331                                              struct smb2_tree *tree1)
332 {
333         struct smb2_transport *transport1 = tree1->session->transport;
334         uint32_t server_capabilities;
335         struct fsctl_net_iface_info info;
336
337         if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
338                 torture_skip_goto(tctx, fail,
339                                   "SMB 3.X Dialect family required for "
340                                   "Multichannel tests\n");
341         }
342
343         server_capabilities = smb2cli_conn_server_capabilities(
344                                         tree1->session->transport->conn);
345         if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
346                 torture_skip_goto(tctx, fail,
347                              "Server does not support multichannel.");
348         }
349
350         torture_assert(tctx,
351                 test_ioctl_network_interface_info(tctx, tree1, &info),
352                 "failed to retrieve network interface info");
353
354         return true;
355 fail:
356         return false;
357 }
358
359 static void test_multichannel_init_smb_create(struct smb2_create *io)
360 {
361         io->in.durable_open = false;
362         io->in.durable_open_v2 = true;
363         io->in.persistent_open = false;
364         io->in.create_guid = GUID_random();
365         io->in.timeout = 0x493E0; /* 300000 */
366         /* windows 2016 returns 300000 0x493E0 */
367 }
368
369 /* Timer handler function notifies the registering function that time is up */
370 static void timeout_cb(struct tevent_context *ev,
371                        struct tevent_timer *te,
372                        struct timeval current_time,
373                        void *private_data)
374 {
375         bool *timesup = (bool *)private_data;
376         *timesup = true;
377 }
378
379 /*
380  * Oplock break - Test 1
381  * Test to confirm that server sends oplock breaks as expected.
382  * open file1 in session 2A
383  * open file2 in session 2B
384  * open file1 in session 1
385  *      oplock break received
386  * open file1 in session 1
387  *      oplock break received
388  * Cleanup
389  */
390 static bool test_multichannel_oplock_break_test1(struct torture_context *tctx,
391                                            struct smb2_tree *tree1)
392 {
393         const char *host = torture_setting_string(tctx, "host", NULL);
394         const char *share = torture_setting_string(tctx, "share", NULL);
395         struct cli_credentials *credentials = popt_get_cmdline_credentials();
396         NTSTATUS status;
397         TALLOC_CTX *mem_ctx = talloc_new(tctx);
398         struct smb2_handle _h;
399         struct smb2_handle h_client1_file1 = {{0}};
400         struct smb2_handle h_client1_file2 = {{0}};
401         struct smb2_handle h_client1_file3 = {{0}};
402         struct smb2_handle h_client2_file1 = {{0}};
403         struct smb2_handle h_client2_file2 = {{0}};
404         struct smb2_handle h_client2_file3 = {{0}};
405         struct smb2_create io1, io2, io3;
406         bool ret = true;
407         const char *fname1 = BASEDIR "\\oplock_break_test1.dat";
408         const char *fname2 = BASEDIR "\\oplock_break_test2.dat";
409         const char *fname3 = BASEDIR "\\oplock_break_test3.dat";
410         struct smb2_tree *tree2A = NULL;
411         struct smb2_tree *tree2B = NULL;
412         struct smb2_tree *tree2C = NULL;
413         struct smb2_transport *transport1 = tree1->session->transport;
414         struct smbcli_options transport2_options;
415         struct smb2_session *session1 = tree1->session;
416         uint16_t local_port = 0;
417
418         if (!test_multichannel_initial_checks(tctx, tree1)) {
419                 return true;
420         }
421
422         torture_comment(tctx, "Oplock break retry: Test1\n");
423
424         torture_reset_break_info(tctx, &break_info);
425
426         transport1->oplock.handler = torture_oplock_ack_handler;
427         transport1->oplock.private_data = tree1;
428         torture_comment(tctx, "transport1  [%p]\n", transport1);
429         local_port = torture_get_local_port_from_transport(transport1);
430         torture_comment(tctx, "transport1 uses tcp port: %d\n", local_port);
431
432         status = torture_smb2_testdir(tree1, BASEDIR, &_h);
433         CHECK_STATUS(status, NT_STATUS_OK);
434         smb2_util_close(tree1, _h);
435         smb2_util_unlink(tree1, fname1);
436         smb2_util_unlink(tree1, fname2);
437         smb2_util_unlink(tree1, fname3);
438         CHECK_VAL(break_info.count, 0);
439
440         smb2_oplock_create_share(&io1, fname1,
441                         smb2_util_share_access("RWD"),
442                         smb2_util_oplock_level("b"));
443         test_multichannel_init_smb_create(&io1);
444
445         smb2_oplock_create_share(&io2, fname2,
446                         smb2_util_share_access("RWD"),
447                         smb2_util_oplock_level("b"));
448         test_multichannel_init_smb_create(&io2);
449
450         smb2_oplock_create_share(&io3, fname3,
451                         smb2_util_share_access("RWD"),
452                         smb2_util_oplock_level("b"));
453         test_multichannel_init_smb_create(&io3);
454
455         transport2_options = transport1->options;
456
457         ret = test_multichannel_create_channels(tctx, host, share,
458                                                   credentials,
459                                                   &transport2_options,
460                                                   &tree2A, &tree2B, NULL);
461         torture_assert(tctx, ret, "Could not create channels.\n");
462
463         /* 2a opens file1 */
464         torture_comment(tctx, "client2 opens fname1 via session 2A\n");
465         status = smb2_create(tree2A, mem_ctx, &io1);
466         CHECK_STATUS(status, NT_STATUS_OK);
467         h_client2_file1 = io1.out.file.handle;
468         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
469         CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
470         torture_wait_for_oplock_break(tctx);
471         CHECK_VAL(break_info.count, 0);
472
473         /* 2b opens file2 */
474         torture_comment(tctx, "client2 opens fname2 via session 2B\n");
475         status = smb2_create(tree2B, mem_ctx, &io2);
476         CHECK_STATUS(status, NT_STATUS_OK);
477         h_client2_file2 = io2.out.file.handle;
478         CHECK_CREATED(&io2, CREATED, FILE_ATTRIBUTE_ARCHIVE);
479         CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("b"));
480         torture_wait_for_oplock_break(tctx);
481         CHECK_VAL(break_info.count, 0);
482
483
484         /* 1 opens file1 - batchoplock break? */
485         torture_comment(tctx, "client1 opens fname1 via session 1\n");
486         io1.in.oplock_level = smb2_util_oplock_level("b");
487         status = smb2_create(tree1, mem_ctx, &io1);
488         CHECK_STATUS(status, NT_STATUS_OK);
489         h_client1_file1 = io1.out.file.handle;
490         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
491         CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("s"));
492         torture_wait_for_oplock_break(tctx);
493         CHECK_VAL(break_info.count, 1);
494
495         torture_reset_break_info(tctx, &break_info);
496
497         /* 1 opens file2 - batchoplock break? */
498         torture_comment(tctx, "client1 opens fname2 via session 1\n");
499         io2.in.oplock_level = smb2_util_oplock_level("b");
500         status = smb2_create(tree1, mem_ctx, &io2);
501         CHECK_STATUS(status, NT_STATUS_OK);
502         h_client1_file2 = io2.out.file.handle;
503         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
504         CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("s"));
505         torture_wait_for_oplock_break(tctx);
506         CHECK_VAL(break_info.count, 1);
507
508         /* cleanup everything */
509         torture_reset_break_info(tctx, &break_info);
510
511         smb2_util_close(tree1, h_client1_file1);
512         smb2_util_close(tree1, h_client1_file2);
513         smb2_util_close(tree1, h_client1_file3);
514         smb2_util_close(tree2A, h_client2_file1);
515         smb2_util_close(tree2A, h_client2_file2);
516         smb2_util_close(tree2A, h_client2_file3);
517
518         smb2_util_unlink(tree1, fname1);
519         smb2_util_unlink(tree1, fname2);
520         smb2_util_unlink(tree1, fname3);
521         CHECK_VAL(break_info.count, 0);
522         test_multichannel_free_channels(tree2A, tree2B, tree2C);
523         tree2A = tree2B = tree2C = NULL;
524 done:
525         tree1->session = session1;
526
527         smb2_util_close(tree1, h_client1_file1);
528         smb2_util_close(tree1, h_client1_file2);
529         smb2_util_close(tree1, h_client1_file3);
530         if (tree2A != NULL) {
531                 smb2_util_close(tree2A, h_client2_file1);
532                 smb2_util_close(tree2A, h_client2_file2);
533                 smb2_util_close(tree2A, h_client2_file3);
534         }
535
536         smb2_util_unlink(tree1, fname1);
537         smb2_util_unlink(tree1, fname2);
538         smb2_util_unlink(tree1, fname3);
539         smb2_deltree(tree1, BASEDIR);
540
541         test_multichannel_free_channels(tree2A, tree2B, tree2C);
542         talloc_free(tree1);
543         talloc_free(mem_ctx);
544
545         return ret;
546 }
547
548 /*
549  * Oplock Break Test 2
550  * Test to see if oplock break retries are sent by the server.
551  * Also checks to see if new channels can be created and used
552  * after an oplock break retry.
553  * open file1 in 2A
554  * open file2 in 2B
555  * open file1 in session 1
556  *      oplock break received
557  * block channel on which oplock break received
558  * open file2 in session 1
559  *      oplock break not received. Retry received.
560  *      file opened
561  * write to file2 on 2B
562  *      Break sent to session 1(which has file2 open)
563  *      Break sent to session 2A(which has read oplock)
564  * close file1 in session 1
565  * open file1 with session 1
566  * unblock blocked channel
567  * disconnect blocked channel
568  * connect channel 2D
569  * open file3 in 2D
570  * open file3 in session 1
571  *      receive break
572  */
573 static bool test_multichannel_oplock_break_test2(struct torture_context *tctx,
574                                            struct smb2_tree *tree1)
575 {
576         const char *host = torture_setting_string(tctx, "host", NULL);
577         const char *share = torture_setting_string(tctx, "share", NULL);
578         struct cli_credentials *credentials = popt_get_cmdline_credentials();
579         NTSTATUS status;
580         TALLOC_CTX *mem_ctx = talloc_new(tctx);
581         struct smb2_handle _h;
582         struct smb2_handle h_client1_file1 = {{0}};
583         struct smb2_handle h_client1_file2 = {{0}};
584         struct smb2_handle h_client1_file3 = {{0}};
585         struct smb2_handle h_client2_file1 = {{0}};
586         struct smb2_handle h_client2_file2 = {{0}};
587         struct smb2_handle h_client2_file3 = {{0}};
588         struct smb2_create io1, io2, io3;
589         bool ret = true;
590         const char *fname1 = BASEDIR "\\oplock_break_test1.dat";
591         const char *fname2 = BASEDIR "\\oplock_break_test2.dat";
592         const char *fname3 = BASEDIR "\\oplock_break_test3.dat";
593         struct smb2_tree *tree2A = NULL;
594         struct smb2_tree *tree2B = NULL;
595         struct smb2_tree *tree2C = NULL;
596         struct smb2_tree *tree2D = NULL;
597         struct smb2_transport *transport1 = tree1->session->transport;
598         struct smb2_transport *transport2 = NULL;
599         struct smbcli_options transport2_options;
600         struct smb2_session *session1 = tree1->session;
601         uint16_t local_port = 0;
602         DATA_BLOB blob;
603         bool block_setup = false;
604         bool block_ok = false;
605         bool unblock_ok = false;
606
607         if (!test_multichannel_initial_checks(tctx, tree1)) {
608                 return true;
609         }
610
611         torture_comment(tctx, "Oplock break retry: Test2\n");
612
613         torture_reset_break_info(tctx, &break_info);
614
615         transport1->oplock.handler = torture_oplock_ack_handler;
616         transport1->oplock.private_data = tree1;
617         torture_comment(tctx, "transport1  [%p]\n", transport1);
618         local_port = torture_get_local_port_from_transport(transport1);
619         torture_comment(tctx, "transport1 uses tcp port: %d\n", local_port);
620
621         status = torture_smb2_testdir(tree1, BASEDIR, &_h);
622         CHECK_STATUS(status, NT_STATUS_OK);
623         smb2_util_close(tree1, _h);
624         smb2_util_unlink(tree1, fname1);
625         smb2_util_unlink(tree1, fname2);
626         smb2_util_unlink(tree1, fname3);
627         CHECK_VAL(break_info.count, 0);
628
629         smb2_oplock_create_share(&io1, fname1,
630                         smb2_util_share_access("RWD"),
631                         smb2_util_oplock_level("b"));
632         test_multichannel_init_smb_create(&io1);
633
634         smb2_oplock_create_share(&io2, fname2,
635                         smb2_util_share_access("RWD"),
636                         smb2_util_oplock_level("b"));
637         test_multichannel_init_smb_create(&io2);
638
639         smb2_oplock_create_share(&io3, fname3,
640                         smb2_util_share_access("RWD"),
641                         smb2_util_oplock_level("b"));
642         test_multichannel_init_smb_create(&io3);
643
644         transport2_options = transport1->options;
645
646         ret = test_multichannel_create_channels(tctx, host, share,
647                                                   credentials,
648                                                   &transport2_options,
649                                                   &tree2A, &tree2B, &tree2C);
650         torture_assert(tctx, ret, "Could not create channels.\n");
651
652         torture_comment(tctx, "client2 opens fname1 via session 2A\n");
653         io1.in.oplock_level = smb2_util_oplock_level("b");
654         status = smb2_create(tree2A, mem_ctx, &io1);
655         CHECK_STATUS(status, NT_STATUS_OK);
656         h_client2_file1 = io1.out.file.handle;
657         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
658         CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
659         torture_wait_for_oplock_break(tctx);
660         CHECK_VAL(break_info.count, 0);
661
662
663         torture_comment(tctx, "client2 opens fname2 via session 2B\n");
664         io2.in.oplock_level = smb2_util_oplock_level("b");
665         status = smb2_create(tree2B, mem_ctx, &io2);
666         CHECK_STATUS(status, NT_STATUS_OK);
667         h_client2_file2 = io2.out.file.handle;
668         CHECK_CREATED(&io2, CREATED, FILE_ATTRIBUTE_ARCHIVE);
669         CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("b"));
670         torture_wait_for_oplock_break(tctx);
671         CHECK_VAL(break_info.count, 0);
672
673
674         torture_comment(tctx, "client1 opens fname1 via session 1\n");
675         io1.in.oplock_level = smb2_util_oplock_level("b");
676         status = smb2_create(tree1, mem_ctx, &io1);
677         CHECK_STATUS(status, NT_STATUS_OK);
678         h_client1_file1 = io1.out.file.handle;
679         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
680         CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("s"));
681         torture_wait_for_oplock_break(tctx);
682         CHECK_VAL(break_info.count, 1);
683
684         /* We use the transport over which this oplock break was received */
685         transport2 = break_info.received_transport;
686         torture_reset_break_info(tctx, &break_info);
687
688         block_setup = test_setup_blocked_transports(tctx);
689         torture_assert(tctx, block_setup, "test_setup_blocked_transports");
690
691         /* block channel */
692         block_ok = test_block_smb2_transport(tctx, transport2);
693
694         torture_comment(tctx, "client1 opens fname2 via session 1\n");
695         io2.in.oplock_level = smb2_util_oplock_level("b");
696         status = smb2_create(tree1, mem_ctx, &io2);
697         CHECK_STATUS(status, NT_STATUS_OK);
698         h_client1_file2 = io2.out.file.handle;
699         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
700         CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("s"));
701
702         /*
703          * Samba downgrades oplock to a level 2 oplock.
704          * Windows 2016 revokes oplock
705          */
706         torture_wait_for_oplock_break(tctx);
707         CHECK_VAL(break_info.count, 1);
708         torture_reset_break_info(tctx, &break_info);
709
710         torture_comment(tctx, "Trying write to file2 on tree2B\n");
711
712         blob = data_blob_string_const("Here I am");
713         status = smb2_util_write(tree2B,
714                                  h_client2_file2,
715                                  blob.data,
716                                  0,
717                                  blob.length);
718         torture_assert_ntstatus_ok(tctx, status,
719                 "failed to write file2 via channel 2B");
720
721         /*
722          * Samba: Write triggers 2 oplock breaks
723          *  for session 1 which has file2 open
724          *  for session 2 which has type 2 oplock
725          * Windows 2016: Only one oplock break for session 1
726          */
727         torture_wait_for_oplock_break(tctx);
728         CHECK_VAL_GREATER_THAN(break_info.count, 0);
729         torture_reset_break_info(tctx, &break_info);
730
731         torture_comment(tctx, "client1 closes fname2 via session 1\n");
732         smb2_util_close(tree1, h_client1_file2);
733
734         torture_comment(tctx, "client1 opens fname2 via session 1 again\n");
735         io2.in.oplock_level = smb2_util_oplock_level("b");
736         status = smb2_create(tree1, mem_ctx, &io2);
737         CHECK_STATUS(status, NT_STATUS_OK);
738         h_client1_file2 = io2.out.file.handle;
739         io2.out.alloc_size = 0;
740         io2.out.size = 0;
741         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
742         CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("s"));
743
744         /*
745          * now add a fourth channel and repeat the test, we need to reestablish
746          * transport2 because the remote end has invalidated our connection
747          */
748         torture_comment(tctx, "Connecting session 2D\n");
749         tree2D = test_multichannel_create_channel(tctx, host, share,
750                                      credentials, &transport2_options, tree2B);
751         if (!tree2D) {
752                 goto done;
753         }
754
755         torture_reset_break_info(tctx, &break_info);
756         torture_comment(tctx, "client 2 opening fname3 over transport2D\n");
757         status = smb2_create(tree2D, mem_ctx, &io3);
758         CHECK_STATUS(status, NT_STATUS_OK);
759         h_client2_file3 = io3.out.file.handle;
760         CHECK_CREATED(&io3, CREATED, FILE_ATTRIBUTE_ARCHIVE);
761         CHECK_VAL(io3.out.oplock_level, smb2_util_oplock_level("b"));
762         torture_wait_for_oplock_break(tctx);
763         CHECK_VAL(break_info.count, 0);
764
765         torture_comment(tctx, "client1 opens fname3 via session 1\n");
766         status = smb2_create(tree1, mem_ctx, &io3);
767         CHECK_STATUS(status, NT_STATUS_OK);
768         h_client1_file3 = io3.out.file.handle;
769         CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
770         CHECK_VAL(io3.out.oplock_level, smb2_util_oplock_level("s"));
771         torture_wait_for_oplock_break(tctx);
772         CHECK_VAL(break_info.count, 1);
773
774 done:
775         if (block_ok && !unblock_ok) {
776                 test_unblock_smb2_transport(tctx, transport2);
777         }
778         test_cleanup_blocked_transports(tctx);
779
780         tree1->session = session1;
781
782         smb2_util_close(tree1, h_client1_file1);
783         smb2_util_close(tree1, h_client1_file2);
784         smb2_util_close(tree1, h_client1_file3);
785         if (tree2B != NULL) {
786                 smb2_util_close(tree2B, h_client2_file1);
787                 smb2_util_close(tree2B, h_client2_file2);
788                 smb2_util_close(tree2B, h_client2_file3);
789         }
790
791         smb2_util_unlink(tree1, fname1);
792         smb2_util_unlink(tree1, fname2);
793         smb2_util_unlink(tree1, fname3);
794         smb2_deltree(tree1, BASEDIR);
795
796         test_multichannel_free_channels(tree2A, tree2B, tree2C);
797         if (tree2D != NULL) {
798                 TALLOC_FREE(tree2D);
799         }
800         talloc_free(tree1);
801         talloc_free(mem_ctx);
802
803         return ret;
804 }
805
806 static const uint64_t LEASE1F1 = 0xBADC0FFEE0DDF00Dull;
807 static const uint64_t LEASE1F2 = 0xBADC0FFEE0DDD00Dull;
808 static const uint64_t LEASE1F3 = 0xDADC0FFEE0DDD00Dull;
809 static const uint64_t LEASE2F1 = 0xDEADBEEFFEEDBEADull;
810 static const uint64_t LEASE2F2 = 0xDAD0FFEDD00DF00Dull;
811 static const uint64_t LEASE2F3 = 0xBAD0FFEDD00DF00Dull;
812
813 /*
814  * Lease Break Test 1:
815  * Test to check if lease breaks are sent by the server as expected.
816  *      open file1 in session 2A
817  *      open file2 in session 2B
818  *      open file3 in session 2C
819  *      open file1 in session 1
820  *           lease break sent
821  *      open file2 in session 1
822  *           lease break sent
823  *      open file3 in session 1
824  *           lease break sent
825  */
826 static bool test_multichannel_lease_break_test1(struct torture_context *tctx,
827                                                 struct smb2_tree *tree1)
828 {
829         const char *host = torture_setting_string(tctx, "host", NULL);
830         const char *share = torture_setting_string(tctx, "share", NULL);
831         struct cli_credentials *credentials = popt_get_cmdline_credentials();
832         NTSTATUS status;
833         TALLOC_CTX *mem_ctx = talloc_new(tctx);
834         struct smb2_handle _h;
835         struct smb2_handle *h = NULL;
836         struct smb2_handle h_client1_file1 = {{0}};
837         struct smb2_handle h_client1_file2 = {{0}};
838         struct smb2_handle h_client1_file3 = {{0}};
839         struct smb2_handle h_client2_file1 = {{0}};
840         struct smb2_handle h_client2_file2 = {{0}};
841         struct smb2_handle h_client2_file3 = {{0}};
842         struct smb2_create io1, io2, io3;
843         bool ret = true;
844         const char *fname1 = BASEDIR "\\lease_break_test1.dat";
845         const char *fname2 = BASEDIR "\\lease_break_test2.dat";
846         const char *fname3 = BASEDIR "\\lease_break_test3.dat";
847         struct smb2_tree *tree2A = NULL;
848         struct smb2_tree *tree2B = NULL;
849         struct smb2_tree *tree2C = NULL;
850         struct smb2_transport *transport1 = tree1->session->transport;
851         struct smbcli_options transport2_options;
852         struct smb2_session *session1 = tree1->session;
853         uint16_t local_port = 0;
854         struct smb2_lease ls1;
855         struct smb2_lease ls2;
856         struct smb2_lease ls3;
857
858         if (!test_multichannel_initial_checks(tctx, tree1)) {
859                 return true;
860         }
861
862         torture_comment(tctx, "Lease break retry: Test1\n");
863
864         torture_reset_lease_break_info(tctx, &lease_break_info);
865
866         transport1->lease.handler = torture_lease_handler;
867         transport1->lease.private_data = tree1;
868         torture_comment(tctx, "transport1  [%p]\n", transport1);
869         local_port = torture_get_local_port_from_transport(transport1);
870         torture_comment(tctx, "transport1 uses tcp port: %d\n", local_port);
871
872         status = torture_smb2_testdir(tree1, BASEDIR, &_h);
873         CHECK_STATUS(status, NT_STATUS_OK);
874         smb2_util_close(tree1, _h);
875         smb2_util_unlink(tree1, fname1);
876         smb2_util_unlink(tree1, fname2);
877         smb2_util_unlink(tree1, fname3);
878         CHECK_VAL(lease_break_info.count, 0);
879
880         smb2_lease_create(&io1, &ls1, false, fname1, LEASE2F1,
881                           smb2_util_lease_state("RHW"));
882         test_multichannel_init_smb_create(&io1);
883
884         smb2_lease_create(&io2, &ls2, false, fname2, LEASE2F2,
885                           smb2_util_lease_state("RHW"));
886         test_multichannel_init_smb_create(&io2);
887
888         smb2_lease_create(&io3, &ls3, false, fname3, LEASE2F3,
889                           smb2_util_lease_state("RHW"));
890         test_multichannel_init_smb_create(&io3);
891
892         transport2_options = transport1->options;
893
894         ret = test_multichannel_create_channels(tctx, host, share,
895                                                   credentials,
896                                                   &transport2_options,
897                                                   &tree2A, &tree2B, &tree2C);
898         torture_assert(tctx, ret, "Could not create channels.\n");
899
900         /* 2a opens file1 */
901         torture_comment(tctx, "client2 opens fname1 via session 2A\n");
902         status = smb2_create(tree2A, mem_ctx, &io1);
903         CHECK_STATUS(status, NT_STATUS_OK);
904         h_client2_file1 = io1.out.file.handle;
905         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
906         CHECK_LEASE(&io1, "RHW", true, LEASE2F1, 0);
907         CHECK_VAL(lease_break_info.count, 0);
908
909         /* 2b opens file2 */
910         torture_comment(tctx, "client2 opens fname2 via session 2B\n");
911         status = smb2_create(tree2B, mem_ctx, &io2);
912         CHECK_STATUS(status, NT_STATUS_OK);
913         h_client2_file2 = io2.out.file.handle;
914         CHECK_CREATED(&io2, CREATED, FILE_ATTRIBUTE_ARCHIVE);
915         CHECK_LEASE(&io2, "RHW", true, LEASE2F2, 0);
916         CHECK_VAL(lease_break_info.count, 0);
917
918         /* 2c opens file3 */
919         torture_comment(tctx, "client2 opens fname3 via session 2C\n");
920         smb2_lease_create(&io3, &ls3, false, fname3, LEASE2F3,
921                           smb2_util_lease_state("RHW"));
922         status = smb2_create(tree2C, mem_ctx, &io3);
923         CHECK_STATUS(status, NT_STATUS_OK);
924         h_client2_file3 = io3.out.file.handle;
925         CHECK_CREATED(&io3, CREATED, FILE_ATTRIBUTE_ARCHIVE);
926         CHECK_LEASE(&io3, "RHW", true, LEASE2F3, 0);
927         CHECK_VAL(lease_break_info.count, 0);
928
929         /* 1 opens file1 - lease break? */
930         torture_comment(tctx, "client1 opens fname1 via session 1\n");
931         smb2_lease_create(&io1, &ls1, false, fname1, LEASE1F1,
932                           smb2_util_lease_state("RHW"));
933         status = smb2_create(tree1, mem_ctx, &io1);
934         CHECK_STATUS(status, NT_STATUS_OK);
935         h_client1_file1 = io1.out.file.handle;
936         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
937         CHECK_LEASE(&io1, "RH", true, LEASE1F1, 0);
938         CHECK_BREAK_INFO("RHW", "RH", LEASE2F1);
939         CHECK_VAL(lease_break_info.count, 1);
940
941         torture_reset_lease_break_info(tctx, &lease_break_info);
942
943         /* 1 opens file2 - lease break? */
944         torture_comment(tctx, "client1 opens fname2 via session 1\n");
945         smb2_lease_create(&io2, &ls2, false, fname2, LEASE1F2,
946                           smb2_util_lease_state("RHW"));
947         status = smb2_create(tree1, mem_ctx, &io2);
948         CHECK_STATUS(status, NT_STATUS_OK);
949         h_client1_file2 = io2.out.file.handle;
950         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
951         CHECK_LEASE(&io2, "RH", true, LEASE1F2, 0);
952         CHECK_BREAK_INFO("RHW", "RH", LEASE2F2);
953         CHECK_VAL(lease_break_info.count, 1);
954
955         torture_reset_lease_break_info(tctx, &lease_break_info);
956
957         /* 1 opens file3 - lease break? */
958         torture_comment(tctx, "client1 opens fname3 via session 1\n");
959         smb2_lease_create(&io3, &ls3, false, fname3, LEASE1F3,
960                           smb2_util_lease_state("RHW"));
961         status = smb2_create(tree1, mem_ctx, &io3);
962         CHECK_STATUS(status, NT_STATUS_OK);
963         h_client1_file3 = io3.out.file.handle;
964         CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
965         CHECK_LEASE(&io3, "RH", true, LEASE1F3, 0);
966         CHECK_BREAK_INFO("RHW", "RH", LEASE2F3);
967         CHECK_VAL(lease_break_info.count, 1);
968
969         /* cleanup everything */
970         torture_reset_lease_break_info(tctx, &lease_break_info);
971
972         smb2_util_close(tree1, h_client1_file1);
973         smb2_util_close(tree1, h_client1_file2);
974         smb2_util_close(tree1, h_client1_file3);
975         smb2_util_close(tree2A, h_client2_file1);
976         smb2_util_close(tree2A, h_client2_file2);
977         smb2_util_close(tree2A, h_client2_file3);
978
979         smb2_util_unlink(tree1, fname1);
980         smb2_util_unlink(tree1, fname2);
981         smb2_util_unlink(tree1, fname3);
982         CHECK_VAL(lease_break_info.count, 0);
983         test_multichannel_free_channels(tree2A, tree2B, tree2C);
984         tree2A = tree2B = tree2C = NULL;
985 done:
986         tree1->session = session1;
987
988         smb2_util_close(tree1, h_client1_file1);
989         smb2_util_close(tree1, h_client1_file2);
990         smb2_util_close(tree1, h_client1_file3);
991         if (tree2A != NULL) {
992                 smb2_util_close(tree2A, h_client2_file1);
993                 smb2_util_close(tree2A, h_client2_file2);
994                 smb2_util_close(tree2A, h_client2_file3);
995         }
996
997         if (h != NULL) {
998                 smb2_util_close(tree1, *h);
999         }
1000
1001         smb2_util_unlink(tree1, fname1);
1002         smb2_util_unlink(tree1, fname2);
1003         smb2_util_unlink(tree1, fname3);
1004         smb2_deltree(tree1, BASEDIR);
1005
1006         test_multichannel_free_channels(tree2A, tree2B, tree2C);
1007         talloc_free(tree1);
1008         talloc_free(mem_ctx);
1009
1010         return ret;
1011 }
1012
1013 /*
1014  * Lease Break Test 2:
1015  * Test for lease break retries being sent by the server.
1016  *      Connect 2A, 2B
1017  *      open file1 in session 2A
1018  *      open file2 in session 2B
1019  *      block 2A
1020  *      open file2 in session 1
1021  *           lease break retry reaches the client?
1022  *      Connect 2C
1023  *      open file3 in session 2C
1024  *      unblock 2A
1025  *      open file1 in session 1
1026  *           lease break reaches the client?
1027  *      open file3 in session 1
1028  *           lease break reached the client?
1029  *      Cleanup
1030  *           On deletion by 1, lease breaks sent for file1, file2 and file3
1031  *           on 2B
1032  *           This changes RH lease to R for Session 2.
1033  *           (This has been disabled while we add support for sending lease
1034  *            break for handle leases.)
1035  */
1036 static bool test_multichannel_lease_break_test2(struct torture_context *tctx,
1037                                                 struct smb2_tree *tree1)
1038 {
1039         const char *host = torture_setting_string(tctx, "host", NULL);
1040         const char *share = torture_setting_string(tctx, "share", NULL);
1041         struct cli_credentials *credentials = popt_get_cmdline_credentials();
1042         NTSTATUS status;
1043         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1044         struct smb2_handle _h;
1045         struct smb2_handle *h = NULL;
1046         struct smb2_handle h_client1_file1 = {{0}};
1047         struct smb2_handle h_client1_file2 = {{0}};
1048         struct smb2_handle h_client1_file3 = {{0}};
1049         struct smb2_handle h_client2_file1 = {{0}};
1050         struct smb2_handle h_client2_file2 = {{0}};
1051         struct smb2_handle h_client2_file3 = {{0}};
1052         struct smb2_create io1, io2, io3;
1053         bool ret = true;
1054         const char *fname1 = BASEDIR "\\lease_break_test1.dat";
1055         const char *fname2 = BASEDIR "\\lease_break_test2.dat";
1056         const char *fname3 = BASEDIR "\\lease_break_test3.dat";
1057         struct smb2_tree *tree2A = NULL;
1058         struct smb2_tree *tree2B = NULL;
1059         struct smb2_tree *tree2C = NULL;
1060         struct smb2_transport *transport1 = tree1->session->transport;
1061         struct smb2_transport *transport2A = NULL;
1062         struct smbcli_options transport2_options;
1063         struct smb2_session *session1 = tree1->session;
1064         uint16_t local_port = 0;
1065         struct smb2_lease ls1;
1066         struct smb2_lease ls2;
1067         struct smb2_lease ls3;
1068         bool block_setup = false;
1069         bool block_ok = false;
1070         bool unblock_ok = false;
1071
1072
1073         if (!test_multichannel_initial_checks(tctx, tree1)) {
1074                 return true;
1075         }
1076
1077         torture_comment(tctx, "Lease break retry: Test2\n");
1078
1079         torture_reset_lease_break_info(tctx, &lease_break_info);
1080
1081         transport1->lease.handler = torture_lease_handler;
1082         transport1->lease.private_data = tree1;
1083         torture_comment(tctx, "transport1  [%p]\n", transport1);
1084         local_port = torture_get_local_port_from_transport(transport1);
1085         torture_comment(tctx, "transport1 uses tcp port: %d\n", local_port);
1086
1087         status = torture_smb2_testdir(tree1, BASEDIR, &_h);
1088         CHECK_STATUS(status, NT_STATUS_OK);
1089         smb2_util_close(tree1, _h);
1090         smb2_util_unlink(tree1, fname1);
1091         smb2_util_unlink(tree1, fname2);
1092         smb2_util_unlink(tree1, fname3);
1093         CHECK_VAL(lease_break_info.count, 0);
1094
1095         smb2_lease_create(&io1, &ls1, false, fname1, LEASE2F1,
1096                           smb2_util_lease_state("RHW"));
1097         test_multichannel_init_smb_create(&io1);
1098
1099         smb2_lease_create(&io2, &ls2, false, fname2, LEASE2F2,
1100                           smb2_util_lease_state("RHW"));
1101         test_multichannel_init_smb_create(&io2);
1102
1103         smb2_lease_create(&io3, &ls3, false, fname3, LEASE2F3,
1104                           smb2_util_lease_state("RHW"));
1105         test_multichannel_init_smb_create(&io3);
1106
1107         transport2_options = transport1->options;
1108
1109         ret = test_multichannel_create_channels(tctx, host, share,
1110                                                   credentials,
1111                                                   &transport2_options,
1112                                                   &tree2A, &tree2B, NULL);
1113         torture_assert(tctx, ret, "Could not create channels.\n");
1114         transport2A = tree2A->session->transport;
1115
1116         /* 2a opens file1 */
1117         torture_comment(tctx, "client2 opens fname1 via session 2A\n");
1118         smb2_lease_create(&io1, &ls1, false, fname1, LEASE2F1,
1119                           smb2_util_lease_state("RHW"));
1120         status = smb2_create(tree2A, mem_ctx, &io1);
1121         CHECK_STATUS(status, NT_STATUS_OK);
1122         h_client2_file1 = io1.out.file.handle;
1123         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1124         CHECK_LEASE(&io1, "RHW", true, LEASE2F1, 0);
1125         CHECK_VAL(io1.out.durable_open_v2, false); //true);
1126         CHECK_VAL(io1.out.timeout, io1.in.timeout);
1127         CHECK_VAL(io1.out.durable_open, false);
1128         CHECK_VAL(lease_break_info.count, 0);
1129
1130         /* 2b opens file2 */
1131         torture_comment(tctx, "client2 opens fname2 via session 2B\n");
1132         smb2_lease_create(&io2, &ls2, false, fname2, LEASE2F2,
1133                           smb2_util_lease_state("RHW"));
1134         status = smb2_create(tree2B, mem_ctx, &io2);
1135         CHECK_STATUS(status, NT_STATUS_OK);
1136         h_client2_file2 = io2.out.file.handle;
1137         CHECK_CREATED(&io2, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1138         CHECK_LEASE(&io2, "RHW", true, LEASE2F2, 0);
1139         CHECK_VAL(io2.out.durable_open_v2, false); //true);
1140         CHECK_VAL(io2.out.timeout, io2.in.timeout);
1141         CHECK_VAL(io2.out.durable_open, false);
1142         CHECK_VAL(lease_break_info.count, 0);
1143
1144         block_setup = test_setup_blocked_transports(tctx);
1145         torture_assert(tctx, block_setup, "test_setup_blocked_transports");
1146
1147         torture_comment(tctx, "Blocking 2A\n");
1148         /* Block 2A */
1149         block_ok = test_block_smb2_transport(tctx, transport2A);
1150         torture_assert(tctx, block_ok, "we could not block tcp transport");
1151
1152         torture_wait_for_lease_break(tctx);
1153         CHECK_VAL(lease_break_info.count, 0);
1154
1155         /* 1 opens file2 */
1156         torture_comment(tctx,
1157                         "Client opens fname2 with session1 with 2A blocked\n");
1158         smb2_lease_create(&io2, &ls2, false, fname2, LEASE1F2,
1159                           smb2_util_lease_state("RHW"));
1160         status = smb2_create(tree1, mem_ctx, &io2);
1161         CHECK_STATUS(status, NT_STATUS_OK);
1162         h_client1_file2 = io2.out.file.handle;
1163         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1164         CHECK_LEASE(&io2, "RH", true, LEASE1F2, 0);
1165         CHECK_VAL(io2.out.durable_open_v2, false);
1166         CHECK_VAL(io2.out.timeout, 0);
1167         CHECK_VAL(io2.out.durable_open, false);
1168
1169         if (lease_break_info.count == 0) {
1170                 torture_comment(tctx,
1171                                 "Did not receive expected lease break!!\n");
1172         } else {
1173                 torture_comment(tctx, "Received %d lease break(s)!!\n",
1174                                 lease_break_info.count);
1175         }
1176
1177         /*
1178          * We got breaks on both channels
1179          * (one failed on the blocked connection)
1180          */
1181         CHECK_VAL(lease_break_info.count, 2);
1182         lease_break_info.count -= 1;
1183         CHECK_VAL(lease_break_info.failures, 1);
1184         lease_break_info.failures -= 1;
1185         CHECK_BREAK_INFO("RHW", "RH", LEASE2F2);
1186         torture_reset_lease_break_info(tctx, &lease_break_info);
1187
1188         /* Connect 2C */
1189         torture_comment(tctx, "Connecting session 2C\n");
1190         talloc_free(tree2C);
1191         tree2C = test_multichannel_create_channel(tctx, host, share,
1192                                 credentials, &transport2_options, tree2A);
1193         if (!tree2C) {
1194                 goto done;
1195         }
1196
1197         /* 2c opens file3 */
1198         torture_comment(tctx, "client2 opens fname3 via session 2C\n");
1199         smb2_lease_create(&io3, &ls3, false, fname3, LEASE2F3,
1200                           smb2_util_lease_state("RHW"));
1201         status = smb2_create(tree2C, mem_ctx, &io3);
1202         CHECK_STATUS(status, NT_STATUS_OK);
1203         h_client2_file3 = io3.out.file.handle;
1204         CHECK_CREATED(&io3, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1205         CHECK_LEASE(&io3, "RHW", true, LEASE2F3, 0);
1206         CHECK_VAL(io3.out.durable_open_v2, false);
1207         CHECK_VAL(io3.out.timeout, io2.in.timeout);
1208         CHECK_VAL(io3.out.durable_open, false);
1209         CHECK_VAL(lease_break_info.count, 0);
1210
1211         /* Unblock 2A */
1212         torture_comment(tctx, "Unblocking 2A\n");
1213         unblock_ok = test_unblock_smb2_transport(tctx, transport2A);
1214         torture_assert(tctx, unblock_ok, "we could not unblock tcp transport");
1215
1216         /* 1 opens file1 */
1217         torture_comment(tctx, "Client opens fname1 with session 1\n");
1218         smb2_lease_create(&io1, &ls1, false, fname1, LEASE1F1,
1219                           smb2_util_lease_state("RHW"));
1220         status = smb2_create(tree1, mem_ctx, &io1);
1221         CHECK_STATUS(status, NT_STATUS_OK);
1222         h_client1_file1 = io1.out.file.handle;
1223         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1224         CHECK_LEASE(&io1, "RH", true, LEASE1F1, 0);
1225
1226         if (lease_break_info.count == 0) {
1227                 torture_comment(tctx,
1228                                 "Did not receive expected lease break!!\n");
1229         } else {
1230                 torture_comment(tctx,
1231                                 "Received %d lease break(s)!!\n",
1232                                 lease_break_info.count);
1233         }
1234         CHECK_VAL(lease_break_info.count, 1);
1235         CHECK_BREAK_INFO("RHW", "RH", LEASE2F1);
1236         torture_reset_lease_break_info(tctx, &lease_break_info);
1237
1238         /*1 opens file3 */
1239         torture_comment(tctx, "client opens fname3 via session 1\n");
1240
1241         smb2_lease_create(&io3, &ls3, false, fname3, LEASE1F3,
1242                           smb2_util_lease_state("RHW"));
1243         status = smb2_create(tree1, mem_ctx, &io3);
1244         CHECK_STATUS(status, NT_STATUS_OK);
1245         h_client1_file3 = io3.out.file.handle;
1246         CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1247         CHECK_LEASE(&io3, "RH", true, LEASE1F3, 0);
1248
1249         if (lease_break_info.count == 0) {
1250                 torture_comment(tctx,
1251                                 "Did not receive expected lease break!!\n");
1252         } else {
1253                 torture_comment(tctx,
1254                                 "Received %d lease break(s)!!\n",
1255                                 lease_break_info.count);
1256         }
1257         CHECK_VAL(lease_break_info.count, 1);
1258         CHECK_BREAK_INFO("RHW", "RH", LEASE2F3);
1259         torture_reset_lease_break_info(tctx, &lease_break_info);
1260
1261         smb2_util_close(tree1, h_client1_file1);
1262         smb2_util_close(tree1, h_client1_file2);
1263         smb2_util_close(tree1, h_client1_file3);
1264
1265         /*
1266          * Session 2 still has RW lease on file 1. Deletion of this file by 1
1267          *  leads to a lease break call to session 2 file1
1268          */
1269         smb2_util_unlink(tree1, fname1);
1270         /*
1271          * Bug - Samba does not revoke Handle lease on unlink
1272          * CHECK_BREAK_INFO("RH", "R", LEASE2F1);
1273          */
1274         torture_reset_lease_break_info(tctx, &lease_break_info);
1275
1276         /*
1277          * Session 2 still has RW lease on file 2. Deletion of this file by 1
1278          *  leads to a lease break call to session 2 file2
1279          */
1280         smb2_util_unlink(tree1, fname2);
1281         /*
1282          * Bug - Samba does not revoke Handle lease on unlink
1283          * CHECK_BREAK_INFO("RH", "R", LEASE2F2);
1284          */
1285         torture_reset_lease_break_info(tctx, &lease_break_info);
1286
1287         /*
1288          * Session 2 still has RW lease on file 3. Deletion of this file by 1
1289          *  leads to a lease break call to session 2 file3
1290          */
1291         smb2_util_unlink(tree1, fname3);
1292         /*
1293          * Bug - Samba does not revoke Handle lease on unlink
1294          * CHECK_BREAK_INFO("RH", "R", LEASE2F3);
1295          */
1296         torture_reset_lease_break_info(tctx, &lease_break_info);
1297
1298         smb2_util_close(tree2C, h_client2_file1);
1299         smb2_util_close(tree2C, h_client2_file2);
1300         smb2_util_close(tree2C, h_client2_file3);
1301
1302         test_multichannel_free_channels(tree2A, tree2B, tree2C);
1303         tree2A = tree2B = tree2C = NULL;
1304
1305 done:
1306         if (block_ok && !unblock_ok) {
1307                 test_unblock_smb2_transport(tctx, transport2A);
1308         }
1309         if (block_setup) {
1310                 test_cleanup_blocked_transports(tctx);
1311         }
1312
1313         tree1->session = session1;
1314
1315         smb2_util_close(tree1, h_client1_file1);
1316         smb2_util_close(tree1, h_client1_file2);
1317         smb2_util_close(tree1, h_client1_file3);
1318         if (tree2A != NULL) {
1319                 smb2_util_close(tree2A, h_client2_file1);
1320                 smb2_util_close(tree2A, h_client2_file2);
1321                 smb2_util_close(tree2A, h_client2_file3);
1322         }
1323
1324         if (h != NULL) {
1325                 smb2_util_close(tree1, *h);
1326         }
1327
1328         smb2_util_unlink(tree1, fname1);
1329         smb2_util_unlink(tree1, fname2);
1330         smb2_util_unlink(tree1, fname3);
1331         smb2_deltree(tree1, BASEDIR);
1332
1333         test_multichannel_free_channels(tree2A, tree2B, tree2C);
1334         talloc_free(tree1);
1335         talloc_free(mem_ctx);
1336
1337         return ret;
1338 }
1339
1340 /*
1341  * Test 3: Check to see how the server behaves if lease break
1342  *      response is sent over a different channel to one over which
1343  *      the break is received.
1344  *      Connect 2A, 2B
1345  *      open file1 in session 2A
1346  *      open file1 in session 1
1347  *           Lease break sent to 2A
1348  *           2B sends back lease break reply.
1349  *      session 1 allowed to open file
1350  */
1351 static bool test_multichannel_lease_break_test3(struct torture_context *tctx,
1352                                                 struct smb2_tree *tree1)
1353 {
1354         const char *host = torture_setting_string(tctx, "host", NULL);
1355         const char *share = torture_setting_string(tctx, "share", NULL);
1356         struct cli_credentials *credentials = popt_get_cmdline_credentials();
1357         NTSTATUS status;
1358         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1359         struct smb2_handle _h;
1360         struct smb2_handle *h = NULL;
1361         struct smb2_handle h_client1_file1 = {{0}};
1362         struct smb2_handle h_client2_file1 = {{0}};
1363         struct smb2_create io1;
1364         bool ret = true;
1365         const char *fname1 = BASEDIR "\\lease_break_test1.dat";
1366         struct smb2_tree *tree2A = NULL;
1367         struct smb2_tree *tree2B = NULL;
1368         struct smb2_transport *transport1 = tree1->session->transport;
1369         struct smb2_transport *transport2A = NULL;
1370         struct smbcli_options transport2_options;
1371         uint16_t local_port = 0;
1372         struct smb2_lease ls1;
1373         struct tevent_timer *te = NULL;
1374         struct timeval ne;
1375         bool timesup = false;
1376         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1377
1378         if (!test_multichannel_initial_checks(tctx, tree1)) {
1379                 return true;
1380         }
1381
1382         torture_comment(tctx, "Lease break retry: Test3\n");
1383
1384         torture_reset_lease_break_info(tctx, &lease_break_info);
1385
1386         transport1->lease.handler = torture_lease_handler;
1387         transport1->lease.private_data = tree1;
1388         torture_comment(tctx, "transport1  [%p]\n", transport1);
1389         local_port = torture_get_local_port_from_transport(transport1);
1390         torture_comment(tctx, "transport1 uses tcp port: %d\n", local_port);
1391
1392         status = torture_smb2_testdir(tree1, BASEDIR, &_h);
1393         CHECK_STATUS(status, NT_STATUS_OK);
1394         smb2_util_close(tree1, _h);
1395         smb2_util_unlink(tree1, fname1);
1396         CHECK_VAL(lease_break_info.count, 0);
1397
1398         smb2_lease_create(&io1, &ls1, false, fname1, LEASE2F1,
1399                           smb2_util_lease_state("RHW"));
1400         test_multichannel_init_smb_create(&io1);
1401
1402         transport2_options = transport1->options;
1403
1404         ret = test_multichannel_create_channels(tctx, host, share,
1405                                                 credentials,
1406                                                 &transport2_options,
1407                                                 &tree2A, &tree2B, NULL);
1408         torture_assert(tctx, ret, "Could not create channels.\n");
1409         transport2A = tree2A->session->transport;
1410         transport2A->lease.private_data = tree2B;
1411
1412         /* 2a opens file1 */
1413         torture_comment(tctx, "client2 opens fname1 via session 2A\n");
1414         smb2_lease_create(&io1, &ls1, false, fname1, LEASE2F1,
1415                           smb2_util_lease_state("RHW"));
1416         status = smb2_create(tree2A, mem_ctx, &io1);
1417         CHECK_STATUS(status, NT_STATUS_OK);
1418         h_client2_file1 = io1.out.file.handle;
1419         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1420         CHECK_LEASE(&io1, "RHW", true, LEASE2F1, 0);
1421         CHECK_VAL(io1.out.durable_open_v2, false); //true);
1422         CHECK_VAL(io1.out.timeout, io1.in.timeout);
1423         CHECK_VAL(io1.out.durable_open, false);
1424         CHECK_VAL(lease_break_info.count, 0);
1425
1426         /* Set a timeout for 5 seconds for session 1 to open file1 */
1427         ne = tevent_timeval_current_ofs(0, 5000000);
1428         te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, &timesup);
1429         if (te == NULL) {
1430                 torture_comment(tctx, "Failed to add timer.");
1431                 goto done;
1432         }
1433
1434         /* 1 opens file2 */
1435         torture_comment(tctx, "Client opens fname1 with session 1\n");
1436         smb2_lease_create(&io1, &ls1, false, fname1, LEASE1F1,
1437                           smb2_util_lease_state("RHW"));
1438         status = smb2_create(tree1, mem_ctx, &io1);
1439         CHECK_STATUS(status, NT_STATUS_OK);
1440         h_client1_file1 = io1.out.file.handle;
1441         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1442         CHECK_LEASE(&io1, "RH", true, LEASE1F1, 0);
1443         CHECK_VAL(io1.out.durable_open_v2, false);
1444         CHECK_VAL(io1.out.timeout, 0);
1445         CHECK_VAL(io1.out.durable_open, false);
1446
1447         CHECK_VAL(lease_break_info.count, 1);
1448         CHECK_BREAK_INFO("RHW", "RH", LEASE2F1);
1449
1450         /*
1451          * Check if timeout handler was fired. This would indicate
1452          * that the server didn't receive a reply for the oplock break
1453          * from the client and the server let session 1 open the file
1454          * only after the oplock break timeout.
1455          */
1456         CHECK_VAL(timesup, false);
1457
1458 done:
1459         smb2_util_close(tree1, h_client1_file1);
1460         if (tree2A != NULL) {
1461                 smb2_util_close(tree2A, h_client2_file1);
1462         }
1463
1464         if (h != NULL) {
1465                 smb2_util_close(tree1, *h);
1466         }
1467
1468         smb2_util_unlink(tree1, fname1);
1469         smb2_deltree(tree1, BASEDIR);
1470
1471         test_multichannel_free_channels(tree2A, tree2B, NULL);
1472         talloc_free(tree1);
1473         talloc_free(mem_ctx);
1474
1475         return ret;
1476 }
1477
1478 /*
1479  * Test limits of channels
1480  */
1481 static bool test_multichannel_num_channels(struct torture_context *tctx,
1482                                            struct smb2_tree *tree1)
1483 {
1484         const char *host = torture_setting_string(tctx, "host", NULL);
1485         const char *share = torture_setting_string(tctx, "share", NULL);
1486         struct cli_credentials *credentials = popt_get_cmdline_credentials();
1487         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1488         bool ret = true;
1489         struct smb2_tree **tree2 = NULL;
1490         struct smb2_transport *transport1 = tree1->session->transport;
1491         struct smb2_transport **transport2 = NULL;
1492         struct smbcli_options transport2_options;
1493         struct smb2_session **session2 = NULL;
1494         uint32_t server_capabilities;
1495         int i;
1496         int max_channels = 33; /* 32 is the W2K12R2 and W2K16 limit */
1497
1498         if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
1499                 torture_fail(tctx,
1500                              "SMB 3.X Dialect family required for Multichannel"
1501                              " tests\n");
1502         }
1503
1504         server_capabilities = smb2cli_conn_server_capabilities(
1505                                         tree1->session->transport->conn);
1506         if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
1507                 torture_fail(tctx,
1508                              "Server does not support multichannel.");
1509         }
1510
1511         torture_comment(tctx, "Testing max. number of channels\n");
1512
1513         transport2_options = transport1->options;
1514         transport2_options.client_guid = GUID_random();
1515
1516         tree2           = talloc_zero_array(mem_ctx, struct smb2_tree *,
1517                                             max_channels);
1518         transport2      = talloc_zero_array(mem_ctx, struct smb2_transport *,
1519                                             max_channels);
1520         session2        = talloc_zero_array(mem_ctx, struct smb2_session *,
1521                                             max_channels);
1522         if (tree2 == NULL || transport2 == NULL || session2 == NULL) {
1523                 torture_fail(tctx, "out of memory");
1524         }
1525
1526         for (i = 0; i < max_channels; i++) {
1527
1528                 NTSTATUS expected_status;
1529
1530                 torture_assert_ntstatus_ok_goto(tctx,
1531                         smb2_connect(tctx,
1532                                 host,
1533                                 lpcfg_smb_ports(tctx->lp_ctx),
1534                                 share,
1535                                 lpcfg_resolve_context(tctx->lp_ctx),
1536                                 credentials,
1537                                 &tree2[i],
1538                                 tctx->ev,
1539                                 &transport2_options,
1540                                 lpcfg_socket_options(tctx->lp_ctx),
1541                                 lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1542                                 ),
1543                         ret, done, "smb2_connect failed");
1544
1545                 transport2[i] = tree2[i]->session->transport;
1546
1547                 if (i == 0) {
1548                         /*
1549                          * done for the 1st channel
1550                          *
1551                          * For all remaining channels we do the
1552                          * session setup on our own.
1553                          */
1554                         transport2_options.only_negprot = true;
1555                         continue;
1556                 }
1557
1558                 /*
1559                  * Now bind the session2[i] to the transport2
1560                  */
1561                 session2[i] = smb2_session_channel(transport2[i],
1562                                                    lpcfg_gensec_settings(tctx,
1563                                                                  tctx->lp_ctx),
1564                                                    tree2[0],
1565                                                    tree2[0]->session);
1566
1567                 torture_assert(tctx, session2[i] != NULL,
1568                                "smb2_session_channel failed");
1569
1570                 torture_comment(tctx, "established transport2 [#%d]\n", i);
1571
1572                 if (i >= 32) {
1573                         expected_status = NT_STATUS_INSUFFICIENT_RESOURCES;
1574                 } else {
1575                         expected_status = NT_STATUS_OK;
1576                 }
1577
1578                 torture_assert_ntstatus_equal_goto(tctx,
1579                         smb2_session_setup_spnego(session2[i],
1580                                 popt_get_cmdline_credentials(),
1581                                 0 /* previous_session_id */),
1582                         expected_status,
1583                         ret, done,
1584                         talloc_asprintf(tctx, "failed to establish session "
1585                                               "setup for channel #%d", i));
1586
1587                 torture_comment(tctx, "bound session2 [#%d] to session2 [0]\n",
1588                                 i);
1589         }
1590
1591  done:
1592         talloc_free(mem_ctx);
1593
1594         return ret;
1595 }
1596
1597 struct torture_suite *torture_smb2_multichannel_init(TALLOC_CTX *ctx)
1598 {
1599         struct torture_suite *suite = torture_suite_create(ctx, "multichannel");
1600         struct torture_suite *suite_generic = torture_suite_create(ctx,
1601                                                                    "generic");
1602         struct torture_suite *suite_oplocks = torture_suite_create(ctx,
1603                                                                    "oplocks");
1604         struct torture_suite *suite_leases = torture_suite_create(ctx,
1605                                                                   "leases");
1606
1607         torture_suite_add_suite(suite, suite_generic);
1608         torture_suite_add_suite(suite, suite_oplocks);
1609         torture_suite_add_suite(suite, suite_leases);
1610
1611         torture_suite_add_1smb2_test(suite_generic, "interface_info",
1612                                      test_multichannel_interface_info);
1613         torture_suite_add_1smb2_test(suite_generic, "num_channels",
1614                                      test_multichannel_num_channels);
1615         torture_suite_add_1smb2_test(suite_oplocks, "test1",
1616                                      test_multichannel_oplock_break_test1);
1617         torture_suite_add_1smb2_test(suite_oplocks, "test2",
1618                                      test_multichannel_oplock_break_test2);
1619         torture_suite_add_1smb2_test(suite_leases, "test1",
1620                                      test_multichannel_lease_break_test1);
1621         torture_suite_add_1smb2_test(suite_leases, "test2",
1622                                      test_multichannel_lease_break_test2);
1623         torture_suite_add_1smb2_test(suite_leases, "test3",
1624                                      test_multichannel_lease_break_test3);
1625
1626         suite->description = talloc_strdup(suite, "SMB2 Multichannel tests");
1627
1628         return suite;
1629 }