diff --git a/misc.c b/misc.c index 782ed4c..b431a67 100644 --- a/misc.c +++ b/misc.c @@ -161,6 +161,46 @@ out: return retval; } +/** + * Escape \ space ' and " in a string + * @param input Pointer to the string to escape + * @returns A newly allocated string containing the result or NULL + * on error. Caller must free it after use. + */ +char * +escape_string(const char *input) +{ + char *out = strdup(input); + int len = strlen(out); + const char *esc = "\'\"\\ "; + + if (!out) + { + MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Error in escape_string: out of memory"); + return NULL; + } + + for (int pos = 0; pos < len; ++pos) + { + if (strchr(esc, out[pos])) + { + char *buf = realloc(out, ++len + 1); + if (buf == NULL) + { + free(out); + MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Error in escape_string: out of memory"); + return NULL; + } + out = buf; + memmove(out + pos + 1, out + pos, len - pos + 1); + out[pos] = '\\'; + pos += 1; + } + } + + PrintDebug(L"escape_string: in: '%hs' out: '%hs' len = %d", input, out, len); + return out; +} /* * Generate a management command from user input and send it @@ -170,25 +210,19 @@ ManagementCommandFromInput(connection_t *c, LPCSTR fmt, HWND hDlg, int id) { BOOL retval = FALSE; LPSTR input, cmd; - int input_len, cmd_len, pos; + int input_len, cmd_len; GetDlgItemTextUtf8(hDlg, id, &input, &input_len); /* Escape input if needed */ - for (pos = 0; pos < input_len; ++pos) + char *input_e = escape_string(input); + if (!input_e) { - if (input[pos] == '\\' || input[pos] == '"') - { - LPSTR buf = realloc(input, ++input_len + 1); - if (buf == NULL) - goto out; - - input = buf; - memmove(input + pos + 1, input + pos, input_len - pos + 1); - input[pos] = '\\'; - pos += 1; - } + goto out; } + free(input); + input = input_e; + input_len = strlen(input); cmd_len = input_len + strlen(fmt); cmd = malloc(cmd_len); diff --git a/misc.h b/misc.h index e1b5833..732d803 100644 --- a/misc.h +++ b/misc.h @@ -86,4 +86,7 @@ GetDlgItemTextUtf8(HWND hDlg, int id, LPSTR* str, int* len); */ void set_openssl_env_vars(void); +/* Return escaped copy of a string */ +char *escape_string(const char *str); + #endif diff --git a/openvpn.c b/openvpn.c index 44ef8d7..89f5d01 100644 --- a/openvpn.c +++ b/openvpn.c @@ -733,13 +733,13 @@ GenericPassDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { /* send username */ template = "username \"Auth\" \"%s\""; - fmt = malloc(strlen(template) + strlen(param->user)); + char *username = escape_string(param->user); + fmt = malloc(strlen(template) + strlen(username)); - if (fmt) + if (fmt && username) { - sprintf(fmt, template, param->user); + sprintf(fmt, template, username); ManagementCommand(param->c, fmt, NULL, regular); - free(fmt); } else /* no memory? send an emty username and let it error out */ { @@ -747,6 +747,8 @@ GenericPassDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) L"Out of memory: sending a generic username for dynamic CR", false); ManagementCommand(param->c, "username \"Auth\" \"user\"", NULL, regular); } + free(fmt); + free(username); /* password template */ template = "password \"Auth\" \"CRV1::%s::%%s\"";