Integrated authentication test in WebServer
This commit is contained in:
parent
42c41171ce
commit
1337a7e231
|
@ -5,3 +5,4 @@
|
||||||
.vscode/ipch
|
.vscode/ipch
|
||||||
|
|
||||||
include/WLAN_Logins.h
|
include/WLAN_Logins.h
|
||||||
|
include/Crypto_Config.h
|
||||||
|
|
|
@ -2,4 +2,7 @@
|
||||||
|
|
||||||
## Setup notes
|
## Setup notes
|
||||||
|
|
||||||
Copy `include/WLAN_Logins.h.example` to `include/WLAN_Logins.h` and modify as you need.
|
On the files below, remove the `.example` part of the name and adjust to your needs:
|
||||||
|
|
||||||
|
- `include/WLAN_Logins.h.example`
|
||||||
|
- `include/Crypto_Config.h.example`
|
||||||
|
|
|
@ -4,27 +4,30 @@
|
||||||
#include <HTTPResponse.hpp>
|
#include <HTTPResponse.hpp>
|
||||||
#include <HTTPServer.hpp>
|
#include <HTTPServer.hpp>
|
||||||
|
|
||||||
|
#include "ChallengeResponse.h"
|
||||||
|
|
||||||
class Fader;
|
class Fader;
|
||||||
|
|
||||||
class HTTPServer
|
class WebServer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool start(void);
|
bool start(void);
|
||||||
|
|
||||||
void setFader(Fader *fader) { m_fader = fader;}
|
void setFader(Fader *fader) { m_fader = fader;}
|
||||||
|
|
||||||
static HTTPServer &instance(void)
|
static WebServer &instance(void)
|
||||||
{
|
{
|
||||||
static HTTPServer theInstance;
|
static WebServer theInstance;
|
||||||
return theInstance;
|
return theInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
httpsserver::HTTPServer *m_server;
|
httpsserver::HTTPServer *m_server;
|
||||||
|
ChallengeResponse m_cr;
|
||||||
|
|
||||||
Fader *m_fader;
|
Fader *m_fader;
|
||||||
|
|
||||||
HTTPServer(void);
|
WebServer(void);
|
||||||
|
|
||||||
static void serverTask(void *arg);
|
static void serverTask(void *arg);
|
||||||
|
|
||||||
|
@ -33,5 +36,8 @@ class HTTPServer
|
||||||
// handlers
|
// handlers
|
||||||
static void handleRoot(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res);
|
static void handleRoot(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res);
|
||||||
static void handleColor(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res);
|
static void handleColor(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res);
|
||||||
|
static void handleChallenge(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res);
|
||||||
|
static void handleAuthTest(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res);
|
||||||
|
static void handleUpdate(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res);
|
||||||
static void handle404(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res);
|
static void handle404(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res);
|
||||||
};
|
};
|
|
@ -0,0 +1,38 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import requests
|
||||||
|
import sys
|
||||||
|
import hashlib
|
||||||
|
import time
|
||||||
|
import re
|
||||||
|
|
||||||
|
IP = sys.argv[1]
|
||||||
|
|
||||||
|
# read the salt from the header file
|
||||||
|
with open("../include/Crypto_Config.h", "r") as header:
|
||||||
|
for line in header:
|
||||||
|
if "SALT" in line:
|
||||||
|
mo = re.search(r'"(.*)"', line)
|
||||||
|
SALT = mo.groups()[0]
|
||||||
|
|
||||||
|
print(f'SALT = "{SALT}"')
|
||||||
|
|
||||||
|
# read and store the password from the user
|
||||||
|
pwd = input("Enter password: ")
|
||||||
|
|
||||||
|
# request and parse a challenge from the server
|
||||||
|
challenge = requests.get(f"http://{IP}/challenge").json()
|
||||||
|
|
||||||
|
nonce = int(challenge['nonce'])
|
||||||
|
|
||||||
|
print(f"Nonce: {nonce}")
|
||||||
|
|
||||||
|
# build response string
|
||||||
|
responsestr = pwd + ":" + str(nonce) + ":" + SALT
|
||||||
|
|
||||||
|
m = hashlib.sha256()
|
||||||
|
m.update(responsestr.encode('utf-8'))
|
||||||
|
response = m.hexdigest()
|
||||||
|
|
||||||
|
result = requests.get(f"http://{IP}/authtest", {"response": response})
|
||||||
|
print(result.text)
|
|
@ -1,18 +1,21 @@
|
||||||
/* HTTP Server setup and handler functions */
|
/* HTTP Server setup and handler functions */
|
||||||
|
|
||||||
#include <SPIFFS.h>
|
#include <SPIFFS.h>
|
||||||
|
#include <mbedtls/sha256.h>
|
||||||
|
|
||||||
#include "HTTPServer.h"
|
#include "WebServer.h"
|
||||||
|
|
||||||
|
#include "Crypto_Config.h"
|
||||||
|
|
||||||
#include "Fader.h"
|
#include "Fader.h"
|
||||||
|
|
||||||
HTTPServer::HTTPServer(void)
|
WebServer::WebServer(void)
|
||||||
: m_fader(NULL)
|
: m_cr(crypto::HTTP_PASSWORD), m_fader(NULL)
|
||||||
{
|
{
|
||||||
m_server = new httpsserver::HTTPServer();
|
m_server = new httpsserver::HTTPServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPServer::serveFile(String filename, httpsserver::HTTPResponse *res)
|
void WebServer::serveFile(String filename, httpsserver::HTTPResponse *res)
|
||||||
{
|
{
|
||||||
uint8_t buf[1024];
|
uint8_t buf[1024];
|
||||||
File f = SPIFFS.open(filename.c_str(), "r");
|
File f = SPIFFS.open(filename.c_str(), "r");
|
||||||
|
@ -30,7 +33,7 @@ void HTTPServer::serveFile(String filename, httpsserver::HTTPResponse *res)
|
||||||
f.close();
|
f.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPServer::handleRoot(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res)
|
void WebServer::handleRoot(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res)
|
||||||
{
|
{
|
||||||
serveFile("/index.html", res);
|
serveFile("/index.html", res);
|
||||||
res->setHeader("Content-Type", "text/html");
|
res->setHeader("Content-Type", "text/html");
|
||||||
|
@ -44,7 +47,7 @@ static void error400(httpsserver::HTTPResponse *res, const std::string &reason)
|
||||||
res->setStatusCode(400);
|
res->setStatusCode(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPServer::handleColor(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res)
|
void WebServer::handleColor(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res)
|
||||||
{
|
{
|
||||||
res->setHeader("Content-Type", "text/plain");
|
res->setHeader("Content-Type", "text/plain");
|
||||||
|
|
||||||
|
@ -94,10 +97,84 @@ void HTTPServer::handleColor(httpsserver::HTTPRequest *req, httpsserver::HTTPRes
|
||||||
res->print(" w:");
|
res->print(" w:");
|
||||||
res->println(w);
|
res->println(w);
|
||||||
|
|
||||||
HTTPServer::instance().m_fader->fade_color({r,g,b,w});
|
WebServer::instance().m_fader->fade_color({r,g,b,w});
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPServer::handle404(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res)
|
void WebServer::handleUpdate(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res)
|
||||||
|
{
|
||||||
|
res->setHeader("Content-Type", "text/plain");
|
||||||
|
|
||||||
|
httpsserver::ResourceParameters * params = req->getParams();
|
||||||
|
|
||||||
|
if(!params->isRequestParameterSet("content")) {
|
||||||
|
error400(res, "Send update image as 'content'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
res->print("Content length: ");
|
||||||
|
res->println(req->getContentLength());
|
||||||
|
|
||||||
|
res->println("Content:");
|
||||||
|
res->println("--------------------------------------------------------------------------------");
|
||||||
|
|
||||||
|
uint8_t buf[128];
|
||||||
|
while(!req->requestComplete()) {
|
||||||
|
size_t bytes_processed = req->readBytes(buf, 128);
|
||||||
|
res->write(buf, bytes_processed);
|
||||||
|
}
|
||||||
|
res->println("--------------------------------------------------------------------------------");
|
||||||
|
|
||||||
|
std::vector<uint8_t> d;
|
||||||
|
d.push_back(1);
|
||||||
|
d.push_back(2);
|
||||||
|
d.push_back(3);
|
||||||
|
|
||||||
|
uint8_t sha256sum[32];
|
||||||
|
mbedtls_sha256_ret(d.data(), d.size(), sha256sum, 0);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < 32; i++) {
|
||||||
|
static const char *conv = "0123456789abcdef";
|
||||||
|
|
||||||
|
uint8_t b = sha256sum[i];
|
||||||
|
|
||||||
|
res->print(conv[(b >> 4)]);
|
||||||
|
res->print(conv[(b &0x0F)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
res->println();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebServer::handleChallenge(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res)
|
||||||
|
{
|
||||||
|
res->setHeader("Content-Type", "application/json");
|
||||||
|
|
||||||
|
std::ostringstream responseBuilder;
|
||||||
|
responseBuilder << "{ \"nonce\": " << WebServer::instance().m_cr.nonce() << "}";
|
||||||
|
|
||||||
|
res->println(responseBuilder.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebServer::handleAuthTest(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res)
|
||||||
|
{
|
||||||
|
res->setHeader("Content-Type", "text/plain");
|
||||||
|
|
||||||
|
httpsserver::ResourceParameters * params = req->getParams();
|
||||||
|
|
||||||
|
if(!params->isRequestParameterSet("response")) {
|
||||||
|
error400(res, "Parameter 'response' not set.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string response = params->getRequestParameter("response");
|
||||||
|
bool result = WebServer::instance().m_cr.verify(response);
|
||||||
|
|
||||||
|
if(result) {
|
||||||
|
res->println("Authentication test successful!");
|
||||||
|
} else {
|
||||||
|
res->println("Authentication test failed (invalid response)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebServer::handle404(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res)
|
||||||
{
|
{
|
||||||
req->discardRequestBody();
|
req->discardRequestBody();
|
||||||
|
|
||||||
|
@ -107,19 +184,28 @@ void HTTPServer::handle404(httpsserver::HTTPRequest *req, httpsserver::HTTPRespo
|
||||||
res->println("Error 404: Not found");
|
res->println("Error 404: Not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPServer::serverTask(void *arg)
|
void WebServer::serverTask(void *arg)
|
||||||
{
|
{
|
||||||
httpsserver::ResourceNode *nodeRoot = new httpsserver::ResourceNode("/", "GET",
|
httpsserver::ResourceNode *nodeRoot = new httpsserver::ResourceNode("/", "GET",
|
||||||
HTTPServer::handleRoot);
|
WebServer::handleRoot);
|
||||||
httpsserver::ResourceNode *nodeColor = new httpsserver::ResourceNode("/color", "GET",
|
httpsserver::ResourceNode *nodeColor = new httpsserver::ResourceNode("/color", "GET",
|
||||||
HTTPServer::handleColor);
|
WebServer::handleColor);
|
||||||
|
httpsserver::ResourceNode *nodeUpdate = new httpsserver::ResourceNode("/update", "POST",
|
||||||
|
WebServer::handleUpdate);
|
||||||
|
httpsserver::ResourceNode *nodeChallenge = new httpsserver::ResourceNode("/challenge", "GET",
|
||||||
|
WebServer::handleChallenge);
|
||||||
|
httpsserver::ResourceNode *nodeAuthTest = new httpsserver::ResourceNode("/authtest", "GET",
|
||||||
|
WebServer::handleAuthTest);
|
||||||
httpsserver::ResourceNode *node404 = new httpsserver::ResourceNode("", "GET",
|
httpsserver::ResourceNode *node404 = new httpsserver::ResourceNode("", "GET",
|
||||||
HTTPServer::handle404);
|
WebServer::handle404);
|
||||||
|
|
||||||
HTTPServer &server = HTTPServer::instance();
|
WebServer &server = WebServer::instance();
|
||||||
|
|
||||||
server.m_server->registerNode(nodeRoot);
|
server.m_server->registerNode(nodeRoot);
|
||||||
server.m_server->registerNode(nodeColor);
|
server.m_server->registerNode(nodeColor);
|
||||||
|
server.m_server->registerNode(nodeUpdate);
|
||||||
|
server.m_server->registerNode(nodeChallenge);
|
||||||
|
server.m_server->registerNode(nodeAuthTest);
|
||||||
server.m_server->setDefaultNode(node404);
|
server.m_server->setDefaultNode(node404);
|
||||||
|
|
||||||
Serial.println("[server] Starting HTTP Server...");
|
Serial.println("[server] Starting HTTP Server...");
|
||||||
|
@ -137,10 +223,10 @@ void HTTPServer::serverTask(void *arg)
|
||||||
Serial.println("[server] Server died?! This should never happen.");
|
Serial.println("[server] Server died?! This should never happen.");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HTTPServer::start(void)
|
bool WebServer::start(void)
|
||||||
{
|
{
|
||||||
xTaskCreate(
|
xTaskCreate(
|
||||||
HTTPServer::serverTask, /* Task function. */
|
WebServer::serverTask, /* Task function. */
|
||||||
"HTTP Server Task", /* name of task. */
|
"HTTP Server Task", /* name of task. */
|
||||||
6144, /* Stack size of task */
|
6144, /* Stack size of task */
|
||||||
NULL, /* parameter of the task */
|
NULL, /* parameter of the task */
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <SPIFFS.h>
|
#include <SPIFFS.h>
|
||||||
|
|
||||||
#include "WLAN_Logins.h"
|
#include "WLAN_Logins.h"
|
||||||
#include "HTTPServer.h"
|
#include "WebServer.h"
|
||||||
#include "Fader.h"
|
#include "Fader.h"
|
||||||
#include "UDPProto.h"
|
#include "UDPProto.h"
|
||||||
|
|
||||||
|
@ -223,8 +223,8 @@ void setup()
|
||||||
udpProto.start(2703);
|
udpProto.start(2703);
|
||||||
|
|
||||||
// start the web server
|
// start the web server
|
||||||
HTTPServer::instance().setFader(&ledFader);
|
WebServer::instance().setFader(&ledFader);
|
||||||
HTTPServer::instance().start();
|
WebServer::instance().start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|
Loading…
Reference in New Issue