[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