diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:34:54 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:34:54 +0000 |
commit | 0915b3ef56dfac3113cce55a59a5765dc94976be (patch) | |
tree | a8fea11d50b4f083e1bf0f90025ece7f0824784a /lib/remote/httphandler.cpp | |
parent | Initial commit. (diff) | |
download | icinga2-0915b3ef56dfac3113cce55a59a5765dc94976be.tar.xz icinga2-0915b3ef56dfac3113cce55a59a5765dc94976be.zip |
Adding upstream version 2.13.6.upstream/2.13.6upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | lib/remote/httphandler.cpp | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/lib/remote/httphandler.cpp b/lib/remote/httphandler.cpp new file mode 100644 index 0000000..e1bb4f4 --- /dev/null +++ b/lib/remote/httphandler.cpp @@ -0,0 +1,129 @@ +/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ + +#include "base/logger.hpp" +#include "remote/httphandler.hpp" +#include "remote/httputility.hpp" +#include "base/singleton.hpp" +#include "base/exception.hpp" +#include <boost/algorithm/string/join.hpp> +#include <boost/beast/http.hpp> + +using namespace icinga; + +Dictionary::Ptr HttpHandler::m_UrlTree; + +void HttpHandler::Register(const Url::Ptr& url, const HttpHandler::Ptr& handler) +{ + if (!m_UrlTree) + m_UrlTree = new Dictionary(); + + Dictionary::Ptr node = m_UrlTree; + + for (const String& elem : url->GetPath()) { + Dictionary::Ptr children = node->Get("children"); + + if (!children) { + children = new Dictionary(); + node->Set("children", children); + } + + Dictionary::Ptr sub_node = children->Get(elem); + if (!sub_node) { + sub_node = new Dictionary(); + children->Set(elem, sub_node); + } + + node = sub_node; + } + + Array::Ptr handlers = node->Get("handlers"); + + if (!handlers) { + handlers = new Array(); + node->Set("handlers", handlers); + } + + handlers->Add(handler); +} + +void HttpHandler::ProcessRequest( + AsioTlsStream& stream, + const ApiUser::Ptr& user, + boost::beast::http::request<boost::beast::http::string_body>& request, + boost::beast::http::response<boost::beast::http::string_body>& response, + boost::asio::yield_context& yc, + HttpServerConnection& server +) +{ + Dictionary::Ptr node = m_UrlTree; + std::vector<HttpHandler::Ptr> handlers; + + Url::Ptr url = new Url(request.target().to_string()); + auto& path (url->GetPath()); + + for (std::vector<String>::size_type i = 0; i <= path.size(); i++) { + Array::Ptr current_handlers = node->Get("handlers"); + + if (current_handlers) { + ObjectLock olock(current_handlers); + for (const HttpHandler::Ptr& current_handler : current_handlers) { + handlers.push_back(current_handler); + } + } + + Dictionary::Ptr children = node->Get("children"); + + if (!children) { + node.reset(); + break; + } + + if (i == path.size()) + break; + + node = children->Get(path[i]); + + if (!node) + break; + } + + std::reverse(handlers.begin(), handlers.end()); + + Dictionary::Ptr params; + + try { + params = HttpUtility::FetchRequestParameters(url, request.body()); + } catch (const std::exception& ex) { + HttpUtility::SendJsonError(response, params, 400, "Invalid request body: " + DiagnosticInformation(ex, false)); + return; + } + + bool processed = false; + + /* + * HandleRequest may throw a permission exception. + * DO NOT return a specific permission error. This + * allows attackers to guess from words which objects + * do exist. + */ + try { + for (const HttpHandler::Ptr& handler : handlers) { + if (handler->HandleRequest(stream, user, request, url, response, params, yc, server)) { + processed = true; + break; + } + } + } catch (const std::exception& ex) { + Log(LogWarning, "HttpServerConnection") + << "Error while processing HTTP request: " << ex.what(); + + processed = false; + } + + if (!processed) { + HttpUtility::SendJsonError(response, params, 404, "The requested path '" + boost::algorithm::join(path, "/") + + "' could not be found or the request method is not valid for this path."); + return; + } +} + |