HANDLE FindNetUserHandle(LPCSTR acc) { IJabberInterface *ji = getJabberApi(acc); if (!ji) return NULL; PBYTE m_psProto = *(PBYTE*)((PBYTE)ji + sizeof(*ji)); // see CJabberInterface in jabber_proto.h PHANDLE pResult = (PHANDLE)(m_psProto + // see CJabberProto in jabber_proto.h sizeof(PVOID) + // skip vtable ptr sizeof(PVOID) + // skip m_ThreadInfo SIZE_OF_JABBER_OPTIONS); // skip m_options //for (int i=0; i < 100; i++) { // __try { // if (GetNetlibHandleType(*pResult) == NLH_USER) // MessageBox(0, L"1", L"1", 0); // } // __except (EXCEPTION_EXECUTE_HANDLER){ // AllocConsole(); // } // pResult++; //} if (GetNetlibHandleType(*pResult) != NLH_USER) pResult += 4; if (GetNetlibHandleType(*pResult) != NLH_USER) pResult += 4; if (GetNetlibHandleType(*pResult) != NLH_USER) pResult += 4; assert(GetNetlibHandleType(*pResult) == NLH_USER); return *pResult; }
INT_PTR NetlibShutdown(WPARAM wParam, LPARAM) { if (wParam) { WaitForSingleObject(hConnectionHeaderMutex,INFINITE); switch(GetNetlibHandleType(wParam)) { case NLH_CONNECTION: { struct NetlibConnection* nlc = (struct NetlibConnection*)wParam; if (nlc->hSsl) si.shutdown(nlc->hSsl); if (nlc->s != INVALID_SOCKET) shutdown(nlc->s, 2); if (nlc->s2 != INVALID_SOCKET) shutdown(nlc->s2, 2); nlc->termRequested = true; } break; case NLH_BOUNDPORT: { struct NetlibBoundPort* nlb = (struct NetlibBoundPort*)wParam; if (nlb->s != INVALID_SOCKET) shutdown(nlb->s, 2); } break; } ReleaseMutex(hConnectionHeaderMutex); } return 0; }
static INT_PTR NetlibGetSocket(WPARAM wParam, LPARAM) { SOCKET s; if(wParam==0) { s=INVALID_SOCKET; SetLastError(ERROR_INVALID_PARAMETER); } else { WaitForSingleObject(hConnectionHeaderMutex,INFINITE); switch(GetNetlibHandleType(wParam)) { case NLH_CONNECTION: s=((struct NetlibConnection*)wParam)->s; break; case NLH_BOUNDPORT: s=((struct NetlibBoundPort*)wParam)->s; break; default: s=INVALID_SOCKET; SetLastError(ERROR_INVALID_PARAMETER); break; } ReleaseMutex(hConnectionHeaderMutex); } return s; }
INT_PTR NetlibHttpGatewaySetInfo(WPARAM wParam, LPARAM lParam) { NETLIBHTTPPROXYINFO *nlhpi = (NETLIBHTTPPROXYINFO*)lParam; NetlibConnection *nlc = (struct NetlibConnection*)wParam; if (GetNetlibHandleType(nlc) != NLH_CONNECTION || nlhpi == NULL || nlhpi->cbSize < (sizeof(NETLIBHTTPPROXYINFO) - sizeof(int)) || nlhpi->szHttpPostUrl == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } mir_free(nlc->nlhpi.szHttpGetUrl); mir_free(nlc->nlhpi.szHttpPostUrl); nlc->nlhpi.combinePackets = 1; memcpy(&nlc->nlhpi, nlhpi, min(nlhpi->cbSize, sizeof(*nlhpi))); if (nlc->nlhpi.combinePackets == 0) nlc->nlhpi.combinePackets = 1; nlc->nlhpi.szHttpGetUrl = mir_strdup(nlc->nlhpi.szHttpGetUrl); nlc->nlhpi.szHttpPostUrl = mir_strdup(nlc->nlhpi.szHttpPostUrl); return 1; }
INT_PTR NetlibHttpSetSticky(WPARAM wParam, LPARAM lParam) { NetlibUser * nu = (NetlibUser*)wParam; if (GetNetlibHandleType(nu) != NLH_USER) return ERROR_INVALID_PARAMETER; replaceStr(nu->szStickyHeaders, (char*)lParam); // pointer is ours return 0; }
INT_PTR NetlibHttpSetSticky(WPARAM wParam, LPARAM lParam) { struct NetlibUser * nu = (struct NetlibUser*)wParam; if (GetNetlibHandleType(nu)!=NLH_USER) return ERROR_INVALID_PARAMETER; mir_free(nu->szStickyHeaders); nu->szStickyHeaders = mir_strdup((char*)lParam); // pointer is ours return 0; }
INT_PTR NetlibHttpSetPollingTimeout(WPARAM wParam, LPARAM lParam) { int oldTimeout; NetlibConnection *nlc = (struct NetlibConnection*)wParam; if (GetNetlibHandleType(nlc) != NLH_CONNECTION) return -1; oldTimeout = nlc->pollingTimeout; nlc->pollingTimeout = lParam; return oldTimeout; }
static INT_PTR NetlibSetUserSettings(WPARAM wParam,LPARAM lParam) { NETLIBUSERSETTINGS *nlus=(NETLIBUSERSETTINGS*)lParam; struct NetlibUser *nlu=(struct NetlibUser*)wParam; if(GetNetlibHandleType(nlu)!=NLH_USER || nlus==NULL || nlus->cbSize!=sizeof(NETLIBUSERSETTINGS)) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } NetlibSaveUserSettingsStruct(nlu->user.szSettingsModule,nlus); return 1; }
INT_PTR NetlibOpenConnection(WPARAM wParam,LPARAM lParam) { NETLIBOPENCONNECTION *nloc = (NETLIBOPENCONNECTION*)lParam; struct NetlibUser *nlu = (struct NetlibUser*)wParam; struct NetlibConnection *nlc; NetlibLogf(nlu,"Connection request to %s:%d (Flags %x)....", nloc->szHost, nloc->wPort, nloc->flags); if (GetNetlibHandleType(nlu) != NLH_USER || !(nlu->user.flags & NUF_OUTGOING) || nloc == NULL || (nloc->cbSize != NETLIBOPENCONNECTION_V1_SIZE && nloc->cbSize != sizeof(NETLIBOPENCONNECTION)) || nloc->szHost == NULL || nloc->wPort == 0) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } nlc = (struct NetlibConnection*)mir_calloc(sizeof(struct NetlibConnection)); nlc->handleType = NLH_CONNECTION; nlc->nlu = nlu; nlc->nloc = *nloc; nlc->nloc.szHost = mir_strdup(nloc->szHost); nlc->s = INVALID_SOCKET; nlc->s2 = INVALID_SOCKET; nlc->dnsThroughProxy = nlu->settings.dnsThroughProxy != 0; InitializeCriticalSection(&nlc->csHttpSequenceNums); nlc->hOkToCloseEvent = CreateEvent(NULL,TRUE,TRUE,NULL); nlc->dontCloseNow = 0; NetlibInitializeNestedCS(&nlc->ncsSend); NetlibInitializeNestedCS(&nlc->ncsRecv); if (!NetlibDoConnect(nlc)) { FreePartiallyInitedConnection(nlc); return 0; } if (iUPnPCleanup == 0) { EnterCriticalSection(&csNetlibUser); if (iUPnPCleanup == 0) { iUPnPCleanup = 1; forkthread(NetlibUPnPCleanup, 0, NULL); } LeaveCriticalSection(&csNetlibUser); } return (INT_PTR)nlc; }
INT_PTR NetlibPacketRecverGetMore(WPARAM wParam, LPARAM lParam) { struct NetlibPacketRecver *nlpr = (struct NetlibPacketRecver*)wParam; NETLIBPACKETRECVER *nlprParam = (NETLIBPACKETRECVER*)lParam; if (GetNetlibHandleType(nlpr) != NLH_PACKETRECVER || nlprParam == NULL || nlprParam->cbSize != sizeof(NETLIBPACKETRECVER) || nlprParam->bytesUsed > nlpr->packetRecver.bytesAvailable) { SetLastError(ERROR_INVALID_PARAMETER); return SOCKET_ERROR; } if (Miranda_Terminated()) { /* HACK: Lame, break while loops of protocols that can't kill their while loops, (cough, ICQ, cough) */ SetLastError(ERROR_TIMEOUT); return SOCKET_ERROR; } nlpr->packetRecver.dwTimeout = nlprParam->dwTimeout; if (nlprParam->bytesUsed == 0) { if (nlpr->packetRecver.bytesAvailable == nlpr->packetRecver.bufferSize) { nlpr->packetRecver.bytesAvailable = 0; NetlibLogf(nlpr->nlc->nlu, "Packet recver: packet overflowed buffer, ditching"); } } else { MoveMemory(nlpr->packetRecver.buffer, nlpr->packetRecver.buffer + nlprParam->bytesUsed, nlpr->packetRecver.bytesAvailable - nlprParam->bytesUsed); nlpr->packetRecver.bytesAvailable -= nlprParam->bytesUsed; } if (nlprParam->dwTimeout != INFINITE) { if (!si.pending(nlpr->nlc->hSsl) && WaitUntilReadable(nlpr->nlc->s, nlprParam->dwTimeout) <= 0) { *nlprParam = nlpr->packetRecver; return SOCKET_ERROR; } } INT_PTR recvResult = NLRecv(nlpr->nlc, (char*)nlpr->packetRecver.buffer + nlpr->packetRecver.bytesAvailable, nlpr->packetRecver.bufferSize - nlpr->packetRecver.bytesAvailable, 0); if (recvResult > 0) nlpr->packetRecver.bytesAvailable += recvResult; *nlprParam = nlpr->packetRecver; return recvResult; }
INT_PTR NetlibPacketRecverCreate(WPARAM wParam, LPARAM lParam) { NetlibConnection *nlc = (struct NetlibConnection*)wParam; struct NetlibPacketRecver *nlpr; if (GetNetlibHandleType(nlc) != NLH_CONNECTION || lParam == 0) { SetLastError(ERROR_INVALID_PARAMETER); return (INT_PTR)(struct NetlibPacketRecver*)NULL; } nlpr = (struct NetlibPacketRecver*)mir_calloc(sizeof(struct NetlibPacketRecver)); if (nlpr == NULL) { SetLastError(ERROR_OUTOFMEMORY); return (INT_PTR)(struct NetlibPacketRecver*)NULL; } nlpr->handleType = NLH_PACKETRECVER; nlpr->nlc = nlc; nlpr->packetRecver.cbSize = sizeof(nlpr->packetRecver); nlpr->packetRecver.bufferSize = lParam; nlpr->packetRecver.buffer = (PBYTE)mir_alloc(nlpr->packetRecver.bufferSize); nlpr->packetRecver.bytesUsed = 0; nlpr->packetRecver.bytesAvailable = 0; return (INT_PTR)nlpr; }
INT_PTR NetlibCloseHandle(WPARAM wParam, LPARAM) { switch(GetNetlibHandleType(wParam)) { case NLH_USER: { struct NetlibUser *nlu=(struct NetlibUser*)wParam; int i; EnterCriticalSection(&csNetlibUser); i = netlibUser.getIndex(nlu); if (i >= 0) netlibUser.remove(i); LeaveCriticalSection(&csNetlibUser); NetlibFreeUserSettingsStruct(&nlu->settings); mir_free(nlu->user.szSettingsModule); mir_free(nlu->user.szDescriptiveName); mir_free(nlu->user.szHttpGatewayHello); mir_free(nlu->user.szHttpGatewayUserAgent); mir_free(nlu->szStickyHeaders); break; } case NLH_CONNECTION: { struct NetlibConnection *nlc=(struct NetlibConnection*)wParam; HANDLE waitHandles[4]; DWORD waitResult; WaitForSingleObject(hConnectionHeaderMutex,INFINITE); if (nlc->usingHttpGateway) { HttpGatewayRemovePacket(nlc, -1); } else { if(nlc->s != INVALID_SOCKET) { NetlibDoClose(nlc); } if (nlc->s2 != INVALID_SOCKET) closesocket(nlc->s2); nlc->s2 = INVALID_SOCKET; } ReleaseMutex(hConnectionHeaderMutex); waitHandles[0]=hConnectionHeaderMutex; waitHandles[1]=nlc->hOkToCloseEvent; waitHandles[2]=nlc->ncsRecv.hMutex; waitHandles[3]=nlc->ncsSend.hMutex; waitResult=WaitForMultipleObjects( SIZEOF(waitHandles),waitHandles,TRUE,INFINITE); if(waitResult<WAIT_OBJECT_0 || waitResult >= WAIT_OBJECT_0 + SIZEOF(waitHandles)) { ReleaseMutex(hConnectionHeaderMutex); SetLastError(ERROR_INVALID_PARAMETER); //already been closed return 0; } nlc->handleType=0; mir_free(nlc->nlhpi.szHttpPostUrl); mir_free(nlc->nlhpi.szHttpGetUrl); mir_free(nlc->dataBuffer); mir_free((char*)nlc->nloc.szHost); mir_free(nlc->szNewUrl); mir_free(nlc->szProxyServer); NetlibDeleteNestedCS(&nlc->ncsRecv); NetlibDeleteNestedCS(&nlc->ncsSend); CloseHandle(nlc->hOkToCloseEvent); DeleteCriticalSection(&nlc->csHttpSequenceNums); ReleaseMutex(hConnectionHeaderMutex); NetlibLogf(nlc->nlu,"(%p:%u) Connection closed",nlc,nlc->s); break; } case NLH_BOUNDPORT: return NetlibFreeBoundPort((struct NetlibBoundPort*)wParam); case NLH_PACKETRECVER: { struct NetlibPacketRecver *nlpr=(struct NetlibPacketRecver*)wParam; mir_free(nlpr->packetRecver.buffer); break; } default: SetLastError(ERROR_INVALID_PARAMETER); return 0; } mir_free((void*)wParam); return 1; }
INT_PTR NetlibHttpTransaction(WPARAM wParam, LPARAM lParam) { NetlibUser *nlu = (NetlibUser*)wParam; NETLIBHTTPREQUEST *nlhr = (NETLIBHTTPREQUEST*)lParam, *nlhrReply; if (GetNetlibHandleType(nlu) != NLH_USER || !(nlu->user.flags & NUF_OUTGOING) || nlhr == NULL || nlhr->cbSize != sizeof(NETLIBHTTPREQUEST) || nlhr->szUrl == NULL || nlhr->szUrl[0] == 0) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } if (nlhr->nlc != NULL && GetNetlibHandleType(nlhr->nlc) != NLH_CONNECTION) nlhr->nlc = NULL; NetlibConnection *nlc = NetlibHttpProcessUrl(nlhr, nlu, (NetlibConnection*)nlhr->nlc); if (nlc == NULL) return 0; NETLIBHTTPREQUEST nlhrSend; char szUserAgent[64]; nlhrSend = *nlhr; nlhrSend.flags &= ~NLHRF_REMOVEHOST; nlhrSend.flags |= NLHRF_GENERATEHOST | NLHRF_SMARTREMOVEHOST | NLHRF_SMARTAUTHHEADER; bool doneUserAgentHeader = NetlibHttpFindHeader(nlhr, "User-Agent") != NULL; bool doneAcceptEncoding = NetlibHttpFindHeader(nlhr, "Accept-Encoding") != NULL; if (!doneUserAgentHeader || !doneAcceptEncoding) { nlhrSend.headers = (NETLIBHTTPHEADER*)mir_alloc(sizeof(NETLIBHTTPHEADER) * (nlhrSend.headersCount + 2)); memcpy(nlhrSend.headers, nlhr->headers, sizeof(NETLIBHTTPHEADER) * nlhr->headersCount); } if (!doneUserAgentHeader) { nlhrSend.headers[nlhrSend.headersCount].szName = "User-Agent"; nlhrSend.headers[nlhrSend.headersCount].szValue = szUserAgent; ++nlhrSend.headersCount; char szMirandaVer[64]; strncpy_s(szMirandaVer, MIRANDA_VERSION_STRING, _TRUNCATE); #if defined(_WIN64) strncat_s(szMirandaVer, " x64", _TRUNCATE); #endif char *pspace = strchr(szMirandaVer, ' '); if (pspace) { *pspace++ = '\0'; mir_snprintf(szUserAgent, "Miranda/%s (%s)", szMirandaVer, pspace); } else mir_snprintf(szUserAgent, "Miranda/%s", szMirandaVer); } if (!doneAcceptEncoding) { nlhrSend.headers[nlhrSend.headersCount].szName = "Accept-Encoding"; nlhrSend.headers[nlhrSend.headersCount].szValue = "deflate, gzip"; ++nlhrSend.headersCount; } if (NetlibHttpSendRequest((WPARAM)nlc, (LPARAM)&nlhrSend) == SOCKET_ERROR) { if (!doneUserAgentHeader || !doneAcceptEncoding) mir_free(nlhrSend.headers); nlhr->resultCode = nlhrSend.resultCode; NetlibCloseHandle((WPARAM)nlc, 0); return 0; } if (!doneUserAgentHeader || !doneAcceptEncoding) mir_free(nlhrSend.headers); DWORD dflags = (nlhr->flags & NLHRF_DUMPASTEXT ? MSG_DUMPASTEXT : 0) | (nlhr->flags & NLHRF_NODUMP ? MSG_NODUMP : (nlhr->flags & NLHRF_DUMPPROXY ? MSG_DUMPPROXY : 0)) | (nlhr->flags & NLHRF_NOPROXY ? MSG_RAW : 0); DWORD hflags = (nlhr->flags & NLHRF_NODUMP ? MSG_NODUMP : (nlhr->flags & NLHRF_DUMPPROXY ? MSG_DUMPPROXY : 0)) | (nlhr->flags & NLHRF_NOPROXY ? MSG_RAW : 0); if (nlhr->requestType == REQUEST_HEAD) nlhrReply = (NETLIBHTTPREQUEST*)NetlibHttpRecvHeaders((WPARAM)nlc, 0); else nlhrReply = NetlibHttpRecv(nlc, hflags, dflags); if (nlhrReply) { nlhrReply->szUrl = nlc->szNewUrl; nlc->szNewUrl = NULL; } if ((nlhr->flags & NLHRF_PERSISTENT) == 0 || nlhrReply == NULL) { NetlibCloseHandle((WPARAM)nlc, 0); if (nlhrReply) nlhrReply->nlc = NULL; } else nlhrReply->nlc = nlc; return (INT_PTR)nlhrReply; }
INT_PTR NetlibHttpSendRequest(WPARAM wParam, LPARAM lParam) { NetlibConnection *nlc = (struct NetlibConnection*)wParam; NETLIBHTTPREQUEST *nlhr = (NETLIBHTTPREQUEST*)lParam; NETLIBHTTPREQUEST *nlhrReply = NULL; HttpSecurityContext httpSecurity; struct ResizableCharBuffer httpRequest = { 0 }; char *szHost = NULL, *szNewUrl = NULL; char *pszProxyAuthHdr = NULL, *pszAuthHdr = NULL; int i, doneHostHeader, doneContentLengthHeader, doneProxyAuthHeader, doneAuthHeader; int bytesSent = 0; bool lastFirstLineFail = false; if (nlhr == NULL || nlhr->cbSize != sizeof(NETLIBHTTPREQUEST) || nlhr->szUrl == NULL || nlhr->szUrl[0] == '\0') { SetLastError(ERROR_INVALID_PARAMETER); return SOCKET_ERROR; } NetlibUser *nlu = nlc->nlu; if (GetNetlibHandleType(nlu) != NLH_USER) { SetLastError(ERROR_INVALID_PARAMETER); return SOCKET_ERROR; } int hdrTimeout = (nlhr->timeout) ? nlhr->timeout : HTTPRECVHEADERSTIMEOUT; const char *pszRequest; switch (nlhr->requestType) { case REQUEST_GET: pszRequest = "GET"; break; case REQUEST_POST: pszRequest = "POST"; break; case REQUEST_CONNECT: pszRequest = "CONNECT"; break; case REQUEST_HEAD: pszRequest = "HEAD"; break; case REQUEST_PUT: pszRequest = "PUT"; break; case REQUEST_DELETE: pszRequest = "DELETE"; break; default: SetLastError(ERROR_INVALID_PARAMETER); return SOCKET_ERROR; } if (!nlc->usingHttpGateway) if (!NetlibEnterNestedCS(nlc, NLNCS_SEND)) return SOCKET_ERROR; const char *pszFullUrl = nlhr->szUrl; const char *pszUrl = NULL; unsigned complete = false; int count = 11; while (--count) { if (GetNetlibHandleType(nlc) != NLH_CONNECTION) { nlc = NULL; bytesSent = SOCKET_ERROR; break; } if (!NetlibReconnect(nlc)) { bytesSent = SOCKET_ERROR; break; } if (!pszUrl) { pszUrl = pszFullUrl; if (nlhr->flags & (NLHRF_SMARTREMOVEHOST | NLHRF_REMOVEHOST | NLHRF_GENERATEHOST)) { bool usingProxy = nlc->proxyType == PROXYTYPE_HTTP && !(nlhr->flags & NLHRF_SSL); mir_free(szHost); szHost = NULL; const char *ppath, *phost; phost = strstr(pszUrl, "://"); if (phost == NULL) phost = pszUrl; else phost += 3; ppath = strchr(phost, '/'); if (ppath == phost) phost = NULL; if (nlhr->flags & NLHRF_GENERATEHOST) { szHost = mir_strdup(phost); if (ppath && phost) szHost[ppath - phost] = 0; } if (nlhr->flags & NLHRF_REMOVEHOST || (nlhr->flags & NLHRF_SMARTREMOVEHOST && !usingProxy)) pszUrl = ppath ? ppath : "/"; if (usingProxy && phost && !nlc->dnsThroughProxy) { char* tszHost = mir_strdup(phost); if (ppath && phost) tszHost[ppath - phost] = 0; char* cln = strchr(tszHost, ':'); if (cln) *cln = 0; if (inet_addr(tszHost) == INADDR_NONE) { DWORD ip = DnsLookup(nlu, tszHost); if (ip && szHost) { mir_free(szHost); szHost = (char*)mir_alloc(64); if (cln) *cln = ':'; mir_snprintf(szHost, 64, "%s%s", inet_ntoa(*(PIN_ADDR)&ip), cln ? cln : ""); } } mir_free(tszHost); } } } if (nlc->proxyAuthNeeded && proxyAuthList.getCount()) { if (httpSecurity.m_szProvider == NULL && nlc->szProxyServer) { const char *szAuthMethodNlu = proxyAuthList.find(nlc->szProxyServer); if (szAuthMethodNlu) { mir_free(pszProxyAuthHdr); pszProxyAuthHdr = httpSecurity.Execute(nlc, nlc->szProxyServer, szAuthMethodNlu, "", complete); } } } nlc->proxyAuthNeeded = false; AppendToCharBuffer(&httpRequest, "%s %s HTTP/1.%d\r\n", pszRequest, pszUrl, (nlhr->flags & NLHRF_HTTP11) != 0); //HTTP headers doneHostHeader = doneContentLengthHeader = doneProxyAuthHeader = doneAuthHeader = 0; for (i=0; i < nlhr->headersCount; i++) { NETLIBHTTPHEADER &p = nlhr->headers[i]; if (!mir_strcmpi(p.szName, "Host")) doneHostHeader = 1; else if (!mir_strcmpi(p.szName, "Content-Length")) doneContentLengthHeader = 1; else if (!mir_strcmpi(p.szName, "Proxy-Authorization")) doneProxyAuthHeader = 1; else if (!mir_strcmpi(p.szName, "Authorization")) doneAuthHeader = 1; else if (!mir_strcmpi(p.szName, "Connection")) continue; if (p.szValue == NULL) continue; AppendToCharBuffer(&httpRequest, "%s: %s\r\n", p.szName, p.szValue); } if (szHost && !doneHostHeader) AppendToCharBuffer(&httpRequest, "%s: %s\r\n", "Host", szHost); if (pszProxyAuthHdr && !doneProxyAuthHeader) AppendToCharBuffer(&httpRequest, "%s: %s\r\n", "Proxy-Authorization", pszProxyAuthHdr); if (pszAuthHdr && !doneAuthHeader) AppendToCharBuffer(&httpRequest, "%s: %s\r\n", "Authorization", pszAuthHdr); AppendToCharBuffer(&httpRequest, "%s: %s\r\n", "Connection", "Keep-Alive"); AppendToCharBuffer(&httpRequest, "%s: %s\r\n", "Proxy-Connection", "Keep-Alive"); // Add Sticky Headers if (nlu->szStickyHeaders != NULL) AppendToCharBuffer(&httpRequest, "%s\r\n", nlu->szStickyHeaders); //send it bytesSent = SendHttpRequestAndData(nlc, &httpRequest, nlhr, !doneContentLengthHeader); if (bytesSent == SOCKET_ERROR) break; //ntlm reply if (doneContentLengthHeader && nlhr->requestType != REQUEST_HEAD) break; DWORD fflags = MSG_PEEK | MSG_NODUMP | ((nlhr->flags & NLHRF_NOPROXY) ? MSG_RAW : 0); DWORD dwTimeOutTime = hdrTimeout < 0 ? -1 : GetTickCount() + hdrTimeout; if (!HttpPeekFirstResponseLine(nlc, dwTimeOutTime, fflags, &nlhr->resultCode, NULL, NULL)) { DWORD err = GetLastError(); NetlibLogf(nlu, "%s %d: %s Failed (%u %u)", __FILE__, __LINE__, "HttpPeekFirstResponseLine", err, count); // connection died while we were waiting if (GetNetlibHandleType(nlc) != NLH_CONNECTION) { nlc = NULL; break; } if (err == ERROR_TIMEOUT || err == ERROR_BAD_FORMAT || err == ERROR_BUFFER_OVERFLOW || lastFirstLineFail || nlc->termRequested || nlhr->requestType == REQUEST_CONNECT) { bytesSent = SOCKET_ERROR; break; } lastFirstLineFail = true; continue; } int resultCode = nlhr->resultCode; lastFirstLineFail = false; DWORD hflags = (nlhr->flags & (NLHRF_NODUMP | NLHRF_NODUMPHEADERS | NLHRF_NODUMPSEND) ? MSG_NODUMP : (nlhr->flags & NLHRF_DUMPPROXY ? MSG_DUMPPROXY : 0)) | (nlhr->flags & NLHRF_NOPROXY ? MSG_RAW : 0); DWORD dflags = (nlhr->flags & (NLHRF_NODUMP | NLHRF_NODUMPSEND) ? MSG_NODUMP : MSG_DUMPASTEXT | MSG_DUMPPROXY) | (nlhr->flags & NLHRF_NOPROXY ? MSG_RAW : 0) | MSG_NODUMP; if (resultCode == 100) nlhrReply = (NETLIBHTTPREQUEST*)NetlibHttpRecvHeaders((WPARAM)nlc, hflags); else if (resultCode == 307 || ((resultCode == 301 || resultCode == 302) && (nlhr->flags & NLHRF_REDIRECT))) { // redirect pszUrl = NULL; if (nlhr->requestType == REQUEST_HEAD) nlhrReply = (NETLIBHTTPREQUEST*)NetlibHttpRecvHeaders((WPARAM)nlc, hflags); else nlhrReply = NetlibHttpRecv(nlc, hflags, dflags); if (nlhrReply) { char* tmpUrl = NetlibHttpFindHeader(nlhrReply, "Location"); if (tmpUrl) { size_t rlen = 0; if (tmpUrl[0] == '/') { const char *ppath, *phost; phost = strstr(pszFullUrl, "://"); phost = phost ? phost + 3 : pszFullUrl; ppath = strchr(phost, '/'); rlen = ppath ? ppath - pszFullUrl : mir_strlen(pszFullUrl); } nlc->szNewUrl = (char*)mir_realloc(nlc->szNewUrl, rlen + mir_strlen(tmpUrl) * 3 + 1); strncpy(nlc->szNewUrl, pszFullUrl, rlen); mir_strcpy(nlc->szNewUrl + rlen, tmpUrl); pszFullUrl = nlc->szNewUrl; pszUrl = NULL; if (NetlibHttpProcessUrl(nlhr, nlu, nlc, pszFullUrl) == NULL) { bytesSent = SOCKET_ERROR; break; } } else { NetlibHttpSetLastErrorUsingHttpResult(resultCode); bytesSent = SOCKET_ERROR; break; } } else { NetlibHttpSetLastErrorUsingHttpResult(resultCode); bytesSent = SOCKET_ERROR; break; } } else if (resultCode == 401 && !doneAuthHeader) { //auth required if (nlhr->requestType == REQUEST_HEAD) nlhrReply = (NETLIBHTTPREQUEST*)NetlibHttpRecvHeaders((WPARAM)nlc, hflags); else nlhrReply = NetlibHttpRecv(nlc, hflags, dflags); mir_free(pszAuthHdr); pszAuthHdr = NULL; if (nlhrReply) { char *szAuthStr = NULL; if (!complete) { szAuthStr = NetlibHttpFindAuthHeader(nlhrReply, "WWW-Authenticate", httpSecurity.m_szProvider); if (szAuthStr) { char *szChallenge = strchr(szAuthStr, ' '); if (!szChallenge || !*lrtrimp(szChallenge)) complete = true; } } if (complete && httpSecurity.m_hNtlmSecurity) szAuthStr = httpSecurity.TryBasic() ? NetlibHttpFindAuthHeader(nlhrReply, "WWW-Authenticate", "Basic") : NULL; if (szAuthStr) { char *szChallenge = strchr(szAuthStr, ' '); if (szChallenge) { *szChallenge = 0; szChallenge = lrtrimp(szChallenge + 1); } pszAuthHdr = httpSecurity.Execute(nlc, szHost, szAuthStr, szChallenge, complete); } } if (pszAuthHdr == NULL) { proxyAuthList.add(szHost, NULL); NetlibHttpSetLastErrorUsingHttpResult(resultCode); bytesSent = SOCKET_ERROR; break; } } else if (resultCode == 407 && !doneProxyAuthHeader) { //proxy auth required if (nlhr->requestType == REQUEST_HEAD) nlhrReply = (NETLIBHTTPREQUEST*)NetlibHttpRecvHeaders((WPARAM)nlc, hflags); else nlhrReply = NetlibHttpRecv(nlc, hflags, dflags); mir_free(pszProxyAuthHdr); pszProxyAuthHdr = NULL; if (nlhrReply) { char *szAuthStr = NULL; if (!complete) { szAuthStr = NetlibHttpFindAuthHeader(nlhrReply, "Proxy-Authenticate", httpSecurity.m_szProvider); if (szAuthStr) { char *szChallenge = strchr(szAuthStr, ' '); if (!szChallenge || !*lrtrimp(szChallenge + 1)) complete = true; } } if (complete && httpSecurity.m_hNtlmSecurity) szAuthStr = httpSecurity.TryBasic() ? NetlibHttpFindAuthHeader(nlhrReply, "Proxy-Authenticate", "Basic") : NULL; if (szAuthStr) { char *szChallenge = strchr(szAuthStr, ' '); if (szChallenge) { *szChallenge = 0; szChallenge = lrtrimp(szChallenge + 1); } pszProxyAuthHdr = httpSecurity.Execute(nlc, nlc->szProxyServer, szAuthStr, szChallenge, complete); } } if (pszProxyAuthHdr == NULL) { proxyAuthList.add(nlc->szProxyServer, NULL); NetlibHttpSetLastErrorUsingHttpResult(resultCode); bytesSent = SOCKET_ERROR; break; } } else break; if (pszProxyAuthHdr && resultCode != 407 && !doneProxyAuthHeader) replaceStr(pszProxyAuthHdr, NULL); if (pszAuthHdr && resultCode != 401 && !doneAuthHeader) replaceStr(pszAuthHdr, NULL); if (nlhrReply) { NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); nlhrReply = NULL; } } if (count == 0) bytesSent = SOCKET_ERROR; if (nlhrReply) NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); //clean up mir_free(pszProxyAuthHdr); mir_free(pszAuthHdr); mir_free(szHost); mir_free(szNewUrl); if (nlc && !nlc->usingHttpGateway) NetlibLeaveNestedCS(&nlc->ncsSend); return bytesSent; }
INT_PTR NetlibBindPort(WPARAM wParam,LPARAM lParam) { NETLIBBIND *nlb = (NETLIBBIND*)lParam; struct NetlibUser *nlu = (struct NetlibUser*)wParam; struct NetlibBoundPort *nlbp; SOCKADDR_IN sin; int foundPort = 0; UINT dwThreadId; if (GetNetlibHandleType(nlu) != NLH_USER || !(nlu->user.flags & NUF_INCOMING) || nlb == NULL || nlb->pfnNewConnection == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } if (nlb->cbSize != sizeof(NETLIBBIND) && nlb->cbSize != NETLIBBIND_SIZEOF_V2 && nlb->cbSize != NETLIBBIND_SIZEOF_V1) { return 0; } nlbp = (NetlibBoundPort*)mir_calloc(sizeof(NetlibBoundPort)); nlbp->handleType = NLH_BOUNDPORT; nlbp->nlu = nlu; nlbp->pfnNewConnectionV2 = nlb->pfnNewConnectionV2; nlbp->s = socket(AF_INET, SOCK_STREAM, 0); nlbp->pExtra = (nlb->cbSize != NETLIBBIND_SIZEOF_V1) ? nlb->pExtra : NULL; if (nlbp->s == INVALID_SOCKET) { NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"socket",WSAGetLastError()); mir_free(nlbp); return 0; } sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_ANY); sin.sin_port = 0; /* if the netlib user wanted a free port given in the range, then they better have given wPort==0, let's hope so */ if (nlu->settings.specifyIncomingPorts && nlu->settings.szIncomingPorts && nlb->wPort == 0) { if (!BindSocketToPort(nlu->settings.szIncomingPorts, nlbp->s, &nlu->outportnum)) { NetlibLogf(nlu, "Netlib bind: Not enough ports for incoming connections specified"); SetLastError(WSAEADDRINUSE); } else foundPort = 1; } else { /* if ->wPort==0 then they'll get any free port, otherwise they'll be asking for whatever was in nlb->wPort*/ if (nlb->wPort != 0) { NetlibLogf(nlu,"%s %d: trying to bind port %d, this 'feature' can be abused, please be sure you want to allow it.",__FILE__,__LINE__,nlb->wPort); sin.sin_port = htons(nlb->wPort); } if (bind(nlbp->s, (PSOCKADDR)&sin, sizeof(sin)) == 0) foundPort = 1; } if (!foundPort) { NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"bind",WSAGetLastError()); closesocket(nlbp->s); mir_free(nlbp); return 0; } if (listen(nlbp->s, 5)) { NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"listen",WSAGetLastError()); closesocket(nlbp->s); mir_free(nlbp); return 0; } { int len; DWORD extIP; ZeroMemory(&sin,sizeof(sin)); len = sizeof(sin); if (getsockname(nlbp->s,(SOCKADDR *)&sin,&len)) { NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"getsockname",WSAGetLastError()); closesocket(nlbp->s); mir_free(nlbp); return 0; } nlb->wPort = ntohs(sin.sin_port); nlbp->wPort = nlb->wPort; nlb->dwInternalIP = ntohl(sin.sin_addr.S_un.S_addr); if (nlb->dwInternalIP == 0) { char hostname[64]; struct hostent *he; gethostname(hostname, SIZEOF(hostname)); he = gethostbyname(hostname); if (he && he->h_addr_list[0]) nlb->dwInternalIP = ntohl(*(PDWORD)he->h_addr_list[0]); } if (nlu->settings.enableUPnP && NetlibUPnPAddPortMapping(nlb->wPort, "TCP", &nlbp->wExPort, &extIP, nlb->cbSize > NETLIBBIND_SIZEOF_V2)) { NetlibLogf(NULL, "UPnP port mapping succeeded. Internal Port: %u External Port: %u\n", nlb->wPort, nlbp->wExPort); if (nlb->cbSize > NETLIBBIND_SIZEOF_V2) { nlb->wExPort = nlbp->wExPort; nlb->dwExternalIP = extIP; } } else { if (nlu->settings.enableUPnP) NetlibLogf(NULL, "UPnP port mapping failed. Internal Port: %u\n", nlb->wPort); else NetlibLogf(NULL, "UPnP disabled. Internal Port: %u\n", nlb->wPort); nlbp->wExPort = 0; if (nlb->cbSize > NETLIBBIND_SIZEOF_V2) { nlb->wExPort = nlb->wPort; nlb->dwExternalIP = nlb->dwInternalIP; } } } nlbp->hThread = (HANDLE)forkthreadex(NULL, 0, NetlibBindAcceptThread, 0, nlbp, &dwThreadId); return (INT_PTR)nlbp; }
int NetlibHttpGatewayRecv(NetlibConnection *nlc, char *buf, int len, int flags) { bool peek = (flags & MSG_PEEK) != 0; if (nlc->dataBufferLen != 0 && (!peek || nlc->dataBufferLen >= len)) return HttpGatewayReadSetResult(nlc, buf, len, peek); NetlibUser *nlu = nlc->nlu; if (GetNetlibHandleType(nlu) != NLH_USER) return SOCKET_ERROR; for (int retryCount = 0; retryCount < NETLIBHTTP_RETRYCOUNT;) { if (nlc->nlhpi.szHttpGetUrl == NULL && retryCount == 0) { if (nlc->pollingTimeout == 0) nlc->pollingTimeout = 30; /* We Need to sleep/wait for the data to send before we do receive */ for (int pollCount = nlc->pollingTimeout; pollCount--;) { if (nlc->pHttpProxyPacketQueue != NULL && GetTickCount() - nlc->lastPost > 1000) break; if (nlc->termRequested || (SleepEx(1000, TRUE) && Miranda_Terminated())) return SOCKET_ERROR; } nlc->lastPost = GetTickCount(); if (nlc->pHttpProxyPacketQueue == NULL && nlu->user.pfnHttpGatewayWrapSend != NULL) if (nlu->user.pfnHttpGatewayWrapSend(nlc, (PBYTE)"", 0, MSG_NOHTTPGATEWAYWRAP, NetlibSend) == SOCKET_ERROR) return SOCKET_ERROR; } int numPackets = 0; if (nlc->nlhpi.szHttpGetUrl) { if (!NetlibHttpGatewaySend(nlc, reqOldGet, NULL, 0)) { if (GetLastError() == ERROR_ACCESS_DENIED || nlc->termRequested) break; ++retryCount; continue; } } else { if (!NetlibHttpGatewayStdPost(nlc, numPackets)) { if (GetLastError() == ERROR_ACCESS_DENIED || nlc->termRequested) break; ++retryCount; continue; } } NETLIBHTTPREQUEST *nlhrReply = NetlibHttpRecv(nlc, flags | MSG_RAW | MSG_DUMPPROXY, MSG_RAW | MSG_DUMPPROXY); if (nlhrReply == NULL) return SOCKET_ERROR; if (nlu->user.pfnHttpGatewayUnwrapRecv && !(flags & MSG_NOHTTPGATEWAYWRAP)) nlhrReply->pData = (char*)nlu->user.pfnHttpGatewayUnwrapRecv(nlhrReply, (PBYTE)nlhrReply->pData, nlhrReply->dataLength, &nlhrReply->dataLength, mir_realloc); if (nlhrReply->resultCode >= 300) { int resultCode = nlhrReply->resultCode; NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); if (nlc->nlhpi.szHttpGetUrl && resultCode != 404) { NetlibLogf(nlu, "Error received from proxy, retrying"); continue; } else { NetlibLogf(nlu, "Error received from proxy, retry attempts exceeded (%u)", retryCount); SetLastError(ERROR_GEN_FAILURE); return SOCKET_ERROR; } } else { retryCount = 0; HttpGatewayRemovePacket(nlc, numPackets); } if (nlhrReply->dataLength) { if (peek) { int rbytes = nlc->dataBufferLen + nlhrReply->dataLength; nlc->dataBuffer = (PBYTE)mir_realloc(nlc->dataBuffer, rbytes); memcpy(nlc->dataBuffer + nlc->dataBufferLen, nlhrReply->pData, nlhrReply->dataLength); nlc->dataBufferLen = rbytes; NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); return HttpGatewayReadSetResult(nlc, buf, len, peek); } else { int bytes = min(len, nlhrReply->dataLength); int rbytes = nlhrReply->dataLength - bytes; memcpy(buf, nlhrReply->pData, bytes); nlc->dataBuffer = (PBYTE)mir_realloc(nlc->dataBuffer, rbytes); if (rbytes) memcpy(nlc->dataBuffer, nlhrReply->pData + bytes, rbytes); nlc->dataBufferLen = rbytes; NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); return bytes; } } else { if ((peek && nlc->dataBufferLen != 0) || nlhrReply->pData) { NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); return HttpGatewayReadSetResult(nlc, buf, len, peek); } } NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); } SetLastError(ERROR_GEN_FAILURE); return SOCKET_ERROR; }