From f2652e25b650b10f72d3dc3976113bfc779f5458 Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Sat, 13 Jan 2024 19:10:47 +0000 Subject: [PATCH] Add the fingerprint cloak method to the cloak_user module. --- docs/conf/modules.conf.example | 15 ++++++++++- src/modules/m_cloak_user.cpp | 47 ++++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/docs/conf/modules.conf.example b/docs/conf/modules.conf.example index 1fef7302c..1c8eef18f 100644 --- a/docs/conf/modules.conf.example +++ b/docs/conf/modules.conf.example @@ -653,7 +653,8 @@ #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# # User data cloak module: Adds the "account" (services account name), # "account-id" (services account id), "nickname" (current nickname), -# and "username" (RFC 1413 identification string) cloak methods. +# "fingerprint" (client certificate fingerprint), and "username" (RFC +# 1413 identification string) cloak methods. # # #-#-#-#-#-#-#-#-#-#-#- USER CLOAK CONFIGURATION -#-#-#-#-#-#-#-#-#-#-# @@ -670,6 +671,11 @@ # host character, or "truncate" to truncate the cloak # # at the invalid host character. Defaults to "strip". # # # +# length - If using the "fingerprint" method them the number of # +# characters of the fingerprint hash to use. Defaults # +# to the value of minus the length of # +# the prefix and suffix fields. # +# # # prefix - A freeform value to prefix cloaks with. This must # # not contain spaces. # # # @@ -694,6 +700,13 @@ # prefix="" # suffix=".users.example.com"> # +# +# #& tag, const CharState& hm) ATTR_NOT_NULL(2) : Cloak::Method(engine, tag) , hostmap(hm) @@ -186,6 +186,47 @@ public: } }; +class FingerprintMethod final + : public UserMethodBase +{ +private: + // Dynamic reference to the certificate api. + UserCertificateAPI sslapi; + + // The number of octets of the fingerprint to use. + size_t length; + + // Retrieves the middle segment of the cloak. + std::string GetMiddle(LocalUser* user) override + { + const ssl_cert* cert = sslapi ? sslapi->GetCertificate(user) : nullptr; + if (!cert || !cert->IsUsable()) + return {}; + + return cert->GetFingerprint().substr(0, length); + } + + // Calculates the longest valid fingerprint length. + inline size_t GetMaxLength() + { + return ServerInstance->Config->Limits.MaxHost - prefix.length() - suffix.length(); + } + +public: + FingerprintMethod(const Cloak::Engine* engine, const std::shared_ptr& tag, const CharState& hm) ATTR_NOT_NULL(2) + : UserMethodBase(engine, tag, hm) + , sslapi(engine->creator) + , length(tag->getNum("length", GetMaxLength(), 1, GetMaxLength())) + { + } + + void GetLinkData(Module::LinkData& data, std::string& compatdata) override + { + UserMethodBase::GetLinkData(data, compatdata); + data["length"] = ConvToStr(length); + } +}; + class NickMethod final : public UserMethodBase { @@ -248,6 +289,7 @@ class ModuleCloakUser final private: UserEngine accountcloak; UserEngine accountidcloak; + UserEngine fingerprintcloak; UserEngine nicknamecloak; UserEngine usernamecloak; Cloak::API cloakapi; @@ -259,6 +301,7 @@ public: , Account::EventListener(this) , accountcloak(this, "account", hostmap) , accountidcloak(this, "account-id", hostmap) + , fingerprintcloak(this, "fingerprint", hostmap) , nicknamecloak(this, "nickname", hostmap) , usernamecloak(this, "username", hostmap) , cloakapi(this)