in Source/HTTP/WinHttp/winhttp_connection.cpp [599:683]
void WinHttpConnection::callback_status_request_error(
_In_ HINTERNET hRequestHandle,
_In_ WinHttpConnection* pRequestContext,
_In_ void* statusInfo)
{
WINHTTP_ASYNC_RESULT *error_result = reinterpret_cast<WINHTTP_ASYNC_RESULT *>(statusInfo);
if (error_result == nullptr)
return;
DWORD errorCode = error_result->dwError;
HC_TRACE_ERROR(HTTPCLIENT, "HCHttpCallPerform [ID %llu] [TID %ul] WINHTTP_CALLBACK_STATUS_REQUEST_ERROR dwResult=%d dwError=%d", TO_ULL(HCHttpCallGetId(pRequestContext->m_call)), GetCurrentThreadId(), error_result->dwResult, error_result->dwError);
bool reissueSend{ false };
if (error_result->dwError == ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED)
{
SecPkgContext_IssuerListInfoEx* pIssuerList{ nullptr };
DWORD dwBufferSize{ sizeof(void*) };
if (WinHttpQueryOption(
hRequestHandle,
WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST,
&pIssuerList,
&dwBufferSize
))
{
PCERT_CONTEXT pClientCert{ nullptr };
PCCERT_CHAIN_CONTEXT pClientCertChain{ nullptr };
CERT_CHAIN_FIND_BY_ISSUER_PARA searchCriteria{};
searchCriteria.cbSize = sizeof(CERT_CHAIN_FIND_BY_ISSUER_PARA);
searchCriteria.cIssuer = pIssuerList->cIssuers;
searchCriteria.rgIssuer = pIssuerList->aIssuers;
HCERTSTORE hCertStore = CertOpenSystemStore(0, L"MY");
if (hCertStore)
{
pClientCertChain = CertFindChainInStore(
hCertStore,
X509_ASN_ENCODING,
CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_URL_FLAG | CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_FLAG,
CERT_CHAIN_FIND_BY_ISSUER,
&searchCriteria,
nullptr
);
if (pClientCertChain)
{
pClientCert = (PCERT_CONTEXT)pClientCertChain->rgpChain[0]->rgpElement[0]->pCertContext;
// "!!" to cast from BOOL to bool
reissueSend = !!WinHttpSetOption(
hRequestHandle,
WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
(LPVOID)pClientCert,
sizeof(CERT_CONTEXT)
);
CertFreeCertificateChain(pClientCertChain);
}
CertCloseStore(hCertStore, 0);
}
GlobalFree(pIssuerList);
}
else
{
auto certError = GetLastError();
HC_TRACE_ERROR(HTTPCLIENT, "WinHttp returned ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED but unable to get cert issuer list, dwError=%d", certError);
}
}
if (reissueSend)
{
HRESULT hr = pRequestContext->SendRequest();
if (FAILED(hr))
{
HC_TRACE_ERROR(HTTPCLIENT, "WinHttpConnection Failure to send HTTP request 0x%0.8x", hr);
pRequestContext->complete_task(E_FAIL, hr);
}
}
else
{
pRequestContext->complete_task(E_FAIL, HRESULT_FROM_WIN32(errorCode));
}
}