Esempio n. 1
0
static bool NetlibInitHttpsConnection(struct NetlibConnection *nlc, struct NetlibUser *nlu, NETLIBOPENCONNECTION *nloc)
{	//rfc2817
	NETLIBHTTPREQUEST nlhrSend = {0}, *nlhrReply;
	char szUrl[512];

	nlhrSend.cbSize = sizeof(nlhrSend);
	nlhrSend.requestType = REQUEST_CONNECT;
	nlhrSend.flags = NLHRF_GENERATEHOST | NLHRF_DUMPPROXY | NLHRF_SMARTAUTHHEADER | NLHRF_HTTP11 | NLHRF_NOPROXY | NLHRF_REDIRECT;
	if (nlc->dnsThroughProxy) 
	{
		mir_snprintf(szUrl, SIZEOF(szUrl), "%s:%u", nloc->szHost, nloc->wPort);
	}
	else 
	{
		DWORD ip = DnsLookup(nlu, nloc->szHost);
		if (ip == 0) return false;
		mir_snprintf(szUrl, SIZEOF(szUrl), "%s:%u", inet_ntoa(*(PIN_ADDR)&ip), nloc->wPort);
	}
	nlhrSend.szUrl = szUrl;

	nlc->usingHttpGateway = true;

	if (NetlibHttpSendRequest((WPARAM)nlc, (LPARAM)&nlhrSend) == SOCKET_ERROR)
	{
		nlc->usingHttpGateway = false;
		return 0;
	}
	nlhrReply = NetlibHttpRecv(nlc, MSG_DUMPPROXY | MSG_RAW, MSG_DUMPPROXY | MSG_RAW, true);
	nlc->usingHttpGateway = false;
	if (nlhrReply == NULL) return false;
	if (nlhrReply->resultCode < 200 || nlhrReply->resultCode >= 300)
	{
		if (nlhrReply->resultCode == 403 && nlc->dnsThroughProxy) 
		{
			NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply);
			nlc->dnsThroughProxy = 0;
			return NetlibInitHttpsConnection(nlc, nlu, nloc);
		}

		NetlibHttpSetLastErrorUsingHttpResult(nlhrReply->resultCode);
		NetlibLogf(nlu,"%s %d: %s request failed (%u %s)",__FILE__,__LINE__,nlu->settings.proxyType==PROXYTYPE_HTTP?"HTTP":"HTTPS",nlhrReply->resultCode,nlhrReply->szResultDescr);
		NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply);
		return 0;
	}
	NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply);
	//connected
	return true;
}
Esempio n. 2
0
int NetlibInitHttpConnection(NetlibConnection *nlc, NetlibUser *nlu, NETLIBOPENCONNECTION *nloc)
{
	NETLIBHTTPREQUEST *nlhrReply = NULL;

	nlc->nlhpi.firstGetSequence = 1;
	nlc->nlhpi.firstPostSequence = 1;

	if (nlu->user.szHttpGatewayHello != NULL)
	{
		nlc->usingHttpGateway = true;
		if (NetlibHttpGatewaySend(nlc, reqHelloGet, NULL, 0))
			nlhrReply = NetlibHttpRecv(nlc, MSG_DUMPPROXY | MSG_RAW, MSG_DUMPPROXY | MSG_RAW);
		nlc->usingHttpGateway = false;
		if (nlhrReply == NULL) return 0;

		if (nlhrReply->resultCode != 200)
		{
			NetlibHttpSetLastErrorUsingHttpResult(nlhrReply->resultCode);
			NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply);
			return 0;
		}
	}
	if (!nlu->user.pfnHttpGatewayInit(nlc, nloc, nlhrReply))
	{
		NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply);
		return 0;
	}
	NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply);

	/*
	 * Gena01 - Ok, we should be able to use just POST. Needed for Yahoo, NO GET requests
	 */
	if (nlc->nlhpi.szHttpPostUrl == NULL)
	{
		SetLastError(ERROR_BAD_FORMAT);
		return 0;
	}

	nlc->usingHttpGateway = true;

	//now properly connected
	if (nlu->user.pfnHttpGatewayBegin && !nlu->user.pfnHttpGatewayBegin(nlc, nloc))
		return 0;

	return 1;
}
Esempio n. 3
0
static bool NetlibHttpGatewayOscarPost(NetlibConnection *nlc, const char *buf, int len, int flags)
{
	NETLIBHTTPREQUEST *nlhrReply = NULL;
	NetlibConnection nlcSend = {0};

	nlcSend.handleType       = NLH_CONNECTION;
	nlcSend.nlu              = nlc->nlu;
	nlcSend.nlhpi            = nlc->nlhpi;
	nlcSend.s                = nlc->s2;
	nlcSend.usingHttpGateway = nlc->usingHttpGateway;
	nlcSend.szProxyServer    = nlc->szProxyServer;
	nlcSend.wProxyPort       = nlc->wProxyPort;
	nlcSend.proxyType        = nlc->proxyType;

	if (!NetlibReconnect(&nlcSend)) return false;
	nlc->s2 = nlcSend.s;

	nlcSend.hOkToCloseEvent	= CreateEvent(NULL, TRUE, TRUE, NULL);
	NetlibInitializeNestedCS(&nlcSend.ncsRecv);
	NetlibInitializeNestedCS(&nlcSend.ncsSend);

	bool res = NetlibHttpGatewaySend(&nlcSend, reqOldPost, buf, len);
	if (res)
	{
		NETLIBHTTPREQUEST *nlhrReply = NetlibHttpRecv(&nlcSend, flags | MSG_RAW | MSG_DUMPPROXY, MSG_RAW | MSG_DUMPPROXY);
		if (nlhrReply != NULL)
		{
			if (nlhrReply->resultCode != 200) 
			{
				NetlibHttpSetLastErrorUsingHttpResult(nlhrReply->resultCode);
				res = false;
			}
			NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply);
		}
		else
			res = false;
	}

	NetlibDeleteNestedCS(&nlcSend.ncsSend);
	NetlibDeleteNestedCS(&nlcSend.ncsRecv);
	CloseHandle(nlcSend.hOkToCloseEvent);

	nlc->s2 = nlcSend.s;
	mir_free((char*)nlcSend.nloc.szHost);

	EnterCriticalSection(&nlc->csHttpSequenceNums);

	nlc->nlhpi.firstPostSequence++;
	if (nlc->nlhpi.flags & NLHPIF_GETPOSTSAMESEQUENCE) nlc->nlhpi.firstGetSequence++;

	LeaveCriticalSection(&nlc->csHttpSequenceNums);

	return res;
}
Esempio n. 4
0
static bool NetlibHttpGatewayOscarPost(NetlibConnection *nlc, const char *buf, int len, int flags)
{
	NetlibConnection *nlcSend = new NetlibConnection();
	nlcSend->nlu = nlc->nlu;
	nlcSend->nlhpi = nlc->nlhpi;
	nlcSend->s = nlc->s2;
	nlcSend->usingHttpGateway = nlc->usingHttpGateway;
	nlcSend->szProxyServer = nlc->szProxyServer;
	nlcSend->wProxyPort = nlc->wProxyPort;
	nlcSend->proxyType = nlc->proxyType;
	if (!NetlibReconnect(nlcSend)) {
		delete nlcSend;
		return false;
	}

	nlc->s2 = nlcSend->s;

	bool res = NetlibHttpGatewaySend(nlcSend, reqOldPost, buf, len);
	if (res) {
		NETLIBHTTPREQUEST *nlhrReply = NetlibHttpRecv(nlcSend, flags | MSG_RAW | MSG_DUMPPROXY, MSG_RAW | MSG_DUMPPROXY);
		if (nlhrReply != NULL) {
			if (nlhrReply->resultCode != 200) {
				NetlibHttpSetLastErrorUsingHttpResult(nlhrReply->resultCode);
				res = false;
			}
			NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply);
		}
		else res = false;
	}

	nlc->s2 = nlcSend->s;
	delete nlcSend;

	mir_cslock lck(nlc->csHttpSequenceNums);
	nlc->nlhpi.firstPostSequence++;
	if (nlc->nlhpi.flags & NLHPIF_GETPOSTSAMESEQUENCE)
		nlc->nlhpi.firstGetSequence++;

	return res;
}
Esempio n. 5
0
INT_PTR NetlibHttpRecvHeaders(WPARAM wParam, LPARAM lParam)
{
	NetlibConnection *nlc = (struct NetlibConnection*)wParam;
	if (!NetlibEnterNestedCS(nlc, NLNCS_RECV))
		return 0;

	char *peol, *pbuffer;
	int headersCount = 0, bufferSize = 8192;

	DWORD dwRequestTimeoutTime = GetTickCount() + HTTPRECVDATATIMEOUT;
	NETLIBHTTPREQUEST *nlhr = (NETLIBHTTPREQUEST*)mir_calloc(sizeof(NETLIBHTTPREQUEST));
	nlhr->cbSize = sizeof(NETLIBHTTPREQUEST);
	nlhr->nlc = nlc;  // Needed to id connection in the protocol HTTP gateway wrapper functions
	nlhr->requestType = REQUEST_RESPONSE;

	int firstLineLength = 0;
	if (!HttpPeekFirstResponseLine(nlc, dwRequestTimeoutTime, lParam | MSG_PEEK, &nlhr->resultCode, &nlhr->szResultDescr, &firstLineLength)) {
		NetlibLeaveNestedCS(&nlc->ncsRecv);
		NetlibHttpFreeRequestStruct(0, (LPARAM)nlhr);
		return 0;
	}

	char *buffer = (char*)mir_alloc(bufferSize + 1);
	int bytesPeeked = NLRecv(nlc, buffer, min(firstLineLength, bufferSize), lParam | MSG_DUMPASTEXT);
	if (bytesPeeked != firstLineLength) {
		NetlibLeaveNestedCS(&nlc->ncsRecv);
		NetlibHttpFreeRequestStruct(0, (LPARAM)nlhr);
		if (bytesPeeked != SOCKET_ERROR) SetLastError(ERROR_HANDLE_EOF);
		mir_free(buffer);
		return 0;
	}

	// Make sure all headers arrived
	bytesPeeked = 0;
	for (bool headersCompleted = false; !headersCompleted;) {
		if (bytesPeeked >= bufferSize) {
			bufferSize += 8192;
			mir_free(buffer);
			if (bufferSize > 32 * 1024) {
				bytesPeeked = 0;
				break;
			}
			buffer = (char*)mir_alloc(bufferSize + 1);
		}

		bytesPeeked = RecvWithTimeoutTime(nlc, dwRequestTimeoutTime, buffer, bufferSize, MSG_PEEK | MSG_NODUMP | lParam);
		if (bytesPeeked == 0)
			break;

		if (bytesPeeked == SOCKET_ERROR) {
			bytesPeeked = 0;
			break;
		}
		buffer[bytesPeeked] = 0;

		for (pbuffer = buffer, headersCount = 0;; pbuffer = peol + 1, ++headersCount) {
			peol = strchr(pbuffer, '\n');
			if (peol == NULL) break;
			if (peol == pbuffer || (peol == (pbuffer + 1) && *pbuffer == '\r')) {
				bytesPeeked = peol - buffer + 1;
				headersCompleted = true;
				break;
			}
		}
	}

	// Receive headers
	if (bytesPeeked > 0)
		bytesPeeked = NLRecv(nlc, buffer, bytesPeeked, lParam | MSG_DUMPASTEXT);
	if (bytesPeeked <= 0) {
		NetlibLeaveNestedCS(&nlc->ncsRecv);
		NetlibHttpFreeRequestStruct(0, (LPARAM)nlhr);
		mir_free(buffer);
		return 0;
	}
	buffer[bytesPeeked] = 0;

	nlhr->headersCount = headersCount;
	nlhr->headers = (NETLIBHTTPHEADER*)mir_calloc(sizeof(NETLIBHTTPHEADER) * headersCount);

	for (pbuffer = buffer, headersCount = 0;; pbuffer = peol + 1, ++headersCount) {
		peol = strchr(pbuffer, '\n');
		if (peol == NULL || peol == pbuffer || (peol == (pbuffer + 1) && *pbuffer == '\r')) break;
		*peol = 0;

		char *pColon = strchr(pbuffer, ':');
		if (pColon == NULL) {
			NetlibHttpFreeRequestStruct(0, (LPARAM)nlhr); nlhr = NULL;
			SetLastError(ERROR_INVALID_DATA);
			break;
		}

		*(pColon++) = 0;
		nlhr->headers[headersCount].szName = mir_strdup(rtrim(pbuffer));
		nlhr->headers[headersCount].szValue = mir_strdup(lrtrimp(pColon));
	}

	NetlibLeaveNestedCS(&nlc->ncsRecv);
	mir_free(buffer);
	return (INT_PTR)nlhr;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
NETLIBHTTPREQUEST* NetlibHttpRecv(NetlibConnection *nlc, DWORD hflags, DWORD dflags, bool isConnect)
{
	int dataLen = -1, i, chunkhdr = 0;
	bool chunked = false;
	int cenc = 0, cenctype = 0, close = 0;

next:
	NETLIBHTTPREQUEST *nlhrReply = (NETLIBHTTPREQUEST*)NetlibHttpRecvHeaders((WPARAM)nlc, hflags);
	if (nlhrReply == NULL)
		return NULL;

	if (nlhrReply->resultCode == 100) {
		NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply);
		goto next;
	}

	for (i = 0; i < nlhrReply->headersCount; i++) {
		NETLIBHTTPHEADER &p = nlhrReply->headers[i];
		if (!mir_strcmpi(p.szName, "Content-Length"))
			dataLen = atoi(p.szValue);

		if (!mir_strcmpi(p.szName, "Content-Encoding")) {
			cenc = i;
			if (strstr(p.szValue, "gzip"))
				cenctype = 1;
			else if (strstr(p.szValue, "deflate"))
				cenctype = 2;
		}

		if (!mir_strcmpi(p.szName, "Connection"))
			close = !mir_strcmpi(p.szValue, "close");

		if (!mir_strcmpi(p.szName, "Transfer-Encoding") && !mir_strcmpi(p.szValue, "chunked")) {
			chunked = true;
			chunkhdr = i;
			dataLen = -1;
		}
	}

	if (nlhrReply->resultCode >= 200 && (dataLen > 0 || (!isConnect && dataLen < 0))) {
		int recvResult, chunksz = -1;
		int dataBufferAlloced;

		if (chunked) {
			chunksz = NetlibHttpRecvChunkHeader(nlc, true, dflags);
			if (chunksz == SOCKET_ERROR) {
				NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply);
				return NULL;
			}
			dataLen = chunksz;
		}
		dataBufferAlloced = dataLen < 0 ? 2048 : dataLen + 1;
		nlhrReply->pData = (char*)mir_realloc(nlhrReply->pData, dataBufferAlloced);

		while (chunksz != 0) {
			while (true) {
				recvResult = RecvWithTimeoutTime(nlc, GetTickCount() + HTTPRECVDATATIMEOUT,
					nlhrReply->pData + nlhrReply->dataLength,
					dataBufferAlloced - nlhrReply->dataLength - 1,
					dflags | (cenctype ? MSG_NODUMP : 0));

				if (recvResult == 0) break;
				if (recvResult == SOCKET_ERROR) {
					NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply);
					return NULL;
				}
				nlhrReply->dataLength += recvResult;

				if (dataLen >= 0) {
					if (nlhrReply->dataLength >= dataLen)
						break;
				}
				else if ((dataBufferAlloced - nlhrReply->dataLength) < 256) {
					dataBufferAlloced += 2048;
					nlhrReply->pData = (char*)mir_realloc(nlhrReply->pData, dataBufferAlloced);
					if (nlhrReply->pData == NULL) {
						SetLastError(ERROR_OUTOFMEMORY);
						NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply);
						return NULL;
					}
				}
				Sleep(10);
			}

			if (!chunked)
				break;

			chunksz = NetlibHttpRecvChunkHeader(nlc, false, dflags);
			if (chunksz == SOCKET_ERROR) {
				NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply);
				return NULL;
			}
			dataLen += chunksz;
			dataBufferAlloced += chunksz;

			nlhrReply->pData = (char*)mir_realloc(nlhrReply->pData, dataBufferAlloced);
		}

		nlhrReply->pData[nlhrReply->dataLength] = '\0';
	}

	if (chunked) {
		nlhrReply->headers[chunkhdr].szName = (char*)mir_realloc(nlhrReply->headers[chunkhdr].szName, 16);
		mir_strcpy(nlhrReply->headers[chunkhdr].szName, "Content-Length");

		nlhrReply->headers[chunkhdr].szValue = (char*)mir_realloc(nlhrReply->headers[chunkhdr].szValue, 16);
		mir_snprintf(nlhrReply->headers[chunkhdr].szValue, 16, "%u", nlhrReply->dataLength);
	}

	if (cenctype) {
		int bufsz = nlhrReply->dataLength;
		char* szData = NULL;

		switch (cenctype) {
		case 1:
			szData = gzip_decode(nlhrReply->pData, &bufsz, 0x10 | MAX_WBITS);
			break;

		case 2:
			szData = gzip_decode(nlhrReply->pData, &bufsz, -MAX_WBITS);
			if (bufsz < 0) {
				bufsz = nlhrReply->dataLength;
				szData = gzip_decode(nlhrReply->pData, &bufsz, MAX_WBITS);
			}
			break;
		}

		if (bufsz > 0) {
			NetlibDumpData(nlc, (PBYTE)szData, bufsz, 0, dflags);
			mir_free(nlhrReply->pData);
			nlhrReply->pData = szData;
			nlhrReply->dataLength = bufsz;

			mir_free(nlhrReply->headers[cenc].szName);
			mir_free(nlhrReply->headers[cenc].szValue);
			memmove(&nlhrReply->headers[cenc], &nlhrReply->headers[cenc+1], (--nlhrReply->headersCount-cenc)*sizeof(nlhrReply->headers[0]));
		}
		else if (bufsz == 0) {
			mir_free(nlhrReply->pData);
			nlhrReply->pData = NULL;
			nlhrReply->dataLength = 0;
		}
	}

	if (close &&
		(nlc->proxyType != PROXYTYPE_HTTP || nlc->nloc.flags & NLOCF_SSL) &&
		(!isConnect || nlhrReply->resultCode != 200))
		NetlibDoClose(nlc);

	return nlhrReply;
}
Esempio n. 8
0
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);
	}

	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 && nlc->nlu->user.pfnHttpGatewayWrapSend != NULL)
			{
				if (nlc->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 (nlc->nlu->user.pfnHttpGatewayUnwrapRecv && !(flags & MSG_NOHTTPGATEWAYWRAP))
		{
			nlhrReply->pData = (char*)nlc->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(nlc->nlu, "Error received from proxy, retrying");
				continue;
			}
			else
			{
				NetlibLogf(nlc->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;
}