* Move device utils code and provide context parameter (for log).
authorMilan Broz <gmazyland@gmail.com>
Sun, 30 Aug 2009 18:09:21 +0000 (18:09 +0000)
committerMilan Broz <gmazyland@gmail.com>
Sun, 30 Aug 2009 18:09:21 +0000 (18:09 +0000)
* Keyfile now must be provided by path, only stdin file descriptor is used (api only).
* Do not call isatty() on closed keyfile descriptor.

Signed-off-by: Milan Broz <mbroz@redhat.com>
git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@93 36d66b0a-2a48-0410-832c-cd162a569da5

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

index e12935f..65ed80a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,6 +5,9 @@
        * Add log macros and make logging modre consitent.
        * Move command successful messages to verbose level.
        * Introduce --debug parameter.
+       * Move device utils code and provide context parameter (for log).
+       * Keyfile now must be provided by path, only stdin file descriptor is used (api only).
+       * Do not call isatty() on closed keyfile descriptor.
 
 2009-08-17  Milan Broz  <mbroz@redhat.com>
        * Fix PBKDF2 speed calculation for large passhrases.
index 25163b2..344cd7c 100644 (file)
@@ -8,6 +8,7 @@
 #include <stdint.h>
 #include <stdarg.h>
 #include <unistd.h>
+#include <inttypes.h>
 
 #include <libintl.h>
 #include <locale.h>
@@ -26,6 +27,8 @@
 
 #define CRYPT_FLAG_PRIVATE_MASK ((unsigned int)-1 << 24)
 
+#define at_least_one(a) ({ __typeof__(a) __at_least_one=(a); (__at_least_one)?__at_least_one:1; })
+
 struct hash_type {
        char            *name;
        void            *private;
@@ -39,6 +42,11 @@ struct hash_backend {
        void                    (*free_hashes)(struct hash_type *hashes);
 };
 
+struct device_infos {
+       uint64_t        size;
+       int             readonly;
+};
+
 struct crypt_device;
 
 void set_error_va(const char *fmt, va_list va);
@@ -82,10 +90,15 @@ int sector_size_for_device(const char *device);
 ssize_t write_blockwise(int fd, const void *buf, size_t count);
 ssize_t read_blockwise(int fd, void *_buf, size_t count);
 ssize_t write_lseek_blockwise(int fd, const char *buf, size_t count, off_t offset);
+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);
 
-int get_key(char *prompt, char **key, unsigned int *passLen, int key_size,
-            const char *key_file, int passphrase_fd, int timeout, int how2verify, struct crypt_device *cd);
+int parse_into_name_and_mode(const char *nameAndMode, char *name, char *mode);
 
 void set_default_log(void (*log)(int class, char *msg));
 void logger(struct crypt_device *cd, int class, const char *file, int line, const char *format, ...);
index dc4c2e7..0cf2f0d 100644 (file)
@@ -1,19 +1,11 @@
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
+#include <stdarg.h>
 #include <fcntl.h>
-#include <unistd.h>
 #include <errno.h>
-#include <signal.h>
-#include <assert.h>
 
 #include "libcryptsetup.h"
-#include "internal.h"
-#include "blockdev.h"
 #include "luks.h"
 #include "internal.h"
 
@@ -23,13 +15,6 @@ struct crypt_device {
        void *log_usrptr;
 };
 
-struct device_infos {
-       uint64_t        size;
-       int             readonly;
-};
-
-#define at_least_one(a) ({ __typeof__(a) __at_least_one=(a); (__at_least_one)?__at_least_one:1; })
-
 /* Log helper */
 static void (*_default_log)(int class, char *msg) = NULL;
 static int _debug_level = 0;
@@ -122,107 +107,7 @@ static char *process_key(struct crypt_device *cd,
        return key;
 }
 
-static int get_device_infos(const char *device, struct device_infos *infos)
-{
-       char buf[128];
-       uint64_t size;
-       unsigned long size_small;
-       int readonly = 0;
-       int ret = -1;
-       int fd;
-
-       /* Try to open read-write to check whether it is a read-only device */
-       fd = open(device, O_RDWR);
-       if (fd < 0) {
-               if (errno == EROFS) {
-                       readonly = 1;
-                       fd = open(device, O_RDONLY);
-               }
-       } else {
-               close(fd);
-               fd = open(device, O_RDONLY);
-       }
-       if (fd < 0) {
-               set_error("Error opening device: %s",
-                         strerror_r(errno, buf, 128));
-               return -1;
-       }
-
-#ifdef BLKROGET
-       /* If the device can be opened read-write, i.e. readonly is still 0, then
-        * check whether BKROGET says that it is read-only. E.g. read-only loop
-        * devices may be openend read-write but are read-only according to BLKROGET
-        */
-       if (readonly == 0) {
-               if (ioctl(fd, BLKROGET, &readonly) < 0) {
-                       set_error("BLKROGET failed on device: %s",
-                                 strerror_r(errno, buf, 128));
-                       return -1;
-               }
-       }
-#else
-#error BLKROGET not available
-#endif
-
-#ifdef BLKGETSIZE64
-       if (ioctl(fd, BLKGETSIZE64, &size) >= 0) {
-               size >>= SECTOR_SHIFT;
-               ret = 0;
-               goto out;
-       }
-#endif
-
-#ifdef BLKGETSIZE
-       if (ioctl(fd, BLKGETSIZE, &size_small) >= 0) {
-               size = (uint64_t)size_small;
-               ret = 0;
-               goto out;
-       }
-#else
-#      error Need at least the BLKGETSIZE ioctl!
-#endif
-
-       set_error("BLKGETSIZE ioctl failed on device: %s",
-                 strerror_r(errno, buf, 128));
-
-out:
-       if (ret == 0) {
-               infos->size = size;
-               infos->readonly = readonly;
-       }
-       close(fd);
-       return ret;
-}
-
-static int wipe_device_header(const char *device, int sectors)
-{
-       char *buffer;
-       int size = sectors * SECTOR_SIZE;
-       int r = -1;
-       int devfd;
-
-       devfd = open(device, O_RDWR | O_DIRECT | O_SYNC);
-       if(devfd == -1) {
-               set_error("Can't wipe header on device %s", device);
-               return -EINVAL;
-       }
-
-       buffer = malloc(size);
-       if (!buffer) {
-               close(devfd);
-               return -ENOMEM;
-       }
-       memset(buffer, 0, size);
-
-       r = write_blockwise(devfd, buffer, size) < size ? -EIO : 0;
-
-       free(buffer);
-       close(devfd);
-
-       return r;
-}
-
-static int parse_into_name_and_mode(const char *nameAndMode, char *name, char *mode)
+int parse_into_name_and_mode(const char *nameAndMode, char *name, char *mode)
 {
 /* Token content stringification, see info cpp/stringification */
 #define str(s) #s
@@ -311,7 +196,7 @@ static int create_device_helper(int reload, struct crypt_options *options)
                return -EINVAL;
        }
 
-       if (get_device_infos(options->device, &infos) < 0)
+       if (get_device_infos(options->device, &infos, cd) < 0)
                return -ENOTBLK;
 
        if (!options->size) {
@@ -331,7 +216,7 @@ static int create_device_helper(int reload, struct crypt_options *options)
                options->flags |= CRYPT_FLAG_READONLY;
 
        get_key("Enter passphrase: ", &key, &keyLen, options->key_size,
-               options->key_file, options->passphrase_fd, options->timeout, options->flags, NULL);
+               options->key_file, options->timeout, options->flags, NULL);
        if (!key) {
                log_err(cd, "Key reading error");
                return -ENOENT;
@@ -370,7 +255,7 @@ static int luks_remove_helper(struct crypt_device *cd,
 
        if(supply_it) {
                get_key("Enter LUKS passphrase to be deleted: ",&password,&passwordLen, 0, options->new_key_file,
-                       options->passphrase_fd, options->timeout, options->flags, cd);
+                       options->timeout, options->flags, cd);
                if(!password) {
                        r = -EINVAL; goto out;
                }
@@ -399,7 +284,7 @@ static int luks_remove_helper(struct crypt_device *cd,
        if(options->flags & CRYPT_FLAG_VERIFY_ON_DELKEY) {
                options->flags &= ~CRYPT_FLAG_VERIFY_ON_DELKEY;
                get_key("Enter any remaining LUKS passphrase: ",&password,&passwordLen, 0, options->key_file,
-                       options->passphrase_fd, options->timeout, options->flags, cd);
+                       options->timeout, options->flags, cd);
                if(!password) {
                        r = -EINVAL; goto out;
                }
@@ -462,7 +347,7 @@ int crypt_resize_device(struct crypt_options *options)
        if (r < 0)
                return r;
 
-       if (get_device_infos(device, &infos) < 0)
+       if (get_device_infos(device, &infos, cd) < 0)
                return -EINVAL;
 
        if (!options->size) {
@@ -597,7 +482,7 @@ int crypt_luksFormat(struct crypt_options *options)
        logger(options, CRYPT_LOG_ERROR, "pitr %d\n", header.keyblock[0].passwordIterations);
 #endif
        get_key("Enter LUKS passphrase: ",&password,&passwordLen, 0, options->new_key_file,
-               options->passphrase_fd, options->timeout, options->flags, NULL);
+               options->timeout, options->flags, NULL);
        if(!password) {
                r = -EINVAL; goto out;
        }
@@ -640,7 +525,7 @@ int crypt_luksOpen(struct crypt_options *options)
        if (!LUKS_device_ready(options->device, O_RDONLY | excl))
                return -ENOTBLK;
 
-       if (get_device_infos(options->device, &infos) < 0) {
+       if (get_device_infos(options->device, &infos, cd) < 0) {
                log_err(cd, "Can't get device information.\n");
                return -ENOTBLK;
        }
@@ -659,11 +544,14 @@ start:
                password = safe_alloc(passwordLen + 1);
                strncpy(password, options->passphrase, passwordLen + 1);
                tries = 0;
-       } else if(get_key(prompt, &password, &passwordLen, options->key_size, options->key_file,
-               options->passphrase_fd, options->timeout, options->flags, cd))
-               tries--;
-       else
-               tries = 0;
+       } else {
+               get_key(prompt, &password, &passwordLen, options->key_size, options->key_file,
+                       options->timeout, options->flags, cd);
+               if (password)
+                       tries--;
+               else
+                       tries = 0;
+       }
 
        if(!password) {
                r = -EINVAL; goto out;
@@ -761,7 +649,6 @@ int crypt_luksAddKey(struct crypt_options *options)
                 &passwordLen, 
                 0,
                 options->key_file, 
-                options->passphrase_fd, 
                 options->timeout, 
                 options->flags & ~(CRYPT_FLAG_VERIFY | CRYPT_FLAG_VERIFY_IF_POSSIBLE), cd);
 
@@ -780,7 +667,6 @@ int crypt_luksAddKey(struct crypt_options *options)
                 &passwordLen,
                 0,
                 options->new_key_file,
-                options->passphrase_fd,
                 options->timeout, 
                 options->flags, cd);
        if(!password) {
index 890e620..119ac0d 100644 (file)
@@ -390,13 +390,11 @@ out_err:
  * 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)
- *
- * Returns true when more keys are available (that is when password
- * reading can be retried as for interactive terminals).
  */
 
-int get_key(char *prompt, char **key, unsigned int *passLen, int key_size,
-            const char *key_file, int passphrase_fd, int timeout, int how2verify, struct crypt_device *cd)
+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;
        const int verify = how2verify & CRYPT_FLAG_VERIFY;
@@ -407,7 +405,7 @@ int get_key(char *prompt, char **key, unsigned int *passLen, int key_size,
 
        if(key_file && !strcmp(key_file, "-")) {
                /* Allow binary reading from stdin */
-               fd = passphrase_fd;
+               fd = STDIN_FILENO;
                newline_stop = 0;
                read_horizon = 0;
        } else if (key_file) {
@@ -496,15 +494,129 @@ int get_key(char *prompt, char **key, unsigned int *passLen, int key_size,
                *key = pass;
                *passLen = i;
        }
-
-       return isatty(fd); /* Return true, when password reading can be tried on interactive fds */
+       return;
 
 out_err:
        if(pass)
                safe_free(pass);
        *key = NULL;
        *passLen = 0;
-       return 0;
+}
+
+int device_ready(struct crypt_device *cd, const char *device, int mode)
+{
+       int devfd;
+       struct stat st;
+
+       if(stat(device, &st) < 0) {
+               log_err(cd, _("Device %s doesn't exist or access denied.\n"), device);
+               return 0;
+       }
+
+       if (!mode)
+               return 1;
+
+       devfd = open(device, mode | O_DIRECT | O_SYNC);
+       if(devfd < 0) {
+               log_err(cd, _("Can't open device %s for %s%s access.\n"), device,
+                       (mode & O_EXCL) ? _("exclusive ") : "",
+                       (mode & O_RDWR) ? _("writable") : _("read-only"));
+               return 0;
+       }
+       close(devfd);
+
+       return 1;
+}
+
+int get_device_infos(const char *device, struct device_infos *infos, struct crypt_device *cd)
+{
+       uint64_t size;
+       unsigned long size_small;
+       int readonly = 0;
+       int ret = -1;
+       int fd;
+
+       /* Try to open read-write to check whether it is a read-only device */
+       fd = open(device, O_RDWR);
+       if (fd < 0) {
+               if (errno == EROFS) {
+                       readonly = 1;
+                       fd = open(device, O_RDONLY);
+               }
+       } else {
+               close(fd);
+               fd = open(device, O_RDONLY);
+       }
+       if (fd < 0) {
+               log_err(cd, _("Cannot open device: %s\n"), device);
+               return -1;
+       }
+
+#ifdef BLKROGET
+       /* If the device can be opened read-write, i.e. readonly is still 0, then
+        * check whether BKROGET says that it is read-only. E.g. read-only loop
+        * devices may be openend read-write but are read-only according to BLKROGET
+        */
+       if (readonly == 0 && ioctl(fd, BLKROGET, &readonly) < 0) {
+               log_err(cd, _("BLKROGET failed on device %s.\n"), device);
+               goto out;
+       }
+#else
+#error BLKROGET not available
+#endif
+
+#ifdef BLKGETSIZE64
+       if (ioctl(fd, BLKGETSIZE64, &size) >= 0) {
+               size >>= SECTOR_SHIFT;
+               ret = 0;
+               goto out;
+       }
+#endif
+
+#ifdef BLKGETSIZE
+       if (ioctl(fd, BLKGETSIZE, &size_small) >= 0) {
+               size = (uint64_t)size_small;
+               ret = 0;
+               goto out;
+       }
+#else
+#      error Need at least the BLKGETSIZE ioctl!
+#endif
+
+       log_err(cd, _("BLKGETSIZE failed on device %s.\n"), device);
+out:
+       if (ret == 0) {
+               infos->size = size;
+               infos->readonly = readonly;
+       }
+       close(fd);
+       return ret;
+}
+
+int wipe_device_header(const char *device, int sectors)
+{
+       char *buffer;
+       int size = sectors * SECTOR_SIZE;
+       int r = -1;
+       int devfd;
+
+       devfd = open(device, O_RDWR | O_DIRECT | O_SYNC);
+       if(devfd == -1)
+               return -EINVAL;
+
+       buffer = malloc(size);
+       if (!buffer) {
+               close(devfd);
+               return -ENOMEM;
+       }
+       memset(buffer, 0, size);
+
+       r = write_blockwise(devfd, buffer, size) < size ? -EIO : 0;
+
+       free(buffer);
+       close(devfd);
+
+       return r;
 }
 
 /* MEMLOCK */