Tor 0.4.9.0-alpha-dev
getpass.c
Go to the documentation of this file.
1/* Copyright (c) 2003-2004, Roger Dingledine
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
4/* See LICENSE for licensing information */
5
6/**
7 * \file getpass.c
8 * \brief Cross-platform wrapper to read passphrases from the terminal.
9 **/
10
11#include "lib/term/getpass.h"
12
13#include "lib/log/util_bug.h"
14#include "lib/malloc/malloc.h"
15
16#ifdef _WIN32
17#include <windows.h>
18#include <conio.h>
19#include <wchar.h>
20/* Some mingw headers lack these. :p */
21#if defined(HAVE_DECL__GETWCH) && !HAVE_DECL__GETWCH
22wint_t _getwch(void);
23#endif
24#ifndef WEOF
25#define WEOF (wchar_t)(0xFFFF)
26#endif
27#if defined(HAVE_DECL_SECUREZEROMEMORY) && !HAVE_DECL_SECUREZEROMEMORY
28static inline void
29SecureZeroMemory(PVOID ptr, SIZE_T cnt)
30{
31 volatile char *vcptr = (volatile char*)ptr;
32 while (cnt--)
33 *vcptr++ = 0;
34}
35#endif /* defined(HAVE_DECL_SECUREZEROMEMORY) && !HAVE_DECL_SECUREZEROMEMORY */
36#elif defined(HAVE_READPASSPHRASE_H)
37#include <readpassphrase.h>
38#else
39#include "ext/tor_readpassphrase.h"
40#endif /* defined(_WIN32) || ... */
41
42#include <stdlib.h>
43#include <string.h>
44
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.
48 */
49ssize_t
50tor_getpass(const char *prompt, char *output, size_t buflen)
51{
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);
56 if (pwd == NULL)
57 return -1;
58 return strlen(pwd);
59#elif defined(_WIN32)
60 int r = -1;
61 while (*prompt) {
62 _putch(*prompt++);
63 }
64
65 tor_assert(buflen <= INT_MAX);
66 wchar_t *buf = tor_calloc(buflen, sizeof(wchar_t));
67
68 wchar_t *ptr = buf, *lastch = buf + buflen - 1;
69 while (ptr < lastch) {
70 wint_t ch = _getwch();
71 switch (ch) {
72 case '\r':
73 case '\n':
74 case WEOF:
75 goto done_reading;
76 case 3:
77 goto done; /* Can't actually read ctrl-c this way. */
78 case '\b':
79 if (ptr > buf)
80 --ptr;
81 continue;
82 case 0:
83 case 0xe0:
84 ch = _getwch(); /* Ignore; this is a function or arrow key */
85 break;
86 default:
87 *ptr++ = ch;
88 break;
89 }
90 }
91 done_reading:
92 ;
93
94#ifndef WC_ERR_INVALID_CHARS
95#define WC_ERR_INVALID_CHARS 0x80
96#endif
97
98 /* Now convert it to UTF-8 */
99 r = WideCharToMultiByte(CP_UTF8,
100 WC_NO_BEST_FIT_CHARS|WC_ERR_INVALID_CHARS,
101 buf, (int)(ptr-buf),
102 output, (int)(buflen-1),
103 NULL, NULL);
104 if (r <= 0) {
105 r = -1;
106 goto done;
107 }
108
109 tor_assert(r < (int)buflen);
110
111 output[r] = 0;
112
113 done:
114 SecureZeroMemory(buf, sizeof(wchar_t)*buflen);
115 tor_free(buf);
116 return r;
117#else
118#error "No implementation for tor_getpass found!"
119#endif /* defined(HAVE_READPASSPHRASE) || ... */
120}
ssize_t tor_getpass(const char *prompt, char *output, size_t buflen)
Definition: getpass.c:50
Header for getpass.c.
Headers for util_malloc.c.
#define tor_free(p)
Definition: malloc.h:56
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition: util_bug.h:103