#include "oplock_break_handler.h"
#include "lease_break_handler.h"
#include "torture/smb2/block.h"
+#include "lib/util/tevent_ntstatus.h"
#define BASEDIR "multichanneltestdir"
/* windows 2016 returns 300000 0x493E0 */
}
-/*
- * We simulate blocking incoming oplock break requests by simply ignoring
- * the incoming break requests.
- */
-static bool test_set_ignore_break_handler(struct torture_context *tctx,
- struct smb2_transport *transport)
-{
- transport->oplock.handler = torture_oplock_ignore_handler;
- transport->lease.handler = torture_lease_ignore_handler;
-
- return true;
-}
-
-static bool test_reset_break_handler(struct torture_context *tctx,
- struct smb2_transport *transport)
-{
- transport->oplock.handler = torture_oplock_ack_handler;
- transport->lease.handler = torture_lease_handler;
-
- return true;
-}
-
/*
* Use iptables to block channels
*/
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,
if (use_iptables) {
return test_iptables_block_channel(tctx, transport, name);
} else {
- return test_set_ignore_break_handler(tctx, transport);
+ return test_block_smb2_transport_fsctl_smbtorture(tctx, transport, name);
}
}
if (use_iptables) {
return test_iptables_unblock_channel(tctx, transport, name);
} else {
- return test_reset_break_handler(tctx, transport);
+ return true;
}
}