fixed up the .in side of SMB2 negprot
authorAndrew Tridgell <tridge@samba.org>
Tue, 12 Feb 2008 01:54:44 +0000 (12:54 +1100)
committerAndrew Tridgell <tridge@samba.org>
Tue, 12 Feb 2008 01:54:44 +0000 (12:54 +1100)
fixed the input side of the SMB2 negprot structure and parsers according to the documentation
(This used to be commit 55af8acc7b32c24e4b1187e9d8d1c8f060e914b0)

source4/libcli/smb2/connect.c
source4/libcli/smb2/negprot.c
source4/libcli/smb2/smb2_calls.h
source4/smb_server/smb/negprot.c
source4/smb_server/smb2/negprot.c
source4/smb_server/smb_server.h

index 4518203183294f467b8de599b8f9241fc9104616..a2ae828fa57b62bbba58198e4affa12a9e3584ca 100644 (file)
@@ -120,6 +120,7 @@ static void continue_socket(struct composite_context *creq)
        struct smbcli_socket *sock;
        struct smb2_transport *transport;
        struct smb2_request *req;
+       uint16_t dialects[1];
 
        c->status = smbcli_sock_connect_recv(creq, state, &sock);
        if (!composite_is_ok(c)) return;
@@ -128,7 +129,12 @@ static void continue_socket(struct composite_context *creq)
        if (composite_nomem(transport, c)) return;
 
        ZERO_STRUCT(state->negprot);
-       state->negprot.in.unknown1 = 0x0001;
+       state->negprot.in.dialect_count = 1;
+       state->negprot.in.security_mode = 0;
+       state->negprot.in.capabilities  = 0;
+       unix_to_nt_time(&state->negprot.in.start_time, time(NULL));
+       dialects[0] = 0;
+       state->negprot.in.dialects = dialects;
 
        req = smb2_negprot_send(transport, &state->negprot);
        if (composite_nomem(req, c)) return;
index 38fe0e7e5358e43a90e14da873af14e25d4ecf8f..a678ebe229af180b59e5344bc6e81019c55b5d67 100644 (file)
@@ -31,16 +31,33 @@ struct smb2_request *smb2_negprot_send(struct smb2_transport *transport,
                                       struct smb2_negprot *io)
 {
        struct smb2_request *req;
-       
-       req = smb2_request_init(transport, SMB2_OP_NEGPROT, 0x26, false, 0);
+       uint16_t size = 0x24 + io->in.dialect_count*2;
+        DATA_BLOB guid_blob;
+       enum ndr_err_code ndr_err;
+       int i;
+
+       req = smb2_request_init(transport, SMB2_OP_NEGPROT, size, false, 0);
        if (req == NULL) return NULL;
 
-       /* this seems to be a bug, they use 0x24 but the length is 0x26 */
-       SSVAL(req->out.body, 0x00, 0x24);
 
-       SSVAL(req->out.body, 0x02, io->in.unknown1);
-       memcpy(req->out.body+0x04, io->in.unknown2, 32);
-       SSVAL(req->out.body, 0x24, io->in.unknown3);
+       ndr_err = ndr_push_struct_blob(&guid_blob, req, NULL,
+                                      &io->in.client_guid,
+                                      (ndr_push_flags_fn_t)ndr_push_GUID);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || guid_blob.length != 16) {
+               talloc_free(req);
+               return NULL;
+       }
+
+       SSVAL(req->out.body, 0x00, 0x24);
+       SSVAL(req->out.body, 0x02, io->in.dialect_count);
+       SSVAL(req->out.body, 0x04, io->in.security_mode);
+       SSVAL(req->out.body, 0x06, io->in.reserved);
+       SIVAL(req->out.body, 0x08, io->in.capabilities);
+       memcpy(req->out.body+0x0C, guid_blob.data, guid_blob.length);
+       smbcli_push_nttime(req->out.body, 0x1C, io->in.start_time);
+       for (i=0;i<io->in.dialect_count;i++) {
+               SSVAL(req->out.body, 0x24 + i*2, io->in.dialects[i]);           
+       }
 
        smb2_transport_send(req);
 
index 6a551da4aebe8f6cb0be4241c624a7177cfe13da..41fb35b8f3a0f40e433c4519143d5513baeb5c15 100644 (file)
 
 struct smb2_negprot {
        struct {
-               /* static body buffer 38 (0x26) bytes */
-               /* uint16_t buffer_code;  0x24 (why?) */
-               uint16_t unknown1;    /* 0x0001 */
-               uint8_t  unknown2[32]; /* all zero */
-               uint16_t unknown3; /* 0x00000 */
+               uint16_t dialect_count;    /* size of dialects array */
+               uint16_t security_mode;    /* 0==signing disabled   
+                                             1==signing enabled */
+               uint16_t reserved;
+               uint32_t capabilities;
+               struct GUID client_guid;
+               NTTIME   start_time;
+               uint16_t *dialects;
        } in;
        struct {
                /* static body buffer 64 (0x40) bytes */
index 6d9ff838cb0398290bef94ad706cb7dc8259c4b3..b57e5e1d6452c19568f39df67abb621253a50bc4 100644 (file)
@@ -466,6 +466,7 @@ static const struct {
        void (*proto_reply_fn)(struct smbsrv_request *req, uint16_t choice);
        int protocol_level;
 } supported_protocols[] = {
+       {"SMB 2.002",                   "SMB2",         reply_smb2,     PROTOCOL_SMB2},
        {"SMB 2.001",                   "SMB2",         reply_smb2,     PROTOCOL_SMB2},
        {"NT LANMAN 1.0",               "NT1",          reply_nt1,      PROTOCOL_NT1},
        {"NT LM 0.12",                  "NT1",          reply_nt1,      PROTOCOL_NT1},
index 8e3cfd354751a703aeb0fefaa3bb9e85ebe3ef59..68509d71c6a3f37e537695ce768af782454d7180 100644 (file)
@@ -21,6 +21,7 @@
 #include "includes.h"
 #include "auth/credentials/credentials.h"
 #include "auth/gensec/gensec.h"
+#include "libcli/raw/libcliraw.h"
 #include "libcli/smb2/smb2.h"
 #include "libcli/smb2/smb2_calls.h"
 #include "smb_server/smb_server.h"
@@ -92,6 +93,12 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2
        struct timeval current_time;
        struct timeval boot_time;
 
+       /* we only do dialect 0 for now */
+       if (io->in.dialect_count < 1 ||
+           io->in.dialects[0] != 0) {
+               return NT_STATUS_NOT_SUPPORTED;
+       }
+
        req->smb_conn->negotiate.protocol = PROTOCOL_SMB2;
 
        current_time = timeval_current(); /* TODO: handle timezone?! */
@@ -155,6 +162,9 @@ static void smb2srv_negprot_send(struct smb2srv_request *req, struct smb2_negpro
 void smb2srv_negprot_recv(struct smb2srv_request *req)
 {
        struct smb2_negprot *io;
+       int i;
+       DATA_BLOB guid_blob;
+       enum ndr_err_code ndr_err;
 
        if (req->in.body_size < 0x26) {
                smb2srv_send_error(req,  NT_STATUS_FOOBAR);
@@ -168,9 +178,30 @@ void smb2srv_negprot_recv(struct smb2srv_request *req)
                return;
        }
 
-       io->in.unknown1 = SVAL(req->in.body, 0x02);
-       memcpy(io->in.unknown2, req->in.body + 0x04, 0x20);
-       io->in.unknown3 = SVAL(req->in.body, 0x24);
+       io->in.dialect_count = SVAL(req->in.body, 0x02);
+       io->in.security_mode = SVAL(req->in.body, 0x04);
+       io->in.reserved      = SVAL(req->in.body, 0x06);
+       io->in.capabilities  = IVAL(req->in.body, 0x08);
+       guid_blob.data       = req->in.body + 0xC;
+       guid_blob.length     = 16;
+       ndr_err = ndr_pull_struct_blob(&guid_blob, req, NULL, &io->in.client_guid, 
+                                      (ndr_pull_flags_fn_t)ndr_pull_GUID);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               smbsrv_terminate_connection(req->smb_conn, nt_errstr(NT_STATUS_FOOBAR));
+               talloc_free(req);
+               return;
+       }
+       io->in.start_time = smbcli_pull_nttime(req->in.body, 0x1C);
+
+       io->in.dialects = talloc_array(req, uint16_t, io->in.dialect_count);
+       if (io->in.dialects == NULL) {
+               smbsrv_terminate_connection(req->smb_conn, nt_errstr(NT_STATUS_NO_MEMORY));
+               talloc_free(req);
+               return;
+       }
+       for (i=0;i<io->in.dialect_count;i++) {
+               io->in.dialects[i] = SVAL(req->in.body, 0x24+i*2);
+       }
 
        req->status = smb2srv_negprot_backend(req, io);
 
@@ -182,14 +213,13 @@ void smb2srv_negprot_recv(struct smb2srv_request *req)
 }
 
 /*
- * reply to a SMB negprot request with dialect "SMB 2.001"
+ * reply to a SMB negprot request with dialect "SMB 2.002"
  */
 void smb2srv_reply_smb_negprot(struct smbsrv_request *smb_req)
 {
        struct smb2srv_request *req;
        uint32_t body_fixed_size = 0x26;
 
-       /* create a fake SMB2 negprot request */
        req = talloc_zero(smb_req->smb_conn, struct smb2srv_request);
        if (!req) goto nomem;
        req->smb_conn           = smb_req->smb_conn;
index 5644dfe6fb44da82c3f97a05315c06e1c1458b58..bb0673b7d0523ea982662a9bd2de0da97bd16497 100644 (file)
@@ -291,7 +291,7 @@ struct smbsrv_connection {
        
                /* the negotiatiated protocol */
                enum protocol_types protocol;
-       
+
                /* authentication context for multi-part negprot */
                struct auth_context *auth_context;