mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-28 08:59:37 -05:00
detached proxy negociation code from pqisslproxy so as to use it in FriendServer as well
This commit is contained in:
parent
896762b948
commit
2456dbb2a0
@ -127,9 +127,6 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st
|
||||
RsSerialiser *rss = new RsSerialiser(); // deleted by ~pqistreamer()
|
||||
rss->addSerialType(fss);
|
||||
|
||||
// FsSerializer().serialise(item,data,&size);
|
||||
// write(CreateSocket,data,size); // shouldn't we use the pqistreamer in R/W mode instead?
|
||||
|
||||
RsFdBinInterface *bio = new RsFdBinInterface(CreateSocket,true); // deleted by ~pqistreamer()
|
||||
|
||||
pqithreadstreamer p(this,rss,RsPeerId(),bio,BIN_FLAGS_READABLE | BIN_FLAGS_WRITEABLE | BIN_FLAGS_NO_CLOSE);
|
||||
|
@ -399,6 +399,7 @@ HEADERS += pqi/authssl.h \
|
||||
pqi/pqissl.h \
|
||||
pqi/pqissllistener.h \
|
||||
pqi/pqisslpersongrp.h \
|
||||
pqi/pqiproxy.h \
|
||||
pqi/pqisslproxy.h \
|
||||
pqi/pqistore.h \
|
||||
pqi/pqistreamer.h \
|
||||
@ -571,6 +572,7 @@ SOURCES += pqi/authgpg.cc \
|
||||
pqi/pqissl.cc \
|
||||
pqi/pqissllistener.cc \
|
||||
pqi/pqisslpersongrp.cc \
|
||||
pqi/pqiproxy.cc \
|
||||
pqi/pqisslproxy.cc \
|
||||
pqi/pqistore.cc \
|
||||
pqi/pqistreamer.cc \
|
||||
|
467
libretroshare/src/pqi/pqiproxy.cc
Normal file
467
libretroshare/src/pqi/pqiproxy.cc
Normal file
@ -0,0 +1,467 @@
|
||||
#include "util/rsdebug.h"
|
||||
#include "util/rsnet.h"
|
||||
|
||||
#include "pqi/pqiproxy.h"
|
||||
|
||||
//#define PROXY_DEBUG 1
|
||||
|
||||
int pqiproxyconnection::proxy_negotiate_connection(int sockfd)
|
||||
{
|
||||
int ret = 0;
|
||||
switch(mProxyState)
|
||||
{
|
||||
case PROXY_STATE_INIT:
|
||||
ret = Proxy_Send_Method(sockfd); // checks basic conn, sends Method when able.
|
||||
break;
|
||||
|
||||
case PROXY_STATE_WAITING_METHOD_RESPONSE:
|
||||
ret = Proxy_Send_Address(sockfd); // waits for Method Response, send Address when able.
|
||||
break;
|
||||
|
||||
case PROXY_STATE_WAITING_SOCKS_RESPONSE:
|
||||
ret = Proxy_Connection_Complete(sockfd); // wait for ACK.
|
||||
break;
|
||||
|
||||
case PROXY_STATE_CONNECTION_COMPLETE:
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Basic_Connection_Complete() COMPLETED";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
|
||||
case PROXY_STATE_FAILED:
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Basic_Connection_Complete() FAILED";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Basic_Connection_Complete() IN PROGRESS";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
// In Progress.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int pqiproxyconnection::Proxy_Send_Method(int sockfd)
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Send_Method() Basic complete, sending Method";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
/* send hello to proxy server */
|
||||
char method_hello_data[3] = { 0x05, 0x01, 0x00 }; // [ Ver | nMethods (1) | No Auth Method ]
|
||||
|
||||
int sent = send(sockfd, method_hello_data, 3, 0);
|
||||
if (sent != 3)
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Send_Method() Send Failure";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Send_Method() Send Method Okay";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
mProxyState = PROXY_STATE_WAITING_METHOD_RESPONSE;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pqiproxyconnection::Proxy_Method_Response(int sockfd)
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response()";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
/* get response from proxy server */
|
||||
|
||||
char method_response[2];
|
||||
|
||||
/*
|
||||
first it was:
|
||||
|
||||
int recvd = recv(sockfd, method_response, 2, MSG_WAITALL);
|
||||
|
||||
this does not work on windows, because the socket is in nonblocking mode
|
||||
the winsock reference says about the recv function and MSG_WAITALL:
|
||||
|
||||
"Note that if the underlying transport does not support MSG_WAITALL,
|
||||
or if the socket is in a non-blocking mode, then this call will fail with WSAEOPNOTSUPP."
|
||||
|
||||
now it is a two step process:
|
||||
|
||||
int recvd = recv(sockfd, method_response, 2, MSG_PEEK); // test how many bytes are in the input queue
|
||||
if (enaugh bytes available){
|
||||
recvd = recv(sockfd, method_response, 2, 0);
|
||||
}
|
||||
|
||||
this does not work on windows:
|
||||
if ((recvd == -1) && (errno == EAGAIN)) return TRY_AGAIN_LATER;
|
||||
|
||||
instead have to do:
|
||||
if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) return TRY_AGAIN_LATER;
|
||||
*/
|
||||
|
||||
// test how many bytes can be read from the queue
|
||||
int recvd = recv(sockfd, method_response, 2, MSG_PEEK);
|
||||
if (recvd != 2)
|
||||
{
|
||||
#ifdef WINDOWS_SYS
|
||||
if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK))
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response() waiting for more data (windows)";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if ((recvd == -1) && (errno == EAGAIN))
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response() EAGAIN";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if (recvd == -1)
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response() recv error peek";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response() waiting for more data";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// read the bytes
|
||||
recvd = recv(sockfd, method_response, 2, 0);
|
||||
if (recvd != 2)
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response() recv error";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
// does it make sense?
|
||||
if (method_response[0] != 0x05)
|
||||
{
|
||||
|
||||
// Error.
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x05. Is: ";
|
||||
std::cerr << (uint32_t) method_response[0];
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (method_response[1] != 0x00)
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x00. Is: ";
|
||||
std::cerr << (uint32_t) method_response[1];
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
// Error.
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response() Response Okay";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define MAX_SOCKS_REQUEST_LEN 262 // 4 + 1 + 255 + 2.
|
||||
|
||||
int pqiproxyconnection::Proxy_Send_Address(int sockfd)
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Send_Address() Checking Method Response";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
// Check Method Response.
|
||||
int ret = Proxy_Method_Response(sockfd);
|
||||
if (ret != 1)
|
||||
{
|
||||
return ret; // Method Response not complete.
|
||||
}
|
||||
|
||||
char socks_request[MAX_SOCKS_REQUEST_LEN] =
|
||||
{ 0x05, // SOCKS VERSION.
|
||||
0x01, // CONNECT (Tor doesn't support BIND or UDP).
|
||||
0x00, // RESERVED.
|
||||
0x03, // ADDRESS TYPE (Domain Name)
|
||||
0x00, // Length of Domain name... the rest is variable so can't hard code it!
|
||||
};
|
||||
|
||||
/* get the length of the domain name, pack so we can't overflow uint8_t */
|
||||
uint8_t len = mDomainAddress.length();
|
||||
socks_request[4] = len;
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
socks_request[5 + i] = mDomainAddress[i];
|
||||
}
|
||||
|
||||
/* now add the port, being careful with packing */
|
||||
uint16_t net_port = htons(mRemotePort);
|
||||
socks_request[5 + len] = ((uint8_t *) &net_port)[0];
|
||||
socks_request[5 + len + 1] = ((uint8_t *) &net_port)[1];
|
||||
|
||||
int pkt_len = 5 + len + 2;
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Send_Address() Sending String: ";
|
||||
for(int i = 0; i < pkt_len; i++)
|
||||
std::cerr << (uint32_t) socks_request[i];
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
int sent = send(sockfd, socks_request, pkt_len, 0);
|
||||
if (sent != pkt_len)
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Send_Address() Send Error";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Send_Address() Sent Okay";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
mProxyState = PROXY_STATE_WAITING_SOCKS_RESPONSE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pqiproxyconnection::Proxy_Connection_Complete(int sockfd)
|
||||
{
|
||||
/* get response from proxy server */
|
||||
/* response is similar format to request - with variable length data */
|
||||
|
||||
char socks_response[MAX_SOCKS_REQUEST_LEN];
|
||||
|
||||
// test how many bytes can be read
|
||||
int recvd = recv(sockfd, socks_response, 5, MSG_PEEK);
|
||||
if (recvd != 5)
|
||||
{
|
||||
#ifdef WINDOWS_SYS
|
||||
if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK))
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data (windows)";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if ((recvd == -1) && (errno == EAGAIN))
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() EAGAIN";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
else if (recvd == -1)
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error peek";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// read the bytes
|
||||
recvd = recv(sockfd, socks_response, 5, 0);
|
||||
if (recvd != 5)
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
// error checking.
|
||||
if (socks_response[0] != 0x05)
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[0] != 0x05. is: ";
|
||||
std::cerr << (uint32_t) socks_response[0];
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
// error.
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (socks_response[1] != 0x00)
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[1] != 0x00. is: ";
|
||||
std::cerr << (uint32_t) socks_response[1];
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
// connection failed.
|
||||
return -1;
|
||||
}
|
||||
|
||||
int address_bytes = 0;
|
||||
switch(socks_response[3]) // Address Type.
|
||||
{
|
||||
case 0x01:
|
||||
// IPv4 4 address bytes.
|
||||
address_bytes = 4;
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv4 Address Type";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
break;
|
||||
case 0x04:
|
||||
// IPv6 16 address bytes.
|
||||
address_bytes = 16;
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv6 Address Type";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
break;
|
||||
case 0x03:
|
||||
// Variable address bytes - specified in next byte.
|
||||
address_bytes = 1 + socks_response[4];
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() Domain Address Type. len: " << address_bytes;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
// unknown error.
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR Unknown Address Type";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// test how many bytes can be read
|
||||
recvd = recv(sockfd, &(socks_response[5]), address_bytes + 1, MSG_PEEK); // address_bytes - 1 + 2...
|
||||
if (recvd != address_bytes + 1)
|
||||
{
|
||||
#ifdef WINDOWS_SYS
|
||||
if((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK))
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data(2) (windows)";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if ((recvd == -1) && (errno == EAGAIN))
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR EAGAIN at end.";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
// Waiting - shouldn't happen.
|
||||
return 0;
|
||||
}
|
||||
else if (recvd == -1)
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR recving(2)";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data(2)";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// read the bytes
|
||||
recvd = recv(sockfd, &(socks_response[5]), address_bytes + 1, 0); // address_bytes - 1 + 2...
|
||||
if (recvd != address_bytes + 1)
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error (2)";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() Received String: ";
|
||||
for(int i = 0; i < 4 + address_bytes + 2; i++)
|
||||
std::cerr << (uint32_t) socks_response[i];
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
// should print address.
|
||||
// if we get here - connection is good!.
|
||||
mProxyState = PROXY_STATE_CONNECTION_COMPLETE;
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
70
libretroshare/src/pqi/pqiproxy.h
Normal file
70
libretroshare/src/pqi/pqiproxy.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*******************************************************************************
|
||||
* libretroshare/src/pqi: pqiproxy.h *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2004-2013 by Robert Fernie. *
|
||||
* Copyright 2004-2021 by retroshare team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class pqiproxyconnection
|
||||
{
|
||||
public:
|
||||
enum ProxyState: uint8_t {
|
||||
PROXY_STATE_FAILED = 0x00,
|
||||
PROXY_STATE_INIT = 0x01,
|
||||
PROXY_STATE_WAITING_METHOD_RESPONSE = 0x02,
|
||||
PROXY_STATE_WAITING_SOCKS_RESPONSE = 0x03,
|
||||
PROXY_STATE_CONNECTION_COMPLETE = 0x04
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief proxy_negotiate_connection
|
||||
* Negotiate the connection with the proxy that is connected with openned socket sockfd. The caller needs to
|
||||
* connect the socket *before* trying to call proxy_negotiate_connection(). The function must be called as many times as
|
||||
* necessary until it returns 1 (success) or -1 (error) in which case the socket needs to be closed.
|
||||
* \return
|
||||
* -1 : error. The socket must be closed as soon as possible.
|
||||
* 0 : in progress. The function needs to be called again asap.
|
||||
* 1 : proxy connection is fully negociated. Client can send data to the socket.
|
||||
*/
|
||||
int proxy_negotiate_connection(int sockfd);
|
||||
|
||||
void setRemotePort(uint16_t v) { mRemotePort = v; }
|
||||
void setRemoteAddress(const std::string& s) { mDomainAddress = s; }
|
||||
|
||||
ProxyState proxyConnectionState() const { return mProxyState ; }
|
||||
|
||||
void proxy_init() { mProxyState = PROXY_STATE_INIT; }
|
||||
private:
|
||||
|
||||
ProxyState mProxyState;
|
||||
|
||||
std::string mDomainAddress;
|
||||
uint16_t mRemotePort;
|
||||
|
||||
// These are the internal steps in setting up the Proxy Connection.
|
||||
int Proxy_Send_Method(int sockfd);
|
||||
int Proxy_Method_Response(int sockfd);
|
||||
int Proxy_Send_Address(int sockfd);
|
||||
int Proxy_Connection_Complete(int sockfd);
|
||||
};
|
||||
|
@ -38,12 +38,6 @@ static struct RsLog::logInfo pqisslproxyzoneInfo = {RsLog::Default, "pqisslproxy
|
||||
// #define PROXY_DEBUG 1
|
||||
// #define PROXY_DEBUG_LOG 1
|
||||
|
||||
#define PROXY_STATE_FAILED 0
|
||||
#define PROXY_STATE_INIT 1
|
||||
#define PROXY_STATE_WAITING_METHOD_RESPONSE 2
|
||||
#define PROXY_STATE_WAITING_SOCKS_RESPONSE 3
|
||||
#define PROXY_STATE_CONNECTION_COMPLETE 4
|
||||
|
||||
pqisslproxy::pqisslproxy(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm)
|
||||
:pqissl(l, parent, lm)
|
||||
{
|
||||
@ -74,7 +68,7 @@ int pqisslproxy::Initiate_Connection()
|
||||
rslog(RSL_DEBUG_BASIC, pqisslproxyzone,
|
||||
"pqisslproxy::Initiate_Connection() Connection to Proxy");
|
||||
/* init proxy state */
|
||||
mProxyState = PROXY_STATE_INIT;
|
||||
proxy_init();
|
||||
|
||||
/* call standard Init_Conn() */
|
||||
return pqissl::Initiate_Connection();
|
||||
@ -98,486 +92,18 @@ int pqisslproxy::Basic_Connection_Complete()
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
switch(mProxyState)
|
||||
{
|
||||
case PROXY_STATE_INIT:
|
||||
ret = Proxy_Send_Method(); // checks basic conn, sends Method when able.
|
||||
break;
|
||||
int ret;
|
||||
|
||||
case PROXY_STATE_WAITING_METHOD_RESPONSE:
|
||||
ret = Proxy_Send_Address(); // waits for Method Response, send Address when able.
|
||||
break;
|
||||
if(proxyConnectionState() == PROXY_STATE_INIT && 1!=(ret=pqissl::Basic_Connection_Complete()))
|
||||
return ret; // basic connection not complete.
|
||||
|
||||
case PROXY_STATE_WAITING_SOCKS_RESPONSE:
|
||||
ret = Proxy_Connection_Complete(); // wait for ACK.
|
||||
break;
|
||||
ret = proxy_negotiate_connection(sockfd);
|
||||
|
||||
case PROXY_STATE_CONNECTION_COMPLETE:
|
||||
if(ret < 0)
|
||||
reset_locked();
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Basic_Connection_Complete() COMPLETED";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
|
||||
case PROXY_STATE_FAILED:
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Basic_Connection_Complete() FAILED";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
reset_locked();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Basic_Connection_Complete() FAILED(2)";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
reset_locked();
|
||||
return -1; // FAILURE.
|
||||
}
|
||||
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Basic_Connection_Complete() IN PROGRESS";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
// In Progress.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int pqisslproxy::Proxy_Send_Method()
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Send_Method() Checking pqissl::Basic_Connection_Complete()";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
int ret = pqissl::Basic_Connection_Complete();
|
||||
if (ret != 1)
|
||||
{
|
||||
return ret; // basic connection not complete.
|
||||
}
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Send_Method() Basic complete, sending Method";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
/* send hello to proxy server */
|
||||
char method_hello_data[3] = { 0x05, 0x01, 0x00 }; // [ Ver | nMethods (1) | No Auth Method ]
|
||||
|
||||
int sent = send(sockfd, method_hello_data, 3, 0);
|
||||
if (sent != 3)
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Send_Method() Send Failure";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Send_Method() Send Method Okay";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
mProxyState = PROXY_STATE_WAITING_METHOD_RESPONSE;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pqisslproxy::Proxy_Method_Response()
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response()";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
/* get response from proxy server */
|
||||
|
||||
char method_response[2];
|
||||
|
||||
/*
|
||||
first it was:
|
||||
|
||||
int recvd = recv(sockfd, method_response, 2, MSG_WAITALL);
|
||||
|
||||
this does not work on windows, because the socket is in nonblocking mode
|
||||
the winsock reference says about the recv function and MSG_WAITALL:
|
||||
|
||||
"Note that if the underlying transport does not support MSG_WAITALL,
|
||||
or if the socket is in a non-blocking mode, then this call will fail with WSAEOPNOTSUPP."
|
||||
|
||||
now it is a two step process:
|
||||
|
||||
int recvd = recv(sockfd, method_response, 2, MSG_PEEK); // test how many bytes are in the input queue
|
||||
if (enaugh bytes available){
|
||||
recvd = recv(sockfd, method_response, 2, 0);
|
||||
}
|
||||
|
||||
this does not work on windows:
|
||||
if ((recvd == -1) && (errno == EAGAIN)) return TRY_AGAIN_LATER;
|
||||
|
||||
instead have to do:
|
||||
if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) return TRY_AGAIN_LATER;
|
||||
*/
|
||||
|
||||
// test how many bytes can be read from the queue
|
||||
int recvd = recv(sockfd, method_response, 2, MSG_PEEK);
|
||||
if (recvd != 2)
|
||||
{
|
||||
#ifdef WINDOWS_SYS
|
||||
if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK))
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response() waiting for more data (windows)";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if ((recvd == -1) && (errno == EAGAIN))
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response() EAGAIN";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if (recvd == -1)
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response() recv error peek";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response() waiting for more data";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// read the bytes
|
||||
recvd = recv(sockfd, method_response, 2, 0);
|
||||
if (recvd != 2)
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response() recv error";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
// does it make sense?
|
||||
if (method_response[0] != 0x05)
|
||||
{
|
||||
|
||||
// Error.
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x05. Is: ";
|
||||
std::cerr << (uint32_t) method_response[0];
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (method_response[1] != 0x00)
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x00. Is: ";
|
||||
std::cerr << (uint32_t) method_response[1];
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
// Error.
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response() Response Okay";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define MAX_SOCKS_REQUEST_LEN 262 // 4 + 1 + 255 + 2.
|
||||
|
||||
int pqisslproxy::Proxy_Send_Address()
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Send_Address() Checking Method Response";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
// Check Method Response.
|
||||
int ret = Proxy_Method_Response();
|
||||
if (ret != 1)
|
||||
{
|
||||
return ret; // Method Response not complete.
|
||||
}
|
||||
|
||||
char socks_request[MAX_SOCKS_REQUEST_LEN] =
|
||||
{ 0x05, // SOCKS VERSION.
|
||||
0x01, // CONNECT (Tor doesn't support BIND or UDP).
|
||||
0x00, // RESERVED.
|
||||
0x03, // ADDRESS TYPE (Domain Name)
|
||||
0x00, // Length of Domain name... the rest is variable so can't hard code it!
|
||||
};
|
||||
|
||||
/* get the length of the domain name, pack so we can't overflow uint8_t */
|
||||
uint8_t len = mDomainAddress.length();
|
||||
socks_request[4] = len;
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
socks_request[5 + i] = mDomainAddress[i];
|
||||
}
|
||||
|
||||
/* now add the port, being careful with packing */
|
||||
uint16_t net_port = htons(mRemotePort);
|
||||
socks_request[5 + len] = ((uint8_t *) &net_port)[0];
|
||||
socks_request[5 + len + 1] = ((uint8_t *) &net_port)[1];
|
||||
|
||||
int pkt_len = 5 + len + 2;
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Send_Address() Sending String: ";
|
||||
for(int i = 0; i < pkt_len; i++)
|
||||
std::cerr << (uint32_t) socks_request[i];
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
int sent = send(sockfd, socks_request, pkt_len, 0);
|
||||
if (sent != pkt_len)
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Send_Address() Send Error";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Send_Address() Sent Okay";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
mProxyState = PROXY_STATE_WAITING_SOCKS_RESPONSE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pqisslproxy::Proxy_Connection_Complete()
|
||||
{
|
||||
/* get response from proxy server */
|
||||
/* response is similar format to request - with variable length data */
|
||||
|
||||
char socks_response[MAX_SOCKS_REQUEST_LEN];
|
||||
|
||||
// test how many bytes can be read
|
||||
int recvd = recv(sockfd, socks_response, 5, MSG_PEEK);
|
||||
if (recvd != 5)
|
||||
{
|
||||
#ifdef WINDOWS_SYS
|
||||
if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK))
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data (windows)";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if ((recvd == -1) && (errno == EAGAIN))
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() EAGAIN";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
else if (recvd == -1)
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error peek";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// read the bytes
|
||||
recvd = recv(sockfd, socks_response, 5, 0);
|
||||
if (recvd != 5)
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
// error checking.
|
||||
if (socks_response[0] != 0x05)
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[0] != 0x05. is: ";
|
||||
std::cerr << (uint32_t) socks_response[0];
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
// error.
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (socks_response[1] != 0x00)
|
||||
{
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[1] != 0x00. is: ";
|
||||
std::cerr << (uint32_t) socks_response[1];
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
// connection failed.
|
||||
return -1;
|
||||
}
|
||||
|
||||
int address_bytes = 0;
|
||||
switch(socks_response[3]) // Address Type.
|
||||
{
|
||||
case 0x01:
|
||||
// IPv4 4 address bytes.
|
||||
address_bytes = 4;
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv4 Address Type";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
break;
|
||||
case 0x04:
|
||||
// IPv6 16 address bytes.
|
||||
address_bytes = 16;
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv6 Address Type";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
break;
|
||||
case 0x03:
|
||||
// Variable address bytes - specified in next byte.
|
||||
address_bytes = 1 + socks_response[4];
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() Domain Address Type. len: " << address_bytes;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
// unknown error.
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR Unknown Address Type";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// test how many bytes can be read
|
||||
recvd = recv(sockfd, &(socks_response[5]), address_bytes + 1, MSG_PEEK); // address_bytes - 1 + 2...
|
||||
if (recvd != address_bytes + 1)
|
||||
{
|
||||
#ifdef WINDOWS_SYS
|
||||
if((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK))
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data(2) (windows)";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if ((recvd == -1) && (errno == EAGAIN))
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR EAGAIN at end.";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
// Waiting - shouldn't happen.
|
||||
return 0;
|
||||
}
|
||||
else if (recvd == -1)
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR recving(2)";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data(2)";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// read the bytes
|
||||
recvd = recv(sockfd, &(socks_response[5]), address_bytes + 1, 0); // address_bytes - 1 + 2...
|
||||
if (recvd != address_bytes + 1)
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error (2)";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() Received String: ";
|
||||
for(int i = 0; i < 4 + address_bytes + 2; i++)
|
||||
std::cerr << (uint32_t) socks_response[i];
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
// should print address.
|
||||
// if we get here - connection is good!.
|
||||
mProxyState = PROXY_STATE_CONNECTION_COMPLETE;
|
||||
return 1;
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool pqisslproxy::connect_parameter(uint32_t type, const std::string &value)
|
||||
{
|
||||
@ -591,7 +117,7 @@ bool pqisslproxy::connect_parameter(uint32_t type, const std::string &value)
|
||||
#ifdef PROXY_DEBUG_LOG
|
||||
rslog(RSL_WARNING, pqisslproxyzone, out);
|
||||
#endif
|
||||
mDomainAddress = value;
|
||||
setRemoteAddress(value);
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << out << std::endl;
|
||||
#endif
|
||||
@ -614,7 +140,7 @@ bool pqisslproxy::connect_parameter(uint32_t type, uint32_t value)
|
||||
#ifdef PROXY_DEBUG_LOG
|
||||
rslog(RSL_WARNING, pqisslproxyzone, out);
|
||||
#endif
|
||||
mRemotePort = value;
|
||||
setRemotePort(value);
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << out << std::endl;
|
||||
#endif
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
// operating system specific network header.
|
||||
#include "pqi/pqinetwork.h"
|
||||
#include "pqi/pqiproxy.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
@ -39,40 +40,27 @@
|
||||
* fns declared here are different -> all others are identical.
|
||||
*/
|
||||
|
||||
class pqisslproxy: public pqissl
|
||||
class pqisslproxy: public pqissl, public pqiproxyconnection
|
||||
{
|
||||
public:
|
||||
pqisslproxy(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm);
|
||||
virtual ~pqisslproxy();
|
||||
pqisslproxy(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm);
|
||||
virtual ~pqisslproxy();
|
||||
|
||||
// NetInterface. Is the same.
|
||||
// BinInterface. Is the same.
|
||||
// NetInterface. Is the same.
|
||||
// BinInterface. Is the same.
|
||||
|
||||
virtual bool connect_parameter(uint32_t type, const std::string &value);
|
||||
virtual bool connect_parameter(uint32_t type, uint32_t value);
|
||||
virtual bool connect_parameter(uint32_t type, const std::string &value);
|
||||
virtual bool connect_parameter(uint32_t type, uint32_t value);
|
||||
|
||||
protected:
|
||||
|
||||
//Initiate is the same - except it uses the Proxy Address rather than the Peer Address.
|
||||
// minor tweaks to setup data state.
|
||||
virtual int Initiate_Connection();
|
||||
//Initiate is the same - except it uses the Proxy Address rather than the Peer Address.
|
||||
// minor tweaks to setup data state.
|
||||
virtual int Initiate_Connection();
|
||||
|
||||
// The real overloading is done in Basic Connection Complete.
|
||||
// Instead of just checking for an open socket, we need to communicate with the SOCKS5 proxy.
|
||||
virtual int Basic_Connection_Complete();
|
||||
|
||||
// These are the internal steps in setting up the Proxy Connection.
|
||||
virtual int Proxy_Send_Method();
|
||||
virtual int Proxy_Method_Response();
|
||||
virtual int Proxy_Send_Address();
|
||||
virtual int Proxy_Connection_Complete();
|
||||
|
||||
private:
|
||||
|
||||
uint32_t mProxyState;
|
||||
|
||||
std::string mDomainAddress;
|
||||
uint16_t mRemotePort;
|
||||
// The real overloading is done in Basic Connection Complete.
|
||||
// Instead of just checking for an open socket, we need to communicate with the SOCKS5 proxy.
|
||||
virtual int Basic_Connection_Complete();
|
||||
};
|
||||
|
||||
#endif // MRK_PQI_SSL_PROXY_HEADER
|
||||
|
Loading…
Reference in New Issue
Block a user