aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Sadie Powell2021-06-18 15:02:34 +0100
committerGravatar Sadie Powell2021-06-18 15:02:34 +0100
commitb2fde769b6daa6fe062525210d65ae5f1536f4bf (patch)
treee9039e6a3b9a8f3241b71108f4bf2193f4c61b11 /src
parentImport a greatly refactored version of the opmoderated module. (diff)
parentFix some inverted ignoreuntil values in the connectban module. (diff)
Merge branch 'insp3' into master.
Diffstat (limited to 'src')
-rw-r--r--src/coremods/core_channel/cmode_l.cpp19
-rw-r--r--src/coremods/core_xline/core_xline.cpp2
-rw-r--r--src/modules.cpp1
-rw-r--r--src/modules/extra/m_ssl_gnutls.cpp62
-rw-r--r--src/modules/m_connectban.cpp27
-rw-r--r--src/modules/m_joinflood.cpp7
-rw-r--r--src/users.cpp7
7 files changed, 76 insertions, 49 deletions
diff --git a/src/coremods/core_channel/cmode_l.cpp b/src/coremods/core_channel/cmode_l.cpp
index 578f762b8..0fdfdeefd 100644
--- a/src/coremods/core_channel/cmode_l.cpp
+++ b/src/coremods/core_channel/cmode_l.cpp
@@ -40,8 +40,21 @@ bool ModeChannelLimit::ResolveModeConflict(const std::string& their_param, const
ModeAction ModeChannelLimit::OnSet(User* user, Channel* chan, std::string& parameter)
{
size_t limit = ConvToNum<size_t>(parameter);
- if (limit < 1)
- return MODEACTION_DENY;
+ if (limit < 1 || limit > INTPTR_MAX)
+ {
+ if (IS_LOCAL(user))
+ {
+ // If the setter is local then we can safely just reject this here.
+ user->WriteNumeric(Numerics::InvalidModeParameter(chan, this, parameter));
+ return MODEACTION_DENY;
+ }
+ else
+ {
+ // If the setter is remote we *must* set the mode to avoid a desync
+ // so instead clamp it to the allowed range instead.
+ limit = std::clamp<size_t>(limit, 1, INTPTR_MAX);
+ }
+ }
ext.Set(chan, limit);
return MODEACTION_ALLOW;
@@ -49,5 +62,5 @@ ModeAction ModeChannelLimit::OnSet(User* user, Channel* chan, std::string& param
void ModeChannelLimit::SerializeParam(Channel* chan, intptr_t n, std::string& out)
{
- out += ConvToStr(n);
+ out += ConvToStr(static_cast<size_t>(n));
}
diff --git a/src/coremods/core_xline/core_xline.cpp b/src/coremods/core_xline/core_xline.cpp
index 6a3e7f762..5848ca83d 100644
--- a/src/coremods/core_xline/core_xline.cpp
+++ b/src/coremods/core_xline/core_xline.cpp
@@ -82,7 +82,7 @@ class CoreModXLine : public Module
user->CheckLines(true);
}
- void OnChangeRealHost(User* user, const std::string& newhost) override
+ void OnPostChangeRealHost(User* user) override
{
LocalUser* luser = IS_LOCAL(user);
if (!luser || luser->quitting)
diff --git a/src/modules.cpp b/src/modules.cpp
index 848f30d57..3651c2ad6 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -141,6 +141,7 @@ void Module::OnPostTopicChange(User*, Channel*, const std::string&) { DetachEve
void Module::OnDecodeMetaData(Extensible*, const std::string&, const std::string&) { DetachEvent(I_OnDecodeMetaData); }
void Module::OnChangeHost(User*, const std::string&) { DetachEvent(I_OnChangeHost); }
void Module::OnChangeRealHost(User*, const std::string&) { DetachEvent(I_OnChangeRealHost); }
+void Module::OnPostChangeRealHost(User*) { DetachEvent(I_OnPostChangeRealHost); }
void Module::OnChangeRealName(User*, const std::string&) { DetachEvent(I_OnChangeRealName); }
void Module::OnChangeIdent(User*, const std::string&) { DetachEvent(I_OnChangeIdent); }
void Module::OnAddLine(User*, XLine*) { DetachEvent(I_OnAddLine); }
diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp
index a31c5d374..d13bd0cfd 100644
--- a/src/modules/extra/m_ssl_gnutls.cpp
+++ b/src/modules/extra/m_ssl_gnutls.cpp
@@ -676,26 +676,14 @@ class GnuTLSIOHook : public SSLIOHook
void VerifyCertificate()
{
- unsigned int certstatus;
- const gnutls_datum_t* cert_list;
- int ret;
- unsigned int cert_list_size;
- gnutls_x509_crt_t cert;
- char str[512];
- unsigned char digest[512];
- size_t digest_size = sizeof(digest);
- size_t name_size = sizeof(str);
ssl_cert* certinfo = new ssl_cert;
this->certificate = certinfo;
- /* This verification function uses the trusted CAs in the credentials
- * structure. So you must have installed one or more CA certificates.
- */
- ret = gnutls_certificate_verify_peers2(this->sess, &certstatus);
-
+ unsigned int certstatus;
+ int ret = gnutls_certificate_verify_peers2(this->sess, &certstatus);
if (ret < 0)
{
- certinfo->error = std::string(gnutls_strerror(ret));
+ certinfo->error = gnutls_strerror(ret);
return;
}
@@ -704,16 +692,13 @@ class GnuTLSIOHook : public SSLIOHook
certinfo->revoked = (certstatus & GNUTLS_CERT_REVOKED);
certinfo->trusted = !(certstatus & GNUTLS_CERT_SIGNER_NOT_CA);
- /* Up to here the process is the same for X.509 certificates and
- * OpenPGP keys. From now on X.509 certificates are assumed. This can
- * be easily extended to work with openpgp keys as well.
- */
if (gnutls_certificate_type_get(this->sess) != GNUTLS_CRT_X509)
{
certinfo->error = "No X509 keys sent";
return;
}
+ gnutls_x509_crt_t cert;
ret = gnutls_x509_crt_init(&cert);
if (ret < 0)
{
@@ -721,18 +706,17 @@ class GnuTLSIOHook : public SSLIOHook
return;
}
- cert_list_size = 0;
- cert_list = gnutls_certificate_get_peers(this->sess, &cert_list_size);
+ char buffer[512];
+ size_t buffer_size = sizeof(buffer);
+
+ unsigned int cert_list_size = 0;
+ const gnutls_datum_t* cert_list = gnutls_certificate_get_peers(this->sess, &cert_list_size);
if (cert_list == NULL)
{
certinfo->error = "No certificate was found";
goto info_done_dealloc;
}
- /* This is not a real world example, since we only check the first
- * certificate in the given chain.
- */
-
ret = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
if (ret < 0)
{
@@ -740,31 +724,31 @@ class GnuTLSIOHook : public SSLIOHook
goto info_done_dealloc;
}
- if (gnutls_x509_crt_get_dn(cert, str, &name_size) == 0)
+ if (gnutls_x509_crt_get_dn(cert, buffer, &buffer_size) == 0)
{
- std::string& dn = certinfo->dn;
- dn = str;
- // Make sure there are no chars in the string that we consider invalid
- if (dn.find_first_of("\r\n") != std::string::npos)
- dn.clear();
+ // Make sure there are no chars in the string that we consider invalid.
+ certinfo->dn = buffer;
+ if (certinfo->dn.find_first_of("\r\n") != std::string::npos)
+ certinfo->dn.clear();
}
- name_size = sizeof(str);
- if (gnutls_x509_crt_get_issuer_dn(cert, str, &name_size) == 0)
+ buffer_size = sizeof(buffer);
+ if (gnutls_x509_crt_get_issuer_dn(cert, buffer, &buffer_size) == 0)
{
- std::string& issuer = certinfo->issuer;
- issuer = str;
- if (issuer.find_first_of("\r\n") != std::string::npos)
- issuer.clear();
+ // Make sure there are no chars in the string that we consider invalid.
+ certinfo->issuer = buffer;
+ if (certinfo->issuer.find_first_of("\r\n") != std::string::npos)
+ certinfo->issuer.clear();
}
- if ((ret = gnutls_x509_crt_get_fingerprint(cert, GetProfile().GetHash(), digest, &digest_size)) < 0)
+ buffer_size = sizeof(buffer);
+ if ((ret = gnutls_x509_crt_get_fingerprint(cert, GetProfile().GetHash(), buffer, &buffer_size)) < 0)
{
certinfo->error = gnutls_strerror(ret);
}
else
{
- certinfo->fingerprint = Hex::Encode(digest, digest_size);
+ certinfo->fingerprint = Hex::Encode(buffer, buffer_size);
}
/* Beware here we do not check for errors.
diff --git a/src/modules/m_connectban.cpp b/src/modules/m_connectban.cpp
index 846de9e80..7146e0df2 100644
--- a/src/modules/m_connectban.cpp
+++ b/src/modules/m_connectban.cpp
@@ -26,18 +26,25 @@
#include "inspircd.h"
#include "xline.h"
+#include "modules/server.h"
#include "modules/webirc.h"
-class ModuleConnectBan
+class ModuleConnectBan final
: public Module
+ , public ServerProtocol::LinkEventListener
, public WebIRC::EventListener
{
+ private:
typedef std::map<irc::sockets::cidr_mask, unsigned int> ConnectMap;
+
ConnectMap connects;
unsigned long threshold;
unsigned long banduration;
unsigned int ipv4_cidr;
unsigned int ipv6_cidr;
+ unsigned long bootwait;
+ unsigned long splitwait;
+ time_t ignoreuntil;
std::string banmessage;
unsigned char GetRange(LocalUser* user)
@@ -72,9 +79,14 @@ class ModuleConnectBan
}
public:
+ // Stop GCC warnings about the deprecated OnServerSplit event.
+ using ServerProtocol::LinkEventListener::OnServerSplit;
+
ModuleConnectBan()
: Module(VF_VENDOR, "Z-lines IP addresses which make excessive connections to the server.")
+ , ServerProtocol::LinkEventListener(this)
, WebIRC::EventListener(this)
+ , ignoreuntil(0)
{
}
@@ -91,8 +103,13 @@ class ModuleConnectBan
ipv4_cidr = static_cast<unsigned int>(tag->getUInt("ipv4cidr", 32, 1, 32));
ipv6_cidr = static_cast<unsigned int>(tag->getUInt("ipv6cidr", 128, 1, 128));
threshold = tag->getUInt("threshold", 10, 1);
+ bootwait = tag->getDuration("bootwait", 60*2);
+ splitwait = tag->getDuration("splitwait", 60*2);
banduration = tag->getDuration("duration", 10*60, 1);
banmessage = tag->getString("banmessage", "Your IP range has been attempting to connect too many times in too short a duration. Wait a while, and you will be able to connect.");
+
+ if (status.initial)
+ ignoreuntil = ServerInstance->Time() + bootwait;
}
void OnWebIRCAuth(LocalUser* user, const WebIRC::FlagMap* flags) override
@@ -109,9 +126,15 @@ class ModuleConnectBan
iter->second--;
}
+ void OnServerSplit(const Server* server, bool error) override
+ {
+ if (splitwait)
+ ignoreuntil = std::max<time_t>(ignoreuntil, ServerInstance->Time() + splitwait);
+ }
+
void OnSetUserIP(LocalUser* u) override
{
- if (IsExempt(u))
+ if (IsExempt(u) || ignoreuntil > ServerInstance->Time())
return;
irc::sockets::cidr_mask mask(u->client_sa, GetRange(u));
diff --git a/src/modules/m_joinflood.cpp b/src/modules/m_joinflood.cpp
index 5dfeb845f..c8836d12f 100644
--- a/src/modules/m_joinflood.cpp
+++ b/src/modules/m_joinflood.cpp
@@ -152,20 +152,21 @@ class ModuleJoinFlood
{
}
- void ReadConfig(ConfigStatus&) override
+ void ReadConfig(ConfigStatus& status) override
{
auto tag = ServerInstance->Config->ConfValue("joinflood");
duration = static_cast<unsigned int>(tag->getDuration("duration", 60, 10, 600));
bootwait = tag->getDuration("bootwait", 30);
splitwait = tag->getDuration("splitwait", 30);
- ignoreuntil = ServerInstance->startup_time + bootwait;
+ if (status.initial)
+ ignoreuntil = ServerInstance->startup_time + bootwait;
}
void OnServerSplit(const Server* server, bool error) override
{
if (splitwait)
- ignoreuntil = ServerInstance->Time() + splitwait;
+ ignoreuntil = std::max<time_t>(ignoreuntil, ServerInstance->Time() + splitwait);
}
ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven, bool override) override
diff --git a/src/users.cpp b/src/users.cpp
index b24a4d20d..bace2ed32 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -1036,11 +1036,16 @@ void User::ChangeRealHost(const std::string& host, bool resetdisplay)
return;
// Don't call the OnChangeRealHost event when initialising a user.
- if (!realhost.empty())
+ const bool initializing = realhost.empty();
+ if (!initializing)
FOREACH_MOD(OnChangeRealHost, (this, host));
realhost = host;
this->InvalidateCache();
+
+ // Don't call the OnPostChangeRealHost event when initialising a user.
+ if (!this->quitting && !initializing)
+ FOREACH_MOD(OnPostChangeRealHost, (this));
}
bool User::ChangeIdent(const std::string& newident)