commit 4e11c2ca6c9396bf8462acb13e01e3d27e4752cc Author: Nick Mathewson nickm@torproject.org Date: Fri Jun 29 10:50:05 2018 -0400
Extract getpass to a new lib/term library
(Term is short for terminal) --- .gitignore | 2 + Makefile.am | 2 + src/common/compat.c | 102 ---------------------------------------- src/common/compat.h | 2 - src/common/include.am | 9 +--- src/include.am | 1 + src/lib/term/.may_include | 9 ++++ src/lib/term/getpass.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib/term/getpass.h | 13 ++++++ src/lib/term/include.am | 24 ++++++++++ src/or/routerkeys.c | 1 + 11 files changed, 168 insertions(+), 112 deletions(-)
diff --git a/.gitignore b/.gitignore index b21b03efe..b1de1d79d 100644 --- a/.gitignore +++ b/.gitignore @@ -205,6 +205,8 @@ uptime-*.json /src/lib/libtor-string-testing.a /src/lib/libtor-smartlist-core.a /src/lib/libtor-smartlist-core-testing.a +/src/lib/libtor-term.a +/src/lib/libtor-term-testing.a /src/lib/libtor-thread.a /src/lib/libtor-thread-testing.a /src/lib/libtor-time.a diff --git a/Makefile.am b/Makefile.am index 68cc3b5f1..8fa6f9970 100644 --- a/Makefile.am +++ b/Makefile.am @@ -56,6 +56,7 @@ TOR_UTIL_LIBS = \ src/lib/libtor-lock.a \ src/lib/libtor-fdio.a \ src/lib/libtor-string.a \ + src/lib/libtor-term.a \ src/lib/libtor-smartlist-core.a \ src/lib/libtor-malloc.a \ src/lib/libtor-wallclock.a \ @@ -79,6 +80,7 @@ TOR_UTIL_TESTING_LIBS = \ src/lib/libtor-math-testing.a \ src/lib/libtor-meminfo-testing.a \ src/lib/libtor-osinfo-testing.a \ + src/lib/libtor-term-testing.a \ src/lib/libtor-log-testing.a \ src/lib/libtor-lock-testing.a \ src/lib/libtor-fdio-testing.a \ diff --git a/src/common/compat.c b/src/common/compat.c index 2f9db70a4..c159e65c7 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -67,31 +67,6 @@ #include <sys/capability.h> #endif
-#ifdef _WIN32 -#include <conio.h> -#include <wchar.h> -/* Some mingw headers lack these. :p */ -#if defined(HAVE_DECL__GETWCH) && !HAVE_DECL__GETWCH -wint_t _getwch(void); -#endif -#ifndef WEOF -#define WEOF (wchar_t)(0xFFFF) -#endif -#if defined(HAVE_DECL_SECUREZEROMEMORY) && !HAVE_DECL_SECUREZEROMEMORY -static inline void -SecureZeroMemory(PVOID ptr, SIZE_T cnt) -{ - volatile char *vcptr = (volatile char*)ptr; - while (cnt--) - *vcptr++ = 0; -} -#endif /* defined(HAVE_DECL_SECUREZEROMEMORY) && !HAVE_DECL_SECUREZEROMEMORY */ -#elif defined(HAVE_READPASSPHRASE_H) -#include <readpassphrase.h> -#else -#include "tor_readpassphrase.h" -#endif /* defined(_WIN32) || ... */ - /* Includes for the process attaching prevention */ #if defined(HAVE_SYS_PRCTL_H) && defined(__linux__) /* Only use the linux prctl; the IRIX prctl is totally different */ @@ -131,80 +106,3 @@ SecureZeroMemory(PVOID ptr, SIZE_T cnt) /* * Process control */ - -/** Emit the password prompt <b>prompt</b>, then read up to <b>buflen</b> - * bytes of passphrase into <b>output</b>. Return the number of bytes in - * the passphrase, excluding terminating NUL. - */ -ssize_t -tor_getpass(const char *prompt, char *output, size_t buflen) -{ - tor_assert(buflen <= SSIZE_MAX); - tor_assert(buflen >= 1); -#if defined(HAVE_READPASSPHRASE) - char *pwd = readpassphrase(prompt, output, buflen, RPP_ECHO_OFF); - if (pwd == NULL) - return -1; - return strlen(pwd); -#elif defined(_WIN32) - int r = -1; - while (*prompt) { - _putch(*prompt++); - } - - tor_assert(buflen <= INT_MAX); - wchar_t *buf = tor_calloc(buflen, sizeof(wchar_t)); - - wchar_t *ptr = buf, *lastch = buf + buflen - 1; - while (ptr < lastch) { - wint_t ch = _getwch(); - switch (ch) { - case '\r': - case '\n': - case WEOF: - goto done_reading; - case 3: - goto done; /* Can't actually read ctrl-c this way. */ - case '\b': - if (ptr > buf) - --ptr; - continue; - case 0: - case 0xe0: - ch = _getwch(); /* Ignore; this is a function or arrow key */ - break; - default: - *ptr++ = ch; - break; - } - } - done_reading: - ; - -#ifndef WC_ERR_INVALID_CHARS -#define WC_ERR_INVALID_CHARS 0x80 -#endif - - /* Now convert it to UTF-8 */ - r = WideCharToMultiByte(CP_UTF8, - WC_NO_BEST_FIT_CHARS|WC_ERR_INVALID_CHARS, - buf, (int)(ptr-buf), - output, (int)(buflen-1), - NULL, NULL); - if (r <= 0) { - r = -1; - goto done; - } - - tor_assert(r < (int)buflen); - - output[r] = 0; - - done: - SecureZeroMemory(buf, sizeof(wchar_t)*buflen); - tor_free(buf); - return r; -#else -#error "No implementation for tor_getpass found!" -#endif /* defined(HAVE_READPASSPHRASE) || ... */ -} diff --git a/src/common/compat.h b/src/common/compat.h index 7e7a81496..a29a3242b 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -86,8 +86,6 @@ typedef enum {
/* ===== OS compatibility */
-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 "lib/thread/threads.h"
diff --git a/src/common/include.am b/src/common/include.am index e68a87b10..a7a3b30f7 100644 --- a/src/common/include.am +++ b/src/common/include.am @@ -17,20 +17,13 @@ else libor_extra_source= endif
-if BUILD_READPASSPHRASE_C -readpassphrase_source=src/ext/readpassphrase.c -else -readpassphrase_source= -endif - LIBOR_A_SRC = \ src/common/address_set.c \ src/common/compat.c \ src/common/util.c \ src/common/token_bucket.c \ src/common/workqueue.c \ - $(libor_extra_source) \ - $(readpassphrase_source) + $(libor_extra_source)
src/common/src_common_libor_testing_a-log.$(OBJEXT) \ src/common/log.$(OBJEXT): micro-revision.i diff --git a/src/include.am b/src/include.am index 69a2dc5ae..1ed07425a 100644 --- a/src/include.am +++ b/src/include.am @@ -24,6 +24,7 @@ include src/lib/process/include.am include src/lib/sandbox/include.am include src/lib/string/include.am include src/lib/smartlist_core/include.am +include src/lib/term/include.am include src/lib/testsupport/include.am include src/lib/thread/include.am include src/lib/time/include.am diff --git a/src/lib/term/.may_include b/src/lib/term/.may_include new file mode 100644 index 000000000..c93a06e59 --- /dev/null +++ b/src/lib/term/.may_include @@ -0,0 +1,9 @@ +orconfig.h + +lib/cc/*.h +lib/log/*.h +lib/term/*.h +lib/malloc/*.h + +# From src/ext +tor_readpassphrase.h diff --git a/src/lib/term/getpass.c b/src/lib/term/getpass.c new file mode 100644 index 000000000..10c99914f --- /dev/null +++ b/src/lib/term/getpass.c @@ -0,0 +1,115 @@ +/* Copyright (c) 2003-2004, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "lib/term/getpass.h" + +#include "lib/log/util_bug.h" +#include "lib/malloc/util_malloc.h" + +#ifdef _WIN32 +#include <windows.h> +#include <conio.h> +#include <wchar.h> +/* Some mingw headers lack these. :p */ +#if defined(HAVE_DECL__GETWCH) && !HAVE_DECL__GETWCH +wint_t _getwch(void); +#endif +#ifndef WEOF +#define WEOF (wchar_t)(0xFFFF) +#endif +#if defined(HAVE_DECL_SECUREZEROMEMORY) && !HAVE_DECL_SECUREZEROMEMORY +static inline void +SecureZeroMemory(PVOID ptr, SIZE_T cnt) +{ + volatile char *vcptr = (volatile char*)ptr; + while (cnt--) + *vcptr++ = 0; +} +#endif /* defined(HAVE_DECL_SECUREZEROMEMORY) && !HAVE_DECL_SECUREZEROMEMORY */ +#elif defined(HAVE_READPASSPHRASE_H) +#include <readpassphrase.h> +#else +#include "tor_readpassphrase.h" +#endif /* defined(_WIN32) || ... */ + +#include <stdlib.h> +#include <string.h> + +/** Emit the password prompt <b>prompt</b>, then read up to <b>buflen</b> + * bytes of passphrase into <b>output</b>. Return the number of bytes in + * the passphrase, excluding terminating NUL. + */ +ssize_t +tor_getpass(const char *prompt, char *output, size_t buflen) +{ + tor_assert(buflen <= SSIZE_MAX); + tor_assert(buflen >= 1); +#if defined(HAVE_READPASSPHRASE) + char *pwd = readpassphrase(prompt, output, buflen, RPP_ECHO_OFF); + if (pwd == NULL) + return -1; + return strlen(pwd); +#elif defined(_WIN32) + int r = -1; + while (*prompt) { + _putch(*prompt++); + } + + tor_assert(buflen <= INT_MAX); + wchar_t *buf = tor_calloc(buflen, sizeof(wchar_t)); + + wchar_t *ptr = buf, *lastch = buf + buflen - 1; + while (ptr < lastch) { + wint_t ch = _getwch(); + switch (ch) { + case '\r': + case '\n': + case WEOF: + goto done_reading; + case 3: + goto done; /* Can't actually read ctrl-c this way. */ + case '\b': + if (ptr > buf) + --ptr; + continue; + case 0: + case 0xe0: + ch = _getwch(); /* Ignore; this is a function or arrow key */ + break; + default: + *ptr++ = ch; + break; + } + } + done_reading: + ; + +#ifndef WC_ERR_INVALID_CHARS +#define WC_ERR_INVALID_CHARS 0x80 +#endif + + /* Now convert it to UTF-8 */ + r = WideCharToMultiByte(CP_UTF8, + WC_NO_BEST_FIT_CHARS|WC_ERR_INVALID_CHARS, + buf, (int)(ptr-buf), + output, (int)(buflen-1), + NULL, NULL); + if (r <= 0) { + r = -1; + goto done; + } + + tor_assert(r < (int)buflen); + + output[r] = 0; + + done: + SecureZeroMemory(buf, sizeof(wchar_t)*buflen); + tor_free(buf); + return r; +#else +#error "No implementation for tor_getpass found!" +#endif /* defined(HAVE_READPASSPHRASE) || ... */ +} diff --git a/src/lib/term/getpass.h b/src/lib/term/getpass.h new file mode 100644 index 000000000..9d03f7036 --- /dev/null +++ b/src/lib/term/getpass.h @@ -0,0 +1,13 @@ +/* Copyright (c) 2003-2004, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_GETPASS_H +#define TOR_GETPASS_H + +#include "lib/cc/torint.h" + +ssize_t tor_getpass(const char *prompt, char *output, size_t buflen); + +#endif diff --git a/src/lib/term/include.am b/src/lib/term/include.am new file mode 100644 index 000000000..55fe548eb --- /dev/null +++ b/src/lib/term/include.am @@ -0,0 +1,24 @@ + +noinst_LIBRARIES += src/lib/libtor-term.a + +if UNITTESTS_ENABLED +noinst_LIBRARIES += src/lib/libtor-term-testing.a +endif + +if BUILD_READPASSPHRASE_C +readpassphrase_source=src/ext/readpassphrase.c +else +readpassphrase_source= +endif + +src_lib_libtor_term_a_SOURCES = \ + src/lib/term/getpass.c \ + $(readpassphrase_source) + +src_lib_libtor_term_testing_a_SOURCES = \ + $(src_lib_libtor_term_a_SOURCES) +src_lib_libtor_term_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS) +src_lib_libtor_term_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) + +noinst_HEADERS += \ + src/lib/term/getpass.h diff --git a/src/or/routerkeys.c b/src/or/routerkeys.c index 1e0a6fc65..b6d4d83d6 100644 --- a/src/or/routerkeys.c +++ b/src/or/routerkeys.c @@ -21,6 +21,7 @@ #include "lib/crypt_ops/crypto_pwbox.h" #include "or/routerkeys.h" #include "or/torcert.h" +#include "lib/term/getpass.h"
#define ENC_KEY_HEADER "Boxed Ed25519 key" #define ENC_KEY_TAG "master"
tor-commits@lists.torproject.org