Electroneum
Loading...
Searching...
No Matches
password.cpp
Go to the documentation of this file.
1// Copyrights(c) 2017-2021, The Electroneum Project
2// Copyrights(c) 2014-2019, The Monero Project
3//
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without modification, are
7// permitted provided that the following conditions are met:
8//
9// 1. Redistributions of source code must retain the above copyright notice, this list of
10// conditions and the following disclaimer.
11//
12// 2. Redistributions in binary form must reproduce the above copyright notice, this list
13// of conditions and the following disclaimer in the documentation and/or other
14// materials provided with the distribution.
15//
16// 3. Neither the name of the copyright holder nor the names of its contributors may be
17// used to endorse or promote products derived from this software without specific
18// prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
31
32#include "password.h"
33
34#include <iostream>
35#include <stdio.h>
36
37#if defined(_WIN32)
38#include <io.h>
39#include <windows.h>
40#else
41#include <termios.h>
42#include <unistd.h>
43#endif
44
45#define EOT 0x4
46
47namespace
48{
49#if defined(_WIN32)
50 bool is_cin_tty() noexcept
51 {
52 return 0 != _isatty(_fileno(stdin));
53 }
54
55 bool read_from_tty(epee::wipeable_string& pass, bool hide_input)
56 {
57 HANDLE h_cin = ::GetStdHandle(STD_INPUT_HANDLE);
58
59 DWORD mode_old;
60 ::GetConsoleMode(h_cin, &mode_old);
61 DWORD mode_new = mode_old & ~((hide_input ? ENABLE_ECHO_INPUT : 0) | ENABLE_LINE_INPUT);
62 ::SetConsoleMode(h_cin, mode_new);
63
64 bool r = true;
66 std::vector<int> chlen;
69 {
70 DWORD read;
71 wchar_t ucs2_ch;
72 r = (TRUE == ::ReadConsoleW(h_cin, &ucs2_ch, 1, &read, NULL));
73 r &= (1 == read);
74
75 if (!r)
76 {
77 break;
78 }
79 else if (ucs2_ch == L'\r')
80 {
81 std::cout << std::endl;
82 break;
83 }
84 else if (ucs2_ch == L'\b')
85 {
86 if (!pass.empty())
87 {
88 int len = chlen.back();
89 chlen.pop_back();
90 while(len-- > 0)
91 pass.pop_back();
92 }
93 continue;
94 }
95
96 char utf8_ch[8] = {0};
97 int len;
98 if((len = WideCharToMultiByte(CP_UTF8, 0, &ucs2_ch, 1, utf8_ch, sizeof(utf8_ch), NULL, NULL)) <= 0)
99 break;
100
102 break;
103
104 chlen.push_back(len);
105 pass += utf8_ch;
106 }
107
108 ::SetConsoleMode(h_cin, mode_old);
109
110 return r;
111 }
112
113#else // end WIN32
114
115 bool is_cin_tty() noexcept
116 {
117 return 0 != isatty(fileno(stdin));
118 }
119
120 int getch(bool hide_input) noexcept
121 {
122 struct termios tty_old;
123 tcgetattr(STDIN_FILENO, &tty_old);
124
125 struct termios tty_new;
126 tty_new = tty_old;
127 tty_new.c_lflag &= ~(ICANON | (hide_input ? ECHO : 0));
128 tcsetattr(STDIN_FILENO, TCSANOW, &tty_new);
129
130 int ch = getchar();
131
132 tcsetattr(STDIN_FILENO, TCSANOW, &tty_old);
133
134 return ch;
135 }
136
137 bool read_from_tty(epee::wipeable_string& aPass, bool hide_input)
138 {
139 static constexpr const char BACKSPACE = 127;
140
143 {
144 int ch = getch(hide_input);
145 if (EOF == ch || ch == EOT)
146 {
147 return false;
148 }
149 else if (ch == '\n' || ch == '\r')
150 {
151 std::cout << std::endl;
152 break;
153 }
154 else if (ch == BACKSPACE)
155 {
156 if (!aPass.empty())
157 {
158 aPass.pop_back();
159 if (!hide_input)
160 std::cout << "\b\b\b \b\b\b" << std::flush;
161 }
162 else
163 {
164 if (!hide_input)
165 std::cout << "\b\b \b\b" << std::flush;
166 }
167 }
168 else
169 {
170 aPass.push_back(ch);
171 }
172 }
173
174 return true;
175 }
176
177#endif // end !WIN32
178
179 bool read_from_tty(const bool verify, const char *message, bool hide_input, epee::wipeable_string& pass1, epee::wipeable_string& pass2)
180 {
181 while (true)
182 {
183 if (message)
184 std::cout << message <<": " << std::flush;
185 if (!read_from_tty(pass1, hide_input))
186 return false;
187 if (verify)
188 {
189 std::cout << "Confirm password: ";
190 if (!read_from_tty(pass2, hide_input))
191 return false;
192 if(pass1!=pass2)
193 {
194 std::cout << "Passwords do not match! Please try again." << std::endl;
195 pass1.clear();
196 pass2.clear();
197 }
198 else //new password matches
199 return true;
200 }
201 else
202 return true;
203 //No need to verify password entered at this point in the code
204 }
205
206 return false;
207 }
208
209 bool read_from_file(epee::wipeable_string& pass)
210 {
212 for (size_t i = 0; i < tools::password_container::max_password_size; ++i)
213 {
214 char ch = static_cast<char>(std::cin.get());
215 if (std::cin.eof() || ch == '\n' || ch == '\r')
216 {
217 break;
218 }
219 else if (std::cin.fail())
220 {
221 return false;
222 }
223 else
224 {
225 pass.push_back(ch);
226 }
227 }
228 return true;
229 }
230
231} // anonymous namespace
232
233namespace tools
234{
235 // deleted via private member
236 password_container::password_container() noexcept : m_password() {}
238 : m_password(std::move(password))
239 {
240 }
245
247 {
248 m_password.clear();
249 }
250
251 std::atomic<bool> password_container::is_prompting(false);
252
253 boost::optional<password_container> password_container::prompt(const bool verify, const char *message, bool hide_input)
254 {
255 is_prompting = true;
256 password_container pass1{};
257 password_container pass2{};
258 if (is_cin_tty() ? read_from_tty(verify, message, hide_input, pass1.m_password, pass2.m_password) : read_from_file(pass1.m_password))
259 {
260 is_prompting = false;
261 return {std::move(pass1)};
262 }
263
264 is_prompting = false;
265 return boost::none;
266 }
267
268 boost::optional<login> login::parse(std::string&& userpass, bool verify, const std::function<boost::optional<password_container>(bool)> &prompt)
269 {
270 login out{};
271
272 const auto loc = userpass.find(':');
273 if (loc == std::string::npos)
274 {
275 auto result = prompt(verify);
276 if (!result)
277 return boost::none;
278
279 out.password = std::move(*result);
280 }
281 else
282 {
283 out.password = password_container{userpass.substr(loc + 1)};
284 }
285
286 out.username = userpass.substr(0, loc);
287 password_container wipe{std::move(userpass)};
288 return {std::move(out)};
289 }
290}
bool empty() const noexcept
size_t size() const noexcept
password_container() noexcept
Empty password.
Definition password.cpp:236
~password_container() noexcept
Wipes internal password.
Definition password.cpp:246
const epee::wipeable_string & password() const noexcept
Definition password.h:66
static boost::optional< password_container > prompt(bool verify, const char *mesage="Password", bool hide_input=true)
Definition password.cpp:253
static constexpr const size_t max_password_size
Definition password.h:44
static std::atomic< bool > is_prompting
Definition password.h:55
std::string message("Message requiring signing")
Various Tools.
Definition tools.cpp:31
#define EOT
Definition password.cpp:45
static boost::optional< login > parse(std::string &&userpass, bool verify, const std::function< boost::optional< password_container >(bool)> &prompt)
Definition password.cpp:268
login()=default