[tor-commits] [tor/master] Add a getpass implementation for windows that won't totally suck
nickm at torproject.org
nickm at torproject.org
Thu Jun 25 14:53:17 UTC 2015
commit a64f2d167eab4baefb4fe2471fd2e554a132d37f
Author: Nick Mathewson <nickm at torproject.org>
Date: Wed Jun 17 11:22:31 2015 -0400
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.
---
src/common/compat.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 64 insertions(+), 1 deletion(-)
diff --git a/src/common/compat.c b/src/common/compat.c
index a931f0a..4a35183 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -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);
More information about the tor-commits
mailing list