Skip to content

Commit

Permalink
UI communication progress
Browse files Browse the repository at this point in the history
  • Loading branch information
Aircoookie committed Oct 13, 2024
1 parent af1ee61 commit b02bc29
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 1 deletion.
3 changes: 3 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@

</p>

> [!CAUTION]
> This branch is actively used for research purposes. **Please do not push** to it.
# Welcome to my project WLED! ✨

A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B, WS2811, SK6812) LEDs or also SPI based chipsets like the WS2801 and APA102!
Expand Down
14 changes: 14 additions & 0 deletions wled00/crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ bool hmac_verify(const char* message, const char* psk, const byte* signature) {
return true;
}

bool verify_json_hmac(JsonObject root) {
JsonObject msg = root["msg"];
if (!msg) {
Serial.println(F("No message object found in JSON."));
return false;
}
const char *sig = msg["sig"];
if (sig == nullptr) {
Serial.println(F("No signature found in JSON."));
return false;
}

}

bool hmac_test() {
Serial.println(F("Testing HMAC..."));
unsigned long start = millis();
Expand Down
37 changes: 37 additions & 0 deletions wled00/data/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ function loadSkinCSS(cId)
}
}

var useSRA = false;
var sraWindow = null;
var sraOrigin = '';

function getURL(path) {
return (loc ? locproto + "//" + locip : "") + path;
}
Expand Down Expand Up @@ -243,6 +247,13 @@ function onLoad()
var sett = localStorage.getItem('wledUiCfg');
if (sett) cfg = mergeDeep(cfg, JSON.parse(sett));

if (window.opener) {
// can't get opener origin due to cross-origin browser policy
//var openerOrigin = window.opener.location.origin;
//console.log("WLED-UI opener origin: " + openerOrigin);
window.opener.postMessage('{"wled-ui":"onload"}', '*'); //openerOrigin);
}

tooltip();
resetPUtil();
initFilters();
Expand Down Expand Up @@ -301,6 +312,26 @@ function onLoad()
});
}

function handleWindowMessageEvent(event) {
console.log(`Received message: ${event.data}`);
console.log(`origin: ${event.origin}`);
try {
var json = JSON.parse(event.data)
} catch (e) {
console.log(`Error parsing JSON: ${e}`);
return;
}
if (json['wled-rc'] === 'ready') {
useSRA = true;
sraWindow = event.source;
sraOrigin = event.origin;
} else if (json['wled-rc'] === 'hmac') {
console.log(`Received HMAC: ${json['hmac']}`);
}
}

onmessage = (event) => { handleWindowMessageEvent(event) };

function updateTablinks(tabI)
{
var tablinks = gEBCN("tablinks");
Expand Down Expand Up @@ -1703,6 +1734,12 @@ function requestJson(command=null)
if (req.length > 500 && lastinfo && lastinfo.arch == "esp8266") useWs = false; // esp8266 can only handle 500 bytes
};

if (command && useSRA && !command['sig']) { // secure remote access integration, need to get HMAC from rc.wled.me
// if we already have a command including a signature, we are good to go
sraWindow.postMessage(JSON.stringify({"wled-ui":"hmac-req", "msg":command}), sraOrigin);
return; // TODO need a sort of pending indicator
}

if (useWs) {
ws.send(req?req:'{"v":true}');
return;
Expand Down
30 changes: 29 additions & 1 deletion wled00/wled_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,16 +297,44 @@ void initServer()
DeserializationError error = deserializeJson(*pDoc, (uint8_t*)(request->_tempObject));

// if enabled, calculate HMAC and verify it
Serial.println("HMAC verification");
Serial.println(F("HMAC verification"));
Serial.write((const char*)request->_tempObject, request->contentLength());

// actually we need to verify the HMAC of the nested "msg" object
if (strlen((const char*)request->_tempObject) > request->contentLength()) {
Serial.println(F("HMAC verification failed: content is not null-terminated"));
releaseJSONBufferLock();
serveJsonError(request, 400, ERR_JSON);
return;
}
// find the "msg" object in JSON
char * msgPtr = strstr((const char*)request->_tempObject, "\"msg\":");
if (msgPtr == NULL) {
Serial.println(F("HMAC verification failed: no \"msg\" object found"));
releaseJSONBufferLock();
serveJsonError(request, 400, ERR_JSON);
return;
}
char * objStart = strchr(msgPtr, '{');

JsonObject root = pDoc->as<JsonObject>();
if (error || root.isNull()) {
releaseJSONBufferLock();
serveJsonError(request, 400, ERR_JSON);
return;
}

// if (root.containsKey("sig")) {
// const char* hmacProvided = root["sig"];
// char hmac_calculated[SHA256HMAC_SIZE];
// hmac_sign((const char*)request->_tempObject, settings.hmacKey, (byte*)hmac_calculated);
// if (memcmp(hmac_calculated, hmac, SHA256HMAC_SIZE) != 0) {
// releaseJSONBufferLock();
// serveJsonError(request, 401, ERR_HMAC);
// return;
// }
// }

// old 4-digit pin logic for settings authentication (no transport encryption)
if (root.containsKey("pin")) checkSettingsPIN(root["pin"].as<const char*>());

Expand Down

0 comments on commit b02bc29

Please sign in to comment.