Merge pull request #4547 from andreesteve/gatewayip

Gateway client (RDG) must connect to same IP/server for both channels
This commit is contained in:
Martin Fleisz 2018-04-12 10:43:34 +02:00 committed by GitHub
commit d1b4b410fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 78 additions and 9 deletions

View File

@ -1027,8 +1027,10 @@ static BOOL rdg_tls_in_connect(rdpRdg* rdg, const char* hostname, UINT16 port, i
BIO* bufferedBio = NULL;
rdpSettings* settings = rdg->settings;
const char* peerHostname = settings->GatewayHostname;
int peerPort = settings->GatewayPort;
UINT16 peerPort = settings->GatewayPort;
BOOL isProxyConnection = FALSE;
int outChannelSocket = 0;
char* gatewayAddress = NULL;
assert(hostname != NULL);
if (settings->ProxyType)
@ -1037,17 +1039,45 @@ static BOOL rdg_tls_in_connect(rdpRdg* rdg, const char* hostname, UINT16 port, i
peerPort = settings->ProxyPort;
isProxyConnection = TRUE;
}
else
{
/**
* if settings->GatewayHostname is a name, it may be mapped to more than one
* IP address (thus potentially multiple gateway servers) - to avoid openning
* the IN channel with one server and the OUT channel with another server
* we want to use the same IP when connecting to both IN and OUT channels
* below we get the peer ip address in use by the OUT channel and use it
* when opening the connection for the IN channel
*/
BIO_get_socket(rdg->tlsOut->underlying, &outChannelSocket);
gatewayAddress = freerdp_tcp_get_peer_address(outChannelSocket);
if (gatewayAddress == NULL)
{
WLog_DBG(TAG,
"RDG out channel was created but gateway IP couldn't be resolved. Falling back to resolving gateway hostname again for IN channel.");
}
else
{
WLog_DBG(TAG, "Gateway hostname %s resolved to IP %s.", peerHostname, gatewayAddress);
peerHostname = gatewayAddress;
}
}
sockfd = freerdp_tcp_connect(rdg->context, settings, peerHostname,
peerPort, timeout);
if (sockfd < 1)
{
free(gatewayAddress);
return FALSE;
}
socketBio = BIO_new(BIO_s_simple_socket());
if (!socketBio)
{
free(gatewayAddress);
closesocket(sockfd);
return FALSE;
}
@ -1057,6 +1087,7 @@ static BOOL rdg_tls_in_connect(rdpRdg* rdg, const char* hostname, UINT16 port, i
if (!bufferedBio)
{
free(gatewayAddress);
BIO_free(socketBio);
return FALSE;
}
@ -1066,6 +1097,7 @@ static BOOL rdg_tls_in_connect(rdpRdg* rdg, const char* hostname, UINT16 port, i
if (!status)
{
free(gatewayAddress);
BIO_free_all(bufferedBio);
return FALSE;
}
@ -1077,6 +1109,7 @@ static BOOL rdg_tls_in_connect(rdpRdg* rdg, const char* hostname, UINT16 port, i
if (status < 1)
{
free(gatewayAddress);
return FALSE;
}

View File

@ -664,17 +664,16 @@ BIO_METHOD* BIO_s_buffered_socket(void)
return bio_methods;
}
static char* freerdp_tcp_get_ip_address(int sockfd, BOOL* pIPv6)
static char* freerdp_tcp_address_to_string(const struct sockaddr_storage* addr, BOOL* pIPv6)
{
socklen_t length;
char ipAddress[INET6_ADDRSTRLEN + 1] = { 0 };
struct sockaddr_storage saddr = { 0 };
struct sockaddr_in6* sockaddr_ipv6 = (struct sockaddr_in6*)&saddr;
struct sockaddr_in* sockaddr_ipv4 = (struct sockaddr_in*)&saddr;
length = sizeof(struct sockaddr_storage);
struct sockaddr_in6* sockaddr_ipv6 = (struct sockaddr_in6*)addr;
struct sockaddr_in* sockaddr_ipv4 = (struct sockaddr_in*)addr;
if (getsockname(sockfd, (struct sockaddr*)&saddr, &length) != 0)
if (addr == NULL)
{
return NULL;
}
switch (sockaddr_ipv4->sin_family)
{
@ -698,12 +697,40 @@ static char* freerdp_tcp_get_ip_address(int sockfd, BOOL* pIPv6)
return NULL;
}
if (pIPv6)
if (pIPv6 != NULL)
{
*pIPv6 = (sockaddr_ipv4->sin_family == AF_INET6);
}
return _strdup(ipAddress);
}
static char* freerdp_tcp_get_ip_address(int sockfd, BOOL* pIPv6)
{
struct sockaddr_storage saddr = { 0 };
socklen_t length = sizeof(struct sockaddr_storage);
if (getsockname(sockfd, (struct sockaddr*)&saddr, &length) != 0)
{
return NULL;
}
return freerdp_tcp_address_to_string(&saddr, pIPv6);
}
char* freerdp_tcp_get_peer_address(int sockfd)
{
struct sockaddr_storage saddr = { 0 };
socklen_t length = sizeof(struct sockaddr_storage);
if (getpeername(sockfd, (struct sockaddr*)&saddr, &length) != 0)
{
return NULL;
}
return freerdp_tcp_address_to_string(&saddr, NULL);
}
static int freerdp_uds_connect(const char* path)
{
#ifndef _WIN32
@ -1110,6 +1137,7 @@ int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings,
if (sockfd <= 0)
{
char port_str[16];
char* peerAddress;
struct addrinfo hints;
struct addrinfo* addr;
struct addrinfo* result;
@ -1150,6 +1178,12 @@ int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings,
return -1;
}
if ((peerAddress = freerdp_tcp_address_to_string(addr->ai_addr, NULL)) != NULL)
{
WLog_DBG(TAG, "connecting to peer %s", peerAddress);
free(peerAddress);
}
if (!freerdp_tcp_connect_timeout(context, sockfd, addr->ai_addr,
addr->ai_addrlen, timeout))
{

View File

@ -67,4 +67,6 @@ FREERDP_LOCAL int freerdp_tcp_connect(rdpContext* context,
rdpSettings* settings,
const char* hostname, int port, int timeout);
FREERDP_LOCAL char* freerdp_tcp_get_peer_address(int sockfd);
#endif /* FREERDP_LIB_CORE_TCP_H */