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 
test_ioctl_network_interface_info(struct torture_context * tctx,struct smb2_tree * tree,struct fsctl_net_iface_info * info)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 
test_multichannel_interface_info(struct torture_context * tctx,struct smb2_tree * tree)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 
test_multichannel_create_channel(struct torture_context * tctx,const char * host,const char * share,struct cli_credentials * credentials,struct smbcli_options * transport_options,struct smb2_tree * parent_tree)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 				struct smbcli_options *transport_options,
172 				struct smb2_tree *parent_tree
173 				)
174 {
175 	NTSTATUS status;
176 	struct smb2_transport *transport;
177 	struct smb2_session *session;
178 	bool ret = true;
179 	struct smb2_tree *tree;
180 
181 	status = smb2_connect(tctx,
182 			host,
183 			lpcfg_smb_ports(tctx->lp_ctx),
184 			share,
185 			lpcfg_resolve_context(tctx->lp_ctx),
186 			credentials,
187 			&tree,
188 			tctx->ev,
189 			transport_options,
190 			lpcfg_socket_options(tctx->lp_ctx),
191 			lpcfg_gensec_settings(tctx, tctx->lp_ctx)
192 			);
193 	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
194 			"smb2_connect failed");
195 	transport = tree->session->transport;
196 	transport->oplock.handler = torture_oplock_ack_handler;
197 	transport->oplock.private_data = tree;
198 	transport->lease.handler = torture_lease_handler;
199 	transport->lease.private_data = tree;
200 	torture_comment(tctx, "established transport [%p]\n", transport);
201 
202 	/*
203 	 * If parent tree is set, bind the session to the parent transport
204 	 */
205 	if (parent_tree) {
206 		session = smb2_session_channel(transport,
207 				lpcfg_gensec_settings(tctx, tctx->lp_ctx),
208 				parent_tree, parent_tree->session);
209 		torture_assert_goto(tctx, session != NULL, ret, done,
210 				"smb2_session_channel failed");
211 
212 		tree->smbXcli = parent_tree->smbXcli;
213 		tree->session = session;
214 		status = smb2_session_setup_spnego(session,
215 						credentials,
216 						0 /* previous_session_id */);
217 		CHECK_STATUS(status, NT_STATUS_OK);
218 		torture_comment(tctx, "bound new session to parent\n");
219 	}
220 	/*
221 	 * We absolutely need to make sure to send something over this
222 	 * connection to register the oplock break handler with the smb client
223 	 * connection. If we do not send something (at least a keepalive), we
224 	 * will *NEVER* receive anything over this transport.
225 	 */
226 	smb2_keepalive(transport);
227 
228 done:
229 	if (ret) {
230 		return tree;
231 	} else {
232 		return NULL;
233 	}
234 }
235 
test_multichannel_create_channels(struct torture_context * tctx,const char * host,const char * share,struct cli_credentials * credentials,struct smbcli_options * transport_options,struct smb2_tree ** tree2A,struct smb2_tree ** tree2B,struct smb2_tree ** tree2C)236 bool test_multichannel_create_channels(
237 				struct torture_context *tctx,
238 				const char *host,
239 				const char *share,
240 				struct cli_credentials *credentials,
241 				struct smbcli_options *transport_options,
242 				struct smb2_tree **tree2A,
243 				struct smb2_tree **tree2B,
244 				struct smb2_tree **tree2C
245 				)
246 {
247 	struct smb2_tree *tree;
248 	struct smb2_transport *transport2A;
249 	struct smb2_transport *transport2B;
250 	struct smb2_transport *transport2C;
251 	uint16_t local_port = 0;
252 
253 	transport_options->client_guid = GUID_random();
254 
255 	/* Session 2A */
256 	torture_comment(tctx, "Setting up connection 2A\n");
257 	tree = test_multichannel_create_channel(tctx, host, share,
258 				credentials, transport_options, NULL);
259 	if (!tree) {
260 		goto done;
261 	}
262 	*tree2A = tree;
263 	transport2A = tree->session->transport;
264 	local_port = torture_get_local_port_from_transport(transport2A);
265 	torture_comment(tctx, "transport2A uses tcp port: %d\n", local_port);
266 
267 	/* Session 2B */
268 	if (tree2B) {
269 		torture_comment(tctx, "Setting up connection 2B\n");
270 		tree = test_multichannel_create_channel(tctx, host, share,
271 				credentials, transport_options, *tree2A);
272 		if (!tree) {
273 			goto done;
274 		}
275 		*tree2B = tree;
276 		transport2B = tree->session->transport;
277 		local_port = torture_get_local_port_from_transport(transport2B);
278 		torture_comment(tctx, "transport2B uses tcp port: %d\n",
279 								local_port);
280 	}
281 
282 	/* Session 2C */
283 	if (tree2C) {
284 		torture_comment(tctx, "Setting up connection 2C\n");
285 		tree = test_multichannel_create_channel(tctx, host, share,
286 				credentials, transport_options, *tree2A);
287 		if (!tree) {
288 			goto done;
289 		}
290 		*tree2C = tree;
291 		transport2C = tree->session->transport;
292 		local_port = torture_get_local_port_from_transport(transport2C);
293 		torture_comment(tctx, "transport2C uses tcp port: %d\n",
294 								local_port);
295 	}
296 
297 	return true;
298 done:
299 	return false;
300 }
301 
test_multichannel_free_channels(struct smb2_tree * tree2A,struct smb2_tree * tree2B,struct smb2_tree * tree2C)302 static void test_multichannel_free_channels(struct smb2_tree *tree2A,
303 					     struct smb2_tree *tree2B,
304 					     struct smb2_tree *tree2C)
305 {
306 	TALLOC_FREE(tree2A);
307 	TALLOC_FREE(tree2B);
308 	TALLOC_FREE(tree2C);
309 }
310 
test_multichannel_initial_checks(struct torture_context * tctx,struct smb2_tree * tree1)311 static bool test_multichannel_initial_checks(struct torture_context *tctx,
312 					     struct smb2_tree *tree1)
313 {
314 	struct smb2_transport *transport1 = tree1->session->transport;
315 	uint32_t server_capabilities;
316 	struct fsctl_net_iface_info info;
317 
318 	if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
319 		torture_skip_goto(tctx, fail,
320 				  "SMB 3.X Dialect family required for "
321 				  "Multichannel tests\n");
322 	}
323 
324 	server_capabilities = smb2cli_conn_server_capabilities(
325 					tree1->session->transport->conn);
326 	if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
327 		torture_skip_goto(tctx, fail,
328 			     "Server does not support multichannel.");
329 	}
330 
331 	torture_assert(tctx,
332 		test_ioctl_network_interface_info(tctx, tree1, &info),
333 		"failed to retrieve network interface info");
334 
335 	return true;
336 fail:
337 	return false;
338 }
339 
test_multichannel_init_smb_create(struct smb2_create * io)340 static void test_multichannel_init_smb_create(struct smb2_create *io)
341 {
342 	io->in.durable_open = false;
343 	io->in.durable_open_v2 = true;
344 	io->in.persistent_open = false;
345 	io->in.create_guid = GUID_random();
346 	io->in.timeout = 0x493E0; /* 300000 */
347 	/* windows 2016 returns 300000 0x493E0 */
348 }
349 
350 /*
351  * We simulate blocking incoming oplock break requests by simply ignoring
352  * the incoming break requests.
353  */
test_set_ignore_break_handler(struct torture_context * tctx,struct smb2_transport * transport)354 static bool test_set_ignore_break_handler(struct torture_context *tctx,
355 					  struct smb2_transport *transport)
356 {
357 	transport->oplock.handler = torture_oplock_ignore_handler;
358 	transport->lease.handler = torture_lease_ignore_handler;
359 
360 	return true;
361 }
362 
test_reset_break_handler(struct torture_context * tctx,struct smb2_transport * transport)363 static bool test_reset_break_handler(struct torture_context *tctx,
364 				     struct smb2_transport *transport)
365 {
366 	transport->oplock.handler = torture_oplock_ack_handler;
367 	transport->lease.handler = torture_lease_handler;
368 
369 	return true;
370 }
371 
372 /*
373  * Use iptables to block channels
374  */
test_iptables_block_channel(struct torture_context * tctx,struct smb2_transport * transport,const char * name)375 static bool test_iptables_block_channel(struct torture_context *tctx,
376 					struct smb2_transport *transport,
377 					const char *name)
378 {
379 	uint16_t local_port;
380 	bool ret;
381 
382 	local_port = torture_get_local_port_from_transport(transport);
383 	torture_comment(tctx, "transport uses tcp port: %d\n", local_port);
384 	ret = torture_block_tcp_transport_name(tctx, transport, name);
385 	torture_assert(tctx, ret, "we could not block tcp transport");
386 
387 	return ret;
388 }
389 
test_iptables_unblock_channel(struct torture_context * tctx,struct smb2_transport * transport,const char * name)390 static bool test_iptables_unblock_channel(struct torture_context *tctx,
391 					  struct smb2_transport *transport,
392 					  const char *name)
393 {
394 	uint16_t local_port;
395 	bool ret;
396 
397 	local_port = torture_get_local_port_from_transport(transport);
398 	torture_comment(tctx, "transport uses tcp port: %d\n", local_port);
399 	ret = torture_unblock_tcp_transport_name(tctx, transport, name);
400 	torture_assert(tctx, ret, "we could not block tcp transport");
401 
402 	return ret;
403 }
404 
405 #define test_block_channel(_tctx, _t) _test_block_channel(_tctx, _t, #_t)
_test_block_channel(struct torture_context * tctx,struct smb2_transport * transport,const char * name)406 static bool _test_block_channel(struct torture_context *tctx,
407 					  struct smb2_transport *transport,
408 					  const char *name)
409 {
410 	bool use_iptables = torture_setting_bool(tctx,
411 					"use_iptables", false);
412 
413 	if (use_iptables) {
414 		return test_iptables_block_channel(tctx, transport, name);
415 	} else {
416 		return test_set_ignore_break_handler(tctx, transport);
417 	}
418 }
419 
420 #define test_unblock_channel(_tctx, _t) _test_unblock_channel(_tctx, _t, #_t)
_test_unblock_channel(struct torture_context * tctx,struct smb2_transport * transport,const char * name)421 static bool _test_unblock_channel(struct torture_context *tctx,
422 					  struct smb2_transport *transport,
423 					  const char *name)
424 {
425 	bool use_iptables = torture_setting_bool(tctx,
426 					"use_iptables", false);
427 
428 	if (use_iptables) {
429 		return test_iptables_unblock_channel(tctx, transport, name);
430 	} else {
431 		return test_reset_break_handler(tctx, transport);
432 	}
433 }
434 
test_cleanup_blocked_channels(struct torture_context * tctx)435 static void test_cleanup_blocked_channels(struct torture_context *tctx)
436 {
437 	bool use_iptables = torture_setting_bool(tctx,
438 					"use_iptables", false);
439 
440 	if (use_iptables) {
441 		torture_unblock_cleanup(tctx);
442 	}
443 }
444 
445 /* Timer handler function notifies the registering function that time is up */
timeout_cb(struct tevent_context * ev,struct tevent_timer * te,struct timeval current_time,void * private_data)446 static void timeout_cb(struct tevent_context *ev,
447 		       struct tevent_timer *te,
448 		       struct timeval current_time,
449 		       void *private_data)
450 {
451 	bool *timesup = (bool *)private_data;
452 	*timesup = true;
453 }
454 
455 /*
456  * Oplock break - Test 1
457  * Test to confirm that server sends oplock breaks as expected.
458  * open file1 in session 2A
459  * open file2 in session 2B
460  * open file1 in session 1
461  *      oplock break received
462  * open file1 in session 1
463  *      oplock break received
464  * Cleanup
465  */
test_multichannel_oplock_break_test1(struct torture_context * tctx,struct smb2_tree * tree1)466 static bool test_multichannel_oplock_break_test1(struct torture_context *tctx,
467 					   struct smb2_tree *tree1)
468 {
469 	const char *host = torture_setting_string(tctx, "host", NULL);
470 	const char *share = torture_setting_string(tctx, "share", NULL);
471 	struct cli_credentials *credentials = popt_get_cmdline_credentials();
472 	NTSTATUS status;
473 	TALLOC_CTX *mem_ctx = talloc_new(tctx);
474 	struct smb2_handle _h;
475 	struct smb2_handle h_client1_file1 = {{0}};
476 	struct smb2_handle h_client1_file2 = {{0}};
477 	struct smb2_handle h_client1_file3 = {{0}};
478 	struct smb2_handle h_client2_file1 = {{0}};
479 	struct smb2_handle h_client2_file2 = {{0}};
480 	struct smb2_handle h_client2_file3 = {{0}};
481 	struct smb2_create io1, io2, io3;
482 	bool ret = true;
483 	const char *fname1 = BASEDIR "\\oplock_break_test1.dat";
484 	const char *fname2 = BASEDIR "\\oplock_break_test2.dat";
485 	const char *fname3 = BASEDIR "\\oplock_break_test3.dat";
486 	struct smb2_tree *tree2A = NULL;
487 	struct smb2_tree *tree2B = NULL;
488 	struct smb2_tree *tree2C = NULL;
489 	struct smb2_transport *transport1 = tree1->session->transport;
490 	struct smbcli_options transport2_options;
491 	struct smb2_session *session1 = tree1->session;
492 	uint16_t local_port = 0;
493 
494 	if (!test_multichannel_initial_checks(tctx, tree1)) {
495 		return true;
496 	}
497 
498 	torture_comment(tctx, "Oplock break retry: Test1\n");
499 
500 	torture_reset_break_info(tctx, &break_info);
501 
502 	transport1->oplock.handler = torture_oplock_ack_handler;
503 	transport1->oplock.private_data = tree1;
504 	torture_comment(tctx, "transport1  [%p]\n", transport1);
505 	local_port = torture_get_local_port_from_transport(transport1);
506 	torture_comment(tctx, "transport1 uses tcp port: %d\n", local_port);
507 
508 	status = torture_smb2_testdir(tree1, BASEDIR, &_h);
509 	CHECK_STATUS(status, NT_STATUS_OK);
510 	smb2_util_close(tree1, _h);
511 	smb2_util_unlink(tree1, fname1);
512 	smb2_util_unlink(tree1, fname2);
513 	smb2_util_unlink(tree1, fname3);
514 	CHECK_VAL(break_info.count, 0);
515 
516 	smb2_oplock_create_share(&io1, fname1,
517 			smb2_util_share_access("RWD"),
518 			smb2_util_oplock_level("b"));
519 	test_multichannel_init_smb_create(&io1);
520 
521 	smb2_oplock_create_share(&io2, fname2,
522 			smb2_util_share_access("RWD"),
523 			smb2_util_oplock_level("b"));
524 	test_multichannel_init_smb_create(&io2);
525 
526 	smb2_oplock_create_share(&io3, fname3,
527 			smb2_util_share_access("RWD"),
528 			smb2_util_oplock_level("b"));
529 	test_multichannel_init_smb_create(&io3);
530 
531 	transport2_options = transport1->options;
532 
533 	ret = test_multichannel_create_channels(tctx, host, share,
534 						  credentials,
535 						  &transport2_options,
536 						  &tree2A, &tree2B, NULL);
537 	torture_assert(tctx, ret, "Could not create channels.\n");
538 
539 	/* 2a opens file1 */
540 	torture_comment(tctx, "client2 opens fname1 via session 2A\n");
541 	status = smb2_create(tree2A, mem_ctx, &io1);
542 	CHECK_STATUS(status, NT_STATUS_OK);
543 	h_client2_file1 = io1.out.file.handle;
544 	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
545 	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
546 	torture_wait_for_oplock_break(tctx);
547 	CHECK_VAL(break_info.count, 0);
548 
549 	/* 2b opens file2 */
550 	torture_comment(tctx, "client2 opens fname2 via session 2B\n");
551 	status = smb2_create(tree2B, mem_ctx, &io2);
552 	CHECK_STATUS(status, NT_STATUS_OK);
553 	h_client2_file2 = io2.out.file.handle;
554 	CHECK_CREATED(&io2, CREATED, FILE_ATTRIBUTE_ARCHIVE);
555 	CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("b"));
556 	torture_wait_for_oplock_break(tctx);
557 	CHECK_VAL(break_info.count, 0);
558 
559 
560 	/* 1 opens file1 - batchoplock break? */
561 	torture_comment(tctx, "client1 opens fname1 via session 1\n");
562 	io1.in.oplock_level = smb2_util_oplock_level("b");
563 	status = smb2_create(tree1, mem_ctx, &io1);
564 	CHECK_STATUS(status, NT_STATUS_OK);
565 	h_client1_file1 = io1.out.file.handle;
566 	CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
567 	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("s"));
568 	torture_wait_for_oplock_break(tctx);
569 	CHECK_VAL(break_info.count, 1);
570 
571 	torture_reset_break_info(tctx, &break_info);
572 
573 	/* 1 opens file2 - batchoplock break? */
574 	torture_comment(tctx, "client1 opens fname2 via session 1\n");
575 	io2.in.oplock_level = smb2_util_oplock_level("b");
576 	status = smb2_create(tree1, mem_ctx, &io2);
577 	CHECK_STATUS(status, NT_STATUS_OK);
578 	h_client1_file2 = io2.out.file.handle;
579 	CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
580 	CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("s"));
581 	torture_wait_for_oplock_break(tctx);
582 	CHECK_VAL(break_info.count, 1);
583 
584 	/* cleanup everything */
585 	torture_reset_break_info(tctx, &break_info);
586 
587 	smb2_util_close(tree1, h_client1_file1);
588 	smb2_util_close(tree1, h_client1_file2);
589 	smb2_util_close(tree1, h_client1_file3);
590 	smb2_util_close(tree2A, h_client2_file1);
591 	smb2_util_close(tree2A, h_client2_file2);
592 	smb2_util_close(tree2A, h_client2_file3);
593 
594 	smb2_util_unlink(tree1, fname1);
595 	smb2_util_unlink(tree1, fname2);
596 	smb2_util_unlink(tree1, fname3);
597 	CHECK_VAL(break_info.count, 0);
598 	test_multichannel_free_channels(tree2A, tree2B, tree2C);
599 	tree2A = tree2B = tree2C = NULL;
600 done:
601 	tree1->session = session1;
602 
603 	smb2_util_close(tree1, h_client1_file1);
604 	smb2_util_close(tree1, h_client1_file2);
605 	smb2_util_close(tree1, h_client1_file3);
606 	if (tree2A != NULL) {
607 		smb2_util_close(tree2A, h_client2_file1);
608 		smb2_util_close(tree2A, h_client2_file2);
609 		smb2_util_close(tree2A, h_client2_file3);
610 	}
611 
612 	smb2_util_unlink(tree1, fname1);
613 	smb2_util_unlink(tree1, fname2);
614 	smb2_util_unlink(tree1, fname3);
615 	smb2_deltree(tree1, BASEDIR);
616 
617 	test_multichannel_free_channels(tree2A, tree2B, tree2C);
618 	talloc_free(tree1);
619 	talloc_free(mem_ctx);
620 
621 	return ret;
622 }
623 
624 /*
625  * Oplock Break Test 2
626  * Test to see if oplock break retries are sent by the server.
627  * Also checks to see if new channels can be created and used
628  * after an oplock break retry.
629  * open file1 in 2A
630  * open file2 in 2B
631  * open file1 in session 1
632  *      oplock break received
633  * block channel on which oplock break received
634  * open file2 in session 1
635  *      oplock break not received. Retry received.
636  *      file opened
637  * write to file2 on 2B
638  *      Break sent to session 1(which has file2 open)
639  *      Break sent to session 2A(which has read oplock)
640  * close file1 in session 1
641  * open file1 with session 1
642  * unblock blocked channel
643  * disconnect blocked channel
644  * connect channel 2D
645  * open file3 in 2D
646  * open file3 in session 1
647  *      receive break
648  */
test_multichannel_oplock_break_test2(struct torture_context * tctx,struct smb2_tree * tree1)649 static bool test_multichannel_oplock_break_test2(struct torture_context *tctx,
650 					   struct smb2_tree *tree1)
651 {
652 	const char *host = torture_setting_string(tctx, "host", NULL);
653 	const char *share = torture_setting_string(tctx, "share", NULL);
654 	struct cli_credentials *credentials = popt_get_cmdline_credentials();
655 	NTSTATUS status;
656 	TALLOC_CTX *mem_ctx = talloc_new(tctx);
657 	struct smb2_handle _h;
658 	struct smb2_handle h_client1_file1 = {{0}};
659 	struct smb2_handle h_client1_file2 = {{0}};
660 	struct smb2_handle h_client1_file3 = {{0}};
661 	struct smb2_handle h_client2_file1 = {{0}};
662 	struct smb2_handle h_client2_file2 = {{0}};
663 	struct smb2_handle h_client2_file3 = {{0}};
664 	struct smb2_create io1, io2, io3;
665 	bool ret = true;
666 	const char *fname1 = BASEDIR "\\oplock_break_test1.dat";
667 	const char *fname2 = BASEDIR "\\oplock_break_test2.dat";
668 	const char *fname3 = BASEDIR "\\oplock_break_test3.dat";
669 	struct smb2_tree *tree2A = NULL;
670 	struct smb2_tree *tree2B = NULL;
671 	struct smb2_tree *tree2C = NULL;
672 	struct smb2_tree *tree2D = NULL;
673 	struct smb2_transport *transport1 = tree1->session->transport;
674 	struct smb2_transport *transport2 = NULL;
675 	struct smbcli_options transport2_options;
676 	struct smb2_session *session1 = tree1->session;
677 	uint16_t local_port = 0;
678 	DATA_BLOB blob;
679 	bool block_ok = false;
680 	bool unblock_ok = false;
681 
682 	if (!test_multichannel_initial_checks(tctx, tree1)) {
683 		return true;
684 	}
685 
686 	torture_comment(tctx, "Oplock break retry: Test2\n");
687 
688 	torture_reset_break_info(tctx, &break_info);
689 
690 	transport1->oplock.handler = torture_oplock_ack_handler;
691 	transport1->oplock.private_data = tree1;
692 	torture_comment(tctx, "transport1  [%p]\n", transport1);
693 	local_port = torture_get_local_port_from_transport(transport1);
694 	torture_comment(tctx, "transport1 uses tcp port: %d\n", local_port);
695 
696 	status = torture_smb2_testdir(tree1, BASEDIR, &_h);
697 	CHECK_STATUS(status, NT_STATUS_OK);
698 	smb2_util_close(tree1, _h);
699 	smb2_util_unlink(tree1, fname1);
700 	smb2_util_unlink(tree1, fname2);
701 	smb2_util_unlink(tree1, fname3);
702 	CHECK_VAL(break_info.count, 0);
703 
704 	smb2_oplock_create_share(&io1, fname1,
705 			smb2_util_share_access("RWD"),
706 			smb2_util_oplock_level("b"));
707 	test_multichannel_init_smb_create(&io1);
708 
709 	smb2_oplock_create_share(&io2, fname2,
710 			smb2_util_share_access("RWD"),
711 			smb2_util_oplock_level("b"));
712 	test_multichannel_init_smb_create(&io2);
713 
714 	smb2_oplock_create_share(&io3, fname3,
715 			smb2_util_share_access("RWD"),
716 			smb2_util_oplock_level("b"));
717 	test_multichannel_init_smb_create(&io3);
718 
719 	transport2_options = transport1->options;
720 
721 	ret = test_multichannel_create_channels(tctx, host, share,
722 						  credentials,
723 						  &transport2_options,
724 						  &tree2A, &tree2B, &tree2C);
725 	torture_assert(tctx, ret, "Could not create channels.\n");
726 
727 	torture_comment(tctx, "client2 opens fname1 via session 2A\n");
728 	io1.in.oplock_level = smb2_util_oplock_level("b");
729 	status = smb2_create(tree2A, mem_ctx, &io1);
730 	CHECK_STATUS(status, NT_STATUS_OK);
731 	h_client2_file1 = io1.out.file.handle;
732 	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
733 	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
734 	torture_wait_for_oplock_break(tctx);
735 	CHECK_VAL(break_info.count, 0);
736 
737 
738 	torture_comment(tctx, "client2 opens fname2 via session 2B\n");
739 	io2.in.oplock_level = smb2_util_oplock_level("b");
740 	status = smb2_create(tree2B, mem_ctx, &io2);
741 	CHECK_STATUS(status, NT_STATUS_OK);
742 	h_client2_file2 = io2.out.file.handle;
743 	CHECK_CREATED(&io2, CREATED, FILE_ATTRIBUTE_ARCHIVE);
744 	CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("b"));
745 	torture_wait_for_oplock_break(tctx);
746 	CHECK_VAL(break_info.count, 0);
747 
748 
749 	torture_comment(tctx, "client1 opens fname1 via session 1\n");
750 	io1.in.oplock_level = smb2_util_oplock_level("b");
751 	status = smb2_create(tree1, mem_ctx, &io1);
752 	CHECK_STATUS(status, NT_STATUS_OK);
753 	h_client1_file1 = io1.out.file.handle;
754 	CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
755 	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("s"));
756 	torture_wait_for_oplock_break(tctx);
757 	CHECK_VAL(break_info.count, 1);
758 
759 	/* We use the transport over which this oplock break was received */
760 	transport2 = break_info.received_transport;
761 	torture_reset_break_info(tctx, &break_info);
762 
763 	/* block channel */
764 	block_ok = test_block_channel(tctx, transport2);
765 
766 	torture_comment(tctx, "client1 opens fname2 via session 1\n");
767 	io2.in.oplock_level = smb2_util_oplock_level("b");
768 	status = smb2_create(tree1, mem_ctx, &io2);
769 	CHECK_STATUS(status, NT_STATUS_OK);
770 	h_client1_file2 = io2.out.file.handle;
771 	CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
772 	CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("s"));
773 
774 	/*
775 	 * Samba downgrades oplock to a level 2 oplock.
776 	 * Windows 2016 revokes oplock
777 	 */
778 	torture_wait_for_oplock_break(tctx);
779 	CHECK_VAL(break_info.count, 1);
780 	torture_reset_break_info(tctx, &break_info);
781 
782 	torture_comment(tctx, "Trying write to file2 on tree2B\n");
783 
784 	blob = data_blob_string_const("Here I am");
785 	status = smb2_util_write(tree2B,
786 				 h_client2_file2,
787 				 blob.data,
788 				 0,
789 				 blob.length);
790 	torture_assert_ntstatus_ok(tctx, status,
791 		"failed to write file2 via channel 2B");
792 
793 	/*
794 	 * Samba: Write triggers 2 oplock breaks
795 	 *  for session 1 which has file2 open
796 	 *  for session 2 which has type 2 oplock
797 	 * Windows 2016: Only one oplock break for session 1
798 	 */
799 	torture_wait_for_oplock_break(tctx);
800 	CHECK_VAL_GREATER_THAN(break_info.count, 0);
801 	torture_reset_break_info(tctx, &break_info);
802 
803 	torture_comment(tctx, "client1 closes fname2 via session 1\n");
804 	smb2_util_close(tree1, h_client1_file2);
805 
806 	torture_comment(tctx, "client1 opens fname2 via session 1 again\n");
807 	io2.in.oplock_level = smb2_util_oplock_level("b");
808 	status = smb2_create(tree1, mem_ctx, &io2);
809 	CHECK_STATUS(status, NT_STATUS_OK);
810 	h_client1_file2 = io2.out.file.handle;
811 	io2.out.alloc_size = 0;
812 	io2.out.size = 0;
813 	CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
814 	CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("s"));
815 
816 	/*
817 	 * now add a fourth channel and repeat the test, we need to reestablish
818 	 * transport2 because the remote end has invalidated our connection
819 	 */
820 	torture_comment(tctx, "Connecting session 2D\n");
821 	tree2D = test_multichannel_create_channel(tctx, host, share,
822 				     credentials, &transport2_options, tree2B);
823 	if (!tree2D) {
824 		goto done;
825 	}
826 
827 	torture_reset_break_info(tctx, &break_info);
828 	torture_comment(tctx, "client 2 opening fname3 over transport2D\n");
829 	status = smb2_create(tree2D, mem_ctx, &io3);
830 	CHECK_STATUS(status, NT_STATUS_OK);
831 	h_client2_file3 = io3.out.file.handle;
832 	CHECK_CREATED(&io3, CREATED, FILE_ATTRIBUTE_ARCHIVE);
833 	CHECK_VAL(io3.out.oplock_level, smb2_util_oplock_level("b"));
834 	torture_wait_for_oplock_break(tctx);
835 	CHECK_VAL(break_info.count, 0);
836 
837 	torture_comment(tctx, "client1 opens fname3 via session 1\n");
838 	status = smb2_create(tree1, mem_ctx, &io3);
839 	CHECK_STATUS(status, NT_STATUS_OK);
840 	h_client1_file3 = io3.out.file.handle;
841 	CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
842 	CHECK_VAL(io3.out.oplock_level, smb2_util_oplock_level("s"));
843 	torture_wait_for_oplock_break(tctx);
844 	CHECK_VAL(break_info.count, 1);
845 
846 done:
847 	if (block_ok && !unblock_ok) {
848 		test_unblock_channel(tctx, transport2);
849 	}
850 	test_cleanup_blocked_channels(tctx);
851 
852 	tree1->session = session1;
853 
854 	smb2_util_close(tree1, h_client1_file1);
855 	smb2_util_close(tree1, h_client1_file2);
856 	smb2_util_close(tree1, h_client1_file3);
857 	if (tree2B != NULL) {
858 		smb2_util_close(tree2B, h_client2_file1);
859 		smb2_util_close(tree2B, h_client2_file2);
860 		smb2_util_close(tree2B, h_client2_file3);
861 	}
862 
863 	smb2_util_unlink(tree1, fname1);
864 	smb2_util_unlink(tree1, fname2);
865 	smb2_util_unlink(tree1, fname3);
866 	smb2_deltree(tree1, BASEDIR);
867 
868 	test_multichannel_free_channels(tree2A, tree2B, tree2C);
869 	if (tree2D != NULL) {
870 		TALLOC_FREE(tree2D);
871 	}
872 	talloc_free(tree1);
873 	talloc_free(mem_ctx);
874 
875 	return ret;
876 }
877 
878 static const uint64_t LEASE1F1 = 0xBADC0FFEE0DDF00Dull;
879 static const uint64_t LEASE1F2 = 0xBADC0FFEE0DDD00Dull;
880 static const uint64_t LEASE1F3 = 0xDADC0FFEE0DDD00Dull;
881 static const uint64_t LEASE2F1 = 0xDEADBEEFFEEDBEADull;
882 static const uint64_t LEASE2F2 = 0xDAD0FFEDD00DF00Dull;
883 static const uint64_t LEASE2F3 = 0xBAD0FFEDD00DF00Dull;
884 
885 /*
886  * Lease Break Test 1:
887  * Test to check if lease breaks are sent by the server as expected.
888  *      open file1 in session 2A
889  *      open file2 in session 2B
890  *      open file3 in session 2C
891  *      open file1 in session 1
892  *           lease break sent
893  *      open file2 in session 1
894  *           lease break sent
895  *      open file3 in session 1
896  *           lease break sent
897  */
test_multichannel_lease_break_test1(struct torture_context * tctx,struct smb2_tree * tree1)898 static bool test_multichannel_lease_break_test1(struct torture_context *tctx,
899 						struct smb2_tree *tree1)
900 {
901 	const char *host = torture_setting_string(tctx, "host", NULL);
902 	const char *share = torture_setting_string(tctx, "share", NULL);
903 	struct cli_credentials *credentials = popt_get_cmdline_credentials();
904 	NTSTATUS status;
905 	TALLOC_CTX *mem_ctx = talloc_new(tctx);
906 	struct smb2_handle _h;
907 	struct smb2_handle *h = NULL;
908 	struct smb2_handle h_client1_file1 = {{0}};
909 	struct smb2_handle h_client1_file2 = {{0}};
910 	struct smb2_handle h_client1_file3 = {{0}};
911 	struct smb2_handle h_client2_file1 = {{0}};
912 	struct smb2_handle h_client2_file2 = {{0}};
913 	struct smb2_handle h_client2_file3 = {{0}};
914 	struct smb2_create io1, io2, io3;
915 	bool ret = true;
916 	const char *fname1 = BASEDIR "\\lease_break_test1.dat";
917 	const char *fname2 = BASEDIR "\\lease_break_test2.dat";
918 	const char *fname3 = BASEDIR "\\lease_break_test3.dat";
919 	struct smb2_tree *tree2A = NULL;
920 	struct smb2_tree *tree2B = NULL;
921 	struct smb2_tree *tree2C = NULL;
922 	struct smb2_transport *transport1 = tree1->session->transport;
923 	struct smbcli_options transport2_options;
924 	struct smb2_session *session1 = tree1->session;
925 	uint16_t local_port = 0;
926 	struct smb2_lease ls1;
927 	struct smb2_lease ls2;
928 	struct smb2_lease ls3;
929 
930 	if (!test_multichannel_initial_checks(tctx, tree1)) {
931 		return true;
932 	}
933 
934 	torture_comment(tctx, "Lease break retry: Test1\n");
935 
936 	torture_reset_lease_break_info(tctx, &lease_break_info);
937 
938 	transport1->lease.handler = torture_lease_handler;
939 	transport1->lease.private_data = tree1;
940 	torture_comment(tctx, "transport1  [%p]\n", transport1);
941 	local_port = torture_get_local_port_from_transport(transport1);
942 	torture_comment(tctx, "transport1 uses tcp port: %d\n", local_port);
943 
944 	status = torture_smb2_testdir(tree1, BASEDIR, &_h);
945 	CHECK_STATUS(status, NT_STATUS_OK);
946 	smb2_util_close(tree1, _h);
947 	smb2_util_unlink(tree1, fname1);
948 	smb2_util_unlink(tree1, fname2);
949 	smb2_util_unlink(tree1, fname3);
950 	CHECK_VAL(lease_break_info.count, 0);
951 
952 	smb2_lease_create(&io1, &ls1, false, fname1, LEASE2F1,
953 			  smb2_util_lease_state("RHW"));
954 	test_multichannel_init_smb_create(&io1);
955 
956 	smb2_lease_create(&io2, &ls2, false, fname2, LEASE2F2,
957 			  smb2_util_lease_state("RHW"));
958 	test_multichannel_init_smb_create(&io2);
959 
960 	smb2_lease_create(&io3, &ls3, false, fname3, LEASE2F3,
961 			  smb2_util_lease_state("RHW"));
962 	test_multichannel_init_smb_create(&io3);
963 
964 	transport2_options = transport1->options;
965 
966 	ret = test_multichannel_create_channels(tctx, host, share,
967 						  credentials,
968 						  &transport2_options,
969 						  &tree2A, &tree2B, &tree2C);
970 	torture_assert(tctx, ret, "Could not create channels.\n");
971 
972 	/* 2a opens file1 */
973 	torture_comment(tctx, "client2 opens fname1 via session 2A\n");
974 	status = smb2_create(tree2A, mem_ctx, &io1);
975 	CHECK_STATUS(status, NT_STATUS_OK);
976 	h_client2_file1 = io1.out.file.handle;
977 	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
978 	CHECK_LEASE(&io1, "RHW", true, LEASE2F1, 0);
979 	CHECK_VAL(lease_break_info.count, 0);
980 
981 	/* 2b opens file2 */
982 	torture_comment(tctx, "client2 opens fname2 via session 2B\n");
983 	status = smb2_create(tree2B, mem_ctx, &io2);
984 	CHECK_STATUS(status, NT_STATUS_OK);
985 	h_client2_file2 = io2.out.file.handle;
986 	CHECK_CREATED(&io2, CREATED, FILE_ATTRIBUTE_ARCHIVE);
987 	CHECK_LEASE(&io2, "RHW", true, LEASE2F2, 0);
988 	CHECK_VAL(lease_break_info.count, 0);
989 
990 	/* 2c opens file3 */
991 	torture_comment(tctx, "client2 opens fname3 via session 2C\n");
992 	smb2_lease_create(&io3, &ls3, false, fname3, LEASE2F3,
993 			  smb2_util_lease_state("RHW"));
994 	status = smb2_create(tree2C, mem_ctx, &io3);
995 	CHECK_STATUS(status, NT_STATUS_OK);
996 	h_client2_file3 = io3.out.file.handle;
997 	CHECK_CREATED(&io3, CREATED, FILE_ATTRIBUTE_ARCHIVE);
998 	CHECK_LEASE(&io3, "RHW", true, LEASE2F3, 0);
999 	CHECK_VAL(lease_break_info.count, 0);
1000 
1001 	/* 1 opens file1 - lease break? */
1002 	torture_comment(tctx, "client1 opens fname1 via session 1\n");
1003 	smb2_lease_create(&io1, &ls1, false, fname1, LEASE1F1,
1004 			  smb2_util_lease_state("RHW"));
1005 	status = smb2_create(tree1, mem_ctx, &io1);
1006 	CHECK_STATUS(status, NT_STATUS_OK);
1007 	h_client1_file1 = io1.out.file.handle;
1008 	CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1009 	CHECK_LEASE(&io1, "RH", true, LEASE1F1, 0);
1010 	CHECK_BREAK_INFO("RHW", "RH", LEASE2F1);
1011 	CHECK_VAL(lease_break_info.count, 1);
1012 
1013 	torture_reset_lease_break_info(tctx, &lease_break_info);
1014 
1015 	/* 1 opens file2 - lease break? */
1016 	torture_comment(tctx, "client1 opens fname2 via session 1\n");
1017 	smb2_lease_create(&io2, &ls2, false, fname2, LEASE1F2,
1018 			  smb2_util_lease_state("RHW"));
1019 	status = smb2_create(tree1, mem_ctx, &io2);
1020 	CHECK_STATUS(status, NT_STATUS_OK);
1021 	h_client1_file2 = io2.out.file.handle;
1022 	CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1023 	CHECK_LEASE(&io2, "RH", true, LEASE1F2, 0);
1024 	CHECK_BREAK_INFO("RHW", "RH", LEASE2F2);
1025 	CHECK_VAL(lease_break_info.count, 1);
1026 
1027 	torture_reset_lease_break_info(tctx, &lease_break_info);
1028 
1029 	/* 1 opens file3 - lease break? */
1030 	torture_comment(tctx, "client1 opens fname3 via session 1\n");
1031 	smb2_lease_create(&io3, &ls3, false, fname3, LEASE1F3,
1032 			  smb2_util_lease_state("RHW"));
1033 	status = smb2_create(tree1, mem_ctx, &io3);
1034 	CHECK_STATUS(status, NT_STATUS_OK);
1035 	h_client1_file3 = io3.out.file.handle;
1036 	CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1037 	CHECK_LEASE(&io3, "RH", true, LEASE1F3, 0);
1038 	CHECK_BREAK_INFO("RHW", "RH", LEASE2F3);
1039 	CHECK_VAL(lease_break_info.count, 1);
1040 
1041 	/* cleanup everything */
1042 	torture_reset_lease_break_info(tctx, &lease_break_info);
1043 
1044 	smb2_util_close(tree1, h_client1_file1);
1045 	smb2_util_close(tree1, h_client1_file2);
1046 	smb2_util_close(tree1, h_client1_file3);
1047 	smb2_util_close(tree2A, h_client2_file1);
1048 	smb2_util_close(tree2A, h_client2_file2);
1049 	smb2_util_close(tree2A, h_client2_file3);
1050 
1051 	smb2_util_unlink(tree1, fname1);
1052 	smb2_util_unlink(tree1, fname2);
1053 	smb2_util_unlink(tree1, fname3);
1054 	CHECK_VAL(lease_break_info.count, 0);
1055 	test_multichannel_free_channels(tree2A, tree2B, tree2C);
1056 	tree2A = tree2B = tree2C = NULL;
1057 done:
1058 	tree1->session = session1;
1059 
1060 	smb2_util_close(tree1, h_client1_file1);
1061 	smb2_util_close(tree1, h_client1_file2);
1062 	smb2_util_close(tree1, h_client1_file3);
1063 	if (tree2A != NULL) {
1064 		smb2_util_close(tree2A, h_client2_file1);
1065 		smb2_util_close(tree2A, h_client2_file2);
1066 		smb2_util_close(tree2A, h_client2_file3);
1067 	}
1068 
1069 	if (h != NULL) {
1070 		smb2_util_close(tree1, *h);
1071 	}
1072 
1073 	smb2_util_unlink(tree1, fname1);
1074 	smb2_util_unlink(tree1, fname2);
1075 	smb2_util_unlink(tree1, fname3);
1076 	smb2_deltree(tree1, BASEDIR);
1077 
1078 	test_multichannel_free_channels(tree2A, tree2B, tree2C);
1079 	talloc_free(tree1);
1080 	talloc_free(mem_ctx);
1081 
1082 	return ret;
1083 }
1084 
1085 /*
1086  * Lease Break Test 2:
1087  * Test for lease break retries being sent by the server.
1088  *      Connect 2A, 2B
1089  *      open file1 in session 2A
1090  *      open file2 in session 2B
1091  *      block 2A
1092  *      open file2 in session 1
1093  *           lease break retry reaches the client?
1094  *      Connect 2C
1095  *      open file3 in session 2C
1096  *      unblock 2A
1097  *      open file1 in session 1
1098  *           lease break reaches the client?
1099  *      open file3 in session 1
1100  *           lease break reached the client?
1101  *      Cleanup
1102  *           On deletion by 1, lease breaks sent for file1, file2 and file3
1103  *           on 2B
1104  *           This changes RH lease to R for Session 2.
1105  *           (This has been disabled while we add support for sending lease
1106  *            break for handle leases.)
1107  */
test_multichannel_lease_break_test2(struct torture_context * tctx,struct smb2_tree * tree1)1108 static bool test_multichannel_lease_break_test2(struct torture_context *tctx,
1109 						struct smb2_tree *tree1)
1110 {
1111 	const char *host = torture_setting_string(tctx, "host", NULL);
1112 	const char *share = torture_setting_string(tctx, "share", NULL);
1113 	struct cli_credentials *credentials = popt_get_cmdline_credentials();
1114 	NTSTATUS status;
1115 	TALLOC_CTX *mem_ctx = talloc_new(tctx);
1116 	struct smb2_handle _h;
1117 	struct smb2_handle *h = NULL;
1118 	struct smb2_handle h_client1_file1 = {{0}};
1119 	struct smb2_handle h_client1_file2 = {{0}};
1120 	struct smb2_handle h_client1_file3 = {{0}};
1121 	struct smb2_handle h_client2_file1 = {{0}};
1122 	struct smb2_handle h_client2_file2 = {{0}};
1123 	struct smb2_handle h_client2_file3 = {{0}};
1124 	struct smb2_create io1, io2, io3;
1125 	bool ret = true;
1126 	const char *fname1 = BASEDIR "\\lease_break_test1.dat";
1127 	const char *fname2 = BASEDIR "\\lease_break_test2.dat";
1128 	const char *fname3 = BASEDIR "\\lease_break_test3.dat";
1129 	struct smb2_tree *tree2A = NULL;
1130 	struct smb2_tree *tree2B = NULL;
1131 	struct smb2_tree *tree2C = NULL;
1132 	struct smb2_transport *transport1 = tree1->session->transport;
1133 	struct smb2_transport *transport2A = NULL;
1134 	struct smbcli_options transport2_options;
1135 	struct smb2_session *session1 = tree1->session;
1136 	uint16_t local_port = 0;
1137 	struct smb2_lease ls1;
1138 	struct smb2_lease ls2;
1139 	struct smb2_lease ls3;
1140 	bool block_ok = false;
1141 	bool unblock_ok = false;
1142 
1143 
1144 	if (!test_multichannel_initial_checks(tctx, tree1)) {
1145 		return true;
1146 	}
1147 
1148 	torture_comment(tctx, "Lease break retry: Test2\n");
1149 
1150 	torture_reset_lease_break_info(tctx, &lease_break_info);
1151 
1152 	transport1->lease.handler = torture_lease_handler;
1153 	transport1->lease.private_data = tree1;
1154 	torture_comment(tctx, "transport1  [%p]\n", transport1);
1155 	local_port = torture_get_local_port_from_transport(transport1);
1156 	torture_comment(tctx, "transport1 uses tcp port: %d\n", local_port);
1157 
1158 	status = torture_smb2_testdir(tree1, BASEDIR, &_h);
1159 	CHECK_STATUS(status, NT_STATUS_OK);
1160 	smb2_util_close(tree1, _h);
1161 	smb2_util_unlink(tree1, fname1);
1162 	smb2_util_unlink(tree1, fname2);
1163 	smb2_util_unlink(tree1, fname3);
1164 	CHECK_VAL(lease_break_info.count, 0);
1165 
1166 	smb2_lease_create(&io1, &ls1, false, fname1, LEASE2F1,
1167 			  smb2_util_lease_state("RHW"));
1168 	test_multichannel_init_smb_create(&io1);
1169 
1170 	smb2_lease_create(&io2, &ls2, false, fname2, LEASE2F2,
1171 			  smb2_util_lease_state("RHW"));
1172 	test_multichannel_init_smb_create(&io2);
1173 
1174 	smb2_lease_create(&io3, &ls3, false, fname3, LEASE2F3,
1175 			  smb2_util_lease_state("RHW"));
1176 	test_multichannel_init_smb_create(&io3);
1177 
1178 	transport2_options = transport1->options;
1179 
1180 	ret = test_multichannel_create_channels(tctx, host, share,
1181 						  credentials,
1182 						  &transport2_options,
1183 						  &tree2A, &tree2B, NULL);
1184 	torture_assert(tctx, ret, "Could not create channels.\n");
1185 	transport2A = tree2A->session->transport;
1186 
1187 	/* 2a opens file1 */
1188 	torture_comment(tctx, "client2 opens fname1 via session 2A\n");
1189 	smb2_lease_create(&io1, &ls1, false, fname1, LEASE2F1,
1190 			  smb2_util_lease_state("RHW"));
1191 	status = smb2_create(tree2A, mem_ctx, &io1);
1192 	CHECK_STATUS(status, NT_STATUS_OK);
1193 	h_client2_file1 = io1.out.file.handle;
1194 	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1195 	CHECK_LEASE(&io1, "RHW", true, LEASE2F1, 0);
1196 	CHECK_VAL(io1.out.durable_open_v2, false); //true);
1197 	CHECK_VAL(io1.out.timeout, io1.in.timeout);
1198 	CHECK_VAL(io1.out.durable_open, false);
1199 	CHECK_VAL(lease_break_info.count, 0);
1200 
1201 	/* 2b opens file2 */
1202 	torture_comment(tctx, "client2 opens fname2 via session 2B\n");
1203 	smb2_lease_create(&io2, &ls2, false, fname2, LEASE2F2,
1204 			  smb2_util_lease_state("RHW"));
1205 	status = smb2_create(tree2B, mem_ctx, &io2);
1206 	CHECK_STATUS(status, NT_STATUS_OK);
1207 	h_client2_file2 = io2.out.file.handle;
1208 	CHECK_CREATED(&io2, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1209 	CHECK_LEASE(&io2, "RHW", true, LEASE2F2, 0);
1210 	CHECK_VAL(io2.out.durable_open_v2, false); //true);
1211 	CHECK_VAL(io2.out.timeout, io2.in.timeout);
1212 	CHECK_VAL(io2.out.durable_open, false);
1213 	CHECK_VAL(lease_break_info.count, 0);
1214 
1215 
1216 	torture_comment(tctx, "Blocking 2A\n");
1217 	/* Block 2A */
1218 	block_ok = test_block_channel(tctx, transport2A);
1219 	torture_assert(tctx, block_ok, "we could not block tcp transport");
1220 
1221 	/* 1 opens file2 */
1222 	torture_comment(tctx,
1223 			"Client opens fname2 with session1 with 2A blocked\n");
1224 	smb2_lease_create(&io2, &ls2, false, fname2, LEASE1F2,
1225 			  smb2_util_lease_state("RHW"));
1226 	status = smb2_create(tree1, mem_ctx, &io2);
1227 	CHECK_STATUS(status, NT_STATUS_OK);
1228 	h_client1_file2 = io2.out.file.handle;
1229 	CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1230 	CHECK_LEASE(&io2, "RH", true, LEASE1F2, 0);
1231 	CHECK_VAL(io2.out.durable_open_v2, false);
1232 	CHECK_VAL(io2.out.timeout, 0);
1233 	CHECK_VAL(io2.out.durable_open, false);
1234 
1235 	if (lease_break_info.count == 0) {
1236 		torture_comment(tctx,
1237 				"Did not receive expected lease break!!\n");
1238 	} else {
1239 		torture_comment(tctx, "Received %d lease break(s)!!\n",
1240 				lease_break_info.count);
1241 	}
1242 
1243 	CHECK_VAL(lease_break_info.count, 1);
1244 	CHECK_BREAK_INFO("RHW", "RH", LEASE2F2);
1245 	torture_reset_lease_break_info(tctx, &lease_break_info);
1246 
1247 	/* Connect 2C */
1248 	torture_comment(tctx, "Connecting session 2C\n");
1249 	talloc_free(tree2C);
1250 	tree2C = test_multichannel_create_channel(tctx, host, share,
1251 				credentials, &transport2_options, tree2A);
1252 	if (!tree2C) {
1253 		goto done;
1254 	}
1255 
1256 	/* 2c opens file3 */
1257 	torture_comment(tctx, "client2 opens fname3 via session 2C\n");
1258 	smb2_lease_create(&io3, &ls3, false, fname3, LEASE2F3,
1259 			  smb2_util_lease_state("RHW"));
1260 	status = smb2_create(tree2C, mem_ctx, &io3);
1261 	CHECK_STATUS(status, NT_STATUS_OK);
1262 	h_client2_file3 = io3.out.file.handle;
1263 	CHECK_CREATED(&io3, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1264 	CHECK_LEASE(&io3, "RHW", true, LEASE2F3, 0);
1265 	CHECK_VAL(io3.out.durable_open_v2, false);
1266 	CHECK_VAL(io3.out.timeout, io2.in.timeout);
1267 	CHECK_VAL(io3.out.durable_open, false);
1268 	CHECK_VAL(lease_break_info.count, 0);
1269 
1270 	/* Unblock 2A */
1271 	torture_comment(tctx, "Unblocking 2A\n");
1272 	unblock_ok = test_unblock_channel(tctx, transport2A);
1273 	torture_assert(tctx, unblock_ok, "we could not unblock tcp transport");
1274 
1275 	/* 1 opens file1 */
1276 	torture_comment(tctx, "Client opens fname1 with session 1\n");
1277 	smb2_lease_create(&io1, &ls1, false, fname1, LEASE1F1,
1278 			  smb2_util_lease_state("RHW"));
1279 	status = smb2_create(tree1, mem_ctx, &io1);
1280 	CHECK_STATUS(status, NT_STATUS_OK);
1281 	h_client1_file1 = io1.out.file.handle;
1282 	CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1283 	CHECK_LEASE(&io1, "RH", true, LEASE1F1, 0);
1284 
1285 	if (lease_break_info.count == 0) {
1286 		torture_comment(tctx,
1287 				"Did not receive expected lease break!!\n");
1288 	} else {
1289 		torture_comment(tctx,
1290 				"Received %d lease break(s)!!\n",
1291 				lease_break_info.count);
1292 	}
1293 	CHECK_VAL(lease_break_info.count, 1);
1294 	CHECK_BREAK_INFO("RHW", "RH", LEASE2F1);
1295 	torture_reset_lease_break_info(tctx, &lease_break_info);
1296 
1297 	/*1 opens file3 */
1298 	torture_comment(tctx, "client opens fname3 via session 1\n");
1299 
1300 	smb2_lease_create(&io3, &ls3, false, fname3, LEASE1F3,
1301 			  smb2_util_lease_state("RHW"));
1302 	status = smb2_create(tree1, mem_ctx, &io3);
1303 	CHECK_STATUS(status, NT_STATUS_OK);
1304 	h_client1_file3 = io3.out.file.handle;
1305 	CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1306 	CHECK_LEASE(&io3, "RH", true, LEASE1F3, 0);
1307 
1308 	if (lease_break_info.count == 0) {
1309 		torture_comment(tctx,
1310 				"Did not receive expected lease break!!\n");
1311 	} else {
1312 		torture_comment(tctx,
1313 				"Received %d lease break(s)!!\n",
1314 				lease_break_info.count);
1315 	}
1316 	CHECK_VAL(lease_break_info.count, 1);
1317 	CHECK_BREAK_INFO("RHW", "RH", LEASE2F3);
1318 	torture_reset_lease_break_info(tctx, &lease_break_info);
1319 
1320 	smb2_util_close(tree1, h_client1_file1);
1321 	smb2_util_close(tree1, h_client1_file2);
1322 	smb2_util_close(tree1, h_client1_file3);
1323 
1324 	/*
1325 	 * Session 2 still has RW lease on file 1. Deletion of this file by 1
1326 	 *  leads to a lease break call to session 2 file1
1327 	 */
1328 	smb2_util_unlink(tree1, fname1);
1329 	/*
1330 	 * Bug - Samba does not revoke Handle lease on unlink
1331 	 * CHECK_BREAK_INFO("RH", "R", LEASE2F1);
1332 	 */
1333 	torture_reset_lease_break_info(tctx, &lease_break_info);
1334 
1335 	/*
1336 	 * Session 2 still has RW lease on file 2. Deletion of this file by 1
1337 	 *  leads to a lease break call to session 2 file2
1338 	 */
1339 	smb2_util_unlink(tree1, fname2);
1340 	/*
1341 	 * Bug - Samba does not revoke Handle lease on unlink
1342 	 * CHECK_BREAK_INFO("RH", "R", LEASE2F2);
1343 	 */
1344 	torture_reset_lease_break_info(tctx, &lease_break_info);
1345 
1346 	/*
1347 	 * Session 2 still has RW lease on file 3. Deletion of this file by 1
1348 	 *  leads to a lease break call to session 2 file3
1349 	 */
1350 	smb2_util_unlink(tree1, fname3);
1351 	/*
1352 	 * Bug - Samba does not revoke Handle lease on unlink
1353 	 * CHECK_BREAK_INFO("RH", "R", LEASE2F3);
1354 	 */
1355 	torture_reset_lease_break_info(tctx, &lease_break_info);
1356 
1357 	smb2_util_close(tree2C, h_client2_file1);
1358 	smb2_util_close(tree2C, h_client2_file2);
1359 	smb2_util_close(tree2C, h_client2_file3);
1360 
1361 	test_multichannel_free_channels(tree2A, tree2B, tree2C);
1362 	tree2A = tree2B = tree2C = NULL;
1363 
1364 done:
1365 	if (block_ok && !unblock_ok) {
1366 		test_unblock_channel(tctx, transport2A);
1367 	}
1368 	test_cleanup_blocked_channels(tctx);
1369 
1370 	tree1->session = session1;
1371 
1372 	smb2_util_close(tree1, h_client1_file1);
1373 	smb2_util_close(tree1, h_client1_file2);
1374 	smb2_util_close(tree1, h_client1_file3);
1375 	if (tree2A != NULL) {
1376 		smb2_util_close(tree2A, h_client2_file1);
1377 		smb2_util_close(tree2A, h_client2_file2);
1378 		smb2_util_close(tree2A, h_client2_file3);
1379 	}
1380 
1381 	if (h != NULL) {
1382 		smb2_util_close(tree1, *h);
1383 	}
1384 
1385 	smb2_util_unlink(tree1, fname1);
1386 	smb2_util_unlink(tree1, fname2);
1387 	smb2_util_unlink(tree1, fname3);
1388 	smb2_deltree(tree1, BASEDIR);
1389 
1390 	test_multichannel_free_channels(tree2A, tree2B, tree2C);
1391 	talloc_free(tree1);
1392 	talloc_free(mem_ctx);
1393 
1394 	return ret;
1395 }
1396 
1397 /*
1398  * Test 3: Check to see how the server behaves if lease break
1399  *      response is sent over a different channel to one over which
1400  *      the break is received.
1401  *      Connect 2A, 2B
1402  *      open file1 in session 2A
1403  *      open file1 in session 1
1404  *           Lease break sent to 2A
1405  *           2B sends back lease break reply.
1406  *      session 1 allowed to open file
1407  */
test_multichannel_lease_break_test3(struct torture_context * tctx,struct smb2_tree * tree1)1408 static bool test_multichannel_lease_break_test3(struct torture_context *tctx,
1409 						struct smb2_tree *tree1)
1410 {
1411 	const char *host = torture_setting_string(tctx, "host", NULL);
1412 	const char *share = torture_setting_string(tctx, "share", NULL);
1413 	struct cli_credentials *credentials = popt_get_cmdline_credentials();
1414 	NTSTATUS status;
1415 	TALLOC_CTX *mem_ctx = talloc_new(tctx);
1416 	struct smb2_handle _h;
1417 	struct smb2_handle *h = NULL;
1418 	struct smb2_handle h_client1_file1 = {{0}};
1419 	struct smb2_handle h_client2_file1 = {{0}};
1420 	struct smb2_create io1;
1421 	bool ret = true;
1422 	const char *fname1 = BASEDIR "\\lease_break_test1.dat";
1423 	struct smb2_tree *tree2A = NULL;
1424 	struct smb2_tree *tree2B = NULL;
1425 	struct smb2_transport *transport1 = tree1->session->transport;
1426 	struct smb2_transport *transport2A = NULL;
1427 	struct smbcli_options transport2_options;
1428 	uint16_t local_port = 0;
1429 	struct smb2_lease ls1;
1430 	struct tevent_timer *te = NULL;
1431 	struct timeval ne;
1432 	bool timesup = false;
1433 	TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1434 
1435 	if (!test_multichannel_initial_checks(tctx, tree1)) {
1436 		return true;
1437 	}
1438 
1439 	torture_comment(tctx, "Lease break retry: Test3\n");
1440 
1441 	torture_reset_lease_break_info(tctx, &lease_break_info);
1442 
1443 	transport1->lease.handler = torture_lease_handler;
1444 	transport1->lease.private_data = tree1;
1445 	torture_comment(tctx, "transport1  [%p]\n", transport1);
1446 	local_port = torture_get_local_port_from_transport(transport1);
1447 	torture_comment(tctx, "transport1 uses tcp port: %d\n", local_port);
1448 
1449 	status = torture_smb2_testdir(tree1, BASEDIR, &_h);
1450 	CHECK_STATUS(status, NT_STATUS_OK);
1451 	smb2_util_close(tree1, _h);
1452 	smb2_util_unlink(tree1, fname1);
1453 	CHECK_VAL(lease_break_info.count, 0);
1454 
1455 	smb2_lease_create(&io1, &ls1, false, fname1, LEASE2F1,
1456 			  smb2_util_lease_state("RHW"));
1457 	test_multichannel_init_smb_create(&io1);
1458 
1459 	transport2_options = transport1->options;
1460 
1461 	ret = test_multichannel_create_channels(tctx, host, share,
1462 						credentials,
1463 						&transport2_options,
1464 						&tree2A, &tree2B, NULL);
1465 	torture_assert(tctx, ret, "Could not create channels.\n");
1466 	transport2A = tree2A->session->transport;
1467 	transport2A->lease.private_data = tree2B;
1468 
1469 	/* 2a opens file1 */
1470 	torture_comment(tctx, "client2 opens fname1 via session 2A\n");
1471 	smb2_lease_create(&io1, &ls1, false, fname1, LEASE2F1,
1472 			  smb2_util_lease_state("RHW"));
1473 	status = smb2_create(tree2A, mem_ctx, &io1);
1474 	CHECK_STATUS(status, NT_STATUS_OK);
1475 	h_client2_file1 = io1.out.file.handle;
1476 	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1477 	CHECK_LEASE(&io1, "RHW", true, LEASE2F1, 0);
1478 	CHECK_VAL(io1.out.durable_open_v2, false); //true);
1479 	CHECK_VAL(io1.out.timeout, io1.in.timeout);
1480 	CHECK_VAL(io1.out.durable_open, false);
1481 	CHECK_VAL(lease_break_info.count, 0);
1482 
1483 	/* Set a timeout for 5 seconds for session 1 to open file1 */
1484 	ne = tevent_timeval_current_ofs(0, 5000000);
1485 	te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, &timesup);
1486 	if (te == NULL) {
1487 		torture_comment(tctx, "Failed to add timer.");
1488 		goto done;
1489 	}
1490 
1491 	/* 1 opens file2 */
1492 	torture_comment(tctx, "Client opens fname1 with session 1\n");
1493 	smb2_lease_create(&io1, &ls1, false, fname1, LEASE1F1,
1494 			  smb2_util_lease_state("RHW"));
1495 	status = smb2_create(tree1, mem_ctx, &io1);
1496 	CHECK_STATUS(status, NT_STATUS_OK);
1497 	h_client1_file1 = io1.out.file.handle;
1498 	CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1499 	CHECK_LEASE(&io1, "RH", true, LEASE1F1, 0);
1500 	CHECK_VAL(io1.out.durable_open_v2, false);
1501 	CHECK_VAL(io1.out.timeout, 0);
1502 	CHECK_VAL(io1.out.durable_open, false);
1503 
1504 	CHECK_VAL(lease_break_info.count, 1);
1505 	CHECK_BREAK_INFO("RHW", "RH", LEASE2F1);
1506 
1507 	/*
1508 	 * Check if timeout handler was fired. This would indicate
1509 	 * that the server didn't receive a reply for the oplock break
1510 	 * from the client and the server let session 1 open the file
1511 	 * only after the oplock break timeout.
1512 	 */
1513 	CHECK_VAL(timesup, false);
1514 
1515 done:
1516 	smb2_util_close(tree1, h_client1_file1);
1517 	if (tree2A != NULL) {
1518 		smb2_util_close(tree2A, h_client2_file1);
1519 	}
1520 
1521 	if (h != NULL) {
1522 		smb2_util_close(tree1, *h);
1523 	}
1524 
1525 	smb2_util_unlink(tree1, fname1);
1526 	smb2_deltree(tree1, BASEDIR);
1527 
1528 	test_multichannel_free_channels(tree2A, tree2B, NULL);
1529 	talloc_free(tree1);
1530 	talloc_free(mem_ctx);
1531 
1532 	return ret;
1533 }
1534 
1535 /* lease handler for test4 */
test4_lease_break_handler(struct smb2_transport * transport,const struct smb2_lease_break * lb,void * private_data)1536 static bool test4_lease_break_handler(struct smb2_transport *transport,
1537 			   const struct smb2_lease_break *lb,
1538 			   void *private_data)
1539 {
1540 	NTSTATUS status;
1541 	bool ret = true;
1542 	struct smb2_tree *test4_tree2 = private_data;
1543 	struct torture_context *tctx = lease_break_info.tctx;
1544 	struct smb2_handle test4_h_file = lease_break_info.oplock_handle;
1545 	DATA_BLOB blob;
1546 
1547 	lease_break_info.lease_transport = transport;
1548 	lease_break_info.lease_break = *lb;
1549 	lease_break_info.count++;
1550 
1551 	torture_comment(tctx, "Test 6 Lease break handler called.\n");
1552 	torture_comment(tctx, "Trying write to file using given session.\n");
1553 
1554 	blob = data_blob_string_const("Here I am");
1555 	status = smb2_util_write(test4_tree2,
1556 				 test4_h_file,
1557 				 blob.data,
1558 				 0,
1559 				 blob.length);
1560 	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1561 		"failed to write file");
1562 
1563 done:
1564 	return ret;
1565 }
1566 
1567 /*
1568  * Lease Break Test 4:
1569  * Test to see how the server behaves when the client flushes data back to the
1570  * server but doesn't send the lease break response over the channel. Does it
1571  * then retry the lease break?
1572  *      Connect 2A, 2B
1573  *      open file1 in session 2A
1574  *      set lease handler for 2A to ignore break requests
1575  *      open file1 in session 1
1576  *           Lease break sent to 2A
1577  *           Write to file in 2A
1578  *           Do not send ack to lease break
1579  *      Check to see if second lease break sent
1580  *      Cleanup
1581  */
test_multichannel_lease_break_test4(struct torture_context * tctx,struct smb2_tree * tree1)1582 static bool test_multichannel_lease_break_test4(struct torture_context *tctx,
1583 						struct smb2_tree *tree1)
1584 {
1585 	const char *host = torture_setting_string(tctx, "host", NULL);
1586 	const char *share = torture_setting_string(tctx, "share", NULL);
1587 	struct cli_credentials *credentials = popt_get_cmdline_credentials();
1588 	NTSTATUS status;
1589 	TALLOC_CTX *mem_ctx = talloc_new(tctx);
1590 	struct smb2_handle _h;
1591 	struct smb2_handle *h = NULL;
1592 	struct smb2_handle h_client1_file1 = {{0}};
1593 	struct smb2_handle h_client2_file1 = {{0}};
1594 	struct smb2_create io1, io2, io3;
1595 	bool ret = true;
1596 	const char *fname1 = BASEDIR "\\lease_break_test1.dat";
1597 	const char *fname2 = BASEDIR "\\lease_break_test2.dat";
1598 	const char *fname3 = BASEDIR "\\lease_break_test3.dat";
1599 	struct smb2_tree *tree2A = NULL;
1600 	struct smb2_tree *tree2B = NULL;
1601 	struct smb2_tree *tree2C = NULL;
1602 	struct smb2_transport *transport1 = tree1->session->transport;
1603 	struct smb2_transport *transport2A = NULL;
1604 	struct smbcli_options transport2_options;
1605 	struct smb2_session *session1 = tree1->session;
1606 	uint16_t local_port = 0;
1607 	struct smb2_lease ls1;
1608 	struct smb2_lease ls2;
1609 	struct smb2_lease ls3;
1610 
1611 	if (!test_multichannel_initial_checks(tctx, tree1)) {
1612 		return true;
1613 	}
1614 
1615 	torture_comment(tctx, "Lease break retry: Test4\n");
1616 	torture_comment(tctx, "This test is specifically expected to run "
1617 			"against samba and will not work against windows "
1618 			"servers. The windows server assumes that if the "
1619 			"send() command returns successfully, the lease break "
1620 			"has been delivered. In this test, we rely on the "
1621 			"Samba behaviour of waiting for a reply for the lease "
1622 			"break from the server instead.\n");
1623 
1624 	torture_reset_lease_break_info(tctx, &lease_break_info);
1625 
1626 	transport1->lease.handler = torture_lease_handler;
1627 	transport1->lease.private_data = tree1;
1628 	torture_comment(tctx, "transport1  [%p]\n", transport1);
1629 	local_port = torture_get_local_port_from_transport(transport1);
1630 	torture_comment(tctx, "transport1 uses tcp port: %d\n", local_port);
1631 
1632 	status = torture_smb2_testdir(tree1, BASEDIR, &_h);
1633 	CHECK_STATUS(status, NT_STATUS_OK);
1634 	smb2_util_close(tree1, _h);
1635 	smb2_util_unlink(tree1, fname1);
1636 	smb2_util_unlink(tree1, fname2);
1637 	smb2_util_unlink(tree1, fname3);
1638 	CHECK_VAL(lease_break_info.count, 0);
1639 
1640 	smb2_lease_create(&io1, &ls1, false, fname1, LEASE2F1,
1641 			  smb2_util_lease_state("RHW"));
1642 	test_multichannel_init_smb_create(&io1);
1643 
1644 	smb2_lease_create(&io2, &ls2, false, fname2, LEASE2F2,
1645 			  smb2_util_lease_state("RHW"));
1646 	test_multichannel_init_smb_create(&io2);
1647 
1648 	smb2_lease_create(&io3, &ls3, false, fname3, LEASE2F3,
1649 			  smb2_util_lease_state("RHW"));
1650 	test_multichannel_init_smb_create(&io3);
1651 
1652 	transport2_options = transport1->options;
1653 
1654 	ret = test_multichannel_create_channels(tctx, host, share,
1655 						  credentials,
1656 						  &transport2_options,
1657 						  &tree2A, &tree2B, NULL);
1658 	torture_assert(tctx, ret, "Could not create channels.\n");
1659 	transport2A = tree2A->session->transport;
1660 
1661 	torture_comment(tctx, "client2 opens fname1 via session 2A\n");
1662 	smb2_lease_create(&io1, &ls1, false, fname1, LEASE2F1,
1663 			  smb2_util_lease_state("RHW"));
1664 	status = smb2_create(tree2A, mem_ctx, &io1);
1665 	CHECK_STATUS(status, NT_STATUS_OK);
1666 	h_client2_file1 = io1.out.file.handle;
1667 	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1668 	CHECK_LEASE(&io1, "RHW", true, LEASE2F1, 0);
1669 	CHECK_VAL(io1.out.durable_open_v2, false); //true);
1670 	CHECK_VAL(io1.out.timeout, io1.in.timeout);
1671 	CHECK_VAL(io1.out.durable_open, false);
1672 	CHECK_VAL(lease_break_info.count, 0);
1673 
1674 	torture_comment(tctx, "Blocking 2A\n");
1675 	/* Set our lease handler for 2A */
1676 	lease_break_info.oplock_handle = h_client2_file1;
1677 	transport2A->lease.handler = test4_lease_break_handler;
1678 
1679 	torture_comment(tctx,
1680 			"Client opens fname1 with session 1 with 2A blocked\n");
1681 	smb2_lease_create(&io1, &ls1, false, fname1, LEASE1F1,
1682 			  smb2_util_lease_state("RHW"));
1683 	status = smb2_create(tree1, mem_ctx, &io1);
1684 	CHECK_STATUS(status, NT_STATUS_OK);
1685 	h_client1_file1 = io1.out.file.handle;
1686 	CHECK_LEASE(&io1, "RH", true, LEASE1F1, 0);
1687 
1688 	if (lease_break_info.count == 0) {
1689 		torture_comment(tctx,
1690 				"Did not receive expected lease break!!\n");
1691 	} else {
1692 		torture_comment(tctx,
1693 				"Received %d lease break(s)!!\n",
1694 				lease_break_info.count);
1695 	}
1696 
1697 	/* Should receive 2 lease breaks */
1698 	CHECK_VAL(lease_break_info.count, 2);
1699 	torture_reset_lease_break_info(tctx, &lease_break_info);
1700 
1701 done:
1702 	tree1->session = session1;
1703 
1704 	smb2_util_close(tree1, h_client1_file1);
1705 	if (tree2A != NULL) {
1706 		smb2_util_close(tree2A, h_client2_file1);
1707 	}
1708 
1709 	if (h != NULL) {
1710 		smb2_util_close(tree1, *h);
1711 	}
1712 
1713 	smb2_util_unlink(tree1, fname1);
1714 	smb2_deltree(tree1, BASEDIR);
1715 
1716 	test_multichannel_free_channels(tree2A, tree2B, tree2C);
1717 	talloc_free(tree1);
1718 	talloc_free(mem_ctx);
1719 
1720 	return ret;
1721 }
1722 
1723 /*
1724  * Test limits of channels
1725  */
test_multichannel_num_channels(struct torture_context * tctx,struct smb2_tree * tree1)1726 static bool test_multichannel_num_channels(struct torture_context *tctx,
1727 					   struct smb2_tree *tree1)
1728 {
1729 	const char *host = torture_setting_string(tctx, "host", NULL);
1730 	const char *share = torture_setting_string(tctx, "share", NULL);
1731 	struct cli_credentials *credentials = popt_get_cmdline_credentials();
1732 	TALLOC_CTX *mem_ctx = talloc_new(tctx);
1733 	bool ret = true;
1734 	struct smb2_tree **tree2 = NULL;
1735 	struct smb2_transport *transport1 = tree1->session->transport;
1736 	struct smb2_transport **transport2 = NULL;
1737 	struct smbcli_options transport2_options;
1738 	struct smb2_session **session2 = NULL;
1739 	uint32_t server_capabilities;
1740 	int i;
1741 	int max_channels = 33; /* 32 is the W2K12R2 and W2K16 limit */
1742 
1743 	if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
1744 		torture_fail(tctx,
1745 			     "SMB 3.X Dialect family required for Multichannel"
1746 			     " tests\n");
1747 	}
1748 
1749 	server_capabilities = smb2cli_conn_server_capabilities(
1750 					tree1->session->transport->conn);
1751 	if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
1752 		torture_fail(tctx,
1753 			     "Server does not support multichannel.");
1754 	}
1755 
1756 	torture_comment(tctx, "Testing max. number of channels\n");
1757 
1758 	transport2_options = transport1->options;
1759 	transport2_options.client_guid = GUID_random();
1760 
1761 	tree2		= talloc_zero_array(mem_ctx, struct smb2_tree *,
1762 					    max_channels);
1763 	transport2	= talloc_zero_array(mem_ctx, struct smb2_transport *,
1764 					    max_channels);
1765 	session2	= talloc_zero_array(mem_ctx, struct smb2_session *,
1766 					    max_channels);
1767 	if (tree2 == NULL || transport2 == NULL || session2 == NULL) {
1768 		torture_fail(tctx, "out of memory");
1769 	}
1770 
1771 	for (i = 0; i < max_channels; i++) {
1772 
1773 		NTSTATUS expected_status;
1774 
1775 		torture_assert_ntstatus_ok_goto(tctx,
1776 			smb2_connect(tctx,
1777 				host,
1778 				lpcfg_smb_ports(tctx->lp_ctx),
1779 				share,
1780 				lpcfg_resolve_context(tctx->lp_ctx),
1781 				credentials,
1782 				&tree2[i],
1783 				tctx->ev,
1784 				&transport2_options,
1785 				lpcfg_socket_options(tctx->lp_ctx),
1786 				lpcfg_gensec_settings(tctx, tctx->lp_ctx)
1787 				),
1788 			ret, done, "smb2_connect failed");
1789 
1790 		transport2[i] = tree2[i]->session->transport;
1791 
1792 		if (i == 0) {
1793 			/* done for the 1st channel */
1794 			continue;
1795 		}
1796 
1797 		/*
1798 		 * Now bind the session2[i] to the transport2
1799 		 */
1800 		session2[i] = smb2_session_channel(transport2[i],
1801 						   lpcfg_gensec_settings(tctx,
1802 								 tctx->lp_ctx),
1803 						   tree2[0],
1804 						   tree2[0]->session);
1805 
1806 		torture_assert(tctx, session2[i] != NULL,
1807 			       "smb2_session_channel failed");
1808 
1809 		torture_comment(tctx, "established transport2 [#%d]\n", i);
1810 
1811 		if (i >= 32) {
1812 			expected_status = NT_STATUS_INSUFFICIENT_RESOURCES;
1813 		} else {
1814 			expected_status = NT_STATUS_OK;
1815 		}
1816 
1817 		torture_assert_ntstatus_equal_goto(tctx,
1818 			smb2_session_setup_spnego(session2[i],
1819 				popt_get_cmdline_credentials(),
1820 				0 /* previous_session_id */),
1821 			expected_status,
1822 			ret, done,
1823 			talloc_asprintf(tctx, "failed to establish session "
1824 					      "setup for channel #%d", i));
1825 
1826 		torture_comment(tctx, "bound session2 [#%d] to session2 [0]\n",
1827 				i);
1828 	}
1829 
1830  done:
1831 	talloc_free(mem_ctx);
1832 
1833 	return ret;
1834 }
1835 
torture_smb2_multichannel_init(TALLOC_CTX * ctx)1836 struct torture_suite *torture_smb2_multichannel_init(TALLOC_CTX *ctx)
1837 {
1838 	struct torture_suite *suite = torture_suite_create(ctx, "multichannel");
1839 	struct torture_suite *suite_generic = torture_suite_create(ctx,
1840 								   "generic");
1841 	struct torture_suite *suite_oplocks = torture_suite_create(ctx,
1842 								   "oplocks");
1843 	struct torture_suite *suite_leases = torture_suite_create(ctx,
1844 								  "leases");
1845 
1846 	torture_suite_add_suite(suite, suite_generic);
1847 	torture_suite_add_suite(suite, suite_oplocks);
1848 	torture_suite_add_suite(suite, suite_leases);
1849 
1850 	torture_suite_add_1smb2_test(suite, "interface_info",
1851 				     test_multichannel_interface_info);
1852 	torture_suite_add_1smb2_test(suite_generic, "num_channels",
1853 				     test_multichannel_num_channels);
1854 	torture_suite_add_1smb2_test(suite_oplocks, "test1",
1855 				     test_multichannel_oplock_break_test1);
1856 	torture_suite_add_1smb2_test(suite_oplocks, "test2",
1857 				     test_multichannel_oplock_break_test2);
1858 	torture_suite_add_1smb2_test(suite_leases, "test1",
1859 				     test_multichannel_lease_break_test1);
1860 	torture_suite_add_1smb2_test(suite_leases, "test2",
1861 				     test_multichannel_lease_break_test2);
1862 	torture_suite_add_1smb2_test(suite_leases, "test3",
1863 				     test_multichannel_lease_break_test3);
1864 	torture_suite_add_1smb2_test(suite_leases, "test4",
1865 				     test_multichannel_lease_break_test4);
1866 
1867 	suite->description = talloc_strdup(suite, "SMB2 Multichannel tests");
1868 
1869 	return suite;
1870 }
1871