espilon-source/espilon_bot/components/mod_honeypot/hp_config.c
Eun0us 6d45770d98 epsilon: merge command system into core + add 5 new modules
Move command registry from components/command/ into components/core/.
New modules: mod_canbus, mod_honeypot, mod_fallback, mod_redteam, mod_ota.
Replace mod_proxy with tun_core (multiplexed SOCKS5 tunnel).
Kconfig extended with per-module settings and async worker config.
2026-02-28 20:07:59 +01:00

205 lines
5.9 KiB
C

/*
* hp_config.c
* NVS-backed runtime configuration for honeypot services.
*/
#include "sdkconfig.h"
#ifdef CONFIG_MODULE_HONEYPOT
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "esp_log.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "hp_config.h"
#define TAG "HP_CFG"
#define NVS_NS "hp_cfg"
/* ============================================================
* Default banners
* ============================================================ */
static const struct {
const char *service;
const char *banner;
} default_banners[] = {
{ "ssh", "SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6\r\n" },
{ "telnet", "\r\nUbuntu 22.04.3 LTS\r\nlogin: " },
{ "ftp", "220 ProFTPD 1.3.5e Server (Debian)\r\n" },
{ "http", "HTTP/1.1 200 OK\r\nServer: Apache/2.4.54 (Ubuntu)\r\n" },
};
#define NUM_BANNERS (sizeof(default_banners) / sizeof(default_banners[0]))
/* ============================================================
* Default thresholds
* ============================================================ */
static const struct {
const char *key;
int value;
} default_thresholds[] = {
{ "portscan", 5 },
{ "synflood", 50 },
{ "icmp", 10 },
{ "udpflood", 100 },
{ "arpflood", 50 },
{ "tarpit_ms", 2000 },
};
#define NUM_THRESHOLDS (sizeof(default_thresholds) / sizeof(default_thresholds[0]))
/* ============================================================
* Init
* ============================================================ */
void hp_config_init(void)
{
ESP_LOGI(TAG, "Config subsystem ready (NVS ns=%s)", NVS_NS);
}
/* ============================================================
* Banner helpers
* ============================================================ */
static const char *_default_banner(const char *service)
{
for (size_t i = 0; i < NUM_BANNERS; i++) {
if (strcmp(default_banners[i].service, service) == 0)
return default_banners[i].banner;
}
return "";
}
esp_err_t hp_config_get_banner(const char *service, char *out, size_t out_len)
{
nvs_handle_t h;
esp_err_t err = nvs_open(NVS_NS, NVS_READONLY, &h);
if (err == ESP_OK) {
char key[16];
snprintf(key, sizeof(key), "b_%s", service);
size_t len = out_len;
err = nvs_get_str(h, key, out, &len);
nvs_close(h);
if (err == ESP_OK)
return ESP_OK;
}
/* Fall back to compile-time default */
const char *def = _default_banner(service);
snprintf(out, out_len, "%s", def);
return ESP_OK;
}
esp_err_t hp_config_set_banner(const char *service, const char *value)
{
nvs_handle_t h;
esp_err_t err = nvs_open(NVS_NS, NVS_READWRITE, &h);
if (err != ESP_OK) return err;
char key[16];
snprintf(key, sizeof(key), "b_%s", service);
err = nvs_set_str(h, key, value);
if (err == ESP_OK) err = nvs_commit(h);
nvs_close(h);
return err;
}
/* ============================================================
* Threshold helpers
* ============================================================ */
static int _default_threshold(const char *key)
{
for (size_t i = 0; i < NUM_THRESHOLDS; i++) {
if (strcmp(default_thresholds[i].key, key) == 0)
return default_thresholds[i].value;
}
return 0;
}
int hp_config_get_threshold(const char *key)
{
nvs_handle_t h;
esp_err_t err = nvs_open(NVS_NS, NVS_READONLY, &h);
if (err == ESP_OK) {
char nkey[16];
snprintf(nkey, sizeof(nkey), "t_%s", key);
int32_t val = 0;
err = nvs_get_i32(h, nkey, &val);
nvs_close(h);
if (err == ESP_OK)
return (int)val;
}
return _default_threshold(key);
}
esp_err_t hp_config_set_threshold(const char *key, int value)
{
/* Clamp to sane range */
if (value < 1) value = 1;
if (value > 10000) value = 10000;
nvs_handle_t h;
esp_err_t err = nvs_open(NVS_NS, NVS_READWRITE, &h);
if (err != ESP_OK) return err;
char nkey[16];
snprintf(nkey, sizeof(nkey), "t_%s", key);
err = nvs_set_i32(h, nkey, (int32_t)value);
if (err == ESP_OK) err = nvs_commit(h);
nvs_close(h);
return err;
}
/* ============================================================
* Reset
* ============================================================ */
esp_err_t hp_config_reset_all(void)
{
nvs_handle_t h;
esp_err_t err = nvs_open(NVS_NS, NVS_READWRITE, &h);
if (err != ESP_OK) return err;
err = nvs_erase_all(h);
if (err == ESP_OK) err = nvs_commit(h);
nvs_close(h);
ESP_LOGI(TAG, "Config reset to defaults");
return err;
}
/* ============================================================
* List
* ============================================================ */
int hp_config_list(const char *type_filter, char *buf, size_t buf_len)
{
int off = 0;
bool show_banners = (!type_filter || !type_filter[0] ||
strcmp(type_filter, "banner") == 0);
bool show_thresholds = (!type_filter || !type_filter[0] ||
strcmp(type_filter, "threshold") == 0);
if (show_banners) {
for (size_t i = 0; i < NUM_BANNERS; i++) {
char val[128];
hp_config_get_banner(default_banners[i].service, val, sizeof(val));
/* Truncate for display (strip \r\n) */
char *p = val;
while (*p && *p != '\r' && *p != '\n') p++;
*p = '\0';
off += snprintf(buf + off, buf_len - off,
"banner_%s=%s ", default_banners[i].service, val);
}
}
if (show_thresholds) {
for (size_t i = 0; i < NUM_THRESHOLDS; i++) {
int val = hp_config_get_threshold(default_thresholds[i].key);
off += snprintf(buf + off, buf_len - off,
"threshold_%s=%d ", default_thresholds[i].key, val);
}
}
return off;
}
#endif /* CONFIG_MODULE_HONEYPOT */