[PATCH 2/5] winhttp: Use separate SSL read and write buffers.
Paul Gofman
pgofman at codeweavers.com
Thu Jan 20 09:35:31 CST 2022
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
Websockets are full duplex and sends and receives already go to different queues.
Thus sends and receives may race on the SSL buffer.
dlls/winhttp/net.c | 34 +++++++++++++++++++++-------------
dlls/winhttp/winhttp_private.h | 2 +-
2 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/dlls/winhttp/net.c b/dlls/winhttp/net.c
index 3016608404a..68aee036734 100644
--- a/dlls/winhttp/net.c
+++ b/dlls/winhttp/net.c
@@ -250,7 +250,8 @@ void netconn_close( struct netconn *conn )
if (conn->secure)
{
free( conn->peek_msg_mem );
- free(conn->ssl_buf);
+ free(conn->ssl_read_buf);
+ free(conn->ssl_write_buf);
free(conn->extra_buf);
DeleteSecurityContext(&conn->ssl_ctx);
}
@@ -365,8 +366,13 @@ DWORD netconn_secure_connect( struct netconn *conn, WCHAR *hostname, DWORD secur
break;
}
- conn->ssl_buf = malloc(conn->ssl_sizes.cbHeader + conn->ssl_sizes.cbMaximumMessage + conn->ssl_sizes.cbTrailer);
- if(!conn->ssl_buf) {
+ conn->ssl_read_buf = malloc(conn->ssl_sizes.cbHeader + conn->ssl_sizes.cbMaximumMessage + conn->ssl_sizes.cbTrailer);
+ if(!conn->ssl_read_buf) {
+ res = ERROR_OUTOFMEMORY;
+ break;
+ }
+ conn->ssl_write_buf = malloc(conn->ssl_sizes.cbHeader + conn->ssl_sizes.cbMaximumMessage + conn->ssl_sizes.cbTrailer);
+ if(!conn->ssl_write_buf) {
res = ERROR_OUTOFMEMORY;
break;
}
@@ -377,8 +383,10 @@ DWORD netconn_secure_connect( struct netconn *conn, WCHAR *hostname, DWORD secur
if(status != SEC_E_OK || res != ERROR_SUCCESS) {
WARN("Failed to initialize security context: %08x\n", status);
- free(conn->ssl_buf);
- conn->ssl_buf = NULL;
+ free(conn->ssl_read_buf);
+ conn->ssl_read_buf = NULL;
+ free(conn->ssl_write_buf);
+ conn->ssl_write_buf = NULL;
DeleteSecurityContext(&ctx);
return ERROR_WINHTTP_SECURE_CHANNEL_ERROR;
}
@@ -393,9 +401,9 @@ DWORD netconn_secure_connect( struct netconn *conn, WCHAR *hostname, DWORD secur
static DWORD send_ssl_chunk( struct netconn *conn, const void *msg, size_t size )
{
SecBuffer bufs[4] = {
- {conn->ssl_sizes.cbHeader, SECBUFFER_STREAM_HEADER, conn->ssl_buf},
- {size, SECBUFFER_DATA, conn->ssl_buf+conn->ssl_sizes.cbHeader},
- {conn->ssl_sizes.cbTrailer, SECBUFFER_STREAM_TRAILER, conn->ssl_buf+conn->ssl_sizes.cbHeader+size},
+ {conn->ssl_sizes.cbHeader, SECBUFFER_STREAM_HEADER, conn->ssl_write_buf},
+ {size, SECBUFFER_DATA, conn->ssl_write_buf+conn->ssl_sizes.cbHeader},
+ {conn->ssl_sizes.cbTrailer, SECBUFFER_STREAM_TRAILER, conn->ssl_write_buf+conn->ssl_sizes.cbHeader+size},
{0, SECBUFFER_EMPTY, NULL}
};
SecBufferDesc buf_desc = {SECBUFFER_VERSION, ARRAY_SIZE(bufs), bufs};
@@ -408,7 +416,7 @@ static DWORD send_ssl_chunk( struct netconn *conn, const void *msg, size_t size
return res;
}
- if (sock_send( conn->socket, conn->ssl_buf, bufs[0].cbBuffer + bufs[1].cbBuffer + bufs[2].cbBuffer, 0 ) < 1)
+ if (sock_send( conn->socket, conn->ssl_write_buf, bufs[0].cbBuffer + bufs[1].cbBuffer + bufs[2].cbBuffer, 0 ) < 1)
{
WARN("send failed\n");
return WSAGetLastError();
@@ -456,13 +464,13 @@ static DWORD read_ssl_chunk( struct netconn *conn, void *buf, SIZE_T buf_size, S
assert(conn->extra_len < ssl_buf_size);
if(conn->extra_len) {
- memcpy(conn->ssl_buf, conn->extra_buf, conn->extra_len);
+ memcpy(conn->ssl_read_buf, conn->extra_buf, conn->extra_len);
buf_len = conn->extra_len;
conn->extra_len = 0;
free(conn->extra_buf);
conn->extra_buf = NULL;
}else {
- if ((buf_len = sock_recv( conn->socket, conn->ssl_buf + conn->extra_len, ssl_buf_size - conn->extra_len, 0)) < 0)
+ if ((buf_len = sock_recv( conn->socket, conn->ssl_read_buf + conn->extra_len, ssl_buf_size - conn->extra_len, 0)) < 0)
return WSAGetLastError();
if (!buf_len)
@@ -479,7 +487,7 @@ static DWORD read_ssl_chunk( struct netconn *conn, void *buf, SIZE_T buf_size, S
memset(bufs, 0, sizeof(bufs));
bufs[0].BufferType = SECBUFFER_DATA;
bufs[0].cbBuffer = buf_len;
- bufs[0].pvBuffer = conn->ssl_buf;
+ bufs[0].pvBuffer = conn->ssl_read_buf;
switch ((res = DecryptMessage( &conn->ssl_ctx, &buf_desc, 0, NULL )))
{
@@ -498,7 +506,7 @@ static DWORD read_ssl_chunk( struct netconn *conn, void *buf, SIZE_T buf_size, S
case SEC_E_INCOMPLETE_MESSAGE:
assert(buf_len < ssl_buf_size);
- if ((size = sock_recv( conn->socket, conn->ssl_buf + buf_len, ssl_buf_size - buf_len, 0 )) < 1)
+ if ((size = sock_recv( conn->socket, conn->ssl_read_buf + buf_len, ssl_buf_size - buf_len, 0 )) < 1)
return SEC_E_INCOMPLETE_MESSAGE;
buf_len += size;
diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h
index 291a38e7bdd..1538a61da6d 100644
--- a/dlls/winhttp/winhttp_private.h
+++ b/dlls/winhttp/winhttp_private.h
@@ -108,7 +108,7 @@ struct netconn
ULONGLONG keep_until;
CtxtHandle ssl_ctx;
SecPkgContext_StreamSizes ssl_sizes;
- char *ssl_buf;
+ char *ssl_read_buf, *ssl_write_buf;
char *extra_buf;
size_t extra_len;
char *peek_msg;
--
2.34.1
More information about the wine-devel
mailing list