[PATCH 1/1] secur32: Return a SECBUFFER_MISSING buffer from the handshake if the input message is incomplete.

Hans Leidekker wine at gitlab.winehq.org
Wed Jun 29 07:56:00 CDT 2022


From: Hans Leidekker <hans at codeweavers.com>

---
 dlls/secur32/schannel.c       | 25 +++++++++++++++++++++++--
 dlls/secur32/tests/schannel.c | 21 ++++++++++++++++++++-
 2 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c
index 7dc9bd1d21a..70018e57f7e 100644
--- a/dlls/secur32/schannel.c
+++ b/dlls/secur32/schannel.c
@@ -747,6 +747,18 @@ static inline BOOL is_dtls_context(const struct schan_context *ctx)
     return ctx->header_size == HEADER_SIZE_DTLS;
 }
 
+static void fill_missing_sec_buffer(SecBufferDesc *input, DWORD size)
+{
+    int idx = schan_find_sec_buffer_idx(input, 0, SECBUFFER_EMPTY);
+    if (idx == -1) WARN("no empty buffer\n");
+    else
+    {
+        SecBuffer *buffer = &input->pBuffers[idx];
+        buffer->BufferType = SECBUFFER_MISSING;
+        buffer->cbBuffer = size;
+    }
+}
+
 /***********************************************************************
  *              InitializeSecurityContextW
  */
@@ -887,7 +899,15 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
             buffer = &pInput->pBuffers[idx];
             ptr = buffer->pvBuffer;
 
-            while (buffer->cbBuffer > expected_size + ctx->header_size)
+            if (buffer->cbBuffer < ctx->header_size)
+            {
+                TRACE("Expected at least %Iu bytes, but buffer only contains %lu bytes.\n",
+                      ctx->header_size, buffer->cbBuffer);
+                fill_missing_sec_buffer(pInput, ctx->header_size - buffer->cbBuffer);
+                return SEC_E_INCOMPLETE_MESSAGE;
+            }
+
+            while (buffer->cbBuffer >= expected_size + ctx->header_size)
             {
                 record_size = ctx->header_size + read_record_size(ptr, ctx->header_size);
 
@@ -899,7 +919,8 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
             if (!expected_size)
             {
                 TRACE("Expected at least %Iu bytes, but buffer only contains %lu bytes.\n",
-                      max(ctx->header_size + 1, record_size), buffer->cbBuffer);
+                      max(ctx->header_size, record_size), buffer->cbBuffer);
+                fill_missing_sec_buffer(pInput, record_size - buffer->cbBuffer);
                 return SEC_E_INCOMPLETE_MESSAGE;
             }
 
diff --git a/dlls/secur32/tests/schannel.c b/dlls/secur32/tests/schannel.c
index c68474e9eae..8322b5a80a5 100644
--- a/dlls/secur32/tests/schannel.c
+++ b/dlls/secur32/tests/schannel.c
@@ -1132,8 +1132,10 @@ static void test_communication(void)
     ok( context2.dwLower == 0xdeadbeef, "Did not expect dwLower to be set on new context\n");
     ok( context2.dwUpper == 0xdeadbeef, "Did not expect dwUpper to be set on new context\n");
 
-    buffers[1].cBuffers = 1;
+    buffers[1].cBuffers = 2;
     buffers[1].pBuffers[0].cbBuffer = 0;
+    buffers[1].pBuffers[1].cbBuffer = 0;
+    buffers[1].pBuffers[1].BufferType = SECBUFFER_EMPTY;
 
     status = InitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
@@ -1141,6 +1143,10 @@ static void test_communication(void)
     ok(status == SEC_E_INCOMPLETE_MESSAGE, "Got unexpected status %#lx.\n", status);
     ok(buffers[0].pBuffers[0].cbBuffer == buf_size, "Output buffer size changed.\n");
     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_TOKEN, "Output buffer type changed.\n");
+    ok(buffers[1].pBuffers[1].cbBuffer == 5 ||
+       broken(buffers[1].pBuffers[1].cbBuffer == 0), /* < win10 */ "Wrong buffer size.\n");
+    ok(buffers[1].pBuffers[1].BufferType == SECBUFFER_MISSING ||
+       broken(buffers[1].pBuffers[1].BufferType == SECBUFFER_EMPTY), /* < win10 */ "Wrong buffer type.\n");
 
     buf = &buffers[1].pBuffers[0];
     buf->cbBuffer = buf_size;
@@ -1149,6 +1155,8 @@ static void test_communication(void)
         return;
 
     buffers[1].pBuffers[0].cbBuffer = 4;
+    buffers[1].pBuffers[1].cbBuffer = 0;
+    buffers[1].pBuffers[1].BufferType = SECBUFFER_EMPTY;
     status = InitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
             0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
@@ -1156,9 +1164,15 @@ static void test_communication(void)
        "Got unexpected status %#lx.\n", status);
     ok(buffers[0].pBuffers[0].cbBuffer == buf_size, "Output buffer size changed.\n");
     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_TOKEN, "Output buffer type changed.\n");
+    ok(buffers[1].pBuffers[1].cbBuffer == 1 ||
+       broken(buffers[1].pBuffers[1].cbBuffer == 0), /* < win10 */ "Wrong buffer size.\n");
+    ok(buffers[1].pBuffers[1].BufferType == SECBUFFER_MISSING ||
+       broken(buffers[1].pBuffers[1].BufferType == SECBUFFER_EMPTY), /* < win10 */ "Wrong buffer type.\n");
 
     context2.dwLower = context2.dwUpper = 0xdeadbeef;
     buffers[1].pBuffers[0].cbBuffer = 5;
+    buffers[1].pBuffers[1].cbBuffer = 0;
+    buffers[1].pBuffers[1].BufferType = SECBUFFER_EMPTY;
     status = InitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
             0, 0, &buffers[1], 0, &context2, &buffers[0], &attrs, NULL);
@@ -1166,9 +1180,14 @@ static void test_communication(void)
        "Got unexpected status %#lx.\n", status);
     ok(buffers[0].pBuffers[0].cbBuffer == buf_size, "Output buffer size changed.\n");
     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_TOKEN, "Output buffer type changed.\n");
+    ok(buffers[1].pBuffers[1].cbBuffer > 5 ||
+       broken(buffers[1].pBuffers[1].cbBuffer == 0), /* < win10 */ "Wrong buffer size\n" );
+    ok(buffers[1].pBuffers[1].BufferType == SECBUFFER_MISSING ||
+       broken(buffers[1].pBuffers[1].BufferType == SECBUFFER_EMPTY), /* < win10 */ "Wrong buffer type.\n");
     ok( context2.dwLower == 0xdeadbeef, "Did not expect dwLower to be set on new context\n");
     ok( context2.dwUpper == 0xdeadbeef, "Did not expect dwUpper to be set on new context\n");
 
+    buffers[1].cBuffers = 1;
     buffers[1].pBuffers[0].cbBuffer = ret;
     status = InitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM|ISC_REQ_USE_SUPPLIED_CREDS,
-- 
GitLab

https://gitlab.winehq.org/wine/wine/-/merge_requests/342



More information about the wine-devel mailing list