Skip to content

Commit a7ced9c

Browse files
me-no-devigrr
authored andcommitted
make HTTP Update Server more secure (esp8266#2104)
* make HTTP Update Server more secure * added option for authentication * added option to change the url for upload * move to overloaded setup * remove delay in both examples * Get better result responses * fix strings interesting, the meta did not refresh if the successResponse is put in "R"
1 parent 32bd42b commit a7ced9c

File tree

4 files changed

+94
-14
lines changed

4 files changed

+94
-14
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
To upload through terminal you can use: curl -F "[email protected]" esp8266-webupdate.local/update
3+
*/
4+
5+
#include <ESP8266WiFi.h>
6+
#include <WiFiClient.h>
7+
#include <ESP8266WebServer.h>
8+
#include <ESP8266mDNS.h>
9+
#include <ESP8266HTTPUpdateServer.h>
10+
11+
const char* host = "esp8266-webupdate";
12+
const char* update_path = "/firmware";
13+
const char* update_username = "admin";
14+
const char* update_password = "admin";
15+
const char* ssid = "........";
16+
const char* password = "........";
17+
18+
ESP8266WebServer httpServer(80);
19+
ESP8266HTTPUpdateServer httpUpdater;
20+
21+
void setup(void){
22+
23+
Serial.begin(115200);
24+
Serial.println();
25+
Serial.println("Booting Sketch...");
26+
WiFi.mode(WIFI_AP_STA);
27+
WiFi.begin(ssid, password);
28+
29+
while(WiFi.waitForConnectResult() != WL_CONNECTED){
30+
WiFi.begin(ssid, password);
31+
Serial.println("WiFi failed, retrying.");
32+
}
33+
34+
MDNS.begin(host);
35+
36+
httpUpdater.setup(&httpServer, update_path, update_username, update_password);
37+
httpServer.begin();
38+
39+
MDNS.addService("http", "tcp", 80);
40+
Serial.printf("HTTPUpdateServer ready! Open http://%s.local%s in your browser and login with username '%s' and password '%s'\n", host, update_path, update_username, update_password);
41+
}
42+
43+
void loop(void){
44+
httpServer.handleClient();
45+
}

libraries/ESP8266HTTPUpdateServer/examples/WebUpdater/WebUpdater.ino

-1
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,4 @@ void setup(void){
3939

4040
void loop(void){
4141
httpServer.handleClient();
42-
delay(1);
4342
}

libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp

+27-12
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,41 @@
77

88

99
const char* ESP8266HTTPUpdateServer::_serverIndex =
10-
R"(<html><body><form method='POST' action='/update' enctype='multipart/form-data'>
10+
R"(<html><body><form method='POST' action='' enctype='multipart/form-data'>
1111
<input type='file' name='update'>
1212
<input type='submit' value='Update'>
1313
</form>
1414
</body></html>)";
15+
const char* ESP8266HTTPUpdateServer::_failedResponse = R"(Update Failed!)";
16+
const char* ESP8266HTTPUpdateServer::_successResponse = "<META http-equiv=\"refresh\" content=\"15;URL=\">Update Success! Rebooting...";
1517

1618
ESP8266HTTPUpdateServer::ESP8266HTTPUpdateServer(bool serial_debug)
1719
{
1820
_serial_output = serial_debug;
1921
_server = NULL;
22+
_username = NULL;
23+
_password = NULL;
24+
_authenticated = false;
2025
}
2126

22-
void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server)
27+
void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const char * path, const char * username, const char * password)
2328
{
2429
_server = server;
30+
_username = (char *)username;
31+
_password = (char *)password;
2532

2633
// handler for the /update form page
27-
_server->on("/update", HTTP_GET, [&](){
28-
_server->sendHeader("Connection", "close");
29-
_server->sendHeader("Access-Control-Allow-Origin", "*");
34+
_server->on(path, HTTP_GET, [&](){
35+
if(_username != NULL && _password != NULL && !_server->authenticate(_username, _password))
36+
return _server->requestAuthentication();
3037
_server->send(200, "text/html", _serverIndex);
3138
});
3239

3340
// handler for the /update form POST (once file upload finishes)
34-
_server->on("/update", HTTP_POST, [&](){
35-
_server->sendHeader("Connection", "close");
36-
_server->sendHeader("Access-Control-Allow-Origin", "*");
37-
_server->send(200, "text/html", (Update.hasError())?"FAIL":"<META http-equiv=\"refresh\" content=\"15;URL=/update\">OK");
41+
_server->on(path, HTTP_POST, [&](){
42+
if(!_authenticated)
43+
return _server->requestAuthentication();
44+
_server->send(200, "text/html", Update.hasError() ? _failedResponse : _successResponse);
3845
ESP.restart();
3946
},[&](){
4047
// handler for the file upload, get's the sketch bytes, and writes
@@ -43,27 +50,35 @@ void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server)
4350
if(upload.status == UPLOAD_FILE_START){
4451
if (_serial_output)
4552
Serial.setDebugOutput(true);
53+
54+
_authenticated = (_username == NULL || _password == NULL || _server->authenticate(_username, _password));
55+
if(!_authenticated){
56+
if (_serial_output)
57+
Serial.printf("Unauthenticated Update\n");
58+
return;
59+
}
60+
4661
WiFiUDP::stopAll();
4762
if (_serial_output)
4863
Serial.printf("Update: %s\n", upload.filename.c_str());
4964
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
5065
if(!Update.begin(maxSketchSpace)){//start with max available size
5166
if (_serial_output) Update.printError(Serial);
5267
}
53-
} else if(upload.status == UPLOAD_FILE_WRITE){
68+
} else if(_authenticated && upload.status == UPLOAD_FILE_WRITE){
5469
if (_serial_output) Serial.printf(".");
5570
if(Update.write(upload.buf, upload.currentSize) != upload.currentSize){
5671
if (_serial_output) Update.printError(Serial);
5772

5873
}
59-
} else if(upload.status == UPLOAD_FILE_END){
74+
} else if(_authenticated && upload.status == UPLOAD_FILE_END){
6075
if(Update.end(true)){ //true to set the size to the current progress
6176
if (_serial_output) Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
6277
} else {
6378
if (_serial_output) Update.printError(Serial);
6479
}
6580
if (_serial_output) Serial.setDebugOutput(false);
66-
} else if(upload.status == UPLOAD_FILE_ABORTED){
81+
} else if(_authenticated && upload.status == UPLOAD_FILE_ABORTED){
6782
Update.end();
6883
if (_serial_output) Serial.println("Update was aborted");
6984
}

libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h

+22-1
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,30 @@ class ESP8266HTTPUpdateServer
99
bool _serial_output;
1010
ESP8266WebServer *_server;
1111
static const char *_serverIndex;
12+
static const char *_failedResponse;
13+
static const char *_successResponse;
14+
char * _username;
15+
char * _password;
16+
bool _authenticated;
1217
public:
1318
ESP8266HTTPUpdateServer(bool serial_debug=false);
14-
void setup(ESP8266WebServer *server=NULL);
19+
20+
void setup(ESP8266WebServer *server)
21+
{
22+
setup(server, NULL, NULL);
23+
}
24+
25+
void setup(ESP8266WebServer *server, const char * path)
26+
{
27+
setup(server, path, NULL, NULL);
28+
}
29+
30+
void setup(ESP8266WebServer *server, const char * username, const char * password)
31+
{
32+
setup(server, "/update", username, password);
33+
}
34+
35+
void setup(ESP8266WebServer *server, const char * path, const char * username, const char * password);
1536
};
1637

1738

0 commit comments

Comments
 (0)