winhttp: Add support for WINHTTP_ENABLE_SSL_REVOCATION.

This also fixes a regression caused by 0b61334b9d,
which is causing Office 2013 to fail to login, saying that there is a problem
with your account.

Signed-off-by: Zhiyi Zhang <zzhang@codeweavers.com>
Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
oldstable
Zhiyi Zhang 2018-08-24 16:32:49 +08:00 committed by Alexandre Julliard
parent 56b05ded78
commit b55f568383
5 changed files with 54 additions and 8 deletions

View File

@ -160,7 +160,7 @@ static int sock_recv(int fd, void *msg, size_t len, int flags)
return ret;
}
static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, WCHAR *server, DWORD security_flags )
static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, WCHAR *server, DWORD security_flags, BOOL check_revocation )
{
HCERTSTORE store = cert->hCertStore;
BOOL ret;
@ -173,9 +173,10 @@ static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, WCHAR *server, DWORD secu
TRACE("verifying %s\n", debugstr_w( server ));
chainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth;
if ((ret = CertGetCertificateChain( NULL, cert, NULL, store, &chainPara,
CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
NULL, &chain )))
ret = CertGetCertificateChain( NULL, cert, NULL, store, &chainPara,
check_revocation ? CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT : 0,
NULL, &chain );
if (ret)
{
if (chain->TrustStatus.dwErrorStatus)
{
@ -370,7 +371,8 @@ BOOL netconn_close( netconn_t *conn )
return TRUE;
}
BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_flags, CredHandle *cred_handle )
BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_flags, CredHandle *cred_handle,
BOOL check_revocation)
{
SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}};
SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs};
@ -466,7 +468,7 @@ BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_fl
status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
if(status == SEC_E_OK) {
res = netconn_verify_cert(cert, hostname, security_flags);
res = netconn_verify_cert(cert, hostname, security_flags, check_revocation);
CertFreeCertificateContext(cert);
if(res != ERROR_SUCCESS) {
WARN("cert verify failed: %u\n", res);

View File

@ -1769,7 +1769,7 @@ static BOOL open_connection( request_t *request )
if (!ensure_cred_handle( connect->session ) ||
!netconn_secure_connect( netconn, connect->hostname, request->security_flags,
&connect->session->cred_handle ))
&connect->session->cred_handle, request->check_revocation ))
{
heap_free( addressW );
netconn_close( netconn );

View File

@ -1020,6 +1020,18 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
}
FIXME("WINHTTP_OPTION_CLIENT_CERT_CONTEXT\n");
return TRUE;
case WINHTTP_OPTION_ENABLE_FEATURE:
if(buflen == sizeof( DWORD ) && *(DWORD *)buffer == WINHTTP_ENABLE_SSL_REVOCATION)
{
request->check_revocation = TRUE;
SetLastError( NO_ERROR );
return TRUE;
}
else
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
default:
FIXME("unimplemented option %u\n", option);
set_last_error( ERROR_WINHTTP_INVALID_OPTION );

View File

@ -201,6 +201,37 @@ static void test_QueryOption(void)
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
feature = 0xdeadbeef;
size = sizeof(feature);
SetLastError(0xdeadbeef);
ret = WinHttpQueryOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, &size);
ok(!ret, "should fail to query enabled features for a request\n");
ok(feature == 0xdeadbeef, "expect feature 0xdeadbeef, got %u\n", feature);
ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
feature = WINHTTP_ENABLE_SSL_REVOCATION;
SetLastError(0xdeadbeef);
ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, 0, sizeof(feature));
ok(!ret, "should fail to enable WINHTTP_ENABLE_SSL_REVOCATION with invalid parameters\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
SetLastError(0xdeadbeef);
ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, 0);
ok(!ret, "should fail to enable WINHTTP_ENABLE_SSL_REVOCATION with invalid parameters\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
SetLastError(0xdeadbeef);
ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, sizeof(feature));
ok(ret, "failed to set feature\n");
ok(GetLastError() == NO_ERROR || broken(GetLastError() == 0xdeadbeef), /* Doesn't set error code on Vista or older */
"expected NO_ERROR, got %u\n", GetLastError());
feature = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, sizeof(feature));
ok(!ret, "should fail to enable WINHTTP_ENABLE_SSL_REVOCATION with invalid parameters\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
SetLastError(0xdeadbeef);
ret = WinHttpCloseHandle(request);
ok(ret, "WinHttpCloseHandle failed on closing request: %u\n", GetLastError());

View File

@ -210,6 +210,7 @@ typedef struct
DWORD optional_len;
netconn_t *netconn;
DWORD security_flags;
BOOL check_revocation;
const CERT_CONTEXT *server_cert;
int resolve_timeout;
int connect_timeout;
@ -306,7 +307,7 @@ void netconn_unload( void ) DECLSPEC_HIDDEN;
ULONG netconn_query_data_available( netconn_t * ) DECLSPEC_HIDDEN;
BOOL netconn_recv( netconn_t *, void *, size_t, int, int * ) DECLSPEC_HIDDEN;
BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_storage *, int ) DECLSPEC_HIDDEN;
BOOL netconn_secure_connect( netconn_t *, WCHAR *, DWORD, CredHandle * ) DECLSPEC_HIDDEN;
BOOL netconn_secure_connect( netconn_t *, WCHAR *, DWORD, CredHandle *, BOOL ) DECLSPEC_HIDDEN;
BOOL netconn_send( netconn_t *, const void *, size_t, int * ) DECLSPEC_HIDDEN;
DWORD netconn_set_timeout( netconn_t *, BOOL, int ) DECLSPEC_HIDDEN;
BOOL netconn_is_alive( netconn_t * ) DECLSPEC_HIDDEN;