#include <stdint.h>
#include <stdarg.h>
#include <unistd.h>
+#include <inttypes.h>
#include <libintl.h>
#include <locale.h>
#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;
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);
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, ...);
#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"
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;
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
return -EINVAL;
}
- if (get_device_infos(options->device, &infos) < 0)
+ if (get_device_infos(options->device, &infos, cd) < 0)
return -ENOTBLK;
if (!options->size) {
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;
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;
}
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;
}
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) {
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;
}
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;
}
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;
&passwordLen,
0,
options->key_file,
- options->passphrase_fd,
options->timeout,
options->flags & ~(CRYPT_FLAG_VERIFY | CRYPT_FLAG_VERIFY_IF_POSSIBLE), cd);
&passwordLen,
0,
options->new_key_file,
- options->passphrase_fd,
options->timeout,
options->flags, cd);
if(!password) {
* 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;
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) {
*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 */