Integrated authentication test in WebServer

This commit is contained in:
Thomas Kolb 2019-11-25 22:45:01 +01:00
parent 42c41171ce
commit 1337a7e231
6 changed files with 157 additions and 23 deletions

1
.gitignore vendored
View file

@ -5,3 +5,4 @@
.vscode/ipch
include/WLAN_Logins.h
include/Crypto_Config.h

View file

@ -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`

View file

@ -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
View 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)

View file

@ -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 */

View file

@ -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() {