Junk characters in htttps get response - c++

I am facing a weird situation with a Windows application (OCX control) written in C++, which was working fine until 2 days ago. No updates were added to the application. Then suddenly, it started to have errors in the communication with a remote test server. Basically, the error is that in the response of a GET request, I am seeing junk characters like this: ÑòWo †¶âBA etc
The function that I am using for the HTTP requests is:
TCHAR* openUrlFunction(TCHAR *strServer, TCHAR *strPath, TCHAR *userAgent){
HINTERNET httpSession = NULL;
HINTERNET httpConnect = NULL;
HINTERNET httpRequest = NULL;
HINTERNET hFile = NULL;
BOOL resDownload = FALSE;
TCHAR bufferIdent[60] = { 0 };
TCHAR bufferMirror[500] = { 0 };
TCHAR szURL[200] = { 0 };
TCHAR sError[7] = { 0 };
DWORD dwFlags;
// DWORD dwTimeOut = 25000;
DWORD dwBuffLen = sizeof(dwFlags);
int i = 0;
DWORD dwRead, error;
int len;
TCHAR *res1;
TCHAR delimeter[6] = _T("\f\n\r\t\v");
HRESULT resCat;
bufferIdent[0] = '\0';
bufferMirror[0] = '\0';
szURL[0] = '\0';
std::string ss;
httpSession = InternetOpen(strAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); // header
if (httpSession)
{
httpConnect = InternetConnect(httpSession, strServer, INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
if (httpConnect)
{
httpRequest = HttpOpenRequest(httpConnect, "GET", strPath, NULL, NULL, NULL, INTERNET_FLAG_SECURE, 0); parametros.
if (HttpSendRequest(httpRequest, NULL, 0, NULL, 0)) {
if (httpRequest)
{
while (InternetReadFile(httpRequest, bufferMirror, 499, &dwRead)) // Se lee el retorno
{
if (dwRead == 0)
break;
StrTrim(bufferMirror, delimeter);
while (bufferMirror[i] != NULL){
if (bufferMirror[i] != char(10))
ss = ss + bufferMirror[i];
i++;
if (bufferMirror[i] == char(10))
break;
}
i = 0;
}
}
}
else{
error = GetLastError();
_stprintf_s(sError, 7, _T("%d"), error);
InternetCloseHandle(httpRequest);
InternetCloseHandle(httpConnect);
InternetCloseHandle(httpSession);
return sError;
}
InternetCloseHandle(httpRequest);
}
InternetCloseHandle(httpConnect);
}
InternetCloseHandle(httpSession);
len = ss.length();
if (len == 0){
return NULL;
}
res1 = new TCHAR[len + 1];
resCat = StringCchCopyN(res1, len + 1, ss.c_str(), len);
if (!SUCCEEDED(resCat))
return NULL;
return res1;
}
The interesting thing here was that I decided to monitor the traffic so I have installed Fiddler on the same machine (Windows 10) where the problem is happening. After started Fiddler, I made a test with the Application and voila, the response was clear and well-formed and no junk characters were present.
I suspect that the Fiddler Everywhere Certificate that is installed has something to do with the result. So, if I turn off Fiddler, and make a new test, I again receive the junk characters.
I have checked the TLS configuration in the computer and nothing is wrong there. I am not sure if a Windows update could have caused this situation.
We have 3 machines, and the problem is occurring on 2 of the 3. All of them are Windows 10, but maybe different updates.
One other important thing here is that the server is for testing, and the client did not install any SSL certificate.

Well after looking into this problem, I just found that the root of the issue was more related to the fact the one of the variables was not correctly initialized and before the http request, this variable could contain junk characters so the next steps of the process were affected for the garbage that the variable contained. Another thing was that the connection problem with WININET was solved after installing a right SSL certificate. Even after setting some flags to bypass the SSL validation, did not work. The connection only was possible when the server was configured with the SSL certificate.

Related

Only Fiddler fixes my WININET GET request

I need to send WININET request to rest server and get json response. Code works only while fiddler is working. I've tried everything what I've found but every time I get 0 into bytesRead. There aren't any errors and HttpSendRequestand and InternetReadFile both return true but buffer is still empty.
Server works fine and answers in a right way. When fiddler is running I get my 76 bytes, which I need. I tried to figure out using that blog Help! Running Fiddler Fixes My App???, no luck.
HINTERNET session = nullptr;
HINTERNET request = nullptr;
HINTERNET connect = nullptr;
BOOST_SCOPE_EXIT((&session)(&request)(&connect)) {
if (request != nullptr)
::InternetCloseHandle(request);
if (session != nullptr)
::InternetCloseHandle(session);
if (connect != nullptr)
::InternetCloseHandle(connect);
} BOOST_SCOPE_EXIT_END;
try
{
//std::wstring agent(L"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
std::wstring agent{ L"Mozilla/5.0 (compatible)" };
session = ::InternetOpen(agent.c_str(), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (!session)
return;
InternetSetStatusCallback(
session,
(INTERNET_STATUS_CALLBACK)IStatusCallback);
connect = InternetConnect(
session
, serverName.c_str()
, INTERNET_DEFAULT_HTTP_PORT
, NULL
, NULL
, INTERNET_SERVICE_HTTP
, 0
, 1);
if (!connect)
return;
//const wchar_t* parrAcceptTypes[] = { L"text/*", NULL };
const wchar_t* parrAcceptTypes[] = { L"application/json", L"text/*", NULL };
request = HttpOpenRequest(
connect
, L"GET"
, virtualFolder.c_str()
, L"HTTP/1.1"
, NULL
, parrAcceptTypes
, /*INTERNET_FLAG_KEEP_CONNECTION*/INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_PRAGMA_NOCACHE
, 1);
std::string data;
if (request)
{
BOOL isRequestComplete = HttpSendRequest(request, NULL, 0, NULL, 0);
if (isRequestComplete)
{
const int dataSize = 1024;
BYTE buff[dataSize];
DWORD bytesRead = (DWORD)-1;
BOOL bKeepReading = true;
while (bKeepReading && bytesRead != 0)
{
bKeepReading = InternetReadFile(request, buff, sizeof(buff) - 1, &bytesRead);
data.append((char*)buff, bytesRead);
}
}
else
{
DWORD dwErr = GetLastError();
InternetErrorDlg(parent_, request, dwErr, 0, NULL);
LERR_ << "Request was failed. Error code: " << dwErr;
}
}

SCHANNEL TLS Server side cannot CertFindCertificateInStore

I am adding TLS encryption to a server side application. I am using the Schannel API to add the TLS. I am having a problem with CertFindCertificateInStore. It does not ever find the certificate that I am searching for. As criteria for the search I am using the name of the certificate. I have spent many hours on this now and do not understand why it is not working. Any help would be immensely appreciated. The function I am using this in is found below. Thanks,
int ServerCreateCredentials() {
//- get the certificate store
HCERTSTORE myCertStore = NULL;
myCertStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
X509_ASN_ENCODING,
NULL,
CERT_SYSTEM_STORE_LOCAL_MACHINE,
L"My");
// check for the failure to find the appropriate store
if (myCertStore == NULL) {
return 1;
}
// find the certificate in the store
m_CertificateContext = CertFindCertificateInStore(
myCertStore,
X509_ASN_ENCODING,
0,
CERT_FIND_SUBJECT_STR_A,
(LPVOID) CertificateName,
NULL);
if (m_CertificateContext == NULL) {
// try unicode
m_CertificateContext = CertFindCertificateInStore(
myCertStore,
X509_ASN_ENCODING,
0,
CERT_FIND_SUBJECT_STR_W,
CertificateName,
NULL);
if (m_CertificateContext == NULL ) {
// free the store
CertCloseStore(myCertStore, CERT_CLOSE_STORE_CHECK_FLAG);
return 2;
}
}
TimeStamp life;
// get the credentials
SCHANNEL_CRED SchannelCredentials;
ZeroMemory(&SchannelCredentials, sizeof(SchannelCredentials));
SchannelCredentials.dwVersion = SCHANNEL_CRED_VERSION;
SchannelCredentials.cCreds = 1; // number of credentials
SchannelCredentials.paCred = &m_CertificateContext; // credentials
SchannelCredentials.hRootStore = myCertStore; // certificate store location
SchannelCredentials.dwMinimumCipherStrength = 80; // minimum encryption allowed
SchannelCredentials.grbitEnabledProtocols = 0; // let the dll decide
SchannelCredentials.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION
| SCH_CRED_NO_SERVERNAME_CHECK
| SCH_CRED_REVOCATION_CHECK_CHAIN;
DWORD Status = SEC_E_OK;
Status = m_securityFunctionTable.AcquireCredentialsHandle(
NULL,
UNISP_NAME,
SECPKG_CRED_INBOUND,
NULL,
&SchannelCredentials,
NULL,
NULL,
&m_credentials,
&life);
// at this point we should be good
// free the store
CertCloseStore(myCertStore, CERT_CLOSE_STORE_CHECK_FLAG);
if (Status != SEC_E_OK) {
return 3;
}
return 0;
I have figured out that I was not searching on the correct parameters. You need to search based on the subject name and then it will work.

C++ WinInet no second request

I'm currently coding a website watcher, witch calls every minute a website and parses the new threads. Because I only need the HTTP I just used the WinInet-API. Everything works, but than I saw that the second request (and following requests) is always empty. Also the forum/site doesn't log a second visit.
I have no clue what happened. I set no cache and I'm closing everything at the end.
The code is:
char *getRequest(wchar_t *url)
{
HINTERNET hInet = InternetOpen(L"MyBrowser", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (!hInet)
{
processError(L"Error getRequest 1");
return 0;
}
HINTERNET hUrl = InternetOpenUrl(hInet, url, NULL, 0, INTERNET_FLAG_PRAGMA_NOCACHE, 0);
if (!hUrl)
{
processError(L"Error getRequest 2");
InternetCloseHandle(hInet);
return 0;
}
DWORD dwNumberOfBytesRead = 0;
char *ret = (char*)LocalAlloc(LMEM_ZEROINIT, 4096);
if (!InternetReadFile(hUrl, ret, 4096, &dwNumberOfBytesRead))
{
processError(L"Error getRequest 3");
InternetCloseHandle(hUrl);
InternetCloseHandle(hInet);
LocalFree(ret);
return 0;
}
InternetCloseHandle(hUrl);
InternetCloseHandle(hInet);
return ret;
}
At wireshark there is no connection too.
Thank you!

FtpGetFile WinINEt never returns

I'm experiencing a curious problem (very strange, let me say hehe). During a FTP download of an EXE file (24 MB), if the connection is ever interrupted, it appears that the function FtpGetFile of the WinINEt library has a bug and it never returns. This causes that future file transfers fail (the connection is already opened).
Apparently, I found a workaround by increasing the timeout of the server transfers but I do not like it. I didn't found a similar problem by googling (maybe I introduced the wrong keywords).
I read some forums on the internet and it seems that everyone does not recommend using the FtpGetFile because it is buggy.
This appears in a network scenario that has a big lag (and not always) but in good conditions it disappears (downloads take place correctly and FtpGetFile returns always).
Here is how I use the function:
if( FtpGetFile(m_hFtpSession, strSourcePath.c_str(), strTargetPath.c_str(), 0, 0, FTP_TRANSFER_TYPE_BINARY, 0)==TRUE)
Can anyone confirm that? Should I refactor my code and look for an update?
Thank you
I found a way to download files without using FtpGetFile. I hope this code can help someone:
bool RetrieveFile(const string& strSource, const string& strTarget) {
/* The handle for the transfer */
HINTERNET hTransfer = NULL;
/*
* Set default error
*/
DWORD error = ERROR_SUCCESS;
if( !isConnected ) {
debug("%s(): ERROR not connected\n", __FUNCTION__);
return false;
}
/* Initiate access to a remote FTP connection */
hTransfer = FtpOpenFile(hFtpSession, strSource.c_str(), GENERIC_READ,
FTP_TRANSFER_TYPE_BINARY, 0);
if(hTransfer) {
std::ofstream myostream(strTarget.c_str(), std::ios::binary);
if ( myostream.is_open() ) {
static const DWORD SIZE = 1024;
BYTE data[SIZE];
DWORD size = 0;
do {
BOOL result = InternetReadFile(hTransfer, data, SIZE, &size);
if ( result == FALSE ) {
error = GetLastError();
Debug("InternetReadFile(): %lu\n", error);
}
myostream.write((const char*)data, size);
}
while ((error == ERROR_SUCCESS) && (size > 0));
// Close the stream
myostream.close();
}
else {
Debug("Could not open '%s'.\n", strTarget.c_str());
error = ERROR_FILE_NOT_FOUND; // Not necessarily not found, but it is to describe a file error which is different from ERROR_SUCCESS
}
// Close
const BOOL result = InternetCloseHandle(hTransfer);
if ( result == FALSE ) {
const DWORD error = GetLastError();
debug("InternetClose(): %lu\n", error);
}
/* Check error status of the process */
return (error == ERROR_SUCCESS);
}
DWORD dwInetError;
DWORD dwExtLength = 1000;
TCHAR *szExtErrMsg = NULL;
TCHAR errmsg[1000];
szExtErrMsg = errmsg;
int returned = InternetGetLastResponseInfo( &dwInetError, szExtErrMsg, &dwExtLength );
debug("dwInetError: %d Returned: %d\n", dwInetError, returned);
debug("Buffer: %s\n", szExtErrMsg);
debug("%s() : ERROR to get '%s' file (errorCode=%d)\n", __FUNCTION__, strSource.c_str(), GetLastError());
return false;
}

C++ wininet, connect to weblogin, how to set cookies?

Hey all i want to login onto my works webpage with wininet, this is my current code:
int main()
{
HINTERNET hInet = InternetOpenA("UserAgent/1.0", INTERNET_OPEN_TYPE_PRECONFIG,0, 0, 0 );
if(!hInet)
{
printf("hInet Failed!\n");
return -1;
}
HINTERNET hConnection = InternetConnectA( hInet,"app.tamigo.com",INTERNET_DEFAULT_HTTPS_PORT,"","", INTERNET_SERVICE_HTTP,0,0);
if (!hConnection)
{
InternetCloseHandle(hInet);
printf("InternetConnectA failed!\n");
return -1;
}
HINTERNET hRequest = HttpOpenRequestA( hConnection, "Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",NULL,"https://app.tamigo.com/Home/Pages/Login.aspx", NULL, INTERNET_FLAG_KEEP_CONNECTION, 0 );
if (!hRequest)
{
printf("BuildRequestHeader failed %d!\n",GetLastError());
InternetCloseHandle(hConnection);
InternetCloseHandle(hInet);
return -1;
}
HttpSendRequestA(hRequest, NULL, 0, NULL, 0);
DWORD dwInfoLevel = HTTP_QUERY_RAW_HEADERS_CRLF;
DWORD dwInfoBufferLength = 10;
BYTE *pInfoBuffer = (BYTE *)malloc(dwInfoBufferLength+1);
while (!HttpQueryInfo(hRequest, dwInfoLevel, pInfoBuffer, &dwInfoBufferLength, NULL))
{
DWORD dwError = GetLastError();
if (dwError == ERROR_INSUFFICIENT_BUFFER)
{
free(pInfoBuffer);
pInfoBuffer = (BYTE *)malloc(dwInfoBufferLength+1);
}
else
{
fprintf(stderr, "HttpQueryInfo failed, error = %d (0x%x)\n",
GetLastError(), GetLastError());
break;
}
}
pInfoBuffer[dwInfoBufferLength] = '\0';
printf("%s", pInfoBuffer);
free(pInfoBuffer);
cin.get();
return 1;
}
if this code is right, i have to login with my username and pass,i got a cookie using "Firefox plugin Tamper Data". How can i set this cookie with wininet?
Thanks alot for reading and for your time
If the cookie already exists from a previous WinInet request, then WinInet will send it automatically. However, if the cookie does not exist in WinInet's cookie cache (if instance, if you got the cookie from another source), then you will have to use HttpAddRequestHeaders() to provide your own Cookie: request header before calling HttpSendRequest().