secur32: Fix race between schan_(Encrypt|Decrypt)Message.
Signed-off-by: Anton Romanov <theli.ua@gmail.com> Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
3864851feb
commit
3c40ffbfad
|
@ -57,6 +57,7 @@ struct schan_handle
|
||||||
struct schan_context
|
struct schan_context
|
||||||
{
|
{
|
||||||
schan_imp_session session;
|
schan_imp_session session;
|
||||||
|
struct schan_transport transport;
|
||||||
ULONG req_ctx_attr;
|
ULONG req_ctx_attr;
|
||||||
const CERT_CONTEXT *cert;
|
const CERT_CONTEXT *cert;
|
||||||
};
|
};
|
||||||
|
@ -789,7 +790,6 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
|
||||||
struct schan_context *ctx;
|
struct schan_context *ctx;
|
||||||
struct schan_buffers *out_buffers;
|
struct schan_buffers *out_buffers;
|
||||||
struct schan_credentials *cred;
|
struct schan_credentials *cred;
|
||||||
struct schan_transport transport;
|
|
||||||
SIZE_T expected_size = ~0UL;
|
SIZE_T expected_size = ~0UL;
|
||||||
SECURITY_STATUS ret;
|
SECURITY_STATUS ret;
|
||||||
|
|
||||||
|
@ -833,6 +833,9 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
|
||||||
return SEC_E_INTERNAL_ERROR;
|
return SEC_E_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx->transport.ctx = ctx;
|
||||||
|
schan_imp_set_session_transport(ctx->session, &ctx->transport);
|
||||||
|
|
||||||
if (pszTargetName && *pszTargetName)
|
if (pszTargetName && *pszTargetName)
|
||||||
{
|
{
|
||||||
UINT len = WideCharToMultiByte( CP_UNIXCP, 0, pszTargetName, -1, NULL, 0, NULL, NULL );
|
UINT len = WideCharToMultiByte( CP_UNIXCP, 0, pszTargetName, -1, NULL, 0, NULL, NULL );
|
||||||
|
@ -891,24 +894,22 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
|
||||||
|
|
||||||
ctx->req_ctx_attr = fContextReq;
|
ctx->req_ctx_attr = fContextReq;
|
||||||
|
|
||||||
transport.ctx = ctx;
|
init_schan_buffers(&ctx->transport.in, pInput, schan_init_sec_ctx_get_next_input_buffer);
|
||||||
init_schan_buffers(&transport.in, pInput, schan_init_sec_ctx_get_next_input_buffer);
|
ctx->transport.in.limit = expected_size;
|
||||||
transport.in.limit = expected_size;
|
init_schan_buffers(&ctx->transport.out, pOutput, schan_init_sec_ctx_get_next_output_buffer);
|
||||||
init_schan_buffers(&transport.out, pOutput, schan_init_sec_ctx_get_next_output_buffer);
|
|
||||||
schan_imp_set_session_transport(ctx->session, &transport);
|
|
||||||
|
|
||||||
/* Perform the TLS handshake */
|
/* Perform the TLS handshake */
|
||||||
ret = schan_imp_handshake(ctx->session);
|
ret = schan_imp_handshake(ctx->session);
|
||||||
|
|
||||||
if(transport.in.offset && transport.in.offset != pInput->pBuffers[0].cbBuffer) {
|
if(ctx->transport.in.offset && ctx->transport.in.offset != pInput->pBuffers[0].cbBuffer) {
|
||||||
if(pInput->cBuffers<2 || pInput->pBuffers[1].BufferType!=SECBUFFER_EMPTY)
|
if(pInput->cBuffers<2 || pInput->pBuffers[1].BufferType!=SECBUFFER_EMPTY)
|
||||||
return SEC_E_INVALID_TOKEN;
|
return SEC_E_INVALID_TOKEN;
|
||||||
|
|
||||||
pInput->pBuffers[1].BufferType = SECBUFFER_EXTRA;
|
pInput->pBuffers[1].BufferType = SECBUFFER_EXTRA;
|
||||||
pInput->pBuffers[1].cbBuffer = pInput->pBuffers[0].cbBuffer-transport.in.offset;
|
pInput->pBuffers[1].cbBuffer = pInput->pBuffers[0].cbBuffer-ctx->transport.in.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
out_buffers = &transport.out;
|
out_buffers = &ctx->transport.out;
|
||||||
if (out_buffers->current_buffer_idx != -1)
|
if (out_buffers->current_buffer_idx != -1)
|
||||||
{
|
{
|
||||||
SecBuffer *buffer = &out_buffers->desc->pBuffers[out_buffers->current_buffer_idx];
|
SecBuffer *buffer = &out_buffers->desc->pBuffers[out_buffers->current_buffer_idx];
|
||||||
|
@ -1205,7 +1206,6 @@ static int schan_encrypt_message_get_next_buffer_token(const struct schan_transp
|
||||||
static SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle,
|
static SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle,
|
||||||
ULONG quality, PSecBufferDesc message, ULONG message_seq_no)
|
ULONG quality, PSecBufferDesc message, ULONG message_seq_no)
|
||||||
{
|
{
|
||||||
struct schan_transport transport;
|
|
||||||
struct schan_context *ctx;
|
struct schan_context *ctx;
|
||||||
struct schan_buffers *b;
|
struct schan_buffers *b;
|
||||||
SECURITY_STATUS status;
|
SECURITY_STATUS status;
|
||||||
|
@ -1235,13 +1235,10 @@ static SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle
|
||||||
data = HeapAlloc(GetProcessHeap(), 0, data_size);
|
data = HeapAlloc(GetProcessHeap(), 0, data_size);
|
||||||
memcpy(data, buffer->pvBuffer, data_size);
|
memcpy(data, buffer->pvBuffer, data_size);
|
||||||
|
|
||||||
transport.ctx = ctx;
|
|
||||||
init_schan_buffers(&transport.in, NULL, NULL);
|
|
||||||
if (schan_find_sec_buffer_idx(message, 0, SECBUFFER_STREAM_HEADER) != -1)
|
if (schan_find_sec_buffer_idx(message, 0, SECBUFFER_STREAM_HEADER) != -1)
|
||||||
init_schan_buffers(&transport.out, message, schan_encrypt_message_get_next_buffer);
|
init_schan_buffers(&ctx->transport.out, message, schan_encrypt_message_get_next_buffer);
|
||||||
else
|
else
|
||||||
init_schan_buffers(&transport.out, message, schan_encrypt_message_get_next_buffer_token);
|
init_schan_buffers(&ctx->transport.out, message, schan_encrypt_message_get_next_buffer_token);
|
||||||
schan_imp_set_session_transport(ctx->session, &transport);
|
|
||||||
|
|
||||||
length = data_size;
|
length = data_size;
|
||||||
status = schan_imp_send(ctx->session, data, &length);
|
status = schan_imp_send(ctx->session, data, &length);
|
||||||
|
@ -1251,7 +1248,7 @@ static SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle
|
||||||
if (length != data_size)
|
if (length != data_size)
|
||||||
status = SEC_E_INTERNAL_ERROR;
|
status = SEC_E_INTERNAL_ERROR;
|
||||||
|
|
||||||
b = &transport.out;
|
b = &ctx->transport.out;
|
||||||
b->desc->pBuffers[b->current_buffer_idx].cbBuffer = b->offset;
|
b->desc->pBuffers[b->current_buffer_idx].cbBuffer = b->offset;
|
||||||
HeapFree(GetProcessHeap(), 0, data);
|
HeapFree(GetProcessHeap(), 0, data);
|
||||||
|
|
||||||
|
@ -1327,7 +1324,6 @@ static void schan_decrypt_fill_buffer(PSecBufferDesc message, ULONG buffer_type,
|
||||||
static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle,
|
static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle,
|
||||||
PSecBufferDesc message, ULONG message_seq_no, PULONG quality)
|
PSecBufferDesc message, ULONG message_seq_no, PULONG quality)
|
||||||
{
|
{
|
||||||
struct schan_transport transport;
|
|
||||||
struct schan_context *ctx;
|
struct schan_context *ctx;
|
||||||
SecBuffer *buffer;
|
SecBuffer *buffer;
|
||||||
SIZE_T data_size;
|
SIZE_T data_size;
|
||||||
|
@ -1371,11 +1367,8 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle
|
||||||
data_size = expected_size - 5;
|
data_size = expected_size - 5;
|
||||||
data = HeapAlloc(GetProcessHeap(), 0, data_size);
|
data = HeapAlloc(GetProcessHeap(), 0, data_size);
|
||||||
|
|
||||||
transport.ctx = ctx;
|
init_schan_buffers(&ctx->transport.in, message, schan_decrypt_message_get_next_buffer);
|
||||||
init_schan_buffers(&transport.in, message, schan_decrypt_message_get_next_buffer);
|
ctx->transport.in.limit = expected_size;
|
||||||
transport.in.limit = expected_size;
|
|
||||||
init_schan_buffers(&transport.out, NULL, NULL);
|
|
||||||
schan_imp_set_session_transport(ctx->session, &transport);
|
|
||||||
|
|
||||||
while (received < data_size)
|
while (received < data_size)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue