mirror of
https://github.com/systemd/systemd.git
synced 2025-01-10 05:18:17 +03:00
128 lines
4.7 KiB
C
128 lines
4.7 KiB
C
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
|
|
#include "cryptenroll-list.h"
|
|
#include "cryptenroll.h"
|
|
#include "format-table.h"
|
|
#include "parse-util.h"
|
|
|
|
struct keyslot_metadata {
|
|
int slot;
|
|
const char *type;
|
|
};
|
|
|
|
int list_enrolled(struct crypt_device *cd) {
|
|
_cleanup_free_ struct keyslot_metadata *keyslot_metadata = NULL;
|
|
_cleanup_(table_unrefp) Table *t = NULL;
|
|
size_t n_keyslot_metadata = 0;
|
|
int slot_max, r;
|
|
TableCell *cell;
|
|
|
|
assert(cd);
|
|
|
|
/* First step, find out all currently used slots */
|
|
assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
|
|
for (int slot = 0; slot < slot_max; slot++) {
|
|
crypt_keyslot_info status;
|
|
|
|
status = crypt_keyslot_status(cd, slot);
|
|
if (!IN_SET(status, CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST))
|
|
continue;
|
|
|
|
if (!GREEDY_REALLOC(keyslot_metadata, n_keyslot_metadata+1))
|
|
return log_oom();
|
|
|
|
keyslot_metadata[n_keyslot_metadata++] = (struct keyslot_metadata) {
|
|
.slot = slot,
|
|
};
|
|
}
|
|
|
|
/* Second step, enumerate through all tokens, and update the slot table, indicating what kind of
|
|
* token they are assigned to */
|
|
for (int token = 0; token < sym_crypt_token_max(CRYPT_LUKS2); token++) {
|
|
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
|
const char *type;
|
|
JsonVariant *w, *z;
|
|
EnrollType et;
|
|
|
|
r = cryptsetup_get_token_as_json(cd, token, NULL, &v);
|
|
if (IN_SET(r, -ENOENT, -EINVAL))
|
|
continue;
|
|
if (r < 0) {
|
|
log_warning_errno(r, "Failed to read JSON token data off disk, ignoring: %m");
|
|
continue;
|
|
}
|
|
|
|
w = json_variant_by_key(v, "type");
|
|
if (!w || !json_variant_is_string(w)) {
|
|
log_warning("Token JSON data lacks type field, ignoring.");
|
|
continue;
|
|
}
|
|
|
|
et = luks2_token_type_from_string(json_variant_string(w));
|
|
if (et < 0)
|
|
type = "other";
|
|
else
|
|
type = enroll_type_to_string(et);
|
|
|
|
w = json_variant_by_key(v, "keyslots");
|
|
if (!w || !json_variant_is_array(w)) {
|
|
log_warning("Token JSON data lacks keyslots field, ignoring.");
|
|
continue;
|
|
}
|
|
|
|
JSON_VARIANT_ARRAY_FOREACH(z, w) {
|
|
unsigned u;
|
|
|
|
if (!json_variant_is_string(z)) {
|
|
log_warning("Token JSON data's keyslot field is not an array of strings, ignoring.");
|
|
continue;
|
|
}
|
|
|
|
r = safe_atou(json_variant_string(z), &u);
|
|
if (r < 0) {
|
|
log_warning_errno(r, "Token JSON data's keyslot field is not an integer formatted as string, ignoring.");
|
|
continue;
|
|
}
|
|
|
|
for (size_t i = 0; i < n_keyslot_metadata; i++) {
|
|
if ((unsigned) keyslot_metadata[i].slot != u)
|
|
continue;
|
|
|
|
if (keyslot_metadata[i].type) /* Slot claimed multiple times? */
|
|
keyslot_metadata[i].type = POINTER_MAX;
|
|
else
|
|
keyslot_metadata[i].type = type;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Finally, create a table out of it all */
|
|
t = table_new("slot", "type");
|
|
if (!t)
|
|
return log_oom();
|
|
|
|
assert_se(cell = table_get_cell(t, 0, 0));
|
|
(void) table_set_align_percent(t, cell, 100);
|
|
|
|
for (size_t i = 0; i < n_keyslot_metadata; i++) {
|
|
r = table_add_many(
|
|
t,
|
|
TABLE_INT, keyslot_metadata[i].slot,
|
|
TABLE_STRING, keyslot_metadata[i].type == POINTER_MAX ? "conflict" :
|
|
keyslot_metadata[i].type ?: "password");
|
|
if (r < 0)
|
|
return table_log_add_error(r);
|
|
}
|
|
|
|
if (table_isempty(t)) {
|
|
log_info("No slots found.");
|
|
return 0;
|
|
}
|
|
|
|
r = table_print(t, stdout);
|
|
if (r < 0)
|
|
return log_error_errno(r, "Failed to show slot table: %m");
|
|
|
|
return 0;
|
|
}
|