From 6e5307c037461ecadd02d5deaf6491e6241d83ce Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 10 Mar 2023 10:36:00 +0100 Subject: [PATCH] [client,common] fix on off option parsing * Return an enum to allow evaluation of what option was provided * fix /sec:nla and /sec:nla:on behaviour. --- client/common/cmdline.c | 168 ++++++++++++++++++++++++---------------- client/common/cmdline.h | 6 +- 2 files changed, 107 insertions(+), 67 deletions(-) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 248a975a8..6494fe062 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -1730,17 +1730,25 @@ BOOL option_equals(const char* what, const char* val) return _stricmp(what, val) == 0; } -static int parse_on_off_option(const char* value) +typedef enum +{ + PARSE_ON, + PARSE_OFF, + PARSE_NONE, + PARSE_FAIL +} PARSE_ON_OFF_RESULT; + +static PARSE_ON_OFF_RESULT parse_on_off_option(const char* value) { WINPR_ASSERT(value); const char* sep = strchr(value, ':'); if (!sep) - return 1; + return PARSE_NONE; if (option_equals("on", &sep[1])) - return 1; + return PARSE_ON; if (option_equals("off", &sep[1])) - return 0; - return -1; + return PARSE_OFF; + return PARSE_FAIL; } static int parse_tls_ciphers(rdpSettings* settings, const char* Value) @@ -1901,40 +1909,40 @@ static int parse_gfx_options(rdpSettings* settings, const COMMAND_LINE_ARGUMENT_ #ifdef WITH_GFX_H264 if (option_starts_with("AVC444", val)) { - const int bval = parse_on_off_option(val); - if (bval < 0) + const PARSE_ON_OFF_RESULT bval = parse_on_off_option(val); + if (bval == PARSE_FAIL) rc = COMMAND_LINE_ERROR_UNEXPECTED_VALUE; else - GfxAVC444 = bval > 0; + GfxAVC444 = bval != PARSE_OFF; codecSelected = TRUE; } else if (option_starts_with("AVC420", val)) { - const int bval = parse_on_off_option(val); - if (bval < 0) + const PARSE_ON_OFF_RESULT bval = parse_on_off_option(val); + if (bval == PARSE_FAIL) rc = COMMAND_LINE_ERROR_UNEXPECTED_VALUE; else - GfxH264 = bval > 0; + GfxH264 = bval != PARSE_OFF; codecSelected = TRUE; } else #endif if (option_starts_with("RFX", val)) { - const int bval = parse_on_off_option(val); - if (bval < 0) + const PARSE_ON_OFF_RESULT bval = parse_on_off_option(val); + if (bval == PARSE_FAIL) rc = COMMAND_LINE_ERROR_UNEXPECTED_VALUE; else - RemoteFxCodec = bval > 0; + RemoteFxCodec = bval != PARSE_OFF; codecSelected = TRUE; } else if (option_starts_with("progressive", val)) { - const int bval = parse_on_off_option(val); - if (bval < 0) + const PARSE_ON_OFF_RESULT bval = parse_on_off_option(val); + if (bval == PARSE_FAIL) rc = COMMAND_LINE_ERROR_UNEXPECTED_VALUE; else - GfxProgressive = bval > 0; + GfxProgressive = bval != PARSE_OFF; codecSelected = TRUE; } else if (option_starts_with("mask:", val)) @@ -1948,22 +1956,25 @@ static int parse_gfx_options(rdpSettings* settings, const COMMAND_LINE_ARGUMENT_ } else if (option_starts_with("small-cache", val)) { - const int bval = parse_on_off_option(val); - if (bval < 0) + const PARSE_ON_OFF_RESULT bval = parse_on_off_option(val); + if (bval == PARSE_FAIL) rc = COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - else if (!freerdp_settings_set_bool(settings, FreeRDP_GfxSmallCache, bval > 0)) + else if (!freerdp_settings_set_bool(settings, FreeRDP_GfxSmallCache, + bval != PARSE_OFF)) rc = COMMAND_LINE_ERROR; } else if (option_starts_with("thin-client", val)) { - const int bval = parse_on_off_option(val); - if (bval < 0) + const PARSE_ON_OFF_RESULT bval = parse_on_off_option(val); + if (bval == PARSE_FAIL) rc = COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - else if (!freerdp_settings_set_bool(settings, FreeRDP_GfxThinClient, bval > 0)) + else if (!freerdp_settings_set_bool(settings, FreeRDP_GfxThinClient, + bval != PARSE_OFF)) rc = COMMAND_LINE_ERROR; if ((rc == CHANNEL_RC_OK) && (bval > 0)) { - if (!freerdp_settings_set_bool(settings, FreeRDP_GfxSmallCache, bval > 0)) + if (!freerdp_settings_set_bool(settings, FreeRDP_GfxSmallCache, + bval != PARSE_OFF)) rc = COMMAND_LINE_ERROR; } } @@ -2128,10 +2139,11 @@ static int parse_kbd_options(rdpSettings* settings, const COMMAND_LINE_ARGUMENT_ } else if (option_starts_with("unicode", val)) { - const int bval = parse_on_off_option(val); - if (bval < 0) + const PARSE_ON_OFF_RESULT bval = parse_on_off_option(val); + if (bval == PARSE_FAIL) rc = COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - else if (!freerdp_settings_set_bool(settings, FreeRDP_UnicodeInput, bval > 0)) + else if (!freerdp_settings_set_bool(settings, FreeRDP_UnicodeInput, + bval != PARSE_OFF)) rc = COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } #if defined(WITH_FREERDP_DEPRECATED_COMMANDLINE) @@ -2288,32 +2300,34 @@ static int parse_cache_options(rdpSettings* settings, const COMMAND_LINE_ARGUMEN } else { - const int bval = parse_on_off_option(val); - if (bval < 0) + const PARSE_ON_OFF_RESULT bval = parse_on_off_option(val); + if (bval == PARSE_FAIL) rc = COMMAND_LINE_ERROR_UNEXPECTED_VALUE; else { if (option_starts_with("bitmap", val)) { - if (!freerdp_settings_set_bool(settings, FreeRDP_BitmapCacheEnabled, bval > 0)) + if (!freerdp_settings_set_bool(settings, FreeRDP_BitmapCacheEnabled, + bval != PARSE_OFF)) rc = COMMAND_LINE_ERROR; } else if (option_starts_with("glyph", val)) { if (!freerdp_settings_set_uint32(settings, FreeRDP_GlyphSupportLevel, - bval > 0 ? GLYPH_SUPPORT_FULL - : GLYPH_SUPPORT_NONE)) + bval != PARSE_OFF ? GLYPH_SUPPORT_FULL + : GLYPH_SUPPORT_NONE)) rc = COMMAND_LINE_ERROR; } else if (option_starts_with("persist", val)) { if (!freerdp_settings_set_bool(settings, FreeRDP_BitmapCachePersistEnabled, - bval > 0)) + bval != PARSE_OFF)) rc = COMMAND_LINE_ERROR; } else if (option_starts_with("offscreen", val)) { - if (!freerdp_settings_set_uint32(settings, FreeRDP_OffscreenSupportLevel, bval)) + if (!freerdp_settings_set_uint32(settings, FreeRDP_OffscreenSupportLevel, + bval != PARSE_OFF)) rc = COMMAND_LINE_ERROR; } } @@ -3584,51 +3598,69 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "sec") { - BOOL RdpSecurity = FALSE; - BOOL TlsSecurity = FALSE; - BOOL NlaSecurity = FALSE; - BOOL ExtSecurity = FALSE; size_t count = 0, x; char** ptr = CommandLineParseCommaSeparatedValues(arg->Value, &count); if (count == 0) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + size_t singleOptionWithoutOnOff = 0; for (x = 0; x < count; x++) { const char* cur = ptr[x]; - const int bval = parse_on_off_option(cur); - if (bval < 0) + const PARSE_ON_OFF_RESULT bval = parse_on_off_option(cur); + if (bval == PARSE_FAIL) { free(ptr); return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } - if (option_equals("rdp", cur)) /* Standard RDP */ - RdpSecurity = bval > 0; - else if (option_equals("tls", cur)) /* TLS */ - TlsSecurity = bval > 0; - else if (option_equals("nla", cur)) /* NLA */ - NlaSecurity = bval > 0; - else if (option_equals("ext", cur)) /* NLA Extended */ - ExtSecurity = bval > 0; + + const BOOL val = bval != PARSE_OFF; + size_t id = 0; + if (option_starts_with("rdp", cur)) /* Standard RDP */ + { + id = FreeRDP_RdpSecurity; + if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, val)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + } + else if (option_starts_with("tls", cur)) /* TLS */ + id = FreeRDP_TlsSecurity; + else if (option_starts_with("nla", cur)) /* NLA */ + id = FreeRDP_NlaSecurity; + else if (option_starts_with("ext", cur)) /* NLA Extended */ + id = FreeRDP_ExtSecurity; else { WLog_ERR(TAG, "unknown protocol security: %s", arg->Value); free(ptr); return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } + + if ((bval == PARSE_NONE) && (count == 1)) + singleOptionWithoutOnOff = id; + if (!freerdp_settings_set_bool(settings, id, val)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } + if (singleOptionWithoutOnOff != 0) + { + const size_t options[] = { FreeRDP_UseRdpSecurityLayer, FreeRDP_RdpSecurity, + FreeRDP_NlaSecurity, FreeRDP_TlsSecurity }; + + for (size_t x = 0; x < ARRAYSIZE(options); x++) + { + if (!freerdp_settings_set_bool(settings, options[x], FALSE)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + } + + if (!freerdp_settings_set_bool(settings, singleOptionWithoutOnOff, TRUE)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + if (singleOptionWithoutOnOff == FreeRDP_RdpSecurity) + { + if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, TRUE)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + } + } free(ptr); - if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, RdpSecurity)) - return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - if (!freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, RdpSecurity)) - return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - if (!freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, TlsSecurity)) - return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - if (!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, NlaSecurity)) - return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - if (!freerdp_settings_set_bool(settings, FreeRDP_ExtSecurity, ExtSecurity)) - return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } CommandLineSwitchCase(arg, "encryption-methods") { @@ -3881,13 +3913,19 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, { Floatbar &= ~0x02u; - const int bval = parse_on_off_option(cur); - if (bval > 0) - Floatbar |= 0x02u; - else if (bval == 0) - Floatbar &= ~0x02u; - else - return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + const PARSE_ON_OFF_RESULT bval = parse_on_off_option(cur); + switch (bval) + { + case PARSE_ON: + case PARSE_NONE: + Floatbar |= 0x02u; + break; + case PARSE_OFF: + Floatbar &= ~0x02u; + break; + default: + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + } } /* default:[visible|hidden] */ else if (option_starts_with("default:", cur)) diff --git a/client/common/cmdline.h b/client/common/cmdline.h index 4c55cbb54..1d90f71ce 100644 --- a/client/common/cmdline.h +++ b/client/common/cmdline.h @@ -373,8 +373,10 @@ static const COMMAND_LINE_ARGUMENT_A global_cmd_args[] = { "Scaling factor for desktop applications (value between 100 and 500)" }, { "scale-device", COMMAND_LINE_VALUE_REQUIRED, "100|140|180", "100", NULL, -1, NULL, "Scaling factor for app store applications" }, - { "sec", COMMAND_LINE_VALUE_REQUIRED, "[rdp|tls|nla|ext]", NULL, NULL, -1, NULL, - "Force specific protocol security" }, + { "sec", COMMAND_LINE_VALUE_REQUIRED, + "[rdp[:[on|off]]|tls[:[on|off]]|nla[:[on|off]]|ext[:[on|off]]]", NULL, NULL, -1, NULL, + "Force specific protocol security. e.g. /sec:nla enables NLA and disables all others, while " + "/sec:nla:[on|off] just toggles NLA" }, #if defined(WITH_FREERDP_DEPRECATED_COMMANDLINE) { "sec-ext", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "[DEPRECATED, use /sec:ext] NLA extended protocol security" },