Added support for ip whitelist and added rest method to update/get the config file

This commit is contained in:
Leon Etienne (ubuntu wsl)
2020-10-02 13:16:57 +02:00
parent 66882b3b67
commit 5f7e4e2cf2
9 changed files with 198 additions and 23 deletions

View File

@@ -82,6 +82,7 @@ void HttpServer::EventHandler(mg_connection* pNc, int ev, void* p)
http_message* hpm = (http_message*)p;
std::string requestedUri = FixUnterminatedString(hpm->uri.p, hpm->uri.len);
// Get clients ip address
std::string peer_addr;
{
char buf[32];
@@ -89,13 +90,7 @@ void HttpServer::EventHandler(mg_connection* pNc, int ev, void* p)
peer_addr = buf;
}
if ((XGConfig::general.onlyAllowLocalhost) && (peer_addr != "127.0.0.1"))
{
Json j;
j.CloneFrom(RestResponseTemplates::GetByCode(UNAUTHORIZED, "Only localhost allowed!"));
ServeStringToConnection(pNc, j.Render(), UNAUTHORIZED);
}
else
if (IsConnectionAllowed(peer_addr))
{
try
{
@@ -128,6 +123,12 @@ void HttpServer::EventHandler(mg_connection* pNc, int ev, void* p)
break;
}
else // Client is not allowed, serve error json
{
Json j;
j.CloneFrom(RestResponseTemplates::GetByCode(UNAUTHORIZED, "Only localhost allowed!"));
ServeStringToConnection(pNc, j.Render(), UNAUTHORIZED);
}
}
return;
@@ -199,6 +200,36 @@ void HttpServer::ServeDownloadeableResource(mg_connection* pNc, int ev, void* p,
return;
}
bool HttpServer::IsConnectionAllowed(std::string peer_address)
{
// Localhost is always allowed!
if (peer_address == "127.0.0.1") return true;
// Peer is not localhost, but only localhost is allowed!
else if (XGConfig::access.only_allow_localhost) return false;
// Let's check if the whitelist is active
else if (XGConfig::access.enable_whitelist)
{
// It is. Let's check if our peer is whitelisted
for (std::size_t i = 0; i < XGConfig::access.whitelist.size(); i++)
{
// Whitelist is enabled, and peer is whitelisted
if (XGConfig::access.whitelist[i] == peer_address) return true;
}
// Whitelist is enabled, but peer is NOT whitelisted
return false;
}
else // Whitelist is NOT enabled and only_allow_localhost is FALSE!
{
return true;
}
// Should never come to this point
return false;
}
void HttpServer::OnExit()
{
log->cout << "Shutting down http-server...";

View File

@@ -29,6 +29,8 @@ namespace Rest
static void ServeStringToConnection(struct mg_connection* c, std::string str, int httpStatusCode = 200);
static std::string FixUnterminatedString(const char* cstr, const std::size_t len);
static bool IsConnectionAllowed(std::string peer_address);
struct mg_mgr* pMgr;
struct mg_connection* pNc;

View File

@@ -42,6 +42,7 @@ bool RestQueryHandler::ProcessQuery(const std::string clientAdress, const Json&
else if (requestName == "fetch_alltime_logs") return FetchAlltimeLogs(requestBody, responseBody, responseCode);
else if (requestName == "update_dep_youtubedl") return UpdateYoutubeDL(requestBody, responseBody, responseCode);
else if (requestName == "remove_download_entry") return RemoveDownloadEntry(requestBody, responseBody, responseCode);
else if (requestName == "update_config") return UpdateConfig(requestBody, responseBody, responseCode);
@@ -437,6 +438,44 @@ bool RestQueryHandler::RemoveDownloadEntry(const JsonBlock& request, JsonBlock&
return true;
}
bool RestQueryHandler::UpdateConfig(const JsonBlock& request, JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode)
{
if (ValidateField("config", JDType::JSON, request, responseBody))
{
bool prevStateConsole = XGConfig::general.show_console;
XGConfig::LoadFromJson(request.Get("config").AsJson);
// Update console, if necessary
if (XGConfig::general.show_console != prevStateConsole)
{
if (XGConfig::general.show_console) ConsoleManager::ShowConsole();
else ConsoleManager::HideConsole();
}
log->cout << "Updated config values...";
log->Flush();
XGConfig::Save();
responseBody.Set("message") = "Updated no settings";
}
else
{
responseBody.Set("message") = "Updated no settings";
}
responseCode = OK;
responseBody.CloneFrom(RestResponseTemplates::GetByCode(OK));
responseBody.Set("settings") = XGConfig::GetSavefileBuffer();
return true;
}
bool RestQueryHandler::ValidateField(const std::string name, const JasonPP::JDType type, const JasonPP::Json& checkThat, JasonPP::JsonBlock& putErrorResponseHere)

View File

@@ -34,6 +34,7 @@ namespace Rest
static bool GetDiskUsage(const JasonPP::JsonBlock& request, JasonPP::JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode);
static bool UpdateYoutubeDL(const JasonPP::JsonBlock& request, JasonPP::JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode);
static bool RemoveDownloadEntry(const JasonPP::JsonBlock& request, JasonPP::JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode);
static bool UpdateConfig(const JasonPP::JsonBlock& request, JasonPP::JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode);
static bool ValidateField(const std::string name, const JasonPP::JDType type, const JasonPP::Json& checkThat, JasonPP::JsonBlock& putErrorResponseHere);

View File

@@ -45,13 +45,20 @@ void XGConfig::InitializeDefaultValues()
downloader.num_threads = 1;
general.show_console = true;
general.onlyAllowLocalhost = true;
access.only_allow_localhost = true;
access.enable_whitelist = true;
access.whitelist = std::vector<std::string>();
access.whitelist.push_back("127.0.0.1"); // Add localhost to whitelist
return;
}
void XGConfig::LoadFromJson(const JasonPP::JsonBlock& json)
{
savefileBuffer.Clear();
savefileBuffer.CloneFrom(json);
if (IsJsonFieldValid(json, "logging.logfile_json", JDType::STRING))
{
logging.logfile_json = json.ShorthandGet("logging.logfile_json").AsString;
@@ -103,9 +110,28 @@ void XGConfig::LoadFromJson(const JasonPP::JsonBlock& json)
{
general.show_console = json.ShorthandGet("general.show_console").AsBool;
}
if (IsJsonFieldValid(json, "general.onlyAllowLocalhost", JDType::BOOL))
if (IsJsonFieldValid(json, "access.only_allow_localhost", JDType::BOOL))
{
general.onlyAllowLocalhost = json.ShorthandGet("general.onlyAllowLocalhost").AsBool;
access.only_allow_localhost = json.ShorthandGet("access.only_allow_localhost").AsBool;
}
if (IsJsonFieldValid(json, "access.enable_whitelist", JDType::BOOL))
{
access.enable_whitelist = json.ShorthandGet("access.enable_whitelist").AsBool;
}
if (IsJsonFieldValid(json, "access.whitelist", JDType::ARRAY))
{
const JsonArray& cachedArr = json.ShorthandGet("access.whitelist").AsArray;
access.whitelist.clear();
for (std::size_t i = 0; i < cachedArr.Size(); i++)
{
if (cachedArr[i].GetDataType() == JDType::STRING)
{
access.whitelist.push_back(cachedArr[i].AsString);
}
}
}
return;
@@ -113,10 +139,13 @@ void XGConfig::LoadFromJson(const JasonPP::JsonBlock& json)
JsonBlock XGConfig::CreateJson()
{
JsonArray jsnArrWhitelist;
jsnArrWhitelist.Add(access.whitelist);
return JsonBlock({
Ele("httpServer", JsonBlock({
Ele("port", httpServer.port),
Ele("pollingRate", httpServer.polling_rate),
Ele("polling_rate", httpServer.polling_rate),
Ele("rootdir", httpServer.rootdir)
})),
Ele("logging", JsonBlock({
@@ -131,7 +160,11 @@ JsonBlock XGConfig::CreateJson()
})),
Ele("general", JsonBlock({
Ele("show_console", general.show_console),
Ele("onlyAllowLocalhost", general.onlyAllowLocalhost)
})),
Ele("access", JsonBlock({
Ele("only_allow_localhost", access.only_allow_localhost),
Ele("enable_whitelist", access.enable_whitelist),
Ele("whitelist", jsnArrWhitelist),
}))
});
}
@@ -210,6 +243,8 @@ void XGConfig::Save()
bool XGConfig::SaveToFile(std::string filename)
{
Json cfgStruct(CreateJson());
savefileBuffer.Clear();
savefileBuffer.CloneFrom(cfgStruct.AsJson);
return FileSystem::WriteFile(filename, cfgStruct.Render());
}
@@ -245,5 +280,7 @@ XGConfig::HttpServer XGConfig::httpServer;
XGConfig::Logging XGConfig::logging;
XGConfig::Downloader XGConfig::downloader;
XGConfig::General XGConfig::general;
XGConfig::Access XGConfig::access;
JasonPP::JsonBlock XGConfig::savefileBuffer;
::Logging::Logger* XGConfig::log;

View File

@@ -1,4 +1,5 @@
#pragma once
#include <vector>
#include "Filesystem.h"
#include "external_dependencies/leonetienne/JasonPP/JasonPP.hpp"
#include "Logger.h"
@@ -30,27 +31,37 @@ public:
struct General
{
bool show_console;
bool onlyAllowLocalhost;
};
struct Access
{
bool only_allow_localhost;
bool enable_whitelist;
std::vector<std::string> whitelist;
};
static void PreInit();
static void Save();
static void PostExit();
static void LoadFromJson(const JasonPP::JsonBlock& json);
static XGConfig::HttpServer httpServer;
static XGConfig::Logging logging;
static XGConfig::Downloader downloader;
static XGConfig::General general;
static XGConfig::Access access;
static const JasonPP::JsonBlock& GetSavefileBuffer() { return savefileBuffer; }
static ::Logging::Logger* log;
private:
static bool SaveToFile(std::string filename);
static JasonPP::JsonBlock savefileBuffer;
static bool IsJsonFieldValid(const JasonPP::JsonBlock& json, const std::string key, const JasonPP::JDType type);
static void InitializeDefaultValues();
static JasonPP::JsonBlock CreateJson();
static void LoadFromJson(const JasonPP::JsonBlock& json);
static void Load();
};