Signed-off-by: Paul Gofman pgofman@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;