Integrated authentication test in WebServer
This commit is contained in:
parent
42c41171ce
commit
1337a7e231
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,3 +5,4 @@
|
|||
.vscode/ipch
|
||||
|
||||
include/WLAN_Logins.h
|
||||
include/Crypto_Config.h
|
||||
|
|
|
@ -2,4 +2,7 @@
|
|||
|
||||
## 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 <HTTPServer.hpp>
|
||||
|
||||
#include "ChallengeResponse.h"
|
||||
|
||||
class Fader;
|
||||
|
||||
class HTTPServer
|
||||
class WebServer
|
||||
{
|
||||
public:
|
||||
bool start(void);
|
||||
|
||||
void setFader(Fader *fader) { m_fader = fader;}
|
||||
|
||||
static HTTPServer &instance(void)
|
||||
static WebServer &instance(void)
|
||||
{
|
||||
static HTTPServer theInstance;
|
||||
static WebServer theInstance;
|
||||
return theInstance;
|
||||
}
|
||||
|
||||
private:
|
||||
httpsserver::HTTPServer *m_server;
|
||||
ChallengeResponse m_cr;
|
||||
|
||||
Fader *m_fader;
|
||||
|
||||
HTTPServer(void);
|
||||
WebServer(void);
|
||||
|
||||
static void serverTask(void *arg);
|
||||
|
||||
|
@ -33,5 +36,8 @@ class HTTPServer
|
|||
// handlers
|
||||
static void handleRoot(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);
|
||||
};
|
38
scripts/authtest.py
Executable file
38
scripts/authtest.py
Executable file
|
@ -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 */
|
||||
|
||||
#include <SPIFFS.h>
|
||||
#include <mbedtls/sha256.h>
|
||||
|
||||
#include "HTTPServer.h"
|
||||
#include "WebServer.h"
|
||||
|
||||
#include "Crypto_Config.h"
|
||||
|
||||
#include "Fader.h"
|
||||
|
||||
HTTPServer::HTTPServer(void)
|
||||
: m_fader(NULL)
|
||||
WebServer::WebServer(void)
|
||||
: m_cr(crypto::HTTP_PASSWORD), m_fader(NULL)
|
||||
{
|
||||
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];
|
||||
File f = SPIFFS.open(filename.c_str(), "r");
|
||||
|
@ -30,7 +33,7 @@ void HTTPServer::serveFile(String filename, httpsserver::HTTPResponse *res)
|
|||
f.close();
|
||||
}
|
||||
|
||||
void HTTPServer::handleRoot(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res)
|
||||
void WebServer::handleRoot(httpsserver::HTTPRequest *req, httpsserver::HTTPResponse *res)
|
||||
{
|
||||
serveFile("/index.html", res);
|
||||
res->setHeader("Content-Type", "text/html");
|
||||
|
@ -44,7 +47,7 @@ static void error400(httpsserver::HTTPResponse *res, const std::string &reason)
|
|||
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");
|
||||
|
||||
|
@ -94,10 +97,84 @@ void HTTPServer::handleColor(httpsserver::HTTPRequest *req, httpsserver::HTTPRes
|
|||
res->print(" 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();
|
||||
|
||||
|
@ -107,19 +184,28 @@ void HTTPServer::handle404(httpsserver::HTTPRequest *req, httpsserver::HTTPRespo
|
|||
res->println("Error 404: Not found");
|
||||
}
|
||||
|
||||
void HTTPServer::serverTask(void *arg)
|
||||
void WebServer::serverTask(void *arg)
|
||||
{
|
||||
httpsserver::ResourceNode *nodeRoot = new httpsserver::ResourceNode("/", "GET",
|
||||
HTTPServer::handleRoot);
|
||||
WebServer::handleRoot);
|
||||
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",
|
||||
HTTPServer::handle404);
|
||||
WebServer::handle404);
|
||||
|
||||
HTTPServer &server = HTTPServer::instance();
|
||||
WebServer &server = WebServer::instance();
|
||||
|
||||
server.m_server->registerNode(nodeRoot);
|
||||
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);
|
||||
|
||||
Serial.println("[server] Starting HTTP Server...");
|
||||
|
@ -137,10 +223,10 @@ void HTTPServer::serverTask(void *arg)
|
|||
Serial.println("[server] Server died?! This should never happen.");
|
||||
}
|
||||
|
||||
bool HTTPServer::start(void)
|
||||
bool WebServer::start(void)
|
||||
{
|
||||
xTaskCreate(
|
||||
HTTPServer::serverTask, /* Task function. */
|
||||
WebServer::serverTask, /* Task function. */
|
||||
"HTTP Server Task", /* name of task. */
|
||||
6144, /* Stack size of task */
|
||||
NULL, /* parameter of the task */
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <SPIFFS.h>
|
||||
|
||||
#include "WLAN_Logins.h"
|
||||
#include "HTTPServer.h"
|
||||
#include "WebServer.h"
|
||||
#include "Fader.h"
|
||||
#include "UDPProto.h"
|
||||
|
||||
|
@ -223,8 +223,8 @@ void setup()
|
|||
udpProto.start(2703);
|
||||
|
||||
// start the web server
|
||||
HTTPServer::instance().setFader(&ledFader);
|
||||
HTTPServer::instance().start();
|
||||
WebServer::instance().setFader(&ledFader);
|
||||
WebServer::instance().start();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
|
Loading…
Reference in a new issue