Hans Leidekker : wininet: Always store the SSL context.

Alexandre Julliard julliard at winehq.org
Wed Dec 11 13:05:46 CST 2013


Module: wine
Branch: master
Commit: 7ba776532d73a180130a33aee46e6182b535ce8e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=7ba776532d73a180130a33aee46e6182b535ce8e

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Wed Dec 11 10:49:34 2013 +0100

wininet: Always store the SSL context.

This allows applications to query certificate properties when verification has failed.

---

 dlls/wininet/netconnection.c |   18 ++++++++----------
 dlls/wininet/tests/http.c    |   25 +++++++++++++++++++++++++
 2 files changed, 33 insertions(+), 10 deletions(-)

diff --git a/dlls/wininet/netconnection.c b/dlls/wininet/netconnection.c
index c90ef69..86c9b08 100644
--- a/dlls/wininet/netconnection.c
+++ b/dlls/wininet/netconnection.c
@@ -369,6 +369,7 @@ DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, BOOL m
     netconn->security_flags = security_flags | server->security_flags;
     netconn->mask_errors = mask_errors;
     list_init(&netconn->pool_entry);
+    SecInvalidateHandle(&netconn->ssl_ctx);
 
     result = create_netconn_socket(server, netconn, timeout);
     if (result != ERROR_SUCCESS) {
@@ -407,7 +408,8 @@ void free_netconn(netconn_t *netconn)
         heap_free(netconn->extra_buf);
         netconn->extra_buf = NULL;
         netconn->extra_len = 0;
-        DeleteSecurityContext(&netconn->ssl_ctx);
+        if (SecIsValidHandle(&netconn->ssl_ctx))
+            DeleteSecurityContext(&netconn->ssl_ctx);
     }
 
     heap_free(netconn);
@@ -586,6 +588,10 @@ static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode
         TRACE("InitializeSecurityContext ret %08x\n", status);
 
         if(status == SEC_E_OK) {
+            if(SecIsValidHandle(&connection->ssl_ctx))
+                DeleteSecurityContext(&connection->ssl_ctx);
+            connection->ssl_ctx = ctx;
+
             if(in_bufs[1].BufferType == SECBUFFER_EXTRA)
                 FIXME("SECBUFFER_EXTRA not supported\n");
 
@@ -617,19 +623,14 @@ static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode
         }
     }
 
-
     if(status != SEC_E_OK || res != ERROR_SUCCESS) {
-        WARN("Failed to initialize security context failed: %08x\n", status);
+        WARN("Failed to establish SSL connection: %08x (%u)\n", status, res);
         heap_free(connection->ssl_buf);
         connection->ssl_buf = NULL;
-        DeleteSecurityContext(&ctx);
         return res ? res : ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
     }
 
-
     TRACE("established SSL connection\n");
-    connection->ssl_ctx = ctx;
-
     connection->secure = TRUE;
     connection->security_flags |= SECURITY_FLAG_SECURE;
 
@@ -963,9 +964,6 @@ LPCVOID NETCON_GetCert(netconn_t *connection)
     const CERT_CONTEXT *ret;
     SECURITY_STATUS res;
 
-    if (!connection->secure)
-        return NULL;
-
     res = QueryContextAttributesW(&connection->ssl_ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&ret);
     return res == SEC_E_OK ? ret : NULL;
 }
diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c
index eb09bc7..951460f 100644
--- a/dlls/wininet/tests/http.c
+++ b/dlls/wininet/tests/http.c
@@ -4137,6 +4137,7 @@ static void _set_secflags(unsigned line, HINTERNET req, BOOL use_undoc, DWORD fl
 
 static void test_security_flags(void)
 {
+    INTERNET_CERTIFICATE_INFOA *cert;
     HINTERNET ses, conn, req;
     DWORD size, flags;
     char buf[100];
@@ -4259,6 +4260,30 @@ static void test_security_flags(void)
     ok(req_error == ERROR_INTERNET_SEC_CERT_REV_FAILED || broken(req_error == ERROR_INTERNET_SEC_CERT_ERRORS),
        "req_error = %d\n", req_error);
 
+    size = 0;
+    res = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT, NULL, &size);
+    ok(res || GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InternetQueryOption failed: %d\n", GetLastError());
+    ok(size == sizeof(INTERNET_CERTIFICATE_INFOA), "size = %u\n", size);
+    cert = HeapAlloc(GetProcessHeap(), 0, size);
+    cert->lpszSubjectInfo = NULL;
+    cert->lpszIssuerInfo = NULL;
+    cert->lpszSignatureAlgName = (char *)0xdeadbeef;
+    cert->lpszEncryptionAlgName = (char *)0xdeadbeef;
+    cert->lpszProtocolName = (char *)0xdeadbeef;
+    cert->dwKeySize = 0xdeadbeef;
+    res = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT, cert, &size);
+    ok(res, "InternetQueryOption failed: %u\n", GetLastError());
+    if (res)
+    {
+        ok(cert->lpszSubjectInfo && strlen(cert->lpszSubjectInfo) > 1, "expected a non-empty subject name\n");
+        ok(cert->lpszIssuerInfo && strlen(cert->lpszIssuerInfo) > 1, "expected a non-empty issuer name\n");
+        ok(!cert->lpszSignatureAlgName, "unexpected signature algorithm name\n");
+        ok(!cert->lpszEncryptionAlgName, "unexpected encryption algorithm name\n");
+        ok(!cert->lpszProtocolName, "unexpected protocol name\n");
+        ok(cert->dwKeySize != 0xdeadbeef, "unexpected key size\n");
+    }
+    HeapFree(GetProcessHeap(), 0, cert);
+
     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
     CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);




More information about the wine-cvs mailing list