From f03b2e227ae6a459d4127fdf1e07092d1c1fd0e2 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Thu, 8 Sep 2011 01:32:08 -0400 Subject: [PATCH 1/6] Read the password from stdin if -p - is sent --- client/X11/xfreerdp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index 3c9b36c03..5e7a57c90 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -727,6 +727,11 @@ int main(int argc, char* argv[]) if (freerdp_parse_args(instance->settings, argc, argv, xf_process_plugin_args, chanman, xf_process_ui_args, NULL) < 0) return 1; + if (strcmp("-", instance->settings->password) == 0) + { + fgets(instance->settings->password, 512-1, stdin); + *(instance->settings->password + strlen(instance->settings->password) - 1) = '\0'; + } data = (struct thread_data*) xzalloc(sizeof(struct thread_data)); data->instance = instance; From 6b8ac9ef18955ee3f1ff1caa5ca07e6c2fe50be7 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Thu, 8 Sep 2011 01:35:46 -0400 Subject: [PATCH 2/6] Add prompt for the password when reading from stdin --- client/X11/xfreerdp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index 5e7a57c90..ece970c0c 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -729,6 +729,7 @@ int main(int argc, char* argv[]) return 1; if (strcmp("-", instance->settings->password) == 0) { + printf("Password: "); fgets(instance->settings->password, 512-1, stdin); *(instance->settings->password + strlen(instance->settings->password) - 1) = '\0'; } From 091e60012744fa5efa9d23295a6f282fc1bb0d7a Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Thu, 8 Sep 2011 02:10:22 -0400 Subject: [PATCH 3/6] Fix memory leak in instance->settings->password when reading from stdin --- client/X11/xfreerdp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index ece970c0c..9a1e85a05 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -729,9 +729,13 @@ int main(int argc, char* argv[]) return 1; if (strcmp("-", instance->settings->password) == 0) { + char* password; + password = xmalloc(512 * sizeof(char)); printf("Password: "); - fgets(instance->settings->password, 512-1, stdin); - *(instance->settings->password + strlen(instance->settings->password) - 1) = '\0'; + fgets(password, 512 - 1, stdin); + *(password + strlen(password) - 1) = '\0'; + xfree(instance->settings->password); + instance->settings->password = password; } data = (struct thread_data*) xzalloc(sizeof(struct thread_data)); From 9b70c396f7eab21a400c8b5223ded2d9ffed9092 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Thu, 8 Sep 2011 02:41:08 -0400 Subject: [PATCH 4/6] Turn off ECHO on stdin when reading a password Note that POSIX claims we need to handle signals when using tc{get,set}attr lest the terminal not be reset to its original state. Tests with Bash/xterm show this to be not necessary: sending SIGINT, SIGILL, etc. to the application while it's waiting for a password results in a terminal with ECHO back on. It would probably be a good idea to handle the signals anyway. --- client/X11/xfreerdp.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index 9a1e85a05..de5dcb9c9 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -730,9 +731,36 @@ int main(int argc, char* argv[]) if (strcmp("-", instance->settings->password) == 0) { char* password; + struct termios orig_flags, no_echo_flags; + password = xmalloc(512 * sizeof(char)); + printf("Password: "); + + if (tcgetattr(fileno(stdin), &orig_flags) != 0) + { + perror(strerror(errno)); + return(errno); + } + no_echo_flags = orig_flags; + no_echo_flags.c_lflag &= ~ECHO; + no_echo_flags.c_lflag |= ECHONL; + if (tcsetattr(fileno(stdin), TCSAFLUSH, &no_echo_flags) != 0) + { + tcsetattr(fileno(stdin), TCSANOW, &orig_flags); + perror(strerror(errno)); + return(errno); + } + fgets(password, 512 - 1, stdin); + + if (tcsetattr(fileno(stdin), TCSADRAIN, &orig_flags) != 0) + { + tcsetattr(fileno(stdin), TCSANOW, &orig_flags); + perror(strerror(errno)); + return(errno); + } + *(password + strlen(password) - 1) = '\0'; xfree(instance->settings->password); instance->settings->password = password; From 1b8a31bb2edbbeb82f8cdcfcea0eec12842ee541 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Thu, 8 Sep 2011 02:47:18 -0400 Subject: [PATCH 5/6] Add some comments --- client/X11/xfreerdp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index de5dcb9c9..d930d457c 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -737,6 +737,7 @@ int main(int argc, char* argv[]) printf("Password: "); + /* Turn off ECHO on stdin, but still echo newlines */ if (tcgetattr(fileno(stdin), &orig_flags) != 0) { perror(strerror(errno)); @@ -754,6 +755,7 @@ int main(int argc, char* argv[]) fgets(password, 512 - 1, stdin); + /* Reset stdin to how it was */ if (tcsetattr(fileno(stdin), TCSADRAIN, &orig_flags) != 0) { tcsetattr(fileno(stdin), TCSANOW, &orig_flags); From 79e69368194077b52e6f9e8e0dc8b1b2107ec377 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Thu, 8 Sep 2011 12:25:24 -0400 Subject: [PATCH 6/6] Wrap the tcsetattr() call in a fork() so the terminal can always be restored on exit --- client/X11/xfreerdp.c | 58 +++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index d930d457c..5029ae6f5 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -731,38 +731,58 @@ int main(int argc, char* argv[]) if (strcmp("-", instance->settings->password) == 0) { char* password; - struct termios orig_flags, no_echo_flags; + const int PASSSIZE = 512; + struct termios term_flags; + int pipe_ends[2]; - password = xmalloc(512 * sizeof(char)); + password = xmalloc(PASSSIZE * sizeof(char)); printf("Password: "); /* Turn off ECHO on stdin, but still echo newlines */ - if (tcgetattr(fileno(stdin), &orig_flags) != 0) + if (tcgetattr(fileno(stdin), &term_flags) != 0) { perror(strerror(errno)); - return(errno); - } - no_echo_flags = orig_flags; - no_echo_flags.c_lflag &= ~ECHO; - no_echo_flags.c_lflag |= ECHONL; - if (tcsetattr(fileno(stdin), TCSAFLUSH, &no_echo_flags) != 0) - { - tcsetattr(fileno(stdin), TCSANOW, &orig_flags); - perror(strerror(errno)); - return(errno); + exit(errno); } - fgets(password, 512 - 1, stdin); - - /* Reset stdin to how it was */ - if (tcsetattr(fileno(stdin), TCSADRAIN, &orig_flags) != 0) + if (pipe(pipe_ends) != 0) { - tcsetattr(fileno(stdin), TCSANOW, &orig_flags); perror(strerror(errno)); - return(errno); + exit(errno); } + switch (fork()) + { + case -1: + perror(strerror(errno)); + exit(errno); + + case 0: + close(pipe_ends[0]); + term_flags.c_lflag &= ~ECHO; + term_flags.c_lflag |= ECHONL; + tcsetattr(fileno(stdin), TCSAFLUSH, &term_flags); + fgets(password, PASSSIZE - 1, stdin); + write(pipe_ends[1], password, strlen(password)); + close(pipe_ends[1]); + exit(EXIT_SUCCESS); + + default: + wait(); + if (tcsetattr(fileno(stdin), TCSADRAIN, &term_flags) != 0) + { + tcsetattr(fileno(stdin), TCSANOW, &term_flags); + perror(strerror(errno)); + exit(errno); + } + break; + } + + close(pipe_ends[1]); + read(pipe_ends[0], password, PASSSIZE); + close(pipe_ends[0]); + *(password + strlen(password) - 1) = '\0'; xfree(instance->settings->password); instance->settings->password = password;