Browse Source

Added basic authetication and CSRF check to websocket requests

fastled
Xose Pérez 8 years ago
parent
commit
4de83916d1
3 changed files with 58 additions and 10 deletions
  1. +10
    -4
      code/html/custom.js
  2. +12
    -3
      code/src/defaults.h
  3. +36
    -3
      code/src/web.ino

+ 10
- 4
code/html/custom.js View File

@ -1,8 +1,9 @@
var websock; var websock;
var csrf;
function doUpdate() { function doUpdate() {
var data = $("#formSave").serializeArray(); var data = $("#formSave").serializeArray();
websock.send(JSON.stringify({'config': data}));
websock.send(JSON.stringify({'csrf': csrf, 'config': data}));
$(".powExpected").val(0); $(".powExpected").val(0);
return false; return false;
} }
@ -10,19 +11,19 @@ function doUpdate() {
function doReset() { function doReset() {
var response = window.confirm("Are you sure you want to reset the device?"); var response = window.confirm("Are you sure you want to reset the device?");
if (response == false) return false; if (response == false) return false;
websock.send(JSON.stringify({'action': 'reset'}));
websock.send(JSON.stringify({'csrf': csrf, 'action': 'reset'}));
return false; return false;
} }
function doReconnect() { function doReconnect() {
var response = window.confirm("Are you sure you want to disconnect from the current WIFI network?"); var response = window.confirm("Are you sure you want to disconnect from the current WIFI network?");
if (response == false) return false; if (response == false) return false;
websock.send(JSON.stringify({'action': 'reconnect'}));
websock.send(JSON.stringify({'csrf': csrf, 'action': 'reconnect'}));
return false; return false;
} }
function doToggle(element, value) { function doToggle(element, value) {
websock.send(JSON.stringify({'action': value ? 'on' : 'off'}));
websock.send(JSON.stringify({'csrf': csrf, 'action': value ? 'on' : 'off'}));
return false; return false;
} }
@ -40,6 +41,11 @@ function toggleMenu() {
function processData(data) { function processData(data) {
// CSRF
if ("csrf" in data) {
csrf = data.csrf;
}
// messages // messages
if ("message" in data) { if ("message" in data) {
window.alert(data.message); window.alert(data.message);


+ 12
- 3
code/src/defaults.h View File

@ -68,13 +68,22 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// WIFI
// WIFI & WEB
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#define WIFI_RECONNECT_INTERVAL 300000 #define WIFI_RECONNECT_INTERVAL 300000
#define WIFI_MAX_NETWORKS 3 #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 OTA_PORT 8266
#define NOFUSS_SERVER "http://192.168.1.100" #define NOFUSS_SERVER "http://192.168.1.100"
#define NOFUSS_INTERVAL 3600000 #define NOFUSS_INTERVAL 3600000


+ 36
- 3
code/src/web.ino View File

@ -10,14 +10,16 @@ Copyright (C) 2016 by Xose Pérez <xose dot perez at gmail dot com>
#include <ESPAsyncTCP.h> #include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h> #include <ESPAsyncWebServer.h>
#include <ESP8266mDNS.h> #include <ESP8266mDNS.h>
#include "FS.h"
#include <FS.h>
#include <Hash.h> #include <Hash.h>
#include "AsyncJson.h"
#include <AsyncJson.h>
#include <ArduinoJson.h> #include <ArduinoJson.h>
AsyncWebServer server(80); AsyncWebServer server(80);
AsyncWebSocket ws("/ws"); AsyncWebSocket ws("/ws");
unsigned long _csrf[CSRF_BUFFER_SIZE];
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// WEBSOCKETS // WEBSOCKETS
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -43,6 +45,16 @@ void webSocketParse(uint32_t client_id, uint8_t * payload, size_t length) {
return; 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 // Check actions
if (root.containsKey("action")) { if (root.containsKey("action")) {
@ -144,6 +156,12 @@ void webSocketStart(uint32_t client_id) {
DynamicJsonBuffer jsonBuffer; DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.createObject(); 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["app"] = app;
root["manufacturer"] = String(MANUFACTURER); root["manufacturer"] = String(MANUFACTURER);
root["chipid"] = chipid; root["chipid"] = chipid;
@ -222,14 +240,29 @@ void webSocketEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsE
// WEBSERVER // 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() { void webSetup() {
// Setup websocket plugin // Setup websocket plugin
ws.onEvent(webSocketEvent); ws.onEvent(webSocketEvent);
server.addHandler(&ws); server.addHandler(&ws);
// Serve home
server.on("/", HTTP_GET, onHome);
server.on("/index.html", HTTP_GET, onHome);
// Serve static files // Serve static files
server.serveStatic("/", SPIFFS, "/").setDefaultFile("/index.html");
server.serveStatic("/", SPIFFS, "/");
// 404 // 404
server.onNotFound([](AsyncWebServerRequest *request){ server.onNotFound([](AsyncWebServerRequest *request){


Loading…
Cancel
Save