diff --git a/configure.ac b/configure.ac index 952fc9fb0..6010172a7 100644 --- a/configure.ac +++ b/configure.ac @@ -386,6 +386,7 @@ AC_CHECK_FUNCS( ftime \ getaddrinfo \ getifaddrs \ + getpass \ getrlimit \ gettimeofday \ gmtime_r \ @@ -399,6 +400,7 @@ AC_CHECK_FUNCS( pipe \ pipe2 \ prctl \ + readpassphrase \ rint \ sigaction \ socketpair \ @@ -926,6 +928,7 @@ AC_CHECK_HEADERS( netinet/in.h \ netinet/in6.h \ pwd.h \ + readpassphrase.h \ stdint.h \ sys/eventfd.h \ sys/file.h \ diff --git a/src/common/compat.c b/src/common/compat.c index 8da7ef3f6..701027523 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -67,6 +67,9 @@ #ifdef HAVE_CRT_EXTERNS_H #include #endif +#ifdef HAVE_READPASSPHRASE_H +#include +#endif #ifndef HAVE_GETTIMEOFDAY #ifdef HAVE_FTIME @@ -3242,3 +3245,33 @@ tor_sleep_msec(int msec) } #endif +/** Emit the password prompt prompt, then read up to buflen + * characters of passphrase into output. */ +ssize_t +tor_getpass(const char *prompt, char *output, size_t buflen) +{ + tor_assert(buflen <= SSIZE_MAX); +#if defined(HAVE_READPASSPHRASE) + char *pwd = readpassphrase(prompt, output, buflen, RPP_ECHO_OFF); + if (pwd == NULL) + return -1; + return strlen(pwd); +#elif defined(HAVE_GETPASS) + /* XXX We shouldn't actually use this; it's deprecated to hell and back */ + memset(output, 0, buflen); + char *pwd = getpass(prompt); + if (pwd == NULL) + return -1; + ssize_t len = (ssize_t)strlen(pwd); + strlcpy(output, pwd, buflen); + memset(pwd, 0, len); + return len; +#else + /* XXX This is even worse. */ + puts(prompt); + ssize_t n = read(STDIN_FILENO, output, buflen); + if (n < 0) + return -1; + return n; +#endif +} diff --git a/src/common/compat.h b/src/common/compat.h index 5189b7e05..549ed827d 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -708,6 +708,8 @@ STATIC int tor_ersatz_socketpair(int family, int type, int protocol, #endif #endif +ssize_t tor_getpass(const char *prompt, char *output, size_t buflen); + /* This needs some of the declarations above so we include it here. */ #include "compat_threads.h"