The getpass() function is present in SUSv2, but marked LEGACY. It is
removed in POSIX.1-2001. Additionally, on Solaris getpass() returns
maximum 8 bytes. This will make longer passwords fail with no
possibility for user to know what is happening.

This patch removes usage of getpass() completely and replaces it with
direct implementation of what getpass() does: opens tty (existing code),
outputs the prompt (existing code), turns off echoing (new code), reads
one line (existing code shared with echoed mode), restores tty state
(new code) and closes tty (existing code).

Signed-off-by: Tõivo Leedjärv <69477666+tleedj...@users.noreply.github.com>
---
 configure.ac                  |  4 ++-
 src/openvpn/console_builtin.c | 63 +++++++++++++++++++++--------------
 2 files changed, 41 insertions(+), 26 deletions(-)

diff --git a/configure.ac b/configure.ac
index 1ab8fe59..2c094da7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -645,7 +645,7 @@ AC_FUNC_FORK

 AC_CHECK_FUNCS([ \
        daemon chroot getpwnam setuid nice system getpid dup dup2 \
-       getpass syslog openlog mlockall getgrnam setgid \
+       syslog openlog mlockall getgrnam setgid \
        setgroups stat flock readv writev time gettimeofday \
        ctime memset vsnprintf strdup \
        setsid chdir putenv getpeername unlink \
@@ -653,6 +653,8 @@ AC_CHECK_FUNCS([ \
        epoll_create strsep \
 ])

+AC_CHECK_HEADERS([termios.h])
+
 AC_CHECK_LIB(
        [dl],
        [dlopen],
diff --git a/src/openvpn/console_builtin.c b/src/openvpn/console_builtin.c
index 445928bf..f1d91b32 100644
--- a/src/openvpn/console_builtin.c
+++ b/src/openvpn/console_builtin.c
@@ -40,6 +40,10 @@
 #include "buffer.h"
 #include "misc.h"

+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+
 #ifdef _WIN32

 #include "win32.h"
@@ -138,7 +142,7 @@ get_console_input_win32(const char *prompt, const
bool echo, char *input, const
 #endif   /* _WIN32 */


-#ifdef HAVE_GETPASS
+#ifdef HAVE_TERMIOS_H

 /**
  * Open the current console TTY for read/write operations
@@ -177,7 +181,7 @@ close_tty(FILE *fp)
     }
 }

-#endif   /* HAVE_GETPASS */
+#endif   /* HAVE_TERMIOS_H */


 /**
@@ -201,7 +205,9 @@ get_console_input(const char *prompt, const bool
echo, char *input, const int ca

 #if defined(_WIN32)
     return get_console_input_win32(prompt, echo, input, capacity);
-#elif defined(HAVE_GETPASS)
+#elif defined(HAVE_TERMIOS_H)
+    int restore_tty = 0;
+    struct termios tty_a, tty_save;

     /* did we --daemon'ize before asking for passwords?
      * (in which case neither stdin or stderr are connected to a tty and
@@ -220,33 +226,40 @@ get_console_input(const char *prompt, const bool
echo, char *input, const int ca
         close(fd);
     }

-    if (echo)
-    {
-        FILE *fp;
+    FILE *fp;

-        fp = open_tty(true);
-        fprintf(fp, "%s", prompt);
-        fflush(fp);
-        close_tty(fp);
+    fp = open_tty(true);
+    fprintf(fp, "%s", prompt);
+    fflush(fp);
+    close_tty(fp);

-        fp = open_tty(false);
-        if (fgets(input, capacity, fp) != NULL)
-        {
-            chomp(input);
-            ret = true;
-        }
-        close_tty(fp);
+    fp = open_tty(false);
+
+    if (!echo && (tcgetattr(fileno(fp), &tty_a) == 0))
+    {
+        tty_save = tty_a;
+        tty_a.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ISIG);
+        restore_tty = (tcsetattr(fileno(fp), TCSAFLUSH, &tty_a) == 0);
     }
-    else
+
+    if (fgets(input, capacity, fp) != NULL)
     {
-        char *gp = getpass(prompt);
-        if (gp)
-        {
-            strncpynt(input, gp, capacity);
-            secure_memzero(gp, strlen(gp));
-            ret = true;
-        }
+        chomp(input);
+        ret = true;
     }
+
+    if (!echo && restore_tty)
+    {
+        (void) tcsetattr(fileno(fp), TCSAFLUSH, &tty_save);
+
+        /* Echo the non-echoed newline */
+        close_tty(fp);
+        fp = open_tty(true);
+        fprintf(fp, "\n");
+        fflush(fp);
+    }
+
+    close_tty(fp);
 #else  /* if defined(_WIN32) */
     msg(M_FATAL, "Sorry, but I can't get console input on this OS
(%s)", prompt);
 #endif /* if defined(_WIN32) */
-- 
2.26.2


_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to