From f6b6eba0ab042515f6fa8d8c51bd958e7e4fa8fb Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 8 Aug 2018 10:25:09 +0200 Subject: [PATCH 1/3] Try redirection FQDN first, but check if it is resolvable. --- libfreerdp/core/connection.c | 55 ++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 5f029b352..4cdfaed7a 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -412,29 +412,48 @@ BOOL rdp_client_redirect(rdpRdp* rdp) } else { - if (settings->RedirectionFlags & LB_TARGET_NET_ADDRESS) - { - free(settings->ServerHostname); - settings->ServerHostname = _strdup(settings->TargetNetAddress); + BOOL useFQDN = FALSE; - if (!settings->ServerHostname) - return FALSE; + if (settings->RedirectionFlags & LB_TARGET_FQDN) + { + 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); + + if (!settings->ServerHostname) + return FALSE; + + useFQDN = TRUE; + } } - else if (settings->RedirectionFlags & LB_TARGET_FQDN) - { - free(settings->ServerHostname); - settings->ServerHostname = _strdup(settings->RedirectionTargetFQDN); - if (!settings->ServerHostname) - return FALSE; - } - else if (settings->RedirectionFlags & LB_TARGET_NETBIOS_NAME) + if (!useFQDN) { - free(settings->ServerHostname); - settings->ServerHostname = _strdup(settings->RedirectionTargetNetBiosName); + if (settings->RedirectionFlags & LB_TARGET_NET_ADDRESS) + { + free(settings->ServerHostname); + settings->ServerHostname = _strdup(settings->TargetNetAddress); - if (!settings->ServerHostname) - return FALSE; + if (!settings->ServerHostname) + return FALSE; + } + else if (settings->RedirectionFlags & LB_TARGET_NETBIOS_NAME) + { + free(settings->ServerHostname); + settings->ServerHostname = _strdup(settings->RedirectionTargetNetBiosName); + + if (!settings->ServerHostname) + return FALSE; + } } } From cc5e402cdac3b57680fa86dc939bf7603c755e89 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 8 Aug 2018 11:16:24 +0200 Subject: [PATCH 2/3] Added command line option /redirect-prefer: Since redirection sometimes happens with internal DNS names that are resolved different by outside DNS it must be possible to override the preferred redirection hint. --- client/common/cmdline.c | 21 ++++++++++++++++----- client/common/cmdline.h | 1 + include/freerdp/settings.h | 3 ++- libfreerdp/core/connection.c | 9 ++++++--- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 98421c488..20c594cc2 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -1435,6 +1435,17 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (!(settings->AuthenticationServiceClass = _strdup(arg->Value))) return COMMAND_LINE_ERROR_MEMORY; } + 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 + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + } CommandLineSwitchCase(arg, "credentials-delegation") { settings->DisableCredentialsDelegation = arg->Value ? FALSE : TRUE; @@ -2187,18 +2198,18 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, { #ifdef WITH_GFX_H264 - if (_strnicmp("AVC444", arg->Value, 6) == 0) + if (_strnicmp("AVC444", arg->Value, 7) == 0) { settings->GfxH264 = TRUE; settings->GfxAVC444 = TRUE; } - else if (_strnicmp("AVC420", arg->Value, 6) == 0) + else if (_strnicmp("AVC420", arg->Value, 7) == 0) { settings->GfxH264 = TRUE; } else #endif - if (_strnicmp("RFX", arg->Value, 3) != 0) + if (_strnicmp("RFX", arg->Value, 4) != 0) return COMMAND_LINE_ERROR; } } @@ -2230,11 +2241,11 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (arg->Value) { - if (_strnicmp("AVC444", arg->Value, 6) == 0) + if (_strnicmp("AVC444", arg->Value, 7) == 0) { settings->GfxAVC444 = TRUE; } - else if (_strnicmp("AVC420", arg->Value, 6) != 0) + else if (_strnicmp("AVC420", arg->Value, 7) != 0) return COMMAND_LINE_ERROR; } } diff --git a/client/common/cmdline.h b/client/common/cmdline.h index c1210925f..dda685824 100644 --- a/client/common/cmdline.h +++ b/client/common/cmdline.h @@ -141,6 +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" }, { "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/include/freerdp/settings.h b/include/freerdp/settings.h index e4237dc88..0a548e778 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -1078,7 +1078,8 @@ struct rdp_settings ALIGN64 UINT32* TargetNetPorts; /* 1230 */ ALIGN64 char* RedirectionAcceptedCert; /* 1231 */ ALIGN64 UINT32 RedirectionAcceptedCertLength;/* 1232 */ - UINT64 padding1280[1280 - 1233]; /* 1233 */ + ALIGN64 UINT32 RedirectionPreferType; /* 1233 */ + UINT64 padding1280[1280 - 1234]; /* 1234 */ /** * Security diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 4cdfaed7a..fbfc66cd2 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -412,9 +412,12 @@ 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; - if (settings->RedirectionFlags & LB_TARGET_FQDN) + if (tryFQDN && (settings->RedirectionFlags & LB_TARGET_FQDN)) { int status; struct addrinfo hints = { 0 }; @@ -438,7 +441,7 @@ BOOL rdp_client_redirect(rdpRdp* rdp) if (!useFQDN) { - if (settings->RedirectionFlags & LB_TARGET_NET_ADDRESS) + if (tryNetAddress && (settings->RedirectionFlags & LB_TARGET_NET_ADDRESS)) { free(settings->ServerHostname); settings->ServerHostname = _strdup(settings->TargetNetAddress); @@ -446,7 +449,7 @@ BOOL rdp_client_redirect(rdpRdp* rdp) if (!settings->ServerHostname) return FALSE; } - else if (settings->RedirectionFlags & LB_TARGET_NETBIOS_NAME) + else if (tryNetbios && (settings->RedirectionFlags & LB_TARGET_NETBIOS_NAME)) { free(settings->ServerHostname); settings->ServerHostname = _strdup(settings->RedirectionTargetNetBiosName); From 13564dbb413d6eb302ae6c154f3ecae5073e0dc3 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 8 Aug 2018 12:26:57 +0200 Subject: [PATCH 3/3] Allow redirect address override with a list of values. --- client/common/cmdline.c | 39 +++++++++-- client/common/cmdline.h | 2 +- libfreerdp/core/connection.c | 128 ++++++++++++++++++++++++----------- 3 files changed, 121 insertions(+), 48 deletions(-) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 20c594cc2..d6a1d3ab3 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 dda685824..8affc186e 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 fbfc66cd2..27c2b5746 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); + const BOOL tryFQDN = (redirectionMask & 0x01) == 0; + const BOOL tryNetAddress = (redirectionMask & 0x02) == 0; + const BOOL tryNetbios = (redirectionMask & 0x04) == 0; - if (status == 0) - { - freeaddrinfo(result); - free(settings->ServerHostname); - settings->ServerHostname = _strdup(settings->RedirectionTargetFQDN); + if (tryFQDN && !haveRedirectAddress) + haveRedirectAddress = rdp_client_redirect_try_fqdn(settings); - if (!settings->ServerHostname) - return FALSE; + if (tryNetAddress && !haveRedirectAddress) + haveRedirectAddress = rdp_client_redirect_try_ip(settings); - useFQDN = TRUE; - } - } - - if (!useFQDN) - { - if (tryNetAddress && (settings->RedirectionFlags & LB_TARGET_NET_ADDRESS)) - { - free(settings->ServerHostname); - settings->ServerHostname = _strdup(settings->TargetNetAddress); - - if (!settings->ServerHostname) - return FALSE; - } - else if (tryNetbios && (settings->RedirectionFlags & LB_TARGET_NETBIOS_NAME)) - { - free(settings->ServerHostname); - settings->ServerHostname = _strdup(settings->RedirectionTargetNetBiosName); - - if (!settings->ServerHostname) - return FALSE; - } + if (tryNetbios && !haveRedirectAddress) + haveRedirectAddress = rdp_client_redirect_try_netbios(settings); + + redirectionMask >>= 3; } + while (!haveRedirectAddress && (redirectionMask != 0)); } if (settings->RedirectionFlags & LB_USERNAME)