Mikko Rasa : secur32: Only process full TLS frames in schan_DecryptMessage.

Alexandre Julliard julliard at winehq.org
Wed Sep 15 18:18:40 CDT 2010


Module: wine
Branch: master
Commit: b335e94788647afa013b5e58791f176b2a459e38
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=b335e94788647afa013b5e58791f176b2a459e38

Author: Mikko Rasa <tdb at tdb.fi>
Date:   Wed Sep 15 20:30:09 2010 +0300

secur32: Only process full TLS frames in schan_DecryptMessage.

---

 dlls/secur32/schannel.c |   30 ++++++++++++++++++++++++++++--
 1 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c
index 0e8b9e2..78757ac 100644
--- a/dlls/secur32/schannel.c
+++ b/dlls/secur32/schannel.c
@@ -105,6 +105,7 @@ struct schan_transport;
 struct schan_buffers
 {
     SIZE_T offset;
+    SIZE_T limit;
     const SecBufferDesc *desc;
     int current_buffer_idx;
     BOOL allow_buffer_resize;
@@ -492,6 +493,7 @@ static void init_schan_buffers(struct schan_buffers *s, const PSecBufferDesc des
         int (*get_next_buffer)(const struct schan_transport *, struct schan_buffers *))
 {
     s->offset = 0;
+    s->limit = 0;
     s->desc = desc;
     s->current_buffer_idx = -1;
     s->allow_buffer_resize = FALSE;
@@ -599,6 +601,16 @@ static ssize_t schan_pull(gnutls_transport_ptr_t transport, void *buff, size_t b
         return -1;
     }
 
+    if (t->in.limit != 0 && t->in.offset + buff_len >= t->in.limit)
+    {
+        buff_len = t->in.limit - t->in.offset;
+        if (buff_len == 0)
+        {
+            pgnutls_transport_set_errno(t->ctx->session, EAGAIN);
+            return -1;
+        }
+    }
+
     memcpy(buff, b, buff_len);
     t->in.offset += buff_len;
 
@@ -1208,10 +1220,11 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle
     SecBuffer *buffer;
     SIZE_T data_size;
     char *data;
+    unsigned expected_size;
     ssize_t received = 0;
     ssize_t ret;
     int idx;
-    char *buf_ptr;
+    unsigned char *buf_ptr;
 
     TRACE("context_handle %p, message %p, message_seq_no %d, quality %p\n",
             context_handle, message, message_seq_no, quality);
@@ -1225,12 +1238,22 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle
     if (idx == -1)
         return SEC_E_INVALID_TOKEN;
     buffer = &message->pBuffers[idx];
+    buf_ptr = buffer->pvBuffer;
+
+    expected_size = 5 + ((buf_ptr[3] << 8) | buf_ptr[4]);
+    if(buffer->cbBuffer < expected_size)
+    {
+        TRACE("Expected %u bytes, but buffer only contains %u bytes\n", expected_size, buffer->cbBuffer);
+        TRACE("Returning SEC_E_INCOMPLETE_MESSAGE\n");
+        return SEC_E_INCOMPLETE_MESSAGE;
+    }
 
     data_size = buffer->cbBuffer;
     data = HeapAlloc(GetProcessHeap(), 0, data_size);
 
     transport.ctx = ctx;
     init_schan_buffers(&transport.in, message, schan_decrypt_message_get_next_buffer);
+    transport.in.limit = expected_size;
     init_schan_buffers(&transport.out, NULL, NULL);
     pgnutls_transport_set_ptr(ctx->session, (gnutls_transport_ptr_t)&transport);
 
@@ -1266,7 +1289,6 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle
 
     TRACE("Received %zd bytes\n", received);
 
-    buf_ptr = buffer->pvBuffer;
     memcpy(buf_ptr + 5, data, received);
     HeapFree(GetProcessHeap(), 0, data);
 
@@ -1276,6 +1298,10 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle
     schan_decrypt_fill_buffer(message, SECBUFFER_STREAM_TRAILER,
         buf_ptr + 5 + received, buffer->cbBuffer - 5 - received);
 
+    if(buffer->cbBuffer > expected_size)
+        schan_decrypt_fill_buffer(message, SECBUFFER_EXTRA,
+            buf_ptr + expected_size, buffer->cbBuffer - expected_size);
+
     buffer->BufferType = SECBUFFER_STREAM_HEADER;
     buffer->cbBuffer = 5;
 




More information about the wine-cvs mailing list