Remove Legacy Credential Bootstrap Paths
Decouple user provisioning from HTTPS identity storage while retaining compatible v1 user records and migrating TLS material to the credential-free v2 format. Add focused security regression coverage and update operator documentation.
This commit is contained in:
+8
-62
@@ -15,7 +15,6 @@
|
||||
#include "secure_random.h"
|
||||
#include "ssh_transport.h"
|
||||
#include "user_database.h"
|
||||
#include "web_security.h"
|
||||
#include "web_serial_transport.h"
|
||||
|
||||
#define USER_CONSOLE_KEY_LINE_CAPACITY 256U
|
||||
@@ -28,7 +27,6 @@ static void print_usage(void)
|
||||
printf("Usage:\n");
|
||||
printf(" user status|list\n");
|
||||
printf(" user show <username>\n");
|
||||
printf(" user bootstrap [--generate]\n");
|
||||
printf(" user recover --force\n");
|
||||
printf(" user add <username> <user|admin> [--generate]\n");
|
||||
printf(" user delete <username> --force\n");
|
||||
@@ -100,12 +98,11 @@ static int show_users(const char *selected)
|
||||
return 1;
|
||||
}
|
||||
if (selected == NULL) {
|
||||
printf("User database: generation=%lu users=%u/%u admins=%u bootstrapped=%s\n",
|
||||
printf("User database: generation=%lu users=%u/%u admins=%u\n",
|
||||
(unsigned long)s_user_snapshot.generation,
|
||||
(unsigned int)s_user_snapshot.user_count,
|
||||
USER_DATABASE_MAX_USERS,
|
||||
(unsigned int)s_user_snapshot.admin_count,
|
||||
s_user_snapshot.admin_bootstrapped ? "yes" : "no");
|
||||
(unsigned int)s_user_snapshot.admin_count);
|
||||
}
|
||||
bool found = false;
|
||||
for (size_t index = 0U; index < USER_DATABASE_MAX_USERS; ++index) {
|
||||
@@ -123,8 +120,8 @@ static int show_users(const char *selected)
|
||||
printf("User '%s' not found.\n", selected);
|
||||
return 1;
|
||||
}
|
||||
if (!s_user_snapshot.admin_bootstrapped) {
|
||||
printf("Administrative network access is not bootstrapped; use 'user bootstrap'.\n");
|
||||
if (s_user_snapshot.admin_count == 0U) {
|
||||
printf("No administrators; use 'user add <username> admin' on UART0.\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -170,52 +167,13 @@ static void show_generated_password(const char *username,
|
||||
|
||||
static int recover_database(void)
|
||||
{
|
||||
web_security_credentials_t credentials;
|
||||
memset(&credentials, 0, sizeof(credentials));
|
||||
esp_err_t error = web_security_show_credentials(&credentials);
|
||||
if (error == ESP_OK) {
|
||||
const user_database_legacy_credentials_t legacy = {
|
||||
.username = (const uint8_t *)credentials.username,
|
||||
.username_length = credentials.username_length,
|
||||
.password = (const uint8_t *)credentials.password,
|
||||
.password_length = credentials.password_length,
|
||||
};
|
||||
error = user_database_recover_from_legacy(&legacy);
|
||||
}
|
||||
secure_wipe(&credentials, sizeof(credentials));
|
||||
esp_err_t error = user_database_recover_empty();
|
||||
if (error != ESP_OK) {
|
||||
printf("Could not recover user database: %s\n", esp_err_to_name(error));
|
||||
return 1;
|
||||
}
|
||||
printf("User database replaced from the current legacy network credential.\n");
|
||||
printf("The imported account has role user; run 'user bootstrap' to establish an administrator.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bootstrap(bool generated)
|
||||
{
|
||||
esp_err_t error;
|
||||
if (generated) {
|
||||
user_database_generated_password_t password;
|
||||
error = user_database_bootstrap_admin_generated(&password);
|
||||
if (error == ESP_OK) {
|
||||
show_generated_password("admin", &password);
|
||||
}
|
||||
} else {
|
||||
uint8_t password[USER_DATABASE_PASSWORD_CAPACITY + 1U] = {0};
|
||||
size_t password_length = 0U;
|
||||
error = read_password(password, &password_length);
|
||||
if (error == ESP_OK) {
|
||||
error = user_database_bootstrap_admin(password, password_length);
|
||||
}
|
||||
secure_wipe(password, sizeof(password));
|
||||
}
|
||||
if (error != ESP_OK) {
|
||||
printf("Could not bootstrap administrator: %s\n", esp_err_to_name(error));
|
||||
return 1;
|
||||
}
|
||||
revoke_user_network_sessions("admin");
|
||||
printf("Administrator account bootstrapped. Role-aware HTTPS and SSH authentication is active.\n");
|
||||
printf("User database rebuilt empty; no credentials imported.\n");
|
||||
printf("Use 'user add <username> admin' on UART0 to create an administrator.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -422,18 +380,6 @@ static int command_user_inner(int argc, char **argv)
|
||||
}
|
||||
return recover_database();
|
||||
}
|
||||
if ((argc == 2 || argc == 3) && strcmp(argv[1], "bootstrap") == 0) {
|
||||
bool generated = argc == 3 && strcmp(argv[2], "--generate") == 0;
|
||||
if (argc == 3 && !generated) {
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if (remote) {
|
||||
printf("Administrator bootstrap is restricted to physical UART0.\n");
|
||||
return 1;
|
||||
}
|
||||
return bootstrap(generated);
|
||||
}
|
||||
if ((argc == 4 || argc == 5) && strcmp(argv[1], "add") == 0) {
|
||||
bool generated = argc == 5 && strcmp(argv[4], "--generate") == 0;
|
||||
if (argc == 5 && !generated) {
|
||||
@@ -449,7 +395,7 @@ static int command_user_inner(int argc, char **argv)
|
||||
error = user_database_delete((const uint8_t *)argv[2], strlen(argv[2]));
|
||||
}
|
||||
if (error != ESP_OK) {
|
||||
printf("Could not delete user (the migrated or final admin is protected): %s\n",
|
||||
printf("Could not delete user (the final admin is protected): %s\n",
|
||||
esp_err_to_name(error));
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user