1 /* Copyright (c) 2003-2004, Roger Dingledine
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2020, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
8 * \brief Cross-platform wrapper to read passphrases from the terminal.
11 #include "lib/term/getpass.h"
13 #include "lib/log/util_bug.h"
14 #include "lib/malloc/malloc.h"
20 /* Some mingw headers lack these. :p */
21 #if defined(HAVE_DECL__GETWCH) && !HAVE_DECL__GETWCH
25 #define WEOF (wchar_t)(0xFFFF)
27 #if defined(HAVE_DECL_SECUREZEROMEMORY) && !HAVE_DECL_SECUREZEROMEMORY
29 SecureZeroMemory(PVOID ptr
, SIZE_T cnt
)
31 volatile char *vcptr
= (volatile char*)ptr
;
35 #endif /* defined(HAVE_DECL_SECUREZEROMEMORY) && !HAVE_DECL_SECUREZEROMEMORY */
36 #elif defined(HAVE_READPASSPHRASE_H)
37 #include <readpassphrase.h>
39 #include "ext/tor_readpassphrase.h"
40 #endif /* defined(_WIN32) || ... */
45 /** Emit the password prompt <b>prompt</b>, then read up to <b>buflen</b>
46 * bytes of passphrase into <b>output</b>. Return the number of bytes in
47 * the passphrase, excluding terminating NUL.
50 tor_getpass(const char *prompt
, char *output
, size_t buflen
)
52 tor_assert(buflen
<= SSIZE_MAX
);
53 tor_assert(buflen
>= 1);
54 #if defined(HAVE_READPASSPHRASE)
55 char *pwd
= readpassphrase(prompt
, output
, buflen
, RPP_ECHO_OFF
);
65 tor_assert(buflen
<= INT_MAX
);
66 wchar_t *buf
= tor_calloc(buflen
, sizeof(wchar_t));
68 wchar_t *ptr
= buf
, *lastch
= buf
+ buflen
- 1;
69 while (ptr
< lastch
) {
70 wint_t ch
= _getwch();
77 goto done
; /* Can't actually read ctrl-c this way. */
84 ch
= _getwch(); /* Ignore; this is a function or arrow key */
94 #ifndef WC_ERR_INVALID_CHARS
95 #define WC_ERR_INVALID_CHARS 0x80
98 /* Now convert it to UTF-8 */
99 r
= WideCharToMultiByte(CP_UTF8
,
100 WC_NO_BEST_FIT_CHARS
|WC_ERR_INVALID_CHARS
,
102 output
, (int)(buflen
-1),
109 tor_assert(r
< (int)buflen
);
114 SecureZeroMemory(buf
, sizeof(wchar_t)*buflen
);
118 #error "No implementation for tor_getpass found!"
119 #endif /* defined(HAVE_READPASSPHRASE) || ... */