Просмотр исходного кода

added config entries for MQTT TLS (#2651)

3 new entries in the config section, for setting file paths for
        - Root CA
        - Client Certificate
        - Client Private Key
 (all set as expert parameters)

- logging cert filenames

added config entries for MQTT TLS

 3 new entries in the config section, for setting file paths for
        - Root CA
        - Client Certificate
        - Client Private Key

- logging cert filenames

MQTT-TLS: Updates for the PR comments

- config.ini now has default values closer to "real" life filenames
- MQTT cert entries are hidden as Expert parameters
- Fixed debug logging at MQTT interface for unhandled messages
LordGuilly 2 лет назад
Родитель
Сommit
75b15b8e9d

+ 17 - 1
code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp

@@ -37,6 +37,9 @@ void ClassFlowMQTT::SetInitialParameter(void)
     topicUptime = "";
     topicFreeMem = "";
 
+    caCertFilename = "";
+    clientCertFilename = "";
+    clientKeyFilename = "";
     clientname = wlan_config.hostname;
 
     OldValue = "";
@@ -102,6 +105,18 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
     while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
     {
         splitted = ZerlegeZeile(aktparamgraph);
+        if ((toUpper(splitted[0]) == "CACERT") && (splitted.size() > 1))
+        {
+            this->caCertFilename = splitted[1];
+        }  
+        if ((toUpper(splitted[0]) == "CLIENTCERT") && (splitted.size() > 1))
+        {
+            this->clientCertFilename = splitted[1];
+        }  
+        if ((toUpper(splitted[0]) == "CLIENTKEY") && (splitted.size() > 1))
+        {
+            this->clientKeyFilename = splitted[1];
+        }  
         if ((toUpper(splitted[0]) == "USER") && (splitted.size() > 1))
         {
             this->user = splitted[1];
@@ -196,7 +211,8 @@ bool ClassFlowMQTT::Start(float AutoInterval)
     mqttServer_setParameter(flowpostprocessing->GetNumbers(), keepAlive, roundInterval);
 
     bool MQTTConfigCheck = MQTT_Configure(uri, clientname, user, password, maintopic, LWT_TOPIC, LWT_CONNECTED,
-                                     LWT_DISCONNECTED, keepAlive, SetRetainFlag, (void *)&GotConnected);
+                                     LWT_DISCONNECTED, caCertFilename, clientCertFilename, clientKeyFilename,
+                                     keepAlive, SetRetainFlag, (void *)&GotConnected);
 
     if (!MQTTConfigCheck) {
         return false;

+ 1 - 0
code/components/jomjol_flowcontroll/ClassFlowMQTT.h

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

+ 42 - 0
code/components/jomjol_mqtt/interface_mqtt.cpp

@@ -2,6 +2,9 @@
 #include "interface_mqtt.h"
 
 #include "esp_log.h"
+#if DEBUG_DETAIL_ON
+    #include "esp_timer.h"
+#endif
 #include "connect_wlan.h"
 #include "mqtt_client.h"
 #include "ClassLogFile.h"
@@ -32,6 +35,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;
+std::string caCert, clientCert, clientKey;
 int keepalive;
 bool SetRetainFlag;
 void (*callbackOnConnected)(std::string, bool) = NULL;
@@ -169,6 +173,10 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) {
             else if (event->error_handle->connect_return_code == MQTT_CONNECTION_REFUSE_NOT_AUTHORIZED) {
                 LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Connection refused, not authorized. Check username/password (0x05)");
             }
+            else {
+                LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Other event id:" + event->error_handle->connect_return_code);
+                ESP_LOGE(TAG, "Other event id:%d", event->error_handle->connect_return_code);
+            }
 
             #ifdef DEBUG_DETAIL_ON 
                 ESP_LOGD(TAG, "MQTT_EVENT_ERROR - esp_mqtt_error_codes:");
@@ -198,6 +206,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 _lwt, std::string _lwt_connected, std::string _lwt_disconnected,
+        std::string _cacertfilename, std::string _clientcertfilename, std::string _clientkeyfilename, 
                     int _keepalive, bool _SetRetainFlag, void *_callbackOnConnected) {
     if ((_mqttURI.length() == 0) || (_maintopic.length() == 0) || (_clientid.length() == 0)) 
     {
@@ -215,6 +224,25 @@ bool MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _us
     maintopic = _maintopic;
     callbackOnConnected = ( void (*)(std::string, bool) )(_callbackOnConnected);
 
+    if (_clientcertfilename.length() && _clientkeyfilename.length()){
+        std::ifstream cert_ifs(_clientcertfilename);
+        std::string cert_content((std::istreambuf_iterator<char>(cert_ifs)), (std::istreambuf_iterator<char>()));
+        clientCert = cert_content;
+        LogFile.WriteToFile(ESP_LOG_INFO, TAG, "using clientCert: " + _clientcertfilename);
+
+        std::ifstream key_ifs(_clientkeyfilename);
+        std::string key_content((std::istreambuf_iterator<char>(key_ifs)), (std::istreambuf_iterator<char>()));
+        clientKey = key_content;
+        LogFile.WriteToFile(ESP_LOG_INFO, TAG, "using clientKey: " + _clientkeyfilename);
+    }
+
+    if (_cacertfilename.length() ){
+        std::ifstream ifs(_cacertfilename);
+        std::string content((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
+        caCert = content;
+        LogFile.WriteToFile(ESP_LOG_INFO, TAG, "using caCert: " + _cacertfilename);
+    }
+
     if (_user.length() && _password.length()){
         user = _user;
         password = _password;
@@ -268,6 +296,20 @@ int MQTT_Init() {
     mqtt_cfg.session.keepalive = keepalive;
     mqtt_cfg.buffer.size = 1536;                         // size of MQTT send/receive buffer (Default: 1024)
 
+    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;
+    }
+
+    if (clientCert.length() && clientKey.length()){
+        mqtt_cfg.credentials.authentication.certificate = clientCert.c_str();
+        mqtt_cfg.credentials.authentication.certificate_len = clientCert.length() + 1;
+        
+        mqtt_cfg.credentials.authentication.key = clientKey.c_str();
+        mqtt_cfg.credentials.authentication.key_len = clientKey.length() + 1;
+    }
+
     if (user.length() && password.length()){
         mqtt_cfg.credentials.username = user.c_str();
         mqtt_cfg.credentials.authentication.password = password.c_str();

+ 1 - 0
code/components/jomjol_mqtt/interface_mqtt.h

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

+ 3 - 0
sd-card/config/config.ini

@@ -62,6 +62,9 @@ CheckDigitIncreaseConsistency = false
 RetainMessages = false
 HomeassistantDiscovery = false
 ;MeterType = other
+;CACert = /config/certs/RootCA.pem
+;ClientCert = /config/certs/client.pem.crt
+;ClientKey = /config/certs/client.pem.key
 
 ;[InfluxDB]
 ;Uri = undefined

+ 39 - 0
sd-card/html/edit_config_param.html

@@ -753,6 +753,39 @@
 			<td>$TOOLTIP_MQTT_password</td>
 		</tr>
 
+		<tr class="MQTTItem expert" id="exMqtt">
+			<td class="indent1">
+				<input type="checkbox" id="MQTT_CACert_enabled" value="1"  onclick = 'InvertEnableItem("MQTT", "CACert")' unchecked >
+				<label for=MQTT_CACert_enabled><class id="MQTT_CACert_text" style="color:black;">Root CA Certificate file</class></label>
+			</td>
+			<td>
+				<input type="text" id="MQTT_CACert_value1">
+			</td>
+			<td>$TOOLTIP_MQTT_CACert</td>
+		</tr>
+
+		<tr class="MQTTItem expert" id="exMqtt">
+			<td class="indent1">
+				<input type="checkbox" id="MQTT_ClientCert_enabled" value="1"  onclick = 'InvertEnableItem("MQTT", "ClientCert")' unchecked >
+				<label for=MQTT_ClientCert_enabled><class id="MQTT_ClientCert_text" style="color:black;">Client Certificate file</class></label>
+			</td>
+			<td>
+				<input type="text" id="MQTT_ClientCert_value1">
+			</td>
+			<td>$TOOLTIP_MQTT_ClientCert</td>
+		</tr>
+
+		<tr class="MQTTItem expert" id="exMqtt">
+			<td class="indent1">
+				<input type="checkbox" id="MQTT_ClientKey_enabled" value="1"  onclick = 'InvertEnableItem("MQTT", "ClientKey")' unchecked >
+				<label for=MQTT_ClientKey_enabled><class id="MQTT_ClientKey_text" style="color:black;">Client Key file</class></label>
+			</td>
+			<td>
+				<input type="text" id="MQTT_ClientKey_value1">
+			</td>
+			<td>$TOOLTIP_MQTT_ClientKey</td>
+		</tr>
+
 		<tr class="MQTTItem">
 			<td class="indent1">
 				<label><class id="MQTT_RetainMessages_text" style="color:black;">Retain Messages</class></label>
@@ -2089,6 +2122,9 @@ function UpdateInput() {
     WriteParameter(param, category, "MQTT", "RetainMessages", false);
     WriteParameter(param, category, "MQTT", "HomeassistantDiscovery", false);
     WriteParameter(param, category, "MQTT", "MeterType", true);
+	WriteParameter(param, category, "MQTT", "CACert", true);
+	WriteParameter(param, category, "MQTT", "ClientCert", true);
+	WriteParameter(param, category, "MQTT", "ClientKey", true);
     
     WriteParameter(param, category, "InfluxDB", "Uri", true);	
     WriteParameter(param, category, "InfluxDB", "Database", true);	
@@ -2225,6 +2261,9 @@ function ReadParameterAll()
     ReadParameter(param, "MQTT", "RetainMessages", false);
     ReadParameter(param, "MQTT", "HomeassistantDiscovery", false);
     ReadParameter(param, "MQTT", "MeterType", true);
+	ReadParameter(param, "MQTT", "CACert", true);
+	ReadParameter(param, "MQTT", "ClientCert", true);
+	ReadParameter(param, "MQTT", "ClientKey", true);
 
     ReadParameter(param, "InfluxDB", "Uri", true);
     ReadParameter(param, "InfluxDB", "Database", true);

+ 3 - 0
sd-card/html/readconfigparam.js

@@ -183,6 +183,9 @@ function ParseConfig() {
      ParamAddValue(param, catname, "RetainMessages");
      ParamAddValue(param, catname, "HomeassistantDiscovery");
      ParamAddValue(param, catname, "MeterType");
+     ParamAddValue(param, catname, "CACert");
+     ParamAddValue(param, catname, "ClientCert");
+     ParamAddValue(param, catname, "ClientKey");
 
      var catname = "InfluxDB";
      category[catname] = new Object();