diff --git a/example/config.jsonc b/example/config.jsonc index f79b0a4..0cee3fd 100644 --- a/example/config.jsonc +++ b/example/config.jsonc @@ -34,8 +34,9 @@ "127.0.0.1/24", "::1/128" ], - // if this regex matches the resource requested, this rule will not be applied - "exclude_regex": ".*/commit/.*" + // if this regex matches the resource requested, a different rule will be applied + "exclude_regex": ".*/commit/.*", + "action_on_exclude": "DENY" } ] } \ No newline at end of file diff --git a/src/config/Config.cpp b/src/config/Config.cpp index a2c83b4..2ec855d 100644 --- a/src/config/Config.cpp +++ b/src/config/Config.cpp @@ -9,6 +9,9 @@ static CConfig::eConfigIPAction strToAction(const std::string& s) { // TODO: allow any case I'm lazy it's 1am + if (s.empty()) + return CConfig::IP_ACTION_NONE; + if (s == "ALLOW" || s == "allow" || s == "Allow") return CConfig::IP_ACTION_ALLOW; if (s == "Deny" || s == "deny" || s == "Deny") @@ -16,7 +19,8 @@ static CConfig::eConfigIPAction strToAction(const std::string& s) { if (s == "CHALLENGE" || s == "challenge" || s == "Challenge") return CConfig::IP_ACTION_CHALLENGE; - throw std::runtime_error("Invalid ip config action"); + Debug::log(ERR, "Invalid action: {}, assuming NONE", s); + return CConfig::IP_ACTION_NONE; } CConfig::CConfig() { @@ -31,8 +35,9 @@ CConfig::CConfig() { // parse some datas for (const auto& ic : m_config.ip_configs) { SIPRangeConfigParsed parsed; - parsed.action = strToAction(ic.action); - parsed.difficulty = ic.difficulty; + parsed.action = strToAction(ic.action); + parsed.difficulty = ic.difficulty; + parsed.action_on_exclude = strToAction(ic.action_on_exclude); if (!ic.exclude_regex.empty()) { parsed.exclude_regex = std::make_unique(ic.exclude_regex); diff --git a/src/config/Config.hpp b/src/config/Config.hpp index 8d83c42..e45778a 100644 --- a/src/config/Config.hpp +++ b/src/config/Config.hpp @@ -12,7 +12,8 @@ class CConfig { CConfig(); enum eConfigIPAction : uint8_t { - IP_ACTION_DENY = 0, + IP_ACTION_NONE = 0, + IP_ACTION_DENY, IP_ACTION_ALLOW, IP_ACTION_CHALLENGE }; @@ -20,8 +21,9 @@ class CConfig { struct SIPRangeConfig { std::string action = ""; std::vector ip_ranges; - int difficulty = -1; - std::string exclude_regex = ""; + int difficulty = -1; + std::string exclude_regex = ""; + std::string action_on_exclude = ""; }; struct SIPRangeConfigParsed { @@ -29,6 +31,7 @@ class CConfig { std::vector ip_ranges; int difficulty = -1; std::unique_ptr exclude_regex; + eConfigIPAction action_on_exclude = IP_ACTION_NONE; }; struct SConfig { diff --git a/src/core/Handler.cpp b/src/core/Handler.cpp index 9e346a5..eced76c 100644 --- a/src/core/Handler.cpp +++ b/src/core/Handler.cpp @@ -248,7 +248,19 @@ void CServerHandler::onRequest(const Pistache::Http::Request& req, Pistache::Htt // if we have an exclude regex and it matches the resource, skip this rule if (ic.exclude_regex && RE2::FullMatch(req.resource(), *ic.exclude_regex)) { - Debug::log(LOG, " | ip rule matched for {}, but resource is excluded.", REQUEST_IP); + if (ic.action_on_exclude == CConfig::IP_ACTION_ALLOW) { + Debug::log(LOG, " | Action: PASS (ip rule matched for {}, excluded resource, exclude action is PASS)", REQUEST_IP); + proxyPass(req, response); + return; + } else if (ic.action_on_exclude == CConfig::IP_ACTION_DENY) { + Debug::log(LOG, " | Action: DENY (ip rule matched for {}, excluded resource, exclude action is DENY)", REQUEST_IP); + response.send(Pistache::Http::Code::Forbidden, "Forbidden"); + return; + } else if (ic.action_on_exclude == CConfig::IP_ACTION_CHALLENGE) { + Debug::log(LOG, " | ip rule matched for {}, excluded resource, exclude action is CHALLENGE", REQUEST_IP); + break; + } + Debug::log(LOG, " | ip rule matched for {}, excluded resource, exclude action is NONE", REQUEST_IP); continue; }