From bee2b1f191e3a2d2a9dca9605f5dece83a8bbc43 Mon Sep 17 00:00:00 2001 From: rodriguezst <2828844+rodriguezst@users.noreply.github.com> Date: Fri, 10 Jun 2022 08:29:19 +0000 Subject: [PATCH 1/7] Add MQTT SSL preference keys --- PreferencesKeys.h | 3 +++ WebCfgServer.cpp | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/PreferencesKeys.h b/PreferencesKeys.h index 8e48fc1..56466db 100644 --- a/PreferencesKeys.h +++ b/PreferencesKeys.h @@ -10,6 +10,9 @@ #define preference_mqtt_lock_path "mqttpath" #define preference_opener_enabled "openerena" #define preference_mqtt_opener_path "mqttoppath" +#define preference_mqtt_ca "mqttca" +#define preference_mqtt_crt "mqttcrt" +#define preference_mqtt_key "mqttkey" #define preference_hostname "hostname" #define preference_network_timeout "nettmout" #define preference_query_interval_lockstate "lockStInterval" diff --git a/WebCfgServer.cpp b/WebCfgServer.cpp index ac258e9..adc1448 100644 --- a/WebCfgServer.cpp +++ b/WebCfgServer.cpp @@ -168,6 +168,21 @@ bool WebCfgServer::processArgs(String& message) _preferences->putString(preference_mqtt_opener_path, value); configChanged = true; } + else if(key == "MQTTCA") + { + _preferences->putString(preference_mqtt_ca, value); + configChanged = true; + } + else if(key == "MQTTCRT") + { + _preferences->putString(preference_mqtt_crt, value); + configChanged = true; + } + else if(key == "MQTTKEY") + { + _preferences->putString(preference_mqtt_key, value); + configChanged = true; + } else if(key == "HOSTNAME") { _preferences->putString(preference_hostname, value); @@ -437,6 +452,9 @@ void WebCfgServer::buildMqttConfigHtml(String &response) printInputField(response, "MQTTPORT", "MQTT Broker port", _preferences->getInt(preference_mqtt_broker_port), 5); printInputField(response, "MQTTUSER", "MQTT User (# to clear)", _preferences->getString(preference_mqtt_user).c_str(), 30); printInputField(response, "MQTTPASS", "MQTT Password", "*", 30, true); + printInputField(response, "MQTTCA", "MQTT SSL CA Certificate", _preferences->getString(preference_mqtt_ca).c_str(), 180); + printInputField(response, "MQTTCRT", "MQTT SSL Client Certificate", _preferences->getString(preference_mqtt_crt).c_str(), 180); + printInputField(response, "MQTTKEY", "MQTT SSL Client Key", _preferences->getString(preference_mqtt_key).c_str(), 180); printInputField(response, "NETTIMEOUT", "Network Timeout until restart (seconds; -1 to disable)", _preferences->getInt(preference_network_timeout), 5); response.concat(""); response.concat("
"); From 7481b1f4f013b016cc6f08d02ee50d273a52479f Mon Sep 17 00:00:00 2001 From: rodriguezst <2828844+rodriguezst@users.noreply.github.com> Date: Fri, 10 Jun 2022 09:31:20 +0000 Subject: [PATCH 2/7] Implemented MQTT over TLS for WiFiDevice --- CMakeLists.txt | 1 + Network.cpp | 4 ++-- networkDevices/WifiDevice.cpp | 30 +++++++++++++++++++++++++----- networkDevices/WifiDevice.h | 9 ++++++--- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b8f3d2..a9816e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,6 +83,7 @@ target_link_arduino_libraries(${PROJECT_NAME} PRIVATE core WiFi + WiFiClientSecure Update # WebServer DNSServer diff --git a/Network.cpp b/Network.cpp index 0339e76..61435fc 100644 --- a/Network.cpp +++ b/Network.cpp @@ -42,11 +42,11 @@ void Network::setupDevice(const NetworkDeviceType hardware) break; case NetworkDeviceType::WiFi: Serial.println(F("Network device: Builtin WiFi")); - _device = new WifiDevice(_hostname); + _device = new WifiDevice(_hostname, _preferences); break; default: Serial.println(F("Unknown network device type, defaulting to WiFi")); - _device = new WifiDevice(_hostname); + _device = new WifiDevice(_hostname, _preferences); break; } } diff --git a/networkDevices/WifiDevice.cpp b/networkDevices/WifiDevice.cpp index 87633f1..ad940ba 100644 --- a/networkDevices/WifiDevice.cpp +++ b/networkDevices/WifiDevice.cpp @@ -1,15 +1,35 @@ #include #include "WifiDevice.h" #include "WiFiManager.h" +#include "../PreferencesKeys.h" -WifiDevice::WifiDevice(const String& hostname) -: NetworkDevice(hostname), - _mqttClient(_wifiClient) -{} +WifiDevice::WifiDevice(const String& hostname, Preferences* _preferences) +: NetworkDevice(hostname) +{ + String MQTT_CA = _preferences->getString(preference_mqtt_ca); + String MQTT_CRT = _preferences->getString(preference_mqtt_crt); + String MQTT_KEY = _preferences->getString(preference_mqtt_key); + + if(MQTT_CA.length() > 0) + { + _wifiClientSecure = new WiFiClientSecure(); + _wifiClientSecure->setCACert(MQTT_CA.c_str()); + if(MQTT_CRT.length() > 0 && MQTT_KEY.length() > 0) + { + _wifiClientSecure->setCertificate(MQTT_CRT.c_str()); + _wifiClientSecure->setPrivateKey(MQTT_KEY.c_str()); + } + _mqttClient = new PubSubClient(*_wifiClientSecure); + } else + { + _wifiClient = new WiFiClient(); + _mqttClient = new PubSubClient(*_wifiClient); + } +} PubSubClient *WifiDevice::mqttClient() { - return &_mqttClient; + return _mqttClient; } void WifiDevice::initialize() diff --git a/networkDevices/WifiDevice.h b/networkDevices/WifiDevice.h index 4680210..d789386 100644 --- a/networkDevices/WifiDevice.h +++ b/networkDevices/WifiDevice.h @@ -1,13 +1,15 @@ #pragma once #include +#include +#include #include "NetworkDevice.h" #include "../SpiffsCookie.h" class WifiDevice : public NetworkDevice { public: - WifiDevice(const String& hostname); + WifiDevice(const String& hostname, Preferences* _preferences); virtual void initialize(); virtual void reconfigure(); @@ -20,7 +22,8 @@ public: virtual PubSubClient *mqttClient(); private: - WiFiClient _wifiClient; - PubSubClient _mqttClient; + WiFiClient* _wifiClient = nullptr; + WiFiClientSecure* _wifiClientSecure = nullptr; + PubSubClient* _mqttClient = nullptr; SpiffsCookie _cookie; }; From 2391809166164080e7bf32179e9188a0636df610 Mon Sep 17 00:00:00 2001 From: rodriguezst <2828844+rodriguezst@users.noreply.github.com> Date: Mon, 13 Jun 2022 09:52:06 +0000 Subject: [PATCH 3/7] Store keys in WifiDevice object --- networkDevices/WifiDevice.cpp | 24 +++++++++++++++--------- networkDevices/WifiDevice.h | 7 +++++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/networkDevices/WifiDevice.cpp b/networkDevices/WifiDevice.cpp index ad940ba..cf46cbd 100644 --- a/networkDevices/WifiDevice.cpp +++ b/networkDevices/WifiDevice.cpp @@ -6,22 +6,28 @@ WifiDevice::WifiDevice(const String& hostname, Preferences* _preferences) : NetworkDevice(hostname) { - String MQTT_CA = _preferences->getString(preference_mqtt_ca); - String MQTT_CRT = _preferences->getString(preference_mqtt_crt); - String MQTT_KEY = _preferences->getString(preference_mqtt_key); - - if(MQTT_CA.length() > 0) + size_t caLength = _preferences->getString(preference_mqtt_ca,_ca,TLS_CA_MAX_SIZE); + size_t crtLength = _preferences->getString(preference_mqtt_crt,_cert,TLS_CERT_MAX_SIZE); + size_t keyLength = _preferences->getString(preference_mqtt_key,_key,TLS_KEY_MAX_SIZE); + + if(caLength > 1) // length is 1 when empty { + Serial.println(F("MQTT over TLS.")); + Serial.print(_ca); _wifiClientSecure = new WiFiClientSecure(); - _wifiClientSecure->setCACert(MQTT_CA.c_str()); - if(MQTT_CRT.length() > 0 && MQTT_KEY.length() > 0) + _wifiClientSecure->setCACert(_ca); + if(crtLength > 1 && keyLength > 1) // length is 1 when empty { - _wifiClientSecure->setCertificate(MQTT_CRT.c_str()); - _wifiClientSecure->setPrivateKey(MQTT_KEY.c_str()); + Serial.println(F("MQTT with client certificate.")); + Serial.print(_cert); + Serial.print(_key); + _wifiClientSecure->setCertificate(_cert); + _wifiClientSecure->setPrivateKey(_key); } _mqttClient = new PubSubClient(*_wifiClientSecure); } else { + Serial.println(F("MQTT without TLS.")); _wifiClient = new WiFiClient(); _mqttClient = new PubSubClient(*_wifiClient); } diff --git a/networkDevices/WifiDevice.h b/networkDevices/WifiDevice.h index d789386..ec1ed1e 100644 --- a/networkDevices/WifiDevice.h +++ b/networkDevices/WifiDevice.h @@ -6,6 +6,10 @@ #include "NetworkDevice.h" #include "../SpiffsCookie.h" +#define TLS_CA_MAX_SIZE 1800 +#define TLS_CERT_MAX_SIZE 1800 +#define TLS_KEY_MAX_SIZE 1800 + class WifiDevice : public NetworkDevice { public: @@ -26,4 +30,7 @@ private: WiFiClientSecure* _wifiClientSecure = nullptr; PubSubClient* _mqttClient = nullptr; SpiffsCookie _cookie; + char _ca[TLS_CA_MAX_SIZE]; + char _cert[TLS_CERT_MAX_SIZE]; + char _key[TLS_KEY_MAX_SIZE]; }; From 648114fcbe78af9fa6aa74b42a106a4fc4ed1535 Mon Sep 17 00:00:00 2001 From: rodriguezst <2828844+rodriguezst@users.noreply.github.com> Date: Mon, 13 Jun 2022 11:59:42 +0000 Subject: [PATCH 4/7] Use textarea instead of input tags for certs --- WebCfgServer.cpp | 32 +++++++++++++++++++++++++++++--- WebCfgServer.h | 1 + networkDevices/WifiDevice.cpp | 6 +++--- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/WebCfgServer.cpp b/WebCfgServer.cpp index adc1448..af24b06 100644 --- a/WebCfgServer.cpp +++ b/WebCfgServer.cpp @@ -452,9 +452,9 @@ void WebCfgServer::buildMqttConfigHtml(String &response) printInputField(response, "MQTTPORT", "MQTT Broker port", _preferences->getInt(preference_mqtt_broker_port), 5); printInputField(response, "MQTTUSER", "MQTT User (# to clear)", _preferences->getString(preference_mqtt_user).c_str(), 30); printInputField(response, "MQTTPASS", "MQTT Password", "*", 30, true); - printInputField(response, "MQTTCA", "MQTT SSL CA Certificate", _preferences->getString(preference_mqtt_ca).c_str(), 180); - printInputField(response, "MQTTCRT", "MQTT SSL Client Certificate", _preferences->getString(preference_mqtt_crt).c_str(), 180); - printInputField(response, "MQTTKEY", "MQTT SSL Client Key", _preferences->getString(preference_mqtt_key).c_str(), 180); + printTextarea(response, "MQTTCA", "MQTT SSL CA Certificate", _preferences->getString(preference_mqtt_ca).c_str(), 1800); + printTextarea(response, "MQTTCRT", "MQTT SSL Client Certificate", _preferences->getString(preference_mqtt_crt).c_str(), 1800); + printTextarea(response, "MQTTKEY", "MQTT SSL Client Key", _preferences->getString(preference_mqtt_key).c_str(), 1800); printInputField(response, "NETTIMEOUT", "Network Timeout until restart (seconds; -1 to disable)", _preferences->getInt(preference_network_timeout), 5); response.concat(""); response.concat("
"); @@ -598,6 +598,32 @@ void WebCfgServer::printCheckBox(String &response, const char *token, const char response.concat("/>"); } +void WebCfgServer::printTextarea(String& response, + const char *token, + const char *description, + const char *value, + const size_t maxLength) +{ + char maxLengthStr[20]; + + itoa(maxLength, maxLengthStr, 10); + + response.concat(""); + response.concat(""); + response.concat(description); + response.concat(""); + response.concat(""); + response.concat(" "); + response.concat(""); + response.concat(""); +} + void WebCfgServer::printParameter(String& response, const char *description, const char *value) { response.concat(""); diff --git a/WebCfgServer.h b/WebCfgServer.h index f8152bf..6d0b4b3 100644 --- a/WebCfgServer.h +++ b/WebCfgServer.h @@ -41,6 +41,7 @@ private: void printInputField(String& response, const char* token, const char* description, const char* value, const size_t maxLength, const bool isPassword = false); void printInputField(String& response, const char* token, const char* description, const int value, size_t maxLength); void printCheckBox(String& response, const char* token, const char* description, const bool value); + void printTextarea(String& response, const char *token, const char *description, const char *value, const size_t maxLength); void printParameter(String& response, const char* description, const char* value); diff --git a/networkDevices/WifiDevice.cpp b/networkDevices/WifiDevice.cpp index cf46cbd..6eee29e 100644 --- a/networkDevices/WifiDevice.cpp +++ b/networkDevices/WifiDevice.cpp @@ -13,14 +13,14 @@ WifiDevice::WifiDevice(const String& hostname, Preferences* _preferences) if(caLength > 1) // length is 1 when empty { Serial.println(F("MQTT over TLS.")); - Serial.print(_ca); + Serial.println(_ca); _wifiClientSecure = new WiFiClientSecure(); _wifiClientSecure->setCACert(_ca); if(crtLength > 1 && keyLength > 1) // length is 1 when empty { Serial.println(F("MQTT with client certificate.")); - Serial.print(_cert); - Serial.print(_key); + Serial.println(_cert); + Serial.println(_key); _wifiClientSecure->setCertificate(_cert); _wifiClientSecure->setPrivateKey(_key); } From cb4e16cee4eeb650c2d4e140cb85487e40deb66d Mon Sep 17 00:00:00 2001 From: rodriguezst <2828844+rodriguezst@users.noreply.github.com> Date: Mon, 13 Jun 2022 14:24:49 +0000 Subject: [PATCH 5/7] Rebase from master branch --- networkDevices/WifiDevice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networkDevices/WifiDevice.cpp b/networkDevices/WifiDevice.cpp index 6eee29e..8a26b59 100644 --- a/networkDevices/WifiDevice.cpp +++ b/networkDevices/WifiDevice.cpp @@ -74,7 +74,7 @@ void WifiDevice::initialize() Serial.println(WiFi.localIP().toString()); } - _mqttClient.setBufferSize(_mqttMaxBufferSize); + _mqttClient->setBufferSize(_mqttMaxBufferSize); } void WifiDevice::reconfigure() From 9b1adf7032a0b18075e7e587f7459311a0ef1c19 Mon Sep 17 00:00:00 2001 From: rodriguezst <2828844+rodriguezst@users.noreply.github.com> Date: Mon, 13 Jun 2022 14:40:51 +0000 Subject: [PATCH 6/7] Set certificate buffer sizes at CMakelists.txt --- CMakeLists.txt | 5 +++++ WebCfgServer.cpp | 6 +++--- networkDevices/WifiDevice.h | 4 ---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a9816e8..58cdf70 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,11 @@ project(nuki_hub CXX) set(LOG_LEVEL ARDUHAL_LOG_LEVEL_NONE) +# Length of char arrays to store certificates for MQTTS +add_compile_definitions(TLS_CA_MAX_SIZE=1800) +add_compile_definitions(TLS_CERT_MAX_SIZE=1800) +add_compile_definitions(TLS_KEY_MAX_SIZE=1800) + include_directories(${PROJECT_NAME} PRIVATE lib/Crc16 diff --git a/WebCfgServer.cpp b/WebCfgServer.cpp index af24b06..8cec783 100644 --- a/WebCfgServer.cpp +++ b/WebCfgServer.cpp @@ -452,9 +452,9 @@ void WebCfgServer::buildMqttConfigHtml(String &response) printInputField(response, "MQTTPORT", "MQTT Broker port", _preferences->getInt(preference_mqtt_broker_port), 5); printInputField(response, "MQTTUSER", "MQTT User (# to clear)", _preferences->getString(preference_mqtt_user).c_str(), 30); printInputField(response, "MQTTPASS", "MQTT Password", "*", 30, true); - printTextarea(response, "MQTTCA", "MQTT SSL CA Certificate", _preferences->getString(preference_mqtt_ca).c_str(), 1800); - printTextarea(response, "MQTTCRT", "MQTT SSL Client Certificate", _preferences->getString(preference_mqtt_crt).c_str(), 1800); - printTextarea(response, "MQTTKEY", "MQTT SSL Client Key", _preferences->getString(preference_mqtt_key).c_str(), 1800); + printTextarea(response, "MQTTCA", "MQTT SSL CA Certificate", _preferences->getString(preference_mqtt_ca).c_str(), TLS_CA_MAX_SIZE); + printTextarea(response, "MQTTCRT", "MQTT SSL Client Certificate", _preferences->getString(preference_mqtt_crt).c_str(), TLS_CERT_MAX_SIZE); + printTextarea(response, "MQTTKEY", "MQTT SSL Client Key", _preferences->getString(preference_mqtt_key).c_str(), TLS_KEY_MAX_SIZE); printInputField(response, "NETTIMEOUT", "Network Timeout until restart (seconds; -1 to disable)", _preferences->getInt(preference_network_timeout), 5); response.concat(""); response.concat("
"); diff --git a/networkDevices/WifiDevice.h b/networkDevices/WifiDevice.h index ec1ed1e..8f2e522 100644 --- a/networkDevices/WifiDevice.h +++ b/networkDevices/WifiDevice.h @@ -6,10 +6,6 @@ #include "NetworkDevice.h" #include "../SpiffsCookie.h" -#define TLS_CA_MAX_SIZE 1800 -#define TLS_CERT_MAX_SIZE 1800 -#define TLS_KEY_MAX_SIZE 1800 - class WifiDevice : public NetworkDevice { public: From 1c4fc0e9020427558aff9a013bbd10c49551af73 Mon Sep 17 00:00:00 2001 From: rodriguezst <2828844+rodriguezst@users.noreply.github.com> Date: Wed, 15 Jun 2022 10:35:50 +0000 Subject: [PATCH 7/7] Print SSL errors for debugging --- CMakeLists.txt | 4 ++-- Network.cpp | 2 ++ networkDevices/NetworkDevice.h | 1 + networkDevices/W5500Device.cpp | 7 +++++++ networkDevices/W5500Device.h | 1 + networkDevices/WifiDevice.cpp | 12 ++++++++++++ networkDevices/WifiDevice.h | 1 + 7 files changed, 26 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 58cdf70..8dd9c71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,8 @@ project(nuki_hub CXX) set(LOG_LEVEL ARDUHAL_LOG_LEVEL_NONE) # Length of char arrays to store certificates for MQTTS -add_compile_definitions(TLS_CA_MAX_SIZE=1800) -add_compile_definitions(TLS_CERT_MAX_SIZE=1800) +add_compile_definitions(TLS_CA_MAX_SIZE=1500) +add_compile_definitions(TLS_CERT_MAX_SIZE=1500) add_compile_definitions(TLS_KEY_MAX_SIZE=1800) include_directories(${PROJECT_NAME} diff --git a/Network.cpp b/Network.cpp index 61435fc..91fb69b 100644 --- a/Network.cpp +++ b/Network.cpp @@ -161,6 +161,8 @@ bool Network::reconnect() { Serial.print(F("MQTT connect failed, rc=")); Serial.println(_device->mqttClient()->state()); + _device->printError(); + _device->mqttClient()->disconnect(); _mqttConnected = false; _nextReconnect = millis() + 5000; } diff --git a/networkDevices/NetworkDevice.h b/networkDevices/NetworkDevice.h index e1ec20c..7fc65bf 100644 --- a/networkDevices/NetworkDevice.h +++ b/networkDevices/NetworkDevice.h @@ -14,6 +14,7 @@ public: virtual void initialize() = 0; virtual bool reconnect() = 0; virtual void reconfigure() = 0; + virtual void printError() = 0; virtual void update() = 0; diff --git a/networkDevices/W5500Device.cpp b/networkDevices/W5500Device.cpp index 1041046..79bbc85 100644 --- a/networkDevices/W5500Device.cpp +++ b/networkDevices/W5500Device.cpp @@ -117,6 +117,13 @@ void W5500Device::resetDevice() nwDelay(1500); } + +void W5500Device::printError() +{ + Serial.print(F("Free Heap: ")); + Serial.println(ESP.getFreeHeap()); +} + PubSubClient *W5500Device::mqttClient() { return _mqttClient; diff --git a/networkDevices/W5500Device.h b/networkDevices/W5500Device.h index 6cd1bc5..9ba726d 100644 --- a/networkDevices/W5500Device.h +++ b/networkDevices/W5500Device.h @@ -13,6 +13,7 @@ public: virtual void initialize(); virtual bool reconnect(); virtual void reconfigure(); + virtual void printError(); virtual void update(); diff --git a/networkDevices/WifiDevice.cpp b/networkDevices/WifiDevice.cpp index 8a26b59..3428e99 100644 --- a/networkDevices/WifiDevice.cpp +++ b/networkDevices/WifiDevice.cpp @@ -84,6 +84,18 @@ void WifiDevice::reconfigure() ESP.restart(); } +void WifiDevice::printError() +{ + if(_wifiClientSecure != nullptr) + { + char lastError[100]; + _wifiClientSecure->lastError(lastError,100); + Serial.println(lastError); + } + Serial.print(F("Free Heap: ")); + Serial.println(ESP.getFreeHeap()); +} + bool WifiDevice::isConnected() { return WiFi.isConnected(); diff --git a/networkDevices/WifiDevice.h b/networkDevices/WifiDevice.h index 8f2e522..27b6728 100644 --- a/networkDevices/WifiDevice.h +++ b/networkDevices/WifiDevice.h @@ -14,6 +14,7 @@ public: virtual void initialize(); virtual void reconfigure(); virtual bool reconnect(); + virtual void printError(); virtual void update();