From dd9da2853a01abbadf710004741ca0a837448823 Mon Sep 17 00:00:00 2001 From: Aircoookie <21045690+Aircoookie@users.noreply.github.com> Date: Wed, 14 Jun 2023 11:53:39 +0200 Subject: [PATCH] Support settings pin unlock via JSON Also supports locking by providing any incorrect pin --- CHANGELOG.md | 4 ++++ wled00/const.h | 5 ++++- wled00/fcn_declare.h | 1 + wled00/set.cpp | 5 ++--- wled00/util.cpp | 10 ++++++++++ wled00/wled.cpp | 2 +- wled00/wled.h | 2 +- wled00/wled_server.cpp | 9 ++++----- 8 files changed, 27 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63fa9c69..c3b109d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## WLED changelog +#### Build 2306140 + +- Add settings PIN (un)locking to JSON post API + #### Build 2306130 - Bumped version to 0.14-b3 (beta 3) - added pin dropdowns in LED preferences (not for LED pins) and usermods diff --git a/wled00/const.h b/wled00/const.h index db14e972..793d3c5e 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -443,7 +443,10 @@ #define DEFAULT_LED_COUNT 30 #endif -#define INTERFACE_UPDATE_COOLDOWN 2000 //time in ms to wait between websockets, alexa, and MQTT updates +#define INTERFACE_UPDATE_COOLDOWN 2000 // time in ms to wait between websockets, alexa, and MQTT updates + +#define PIN_RETRY_COOLDOWN 3000 // time in ms after an incorrect attempt PIN and OTA pass will be rejected even if correct +#define PIN_TIMEOUT 900000 // time in ms after which the PIN will be required again, 15 minutes // HW_PIN_SCL & HW_PIN_SDA are used for information in usermods settings page and usermods themselves // which GPIO pins are actually used in a hardwarea layout (controller board) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 9d4e9e0e..153f26bd 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -335,6 +335,7 @@ void releaseJSONBufferLock(); uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen); uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxLen, uint8_t *var = nullptr); int16_t extractModeDefaults(uint8_t mode, const char *segVar); +void checkSettingsPIN(const char *pin); uint16_t crc16(const unsigned char* data_p, size_t length); um_data_t* simulateSound(uint8_t simulationId); void enumerateLedmaps(); diff --git a/wled00/set.cpp b/wled00/set.cpp index cc3c0bca..d9297fe2 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -10,8 +10,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) // PIN code request if (subPage == 252) { - correctPIN = (strlen(settingsPIN)==0 || strncmp(settingsPIN, request->arg(F("PIN")).c_str(), 4)==0); - lastEditTime = millis(); + checkSettingsPIN(request->arg(F("PIN")).c_str()); return; } @@ -484,7 +483,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) if (otaLock && strcmp(otaPass,request->arg(F("OP")).c_str()) == 0) { // brute force protection: do not unlock even if correct if last save was less than 3 seconds ago - if (millis() - lastEditTime > 3000) pwdCorrect = true; + if (millis() - lastEditTime > PIN_RETRY_COOLDOWN) pwdCorrect = true; } if (!otaLock && request->arg(F("OP")).length() > 0) { diff --git a/wled00/util.cpp b/wled00/util.cpp index ebe11315..cf04aa5d 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -373,6 +373,16 @@ int16_t extractModeDefaults(uint8_t mode, const char *segVar) } +void checkSettingsPIN(const char* pin) { + if (!pin) return; + if (!correctPIN && millis() - lastEditTime < PIN_RETRY_COOLDOWN) return; // guard against PIN brute force + bool correctBefore = correctPIN; + correctPIN = (strlen(settingsPIN) == 0 || strncmp(settingsPIN, pin, 4) == 0); + if (correctBefore != correctPIN) createEditHandler(correctPIN); + lastEditTime = millis(); +} + + uint16_t crc16(const unsigned char* data_p, size_t length) { uint8_t x; uint16_t crc = 0xFFFF; diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 6954bbee..5f807c4f 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -138,7 +138,7 @@ void WLED::loop() } // 15min PIN time-out - if (strlen(settingsPIN)>0 && millis() - lastEditTime > 900000) { + if (strlen(settingsPIN)>0 && correctPIN && millis() - lastEditTime > PIN_TIMEOUT) { correctPIN = false; createEditHandler(false); } diff --git a/wled00/wled.h b/wled00/wled.h index 03380f8f..cb33feb9 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2306130 +#define VERSION 2306140 //uncomment this if you have a "my_config.h" file you'd like to use //#define WLED_USE_MY_CONFIG diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp index d3d3eb22..385fd3f1 100644 --- a/wled00/wled_server.cpp +++ b/wled00/wled_server.cpp @@ -198,6 +198,8 @@ void initServer() request->send(400, "application/json", F("{\"error\":9}")); // ERR_JSON return; } + if (root.containsKey("pin")) checkSettingsPIN(root["pin"].as()); + const String& url = request->url(); isConfig = url.indexOf("cfg") > -1; if (!isConfig) { @@ -582,7 +584,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) } // if OTA locked or too frequent PIN entry requests fail hard - if ((subPage == 1 && wifiLock && otaLock) || (post && !correctPIN && millis()-lastEditTime < 3000)) + if ((subPage == 1 && wifiLock && otaLock) || (post && !correctPIN && millis()-lastEditTime < PIN_RETRY_COOLDOWN)) { serveMessage(request, 500, "Access Denied", FPSTR(s_unlock_ota), 254); return; } @@ -606,10 +608,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) case 252: strcpy_P(s, correctPIN ? PSTR("PIN accepted") : PSTR("PIN rejected")); break; } - if (subPage == 252) { - createEditHandler(correctPIN); - } else - strcat_P(s, PSTR(" settings saved.")); + if (subPage != 252) strcat_P(s, PSTR(" settings saved.")); if (subPage == 252 && correctPIN) { subPage = originalSubPage; // on correct PIN load settings page the user intended