2 * Password quality check wrapper
4 * Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved.
5 * Copyright (C) 2012-2020 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_pwquality(const char *password)
67 passwdqc_params_t params;
69 const char *check_reason;
70 const char *config = PASSWDQC_CONFIG_FILE;
72 passwdqc_params_reset(¶ms);
74 if (*config && passwdqc_params_load(¶ms, &parse_reason, config)) {
75 log_err(_("Cannot check password quality: %s"),
76 (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)"),
90 #else /* !(ENABLE_PWQUALITY || ENABLE_PASSWDQC) */
91 static int tools_check_pwquality(const char *password)
95 #endif /* ENABLE_PWQUALITY || ENABLE_PASSWDQC */
97 /* Password reading helpers */
98 static int untimed_read(int fd, char *pass, size_t maxlen)
102 i = read(fd, pass, maxlen);
106 } else if (i == 0) { /* EOF */
113 static int timed_read(int fd, char *pass, size_t maxlen, long timeout)
116 fd_set fds = {}; /* Just to avoid scan-build false report for FD_SET */
124 if (select(fd+1, &fds, NULL, NULL, &t) > 0)
125 failed = untimed_read(fd, pass, maxlen);
130 static int interactive_pass(const char *prompt, char *pass, size_t maxlen,
133 struct termios orig, tmp;
140 /* Read and write to /dev/tty if available */
141 infd = open("/dev/tty", O_RDWR);
144 outfd = STDERR_FILENO;
148 if (tcgetattr(infd, &orig))
151 memcpy(&tmp, &orig, sizeof(tmp));
152 tmp.c_lflag &= ~ECHO;
154 if (prompt && write(outfd, prompt, strlen(prompt)) < 0)
157 tcsetattr(infd, TCSAFLUSH, &tmp);
159 failed = timed_read(infd, pass, maxlen, timeout);
161 failed = untimed_read(infd, pass, maxlen);
162 tcsetattr(infd, TCSAFLUSH, &orig);
165 if (!failed && write(outfd, "\n", 1)) {};
167 if (infd != STDIN_FILENO)
172 static int crypt_get_key_tty(const char *prompt,
173 char **key, size_t *key_size,
174 int timeout, int verify,
175 struct crypt_device *cd)
177 int key_size_max = DEFAULT_PASSPHRASE_SIZE_MAX;
179 char *pass = NULL, *pass_verify = NULL;
184 log_dbg("Interactive passphrase entry requested.");
186 pass = crypt_safe_alloc(key_size_max + 1);
188 log_err( _("Out of memory while reading passphrase."));
192 if (interactive_pass(prompt, pass, key_size_max, timeout)) {
193 log_err(_("Error reading passphrase from terminal."));
196 pass[key_size_max] = '\0';
199 pass_verify = crypt_safe_alloc(key_size_max);
201 log_err(_("Out of memory while reading passphrase."));
206 if (interactive_pass(_("Verify passphrase: "),
207 pass_verify, key_size_max, timeout)) {
208 log_err(_("Error reading passphrase from terminal."));
212 if (strncmp(pass, pass_verify, key_size_max)) {
213 log_err(_("Passphrases do not match."));
220 *key_size = strlen(pass);
223 crypt_safe_free(pass_verify);
225 crypt_safe_free(pass);
230 * Note: --key-file=- is interpreted as a read from a binary file (stdin)
231 * key_size_max == 0 means detect maximum according to input type (tty/file)
233 int tools_get_key(const char *prompt,
234 char **key, size_t *key_size,
235 uint64_t keyfile_offset, size_t keyfile_size_max,
236 const char *key_file,
237 int timeout, int verify, int pwquality,
238 struct crypt_device *cd)
240 char tmp[PATH_MAX], *backing_file;
241 int r = -EINVAL, block;
243 block = tools_signals_blocked();
247 if (tools_is_stdin(key_file)) {
248 if (isatty(STDIN_FILENO)) {
249 if (keyfile_offset) {
250 log_err(_("Cannot use offset with terminal input."));
252 if (!prompt && !crypt_get_device_name(cd))
253 snprintf(tmp, sizeof(tmp), _("Enter passphrase: "));
255 backing_file = crypt_loop_backing_file(crypt_get_device_name(cd));
256 snprintf(tmp, sizeof(tmp), _("Enter passphrase for %s: "), backing_file ?: crypt_get_device_name(cd));
259 r = crypt_get_key_tty(prompt ?: tmp, key, key_size, timeout, verify, cd);
262 log_dbg("STDIN descriptor passphrase entry requested.");
263 /* No keyfile means STDIN with EOL handling (\n will end input)). */
264 r = crypt_keyfile_device_read(cd, NULL, key, key_size,
265 keyfile_offset, keyfile_size_max,
266 key_file ? 0 : CRYPT_KEYFILE_STOP_EOL);
269 log_dbg("File descriptor passphrase entry requested.");
270 r = crypt_keyfile_device_read(cd, key_file, key, key_size,
271 keyfile_offset, keyfile_size_max, 0);
277 /* Check pwquality for password (not keyfile) */
278 if (pwquality && !opt_force_password && !key_file && !r)
279 r = tools_check_pwquality(*key);
284 void tools_passphrase_msg(int r)
287 log_err(_("No key available with this passphrase."));
288 else if (r == -ENOENT)
289 log_err(_("No usable keyslot is available."));
292 int tools_read_mk(const char *file, char **key, int keysize)
296 if (!keysize || !key)
299 *key = crypt_safe_alloc(keysize);
303 fd = open(file, O_RDONLY);
305 log_err(_("Cannot read keyfile %s."), file);
309 if (read_buffer(fd, *key, keysize) != keysize) {
310 log_err(_("Cannot read %d bytes from keyfile %s."), keysize, file);
317 crypt_safe_free(*key);
322 int tools_write_mk(const char *file, const char *key, int keysize)
326 fd = open(file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR);
328 log_err(_("Cannot open keyfile %s for write."), file);
332 if (write_buffer(fd, key, keysize) == keysize)
335 log_err(_("Cannot write to keyfile %s."), file);