From fa6aa2a84a446507189d4d972a3a7b51f5108726 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 28 Oct 2024 22:16:43 +0100 Subject: [PATCH] lb/ConditionConfig: add variables $peer_subject, $peer_issuer_subject --- debian/changelog | 2 +- doc/lb.rst | 2 ++ src/lb/Branch.hxx | 16 ++++++++-------- src/lb/ConditionConfig.hxx | 18 +++++++++++++----- src/lb/ConfigParser.cxx | 4 ++++ src/lb/Goto.hxx | 4 ++-- src/lb/Goto.txx | 6 +++--- src/lb/HttpConnection.cxx | 2 +- 8 files changed, 34 insertions(+), 20 deletions(-) diff --git a/debian/changelog b/debian/changelog index 715fd4712..50e4b6ada 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,6 @@ cm4all-beng-proxy (18.6) unstable; urgency=low - * + * lb: add variables $peer_subject, $peer_issuer_subject -- diff --git a/doc/lb.rst b/doc/lb.rst index 27380c4d3..9966c0bc9 100644 --- a/doc/lb.rst +++ b/doc/lb.rst @@ -269,6 +269,8 @@ another branch. The following “variables” are available: - ``$remote_address``: the client address. +- ``$peer_subject``, ``$peer_issuer_subject``: the subject of the + (issuer of the) client certificate (see :ref:`ssl_verify`). - ``$request_method``: the HTTP request method (``GET``, ``POST``, ...) - ``$request_uri``: the HTTP request URI diff --git a/src/lb/Branch.hxx b/src/lb/Branch.hxx index 0f3960376..1840e7f08 100644 --- a/src/lb/Branch.hxx +++ b/src/lb/Branch.hxx @@ -25,10 +25,10 @@ public: return config; } - template + template [[gnu::pure]] - bool MatchRequest(const R &request) const noexcept { - return config.condition.MatchRequest(request); + bool MatchRequest(const C &connection, const R &request) const noexcept { + return config.condition.MatchRequest(connection, request); } const LbGoto &GetDestination() const noexcept { @@ -50,13 +50,13 @@ public: return config; } - template + template [[gnu::pure]] - const LbGoto &FindRequestLeaf(const R &request) const noexcept { + const LbGoto &FindRequestLeaf(const C &connection, const R &request) const noexcept { for (const auto &i : conditions) - if (i.MatchRequest(request)) - return i.GetDestination().FindRequestLeaf(request); + if (i.MatchRequest(connection, request)) + return i.GetDestination().FindRequestLeaf(connection, request); - return fallback.FindRequestLeaf(request); + return fallback.FindRequestLeaf(connection, request); } }; diff --git a/src/lb/ConditionConfig.hxx b/src/lb/ConditionConfig.hxx index 22465d990..9fd792380 100644 --- a/src/lb/ConditionConfig.hxx +++ b/src/lb/ConditionConfig.hxx @@ -16,6 +16,8 @@ struct LbAttributeReference { enum class Type { REMOTE_ADDRESS, + PEER_SUBJECT, + PEER_ISSUER_SUBJECT, METHOD, URI, HEADER, @@ -34,14 +36,20 @@ struct LbAttributeReference { return type == Type::REMOTE_ADDRESS; } - template + template [[gnu::pure]] - const char *GetRequestAttribute(const R &request) const noexcept { + const char *GetRequestAttribute(const C &connection, const R &request) const noexcept { switch (type) { case Type::REMOTE_ADDRESS: /* unreachable - handled as a special case */ break; + case Type::PEER_SUBJECT: + return connection.GetPeerSubject(); + + case Type::PEER_ISSUER_SUBJECT: + return connection.GetPeerIssuerSubject(); + case Type::METHOD: return http_method_to_string(request.method); @@ -90,13 +98,13 @@ struct LbConditionConfig { return std::visit(MatchHelper{s}, value) ^ negate; } - template + template [[gnu::pure]] - bool MatchRequest(const R &request) const noexcept { + bool MatchRequest(const C &connection, const R &request) const noexcept { if (attribute_reference.type == LbAttributeReference::Type::REMOTE_ADDRESS) return MatchAddress(request.remote_address); - const char *s = attribute_reference.GetRequestAttribute(request); + const char *s = attribute_reference.GetRequestAttribute(connection, request); if (s == nullptr) s = ""; diff --git a/src/lb/ConfigParser.cxx b/src/lb/ConfigParser.cxx index 3c1d8449c..27aa25d87 100644 --- a/src/lb/ConfigParser.cxx +++ b/src/lb/ConfigParser.cxx @@ -794,6 +794,10 @@ ParseAttributeReference(const char *p) return LbAttributeReference::Type::URI; } else if (StringIsEqual(p, "remote_address")) { return LbAttributeReference::Type::REMOTE_ADDRESS; + } else if (StringIsEqual(p, "peer_subject")) { + return LbAttributeReference::Type::PEER_SUBJECT; + } else if (StringIsEqual(p, "peer_issuer_subject")) { + return LbAttributeReference::Type::PEER_ISSUER_SUBJECT; } else if (auto header = StringAfterPrefix(p, "http_")) { LbAttributeReference a(LbAttributeReference::Type::HEADER, header); if (a.name.empty()) diff --git a/src/lb/Goto.hxx b/src/lb/Goto.hxx index 7afbc31c5..1349ee38b 100644 --- a/src/lb/Goto.hxx +++ b/src/lb/Goto.hxx @@ -64,7 +64,7 @@ struct LbGoto { return destination.index() != 0; } - template + template [[gnu::pure]] - const LbGoto &FindRequestLeaf(const R &request) const noexcept; + const LbGoto &FindRequestLeaf(const C &connection, const R &request) const noexcept; }; diff --git a/src/lb/Goto.txx b/src/lb/Goto.txx index 1a5336772..51dd85c90 100644 --- a/src/lb/Goto.txx +++ b/src/lb/Goto.txx @@ -7,12 +7,12 @@ #include "Goto.hxx" #include "Branch.hxx" -template +template const LbGoto & -LbGoto::FindRequestLeaf(const R &request) const noexcept +LbGoto::FindRequestLeaf(const C &connection, const R &request) const noexcept { if (auto *branch = std::get_if(&destination)) - return (*branch)->FindRequestLeaf(request); + return (*branch)->FindRequestLeaf(connection, request); return *this; } diff --git a/src/lb/HttpConnection.cxx b/src/lb/HttpConnection.cxx index b86a168b8..70774d4b7 100644 --- a/src/lb/HttpConnection.cxx +++ b/src/lb/HttpConnection.cxx @@ -287,7 +287,7 @@ LbHttpConnection::HandleHttpRequest(const LbGoto &destination, const StopwatchPtr &parent_stopwatch, CancellablePointer &cancel_ptr) noexcept { - const auto &goto_ = destination.FindRequestLeaf(request); + const auto &goto_ = destination.FindRequestLeaf(*this, request); std::visit([&](const auto &value){ using T = std::decay_t;