Harden cleanup and reduce internal RAM use. Phase 8C nearly validated
and somewhat stable.
This commit is contained in:
@@ -29,7 +29,6 @@
|
||||
#define ADMIN_UART_CONSOLE_TASK_PRIORITY 3U
|
||||
#define ADMIN_SSH_CONSOLE_MAX_ARGUMENTS 10U
|
||||
#define ADMIN_SSH_CONSOLE_HISTORY_DEPTH 4U
|
||||
#define ADMIN_SSH_CONSOLE_COMPLETION_OUTPUT_CAPACITY 2048U
|
||||
#define ADMIN_SSH_CONTROL_QUEUE_LENGTH 2U
|
||||
#define ADMIN_SSH_CONTROL_TASK_STACK_SIZE 4096U
|
||||
#define ADMIN_SSH_CONTROL_TASK_PRIORITY 3U
|
||||
@@ -94,7 +93,7 @@ typedef struct {
|
||||
static portMUX_TYPE s_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
static admin_session_t s_sessions[ADMIN_SSH_CONSOLE_MAX_SESSIONS];
|
||||
/* admin_ssh_console_feed_input() is called only by the sole SSH owner task. */
|
||||
static char s_completion_output[ADMIN_SSH_CONSOLE_COMPLETION_OUTPUT_CAPACITY];
|
||||
static char s_completion_output[CONSOLE_COMPLETION_OUTPUT_CAPACITY];
|
||||
|
||||
static StaticQueue_t s_request_queue_storage;
|
||||
static uint8_t s_request_queue_bytes[ADMIN_SSH_CONSOLE_REQUEST_QUEUE_LENGTH *
|
||||
|
||||
@@ -329,7 +329,7 @@ static ssize_t console_read_with_late_terminal_upgrade(int file_descriptor,
|
||||
}
|
||||
|
||||
/* The UART frontend is the sole caller of linenoise's completion callback. */
|
||||
static char s_uart_completion_output[2048U];
|
||||
static char s_uart_completion_output[CONSOLE_COMPLETION_OUTPUT_CAPACITY];
|
||||
|
||||
static void console_completion_callback(const char *buffer, linenoiseCompletions *completions)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Current longest formatted match list is below this; overflow fails closed. */
|
||||
#define CONSOLE_COMPLETION_OUTPUT_CAPACITY 1024U
|
||||
|
||||
/* Install late-terminal upgrade handling and project-specific completion. */
|
||||
void console_completion_install(void);
|
||||
|
||||
|
||||
+31
-4
@@ -7,6 +7,7 @@
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
@@ -17,8 +18,10 @@
|
||||
|
||||
#define SERIAL_UART_RX_RING_SIZE 8192
|
||||
#define SERIAL_UART_EVENT_QUEUE_SIZE 64
|
||||
#define SERIAL_RX_STREAM_SIZE 16384
|
||||
#define SERIAL_TX_STREAM_SIZE 8192
|
||||
#define SERIAL_RX_STREAM_SIZE 16384U
|
||||
#define SERIAL_TX_STREAM_SIZE 8192U
|
||||
#define SERIAL_RX_STREAM_STORAGE_SIZE (SERIAL_RX_STREAM_SIZE + 1U)
|
||||
#define SERIAL_TX_STREAM_STORAGE_SIZE (SERIAL_TX_STREAM_SIZE + 1U)
|
||||
#define SERIAL_IO_CHUNK_SIZE 256
|
||||
#define SERIAL_TASK_STACK_SIZE 4096
|
||||
#define SERIAL_TASK_PRIORITY 10
|
||||
@@ -32,6 +35,10 @@ static SemaphoreHandle_t s_state_mutex;
|
||||
static SemaphoreHandle_t s_task_stopped;
|
||||
static StreamBufferHandle_t s_rx_stream;
|
||||
static StreamBufferHandle_t s_tx_stream;
|
||||
static StaticStreamBuffer_t s_rx_stream_control;
|
||||
static StaticStreamBuffer_t s_tx_stream_control;
|
||||
static uint8_t *s_rx_stream_storage;
|
||||
static uint8_t *s_tx_stream_storage;
|
||||
static QueueHandle_t s_uart_event_queue;
|
||||
static TaskHandle_t s_event_task;
|
||||
static portMUX_TYPE s_counter_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
@@ -472,8 +479,24 @@ esp_err_t serial_service_init(const serial_config_t *initial_config)
|
||||
|
||||
s_state_mutex = xSemaphoreCreateMutex();
|
||||
s_task_stopped = xSemaphoreCreateBinary();
|
||||
s_rx_stream = xStreamBufferCreate(SERIAL_RX_STREAM_SIZE, 1);
|
||||
s_tx_stream = xStreamBufferCreate(SERIAL_TX_STREAM_SIZE, 1);
|
||||
s_rx_stream_storage = heap_caps_calloc_prefer(
|
||||
1U, SERIAL_RX_STREAM_STORAGE_SIZE, 2,
|
||||
MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT,
|
||||
MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
s_tx_stream_storage = heap_caps_calloc_prefer(
|
||||
1U, SERIAL_TX_STREAM_STORAGE_SIZE, 2,
|
||||
MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT,
|
||||
MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
if (s_rx_stream_storage != NULL) {
|
||||
s_rx_stream = xStreamBufferCreateStatic(
|
||||
SERIAL_RX_STREAM_STORAGE_SIZE, 1U, s_rx_stream_storage,
|
||||
&s_rx_stream_control);
|
||||
}
|
||||
if (s_tx_stream_storage != NULL) {
|
||||
s_tx_stream = xStreamBufferCreateStatic(
|
||||
SERIAL_TX_STREAM_STORAGE_SIZE, 1U, s_tx_stream_storage,
|
||||
&s_tx_stream_control);
|
||||
}
|
||||
if (s_state_mutex == NULL || s_task_stopped == NULL ||
|
||||
s_rx_stream == NULL || s_tx_stream == NULL) {
|
||||
if (s_state_mutex != NULL) {
|
||||
@@ -488,10 +511,14 @@ esp_err_t serial_service_init(const serial_config_t *initial_config)
|
||||
if (s_tx_stream != NULL) {
|
||||
vStreamBufferDelete(s_tx_stream);
|
||||
}
|
||||
heap_caps_free(s_rx_stream_storage);
|
||||
heap_caps_free(s_tx_stream_storage);
|
||||
s_state_mutex = NULL;
|
||||
s_task_stopped = NULL;
|
||||
s_rx_stream = NULL;
|
||||
s_tx_stream = NULL;
|
||||
s_rx_stream_storage = NULL;
|
||||
s_tx_stream_storage = NULL;
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
|
||||
+15
-3
@@ -89,6 +89,7 @@ static uint32_t s_external_close_id[SSH_TRANSPORT_MAX_SESSIONS];
|
||||
static ssh_transport_counters_t s_counters;
|
||||
static SemaphoreHandle_t s_command_mutex;
|
||||
static bool s_initializing;
|
||||
static bool s_init_faulted;
|
||||
static bool s_initialized;
|
||||
static bool s_running;
|
||||
static bool s_transitioning;
|
||||
@@ -1294,20 +1295,29 @@ esp_err_t ssh_transport_init(void)
|
||||
taskEXIT_CRITICAL(&s_lock);
|
||||
return ESP_OK;
|
||||
}
|
||||
if (s_initializing) {
|
||||
if (s_initializing || s_init_faulted) {
|
||||
taskEXIT_CRITICAL(&s_lock);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
s_initializing = true;
|
||||
taskEXIT_CRITICAL(&s_lock);
|
||||
|
||||
bool wolfssh_initialized = false;
|
||||
esp_err_t error = secure_random_init();
|
||||
if (error != ESP_OK) {
|
||||
error = ESP_ERR_INVALID_STATE;
|
||||
goto fail;
|
||||
}
|
||||
if (wolfSSL_SetAllocators(ssh_malloc, ssh_free, ssh_realloc) != 0 ||
|
||||
wolfSSH_Init() != WS_SUCCESS || wc_SetSeed_Cb(ssh_seed) != 0) {
|
||||
if (wolfSSL_SetAllocators(ssh_malloc, ssh_free, ssh_realloc) != 0) {
|
||||
error = ESP_FAIL;
|
||||
goto fail;
|
||||
}
|
||||
if (wolfSSH_Init() != WS_SUCCESS) {
|
||||
error = ESP_FAIL;
|
||||
goto fail;
|
||||
}
|
||||
wolfssh_initialized = true;
|
||||
if (wc_SetSeed_Cb(ssh_seed) != 0) {
|
||||
error = ESP_FAIL;
|
||||
goto fail;
|
||||
}
|
||||
@@ -1347,7 +1357,9 @@ esp_err_t ssh_transport_init(void)
|
||||
return ESP_OK;
|
||||
|
||||
fail:
|
||||
bool cleanup_failed = wolfssh_initialized && wolfSSH_Cleanup() != WS_SUCCESS;
|
||||
taskENTER_CRITICAL(&s_lock);
|
||||
s_init_faulted = cleanup_failed;
|
||||
s_initializing = false;
|
||||
taskEXIT_CRITICAL(&s_lock);
|
||||
return error;
|
||||
|
||||
+30
-16
@@ -47,6 +47,7 @@ static portMUX_TYPE s_state_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
static atomic_bool s_initialized;
|
||||
static atomic_bool s_initializing;
|
||||
static atomic_bool s_init_faulted;
|
||||
static atomic_uint s_usb_state;
|
||||
/* Changes on every effective CDC open/close boundary, even during one task poll. */
|
||||
static atomic_uint s_connection_generation;
|
||||
@@ -816,13 +817,19 @@ static void reset_uninitialized_state(void)
|
||||
taskEXIT_CRITICAL(&s_state_lock);
|
||||
}
|
||||
|
||||
static void cleanup_init_allocations(bool cdc_initialized, bool driver_installed)
|
||||
static esp_err_t cleanup_init_allocations(bool cdc_initialized, bool driver_installed)
|
||||
{
|
||||
if (cdc_initialized) {
|
||||
(void)tinyusb_cdcacm_deinit(TINYUSB_CDC_ACM_0);
|
||||
esp_err_t error = tinyusb_cdcacm_deinit(TINYUSB_CDC_ACM_0);
|
||||
if (error != ESP_OK) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
if (driver_installed) {
|
||||
(void)tinyusb_driver_uninstall();
|
||||
esp_err_t error = tinyusb_driver_uninstall();
|
||||
if (error != ESP_OK) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
if (s_control_queue != NULL) {
|
||||
vQueueDelete(s_control_queue);
|
||||
@@ -833,12 +840,27 @@ static void cleanup_init_allocations(bool cdc_initialized, bool driver_installed
|
||||
s_host_rx_stream = NULL;
|
||||
}
|
||||
reset_uninitialized_state();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t fail_initialization(esp_err_t original_error,
|
||||
bool cdc_initialized,
|
||||
bool driver_installed)
|
||||
{
|
||||
esp_err_t cleanup_error = cleanup_init_allocations(cdc_initialized, driver_installed);
|
||||
if (cleanup_error != ESP_OK) {
|
||||
/* Retain callback-facing storage and reject retries after incomplete teardown. */
|
||||
atomic_store(&s_init_faulted, true);
|
||||
original_error = cleanup_error;
|
||||
}
|
||||
atomic_store(&s_initializing, false);
|
||||
return original_error;
|
||||
}
|
||||
|
||||
esp_err_t usb_cdc_transport_init(void)
|
||||
{
|
||||
bool expected = false;
|
||||
if (atomic_load(&s_initialized) ||
|
||||
if (atomic_load(&s_initialized) || atomic_load(&s_init_faulted) ||
|
||||
!atomic_compare_exchange_strong(&s_initializing, &expected, true)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
@@ -870,9 +892,7 @@ esp_err_t usb_cdc_transport_init(void)
|
||||
s_control_queue = xQueueCreate(USB_CDC_CONTROL_QUEUE_LENGTH,
|
||||
sizeof(usb_cdc_control_t));
|
||||
if (s_control_queue == NULL) {
|
||||
cleanup_init_allocations(false, false);
|
||||
atomic_store(&s_initializing, false);
|
||||
return ESP_ERR_NO_MEM;
|
||||
return fail_initialization(ESP_ERR_NO_MEM, false, false);
|
||||
}
|
||||
|
||||
/* ESP32-S3's default full-speed internal PHY is fixed to GPIO19/20. */
|
||||
@@ -884,9 +904,7 @@ esp_err_t usb_cdc_transport_init(void)
|
||||
|
||||
result = tinyusb_driver_install(&usb_config);
|
||||
if (result != ESP_OK) {
|
||||
cleanup_init_allocations(false, false);
|
||||
atomic_store(&s_initializing, false);
|
||||
return result;
|
||||
return fail_initialization(result, false, false);
|
||||
}
|
||||
|
||||
const tinyusb_config_cdcacm_t cdc_config = {
|
||||
@@ -898,9 +916,7 @@ esp_err_t usb_cdc_transport_init(void)
|
||||
};
|
||||
result = tinyusb_cdcacm_init(&cdc_config);
|
||||
if (result != ESP_OK) {
|
||||
cleanup_init_allocations(false, true);
|
||||
atomic_store(&s_initializing, false);
|
||||
return result;
|
||||
return fail_initialization(result, false, true);
|
||||
}
|
||||
|
||||
TaskHandle_t task = NULL;
|
||||
@@ -910,9 +926,7 @@ esp_err_t usb_cdc_transport_init(void)
|
||||
NULL,
|
||||
USB_CDC_TASK_PRIORITY,
|
||||
&task) != pdPASS) {
|
||||
cleanup_init_allocations(true, true);
|
||||
atomic_store(&s_initializing, false);
|
||||
return ESP_ERR_NO_MEM;
|
||||
return fail_initialization(ESP_ERR_NO_MEM, true, true);
|
||||
}
|
||||
|
||||
atomic_store(&s_transport_task, (uintptr_t)task);
|
||||
|
||||
+65
-33
@@ -6,6 +6,7 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_heap_caps.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "mbedtls/ecp.h"
|
||||
@@ -66,7 +67,7 @@ typedef struct {
|
||||
|
||||
static SemaphoreHandle_t s_mutex;
|
||||
static stored_database_t s_database;
|
||||
static stored_database_t s_candidate;
|
||||
static stored_database_t *s_candidate;
|
||||
static bool s_initialized;
|
||||
static uint8_t s_dummy_salt[USER_DATABASE_PASSWORD_SALT_LENGTH];
|
||||
static uint8_t s_dummy_hash[USER_DATABASE_PASSWORD_HASH_LENGTH];
|
||||
@@ -80,9 +81,30 @@ static esp_err_t initialize_dummy_verifier(void)
|
||||
return error;
|
||||
}
|
||||
|
||||
static esp_err_t allocate_candidate(void)
|
||||
{
|
||||
if (s_candidate != NULL) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
s_candidate = heap_caps_calloc_prefer(
|
||||
1U, sizeof(*s_candidate), 2,
|
||||
MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT,
|
||||
MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
return s_candidate != NULL ? ESP_OK : ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
static void discard_candidate(void)
|
||||
{
|
||||
secure_wipe(&s_candidate, sizeof(s_candidate));
|
||||
if (s_candidate != NULL) {
|
||||
secure_wipe(s_candidate, sizeof(*s_candidate));
|
||||
}
|
||||
}
|
||||
|
||||
static void release_candidate(void)
|
||||
{
|
||||
discard_candidate();
|
||||
heap_caps_free(s_candidate);
|
||||
s_candidate = NULL;
|
||||
}
|
||||
|
||||
static bool constant_time_equal(const uint8_t *left, const uint8_t *right, size_t length)
|
||||
@@ -437,10 +459,10 @@ static esp_err_t next_generation(uint32_t *generation)
|
||||
|
||||
static esp_err_t commit_candidate_locked(void)
|
||||
{
|
||||
recount(&s_candidate);
|
||||
esp_err_t error = next_generation(&s_candidate.generation);
|
||||
recount(s_candidate);
|
||||
esp_err_t error = next_generation(&s_candidate->generation);
|
||||
if (error == ESP_OK) {
|
||||
error = validate_database(&s_candidate);
|
||||
error = validate_database(s_candidate);
|
||||
}
|
||||
if (error != ESP_OK) {
|
||||
discard_candidate();
|
||||
@@ -451,7 +473,7 @@ static esp_err_t commit_candidate_locked(void)
|
||||
error = nvs_open(USER_DATABASE_NVS_NAMESPACE, NVS_READWRITE, &handle);
|
||||
if (error == ESP_OK) {
|
||||
error = nvs_set_blob(handle, USER_DATABASE_NVS_BLOB_KEY,
|
||||
&s_candidate, sizeof(s_candidate));
|
||||
s_candidate, sizeof(*s_candidate));
|
||||
if (error == ESP_OK) {
|
||||
error = nvs_commit(handle);
|
||||
}
|
||||
@@ -459,7 +481,7 @@ static esp_err_t commit_candidate_locked(void)
|
||||
}
|
||||
if (error == ESP_OK) {
|
||||
secure_wipe(&s_database, sizeof(s_database));
|
||||
s_database = s_candidate;
|
||||
s_database = *s_candidate;
|
||||
}
|
||||
discard_candidate();
|
||||
return error;
|
||||
@@ -530,8 +552,8 @@ static esp_err_t synchronize_legacy_locked(
|
||||
return error;
|
||||
}
|
||||
|
||||
s_candidate = s_database;
|
||||
stored_user_t *candidate_user = &s_candidate.users[index];
|
||||
*s_candidate = s_database;
|
||||
stored_user_t *candidate_user = &s_candidate->users[index];
|
||||
error = set_record_password(candidate_user, legacy->password,
|
||||
legacy->password_length);
|
||||
if (error == ESP_OK) {
|
||||
@@ -557,12 +579,16 @@ esp_err_t user_database_init(const user_database_legacy_credentials_t *legacy,
|
||||
if (s_mutex == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
esp_err_t error = nvs_flash_init();
|
||||
esp_err_t error = allocate_candidate();
|
||||
if (error != ESP_OK) {
|
||||
vSemaphoreDelete(s_mutex);
|
||||
s_mutex = NULL;
|
||||
return error;
|
||||
}
|
||||
error = nvs_flash_init();
|
||||
if (error != ESP_OK) {
|
||||
goto init_failed;
|
||||
}
|
||||
|
||||
bool storage_missing = false;
|
||||
nvs_handle_t handle;
|
||||
@@ -621,7 +647,7 @@ esp_err_t user_database_init(const user_database_legacy_credentials_t *legacy,
|
||||
}
|
||||
*load_result = USER_DATABASE_LOAD_MIGRATED_LEGACY;
|
||||
recount(&s_database);
|
||||
s_candidate = s_database;
|
||||
*s_candidate = s_database;
|
||||
error = commit_candidate_locked();
|
||||
if (error != ESP_OK) {
|
||||
goto init_failed;
|
||||
@@ -635,7 +661,7 @@ esp_err_t user_database_init(const user_database_legacy_credentials_t *legacy,
|
||||
|
||||
init_failed:
|
||||
secure_wipe(&s_database, sizeof(s_database));
|
||||
discard_candidate();
|
||||
release_candidate();
|
||||
secure_wipe(s_dummy_salt, sizeof(s_dummy_salt));
|
||||
secure_wipe(s_dummy_hash, sizeof(s_dummy_hash));
|
||||
vSemaphoreDelete(s_mutex);
|
||||
@@ -673,17 +699,23 @@ esp_err_t user_database_recover_from_legacy(
|
||||
if (s_mutex == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
esp_err_t error = nvs_flash_init();
|
||||
esp_err_t error = allocate_candidate();
|
||||
if (error != ESP_OK) {
|
||||
vSemaphoreDelete(s_mutex);
|
||||
s_mutex = NULL;
|
||||
return error;
|
||||
}
|
||||
error = nvs_flash_init();
|
||||
if (error != ESP_OK) {
|
||||
goto recovery_failed;
|
||||
}
|
||||
|
||||
memset(&s_database, 0, sizeof(s_database));
|
||||
memset(&s_candidate, 0, sizeof(s_candidate));
|
||||
s_candidate.version = USER_DATABASE_SCHEMA_VERSION;
|
||||
s_candidate.size = sizeof(s_candidate);
|
||||
s_candidate.generation = 1U;
|
||||
error = initialize_user(&s_candidate.users[0], legacy->username,
|
||||
memset(s_candidate, 0, sizeof(*s_candidate));
|
||||
s_candidate->version = USER_DATABASE_SCHEMA_VERSION;
|
||||
s_candidate->size = sizeof(*s_candidate);
|
||||
s_candidate->generation = 1U;
|
||||
error = initialize_user(&s_candidate->users[0], legacy->username,
|
||||
legacy->username_length, USER_ROLE_USER,
|
||||
legacy->password, legacy->password_length);
|
||||
if (error == ESP_OK) {
|
||||
@@ -701,7 +733,7 @@ esp_err_t user_database_recover_from_legacy(
|
||||
|
||||
recovery_failed:
|
||||
secure_wipe(&s_database, sizeof(s_database));
|
||||
discard_candidate();
|
||||
release_candidate();
|
||||
secure_wipe(s_dummy_salt, sizeof(s_dummy_salt));
|
||||
secure_wipe(s_dummy_hash, sizeof(s_dummy_hash));
|
||||
vSemaphoreDelete(s_mutex);
|
||||
@@ -918,11 +950,11 @@ static esp_err_t create_locked(const uint8_t *username, size_t username_length,
|
||||
if (free_index < 0) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
s_candidate = s_database;
|
||||
esp_err_t error = initialize_user(&s_candidate.users[free_index], username,
|
||||
*s_candidate = s_database;
|
||||
esp_err_t error = initialize_user(&s_candidate->users[free_index], username,
|
||||
username_length, role, password, password_length);
|
||||
if (error == ESP_OK && role == USER_ROLE_ADMIN) {
|
||||
s_candidate.admin_bootstrapped = 1U;
|
||||
s_candidate->admin_bootstrapped = 1U;
|
||||
}
|
||||
if (error == ESP_OK) {
|
||||
return commit_candidate_locked();
|
||||
@@ -984,15 +1016,15 @@ esp_err_t user_database_bootstrap_admin(const uint8_t *password,
|
||||
error = create_locked(s_admin_username, sizeof(s_admin_username) - 1U,
|
||||
USER_ROLE_ADMIN, password, password_length);
|
||||
} else {
|
||||
s_candidate = s_database;
|
||||
stored_user_t *user = &s_candidate.users[index];
|
||||
*s_candidate = s_database;
|
||||
stored_user_t *user = &s_candidate->users[index];
|
||||
error = set_record_password(user, password, password_length);
|
||||
if (error == ESP_OK) {
|
||||
user->role = USER_ROLE_ADMIN;
|
||||
error = next_generation(&user->auth_generation);
|
||||
}
|
||||
if (error == ESP_OK) {
|
||||
s_candidate.admin_bootstrapped = 1U;
|
||||
s_candidate->admin_bootstrapped = 1U;
|
||||
error = commit_candidate_locked();
|
||||
} else {
|
||||
discard_candidate();
|
||||
@@ -1026,7 +1058,7 @@ static esp_err_t mutate_user_begin(const uint8_t *username, size_t username_leng
|
||||
if (*index < 0) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
s_candidate = s_database;
|
||||
*s_candidate = s_database;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -1050,7 +1082,7 @@ esp_err_t user_database_delete(const uint8_t *username, size_t username_length)
|
||||
error = ESP_ERR_INVALID_STATE;
|
||||
discard_candidate();
|
||||
} else {
|
||||
secure_wipe(&s_candidate.users[index], sizeof(s_candidate.users[index]));
|
||||
secure_wipe(&s_candidate->users[index], sizeof(s_candidate->users[index]));
|
||||
error = commit_candidate_locked();
|
||||
}
|
||||
}
|
||||
@@ -1069,7 +1101,7 @@ esp_err_t user_database_set_role(const uint8_t *username, size_t username_length
|
||||
int index;
|
||||
esp_err_t error = mutate_user_begin(username, username_length, &index);
|
||||
if (error == ESP_OK) {
|
||||
stored_user_t *user = &s_candidate.users[index];
|
||||
stored_user_t *user = &s_candidate->users[index];
|
||||
if (user->role == role) {
|
||||
error = ESP_OK;
|
||||
discard_candidate();
|
||||
@@ -1080,7 +1112,7 @@ esp_err_t user_database_set_role(const uint8_t *username, size_t username_length
|
||||
user->role = (uint8_t)role;
|
||||
error = next_generation(&user->auth_generation);
|
||||
if (error == ESP_OK && role == USER_ROLE_ADMIN) {
|
||||
s_candidate.admin_bootstrapped = 1U;
|
||||
s_candidate->admin_bootstrapped = 1U;
|
||||
}
|
||||
if (error == ESP_OK) {
|
||||
error = commit_candidate_locked();
|
||||
@@ -1104,7 +1136,7 @@ esp_err_t user_database_set_password(const uint8_t *username, size_t username_le
|
||||
int index;
|
||||
esp_err_t error = mutate_user_begin(username, username_length, &index);
|
||||
if (error == ESP_OK) {
|
||||
stored_user_t *user = &s_candidate.users[index];
|
||||
stored_user_t *user = &s_candidate->users[index];
|
||||
error = set_record_password(user, password, password_length);
|
||||
if (error == ESP_OK) {
|
||||
error = next_generation(&user->auth_generation);
|
||||
@@ -1149,7 +1181,7 @@ esp_err_t user_database_add_ssh_key(
|
||||
int user_index;
|
||||
esp_err_t error = mutate_user_begin(username, username_length, &user_index);
|
||||
if (error == ESP_OK) {
|
||||
stored_user_t *user = &s_candidate.users[user_index];
|
||||
stored_user_t *user = &s_candidate->users[user_index];
|
||||
int free_index = -1;
|
||||
for (size_t index = 0U;
|
||||
index < USER_DATABASE_MAX_SSH_KEYS_PER_USER; ++index) {
|
||||
@@ -1210,7 +1242,7 @@ esp_err_t user_database_remove_ssh_key(const uint8_t *username,
|
||||
int user_index;
|
||||
esp_err_t error = mutate_user_begin(username, username_length, &user_index);
|
||||
if (error == ESP_OK) {
|
||||
stored_user_t *user = &s_candidate.users[user_index];
|
||||
stored_user_t *user = &s_candidate->users[user_index];
|
||||
if (user->keys[key_index].active == 0U) {
|
||||
error = ESP_ERR_NOT_FOUND;
|
||||
discard_candidate();
|
||||
@@ -1239,7 +1271,7 @@ esp_err_t user_database_clear_ssh_keys(const uint8_t *username,
|
||||
int user_index;
|
||||
esp_err_t error = mutate_user_begin(username, username_length, &user_index);
|
||||
if (error == ESP_OK) {
|
||||
stored_user_t *user = &s_candidate.users[user_index];
|
||||
stored_user_t *user = &s_candidate->users[user_index];
|
||||
if (user->key_count == 0U) {
|
||||
error = ESP_OK;
|
||||
discard_candidate();
|
||||
|
||||
+9
-2
@@ -695,8 +695,13 @@ esp_err_t web_server_start(void)
|
||||
serial_transport_attached = attach_error == ESP_OK;
|
||||
}
|
||||
if (error != ESP_OK && server != NULL) {
|
||||
(void)httpd_ssl_stop(server);
|
||||
server = NULL;
|
||||
esp_err_t cleanup_error = httpd_ssl_stop(server);
|
||||
if (cleanup_error == ESP_OK) {
|
||||
server = NULL;
|
||||
} else {
|
||||
/* Retain ownership so stop can retry and start cannot allocate a second server. */
|
||||
error = cleanup_error;
|
||||
}
|
||||
}
|
||||
|
||||
xSemaphoreTake(s_server_mutex, portMAX_DELAY);
|
||||
@@ -708,6 +713,8 @@ esp_err_t web_server_start(void)
|
||||
s_server = server;
|
||||
++s_counters.starts;
|
||||
} else {
|
||||
/* A non-NULL handle is a partially started server whose cleanup failed. */
|
||||
s_server = server;
|
||||
++s_counters.start_failures;
|
||||
}
|
||||
xSemaphoreGive(s_server_mutex);
|
||||
|
||||
Reference in New Issue
Block a user