From ec026ab3a8bffaaae89e998466bcc06120c06827 Mon Sep 17 00:00:00 2001 From: Guillermo Ruffino Date: Fri, 10 Jul 2020 17:36:29 -0300 Subject: [PATCH] Revert "Add ESP32 support for WPA2-EAP Enterprise WiFi authentication (#1080)" (#1117) This reverts commit c693c219f46c345dd64ea8c670d876615ba2077d. --- esphome/components/wifi/__init__.py | 88 +------------------ esphome/components/wifi/wifi_component.cpp | 2 - esphome/components/wifi/wifi_component.h | 13 --- .../components/wifi/wifi_component_esp32.cpp | 46 ---------- esphome/config_validation.py | 23 ----- esphome/const.py | 5 -- requirements.txt | 1 - requirements_test.txt | 1 - 8 files changed, 1 insertion(+), 178 deletions(-) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 8b68264b8e..d3c7e51603 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -1,6 +1,3 @@ -import logging -from cryptography.hazmat.primitives.asymmetric import rsa, ec, ed448, ed25519 - import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation @@ -8,15 +5,12 @@ from esphome.automation import Condition from esphome.const import CONF_AP, CONF_BSSID, CONF_CHANNEL, CONF_DNS1, CONF_DNS2, CONF_DOMAIN, \ CONF_FAST_CONNECT, CONF_GATEWAY, CONF_HIDDEN, CONF_ID, CONF_MANUAL_IP, CONF_NETWORKS, \ CONF_PASSWORD, CONF_POWER_SAVE_MODE, CONF_REBOOT_TIMEOUT, CONF_SSID, CONF_STATIC_IP, \ - CONF_SUBNET, CONF_USE_ADDRESS, CONF_PRIORITY, CONF_IDENTITY, CONF_CERTIFICATE_AUTHORITY, \ - CONF_CERTIFICATE, CONF_KEY, CONF_USERNAME, CONF_EAP + CONF_SUBNET, CONF_USE_ADDRESS, CONF_PRIORITY from esphome.core import CORE, HexInt, coroutine_with_priority -_LOGGER = logging.getLogger(__name__) AUTO_LOAD = ['network'] wifi_ns = cg.esphome_ns.namespace('wifi') -EAPAuth = wifi_ns.struct('EAPAuth') IPAddress = cg.global_ns.class_('IPAddress') ManualIP = wifi_ns.struct('ManualIP') WiFiComponent = wifi_ns.class_('WiFiComponent', cg.Component) @@ -42,55 +36,6 @@ def validate_password(value): return value -def validate_eap(value): - if CONF_USERNAME in value: - if CONF_IDENTITY not in value: - _LOGGER.info("EAP 'identity:' is not set, assuming username.") - value[CONF_IDENTITY] = value[CONF_USERNAME] - if CONF_PASSWORD not in value: - raise cv.Invalid("You cannot use the EAP 'username:' option without a 'password:'. " - "Please provide the 'password:' key") - if CONF_CERTIFICATE in value or CONF_KEY in value: - if CONF_CERTIFICATE not in value and CONF_KEY not in value: - raise cv.Invalid("You have provided an EAP 'certificate:' or 'key:' without providing " - "the other. Please check you have provided both.") - # Check the key is valid and for this certificate, just to check the user hasn't pasted - # the wrong thing. I write this after I spent a while debugging that exact issue. - # This may require a password to decrypt to key, so we should verify that at the same time. - certPw = None - if CONF_PASSWORD in value: - certPw = value[CONF_PASSWORD] - - cert = cv.load_certificate(value[CONF_CERTIFICATE]) - try: - key = cv.load_key(value[CONF_KEY], certPw) - except ValueError as e: - raise cv.Invalid( - "There was an error with the EAP 'password:' provided for 'key:' :%s" % e - ) - except TypeError as e: - raise cv.Invalid("There was an error with the EAP 'key:' provided :%s" % e) - - if isinstance(key, rsa.RSAPrivateKey): - if key.public_key().public_numbers() != cert.public_key().public_numbers(): - raise cv.Invalid("The provided EAP 'key:' does not match the 'certificate:'") - elif isinstance(key, ec.EllipticCurvePrivateKey): - if key.public_key().public_numbers() != cert.public_key().public_numbers(): - raise cv.Invalid("The provided EAP 'key:' does not match the 'certificate:'") - elif isinstance(key, ed448.Ed448PrivateKey): - if key.public_key() != cert: - raise cv.Invalid("The provided EAP 'key:' does not match the 'certificate:'") - elif isinstance(key, ed25519.Ed25519PrivateKey): - if key.public_key() != cert: - raise cv.Invalid("The provided EAP 'key:' does not match the 'certificate:'") - else: - _LOGGER.warning( - "Unrecognised EAP 'certificate:' 'key:' pair format: %s. Proceed with caution!", - type(key) - ) - return value - - def validate_channel(value): value = cv.positive_int(value) if value < 1: @@ -111,15 +56,6 @@ STA_MANUAL_IP_SCHEMA = AP_MANUAL_IP_SCHEMA.extend({ cv.Optional(CONF_DNS2, default="0.0.0.0"): cv.ipv4, }) -EAP_AUTH_SCHEMA = cv.Schema({ - cv.Optional(CONF_IDENTITY): cv.string_strict, - cv.Optional(CONF_USERNAME): cv.string_strict, - cv.Optional(CONF_PASSWORD): cv.string_strict, - cv.Optional(CONF_CERTIFICATE_AUTHORITY): cv.certificate, - cv.Optional(CONF_CERTIFICATE): cv.certificate, - cv.Optional(CONF_KEY): cv.string_strict, -}) - WIFI_NETWORK_BASE = cv.Schema({ cv.GenerateID(): cv.declare_id(WiFiAP), cv.Optional(CONF_SSID): cv.ssid, @@ -137,7 +73,6 @@ WIFI_NETWORK_STA = WIFI_NETWORK_BASE.extend({ cv.Optional(CONF_BSSID): cv.mac_address, cv.Optional(CONF_HIDDEN): cv.boolean, cv.Optional(CONF_PRIORITY, default=0.0): cv.float_, - cv.Optional(CONF_EAP): EAP_AUTH_SCHEMA, }) @@ -158,10 +93,6 @@ def validate(config): raise cv.Invalid("Please specify at least an SSID or an Access Point " "to create.") - for network in config[CONF_NETWORKS]: - if CONF_EAP in network: - network[CONF_EAP] = validate_eap(network[CONF_EAP]) - if config.get(CONF_FAST_CONNECT, False): networks = config.get(CONF_NETWORKS, []) if not networks: @@ -187,7 +118,6 @@ CONFIG_SCHEMA = cv.All(cv.Schema({ cv.Optional(CONF_SSID): cv.ssid, cv.Optional(CONF_PASSWORD): validate_password, cv.Optional(CONF_MANUAL_IP): STA_MANUAL_IP_SCHEMA, - cv.Optional(CONF_EAP): EAP_AUTH_SCHEMA, cv.Optional(CONF_AP): WIFI_NETWORK_AP, cv.Optional(CONF_DOMAIN, default='.local'): cv.domain_name, @@ -203,20 +133,6 @@ CONFIG_SCHEMA = cv.All(cv.Schema({ }), validate) -def eap_auth(config): - if config is None: - return None - return cg.StructInitializer( - EAPAuth, - ('identity', config.get(CONF_IDENTITY, "")), - ('username', config.get(CONF_USERNAME, "")), - ('password', config.get(CONF_PASSWORD, "")), - ('ca_cert', config.get(CONF_CERTIFICATE_AUTHORITY, "")), - ('client_cert', config.get(CONF_CERTIFICATE, "")), - ('client_key', config.get(CONF_KEY, "")), - ) - - def safe_ip(ip): if ip is None: return IPAddress(0, 0, 0, 0) @@ -242,8 +158,6 @@ def wifi_network(config, static_ip): cg.add(ap.set_ssid(config[CONF_SSID])) if CONF_PASSWORD in config: cg.add(ap.set_password(config[CONF_PASSWORD])) - if CONF_EAP in config: - cg.add(ap.set_eap(eap_auth(config[CONF_EAP]))) if CONF_BSSID in config: cg.add(ap.set_bssid([HexInt(i) for i in config[CONF_BSSID].parts])) if CONF_HIDDEN in config: diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index dc955add25..d56e75a070 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -541,14 +541,12 @@ void WiFiAP::set_ssid(const std::string &ssid) { this->ssid_ = ssid; } void WiFiAP::set_bssid(bssid_t bssid) { this->bssid_ = bssid; } void WiFiAP::set_bssid(optional bssid) { this->bssid_ = bssid; } void WiFiAP::set_password(const std::string &password) { this->password_ = password; } -void WiFiAP::set_eap(optional eap_auth) { this->eap_ = eap_auth; } void WiFiAP::set_channel(optional channel) { this->channel_ = channel; } void WiFiAP::set_manual_ip(optional manual_ip) { this->manual_ip_ = manual_ip; } void WiFiAP::set_hidden(bool hidden) { this->hidden_ = hidden; } const std::string &WiFiAP::get_ssid() const { return this->ssid_; } const optional &WiFiAP::get_bssid() const { return this->bssid_; } const std::string &WiFiAP::get_password() const { return this->password_; } -const optional &WiFiAP::get_eap() const { return this->eap_; } const optional &WiFiAP::get_channel() const { return this->channel_; } const optional &WiFiAP::get_manual_ip() const { return this->manual_ip_; } bool WiFiAP::get_hidden() const { return this->hidden_; } diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index d58ea6c0fa..d04e1c2ce0 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -57,16 +57,6 @@ struct ManualIP { IPAddress dns2; ///< The second DNS server. 0.0.0.0 for default. }; -struct EAPAuth { - std::string identity; // required for all auth types - std::string username; - std::string password; - char *ca_cert; // optionally verify authentication server - // used for EAP-TLS - char *client_cert; - char *client_key; -}; - using bssid_t = std::array; class WiFiAP { @@ -75,7 +65,6 @@ class WiFiAP { void set_bssid(bssid_t bssid); void set_bssid(optional bssid); void set_password(const std::string &password); - void set_eap(optional eap_auth); void set_channel(optional channel); void set_priority(float priority) { priority_ = priority; } void set_manual_ip(optional manual_ip); @@ -83,7 +72,6 @@ class WiFiAP { const std::string &get_ssid() const; const optional &get_bssid() const; const std::string &get_password() const; - const optional &get_eap() const; const optional &get_channel() const; float get_priority() const { return priority_; } const optional &get_manual_ip() const; @@ -93,7 +81,6 @@ class WiFiAP { std::string ssid_; optional bssid_; std::string password_; - optional eap_; optional channel_; float priority_{0}; optional manual_ip_; diff --git a/esphome/components/wifi/wifi_component_esp32.cpp b/esphome/components/wifi/wifi_component_esp32.cpp index 86c8078171..e345ab1671 100644 --- a/esphome/components/wifi/wifi_component_esp32.cpp +++ b/esphome/components/wifi/wifi_component_esp32.cpp @@ -6,7 +6,6 @@ #include #include -#include #include "lwip/err.h" #include "lwip/dns.h" @@ -188,51 +187,6 @@ bool WiFiComponent::wifi_sta_connect_(WiFiAP ap) { return false; } - // setup enterprise authentication if required - if (ap.get_eap().has_value()) { - // note: all certificates and keys have to be null terminated. Lengths are appended by +1 to include \0. - EAPAuth eap = ap.get_eap().value(); - err = esp_wifi_sta_wpa2_ent_set_identity((uint8_t *) eap.identity.c_str(), eap.identity.length()); - if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_identity failed! %d", err); - } - int ca_cert_len = strlen(eap.ca_cert); - int client_cert_len = strlen(eap.client_cert); - int client_key_len = strlen(eap.client_key); - if (ca_cert_len) { - err = esp_wifi_sta_wpa2_ent_set_ca_cert((uint8_t *) eap.ca_cert, ca_cert_len + 1); - if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_ca_cert failed! %d", err); - } - } - // workout what type of EAP this is - // validation is not required as the config tool has already validated it - if (client_cert_len && client_key_len) { - // if we have certs, this must be EAP-TLS - err = esp_wifi_sta_wpa2_ent_set_cert_key((uint8_t *) eap.client_cert, client_cert_len + 1, - (uint8_t *) eap.client_key, client_key_len + 1, - (uint8_t *) eap.password.c_str(), strlen(eap.password.c_str())); - if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_cert_key failed! %d", err); - } - } else { - // in the absence of certs, assume this is username/password based - err = esp_wifi_sta_wpa2_ent_set_username((uint8_t *) eap.username.c_str(), eap.username.length()); - if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_username failed! %d", err); - } - err = esp_wifi_sta_wpa2_ent_set_password((uint8_t *) eap.password.c_str(), eap.password.length()); - if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_password failed! %d", err); - } - } - esp_wpa2_config_t wpa2Config = WPA2_CONFIG_INIT_DEFAULT(); - err = esp_wifi_sta_wpa2_ent_enable(&wpa2Config); - if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_enable failed! %d", err); - } - } - this->wifi_apply_hostname_(); err = esp_wifi_connect(); diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 9f7bdddaf0..1319786841 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -10,10 +10,6 @@ from string import ascii_letters, digits import voluptuous as vol -from cryptography import x509 -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives.serialization import load_pem_private_key - from esphome import core from esphome.const import CONF_AVAILABILITY, CONF_COMMAND_TOPIC, CONF_DISCOVERY, CONF_ID, \ CONF_INTERNAL, CONF_NAME, CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, \ @@ -721,25 +717,6 @@ def domain_name(value): return value -def load_certificate(value): - return x509.load_pem_x509_certificate(value.encode('UTF-8'), default_backend()) - - -def load_key(value, password): - if password: - password = password.encode("UTF-8") - return load_pem_private_key(value.encode('UTF-8'), password, default_backend()) - - -def certificate(value): - value = string_strict(value) - try: - load_certificate(value) # raises ValueError - return value - except ValueError: - return Invalid("Invalid certificate") - - def ssid(value): value = string_strict(value) if not value: diff --git a/esphome/const.py b/esphome/const.py index cf2155b83d..8b727b615c 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -76,8 +76,6 @@ CONF_CALIBRATION = 'calibration' CONF_CAPACITANCE = 'capacitance' CONF_CARRIER_DUTY_PERCENT = 'carrier_duty_percent' CONF_CARRIER_FREQUENCY = 'carrier_frequency' -CONF_CERTIFICATE = "certificate" -CONF_CERTIFICATE_AUTHORITY = "certificate_authority" CONF_CHANGE_MODE_EVERY = 'change_mode_every' CONF_CHANNEL = 'channel' CONF_CHANNELS = 'channels' @@ -148,7 +146,6 @@ CONF_DRY_ACTION = 'dry_action' CONF_DRY_MODE = 'dry_mode' CONF_DUMP = 'dump' CONF_DURATION = 'duration' -CONF_EAP = 'eap' CONF_ECHO_PIN = 'echo_pin' CONF_EFFECT = 'effect' CONF_EFFECTS = 'effects' @@ -214,7 +211,6 @@ CONF_I2C = 'i2c' CONF_I2C_ID = 'i2c_id' CONF_ICON = 'icon' CONF_ID = 'id' -CONF_IDENTITY = 'identity' CONF_IDLE = 'idle' CONF_IDLE_ACTION = 'idle_action' CONF_IDLE_LEVEL = 'idle_level' @@ -242,7 +238,6 @@ CONF_JS_URL = 'js_url' CONF_JVC = 'jvc' CONF_KEEP_ON_TIME = 'keep_on_time' CONF_KEEPALIVE = 'keepalive' -CONF_KEY = 'key' CONF_LAMBDA = 'lambda' CONF_LEVEL = 'level' CONF_LG = 'lg' diff --git a/requirements.txt b/requirements.txt index 3efe16cc45..0c99eaccbe 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,5 +10,4 @@ pyserial==3.4 ifaddr==0.1.6 platformio==4.3.3 esptool==2.8 -cryptography==2.9.2 click==7.1.2 diff --git a/requirements_test.txt b/requirements_test.txt index 72078ad6e4..b90c4ea969 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -10,7 +10,6 @@ pyserial==3.4 ifaddr==0.1.6 platformio==4.3.3 esptool==2.8 -cryptography==2.9.2 pylint==2.5.0 flake8==3.7.9