in src/odbc/rsodbc/iam/http/IAMWinHttpClient.cpp [459:694]
rs_string IAMWinHttpClient::SendHttpRequestWithWIA(
const rs_wstring& in_host,
short in_port,
bool in_verifySSL,
const rs_wstring& in_proxyUsername,
const rs_wstring& in_proxyPassword,
const rs_wstring& in_loginToRp,
int in_stsConnectionTimeout
)
{
// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383880(v=vs.85).aspx
HINTERNET sessionHandle = NULL,
connectHandle = NULL,
requestHandle = NULL;
DWORD dwProxyAuthScheme = 0;
size_t httpRequestAttempt = 0;
rs_string httpContentBody;
bool m_usingProxy = !IAMUtils::isEmpty(in_proxyUsername);
if (m_usingProxy)
{
sessionHandle = WinHttpOpen(
USER_AGENT,
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
0);
}
else
{
sessionHandle = WinHttpOpen(
USER_AGENT,
WINHTTP_ACCESS_TYPE_NO_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
0);
}
if (!sessionHandle)
{
return httpContentBody;
}
if (in_verifySSL)
{
//disable insecure tls protocols, otherwise you might as well turn ssl verification off.
DWORD flags = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 |
WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 |
WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
WinHttpSetOption(sessionHandle, WINHTTP_OPTION_SECURE_PROTOCOLS, &flags, sizeof(flags));
}
// Set timeouts
WinHttpSetTimeouts(sessionHandle,
in_stsConnectionTimeout,
in_stsConnectionTimeout,
in_stsConnectionTimeout,
in_stsConnectionTimeout);
connectHandle = WinHttpConnect(
sessionHandle,
in_host.c_str(), // GetAsPlatformWString()
in_port,
0);
if (connectHandle)
{
LPCWSTR accept[] = { L"*/*", NULL };
rs_wstring adfs_url = ADFS_RESOURCE + in_loginToRp;
std::wstring adfs_url_wstring = adfs_url; // .GetAsPlatformWString()
requestHandle = WinHttpOpenRequest(
connectHandle,
L"GET",
const_cast<wchar_t*>(adfs_url_wstring.c_str()),
NULL,
WINHTTP_NO_REFERER,
accept,
WINHTTP_FLAG_REFRESH | WINHTTP_FLAG_SECURE);
}
if (requestHandle)
{
if (!in_verifySSL)
{
DWORD flags = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
WinHttpSetOption(requestHandle, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
}
}
bool isDone = false;
bool isUnauthorized = false;
BOOL success = FALSE;
while (++httpRequestAttempt < MAX_HTTP_ATTEMPT && requestHandle && !isDone)
{
if (0 != dwProxyAuthScheme && m_usingProxy)
{
success = WinHttpSetCredentials(
requestHandle,
WINHTTP_AUTH_TARGET_PROXY,
dwProxyAuthScheme,
in_proxyUsername.c_str(), // GetAsPlatformWString().
in_proxyPassword.c_str(), // GetAsPlatformWString().
NULL);
}
success = WinHttpSendRequest(
requestHandle,
WINHTTP_NO_ADDITIONAL_HEADERS,
0,
WINHTTP_NO_REQUEST_DATA,
0,
0,
0);
if (success)
{
success = WinHttpReceiveResponse(requestHandle, 0);
}
if (!success)
{
if (ERROR_WINHTTP_RESEND_REQUEST == GetLastError())
{
continue;
}
else if (ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED == GetLastError())
{
// [PGODBC-1351] If the server requests the certificate, but does not require it,
// try indicate that it does not have a certificate
WinHttpSetOption(
requestHandle,
WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
WINHTTP_NO_CLIENT_CERT_CONTEXT,
0);
continue;
}
}
DWORD statusCode = 0;
DWORD size = sizeof(statusCode);
if (success)
{
success = WinHttpQueryHeaders(
requestHandle,
WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
NULL,
&statusCode,
&size,
NULL);
}
if (success)
{
httpContentBody = GetContent(requestHandle);
HttpResponseCode responseCode = static_cast<HttpResponseCode>(statusCode);
if (HttpResponseCode::UNAUTHORIZED == responseCode)
{
isUnauthorized = true;
DWORD supportedSchemes;
DWORD firstScheme;
DWORD target;
success = WinHttpQueryAuthSchemes(requestHandle, &supportedSchemes, &firstScheme, &target);
if (success)
{
DWORD scheme = 0;
// [PGODBC-1463] Check and use WINHTTP_AUTH_SCHEME_NEGOTIATE if supported by the server
if (supportedSchemes & WINHTTP_AUTH_SCHEME_NEGOTIATE)
{
scheme = WINHTTP_AUTH_SCHEME_NEGOTIATE;
}
else
if (supportedSchemes & WINHTTP_AUTH_SCHEME_NTLM)
{
scheme = WINHTTP_AUTH_SCHEME_NTLM;
}
else
{
isDone = true;
continue;
}
DWORD flags = WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW;
success = WinHttpSetOption(requestHandle, WINHTTP_OPTION_AUTOLOGON_POLICY, &flags, sizeof(flags))
&& WinHttpSetCredentials(requestHandle, target, scheme, NULL, NULL, NULL);
}
}
else
{
isUnauthorized = false;
isDone = true;
}
}
if (!success)
{
isDone = true;
}
}
if (!success)
{
IAMTHROWGEN2("IAMHttpRequestError", in_host, IAMUtils::GetLastErrorText());
}
if (isUnauthorized)
{
IAMTHROW1(DIAG_INVALID_AUTH_SPEC, "IAMHttpUnauthorizedError", in_host);
}
if (requestHandle)
{
WinHttpCloseHandle(requestHandle);
}
if (connectHandle)
{
WinHttpCloseHandle(connectHandle);
}
if (sessionHandle)
{
WinHttpCloseHandle(sessionHandle);
}
return httpContentBody;
}