mirror of https://github.com/FreeRDP/FreeRDP
Merge pull request #4882 from akallabeth/no_proxy_cidr
Fixed #4878: Added cidr support for proxy exception check.
This commit is contained in:
commit
5339efd6e4
|
@ -103,6 +103,45 @@ BOOL proxy_prepare(rdpSettings* settings, const char** lpPeerHostname, UINT16* l
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL cidr4_match(const struct in_addr* addr, const struct in_addr* net, BYTE bits)
|
||||
{
|
||||
uint32_t mask, amask, nmask;
|
||||
|
||||
if (bits == 0)
|
||||
return TRUE;
|
||||
|
||||
mask = htonl(0xFFFFFFFFu << (32 - bits));
|
||||
amask = addr->s_addr & mask;
|
||||
nmask = net->s_addr & mask;
|
||||
return amask == nmask;
|
||||
}
|
||||
|
||||
static BOOL cidr6_match(const struct in6_addr* address, const struct in6_addr* network,
|
||||
uint8_t bits)
|
||||
{
|
||||
const uint32_t* a = (const uint32_t*)address;
|
||||
const uint32_t* n = (const uint32_t*)network;
|
||||
size_t bits_whole, bits_incomplete;
|
||||
bits_whole = bits >> 5;
|
||||
bits_incomplete = bits & 0x1F;
|
||||
|
||||
if (bits_whole)
|
||||
{
|
||||
if (memcmp(a, n, bits_whole << 2) != 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (bits_incomplete)
|
||||
{
|
||||
uint32_t mask = htonl((0xFFFFFFFFu) << (32 - bits_incomplete));
|
||||
|
||||
if ((a[bits_whole] ^ n[bits_whole]) & mask)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL check_no_proxy(rdpSettings* settings, const char* no_proxy)
|
||||
{
|
||||
const char* delimiter = ",";
|
||||
|
@ -110,10 +149,19 @@ static BOOL check_no_proxy(rdpSettings* settings, const char* no_proxy)
|
|||
char* current;
|
||||
char* copy;
|
||||
size_t host_len;
|
||||
struct sockaddr_in sa4;
|
||||
struct sockaddr_in6 sa6;
|
||||
BOOL is_ipv4 = FALSE;
|
||||
BOOL is_ipv6 = FALSE;
|
||||
|
||||
if (!no_proxy || !settings)
|
||||
return FALSE;
|
||||
|
||||
if (inet_pton(AF_INET, settings->ServerHostname, &sa4.sin_addr) == 1)
|
||||
is_ipv4 = TRUE;
|
||||
else if (inet_pton(AF_INET6, settings->ServerHostname, &sa6.sin6_addr) == 1)
|
||||
is_ipv6 = TRUE;
|
||||
|
||||
host_len = strlen(settings->ServerHostname);
|
||||
copy = _strdup(no_proxy);
|
||||
|
||||
|
@ -136,8 +184,9 @@ static BOOL check_no_proxy(rdpSettings* settings, const char* no_proxy)
|
|||
if (host_len >= currentlen)
|
||||
{
|
||||
const size_t offset = host_len + 1 - currentlen;
|
||||
const char* name = settings->ServerHostname + offset;
|
||||
|
||||
if (strncmp(current + 1, settings->ServerHostname + offset, currentlen - 1) == 0)
|
||||
if (strncmp(current + 1, name, currentlen - 1) == 0)
|
||||
result = TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -146,38 +195,54 @@ static BOOL check_no_proxy(rdpSettings* settings, const char* no_proxy)
|
|||
if (strncmp(current, settings->ServerHostname, currentlen - 1) == 0)
|
||||
result = TRUE;
|
||||
}
|
||||
else
|
||||
else if (current[0] == '.') /* Only compare if the no_proxy variable contains a whole domain. */
|
||||
{
|
||||
if (strcmp(current, settings->ServerHostname) == 0)
|
||||
result = TRUE; /* exact match */
|
||||
else
|
||||
if (host_len > currentlen)
|
||||
{
|
||||
struct sockaddr_in sa4;
|
||||
struct sockaddr_in6 sa6;
|
||||
BOOL is_ip = FALSE;
|
||||
const size_t offset = host_len - currentlen;
|
||||
const char* name = settings->ServerHostname + offset;
|
||||
|
||||
if (inet_pton(AF_INET, settings->ServerHostname, &sa4.sin_addr) == 1)
|
||||
is_ip = TRUE;
|
||||
else if (inet_pton(AF_INET6, settings->ServerHostname, &sa6.sin6_addr) == 1)
|
||||
is_ip = TRUE;
|
||||
if (strncmp(current, name, currentlen) == 0)
|
||||
result = TRUE; /* right-aligned match for host names */
|
||||
}
|
||||
}
|
||||
else if (strcmp(current, settings->ServerHostname) == 0)
|
||||
result = TRUE; /* exact match */
|
||||
else if (is_ipv4 || is_ipv6)
|
||||
{
|
||||
char* rangedelim = strchr(current, '/');
|
||||
|
||||
if (is_ip)
|
||||
/* Check for IP ranges */
|
||||
if (rangedelim != NULL)
|
||||
{
|
||||
const char* range = rangedelim + 1;
|
||||
int sub;
|
||||
int rc = sscanf(range, "%u", &sub);
|
||||
|
||||
if ((rc == 1) && (rc >= 0))
|
||||
{
|
||||
if (!strncmp(current, settings->ServerHostname, currentlen))
|
||||
result = TRUE; /* left-aligned match for IPs */
|
||||
}
|
||||
else if (current[0] == '.') /* Only compare if the no_proxy variable contains a whole domain. */
|
||||
{
|
||||
if (host_len >= currentlen)
|
||||
*rangedelim = '\0';
|
||||
|
||||
if (is_ipv4)
|
||||
{
|
||||
const size_t offset = host_len - currentlen;
|
||||
struct sockaddr_in mask;
|
||||
|
||||
if (!strncmp(current, settings->ServerHostname + offset,
|
||||
currentlen))
|
||||
result = TRUE; /* right-aligned match for host names */
|
||||
if (inet_pton(AF_INET, current, &mask.sin_addr))
|
||||
result = cidr4_match(&sa4.sin_addr, &mask.sin_addr, sub);
|
||||
}
|
||||
else if (is_ipv6)
|
||||
{
|
||||
struct sockaddr_in6 mask;
|
||||
|
||||
if (inet_pton(AF_INET6, current, &mask.sin6_addr))
|
||||
result = cidr6_match(&sa6.sin6_addr, &mask.sin6_addr, sub);
|
||||
}
|
||||
}
|
||||
else
|
||||
WLog_WARN(TAG, "NO_PROXY invalid entry %s", current);
|
||||
}
|
||||
else if (strncmp(current, settings->ServerHostname, currentlen) == 0)
|
||||
result = TRUE; /* left-aligned match for IPs */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue