[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Fri Mar 9 19:48:02 MST 2012


The branch, master has been updated
       via  981e977 Ensure the right tsocket.h is included.
       via  97e1652 Fix up Christian Ambach's multi-credit code - the CreditCharge field is a 16-bit int read, not a 32-bit one.
       via  6e8e3c4 s3:smb2_server validate message ids with largemtu
       via  f6afda0 s3:smb2_server verify creditcharge
       via  eec5ece s3:smb2_server add function to verify creditcharge
       via  bd0ad2b s3:smb2_server: announce LargeMTU for SMB2.1
       via  6d128aa s3:smb2_server increase defaults for read/write/trans sizes to 1MB
       via  7f131d3 s3:smb2_server: add supports_multicredit to sconn
       via  880f64b s3:smb2_server use the correct variables for max read/write
      from  1e8141f Fix bug #8797 - Samba does not correctly handle DENY ACEs when privileges apply. Signed-off-by: Jeremy Allison <jra at samba.org>

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 981e9776f84dcf03f0297f47f63ee548ca089c0f
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Mar 9 17:08:36 2012 -0800

    Ensure the right tsocket.h is included.
    
    Autobuild-User: Jeremy Allison <jra at samba.org>
    Autobuild-Date: Sat Mar 10 03:47:04 CET 2012 on sn-devel-104

commit 97e1652125a46ffbc1510b26abb0379d7df690d3
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Mar 9 16:47:21 2012 -0800

    Fix up Christian Ambach's multi-credit code - the CreditCharge field is a 16-bit int read, not a 32-bit one.

commit 6e8e3c46130ce5882a3bd06bcccf4c383280e583
Author: Christian Ambach <ambi at samba.org>
Date:   Mon Feb 27 17:53:04 2012 -0800

    s3:smb2_server validate message ids with largemtu
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit f6afda0bc867f1080c45e1f6f79d5032c41d2b1a
Author: Christian Ambach <ambi at samba.org>
Date:   Mon Feb 27 17:51:40 2012 -0800

    s3:smb2_server verify creditcharge
    
    for all requests that have max_???? checks, also do a check of the
    creditcharge the client has sent (when using largemtu)
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit eec5ece6f59c5ff30de88af0e182c3b2f7b9579c
Author: Christian Ambach <ambi at samba.org>
Date:   Mon Feb 27 17:49:12 2012 -0800

    s3:smb2_server add function to verify creditcharge
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit bd0ad2bbb5361a92f349ef42171b9bdd1d99b281
Author: Christian Ambach <ambi at samba.org>
Date:   Mon Feb 27 05:57:47 2012 -0800

    s3:smb2_server: announce LargeMTU for SMB2.1
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit 6d128aac119d948f0ecb0dcf6b400b4eb4027fe6
Author: Christian Ambach <ambi at samba.org>
Date:   Mon Feb 27 21:33:13 2012 -0800

    s3:smb2_server increase defaults for read/write/trans sizes to 1MB
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit 7f131d3cee260e5943dc1e113b6eabb677fd4945
Author: Christian Ambach <ambi at samba.org>
Date:   Mon Feb 27 17:45:09 2012 -0800

    s3:smb2_server: add supports_multicredit to sconn
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

commit 880f64b5560b0b27d7f1313c8a78044d871d27ad
Author: Christian Ambach <ambi at samba.org>
Date:   Mon Feb 27 05:56:57 2012 -0800

    s3:smb2_server use the correct variables for max read/write
    
    Signed-off-by: Jeremy Allison <jra at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 source3/include/local.h     |    6 +-
 source3/smbd/globals.h      |    4 ++
 source3/smbd/smb2_find.c    |    8 +++
 source3/smbd/smb2_getinfo.c |    6 ++
 source3/smbd/smb2_negprot.c |   35 ++++++++++--
 source3/smbd/smb2_notify.c  |    7 +++
 source3/smbd/smb2_read.c    |    5 ++
 source3/smbd/smb2_server.c  |  122 +++++++++++++++++++++++++++++++++----------
 source3/smbd/smb2_setinfo.c |    6 ++
 source3/smbd/smb2_write.c   |    5 ++
 10 files changed, 168 insertions(+), 36 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/local.h b/source3/include/local.h
index 281248c..11166df 100644
--- a/source3/include/local.h
+++ b/source3/include/local.h
@@ -232,9 +232,9 @@
 #define CLIENT_NDR_PADDING_SIZE 8
 #define SERVER_NDR_PADDING_SIZE 8
 
-#define DEFAULT_SMB2_MAX_READ (64*1024)
-#define DEFAULT_SMB2_MAX_WRITE (64*1024)
-#define DEFAULT_SMB2_MAX_TRANSACT (64*1024)
+#define DEFAULT_SMB2_MAX_READ (1024*1024)
+#define DEFAULT_SMB2_MAX_WRITE (1024*1024)
+#define DEFAULT_SMB2_MAX_TRANSACT (1024*1024)
 #define DEFAULT_SMB2_MAX_CREDITS 8192
 #define DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR 2
 
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 5b65711..caf7357 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -258,6 +258,9 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
 struct smb_request *smbd_smb2_fake_smb_request(struct smbd_smb2_request *req);
 void remove_smb2_chained_fsp(files_struct *fsp);
 
+NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
+					       uint32_t data_length);
+
 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
 					size_t expected_body_size);
 
@@ -590,6 +593,7 @@ struct smbd_server_connection {
 		uint32_t max_trans;
 		uint32_t max_read;
 		uint32_t max_write;
+		bool supports_multicredit;
 		struct bitmap *credits_bitmap;
 		bool compound_related_in_progress;
 	} smb2;
diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c
index 99d3447..9c0d18b 100644
--- a/source3/smbd/smb2_find.c
+++ b/source3/smbd/smb2_find.c
@@ -282,6 +282,14 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
 		return tevent_req_post(req, ev);
 	}
 
+	status = smbd_smb2_request_verify_creditcharge(smb2req,
+					in_output_buffer_length);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+		return tevent_req_post(req, ev);
+	}
+
 	switch (in_file_info_class) {
 	case SMB2_FIND_DIRECTORY_INFO:
 		info_level = SMB_FIND_FILE_DIRECTORY_INFO;
diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c
index 7d0f946..e8d918d 100644
--- a/source3/smbd/smb2_getinfo.c
+++ b/source3/smbd/smb2_getinfo.c
@@ -97,6 +97,12 @@ 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));
+	if (!NT_STATUS_IS_OK(status)) {
+		return smbd_smb2_request_error(req, status);
+	}
+
 	if (req->compat_chain_fsp) {
 		/* skip check */
 	} else if (in_file_id_persistent != in_file_id_volatile) {
diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c
index d971fba..0351475 100644
--- a/source3/smbd/smb2_negprot.c
+++ b/source3/smbd/smb2_negprot.c
@@ -22,6 +22,7 @@
 #include "smbd/smbd.h"
 #include "smbd/globals.h"
 #include "../libcli/smb/smb_common.h"
+#include "../lib/tsocket/tsocket.h"
 
 /*
  * this is the entry point if SMB2 is selected via
@@ -226,14 +227,36 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
 	}
 
 	/*
-	 * Unless we implement SMB2_CAP_LARGE_MTU,
 	 * 0x10000 (65536) is the maximum allowed message size
+	 * for SMB 2.0
 	 */
 	max_limit = 0x10000;
 
-	max_trans = MIN(max_limit, max_trans);
-	max_read  = MIN(max_limit, max_read);
-	max_write = MIN(max_limit, max_write);
+	if (protocol >= PROTOCOL_SMB2_10) {
+		/* largeMTU is only available on port 445 */
+		if (TCP_SMB_PORT ==
+		    tsocket_address_inet_port(req->sconn->local_address))
+		{
+
+			capabilities |= SMB2_CAP_LARGE_MTU;
+			req->sconn->smb2.supports_multicredit = true;
+
+			/* SMB2.1 has 1 MB of allowed size */
+			max_limit = 0x100000; /* 1MB */
+		}
+	}
+
+	/*
+	 * the defaults are 1MB, but we'll limit this to max_limit based on
+	 * the dialect (64kb for SMB2.0, 1MB for SMB2.1 with LargeMTU)
+	 *
+	 * user configured values exceeding the limits will be overwritten,
+	 * only smaller values will be accepted
+	 */
+
+	max_trans = MIN(max_limit, lp_smb2_max_trans());
+	max_read = MIN(max_limit, lp_smb2_max_read());
+	max_write = MIN(max_limit, lp_smb2_max_write());
 
 	security_offset = SMB2_HDR_BODY + 0x40;
 
@@ -261,8 +284,8 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
 	SIVAL(outbody.data, 0x18,
 	      capabilities);			/* capabilities */
 	SIVAL(outbody.data, 0x1C, max_trans);	/* max transact size */
-	SIVAL(outbody.data, 0x20, max_trans);	/* max read size */
-	SIVAL(outbody.data, 0x24, max_trans);	/* max write size */
+	SIVAL(outbody.data, 0x20, max_read);	/* max read size */
+	SIVAL(outbody.data, 0x24, max_write);	/* max write size */
 	SBVAL(outbody.data, 0x28, 0);		/* system time */
 	SBVAL(outbody.data, 0x30, 0);		/* server start time */
 	SSVAL(outbody.data, 0x38,
diff --git a/source3/smbd/smb2_notify.c b/source3/smbd/smb2_notify.c
index be56b18..3f5365c 100644
--- a/source3/smbd/smb2_notify.c
+++ b/source3/smbd/smb2_notify.c
@@ -77,6 +77,13 @@ 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);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		return smbd_smb2_request_error(req, status);
+	}
+
 	if (req->compat_chain_fsp) {
 		/* skip check */
 	} else if (in_file_id_persistent != in_file_id_volatile) {
diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c
index 13bcbdf..0b6e2ee 100644
--- a/source3/smbd/smb2_read.c
+++ b/source3/smbd/smb2_read.c
@@ -80,6 +80,11 @@ NTSTATUS smbd_smb2_request_process_read(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
 	}
 
+	status = smbd_smb2_request_verify_creditcharge(req, in_length);
+	if (!NT_STATUS_IS_OK(status)) {
+		return smbd_smb2_request_error(req, status);
+	}
+
 	if (req->compat_chain_fsp) {
 		/* skip check */
 	} else if (in_file_id_persistent != in_file_id_volatile) {
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 8533157..3993673 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -306,6 +306,8 @@ static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
 	struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
 	uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
 	unsigned int bitmap_offset;
+	uint16_t credit_charge = 1;
+	uint64_t i;
 
 	if (opcode == SMB2_OP_CANCEL) {
 		/* SMB2_CANCEL requests by definition resend messageids. */
@@ -325,38 +327,65 @@ static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
 
 	if (sconn->smb2.credits_granted == 0) {
 		DEBUG(0,("smb2_validate_message_id: client used more "
-			 "credits than granted message_id (%llu)\n",
+			 "credits than granted, message_id (%llu)\n",
 			 (unsigned long long)message_id));
 		return false;
 	}
 
-	/* client just used a credit. */
-	sconn->smb2.credits_granted -= 1;
-
-	/* Mark the message_id as seen in the bitmap. */
-	bitmap_offset = (unsigned int)(message_id %
-			(uint64_t)(sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR));
-	if (bitmap_query(credits_bm, bitmap_offset)) {
-		DEBUG(0,("smb2_validate_message_id: duplicate message_id "
-			"%llu (bm offset %u)\n",
-			(unsigned long long)message_id,
-			bitmap_offset));
-		return false;
+	if (sconn->smb2.supports_multicredit) {
+		credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
+		credit_charge = MAX(credit_charge, 1);
 	}
-	bitmap_set(credits_bm, bitmap_offset);
 
-	if (message_id == sconn->smb2.seqnum_low + 1) {
-		/* Move the window forward by all the message_id's
-		   already seen. */
-		while (bitmap_query(credits_bm, bitmap_offset)) {
-			DEBUG(10,("smb2_validate_message_id: clearing "
-				"id %llu (position %u) from bitmap\n",
-				(unsigned long long)(sconn->smb2.seqnum_low + 1),
-				bitmap_offset ));
-			bitmap_clear(credits_bm, bitmap_offset);
-			sconn->smb2.seqnum_low += 1;
-			bitmap_offset = (bitmap_offset + 1) %
-				(sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR);
+	DEBUG(11, ("smb2_validate_message_id: mid %llu, credits_granted %llu, "
+		   "charge %llu, max_credits %llu, seqnum_low: %llu\n",
+		   (unsigned long long) message_id,
+		   (unsigned long long) sconn->smb2.credits_granted,
+		   (unsigned long long) credit_charge,
+		   (unsigned long long) sconn->smb2.max_credits,
+		   (unsigned long long) sconn->smb2.seqnum_low));
+
+	/* substract used credits */
+	sconn->smb2.credits_granted -= credit_charge;
+
+	/*
+	 * now check the message ids
+	 *
+	 * for multi-credit requests we need to check all current mid plus
+	 * the implicit mids caused by the credit charge
+	 * e.g. current mid = 15, charge 5 => mark 15-19 as used
+	 */
+
+	for (i = message_id; i <= (message_id+credit_charge-1); i++) {
+
+		DEBUG(11, ("Iterating mid %llu\n", (unsigned long long) i));
+
+		/* Mark the message_ids as seen in the bitmap. */
+		bitmap_offset = (unsigned int)(i %
+				(uint64_t)(sconn->smb2.max_credits *
+					DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR));
+		if (bitmap_query(credits_bm, bitmap_offset)) {
+			DEBUG(0,("smb2_validate_message_id: duplicate "
+				 "message_id %llu (bm offset %u)\n",
+				 (unsigned long long)i, bitmap_offset));
+			return false;
+		}
+		bitmap_set(credits_bm, bitmap_offset);
+
+		if (i == sconn->smb2.seqnum_low + 1) {
+			/* Move the window forward by all the message_id's
+			   already seen. */
+			while (bitmap_query(credits_bm, bitmap_offset)) {
+				DEBUG(10,("smb2_validate_message_id: clearing "
+					  "id %llu (position %u) from bitmap\n",
+					  (unsigned long long)(sconn->smb2.seqnum_low + 1),
+					  bitmap_offset));
+				bitmap_clear(credits_bm, bitmap_offset);
+				sconn->smb2.seqnum_low += 1;
+				bitmap_offset = (bitmap_offset + 1) %
+					(sconn->smb2.max_credits *
+					 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR);
+			}
 		}
 	}
 
@@ -1252,6 +1281,45 @@ static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
 	return NT_STATUS_OK;
 }
 
+NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
+						uint32_t data_length)
+{
+	uint16_t needed_charge;
+	uint16_t credit_charge;
+	const uint8_t *inhdr;
+	int i = req->current_idx;
+
+	if (!req->sconn->smb2.supports_multicredit) {
+		if (data_length > 65536) {
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+		return NT_STATUS_OK;
+	}
+
+	inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
+	credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
+
+	/* requests larger than 64 KB need credit charge */
+	if (credit_charge == 0 && data_length > 65536) {
+		DEBUG(2, ("Request larger than 64KB w/o creditcharge\n"));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	needed_charge = (data_length - 1)/ 65536 + 1;
+
+	DEBUG(10, ("mid %lu, CreditCharge: %d, NeededCharge: %d\n",
+		   BVAL(inhdr, SMB2_HDR_MESSAGE_ID), credit_charge,
+		   needed_charge));
+
+	if (needed_charge > credit_charge) {
+		DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
+					credit_charge, needed_charge));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	return NT_STATUS_OK;
+}
+
 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
 					size_t expected_body_size)
 {
diff --git a/source3/smbd/smb2_setinfo.c b/source3/smbd/smb2_setinfo.c
index ac6adc3..be506cc 100644
--- a/source3/smbd/smb2_setinfo.c
+++ b/source3/smbd/smb2_setinfo.c
@@ -85,6 +85,12 @@ 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);
+	if (!NT_STATUS_IS_OK(status)) {
+		return smbd_smb2_request_error(req, status);
+	}
+
 	if (req->compat_chain_fsp) {
 		/* skip check */
 	} else if (in_file_id_persistent != in_file_id_volatile) {
diff --git a/source3/smbd/smb2_write.c b/source3/smbd/smb2_write.c
index b0ffd44..163672c 100644
--- a/source3/smbd/smb2_write.c
+++ b/source3/smbd/smb2_write.c
@@ -88,6 +88,11 @@ NTSTATUS smbd_smb2_request_process_write(struct smbd_smb2_request *req)
 	in_data_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base;
 	in_data_buffer.length = in_data_length;
 
+	status = smbd_smb2_request_verify_creditcharge(req, in_data_length);
+	if (!NT_STATUS_IS_OK(status)) {
+		return smbd_smb2_request_error(req, status);
+	}
+
 	if (req->compat_chain_fsp) {
 		/* skip check */
 	} else if (in_file_id_persistent != in_file_id_volatile) {


-- 
Samba Shared Repository


More information about the samba-cvs mailing list