Merge pull request #11951 from ksaye/patch-1

Adding support for SAS Token Generation
This commit is contained in:
Adrian Scillato 2021-04-29 23:51:58 -03:00 committed by GitHub
commit 35e28a6c94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 58 additions and 8 deletions

View File

@ -24,6 +24,8 @@
#endif
#ifdef USE_MQTT_AZURE_IOT
#include <t_bearssl.h>
#include <base64.hpp>
#include <JsonParser.h>
#undef MQTT_PORT
#define MQTT_PORT 8883
@ -222,6 +224,53 @@ void MqttInit(void) {
MqttClient.setSocketTimeout(Settings.mqtt_socket_timeout);
}
#ifdef USE_MQTT_AZURE_IOT
String azurePreSharedKeytoSASToken(char *iotHubFQDN, const char *deviceId, const char *preSharedKey, int sasTTL = 86400){
int ttl = time(NULL) + sasTTL;
String dataToSignString = urlEncodeBase64(String(iotHubFQDN) + "/devices/" + String(deviceId)) + "\n" + String(ttl);
char dataToSign[dataToSignString.length() + 1];
dataToSignString.toCharArray(dataToSign, dataToSignString.length() + 1);
unsigned char decodedPSK[32];
unsigned char encryptedSignature[100];
unsigned char encodedSignature[100];
br_sha256_context sha256_context;
br_hmac_key_context hmac_key_context;
br_hmac_context hmac_context;
// need to base64 decode the Preshared key and the length
int base64_decoded_device_length = decode_base64((unsigned char*)preSharedKey, decodedPSK);
// create the sha256 hmac and hash the data
br_sha256_init(&sha256_context);
br_hmac_key_init(&hmac_key_context, sha256_context.vtable, decodedPSK, base64_decoded_device_length);
br_hmac_init(&hmac_context, &hmac_key_context, 32);
br_hmac_update(&hmac_context, dataToSign, sizeof(dataToSign)-1);
br_hmac_out(&hmac_context, encryptedSignature);
// base64 decode the HMAC to a char
encode_base64(encryptedSignature, br_hmac_size(&hmac_context), encodedSignature);
// creating the real SAS Token
String realSASToken = "SharedAccessSignature ";
realSASToken += "sr=" + urlEncodeBase64(String(iotHubFQDN) + "/devices/" + String(deviceId));
realSASToken += "&sig=" + urlEncodeBase64(String((char*)encodedSignature));
realSASToken += "&se=" + String(ttl);
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "SASToken is '%s'"), realSASToken.c_str());
return realSASToken;
}
String urlEncodeBase64(String stringToEncode){
// correctly URL encoding the 64 characters of Base64 and the '=' sign
stringToEncode.replace("+", "%2B");
stringToEncode.replace("=", "%3D");
stringToEncode.replace("/", "%2F");
return stringToEncode;
}
#endif // USE_MQTT_AZURE_IOT
bool MqttIsConnected(void) {
return MqttClient.connected();
}
@ -259,8 +308,7 @@ bool MqttPublishLib(const char* topic, bool retained) {
bool result;
#ifdef USE_MQTT_AZURE_IOT
String sourceTopicString = String(topic);
sourceTopicString.replace("/", "%2F");
String sourceTopicString = urlEncodeBase64(String(topic));
String topicString = "devices/" + String(SettingsText(SET_MQTT_CLIENT));
topicString+= "/messages/events/topic=" + sourceTopicString;
@ -268,9 +316,9 @@ bool MqttPublishLib(const char* topic, bool retained) {
JsonParserObject message_object = mqtt_message.getRootObject();
if (message_object.isValid()) { // only sending valid JSON, yet this is optional
result = MqttClient.publish(topicString.c_str(), TasmotaGlobal.mqtt_data, retained);
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "Sending '%s'"), TasmotaGlobal.mqtt_data);
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "Sending '%s'"), TasmotaGlobal.mqtt_data);
} else {
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "Invalid JSON, '%s' for topic '%s', not sending to Azure IoT Hub"), TasmotaGlobal.mqtt_data, topic);
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "Invalid JSON, '%s' for topic '%s', not sending to Azure IoT Hub"), TasmotaGlobal.mqtt_data, topic);
result = true;
}
#else
@ -747,12 +795,14 @@ void MqttReconnect(void) {
#endif
#ifdef USE_MQTT_AZURE_IOT
if (String(mqtt_pwd).indexOf("SharedAccessSignature") == -1) {
AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_MQTT "Azure IoT incorrect SAS Token format. Refer to https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-mqtt-support"));
return;
String azureMqtt_password = SettingsText(SET_MQTT_PWD);
if (azureMqtt_password.indexOf("SharedAccessSignature") == -1) {
// assuming a PreSharedKey was provided, calculating a SAS Token into azureMqtt_password
azureMqtt_password = azurePreSharedKeytoSASToken(SettingsText(SET_MQTT_HOST), SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_PWD));
}
String azureMqtt_userString = String(SettingsText(SET_MQTT_HOST)) + "/" + String(SettingsText(SET_MQTT_CLIENT)); + "/?api-version=2018-06-30";
if (MqttClient.connect(TasmotaGlobal.mqtt_client, azureMqtt_userString.c_str(), mqtt_pwd, stopic, 1, lwt_retain, TasmotaGlobal.mqtt_data, MQTT_CLEAN_SESSION)) {
if (MqttClient.connect(TasmotaGlobal.mqtt_client, azureMqtt_userString.c_str(), azureMqtt_password.c_str(), stopic, 1, lwt_retain, TasmotaGlobal.mqtt_data, MQTT_CLEAN_SESSION)) {
#else
if (MqttClient.connect(TasmotaGlobal.mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, lwt_retain, TasmotaGlobal.mqtt_data, MQTT_CLEAN_SESSION)) {
#endif // USE_MQTT_AZURE_IOT