diff --git a/code/html/custom.js b/code/html/custom.js
index 828c26dc..581a192e 100644
--- a/code/html/custom.js
+++ b/code/html/custom.js
@@ -1,8 +1,9 @@
var websock;
+var csrf;
function doUpdate() {
var data = $("#formSave").serializeArray();
- websock.send(JSON.stringify({'config': data}));
+ websock.send(JSON.stringify({'csrf': csrf, 'config': data}));
$(".powExpected").val(0);
return false;
}
@@ -10,19 +11,19 @@ function doUpdate() {
function doReset() {
var response = window.confirm("Are you sure you want to reset the device?");
if (response == false) return false;
- websock.send(JSON.stringify({'action': 'reset'}));
+ websock.send(JSON.stringify({'csrf': csrf, 'action': 'reset'}));
return false;
}
function doReconnect() {
var response = window.confirm("Are you sure you want to disconnect from the current WIFI network?");
if (response == false) return false;
- websock.send(JSON.stringify({'action': 'reconnect'}));
+ websock.send(JSON.stringify({'csrf': csrf, 'action': 'reconnect'}));
return false;
}
function doToggle(element, value) {
- websock.send(JSON.stringify({'action': value ? 'on' : 'off'}));
+ websock.send(JSON.stringify({'csrf': csrf, 'action': value ? 'on' : 'off'}));
return false;
}
@@ -40,6 +41,11 @@ function toggleMenu() {
function processData(data) {
+ // CSRF
+ if ("csrf" in data) {
+ csrf = data.csrf;
+ }
+
// messages
if ("message" in data) {
window.alert(data.message);
diff --git a/code/src/defaults.h b/code/src/defaults.h
index bb99d593..fd1ede80 100644
--- a/code/src/defaults.h
+++ b/code/src/defaults.h
@@ -68,13 +68,22 @@
// -----------------------------------------------------------------------------
-// WIFI
+// WIFI & WEB
// -----------------------------------------------------------------------------
#define WIFI_RECONNECT_INTERVAL 300000
#define WIFI_MAX_NETWORKS 3
-#define AP_PASS "fibonacci"
-#define OTA_PASS "fibonacci"
+#define ADMIN_PASS "fibonacci"
+#define AP_PASS ADMIN_PASS
+#define HTTP_USERNAME "admin"
+#define HTTP_PASSWORD ADMIN_PASS
+#define CSRF_BUFFER_SIZE 5
+
+// -----------------------------------------------------------------------------
+// OTA & NOFUSS
+// -----------------------------------------------------------------------------
+
+#define OTA_PASS ADMIN_PASS
#define OTA_PORT 8266
#define NOFUSS_SERVER "http://192.168.1.100"
#define NOFUSS_INTERVAL 3600000
diff --git a/code/src/web.ino b/code/src/web.ino
index da532745..958b2afa 100644
--- a/code/src/web.ino
+++ b/code/src/web.ino
@@ -10,14 +10,16 @@ Copyright (C) 2016 by Xose PĂ©rez
#include
#include
#include
-#include "FS.h"
+#include
#include
-#include "AsyncJson.h"
+#include
#include
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");
+unsigned long _csrf[CSRF_BUFFER_SIZE];
+
// -----------------------------------------------------------------------------
// WEBSOCKETS
// -----------------------------------------------------------------------------
@@ -43,6 +45,16 @@ void webSocketParse(uint32_t client_id, uint8_t * payload, size_t length) {
return;
}
+ // CSRF
+ unsigned long csrf = 0;
+ if (root.containsKey("csrf")) csrf = root["csrf"];
+ if (csrf != _csrf[client_id % CSRF_BUFFER_SIZE]) {
+ DEBUG_MSG("[WEBSOCKET] CSRF check failed\n");
+ ws.text(client_id, "{\"message\": \"Session expired, please reload page...\"}");
+ return;
+ }
+
+
// Check actions
if (root.containsKey("action")) {
@@ -144,6 +156,12 @@ void webSocketStart(uint32_t client_id) {
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
+ // CSRF
+ if (client_id < CSRF_BUFFER_SIZE) {
+ _csrf[client_id] = random(0x7fffffff);
+ }
+ root["csrf"] = _csrf[client_id % CSRF_BUFFER_SIZE];
+
root["app"] = app;
root["manufacturer"] = String(MANUFACTURER);
root["chipid"] = chipid;
@@ -222,14 +240,29 @@ void webSocketEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsE
// WEBSERVER
// -----------------------------------------------------------------------------
+void onHome(AsyncWebServerRequest *request){
+ String password = getSetting("httpPassword", HTTP_PASSWORD);
+ char httpPassword[password.length() + 1];
+ password.toCharArray(httpPassword, password.length() + 1);
+ Serial.println(httpPassword);
+ if (!request->authenticate(HTTP_USERNAME, httpPassword)) {
+ return request->requestAuthentication();
+ }
+ request->send(SPIFFS, "/index.html");
+}
+
void webSetup() {
// Setup websocket plugin
ws.onEvent(webSocketEvent);
server.addHandler(&ws);
+ // Serve home
+ server.on("/", HTTP_GET, onHome);
+ server.on("/index.html", HTTP_GET, onHome);
+
// Serve static files
- server.serveStatic("/", SPIFFS, "/").setDefaultFile("/index.html");
+ server.serveStatic("/", SPIFFS, "/");
// 404
server.onNotFound([](AsyncWebServerRequest *request){