From 13564dbb413d6eb302ae6c154f3ecae5073e0dc3 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 8 Aug 2018 12:26:57 +0200 Subject: [PATCH] Allow redirect address override with a list of values. --- client/common/cmdline.c | 39 +++++++++++--- client/common/cmdline.h | 2 +- libfreerdp/core/connection.c | 126 +++++++++++++++++++++++++++++-------------- 3 files changed, 120 insertions(+), 47 deletions(-) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 20c594c..d6a1d3a 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -1437,13 +1437,38 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "redirect-prefer") { - if (_strnicmp(arg->Value, "fqdn", 5) == 0) - settings->RedirectionPreferType = 0x06; - else if (_strnicmp(arg->Value, "ip", 3) == 0) - settings->RedirectionPreferType = 0x05; - else if (_strnicmp(arg->Value, "netbios", 8) == 0) - settings->RedirectionPreferType = 0x03; - else + size_t count = 0; + char* cur = arg->Value; + settings->RedirectionPreferType = 0; + + do + { + UINT32 mask; + char* next = strchr(cur, ','); + + if (next) + { + *next = '\0'; + next++; + } + + if (_strnicmp(cur, "fqdn", 5) == 0) + mask = 0x06U; + else if (_strnicmp(cur, "ip", 3) == 0) + mask = 0x05U; + else if (_strnicmp(cur, "netbios", 8) == 0) + mask = 0x03U; + else + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + cur = next; + mask = (mask & 0x07); + settings->RedirectionPreferType |= mask << (count * 3); + count++; + } + while (cur != NULL); + + if (count > 3) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } CommandLineSwitchCase(arg, "credentials-delegation") diff --git a/client/common/cmdline.h b/client/common/cmdline.h index dda6858..8affc18 100644 --- a/client/common/cmdline.h +++ b/client/common/cmdline.h @@ -141,7 +141,7 @@ static COMMAND_LINE_ARGUMENT_A args[] = { "pth", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, "pass-the-hash", "Pass the hash (restricted admin mode)" }, { "pwidth", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Physical width of display (in millimeters)" }, { "reconnect-cookie", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Pass base64 reconnect cookie to the connection" }, - { "redirect-prefer", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "When redirecting prefer FQDN|IP|NETBIOS to connect" }, + { "redirect-prefer", COMMAND_LINE_VALUE_REQUIRED, "[,[,]]", NULL, NULL, -1, NULL, "Override the preferred redirection order" }, { "restricted-admin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "restrictedAdmin", "Restricted admin mode" }, { "rfx", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "RemoteFX" }, { "rfx-mode", COMMAND_LINE_VALUE_REQUIRED, "image|video", NULL, NULL, -1, NULL, "RemoteFX mode" }, diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index fbfc66c..27c2b57 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -385,6 +385,79 @@ static BOOL rdp_client_reconnect_channels(rdpRdp* rdp, BOOL redirect) return status; } +static BOOL rdp_client_redirect_resolvable(const char* host) +{ + int status; + struct addrinfo hints = { 0 }; + struct addrinfo* result = NULL; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + status = getaddrinfo(host, NULL, &hints, &result); + errno = 0; + + if (status == 0) + { + freeaddrinfo(result); + return TRUE; + } + + return FALSE; +} + +static BOOL rdp_client_redirect_try_fqdn(rdpSettings* settings) +{ + if (settings->RedirectionFlags & LB_TARGET_FQDN) + { + if (rdp_client_redirect_resolvable(settings->RedirectionTargetFQDN)) + { + free(settings->ServerHostname); + settings->ServerHostname = _strdup(settings->RedirectionTargetFQDN); + + if (!settings->ServerHostname) + return FALSE; + + return TRUE; + } + } + + return FALSE; +} + +static BOOL rdp_client_redirect_try_ip(rdpSettings* settings) +{ + if (settings->RedirectionFlags & LB_TARGET_NET_ADDRESS) + { + free(settings->ServerHostname); + settings->ServerHostname = _strdup(settings->TargetNetAddress); + + if (!settings->ServerHostname) + return FALSE; + + return TRUE; + } + + return FALSE; +} + +static BOOL rdp_client_redirect_try_netbios(rdpSettings* settings) +{ + if (settings->RedirectionFlags & LB_TARGET_NETBIOS_NAME) + { + if (rdp_client_redirect_resolvable(settings->RedirectionTargetNetBiosName)) + { + free(settings->ServerHostname); + settings->ServerHostname = _strdup(settings->RedirectionTargetNetBiosName); + + if (!settings->ServerHostname) + return FALSE; + + return TRUE; + } + } + + return FALSE; +} + BOOL rdp_client_redirect(rdpRdp* rdp) { BOOL status; @@ -412,52 +485,27 @@ BOOL rdp_client_redirect(rdpRdp* rdp) } else { - const BOOL tryFQDN = (settings->RedirectionPreferType & 0x01) == 0; - const BOOL tryNetAddress = (settings->RedirectionPreferType & 0x02) == 0; - const BOOL tryNetbios = (settings->RedirectionPreferType & 0x04) == 0; - BOOL useFQDN = FALSE; + BOOL haveRedirectAddress = FALSE; + UINT32 redirectionMask = settings->RedirectionPreferType; - if (tryFQDN && (settings->RedirectionFlags & LB_TARGET_FQDN)) + do { - int status; - struct addrinfo hints = { 0 }; - struct addrinfo* result = NULL; - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - status = getaddrinfo(settings->RedirectionTargetFQDN, NULL, &hints, &result); - - if (status == 0) - { - freeaddrinfo(result); - free(settings->ServerHostname); - settings->ServerHostname = _strdup(settings->RedirectionTargetFQDN); + const BOOL tryFQDN = (redirectionMask & 0x01) == 0; + const BOOL tryNetAddress = (redirectionMask & 0x02) == 0; + const BOOL tryNetbios = (redirectionMask & 0x04) == 0; - if (!settings->ServerHostname) - return FALSE; - - useFQDN = TRUE; - } - } + if (tryFQDN && !haveRedirectAddress) + haveRedirectAddress = rdp_client_redirect_try_fqdn(settings); - if (!useFQDN) - { - if (tryNetAddress && (settings->RedirectionFlags & LB_TARGET_NET_ADDRESS)) - { - free(settings->ServerHostname); - settings->ServerHostname = _strdup(settings->TargetNetAddress); + if (tryNetAddress && !haveRedirectAddress) + haveRedirectAddress = rdp_client_redirect_try_ip(settings); - if (!settings->ServerHostname) - return FALSE; - } - else if (tryNetbios && (settings->RedirectionFlags & LB_TARGET_NETBIOS_NAME)) - { - free(settings->ServerHostname); - settings->ServerHostname = _strdup(settings->RedirectionTargetNetBiosName); + if (tryNetbios && !haveRedirectAddress) + haveRedirectAddress = rdp_client_redirect_try_netbios(settings); - if (!settings->ServerHostname) - return FALSE; - } + redirectionMask >>= 3; } + while (!haveRedirectAddress && (redirectionMask != 0)); } if (settings->RedirectionFlags & LB_USERNAME) -- 2.7.4