1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-11 20:35:51 +00:00

Compare commits

...

10 Commits

Author SHA1 Message Date
J. Nick Koston
f9ef8af18e Merge remote-tracking branch 'upstream/dev' into wifi_min_ver
# Conflicts:
#	esphome/components/wifi/wifi_component.h
2025-11-10 19:09:10 -06:00
J. Nick Koston
4f411dc4f2 help 2025-11-10 16:47:42 -06:00
J. Nick Koston
4964fdc1b0 help 2025-11-10 16:45:54 -06:00
J. Nick Koston
f275a31c3a preen 2025-11-10 14:37:54 -06:00
J. Nick Koston
d7cef22ddb fix defaults 2025-11-10 14:33:11 -06:00
J. Nick Koston
23b8139d24 fix defaults 2025-11-10 14:31:26 -06:00
J. Nick Koston
3fd5e87379 fix namespace conflicts 2025-11-10 13:51:16 -06:00
J. Nick Koston
8d284ea90c fixes 2025-11-10 13:30:36 -06:00
J. Nick Koston
5a67d2b20b fixes 2025-11-10 13:00:52 -06:00
J. Nick Koston
f84cdad93c [wifi] Add min_auth_mode configuration option 2025-11-10 12:50:17 -06:00
6 changed files with 79 additions and 6 deletions

View File

@@ -1,3 +1,5 @@
import logging
from esphome import automation
from esphome.automation import Condition
import esphome.codegen as cg
@@ -42,6 +44,7 @@ from esphome.const import (
CONF_TTLS_PHASE_2,
CONF_USE_ADDRESS,
CONF_USERNAME,
Platform,
PlatformFramework,
)
from esphome.core import CORE, CoroPriority, HexInt, coroutine_with_priority
@@ -49,10 +52,13 @@ import esphome.final_validate as fv
from . import wpa2_eap
_LOGGER = logging.getLogger(__name__)
AUTO_LOAD = ["network"]
NO_WIFI_VARIANTS = [const.VARIANT_ESP32H2, const.VARIANT_ESP32P4]
CONF_SAVE = "save"
CONF_MIN_AUTH_MODE = "min_auth_mode"
# Maximum number of WiFi networks that can be configured
# Limited to 127 because selected_sta_index_ is int8_t in C++
@@ -70,6 +76,14 @@ WIFI_POWER_SAVE_MODES = {
"LIGHT": WiFiPowerSaveMode.WIFI_POWER_SAVE_LIGHT,
"HIGH": WiFiPowerSaveMode.WIFI_POWER_SAVE_HIGH,
}
WifiMinAuthMode = wifi_ns.enum("WifiMinAuthMode")
WIFI_MIN_AUTH_MODES = {
"WPA": WifiMinAuthMode.WIFI_MIN_AUTH_MODE_WPA,
"WPA2": WifiMinAuthMode.WIFI_MIN_AUTH_MODE_WPA2,
"WPA3": WifiMinAuthMode.WIFI_MIN_AUTH_MODE_WPA3,
}
VALIDATE_WIFI_MIN_AUTH_MODE = cv.enum(WIFI_MIN_AUTH_MODES, upper=True)
WiFiConnectedCondition = wifi_ns.class_("WiFiConnectedCondition", Condition)
WiFiEnabledCondition = wifi_ns.class_("WiFiEnabledCondition", Condition)
WiFiEnableAction = wifi_ns.class_("WiFiEnableAction", automation.Action)
@@ -187,6 +201,27 @@ def validate_variant(_):
raise cv.Invalid(f"WiFi requires component esp32_hosted on {variant}")
def _apply_min_auth_mode_default(config):
"""Apply platform-specific default for min_auth_mode and warn ESP8266 users."""
# Only apply defaults for platforms that support min_auth_mode
if CONF_MIN_AUTH_MODE not in config and (CORE.is_esp8266 or CORE.is_esp32):
if CORE.is_esp8266:
_LOGGER.warning(
"The minimum WiFi authentication mode (wifi -> min_auth_mode) is not set. "
"This controls the weakest encryption your device will accept when connecting to WiFi. "
"Currently defaults to WPA (less secure), but will change to WPA2 (more secure) in 2026.6.0. "
"WPA uses TKIP encryption which has known security vulnerabilities and should be avoided. "
"WPA2 uses AES encryption which is significantly more secure. "
"To silence this warning, explicitly set min_auth_mode under 'wifi:'. "
"If your router supports WPA2 or WPA3, set 'min_auth_mode: WPA2'. "
"If your router only supports WPA, set 'min_auth_mode: WPA'."
)
config[CONF_MIN_AUTH_MODE] = VALIDATE_WIFI_MIN_AUTH_MODE("WPA")
elif CORE.is_esp32:
config[CONF_MIN_AUTH_MODE] = VALIDATE_WIFI_MIN_AUTH_MODE("WPA2")
return config
def final_validate(config):
has_sta = bool(config.get(CONF_NETWORKS, True))
has_ap = CONF_AP in config
@@ -287,6 +322,10 @@ CONFIG_SCHEMA = cv.All(
): cv.enum(WIFI_POWER_SAVE_MODES, upper=True),
cv.Optional(CONF_FAST_CONNECT, default=False): cv.boolean,
cv.Optional(CONF_USE_ADDRESS): cv.string_strict,
cv.Optional(CONF_MIN_AUTH_MODE): cv.All(
VALIDATE_WIFI_MIN_AUTH_MODE,
cv.only_on([Platform.ESP32, Platform.ESP8266]),
),
cv.SplitDefault(CONF_OUTPUT_POWER, esp8266=20.0): cv.All(
cv.decibel, cv.float_range(min=8.5, max=20.5)
),
@@ -311,6 +350,7 @@ CONFIG_SCHEMA = cv.All(
),
}
),
_apply_min_auth_mode_default,
_validate,
)
@@ -420,6 +460,8 @@ async def to_code(config):
cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT]))
cg.add(var.set_power_save_mode(config[CONF_POWER_SAVE_MODE]))
if CONF_MIN_AUTH_MODE in config:
cg.add(var.set_min_auth_mode(config[CONF_MIN_AUTH_MODE]))
if config[CONF_FAST_CONNECT]:
cg.add_define("USE_WIFI_FAST_CONNECT")
cg.add(var.set_passive_scan(config[CONF_PASSIVE_SCAN]))

View File

@@ -225,6 +225,12 @@ enum WiFiPowerSaveMode : uint8_t {
WIFI_POWER_SAVE_HIGH,
};
enum WifiMinAuthMode : uint8_t {
WIFI_MIN_AUTH_MODE_WPA = 0,
WIFI_MIN_AUTH_MODE_WPA2,
WIFI_MIN_AUTH_MODE_WPA3,
};
#ifdef USE_ESP32
struct IDFWiFiEvent;
#endif
@@ -276,6 +282,7 @@ class WiFiComponent : public Component {
bool is_connected();
void set_power_save_mode(WiFiPowerSaveMode power_save);
void set_min_auth_mode(WifiMinAuthMode min_auth_mode) { min_auth_mode_ = min_auth_mode; }
void set_output_power(float output_power) { output_power_ = output_power; }
void set_passive_scan(bool passive);
@@ -491,6 +498,7 @@ class WiFiComponent : public Component {
// Group all 8-bit values together
WiFiComponentState state_{WIFI_COMPONENT_STATE_OFF};
WiFiPowerSaveMode power_save_{WIFI_POWER_SAVE_NONE};
WifiMinAuthMode min_auth_mode_{WIFI_MIN_AUTH_MODE_WPA2};
WiFiRetryPhase retry_phase_{WiFiRetryPhase::INITIAL_CONNECT};
uint8_t num_retried_{0};
// Index into sta_ array for the currently selected AP configuration (-1 = none selected)

View File

@@ -258,8 +258,17 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
if (ap.get_password().empty()) {
conf.threshold.authmode = AUTH_OPEN;
} else {
// Only allow auth modes with at least WPA
conf.threshold.authmode = AUTH_WPA_PSK;
// Set threshold based on configured minimum auth mode
// Note: ESP8266 doesn't support WPA3
switch (this->min_auth_mode_) {
case WIFI_MIN_AUTH_MODE_WPA:
conf.threshold.authmode = AUTH_WPA_PSK;
break;
case WIFI_MIN_AUTH_MODE_WPA2:
case WIFI_MIN_AUTH_MODE_WPA3: // Fall back to WPA2 for ESP8266
conf.threshold.authmode = AUTH_WPA2_PSK;
break;
}
}
conf.threshold.rssi = -127;
#endif

View File

@@ -308,7 +308,18 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
if (ap.get_password().empty()) {
conf.sta.threshold.authmode = WIFI_AUTH_OPEN;
} else {
conf.sta.threshold.authmode = WIFI_AUTH_WPA_WPA2_PSK;
// Set threshold based on configured minimum auth mode
switch (this->min_auth_mode_) {
case WIFI_MIN_AUTH_MODE_WPA:
conf.sta.threshold.authmode = WIFI_AUTH_WPA_PSK;
break;
case WIFI_MIN_AUTH_MODE_WPA2:
conf.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;
break;
case WIFI_MIN_AUTH_MODE_WPA3:
conf.sta.threshold.authmode = WIFI_AUTH_WPA3_PSK;
break;
}
}
#ifdef USE_WIFI_WPA2_EAP
@@ -347,8 +358,6 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
// The minimum rssi to accept in the fast scan mode
conf.sta.threshold.rssi = -127;
conf.sta.threshold.authmode = WIFI_AUTH_OPEN;
wifi_config_t current_conf;
esp_err_t err;
err = esp_wifi_get_config(WIFI_IF_STA, &current_conf);

View File

@@ -2,6 +2,7 @@ psram:
wifi:
use_psram: true
min_auth_mode: WPA
packages:
- !include common.yaml

View File

@@ -1 +1,5 @@
<<: !include common.yaml
wifi:
min_auth_mode: WPA2
packages:
- !include common.yaml