diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 386d33c95..f1ab367cd 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -1435,6 +1435,42 @@ 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") + { + 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") { settings->DisableCredentialsDelegation = arg->Value ? FALSE : TRUE; @@ -2187,18 +2223,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 +2266,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..8affc186e 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, "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/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 5f029b352..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,30 +485,27 @@ BOOL rdp_client_redirect(rdpRdp* rdp) } else { - if (settings->RedirectionFlags & LB_TARGET_NET_ADDRESS) - { - free(settings->ServerHostname); - settings->ServerHostname = _strdup(settings->TargetNetAddress); + BOOL haveRedirectAddress = FALSE; + UINT32 redirectionMask = settings->RedirectionPreferType; - if (!settings->ServerHostname) - return FALSE; - } - else if (settings->RedirectionFlags & LB_TARGET_FQDN) + do { - 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; - } - else if (settings->RedirectionFlags & LB_TARGET_NETBIOS_NAME) - { - free(settings->ServerHostname); - settings->ServerHostname = _strdup(settings->RedirectionTargetNetBiosName); + 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); + + if (tryNetbios && !haveRedirectAddress) + haveRedirectAddress = rdp_client_redirect_try_netbios(settings); + + redirectionMask >>= 3; } + while (!haveRedirectAddress && (redirectionMask != 0)); } if (settings->RedirectionFlags & LB_USERNAME)