From e806276dca8725d87a17830598d853d40e00a830 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Fri, 10 May 2024 09:36:37 +0200 Subject: [PATCH] Fix interactive query retry if LUKS2 unbound keyslot is present If an unbound keyslot is present (e.g.. slot 0 usual slot, slot 1 unbound), the query loop could return ENOENT (keyslot not valid for segment) and this will stop epxected retry for slot quewry (--tries option). If any previous slot rerutned EPERM (no valid passphrase), prefer this return code. --- lib/luks2/luks2_keyslot.c | 14 ++++++++++++-- tests/compat-test2 | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/lib/luks2/luks2_keyslot.c b/lib/luks2/luks2_keyslot.c index fed11b29..bb9d4537 100644 --- a/lib/luks2/luks2_keyslot.c +++ b/lib/luks2/luks2_keyslot.c @@ -415,11 +415,13 @@ static int LUKS2_keyslot_open_priority_digest(struct crypt_device *cd, { json_object *jobj_keyslots, *jobj; crypt_keyslot_priority slot_priority; - int keyslot, r = -ENOENT; + int keyslot, r = -ENOENT, r_old; json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots); json_object_object_foreach(jobj_keyslots, slot, val) { + r_old = r; + if (!json_object_object_get_ex(val, "priority", &jobj)) slot_priority = CRYPT_SLOT_PRIORITY_NORMAL; else @@ -438,6 +440,9 @@ static int LUKS2_keyslot_open_priority_digest(struct crypt_device *cd, former meaning password wrong, latter key slot unusable for segment */ if ((r != -EPERM) && (r != -ENOENT)) break; + /* If a previous keyslot failed with EPERM (bad password) prefer it */ + if (r_old == -EPERM && r == -ENOENT) + r = -EPERM; } return r; @@ -453,11 +458,13 @@ static int LUKS2_keyslot_open_priority(struct crypt_device *cd, { json_object *jobj_keyslots, *jobj; crypt_keyslot_priority slot_priority; - int keyslot, r = -ENOENT; + int keyslot, r = -ENOENT, r_old; json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots); json_object_object_foreach(jobj_keyslots, slot, val) { + r_old = r; + if (!json_object_object_get_ex(val, "priority", &jobj)) slot_priority = CRYPT_SLOT_PRIORITY_NORMAL; else @@ -476,6 +483,9 @@ static int LUKS2_keyslot_open_priority(struct crypt_device *cd, former meaning password wrong, latter key slot unusable for segment */ if ((r != -EPERM) && (r != -ENOENT)) break; + /* If a previous keyslot failed with EPERM (bad password) prefer it */ + if (r_old == -EPERM && r == -ENOENT) + r = -EPERM; } return r; diff --git a/tests/compat-test2 b/tests/compat-test2 index 112245ce..0bc56528 100755 --- a/tests/compat-test2 +++ b/tests/compat-test2 @@ -501,6 +501,37 @@ EOF [ $? -eq 0 ] || return 1 } +# expected unlocked keyslot id +# password +# command arguments +function expect_retried_unlocked_keyslot() +{ + command -v expect >/dev/null || { + echo "WARNING: expect tool missing, interactive test will be skipped." + return 0 + } + + EXPECT_TIMEOUT=60 + + expect_run - >/dev/null <