"Fossies" - the Fresh Open Source Software Archive 
Member "cryptsetup-2.4.3/src/utils_password.c" (13 Jan 2022, 7924 Bytes) of package /linux/misc/cryptsetup-2.4.3.tar.xz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "utils_password.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
2.4.1_vs_2.4.2.
1 /*
2 * Password quality check wrapper
3 *
4 * Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
5 * Copyright (C) 2012-2021 Milan Broz
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22 #include "cryptsetup.h"
23 #include <termios.h>
24
25 #if defined ENABLE_PWQUALITY
26 #include <pwquality.h>
27
28 static int tools_check_pwquality(const char *password)
29 {
30 int r;
31 void *auxerror;
32 pwquality_settings_t *pwq;
33
34 log_dbg("Checking new password using default pwquality settings.");
35 pwq = pwquality_default_settings();
36 if (!pwq)
37 return -EINVAL;
38
39 r = pwquality_read_config(pwq, NULL, &auxerror);
40 if (r) {
41 log_err(_("Cannot check password quality: %s"),
42 pwquality_strerror(NULL, 0, r, auxerror));
43 pwquality_free_settings(pwq);
44 return -EINVAL;
45 }
46
47 r = pwquality_check(pwq, password, NULL, NULL, &auxerror);
48 if (r < 0) {
49 log_err(_("Password quality check failed:\n %s"),
50 pwquality_strerror(NULL, 0, r, auxerror));
51 r = -EPERM;
52 } else {
53 log_dbg("New password libpwquality score is %d.", r);
54 r = 0;
55 }
56
57 pwquality_free_settings(pwq);
58 return r;
59 }
60 #elif defined ENABLE_PASSWDQC
61 #include <passwdqc.h>
62
63 static int tools_check_passwdqc(const char *password)
64 {
65 passwdqc_params_t params;
66 char *parse_reason = NULL;
67 const char *check_reason;
68 const char *config = PASSWDQC_CONFIG_FILE;
69 int r = -EINVAL;
70
71 passwdqc_params_reset(¶ms);
72
73 if (*config && passwdqc_params_load(¶ms, &parse_reason, config)) {
74 log_err(_("Cannot check password quality: %s"),
75 (parse_reason ? parse_reason : "Out of memory"));
76 goto out;
77 }
78
79 check_reason = passwdqc_check(¶ms.qc, password, NULL, NULL);
80 if (check_reason) {
81 log_err(_("Password quality check failed: Bad passphrase (%s)"),
82 check_reason);
83 r = -EPERM;
84 } else
85 r = 0;
86 out:
87 #if HAVE_PASSWDQC_PARAMS_FREE
88 passwdqc_params_free(¶ms);
89 #endif
90 free(parse_reason);
91 return r;
92 }
93 #endif /* ENABLE_PWQUALITY || ENABLE_PASSWDQC */
94
95 /* coverity[ +tainted_string_sanitize_content : arg-0 ] */
96 static int tools_check_password(const char *password)
97 {
98 #if defined ENABLE_PWQUALITY
99 return tools_check_pwquality(password);
100 #elif defined ENABLE_PASSWDQC
101 return tools_check_passwdqc(password);
102 #else
103 return 0;
104 #endif
105 }
106
107 /* Password reading helpers */
108
109 static ssize_t read_tty_eol(int fd, char *pass, size_t maxlen)
110 {
111 bool eol = false;
112 size_t read_size = 0;
113 ssize_t r;
114
115 do {
116 r = read(fd, pass, maxlen - read_size);
117 if ((r == -1 && errno != EINTR) || quit)
118 return -1;
119 if (r >= 0) {
120 if (!r || pass[r-1] == '\n')
121 eol = true;
122 read_size += (size_t)r;
123 pass = pass + r;
124 }
125 } while (!eol && read_size != maxlen);
126
127 return (ssize_t)read_size;
128 }
129
130 /* The pass buffer is zeroed and has trailing \0 already " */
131 static int untimed_read(int fd, char *pass, size_t maxlen)
132 {
133 ssize_t i;
134
135 i = read_tty_eol(fd, pass, maxlen);
136 if (i > 0) {
137 if (pass[i-1] == '\n')
138 pass[i-1] = '\0';
139 i = 0;
140 } else if (i == 0) /* empty input */
141 i = -1;
142
143 return i;
144 }
145
146 static int timed_read(int fd, char *pass, size_t maxlen, long timeout)
147 {
148 struct timeval t;
149 fd_set fds = {}; /* Just to avoid scan-build false report for FD_SET */
150 int failed = -1;
151
152 FD_ZERO(&fds);
153 FD_SET(fd, &fds);
154 t.tv_sec = timeout;
155 t.tv_usec = 0;
156
157 if (select(fd+1, &fds, NULL, NULL, &t) > 0)
158 failed = untimed_read(fd, pass, maxlen);
159
160 return failed;
161 }
162
163 static int interactive_pass(const char *prompt, char *pass, size_t maxlen,
164 long timeout)
165 {
166 struct termios orig, tmp;
167 int failed = -1;
168 int infd, outfd;
169
170 if (maxlen < 1)
171 return failed;
172
173 /* Read and write to /dev/tty if available */
174 infd = open("/dev/tty", O_RDWR);
175 if (infd == -1) {
176 infd = STDIN_FILENO;
177 outfd = STDERR_FILENO;
178 } else
179 outfd = infd;
180
181 if (tcgetattr(infd, &orig))
182 goto out;
183
184 memcpy(&tmp, &orig, sizeof(tmp));
185 tmp.c_lflag &= ~ECHO;
186
187 if (prompt && write(outfd, prompt, strlen(prompt)) < 0)
188 goto out;
189
190 tcsetattr(infd, TCSAFLUSH, &tmp);
191 if (timeout)
192 failed = timed_read(infd, pass, maxlen, timeout);
193 else
194 failed = untimed_read(infd, pass, maxlen);
195 tcsetattr(infd, TCSAFLUSH, &orig);
196 out:
197 if (!failed && write(outfd, "\n", 1)) {};
198
199 if (infd != STDIN_FILENO)
200 close(infd);
201 return failed;
202 }
203
204 static int crypt_get_key_tty(const char *prompt,
205 char **key, size_t *key_size,
206 int timeout, int verify)
207 {
208 int key_size_max = DEFAULT_PASSPHRASE_SIZE_MAX;
209 int r = -EINVAL;
210 char *pass = NULL, *pass_verify = NULL;
211
212 *key = NULL;
213 *key_size = 0;
214
215 log_dbg("Interactive passphrase entry requested.");
216
217 pass = crypt_safe_alloc(key_size_max + 1);
218 if (!pass) {
219 log_err( _("Out of memory while reading passphrase."));
220 return -ENOMEM;
221 }
222
223 if (interactive_pass(prompt, pass, key_size_max, timeout)) {
224 log_err(_("Error reading passphrase from terminal."));
225 goto out;
226 }
227
228 if (verify) {
229 pass_verify = crypt_safe_alloc(key_size_max + 1);
230 if (!pass_verify) {
231 log_err(_("Out of memory while reading passphrase."));
232 r = -ENOMEM;
233 goto out;
234 }
235
236 if (interactive_pass(_("Verify passphrase: "),
237 pass_verify, key_size_max, timeout)) {
238 log_err(_("Error reading passphrase from terminal."));
239 goto out;
240 }
241
242 if (strncmp(pass, pass_verify, key_size_max)) {
243 log_err(_("Passphrases do not match."));
244 r = -EPERM;
245 goto out;
246 }
247 }
248
249 *key = pass;
250 *key_size = strlen(pass);
251 r = 0;
252 out:
253 crypt_safe_free(pass_verify);
254 if (r)
255 crypt_safe_free(pass);
256 return r;
257 }
258
259 /*
260 * Note: --key-file=- is interpreted as a read from a binary file (stdin)
261 * key_size_max == 0 means detect maximum according to input type (tty/file)
262 */
263 int tools_get_key(const char *prompt,
264 char **key, size_t *key_size,
265 uint64_t keyfile_offset, size_t keyfile_size_max,
266 const char *key_file,
267 int timeout, int verify, int pwquality,
268 struct crypt_device *cd)
269 {
270 char tmp[PATH_MAX], *backing_file;
271 int r = -EINVAL, block;
272
273 block = tools_signals_blocked();
274 if (block)
275 set_int_block(0);
276
277 if (tools_is_stdin(key_file)) {
278 if (isatty(STDIN_FILENO)) {
279 if (keyfile_offset) {
280 log_err(_("Cannot use offset with terminal input."));
281 } else {
282 if (!prompt && !crypt_get_device_name(cd))
283 snprintf(tmp, sizeof(tmp), _("Enter passphrase: "));
284 else if (!prompt) {
285 backing_file = crypt_loop_backing_file(crypt_get_device_name(cd));
286 snprintf(tmp, sizeof(tmp), _("Enter passphrase for %s: "), backing_file ?: crypt_get_device_name(cd));
287 free(backing_file);
288 }
289 r = crypt_get_key_tty(prompt ?: tmp, key, key_size, timeout, verify);
290 }
291 } else {
292 log_dbg("STDIN descriptor passphrase entry requested.");
293 /* No keyfile means STDIN with EOL handling (\n will end input)). */
294 r = crypt_keyfile_device_read(cd, NULL, key, key_size,
295 keyfile_offset, keyfile_size_max,
296 key_file ? 0 : CRYPT_KEYFILE_STOP_EOL);
297 }
298 } else {
299 log_dbg("File descriptor passphrase entry requested.");
300 r = crypt_keyfile_device_read(cd, key_file, key, key_size,
301 keyfile_offset, keyfile_size_max, 0);
302 }
303
304 if (block && !quit)
305 set_int_block(1);
306
307 /* Check pwquality for password (not keyfile) */
308 if (pwquality && !key_file && !r)
309 r = tools_check_password(*key);
310
311 return r;
312 }
313
314 void tools_passphrase_msg(int r)
315 {
316 if (r == -EPERM)
317 log_err(_("No key available with this passphrase."));
318 else if (r == -ENOENT)
319 log_err(_("No usable keyslot is available."));
320 }