summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2020-06-22 17:30:28 +0200
committerStefan Metzmacher <metze@samba.org>2020-07-08 15:54:39 +0000
commit3d7f81979c2db790930b369671e8346f0bb25331 (patch)
tree7e9ca88b3b5f5b7de16312b6e0978f45a0a557db /source4
parent68a351b7620a87fc8191666e49058cbfdee62e67 (diff)
downloadsamba-3d7f81979c2db790930b369671e8346f0bb25331.tar.gz
s4:torture/smb2: move smb2_transport blocking to the generic block.[ch]
We may want to use this in other places too, not only multichannel.c BUG: https://bugzilla.samba.org/show_bug.cgi?id=11897 Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Günther Deschner <gd@samba.org>
Diffstat (limited to 'source4')
-rw-r--r--source4/torture/smb2/block.c214
-rw-r--r--source4/torture/smb2/block.h11
-rw-r--r--source4/torture/smb2/multichannel.c236
3 files changed, 236 insertions, 225 deletions
diff --git a/source4/torture/smb2/block.c b/source4/torture/smb2/block.c
index d0cb934adf9..b9982b0574d 100644
--- a/source4/torture/smb2/block.c
+++ b/source4/torture/smb2/block.c
@@ -27,6 +27,9 @@
#include "lib/util/util_net.h"
#include "torture/smb2/block.h"
#include "libcli/smb/smbXcli_base.h"
+#include "lib/util/tevent_ntstatus.h"
+#include "oplock_break_handler.h"
+#include "lease_break_handler.h"
/*
* OUTPUT
@@ -230,3 +233,214 @@ bool torture_unblock_tcp_output_cleanup(struct torture_context *tctx)
{
return iptables_setup_chain(tctx, "OUTPUT", "SMBTORTURE_OUTPUT", true);
}
+
+/*
+ * Use iptables to block channels
+ */
+static bool test_block_smb2_transport_iptables(struct torture_context *tctx,
+ struct smb2_transport *transport,
+ const char *name)
+{
+ uint16_t local_port;
+ bool ret;
+
+ local_port = torture_get_local_port_from_transport(transport);
+ torture_comment(tctx, "transport[%s] uses tcp port: %d\n", name, local_port);
+ ret = torture_block_tcp_output_port(tctx, name, local_port);
+ torture_assert(tctx, ret, "we could not block tcp transport");
+
+ return ret;
+}
+
+static bool test_unblock_smb2_transport_iptables(struct torture_context *tctx,
+ struct smb2_transport *transport,
+ const char *name)
+{
+ uint16_t local_port;
+ bool ret;
+
+ local_port = torture_get_local_port_from_transport(transport);
+ torture_comment(tctx, "transport[%s] uses tcp port: %d\n", name, local_port);
+ ret = torture_unblock_tcp_output_port(tctx, name, local_port);
+ torture_assert(tctx, ret, "we could not block tcp transport");
+
+ return ret;
+}
+
+static bool torture_blocked_lease_handler(struct smb2_transport *transport,
+ const struct smb2_lease_break *lb,
+ void *private_data)
+{
+ struct smb2_transport *transport_copy =
+ talloc_get_type_abort(private_data,
+ struct smb2_transport);
+ bool lease_skip_ack = lease_break_info.lease_skip_ack;
+ bool ok;
+
+ lease_break_info.lease_skip_ack = true;
+ ok = transport_copy->lease.handler(transport,
+ lb,
+ transport_copy->lease.private_data);
+ lease_break_info.lease_skip_ack = lease_skip_ack;
+
+ if (!ok) {
+ return false;
+ }
+
+ if (lease_break_info.lease_skip_ack) {
+ return true;
+ }
+
+ if (lb->break_flags & SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED) {
+ lease_break_info.failures++;
+ }
+
+ return true;
+}
+
+static bool torture_blocked_oplock_handler(struct smb2_transport *transport,
+ const struct smb2_handle *handle,
+ uint8_t level,
+ void *private_data)
+{
+ struct smb2_transport *transport_copy =
+ talloc_get_type_abort(private_data,
+ struct smb2_transport);
+ bool oplock_skip_ack = break_info.oplock_skip_ack;
+ bool ok;
+
+ break_info.oplock_skip_ack = true;
+ ok = transport_copy->oplock.handler(transport,
+ handle,
+ level,
+ transport_copy->oplock.private_data);
+ break_info.oplock_skip_ack = oplock_skip_ack;
+
+ if (!ok) {
+ return false;
+ }
+
+ if (break_info.oplock_skip_ack) {
+ return true;
+ }
+
+ break_info.failures++;
+ break_info.failure_status = NT_STATUS_CONNECTION_DISCONNECTED;
+
+ return true;
+}
+
+static bool test_block_smb2_transport_fsctl_smbtorture(struct torture_context *tctx,
+ struct smb2_transport *transport,
+ const char *name)
+{
+ struct smb2_transport *transport_copy = NULL;
+ DATA_BLOB in_input_buffer = data_blob_null;
+ DATA_BLOB in_output_buffer = data_blob_null;
+ DATA_BLOB out_input_buffer = data_blob_null;
+ DATA_BLOB out_output_buffer = data_blob_null;
+ struct tevent_req *req = NULL;
+ uint16_t local_port;
+ NTSTATUS status;
+ bool ok;
+
+ transport_copy = talloc_zero(transport, struct smb2_transport);
+ torture_assert(tctx, transport_copy, "talloc transport_copy");
+ transport_copy->lease = transport->lease;
+ transport_copy->oplock = transport->oplock;
+
+ local_port = torture_get_local_port_from_transport(transport);
+ torture_comment(tctx, "transport[%s] uses tcp port: %d\n", name, local_port);
+ req = smb2cli_ioctl_send(tctx,
+ tctx->ev,
+ transport->conn,
+ 1000, /* timeout_msec */
+ NULL, /* session */
+ NULL, /* tcon */
+ UINT64_MAX, /* in_fid_persistent */
+ UINT64_MAX, /* in_fid_volatile */
+ FSCTL_SMBTORTURE_FORCE_UNACKED_TIMEOUT,
+ 0, /* in_max_input_length */
+ &in_input_buffer,
+ 0, /* in_max_output_length */
+ &in_output_buffer,
+ SMB2_IOCTL_FLAG_IS_FSCTL);
+ torture_assert(tctx, req != NULL, "smb2cli_ioctl_send() failed");
+ ok = tevent_req_poll_ntstatus(req, tctx->ev, &status);
+ if (ok) {
+ status = NT_STATUS_OK;
+ }
+ torture_assert_ntstatus_ok(tctx, status, "tevent_req_poll_ntstatus() failed");
+ status = smb2cli_ioctl_recv(req, tctx,
+ &out_input_buffer,
+ &out_output_buffer);
+ torture_assert_ntstatus_ok(tctx, status,
+ "FSCTL_SMBTORTURE_FORCE_UNACKED_TIMEOUT failed\n\n"
+ "On a Samba server 'smbd:FSCTL_SMBTORTURE = yes' is needed!\n\n"
+ "Otherwise you may need to use iptables like this:\n"
+ "--option='torture:use_iptables=yes'\n"
+ "And maybe something like this in addition:\n"
+ "--option='torture:iptables_command=sudo /sbin/iptables'\n\n");
+ TALLOC_FREE(req);
+
+ if (transport->lease.handler != NULL) {
+ transport->lease.handler = torture_blocked_lease_handler;
+ transport->lease.private_data = transport_copy;
+ }
+ if (transport->oplock.handler != NULL) {
+ transport->oplock.handler = torture_blocked_oplock_handler;
+ transport->oplock.private_data = transport_copy;
+ }
+
+ return true;
+}
+
+bool _test_block_smb2_transport(struct torture_context *tctx,
+ struct smb2_transport *transport,
+ const char *name)
+{
+ bool use_iptables = torture_setting_bool(tctx,
+ "use_iptables", false);
+
+ if (use_iptables) {
+ return test_block_smb2_transport_iptables(tctx, transport, name);
+ } else {
+ return test_block_smb2_transport_fsctl_smbtorture(tctx, transport, name);
+ }
+}
+
+bool _test_unblock_smb2_transport(struct torture_context *tctx,
+ struct smb2_transport *transport,
+ const char *name)
+{
+ bool use_iptables = torture_setting_bool(tctx,
+ "use_iptables", false);
+
+ if (use_iptables) {
+ return test_unblock_smb2_transport_iptables(tctx, transport, name);
+ } else {
+ return true;
+ }
+}
+
+bool test_setup_blocked_transports(struct torture_context *tctx)
+{
+ bool use_iptables = torture_setting_bool(tctx,
+ "use_iptables", false);
+
+ if (use_iptables) {
+ return torture_block_tcp_output_setup(tctx);
+ }
+
+ return true;
+}
+
+void test_cleanup_blocked_transports(struct torture_context *tctx)
+{
+ bool use_iptables = torture_setting_bool(tctx,
+ "use_iptables", false);
+
+ if (use_iptables) {
+ torture_unblock_tcp_output_cleanup(tctx);
+ }
+}
diff --git a/source4/torture/smb2/block.h b/source4/torture/smb2/block.h
index 7f36b89a693..6a6370a1ab5 100644
--- a/source4/torture/smb2/block.h
+++ b/source4/torture/smb2/block.h
@@ -30,3 +30,14 @@ bool torture_unblock_tcp_output_port(struct torture_context *tctx,
bool torture_block_tcp_output_setup(struct torture_context *tctx);
bool torture_unblock_tcp_output_cleanup(struct torture_context *tctx);
+bool test_setup_blocked_transports(struct torture_context *tctx);
+void test_cleanup_blocked_transports(struct torture_context *tctx);
+
+#define test_block_smb2_transport(_tctx, _t) _test_block_smb2_transport(_tctx, _t, #_t)
+bool _test_block_smb2_transport(struct torture_context *tctx,
+ struct smb2_transport *transport,
+ const char *name);
+#define test_unblock_smb2_transport(_tctx, _t) _test_unblock_smb2_transport(_tctx, _t, #_t)
+bool _test_unblock_smb2_transport(struct torture_context *tctx,
+ struct smb2_transport *transport,
+ const char *name);
diff --git a/source4/torture/smb2/multichannel.c b/source4/torture/smb2/multichannel.c
index 3742cb8bac8..3e29c7d02a9 100644
--- a/source4/torture/smb2/multichannel.c
+++ b/source4/torture/smb2/multichannel.c
@@ -36,7 +36,6 @@
#include "oplock_break_handler.h"
#include "lease_break_handler.h"
#include "torture/smb2/block.h"
-#include "lib/util/tevent_ntstatus.h"
#define BASEDIR "multichanneltestdir"
@@ -367,219 +366,6 @@ static void test_multichannel_init_smb_create(struct smb2_create *io)
/* windows 2016 returns 300000 0x493E0 */
}
-/*
- * Use iptables to block channels
- */
-static bool test_iptables_block_channel(struct torture_context *tctx,
- struct smb2_transport *transport,
- const char *name)
-{
- uint16_t local_port;
- bool ret;
-
- local_port = torture_get_local_port_from_transport(transport);
- torture_comment(tctx, "transport[%s] uses tcp port: %d\n", name, local_port);
- ret = torture_block_tcp_output_port(tctx, name, local_port);
- torture_assert(tctx, ret, "we could not block tcp transport");
-
- return ret;
-}
-
-static bool test_iptables_unblock_channel(struct torture_context *tctx,
- struct smb2_transport *transport,
- const char *name)
-{
- uint16_t local_port;
- bool ret;
-
- local_port = torture_get_local_port_from_transport(transport);
- torture_comment(tctx, "transport[%s] uses tcp port: %d\n", name, local_port);
- ret = torture_unblock_tcp_output_port(tctx, name, local_port);
- torture_assert(tctx, ret, "we could not block tcp transport");
-
- return ret;
-}
-
-static bool torture_blocked_lease_handler(struct smb2_transport *transport,
- const struct smb2_lease_break *lb,
- void *private_data)
-{
- struct smb2_transport *transport_copy =
- talloc_get_type_abort(private_data,
- struct smb2_transport);
- bool lease_skip_ack = lease_break_info.lease_skip_ack;
- bool ok;
-
- lease_break_info.lease_skip_ack = true;
- ok = transport_copy->lease.handler(transport,
- lb,
- transport_copy->lease.private_data);
- lease_break_info.lease_skip_ack = lease_skip_ack;
-
- if (!ok) {
- return false;
- }
-
- if (lease_break_info.lease_skip_ack) {
- return true;
- }
-
- if (lb->break_flags & SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED) {
- lease_break_info.failures++;
- }
-
- return true;
-}
-
-static bool torture_blocked_oplock_handler(struct smb2_transport *transport,
- const struct smb2_handle *handle,
- uint8_t level,
- void *private_data)
-{
- struct smb2_transport *transport_copy =
- talloc_get_type_abort(private_data,
- struct smb2_transport);
- bool oplock_skip_ack = break_info.oplock_skip_ack;
- bool ok;
-
- break_info.oplock_skip_ack = true;
- ok = transport_copy->oplock.handler(transport,
- handle,
- level,
- transport_copy->oplock.private_data);
- break_info.oplock_skip_ack = oplock_skip_ack;
-
- if (!ok) {
- return false;
- }
-
- if (break_info.oplock_skip_ack) {
- return true;
- }
-
- break_info.failures++;
- break_info.failure_status = NT_STATUS_CONNECTION_DISCONNECTED;
-
- return true;
-}
-
-static bool test_block_smb2_transport_fsctl_smbtorture(struct torture_context *tctx,
- struct smb2_transport *transport,
- const char *name)
-{
- struct smb2_transport *transport_copy = NULL;
- DATA_BLOB in_input_buffer = data_blob_null;
- DATA_BLOB in_output_buffer = data_blob_null;
- DATA_BLOB out_input_buffer = data_blob_null;
- DATA_BLOB out_output_buffer = data_blob_null;
- struct tevent_req *req = NULL;
- uint16_t local_port;
- NTSTATUS status;
- bool ok;
-
- transport_copy = talloc_zero(transport, struct smb2_transport);
- torture_assert(tctx, transport_copy, "talloc transport_copy");
- transport_copy->lease = transport->lease;
- transport_copy->oplock = transport->oplock;
-
- local_port = torture_get_local_port_from_transport(transport);
- torture_comment(tctx, "transport[%s] uses tcp port: %d\n", name, local_port);
- req = smb2cli_ioctl_send(tctx,
- tctx->ev,
- transport->conn,
- 1000, /* timeout_msec */
- NULL, /* session */
- NULL, /* tcon */
- UINT64_MAX, /* in_fid_persistent */
- UINT64_MAX, /* in_fid_volatile */
- FSCTL_SMBTORTURE_FORCE_UNACKED_TIMEOUT,
- 0, /* in_max_input_length */
- &in_input_buffer,
- 0, /* in_max_output_length */
- &in_output_buffer,
- SMB2_IOCTL_FLAG_IS_FSCTL);
- torture_assert(tctx, req != NULL, "smb2cli_ioctl_send() failed");
- ok = tevent_req_poll_ntstatus(req, tctx->ev, &status);
- if (ok) {
- status = NT_STATUS_OK;
- }
- torture_assert_ntstatus_ok(tctx, status, "tevent_req_poll_ntstatus() failed");
- status = smb2cli_ioctl_recv(req, tctx,
- &out_input_buffer,
- &out_output_buffer);
- torture_assert_ntstatus_ok(tctx, status,
- "FSCTL_SMBTORTURE_FORCE_UNACKED_TIMEOUT failed\n\n"
- "On a Samba server 'smbd:FSCTL_SMBTORTURE = yes' is needed!\n\n"
- "Otherwise you may need to use iptables like this:\n"
- "--option='torture:use_iptables=yes'\n"
- "And maybe something like this in addition:\n"
- "--option='torture:iptables_command=sudo /sbin/iptables'\n\n");
- TALLOC_FREE(req);
-
- if (transport->lease.handler != NULL) {
- transport->lease.handler = torture_blocked_lease_handler;
- transport->lease.private_data = transport_copy;
- }
- if (transport->oplock.handler != NULL) {
- transport->oplock.handler = torture_blocked_oplock_handler;
- transport->oplock.private_data = transport_copy;
- }
-
- return true;
-}
-
-#define test_block_channel(_tctx, _t) _test_block_channel(_tctx, _t, #_t)
-static bool _test_block_channel(struct torture_context *tctx,
- struct smb2_transport *transport,
- const char *name)
-{
- bool use_iptables = torture_setting_bool(tctx,
- "use_iptables", false);
-
- if (use_iptables) {
- return test_iptables_block_channel(tctx, transport, name);
- } else {
- return test_block_smb2_transport_fsctl_smbtorture(tctx, transport, name);
- }
-}
-
-#define test_unblock_channel(_tctx, _t) _test_unblock_channel(_tctx, _t, #_t)
-static bool _test_unblock_channel(struct torture_context *tctx,
- struct smb2_transport *transport,
- const char *name)
-{
- bool use_iptables = torture_setting_bool(tctx,
- "use_iptables", false);
-
- if (use_iptables) {
- return test_iptables_unblock_channel(tctx, transport, name);
- } else {
- return true;
- }
-}
-
-static bool test_setup_blocked_channels(struct torture_context *tctx)
-{
- bool use_iptables = torture_setting_bool(tctx,
- "use_iptables", false);
-
- if (use_iptables) {
- return torture_block_tcp_output_setup(tctx);
- }
-
- return true;
-}
-
-static void test_cleanup_blocked_channels(struct torture_context *tctx)
-{
- bool use_iptables = torture_setting_bool(tctx,
- "use_iptables", false);
-
- if (use_iptables) {
- torture_unblock_tcp_output_cleanup(tctx);
- }
-}
-
/* Timer handler function notifies the registering function that time is up */
static void timeout_cb(struct tevent_context *ev,
struct tevent_timer *te,
@@ -899,11 +685,11 @@ static bool test_multichannel_oplock_break_test2(struct torture_context *tctx,
transport2 = break_info.received_transport;
torture_reset_break_info(tctx, &break_info);
- block_setup = test_setup_blocked_channels(tctx);
- torture_assert(tctx, block_setup, "test_setup_blocked_channels");
+ block_setup = test_setup_blocked_transports(tctx);
+ torture_assert(tctx, block_setup, "test_setup_blocked_transports");
/* block channel */
- block_ok = test_block_channel(tctx, transport2);
+ block_ok = test_block_smb2_transport(tctx, transport2);
torture_comment(tctx, "client1 opens fname2 via session 1\n");
io2.in.oplock_level = smb2_util_oplock_level("b");
@@ -987,9 +773,9 @@ static bool test_multichannel_oplock_break_test2(struct torture_context *tctx,
done:
if (block_ok && !unblock_ok) {
- test_unblock_channel(tctx, transport2);
+ test_unblock_smb2_transport(tctx, transport2);
}
- test_cleanup_blocked_channels(tctx);
+ test_cleanup_blocked_transports(tctx);
tree1->session = session1;
@@ -1355,12 +1141,12 @@ static bool test_multichannel_lease_break_test2(struct torture_context *tctx,
CHECK_VAL(io2.out.durable_open, false);
CHECK_VAL(lease_break_info.count, 0);
- block_setup = test_setup_blocked_channels(tctx);
- torture_assert(tctx, block_setup, "test_setup_blocked_channels");
+ block_setup = test_setup_blocked_transports(tctx);
+ torture_assert(tctx, block_setup, "test_setup_blocked_transports");
torture_comment(tctx, "Blocking 2A\n");
/* Block 2A */
- block_ok = test_block_channel(tctx, transport2A);
+ block_ok = test_block_smb2_transport(tctx, transport2A);
torture_assert(tctx, block_ok, "we could not block tcp transport");
/* 1 opens file2 */
@@ -1414,7 +1200,7 @@ static bool test_multichannel_lease_break_test2(struct torture_context *tctx,
/* Unblock 2A */
torture_comment(tctx, "Unblocking 2A\n");
- unblock_ok = test_unblock_channel(tctx, transport2A);
+ unblock_ok = test_unblock_smb2_transport(tctx, transport2A);
torture_assert(tctx, unblock_ok, "we could not unblock tcp transport");
/* 1 opens file1 */
@@ -1508,10 +1294,10 @@ static bool test_multichannel_lease_break_test2(struct torture_context *tctx,
done:
if (block_ok && !unblock_ok) {
- test_unblock_channel(tctx, transport2A);
+ test_unblock_smb2_transport(tctx, transport2A);
}
if (block_setup) {
- test_cleanup_blocked_channels(tctx);
+ test_cleanup_blocked_transports(tctx);
}
tree1->session = session1;