Alexandre Julliard : secur32: Pre-allocate the token buffer for handshake() on the PE side.
Alexandre Julliard
julliard at winehq.org
Mon Dec 6 16:07:58 CST 2021
Module: wine
Branch: master
Commit: 1cf48b46845c1364e5d032924a700f372f7b0628
URL: https://source.winehq.org/git/wine.git/?a=commit;h=1cf48b46845c1364e5d032924a700f372f7b0628
Author: Alexandre Julliard <julliard at 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 at 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);
More information about the wine-cvs
mailing list