Merge pull request #3455 from jomjol/mqtt-add-ValidateServerCert-Parameter

MQTT add validate server cert parameter
This commit is contained in:
SybexX
2025-02-14 21:28:29 +01:00
committed by GitHub
15 changed files with 134 additions and 65 deletions

View File

@@ -40,6 +40,7 @@ void ClassFlowMQTT::SetInitialParameter(void)
caCertFilename = ""; caCertFilename = "";
clientCertFilename = ""; clientCertFilename = "";
clientKeyFilename = ""; clientKeyFilename = "";
validateServerCert = true;
clientname = wlan_config.hostname; clientname = wlan_config.hostname;
OldValue = ""; OldValue = "";
@@ -109,15 +110,19 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
std::string _param = GetParameterName(splitted[0]); std::string _param = GetParameterName(splitted[0]);
if ((toUpper(_param) == "CACERT") && (splitted.size() > 1)) if ((toUpper(_param) == "CACERT") && (splitted.size() > 1))
{ {
this->caCertFilename = splitted[1]; this->caCertFilename = "/sdcard" + splitted[1];
}
if ((toUpper(_param) == "VALIDATESERVERCERT") && (splitted.size() > 1))
{
validateServerCert = alphanumericToBoolean(splitted[1]);
} }
if ((toUpper(_param) == "CLIENTCERT") && (splitted.size() > 1)) if ((toUpper(_param) == "CLIENTCERT") && (splitted.size() > 1))
{ {
this->clientCertFilename = splitted[1]; this->clientCertFilename = "/sdcard" + splitted[1];
} }
if ((toUpper(_param) == "CLIENTKEY") && (splitted.size() > 1)) if ((toUpper(_param) == "CLIENTKEY") && (splitted.size() > 1))
{ {
this->clientKeyFilename = splitted[1]; this->clientKeyFilename = "/sdcard" + splitted[1];
} }
if ((toUpper(_param) == "USER") && (splitted.size() > 1)) if ((toUpper(_param) == "USER") && (splitted.size() > 1))
{ {
@@ -133,10 +138,8 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
} }
if ((toUpper(_param) == "RETAINMESSAGES") && (splitted.size() > 1)) if ((toUpper(_param) == "RETAINMESSAGES") && (splitted.size() > 1))
{ {
if (toUpper(splitted[1]) == "TRUE") { SetRetainFlag = alphanumericToBoolean(splitted[1]);
SetRetainFlag = true; setMqtt_Server_Retain(SetRetainFlag);
setMqtt_Server_Retain(SetRetainFlag);
}
} }
if ((toUpper(_param) == "HOMEASSISTANTDISCOVERY") && (splitted.size() > 1)) if ((toUpper(_param) == "HOMEASSISTANTDISCOVERY") && (splitted.size() > 1))
{ {
@@ -225,7 +228,7 @@ bool ClassFlowMQTT::Start(float AutoInterval)
mqttServer_setParameter(flowpostprocessing->GetNumbers(), keepAlive, roundInterval); mqttServer_setParameter(flowpostprocessing->GetNumbers(), keepAlive, roundInterval);
bool MQTTConfigCheck = MQTT_Configure(uri, clientname, user, password, maintopic, domoticzintopic, LWT_TOPIC, LWT_CONNECTED, bool MQTTConfigCheck = MQTT_Configure(uri, clientname, user, password, maintopic, domoticzintopic, LWT_TOPIC, LWT_CONNECTED,
LWT_DISCONNECTED, caCertFilename, clientCertFilename, clientKeyFilename, LWT_DISCONNECTED, caCertFilename, validateServerCert, clientCertFilename, clientKeyFilename,
keepAlive, SetRetainFlag, (void *)&GotConnected); keepAlive, SetRetainFlag, (void *)&GotConnected);
if (!MQTTConfigCheck) { if (!MQTTConfigCheck) {

View File

@@ -20,6 +20,7 @@ protected:
ClassFlowPostProcessing* flowpostprocessing; ClassFlowPostProcessing* flowpostprocessing;
std::string user, password; std::string user, password;
std::string caCertFilename, clientCertFilename, clientKeyFilename; std::string caCertFilename, clientCertFilename, clientKeyFilename;
bool validateServerCert;
bool SetRetainFlag; bool SetRetainFlag;
int keepAlive; // Seconds int keepAlive; // Seconds
float roundInterval; // Minutes float roundInterval; // Minutes

View File

@@ -16,7 +16,6 @@
#include "esp_timer.h" #include "esp_timer.h"
#endif #endif
static const char *TAG = "MQTT IF"; static const char *TAG = "MQTT IF";
std::map<std::string, std::function<void()>>* connectFunktionMap = NULL; std::map<std::string, std::function<void()>>* connectFunktionMap = NULL;
@@ -36,11 +35,11 @@ bool mqtt_connected = false;
esp_mqtt_client_handle_t client = NULL; esp_mqtt_client_handle_t client = NULL;
std::string uri, client_id, lwt_topic, lwt_connected, lwt_disconnected, user, password, maintopic, domoticz_in_topic; std::string uri, client_id, lwt_topic, lwt_connected, lwt_disconnected, user, password, maintopic, domoticz_in_topic;
std::string caCert, clientCert, clientKey; std::string caCert, clientCert, clientKey;
bool validateServerCert = true;
int keepalive; int keepalive;
bool SetRetainFlag; bool SetRetainFlag;
void (*callbackOnConnected)(std::string, bool) = NULL; void (*callbackOnConnected)(std::string, bool) = NULL;
bool MQTTPublish(std::string _key, std::string _content, int qos, bool retained_flag) bool MQTTPublish(std::string _key, std::string _content, int qos, bool retained_flag)
{ {
if (!mqtt_enabled) { // MQTT sevice not started / configured (MQTT_Init not called before) if (!mqtt_enabled) { // MQTT sevice not started / configured (MQTT_Init not called before)
@@ -95,7 +94,6 @@ bool MQTTPublish(std::string _key, std::string _content, int qos, bool retained_
} }
} }
static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) { static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) {
std::string topic = ""; std::string topic = "";
switch (event->event_id) { switch (event->event_id) {
@@ -197,16 +195,14 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) {
return ESP_OK; return ESP_OK;
} }
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) { static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, (int)event_id); ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, (int)event_id);
mqtt_event_handler_cb((esp_mqtt_event_handle_t) event_data); mqtt_event_handler_cb((esp_mqtt_event_handle_t) event_data);
} }
bool MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password, bool MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password,
std::string _maintopic, std::string _domoticz_in_topic, std::string _lwt, std::string _lwt_connected, std::string _lwt_disconnected, std::string _maintopic, std::string _domoticz_in_topic, std::string _lwt, std::string _lwt_connected, std::string _lwt_disconnected,
std::string _cacertfilename, std::string _clientcertfilename, std::string _clientkeyfilename, std::string _cacertfilename, bool _validateServerCert, std::string _clientcertfilename, std::string _clientkeyfilename,
int _keepalive, bool _SetRetainFlag, void *_callbackOnConnected) { int _keepalive, bool _SetRetainFlag, void *_callbackOnConnected) {
if ((_mqttURI.length() == 0) || (_maintopic.length() == 0) || (_clientid.length() == 0)) if ((_mqttURI.length() == 0) || (_maintopic.length() == 0) || (_clientid.length() == 0))
{ {
@@ -225,25 +221,45 @@ bool MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _us
domoticz_in_topic = _domoticz_in_topic; domoticz_in_topic = _domoticz_in_topic;
callbackOnConnected = ( void (*)(std::string, bool) )(_callbackOnConnected); callbackOnConnected = ( void (*)(std::string, bool) )(_callbackOnConnected);
if (_clientcertfilename.length() && _clientkeyfilename.length()){ if (_clientcertfilename.length() && _clientkeyfilename.length()) {
std::ifstream cert_ifs(_clientcertfilename); std::ifstream cert_ifs(_clientcertfilename);
std::string cert_content((std::istreambuf_iterator<char>(cert_ifs)), (std::istreambuf_iterator<char>())); if (cert_ifs.is_open()) {
clientCert = cert_content; std::string cert_content((std::istreambuf_iterator<char>(cert_ifs)), (std::istreambuf_iterator<char>()));
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "using clientCert: " + _clientcertfilename); clientCert = cert_content;
cert_ifs.close();
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "using clientCert: " + _clientcertfilename);
}
else {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "could not open clientCert: " + _clientcertfilename);
}
std::ifstream key_ifs(_clientkeyfilename); std::ifstream key_ifs(_clientkeyfilename);
std::string key_content((std::istreambuf_iterator<char>(key_ifs)), (std::istreambuf_iterator<char>())); if (key_ifs.is_open()) {
clientKey = key_content; std::string key_content((std::istreambuf_iterator<char>(key_ifs)), (std::istreambuf_iterator<char>()));
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "using clientKey: " + _clientkeyfilename); clientKey = key_content;
key_ifs.close();
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "using clientKey: " + _clientkeyfilename);
}
else {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "could not open clientKey: " + _clientkeyfilename);
}
} }
if (_cacertfilename.length() ){ if (_cacertfilename.length()) {
std::ifstream ifs(_cacertfilename); std::ifstream ca_ifs(_cacertfilename);
std::string content((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>())); if (ca_ifs.is_open()) {
caCert = content; std::string content((std::istreambuf_iterator<char>(ca_ifs)), (std::istreambuf_iterator<char>()));
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "using caCert: " + _cacertfilename); caCert = content;
ca_ifs.close();
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "using caCert: " + _cacertfilename);
}
else {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "could not open caCert: " + _cacertfilename);
}
} }
validateServerCert = _validateServerCert;
if (_user.length() && _password.length()){ if (_user.length() && _password.length()){
user = _user; user = _user;
password = _password; password = _password;
@@ -261,7 +277,6 @@ bool MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _us
return true; return true;
} }
int MQTT_Init() { int MQTT_Init() {
if (mqtt_initialized) { if (mqtt_initialized) {
return 0; return 0;
@@ -295,15 +310,18 @@ int MQTT_Init() {
mqtt_cfg.session.last_will.msg = lwt_disconnected.c_str(); mqtt_cfg.session.last_will.msg = lwt_disconnected.c_str();
mqtt_cfg.session.last_will.msg_len = (int)(lwt_disconnected.length()); mqtt_cfg.session.last_will.msg_len = (int)(lwt_disconnected.length());
mqtt_cfg.session.keepalive = keepalive; mqtt_cfg.session.keepalive = keepalive;
mqtt_cfg.buffer.size = 1536; // size of MQTT send/receive buffer (Default: 1024) mqtt_cfg.buffer.size = 2048; // size of MQTT send/receive buffer
if (caCert.length()){ if (caCert.length()) {
mqtt_cfg.broker.verification.certificate = caCert.c_str(); mqtt_cfg.broker.verification.certificate = caCert.c_str();
mqtt_cfg.broker.verification.certificate_len = caCert.length() + 1; mqtt_cfg.broker.verification.certificate_len = caCert.length() + 1;
mqtt_cfg.broker.verification.skip_cert_common_name_check = true;
// Skip any validation of server certificate CN field, this reduces the
// security of TLS and makes the *MQTT* client susceptible to MITM attacks
mqtt_cfg.broker.verification.skip_cert_common_name_check = !validateServerCert;
} }
if (clientCert.length() && clientKey.length()){ if (clientCert.length() && clientKey.length()) {
mqtt_cfg.credentials.authentication.certificate = clientCert.c_str(); mqtt_cfg.credentials.authentication.certificate = clientCert.c_str();
mqtt_cfg.credentials.authentication.certificate_len = clientCert.length() + 1; mqtt_cfg.credentials.authentication.certificate_len = clientCert.length() + 1;
@@ -356,7 +374,6 @@ int MQTT_Init() {
} }
void MQTTdestroy_client(bool _disable = false) { void MQTTdestroy_client(bool _disable = false) {
if (client) { if (client) {
if (mqtt_connected) { if (mqtt_connected) {
@@ -374,17 +391,14 @@ void MQTTdestroy_client(bool _disable = false) {
mqtt_configOK = false; mqtt_configOK = false;
} }
bool getMQTTisEnabled() { bool getMQTTisEnabled() {
return mqtt_enabled; return mqtt_enabled;
} }
bool getMQTTisConnected() { bool getMQTTisConnected() {
return mqtt_connected; return mqtt_connected;
} }
bool mqtt_handler_flow_start(std::string _topic, char* _data, int _data_len) bool mqtt_handler_flow_start(std::string _topic, char* _data, int _data_len)
{ {
ESP_LOGD(TAG, "Handler called: topic %s, data %.*s", _topic.c_str(), _data_len, _data); ESP_LOGD(TAG, "Handler called: topic %s, data %.*s", _topic.c_str(), _data_len, _data);
@@ -393,7 +407,6 @@ bool mqtt_handler_flow_start(std::string _topic, char* _data, int _data_len)
return ESP_OK; return ESP_OK;
} }
bool mqtt_handler_set_prevalue(std::string _topic, char* _data, int _data_len) bool mqtt_handler_set_prevalue(std::string _topic, char* _data, int _data_len)
{ {
//ESP_LOGD(TAG, "Handler called: topic %s, data %.*s", _topic.c_str(), _data_len, _data); //ESP_LOGD(TAG, "Handler called: topic %s, data %.*s", _topic.c_str(), _data_len, _data);
@@ -429,7 +442,6 @@ bool mqtt_handler_set_prevalue(std::string _topic, char* _data, int _data_len)
return ESP_FAIL; return ESP_FAIL;
} }
void MQTTconnected(){ void MQTTconnected(){
if (mqtt_connected) { if (mqtt_connected) {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Connected to broker"); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Connected to broker");
@@ -464,7 +476,6 @@ void MQTTconnected(){
} }
} }
void MQTTregisterConnectFunction(std::string name, std::function<void()> func){ void MQTTregisterConnectFunction(std::string name, std::function<void()> func){
ESP_LOGD(TAG, "MQTTregisteronnectFunction %s\r\n", name.c_str()); ESP_LOGD(TAG, "MQTTregisteronnectFunction %s\r\n", name.c_str());
if (connectFunktionMap == NULL) { if (connectFunktionMap == NULL) {
@@ -483,7 +494,6 @@ void MQTTregisterConnectFunction(std::string name, std::function<void()> func){
} }
} }
void MQTTunregisterConnectFunction(std::string name){ void MQTTunregisterConnectFunction(std::string name){
ESP_LOGD(TAG, "unregisterConnnectFunction %s\r\n", name.c_str()); ESP_LOGD(TAG, "unregisterConnnectFunction %s\r\n", name.c_str());
if ((connectFunktionMap != NULL) && (connectFunktionMap->find(name) != connectFunktionMap->end())) { if ((connectFunktionMap != NULL) && (connectFunktionMap->find(name) != connectFunktionMap->end())) {
@@ -491,7 +501,6 @@ void MQTTunregisterConnectFunction(std::string name){
} }
} }
void MQTTregisterSubscribeFunction(std::string topic, std::function<bool(std::string, char*, int)> func){ void MQTTregisterSubscribeFunction(std::string topic, std::function<bool(std::string, char*, int)> func){
ESP_LOGD(TAG, "registerSubscribeFunction %s", topic.c_str()); ESP_LOGD(TAG, "registerSubscribeFunction %s", topic.c_str());
if (subscribeFunktionMap == NULL) { if (subscribeFunktionMap == NULL) {
@@ -506,7 +515,6 @@ void MQTTregisterSubscribeFunction(std::string topic, std::function<bool(std::st
(*subscribeFunktionMap)[topic] = func; (*subscribeFunktionMap)[topic] = func;
} }
void MQTTdestroySubscribeFunction(){ void MQTTdestroySubscribeFunction(){
if (subscribeFunktionMap != NULL) { if (subscribeFunktionMap != NULL) {
if (mqtt_connected) { if (mqtt_connected) {

View File

@@ -11,7 +11,7 @@
bool MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password, bool MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password,
std::string _maintopic, std::string _domoticz_in_topic, std::string _lwt, std::string _lwt_connected, std::string _lwt_disconnected, std::string _maintopic, std::string _domoticz_in_topic, std::string _lwt, std::string _lwt_connected, std::string _lwt_disconnected,
std::string _cacertfilename, std::string _clientcertfilename, std::string _clientkeyfilename, std::string _cacertfilename, bool _validateServerCert, std::string _clientcertfilename, std::string _clientkeyfilename,
int _keepalive, bool SetRetainFlag, void *callbackOnConnected); int _keepalive, bool SetRetainFlag, void *callbackOnConnected);
int MQTT_Init(); int MQTT_Init();
void MQTTdestroy_client(bool _disable); void MQTTdestroy_client(bool _disable);

View File

@@ -384,6 +384,7 @@ extern "C" void app_main(void)
MakeDir("/sdcard/firmware"); // mandatory for OTA firmware update MakeDir("/sdcard/firmware"); // mandatory for OTA firmware update
MakeDir("/sdcard/img_tmp"); // mandatory for setting up alignment marks MakeDir("/sdcard/img_tmp"); // mandatory for setting up alignment marks
MakeDir("/sdcard/demo"); // mandatory for demo mode MakeDir("/sdcard/demo"); // mandatory for demo mode
MakeDir("/sdcard/config/certs"); // mandatory for mqtt certificates
// Check for updates // Check for updates
// ******************************************** // ********************************************

View File

@@ -57,8 +57,15 @@ build_flags =
${common:esp32-idf.build_flags} ${common:esp32-idf.build_flags}
${flags:runtime.build_flags} ${flags:runtime.build_flags}
; ### Sofware options : (can be set in defines.h) ; ### Sofware options : (can be set in defines.h)
-D BOARD_ESP32CAM_AITHINKER -D BOARD_ESP32CAM_AITHINKER
-D ENABLE_MQTT -D ENABLE_MQTT
;-D MQTT_PROTOCOL_311
-D MQTT_ENABLE_SSL
;-D MQTT_ENABLE_WS
;-D MQTT_ENABLE_WSS
-D MQTT_SUPPORTED_FEATURE_SKIP_CRT_CMN_NAME_CHECK
;-D MQTT_SUPPORTED_FEATURE_CRT_CMN_NAME
;-D MQTT_SUPPORTED_FEATURE_CLIENT_KEY_PASSWORD
-D ENABLE_INFLUXDB -D ENABLE_INFLUXDB
-D ENABLE_WEBHOOK -D ENABLE_WEBHOOK
-D ENABLE_SOFTAP -D ENABLE_SOFTAP

View File

@@ -127,6 +127,12 @@ CONFIG_MQTT_USE_CUSTOM_CONFIG=y
#CONFIG_MQTT_OUTBOX_EXPIRED_TIMEOUT_MS=5000 #CONFIG_MQTT_OUTBOX_EXPIRED_TIMEOUT_MS=5000
#CONFIG_MQTT_CUSTOM_OUTBOX=y # -> Use custom outbox in components/jomjol_mqtt/mqtt_outbox.h/cpp. If USE_PSRAM is enabled in there, it will save 10 kBytes of internal RAM. How ever it also leads to memory fragmentation, see https://github.com/jomjol/AI-on-the-edge-device/issues/2200 #CONFIG_MQTT_CUSTOM_OUTBOX=y # -> Use custom outbox in components/jomjol_mqtt/mqtt_outbox.h/cpp. If USE_PSRAM is enabled in there, it will save 10 kBytes of internal RAM. How ever it also leads to memory fragmentation, see https://github.com/jomjol/AI-on-the-edge-device/issues/2200
#
# mbedTLS
#
CONFIG_MBEDTLS_HAVE_TIME=y
CONFIG_MBEDTLS_HAVE_TIME_DATE=y
# #
# ESP-Driver:LEDC Configurations # ESP-Driver:LEDC Configurations
# #

View File

@@ -43,5 +43,6 @@ Hostname
RSSIThreshold RSSIThreshold
TimeServer TimeServer
CACert CACert
ValidateServerCert
ClientCert ClientCert
ClientKey ClientKey

View File

@@ -1,21 +1,24 @@
# Parameter `CACert` # Parameter `CACert`
Default Value: `""` Default Value: `""`
Example: `/config/certs/RootCA.pem`. Example: `/config/certs/RootCA.crt`.
!!! Warning !!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does! This is an **Expert Parameter**! Only change it if you understand what it does!
Path to the CA certificate file. Path to the CA certificate file.
This is part of the configuration to enable TLS for MQTT. This is part of the configuration to enable TLS 1.2 for MQTT.<br>
The CA Certificate is used by the client to validate the broker is who it claims to be. The CA Certificate is used by the client to validate the broker is who it claims to be.
It allows the client to authenticate the server, which is the first part of the MTLS handshake. It allows the client to authenticate the server, which is the first part of the MTLS handshake.
Usually there is a common RootCA certificate for the MQTT broker Usually there is a common RootCA certificate for the MQTT broker.
More information is available [here](https://jomjol.github.io/AI-on-the-edge-device-docs/MQTT-API/#mqtt-tls).
For more information on how to create your own certificate, see: [mosquitto.org](https://mosquitto.org/man/mosquitto-tls-7.html) or [emqx.com](https://www.emqx.com/en/blog/emqx-server-ssl-tls-secure-connection-configuration-guide).
!!! Note !!! Note
This also means that you might have to change the protocol and port in [uri](https://jomjol.github.io/AI-on-the-edge-device-docs/Parameters/#parameter-uri) to `mqtts://example.com:8883`! This also means that you might have to change the protocol and port in [uri](https://jomjol.github.io/AI-on-the-edge-device-docs/Parameters/#parameter-uri) to `mqtts://example.com:8883`!
!!! Note Only Certificates up to 4096 Bit are supported!
Only TLS 1.2 is supported!

View File

@@ -1,22 +1,23 @@
# Parameter `ClientCert` # Parameter `ClientCert`
Default Value: `""` Default Value: `""`
Example: `/config/certs/client.pem.crt`. Example: `/config/certs/client.crt`.
!!! Warning !!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does! This is an **Expert Parameter**! Only change it if you understand what it does!
Path to the Client Certificate file. Path to the Client Certificate file.
This is part of the configuration to enable TLS for MQTT. This is part of the configuration to enable TLS 1.2 for MQTT.<br>
The Client Certificate is used by the client to prove its identity to the server, in conjunction with the Client Key. The Client Certificate is used by the client to prove its identity to the server, in conjunction with the Client Key.
It is the second part of the MTLS handshake. It is the second part of the MTLS handshake.
Usually there is a one pair of Client Certificate/Key for each client that connects to the MQTT broker Usually there is a one pair of Client Certificate/Key for each client that connects to the MQTT broker.
More information is available [here](https://jomjol.github.io/AI-on-the-edge-device-docs/MQTT-API/#mqtt-tls).
For more information on how to create your own certificate, see: [mosquitto.org](https://mosquitto.org/man/mosquitto-tls-7.html) or [emqx.com](https://www.emqx.com/en/blog/emqx-server-ssl-tls-secure-connection-configuration-guide).
!!! Note !!! Note
If set, `ClientKey` must be set too If set, `ClientKey` must be set too.
This also means that you might have to change the protocol and port in [uri](https://jomjol.github.io/AI-on-the-edge-device-docs/Parameters/#parameter-uri) to `mqtts://example.com:8883`! This also means that you might have to change the protocol and port in [uri](https://jomjol.github.io/AI-on-the-edge-device-docs/Parameters/#parameter-uri) to `mqtts://example.com:8883`!
!!! Note
Only TLS 1.2 is supported!

View File

@@ -1,22 +1,22 @@
# Parameter `ClientKey` # Parameter `ClientKey`
Default Value: `""` Default Value: `""`
Example: `/config/certs/client.pem.key`. Example: `/config/certs/client.key`.
!!! Warning !!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does! This is an **Expert Parameter**! Only change it if you understand what it does!
Path to the Client Key file. Path to the Client Key file.
This is part of the configuration to enable TLS for MQTT. This is part of the configuration to enable TLS 1.2 for MQTT.<br>
The Client Key is used by the client to prove its identity to the server, in conjunction with the Client Certificate. The Client Key is used by the client to prove its identity to the server, in conjunction with the Client Certificate.
It is the second part of the MTLS handshake. It is the second part of the MTLS handshake.
Usually there is a one pair of Client Certificate/Key for each client that connects to the MQTT broker Usually there is a one pair of Client Certificate/Key for each client that connects to the MQTT broker
!!! Note For more information on how to create your own certificate, see: [mosquitto.org](https://mosquitto.org/man/mosquitto-tls-7.html) or [emqx.com](https://www.emqx.com/en/blog/emqx-server-ssl-tls-secure-connection-configuration-guide).
If set, `ClientCert` must be set too
This also means that you might have to change the protocol and port in [uri](https://jomjol.github.io/AI-on-the-edge-device-docs/Parameters/#parameter-uri) to `mqtts://example.com:8883`!
!!! Note !!! Note
Only TLS 1.2 is supported! If set, `ClientCert` must be set too.
This also means that you might have to change the protocol and port in [uri](https://jomjol.github.io/AI-on-the-edge-device-docs/Parameters/#parameter-uri) to `mqtts://example.com:8883`!

View File

@@ -0,0 +1,20 @@
# Parameter `ValidateServerCert`
Default Value: `true`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
Enable or disable the validation of the server certificate CN field.<br>
If `enabled (true)`, the certificate sent by the server is validated using the configured [Root CA Certificate file](https://jomjol.github.io/AI-on-the-edge-device-docs/Parameters/#parameter-cacert).<br>
The server name in [uri](https://jomjol.github.io/AI-on-the-edge-device-docs/Parameters/#parameter-uri) is compared with the CN field of the server certificate.<br>
A connection is only established if they agree. It ensures the origin of the server.
If `disabled (false)`, the ESP32 skipped any validation of server certificate CN field.<br>
This reduces the security of TLS and makes the *MQTT* client susceptible to MITM attacks.
!!! Note
This also means that you might have to change the protocol and port in to `mqtts://example.com:8883`!
If you use public brokers, is recommended to set this parameter to "enabled (true)".

View File

@@ -87,6 +87,7 @@ HomeassistantDiscovery = false
;CACert = /config/certs/RootCA.pem ;CACert = /config/certs/RootCA.pem
;ClientCert = /config/certs/client.pem.crt ;ClientCert = /config/certs/client.pem.crt
;ClientKey = /config/certs/client.pem.key ;ClientKey = /config/certs/client.pem.key
;ValidateServerCert = true
;DomoticzTopicIn = domoticz/in ;DomoticzTopicIn = domoticz/in
;main.DomoticzIDX = 0 ;main.DomoticzIDX = 0

View File

@@ -1120,6 +1120,20 @@
<td>$TOOLTIP_MQTT_ClientKey</td> <td>$TOOLTIP_MQTT_ClientKey</td>
</tr> </tr>
<tr class="MQTTItem expert" unused_id="exMqtt">
<td class="indent1">
<input type="checkbox" id="MQTT_ValidateServerCert_enabled" value="1" onclick = 'InvertEnableItem("MQTT", "ValidateServerCert")' unchecked >
<label for=MQTT_ValidateServerCert_enabled><class id="MQTT_ValidateServerCert_text" style="color:black;">Validate ServerCert</class></label>
</td>
<td>
<select id="MQTT_ValidateServerCert_value1">
<option value="true" selected>enable (true)</option>
<option value="false">disable (false)</option>
</select>
</td>
<td>$TOOLTIP_MQTT_ValidateServerCert</td>
</tr>
<tr class="MQTTItem"> <tr class="MQTTItem">
<td class="indent1"> <td class="indent1">
<label><class id="MQTT_RetainMessages_text" style="color:black;">Retain Messages</class></label> <label><class id="MQTT_RetainMessages_text" style="color:black;">Retain Messages</class></label>
@@ -2353,6 +2367,7 @@ function UpdateInput() {
WriteParameter(param, category, "MQTT", "CACert", true); WriteParameter(param, category, "MQTT", "CACert", true);
WriteParameter(param, category, "MQTT", "ClientCert", true); WriteParameter(param, category, "MQTT", "ClientCert", true);
WriteParameter(param, category, "MQTT", "ClientKey", true); WriteParameter(param, category, "MQTT", "ClientKey", true);
WriteParameter(param, category, "MQTT", "ValidateServerCert", true);
WriteParameter(param, category, "MQTT", "DomoticzTopicIn", true); WriteParameter(param, category, "MQTT", "DomoticzTopicIn", true);
WriteParameter(param, category, "InfluxDB", "Uri", true); WriteParameter(param, category, "InfluxDB", "Uri", true);
@@ -2521,6 +2536,7 @@ function ReadParameterAll() {
ReadParameter(param, "MQTT", "CACert", true); ReadParameter(param, "MQTT", "CACert", true);
ReadParameter(param, "MQTT", "ClientCert", true); ReadParameter(param, "MQTT", "ClientCert", true);
ReadParameter(param, "MQTT", "ClientKey", true); ReadParameter(param, "MQTT", "ClientKey", true);
ReadParameter(param, "MQTT", "ValidateServerCert", true);
ReadParameter(param, "MQTT", "DomoticzTopicIn", true); ReadParameter(param, "MQTT", "DomoticzTopicIn", true);
ReadParameter(param, "InfluxDB", "Uri", true); ReadParameter(param, "InfluxDB", "Uri", true);

View File

@@ -205,6 +205,7 @@ function ParseConfig() {
ParamAddValue(param, catname, "CACert"); ParamAddValue(param, catname, "CACert");
ParamAddValue(param, catname, "ClientCert"); ParamAddValue(param, catname, "ClientCert");
ParamAddValue(param, catname, "ClientKey"); ParamAddValue(param, catname, "ClientKey");
ParamAddValue(param, catname, "ValidateServerCert");
var catname = "InfluxDB"; var catname = "InfluxDB";
category[catname] = new Object(); category[catname] = new Object();