summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--discover/device-handler.c148
-rw-r--r--discover/device-handler.h8
-rw-r--r--discover/discover-server.c18
-rw-r--r--discover/udev.c33
-rw-r--r--test/parser/handler.c6
5 files changed, 206 insertions, 7 deletions
diff --git a/discover/device-handler.c b/discover/device-handler.c
index e75f412..d41bb4b 100644
--- a/discover/device-handler.c
+++ b/discover/device-handler.c
@@ -60,6 +60,13 @@ struct progress_info {
struct list_item list;
};
+struct crypt_info {
+ struct discover_device *source_device;
+ char *dm_name;
+
+ struct list_item list;
+};
+
struct device_handler {
struct discover_server *server;
int dry_run;
@@ -95,6 +102,8 @@ struct device_handler {
struct plugin_option **plugins;
unsigned int n_plugins;
bool plugin_installing;
+
+ struct list crypt_devices;
};
static int mount_device(struct discover_device *dev);
@@ -265,9 +274,30 @@ void device_handler_destroy(struct device_handler *handler)
static int destroy_device(void *arg)
{
struct discover_device *dev = arg;
+ struct process *p;
umount_device(dev);
+ devmapper_destroy_snapshot(dev);
+
+ if (dev->crypt_device) {
+ const char *argv[] = {
+ pb_system_apps.cryptsetup,
+ "luksClose",
+ dev->device->id,
+ NULL
+ };
+
+ p = process_create(dev);
+ p->path = pb_system_apps.cryptsetup;
+ p->argv = argv;
+
+ if (process_run_async(p)) {
+ pb_log("Failed to run cryptsetup\n");
+ return -1;
+ }
+ }
+
return 0;
}
@@ -376,6 +406,7 @@ struct device_handler *device_handler_init(struct discover_server *server,
list_init(&handler->unresolved_boot_options);
list_init(&handler->progress);
+ list_init(&handler->crypt_devices);
/* set up our mount point base */
pb_mkdir_recursive(mount_base());
@@ -399,6 +430,7 @@ struct device_handler *device_handler_init(struct discover_server *server,
void device_handler_reinit(struct device_handler *handler)
{
struct discover_boot_option *opt, *tmp;
+ struct crypt_info *crypt, *c;
struct ramdisk_device *ramdisk;
struct config *config;
unsigned int i;
@@ -449,6 +481,11 @@ void device_handler_reinit(struct device_handler *handler)
discover_server_notify_plugins_remove(handler->server);
+ /* forget encrypted devices */
+ list_for_each_entry_safe(&handler->crypt_devices, crypt, c, list)
+ talloc_free(crypt);
+ list_init(&handler->crypt_devices);
+
set_env_variables(config_get());
/* If the safe mode warning was active disable it now */
@@ -1230,6 +1267,116 @@ void device_handler_release_ramdisk(struct discover_device *device)
device->ramdisk = NULL;
}
+/*
+ * Check if a device name matches the name of an encrypted device that has been
+ * opened. If it matches remove it from the list and remove the original crypt
+ * discover device.
+ */
+bool device_handler_found_crypt_device(struct device_handler *handler,
+ const char *name)
+{
+ struct crypt_info *crypt, *c;
+
+ list_for_each_entry_safe(&handler->crypt_devices, crypt, c, list) {
+ if (!strncmp(crypt->dm_name, name, strlen(crypt->dm_name))) {
+ device_handler_remove(handler, crypt->source_device);
+ list_remove(&crypt->list);
+ talloc_free(crypt);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void cryptsetup_cb(struct process *process)
+{
+ struct device_handler *handler = process->data;
+ struct crypt_info *crypt, *c;
+
+ if (process->exit_status == 0)
+ return;
+ device_handler_status_err(handler,
+ _("Failed to open encrypted device %s"),
+ process->argv[2]);
+
+ /*
+ * Failed to open the device; stop tracking it, but don't remove
+ * the source device.
+ */
+ list_for_each_entry_safe(&handler->crypt_devices, crypt, c, list) {
+ if (!strncmp(crypt->dm_name, process->argv[3],
+ strlen(crypt->dm_name))) {
+ list_remove(&crypt->list);
+ talloc_free(crypt);
+ break;
+ }
+ }
+}
+
+void device_handler_open_encrypted_dev(struct device_handler *handler,
+ char *password, char *device_id)
+{
+ struct discover_device *dev;
+ struct crypt_info *crypt;
+ const char *device_path, **argv;
+ struct process *p;
+ char *name;
+ int result;
+
+ dev = device_lookup_by_id(handler, device_id);
+ if (!dev) {
+ pb_log_fn("Can't find device %s\n", device_id);
+ device_handler_status_err(handler,
+ _("Encrypted device %s does not exist"),
+ device_id);
+ return;
+ }
+
+ device_path = dev->device_path;
+ name = talloc_asprintf(handler, "luks_%s", device_id);
+
+ p = process_create(handler);
+ /* talloc argv under the process so we can access it in cryptsetup_cb */
+ argv = talloc_zero_array(p, const char *, 6);
+ argv[0] = talloc_strdup(argv, pb_system_apps.cryptsetup);
+ argv[1] = talloc_asprintf(argv, "luksOpen");
+ argv[2] = talloc_strdup(argv, device_path);
+ argv[3] = talloc_strdup(argv, name);
+ argv[4] = talloc_asprintf(argv, "-");
+ argv[5] = NULL;
+
+ p->path = pb_system_apps.cryptsetup;
+ p->argv = (const char **)argv;
+ p->exit_cb = cryptsetup_cb;
+ p->data = handler;
+ p->keep_stdout = true;
+ p->pipe_stdin = talloc_asprintf(p, "%s\n", password);
+
+ result = process_run_async(p);
+ if (result) {
+ pb_log("Failed to run cryptsetup\n");
+ return;
+ }
+
+ crypt = talloc(handler, struct crypt_info);
+ crypt->source_device = dev;
+ crypt->dm_name = name;
+ talloc_steal(crypt, name);
+ list_add(&handler->crypt_devices, &crypt->list);
+}
+
+void device_handler_add_encrypted_dev(struct device_handler *handler,
+ struct discover_device *dev)
+{
+ system_info_register_blockdev(dev->device->id, dev->uuid, "");
+ discover_server_notify_device_add(handler->server,
+ dev->device);
+ dev->notified = true;
+ if (!device_lookup_by_uuid(handler, dev->uuid))
+ device_handler_add_device(handler, dev);
+}
+
/* Start discovery on a hotplugged device. The device will be in our devices
* array, but has only just been initialised by the hotplug source.
*/
@@ -2121,7 +2268,6 @@ static int umount_device(struct discover_device *dev)
return -1;
dev->mounted = false;
- devmapper_destroy_snapshot(dev);
pb_rmdir_recursive(mount_base(), dev->mount_path);
diff --git a/discover/device-handler.h b/discover/device-handler.h
index 9619a2d..6591120 100644
--- a/discover/device-handler.h
+++ b/discover/device-handler.h
@@ -33,6 +33,7 @@ struct discover_device {
bool mounted;
bool mounted_rw;
bool unmount;
+ bool crypt_device;
bool notified;
@@ -89,6 +90,9 @@ const struct plugin_option *device_handler_get_plugin(
struct network *device_handler_get_network(
const struct device_handler *handler);
+bool device_handler_found_crypt_device(struct device_handler *handler,
+ const char *name);
+
struct discover_device *discover_device_create(struct device_handler *handler,
const char *uuid, const char *id);
void device_handler_add_device(struct device_handler *handler,
@@ -98,6 +102,10 @@ void device_handler_add_ramdisk(struct device_handler *handler,
struct ramdisk_device *device_handler_get_ramdisk(
struct device_handler *handler);
void device_handler_release_ramdisk(struct discover_device *device);
+void device_handler_open_encrypted_dev(struct device_handler *handler,
+ char *password, char *device_id);
+void device_handler_add_encrypted_dev(struct device_handler *handler,
+ struct discover_device *dev);
int device_handler_discover(struct device_handler *handler,
struct discover_device *dev);
int device_handler_dhcp(struct device_handler *handler,
diff --git a/discover/discover-server.c b/discover/discover-server.c
index 23d6113..1a332cb 100644
--- a/discover/discover-server.c
+++ b/discover/discover-server.c
@@ -365,13 +365,29 @@ static int discover_server_handle_auth_message(struct client *client,
_("Password updated successfully"));
}
break;
+ case AUTH_MSG_DECRYPT:
+ if (!client->can_modify) {
+ pb_log("Unauthenticated client tried to open encrypted device %s\n",
+ auth_msg->decrypt_dev.device_id);
+ rc = -1;
+ status->type = STATUS_ERROR;
+ status->message = talloc_asprintf(status,
+ _("Must authenticate before opening encrypted device"));
+ break;
+ }
+
+ device_handler_open_encrypted_dev(client->server->device_handler,
+ auth_msg->decrypt_dev.password,
+ auth_msg->decrypt_dev.device_id);
+ break;
default:
pb_log("%s: unknown op\n", __func__);
rc = -1;
break;
}
- write_boot_status_message(client->server, client, status);
+ if (status->message)
+ write_boot_status_message(client->server, client, status);
talloc_free(status);
return rc;
diff --git a/discover/udev.c b/discover/udev.c
index fa5d4b4..0c3da66 100644
--- a/discover/udev.c
+++ b/discover/udev.c
@@ -106,7 +106,7 @@ static int udev_handle_block_add(struct pb_udev *udev, struct udev_device *dev,
"swap",
NULL,
};
- bool cdrom, usb;
+ bool cdrom, usb, luks = false;
typestr = udev_device_get_devtype(dev);
if (!typestr) {
@@ -142,11 +142,18 @@ static int udev_handle_block_add(struct pb_udev *udev, struct udev_device *dev,
}
}
- /* Ignore any device mapper devices that aren't logical volumes */
+ /*
+ * Ignore any device mapper devices that aren't logical volumes or
+ * opened encrypted devices
+ */
devname = udev_device_get_property_value(dev, "DM_NAME");
- if (devname && ! udev_device_get_property_value(dev, "DM_LV_NAME")) {
- pb_debug("SKIP: dm-device %s\n", devname);
- return 0;
+ if (devname) {
+ if (device_handler_found_crypt_device(udev->handler, devname)) {
+ luks = true;
+ } else if (!udev_device_get_property_value(dev, "DM_LV_NAME")) {
+ pb_debug("SKIP: dm-device %s\n", devname);
+ return 0;
+ }
}
type = udev_device_get_property_value(dev, "ID_FS_TYPE");
@@ -216,16 +223,32 @@ static int udev_handle_block_add(struct pb_udev *udev, struct udev_device *dev,
usb = !!udev_device_get_property_value(dev, "ID_USB_DRIVER");
if (cdrom)
ddev->device->type = DEVICE_TYPE_OPTICAL;
+ else if (strncmp(type, "crypto_LUKS", strlen("crypto_LUKS")) == 0)
+ ddev->device->type = DEVICE_TYPE_LUKS;
else
ddev->device->type = usb ? DEVICE_TYPE_USB : DEVICE_TYPE_DISK;
udev_setup_device_params(dev, ddev);
+ /*
+ * Don't perform discovery on encrypted devices, just register and
+ * notify clients.
+ */
+ if (ddev->device->type == DEVICE_TYPE_LUKS) {
+ pb_log("Notifying clients about encrypted device %s\n",
+ name);
+ device_handler_add_encrypted_dev(udev->handler, ddev);
+ return 0;
+ }
+
/* Create a snapshot for all disk devices */
if ((ddev->device->type == DEVICE_TYPE_DISK ||
ddev->device->type == DEVICE_TYPE_USB))
devmapper_init_snapshot(udev->handler, ddev);
+ /* Note if this is an opened LUKS device */
+ ddev->crypt_device = luks;
+
device_handler_discover(udev->handler, ddev);
return 0;
diff --git a/test/parser/handler.c b/test/parser/handler.c
index a9856b4..1589570 100644
--- a/test/parser/handler.c
+++ b/test/parser/handler.c
@@ -116,3 +116,9 @@ void discover_server_notify_plugins_remove(struct discover_server *server)
{
(void)server;
}
+
+int devmapper_destroy_snapshot(struct discover_device *device)
+{
+ (void)device;
+ return 0;
+}
OpenPOWER on IntegriCloud