Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added support for using TLS with MQTT #2651

Merged
merged 1 commit into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ void ClassFlowMQTT::SetInitialParameter(void)
topicUptime = "";
topicFreeMem = "";

caCertFilename = "";
clientCertFilename = "";
clientKeyFilename = "";
clientname = wlan_config.hostname;

OldValue = "";
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions code/components/jomjol_flowcontroll/ClassFlowMQTT.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class ClassFlowMQTT :
std::string OldValue;
ClassFlowPostProcessing* flowpostprocessing;
std::string user, password;
std::string caCertFilename, clientCertFilename, clientKeyFilename;
bool SetRetainFlag;
int keepAlive; // Seconds
float roundInterval; // Minutes
Expand Down
42 changes: 42 additions & 0 deletions code/components/jomjol_mqtt/interface_mqtt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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:");
Expand Down Expand Up @@ -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))
{
Expand All @@ -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;
Expand Down Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions code/components/jomjol_mqtt/interface_mqtt.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions sd-card/config/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
39 changes: 39 additions & 0 deletions sd-card/html/edit_config_param.html
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,39 @@ <h4>
<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>
Expand Down Expand Up @@ -2089,6 +2122,9 @@ <h4><input type="checkbox" id="Category_GPIO_enabled" value="1" onclick='Update
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);
Expand Down Expand Up @@ -2225,6 +2261,9 @@ <h4><input type="checkbox" id="Category_GPIO_enabled" value="1" onclick='Update
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);
Expand Down
3 changes: 3 additions & 0 deletions sd-card/html/readconfigparam.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down