1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-23 09:57:40 +03:00

s3:smbd: implement FSCTL_SMBTORTURE_FORCE_UNACKED_TIMEOUT

This will be used by smbtorture in order to simulate channel failures
without relying on iptables.

'smbd:FSCTL_SMBTORTURE = yes' is required in order to active this.

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>
This commit is contained in:
Stefan Metzmacher 2020-06-08 16:33:45 +02:00
parent 88b0da1062
commit bd1285d40d
4 changed files with 98 additions and 3 deletions

View File

@ -375,6 +375,7 @@ struct smbXsrv_connection {
} transport;
struct {
bool force_unacked_timeout;
uint64_t unacked_bytes;
uint32_t rto_usecs;
struct tevent_req *checker_subreq;

View File

@ -41,9 +41,13 @@ struct smb_request *smbd_smb2_fake_smb_request(struct smbd_smb2_request *req)
}
smbreq->request_time = req->request_time;
smbreq->vuid = req->session->global->session_wire_id;
smbreq->tid = req->tcon->compat->cnum;
smbreq->conn = req->tcon->compat;
if (req->session != NULL) {
smbreq->vuid = req->session->global->session_wire_id;
}
if (req->tcon != NULL) {
smbreq->tid = req->tcon->compat->cnum;
smbreq->conn = req->tcon->compat;
}
smbreq->sconn = req->sconn;
smbreq->xconn = req->xconn;
smbreq->session = req->session;

View File

@ -194,6 +194,7 @@ NTSTATUS smbd_smb2_request_process_ioctl(struct smbd_smb2_request *req)
case FSCTL_VALIDATE_NEGOTIATE_INFO_224:
case FSCTL_VALIDATE_NEGOTIATE_INFO:
case FSCTL_QUERY_NETWORK_INTERFACE_INFO:
case FSCTL_SMBTORTURE_FORCE_UNACKED_TIMEOUT:
/*
* Some SMB2 specific CtlCodes like FSCTL_DFS_GET_REFERRALS or
* FSCTL_PIPE_WAIT does not take a file handle.
@ -366,6 +367,45 @@ static void smbd_smb2_request_ioctl_done(struct tevent_req *subreq)
}
}
static struct tevent_req *smb2_ioctl_smbtorture(uint32_t ctl_code,
struct tevent_context *ev,
struct tevent_req *req,
struct smbd_smb2_ioctl_state *state)
{
NTSTATUS status;
bool ok;
ok = lp_parm_bool(-1, "smbd", "FSCTL_SMBTORTURE", false);
if (!ok) {
goto not_supported;
}
switch (ctl_code) {
case FSCTL_SMBTORTURE_FORCE_UNACKED_TIMEOUT:
if (state->in_input.length != 0) {
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
return tevent_req_post(req, ev);
}
state->smb2req->xconn->ack.force_unacked_timeout = true;
tevent_req_done(req);
return tevent_req_post(req, ev);
default:
goto not_supported;
}
not_supported:
if (IS_IPC(state->smbreq->conn)) {
status = NT_STATUS_FS_DRIVER_REQUIRED;
} else {
status = NT_STATUS_INVALID_DEVICE_REQUEST;
}
tevent_req_nterror(req, status);
return tevent_req_post(req, ev);
}
static struct tevent_req *smbd_smb2_ioctl_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
@ -415,6 +455,9 @@ static struct tevent_req *smbd_smb2_ioctl_send(TALLOC_CTX *mem_ctx,
case FSCTL_NETWORK_FILESYSTEM:
return smb2_ioctl_network_fs(in_ctl_code, ev, req, state);
break;
case FSCTL_SMBTORTURE:
return smb2_ioctl_smbtorture(in_ctl_code, ev, req, state);
break;
default:
if (IS_IPC(smbreq->conn)) {
tevent_req_nterror(req, NT_STATUS_FS_DRIVER_REQUIRED);

View File

@ -1201,6 +1201,17 @@ static NTSTATUS smbXsrv_connection_get_acked_bytes(struct smbXsrv_connection *xc
*_acked_bytes = 0;
if (xconn->ack.force_unacked_timeout) {
/*
* Smbtorture tries to test channel failures...
* Just pretend nothing was acked...
*/
DBG_INFO("Simulating channel failure: "
"xconn->ack.unacked_bytes[%llu]\n",
(unsigned long long)xconn->ack.unacked_bytes);
return NT_STATUS_OK;
}
#ifdef __IOCTL_SEND_QUEUE_SIZE_OPCODE
{
int value = 0;
@ -3045,6 +3056,42 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
}
} else if (opcode == SMB2_OP_CANCEL) {
/* Cancel requests are allowed to skip the signing */
} else if (opcode == SMB2_OP_IOCTL) {
/*
* Some special IOCTL calls don't require
* file, tcon nor session.
*
* They typically don't do any real action
* on behalf of the client.
*
* They are mainly used to alter the behavior
* of the connection for testing. So we can
* run as root and skip all file, tcon and session
* checks below.
*/
static const struct smbd_smb2_dispatch_table _root_ioctl_call = {
_OP(SMB2_OP_IOCTL),
.as_root = true,
};
const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
uint32_t in_ctl_code;
size_t needed = 4;
if (needed > body_size) {
return smbd_smb2_request_error(req,
NT_STATUS_INVALID_PARAMETER);
}
in_ctl_code = IVAL(body, 0x04);
/*
* Only add trusted IOCTL codes here!
*/
switch (in_ctl_code) {
case FSCTL_SMBTORTURE_FORCE_UNACKED_TIMEOUT:
call = &_root_ioctl_call;
break;
}
} else if (signing_required) {
/*
* If signing is required we try to sign