Move get_key to common code, simplify verify flags.
authorMilan Broz <gmazyland@gmail.com>
Tue, 26 Oct 2010 22:08:02 +0000 (22:08 +0000)
committerMilan Broz <gmazyland@gmail.com>
Tue, 26 Oct 2010 22:08:02 +0000 (22:08 +0000)
(This code need rewrite anyway).

git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@352 36d66b0a-2a48-0410-832c-cd162a569da5

lib/internal.h
lib/setup.c
lib/utils.c
lib/utils_crypt.c
lib/utils_crypt.h

index e960e10..c7574af 100644 (file)
@@ -18,8 +18,6 @@
 #define DEFAULT_DISK_ALIGNMENT 1048576 /* 1MiB */
 #define DEFAULT_MEM_ALIGNMENT  4096
 
-#define MAX_TTY_PASSWORD_LEN   512
-
 /* private struct crypt_options flags */
 
 #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 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, ...);
 #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)
index 22ace1d..dd137f7 100644 (file)
@@ -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,
                                const char *key_file,
-                               unsigned int flags,
                                int keyIndex)
 {
        struct volume_key *vk;
@@ -174,8 +173,8 @@ static int verify_other_keyslot(struct crypt_device *cd,
        char *password = NULL;
        unsigned int passwordLen;
 
-       get_key(_("Enter any remaining LUKS passphrase: "), &password,
-               &passwordLen, 0, key_file, cd->timeout, flags, cd);
+       crypt_get_key(_("Enter any remaining LUKS passphrase: "), &password,
+                     &passwordLen, 0, key_file, cd->timeout, cd->password_verify, cd);
        if(!password)
                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,
                                      const char *key_file,
-                                     unsigned int flags,
                                      char *message)
 {
        struct volume_key *vk;
@@ -209,8 +207,8 @@ static int find_keyslot_by_passphrase(struct crypt_device *cd,
        unsigned int passwordLen;
        int keyIndex;
 
-       get_key(message,&password,&passwordLen, 0, key_file,
-               cd->timeout, flags, cd);
+       crypt_get_key(message,&password,&passwordLen, 0, key_file,
+                     cd->timeout, cd->password_verify, cd);
        if(!password)
                return -EINVAL;
 
@@ -266,14 +264,14 @@ static int luks_remove_helper(struct crypt_device *cd,
        int r = -EINVAL;
 
        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: "));
                if(key_slot < 0) {
                        r = -EPERM;
                        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);
@@ -298,7 +296,7 @@ static int luks_remove_helper(struct crypt_device *cd,
        }
 
        if(verify)
-               r = verify_other_keyslot(cd, other_key_file, 0, key_slot);
+               r = verify_other_keyslot(cd, other_key_file, key_slot);
        else
                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,
                              unsigned int *key_len, int force_verify)
 {
-       int r, flags = 0;
+       int r;
 
        if (cd->password) {
                *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;
                } else
                        *key_len = r;
-       } else {
-               if (force_verify || cd->password_verify)
-                       flags |= CRYPT_FLAG_VERIFY_IF_POSSIBLE;
-               get_key(msg, key, key_len, 0, NULL, cd->timeout, flags, cd);
-       }
+       } else
+               crypt_get_key(msg, key, key_len, 0, NULL, cd->timeout,
+                             (force_verify || cd->password_verify), cd);
 }
 
 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,
                          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,
@@ -577,8 +573,8 @@ static int crypt_create_and_update_device(struct crypt_options *options, int upd
        if (r)
                return r;
 
-       get_key(_("Enter passphrase: "), &key, &keyLen, options->key_size,
-               options->key_file, cd->timeout, options->flags, cd);
+       crypt_get_key(_("Enter passphrase: "), &key, &keyLen, options->key_size,
+                     options->key_file, cd->timeout, cd->password_verify, cd);
        if (!key)
                r = -ENOENT;
        else
@@ -742,8 +738,8 @@ int crypt_luksFormat(struct crypt_options *options)
                goto out;
        }
 
-       get_key(_("Enter LUKS passphrase: "), &password, &passwordLen, 0,
-               options->new_key_file, options->timeout, options->flags, cd);
+       crypt_get_key(_("Enter LUKS passphrase: "), &password, &passwordLen, 0,
+                     options->new_key_file, cd->timeout, cd->password_verify, cd);
 
        if(!password) {
                r = -EINVAL;
index 8c154ec..eec28ec 100644 (file)
@@ -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;
 }
 
-/* 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 devfd, r = 1;
index e6b2ac5..ee74879 100644 (file)
@@ -85,3 +85,208 @@ void *crypt_safe_realloc(void *data, size_t size)
        crypt_safe_free(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;
+}
index ee8f4cd..7c2bd76 100644 (file)
@@ -4,8 +4,16 @@
 #define MAX_CIPHER_LEN         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);
 
+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_free(void *data);
 void *crypt_safe_realloc(void *data, size_t size);