[PATCH 7/8] secur32: Properly handle NULL pInput argument for DTLS contexts in schan_InitializeSecurityContextW.
Connor McAdams
cmcadams at codeweavers.com
Tue Jan 25 09:32:13 CST 2022
When a NULL pInput argument is passed into InitializeSecurityContextW
for an existing DTLS context, we need to retransmit the last handshake
packet.
Signed-off-by: Connor McAdams <cmcadams at codeweavers.com>
---
dlls/secur32/schannel.c | 41 +++++++++++++++++++---------------
dlls/secur32/schannel_gnutls.c | 2 +-
dlls/secur32/tests/schannel.c | 12 +++++-----
3 files changed, 30 insertions(+), 25 deletions(-)
diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c
index 2c328b96ce4..72be32a2478 100644
--- a/dlls/secur32/schannel.c
+++ b/dlls/secur32/schannel.c
@@ -813,6 +813,7 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
{
struct set_dtls_timeouts_params params = { ctx->transport.session, 0, 60000 };
GNUTLS_CALL( set_dtls_timeouts, ¶ms );
+ expected_size = 0;
}
phNewContext->dwLower = handle;
@@ -824,30 +825,34 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
unsigned char *ptr;
if (!(ctx = schan_get_object(phContext->dwLower, SCHAN_HANDLE_CTX))) return SEC_E_INVALID_HANDLE;
- if (!pInput) return is_dtls_context(ctx) ? SEC_E_INSUFFICIENT_MEMORY : SEC_E_INCOMPLETE_MESSAGE;
- if ((idx = schan_find_sec_buffer_idx(pInput, 0, SECBUFFER_TOKEN)) == -1) return SEC_E_INCOMPLETE_MESSAGE;
-
- buffer = &pInput->pBuffers[idx];
- ptr = buffer->pvBuffer;
+ if (!pInput && !is_dtls_context(ctx)) return SEC_E_INCOMPLETE_MESSAGE;
expected_size = 0;
- while (buffer->cbBuffer > expected_size + ctx->header_size)
+ if (pInput)
{
- record_size = ctx->header_size + read_record_size(ptr, ctx->header_size);
+ if ((idx = schan_find_sec_buffer_idx(pInput, 0, SECBUFFER_TOKEN)) == -1) return SEC_E_INCOMPLETE_MESSAGE;
- if (buffer->cbBuffer < expected_size + record_size) break;
- expected_size += record_size;
- ptr += record_size;
- }
+ buffer = &pInput->pBuffers[idx];
+ ptr = buffer->pvBuffer;
- if (!expected_size)
- {
- TRACE("Expected at least %lu bytes, but buffer only contains %u bytes.\n",
- max(ctx->header_size + 1, record_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);
- TRACE("Using expected_size %lu.\n", expected_size);
+ if (buffer->cbBuffer < expected_size + record_size) break;
+ expected_size += record_size;
+ ptr += record_size;
+ }
+
+ if (!expected_size)
+ {
+ TRACE("Expected at least %lu bytes, but buffer only contains %u bytes.\n",
+ max(ctx->header_size + 1, record_size), buffer->cbBuffer);
+ return SEC_E_INCOMPLETE_MESSAGE;
+ }
+
+ TRACE("Using expected_size %lu.\n", expected_size);
+ }
if (phNewContext) *phNewContext = *phContext;
}
diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c
index ac51cbb5d9f..0bf1337e803 100644
--- a/dlls/secur32/schannel_gnutls.c
+++ b/dlls/secur32/schannel_gnutls.c
@@ -466,7 +466,7 @@ static int pull_timeout(gnutls_transport_ptr_t transport, unsigned int timeout)
TRACE("\n");
- if (get_buffer(t, &t->in, &count)) return 1;
+ if (!t->in.limit || get_buffer(t, &t->in, &count)) return 1;
pgnutls_transport_set_errno(s, EAGAIN);
return -1;
}
diff --git a/dlls/secur32/tests/schannel.c b/dlls/secur32/tests/schannel.c
index 6fbe0c34bd1..902a490a296 100644
--- a/dlls/secur32/tests/schannel.c
+++ b/dlls/secur32/tests/schannel.c
@@ -1693,20 +1693,20 @@ static void test_dtls(void)
ctx_handle2.dwLower = ctx_handle2.dwUpper = 0xdeadbeef;
status = InitializeSecurityContextA( &cred_handle, &ctx_handle, (SEC_CHAR *)"winetest", flags_req, 0, 16, NULL, 0,
&ctx_handle2, &buffers[1], &attr, &exp );
- todo_wine ok( status == SEC_I_CONTINUE_NEEDED, "got %08x\n", status );
+ ok( status == SEC_I_CONTINUE_NEEDED, "got %08x\n", status );
flags_ret = ISC_RET_MANUAL_CRED_VALIDATION | ISC_RET_STREAM | ISC_RET_EXTENDED_ERROR | ISC_RET_DATAGRAM |
ISC_RET_USED_SUPPLIED_CREDS | ISC_RET_CONFIDENTIALITY | ISC_RET_SEQUENCE_DETECT | ISC_RET_REPLAY_DETECT;
- todo_wine ok( attr == flags_ret, "got %08x\n", attr );
+ ok( attr == flags_ret, "got %08x\n", attr );
todo_wine ok( exp.LowPart, "got %08x\n", exp.LowPart );
todo_wine ok( exp.HighPart, "got %08x\n", exp.HighPart );
ok( buffers[1].pBuffers[1].BufferType == SECBUFFER_ALERT, "Expected buffertype SECBUFFER_ALERT, got %#x\n", buffers[1].pBuffers[1].BufferType);
- todo_wine ok( !buffers[1].pBuffers[1].cbBuffer, "Expected SECBUFFER_ALERT buffer to be empty, got %#x\n", buffers[1].pBuffers[1].cbBuffer);
- todo_wine ok( ctx_handle.dwLower == ctx_handle2.dwLower, "dwLower mismatch, expected %#lx, got %#lx\n", ctx_handle.dwLower, ctx_handle2.dwLower);
- todo_wine ok( ctx_handle.dwUpper == ctx_handle2.dwUpper, "dwUpper mismatch, expected %#lx, got %#lx\n", ctx_handle.dwUpper, ctx_handle2.dwUpper);
+ ok( !buffers[1].pBuffers[1].cbBuffer, "Expected SECBUFFER_ALERT buffer to be empty, got %#x\n", buffers[1].pBuffers[1].cbBuffer);
+ ok( ctx_handle.dwLower == ctx_handle2.dwLower, "dwLower mismatch, expected %#lx, got %#lx\n", ctx_handle.dwLower, ctx_handle2.dwLower);
+ ok( ctx_handle.dwUpper == ctx_handle2.dwUpper, "dwUpper mismatch, expected %#lx, got %#lx\n", ctx_handle.dwUpper, ctx_handle2.dwUpper);
/* With no new input buffer, output buffer length should match prior call. */
- todo_wine ok(buffers[1].pBuffers[0].cbBuffer == prev_buf_len, "Output buffer size mismatch, expected %#x, got %#x\n",
+ ok(buffers[1].pBuffers[0].cbBuffer == prev_buf_len, "Output buffer size mismatch, expected %#x, got %#x\n",
prev_buf_len, buffers[1].pBuffers[0].cbBuffer);
free_buffers( &buffers[0] );
--
2.25.1
More information about the wine-devel
mailing list