From bfd9732854dbe1bdae5aa567a046ed17471449d7 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 | 17 +++++++++++++++++ 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, 57 insertions(+), 6 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 7726c24..2c142b6 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -495,6 +495,23 @@ struct smbXsrv_connection { */ struct bitmap *bitmap; bool 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; } credits; bool allow_2ff; diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index 7f44868..67f5a3b 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -59,6 +59,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)) { @@ -106,8 +107,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 (xconn->smb2.credits.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 9a1ca9c..be73391 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -361,6 +361,10 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) xconn->smb2.server.max_trans = max_trans; xconn->smb2.server.max_read = max_read; xconn->smb2.server.max_write = max_write; + + xconn->smb2.credits.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 573635b..d9b5cfe 100644 --- a/source3/smbd/smb2_notify.c +++ b/source3/smbd/smb2_notify.c @@ -58,6 +58,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)) { @@ -79,9 +80,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 (xconn->smb2.credits.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 e6981d1..1988cfc 100644 --- a/source3/smbd/smb2_setinfo.c +++ b/source3/smbd/smb2_setinfo.c @@ -55,6 +55,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)) { @@ -93,8 +94,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 (xconn->smb2.credits.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