/* * hp_config.c * NVS-backed runtime configuration for honeypot services. */ #include "sdkconfig.h" #ifdef CONFIG_MODULE_HONEYPOT #include #include #include #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 */