Add switching between MQTT brokers with self signed client certificates. (#993)
This commit is contained in:
1 parent
f1351ec439
commit
2708858754
2 files changed
+121
-18
No files matched your search
@@ -192,6 +192,51 @@ vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
|
|||||||
# define MQTT_HTTPS_FW_UPDATE_USE_PASSWORD 1 // Set this to 0 if not using TLS connection to MQTT broker to prevent clear text passwords being sent.
|
# define MQTT_HTTPS_FW_UPDATE_USE_PASSWORD 1 // Set this to 0 if not using TLS connection to MQTT broker to prevent clear text passwords being sent.
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
# ifndef MQTT_SECURE_SELF_SIGNED
|
||||||
|
# define MQTT_SECURE_SELF_SIGNED 0
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifndef MQTT_SECURE_SELF_SIGNED_CLIENT
|
||||||
|
# define MQTT_SECURE_SELF_SIGNED_CLIENT 1
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifndef MQTT_SECURE_SELF_SIGNED_INDEX_DEFAULT
|
||||||
|
# define MQTT_SECURE_SELF_SIGNED_INDEX_DEFAULT 0
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if MQTT_SECURE_SELF_SIGNED
|
||||||
|
const char* ss_server_cert PROGMEM = R"EOF("
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
...
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
")EOF";
|
||||||
|
|
||||||
|
const char* ss_client_cert PROGMEM = R"EOF("
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
...
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
")EOF";
|
||||||
|
|
||||||
|
const char* ss_client_key PROGMEM = R"EOF("
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
...
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
")EOF";
|
||||||
|
|
||||||
|
struct ss_certs {
|
||||||
|
const char* server_cert;
|
||||||
|
const char* client_cert;
|
||||||
|
const char* client_key;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ss_certs certs_array[2] = {
|
||||||
|
{ss_server_cert, ss_client_cert, ss_client_key},
|
||||||
|
{ss_server_cert, ss_client_cert, ss_client_key}};
|
||||||
|
|
||||||
|
static_assert(MQTT_SECURE_SELF_SIGNED_INDEX_DEFAULT < (sizeof(certs_array) / sizeof(ss_certs)),
|
||||||
|
"Invalid MQTT self signed default index");
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*------------------DEEP SLEEP parameters ------------------*/
|
/*------------------DEEP SLEEP parameters ------------------*/
|
||||||
|
|||||||
+76
-18
@@ -156,6 +156,8 @@ struct GfSun2000Data {};
|
|||||||
#endif
|
#endif
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void setupTLS(bool self_signed = false, uint8_t index = 0);
|
||||||
|
|
||||||
//adding this to bypass the problem of the arduino builder issue 50
|
//adding this to bypass the problem of the arduino builder issue 50
|
||||||
void callback(char* topic, byte* payload, unsigned int length);
|
void callback(char* topic, byte* payload, unsigned int length);
|
||||||
|
|
||||||
@@ -175,7 +177,8 @@ bool disc = true; // Auto discovery with Home Assistant convention
|
|||||||
unsigned long timer_led_measures = 0;
|
unsigned long timer_led_measures = 0;
|
||||||
static void* eClient = nullptr;
|
static void* eClient = nullptr;
|
||||||
#if defined(ESP8266) || defined(ESP32)
|
#if defined(ESP8266) || defined(ESP32)
|
||||||
static bool mqtt_secure = MQTT_SECURE_DEFAULT;
|
static bool mqtt_secure = (MQTT_SECURE_DEFAULT || MQTT_SECURE_SELF_SIGNED);
|
||||||
|
static uint8_t mqtt_ss_index = MQTT_SECURE_SELF_SIGNED_INDEX_DEFAULT;
|
||||||
static String mqtt_cert = "";
|
static String mqtt_cert = "";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -211,6 +214,10 @@ Preferences preferences;
|
|||||||
# include <FS.h>
|
# include <FS.h>
|
||||||
# include <WiFiManager.h>
|
# include <WiFiManager.h>
|
||||||
X509List caCert;
|
X509List caCert;
|
||||||
|
# if MQTT_SECURE_SELF_SIGNED_CLIENT
|
||||||
|
X509List* pClCert = nullptr;
|
||||||
|
PrivateKey* pClKey = nullptr;
|
||||||
|
# endif
|
||||||
ESP8266WiFiMulti wifiMulti;
|
ESP8266WiFiMulti wifiMulti;
|
||||||
# ifdef MDNS_SD
|
# ifdef MDNS_SD
|
||||||
# include <ESP8266mDNS.h>
|
# include <ESP8266mDNS.h>
|
||||||
@@ -604,7 +611,7 @@ void setup() {
|
|||||||
#if defined(ESP8266) || defined(ESP32)
|
#if defined(ESP8266) || defined(ESP32)
|
||||||
if (mqtt_secure) {
|
if (mqtt_secure) {
|
||||||
eClient = new WiFiClientSecure;
|
eClient = new WiFiClientSecure;
|
||||||
setupTLS();
|
setupTLS(MQTT_SECURE_SELF_SIGNED, mqtt_ss_index);
|
||||||
} else {
|
} else {
|
||||||
eClient = new WiFiClient;
|
eClient = new WiFiClient;
|
||||||
}
|
}
|
||||||
@@ -850,23 +857,51 @@ void setOTA() {
|
|||||||
ArduinoOTA.begin();
|
ArduinoOTA.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupTLS() {
|
void setupTLS(bool self_signed, uint8_t index) {
|
||||||
configTime(0, 0, NTP_SERVER);
|
configTime(0, 0, NTP_SERVER);
|
||||||
WiFiClientSecure* sClient = (WiFiClientSecure*)eClient;
|
WiFiClientSecure* sClient = (WiFiClientSecure*)eClient;
|
||||||
if (mqtt_cert.length() > 0) {
|
# if MQTT_SECURE_SELF_SIGNED
|
||||||
# if defined(ESP32)
|
if (self_signed) {
|
||||||
sClient->setCACert(mqtt_cert.c_str());
|
# if defined(ESP32)
|
||||||
} else {
|
sClient->setCACert(certs_array[index].server_cert);
|
||||||
sClient->setCACert(certificate);
|
# if MQTT_SECURE_SELF_SIGNED_CLIENT
|
||||||
}
|
sClient->setCertificate(certs_array[index].client_cert);
|
||||||
# elif defined(ESP8266)
|
sClient->setPrivateKey(certs_array[index].client_key);
|
||||||
caCert.append(mqtt_cert.c_str());
|
# endif
|
||||||
} else {
|
# elif defined(ESP8266)
|
||||||
caCert.append(certificate);
|
caCert.append(certs_array[index].server_cert);
|
||||||
}
|
sClient->setTrustAnchors(&caCert);
|
||||||
sClient->setTrustAnchors(&caCert);
|
sClient->setBufferSizes(512, 512);
|
||||||
sClient->setBufferSizes(512, 512);
|
# if MQTT_SECURE_SELF_SIGNED_CLIENT
|
||||||
|
if (pClCert != nullptr) {
|
||||||
|
delete pClCert;
|
||||||
|
}
|
||||||
|
if (pClKey != nullptr) {
|
||||||
|
delete pClKey;
|
||||||
|
}
|
||||||
|
pClCert = new X509List(certs_array[index].client_cert);
|
||||||
|
pClKey = new PrivateKey(certs_array[index].client_key);
|
||||||
|
sClient->setClientRSACert(pClCert, pClKey);
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
} else
|
||||||
# endif
|
# endif
|
||||||
|
{
|
||||||
|
if (mqtt_cert.length() > 0) {
|
||||||
|
# if defined(ESP32)
|
||||||
|
sClient->setCACert(mqtt_cert.c_str());
|
||||||
|
} else {
|
||||||
|
sClient->setCACert(certificate);
|
||||||
|
}
|
||||||
|
# elif defined(ESP8266)
|
||||||
|
caCert.append(mqtt_cert.c_str());
|
||||||
|
} else {
|
||||||
|
caCert.append(certificate);
|
||||||
|
}
|
||||||
|
sClient->setTrustAnchors(&caCert);
|
||||||
|
sClient->setBufferSizes(512, 512);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -972,6 +1007,7 @@ void saveMqttConfig() {
|
|||||||
json["gateway_name"] = gateway_name;
|
json["gateway_name"] = gateway_name;
|
||||||
json["mqtt_broker_secure"] = mqtt_secure;
|
json["mqtt_broker_secure"] = mqtt_secure;
|
||||||
json["mqtt_broker_cert"] = mqtt_cert;
|
json["mqtt_broker_cert"] = mqtt_cert;
|
||||||
|
json["mqtt_ss_index"] = mqtt_ss_index;
|
||||||
|
|
||||||
File configFile = SPIFFS.open("/config.json", "w");
|
File configFile = SPIFFS.open("/config.json", "w");
|
||||||
if (!configFile) {
|
if (!configFile) {
|
||||||
@@ -1033,6 +1069,8 @@ void setup_wifimanager(bool reset_settings) {
|
|||||||
mqtt_secure = json.get<bool>("mqtt_secure");
|
mqtt_secure = json.get<bool>("mqtt_secure");
|
||||||
if (json.containsKey("mqtt_cert"))
|
if (json.containsKey("mqtt_cert"))
|
||||||
mqtt_cert = json.get<const char*>("mqtt_cert");
|
mqtt_cert = json.get<const char*>("mqtt_cert");
|
||||||
|
if (json.containsKey("mqtt_ss_index"))
|
||||||
|
mqtt_ss_index = json.get<uint8_t>("mqtt_ss_index");
|
||||||
if (json.containsKey("gateway_name"))
|
if (json.containsKey("gateway_name"))
|
||||||
strcpy(gateway_name, json["gateway_name"]);
|
strcpy(gateway_name, json["gateway_name"]);
|
||||||
} else {
|
} else {
|
||||||
@@ -1834,20 +1872,32 @@ void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
|
|||||||
# endif
|
# endif
|
||||||
client.disconnect();
|
client.disconnect();
|
||||||
bool update_server = false;
|
bool update_server = false;
|
||||||
|
bool secure_connect = SYSdata.get<bool>("mqtt_secure");
|
||||||
void* prev_client = nullptr;
|
void* prev_client = nullptr;
|
||||||
|
bool use_ss_cert = SYSdata.containsKey("mqtt_ss_cert");
|
||||||
|
uint8_t cert_index = mqtt_ss_index;
|
||||||
|
|
||||||
if (SYSdata.containsKey("mqtt_server") && SYSdata.containsKey("mqtt_port")) {
|
if (SYSdata.containsKey("mqtt_server") && SYSdata.containsKey("mqtt_port")) {
|
||||||
if (!SYSdata.containsKey("mqtt_secure")) {
|
if (!SYSdata.containsKey("mqtt_secure")) {
|
||||||
Log.warning(F("mqtt_server provided without mqtt_secure defined - ignoring command" CR));
|
Log.warning(F("mqtt_server provided without mqtt_secure defined - ignoring command" CR));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
# if MQTT_SECURE_SELF_SIGNED
|
||||||
|
if (use_ss_cert) {
|
||||||
|
cert_index = SYSdata.get<uint8_t>("mqtt_ss_cert");
|
||||||
|
if (cert_index >= sizeof(certs_array) / sizeof(ss_certs)) {
|
||||||
|
Log.warning(F("mqtt_ss_cert index invalid - ignoring command" CR));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
update_server = true;
|
update_server = true;
|
||||||
|
|
||||||
if (SYSdata.get<bool>("mqtt_secure") != mqtt_secure) {
|
if (secure_connect != mqtt_secure) {
|
||||||
prev_client = eClient;
|
prev_client = eClient;
|
||||||
if (!mqtt_secure) {
|
if (!mqtt_secure) {
|
||||||
eClient = new WiFiClientSecure;
|
eClient = new WiFiClientSecure;
|
||||||
setupTLS();
|
|
||||||
} else {
|
} else {
|
||||||
Log.warning(F("Switching to unsecure MQTT broker" CR));
|
Log.warning(F("Switching to unsecure MQTT broker" CR));
|
||||||
eClient = new WiFiClient;
|
eClient = new WiFiClient;
|
||||||
@@ -1856,6 +1906,10 @@ void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
|
|||||||
client.setClient(*(Client*)eClient);
|
client.setClient(*(Client*)eClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (secure_connect) {
|
||||||
|
setupTLS(use_ss_cert, cert_index);
|
||||||
|
}
|
||||||
|
|
||||||
client.setServer(SYSdata.get<const char*>("mqtt_server"), SYSdata.get<unsigned int>("mqtt_port"));
|
client.setServer(SYSdata.get<const char*>("mqtt_server"), SYSdata.get<unsigned int>("mqtt_port"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1870,6 +1924,7 @@ void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
|
|||||||
if (update_server) {
|
if (update_server) {
|
||||||
strcpy(mqtt_server, SYSdata["mqtt_server"]);
|
strcpy(mqtt_server, SYSdata["mqtt_server"]);
|
||||||
strcpy(mqtt_port, SYSdata["mqtt_port"]);
|
strcpy(mqtt_port, SYSdata["mqtt_port"]);
|
||||||
|
mqtt_ss_index = cert_index;
|
||||||
if (prev_client != nullptr) {
|
if (prev_client != nullptr) {
|
||||||
mqtt_secure = !mqtt_secure;
|
mqtt_secure = !mqtt_secure;
|
||||||
delete prev_client;
|
delete prev_client;
|
||||||
@@ -1890,6 +1945,9 @@ void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
|
|||||||
}
|
}
|
||||||
strcpy(mqtt_user, prev_user.c_str());
|
strcpy(mqtt_user, prev_user.c_str());
|
||||||
strcpy(mqtt_pass, prev_pass.c_str());
|
strcpy(mqtt_pass, prev_pass.c_str());
|
||||||
|
if (mqtt_secure) {
|
||||||
|
setupTLS(MQTT_SECURE_SELF_SIGNED, mqtt_ss_index);
|
||||||
|
}
|
||||||
connectMQTT();
|
connectMQTT();
|
||||||
}
|
}
|
||||||
# if defined(ZgatewayBT) && defined(ESP32)
|
# if defined(ZgatewayBT) && defined(ESP32)
|
||||||
|
|||||||
Reference in new issue
Block a user