17
17
* version 2 as published by the Free Software Foundation.
18
18
*/
19
19
20
+ /*
21
+ * Modified by Eric Grammatico <eric@grammatico.me>
22
+ *
23
+ * Added support to secured connexion to mqtt server thanks to WiFiClientSecure class.
24
+ * Please see comments in code. You can look for WiFiClientSecure, MY_GATEWAY_ESP8266_SECURE,
25
+ * MY_SSL_CERT, MY_SSL_FINGERPRINT and MY_SSL_CERT_CLIENT in the code below to see what has
26
+ * changed. No new method, no new class to be used by my_sensors.
27
+ *
28
+ * The following constants have to be defined from the gateway code:
29
+ * MY_GATEWAY_ESP8266_SECURE in place of MY_GATEWAY_ESP8266 to go to secure connexions.
30
+ * MY_SSL_CERT_AUTHx Up to three root Certificates Authorities could be defined
31
+ * to validate the mqtt server' certificate. The most secure.
32
+ * MY_SSL_FINGERPRINT Alternatively, the mqtt server' certificate finger print
33
+ * could be used. Less secure and less convenient as you'll
34
+ * have to update the fingerprint each time the mqtt server'
35
+ * certificate is updated
36
+ * If neither MY_SSL_CERT_AUTH1 nor MY_SSL_FINGERPRINT are
37
+ * defined, insecure connexion will be established. The mqtt
38
+ * server' certificate will not be validated.
39
+ * MY_SSL_CERT_CLIENT The mqtt server may require client certificate for
40
+ * MY_SSL_KEY_CLIENT authentication.
41
+ *
42
+ */
20
43
21
44
// Topic structure: MY_MQTT_PUBLISH_TOPIC_PREFIX/NODE-ID/SENSOR-ID/CMD-TYPE/ACK-FLAG/SUB-TYPE
22
45
55
78
#define MY_MQTT_PASSWORD NULL
56
79
#endif
57
80
58
- #if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32)
81
+ #if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP8266_SECURE) || defined( MY_GATEWAY_ESP32)
59
82
#if !defined(MY_WIFI_SSID)
60
83
#error ESP8266/ESP32 MQTT gateway: MY_WIFI_SSID not defined!
61
84
#endif
69
92
#define _MQTT_clientIp IPAddress (MY_IP_ADDRESS)
70
93
#if defined(MY_IP_GATEWAY_ADDRESS)
71
94
#define _gatewayIp IPAddress (MY_IP_GATEWAY_ADDRESS)
72
- #elif defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32)
95
+ #elif defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP8266_SECURE) || defined( MY_GATEWAY_ESP32)
73
96
// Assume the gateway will be the machine on the same network as the local IP
74
97
// but with last octet being '1'
75
98
#define _gatewayIp IPAddress (_MQTT_clientIp[0 ], _MQTT_clientIp[1 ], _MQTT_clientIp[2 ], 1 )
76
99
#endif /* End of MY_IP_GATEWAY_ADDRESS */
77
100
78
101
#if defined(MY_IP_SUBNET_ADDRESS)
79
102
#define _subnetIp IPAddress (MY_IP_SUBNET_ADDRESS)
80
- #elif defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32)
103
+ #elif defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP8266_SECURE) || defined( MY_GATEWAY_ESP32)
81
104
#define _subnetIp IPAddress (255 , 255 , 255 , 0 )
82
105
#endif /* End of MY_IP_SUBNET_ADDRESS */
83
106
#endif /* End of MY_IP_ADDRESS */
84
107
85
108
#if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32)
86
- #if defined(MY_MQTT_CA_CERT) && defined(MY_MQTT_CLIENT_CERT) && defined(MY_MQTT_CLIENT_KEY)
87
- #define EthernetClient WiFiClientSecure
88
- BearSSL::X509List ca_cert (MY_MQTT_CA_CERT);
89
- BearSSL::X509List client_cert (MY_MQTT_CLIENT_CERT);
90
- BearSSL::PrivateKey client_key (MY_MQTT_CLIENT_KEY);
91
- #else
92
109
#define EthernetClient WiFiClient
93
- #endif /* End of MY_MQTT_CA_CERT && MY_MQTT_CLIENT_CERT && MY_MQTT_CLIENT_KEY */
110
+ #elif defined(MY_GATEWAY_ESP8266_SECURE)
111
+ #define EthernetClient WiFiClientSecure
112
+ #if defined(MY_SSL_CERT_AUTH1)
113
+ BearSSL::X509List certAuth; // List to store Certificat Authorities
114
+ #endif
115
+ #if defined(MY_SSL_CERT_CLIENT) && defined(MY_SSL_KEY_CLIENT)
116
+ BearSSL::X509List clientCert; // Client public key
117
+ BearSSL::PrivateKey clientPrivKey; // Client private key
118
+ #endif
119
+ // Set time via NTP, as required for x.509 validation
120
+ // BearSSL checks NotBefore and NotAfter dates in certificates
121
+ // Thus an approximated date/time is needed.
122
+ void setClock () {
123
+ configTime (3 * 3600 , 0 , " pool.ntp.org" , " time.nist.gov" );
124
+
125
+ Serial.print (" Waiting for NTP time sync: " );
126
+ time_t now = time (nullptr );
127
+ while (now < 8 * 3600 * 2 ) {
128
+ delay (500 );
129
+ Serial.print (" ." );
130
+ now = time (nullptr );
131
+ }
132
+ Serial.println (" " );
133
+ struct tm timeinfo;
134
+ gmtime_r (&now, &timeinfo);
135
+ Serial.print (" Current time: " );
136
+ Serial.print (asctime (&timeinfo));
137
+ }
94
138
#elif defined(MY_GATEWAY_LINUX)
95
139
// Nothing to do here
96
140
#else
@@ -161,18 +205,57 @@ bool reconnectMQTT(void)
161
205
}
162
206
delay (1000 );
163
207
GATEWAY_DEBUG (PSTR (" !GWT:RMQ:FAIL\n " ));
208
+ #if defined(MY_GATEWAY_ESP8266_SECURE)
209
+ char sslErr[256 ];
210
+ int errID = _MQTT_ethClient.getLastSSLError (sslErr, sizeof (sslErr));
211
+ GATEWAY_DEBUG (PSTR (" !GWT:RMQ:(%d) %s\n " ), errID, sslErr);
212
+ #endif
164
213
return false ;
165
214
}
166
215
167
216
bool gatewayTransportConnect (void )
168
217
{
169
- #if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32)
218
+ #if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP8266_SECURE) || defined( MY_GATEWAY_ESP32)
170
219
if (WiFi.status () != WL_CONNECTED) {
171
220
GATEWAY_DEBUG (PSTR (" GWT:TPC:CONNECTING...\n " ));
172
221
delay (1000 );
173
222
return false ;
174
223
}
175
224
GATEWAY_DEBUG (PSTR (" GWT:TPC:IP=%s\n " ), WiFi.localIP ().toString ().c_str ());
225
+
226
+ #if defined(MY_GATEWAY_ESP8266_SECURE)
227
+ // Certificate Authorities are stored in the X509 list
228
+ // At least one is needed, but you may need two, or three
229
+ // eg to validate one certificate from LetsEncrypt two is needed
230
+ #if defined(MY_SSL_CERT_AUTH1)
231
+ certAuth.append (MY_SSL_CERT_AUTH1);
232
+ #if defined(MY_SSL_CERT_AUTH2)
233
+ certAuth.append (MY_SSL_CERT_AUTH2);
234
+ #endif
235
+ #if defined(MY_SSL_CERT_AUTH3)
236
+ certAuth.append (MY_SSL_CERT_AUTH3);
237
+ #endif
238
+ _MQTT_ethClient.setTrustAnchors (&certAuth);
239
+ #elif defined(MY_SSL_FINGERPRINT) // MY_SSL_CERT_AUTH1
240
+ // Alternatively, the certificate could be validated with its
241
+ // fingerprint, which is less secure
242
+ _MQTT_ethClient.setFingerprint (MY_SSL_FINGERPRINT);
243
+ #else // MY_SSL_CERT_AUTH1
244
+ // At last, an insecure connexion is accepted. Meaning the
245
+ // server's certificate is not validated.
246
+ _MQTT_ethClient.setInsecure ();
247
+ GATEWAY_DEBUG (PSTR (" GWT:TPC:CONNECTING WITH INSECURE SETTING...\n " ));
248
+ #endif // MY_SSL_CERT_AUTH1
249
+ #if defined(MY_SSL_CERT_CLIENT) && defined(MY_SSL_KEY_CLIENT)
250
+ // The server may required client certificate
251
+ clientCert.append (MY_SSL_CERT_CLIENT);
252
+ clientPrivKey.parse (MY_SSL_KEY_CLIENT);
253
+ _MQTT_ethClient.setClientRSACert (&clientCert, &clientPrivKey);
254
+ #endif
255
+ // Once the secure connexion settings are done, date/time are retrieved
256
+ // to be able to validate certificates.
257
+ setClock ();
258
+ #endif // MY_GATEWAY_ESP8266_SECURE
176
259
#elif defined(MY_GATEWAY_LINUX)
177
260
#if defined(MY_IP_ADDRESS)
178
261
_MQTT_ethClient.bind (_MQTT_clientIp);
@@ -250,10 +333,10 @@ bool gatewayTransportInit(void)
250
333
251
334
_MQTT_client.setCallback (incomingMQTT);
252
335
253
- #if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32)
336
+ #if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP8266_SECURE) || defined( MY_GATEWAY_ESP32)
254
337
// Turn off access point
255
338
WiFi.mode (WIFI_STA);
256
- #if defined(MY_GATEWAY_ESP8266)
339
+ #if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP8266_SECURE)
257
340
WiFi.hostname (MY_HOSTNAME);
258
341
#elif defined(MY_GATEWAY_ESP32)
259
342
WiFi.setHostname (MY_HOSTNAME);
@@ -264,11 +347,6 @@ bool gatewayTransportInit(void)
264
347
(void )WiFi.begin (MY_WIFI_SSID, MY_WIFI_PASSWORD, 0 , MY_WIFI_BSSID);
265
348
#endif
266
349
267
- #if defined(MY_MQTT_CA_CERT) && defined(MY_MQTT_CLIENT_CERT) && defined(MY_MQTT_CLIENT_KEY)
268
- _MQTT_ethClient.setTrustAnchors (&ca_cert);
269
- _MQTT_ethClient.setClientRSACert (&client_cert, &client_key);
270
- #endif /* End of MY_MQTT_CA_CERT && MY_MQTT_CLIENT_CERT && MY_MQTT_CLIENT_KEY */
271
-
272
350
gatewayTransportConnect ();
273
351
274
352
_MQTT_connecting = false ;
@@ -280,7 +358,7 @@ bool gatewayTransportAvailable(void)
280
358
if (_MQTT_connecting) {
281
359
return false ;
282
360
}
283
- #if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32)
361
+ #if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP8266_SECURE) || defined( MY_GATEWAY_ESP32)
284
362
if (WiFi.status () != WL_CONNECTED) {
285
363
#if defined(MY_GATEWAY_ESP32)
286
364
(void )gatewayTransportInit ();
0 commit comments