[PATCH 1/5] winhttp: Move connect end checks out of the loop.

Rémi Bernon rbernon at codeweavers.com
Mon Feb 15 05:47:19 CST 2021


This is only done when InitializeSecurityContextW returns SEC_E_OK,
which will break out of the loop, and the checks forcefully break out
of the loop if any failed.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---

This implements TLS re-handshake properly, instead of incorrectly
returning a client certificate error. It happens with Gears Tactics
online server, although the game still succeeds eventually (as TLS
doesn't mandate for clients to reply to re-handshake requests).

These probably lack some tests, but I couldn't find a way to write
something that's working. I'm sending them anyway, at least for the
discussion, in case I missed something.

It would need an SSL server that asks for a re-handshake, but I think
Wine current implementation lacks some features to create the server
side of such test. I may be wrong though, and maybe I just failed to
figure how to write it?

 dlls/winhttp/net.c | 66 ++++++++++++++++++++++------------------------
 1 file changed, 32 insertions(+), 34 deletions(-)

diff --git a/dlls/winhttp/net.c b/dlls/winhttp/net.c
index 0cc2bb2bef7..46dc6bd21f0 100644
--- a/dlls/winhttp/net.c
+++ b/dlls/winhttp/net.c
@@ -341,53 +341,51 @@ DWORD netconn_secure_connect( struct netconn *conn, WCHAR *hostname, DWORD secur
         status = InitializeSecurityContextW(cred_handle, &ctx, hostname,  isc_req_flags, 0, 0, &in_desc,
                 0, NULL, &out_desc, &attrs, NULL);
         TRACE("InitializeSecurityContext ret %08x\n", status);
+        if(status == SEC_E_OK && in_bufs[1].BufferType == SECBUFFER_EXTRA)
+            FIXME("SECBUFFER_EXTRA not supported\n");
+    }
 
-        if(status == SEC_E_OK) {
-            if(in_bufs[1].BufferType == SECBUFFER_EXTRA)
-                FIXME("SECBUFFER_EXTRA not supported\n");
-
-            status = QueryContextAttributesW(&ctx, SECPKG_ATTR_STREAM_SIZES, &conn->ssl_sizes);
-            if(status != SEC_E_OK) {
-                WARN("Could not get sizes\n");
-                break;
-            }
+    heap_free(read_buf);
 
-            status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
-            if(status == SEC_E_OK) {
-                res = netconn_verify_cert(cert, hostname, security_flags, check_revocation);
-                CertFreeCertificateContext(cert);
-                if(res != ERROR_SUCCESS) {
-                    WARN("cert verify failed: %u\n", res);
-                    break;
-                }
-            }else {
-                WARN("Could not get cert\n");
-                break;
-            }
+    if(status != SEC_E_OK)
+        goto failed;
 
-            conn->ssl_buf = heap_alloc(conn->ssl_sizes.cbHeader + conn->ssl_sizes.cbMaximumMessage + conn->ssl_sizes.cbTrailer);
-            if(!conn->ssl_buf) {
-                res = ERROR_OUTOFMEMORY;
-                break;
-            }
-        }
+    status = QueryContextAttributesW(&ctx, SECPKG_ATTR_STREAM_SIZES, &conn->ssl_sizes);
+    if(status != SEC_E_OK) {
+        WARN("Could not get sizes\n");
+        goto failed;
     }
 
-    heap_free(read_buf);
+    status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
+    if(status != SEC_E_OK) {
+        WARN("Could not get cert\n");
+        goto failed;
+    }
 
-    if(status != SEC_E_OK || res != ERROR_SUCCESS) {
-        WARN("Failed to initialize security context: %08x\n", status);
-        heap_free(conn->ssl_buf);
-        conn->ssl_buf = NULL;
-        DeleteSecurityContext(&ctx);
-        return ERROR_WINHTTP_SECURE_CHANNEL_ERROR;
+    res = netconn_verify_cert(cert, hostname, security_flags, check_revocation);
+    CertFreeCertificateContext(cert);
+    if(res != ERROR_SUCCESS) {
+        WARN("cert verify failed: %u\n", res);
+        goto failed;
     }
 
+    conn->ssl_buf = heap_alloc(conn->ssl_sizes.cbHeader + conn->ssl_sizes.cbMaximumMessage + conn->ssl_sizes.cbTrailer);
+    if(!conn->ssl_buf) {
+        res = ERROR_OUTOFMEMORY;
+        goto failed;
+    }
 
     TRACE("established SSL connection\n");
     conn->secure = TRUE;
     conn->ssl_ctx = ctx;
     return ERROR_SUCCESS;
+
+failed:
+    WARN("Failed to initialize security context: %08x\n", status);
+    heap_free(conn->ssl_buf);
+    conn->ssl_buf = NULL;
+    DeleteSecurityContext(&ctx);
+    return ERROR_WINHTTP_SECURE_CHANNEL_ERROR;
 }
 
 static DWORD send_ssl_chunk( struct netconn *conn, const void *msg, size_t size )
-- 
2.30.0




More information about the wine-devel mailing list