From 738a5b53a4b3140ef5025d070afbd267efc8edbc Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Wed, 6 Jul 2022 10:49:31 +0200 Subject: [PATCH] secur32: Validate input buffers in schan_InitializeSecurityContextW(). Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53309 --- dlls/secur32/schannel.c | 12 ++++++++++++ dlls/secur32/tests/schannel.c | 18 ++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c index 70018e57f7e..34cd3ad9730 100644 --- a/dlls/secur32/schannel.c +++ b/dlls/secur32/schannel.c @@ -759,6 +759,17 @@ static void fill_missing_sec_buffer(SecBufferDesc *input, DWORD size) } } +static BOOL validate_input_buffers(SecBufferDesc *desc) +{ + int i; + for (i = 0; i < desc->cBuffers; i++) + { + SecBuffer *buffer = &desc->pBuffers[i]; + if (buffer->BufferType == SECBUFFER_EMPTY && buffer->cbBuffer) return FALSE; + } + return TRUE; +} + /*********************************************************************** * InitializeSecurityContextW */ @@ -894,6 +905,7 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( if (pInput) { + if (!validate_input_buffers(pInput)) return SEC_E_INVALID_TOKEN; if ((idx = schan_find_sec_buffer_idx(pInput, 0, SECBUFFER_TOKEN)) == -1) return SEC_E_INCOMPLETE_MESSAGE; buffer = &pInput->pBuffers[idx]; diff --git a/dlls/secur32/tests/schannel.c b/dlls/secur32/tests/schannel.c index 8322b5a80a5..a531505648f 100644 --- a/dlls/secur32/tests/schannel.c +++ b/dlls/secur32/tests/schannel.c @@ -1157,11 +1157,11 @@ static void test_communication(void) buffers[1].pBuffers[0].cbBuffer = 4; buffers[1].pBuffers[1].cbBuffer = 0; buffers[1].pBuffers[1].BufferType = SECBUFFER_EMPTY; + buffers[1].pBuffers[1].cbBuffer = 0; status = InitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost", ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM, 0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL); - ok(status == SEC_E_INCOMPLETE_MESSAGE || status == SEC_E_INVALID_TOKEN, - "Got unexpected status %#lx.\n", status); + 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 == 1 || @@ -1173,11 +1173,11 @@ static void test_communication(void) buffers[1].pBuffers[0].cbBuffer = 5; buffers[1].pBuffers[1].cbBuffer = 0; buffers[1].pBuffers[1].BufferType = SECBUFFER_EMPTY; + buffers[1].pBuffers[1].cbBuffer = 0; status = InitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost", ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM, 0, 0, &buffers[1], 0, &context2, &buffers[0], &attrs, NULL); - ok(status == SEC_E_INCOMPLETE_MESSAGE || status == SEC_E_INVALID_TOKEN, - "Got unexpected status %#lx.\n", status); + 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 || @@ -1210,6 +1210,16 @@ static void test_communication(void) context2.dwLower = context2.dwUpper = 0xdeadbeef; buf->BufferType = SECBUFFER_TOKEN; + buffers[1].cBuffers = 2; + buffers[1].pBuffers[1].BufferType = SECBUFFER_EMPTY; + buffers[1].pBuffers[1].cbBuffer = 0xdeadbeef; + + status = InitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost", + ISC_REQ_USE_SUPPLIED_CREDS, + 0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL); + ok(status == SEC_E_INVALID_TOKEN, "Got unexpected status %#lx.\n", status); + + buffers[1].cBuffers = 1; status = InitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost", ISC_REQ_USE_SUPPLIED_CREDS, 0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);