mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-09-21 21:44:58 +02: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>
|
#include <readpassphrase.h>
|
||||||
#elif !defined(_WIN32)
|
#elif !defined(_WIN32)
|
||||||
#include "readpassphrase.h"
|
#include "readpassphrase.h"
|
||||||
|
#else
|
||||||
|
#include <conio.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_GETTIMEOFDAY
|
#ifndef HAVE_GETTIMEOFDAY
|
||||||
@ -3248,16 +3250,77 @@ tor_sleep_msec(int msec)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Emit the password prompt <b>prompt</b>, then read up to <b>buflen</b>
|
/** 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
|
ssize_t
|
||||||
tor_getpass(const char *prompt, char *output, size_t buflen)
|
tor_getpass(const char *prompt, char *output, size_t buflen)
|
||||||
{
|
{
|
||||||
tor_assert(buflen <= SSIZE_MAX);
|
tor_assert(buflen <= SSIZE_MAX);
|
||||||
|
tor_assert(buflen >= 1);
|
||||||
#if defined(HAVE_READPASSPHRASE)
|
#if defined(HAVE_READPASSPHRASE)
|
||||||
char *pwd = readpassphrase(prompt, output, buflen, RPP_ECHO_OFF);
|
char *pwd = readpassphrase(prompt, output, buflen, RPP_ECHO_OFF);
|
||||||
if (pwd == NULL)
|
if (pwd == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
return strlen(pwd);
|
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)
|
#elif defined(HAVE_GETPASS)
|
||||||
/* XXX We shouldn't actually use this; it's deprecated to hell and back */
|
/* XXX We shouldn't actually use this; it's deprecated to hell and back */
|
||||||
memset(output, 0, buflen);
|
memset(output, 0, buflen);
|
||||||
|
Loading…
Reference in New Issue
Block a user