diff --git a/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp b/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp index 287f2da5..e0df96fc 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp @@ -40,6 +40,7 @@ void ClassFlowMQTT::SetInitialParameter(void) caCertFilename = ""; clientCertFilename = ""; clientKeyFilename = ""; + validateServerCert = true; clientname = wlan_config.hostname; OldValue = ""; @@ -110,6 +111,10 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph) if ((toUpper(_param) == "CACERT") && (splitted.size() > 1)) { this->caCertFilename = splitted[1]; + } + if ((toUpper(_param) == "VALIDATESERVERCERT") && (splitted.size() > 1)) + { + validateServerCert = alphanumericToBoolean(splitted[1]); } if ((toUpper(_param) == "CLIENTCERT") && (splitted.size() > 1)) { @@ -133,10 +138,8 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph) } if ((toUpper(_param) == "RETAINMESSAGES") && (splitted.size() > 1)) { - if (toUpper(splitted[1]) == "TRUE") { - SetRetainFlag = true; - setMqtt_Server_Retain(SetRetainFlag); - } + SetRetainFlag = alphanumericToBoolean(splitted[1]); + setMqtt_Server_Retain(SetRetainFlag); } if ((toUpper(_param) == "HOMEASSISTANTDISCOVERY") && (splitted.size() > 1)) { @@ -225,7 +228,7 @@ bool ClassFlowMQTT::Start(float AutoInterval) mqttServer_setParameter(flowpostprocessing->GetNumbers(), keepAlive, roundInterval); 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); if (!MQTTConfigCheck) { diff --git a/code/components/jomjol_flowcontroll/ClassFlowMQTT.h b/code/components/jomjol_flowcontroll/ClassFlowMQTT.h index fcea5b63..272d9a21 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowMQTT.h +++ b/code/components/jomjol_flowcontroll/ClassFlowMQTT.h @@ -19,7 +19,8 @@ protected: std::string OldValue; ClassFlowPostProcessing* flowpostprocessing; std::string user, password; - std::string caCertFilename, clientCertFilename, clientKeyFilename; + std::string caCertFilename, clientCertFilename, clientKeyFilename; + bool validateServerCert; bool SetRetainFlag; int keepAlive; // Seconds float roundInterval; // Minutes diff --git a/code/components/jomjol_mqtt/interface_mqtt.cpp b/code/components/jomjol_mqtt/interface_mqtt.cpp index e970ac50..2681a4bb 100644 --- a/code/components/jomjol_mqtt/interface_mqtt.cpp +++ b/code/components/jomjol_mqtt/interface_mqtt.cpp @@ -36,6 +36,7 @@ bool mqtt_connected = false; 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 caCert, clientCert, clientKey; +bool validateServerCert = true; int keepalive; bool SetRetainFlag; void (*callbackOnConnected)(std::string, bool) = NULL; @@ -206,7 +207,7 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_ 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 _cacertfilename, std::string _clientcertfilename, std::string _clientkeyfilename, + std::string _cacertfilename, bool _validateServerCert, std::string _clientcertfilename, std::string _clientkeyfilename, int _keepalive, bool _SetRetainFlag, void *_callbackOnConnected) { if ((_mqttURI.length() == 0) || (_maintopic.length() == 0) || (_clientid.length() == 0)) { @@ -244,6 +245,8 @@ bool MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _us LogFile.WriteToFile(ESP_LOG_INFO, TAG, "using caCert: " + _cacertfilename); } + validateServerCert = _validateServerCert; + if (_user.length() && _password.length()){ user = _user; password = _password; @@ -295,12 +298,12 @@ int MQTT_Init() { mqtt_cfg.session.last_will.msg = lwt_disconnected.c_str(); mqtt_cfg.session.last_will.msg_len = (int)(lwt_disconnected.length()); 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()){ mqtt_cfg.broker.verification.certificate = caCert.c_str(); mqtt_cfg.broker.verification.certificate_len = caCert.length() + 1; - mqtt_cfg.broker.verification.skip_cert_common_name_check = true; + mqtt_cfg.broker.verification.skip_cert_common_name_check = validateServerCert; } if (clientCert.length() && clientKey.length()){ diff --git a/code/components/jomjol_mqtt/interface_mqtt.h b/code/components/jomjol_mqtt/interface_mqtt.h index 79544736..29b52bb0 100644 --- a/code/components/jomjol_mqtt/interface_mqtt.h +++ b/code/components/jomjol_mqtt/interface_mqtt.h @@ -11,7 +11,7 @@ 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 _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 MQTT_Init(); void MQTTdestroy_client(bool _disable); diff --git a/code/sdkconfig.defaults b/code/sdkconfig.defaults index 0fe53036..dcf193f6 100644 --- a/code/sdkconfig.defaults +++ b/code/sdkconfig.defaults @@ -127,6 +127,8 @@ CONFIG_MQTT_USE_CUSTOM_CONFIG=y #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_ESP_TLS_INSECURE=y + CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=n CONFIG_CAMERA_CORE0=n diff --git a/param-docs/expert-params.txt b/param-docs/expert-params.txt index 056b7128..5f47bca9 100644 --- a/param-docs/expert-params.txt +++ b/param-docs/expert-params.txt @@ -43,5 +43,6 @@ Hostname RSSIThreshold TimeServer CACert +ValidateServerCert ClientCert ClientKey diff --git a/param-docs/parameter-pages/MQTT/CACert.md b/param-docs/parameter-pages/MQTT/CACert.md index 9f2fa8c4..4c0a9214 100644 --- a/param-docs/parameter-pages/MQTT/CACert.md +++ b/param-docs/parameter-pages/MQTT/CACert.md @@ -12,10 +12,14 @@ This is part of the configuration to enable TLS for MQTT. 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. -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). !!! 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`! !!! Note Only TLS 1.2 is supported! + +!!! Note + Only Certificates up to 4096 Bit are supported! diff --git a/param-docs/parameter-pages/MQTT/ClientCert.md b/param-docs/parameter-pages/MQTT/ClientCert.md index 83ca26f9..9902efd4 100644 --- a/param-docs/parameter-pages/MQTT/ClientCert.md +++ b/param-docs/parameter-pages/MQTT/ClientCert.md @@ -12,7 +12,8 @@ This is part of the configuration to enable TLS for MQTT. 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. -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). !!! Note If set, `ClientKey` must be set too diff --git a/param-docs/parameter-pages/MQTT/ValidateServerCert.md b/param-docs/parameter-pages/MQTT/ValidateServerCert.md new file mode 100644 index 00000000..839ae35d --- /dev/null +++ b/param-docs/parameter-pages/MQTT/ValidateServerCert.md @@ -0,0 +1,18 @@ +# 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. + +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).\ +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. A connection will be only established if these match.\ +It ensures the origin of the server. + +If `disabled (false)`, only the validity of the certificate (e.g. expiry) is checked, not the origin (CN field).\ +If you use public brokers, make sure to set this parameter to "enabled", to avoid potential MITM-Attacks! + +!!! Note + This also means that you might have to change the protocol and port in to `mqtts://example.com:8883`! diff --git a/sd-card/config/config.ini b/sd-card/config/config.ini index 851c96bf..46e39384 100644 --- a/sd-card/config/config.ini +++ b/sd-card/config/config.ini @@ -87,6 +87,7 @@ HomeassistantDiscovery = false ;CACert = /config/certs/RootCA.pem ;ClientCert = /config/certs/client.pem.crt ;ClientKey = /config/certs/client.pem.key +;ValidateServerCert = true ;DomoticzTopicIn = domoticz/in ;main.DomoticzIDX = 0 diff --git a/sd-card/html/edit_config_template.html b/sd-card/html/edit_config_template.html index 535717d6..838888a4 100644 --- a/sd-card/html/edit_config_template.html +++ b/sd-card/html/edit_config_template.html @@ -1119,6 +1119,19 @@