mirror of
https://github.com/esphome/esphome.git
synced 2025-11-19 16:25:50 +00:00
[wifi] Add min_auth_mode configuration option (#11814)
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
from esphome import automation
|
from esphome import automation
|
||||||
from esphome.automation import Condition
|
from esphome.automation import Condition
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
@@ -42,6 +44,7 @@ from esphome.const import (
|
|||||||
CONF_TTLS_PHASE_2,
|
CONF_TTLS_PHASE_2,
|
||||||
CONF_USE_ADDRESS,
|
CONF_USE_ADDRESS,
|
||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
|
Platform,
|
||||||
PlatformFramework,
|
PlatformFramework,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, CoroPriority, HexInt, coroutine_with_priority
|
from esphome.core import CORE, CoroPriority, HexInt, coroutine_with_priority
|
||||||
@@ -49,10 +52,13 @@ import esphome.final_validate as fv
|
|||||||
|
|
||||||
from . import wpa2_eap
|
from . import wpa2_eap
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
AUTO_LOAD = ["network"]
|
AUTO_LOAD = ["network"]
|
||||||
|
|
||||||
NO_WIFI_VARIANTS = [const.VARIANT_ESP32H2, const.VARIANT_ESP32P4]
|
NO_WIFI_VARIANTS = [const.VARIANT_ESP32H2, const.VARIANT_ESP32P4]
|
||||||
CONF_SAVE = "save"
|
CONF_SAVE = "save"
|
||||||
|
CONF_MIN_AUTH_MODE = "min_auth_mode"
|
||||||
|
|
||||||
# Maximum number of WiFi networks that can be configured
|
# Maximum number of WiFi networks that can be configured
|
||||||
# Limited to 127 because selected_sta_index_ is int8_t in C++
|
# 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,
|
"LIGHT": WiFiPowerSaveMode.WIFI_POWER_SAVE_LIGHT,
|
||||||
"HIGH": WiFiPowerSaveMode.WIFI_POWER_SAVE_HIGH,
|
"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)
|
WiFiConnectedCondition = wifi_ns.class_("WiFiConnectedCondition", Condition)
|
||||||
WiFiEnabledCondition = wifi_ns.class_("WiFiEnabledCondition", Condition)
|
WiFiEnabledCondition = wifi_ns.class_("WiFiEnabledCondition", Condition)
|
||||||
WiFiEnableAction = wifi_ns.class_("WiFiEnableAction", automation.Action)
|
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}")
|
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):
|
def final_validate(config):
|
||||||
has_sta = bool(config.get(CONF_NETWORKS, True))
|
has_sta = bool(config.get(CONF_NETWORKS, True))
|
||||||
has_ap = CONF_AP in config
|
has_ap = CONF_AP in config
|
||||||
@@ -287,6 +322,10 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
): cv.enum(WIFI_POWER_SAVE_MODES, upper=True),
|
): cv.enum(WIFI_POWER_SAVE_MODES, upper=True),
|
||||||
cv.Optional(CONF_FAST_CONNECT, default=False): cv.boolean,
|
cv.Optional(CONF_FAST_CONNECT, default=False): cv.boolean,
|
||||||
cv.Optional(CONF_USE_ADDRESS): cv.string_strict,
|
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.SplitDefault(CONF_OUTPUT_POWER, esp8266=20.0): cv.All(
|
||||||
cv.decibel, cv.float_range(min=8.5, max=20.5)
|
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,
|
_validate,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -420,6 +460,8 @@ async def to_code(config):
|
|||||||
|
|
||||||
cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT]))
|
cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT]))
|
||||||
cg.add(var.set_power_save_mode(config[CONF_POWER_SAVE_MODE]))
|
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]:
|
if config[CONF_FAST_CONNECT]:
|
||||||
cg.add_define("USE_WIFI_FAST_CONNECT")
|
cg.add_define("USE_WIFI_FAST_CONNECT")
|
||||||
cg.add(var.set_passive_scan(config[CONF_PASSIVE_SCAN]))
|
cg.add(var.set_passive_scan(config[CONF_PASSIVE_SCAN]))
|
||||||
|
|||||||
@@ -225,6 +225,12 @@ enum WiFiPowerSaveMode : uint8_t {
|
|||||||
WIFI_POWER_SAVE_HIGH,
|
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
|
#ifdef USE_ESP32
|
||||||
struct IDFWiFiEvent;
|
struct IDFWiFiEvent;
|
||||||
#endif
|
#endif
|
||||||
@@ -274,6 +280,7 @@ class WiFiComponent : public Component {
|
|||||||
bool is_connected();
|
bool is_connected();
|
||||||
|
|
||||||
void set_power_save_mode(WiFiPowerSaveMode power_save);
|
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_output_power(float output_power) { output_power_ = output_power; }
|
||||||
|
|
||||||
void set_passive_scan(bool passive);
|
void set_passive_scan(bool passive);
|
||||||
@@ -490,6 +497,7 @@ class WiFiComponent : public Component {
|
|||||||
// Group all 8-bit values together
|
// Group all 8-bit values together
|
||||||
WiFiComponentState state_{WIFI_COMPONENT_STATE_OFF};
|
WiFiComponentState state_{WIFI_COMPONENT_STATE_OFF};
|
||||||
WiFiPowerSaveMode power_save_{WIFI_POWER_SAVE_NONE};
|
WiFiPowerSaveMode power_save_{WIFI_POWER_SAVE_NONE};
|
||||||
|
WifiMinAuthMode min_auth_mode_{WIFI_MIN_AUTH_MODE_WPA2};
|
||||||
WiFiRetryPhase retry_phase_{WiFiRetryPhase::INITIAL_CONNECT};
|
WiFiRetryPhase retry_phase_{WiFiRetryPhase::INITIAL_CONNECT};
|
||||||
uint8_t num_retried_{0};
|
uint8_t num_retried_{0};
|
||||||
// Index into sta_ array for the currently selected AP configuration (-1 = none selected)
|
// Index into sta_ array for the currently selected AP configuration (-1 = none selected)
|
||||||
|
|||||||
@@ -258,8 +258,17 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
|
|||||||
if (ap.get_password().empty()) {
|
if (ap.get_password().empty()) {
|
||||||
conf.threshold.authmode = AUTH_OPEN;
|
conf.threshold.authmode = AUTH_OPEN;
|
||||||
} else {
|
} else {
|
||||||
// Only allow auth modes with at least WPA
|
// Set threshold based on configured minimum auth mode
|
||||||
conf.threshold.authmode = AUTH_WPA_PSK;
|
// 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;
|
conf.threshold.rssi = -127;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -308,7 +308,18 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
|
|||||||
if (ap.get_password().empty()) {
|
if (ap.get_password().empty()) {
|
||||||
conf.sta.threshold.authmode = WIFI_AUTH_OPEN;
|
conf.sta.threshold.authmode = WIFI_AUTH_OPEN;
|
||||||
} else {
|
} 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
|
#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
|
// The minimum rssi to accept in the fast scan mode
|
||||||
conf.sta.threshold.rssi = -127;
|
conf.sta.threshold.rssi = -127;
|
||||||
|
|
||||||
conf.sta.threshold.authmode = WIFI_AUTH_OPEN;
|
|
||||||
|
|
||||||
wifi_config_t current_conf;
|
wifi_config_t current_conf;
|
||||||
esp_err_t err;
|
esp_err_t err;
|
||||||
err = esp_wifi_get_config(WIFI_IF_STA, ¤t_conf);
|
err = esp_wifi_get_config(WIFI_IF_STA, ¤t_conf);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ psram:
|
|||||||
|
|
||||||
wifi:
|
wifi:
|
||||||
use_psram: true
|
use_psram: true
|
||||||
|
min_auth_mode: WPA
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
- !include common.yaml
|
- !include common.yaml
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
<<: !include common.yaml
|
wifi:
|
||||||
|
min_auth_mode: WPA2
|
||||||
|
|
||||||
|
packages:
|
||||||
|
- !include common.yaml
|
||||||
|
|||||||
Reference in New Issue
Block a user