Files
TCP_CLIENT_WIN_LIN/socksproxyclient.cpp
2019-07-24 13:51:15 +02:00

517 lines
15 KiB
C++

//#include "stdafx.h"
#include "socksproxyclient.h"
using namespace std;
CSocksProxyClient::CSocksProxyClient(void)
: m_nProxyPort(0)
{
m_sv = SOCKS_V4;
memset(&m_proxyaddress,0,sizeof(m_proxyaddress));
m_sockDescriptor = 0;
m_szProxyServer = new char[512];
m_szErrorMsg = new char[512];
m_szUserName = new char[512];
m_szPassword = new char[512];
}
CSocksProxyClient::~CSocksProxyClient(void)
{
if (m_szErrorMsg != nullptr)
{
delete m_szErrorMsg;
}
if (m_szUserName != nullptr)
{
delete m_szUserName;
}
if (m_szPassword != nullptr)
{
delete m_szPassword;
}
CloseSocket();
}
void CSocksProxyClient::SetSocksVersion(SOCKS_VERSION sv)
{
m_sv = sv;
}
// Sets the proxy server and port to use in subsequent calls
bool CSocksProxyClient::SetProxy(char* szProxy, int nProxyPort/*=1080*/)
{
strcpy(m_szProxyServer, szProxy);
m_nProxyPort = nProxyPort;
struct hostent *he;
//attempt to resolve the proxy
if( !( he = gethostbyname( m_szProxyServer ) ) ){
strcpy(m_szErrorMsg, "Could not resolve proxy");
return false;
}
//store proxy info to avoid lookup later
m_proxyaddress.sin_family = AF_INET;
m_proxyaddress.sin_port = htons(static_cast<uint16_t>(m_nProxyPort));
m_proxyaddress.sin_addr = *( reinterpret_cast<struct in_addr *>( he->h_addr ) );
memset(&(m_proxyaddress.sin_zero ), '\0', 8 ); //clear the struct
std::cout << "ip of server: " << inet_ntoa( m_proxyaddress.sin_addr ) << std::endl;
strcpy(m_szErrorMsg,"Success");
return true;
}
// returns the socket descriptor to use for send / recv calls
#ifdef Windows
SOCKET CSocksProxyClient::GetSocket(void)
#else
int CSocksProxyClient::GetSocket(void)
#endif
{
return m_sockDescriptor;
}
// sets the username to use for authorization
void CSocksProxyClient::SetUserName(char* szUserName)
{
strcpy(m_szUserName,szUserName);
}
// sets the password to use for V5 Authorization
void CSocksProxyClient::SetPassword(char* szPassword)
{
strcpy(m_szPassword,szPassword);
}
// returns the error message
char* CSocksProxyClient::GetErrorMessage(void)
{
return m_szErrorMsg;
}
// closes the socket
void CSocksProxyClient::CloseSocket(void)
{
#ifdef Windows
if (m_sockDescriptor != 0 ) {
closesocket(m_sockDescriptor);
m_sockDescriptor = 0;
strcpy(m_szErrorMsg,"Success");
}
#else
if (m_sockDescriptor != 0 ) {
close(m_sockDescriptor);
m_sockDescriptor = 0;
strcpy(m_szErrorMsg,"Success");
}
#endif
else
strcpy(m_szErrorMsg,"Invalid Socket");
}
char *strlwr(char *str)
{
unsigned char *p = reinterpret_cast<unsigned char*>(str);
while (*p) {
*p = static_cast<unsigned char>(tolower(static_cast<unsigned char>(*p)));
p++;
}
return str;
}
/*
in_addr_t make_inaddr(
unsigned char a1,
unsigned char a2,
unsigned char a3,
unsigned char a4)
{
in_addr_t result;
result = htonl(((uint32_t)a1 << 24)
| ((uint32_t)a2 << 16)
| ((uint32_t)a3 << 8)
| a4);
return result;
}*/
// connects to the specified domain at the given port
bool CSocksProxyClient::Connect(char* szDomain/*=nullptr*/, int nDomainPort/*=80*/)
{
if((m_sockDescriptor = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
strcpy(m_szErrorMsg, "Could not establish socket connection.");
return false;
}
std::cout << "Socket created" << std::endl;
if (m_proxyaddress.sin_port == 0x00)
{
strcpy(m_szErrorMsg,"Proxy Information not set");
return false;
}
if ((szDomain == nullptr) || (strcmp(szDomain,"") == 0))
{
strcpy(m_szErrorMsg,"Invalid domain string");
return false;
}
std::cout << "connect..." << std::endl;
// Code for proxy authentication if allowed by proxy server:
if(connect(m_sockDescriptor, reinterpret_cast<struct sockaddr *>(&m_proxyaddress), sizeof(struct sockaddr)) == -1)
{
strcpy(m_szErrorMsg,"Could not connect to proxy.");
return false;
}
std::cout << "Connected." << std::endl;
unsigned char msg[512];//generally we don't need a big array but domains names can be long some times.
szDomain = strlwr(szDomain);
size_t nlen = 0;
if (m_sv == SOCKS_V4)
{
struct hostent *he;
short dw = static_cast<short>( nDomainPort );
msg[0] = 0x04;
msg[1] = 0x01;
msg[2] = static_cast<unsigned char>(dw>>8);
msg[3] = static_cast<unsigned char>(dw);
if( !( he = gethostbyname( szDomain ) ) ){
strcpy(m_szErrorMsg,"Could not resolve domain");
return false;
}
#ifdef Windows1
struct sockaddr_in dest;
memcpy(&(dest.sin_addr), he->h_addr_list[0], he->h_length);
msg[4] = dest.sin_addr.S_un.S_un_b.s_b1;
msg[5] = dest.sin_addr.S_un.S_un_b.s_b2;
msg[6] = dest.sin_addr.S_un.S_un_b.s_b3;
msg[7] = dest.sin_addr.S_un.S_un_b.s_b4;
#else
std::string ip = szDomain + std::string(".");
size_t pos = 0;
int arrayPos = 3;
std::cout << ip << std::endl;
for (pos = ip.find("."); pos != std::string::npos; pos = ip.find(".")) {
arrayPos++;
if(arrayPos == 8)
break;
msg[arrayPos] = static_cast<unsigned char>(atoi(ip.substr(0, pos).c_str()));
std::cout << "[" << arrayPos << "]: " << std::hex << static_cast<int>( msg[arrayPos] ) << std::dec <<"==" << atoi(ip.substr(0, pos).c_str()) << std::endl;
ip.erase(0, pos +1);
}
#endif
if (m_szUserName != nullptr) {
strcpy(reinterpret_cast<char*>(&msg[8]), m_szUserName);
msg[8+strlen(m_szUserName)] = 0x00;
nlen = 8 + strlen(m_szUserName) +1 ;
} else {
msg[8] = 0x00;
nlen = 9;
}
if (send(m_sockDescriptor, reinterpret_cast<char*>( msg ), nlen, 0) == -1)
{
strcpy(m_szErrorMsg,"Error sending message");
return false;
}
if(recv(m_sockDescriptor, reinterpret_cast<char*>( msg ), 8, 0) <= 0)
std::cout << "recv failed in socks4" << std::endl;
if (msg[1] == 0x5a)
{
strcpy(m_szErrorMsg,"request granted");
return true;
}
else if (msg[1] == 0x5b)
{
strcpy(m_szErrorMsg,"request rejected or failed");
return false;
}
else if (msg[1] == 0x5c)
{
strcpy(m_szErrorMsg,"failed: client is not running identd");
return false;
}
else if (msg[1] == 0x5d)
{
strcpy(m_szErrorMsg,"failed: could not confirm the user id string in the request");
return false;
}
}
else if (m_sv == SOCKS_V4A)
{
msg[0] = 0x04;
msg[1] = 0x01;
short dw = static_cast<short>(nDomainPort);
msg[2] = static_cast<unsigned char>(dw>>8);
msg[3] = static_cast<unsigned char>(dw);
msg[4] = 0x00;
msg[5] = 0x00;
msg[6] = 0x00;
msg[7] = 0xFF;
if (m_szUserName != nullptr)
{
strcpy(reinterpret_cast<char*>(&msg[8]), m_szUserName);
msg[ 8 + strlen(m_szUserName) ] = 0x00;
nlen = 9 + strlen(m_szUserName);
if (send(m_sockDescriptor,(char*)msg,nlen,0) == -1) {
strcpy(m_szErrorMsg,"Error sending message");
return false;
}
strcpy(reinterpret_cast<char*>(msg), szDomain);
msg[strlen(szDomain)] = 0x00;
nlen = strlen(szDomain) + 1;
}
else
{
msg[8] = 0x0;
nlen = 9;
if (send(m_sockDescriptor,reinterpret_cast<char*>( msg ),nlen,0) == -1)
{
strcpy(m_szErrorMsg,"Error sending message");
return false;
}
strcpy(reinterpret_cast<char*>( msg ), szDomain);
msg[strlen(szDomain)] = 0x00;
nlen = strlen(szDomain) + 1;
}
if (send(m_sockDescriptor,reinterpret_cast<char*>( msg ), nlen, 0) == -1) {
strcpy(m_szErrorMsg,"Error sending message");
return false;
} else if(recv(m_sockDescriptor,reinterpret_cast<char*>( msg ), 8, 0) <= 0 ) {
perror("recv failed");
return false;
} else if (msg[1] == 0x5a) {
strcpy(m_szErrorMsg,"request granted");
return true;
} else if (msg[1] == 0x5b) {
strcpy(m_szErrorMsg,"request rejected or failed");
return false;
} else if (msg[1] == 0x5c) {
strcpy(m_szErrorMsg,"failed: client is not running identd");
return false;
} else if (msg[1] == 0x5d) {
strcpy(m_szErrorMsg,"failed: could not confirm the user id string in the request");
return false;
}
}
else if (m_sv == SOCKS_V5)
{
msg[0] = 0x05;
msg[1] = 0x02;
msg[2] = 0x00;
msg[3] = 0x02;
std::cout << "send to proxy msg..." << std::endl;
if (send(m_sockDescriptor,reinterpret_cast<char*>( msg ), 4, 0) == -1) {
strcpy(m_szErrorMsg,"Error sending message");
return false;
}
std::cout << "OK\nRecv from Proxy..." << std::endl;
if( recv(m_sockDescriptor,reinterpret_cast<char*>( msg ), 2, 0) <= 0) {
std::cout << "Recv failed" << std::endl;
}
std::cout << "OK" << std::endl;
if (msg[1] == 0x00) { //no authentication
std::cout << "No Autentifikation" << std::endl;
msg[0] = 0x04;
msg[1] = 0x01;
msg[2] = 0x00;
msg[3] = 0x03;
msg[4] = static_cast<unsigned char>(strlen(szDomain));
strcpy(reinterpret_cast<char*>( &msg[5] ), szDomain);
nlen = strlen(szDomain) + 5;
short dw = static_cast<short>( nDomainPort );
msg[nlen++] = static_cast<unsigned char>(dw>>8);
msg[nlen++] = static_cast<unsigned char>(dw);
}
else if (msg[1] == 0x02)//username/password authentication
{
std::cout << "need Autentifikation" << std::endl;
msg[0] = 0x01;
msg[1] = (unsigned char)(int)strlen(m_szUserName);
strcpy(reinterpret_cast<char*>( &msg[2]), m_szUserName);
nlen = 2+msg[1];
msg[nlen++] = static_cast<unsigned char>(strlen(m_szPassword));
strcpy(reinterpret_cast<char*>(&msg[nlen]), m_szPassword);
nlen += strlen(m_szPassword);
std::cout << "send in autentifk..." << std::endl;
if (send(m_sockDescriptor,(char*)msg,nlen,0) == -1) {
strcpy(m_szErrorMsg,"Error sending message");
return false;
}
std::cout << "recv in autentifk..." << std::endl;
if(recv(m_sockDescriptor,(char*)msg,8,0) <= 0) {
std::cout << "recv in autentifk. failed" << std::endl;
}
if (msg[1] == 0x00) {//status ok so send message
msg[0] = 0x04;
msg[1] = 0x01;
msg[2] = 0x00;
msg[3] = 0x03;
msg[4] = static_cast<unsigned char>(strlen(szDomain));
strcpy(reinterpret_cast<char*>(&msg[5]),szDomain);
nlen = strlen(szDomain)+5;
short dw = static_cast<short>(nDomainPort);
msg[nlen++] = static_cast<unsigned char>(dw>>8);
msg[nlen++] = static_cast<unsigned char>(dw);
} else {
#ifdef Windows
closesocket(m_sockDescriptor);
#else
close(m_sockDescriptor);
#endif
strcpy(m_szErrorMsg,"Error Authenticating User");
return false;
}
} else {
strcpy(m_szErrorMsg,"Authentication Method not supported");
return false;
}
if (send(m_sockDescriptor,reinterpret_cast<char*>( msg ), nlen,0) == -1) {
strcpy(m_szErrorMsg,"Error sending message");
return false;
} else if( recv(m_sockDescriptor,(char*)msg,8,0) <= 0 ) {
std::cout << "recv 2 failed" << std::endl;
return false;
} else if (msg[1] == 0x00) {
strcpy(m_szErrorMsg,"request granted");
return true;
} else if (msg[1] == 0x01) {
strcpy(m_szErrorMsg,"request rejected or failed");
return false;
} else if (msg[1] == 0x02) {
strcpy(m_szErrorMsg,"failed: connection not allowed by ruleset");
return false;
} else if (msg[1] == 0x03) {
strcpy(m_szErrorMsg,"failed: network unreachable");
return false;
} else if (msg[1] == 0x04) {
strcpy(m_szErrorMsg,"failed: host unreachable");
return false;
} else if (msg[1] == 0x05) {
strcpy(m_szErrorMsg,"failed: connection refused by destination host");
return false;
} else if (msg[1] == 0x06) {
strcpy(m_szErrorMsg,"failed: TTL expired");
return false;
} else if (msg[1] == 0x07) {
strcpy(m_szErrorMsg,"failed: command not supported / protocol error");
return false;
} else if (msg[1] == 0x08){
strcpy(m_szErrorMsg,"failed: address type not supported");
return false;
}
}
strcpy(m_szErrorMsg,"Success");
return true;
}
// receives a message from the server
bool CSocksProxyClient::Recv(char* szBuffer, size_t nLen, int nTimeout/*=0*/)
{
if (recv(m_sockDescriptor,szBuffer,nLen,nTimeout) == -1)
{
strcpy(m_szErrorMsg,"Error receiving message");
return false;
}
strcpy(m_szErrorMsg,"Success");
return true;
}
// sends a message to the socks proxy
bool CSocksProxyClient::Send(char* szBuffer, size_t nLength, int nFlags/*=0*/)
{
if (send(m_sockDescriptor,szBuffer,nLength,nFlags) == -1)
{
strcpy(m_szErrorMsg,"Error sending message");
return false;
}
strcpy(m_szErrorMsg,"Success");
return true;
}
// Reads a line of text from the servers response
char *CSocksProxyClient::ReadLine()
{
if (m_sockDescriptor <= 0)
{
strcpy(m_szErrorMsg,"Invalid Socket");
return nullptr;
}
vector<char> vText;
char buffer[1];
//int unsigned charsReceived;
while (true) {
ssize_t charsReceived = recv(m_sockDescriptor, buffer, 1, 0);
if( charsReceived <= 0)
{
strcpy(m_szErrorMsg,"No Message To Recieve");
return nullptr;
}
if(buffer[0] == '\n') {
char *pChar = new char[vText.size() + 1];
memset(pChar, 0, vText.size() + 1);
for (int f = 0; f < static_cast<int>(vText.size()); f++)
pChar[f] = vText[static_cast<std::vector<char>::size_type>(f)];
strcpy(m_szErrorMsg,"Success");
return pChar;
}
else
{
vText.push_back(buffer[0]);
}
}
}