|
12 | 12 | #include "homework-fscrypt.h" |
13 | 13 | #include "homework-mount.h" |
14 | 14 | #include "homework-quota.h" |
| 15 | +#include "keyring-util.h" |
15 | 16 | #include "memory-util.h" |
16 | 17 | #include "missing_keyctl.h" |
17 | 18 | #include "missing_syscall.h" |
|
29 | 30 | #include "user-util.h" |
30 | 31 | #include "xattr-util.h" |
31 | 32 |
|
| 33 | +static int fscrypt_unlink_key(UserRecord *h) { |
| 34 | + _cleanup_free_ void *keyring = NULL; |
| 35 | + size_t keyring_size = 0, n_keys = 0; |
| 36 | + int r; |
| 37 | + |
| 38 | + assert(h); |
| 39 | + assert(user_record_storage(h) == USER_FSCRYPT); |
| 40 | + |
| 41 | + r = fully_set_uid_gid( |
| 42 | + h->uid, |
| 43 | + user_record_gid(h), |
| 44 | + /* supplementary_gids= */ NULL, |
| 45 | + /* n_supplementary_gids= */ 0); |
| 46 | + if (r < 0) |
| 47 | + return log_error_errno(r, "Failed to change UID/GID to " UID_FMT "/" GID_FMT ": %m", |
| 48 | + h->uid, user_record_gid(h)); |
| 49 | + |
| 50 | + r = keyring_read(KEY_SPEC_USER_KEYRING, &keyring, &keyring_size); |
| 51 | + if (r < 0) |
| 52 | + return log_error_errno(r, "Failed to read the keyring of user " UID_FMT ": %m", h->uid); |
| 53 | + |
| 54 | + n_keys = keyring_size / sizeof(key_serial_t); |
| 55 | + assert(keyring_size % sizeof(key_serial_t) == 0); |
| 56 | + |
| 57 | + /* Find any key with a description starting with 'fscrypt:' and unlink it. We need to iterate as we |
| 58 | + * store the key with a description that uses the hash of the secret key, that we do not have when |
| 59 | + * we are deactivating. */ |
| 60 | + FOREACH_ARRAY(key, ((key_serial_t *) keyring), n_keys) { |
| 61 | + _cleanup_free_ char *description = NULL; |
| 62 | + char *d; |
| 63 | + |
| 64 | + r = keyring_describe(*key, &description); |
| 65 | + if (r < 0) { |
| 66 | + if (r == -ENOKEY) /* Something else deleted it already, that's ok. */ |
| 67 | + continue; |
| 68 | + |
| 69 | + return log_error_errno(r, "Failed to describe key id %d: %m", *key); |
| 70 | + } |
| 71 | + |
| 72 | + /* The decription is the final element as per manpage. */ |
| 73 | + d = strrchr(description, ';'); |
| 74 | + if (!d) |
| 75 | + return log_error_errno( |
| 76 | + SYNTHETIC_ERRNO(EINVAL), |
| 77 | + "Failed to parse description of key id %d: %s", |
| 78 | + *key, |
| 79 | + description); |
| 80 | + |
| 81 | + if (!startswith(d + 1, "fscrypt:")) |
| 82 | + continue; |
| 83 | + |
| 84 | + r = keyctl(KEYCTL_UNLINK, *key, KEY_SPEC_USER_KEYRING, 0, 0); |
| 85 | + if (r < 0) { |
| 86 | + if (errno == ENOKEY) /* Something else deleted it already, that's ok. */ |
| 87 | + continue; |
| 88 | + |
| 89 | + return log_error_errno( |
| 90 | + errno, |
| 91 | + "Failed to delete encryption key with id '%d' from the keyring of user " UID_FMT ": %m", |
| 92 | + *key, |
| 93 | + h->uid); |
| 94 | + } |
| 95 | + |
| 96 | + log_debug("Deleted encryption key with id '%d' from the keyring of user " UID_FMT ".", *key, h->uid); |
| 97 | + } |
| 98 | + |
| 99 | + return 0; |
| 100 | +} |
| 101 | + |
| 102 | +int home_flush_keyring_fscrypt(UserRecord *h) { |
| 103 | + int r; |
| 104 | + |
| 105 | + assert(h); |
| 106 | + assert(user_record_storage(h) == USER_FSCRYPT); |
| 107 | + |
| 108 | + if (!uid_is_valid(h->uid)) |
| 109 | + return 0; |
| 110 | + |
| 111 | + r = safe_fork("(sd-delkey)", |
| 112 | + FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_REOPEN_LOG, |
| 113 | + NULL); |
| 114 | + if (r < 0) |
| 115 | + return r; |
| 116 | + if (r == 0) { |
| 117 | + if (fscrypt_unlink_key(h) < 0) |
| 118 | + _exit(EXIT_FAILURE); |
| 119 | + _exit(EXIT_SUCCESS); |
| 120 | + } |
| 121 | + |
| 122 | + return 0; |
| 123 | +} |
| 124 | + |
32 | 125 | static int fscrypt_upload_volume_key( |
33 | 126 | const uint8_t key_descriptor[static FS_KEY_DESCRIPTOR_SIZE], |
34 | 127 | const void *volume_key, |
|
0 commit comments