From 25325ae75b24a4e192be0db33af71b3d111002be Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Fri, 18 Nov 2022 17:55:14 +0000 Subject: [PATCH 1/4] Avoid using a CIDR range when it only represents a single IP. --- src/socket.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/socket.cpp b/src/socket.cpp index 46be75b70..63e00bc93 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -402,16 +402,19 @@ std::string irc::sockets::cidr_mask::str() const unsigned char* base; size_t len; + unsigned char maxlen; switch (type) { case AF_INET: base = (unsigned char*)&sa.in4.sin_addr; len = 4; + maxlen = 32; break; case AF_INET6: base = (unsigned char*)&sa.in6.sin6_addr; len = 16; + maxlen = 128; break; case AF_UNIX: @@ -425,7 +428,14 @@ std::string irc::sockets::cidr_mask::str() const } memcpy(base, bits, len); - return sa.addr() + "/" + ConvToStr((int)length); + + std::string value = sa.addr(); + if (length < maxlen) + { + value.push_back('/'); + value.append(ConvToStr(static_cast(length))); + } + return value; } bool irc::sockets::cidr_mask::operator==(const cidr_mask& other) const From bd260744ecde49adbda20b62a116cf8508984c64 Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Fri, 18 Nov 2022 18:59:30 +0000 Subject: [PATCH 2/4] Fix matching partially expanded IPv6 addresses. --- src/cidr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cidr.cpp b/src/cidr.cpp index f45c63b98..ce5984c40 100644 --- a/src/cidr.cpp +++ b/src/cidr.cpp @@ -68,9 +68,9 @@ bool irc::sockets::MatchCIDR(const std::string &address, const std::string &cidr } const std::string::size_type per_pos = cidr_copy.rfind('/'); - if ((per_pos == std::string::npos) || (per_pos == cidr_copy.length()-1) + if ((per_pos != std::string::npos) && ((per_pos == cidr_copy.length()-1) || (cidr_copy.find_first_not_of("0123456789", per_pos+1) != std::string::npos) - || (cidr_copy.find_first_not_of("0123456789abcdefABCDEF.:") < per_pos)) + || (cidr_copy.find_first_not_of("0123456789abcdefABCDEF.:") < per_pos))) { // The CIDR mask is invalid return false; From 05ebc7fdaa5e476ccf3c1c3d9313ca6a44b90b43 Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Wed, 23 Nov 2022 22:23:35 +0000 Subject: [PATCH 3/4] Allow silence flag metadata to contain unknown flags. This prevents breaking link compatibility if we ever add more silence flags in the future. --- src/modules/m_silence.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/modules/m_silence.cpp b/src/modules/m_silence.cpp index 5065aeb2e..aeb9373ab 100644 --- a/src/modules/m_silence.cpp +++ b/src/modules/m_silence.cpp @@ -105,7 +105,7 @@ class SilenceEntry } // Converts a flag list to a bitmask. - static bool FlagsToBits(const std::string& flags, uint32_t& out) + static bool FlagsToBits(const std::string& flags, uint32_t& out, bool strict) { out = SF_NONE; for (std::string::const_iterator flag = flags.begin(); flag != flags.end(); ++flag) @@ -146,6 +146,8 @@ class SilenceEntry out |= SF_EXEMPT; break; default: + if (!strict) + continue; out = SF_NONE; return false; } @@ -228,7 +230,7 @@ class SilenceExtItem : public SimpleExtItem // Try to parse the flags. uint32_t flags; - if (!SilenceEntry::FlagsToBits(flagstr, flags)) + if (!SilenceEntry::FlagsToBits(flagstr, flags, false)) { ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Malformed silence flags received for %s: %s", user->uuid.c_str(), flagstr.c_str()); @@ -373,7 +375,7 @@ class CommandSilence : public SplitCommand uint32_t flags = SilenceEntry::SF_DEFAULT; if (parameters.size() > 1) { - if (!SilenceEntry::FlagsToBits(parameters[1], flags)) + if (!SilenceEntry::FlagsToBits(parameters[1], flags, true)) { user->WriteNumeric(ERR_SILENCE, mask, parameters[1], "You specified one or more invalid SILENCE flags"); return CMD_FAILURE; From 5a30466990e02d2533976061247d6c6ae097e0bd Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Thu, 24 Nov 2022 19:01:22 +0000 Subject: [PATCH 4/4] Add a workaround for the replies API not working with a cap reference. A Cap::Reference can not be cast to a Cap::Capability& because it may not be available and that would create a null reference. In v4 we can change the API to take a Cap::Capability* but for now this is the best we can do. --- include/modules/ircv3_replies.h | 47 +++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/include/modules/ircv3_replies.h b/include/modules/ircv3_replies.h index dd47d97c3..3bceb5964 100644 --- a/include/modules/ircv3_replies.h +++ b/include/modules/ircv3_replies.h @@ -254,6 +254,53 @@ class IRCv3::Replies::Reply else SendNoticeInternal(user, command, description); } + + void SendIfCap(LocalUser* user, const Cap::Capability* cap, Command* command, const std::string& code, + const std::string& description) + { + if (cap) + SendIfCap(user, *cap, command, code, description); + } + + template + void SendIfCap(LocalUser* user, const Cap::Capability* cap, Command* command, const std::string& code, + const T1& p1, const std::string& description) + { + if (cap) + SendIfCap(user, *cap, command, code, p1, description); + } + + template + void SendIfCap(LocalUser* user, const Cap::Capability* cap, Command* command, const std::string& code, + const T1& p1, const T2& p2, const std::string& description) + { + if (cap) + SendIfCap(user, *cap, command, code, p1, p2, description); + } + + template + void SendIfCap(LocalUser* user, const Cap::Capability* cap, Command* command, const std::string& code, + const T1& p1, const T2& p2, const T3& p3, const std::string& description) + { + if (cap) + SendIfCap(user, *cap, command, code, p1, p2, p3, description); + } + + template + void SendIfCap(LocalUser* user, const Cap::Capability* cap, Command* command, const std::string& code, + const T1& p1, const T2& p2, const T3& p3, const T4& p4, const std::string& description) + { + if (cap) + SendIfCap(user, *cap, command, code, p1, p2, p3, p4, description); + } + + template + void SendIfCap(LocalUser* user, const Cap::Capability* cap, Command* command, const std::string& code, + const T1& p1, const T2& p2, const T3& p3, const T4& p4, const T5& p5, const std::string& description) + { + if (cap) + SendIfCap(user, *cap, command, code, p1, p2, p3, p4, p5, description); + } }; /** Sends a FAIL standard reply. */