From c68b5eb8500055c623486ad0b626a5f7691bfa89 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Tue, 29 Jan 2019 11:40:53 +0100 Subject: [PATCH] winhttp: Implement WINHTTP_OPTION_CLIENT_CERT_CONTEXT. Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- 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 5525c1c0bbe..af484cccf87 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 82615ad12fc..64fa8bbc5fc 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 b46f7087d89..38e39cb925e 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;