2 * Password quality check wrapper
4 * Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
5 * Copyright (C) 2012-2021 Milan Broz
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.
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.
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.
22 #include "cryptsetup.h"
25 int opt_force_password = 0;
27 #if defined ENABLE_PWQUALITY
28 #include <pwquality.h>
30 static int tools_check_pwquality(const char *password)
34 pwquality_settings_t *pwq;
36 log_dbg("Checking new password using default pwquality settings.");
37 pwq = pwquality_default_settings();
41 r = pwquality_read_config(pwq, NULL, &auxerror);
43 log_err(_("Cannot check password quality: %s"),
44 pwquality_strerror(NULL, 0, r, auxerror));
45 pwquality_free_settings(pwq);
49 r = pwquality_check(pwq, password, NULL, NULL, &auxerror);
51 log_err(_("Password quality check failed:\n %s"),
52 pwquality_strerror(NULL, 0, r, auxerror));
55 log_dbg("New password libpwquality score is %d.", r);
59 pwquality_free_settings(pwq);
62 #elif defined ENABLE_PASSWDQC
65 static int tools_check_passwdqc(const char *password)
67 passwdqc_params_t params;
68 char *parse_reason = NULL;
69 const char *check_reason;
70 const char *config = PASSWDQC_CONFIG_FILE;
73 passwdqc_params_reset(¶ms);
75 if (*config && passwdqc_params_load(¶ms, &parse_reason, config)) {
76 log_err(_("Cannot check password quality: %s"),
77 (parse_reason ? parse_reason : "Out of memory"));
81 check_reason = passwdqc_check(¶ms.qc, password, NULL, NULL);
83 log_err(_("Password quality check failed: Bad passphrase (%s)"),
89 #if HAVE_PASSWDQC_PARAMS_FREE
90 passwdqc_params_free(¶ms);
95 #endif /* ENABLE_PWQUALITY || ENABLE_PASSWDQC */
97 /* coverity[ +tainted_string_sanitize_content : arg-0 ] */
98 static int tools_check_password(const char *password)
100 #if defined ENABLE_PWQUALITY
101 return tools_check_pwquality(password);
102 #elif defined ENABLE_PASSWDQC
103 return tools_check_passwdqc(password);
109 /* Password reading helpers */
111 static ssize_t read_tty_eol(int fd, char *pass, size_t maxlen)
114 size_t read_size = 0;
118 r = read(fd, pass, maxlen - read_size);
119 if ((r == -1 && errno != EINTR) || quit)
122 if (!r || pass[r-1] == '\n')
124 read_size += (size_t)r;
127 } while (!eol && read_size != maxlen);
129 return (ssize_t)read_size;
132 /* The pass buffer is zeroed and has trailing \0 already " */
133 static int untimed_read(int fd, char *pass, size_t maxlen)
137 i = read_tty_eol(fd, pass, maxlen);
139 if (pass[i-1] == '\n')
142 } else if (i == 0) /* empty input */
148 static int timed_read(int fd, char *pass, size_t maxlen, long timeout)
151 fd_set fds = {}; /* Just to avoid scan-build false report for FD_SET */
159 if (select(fd+1, &fds, NULL, NULL, &t) > 0)
160 failed = untimed_read(fd, pass, maxlen);
165 static int interactive_pass(const char *prompt, char *pass, size_t maxlen,
168 struct termios orig, tmp;
175 /* Read and write to /dev/tty if available */
176 infd = open("/dev/tty", O_RDWR);
179 outfd = STDERR_FILENO;
183 if (tcgetattr(infd, &orig))
186 memcpy(&tmp, &orig, sizeof(tmp));
187 tmp.c_lflag &= ~ECHO;
189 if (prompt && write(outfd, prompt, strlen(prompt)) < 0)
192 tcsetattr(infd, TCSAFLUSH, &tmp);
194 failed = timed_read(infd, pass, maxlen, timeout);
196 failed = untimed_read(infd, pass, maxlen);
197 tcsetattr(infd, TCSAFLUSH, &orig);
200 if (!failed && write(outfd, "\n", 1)) {};
202 if (infd != STDIN_FILENO)
207 static int crypt_get_key_tty(const char *prompt,
208 char **key, size_t *key_size,
209 int timeout, int verify,
210 struct crypt_device *cd)
212 int key_size_max = DEFAULT_PASSPHRASE_SIZE_MAX;
214 char *pass = NULL, *pass_verify = NULL;
219 log_dbg("Interactive passphrase entry requested.");
221 pass = crypt_safe_alloc(key_size_max + 1);
223 log_err( _("Out of memory while reading passphrase."));
227 if (interactive_pass(prompt, pass, key_size_max, timeout)) {
228 log_err(_("Error reading passphrase from terminal."));
233 pass_verify = crypt_safe_alloc(key_size_max + 1);
235 log_err(_("Out of memory while reading passphrase."));
240 if (interactive_pass(_("Verify passphrase: "),
241 pass_verify, key_size_max, timeout)) {
242 log_err(_("Error reading passphrase from terminal."));
246 if (strncmp(pass, pass_verify, key_size_max)) {
247 log_err(_("Passphrases do not match."));
254 *key_size = strlen(pass);
257 crypt_safe_free(pass_verify);
259 crypt_safe_free(pass);
264 * Note: --key-file=- is interpreted as a read from a binary file (stdin)
265 * key_size_max == 0 means detect maximum according to input type (tty/file)
267 int tools_get_key(const char *prompt,
268 char **key, size_t *key_size,
269 uint64_t keyfile_offset, size_t keyfile_size_max,
270 const char *key_file,
271 int timeout, int verify, int pwquality,
272 struct crypt_device *cd)
274 char tmp[PATH_MAX], *backing_file;
275 int r = -EINVAL, block;
277 block = tools_signals_blocked();
281 if (tools_is_stdin(key_file)) {
282 if (isatty(STDIN_FILENO)) {
283 if (keyfile_offset) {
284 log_err(_("Cannot use offset with terminal input."));
286 if (!prompt && !crypt_get_device_name(cd))
287 snprintf(tmp, sizeof(tmp), _("Enter passphrase: "));
289 backing_file = crypt_loop_backing_file(crypt_get_device_name(cd));
290 snprintf(tmp, sizeof(tmp), _("Enter passphrase for %s: "), backing_file ?: crypt_get_device_name(cd));
293 r = crypt_get_key_tty(prompt ?: tmp, key, key_size, timeout, verify, cd);
296 log_dbg("STDIN descriptor passphrase entry requested.");
297 /* No keyfile means STDIN with EOL handling (\n will end input)). */
298 r = crypt_keyfile_device_read(cd, NULL, key, key_size,
299 keyfile_offset, keyfile_size_max,
300 key_file ? 0 : CRYPT_KEYFILE_STOP_EOL);
303 log_dbg("File descriptor passphrase entry requested.");
304 r = crypt_keyfile_device_read(cd, key_file, key, key_size,
305 keyfile_offset, keyfile_size_max, 0);
311 /* Check pwquality for password (not keyfile) */
312 if (pwquality && !opt_force_password && !key_file && !r)
313 r = tools_check_password(*key);
318 void tools_passphrase_msg(int r)
321 log_err(_("No key available with this passphrase."));
322 else if (r == -ENOENT)
323 log_err(_("No usable keyslot is available."));
326 int tools_read_mk(const char *file, char **key, int keysize)
330 if (keysize <= 0 || !key)
333 *key = crypt_safe_alloc(keysize);
337 fd = open(file, O_RDONLY);
339 log_err(_("Cannot read keyfile %s."), file);
343 if (read_buffer(fd, *key, keysize) != keysize) {
344 log_err(_("Cannot read %d bytes from keyfile %s."), keysize, file);
351 crypt_safe_free(*key);
356 int tools_write_mk(const char *file, const char *key, int keysize)
360 if (keysize <= 0 || !key)
363 fd = open(file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR);
365 log_err(_("Cannot open keyfile %s for write."), file);
369 if (write_buffer(fd, key, keysize) == keysize)
372 log_err(_("Cannot write to keyfile %s."), file);