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 <[email protected]>

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


- Log -----------------------------------------------------------------
commit 981e9776f84dcf03f0297f47f63ee548ca089c0f
Author: Jeremy Allison <[email protected]>
Date:   Fri Mar 9 17:08:36 2012 -0800

    Ensure the right tsocket.h is included.
    
    Autobuild-User: Jeremy Allison <[email protected]>
    Autobuild-Date: Sat Mar 10 03:47:04 CET 2012 on sn-devel-104

commit 97e1652125a46ffbc1510b26abb0379d7df690d3
Author: Jeremy Allison <[email protected]>
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 <[email protected]>
Date:   Mon Feb 27 17:53:04 2012 -0800

    s3:smb2_server validate message ids with largemtu
    
    Signed-off-by: Jeremy Allison <[email protected]>

commit f6afda0bc867f1080c45e1f6f79d5032c41d2b1a
Author: Christian Ambach <[email protected]>
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 <[email protected]>

commit eec5ece6f59c5ff30de88af0e182c3b2f7b9579c
Author: Christian Ambach <[email protected]>
Date:   Mon Feb 27 17:49:12 2012 -0800

    s3:smb2_server add function to verify creditcharge
    
    Signed-off-by: Jeremy Allison <[email protected]>

commit bd0ad2bbb5361a92f349ef42171b9bdd1d99b281
Author: Christian Ambach <[email protected]>
Date:   Mon Feb 27 05:57:47 2012 -0800

    s3:smb2_server: announce LargeMTU for SMB2.1
    
    Signed-off-by: Jeremy Allison <[email protected]>

commit 6d128aac119d948f0ecb0dcf6b400b4eb4027fe6
Author: Christian Ambach <[email protected]>
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 <[email protected]>

commit 7f131d3cee260e5943dc1e113b6eabb677fd4945
Author: Christian Ambach <[email protected]>
Date:   Mon Feb 27 17:45:09 2012 -0800

    s3:smb2_server: add supports_multicredit to sconn
    
    Signed-off-by: Jeremy Allison <[email protected]>

commit 880f64b5560b0b27d7f1313c8a78044d871d27ad
Author: Christian Ambach <[email protected]>
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 <[email protected]>

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

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

Reply via email to