From 78a0c4c6180b9481587e81037e2f1fb4c4345e2c Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 30 Nov 2017 16:56:45 +0100 Subject: [PATCH] Fix #4296: Hardened command line post filter. --- client/common/cmdline.c | 240 +++++++++++-------------- client/common/compatibility.c | 19 +- client/common/test/TestClientCmdLine.c | 167 +++++++++++------ winpr/libwinpr/utils/cmdline.c | 39 ++-- 4 files changed, 248 insertions(+), 217 deletions(-) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index e4374c128..29075ff13 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -397,7 +398,7 @@ BOOL freerdp_client_add_device_channel(rdpSettings* settings, int count, if (count > 2) { - if (!(drive->Path = _strdup(params[2]))) + if (!PathFileExistsA(params[2]) || !(drive->Path = _strdup(params[2]))) { free(drive->Name); free(drive); @@ -736,75 +737,101 @@ error_argv: return FALSE; } -static char** freerdp_command_line_parse_comma_separated_values(char* list, - int* count) +static char** freerdp_command_line_parse_comma_separated_values_ex(const char* name, const char* list, + size_t* count) { char** p; char* str; - int nArgs; - int index; - int nCommas; + size_t nArgs; + size_t index; + size_t nCommas; + size_t prefix, len; nCommas = 0; assert(NULL != count); *count = 0; if (!list) - return NULL; + { + if (name) + { + p = (char**) calloc(1UL, sizeof(char*)); - for (index = 0; list[index]; index++) - nCommas += (list[index] == ',') ? 1 : 0; + if (p) + { + p[0] = name; + *count = 1; + return p; + } + } + + return NULL; + } + + { + const char* it = list; + while((it = strchr(it, ',')) != NULL) + { + it++; + nCommas++; + } + } nArgs = nCommas + 1; - p = (char**) calloc((nArgs + 1UL), sizeof(char*)); + + if (name) + nArgs++; + + prefix = (nArgs + 1UL) * sizeof(char*); + len = strlen(list); + p = (char**) calloc(len + prefix + 1, sizeof(char)); if (!p) return NULL; - str = (char*) list; - p[0] = str; + str = &((char*)p)[prefix]; + memcpy(str, list, len); - for (index = 1; index < nArgs; index++) + if (name) + p[0] = (char*)name; + + for (index = name ? 1 : 0; index < nArgs; index++) { - p[index] = strchr(p[index - 1], ','); - *p[index] = '\0'; - p[index]++; + char* comma = strchr(str, ','); + p[index] = str; + + if (comma) + { + str = comma + 1; + *comma = '\0'; + } } - p[index] = str + strlen(str); *count = nArgs; return p; } -static char** freerdp_command_line_parse_comma_separated_values_offset( - char* list, int* count) +static char** freerdp_command_line_parse_comma_separated_values(char* list, + size_t* count) { - char** p; - char** t; - p = freerdp_command_line_parse_comma_separated_values(list, count); - t = (char**) realloc(p, sizeof(char*) * (*count + 1)); + return freerdp_command_line_parse_comma_separated_values_ex(NULL, list, count); +} - if (!t) - return NULL; - - p = t; - - if (*count) - MoveMemory(&p[1], p, sizeof(char*)** count); - - (*count)++; - return p; +static char** freerdp_command_line_parse_comma_separated_values_offset( + const char* name, char* list, size_t* count) +{ + return freerdp_command_line_parse_comma_separated_values_ex(name, list, count); } static int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT_A* arg) { rdpSettings* settings = (rdpSettings*) context; - BOOL status = FALSE; + BOOL status = TRUE; CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "a") { char** p; - int count; + size_t count; p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count); if ((status = freerdp_client_add_device_channel(settings, count, p))) @@ -817,7 +844,7 @@ static int freerdp_client_command_line_post_filter(void* context, CommandLineSwitchCase(arg, "vc") { char** p; - int count; + size_t count; p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count); status = freerdp_client_add_static_channel(settings, count, p); free(p); @@ -825,7 +852,7 @@ static int freerdp_client_command_line_post_filter(void* context, CommandLineSwitchCase(arg, "dvc") { char** p; - int count; + size_t count; p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count); status = freerdp_client_add_dynamic_channel(settings, count, p); free(p); @@ -833,71 +860,54 @@ static int freerdp_client_command_line_post_filter(void* context, CommandLineSwitchCase(arg, "drive") { char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset(arg->Name, arg->Value, &count); - p[0] = "drive"; status = freerdp_client_add_device_channel(settings, count, p); free(p); } CommandLineSwitchCase(arg, "serial") { char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset(arg->Name, arg->Value, &count); - p[0] = "serial"; status = freerdp_client_add_device_channel(settings, count, p); free(p); } CommandLineSwitchCase(arg, "parallel") { char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset(arg->Name, arg->Value, &count); - p[0] = "parallel"; status = freerdp_client_add_device_channel(settings, count, p); free(p); } CommandLineSwitchCase(arg, "smartcard") { char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset(arg->Name, arg->Value, &count); - p[0] = "smartcard"; status = freerdp_client_add_device_channel(settings, count, p); free(p); } CommandLineSwitchCase(arg, "printer") { - if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) - { - char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, - &count); - p[0] = "printer"; - status = freerdp_client_add_device_channel(settings, count, p); - free(p); - } - else - { - char* p[1]; - int count; - count = 1; - p[0] = "printer"; - status = freerdp_client_add_device_channel(settings, count, p); - } + char** p; + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset(arg->Name, arg->Value, + &count); + status = freerdp_client_add_device_channel(settings, count, p); + free(p); } CommandLineSwitchCase(arg, "usb") { char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset("urbdrc", arg->Value, &count); - p[0] = "urbdrc"; status = freerdp_client_add_dynamic_channel(settings, count, p); free(p); } @@ -923,66 +933,30 @@ static int freerdp_client_command_line_post_filter(void* context, } CommandLineSwitchCase(arg, "sound") { - if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) - { - char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, - &count); - p[0] = "rdpsnd"; - status = freerdp_client_add_static_channel(settings, count, p); - free(p); - } - else - { - char* p[1]; - int count; - count = 1; - p[0] = "rdpsnd"; - status = freerdp_client_add_static_channel(settings, count, p); - } + char** p; + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset("rdpsnd", arg->Value, + &count); + status = freerdp_client_add_static_channel(settings, count, p); + free(p); } CommandLineSwitchCase(arg, "microphone") { - if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) - { - char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, - &count); - p[0] = "audin"; - status = freerdp_client_add_dynamic_channel(settings, count, p); - free(p); - } - else - { - char* p[1]; - int count; - count = 1; - p[0] = "audin"; - status = freerdp_client_add_dynamic_channel(settings, count, p); - } + char** p; + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset("audin", arg->Value, + &count); + status = freerdp_client_add_dynamic_channel(settings, count, p); + free(p); } CommandLineSwitchCase(arg, "multimedia") { - if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) - { - char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, - &count); - p[0] = "tsmf"; - status = freerdp_client_add_dynamic_channel(settings, count, p); - free(p); - } - else - { - char* p[1]; - int count; - count = 1; - p[0] = "tsmf"; - status = freerdp_client_add_dynamic_channel(settings, count, p); - } + char** p; + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset("tsmf", arg->Value, + &count); + status = freerdp_client_add_dynamic_channel(settings, count, p); + free(p); } CommandLineSwitchCase(arg, "heartbeat") { @@ -999,7 +973,7 @@ static int freerdp_client_command_line_post_filter(void* context, settings->PasswordIsSmartcardPin = TRUE; } CommandLineSwitchEnd(arg) - return status ? 1 : 0; + return status ? 1 : -1; } BOOL freerdp_parse_username(char* username, char** user, char** domain) @@ -1250,8 +1224,8 @@ static int freerdp_detect_command_line_pre_filter(void* context, int index, return 0; } -int freerdp_detect_windows_style_command_line_syntax(int argc, char** argv, - int* count, BOOL ignoreUnknown) +static int freerdp_detect_windows_style_command_line_syntax(int argc, char** argv, + size_t* count, BOOL ignoreUnknown) { int status; DWORD flags; @@ -1292,7 +1266,7 @@ int freerdp_detect_windows_style_command_line_syntax(int argc, char** argv, } int freerdp_detect_posix_style_command_line_syntax(int argc, char** argv, - int* count, BOOL ignoreUnknown) + size_t* count, BOOL ignoreUnknown) { int status; DWORD flags; @@ -1339,9 +1313,9 @@ static BOOL freerdp_client_detect_command_line(int argc, char** argv, int old_cli_status; int old_cli_count; int posix_cli_status; - int posix_cli_count; + size_t posix_cli_count; int windows_cli_status; - int windows_cli_count; + size_t windows_cli_count; BOOL compatibility = FALSE; windows_cli_status = freerdp_detect_windows_style_command_line_syntax(argc, argv, &windows_cli_count, ignoreUnknown); @@ -1477,7 +1451,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, char* user = NULL; char* gwUser = NULL; char* str; - int length; + size_t length; int status; DWORD flags; BOOL promptForPassword = FALSE; @@ -1748,7 +1722,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, { UINT32 i; char** p; - int count = 0; + size_t count = 0; p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count); if (!p) @@ -2440,7 +2414,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, { UINT32 i; char** p; - int count = 0; + size_t count = 0; p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count); for (i = 0; i < count; i++) diff --git a/client/common/compatibility.c b/client/common/compatibility.c index 154e7ff5d..468339abe 100644 --- a/client/common/compatibility.c +++ b/client/common/compatibility.c @@ -41,7 +41,7 @@ #define TAG CLIENT_TAG("common.compatibility") -COMMAND_LINE_ARGUMENT_A old_args[] = +static COMMAND_LINE_ARGUMENT_A old_args[] = { { "0", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "connect to console session" }, { "a", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "set color depth in bits, default is 16" }, @@ -93,7 +93,7 @@ COMMAND_LINE_ARGUMENT_A old_args[] = { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; -BOOL freerdp_client_old_parse_hostname(char* str, char** ServerHostname, UINT32* ServerPort) +static BOOL freerdp_client_old_parse_hostname(char* str, char** ServerHostname, UINT32* ServerPort) { char* p; char* host = NULL; @@ -152,7 +152,7 @@ BOOL freerdp_client_old_parse_hostname(char* str, char** ServerHostname, UINT32* return TRUE; } -int freerdp_client_old_process_plugin(rdpSettings* settings, ADDIN_ARGV* args) +static int freerdp_client_old_process_plugin(rdpSettings* settings, ADDIN_ARGV* args) { int args_handled = 0; @@ -231,7 +231,8 @@ int freerdp_client_old_process_plugin(rdpSettings* settings, ADDIN_ARGV* args) return args_handled; } -int freerdp_client_old_command_line_pre_filter(void* context, int index, int argc, LPCSTR* argv) +static int freerdp_client_old_command_line_pre_filter(void* context, int index, int argc, + LPCSTR* argv) { rdpSettings* settings = (rdpSettings*) context; @@ -399,7 +400,7 @@ int freerdp_client_old_command_line_pre_filter(void* context, int index, int arg return 0; } -int freerdp_client_old_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT_A* arg) +static int freerdp_client_old_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT_A* arg) { return 0; } @@ -521,7 +522,7 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe unsigned long val = strtoul(arg->Value, NULL, 0); if ((errno != 0) || (val > INT8_MAX)) - return FALSE; + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; settings->ColorDepth = val; WLog_WARN(TAG, "-a %s -> /bpp:%s", arg->Value, arg->Value); @@ -571,7 +572,7 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe if ((errno != 0) || (w == 0) || (w > UINT16_MAX)) { free(str); - return FALSE; + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } h = strtoul(&p[1], NULL, 0); @@ -579,7 +580,7 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe if ((errno != 0) || (h == 0) || (h > UINT16_MAX)) { free(str); - return FALSE; + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } *p = '\0'; @@ -862,5 +863,5 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe WLog_WARN(TAG, " /port:%"PRIu32"", settings->ServerPort); WLog_WARN(TAG, ""); - return 1; + return 0; } diff --git a/client/common/test/TestClientCmdLine.c b/client/common/test/TestClientCmdLine.c index df8588afa..5b1114f4c 100644 --- a/client/common/test/TestClientCmdLine.c +++ b/client/common/test/TestClientCmdLine.c @@ -4,31 +4,41 @@ #include #include -#define TESTCASE(cmd, expected_return) \ -{ \ - rdpSettings* settings = freerdp_settings_new(0); \ - status = freerdp_client_settings_parse_command_line(settings, ARRAYSIZE(cmd), cmd, FALSE); \ - freerdp_settings_free(settings); \ - if (status != expected_return) { \ - printf("Test argument %s failed\n", #cmd); \ - return -1; \ - } \ -} - -#define TESTCASE_SUCCESS(cmd) \ -{ \ - rdpSettings* settings = freerdp_settings_new(0); \ - status = freerdp_client_settings_parse_command_line(settings, ARRAYSIZE(cmd), cmd, FALSE); \ - freerdp_settings_free(settings); \ - if (status < 0) { \ - printf("Test argument %s failed\n", #cmd); \ - return -1; \ - } \ -} - -int TestClientCmdLine(int argc, char* argv[]) +#define TESTCASE(argv, ret_val) TESTCASE_impl(#argv, argv, ARRAYSIZE(argv), ret_val) +#define TESTCASE_SUCCESS(argv) TESTCASE_impl(#argv, argv, ARRAYSIZE(argv), 0) +static INLINE BOOL TESTCASE_impl(const char* name, char** argv, size_t argc, + int expected_return) { int status; + rdpSettings* settings = freerdp_settings_new(0); + printf("Running test %s\n", name); + + if (!settings) + { + fprintf(stderr, "Test %s could not allocate settings!\n", name); + return FALSE; + } + + status = freerdp_client_settings_parse_command_line(settings, argc, argv, FALSE); + freerdp_settings_free(settings); + + if (status != expected_return) + { + fprintf(stderr, "Test %s failed!\n", name); + return FALSE; + } + + return TRUE; +} + +#if defined(_WIN32) +#define DRIVE_REDIRECT_PATH "c:\\Windows" +#else +#define DRIVE_REDIRECT_PATH "/tmp" +#endif +int TestClientCmdLine(int argc, char* argv[]) +{ + int rc = -1; char* cmd1[] = {"xfreerdp", "--help"}; char* cmd2[] = {"xfreerdp", "/help"}; char* cmd3[] = {"xfreerdp", "-help"}; @@ -39,8 +49,8 @@ int TestClientCmdLine(int argc, char* argv[]) char* cmd8[] = {"xfreerdp", "-v", "test.freerdp.com"}; char* cmd9[] = {"xfreerdp", "--v", "test.freerdp.com"}; char* cmd10[] = {"xfreerdp", "/v:test.freerdp.com"}; - char* cmd11[] = {"xfreerdp", "--plugin", "rdpsnd", "--plugin", "rdpdr", "--data", "disk:media:/tmp", "--", "test.freerdp.com" }; - char* cmd12[] = {"xfreerdp", "/sound", "/drive:media:/tmp", "/v:test.freerdp.com" }; + char* cmd11[] = {"xfreerdp", "--plugin", "rdpsnd", "--plugin", "rdpdr", "--data", "disk:media:"DRIVE_REDIRECT_PATH, "--", "test.freerdp.com" }; + char* cmd12[] = {"xfreerdp", "/sound", "/drive:media,"DRIVE_REDIRECT_PATH, "/v:test.freerdp.com" }; char* cmd13[] = {"xfreerdp", "-u", "test", "-p", "test", "test.freerdp.com"}; char* cmd14[] = {"xfreerdp", "-u", "test", "-p", "test", "-v", "test.freerdp.com"}; char* cmd15[] = {"xfreerdp", "/u:test", "/p:test", "/v:test.freerdp.com"}; @@ -48,60 +58,99 @@ int TestClientCmdLine(int argc, char* argv[]) char* cmd17[] = {"xfreerdp", "--invalid"}; char* cmd18[] = {"xfreerdp", "/kbd-list"}; char* cmd19[] = {"xfreerdp", "/monitor-list"}; + char* cmd20[] = {"xfreerdp", "/sound", "/drive:media:"DRIVE_REDIRECT_PATH, "/v:test.freerdp.com" }; + char* cmd21[] = {"xfreerdp", "/sound", "/drive:media,/foo/bar/blabla", "/v:test.freerdp.com" }; - TESTCASE(cmd1, COMMAND_LINE_STATUS_PRINT_HELP); + if (!TESTCASE(cmd1, COMMAND_LINE_STATUS_PRINT_HELP)) + goto fail; - TESTCASE(cmd2, COMMAND_LINE_STATUS_PRINT_HELP); + if (!TESTCASE(cmd2, COMMAND_LINE_STATUS_PRINT_HELP)) + goto fail; - TESTCASE(cmd3, COMMAND_LINE_STATUS_PRINT_HELP); + if (!TESTCASE(cmd3, COMMAND_LINE_STATUS_PRINT_HELP)) + goto fail; - TESTCASE(cmd4, COMMAND_LINE_STATUS_PRINT_VERSION); + if (!TESTCASE(cmd4, COMMAND_LINE_STATUS_PRINT_VERSION)) + goto fail; - TESTCASE(cmd5, COMMAND_LINE_STATUS_PRINT_VERSION); + if (!TESTCASE(cmd5, COMMAND_LINE_STATUS_PRINT_VERSION)) + goto fail; - TESTCASE(cmd6, COMMAND_LINE_STATUS_PRINT_VERSION); + if (!TESTCASE(cmd6, COMMAND_LINE_STATUS_PRINT_VERSION)) + goto fail; - TESTCASE_SUCCESS(cmd7); + if (!TESTCASE_SUCCESS(cmd7)) + goto fail; - TESTCASE_SUCCESS(cmd8); + if (!TESTCASE_SUCCESS(cmd8)) + goto fail; - TESTCASE_SUCCESS(cmd9); + if (!TESTCASE_SUCCESS(cmd9)) + goto fail; - TESTCASE_SUCCESS(cmd10); + if (!TESTCASE_SUCCESS(cmd10)) + goto fail; - TESTCASE_SUCCESS(cmd11); + if (!TESTCASE_SUCCESS(cmd11)) + goto fail; - TESTCASE_SUCCESS(cmd12); + if (!TESTCASE_SUCCESS(cmd12)) + goto fail; // password gets overwritten therefore it need to be writeable - cmd13[4] = calloc(5, sizeof(char)); - strncpy(cmd13[4], "test", 4); - TESTCASE_SUCCESS(cmd13); + cmd13[4] = _strdup("test"); + cmd14[4] = _strdup("test"); + cmd15[2] = _strdup("/p:test"); + + if (!cmd13[4] || !cmd14[4] || !cmd15[2]) + goto free_arg; + + if (!TESTCASE_SUCCESS(cmd13)) + goto free_arg; + + if (memcmp(cmd13[4], "****", 4) != 0) + goto free_arg; + + if (!TESTCASE_SUCCESS(cmd14)) + goto free_arg; + + if (memcmp(cmd14[4], "****", 4) != 0) + goto free_arg; + + if (!TESTCASE_SUCCESS(cmd15)) + goto free_arg; + + if (memcmp(cmd15[2], "/p:****", 7) != 0) + goto free_arg; + + if (!TESTCASE(cmd16, COMMAND_LINE_ERROR_NO_KEYWORD)) + goto free_arg; + + if (!TESTCASE(cmd17, COMMAND_LINE_ERROR_NO_KEYWORD)) + goto free_arg; + + if (!TESTCASE(cmd18, COMMAND_LINE_STATUS_PRINT)) + goto free_arg; + + if (!TESTCASE(cmd19, COMMAND_LINE_STATUS_PRINT)) + goto free_arg; + + if (!TESTCASE(cmd20, COMMAND_LINE_ERROR)) + goto free_arg; + + if (!TESTCASE(cmd21, COMMAND_LINE_ERROR)) + goto free_arg; + + rc = 0; +free_arg: free(cmd13[4]); - - cmd14[4] = calloc(5, sizeof(char)); - strncpy(cmd14[4], "test", 4); - TESTCASE_SUCCESS(cmd14); free(cmd14[4]); - - cmd15[2] = calloc(7, sizeof(char)); - strncpy(cmd15[2], "/p:test", 6); - TESTCASE_SUCCESS(cmd15); free(cmd15[2]); - - TESTCASE(cmd16, COMMAND_LINE_ERROR_NO_KEYWORD); - - TESTCASE(cmd17, COMMAND_LINE_ERROR_NO_KEYWORD); - - TESTCASE(cmd18, COMMAND_LINE_STATUS_PRINT); - - TESTCASE(cmd19, COMMAND_LINE_STATUS_PRINT); - #if 0 char* cmd20[] = {"-z --plugin cliprdr --plugin rdpsnd --data alsa latency:100 -- --plugin rdpdr --data disk:w7share:/home/w7share -- --plugin drdynvc --data tsmf:decoder:gstreamer -- -u test host.example.com"}; TESTCASE(cmd20, COMMAND_LINE_STATUS_PRINT); #endif - - return 0; +fail: + return rc; } diff --git a/winpr/libwinpr/utils/cmdline.c b/winpr/libwinpr/utils/cmdline.c index 9d751abe9..473286a1e 100644 --- a/winpr/libwinpr/utils/cmdline.c +++ b/winpr/libwinpr/utils/cmdline.c @@ -54,17 +54,15 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* int count; size_t length; BOOL notescaped; - char* sigil; + const char* sigil; size_t sigil_length; - char* keyword; + const char* keyword; SSIZE_T keyword_length; SSIZE_T keyword_index; char* separator; - char* value; + const char* value; int toggle; - status = 0; - notescaped = FALSE; if (!argv) @@ -76,6 +74,7 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* status = 0; else status = COMMAND_LINE_STATUS_PRINT_HELP; + return status; } @@ -101,7 +100,7 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* } } - sigil = (char*) argv[i]; + sigil = argv[i]; length = strlen(argv[i]); if ((sigil[0] == '/') && (flags & COMMAND_LINE_SIGIL_SLASH)) @@ -151,12 +150,12 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* { if ((flags & COMMAND_LINE_IGN_UNKNOWN_KEYWORD)) continue; + return COMMAND_LINE_ERROR_NO_KEYWORD; } keyword_index = sigil_length; - keyword = (char*) &argv[i][keyword_index]; - + keyword = &argv[i][keyword_index]; toggle = -1; if (flags & COMMAND_LINE_SIGIL_ENABLE_DISABLE) @@ -165,13 +164,13 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* { toggle = TRUE; keyword_index += 7; - keyword = (char*) &argv[i][keyword_index]; + keyword = &argv[i][keyword_index]; } else if (strncmp(keyword, "disable-", 8) == 0) { toggle = FALSE; keyword_index += 8; - keyword = (char*) &argv[i][keyword_index]; + keyword = &argv[i][keyword_index]; } } @@ -188,12 +187,11 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* SSIZE_T separator_index = (separator - argv[i]); SSIZE_T value_index = separator_index + 1; keyword_length = (separator - keyword); - value = (char*) &argv[i][value_index]; + value = &argv[i][value_index]; } else { keyword_length = (length - keyword_index); - value = NULL; } @@ -253,10 +251,11 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* argument = TRUE; else argument = FALSE; + if (value_present && argument) { i++; - value = (char*) argv[i]; + value = argv[i]; } else if (!value_present && (options[j].Flags & COMMAND_LINE_VALUE_OPTIONAL)) { @@ -326,7 +325,15 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* } if (postFilter) - postFilter(context, &options[j]); + { + count = postFilter(context, &options[j]); + + if (count < 0) + { + status = COMMAND_LINE_ERROR; + return status; + } + } if (options[j].Flags & COMMAND_LINE_PRINT) return COMMAND_LINE_STATUS_PRINT; @@ -337,6 +344,7 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* else if (options[j].Flags & COMMAND_LINE_PRINT_BUILDCONFIG) return COMMAND_LINE_STATUS_PRINT_BUILDCONFIG; } + if (!found && (flags & COMMAND_LINE_IGN_UNKNOWN_KEYWORD) == 0) return COMMAND_LINE_ERROR_NO_KEYWORD; } @@ -354,7 +362,7 @@ int CommandLineParseArgumentsW(int argc, LPCWSTR* argv, COMMAND_LINE_ARGUMENT_W* int CommandLineClearArgumentsA(COMMAND_LINE_ARGUMENT_A* options) { - int i; + size_t i; for (i = 0; options[i].Name != NULL; i++) { @@ -419,7 +427,6 @@ COMMAND_LINE_ARGUMENT_W* CommandLineFindArgumentW(COMMAND_LINE_ARGUMENT_W* optio COMMAND_LINE_ARGUMENT_A* CommandLineFindNextArgumentA(COMMAND_LINE_ARGUMENT_A* argument) { COMMAND_LINE_ARGUMENT_A* nextArgument; - nextArgument = &argument[1]; if (nextArgument->Name == NULL)