diff --git a/lib/setup.c b/lib/setup.c index 00a38cae..e1be9818 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -368,6 +368,35 @@ static int crypt_uuid_cmp(const char *dm_uuid, const char *hdr_uuid) return 0; } +/* + * compares type of active device to provided string (only if there is no explicit type) + */ +static int crypt_uuid_type_cmp(struct crypt_device *cd, const char *type) +{ + struct crypt_dm_active_device dmd = {}; + int r, len; + + /* Must user header-on-disk if we know type here */ + if (cd->type || !cd->u.none.active_name) + return -EINVAL; + + log_dbg("Checking if active device %s without header has UUID type %s.", + cd->u.none.active_name, type); + + r = dm_query_device(cd, cd->u.none.active_name, DM_ACTIVE_UUID, &dmd); + if (r < 0) + return r; + + r = -ENODEV; + len = strlen(type); + if (dmd.uuid && strlen(dmd.uuid) > len && + !strncmp(dmd.uuid, type, len) && dmd.uuid[len] == '-') + r = 0; + + free(CONST_CAST(void*)dmd.uuid); + return r; +} + int PLAIN_activate(struct crypt_device *cd, const char *name, struct volume_key *vk, @@ -1499,7 +1528,14 @@ int crypt_suspend(struct crypt_device *cd, log_dbg("Suspending volume %s.", name); - r = onlyLUKS(cd); + if (cd->type) { + r = onlyLUKS(cd); + } else { + r = crypt_uuid_type_cmp(cd, CRYPT_LUKS1); + if (r < 0) + log_err(cd, _("This operation is supported only for LUKS device.\n")); + } + if (r < 0) return r; diff --git a/tests/api-test.c b/tests/api-test.c index 53f338c1..7fd85c2f 100644 --- a/tests/api-test.c +++ b/tests/api-test.c @@ -975,8 +975,11 @@ static void SuspendDevice(void) suspend_status = crypt_suspend(cd, CDEVICE_1); if (suspend_status == -ENOTSUP) { printf("WARNING: Suspend/Resume not supported, skipping test.\n"); - goto out; + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + return; } + OK_(suspend_status); FAIL_(crypt_suspend(cd, CDEVICE_1), "already suspended"); @@ -990,10 +993,30 @@ static void SuspendDevice(void) FAIL_(crypt_resume_by_keyfile_offset(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 1, 0), "wrong key"); OK_(crypt_resume_by_keyfile_offset(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0, 0)); FAIL_(crypt_resume_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0), "not suspended"); - _remove_keyfiles(); -out: OK_(crypt_deactivate(cd, CDEVICE_1)); crypt_free(cd); + + /* create LUKS device with detached header */ + OK_(crypt_init(&cd, DEVICE_1)); + OK_(crypt_load(cd, CRYPT_LUKS1, NULL)); + OK_(crypt_set_data_device(cd, DEVICE_2)); + OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0)); + crypt_free(cd); + + /* Should be able to suspend but not resume if not header specified */ + OK_(crypt_init_by_name(&cd, CDEVICE_1)); + OK_(crypt_suspend(cd, CDEVICE_1)); + FAIL_(crypt_suspend(cd, CDEVICE_1), "already suspended"); + FAIL_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)-1), "no header"); + crypt_free(cd); + + OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, DEVICE_1)); + OK_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1))); + + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + + _remove_keyfiles(); } static void AddDeviceLuks(void)