r11668: yay! we get a successful session setup with SMB2, and get back a 64bit uid
authorAndrew Tridgell <tridge@samba.org>
Fri, 11 Nov 2005 07:23:45 +0000 (07:23 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:46:10 +0000 (13:46 -0500)
(This used to be commit 72b34a7c1b66af6be02f66639efc55a19c73e387)

source4/libcli/smb2/negprot.c
source4/libcli/smb2/request.c
source4/libcli/smb2/session.c
source4/libcli/smb2/smb2.h
source4/libcli/smb2/smb2_calls.h
source4/libcli/smb2/transport.c
source4/torture/smb2/connect.c

index ffddf8a2f01b29080fba6a10603d482aaa2fb7f8..5cd4810909ea7e58f21af3c98acdaf67fbb4b7af 100644 (file)
@@ -33,7 +33,6 @@ struct smb2_request *smb2_negprot_send(struct smb2_transport *transport,
 {
        struct smb2_request *req;
        
-
        req = smb2_request_init(transport, SMB2_OP_NEGPROT, 0x26);
        if (req == NULL) return NULL;
 
index e71fc844711c3ac8290eebb9c6eabdaaab18b9c3..93f8043d0c81a3137052501e19e41aaf98e68dd8 100644 (file)
@@ -130,7 +130,7 @@ BOOL smb2_request_is_error(struct smb2_request *req)
 /*
   check if a range in the reply body is out of bounds
 */
-BOOL smb2_oob(struct smb2_request *req, const uint8_t *ptr, uint_t size)
+BOOL smb2_oob_in(struct smb2_request *req, const uint8_t *ptr, uint_t size)
 {
        /* be careful with wraparound! */
        if (ptr < req->in.body ||
@@ -142,14 +142,66 @@ BOOL smb2_oob(struct smb2_request *req, const uint8_t *ptr, uint_t size)
        return False;
 }
 
+/*
+  check if a range in the outgoing body is out of bounds
+*/
+BOOL smb2_oob_out(struct smb2_request *req, const uint8_t *ptr, uint_t size)
+{
+       /* be careful with wraparound! */
+       if (ptr < req->out.body ||
+           ptr >= req->out.body + req->out.body_size ||
+           size > req->out.body_size ||
+           ptr + size > req->out.body + req->out.body_size) {
+               return True;
+       }
+       return False;
+}
+
 /*
   pull a data blob from the body of a reply
 */
 DATA_BLOB smb2_pull_blob(struct smb2_request *req, uint8_t *ptr, uint_t size)
 {
-       if (smb2_oob(req, ptr, size)) {
+       if (smb2_oob_in(req, ptr, size)) {
                return data_blob(NULL, 0);
        }
        return data_blob_talloc(req, ptr, size);
 }
 
+/*
+  pull a ofs/length/blob triple into a data blob
+  the ptr points to the start of the offset/length pair
+*/
+NTSTATUS smb2_pull_ofs_blob(struct smb2_request *req, uint8_t *ptr, DATA_BLOB *blob)
+{
+       uint16_t ofs, size;
+       if (smb2_oob_in(req, ptr, 4)) {
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
+       ofs  = SVAL(ptr, 0);
+       size = SVAL(ptr, 2);
+       if (smb2_oob_in(req, req->in.hdr + ofs, size)) {
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
+       *blob = data_blob_talloc(req, req->in.hdr+ofs, size);
+       NT_STATUS_HAVE_NO_MEMORY(blob->data);
+       return NT_STATUS_OK;
+}
+
+/*
+  push a ofs/length/blob triple into a data blob
+  the ptr points to the start of the offset/length pair
+
+  NOTE: assumes blob goes immediately after the offset/length pair. Needs 
+        to be generalised
+*/
+NTSTATUS smb2_push_ofs_blob(struct smb2_request *req, uint8_t *ptr, DATA_BLOB blob)
+{
+       if (smb2_oob_out(req, ptr, 4+blob.length)) {
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
+       SSVAL(ptr, 0, 4 + (ptr - req->out.hdr));
+       SSVAL(ptr, 2, blob.length);
+       memcpy(ptr+4, blob.data, blob.length);
+       return NT_STATUS_OK;
+}
index 2f9a979feae06393c828d83787280a3970208489..031360fcb948cb93e18f9d0af721ce43072b33cc 100644 (file)
@@ -62,17 +62,22 @@ struct smb2_request *smb2_session_setup_send(struct smb2_session *session,
                                             struct smb2_session_setup *io)
 {
        struct smb2_request *req;
+       NTSTATUS status;
        
        req = smb2_request_init(session->transport, SMB2_OP_SESSSETUP, 
                                0x10 + io->in.secblob.length);
        if (req == NULL) return NULL;
 
+       SBVAL(req->out.hdr,  SMB2_HDR_UID, session->uid);
        SIVAL(req->out.body, 0x00, io->in.unknown1);
        SIVAL(req->out.body, 0x04, io->in.unknown2);
        SIVAL(req->out.body, 0x08, io->in.unknown3);
-       SSVAL(req->out.body, 0x0C, io->in.unknown4);
-       SSVAL(req->out.body, 0x0E, io->in.secblob.length);
-       memcpy(req->out.body+0x10, io->in.secblob.data, io->in.secblob.length);
+       
+       status = smb2_push_ofs_blob(req, req->out.body+0x0C, io->in.secblob);
+       if (!NT_STATUS_IS_OK(status)) {
+               talloc_free(req);
+               return NULL;
+       }
 
        smb2_transport_send(req);
 
@@ -86,10 +91,11 @@ struct smb2_request *smb2_session_setup_send(struct smb2_session *session,
 NTSTATUS smb2_session_setup_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, 
                                 struct smb2_session_setup *io)
 {
-       uint16_t blobsize;
+       NTSTATUS status;
 
        if (!smb2_request_receive(req) || 
-           smb2_request_is_error(req)) {
+           (smb2_request_is_error(req) && 
+            !NT_STATUS_EQUAL(req->status, NT_STATUS_MORE_PROCESSING_REQUIRED))) {
                return smb2_request_destroy(req);
        }
 
@@ -97,10 +103,14 @@ NTSTATUS smb2_session_setup_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
                return NT_STATUS_BUFFER_TOO_SMALL;
        }
 
-       io->out.unknown1     = IVAL(req->in.body, 0x00);
-       io->out.unknown2     = SVAL(req->in.body, 0x04);
-       blobsize             = SVAL(req->in.body, 0x06);
-       io->out.secblob      = smb2_pull_blob(req, req->in.body+0x08, blobsize);
+       io->out.unknown1 = IVAL(req->in.body, 0x00);
+       io->out.uid      = BVAL(req->in.hdr,  SMB2_HDR_UID);
+       
+       status = smb2_pull_ofs_blob(req, req->in.body+0x04, &io->out.secblob);
+       if (!NT_STATUS_IS_OK(status)) {
+               smb2_request_destroy(req);
+               return status;
+       }
        talloc_steal(mem_ctx, io->out.secblob.data);
 
        return smb2_request_destroy(req);
index 2262040b51227e48c46d016a3b42c9fa27de38f7..8ed51b2351fcb3a5a0bda23469918b54b0e9a2a7 100644 (file)
@@ -57,6 +57,7 @@ struct smb2_transport {
 struct smb2_session {
        struct smb2_transport *transport;
        struct gensec_security *gensec;
+       uint64_t uid;
 };
 
 struct smb2_request_buffer {
@@ -141,8 +142,7 @@ struct smb2_request {
 #define SMB2_HDR_SEQNUM  0x18
 #define SMB2_HDR_PID     0x20
 #define SMB2_HDR_TID     0x24
-#define SMB2_HDR_UID     0x28
-#define SMB2_HDR_UID2    0x2c /* whats this? */
+#define SMB2_HDR_UID     0x28 /* 64 bit */
 #define SMB2_HDR_SIG     0x30 /* guess ... */
 #define SMB2_HDR_BODY    0x40
 
index ef0abc3e459dd19688ee3bddbfdbe6437f2cc723..3ee8f90bc97ea403293593e1947704709633b85f 100644 (file)
@@ -50,14 +50,13 @@ struct smb2_session_setup {
                uint32_t unknown1; /* 0x11 */
                uint32_t unknown2; /* 0xF */
                uint32_t unknown3; /* 0x00 */
-               uint16_t unknown4; /* 0x50 */
-               /* uint16_t secblob size here */
+               /* uint16_t secblob ofs/size here */
                DATA_BLOB secblob;
        } in;
        struct {
                uint32_t unknown1; /* 0x09 */
-               uint16_t unknown2; /* 0x48 */
-               /* uint16_t secblob size here */
+               /* uint16_t secblob ofs/size here */
                DATA_BLOB secblob;
+               uint64_t uid; /* returned in header */
        } out;
 };
index dd05eed1dd4e97899c3636e523e8d3aefdc2e0bc..97408b2ae3ac93602c1a4496351d4693b3a64b37 100644 (file)
@@ -183,7 +183,8 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob)
        req->in.ptr       = req->in.body;
        req->status       = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS));
 
-       dump_data(0, req->in.body, req->in.body_size);
+       DEBUG(2, ("SMB2 RECV seqnum=0x%llx\n", req->seqnum));
+       dump_data(2, req->in.body, req->in.body_size);
 
        /* if this request has an async handler then call that to
           notify that the reply has been received. This might destroy
@@ -200,7 +201,7 @@ error:
                DLIST_REMOVE(transport->pending_recv, req);
                req->state = SMB2_REQUEST_ERROR;
        }
-       dump_data(0, blob.data, blob.length);
+       dump_data(2, blob.data, blob.length);
        data_blob_free(&blob);
        return NT_STATUS_UNSUCCESSFUL;
 }
@@ -247,6 +248,9 @@ void smb2_transport_send(struct smb2_request *req)
 
        _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
 
+       DEBUG(2, ("SMB2 send seqnum=0x%llx\n", req->seqnum));
+       dump_data(2, req->out.body, req->out.body_size);
+
        /* check if the transport is dead */
        if (req->transport->socket->sock == NULL) {
                req->state = SMB2_REQUEST_ERROR;
index 43029dd04dbe7d5b1d91e8336206856cbfc543b1..49b9582d4d6422d8c1a662faa8e64b2f4fb674b3 100644 (file)
@@ -76,6 +76,8 @@ static struct smb2_transport *torture_smb2_negprot(TALLOC_CTX *mem_ctx, const ch
        printf("current_time  = %s\n", nt_time_string(mem_ctx, io.out.current_time));
        printf("boot_time     = %s\n", nt_time_string(mem_ctx, io.out.boot_time));
 
+       transport->negotiate.secblob = io.out.secblob;
+
        return transport;
 }
 
@@ -89,12 +91,12 @@ static struct smb2_session *torture_smb2_session(struct smb2_transport *transpor
        struct smb2_session_setup io;
        NTSTATUS status;
        TALLOC_CTX *tmp_ctx = talloc_new(transport);
+       DATA_BLOB secblob;
 
        ZERO_STRUCT(io);
        io.in.unknown1 = 0x11;
        io.in.unknown2 = 0xF;
        io.in.unknown3 = 0x00;
-       io.in.unknown4 = 0x50;
 
        session = smb2_session_init(transport, transport, True);
 
@@ -126,21 +128,39 @@ static struct smb2_session *torture_smb2_session(struct smb2_transport *transpor
                return NULL;
        }
 
-       status = gensec_update(session->gensec, tmp_ctx,
-                              session->transport->negotiate.secblob,
-                              &io.in.secblob);
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && 
-           !NT_STATUS_IS_OK(status)) {
-               DEBUG(1, ("Failed initial gensec_update : %s\n", nt_errstr(status)));
-               return NULL;
-       }
+       secblob = session->transport->negotiate.secblob;
+
+       do {
+               NTSTATUS status1;
+
+               status1 = gensec_update(session->gensec, tmp_ctx, secblob, &io.in.secblob);
+               if (!NT_STATUS_EQUAL(status1, NT_STATUS_MORE_PROCESSING_REQUIRED) && 
+                   !NT_STATUS_IS_OK(status1)) {
+                       DEBUG(1, ("Failed initial gensec_update : %s\n", 
+                                 nt_errstr(status1)));
+                       status = status1;
+                       break;
+               }
+               
+               status = smb2_session_setup(session, tmp_ctx, &io);
+               secblob = io.out.secblob;
+
+               session->uid = io.out.uid;
+
+               if (NT_STATUS_IS_OK(status) && 
+                   NT_STATUS_EQUAL(status1, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+                       status = gensec_update(session->gensec, tmp_ctx, secblob, 
+                                              &io.in.secblob);
+               }
+       } while (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED));
 
-       status = smb2_session_setup(session, tmp_ctx, &io);
        if (!NT_STATUS_IS_OK(status)) {
                printf("session setup failed - %s\n", nt_errstr(status));
                return NULL;
        }
 
+       printf("Session setup gave UID 0x%llx\n", session->uid);
+
        return session;
 }