From 7a4769fdd85780356bc4cd10da316549b46eb73f Mon Sep 17 00:00:00 2001 From: Commander1024 Date: Sun, 30 Aug 2026 12:11:16 +0200 Subject: [PATCH] Allow SSH keys on multiple accounts Update validation and duplicate checks to scope key uniqueness per account, and clarify the console error message. Document cross-account key assignment and authentication testing. --- docs/user_administration_tests.md | 4 ++- src/user_console.c | 2 +- src/user_database.c | 43 ++++++++++--------------------- 3 files changed, 18 insertions(+), 31 deletions(-) diff --git a/docs/user_administration_tests.md b/docs/user_administration_tests.md index fdbc303..a1b9d37 100644 --- a/docs/user_administration_tests.md +++ b/docs/user_administration_tests.md @@ -48,10 +48,12 @@ Verify all of the following fail without changing the account generation or key - Unsupported RSA, certificate, or unknown key types. - Truncated/invalid Base64, mismatched outer and embedded types, trailing blob data, malformed Ed25519 lengths, and an invalid/off-curve ECDSA point. -- Adding the same key again to the same account or assigning it to a different account. +- Adding the same key again to the same account. - Adding a fourth key to an account that already has three. - Deleting an empty/out-of-range slot. +Assign the same public key to a second account and confirm it is accepted, receives an independent slot, and authenticates as the username selected by the SSH client. + Then exercise `user key delete --force` and `user key clear --force`, reboot, and confirm the exact remaining fingerprints persist. Phase 8A stores these keys but does not yet accept SSH key login. ### 5. Legacy credential rotation boundary and reboot reconciliation diff --git a/src/user_console.c b/src/user_console.c index 41dfb8a..2ebcb57 100644 --- a/src/user_console.c +++ b/src/user_console.c @@ -357,7 +357,7 @@ static int add_key(const char *username) secure_wipe(line, sizeof(line)); if (error != ESP_OK) { if (error == USER_DATABASE_ERR_DUPLICATE_SSH_KEY) { - printf("Could not add SSH key: that public key is already assigned to an account.\n"); + printf("Could not add SSH key: that public key is already assigned to this account.\n"); } else if (error == ESP_ERR_NO_MEM) { printf("Could not add SSH key: the account already has %u keys.\n", USER_DATABASE_MAX_SSH_KEYS_PER_USER); diff --git a/src/user_database.c b/src/user_database.c index d6096ac..4c88228 100644 --- a/src/user_database.c +++ b/src/user_database.c @@ -387,15 +387,9 @@ static esp_err_t validate_database(const stored_database_t *database) sizeof(key->blob) - key->blob_length)) { return ESP_ERR_INVALID_RESPONSE; } - for (size_t prior_user = 0U; prior_user <= index; ++prior_user) { - size_t prior_key_limit = prior_user == index - ? key_index - : USER_DATABASE_MAX_SSH_KEYS_PER_USER; - for (size_t prior_key = 0U; prior_key < prior_key_limit; ++prior_key) { - if (stored_keys_equal(key, - &database->users[prior_user].keys[prior_key])) { - return ESP_ERR_INVALID_RESPONSE; - } + for (size_t prior_key = 0U; prior_key < key_index; ++prior_key) { + if (stored_keys_equal(key, &user->keys[prior_key])) { + return ESP_ERR_INVALID_RESPONSE; } } uint8_t fingerprint[USER_DATABASE_SHA256_LENGTH]; @@ -1157,29 +1151,20 @@ esp_err_t user_database_add_ssh_key( if (error == ESP_OK) { stored_user_t *user = &s_candidate.users[user_index]; int free_index = -1; - for (size_t candidate_user_index = 0U; - candidate_user_index < USER_DATABASE_MAX_USERS; ++candidate_user_index) { - stored_user_t *candidate_user = - &s_candidate.users[candidate_user_index]; - if (candidate_user->active == 0U) { - continue; - } - for (size_t index = 0U; - index < USER_DATABASE_MAX_SSH_KEYS_PER_USER; ++index) { - stored_key_t *key = &candidate_user->keys[index]; - if (candidate_user_index == (size_t)user_index && - key->active == 0U && free_index < 0) { + for (size_t index = 0U; + index < USER_DATABASE_MAX_SSH_KEYS_PER_USER; ++index) { + stored_key_t *key = &user->keys[index]; + if (key->active == 0U) { + if (free_index < 0) { free_index = (int)index; } - if (key->active != 0U && key->type_length == key_type_length && - key->blob_length == key_blob_length && - memcmp(key->type, key_type, key_type_length) == 0 && - constant_time_equal(key->blob, key_blob, key_blob_length)) { - error = USER_DATABASE_ERR_DUPLICATE_SSH_KEY; - break; - } + continue; } - if (error != ESP_OK) { + if (key->type_length == key_type_length && + key->blob_length == key_blob_length && + memcmp(key->type, key_type, key_type_length) == 0 && + constant_time_equal(key->blob, key_blob, key_blob_length)) { + error = USER_DATABASE_ERR_DUPLICATE_SSH_KEY; break; } }