Expand admin SSH command capabilities
Add per-session history, tab completion, interactive prompts, and bounded input handling. Support deferred lifecycle and host-key actions after output drains, and document the expanded administration workflow.
This commit is contained in:
+12
-68
@@ -9,19 +9,16 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "admin_ssh_console.h"
|
||||
#include "driver/uart.h"
|
||||
#include "console_input.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_netif_ip_addr.h"
|
||||
#include "esp_wifi_types.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "network_console.h"
|
||||
#include "wifi_config.h"
|
||||
#include "wifi_manager.h"
|
||||
|
||||
#define WIFI_CONSOLE_UART UART_NUM_0
|
||||
#define WIFI_CONSOLE_SECRET_CAPACITY WIFI_CONFIG_PSK_MAX_LEN
|
||||
|
||||
static void print_usage(void)
|
||||
@@ -243,72 +240,19 @@ static esp_err_t apply_candidate(wifi_app_config_t *candidate)
|
||||
|
||||
static esp_err_t read_secret_no_echo(uint8_t *secret, uint8_t *secret_len)
|
||||
{
|
||||
if (admin_ssh_console_dispatch_is_remote()) {
|
||||
printf("Interactive secret entry is restricted to physical UART0.\n");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
uint8_t buffer[WIFI_CONSOLE_SECRET_CAPACITY];
|
||||
uint8_t buffer[WIFI_CONSOLE_SECRET_CAPACITY + 1U] = {0};
|
||||
size_t length = 0U;
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
/*
|
||||
* esp_console may execute on CR while the terminal's trailing LF is still
|
||||
* arriving. Let that line ending settle, then discard only pre-prompt RX so
|
||||
* it cannot be mistaken for an immediately submitted empty secret.
|
||||
*/
|
||||
vTaskDelay(1U);
|
||||
esp_err_t flush_error = uart_flush_input(WIFI_CONSOLE_UART);
|
||||
if (flush_error != ESP_OK) {
|
||||
wifi_config_secure_wipe(buffer, sizeof(buffer));
|
||||
printf("Could not prepare secret input: %s\n", esp_err_to_name(flush_error));
|
||||
return flush_error;
|
||||
esp_err_t error = console_input_read_hidden(
|
||||
"Enter 8..63 printable ASCII characters (input hidden, Ctrl-C cancels): ",
|
||||
buffer, sizeof(buffer), WIFI_CONFIG_PSK_MIN_LEN,
|
||||
WIFI_CONFIG_PSK_MAX_LEN, &length);
|
||||
if (error == ESP_OK) {
|
||||
memset(secret, 0, WIFI_CONFIG_PSK_MAX_LEN);
|
||||
memcpy(secret, buffer, length);
|
||||
*secret_len = (uint8_t)length;
|
||||
}
|
||||
|
||||
printf("Enter 8..63 printable ASCII characters (input hidden, Ctrl-C cancels): ");
|
||||
fflush(stdout);
|
||||
|
||||
for (;;) {
|
||||
uint8_t byte = 0U;
|
||||
int received = uart_read_bytes(WIFI_CONSOLE_UART, &byte, 1U, portMAX_DELAY);
|
||||
if (received != 1) {
|
||||
wifi_config_secure_wipe(buffer, sizeof(buffer));
|
||||
printf("\nSecret input failed.\n");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (byte == 0x03U) {
|
||||
wifi_config_secure_wipe(buffer, sizeof(buffer));
|
||||
printf("\nCancelled.\n");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (byte == '\r' || byte == '\n') {
|
||||
break;
|
||||
}
|
||||
if (byte == 0x08U || byte == 0x7fU) {
|
||||
if (length > 0U) {
|
||||
buffer[--length] = 0U;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (byte < 0x20U || byte > 0x7eU || length >= sizeof(buffer)) {
|
||||
putchar('\a');
|
||||
fflush(stdout);
|
||||
continue;
|
||||
}
|
||||
buffer[length++] = byte;
|
||||
}
|
||||
putchar('\n');
|
||||
|
||||
if (length < WIFI_CONFIG_PSK_MIN_LEN || length > WIFI_CONFIG_PSK_MAX_LEN) {
|
||||
wifi_config_secure_wipe(buffer, sizeof(buffer));
|
||||
printf("Secret length must be 8..63 characters.\n");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
memset(secret, 0, WIFI_CONFIG_PSK_MAX_LEN);
|
||||
memcpy(secret, buffer, length);
|
||||
*secret_len = (uint8_t)length;
|
||||
wifi_config_secure_wipe(buffer, sizeof(buffer));
|
||||
return ESP_OK;
|
||||
return error;
|
||||
}
|
||||
|
||||
static int set_profile(char **argv)
|
||||
|
||||
Reference in New Issue
Block a user