winhttp: Store the server certificate context in the request.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2018-06-11 09:20:35 +02:00 committed by Alexandre Julliard
parent 6bc984a600
commit f5ea51d360
5 changed files with 24 additions and 9 deletions

View File

@ -47,7 +47,6 @@
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "winhttp.h" #include "winhttp.h"
#include "wincrypt.h"
#include "schannel.h" #include "schannel.h"
#include "winhttp_private.h" #include "winhttp_private.h"

View File

@ -1765,6 +1765,10 @@ static BOOL open_connection( request_t *request )
return FALSE; return FALSE;
} }
} }
CertFreeCertificateContext( request->server_cert );
request->server_cert = NULL;
if (!ensure_cred_handle( connect->session ) || if (!ensure_cred_handle( connect->session ) ||
!netconn_secure_connect( netconn, connect->hostname, request->security_flags, !netconn_secure_connect( netconn, connect->hostname, request->security_flags,
&connect->session->cred_handle )) &connect->session->cred_handle ))
@ -1787,6 +1791,13 @@ static BOOL open_connection( request_t *request )
request->netconn = netconn; request->netconn = netconn;
} }
if (netconn->secure && !(request->server_cert = netconn_get_certificate( netconn )))
{
heap_free( addressW );
netconn_close( netconn );
return FALSE;
}
done: done:
request->read_pos = request->read_size = 0; request->read_pos = request->read_size = 0;
request->read_chunked = FALSE; request->read_chunked = FALSE;

View File

@ -40,7 +40,6 @@
#include "winsock2.h" #include "winsock2.h"
#include "ws2ipdef.h" #include "ws2ipdef.h"
#include "winhttp.h" #include "winhttp.h"
#include "wincrypt.h"
#include "winreg.h" #include "winreg.h"
#define COBJMACROS #define COBJMACROS
#include "ole2.h" #include "ole2.h"
@ -597,6 +596,8 @@ static void request_destroy( object_header_t *hdr )
} }
release_object( &request->connect->hdr ); release_object( &request->connect->hdr );
CertFreeCertificateContext( request->server_cert );
destroy_authinfo( request->authinfo ); destroy_authinfo( request->authinfo );
destroy_authinfo( request->proxy_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; 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; *(CERT_CONTEXT **)buffer = (CERT_CONTEXT *)cert;
*buflen = sizeof(cert); *buflen = sizeof(cert);
return TRUE; return TRUE;
} }
case WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT: case WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT:
{ {
const CERT_CONTEXT *cert; const CERT_CONTEXT *cert = request->server_cert;
const CRYPT_OID_INFO *oidInfo; const CRYPT_OID_INFO *oidInfo;
WINHTTP_CERTIFICATE_INFO *ci = buffer; 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 ); set_last_error( ERROR_INSUFFICIENT_BUFFER );
return FALSE; return FALSE;
} }
if (!request->netconn || !(cert = netconn_get_certificate( request->netconn ))) return FALSE; if (!cert) return FALSE;
ci->ftExpiry = cert->pCertInfo->NotAfter; ci->ftExpiry = cert->pCertInfo->NotAfter;
ci->ftStart = cert->pCertInfo->NotBefore; ci->ftStart = cert->pCertInfo->NotBefore;
ci->lpszSubjectInfo = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Subject ); ci->lpszSubjectInfo = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Subject );
ci->lpszIssuerInfo = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Issuer ); ci->lpszIssuerInfo = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Issuer );
ci->lpszProtocolName = NULL; ci->lpszProtocolName = NULL;
oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, cert->pCertInfo->SignatureAlgorithm.pszObjId, 0 );
cert->pCertInfo->SignatureAlgorithm.pszObjId,
0 );
if (oidInfo) if (oidInfo)
ci->lpszSignatureAlgName = (LPWSTR)oidInfo->pwszName; ci->lpszSignatureAlgName = (LPWSTR)oidInfo->pwszName;
else else
@ -795,7 +794,6 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
ci->lpszEncryptionAlgName = NULL; ci->lpszEncryptionAlgName = NULL;
ci->dwKeySize = request->netconn ? netconn_get_cipher_strength( request->netconn ) : 0; ci->dwKeySize = request->netconn ? netconn_get_cipher_strength( request->netconn ) : 0;
CertFreeCertificateContext( cert );
*buflen = sizeof(*ci); *buflen = sizeof(*ci);
return TRUE; return TRUE;
} }

View File

@ -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); 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: cleanup:
WinHttpCloseHandle(req); WinHttpCloseHandle(req);
WinHttpCloseHandle(con); WinHttpCloseHandle(con);

View File

@ -46,6 +46,7 @@
#include "ole2.h" #include "ole2.h"
#include "sspi.h" #include "sspi.h"
#include "wincrypt.h"
static const WCHAR getW[] = {'G','E','T',0}; static const WCHAR getW[] = {'G','E','T',0};
static const WCHAR postW[] = {'P','O','S','T',0}; static const WCHAR postW[] = {'P','O','S','T',0};
@ -209,6 +210,7 @@ typedef struct
DWORD optional_len; DWORD optional_len;
netconn_t *netconn; netconn_t *netconn;
DWORD security_flags; DWORD security_flags;
const CERT_CONTEXT *server_cert;
int resolve_timeout; int resolve_timeout;
int connect_timeout; int connect_timeout;
int send_timeout; int send_timeout;