Merge pull request #20969 from poettering/cryptenroll-no-homed

cryptenroll: politely refuse enrolling keys into homed volumes
This commit is contained in:
Yu Watanabe 2021-10-10 16:00:07 +09:00 committed by GitHub
commit b00756030b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 8 deletions

3
TODO
View file

@ -226,9 +226,6 @@ Features:
* introduce a new group to own TPM devices
* cryptenroll: politely refuse enrolling new keys to homed volumes, since we
we cannot update identity info
* cryptsetup: if only recovery keys are registered and no regular passphrases,
ask user for "recovery key", not "passphrase"

View file

@ -381,6 +381,28 @@ static int parse_argv(int argc, char *argv[]) {
return 1;
}
static int check_for_homed(struct crypt_device *cd) {
int r;
assert_se(cd);
/* Politely refuse operating on homed volumes. The enrolled tokens for the user record and the LUKS2
* volume should not get out of sync. */
for (int token = 0; token < crypt_token_max(CRYPT_LUKS2); token ++) {
r = cryptsetup_get_token_as_json(cd, token, "systemd-homed", NULL);
if (IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE))
continue;
if (r < 0)
return log_error_errno(r, "Failed to read JSON token data off disk: %m");
return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN),
"LUKS2 volume is managed by systemd-homed, please use homectl to enroll tokens.");
}
return 0;
}
static int prepare_luks(
struct crypt_device **ret_cd,
void **ret_volume_key,
@ -405,6 +427,10 @@ static int prepare_luks(
if (r < 0)
return log_error_errno(r, "Failed to load LUKS2 superblock: %m");
r = check_for_homed(cd);
if (r < 0)
return r;
if (!ret_volume_key) {
*ret_cd = TAKE_PTR(cd);
return 0;

View file

@ -698,7 +698,7 @@ static int luks_validate_home_record(
assert(cd);
assert(h);
for (int token = 0;; token++) {
for (int token = 0; token < sym_crypt_token_max(CRYPT_LUKS2); token++) {
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *rr = NULL;
_cleanup_(EVP_CIPHER_CTX_freep) EVP_CIPHER_CTX *context = NULL;
_cleanup_(user_record_unrefp) UserRecord *lhr = NULL;
@ -894,7 +894,7 @@ int home_store_header_identity_luks(
_cleanup_(user_record_unrefp) UserRecord *header_home = NULL;
_cleanup_free_ char *text = NULL;
int token = 0, r;
int r;
assert(h);
@ -924,7 +924,7 @@ int home_store_header_identity_luks(
if (r < 0)
return r;
for (;; token++) {
for (int token = 0; token < sym_crypt_token_max(CRYPT_LUKS2); token++) {
crypt_token_info state;
const char *type;
@ -946,7 +946,6 @@ int home_store_header_identity_luks(
/* Now, let's free the text so that for all further matching tokens we all crypt_json_token_set()
* with a NULL text in order to invalidate the tokens. */
text = mfree(text);
token++;
}
if (text)

View file

@ -54,11 +54,12 @@ extern int (*sym_crypt_token_json_set)(struct crypt_device *cd, int token, const
extern int (*sym_crypt_token_max)(const char *type);
#else
/* As a fallback, use the same hard-coded value libcryptsetup uses internally. */
static inline int sym_crypt_token_max(_unused_ const char *type) {
static inline int crypt_token_max(_unused_ const char *type) {
assert(streq(type, CRYPT_LUKS2));
return 32;
}
#define sym_crypt_token_max(type) crypt_token_max(type)
#endif
extern crypt_token_info (*sym_crypt_token_status)(struct crypt_device *cd, int token, const char **type);
extern int (*sym_crypt_volume_key_get)(struct crypt_device *cd, int keyslot, char *volume_key, size_t *volume_key_size, const char *passphrase, size_t passphrase_size);