The branch, master has been updated
       via  012c9d0 s3:smb2_server: add basic support for SMB 2.1
       via  1c8e8c7 s3:smb2_server: return NOT_SUPPORTED if we don't find a 
common dialect with the client
       via  e603929 s3:smb2_server: max_trans, max_read and max_write are 
limited to 64 kilobytes
       via  a44d3d1 s3:smb2cli: make sure we don't try to send requests on a 
disconnected cli_state
       via  4dca2ac s3:smb2cli: make sure requests are not finished, when we 
send when to the network
       via  0b6087c s3:smb2cli: disconnect the connection, if we're out of 
message ids
       via  5155a15 s3:smb2cli: don't use state->cli->smb2.mid++ as macro 
argument
      from  3e8c665 s3-smbd: Rename reload_printers() and add documentation.

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


- Log -----------------------------------------------------------------
commit 012c9d06a94b532377e9e96f60b20b5f0975af74
Author: Stefan Metzmacher <[email protected]>
Date:   Mon Sep 5 13:14:40 2011 +0200

    s3:smb2_server: add basic support for SMB 2.1
    
    This adds support for the 2 stage negprot, from SMB 1 to SMB 2.1.
    
    Support for this of for now and "max protocol = SMB2" still maps
    to "max protocol = SMB2_02" PROTOCOL_SMB2_02.
    
    In order to activate smb2.1, you need to use "max protocol = SMB2_10".
    
    metze
    
    Autobuild-User: Stefan Metzmacher <[email protected]>
    Autobuild-Date: Mon Sep  5 19:30:58 CEST 2011 on sn-devel-104

commit 1c8e8c7e7b4cc00628b91e2e0596bfa428a2bcdb
Author: Stefan Metzmacher <[email protected]>
Date:   Mon Sep 5 12:23:51 2011 +0200

    s3:smb2_server: return NOT_SUPPORTED if we don't find a common dialect with 
the client
    
    metze

commit e603929b9801ad6cc47dead19d27b42fe46489c7
Author: Stefan Metzmacher <[email protected]>
Date:   Mon Sep 5 12:14:06 2011 +0200

    s3:smb2_server: max_trans, max_read and max_write are limited to 64 
kilobytes
    
    Only if SMB2_CAP_LARGE_MTU is supported we should announce larger limits.
    
    metze

commit a44d3d176400d0c6500fc8d3c05ee73e930fd140
Author: Stefan Metzmacher <[email protected]>
Date:   Mon Sep 5 09:49:53 2011 +0200

    s3:smb2cli: make sure we don't try to send requests on a disconnected 
cli_state
    
    metze

commit 4dca2acfe43fda00637615548fecab1e3313b204
Author: Stefan Metzmacher <[email protected]>
Date:   Mon Sep 5 09:35:43 2011 +0200

    s3:smb2cli: make sure requests are not finished, when we send when to the 
network
    
    metze

commit 0b6087c7be01983be96f3f3cb892ba2f32a8266a
Author: Stefan Metzmacher <[email protected]>
Date:   Mon Sep 5 09:31:54 2011 +0200

    s3:smb2cli: disconnect the connection, if we're out of message ids
    
    metze

commit 5155a15c5cadd2dec9386576c1b4b566be1e4536
Author: Stefan Metzmacher <[email protected]>
Date:   Sat Sep 3 15:23:44 2011 +0200

    s3:smb2cli: don't use state->cli->smb2.mid++ as macro argument
    
    It gets expanded multiple times.
    
    metze

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

Summary of changes:
 source3/libsmb/smb2cli_base.c |   31 +++++++++++++-
 source3/param/loadparm.c      |    3 +-
 source3/smbd/globals.h        |    2 +
 source3/smbd/negprot.c        |    1 +
 source3/smbd/smb2_negprot.c   |   94 ++++++++++++++++++++++++++++++++++++----
 5 files changed, 118 insertions(+), 13 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/libsmb/smb2cli_base.c b/source3/libsmb/smb2cli_base.c
index 9fc824c..7f4b176 100644
--- a/source3/libsmb/smb2cli_base.c
+++ b/source3/libsmb/smb2cli_base.c
@@ -22,6 +22,7 @@
 #include "client.h"
 #include "read_smb.h"
 #include "smb2cli_base.h"
+#include "libsmb/proto.h"
 #include "lib/async_req/async_sock.h"
 #include "lib/util/tevent_ntstatus.h"
 
@@ -252,10 +253,26 @@ NTSTATUS smb2cli_req_compound_submit(struct tevent_req 
**reqs,
        for (i=0; i<num_reqs; i++) {
                size_t reqlen;
                bool ret;
+               uint64_t mid;
+
+               if (!tevent_req_is_in_progress(reqs[i])) {
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
 
                state = tevent_req_data(reqs[i], struct smb2cli_req_state);
 
-               SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, state->cli->smb2.mid++);
+               if (!cli_state_is_connected(state->cli)) {
+                       return NT_STATUS_CONNECTION_DISCONNECTED;
+               }
+
+               if (state->cli->smb2.mid == UINT64_MAX) {
+                       return NT_STATUS_CONNECTION_ABORTED;
+               }
+
+               mid = state->cli->smb2.mid;
+               state->cli->smb2.mid += 1;
+
+               SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, mid);
 
                iov[num_iov].iov_base = state->hdr;
                iov[num_iov].iov_len  = sizeof(state->hdr);
@@ -576,7 +593,17 @@ static void smb2cli_inbuf_received(struct tevent_req 
*subreq)
 
        num_pending = talloc_array_length(cli->conn.pending);
        if (num_pending == 0) {
-               /* no more pending requests, so we are done for now */
+               if (state->cli->smb2.mid < UINT64_MAX) {
+                       /* no more pending requests, so we are done for now */
+                       return;
+               }
+
+               /*
+                * If there are no more requests possible,
+                * because we are out of message ids,
+                * we need to disconnect.
+                */
+               smb2cli_notify_pending(cli, NT_STATUS_CONNECTION_ABORTED);
                return;
        }
        req = cli->conn.pending[0];
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index b0c64c7..305ff2c 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -312,7 +312,8 @@ static void add_to_file_list(const char *fname, const char 
*subfname);
 static bool lp_set_cmdline_helper(const char *pszParmName, const char 
*pszParmValue, bool store_values);
 
 static const struct enum_list enum_protocol[] = {
-       {PROTOCOL_SMB2_02, "SMB2"},
+       {PROTOCOL_SMB2_02, "SMB2"}, /* for now keep PROTOCOL_SMB2_02 */
+       {PROTOCOL_SMB2_10, "SMB2_10"},
        {PROTOCOL_SMB2_02, "SMB2_02"},
        {PROTOCOL_NT1, "NT1"},
        {PROTOCOL_LANMAN2, "LANMAN2"},
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 2e59d9b..6ce9835 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -241,6 +241,7 @@ const char *smb2_opcode_name(uint16_t opcode);
 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size);
 
 void reply_smb2002(struct smb_request *req, uint16_t choice);
+void reply_smb20ff(struct smb_request *req, uint16_t choice);
 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
                             const uint8_t *inbuf, size_t size);
 
@@ -578,6 +579,7 @@ struct smbd_server_connection {
                struct tevent_queue *recv_queue;
                struct tevent_queue *send_queue;
                struct tstream_context *stream;
+               bool negprot_2ff;
                struct {
                        /* an id tree used to allocate vuids */
                        /* this holds info on session vuids that are already
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index 49b9420..a38534f 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -536,6 +536,7 @@ static const struct {
        void (*proto_reply_fn)(struct smb_request *req, uint16 choice);
        int protocol_level;
 } supported_protocols[] = {
+       {"SMB 2.???",               "SMB2_FF",  reply_smb20ff,  
PROTOCOL_SMB2_10},
        {"SMB 2.002",               "SMB2_02",  reply_smb2002,  
PROTOCOL_SMB2_02},
        {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
        {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c
index 5ae9163..56a30d0 100644
--- a/source3/smbd/smb2_negprot.c
+++ b/source3/smbd/smb2_negprot.c
@@ -25,9 +25,9 @@
 
 /*
  * this is the entry point if SMB2 is selected via
- * the SMB negprot
+ * the SMB negprot and the given dialect.
  */
-void reply_smb2002(struct smb_request *req, uint16_t choice)
+static void reply_smb20xx(struct smb_request *req, uint16_t dialect)
 {
        uint8_t *smb2_inbuf;
        uint8_t *smb2_hdr;
@@ -51,7 +51,7 @@ void reply_smb2002(struct smb_request *req, uint16_t choice)
        SSVAL(smb2_body, 0x00, 0x0024); /* struct size */
        SSVAL(smb2_body, 0x02, 0x0001); /* dialect count */
 
-       SSVAL(smb2_dyn,  0x00, 0x0202); /* dialect 2.002 */
+       SSVAL(smb2_dyn,  0x00, dialect);
 
        req->outbuf = NULL;
 
@@ -59,6 +59,25 @@ void reply_smb2002(struct smb_request *req, uint16_t choice)
        return;
 }
 
+/*
+ * this is the entry point if SMB2 is selected via
+ * the SMB negprot and the "SMB 2.002" dialect.
+ */
+void reply_smb2002(struct smb_request *req, uint16_t choice)
+{
+       reply_smb20xx(req, SMB2_DIALECT_REVISION_202);
+}
+
+/*
+ * this is the entry point if SMB2 is selected via
+ * the SMB negprot and the "SMB 2.???" dialect.
+ */
+void reply_smb20ff(struct smb_request *req, uint16_t choice)
+{
+       req->sconn->smb2.negprot_2ff = true;
+       reply_smb20xx(req, SMB2_DIALECT_REVISION_2FF);
+}
+
 NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
 {
        const uint8_t *inbody;
@@ -77,6 +96,11 @@ NTSTATUS smbd_smb2_request_process_negprot(struct 
smbd_smb2_request *req)
        uint16_t dialect_count;
        uint16_t dialect = 0;
        uint32_t capabilities;
+       enum protocol_types protocol = PROTOCOL_NONE;
+       uint32_t max_limit;
+       uint32_t max_trans = lp_smb2_max_trans();
+       uint32_t max_read = lp_smb2_max_read();
+       uint32_t max_write = lp_smb2_max_write();
 
 /* TODO: drop the connection with INVALID_PARAMETER */
 
@@ -102,18 +126,58 @@ NTSTATUS smbd_smb2_request_process_negprot(struct 
smbd_smb2_request *req)
        }
        indyn = (const uint8_t *)req->in.vector[i+2].iov_base;
 
-       for (c=0; c < dialect_count; c++) {
+       for (c=0; protocol == PROTOCOL_NONE && c < dialect_count; c++) {
+               if (lp_maxprotocol() < PROTOCOL_SMB2_10) {
+                       break;
+               }
+               if (lp_minprotocol() > PROTOCOL_SMB2_10) {
+                       break;
+               }
+
+               dialect = SVAL(indyn, c*2);
+               if (dialect == SMB2_DIALECT_REVISION_210) {
+                       protocol = PROTOCOL_SMB2_10;
+                       break;
+               }
+       }
+
+       for (c=0; protocol == PROTOCOL_NONE && c < dialect_count; c++) {
+               if (lp_maxprotocol() < PROTOCOL_SMB2_02) {
+                       break;
+               }
+               if (lp_minprotocol() > PROTOCOL_SMB2_02) {
+                       break;
+               }
+
                dialect = SVAL(indyn, c*2);
                if (dialect == SMB2_DIALECT_REVISION_202) {
+                       protocol = PROTOCOL_SMB2_02;
                        break;
                }
        }
 
-       if (dialect != SMB2_DIALECT_REVISION_202) {
-               return smbd_smb2_request_error(req, 
NT_STATUS_INVALID_PARAMETER);
+       for (c=0; protocol == PROTOCOL_NONE && c < dialect_count; c++) {
+               if (lp_maxprotocol() < PROTOCOL_SMB2_10) {
+                       break;
+               }
+
+               dialect = SVAL(indyn, c*2);
+               if (dialect == SMB2_DIALECT_REVISION_2FF) {
+                       if (req->sconn->smb2.negprot_2ff) {
+                               req->sconn->smb2.negprot_2ff = false;
+                               protocol = PROTOCOL_SMB2_10;
+                               break;
+                       }
+               }
        }
 
-       set_Protocol(PROTOCOL_SMB2_02);
+       if (protocol == PROTOCOL_NONE) {
+               return smbd_smb2_request_error(req, NT_STATUS_NOT_SUPPORTED);
+       }
+
+       if (dialect != SMB2_DIALECT_REVISION_2FF) {
+               set_Protocol(protocol);
+       }
 
        if (get_remote_arch() != RA_SAMBA) {
                set_remote_arch(RA_VISTA);
@@ -139,6 +203,16 @@ NTSTATUS smbd_smb2_request_process_negprot(struct 
smbd_smb2_request *req)
                capabilities |= SMB2_CAP_DFS;
        }
 
+       /*
+        * Unless we implement SMB2_CAP_LARGE_MTU,
+        * 0x10000 (65536) is the maximum allowed message size
+        */
+       max_limit = 0x10000;
+
+       max_trans = MIN(max_limit, max_trans);
+       max_read  = MIN(max_limit, max_read);
+       max_write = MIN(max_limit, max_write);
+
        security_offset = SMB2_HDR_BODY + 0x40;
 
 #if 1
@@ -164,9 +238,9 @@ NTSTATUS smbd_smb2_request_process_negprot(struct 
smbd_smb2_request *req)
               negprot_spnego_blob.data, 16);   /* server guid */
        SIVAL(outbody.data, 0x18,
              capabilities);                    /* capabilities */
-       SIVAL(outbody.data, 0x1C, lp_smb2_max_trans()); /* max transact size */
-       SIVAL(outbody.data, 0x20, lp_smb2_max_read());  /* max read size */
-       SIVAL(outbody.data, 0x24, lp_smb2_max_write()); /* max write size */
+       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 */
        SBVAL(outbody.data, 0x28, 0);           /* system time */
        SBVAL(outbody.data, 0x30, 0);           /* server start time */
        SSVAL(outbody.data, 0x38,


-- 
Samba Shared Repository

Reply via email to