From 39c0d2b666a6ddac7cd3b29fe76be7375690b27b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 14 Jan 2021 17:39:01 +0100 Subject: [PATCH] smbd: implement FSCTL_SMBTORTURE_IOCTL_RESPONSE_BODY_PADDING8 as reproducer for bug 14607 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14607 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke --- .../knownfail.d/samba3.smb2.ioctl.bug14607 | 1 + source3/smbd/smb2_ioctl.c | 41 +++++++++++++++++-- source3/smbd/smb2_ioctl_private.h | 1 + 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 selftest/knownfail.d/samba3.smb2.ioctl.bug14607 diff --git a/selftest/knownfail.d/samba3.smb2.ioctl.bug14607 b/selftest/knownfail.d/samba3.smb2.ioctl.bug14607 new file mode 100644 index 00000000000..c535a8a2723 --- /dev/null +++ b/selftest/knownfail.d/samba3.smb2.ioctl.bug14607 @@ -0,0 +1 @@ +^samba3.smb2.ioctl.*bug14607.nt4_dc diff --git a/source3/smbd/smb2_ioctl.c b/source3/smbd/smb2_ioctl.c index 01ae6d64ac5..8b65a691638 100644 --- a/source3/smbd/smb2_ioctl.c +++ b/source3/smbd/smb2_ioctl.c @@ -41,6 +41,7 @@ static struct tevent_req *smbd_smb2_ioctl_send(TALLOC_CTX *mem_ctx, static NTSTATUS smbd_smb2_ioctl_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, DATA_BLOB *out_output, + uint8_t *body_padding, bool *disconnect); static void smbd_smb2_request_ioctl_done(struct tevent_req *subreq); @@ -195,6 +196,7 @@ NTSTATUS smbd_smb2_request_process_ioctl(struct smbd_smb2_request *req) case FSCTL_VALIDATE_NEGOTIATE_INFO: case FSCTL_QUERY_NETWORK_INTERFACE_INFO: case FSCTL_SMBTORTURE_FORCE_UNACKED_TIMEOUT: + case FSCTL_SMBTORTURE_IOCTL_RESPONSE_BODY_PADDING8: /* * Some SMB2 specific CtlCodes like FSCTL_DFS_GET_REFERRALS or * FSCTL_PIPE_WAIT does not take a file handle. @@ -284,9 +286,12 @@ static void smbd_smb2_request_ioctl_done(struct tevent_req *subreq) NTSTATUS status; NTSTATUS error; /* transport error */ bool disconnect = false; + uint16_t body_size; + uint8_t body_padding = 0; status = smbd_smb2_ioctl_recv(subreq, req, &out_output_buffer, + &body_padding, &disconnect); DEBUG(10,("smbd_smb2_request_ioctl_done: smbd_smb2_ioctl_recv returned " @@ -319,10 +324,15 @@ static void smbd_smb2_request_ioctl_done(struct tevent_req *subreq) return; } - out_input_offset = SMB2_HDR_BODY + 0x30; - out_output_offset = SMB2_HDR_BODY + 0x30; + /* + * Only FSCTL_SMBTORTURE_IOCTL_RESPONSE_BODY_PADDING8 + * sets body_padding to a value different from 0. + */ + body_size = 0x30 + body_padding; + out_input_offset = SMB2_HDR_BODY + body_size; + out_output_offset = SMB2_HDR_BODY + body_size; - outbody = smbd_smb2_generate_outbody(req, 0x30); + outbody = smbd_smb2_generate_outbody(req, body_size); if (outbody.data == NULL) { error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { @@ -350,6 +360,9 @@ static void smbd_smb2_request_ioctl_done(struct tevent_req *subreq) out_output_buffer.length); /* output count */ SIVAL(outbody.data, 0x28, 0); /* flags */ SIVAL(outbody.data, 0x2C, 0); /* reserved */ + if (body_padding != 0) { + memset(outbody.data + 0x30, 0, body_padding); + } /* * Note: Windows Vista and 2008 send back also the @@ -391,6 +404,26 @@ static struct tevent_req *smb2_ioctl_smbtorture(uint32_t ctl_code, tevent_req_done(req); return tevent_req_post(req, ev); + case FSCTL_SMBTORTURE_IOCTL_RESPONSE_BODY_PADDING8: + if (state->in_input.length != 0) { + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); + } + + if (state->in_max_output > 0) { + uint32_t size = state->in_max_output; + + state->out_output = data_blob_talloc(state, NULL, size); + if (tevent_req_nomem(state->out_output.data, req)) { + return tevent_req_post(req, ev); + } + memset(state->out_output.data, 8, size); + } + + state->body_padding = 8; + tevent_req_done(req); + return tevent_req_post(req, ev); + default: goto not_supported; } @@ -476,6 +509,7 @@ static struct tevent_req *smbd_smb2_ioctl_send(TALLOC_CTX *mem_ctx, static NTSTATUS smbd_smb2_ioctl_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, DATA_BLOB *out_output, + uint8_t *body_padding, bool *disconnect) { NTSTATUS status = NT_STATUS_OK; @@ -484,6 +518,7 @@ static NTSTATUS smbd_smb2_ioctl_recv(struct tevent_req *req, enum tevent_req_state req_state; uint64_t err; + *body_padding = state->body_padding; *disconnect = state->disconnect; if ((tevent_req_is_error(req, &req_state, &err) == false) diff --git a/source3/smbd/smb2_ioctl_private.h b/source3/smbd/smb2_ioctl_private.h index ae07fed8606..7a35f8f5d0b 100644 --- a/source3/smbd/smb2_ioctl_private.h +++ b/source3/smbd/smb2_ioctl_private.h @@ -28,6 +28,7 @@ struct smbd_smb2_ioctl_state { DATA_BLOB in_input; uint32_t in_max_output; DATA_BLOB out_output; + uint8_t body_padding; bool disconnect; };