From 889d521e05f2e922683d48c74eb00290e7a2f548 Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Wed, 17 Jul 2024 00:06:50 +0100 Subject: Shuffle the modules about a bit. --- src/modules/m_httpd_acl.cpp | 256 -------------------------------------------- 1 file changed, 256 deletions(-) delete mode 100644 src/modules/m_httpd_acl.cpp (limited to 'src/modules/m_httpd_acl.cpp') diff --git a/src/modules/m_httpd_acl.cpp b/src/modules/m_httpd_acl.cpp deleted file mode 100644 index 77000ec26..000000000 --- a/src/modules/m_httpd_acl.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2018 linuxdaemon - * Copyright (C) 2013, 2017, 2019-2023 Sadie Powell - * Copyright (C) 2013, 2015 Attila Molnar - * Copyright (C) 2012 Robby - * Copyright (C) 2009-2010 Daniel De Graaf - * Copyright (C) 2008 Robin Burchell - * Copyright (C) 2008 Craig Edwards - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" -#include "modules/httpd.h" -#include "stringutils.h" -#include "utility/string.h" - -class HTTPACL final -{ -public: - std::string path; - std::string username; - std::string password; - std::string whitelist; - std::string blacklist; - - HTTPACL(const std::string& set_path, const std::string& set_username, const std::string& set_password, - const std::string& set_whitelist, const std::string& set_blacklist) - : path(set_path) - , username(set_username) - , password(set_password) - , whitelist(set_whitelist) - , blacklist(set_blacklist) - { - } -}; - -class ModuleHTTPAccessList final - : public Module - , public HTTPACLEventListener -{ -private: - std::vector acl_list; - HTTPdAPI API; - -public: - ModuleHTTPAccessList() - : Module(VF_VENDOR, "Allows the server administrator to control who can access resources served over HTTP with the httpd module.") - , HTTPACLEventListener(this) - , API(this) - { - } - - void ReadConfig(ConfigStatus& status) override - { - std::vector new_acls; - for (const auto& [_, c] : ServerInstance->Config->ConfTags("httpdacl")) - { - std::string path = c->getString("path"); - std::string types = c->getString("types"); - irc::commasepstream sep(types); - std::string type; - std::string username; - std::string password; - std::string whitelist; - std::string blacklist; - - while (sep.GetToken(type)) - { - if (insp::equalsci(type, "password")) - { - username = c->getString("username"); - password = c->getString("password"); - } - else if (insp::equalsci(type, "whitelist")) - { - whitelist = c->getString("whitelist"); - } - else if (insp::equalsci(type, "blacklist")) - { - blacklist = c->getString("blacklist"); - } - else - { - throw ModuleException(this, "Invalid HTTP ACL type '" + type + "'"); - } - } - - ServerInstance->Logs.Debug(MODNAME, "Read ACL: path={} pass={} whitelist={} blacklist={}", path, - password, whitelist, blacklist); - - new_acls.emplace_back(path, username, password, whitelist, blacklist); - } - acl_list.swap(new_acls); - } - - void BlockAccess(HTTPRequest* http, unsigned int returnval, const std::string& extraheaderkey = "", const std::string& extraheaderval="") - { - ServerInstance->Logs.Debug(MODNAME, "BlockAccess ({})", returnval); - - std::stringstream data; - data << "" - << "

Error " << returnval << "

" - << "

Access to this resource is denied by an access control list.

" - << "

Please contact your IRC administrator.


" - << "Powered by InspIRCd"; - - HTTPDocumentResponse response(this, *http, &data, returnval); - response.headers.SetHeader("X-Powered-By", MODNAME); - if (!extraheaderkey.empty()) - response.headers.SetHeader(extraheaderkey, extraheaderval); - API->SendResponse(response); - } - - bool IsAccessAllowed(HTTPRequest* http) - { - { - ServerInstance->Logs.Debug(MODNAME, "Handling httpd acl event"); - - for (const auto& acl : acl_list) - { - if (InspIRCd::Match(http->GetPath(), acl.path, ascii_case_insensitive_map)) - { - if (!acl.blacklist.empty()) - { - /* Blacklist */ - irc::commasepstream sep(acl.blacklist); - std::string entry; - - while (sep.GetToken(entry)) - { - if (InspIRCd::Match(http->GetIP(), entry, ascii_case_insensitive_map)) - { - ServerInstance->Logs.Debug(MODNAME, "Denying access to blacklisted resource {} (matched by pattern {}) from ip {} (matched by entry {})", - http->GetPath(), acl.path, http->GetIP(), entry); - BlockAccess(http, 403); - return false; - } - } - } - if (!acl.whitelist.empty()) - { - /* Whitelist */ - irc::commasepstream sep(acl.whitelist); - std::string entry; - bool allow_access = false; - - while (sep.GetToken(entry)) - { - if (InspIRCd::Match(http->GetIP(), entry, ascii_case_insensitive_map)) - allow_access = true; - } - - if (!allow_access) - { - ServerInstance->Logs.Debug(MODNAME, "Denying access to whitelisted resource {} (matched by pattern {}) from ip {} (Not in whitelist)", - http->GetPath(), acl.path, http->GetIP()); - BlockAccess(http, 403); - return false; - } - } - if (!acl.password.empty() && !acl.username.empty()) - { - /* Password auth, first look to see if we have a basic authentication header */ - ServerInstance->Logs.Debug(MODNAME, "Checking HTTP auth password for resource {} (matched by pattern {}) from ip {}, against username {}", - http->GetPath(), acl.path, http->GetIP(), acl.username); - - if (http->headers->IsSet("Authorization")) - { - /* Password has been given, validate it */ - std::string authorization = http->headers->GetHeader("Authorization"); - irc::spacesepstream sep(authorization); - std::string authtype; - std::string base64; - - sep.GetToken(authtype); - if (authtype == "Basic") - { - std::string user; - std::string pass; - - sep.GetToken(base64); - std::string userpass = Base64::Decode(base64); - ServerInstance->Logs.Debug(MODNAME, "HTTP authorization: {} ({})", userpass, base64); - - irc::sepstream userpasspair(userpass, ':'); - if (userpasspair.GetToken(user)) - { - userpasspair.GetToken(pass); - - /* Access granted if username and password are correct */ - if (InspIRCd::TimingSafeCompare(user, acl.username) && InspIRCd::TimingSafeCompare(pass, acl.password)) - { - ServerInstance->Logs.Debug(MODNAME, "HTTP authorization: password and username match"); - return true; - } - else - { - /* Invalid password */ - ServerInstance->Logs.Debug(MODNAME, "HTTP authorization: password and username do not match"); - BlockAccess(http, 401, "WWW-Authenticate", "Basic realm=\"Restricted Object\""); - } - } - else - { - /* Malformed user:pass pair */ - ServerInstance->Logs.Debug(MODNAME, "HTTP authorization: password and username malformed"); - BlockAccess(http, 401, "WWW-Authenticate", "Basic realm=\"Restricted Object\""); - } - } - else - { - /* Unsupported authentication type */ - ServerInstance->Logs.Debug(MODNAME, "HTTP authorization: unsupported auth type: {}", authtype); - BlockAccess(http, 401, "WWW-Authenticate", "Basic realm=\"Restricted Object\""); - } - } - else - { - /* No password given at all, access denied */ - ServerInstance->Logs.Debug(MODNAME, "HTTP authorization: password and username not sent"); - BlockAccess(http, 401, "WWW-Authenticate", "Basic realm=\"Restricted Object\""); - } - return false; - } - - /* A path may only match one ACL (the first it finds in the config file) */ - break; - } - } - } - return true; - } - - ModResult OnHTTPACLCheck(HTTPRequest& req) override - { - if (IsAccessAllowed(&req)) - return MOD_RES_PASSTHRU; - return MOD_RES_DENY; - } -}; - -MODULE_INIT(ModuleHTTPAccessList) -- cgit v1.3.1-10-gc9f91