From: Paul Gofman pgofman@codeweavers.com
--- dlls/cryptnet/cryptnet_main.c | 72 ++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 19 deletions(-)
diff --git a/dlls/cryptnet/cryptnet_main.c b/dlls/cryptnet/cryptnet_main.c index 1068dd26868..ed4add512e6 100644 --- a/dlls/cryptnet/cryptnet_main.c +++ b/dlls/cryptnet/cryptnet_main.c @@ -2028,11 +2028,12 @@ static DWORD handle_ocsp_response(const CERT_INFO *cert, const CERT_INFO *issuer static DWORD verify_cert_revocation_with_ocsp(const CERT_CONTEXT *cert, const WCHAR *base_url, const CERT_REVOCATION_PARA *revpara, FILETIME *next_update) { - HINTERNET ses, con, req = NULL; + HINTERNET ses = NULL, con = NULL, req = NULL; BYTE *request_data = NULL, *response_data = NULL; - DWORD size, flags, status, request_len, response_len, count, ret = CRYPT_E_REVOCATION_OFFLINE; + DWORD size, status, request_len, response_len, count, ret = CRYPT_E_REVOCATION_OFFLINE; + DWORD flags = INTERNET_FLAG_KEEP_CONNECTION; URL_COMPONENTSW comp; - WCHAR *url; + WCHAR *url = NULL;
if (!revpara || !revpara->pIssuerCert) { @@ -2043,8 +2044,11 @@ static DWORD verify_cert_revocation_with_ocsp(const CERT_CONTEXT *cert, const WC return CRYPT_E_REVOCATION_OFFLINE;
url = build_request_url(base_url, request_data, request_len); - LocalFree(request_data); - if (!url) return CRYPT_E_REVOCATION_OFFLINE; + if (!url) + { + ret = CRYPT_E_REVOCATION_OFFLINE; + goto done; + }
memset(&comp, 0, sizeof(comp)); comp.dwStructSize = sizeof(comp); @@ -2052,31 +2056,33 @@ static DWORD verify_cert_revocation_with_ocsp(const CERT_CONTEXT *cert, const WC comp.dwUrlPathLength = ~0u; if (!InternetCrackUrlW(url, 0, 0, &comp)) { - free(url); - return CRYPT_E_REVOCATION_OFFLINE; + ret = CRYPT_E_REVOCATION_OFFLINE; + goto done; }
switch (comp.nScheme) { case INTERNET_SCHEME_HTTP: - flags = 0; break; case INTERNET_SCHEME_HTTPS: - flags = INTERNET_FLAG_SECURE; + flags |= INTERNET_FLAG_SECURE; break; default: FIXME("scheme %u not supported\n", comp.nScheme); - free(url); - return ERROR_NOT_SUPPORTED; + ret = ERROR_NOT_SUPPORTED; + goto done; }
- if (!(ses = InternetOpenW(L"CryptoAPI", 0, NULL, NULL, 0))) return GetLastError(); + if (!(ses = InternetOpenW(L"CryptoAPI", 0, NULL, NULL, 0))) + { + ret = GetLastError(); + goto done; + } comp.lpszHostName[comp.dwHostNameLength] = 0; if (!(con = InternetConnectW(ses, comp.lpszHostName, comp.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0))) { - free(url); - InternetCloseHandle(ses); - return GetLastError(); + ret = GetLastError(); + goto done; } comp.lpszHostName[comp.dwHostNameLength] = '/'; if (!(req = HttpOpenRequestW(con, NULL, comp.lpszUrlPath, NULL, NULL, NULL, flags, 0)) || @@ -2084,13 +2090,40 @@ static DWORD verify_cert_revocation_with_ocsp(const CERT_CONTEXT *cert, const WC
size = sizeof(status); if (!HttpQueryInfoW(req, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL)) goto done; - if (status != HTTP_STATUS_OK) + if (status == HTTP_STATUS_OK) { - WARN("request status %lu\n", status); - goto done; + size = sizeof(response_len); + if (!HttpQueryInfoW(req, HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_CONTENT_LENGTH, &response_len, &size, 0) || + !response_len || !(response_data = malloc(response_len)) || + !InternetReadFile(req, response_data, response_len, &count) || count != response_len) goto done; + + ret = handle_ocsp_response(cert->pCertInfo, revpara->pIssuerCert->pCertInfo, response_data, response_len, + next_update); } + if (ret == ERROR_SUCCESS || ret == CRYPT_E_REVOKED) goto done;
- size = sizeof(response_len); + WARN("GET OCSP request failed, status %lu, ret %#lx, retrying with POST.\n", status, ret); + InternetCloseHandle(req); + req = NULL; + free(response_data); + response_data = NULL; + memset(&comp, 0, sizeof(comp)); + comp.dwStructSize = sizeof(comp); + comp.dwHostNameLength = ~0u; + comp.dwUrlPathLength = ~0u; + if (!InternetCrackUrlW(base_url, 0, 0, &comp)) + { + ret = CRYPT_E_REVOCATION_OFFLINE; + goto done; + } + flags &= ~INTERNET_FLAG_KEEP_CONNECTION; + if (!(req = HttpOpenRequestW(con, L"POST", comp.lpszUrlPath, NULL, NULL, NULL, flags, 0)) || + !HttpSendRequestW(req, L"Content-Type: application/ocsp-request\0", -1, request_data, request_len)) goto done; + if (status != HTTP_STATUS_OK) + { + WARN("request status %lu.\n", status); + goto done; + } if (!HttpQueryInfoW(req, HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_CONTENT_LENGTH, &response_len, &size, 0) || !response_len || !(response_data = malloc(response_len)) || !InternetReadFile(req, response_data, response_len, &count) || count != response_len) goto done; @@ -2099,6 +2132,7 @@ static DWORD verify_cert_revocation_with_ocsp(const CERT_CONTEXT *cert, const WC next_update);
done: + LocalFree(request_data); free(url); free(response_data); InternetCloseHandle(req);