diff --git a/lib/utils_crypt.c b/lib/utils_crypt.c index 788ea455..a9b01eca 100644 --- a/lib/utils_crypt.c +++ b/lib/utils_crypt.c @@ -31,7 +31,6 @@ #include #include #include -#include #include "libcryptsetup.h" #include "nls.h" @@ -150,138 +149,6 @@ void *crypt_safe_realloc(void *data, size_t size) return new_data; } -/* Password reading helpers */ -static int untimed_read(int fd, char *pass, size_t maxlen) -{ - ssize_t i; - - i = read(fd, pass, maxlen); - if (i > 0) { - pass[i-1] = '\0'; - i = 0; - } else if (i == 0) { /* EOF */ - *pass = 0; - i = -1; - } - return i; -} - -static int timed_read(int fd, char *pass, size_t maxlen, long timeout) -{ - struct timeval t; - fd_set fds = {}; /* Just to avoid scan-build false report for FD_SET */ - int failed = -1; - - FD_ZERO(&fds); - FD_SET(fd, &fds); - t.tv_sec = timeout; - t.tv_usec = 0; - - if (select(fd+1, &fds, NULL, NULL, &t) > 0) - failed = untimed_read(fd, pass, maxlen); - - return failed; -} - -static int interactive_pass(const char *prompt, char *pass, size_t maxlen, - long timeout) -{ - struct termios orig, tmp; - int failed = -1; - int infd, outfd; - - if (maxlen < 1) - return failed; - - /* Read and write to /dev/tty if available */ - infd = open("/dev/tty", O_RDWR); - if (infd == -1) { - infd = STDIN_FILENO; - outfd = STDERR_FILENO; - } else - outfd = infd; - - if (tcgetattr(infd, &orig)) - goto out_err; - - memcpy(&tmp, &orig, sizeof(tmp)); - tmp.c_lflag &= ~ECHO; - - if (prompt && write(outfd, prompt, strlen(prompt)) < 0) - goto out_err; - - tcsetattr(infd, TCSAFLUSH, &tmp); - if (timeout) - failed = timed_read(infd, pass, maxlen, timeout); - else - failed = untimed_read(infd, pass, maxlen); - tcsetattr(infd, TCSAFLUSH, &orig); - -out_err: - if (!failed && write(outfd, "\n", 1)) {}; - - if (infd != STDIN_FILENO) - close(infd); - return failed; -} - -static int crypt_get_key_tty(const char *prompt, - char **key, size_t *key_size, - int timeout, int verify, - struct crypt_device *cd) -{ - int key_size_max = DEFAULT_PASSPHRASE_SIZE_MAX; - int r = -EINVAL; - char *pass = NULL, *pass_verify = NULL; - - *key = NULL; - *key_size = 0; - - log_dbg("Interactive passphrase entry requested."); - - pass = crypt_safe_alloc(key_size_max + 1); - if (!pass) { - log_err(cd, _("Out of memory while reading passphrase.\n")); - return -ENOMEM; - } - - if (interactive_pass(prompt, pass, key_size_max, timeout)) { - log_err(cd, _("Error reading passphrase from terminal.\n")); - goto out_err; - } - pass[key_size_max] = '\0'; - - if (verify) { - pass_verify = crypt_safe_alloc(key_size_max); - if (!pass_verify) { - log_err(cd, _("Out of memory while reading passphrase.\n")); - r = -ENOMEM; - goto out_err; - } - - if (interactive_pass(_("Verify passphrase: "), - pass_verify, key_size_max, timeout)) { - log_err(cd, _("Error reading passphrase from terminal.\n")); - goto out_err; - } - - if (strncmp(pass, pass_verify, key_size_max)) { - log_err(cd, _("Passphrases do not match.\n")); - r = -EPERM; - goto out_err; - } - } - - *key = pass; - *key_size = strlen(pass); - r = 0; -out_err: - crypt_safe_free(pass_verify); - if (r) - crypt_safe_free(pass); - return r; -} - /* * A simple call to lseek(3) might not be possible for some inputs (e.g. * reading from a pipe), so this function instead reads of up to BUFSIZ bytes @@ -451,39 +318,6 @@ out_err: return r; } - -/* - * Note: --key-file=- is interpreted as a read from a binary file (stdin) - * key_size_max == 0 means detect maximum according to input type (tty/file) - * timeout and verify options only applies to tty input - */ -int crypt_get_key(const char *prompt, - char **key, size_t *key_size, - size_t keyfile_offset, size_t keyfile_size_max, - const char *key_file, int timeout, int verify, - struct crypt_device *cd) -{ - int read_stdin; - - /* Passphrase read from stdin? */ - read_stdin = (!key_file || !strcmp(key_file, "-")) ? 1 : 0; - - if (read_stdin && isatty(STDIN_FILENO)) { - if (keyfile_offset) { - log_err(cd, _("Cannot use offset with terminal input.\n")); - return -EINVAL; - } - return crypt_get_key_tty(prompt, key, key_size, timeout, verify, cd); - } - - if (read_stdin) - log_dbg("STDIN descriptor passphrase entry requested."); - else - log_dbg("File descriptor passphrase entry requested."); - - return crypt_keyfile_read(cd, key_file, key, key_size, keyfile_offset, keyfile_size_max); -} - ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc) { char buf[3] = "xx\0", *endp, *bytes; diff --git a/lib/utils_crypt.h b/lib/utils_crypt.h index 67605368..64520ad9 100644 --- a/lib/utils_crypt.h +++ b/lib/utils_crypt.h @@ -34,13 +34,6 @@ struct crypt_device; int crypt_parse_name_and_mode(const char *s, char *cipher, int *key_nums, char *cipher_mode); -int crypt_get_key(const char *prompt, - char **key, size_t *key_size, - size_t keyfile_offset, size_t keyfile_size_max, - const char *key_file, - int timeout, int verify, - struct crypt_device *cd); - void *crypt_safe_alloc(size_t size); void crypt_safe_free(void *data); void *crypt_safe_realloc(void *data, size_t size); diff --git a/src/Makefile.am b/src/Makefile.am index 13df26aa..a16cfd98 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -74,6 +74,7 @@ if REENCRYPT cryptsetup_reencrypt_SOURCES = \ $(top_builddir)/lib/utils_crypt.c \ utils_tools.c \ + utils_password.c \ cryptsetup_reencrypt.c \ cryptsetup.h diff --git a/src/cryptsetup_reencrypt.c b/src/cryptsetup_reencrypt.c index be495b9a..7b206978 100644 --- a/src/cryptsetup_reencrypt.c +++ b/src/cryptsetup_reencrypt.c @@ -987,17 +987,13 @@ static int init_passphrase1(struct reenc_ctx *rc, struct crypt_device *cd, retry_count = opt_tries ?: 1; while (retry_count--) { - set_int_handler(0); - r = crypt_get_key(msg, &password, &passwordLen, - 0, 0, NULL /*opt_key_file*/, - 0, 0, cd); + r = tools_get_key(msg, &password, &passwordLen, 0, 0, + NULL /*opt_key_file*/, 0, 0, 0 /*pwquality*/, cd); if (r < 0) return r; if (quit) return -EAGAIN; - /* library uses sigint internally, until it is fixed...*/ - set_int_block(1); if (check) r = crypt_activate_by_passphrase(cd, NULL, slot_to_check, password, passwordLen, 0); @@ -1032,8 +1028,8 @@ static int init_keyfile(struct reenc_ctx *rc, struct crypt_device *cd, int slot_ int r; size_t passwordLen; - r = crypt_get_key(NULL, &password, &passwordLen, opt_keyfile_offset, - opt_keyfile_size, opt_key_file, 0, 0, cd); + r = tools_get_key(NULL, &password, &passwordLen, opt_keyfile_offset, + opt_keyfile_size, opt_key_file, 0, 0, 0, cd); if (r < 0) return r; diff --git a/src/utils_password.c b/src/utils_password.c index d4200aec..84463b58 100644 --- a/src/utils_password.c +++ b/src/utils_password.c @@ -20,6 +20,7 @@ */ #include "cryptsetup.h" +#include int opt_force_password = 0; @@ -112,6 +113,170 @@ int tools_is_stdin(const char *key_file) return strcmp(key_file, "-") ? 0 : 1; } +/* Password reading helpers */ +static int untimed_read(int fd, char *pass, size_t maxlen) +{ + ssize_t i; + + i = read(fd, pass, maxlen); + if (i > 0) { + pass[i-1] = '\0'; + i = 0; + } else if (i == 0) { /* EOF */ + *pass = 0; + i = -1; + } + return i; +} + +static int timed_read(int fd, char *pass, size_t maxlen, long timeout) +{ + struct timeval t; + fd_set fds = {}; /* Just to avoid scan-build false report for FD_SET */ + int failed = -1; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + t.tv_sec = timeout; + t.tv_usec = 0; + + if (select(fd+1, &fds, NULL, NULL, &t) > 0) + failed = untimed_read(fd, pass, maxlen); + + return failed; +} + +static int interactive_pass(const char *prompt, char *pass, size_t maxlen, + long timeout) +{ + struct termios orig, tmp; + int failed = -1; + int infd, outfd; + + if (maxlen < 1) + return failed; + + /* Read and write to /dev/tty if available */ + infd = open("/dev/tty", O_RDWR); + if (infd == -1) { + infd = STDIN_FILENO; + outfd = STDERR_FILENO; + } else + outfd = infd; + + if (tcgetattr(infd, &orig)) + goto out_err; + + memcpy(&tmp, &orig, sizeof(tmp)); + tmp.c_lflag &= ~ECHO; + + if (prompt && write(outfd, prompt, strlen(prompt)) < 0) + goto out_err; + + tcsetattr(infd, TCSAFLUSH, &tmp); + if (timeout) + failed = timed_read(infd, pass, maxlen, timeout); + else + failed = untimed_read(infd, pass, maxlen); + tcsetattr(infd, TCSAFLUSH, &orig); + +out_err: + if (!failed && write(outfd, "\n", 1)) {}; + + if (infd != STDIN_FILENO) + close(infd); + return failed; +} + +static int crypt_get_key_tty(const char *prompt, + char **key, size_t *key_size, + int timeout, int verify, + struct crypt_device *cd) +{ + int key_size_max = DEFAULT_PASSPHRASE_SIZE_MAX; + int r = -EINVAL; + char *pass = NULL, *pass_verify = NULL; + + *key = NULL; + *key_size = 0; + + log_dbg("Interactive passphrase entry requested."); + + pass = crypt_safe_alloc(key_size_max + 1); + if (!pass) { + log_err( _("Out of memory while reading passphrase.\n")); + return -ENOMEM; + } + + if (interactive_pass(prompt, pass, key_size_max, timeout)) { + log_err(_("Error reading passphrase from terminal.\n")); + goto out_err; + } + pass[key_size_max] = '\0'; + + if (verify) { + pass_verify = crypt_safe_alloc(key_size_max); + if (!pass_verify) { + log_err(_("Out of memory while reading passphrase.\n")); + r = -ENOMEM; + goto out_err; + } + + if (interactive_pass(_("Verify passphrase: "), + pass_verify, key_size_max, timeout)) { + log_err(_("Error reading passphrase from terminal.\n")); + goto out_err; + } + + if (strncmp(pass, pass_verify, key_size_max)) { + log_err(_("Passphrases do not match.\n")); + r = -EPERM; + goto out_err; + } + } + + *key = pass; + *key_size = strlen(pass); + r = 0; +out_err: + crypt_safe_free(pass_verify); + if (r) + crypt_safe_free(pass); + return r; +} + +/* + * Note: --key-file=- is interpreted as a read from a binary file (stdin) + * key_size_max == 0 means detect maximum according to input type (tty/file) + * timeout and verify options only applies to tty input + */ +static int crypt_get_key(const char *prompt, + char **key, size_t *key_size, + size_t keyfile_offset, size_t keyfile_size_max, + const char *key_file, int timeout, int verify, + struct crypt_device *cd) +{ + int read_stdin; + + /* Passphrase read from stdin? */ + read_stdin = (!key_file || !strcmp(key_file, "-")) ? 1 : 0; + + if (read_stdin && isatty(STDIN_FILENO)) { + if (keyfile_offset) { + log_err(_("Cannot use offset with terminal input.\n")); + return -EINVAL; + } + return crypt_get_key_tty(prompt, key, key_size, timeout, verify, cd); + } + + if (read_stdin) + log_dbg("STDIN descriptor passphrase entry requested."); + else + log_dbg("File descriptor passphrase entry requested."); + + return crypt_keyfile_read(cd, key_file, key, key_size, keyfile_offset, keyfile_size_max); +} + int tools_get_key(const char *prompt, char **key, size_t *key_size, size_t keyfile_offset, size_t keyfile_size_max,