@@ -16,6 +16,7 @@ static const char s_redirecting[] PROGMEM = "Redirecting...";
1616static const char s_content_enc[] PROGMEM = " Content-Encoding" ;
1717static const char s_unlock_ota [] PROGMEM = " Please unlock OTA in security settings!" ;
1818static const char s_unlock_cfg [] PROGMEM = " Please unlock settings using PIN code!" ;
19+ static const char s_rebooting [] PROGMEM = " Rebooting now..." ;
1920static const char s_notimplemented[] PROGMEM = " Not implemented" ;
2021static const char s_accessdenied[] PROGMEM = " Access Denied" ;
2122static const char _common_js[] PROGMEM = " /common.js" ;
@@ -31,6 +32,22 @@ static bool isIp(const String &str) {
3132 return true ;
3233}
3334
35+ static bool inSubnet (const IPAddress &ip, const IPAddress &subnet, const IPAddress &mask) {
36+ return (((uint32_t )ip & (uint32_t )mask) == ((uint32_t )subnet & (uint32_t )mask));
37+ }
38+
39+ static bool inSameSubnet (const IPAddress &client) {
40+ return inSubnet (client, Network.localIP (), Network.subnetMask ());
41+ }
42+
43+ static bool inLocalSubnet (const IPAddress &client) {
44+ return inSubnet (client, IPAddress (10 ,0 ,0 ,0 ), IPAddress (255 ,0 ,0 ,0 )) // 10.x.x.x
45+ || inSubnet (client, IPAddress (192 ,168 ,0 ,0 ), IPAddress (255 ,255 ,0 ,0 )) // 192.168.x.x
46+ || inSubnet (client, IPAddress (172 ,16 ,0 ,0 ), IPAddress (255 ,240 ,0 ,0 )) // 172.16.x.x
47+ || (inSubnet (client, IPAddress (4 ,3 ,2 ,0 ), IPAddress (255 ,255 ,255 ,0 )) && apActive) // WLED AP
48+ || inSameSubnet (client); // same subnet as WLED device
49+ }
50+
3451/*
3552 * Integrated HTTP web server page declarations
3653 */
@@ -130,7 +147,7 @@ static String msgProcessor(const String& var)
130147 if (optt < 60 ) // redirect to settings after optionType seconds
131148 {
132149 messageBody += F (" <script>setTimeout(RS," );
133- messageBody +=String (optt*1000 );
150+ messageBody += String (optt*1000 );
134151 messageBody += F (" )</script>" );
135152 } else if (optt < 120 ) // redirect back after optionType-60 seconds, unused
136153 {
@@ -270,7 +287,7 @@ void initServer()
270287 });
271288
272289 server.on (F (" /reset" ), HTTP_GET, [](AsyncWebServerRequest *request){
273- serveMessage (request, 200 ,F ( " Rebooting now... " ), F (" Please wait ~10 seconds... " ),129 );
290+ serveMessage (request, 200 , FPSTR (s_rebooting), F (" Please wait ~10 seconds." ), 131 );
274291 doReboot = true ;
275292 });
276293
@@ -385,10 +402,16 @@ void initServer()
385402 if (Update.hasError ()) {
386403 serveMessage (request, 500 , F (" Update failed!" ), F (" Please check your file and retry!" ), 254 );
387404 } else {
388- serveMessage (request, 200 , F (" Update successful!" ), F ( " Rebooting... " ), 131 );
405+ serveMessage (request, 200 , F (" Update successful!" ), FPSTR (s_rebooting ), 131 );
389406 doReboot = true ;
390407 }
391408 },[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool isFinal){
409+ IPAddress client = request->client ()->remoteIP ();
410+ if (((otaSameSubnet && !inSameSubnet (client)) && !strlen (settingsPIN)) || (!otaSameSubnet && !inLocalSubnet (client))) {
411+ DEBUG_PRINTLN (F (" Attempted OTA update from different/non-local subnet!" ));
412+ request->send (401 , FPSTR (CONTENT_TYPE_PLAIN), FPSTR (s_accessdenied));
413+ return ;
414+ }
392415 if (!correctPIN || otaLock) return ;
393416 if (!index){
394417 DEBUG_PRINTLN (F (" OTA Update Start" ));
@@ -573,6 +596,11 @@ void serveSettings(AsyncWebServerRequest* request, bool post) {
573596 }
574597
575598 if (post ) { // settings/set POST request, saving
599+ IPAddress client = request->client ()->remoteIP ();
600+ if (!inLocalSubnet (client)) { // includes same subnet check
601+ serveMessage (request, 401 , FPSTR (s_accessdenied), FPSTR (s_redirecting), 123 );
602+ return ;
603+ }
576604 if (subPage != SUBPAGE_WIFI || !(wifiLock && otaLock)) handleSettingsSet (request, subPage);
577605
578606 char s[32 ];
@@ -624,7 +652,19 @@ void serveSettings(AsyncWebServerRequest* request, bool post) {
624652 case SUBPAGE_DMX : content = PAGE_settings_dmx; len = PAGE_settings_dmx_length; break ;
625653#endif
626654 case SUBPAGE_UM : content = PAGE_settings_um; len = PAGE_settings_um_length; break ;
627- case SUBPAGE_UPDATE : content = PAGE_update; len = PAGE_update_length; break ;
655+ case SUBPAGE_UPDATE : content = PAGE_update; len = PAGE_update_length;
656+ #ifdef ARDUINO_ARCH_ESP32
657+ if (request->hasArg (F (" revert" )) && inLocalSubnet (request->client ()->remoteIP ()) && Update.canRollBack ()) {
658+ doReboot = Update.rollBack ();
659+ if (doReboot) {
660+ serveMessage (request, 200 , F (" Reverted to previous version!" ), FPSTR (s_rebooting), 133 );
661+ } else {
662+ serveMessage (request, 500 , F (" Rollback failed!" ), F (" Please reboot and retry." ), 254 );
663+ }
664+ return ;
665+ }
666+ #endif
667+ break ;
628668#ifndef WLED_DISABLE_2D
629669 case SUBPAGE_2D : content = PAGE_settings_2D; len = PAGE_settings_2D_length; break ;
630670#endif
0 commit comments