mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-13 20:00:08 +01:00
Move get_key to common code, simplify verify flags.
(This code need rewrite anyway). git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@352 36d66b0a-2a48-0410-832c-cd162a569da5
This commit is contained in:
@@ -18,8 +18,6 @@
|
|||||||
#define DEFAULT_DISK_ALIGNMENT 1048576 /* 1MiB */
|
#define DEFAULT_DISK_ALIGNMENT 1048576 /* 1MiB */
|
||||||
#define DEFAULT_MEM_ALIGNMENT 4096
|
#define DEFAULT_MEM_ALIGNMENT 4096
|
||||||
|
|
||||||
#define MAX_TTY_PASSWORD_LEN 512
|
|
||||||
|
|
||||||
/* private struct crypt_options flags */
|
/* private struct crypt_options flags */
|
||||||
|
|
||||||
#define CRYPT_FLAG_FREE_DEVICE (1 << 24)
|
#define CRYPT_FLAG_FREE_DEVICE (1 << 24)
|
||||||
@@ -105,10 +103,6 @@ int device_ready(struct crypt_device *cd, const char *device, int mode);
|
|||||||
int get_device_infos(const char *device, struct device_infos *infos, struct crypt_device *cd);
|
int get_device_infos(const char *device, struct device_infos *infos, struct crypt_device *cd);
|
||||||
int wipe_device_header(const char *device, int sectors);
|
int wipe_device_header(const char *device, int sectors);
|
||||||
|
|
||||||
void get_key(char *prompt, char **key, unsigned int *passLen, int key_size,
|
|
||||||
const char *key_file, int timeout, int how2verify,
|
|
||||||
struct crypt_device *cd);
|
|
||||||
|
|
||||||
void logger(struct crypt_device *cd, int class, const char *file, int line, const char *format, ...);
|
void logger(struct crypt_device *cd, int class, const char *file, int line, const char *format, ...);
|
||||||
#define log_dbg(x...) logger(NULL, CRYPT_LOG_DEBUG, __FILE__, __LINE__, x)
|
#define log_dbg(x...) logger(NULL, CRYPT_LOG_DEBUG, __FILE__, __LINE__, x)
|
||||||
#define log_std(c, x...) logger(c, CRYPT_LOG_NORMAL, __FILE__, __LINE__, x)
|
#define log_std(c, x...) logger(c, CRYPT_LOG_NORMAL, __FILE__, __LINE__, x)
|
||||||
|
|||||||
36
lib/setup.c
36
lib/setup.c
@@ -165,7 +165,6 @@ static int keyslot_verify_or_find_empty(struct crypt_device *cd, int *keyslot)
|
|||||||
|
|
||||||
static int verify_other_keyslot(struct crypt_device *cd,
|
static int verify_other_keyslot(struct crypt_device *cd,
|
||||||
const char *key_file,
|
const char *key_file,
|
||||||
unsigned int flags,
|
|
||||||
int keyIndex)
|
int keyIndex)
|
||||||
{
|
{
|
||||||
struct volume_key *vk;
|
struct volume_key *vk;
|
||||||
@@ -174,8 +173,8 @@ static int verify_other_keyslot(struct crypt_device *cd,
|
|||||||
char *password = NULL;
|
char *password = NULL;
|
||||||
unsigned int passwordLen;
|
unsigned int passwordLen;
|
||||||
|
|
||||||
get_key(_("Enter any remaining LUKS passphrase: "), &password,
|
crypt_get_key(_("Enter any remaining LUKS passphrase: "), &password,
|
||||||
&passwordLen, 0, key_file, cd->timeout, flags, cd);
|
&passwordLen, 0, key_file, cd->timeout, cd->password_verify, cd);
|
||||||
if(!password)
|
if(!password)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@@ -201,7 +200,6 @@ static int verify_other_keyslot(struct crypt_device *cd,
|
|||||||
|
|
||||||
static int find_keyslot_by_passphrase(struct crypt_device *cd,
|
static int find_keyslot_by_passphrase(struct crypt_device *cd,
|
||||||
const char *key_file,
|
const char *key_file,
|
||||||
unsigned int flags,
|
|
||||||
char *message)
|
char *message)
|
||||||
{
|
{
|
||||||
struct volume_key *vk;
|
struct volume_key *vk;
|
||||||
@@ -209,8 +207,8 @@ static int find_keyslot_by_passphrase(struct crypt_device *cd,
|
|||||||
unsigned int passwordLen;
|
unsigned int passwordLen;
|
||||||
int keyIndex;
|
int keyIndex;
|
||||||
|
|
||||||
get_key(message,&password,&passwordLen, 0, key_file,
|
crypt_get_key(message,&password,&passwordLen, 0, key_file,
|
||||||
cd->timeout, flags, cd);
|
cd->timeout, cd->password_verify, cd);
|
||||||
if(!password)
|
if(!password)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@@ -266,14 +264,14 @@ static int luks_remove_helper(struct crypt_device *cd,
|
|||||||
int r = -EINVAL;
|
int r = -EINVAL;
|
||||||
|
|
||||||
if (key_slot == CRYPT_ANY_SLOT) {
|
if (key_slot == CRYPT_ANY_SLOT) {
|
||||||
key_slot = find_keyslot_by_passphrase(cd, key_file, 0,
|
key_slot = find_keyslot_by_passphrase(cd, key_file,
|
||||||
_("Enter LUKS passphrase to be deleted: "));
|
_("Enter LUKS passphrase to be deleted: "));
|
||||||
if(key_slot < 0) {
|
if(key_slot < 0) {
|
||||||
r = -EPERM;
|
r = -EPERM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_std(cd, _("key slot %d selected for deletion.\n"), key_slot);
|
log_std(cd, _("Key slot %d selected for deletion.\n"), key_slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
ki = crypt_keyslot_status(cd, key_slot);
|
ki = crypt_keyslot_status(cd, key_slot);
|
||||||
@@ -298,7 +296,7 @@ static int luks_remove_helper(struct crypt_device *cd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(verify)
|
if(verify)
|
||||||
r = verify_other_keyslot(cd, other_key_file, 0, key_slot);
|
r = verify_other_keyslot(cd, other_key_file, key_slot);
|
||||||
else
|
else
|
||||||
r = 0;
|
r = 0;
|
||||||
|
|
||||||
@@ -422,7 +420,7 @@ int crypt_confirm(struct crypt_device *cd, const char *msg)
|
|||||||
static void key_from_terminal(struct crypt_device *cd, char *msg, char **key,
|
static void key_from_terminal(struct crypt_device *cd, char *msg, char **key,
|
||||||
unsigned int *key_len, int force_verify)
|
unsigned int *key_len, int force_verify)
|
||||||
{
|
{
|
||||||
int r, flags = 0;
|
int r;
|
||||||
|
|
||||||
if (cd->password) {
|
if (cd->password) {
|
||||||
*key = crypt_safe_alloc(MAX_TTY_PASSWORD_LEN);
|
*key = crypt_safe_alloc(MAX_TTY_PASSWORD_LEN);
|
||||||
@@ -434,11 +432,9 @@ static void key_from_terminal(struct crypt_device *cd, char *msg, char **key,
|
|||||||
*key = NULL;
|
*key = NULL;
|
||||||
} else
|
} else
|
||||||
*key_len = r;
|
*key_len = r;
|
||||||
} else {
|
} else
|
||||||
if (force_verify || cd->password_verify)
|
crypt_get_key(msg, key, key_len, 0, NULL, cd->timeout,
|
||||||
flags |= CRYPT_FLAG_VERIFY_IF_POSSIBLE;
|
(force_verify || cd->password_verify), cd);
|
||||||
get_key(msg, key, key_len, 0, NULL, cd->timeout, flags, cd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int volume_key_by_terminal_passphrase(struct crypt_device *cd, int keyslot,
|
static int volume_key_by_terminal_passphrase(struct crypt_device *cd, int keyslot,
|
||||||
@@ -484,7 +480,7 @@ static void key_from_file(struct crypt_device *cd, char *msg,
|
|||||||
char **key, unsigned int *key_len,
|
char **key, unsigned int *key_len,
|
||||||
const char *key_file, size_t key_size)
|
const char *key_file, size_t key_size)
|
||||||
{
|
{
|
||||||
get_key(msg, key, key_len, key_size, key_file, cd->timeout, 0, cd);
|
crypt_get_key(msg, key, key_len, key_size, key_file, cd->timeout, 0, cd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _crypt_init(struct crypt_device **cd,
|
static int _crypt_init(struct crypt_device **cd,
|
||||||
@@ -577,8 +573,8 @@ static int crypt_create_and_update_device(struct crypt_options *options, int upd
|
|||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
get_key(_("Enter passphrase: "), &key, &keyLen, options->key_size,
|
crypt_get_key(_("Enter passphrase: "), &key, &keyLen, options->key_size,
|
||||||
options->key_file, cd->timeout, options->flags, cd);
|
options->key_file, cd->timeout, cd->password_verify, cd);
|
||||||
if (!key)
|
if (!key)
|
||||||
r = -ENOENT;
|
r = -ENOENT;
|
||||||
else
|
else
|
||||||
@@ -742,8 +738,8 @@ int crypt_luksFormat(struct crypt_options *options)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_key(_("Enter LUKS passphrase: "), &password, &passwordLen, 0,
|
crypt_get_key(_("Enter LUKS passphrase: "), &password, &passwordLen, 0,
|
||||||
options->new_key_file, options->timeout, options->flags, cd);
|
options->new_key_file, cd->timeout, cd->password_verify, cd);
|
||||||
|
|
||||||
if(!password) {
|
if(!password) {
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
|
|||||||
208
lib/utils.c
208
lib/utils.c
@@ -237,214 +237,6 @@ ssize_t write_lseek_blockwise(int fd, const char *buf, size_t count, off_t offse
|
|||||||
return write_blockwise(fd, buf, count) + innerCount;
|
return write_blockwise(fd, buf, count) + innerCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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;
|
|
||||||
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 = STDIN_FILENO, outfd;
|
|
||||||
|
|
||||||
if (maxlen < 1)
|
|
||||||
goto out_err;
|
|
||||||
|
|
||||||
/* Read and write to /dev/tty if available */
|
|
||||||
if ((infd = outfd = open("/dev/tty", O_RDWR)) == -1) {
|
|
||||||
infd = STDIN_FILENO;
|
|
||||||
outfd = STDERR_FILENO;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tcgetattr(infd, &orig))
|
|
||||||
goto out_err;
|
|
||||||
|
|
||||||
memcpy(&tmp, &orig, sizeof(tmp));
|
|
||||||
tmp.c_lflag &= ~ECHO;
|
|
||||||
|
|
||||||
if (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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Password reading behaviour matrix of get_key
|
|
||||||
* FIXME: rewrite this from scratch.
|
|
||||||
* p v n h
|
|
||||||
* -----------------+---+---+---+---
|
|
||||||
* interactive | Y | Y | Y | Inf
|
|
||||||
* from fd | N | N | Y | Inf
|
|
||||||
* from binary file | N | N | N | Inf or options->key_size
|
|
||||||
*
|
|
||||||
* Legend: p..prompt, v..can verify, n..newline-stop, h..read horizon
|
|
||||||
*
|
|
||||||
* Note: --key-file=- is interpreted as a read from a binary file (stdin)
|
|
||||||
*/
|
|
||||||
|
|
||||||
void get_key(char *prompt, char **key, unsigned int *passLen, int key_size,
|
|
||||||
const char *key_file, int timeout, int how2verify,
|
|
||||||
struct crypt_device *cd)
|
|
||||||
{
|
|
||||||
int fd = -1;
|
|
||||||
const int verify = how2verify & CRYPT_FLAG_VERIFY;
|
|
||||||
const int verify_if_possible = how2verify & CRYPT_FLAG_VERIFY_IF_POSSIBLE;
|
|
||||||
char *pass = NULL;
|
|
||||||
int read_horizon;
|
|
||||||
int regular_file = 0;
|
|
||||||
int read_stdin;
|
|
||||||
int r;
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
/* Passphrase read from stdin? */
|
|
||||||
read_stdin = (!key_file || !strcmp(key_file, "-")) ? 1 : 0;
|
|
||||||
|
|
||||||
/* read_horizon applies only for real keyfile, not stdin or terminal */
|
|
||||||
read_horizon = (key_file && !read_stdin) ? key_size : 0 /* until EOF */;
|
|
||||||
|
|
||||||
/* Setup file descriptior */
|
|
||||||
fd = read_stdin ? STDIN_FILENO : open(key_file, O_RDONLY);
|
|
||||||
if (fd < 0) {
|
|
||||||
log_err(cd, _("Failed to open key file %s.\n"), key_file ?: "-");
|
|
||||||
goto out_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Interactive case */
|
|
||||||
if(isatty(fd)) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
pass = crypt_safe_alloc(MAX_TTY_PASSWORD_LEN);
|
|
||||||
if (!pass || (i = interactive_pass(prompt, pass, MAX_TTY_PASSWORD_LEN, timeout))) {
|
|
||||||
log_err(cd, _("Error reading passphrase from terminal.\n"));
|
|
||||||
goto out_err;
|
|
||||||
}
|
|
||||||
if (verify || verify_if_possible) {
|
|
||||||
char pass_verify[MAX_TTY_PASSWORD_LEN];
|
|
||||||
i = interactive_pass(_("Verify passphrase: "), pass_verify, sizeof(pass_verify), timeout);
|
|
||||||
if (i || strcmp(pass, pass_verify) != 0) {
|
|
||||||
log_err(cd, _("Passphrases do not match.\n"));
|
|
||||||
goto out_err;
|
|
||||||
}
|
|
||||||
memset(pass_verify, 0, sizeof(pass_verify));
|
|
||||||
}
|
|
||||||
*passLen = strlen(pass);
|
|
||||||
*key = pass;
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* This is either a fd-input or a file, in neither case we can verify the input,
|
|
||||||
* however we don't stop on new lines if it's a binary file.
|
|
||||||
*/
|
|
||||||
int buflen, i;
|
|
||||||
|
|
||||||
if(verify) {
|
|
||||||
log_err(cd, _("Can't do passphrase verification on non-tty inputs.\n"));
|
|
||||||
goto out_err;
|
|
||||||
}
|
|
||||||
/* The following for control loop does an exhausting
|
|
||||||
* read on the key material file, if requested with
|
|
||||||
* key_size == 0, as it's done by LUKS. However, we
|
|
||||||
* should warn the user, if it's a non-regular file,
|
|
||||||
* such as /dev/random, because in this case, the loop
|
|
||||||
* will read forever.
|
|
||||||
*/
|
|
||||||
if(!read_stdin && read_horizon == 0) {
|
|
||||||
if(stat(key_file, &st) < 0) {
|
|
||||||
log_err(cd, _("Failed to stat key file %s.\n"), key_file);
|
|
||||||
goto out_err;
|
|
||||||
}
|
|
||||||
if(!S_ISREG(st.st_mode))
|
|
||||||
log_std(cd, _("Warning: exhausting read requested, but key file %s"
|
|
||||||
" is not a regular file, function might never return.\n"),
|
|
||||||
key_file);
|
|
||||||
else
|
|
||||||
regular_file = 1;
|
|
||||||
}
|
|
||||||
buflen = 0;
|
|
||||||
for(i = 0; read_horizon == 0 || i < read_horizon; i++) {
|
|
||||||
if(i >= buflen - 1) {
|
|
||||||
buflen += 128;
|
|
||||||
pass = crypt_safe_realloc(pass, buflen);
|
|
||||||
if (!pass) {
|
|
||||||
log_err(cd, _("Out of memory while reading passphrase.\n"));
|
|
||||||
goto out_err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r = read(fd, pass + i, 1);
|
|
||||||
if (r < 0) {
|
|
||||||
log_err(cd, _("Error reading passphrase.\n"));
|
|
||||||
goto out_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stop on newline only if not requested read from keyfile */
|
|
||||||
if(r == 0 || (!key_file && pass[i] == '\n'))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* Fail if piped input dies reading nothing */
|
|
||||||
if(!i && !regular_file) {
|
|
||||||
log_dbg("Error reading passphrase.");
|
|
||||||
goto out_err;
|
|
||||||
}
|
|
||||||
pass[i] = 0;
|
|
||||||
*key = pass;
|
|
||||||
*passLen = i;
|
|
||||||
}
|
|
||||||
if(fd != STDIN_FILENO)
|
|
||||||
close(fd);
|
|
||||||
return;
|
|
||||||
|
|
||||||
out_err:
|
|
||||||
if(fd >= 0 && fd != STDIN_FILENO)
|
|
||||||
close(fd);
|
|
||||||
if(pass)
|
|
||||||
crypt_safe_free(pass);
|
|
||||||
*key = NULL;
|
|
||||||
*passLen = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int device_ready(struct crypt_device *cd, const char *device, int mode)
|
int device_ready(struct crypt_device *cd, const char *device, int mode)
|
||||||
{
|
{
|
||||||
int devfd, r = 1;
|
int devfd, r = 1;
|
||||||
|
|||||||
@@ -85,3 +85,208 @@ void *crypt_safe_realloc(void *data, size_t size)
|
|||||||
crypt_safe_free(data);
|
crypt_safe_free(data);
|
||||||
return new_data;
|
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;
|
||||||
|
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 = STDIN_FILENO, outfd;
|
||||||
|
|
||||||
|
if (maxlen < 1)
|
||||||
|
goto out_err;
|
||||||
|
|
||||||
|
/* Read and write to /dev/tty if available */
|
||||||
|
if ((infd = outfd = open("/dev/tty", O_RDWR)) == -1) {
|
||||||
|
infd = STDIN_FILENO;
|
||||||
|
outfd = STDERR_FILENO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tcgetattr(infd, &orig))
|
||||||
|
goto out_err;
|
||||||
|
|
||||||
|
memcpy(&tmp, &orig, sizeof(tmp));
|
||||||
|
tmp.c_lflag &= ~ECHO;
|
||||||
|
|
||||||
|
if (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Password reading behaviour matrix of get_key
|
||||||
|
* FIXME: rewrite this from scratch.
|
||||||
|
* p v n h
|
||||||
|
* -----------------+---+---+---+---
|
||||||
|
* interactive | Y | Y | Y | Inf
|
||||||
|
* from fd | N | N | Y | Inf
|
||||||
|
* from binary file | N | N | N | Inf or options->key_size
|
||||||
|
*
|
||||||
|
* Legend: p..prompt, v..can verify, n..newline-stop, h..read horizon
|
||||||
|
*
|
||||||
|
* Note: --key-file=- is interpreted as a read from a binary file (stdin)
|
||||||
|
*/
|
||||||
|
|
||||||
|
void crypt_get_key(char *prompt, char **key, unsigned int *passLen, int key_size,
|
||||||
|
const char *key_file, int timeout, int verify,
|
||||||
|
struct crypt_device *cd)
|
||||||
|
{
|
||||||
|
int fd = -1;
|
||||||
|
char *pass = NULL;
|
||||||
|
int read_horizon;
|
||||||
|
int regular_file = 0;
|
||||||
|
int read_stdin;
|
||||||
|
int r;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
/* Passphrase read from stdin? */
|
||||||
|
read_stdin = (!key_file || !strcmp(key_file, "-")) ? 1 : 0;
|
||||||
|
|
||||||
|
/* read_horizon applies only for real keyfile, not stdin or terminal */
|
||||||
|
read_horizon = (key_file && !read_stdin) ? key_size : 0 /* until EOF */;
|
||||||
|
|
||||||
|
/* Setup file descriptior */
|
||||||
|
fd = read_stdin ? STDIN_FILENO : open(key_file, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
crypt_log(cd, CRYPT_LOG_ERROR,
|
||||||
|
_("Failed to open key file.\n"));
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interactive case */
|
||||||
|
if(isatty(fd)) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
pass = crypt_safe_alloc(MAX_TTY_PASSWORD_LEN);
|
||||||
|
if (!pass || (i = interactive_pass(prompt, pass, MAX_TTY_PASSWORD_LEN, timeout))) {
|
||||||
|
crypt_log(cd, CRYPT_LOG_ERROR,
|
||||||
|
_("Error reading passphrase from terminal.\n"));
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
if (verify) {
|
||||||
|
char pass_verify[MAX_TTY_PASSWORD_LEN];
|
||||||
|
i = interactive_pass(_("Verify passphrase: "), pass_verify, sizeof(pass_verify), timeout);
|
||||||
|
if (i || strcmp(pass, pass_verify) != 0) {
|
||||||
|
crypt_log(cd, CRYPT_LOG_ERROR,
|
||||||
|
_("Passphrases do not match.\n"));
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
memset(pass_verify, 0, sizeof(pass_verify));
|
||||||
|
}
|
||||||
|
*passLen = strlen(pass);
|
||||||
|
*key = pass;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* This is either a fd-input or a file, in neither case we can verify the input,
|
||||||
|
* however we don't stop on new lines if it's a binary file.
|
||||||
|
*/
|
||||||
|
int buflen, i;
|
||||||
|
|
||||||
|
/* The following for control loop does an exhausting
|
||||||
|
* read on the key material file, if requested with
|
||||||
|
* key_size == 0, as it's done by LUKS. However, we
|
||||||
|
* should warn the user, if it's a non-regular file,
|
||||||
|
* such as /dev/random, because in this case, the loop
|
||||||
|
* will read forever.
|
||||||
|
*/
|
||||||
|
if(!read_stdin && read_horizon == 0) {
|
||||||
|
if(stat(key_file, &st) < 0) {
|
||||||
|
crypt_log(cd, CRYPT_LOG_ERROR,
|
||||||
|
_("Failed to stat key file.\n"));
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
if(!S_ISREG(st.st_mode))
|
||||||
|
crypt_log(cd, CRYPT_LOG_NORMAL,
|
||||||
|
_("Warning: exhausting read requested, but key file"
|
||||||
|
" is not a regular file, function might never return.\n"));
|
||||||
|
else
|
||||||
|
regular_file = 1;
|
||||||
|
}
|
||||||
|
buflen = 0;
|
||||||
|
for(i = 0; read_horizon == 0 || i < read_horizon; i++) {
|
||||||
|
if(i >= buflen - 1) {
|
||||||
|
buflen += 128;
|
||||||
|
pass = crypt_safe_realloc(pass, buflen);
|
||||||
|
if (!pass) {
|
||||||
|
crypt_log(cd, CRYPT_LOG_ERROR,
|
||||||
|
_("Out of memory while reading passphrase.\n"));
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r = read(fd, pass + i, 1);
|
||||||
|
if (r < 0) {
|
||||||
|
crypt_log(cd, CRYPT_LOG_ERROR,
|
||||||
|
_("Error reading passphrase.\n"));
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop on newline only if not requested read from keyfile */
|
||||||
|
if(r == 0 || (!key_file && pass[i] == '\n'))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Fail if piped input dies reading nothing */
|
||||||
|
if(!i && !regular_file)
|
||||||
|
goto out_err;
|
||||||
|
pass[i] = 0;
|
||||||
|
*key = pass;
|
||||||
|
*passLen = i;
|
||||||
|
}
|
||||||
|
if(fd != STDIN_FILENO)
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
|
||||||
|
out_err:
|
||||||
|
if(fd >= 0 && fd != STDIN_FILENO)
|
||||||
|
close(fd);
|
||||||
|
if(pass)
|
||||||
|
crypt_safe_free(pass);
|
||||||
|
*key = NULL;
|
||||||
|
*passLen = 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,8 +4,16 @@
|
|||||||
#define MAX_CIPHER_LEN 32
|
#define MAX_CIPHER_LEN 32
|
||||||
#define MAX_CIPHER_LEN_STR "32"
|
#define MAX_CIPHER_LEN_STR "32"
|
||||||
|
|
||||||
|
#define MAX_TTY_PASSWORD_LEN 512
|
||||||
|
|
||||||
|
struct crypt_device;
|
||||||
|
|
||||||
int crypt_parse_name_and_mode(const char *s, char *cipher, char *cipher_mode);
|
int crypt_parse_name_and_mode(const char *s, char *cipher, char *cipher_mode);
|
||||||
|
|
||||||
|
void crypt_get_key(char *prompt, char **key, unsigned int *passLen, int key_size,
|
||||||
|
const char *key_file, int timeout, int how2verify,
|
||||||
|
struct crypt_device *cd);
|
||||||
|
|
||||||
void *crypt_safe_alloc(size_t size);
|
void *crypt_safe_alloc(size_t size);
|
||||||
void crypt_safe_free(void *data);
|
void crypt_safe_free(void *data);
|
||||||
void *crypt_safe_realloc(void *data, size_t size);
|
void *crypt_safe_realloc(void *data, size_t size);
|
||||||
|
|||||||
Reference in New Issue
Block a user