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;
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.");
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;
}
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)
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,
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);
* 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);
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);
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,