Allow Use Of Non-ASCII Character In SSH Client Passwords (#322)
* Allow Use Of Non-ASCII Character In SSH Client Passwords
This commit is contained in:
parent
17c9c6dbb3
commit
7dd58ed31f
|
@ -1202,7 +1202,9 @@ char *
|
||||||
readpassphrase(const char *prompt, char *outBuf, size_t outBufLen, int flags)
|
readpassphrase(const char *prompt, char *outBuf, size_t outBufLen, int flags)
|
||||||
{
|
{
|
||||||
int current_index = 0;
|
int current_index = 0;
|
||||||
char ch;
|
int utf8_read = 0;
|
||||||
|
char utf8_char[4];
|
||||||
|
wchar_t ch;
|
||||||
wchar_t* wtmp = NULL;
|
wchar_t* wtmp = NULL;
|
||||||
|
|
||||||
if (outBufLen == 0) {
|
if (outBufLen == 0) {
|
||||||
|
@ -1210,7 +1212,7 @@ readpassphrase(const char *prompt, char *outBuf, size_t outBufLen, int flags)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (_kbhit()) _getch();
|
while (_kbhit()) _getwch();
|
||||||
|
|
||||||
wtmp = utf8_to_utf16(prompt);
|
wtmp = utf8_to_utf16(prompt);
|
||||||
if (wtmp == NULL)
|
if (wtmp == NULL)
|
||||||
|
@ -1220,36 +1222,51 @@ readpassphrase(const char *prompt, char *outBuf, size_t outBufLen, int flags)
|
||||||
free(wtmp);
|
free(wtmp);
|
||||||
|
|
||||||
while (current_index < (int)outBufLen - 1) {
|
while (current_index < (int)outBufLen - 1) {
|
||||||
ch = _getch();
|
ch = _getwch();
|
||||||
|
|
||||||
if (ch == '\r') {
|
if (ch == L'\r') {
|
||||||
if (_kbhit()) _getch(); /* read linefeed if its there */
|
if (_kbhit()) _getwch(); /* read linefeed if its there */
|
||||||
break;
|
break;
|
||||||
} else if (ch == '\n') {
|
} else if (ch == L'\n') {
|
||||||
break;
|
break;
|
||||||
} else if (ch == '\b') { /* backspace */
|
} else if (ch == L'\b') { /* backspace */
|
||||||
if (current_index > 0) {
|
if (current_index > 0) {
|
||||||
if (flags & RPP_ECHO_ON)
|
if (flags & RPP_ECHO_ON)
|
||||||
printf_s("%c \b", ch);
|
wprintf_s(L"%c \b", ch);
|
||||||
|
|
||||||
current_index--; /* overwrite last character */
|
/* overwrite last character - remove any utf8 extended chars */
|
||||||
|
while (current_index > 0 && (outBuf[current_index - 1] & 0xC0) == 0x80)
|
||||||
|
current_index--;
|
||||||
|
|
||||||
|
/* overwrite last character - remove first utf8 byte */
|
||||||
|
if (current_index > 0)
|
||||||
|
current_index--;
|
||||||
}
|
}
|
||||||
} else if (ch == '\003') { /* exit on Ctrl+C */
|
} else if (ch == L'\003') { /* exit on Ctrl+C */
|
||||||
fatal("");
|
fatal("");
|
||||||
} else {
|
} else {
|
||||||
if (flags & RPP_SEVENBIT)
|
if (flags & RPP_SEVENBIT)
|
||||||
ch &= 0x7f;
|
ch &= 0x7f;
|
||||||
|
|
||||||
if (isalpha((unsigned char)ch)) {
|
if (iswalpha(ch)) {
|
||||||
if(flags & RPP_FORCELOWER)
|
if(flags & RPP_FORCELOWER)
|
||||||
ch = tolower((unsigned char)ch);
|
ch = towlower(ch);
|
||||||
if(flags & RPP_FORCEUPPER)
|
if(flags & RPP_FORCEUPPER)
|
||||||
ch = toupper((unsigned char)ch);
|
ch = towupper(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
outBuf[current_index++] = ch;
|
/* convert unicode to utf8 characters */
|
||||||
|
int utf8_char_size = sizeof(utf8_char);
|
||||||
|
if ((utf8_read = WideCharToMultiByte(CP_UTF8, 0, &ch, 1, utf8_char, sizeof(utf8_char), NULL, NULL)) == 0)
|
||||||
|
fatal("character conversion failed");
|
||||||
|
|
||||||
|
/* append to output buffer if the characters fit */
|
||||||
|
if (current_index + utf8_read >= outBufLen - 1) break;
|
||||||
|
memcpy(&outBuf[current_index], utf8_char, utf8_read);
|
||||||
|
current_index += utf8_read;
|
||||||
|
|
||||||
if(flags & RPP_ECHO_ON)
|
if(flags & RPP_ECHO_ON)
|
||||||
printf_s("%c", ch);
|
wprintf_s(L"%c", ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1710,186 +1727,186 @@ build_exec_command(const char * command)
|
||||||
return cmd_sp;
|
return cmd_sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cmd is internally decoarated with a set of '"'
|
* cmd is internally decoarated with a set of '"'
|
||||||
* to account for any spaces within the commandline
|
* to account for any spaces within the commandline
|
||||||
* the double quotes and backslash is escaped if needed
|
* the double quotes and backslash is escaped if needed
|
||||||
* this decoration is done only when additional arguments are passed in argv
|
* this decoration is done only when additional arguments are passed in argv
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
build_commandline_string(const char* cmd, char *const argv[], BOOLEAN prepend_module_path)
|
build_commandline_string(const char* cmd, char *const argv[], BOOLEAN prepend_module_path)
|
||||||
{
|
{
|
||||||
char *cmdline, *t, *tmp = NULL, *path = NULL, *ret = NULL;
|
char *cmdline, *t, *tmp = NULL, *path = NULL, *ret = NULL;
|
||||||
char * const *t1;
|
char * const *t1;
|
||||||
DWORD cmdline_len = 0, path_len = 0;
|
DWORD cmdline_len = 0, path_len = 0;
|
||||||
int add_module_path = 0;
|
int add_module_path = 0;
|
||||||
|
|
||||||
if (!cmd) {
|
if (!cmd) {
|
||||||
error("%s invalid argument cmd:%s", __func__, cmd);
|
error("%s invalid argument cmd:%s", __func__, cmd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(path = _strdup(cmd))) {
|
if (!(path = _strdup(cmd))) {
|
||||||
error("failed to duplicate %s", cmd);
|
error("failed to duplicate %s", cmd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
path_len = (DWORD)strlen(path);
|
path_len = (DWORD)strlen(path);
|
||||||
|
|
||||||
if (is_bash_test_env()) {
|
if (is_bash_test_env()) {
|
||||||
memset(path, 0, path_len + 1);
|
memset(path, 0, path_len + 1);
|
||||||
bash_to_win_path(cmd, path, path_len + 1);
|
bash_to_win_path(cmd, path, path_len + 1);
|
||||||
path_len = (DWORD)strlen(path);
|
path_len = (DWORD)strlen(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_absolute_path(path) && prepend_module_path)
|
if (!is_absolute_path(path) && prepend_module_path)
|
||||||
add_module_path = 1;
|
add_module_path = 1;
|
||||||
|
|
||||||
/* compute total cmdline len*/
|
/* compute total cmdline len*/
|
||||||
if (add_module_path)
|
if (add_module_path)
|
||||||
cmdline_len += (DWORD)strlen(__progdir) + 1 + (DWORD)strlen(path) + 1 + 2;
|
cmdline_len += (DWORD)strlen(__progdir) + 1 + (DWORD)strlen(path) + 1 + 2;
|
||||||
else
|
else
|
||||||
cmdline_len += (DWORD)strlen(path) + 1 + 2;
|
cmdline_len += (DWORD)strlen(path) + 1 + 2;
|
||||||
|
|
||||||
if (argv) {
|
if (argv) {
|
||||||
t1 = argv;
|
t1 = argv;
|
||||||
while (*t1) {
|
while (*t1) {
|
||||||
char *p = *t1++;
|
char *p = *t1++;
|
||||||
for (int i = 0; i < (int)strlen(p); i++) {
|
for (int i = 0; i < (int)strlen(p); i++) {
|
||||||
if (p[i] == '\\') {
|
if (p[i] == '\\') {
|
||||||
char * b = p + i;
|
char * b = p + i;
|
||||||
int additional_backslash = 0;
|
int additional_backslash = 0;
|
||||||
int backslash_count = 0;
|
int backslash_count = 0;
|
||||||
/*
|
/*
|
||||||
Backslashes are interpreted literally, unless they immediately
|
Backslashes are interpreted literally, unless they immediately
|
||||||
precede a double quotation mark.
|
precede a double quotation mark.
|
||||||
*/
|
*/
|
||||||
while (b != NULL && *b == '\\') {
|
while (b != NULL && *b == '\\') {
|
||||||
backslash_count++;
|
backslash_count++;
|
||||||
b++;
|
b++;
|
||||||
if (b != NULL && *b == '\"') {
|
if (b != NULL && *b == '\"') {
|
||||||
additional_backslash = 1;
|
additional_backslash = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cmdline_len += backslash_count * (additional_backslash + 1);
|
cmdline_len += backslash_count * (additional_backslash + 1);
|
||||||
i += backslash_count - 1;
|
i += backslash_count - 1;
|
||||||
}
|
}
|
||||||
else if (p[i] == '\"')
|
else if (p[i] == '\"')
|
||||||
/* backslash will be added for every double quote.*/
|
/* backslash will be added for every double quote.*/
|
||||||
cmdline_len += 2;
|
cmdline_len += 2;
|
||||||
else
|
else
|
||||||
cmdline_len++;
|
cmdline_len++;
|
||||||
}
|
}
|
||||||
cmdline_len += 1 + 2; /*for "around cmd arg and traling space*/
|
cmdline_len += 1 + 2; /*for "around cmd arg and traling space*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cmdline = malloc(cmdline_len)) == NULL) {
|
if ((cmdline = malloc(cmdline_len)) == NULL) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
t = cmdline;
|
t = cmdline;
|
||||||
|
|
||||||
*t++ = '\"';
|
*t++ = '\"';
|
||||||
if (add_module_path) {
|
if (add_module_path) {
|
||||||
/* add current module path to start if needed */
|
/* add current module path to start if needed */
|
||||||
memcpy(t, __progdir, strlen(__progdir));
|
memcpy(t, __progdir, strlen(__progdir));
|
||||||
t += strlen(__progdir);
|
t += strlen(__progdir);
|
||||||
*t++ = '\\';
|
*t++ = '\\';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path[0] != '\"') {
|
if (path[0] != '\"') {
|
||||||
/* If path is <executable_path> <arg> then we should add double quotes after <executable_path> i.e., "<executable_path>" <arg> should be passed to CreateProcess().
|
/* If path is <executable_path> <arg> then we should add double quotes after <executable_path> i.e., "<executable_path>" <arg> should be passed to CreateProcess().
|
||||||
* Example - If path is C:\cygwin64\bin\bash.exe /cygdrive/e/openssh-portable-latestw_all/openssh-portable/regress/scp-ssh-wrapper.sh then
|
* Example - If path is C:\cygwin64\bin\bash.exe /cygdrive/e/openssh-portable-latestw_all/openssh-portable/regress/scp-ssh-wrapper.sh then
|
||||||
* we should pass "C:\cygwin64\bin\bash.exe" /cygdrive/e/openssh-portable-latestw_all/openssh-portable/regress/scp-ssh-wrapper.sh
|
* we should pass "C:\cygwin64\bin\bash.exe" /cygdrive/e/openssh-portable-latestw_all/openssh-portable/regress/scp-ssh-wrapper.sh
|
||||||
* to the CreateProcess() otherwise CreateProcess() will fail with error code 2.
|
* to the CreateProcess() otherwise CreateProcess() will fail with error code 2.
|
||||||
*/
|
*/
|
||||||
if (strstr(path, ".exe") && (tmp = strstr(strstr(path, ".exe"), " ")))
|
if (strstr(path, ".exe") && (tmp = strstr(strstr(path, ".exe"), " ")))
|
||||||
{
|
{
|
||||||
size_t tmp_pos = tmp - path;
|
size_t tmp_pos = tmp - path;
|
||||||
memcpy(t, path, tmp_pos);
|
memcpy(t, path, tmp_pos);
|
||||||
t += tmp_pos;
|
t += tmp_pos;
|
||||||
*t++ = '\"';
|
*t++ = '\"';
|
||||||
memcpy(t, tmp, strlen(path) - tmp_pos);
|
memcpy(t, tmp, strlen(path) - tmp_pos);
|
||||||
t += (strlen(path) - tmp_pos);
|
t += (strlen(path) - tmp_pos);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memcpy(t, path, path_len);
|
memcpy(t, path, path_len);
|
||||||
t += path_len;
|
t += path_len;
|
||||||
*t++ = '\"';
|
*t++ = '\"';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/*path already contains "*/
|
/*path already contains "*/
|
||||||
memcpy(t, path + 1, path_len - 1);
|
memcpy(t, path + 1, path_len - 1);
|
||||||
t += path_len - 1;
|
t += path_len - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*t = '\0';
|
*t = '\0';
|
||||||
t = cmdline + strlen(cmdline);
|
t = cmdline + strlen(cmdline);
|
||||||
|
|
||||||
if (argv) {
|
if (argv) {
|
||||||
t1 = argv;
|
t1 = argv;
|
||||||
while (*t1) {
|
while (*t1) {
|
||||||
*t++ = ' ';
|
*t++ = ' ';
|
||||||
char * p1 = *t1++;
|
char * p1 = *t1++;
|
||||||
BOOL add_quotes = FALSE;
|
BOOL add_quotes = FALSE;
|
||||||
/* leave as is if the command is surrounded by single quotes*/
|
/* leave as is if the command is surrounded by single quotes*/
|
||||||
if (p1[0] != '\'')
|
if (p1[0] != '\'')
|
||||||
for (int i = 0; i < (int)strlen(p1); i++) {
|
for (int i = 0; i < (int)strlen(p1); i++) {
|
||||||
if (p1[i] == ' ') {
|
if (p1[i] == ' ') {
|
||||||
add_quotes = TRUE;
|
add_quotes = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (add_quotes)
|
if (add_quotes)
|
||||||
*t++ = '\"';
|
*t++ = '\"';
|
||||||
for (int i = 0; i < (int)strlen(p1); i++) {
|
for (int i = 0; i < (int)strlen(p1); i++) {
|
||||||
if (p1[i] == '\\') {
|
if (p1[i] == '\\') {
|
||||||
char * b = p1 + i;
|
char * b = p1 + i;
|
||||||
int additional_backslash = 0;
|
int additional_backslash = 0;
|
||||||
int backslash_count = 0;
|
int backslash_count = 0;
|
||||||
/*
|
/*
|
||||||
* Backslashes are interpreted literally, unless they immediately
|
* Backslashes are interpreted literally, unless they immediately
|
||||||
* precede a double quotation mark.
|
* precede a double quotation mark.
|
||||||
*/
|
*/
|
||||||
while (b != NULL && *b == '\\') {
|
while (b != NULL && *b == '\\') {
|
||||||
backslash_count++;
|
backslash_count++;
|
||||||
b++;
|
b++;
|
||||||
if (b != NULL && *b == '\"') {
|
if (b != NULL && *b == '\"') {
|
||||||
additional_backslash = 1;
|
additional_backslash = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i += backslash_count - 1;
|
i += backslash_count - 1;
|
||||||
int escaped_backslash_count = backslash_count * (additional_backslash + 1);
|
int escaped_backslash_count = backslash_count * (additional_backslash + 1);
|
||||||
while (escaped_backslash_count--)
|
while (escaped_backslash_count--)
|
||||||
*t++ = '\\';
|
*t++ = '\\';
|
||||||
}
|
}
|
||||||
else if (p1[i] == '\"') {
|
else if (p1[i] == '\"') {
|
||||||
/* Add backslash for every double quote.*/
|
/* Add backslash for every double quote.*/
|
||||||
*t++ = '\\';
|
*t++ = '\\';
|
||||||
*t++ = '\"';
|
*t++ = '\"';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*t++ = p1[i];
|
*t++ = p1[i];
|
||||||
}
|
}
|
||||||
if (add_quotes)
|
if (add_quotes)
|
||||||
*t++ = '\"';
|
*t++ = '\"';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*t = '\0';
|
*t = '\0';
|
||||||
ret = cmdline;
|
ret = cmdline;
|
||||||
cmdline = NULL;
|
cmdline = NULL;
|
||||||
cleanup:
|
cleanup:
|
||||||
if (path)
|
if (path)
|
||||||
free(path);
|
free(path);
|
||||||
if (cmdline)
|
if (cmdline)
|
||||||
free(cmdline);
|
free(cmdline);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
is_bash_test_env()
|
is_bash_test_env()
|
||||||
|
|
Loading…
Reference in New Issue