mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-11-23 01:49:53 +03:00
Protocol.c: adapt ClientConnectGetSocket() for new proxy functions
The function has been greatly improved, here are some of the changes: - The required SESSION (c->Session) parameter is checked correctly: the function returns immediately in case it's NULL. Previously, the function didn't return in case the parameter was NULL; multiple checks were in place, but not in all instances where the parameter was dereferenced. - The resolved IP address is cached with all proxy types. - The "RestoreServerNameAndPort" variable is documented. - The Debug() messages have been improved.
This commit is contained in:
parent
3c21d982fc
commit
63caa4b07f
@ -5996,104 +5996,89 @@ SOCK *ClientConnectToServer(CONNECTION *c)
|
|||||||
// Return a socket by connecting to the server
|
// Return a socket by connecting to the server
|
||||||
SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect)
|
SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect)
|
||||||
{
|
{
|
||||||
SOCK *s = NULL;
|
|
||||||
CLIENT_OPTION *o;
|
|
||||||
WPC_CONNECT w;
|
|
||||||
wchar_t tmp[MAX_SIZE];
|
|
||||||
SESSION *sess;
|
|
||||||
volatile bool *cancel_flag = NULL;
|
volatile bool *cancel_flag = NULL;
|
||||||
void *hWnd;
|
char hostname[MAX_HOST_NAME_LEN];
|
||||||
UINT nat_t_err = 0;
|
bool save_resolved_ip = false;
|
||||||
bool is_additional_rudp_session = false;
|
CLIENT_OPTION *o;
|
||||||
UCHAR uc = 0;
|
SESSION *sess;
|
||||||
IP ret_ip;
|
SOCK *sock = NULL;
|
||||||
|
IP resolved_ip;
|
||||||
// Validate arguments
|
// Validate arguments
|
||||||
if (c == NULL)
|
if (c == NULL || c->Session == NULL || c->Session->ClientOption == NULL)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Zero(&ret_ip, sizeof(IP));
|
cancel_flag = &c->Halt;
|
||||||
Zero(&w, sizeof(w));
|
|
||||||
|
|
||||||
sess = c->Session;
|
sess = c->Session;
|
||||||
|
|
||||||
if (sess != NULL)
|
|
||||||
{
|
|
||||||
cancel_flag = &sess->CancelConnect;
|
|
||||||
is_additional_rudp_session = sess->IsRUDPSession;
|
|
||||||
}
|
|
||||||
|
|
||||||
hWnd = c->hWndForUI;
|
|
||||||
|
|
||||||
o = c->Session->ClientOption;
|
o = c->Session->ClientOption;
|
||||||
|
|
||||||
if (additional_connect)
|
Zero(&resolved_ip, sizeof(resolved_ip));
|
||||||
{
|
|
||||||
if (sess != NULL)
|
|
||||||
{
|
|
||||||
Copy(&ret_ip, &sess->ServerIP_CacheForNextConnect, sizeof(IP));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c->RestoreServerNameAndPort && additional_connect)
|
if (additional_connect == false && c->RestoreServerNameAndPort)
|
||||||
{
|
{
|
||||||
// Restore to the original server name and port number
|
// Update server name and port number.
|
||||||
|
// At the time of writing this comment RestoreServerNameAndPort is never true.
|
||||||
c->RestoreServerNameAndPort = false;
|
c->RestoreServerNameAndPort = false;
|
||||||
|
|
||||||
if (StrCmpi(c->ServerName, o->Hostname) != 0)
|
if (StrCmpi(c->ServerName, o->Hostname) != 0)
|
||||||
{
|
{
|
||||||
StrCpy(c->ServerName, sizeof(c->ServerName), o->Hostname);
|
StrCpy(c->ServerName, sizeof(c->ServerName), o->Hostname);
|
||||||
Zero(&ret_ip, sizeof(IP));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c->ServerPort = o->Port;
|
c->ServerPort = o->Port;
|
||||||
}
|
}
|
||||||
|
|
||||||
StrCpy(w.HostName, sizeof(w.HostName), c->ServerName);
|
if (IsZeroIP(&sess->ServerIP_CacheForNextConnect) == false)
|
||||||
w.Port = c->ServerPort;
|
|
||||||
StrCpy(w.ProxyHostName, sizeof(w.ProxyHostName), o->ProxyName);
|
|
||||||
w.ProxyPort = o->ProxyPort;
|
|
||||||
StrCpy(w.ProxyUsername, sizeof(w.ProxyUsername), o->ProxyUsername);
|
|
||||||
StrCpy(w.ProxyPassword, sizeof(w.ProxyPassword), o->ProxyPassword);
|
|
||||||
StrCpy(w.CustomHttpHeader, sizeof(w.CustomHttpHeader), o->CustomHttpHeader);
|
|
||||||
|
|
||||||
switch (o->ProxyType)
|
|
||||||
{
|
{
|
||||||
case PROXY_DIRECT: // TCP/IP
|
IPToStr(hostname, sizeof(hostname), &sess->ServerIP_CacheForNextConnect);
|
||||||
UniFormat(tmp, sizeof(tmp), _UU("STATUS_4"), w.HostName);
|
Debug("ClientConnectGetSocket(): Using cached IP address %s\n", hostname);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IP tmp;
|
||||||
|
|
||||||
|
StrCpy(hostname, sizeof(hostname), o->ProxyType == PROXY_DIRECT ? c->ServerName : o->ProxyName);
|
||||||
|
|
||||||
|
if (StrToIP(&tmp, hostname) == false)
|
||||||
|
{
|
||||||
|
// The hostname is not an IP address
|
||||||
|
save_resolved_ip = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o->ProxyType == PROXY_DIRECT)
|
||||||
|
{
|
||||||
|
UINT nat_t_err = 0;
|
||||||
|
wchar_t tmp[MAX_SIZE];
|
||||||
|
UniFormat(tmp, sizeof(tmp), _UU("STATUS_4"), hostname);
|
||||||
PrintStatus(sess, tmp);
|
PrintStatus(sess, tmp);
|
||||||
|
|
||||||
// Production job
|
|
||||||
if (o->PortUDP == 0)
|
if (o->PortUDP == 0)
|
||||||
{
|
|
||||||
{
|
{
|
||||||
// If additional_connect == false, enable trying to NAT-T connection
|
// If additional_connect == false, enable trying to NAT-T connection
|
||||||
// If additional_connect == true, follow the IsRUDPSession setting in this session
|
// If additional_connect == true, follow the IsRUDPSession setting in this session
|
||||||
s = TcpIpConnectEx(w.HostName, w.Port,
|
sock = TcpIpConnectEx(hostname, c->ServerPort,
|
||||||
(bool *)cancel_flag, hWnd, &nat_t_err, (additional_connect ? (!is_additional_rudp_session) : false),
|
(bool *)cancel_flag, c->hWndForUI, &nat_t_err, (additional_connect ? (!sess->IsRUDPSession) : false),
|
||||||
true, &ret_ip);
|
true, &resolved_ip);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Mode to connect with R-UDP directly without using NAT-T server when using UDP
|
// Mode to connect with R-UDP directly without using NAT-T server when using UDP
|
||||||
IP ip;
|
IP ip;
|
||||||
|
if (StrToIP(&ip, hostname))
|
||||||
Zero(&ip, sizeof(ip));
|
{
|
||||||
|
sock = NewRUDPClientDirect(VPN_RUDP_SVC_NAME, &ip, o->PortUDP, &nat_t_err,
|
||||||
StrToIP(&ip, o->Hostname);
|
|
||||||
|
|
||||||
|
|
||||||
s = NewRUDPClientDirect(VPN_RUDP_SVC_NAME, &ip, o->PortUDP, &nat_t_err,
|
|
||||||
TIMEOUT_TCP_PORT_CHECK, (bool *)cancel_flag, NULL, NULL, 0, false);
|
TIMEOUT_TCP_PORT_CHECK, (bool *)cancel_flag, NULL, NULL, 0, false);
|
||||||
|
|
||||||
if (s != NULL)
|
if (sock != NULL)
|
||||||
{
|
{
|
||||||
StrCpy(s->UnderlayProtocol, sizeof(s->UnderlayProtocol), SOCK_UNDERLAY_NAT_T);
|
StrCpy(sock->UnderlayProtocol, sizeof(sock->UnderlayProtocol), SOCK_UNDERLAY_NAT_T);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (s == NULL)
|
}
|
||||||
|
|
||||||
|
if (sock == NULL)
|
||||||
{
|
{
|
||||||
// Connection failure
|
// Connection failure
|
||||||
if (nat_t_err != RUDP_ERROR_NAT_T_TWO_OR_MORE)
|
if (nat_t_err != RUDP_ERROR_NAT_T_TWO_OR_MORE)
|
||||||
@ -6104,85 +6089,85 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect)
|
|||||||
{
|
{
|
||||||
c->Err = ERR_NAT_T_TWO_OR_MORE;
|
c->Err = ERR_NAT_T_TWO_OR_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case PROXY_HTTP: // HTTP Proxy
|
|
||||||
UniFormat(tmp, sizeof(tmp), _UU("STATUS_2"), w.HostName, w.ProxyHostName);
|
|
||||||
PrintStatus(sess, tmp);
|
|
||||||
|
|
||||||
// Proxy connection
|
|
||||||
s = ProxyConnectEx3(c, &w, additional_connect, (bool *)cancel_flag, hWnd, 0);
|
|
||||||
if (s == NULL)
|
|
||||||
{
|
|
||||||
// Connection failure
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROXY_SOCKS: // SOCKS4 Proxy
|
|
||||||
UniFormat(tmp, sizeof(tmp), _UU("STATUS_2"), w.HostName, w.ProxyHostName);
|
|
||||||
PrintStatus(sess, tmp);
|
|
||||||
|
|
||||||
// SOCKS4 connection
|
|
||||||
s = SocksConnectEx2(c, w.ProxyHostName, w.ProxyPort,
|
|
||||||
w.HostName, w.Port, w.ProxyUsername, additional_connect, (bool *)cancel_flag,
|
|
||||||
hWnd, 0, &ret_ip);
|
|
||||||
if (s == NULL)
|
|
||||||
{
|
|
||||||
// Connection failure
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROXY_SOCKS5: // SOCKS5 Proxy
|
|
||||||
UniFormat(tmp, sizeof(tmp), _UU("STATUS_2"), w.HostName, w.ProxyHostName);
|
|
||||||
PrintStatus(sess, tmp);
|
|
||||||
|
|
||||||
// SOCKS5 connection
|
|
||||||
s = Socks5Connect(c, &w, additional_connect, (bool *)cancel_flag, hWnd, 0, &ret_ip);
|
|
||||||
if (s == NULL)
|
|
||||||
{
|
|
||||||
// Connection failure
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s == NULL)
|
|
||||||
{
|
|
||||||
// Connection failure
|
|
||||||
c->Err = ERR_CONNECT_FAILED;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Success to connect
|
wchar_t tmp[MAX_SIZE];
|
||||||
// Keep a note of the IP address
|
PROXY_PARAM_OUT out;
|
||||||
if (additional_connect == false || IsZeroIP(&s->RemoteIP))
|
PROXY_PARAM_IN in;
|
||||||
|
UINT ret;
|
||||||
|
|
||||||
|
Zero(&in, sizeof(in));
|
||||||
|
|
||||||
|
in.Timeout = 0;
|
||||||
|
|
||||||
|
StrCpy(in.TargetHostname, sizeof(in.TargetHostname), c->ServerName);
|
||||||
|
in.TargetPort = c->ServerPort;
|
||||||
|
|
||||||
|
StrCpy(in.Hostname, sizeof(in.Hostname), IsEmptyStr(hostname) ? o->ProxyName : hostname);
|
||||||
|
in.Port = o->ProxyPort;
|
||||||
|
|
||||||
|
StrCpy(in.Username, sizeof(in.Username), o->ProxyUsername);
|
||||||
|
StrCpy(in.Password, sizeof(in.Password), o->ProxyPassword);
|
||||||
|
|
||||||
|
StrCpy(in.HttpCustomHeader, sizeof(in.HttpCustomHeader), o->CustomHttpHeader);
|
||||||
|
StrCpy(in.HttpUserAgent, sizeof(in.HttpUserAgent), c->Cedar->HttpUserAgent);
|
||||||
|
|
||||||
|
#ifdef OS_WIN32
|
||||||
|
in.Hwnd = c->hWndForUI;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
UniFormat(tmp, sizeof(tmp), _UU("STATUS_2"), in.TargetHostname, in.Hostname);
|
||||||
|
PrintStatus(sess, tmp);
|
||||||
|
|
||||||
|
switch (o->ProxyType)
|
||||||
{
|
{
|
||||||
char *hostname = o->ProxyType == PROXY_DIRECT ? w.HostName : w.ProxyHostName;
|
case PROXY_HTTP:
|
||||||
if (((s->IsRUDPSocket || s->IPv6) && IsZeroIP(&s->RemoteIP) == false && o->ProxyType == PROXY_DIRECT) || GetIP(&c->Session->ServerIP, hostname) == false)
|
ret = ProxyHttpConnect(&out, &in, cancel_flag);
|
||||||
|
break;
|
||||||
|
case PROXY_SOCKS:
|
||||||
|
ret = ProxySocks4Connect(&out, &in, cancel_flag);
|
||||||
|
break;
|
||||||
|
case PROXY_SOCKS5:
|
||||||
|
ret = ProxySocks5Connect(&out, &in, cancel_flag);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
c->Err = ERR_INTERNAL_ERROR;
|
||||||
|
Debug("ClientConnectGetSocket(): Unknown proxy type: %u!\n", o->ProxyType);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->Err = ProxyCodeToCedar(ret);
|
||||||
|
|
||||||
|
if (c->Err != ERR_NO_ERROR)
|
||||||
{
|
{
|
||||||
Copy(&c->Session->ServerIP, &s->RemoteIP, sizeof(IP));
|
Debug("ClientConnectGetSocket(): Connection via proxy server failed with error %u\n", ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sock = out.Sock;
|
||||||
|
|
||||||
|
CopyIP(&resolved_ip, &out.ResolvedIp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (additional_connect == false || IsZeroIP(&sock->RemoteIP))
|
||||||
|
{
|
||||||
|
if (((sock->IsRUDPSocket || sock->IPv6) && IsZeroIP(&sock->RemoteIP) == false && o->ProxyType == PROXY_DIRECT) || GetIP(&c->Session->ServerIP, hostname) == false)
|
||||||
|
{
|
||||||
|
Copy(&c->Session->ServerIP, &sock->RemoteIP, sizeof(c->Session->ServerIP));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsZeroIP(&ret_ip) == false)
|
if (save_resolved_ip && IsZeroIP(&resolved_ip) == false)
|
||||||
{
|
{
|
||||||
if (c->Session != NULL)
|
Copy(&c->Session->ServerIP_CacheForNextConnect, &resolved_ip, sizeof(c->Session->ServerIP_CacheForNextConnect));
|
||||||
{
|
Debug("ClientConnectGetSocket(): Saved %s IP address %r for future connections.\n", hostname, &resolved_ip);
|
||||||
if (additional_connect == false)
|
|
||||||
{
|
|
||||||
Copy(&c->Session->ServerIP_CacheForNextConnect, &ret_ip, sizeof(IP));
|
|
||||||
|
|
||||||
Debug("Saved ServerIP_CacheForNextConnect: %s = %r\n", c->ServerName, &ret_ip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT ProxyCodeToCedar(UINT code)
|
UINT ProxyCodeToCedar(UINT code)
|
||||||
|
Loading…
Reference in New Issue
Block a user