[PATCH] winhttp: Implement WINHTTP_OPTION_CLIENT_CERT_CONTEXT.

Hans Leidekker hans at codeweavers.com
Tue Jan 29 04:40:53 CST 2019


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/winhttp/request.c         | 23 +++++++++++++----------
 dlls/winhttp/session.c         | 32 +++++++++++++++++++++++++++++---
 dlls/winhttp/winhttp_private.h |  5 +++--
 3 files changed, 45 insertions(+), 15 deletions(-)

diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index 5525c1c0bb..af484cccf8 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -1527,25 +1527,28 @@ static DWORD map_secure_protocols( DWORD mask )
     return ret;
 }
 
-static BOOL ensure_cred_handle( struct session *session )
+static BOOL ensure_cred_handle( struct request *request )
 {
     SECURITY_STATUS status = SEC_E_OK;
 
-    if (session->cred_handle_initialized) return TRUE;
+    if (request->cred_handle_initialized) return TRUE;
 
-    EnterCriticalSection( &session->cs );
-    if (!session->cred_handle_initialized)
+    if (!request->cred_handle_initialized)
     {
         SCHANNEL_CRED cred;
         memset( &cred, 0, sizeof(cred) );
         cred.dwVersion             = SCHANNEL_CRED_VERSION;
-        cred.grbitEnabledProtocols = map_secure_protocols( session->secure_protocols );
+        cred.grbitEnabledProtocols = map_secure_protocols( request->connect->session->secure_protocols );
+        if (request->client_cert)
+        {
+            cred.paCred = &request->client_cert;
+            cred.cCreds = 1;
+        }
         status = AcquireCredentialsHandleW( NULL, (WCHAR *)UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL,
-                                            &cred, NULL, NULL, &session->cred_handle, NULL );
+                                            &cred, NULL, NULL, &request->cred_handle, NULL );
         if (status == SEC_E_OK)
-            session->cred_handle_initialized = TRUE;
+            request->cred_handle_initialized = TRUE;
     }
-    LeaveCriticalSection( &session->cs );
 
     if (status != SEC_E_OK)
     {
@@ -1686,9 +1689,9 @@ static BOOL open_connection( struct request *request )
             CertFreeCertificateContext( request->server_cert );
             request->server_cert = NULL;
 
-            if (!ensure_cred_handle( connect->session ) ||
+            if (!ensure_cred_handle( request ) ||
                 !netconn_secure_connect( netconn, connect->hostname, request->security_flags,
-                                         &connect->session->cred_handle, request->check_revocation ))
+                                         &request->cred_handle, request->check_revocation ))
             {
                 heap_free( addressW );
                 netconn_close( netconn );
diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c
index 82615ad12f..64fa8bbc5f 100644
--- a/dlls/winhttp/session.c
+++ b/dlls/winhttp/session.c
@@ -81,7 +81,6 @@ static void session_destroy( struct object_header *hdr )
     TRACE("%p\n", session);
 
     if (session->unload_event) SetEvent( session->unload_event );
-    if (session->cred_handle_initialized) FreeCredentialsHandle( &session->cred_handle );
     destroy_cookies( session );
 
     session->cs.DebugInfo->Spare[0] = 0;
@@ -610,7 +609,9 @@ static void request_destroy( struct object_header *hdr )
     }
     release_object( &request->connect->hdr );
 
+    if (request->cred_handle_initialized) FreeCredentialsHandle( &request->cred_handle );
     CertFreeCertificateContext( request->server_cert );
+    CertFreeCertificateContext( request->client_cert );
 
     destroy_authinfo( request->authinfo );
     destroy_authinfo( request->proxy_authinfo );
@@ -1000,14 +1001,39 @@ static BOOL request_set_option( struct object_header *hdr, DWORD option, void *b
         return TRUE;
     }
     case WINHTTP_OPTION_CLIENT_CERT_CONTEXT:
+    {
+        const CERT_CONTEXT *cert;
+
         if (!(hdr->flags & WINHTTP_FLAG_SECURE))
         {
             SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_STATE );
             return FALSE;
         }
-        FIXME("WINHTTP_OPTION_CLIENT_CERT_CONTEXT\n");
-        return TRUE;
+        if (!buffer)
+        {
+            CertFreeCertificateContext( request->client_cert );
+            request->client_cert = NULL;
+        }
+        else if (buflen >= sizeof(cert))
+        {
+            if (!(cert = CertDuplicateCertificateContext( buffer ))) return FALSE;
+            CertFreeCertificateContext( request->client_cert );
+            request->client_cert = cert;
+        }
+        else
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            return FALSE;
+        }
 
+        if (request->cred_handle_initialized)
+        {
+            FreeCredentialsHandle( &request->cred_handle );
+            request->cred_handle_initialized = FALSE;
+        }
+
+        return TRUE;
+    }
     case WINHTTP_OPTION_ENABLE_FEATURE:
         if(buflen == sizeof( DWORD ) && *(DWORD *)buffer == WINHTTP_ENABLE_SSL_REVOCATION)
         {
diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h
index b46f7087d8..38e39cb925 100644
--- a/dlls/winhttp/winhttp_private.h
+++ b/dlls/winhttp/winhttp_private.h
@@ -92,8 +92,6 @@ struct session
     WCHAR *proxy_password;
     struct list cookie_cache;
     HANDLE unload_event;
-    CredHandle cred_handle;
-    BOOL cred_handle_initialized;
     DWORD secure_protocols;
 };
 
@@ -182,6 +180,9 @@ struct request
     DWORD security_flags;
     BOOL check_revocation;
     const CERT_CONTEXT *server_cert;
+    const CERT_CONTEXT *client_cert;
+    CredHandle cred_handle;
+    BOOL cred_handle_initialized;
     int resolve_timeout;
     int connect_timeout;
     int send_timeout;
-- 
2.20.1




More information about the wine-devel mailing list