Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ ESP8266WebServer server(80); // ESP8266 web
#include <ArduinoOTA.h> // for Update
#include <DNSServer.h> // DNS for captive portal
#include <HeatPump.h> // SwiCago library: https://github.com/SwiCago/HeatPump
#include <MD5Builder.h> // for the session cookie hash
#include <Ministache.h>
#include <PubSubClient.h> // MQTT: PubSubClient 2.8.0

Expand Down Expand Up @@ -1266,6 +1267,18 @@ void handleLogin() {
renderView(views::login, data, {{"header", partials::header}, {"footer", partials::footer}});
}

// The session cookie is a hash of the client's IP address and the login password
// (https://github.com/floatplane/MitsuQTT/issues/59): it can't be forged without knowing the
// password, and can't be replayed from a different address. Changing the password invalidates
// all sessions.
String sessionCookie() {
MD5Builder md5;
md5.begin();
md5.add(server.client().remoteIP().toString() + config.unit.login_password);
md5.calculate();
return String(F("M2MSESSIONID=")) + md5.toString();
}

// Handle the auth via POST
// If the password is correct, set the session cookie and redirect to the home page
// If the password is incorrect, redirect back to the login page with an error message
Expand All @@ -1274,12 +1287,12 @@ void handleAuth() {

if (server.hasArg("PASSWORD") && server.arg("PASSWORD") == config.unit.login_password) {
server.sendHeader("Cache-Control", "no-cache");
server.sendHeader("Set-Cookie", "M2MSESSIONID=1");
server.sendHeader("Set-Cookie", sessionCookie() + F("; HttpOnly; SameSite=Strict"));
server.sendHeader("Location", "/");
server.send(httpFound, F("text/plain"), "Redirect to home page");
} else {
server.sendHeader("Cache-Control", "no-cache");
server.sendHeader("Set-Cookie", "M2MSESSIONID=0");
server.sendHeader("Set-Cookie", F("M2MSESSIONID=0; HttpOnly; SameSite=Strict"));
server.sendHeader("Location", "/login?authError");
server.send(httpFound, F("text/plain"), "Redirect to login");
}
Expand All @@ -1290,7 +1303,7 @@ void handleLogout() {
LOG(F("handleLogout()"));

server.sendHeader("Cache-Control", "no-cache");
server.sendHeader("Set-Cookie", "M2MSESSIONID=0");
server.sendHeader("Set-Cookie", F("M2MSESSIONID=0; HttpOnly; SameSite=Strict; Max-Age=0"));
server.sendHeader("Location", "/login");
server.send(httpFound, F("text/plain"), "Redirect to login");
}
Expand Down Expand Up @@ -1947,8 +1960,8 @@ String getId() {
// Check if header is present and correct
bool is_authenticated() {
if (server.hasHeader("Cookie")) {
// Found cookie;
if (server.header("Cookie").indexOf("M2MSESSIONID=1") != -1) {
// Found cookie; verify that it contains the session token for this client
if (server.header("Cookie").indexOf(sessionCookie()) != -1) {
// Authentication Successful
return true;
}
Expand Down
1 change: 1 addition & 0 deletions src/main.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,6 @@ bool connectWifi();
bool checkLogin();
HeatpumpSettings change_states(const HeatpumpSettings &settings);
String getTemperatureScale();
String sessionCookie();
bool is_authenticated();
void hpCheckRemoteTemp();
Loading