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