summaryrefslogtreecommitdiffstats
path: root/src/cryptenroll/cryptenroll-list.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptenroll/cryptenroll-list.c')
-rw-r--r--src/cryptenroll/cryptenroll-list.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/src/cryptenroll/cryptenroll-list.c b/src/cryptenroll/cryptenroll-list.c
new file mode 100644
index 0000000..d21df71
--- /dev/null
+++ b/src/cryptenroll/cryptenroll-list.c
@@ -0,0 +1,127 @@
+/* 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_get_rows(t) <= 1) {
+ 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;
+}