s3:smb2_server: add basic support for SMB 2.1
authorStefan Metzmacher <metze@samba.org>
Mon, 5 Sep 2011 11:14:40 +0000 (13:14 +0200)
committerStefan Metzmacher <metze@samba.org>
Mon, 5 Sep 2011 17:30:58 +0000 (19:30 +0200)
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 <metze@samba.org>
Autobuild-Date: Mon Sep  5 19:30:58 CEST 2011 on sn-devel-104

source3/param/loadparm.c
source3/smbd/globals.h
source3/smbd/negprot.c
source3/smbd/smb2_negprot.c

index b0c64c7fa31b0f74ec3576b8749de84dccfaf45f..305ff2cec9547a12d12ca7dab5ceef5c96177681 100644 (file)
@@ -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"},
index 2e59d9bc5f8be552b11ec242c675c5f05c6b5f23..6ce9835dee661b5060d951830b98cb5f00405329 100644 (file)
@@ -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
index 49b9420fbf96cf97a2c19b0d4dc5b47a009ae2d0..a38534f3239e91fb4665fcb3466380a876377689 100644 (file)
@@ -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},
index dfb2da3fdae46d0d66e272da5d8999758de388c7..56a30d0d71ea229cbe8a5ec0f4c10e70ebe14395 100644 (file)
@@ -25,9 +25,9 @@
 
 /*
  * this is the entry point if SMB2 is selected via
- * the SMB negprot and the "SMB 2.002" dialect.
+ * 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, SMB2_DIALECT_REVISION_202);
+       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;
@@ -108,6 +127,28 @@ 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; 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;
@@ -115,11 +156,28 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
                }
        }
 
+       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;
+                       }
+               }
+       }
+
        if (protocol == PROTOCOL_NONE) {
                return smbd_smb2_request_error(req, NT_STATUS_NOT_SUPPORTED);
        }
 
-       set_Protocol(protocol);
+       if (dialect != SMB2_DIALECT_REVISION_2FF) {
+               set_Protocol(protocol);
+       }
 
        if (get_remote_arch() != RA_SAMBA) {
                set_remote_arch(RA_VISTA);