From 6c764fbd4758e1d9d9b2d97c324cc51fe2d09b6e Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 11 Jun 2012 10:22:38 +0200 Subject: [PATCH] wininet: Added InternetGetSecurityInfoByURL[AW] implementation. --- dlls/wininet/http.c | 16 ++++++------ dlls/wininet/internet.c | 59 ++++++++++++++++++++++++++++++++++++++++---- dlls/wininet/internet.h | 5 ++++ dlls/wininet/netconnection.c | 13 +++++++--- 4 files changed, 77 insertions(+), 16 deletions(-) diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c index 620fcf70760..0cec4fba65d 100644 --- a/dlls/wininet/http.c +++ b/dlls/wininet/http.c @@ -244,11 +244,13 @@ void server_release(server_t *server) list_remove(&server->entry); + if(server->cert_chain) + CertFreeCertificateChain(server->cert_chain); heap_free(server->name); heap_free(server); } -static server_t *get_server(const WCHAR *name, INTERNET_PORT port) +server_t *get_server(const WCHAR *name, INTERNET_PORT port, BOOL do_create) { server_t *iter, *server = NULL; @@ -262,13 +264,11 @@ static server_t *get_server(const WCHAR *name, INTERNET_PORT port) } } - if(!server) { - server = heap_alloc(sizeof(*server)); + if(!server && do_create) { + server = heap_alloc_zero(sizeof(*server)); if(server) { - server->addr_len = 0; server->ref = 2; /* list reference and return */ server->port = port; - server->security_flags = 0; list_init(&server->conn_pool); server->name = heap_strdupW(name); if(server->name) { @@ -1724,7 +1724,7 @@ static BOOL HTTP_DealWithProxy(appinfo_t *hIC, http_session_t *session, http_req if(UrlComponents.nPort == INTERNET_INVALID_PORT_NUMBER) UrlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT; - new_server = get_server(UrlComponents.lpszHostName, UrlComponents.nPort); + new_server = get_server(UrlComponents.lpszHostName, UrlComponents.nPort, TRUE); if(!new_server) return FALSE; @@ -3103,7 +3103,7 @@ static DWORD HTTP_HttpOpenRequestW(http_session_t *session, if(port == INTERNET_INVALID_PORT_NUMBER) port = dwFlags & INTERNET_FLAG_SECURE ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT; - request->server = get_server(session->hostName, port); + request->server = get_server(session->hostName, port, TRUE); if(!request->server) { WININET_Release(&request->hdr); return ERROR_OUTOFMEMORY; @@ -3931,7 +3931,7 @@ static DWORD HTTP_HandleRedirect(http_request_t *request, LPCWSTR lpszUrl) if(!using_proxy && (strcmpiW(request->server->name, hostName) || request->server->port != urlComponents.nPort)) { server_t *new_server; - new_server = get_server(hostName, urlComponents.nPort); + new_server = get_server(hostName, urlComponents.nPort, TRUE); server_release(request->server); request->server = new_server; } diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c index 118dcdd3863..2b659dafec2 100644 --- a/dlls/wininet/internet.c +++ b/dlls/wininet/internet.c @@ -61,7 +61,6 @@ #include "winreg.h" #include "winuser.h" #include "wininet.h" -#include "winineti.h" #include "winnls.h" #include "wine/debug.h" #include "winerror.h" @@ -4419,8 +4418,18 @@ DWORD WINAPI PrivacyGetZonePreferenceW( DWORD zone, DWORD type, LPDWORD template */ BOOL WINAPI InternetGetSecurityInfoByURLA(LPSTR lpszURL, PCCERT_CHAIN_CONTEXT *ppCertChain, DWORD *pdwSecureFlags) { - FIXME("(%s %p %p)\n", debugstr_a(lpszURL), ppCertChain, pdwSecureFlags); - return FALSE; + WCHAR *url; + BOOL res; + + TRACE("(%s %p %p)\n", debugstr_a(lpszURL), ppCertChain, pdwSecureFlags); + + url = heap_strdupAtoW(lpszURL); + if(!url) + return FALSE; + + res = InternetGetSecurityInfoByURLW(url, ppCertChain, pdwSecureFlags); + heap_free(url); + return res; } /*********************************************************************** @@ -4428,8 +4437,48 @@ BOOL WINAPI InternetGetSecurityInfoByURLA(LPSTR lpszURL, PCCERT_CHAIN_CONTEXT *p */ BOOL WINAPI InternetGetSecurityInfoByURLW(LPCWSTR lpszURL, PCCERT_CHAIN_CONTEXT *ppCertChain, DWORD *pdwSecureFlags) { - FIXME("(%s %p %p)\n", debugstr_w(lpszURL), ppCertChain, pdwSecureFlags); - return FALSE; + WCHAR hostname[INTERNET_MAX_HOST_NAME_LENGTH]; + URL_COMPONENTSW url = {sizeof(url)}; + server_t *server; + BOOL res = FALSE; + + TRACE("(%s %p %p)\n", debugstr_w(lpszURL), ppCertChain, pdwSecureFlags); + + url.lpszHostName = hostname; + url.dwHostNameLength = sizeof(hostname)/sizeof(WCHAR); + + res = InternetCrackUrlW(lpszURL, 0, 0, &url); + if(!res || url.nScheme != INTERNET_SCHEME_HTTPS) { + SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND); + return FALSE; + } + + if(url.nPort == INTERNET_INVALID_PORT_NUMBER) + url.nPort = INTERNET_DEFAULT_HTTPS_PORT; + + server = get_server(hostname, url.nPort, FALSE); + if(!server) { + SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND); + return FALSE; + } + + if(server->cert_chain) { + const CERT_CHAIN_CONTEXT *chain_dup; + + chain_dup = CertDuplicateCertificateChain(server->cert_chain); + if(chain_dup) { + *ppCertChain = chain_dup; + *pdwSecureFlags = server->security_flags & _SECURITY_ERROR_FLAGS_MASK; + }else { + res = FALSE; + } + }else { + SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND); + res = FALSE; + } + + server_release(server); + return res; } DWORD WINAPI InternetDialA( HWND hwndParent, LPSTR lpszConnectoid, DWORD dwFlags, diff --git a/dlls/wininet/internet.h b/dlls/wininet/internet.h index a25be326f83..e3fb53075b5 100644 --- a/dlls/wininet/internet.h +++ b/dlls/wininet/internet.h @@ -47,6 +47,8 @@ #define ioctlsocket ioctl #endif /* __MINGW32__ */ +#include "winineti.h" + extern HMODULE WININET_hModule DECLSPEC_HIDDEN; #ifndef INET6_ADDRSTRLEN @@ -63,6 +65,7 @@ typedef struct { LONG ref; DWORD security_flags; + const CERT_CHAIN_CONTEXT *cert_chain; struct list entry; struct list conn_pool; @@ -546,6 +549,8 @@ int NETCON_GetCipherStrength(netconn_t*) DECLSPEC_HIDDEN; DWORD NETCON_set_timeout(netconn_t *connection, BOOL send, DWORD value) DECLSPEC_HIDDEN; int sock_get_error(int) DECLSPEC_HIDDEN; +server_t *get_server(const WCHAR*,INTERNET_PORT,BOOL); + extern void URLCacheContainers_CreateDefaults(void) DECLSPEC_HIDDEN; extern void URLCacheContainers_DeleteAll(void) DECLSPEC_HIDDEN; diff --git a/dlls/wininet/netconnection.c b/dlls/wininet/netconnection.c index 47b8453ddee..a705cce5090 100644 --- a/dlls/wininet/netconnection.c +++ b/dlls/wininet/netconnection.c @@ -80,7 +80,6 @@ #include "winbase.h" #include "wininet.h" #include "winerror.h" -#include "wincrypt.h" #include "wine/debug.h" #include "internet.h" @@ -358,15 +357,23 @@ static DWORD netconn_verify_cert(netconn_t *conn, PCCERT_CONTEXT cert, HCERTSTOR } } - CertFreeCertificateChain(chain); - if(err) { WARN("failed %u\n", err); + CertFreeCertificateChain(chain); + if(conn->server->cert_chain) { + CertFreeCertificateChain(conn->server->cert_chain); + conn->server->cert_chain = NULL; + } if(conn->mask_errors) conn->server->security_flags |= conn->security_flags & _SECURITY_ERROR_FLAGS_MASK; return err; } + /* FIXME: Reuse cached chain */ + if(conn->server->cert_chain) + CertFreeCertificateChain(chain); + else + conn->server->cert_chain = chain; return ERROR_SUCCESS; } -- 2.11.4.GIT