mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Add a getpass implementation for windows that won't totally suck
The logic here is inspired by Python's win_getpass(), which I'm assuming is better than nothing.
This commit is contained in:
parent
b9b658e727
commit
a64f2d167e
@ -71,6 +71,8 @@
|
||||
#include <readpassphrase.h>
|
||||
#elif !defined(_WIN32)
|
||||
#include "readpassphrase.h"
|
||||
#else
|
||||
#include <conio.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETTIMEOFDAY
|
||||
@ -3248,16 +3250,77 @@ tor_sleep_msec(int msec)
|
||||
#endif
|
||||
|
||||
/** Emit the password prompt <b>prompt</b>, then read up to <b>buflen</b>
|
||||
* characters of passphrase into <b>output</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;
|
||||
#elif defined(HAVE_GETPASS)
|
||||
/* XXX We shouldn't actually use this; it's deprecated to hell and back */
|
||||
memset(output, 0, buflen);
|
||||
|
Loading…
Reference in New Issue
Block a user