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; }
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; }
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; }
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; }
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; }
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; }