Module: wine Branch: master Commit: 1cf48b46845c1364e5d032924a700f372f7b0628 URL: https://source.winehq.org/git/wine.git/?a=commit;h=1cf48b46845c1364e5d032924...
Author: Alexandre Julliard julliard@winehq.org Date: Fri Dec 3 18:24:24 2021 +0100
secur32: Pre-allocate the token buffer for handshake() on the PE side.
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/secur32/schannel.c | 17 ++++++++++++++++- dlls/secur32/schannel_gnutls.c | 41 +++++++---------------------------------- dlls/secur32/secur32_priv.h | 4 ++-- 3 files changed, 25 insertions(+), 37 deletions(-)
diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c index 432c35cdfde..14645080f38 100644 --- a/dlls/secur32/schannel.c +++ b/dlls/secur32/schannel.c @@ -689,12 +689,14 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry) { + const ULONG extra_size = 0x10000; struct schan_context *ctx; struct schan_buffers *out_buffers; struct schan_credentials *cred; SIZE_T expected_size = ~0UL; SECURITY_STATUS ret; SecBuffer *buffer; + SecBuffer alloc_buffer = { 0 }; int idx;
TRACE("%p %p %s 0x%08x %d %d %p %d %p %p %p %p\n", phCredential, phContext, @@ -814,19 +816,32 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( ctx->req_ctx_attr = fContextReq;
/* Perform the TLS handshake */ - ret = schan_funcs->handshake(ctx->transport.session, pInput, expected_size, pOutput, fContextReq); + if (fContextReq & ISC_REQ_ALLOCATE_MEMORY) + { + alloc_buffer.cbBuffer = extra_size; + alloc_buffer.BufferType = SECBUFFER_TOKEN; + alloc_buffer.pvBuffer = RtlAllocateHeap( GetProcessHeap(), 0, extra_size ); + } + ret = schan_funcs->handshake(ctx->transport.session, pInput, expected_size, pOutput, &alloc_buffer);
out_buffers = &ctx->transport.out; if (out_buffers->current_buffer_idx != -1) { SecBuffer *buffer = &out_buffers->desc->pBuffers[out_buffers->current_buffer_idx]; buffer->cbBuffer = out_buffers->offset; + if (buffer->pvBuffer == alloc_buffer.pvBuffer) + { + RtlReAllocateHeap( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, + buffer->pvBuffer, buffer->cbBuffer ); + alloc_buffer.pvBuffer = NULL; + } } else if (out_buffers->desc && out_buffers->desc->cBuffers > 0) { SecBuffer *buffer = &out_buffers->desc->pBuffers[0]; buffer->cbBuffer = 0; } + RtlFreeHeap( GetProcessHeap(), 0, alloc_buffer.pvBuffer );
if(ctx->transport.in.offset && ctx->transport.in.offset != pInput->pBuffers[0].cbBuffer) { if(pInput->cBuffers<2 || pInput->pBuffers[1].BufferType!=SECBUFFER_EMPTY) diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c index e4da13c9b3e..d832c353fcd 100644 --- a/dlls/secur32/schannel_gnutls.c +++ b/dlls/secur32/schannel_gnutls.c @@ -204,7 +204,7 @@ static void init_schan_buffers(struct schan_buffers *s, const PSecBufferDesc des s->limit = ~0UL; s->desc = desc; s->current_buffer_idx = -1; - s->allow_buffer_resize = FALSE; + s->alloc_buffer = NULL; s->get_next_buffer = get_next_buffer; }
@@ -240,10 +240,9 @@ static int handshake_get_next_buffer_alloc(const struct schan_transport *t, stru idx = schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_EMPTY); if (idx != -1) s->desc->pBuffers[idx].BufferType = SECBUFFER_TOKEN; } - if (idx != -1 && !s->desc->pBuffers[idx].pvBuffer) + if (idx != -1 && !s->desc->pBuffers[idx].pvBuffer && s->alloc_buffer) { - s->desc->pBuffers[idx].cbBuffer = 0; - s->allow_buffer_resize = TRUE; + s->desc->pBuffers[idx] = *s->alloc_buffer; } return idx; } @@ -302,31 +301,6 @@ static int recv_message_get_next_buffer(const struct schan_transport *t, struct return schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_DATA); }
-static void resize_current_buffer(const struct schan_buffers *s, SIZE_T min_size) -{ - SecBuffer *b = &s->desc->pBuffers[s->current_buffer_idx]; - SIZE_T new_size = b->cbBuffer ? b->cbBuffer * 2 : 128; - void *new_data; - - if (b->cbBuffer >= min_size || !s->allow_buffer_resize || min_size > UINT_MAX / 2) return; - - while (new_size < min_size) new_size *= 2; - - if (b->pvBuffer) /* freed with FreeContextBuffer */ - new_data = RtlReAllocateHeap(GetProcessHeap(), 0, b->pvBuffer, new_size); - else - new_data = RtlAllocateHeap(GetProcessHeap(), 0, new_size); - - if (!new_data) - { - TRACE("Failed to resize %p from %d to %ld\n", b->pvBuffer, b->cbBuffer, new_size); - return; - } - - b->cbBuffer = new_size; - b->pvBuffer = new_data; -} - static char *get_buffer(const struct schan_transport *t, struct schan_buffers *s, SIZE_T *count) { SIZE_T max_count; @@ -353,7 +327,6 @@ static char *get_buffer(const struct schan_transport *t, struct schan_buffers *s buffer = &s->desc->pBuffers[s->current_buffer_idx]; TRACE("Using buffer %d: cbBuffer %d, BufferType %#x, pvBuffer %p\n", s->current_buffer_idx, buffer->cbBuffer, buffer->BufferType, buffer->pvBuffer);
- resize_current_buffer(s, s->offset + *count); max_count = buffer->cbBuffer - s->offset; if (s->limit != ~0UL && s->limit < max_count) max_count = s->limit; @@ -362,7 +335,6 @@ static char *get_buffer(const struct schan_transport *t, struct schan_buffers *s { int buffer_idx;
- s->allow_buffer_resize = FALSE; buffer_idx = s->get_next_buffer(t, s); if (buffer_idx == -1) { @@ -580,7 +552,8 @@ static void CDECL schan_set_session_target(schan_session session, const char *ta }
static SECURITY_STATUS CDECL schan_handshake(schan_session session, SecBufferDesc *input, - SIZE_T input_size, SecBufferDesc *output, ULONG flags ) + SIZE_T input_size, SecBufferDesc *output, + SecBuffer *alloc_buffer ) { gnutls_session_t s = (gnutls_session_t)session; struct schan_transport *t = (struct schan_transport *)pgnutls_transport_get_ptr(s); @@ -588,8 +561,8 @@ static SECURITY_STATUS CDECL schan_handshake(schan_session session, SecBufferDes
init_schan_buffers(&t->in, input, handshake_get_next_buffer); t->in.limit = input_size; - init_schan_buffers(&t->out, output, (flags & ISC_REQ_ALLOCATE_MEMORY) ? - handshake_get_next_buffer_alloc : handshake_get_next_buffer ); + init_schan_buffers(&t->out, output, handshake_get_next_buffer_alloc ); + t->out.alloc_buffer = alloc_buffer;
while(1) { err = pgnutls_handshake(s); diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h index 9970c0847e3..6bfa1ff7a26 100644 --- a/dlls/secur32/secur32_priv.h +++ b/dlls/secur32/secur32_priv.h @@ -95,8 +95,8 @@ struct schan_buffers SIZE_T offset; SIZE_T limit; const SecBufferDesc *desc; + SecBuffer *alloc_buffer; int current_buffer_idx; - BOOL allow_buffer_resize; int (*get_next_buffer)(const struct schan_transport *, struct schan_buffers *); };
@@ -122,7 +122,7 @@ struct schan_funcs unsigned int (CDECL *get_session_cipher_block_size)(schan_session); SECURITY_STATUS (CDECL *get_session_peer_certificate)(schan_session, CERT_BLOB *, ULONG *, ULONG *); SECURITY_STATUS (CDECL *get_unique_channel_binding)(schan_session, void *, ULONG *); - SECURITY_STATUS (CDECL *handshake)(schan_session, SecBufferDesc *, SIZE_T, SecBufferDesc *, ULONG ); + SECURITY_STATUS (CDECL *handshake)(schan_session, SecBufferDesc *, SIZE_T, SecBufferDesc *, SecBuffer * ); SECURITY_STATUS (CDECL *recv)(schan_session, SecBufferDesc *, SIZE_T, void *, SIZE_T *); SECURITY_STATUS (CDECL *send)(schan_session, SecBufferDesc *, const void *, SIZE_T *); void (CDECL *set_application_protocols)(schan_session, unsigned char *, unsigned int);