Module: wine Branch: master Commit: 7ba776532d73a180130a33aee46e6182b535ce8e URL: http://source.winehq.org/git/wine.git/?a=commit;h=7ba776532d73a180130a33aee4...
Author: Hans Leidekker hans@codeweavers.com Date: Wed Dec 11 10:49:34 2013 +0100
wininet: Always store the SSL context.
This allows applications to query certificate properties when verification has failed.
---
dlls/wininet/netconnection.c | 18 ++++++++---------- dlls/wininet/tests/http.c | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 10 deletions(-)
diff --git a/dlls/wininet/netconnection.c b/dlls/wininet/netconnection.c index c90ef69..86c9b08 100644 --- a/dlls/wininet/netconnection.c +++ b/dlls/wininet/netconnection.c @@ -369,6 +369,7 @@ DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, BOOL m netconn->security_flags = security_flags | server->security_flags; netconn->mask_errors = mask_errors; list_init(&netconn->pool_entry); + SecInvalidateHandle(&netconn->ssl_ctx);
result = create_netconn_socket(server, netconn, timeout); if (result != ERROR_SUCCESS) { @@ -407,7 +408,8 @@ void free_netconn(netconn_t *netconn) heap_free(netconn->extra_buf); netconn->extra_buf = NULL; netconn->extra_len = 0; - DeleteSecurityContext(&netconn->ssl_ctx); + if (SecIsValidHandle(&netconn->ssl_ctx)) + DeleteSecurityContext(&netconn->ssl_ctx); }
heap_free(netconn); @@ -586,6 +588,10 @@ static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode TRACE("InitializeSecurityContext ret %08x\n", status);
if(status == SEC_E_OK) { + if(SecIsValidHandle(&connection->ssl_ctx)) + DeleteSecurityContext(&connection->ssl_ctx); + connection->ssl_ctx = ctx; + if(in_bufs[1].BufferType == SECBUFFER_EXTRA) FIXME("SECBUFFER_EXTRA not supported\n");
@@ -617,19 +623,14 @@ static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode } }
- if(status != SEC_E_OK || res != ERROR_SUCCESS) { - WARN("Failed to initialize security context failed: %08x\n", status); + WARN("Failed to establish SSL connection: %08x (%u)\n", status, res); heap_free(connection->ssl_buf); connection->ssl_buf = NULL; - DeleteSecurityContext(&ctx); return res ? res : ERROR_INTERNET_SECURITY_CHANNEL_ERROR; }
- TRACE("established SSL connection\n"); - connection->ssl_ctx = ctx; - connection->secure = TRUE; connection->security_flags |= SECURITY_FLAG_SECURE;
@@ -963,9 +964,6 @@ LPCVOID NETCON_GetCert(netconn_t *connection) const CERT_CONTEXT *ret; SECURITY_STATUS res;
- if (!connection->secure) - return NULL; - res = QueryContextAttributesW(&connection->ssl_ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&ret); return res == SEC_E_OK ? ret : NULL; } diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c index eb09bc7..951460f 100644 --- a/dlls/wininet/tests/http.c +++ b/dlls/wininet/tests/http.c @@ -4137,6 +4137,7 @@ static void _set_secflags(unsigned line, HINTERNET req, BOOL use_undoc, DWORD fl
static void test_security_flags(void) { + INTERNET_CERTIFICATE_INFOA *cert; HINTERNET ses, conn, req; DWORD size, flags; char buf[100]; @@ -4259,6 +4260,30 @@ static void test_security_flags(void) ok(req_error == ERROR_INTERNET_SEC_CERT_REV_FAILED || broken(req_error == ERROR_INTERNET_SEC_CERT_ERRORS), "req_error = %d\n", req_error);
+ size = 0; + res = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT, NULL, &size); + ok(res || GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InternetQueryOption failed: %d\n", GetLastError()); + ok(size == sizeof(INTERNET_CERTIFICATE_INFOA), "size = %u\n", size); + cert = HeapAlloc(GetProcessHeap(), 0, size); + cert->lpszSubjectInfo = NULL; + cert->lpszIssuerInfo = NULL; + cert->lpszSignatureAlgName = (char *)0xdeadbeef; + cert->lpszEncryptionAlgName = (char *)0xdeadbeef; + cert->lpszProtocolName = (char *)0xdeadbeef; + cert->dwKeySize = 0xdeadbeef; + res = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT, cert, &size); + ok(res, "InternetQueryOption failed: %u\n", GetLastError()); + if (res) + { + ok(cert->lpszSubjectInfo && strlen(cert->lpszSubjectInfo) > 1, "expected a non-empty subject name\n"); + ok(cert->lpszIssuerInfo && strlen(cert->lpszIssuerInfo) > 1, "expected a non-empty issuer name\n"); + ok(!cert->lpszSignatureAlgName, "unexpected signature algorithm name\n"); + ok(!cert->lpszEncryptionAlgName, "unexpected encryption algorithm name\n"); + ok(!cert->lpszProtocolName, "unexpected protocol name\n"); + ok(cert->dwKeySize != 0xdeadbeef, "unexpected key size\n"); + } + HeapFree(GetProcessHeap(), 0, cert); + CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER); CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER); CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);