fix(network): harden automatic link transitions

This commit is contained in:
agessaman committed 2026-09-03 20:47:11 -07:00
1 parent fc528ae640
commit d9db3e8e6a
6 files changed
+48 -10

No files matched your search

+31 -3
View File
@@ -7,6 +7,7 @@
#include <ESPAsyncWebServer.h>
#include <DNSServer.h>
#include <ArduinoJson.h>
#include <bootloader_random.h>
#include <esp_system.h>
#include <esp_heap_caps.h>
@@ -23,6 +24,24 @@
// so an untouched password field never overwrites the stored value.
static const char SECRET_SENTINEL[] = "********";
// esp_random() has a true entropy source only while RF is active. Ethernet
// LAN mode deliberately keeps Wi-Fi and Bluetooth down, so temporarily enable
// the bootloader RNG source while generating authentication secrets there.
class WebConfigEntropyGuard {
bool _enabled;
public:
WebConfigEntropyGuard()
: _enabled(activeNetworkInterface().medium() ==
NetworkMedium::Ethernet) {
if (_enabled) bootloader_random_enable();
}
~WebConfigEntropyGuard() {
if (_enabled) bootloader_random_disable();
}
};
// Key classification (allowlist, secret detection, slot-prefix parsing) lives in
// helpers/WebConfigKeys.h so it can be unit-tested on the host. Thin aliases keep
// the call sites below readable.
@@ -262,8 +281,11 @@ bool WebConfigServer::startLanMode(IPAddress ip, bool initial_setup, char reply[
}
_initial_setup = initial_setup;
if (_initial_setup) {
for (int i = 0; i < 3; ++i) {
sprintf(&_setup_code[i * 4], "%04X", (unsigned)(esp_random() & 0xffff));
{
WebConfigEntropyGuard entropy;
for (int i = 0; i < 3; ++i) {
sprintf(&_setup_code[i * 4], "%04X", (unsigned)(esp_random() & 0xffff));
}
}
_setup_code[12] = 0;
} else {
@@ -730,7 +752,13 @@ void WebConfigServer::handleLogin(AsyncWebServerRequest* req) {
}
_login_fails = 0;
_login_lock_until = 0;
for (int i = 0; i < 4; i++) sprintf(&_session_token[i * 8], "%08lx", (unsigned long)esp_random());
{
WebConfigEntropyGuard entropy;
for (int i = 0; i < 4; i++) {
sprintf(&_session_token[i * 8], "%08lx",
(unsigned long)esp_random());
}
}
_session_last_seen = now;
AsyncWebServerResponse* res = req->beginResponse(200, "application/json", "{\"ok\":true}");