From b593a397f918b9653b683e953602069befe796ab Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 6 Feb 2015 16:11:13 +0100 Subject: [PATCH] smbd: Fix bug 10839 Signed-off-by: Volker Lendecke --- source3/smbd/globals.h | 18 ++++++++++++++++++ source3/smbd/smb2_getinfo.c | 13 +++++++++++-- source3/smbd/smb2_negprot.c | 4 ++++ source3/smbd/smb2_notify.c | 12 ++++++++++-- source3/smbd/smb2_setinfo.c | 17 +++++++++++++++-- 5 files changed, 58 insertions(+), 6 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 1286ced..a8393eb 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -817,6 +817,24 @@ struct smbd_server_connection { */ struct bitmap *credits_bitmap; bool supports_multicredit; + + /* + * See Samba bug 10839. + * + * According to [MS-SMB2] 3.2.4.1.5 Sending + * Multi-Credit Requests: + * + * > For all other requests, the client MUST set + * > CreditCharge to 1, even if the payload size of a + * > request or the anticipated response is greater + * > than 65536 + * + * For notify, getinfo and setinfo we can only check + * for 1 credit and ignore in_output_buffer_length + * here. + */ + bool ignore_broken_multicredit; + uint32_t max_trans; uint32_t max_read; uint32_t max_write; diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index bbc838d..dcc4fec 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -58,6 +58,7 @@ NTSTATUS smbd_smb2_request_process_getinfo(struct smbd_smb2_request *req) uint64_t in_file_id_volatile; struct files_struct *in_fsp; struct tevent_req *subreq; + uint32_t credit_charge; status = smbd_smb2_request_verify_sizes(req, 0x29); if (!NT_STATUS_IS_OK(status)) { @@ -105,8 +106,16 @@ NTSTATUS smbd_smb2_request_process_getinfo(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); } - status = smbd_smb2_request_verify_creditcharge(req, - MAX(in_input_buffer.length,in_output_buffer_length)); + credit_charge = MAX(in_input_buffer.length, in_output_buffer_length); + if (req->sconn->smb2.ignore_broken_multicredit) { + /* + * see comment in globals.h where ignore_broken_multicredit + * is defined + */ + credit_charge = 65536; + } + + status = smbd_smb2_request_verify_creditcharge(req, credit_charge); if (!NT_STATUS_IS_OK(status)) { return smbd_smb2_request_error(req, status); } diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index 963a557..4163b33 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -379,9 +379,13 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) conn->smb2.server.max_read = max_read; conn->smb2.server.max_write = max_write; + req->sconn->smb2.max_trans = max_trans; req->sconn->smb2.max_read = max_read; req->sconn->smb2.max_write = max_write; + req->sconn->smb2.ignore_broken_multicredit = + lp_parm_bool(-1, "smbd", "ignore broken multicredit", + false); } return smbd_smb2_request_done(req, outbody, &outdyn); diff --git a/source3/smbd/smb2_notify.c b/source3/smbd/smb2_notify.c index c35acc5..91baa59 100644 --- a/source3/smbd/smb2_notify.c +++ b/source3/smbd/smb2_notify.c @@ -57,6 +57,7 @@ NTSTATUS smbd_smb2_request_process_notify(struct smbd_smb2_request *req) struct files_struct *in_fsp; uint64_t in_completion_filter; struct tevent_req *subreq; + uint32_t credit_charge; status = smbd_smb2_request_verify_sizes(req, 0x20); if (!NT_STATUS_IS_OK(status)) { @@ -78,9 +79,16 @@ NTSTATUS smbd_smb2_request_process_notify(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); } - status = smbd_smb2_request_verify_creditcharge(req, - in_output_buffer_length); + credit_charge = in_output_buffer_length; + if (req->sconn->smb2.ignore_broken_multicredit) { + /* + * see comment in globals.h where ignore_broken_multicredit + * is defined + */ + credit_charge = 65536; + } + status = smbd_smb2_request_verify_creditcharge(req, credit_charge); if (!NT_STATUS_IS_OK(status)) { return smbd_smb2_request_error(req, status); } diff --git a/source3/smbd/smb2_setinfo.c b/source3/smbd/smb2_setinfo.c index cda8abc..1bd1a5a 100644 --- a/source3/smbd/smb2_setinfo.c +++ b/source3/smbd/smb2_setinfo.c @@ -51,6 +51,7 @@ NTSTATUS smbd_smb2_request_process_setinfo(struct smbd_smb2_request *req) uint64_t in_file_id_volatile; struct files_struct *in_fsp; struct tevent_req *subreq; + uint32_t credit_charge; status = smbd_smb2_request_verify_sizes(req, 0x21); if (!NT_STATUS_IS_OK(status)) { @@ -89,8 +90,20 @@ NTSTATUS smbd_smb2_request_process_setinfo(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); } - status = smbd_smb2_request_verify_creditcharge(req, - in_input_buffer.length); + credit_charge = in_input_buffer.length; + if (req->sconn->smb2.ignore_broken_multicredit) { + /* + * see comment in globals.h where ignore_broken_multicredit + * is defined + */ + credit_charge = 65536; + } + + status = smbd_smb2_request_verify_creditcharge(req, credit_charge); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } + if (!NT_STATUS_IS_OK(status)) { return smbd_smb2_request_error(req, status); } -- 1.7.9.5