[PATCH] smbd: Fix bug 10839

Volker Lendecke Volker.Lendecke at SerNet.DE
Wed Feb 25 14:03:31 MST 2015


Hi!

This is a patch I'd like to propse for master. The bug is
not strictly a Samba bug, Windows->Windows must have the
same problem, but it's unlikely to get fixed in Windows. As
it affects a real user I've talked to recently, I would like
to get this in.

Comments?

Thanks,

Volker

-- 
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
From 575fe80b7e2de0a9637412130b92232fe74339c7 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 6 Feb 2015 16:11:13 +0100
Subject: [PATCH] smbd: Fix bug 10839

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 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.9.1



More information about the samba-technical mailing list