Beispiel #1
0
static int NetlibInitSocks4Connection(NetlibConnection *nlc, NetlibUser *nlu, NETLIBOPENCONNECTION *nloc)
{	
	//	http://www.socks.nec.com/protocol/socks4.protocol and http://www.socks.nec.com/protocol/socks4a.protocol
	if (!nloc->szHost || !nloc->szHost[0]) return 0;

	size_t nHostLen = strlen(nloc->szHost) + 1;
	size_t nUserLen = nlu->settings.szProxyAuthUser ? strlen(nlu->settings.szProxyAuthUser) + 1 : 1;
	size_t len = 8 + nUserLen;

	char* pInit = (char*)alloca(len + nHostLen);
	pInit[0] = 4;	// SOCKS4
	pInit[1] = 1;	//connect
	*(PWORD)&pInit[2] = htons(nloc->wPort);

	if (nUserLen <= 1) pInit[8] = 0;
	else memcpy(&pInit[8], nlu->settings.szProxyAuthUser, nUserLen);

	//if cannot resolve host, try resolving through proxy (requires SOCKS4a)  
	DWORD ip = DnsLookup(nlu, nloc->szHost);
	*(PDWORD)&pInit[4] = ip ? ip : 0x01000000; 	
	if (!ip) 
	{
		memcpy(&pInit[len], nloc->szHost, nHostLen);
		len += nHostLen;
	}

	if (NLSend(nlc, pInit, (int)len, MSG_DUMPPROXY) == SOCKET_ERROR) 
	{
		NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"NLSend",GetLastError());
		return 0;
	}

	char reply[8];
	if (!RecvUntilTimeout(nlc, reply, sizeof(reply), MSG_DUMPPROXY, RECV_DEFAULT_TIMEOUT)) 
	{
		NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"RecvUntilTimeout",GetLastError());
		return 0;
	}

	switch ((BYTE)reply[1]) 
	{
	case 90: return 1;
	case 91: SetLastError(ERROR_ACCESS_DENIED); break;
	case 92: SetLastError(ERROR_CONNECTION_UNAVAIL); break;
	case 93: SetLastError(ERROR_INVALID_ACCESS); break;
	default: SetLastError(ERROR_INVALID_DATA); break;
	}
	NetlibLogf(nlu,"%s %d: Proxy connection failed (%x %u)",__FILE__,__LINE__, (BYTE)reply[1], GetLastError());
	return 0;
}
Beispiel #2
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;
}
Beispiel #3
0
static int NetlibHttpFallbackToDirect(struct NetlibConnection *nlc, struct NetlibUser *nlu, NETLIBOPENCONNECTION *nloc)
{
	NetlibDoClose(nlc, true);

	NetlibLogf(nlu,"Fallback to direct connection");
	NetlibLogf(nlu,"(%p) Connecting to server %s:%d....", nlc, nloc->szHost, nloc->wPort);

	nlc->proxyAuthNeeded = false;
	nlc->proxyType = 0;
	mir_free(nlc->szProxyServer); nlc->szProxyServer = NULL;
	nlc->sinProxy.sin_family = AF_INET;
	nlc->sinProxy.sin_port = htons(nloc->wPort);
	nlc->sinProxy.sin_addr.S_un.S_addr = DnsLookup(nlu, nloc->szHost);
	if (nlc->sinProxy.sin_addr.S_un.S_addr == 0 || my_connect(nlc, nloc) == SOCKET_ERROR) 
	{
		if (nlc->sinProxy.sin_addr.S_un.S_addr)
			NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "connect", WSAGetLastError());
		return false;
	}
	return true;
}
Beispiel #4
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;
}
Beispiel #5
0
bool NetlibDoConnect(NetlibConnection *nlc)
{
	NETLIBOPENCONNECTION *nloc = &nlc->nloc;
	NetlibUser *nlu = nlc->nlu;

	nlc->sinProxy.sin_family = AF_INET;
	mir_free(nlc->szProxyServer); nlc->szProxyServer = NULL;

	bool usingProxy = false, forceHttps = false;
	if (nlu->settings.useProxy)
	{
		if (nlu->settings.proxyType == PROXYTYPE_IE)
		{
			usingProxy = NetlibGetIeProxyConn(nlc, false);
		}
		else
		{
			if (nlu->settings.szProxyServer && nlu->settings.szProxyServer[0])
			{
				nlc->szProxyServer = mir_strdup(nlu->settings.szProxyServer);
				nlc->wProxyPort = nlu->settings.wProxyPort;
				nlc->proxyType = nlu->settings.proxyType;
				usingProxy = true;
			}
		}
	}

retry:
	if (usingProxy) 
	{
		NetlibLogf(nlu,"(%p) Resolving proxy %s:%d for %s:%d ....", nlc, nlc->szProxyServer, nlc->wProxyPort, nloc->szHost, nloc->wPort);
		nlc->sinProxy.sin_port = htons(nlc->wProxyPort);
		nlc->sinProxy.sin_addr.S_un.S_addr = DnsLookup(nlu, nlc->szProxyServer);
		if (nlc->sinProxy.sin_addr.S_un.S_addr == 0) 
		{
			usingProxy = false;
			nlc->proxyType = 0;
		}
	}
	if (!usingProxy)
	{
		NetlibLogf(nlu,"(%p) Connecting to server %s:%d....", nlc, nloc->szHost, nloc->wPort);
		nlc->sinProxy.sin_port = htons(nloc->wPort);
		nlc->sinProxy.sin_addr.S_un.S_addr = DnsLookup(nlu, nloc->szHost);
	}
	else
		NetlibLogf(nlu,"(%p) Connecting to proxy %s:%d for %s:%d ....", nlc, nlc->szProxyServer, nlc->wProxyPort, nloc->szHost, nloc->wPort);

	if (nlc->sinProxy.sin_addr.S_un.S_addr == 0) return false;

	if (my_connect(nlc, nloc) == SOCKET_ERROR) 
	{
		if (usingProxy && (nlc->proxyType == PROXYTYPE_HTTPS || nlc->proxyType == PROXYTYPE_HTTP))
		{
			usingProxy = false;
			if (!NetlibHttpFallbackToDirect(nlc, nlu, nloc))
			{
				NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "connect", WSAGetLastError());
				return false;
			}
		}
		else
		{
			if (nlu->settings.useProxy && !usingProxy && nlu->settings.proxyType == PROXYTYPE_IE && !forceHttps)
			{
				forceHttps = true;
				usingProxy = NetlibGetIeProxyConn(nlc, true);
				if (usingProxy) goto retry;
			}
			NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "connect", WSAGetLastError());
			return false;
		}
	}

	if (usingProxy && !((nloc->flags & (NLOCF_HTTP | NLOCF_SSL)) == NLOCF_HTTP && 
		(nlc->proxyType == PROXYTYPE_HTTP || nlc->proxyType == PROXYTYPE_HTTPS)))
	{
		if (!WaitUntilWritable(nlc->s, 30000)) return false;

		switch (nlc->proxyType) 
		{
		case PROXYTYPE_SOCKS4:
			if (!NetlibInitSocks4Connection(nlc, nlu, nloc)) return false;
			break;

		case PROXYTYPE_SOCKS5:
			if (!NetlibInitSocks5Connection(nlc, nlu, nloc)) return false;
			break;

		case PROXYTYPE_HTTPS:
			nlc->proxyAuthNeeded = true;
			if (!NetlibInitHttpsConnection(nlc, nlu, nloc))
			{
				usingProxy = false;
				if (!NetlibHttpFallbackToDirect(nlc, nlu, nloc))
					return false;
			}
			break;

		case PROXYTYPE_HTTP:
			nlc->proxyAuthNeeded = true;
			if (!(nlu->user.flags & NUF_HTTPGATEWAY || nloc->flags & NLOCF_HTTPGATEWAY) || nloc->flags & NLOCF_SSL)
			{
				//NLOCF_HTTP not specified and no HTTP gateway available: try HTTPS
				if (!NetlibInitHttpsConnection(nlc, nlu, nloc))
				{
					//can't do HTTPS: try direct
					usingProxy = false;
					if (!NetlibHttpFallbackToDirect(nlc, nlu, nloc))
						return false;
				}
			}
			else 
			{
				if (!NetlibInitHttpConnection(nlc, nlu, nloc)) return false;
			}
			break;

		default:
			SetLastError(ERROR_INVALID_PARAMETER);
			FreePartiallyInitedConnection(nlc);
			return false;
		}
	}
	else if (nloc->flags & NLOCF_HTTPGATEWAY)
	{
		if (!NetlibInitHttpConnection(nlc, nlu, nloc)) return false;
		nlc->usingDirectHttpGateway = true;
	}

	NetlibLogf(nlu,"(%d) Connected to %s:%d", nlc->s, nloc->szHost, nloc->wPort);

	if (NLOCF_SSL & nloc->flags)
	{
		return NetlibStartSsl((WPARAM)nlc, 0) != 0;
	}

	return true;
}
Beispiel #6
0
static int NetlibInitSocks5Connection(struct NetlibConnection *nlc,struct NetlibUser *nlu,NETLIBOPENCONNECTION *nloc)
{	//rfc1928
	BYTE buf[258];

	buf[0]=5;  //yep, socks5
	buf[1]=1;  //one auth method
	buf[2]=nlu->settings.useProxyAuth?2:0;
	if(NLSend(nlc,(char*)buf,3,MSG_DUMPPROXY)==SOCKET_ERROR) {
		NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"NLSend",GetLastError());
		return 0;
	}

	//confirmation of auth method
	if (!RecvUntilTimeout(nlc,(char*)buf,2,MSG_DUMPPROXY,RECV_DEFAULT_TIMEOUT)) {
		NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"RecvUntilTimeout",GetLastError());
		return 0;
	}
	if((buf[1]!=0 && buf[1]!=2)) {
		SetLastError(ERROR_INVALID_ID_AUTHORITY);
		NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"NLRecv",GetLastError());
		return 0;
	}

	if(buf[1]==2) {		//rfc1929
		int nUserLen,nPassLen;
		PBYTE pAuthBuf;

		nUserLen=lstrlenA(nlu->settings.szProxyAuthUser);
		nPassLen=lstrlenA(nlu->settings.szProxyAuthPassword);
		pAuthBuf=(PBYTE)mir_alloc(3+nUserLen+nPassLen);
		pAuthBuf[0]=1;		//auth version
		pAuthBuf[1]=nUserLen;
		memcpy(pAuthBuf+2,nlu->settings.szProxyAuthUser,nUserLen);
		pAuthBuf[2+nUserLen]=nPassLen;
		memcpy(pAuthBuf+3+nUserLen,nlu->settings.szProxyAuthPassword,nPassLen);
		if(NLSend(nlc,(char*)pAuthBuf,3+nUserLen+nPassLen,MSG_DUMPPROXY)==SOCKET_ERROR) {
			NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"NLSend",GetLastError());
			mir_free(pAuthBuf);
			return 0;
		}
		mir_free(pAuthBuf);

		if (!RecvUntilTimeout(nlc,(char*)buf,2,MSG_DUMPPROXY,RECV_DEFAULT_TIMEOUT)) {
			NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"RecvUntilTimeout",GetLastError());
			return 0;
		}
		if(buf[1]) {
			SetLastError(ERROR_ACCESS_DENIED);
			NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"RecvUntilTimeout",GetLastError());
			return 0;
		}
	}

	{	
		PBYTE pInit;
		int nHostLen;
		DWORD hostIP;

		if(nlc->dnsThroughProxy) {
			if((hostIP=inet_addr(nloc->szHost))==INADDR_NONE)
				nHostLen=lstrlenA(nloc->szHost)+1;
			else nHostLen=4;
		}
		else {
			if((hostIP=DnsLookup(nlu,nloc->szHost))==0)
				return 0;
			nHostLen=4;
		}
		pInit=(PBYTE)mir_alloc(6+nHostLen);
		pInit[0]=5;   //SOCKS5
		pInit[1]= nloc->flags & NLOCF_UDP ? 3 : 1; //connect or UDP
		pInit[2]=0;   //reserved
		if(hostIP==INADDR_NONE) {		 //DNS lookup through proxy
			pInit[3]=3;
			pInit[4]=nHostLen-1;
			memcpy(pInit+5,nloc->szHost,nHostLen-1);
		}
		else {
			pInit[3]=1;
			*(PDWORD)(pInit+4)=hostIP;
		}
		*(PWORD)(pInit+4+nHostLen)=htons(nloc->wPort);
		if(NLSend(nlc,(char*)pInit,6+nHostLen,MSG_DUMPPROXY)==SOCKET_ERROR) {
			NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"NLSend",GetLastError());
			mir_free(pInit);
			return 0;
		}
		mir_free(pInit);
	}

	if (!RecvUntilTimeout(nlc,(char*)buf,5,MSG_DUMPPROXY,RECV_DEFAULT_TIMEOUT)) {
		NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"RecvUntilTimeout",GetLastError());
		return 0;
	}

	if ( buf[0]!=5 || buf[1] ) {
		const char* err = "Unknown response"; 
		if ( buf[0] != 5 )
			SetLastError(ERROR_BAD_FORMAT);
		else
		{
			switch(buf[1]) 
			{
			case 1: SetLastError(ERROR_GEN_FAILURE); err = "General failure"; break;
			case 2: SetLastError(ERROR_ACCESS_DENIED); err = "Connection not allowed by ruleset";  break;
			case 3: SetLastError(WSAENETUNREACH); err = "Network unreachable"; break;
			case 4: SetLastError(WSAEHOSTUNREACH); err = "Host unreachable"; break;
			case 5: SetLastError(WSAECONNREFUSED); err = "Connection refused by destination host"; break;
			case 6: SetLastError(WSAETIMEDOUT); err = "TTL expired"; break;
			case 7: SetLastError(ERROR_CALL_NOT_IMPLEMENTED); err = "Command not supported / protocol error"; break;
			case 8: SetLastError(ERROR_INVALID_ADDRESS); err = "Address type not supported"; break;
			default: SetLastError(ERROR_INVALID_DATA); break;
			}
		}
		NetlibLogf(nlu,"%s %d: Proxy conection failed. %s.",__FILE__,__LINE__, err);
		return 0;
	}
	{
		int nRecvSize = 0;
		switch( buf[3] ) {
		case 1:// ipv4 addr
			nRecvSize = 5;
			break;
		case 3:// dns name addr
			nRecvSize = buf[4] + 2;
			break;
		case 4:// ipv6 addr
			nRecvSize = 17;
			break;
		default:
			NetlibLogf(nlu,"%s %d: %s() unknown address type (%u)",__FILE__,__LINE__,"NetlibInitSocks5Connection",(int)buf[3]);
			return 0;
		}
		if (!RecvUntilTimeout(nlc,(char*)buf,nRecvSize,MSG_DUMPPROXY,RECV_DEFAULT_TIMEOUT)) {
			NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"RecvUntilTimeout",GetLastError());
			return 0;
		}	
	}

	//connected
	return 1;
}