|
@@ -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);
|