summaryrefslogtreecommitdiffstats
path: root/src/home/homework-luks.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-10-26 11:07:04 +0200
committerLennart Poettering <lennart@poettering.net>2021-10-28 08:17:46 +0200
commita23cf7f4c767cd2825ea2384f3d9faea85e2b316 (patch)
treedb0b1f4c6c847ffca8659a47a0c78b0989be8f78 /src/home/homework-luks.c
parenthomework: move all LoopDevice handling into HomeSetup too (diff)
downloadsystemd-a23cf7f4c767cd2825ea2384f3d9faea85e2b316.tar.xz
systemd-a23cf7f4c767cd2825ea2384f3d9faea85e2b316.zip
homework: unify similar code for opening existing LUKS DM devices
Let's introduce a new helper acquire_open_luks_device() that combines a few steps we keep doing at three places into one.
Diffstat (limited to '')
-rw-r--r--src/home/homework-luks.c159
1 files changed, 80 insertions, 79 deletions
diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c
index 8e0ddd7739..f30acb0c1c 100644
--- a/src/home/homework-luks.c
+++ b/src/home/homework-luks.c
@@ -384,39 +384,88 @@ static int luks_setup(
return 0;
}
+static int make_dm_names(UserRecord *h, HomeSetup *setup) {
+ assert(h);
+ assert(h->user_name);
+ assert(setup);
+
+ if (!setup->dm_name) {
+ setup->dm_name = strjoin("home-", h->user_name);
+ if (!setup->dm_name)
+ return log_oom();
+ }
+
+ if (!setup->dm_node) {
+ setup->dm_node = path_join("/dev/mapper/", setup->dm_name);
+ if (!setup->dm_node)
+ return log_oom();
+ }
+
+ return 0;
+}
+
+static int acquire_open_luks_device(
+ UserRecord *h,
+ HomeSetup *setup,
+ bool graceful) {
+
+ _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
+ int r;
+
+ assert(h);
+ assert(setup);
+ assert(!setup->crypt_device);
+
+ r = dlopen_cryptsetup();
+ if (r < 0)
+ return r;
+
+ r = make_dm_names(h, setup);
+ if (r < 0)
+ return r;
+
+ r = sym_crypt_init_by_name(&cd, setup->dm_name);
+ if (IN_SET(r, -ENODEV, -EINVAL, -ENOENT) && graceful)
+ return 0;
+ if (r < 0)
+ return log_error_errno(r, "Failed to initialize cryptsetup context for %s: %m", setup->dm_name);
+
+ cryptsetup_enable_logging(cd);
+
+ setup->crypt_device = TAKE_PTR(cd);
+ return 1;
+}
+
static int luks_open(
- const char *dm_name,
- char **passwords,
+ UserRecord *h,
+ HomeSetup *setup,
const PasswordCache *cache,
- struct crypt_device **ret,
sd_id128_t *ret_found_uuid,
void **ret_volume_key,
size_t *ret_volume_key_size) {
- _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
_cleanup_(erase_and_freep) void *vk = NULL;
sd_id128_t p;
char **list;
size_t vks;
int r;
- assert(dm_name);
- assert(ret);
+ assert(h);
+ assert(setup);
+ assert(!setup->crypt_device);
/* Opens a LUKS device that is already set up. Re-validates the password while doing so (which also
* provides us with the volume key, which we want). */
- r = sym_crypt_init_by_name(&cd, dm_name);
+ r = acquire_open_luks_device(h, setup, /* graceful= */ false);
if (r < 0)
- return log_error_errno(r, "Failed to initialize cryptsetup context for %s: %m", dm_name);
-
- cryptsetup_enable_logging(cd);
+ return r;
- r = sym_crypt_load(cd, CRYPT_LUKS2, NULL);
+ r = sym_crypt_load(setup->crypt_device, CRYPT_LUKS2, NULL);
if (r < 0)
return log_error_errno(r, "Failed to load LUKS superblock: %m");
- r = sym_crypt_get_volume_key_size(cd);
+ r = sym_crypt_get_volume_key_size(setup->crypt_device);
if (r <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine LUKS volume key size");
vks = (size_t) r;
@@ -424,7 +473,7 @@ static int luks_open(
if (ret_found_uuid) {
const char *s;
- s = sym_crypt_get_uuid(cd);
+ s = sym_crypt_get_uuid(setup->crypt_device);
if (!s)
return log_error_errno(SYNTHETIC_ERRNO(EMEDIUMTYPE), "LUKS superblock has no UUID.");
@@ -441,8 +490,8 @@ static int luks_open(
FOREACH_POINTER(list,
cache ? cache->pkcs11_passwords : NULL,
cache ? cache->fido2_passwords : NULL,
- passwords) {
- r = luks_try_passwords(cd, list, vk, &vks);
+ h->password) {
+ r = luks_try_passwords(setup->crypt_device, list, vk, &vks);
if (r != -ENOKEY)
break;
}
@@ -451,18 +500,16 @@ static int luks_open(
if (r < 0)
return log_error_errno(r, "Failed to unlocks LUKS superblock: %m");
- log_info("Discovered used LUKS device /dev/mapper/%s, and validated password.", dm_name);
+ log_info("Discovered used LUKS device /dev/mapper/%s, and validated password.", setup->dm_name);
/* This is needed so that crypt_resize() can operate correctly for pre-existing LUKS devices. We need
* to tell libcryptsetup the volume key explicitly, so that it is in the kernel keyring. */
- r = sym_crypt_activate_by_volume_key(cd, NULL, vk, vks, CRYPT_ACTIVATE_KEYRING_KEY);
+ r = sym_crypt_activate_by_volume_key(setup->crypt_device, NULL, vk, vks, CRYPT_ACTIVATE_KEYRING_KEY);
if (r < 0)
return log_error_errno(r, "Failed to upload volume key again: %m");
log_info("Successfully re-activated LUKS device.");
- *ret = TAKE_PTR(cd);
-
if (ret_found_uuid)
*ret_found_uuid = p;
if (ret_volume_key)
@@ -509,26 +556,6 @@ static int fs_validate(
return 0;
}
-static int make_dm_names(UserRecord *h, HomeSetup *setup) {
- assert(h);
- assert(h->user_name);
- assert(setup);
-
- if (!setup->dm_name) {
- setup->dm_name = strjoin("home-", h->user_name);
- if (!setup->dm_name)
- return log_oom();
- }
-
- if (!setup->dm_node) {
- setup->dm_node = path_join("/dev/mapper/", setup->dm_name);
- if (!setup->dm_node)
- return log_oom();
- }
-
- return 0;
-}
-
static int luks_validate(
int fd,
const char *label,
@@ -1171,10 +1198,9 @@ int home_setup_luks(
struct loop_info64 info;
const char *n;
- r = luks_open(setup->dm_name,
- h->password,
+ r = luks_open(h,
+ setup,
cache,
- &setup->crypt_device,
&found_luks_uuid,
&volume_key,
&volume_key_size);
@@ -1490,21 +1516,13 @@ int home_deactivate_luks(UserRecord *h, HomeSetup *setup) {
* don't bother about the loopback device because unlike the DM device it doesn't have a fixed
* name. */
- r = dlopen_cryptsetup();
- if (r < 0)
- return r;
-
- r = make_dm_names(h, setup);
+ r = acquire_open_luks_device(h, setup, /* graceful= */ true);
if (r < 0)
- return r;
-
- r = sym_crypt_init_by_name(&setup->crypt_device, setup->dm_name);
- if (IN_SET(r, -ENODEV, -EINVAL, -ENOENT)) {
- log_debug_errno(r, "LUKS device %s has already been detached.", setup->dm_name);
- we_detached = false;
- } else if (r < 0)
return log_error_errno(r, "Failed to initialize cryptsetup context for %s: %m", setup->dm_name);
- else {
+ if (r == 0) {
+ log_debug("LUKS device %s has already been detached.", setup->dm_name);
+ we_detached = false;
+ } else {
log_info("Discovered used LUKS device %s.", setup->dm_node);
cryptsetup_enable_logging(setup->crypt_device);
@@ -3136,25 +3154,17 @@ int home_lock_luks(UserRecord *h, HomeSetup *setup) {
assert(setup->root_fd < 0);
assert(!setup->crypt_device);
- assert_se(p = user_record_home_directory(h));
- setup->root_fd = open(p, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW);
- if (setup->root_fd < 0)
- return log_error_errno(errno, "Failed to open home directory: %m");
-
- r = make_dm_names(h, setup);
+ r = acquire_open_luks_device(h, setup, /* graceful= */ false);
if (r < 0)
return r;
- r = dlopen_cryptsetup();
- if (r < 0)
- return r;
+ log_info("Discovered used LUKS device %s.", setup->dm_node);
- r = sym_crypt_init_by_name(&setup->crypt_device, setup->dm_name);
- if (r < 0)
- return log_error_errno(r, "Failed to initialize cryptsetup context for %s: %m", setup->dm_name);
+ assert_se(p = user_record_home_directory(h));
- log_info("Discovered used LUKS device %s.", setup->dm_node);
- cryptsetup_enable_logging(setup->crypt_device);
+ setup->root_fd = open(p, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW);
+ if (setup->root_fd < 0)
+ return log_error_errno(errno, "Failed to open home directory: %m");
if (syncfs(setup->root_fd) < 0) /* Snake oil, but let's better be safe than sorry */
return log_error_errno(errno, "Failed to synchronize file system %s: %m", p);
@@ -3210,20 +3220,11 @@ int home_unlock_luks(UserRecord *h, HomeSetup *setup, const PasswordCache *cache
assert(setup);
assert(!setup->crypt_device);
- r = make_dm_names(h, setup);
+ r = acquire_open_luks_device(h, setup, /* graceful= */ false);
if (r < 0)
return r;
- r = dlopen_cryptsetup();
- if (r < 0)
- return r;
-
- r = sym_crypt_init_by_name(&setup->crypt_device, setup->dm_name);
- if (r < 0)
- return log_error_errno(r, "Failed to initialize cryptsetup context for %s: %m", setup->dm_name);
-
log_info("Discovered used LUKS device %s.", setup->dm_node);
- cryptsetup_enable_logging(setup->crypt_device);
r = -ENOKEY;
FOREACH_POINTER(list,