From f5ea51d36092b162ca49555c927ba51608f64f92 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Mon, 11 Jun 2018 09:20:35 +0200 Subject: [PATCH] winhttp: Store the server certificate context in the request. Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- dlls/winhttp/net.c | 1 - dlls/winhttp/request.c | 11 +++++++++++ dlls/winhttp/session.c | 14 ++++++-------- dlls/winhttp/tests/winhttp.c | 5 +++++ dlls/winhttp/winhttp_private.h | 2 ++ 5 files changed, 24 insertions(+), 9 deletions(-) diff --git a/dlls/winhttp/net.c b/dlls/winhttp/net.c index d0d02d535ea..d577a647831 100644 --- a/dlls/winhttp/net.c +++ b/dlls/winhttp/net.c @@ -47,7 +47,6 @@ #include "windef.h" #include "winbase.h" #include "winhttp.h" -#include "wincrypt.h" #include "schannel.h" #include "winhttp_private.h" diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index 96a2c91de55..56ec910294f 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -1765,6 +1765,10 @@ static BOOL open_connection( request_t *request ) return FALSE; } } + + CertFreeCertificateContext( request->server_cert ); + request->server_cert = NULL; + if (!ensure_cred_handle( connect->session ) || !netconn_secure_connect( netconn, connect->hostname, request->security_flags, &connect->session->cred_handle )) @@ -1787,6 +1791,13 @@ static BOOL open_connection( request_t *request ) request->netconn = netconn; } + if (netconn->secure && !(request->server_cert = netconn_get_certificate( netconn ))) + { + heap_free( addressW ); + netconn_close( netconn ); + return FALSE; + } + done: request->read_pos = request->read_size = 0; request->read_chunked = FALSE; diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index e2b91fa513f..fb815682c25 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -40,7 +40,6 @@ #include "winsock2.h" #include "ws2ipdef.h" #include "winhttp.h" -#include "wincrypt.h" #include "winreg.h" #define COBJMACROS #include "ole2.h" @@ -597,6 +596,8 @@ static void request_destroy( object_header_t *hdr ) } release_object( &request->connect->hdr ); + CertFreeCertificateContext( request->server_cert ); + destroy_authinfo( request->authinfo ); destroy_authinfo( request->proxy_authinfo ); @@ -759,14 +760,14 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf return FALSE; } - if (!request->netconn || !(cert = netconn_get_certificate( request->netconn ))) return FALSE; + if (!(cert = CertDuplicateCertificateContext( request->server_cert ))) return FALSE; *(CERT_CONTEXT **)buffer = (CERT_CONTEXT *)cert; *buflen = sizeof(cert); return TRUE; } case WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT: { - const CERT_CONTEXT *cert; + const CERT_CONTEXT *cert = request->server_cert; const CRYPT_OID_INFO *oidInfo; WINHTTP_CERTIFICATE_INFO *ci = buffer; @@ -778,16 +779,14 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf set_last_error( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } - if (!request->netconn || !(cert = netconn_get_certificate( request->netconn ))) return FALSE; + if (!cert) return FALSE; ci->ftExpiry = cert->pCertInfo->NotAfter; ci->ftStart = cert->pCertInfo->NotBefore; ci->lpszSubjectInfo = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Subject ); ci->lpszIssuerInfo = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Issuer ); ci->lpszProtocolName = NULL; - oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, - cert->pCertInfo->SignatureAlgorithm.pszObjId, - 0 ); + oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, cert->pCertInfo->SignatureAlgorithm.pszObjId, 0 ); if (oidInfo) ci->lpszSignatureAlgName = (LPWSTR)oidInfo->pwszName; else @@ -795,7 +794,6 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf ci->lpszEncryptionAlgName = NULL; ci->dwKeySize = request->netconn ? netconn_get_cipher_strength( request->netconn ) : 0; - CertFreeCertificateContext( cert ); *buflen = sizeof(*ci); return TRUE; } diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c index 302974c6999..4b4a84c5fc7 100644 --- a/dlls/winhttp/tests/winhttp.c +++ b/dlls/winhttp/tests/winhttp.c @@ -1107,6 +1107,11 @@ static void test_secure_connection(void) } ok(read_size >= available_size, "read_size = %u, available_size = %u\n", read_size, available_size); + size = sizeof(cert); + ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size); + ok(ret, "failed to retrieve certificate context %u\n", GetLastError()); + if (ret) CertFreeCertificateContext(cert); + cleanup: WinHttpCloseHandle(req); WinHttpCloseHandle(con); diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index 0eb0dead87e..d639a2deb20 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -46,6 +46,7 @@ #include "ole2.h" #include "sspi.h" +#include "wincrypt.h" static const WCHAR getW[] = {'G','E','T',0}; static const WCHAR postW[] = {'P','O','S','T',0}; @@ -209,6 +210,7 @@ typedef struct DWORD optional_len; netconn_t *netconn; DWORD security_flags; + const CERT_CONTEXT *server_cert; int resolve_timeout; int connect_timeout; int send_timeout; -- 2.11.4.GIT