aboutsummaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
authorGravatar Sadie Powell2021-01-07 13:13:58 +0000
committerGravatar Sadie Powell2021-01-07 13:13:58 +0000
commit4f68d162cc55a8e35f9800a2ab85274876061861 (patch)
tree8de0f196ab3447614a6481f9b356e5dc2bae5a27 /src/modules
parentAdd a function for shrinking module names. (diff)
parentImplement support for more XML and IRC colour code escapes. (diff)
Merge branch 'insp3' into master.
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/m_cgiirc.cpp70
-rw-r--r--src/modules/m_classban.cpp14
-rw-r--r--src/modules/m_codepage.cpp19
-rw-r--r--src/modules/m_operchans.cpp6
-rw-r--r--src/modules/m_spanningtree/override_map.cpp1
-rw-r--r--src/modules/m_spanningtree/svsnick.cpp1
6 files changed, 76 insertions, 35 deletions
diff --git a/src/modules/m_cgiirc.cpp b/src/modules/m_cgiirc.cpp
index 553e5e427..a8f126b84 100644
--- a/src/modules/m_cgiirc.cpp
+++ b/src/modules/m_cgiirc.cpp
@@ -39,16 +39,19 @@ enum
RPL_WHOISGATEWAY = 350
};
+// One or more hostmask globs or CIDR ranges.
+typedef std::vector<std::string> MaskList;
+
// Encapsulates information about an ident host.
class IdentHost
{
private:
- std::string hostmask;
+ MaskList hostmasks;
std::string newident;
public:
- IdentHost(const std::string& mask, const std::string& ident)
- : hostmask(mask)
+ IdentHost(const MaskList& masks, const std::string& ident)
+ : hostmasks(masks)
, newident(ident)
{
}
@@ -60,10 +63,19 @@ class IdentHost
bool Matches(LocalUser* user) const
{
- if (!InspIRCd::Match(user->GetRealHost(), hostmask, ascii_case_insensitive_map))
- return false;
+ for (MaskList::const_iterator iter = hostmasks.begin(); iter != hostmasks.end(); ++iter)
+ {
+ // Does the user's hostname match this hostmask?
+ if (InspIRCd::Match(user->GetRealHost(), *iter, ascii_case_insensitive_map))
+ return true;
- return InspIRCd::MatchCIDR(user->GetIPString(), hostmask, ascii_case_insensitive_map);
+ // Does the user's IP address match this hostmask?
+ if (InspIRCd::MatchCIDR(user->GetIPString(), *iter, ascii_case_insensitive_map))
+ return true;
+ }
+
+ // The user didn't match any hostmasks.
+ return false;
}
};
@@ -71,14 +83,14 @@ class IdentHost
class WebIRCHost
{
private:
- std::string hostmask;
+ MaskList hostmasks;
std::string fingerprint;
std::string password;
std::string passhash;
public:
- WebIRCHost(const std::string& mask, const std::string& fp, const std::string& pass, const std::string& hash)
- : hostmask(mask)
+ WebIRCHost(const MaskList& masks, const std::string& fp, const std::string& pass, const std::string& hash)
+ : hostmasks(masks)
, fingerprint(fp)
, password(pass)
, passhash(hash)
@@ -96,26 +108,22 @@ class WebIRCHost
if (!fingerprint.empty() && !InspIRCd::TimingSafeCompare(fp, fingerprint))
return false;
- // Does the user's hostname match our hostmask?
- if (InspIRCd::Match(user->GetRealHost(), hostmask, ascii_case_insensitive_map))
- return true;
+ for (MaskList::const_iterator iter = hostmasks.begin(); iter != hostmasks.end(); ++iter)
+ {
+ // Does the user's hostname match this hostmask?
+ if (InspIRCd::Match(user->GetRealHost(), *iter, ascii_case_insensitive_map))
+ return true;
+
+ // Does the user's IP address match this hostmask?
+ if (InspIRCd::MatchCIDR(user->GetIPString(), *iter, ascii_case_insensitive_map))
+ return true;
+ }
- // Does the user's IP address match our hostmask?
- return InspIRCd::MatchCIDR(user->GetIPString(), hostmask, ascii_case_insensitive_map);
+ // The user didn't match any hostmasks.
+ return false;
}
};
-/*
- * WEBIRC
- * This is used for the webirc method of CGIIRC auth, and is (really) the best way to do these things.
- * Syntax: WEBIRC password gateway hostname ip
- * Where password is a shared key, gateway is the name of the WebIRC gateway and version (e.g. cgiirc), hostname
- * is the resolved host of the client issuing the command and IP is the real IP of the client.
- *
- * How it works:
- * To tie in with the rest of cgiirc module, and to avoid race conditions, /webirc is only processed locally
- * and simply sets metadata on the user, which is later decoded on full connect to give something meaningful.
- */
class CommandWebIRC : public SplitCommand
{
public:
@@ -287,9 +295,13 @@ class ModuleCgiIRC
for (auto& [_, tag] : ServerInstance->Config->ConfTags("cgihost"))
{
+ MaskList masks;
+ irc::spacesepstream maskstream(tag->getString("mask"));
+ for (std::string mask; maskstream.GetToken(mask); )
+ masks.push_back(mask);
+
// Ensure that we have the <cgihost:mask> parameter.
- const std::string mask = tag->getString("mask");
- if (mask.empty())
+ if (masks.empty())
throw ModuleException("<cgihost:mask> is a mandatory field, at " + tag->source.str());
// Determine what lookup type this host uses.
@@ -298,7 +310,7 @@ class ModuleCgiIRC
{
// The IP address should be looked up from the hex IP address.
const std::string newident = tag->getString("newident", "gateway", ServerInstance->IsIdent);
- identhosts.push_back(IdentHost(mask, newident));
+ identhosts.push_back(IdentHost(masks, newident));
}
else if (stdalgo::string::equalsci(type, "webirc"))
{
@@ -317,7 +329,7 @@ class ModuleCgiIRC
tag->source.str().c_str());
}
- webirchosts.push_back(WebIRCHost(mask, fingerprint, password, passwordhash));
+ webirchosts.push_back(WebIRCHost(masks, fingerprint, password, passwordhash));
}
else
{
diff --git a/src/modules/m_classban.cpp b/src/modules/m_classban.cpp
index d3ff35a05..a469b5e6f 100644
--- a/src/modules/m_classban.cpp
+++ b/src/modules/m_classban.cpp
@@ -24,16 +24,28 @@
class ClassExtBan
: public ExtBan::MatchingBase
{
+ private:
+ std::string space;
+ std::string underscore;
+
public:
ClassExtBan(Module* Creator)
: ExtBan::MatchingBase(Creator, "class", 'n')
+ , space(" ")
+ , underscore("_")
{
}
bool IsMatch(User* user, Channel* channel, const std::string& text) override
{
LocalUser* luser = IS_LOCAL(user);
- return luser && InspIRCd::Match(luser->GetClass()->name, text);
+ if (!luser)
+ return false;
+
+ // Replace spaces with underscores as they're prohibited in mode parameters.
+ std::string classname(luser->GetClass()->name);
+ stdalgo::string::replace_all(classname, space, underscore);
+ return InspIRCd::Match(classname, text);
}
};
diff --git a/src/modules/m_codepage.cpp b/src/modules/m_codepage.cpp
index 3507b41a5..3ce821418 100644
--- a/src/modules/m_codepage.cpp
+++ b/src/modules/m_codepage.cpp
@@ -76,6 +76,21 @@ class ModuleCodepage
hashmap.swap(newhash);
}
+ void CheckDuplicateNick()
+ {
+ insp::flat_set<std::string, irc::insensitive_swo> duplicates;
+ const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers();
+ for (UserManager::LocalList::const_iterator iter = list.begin(); iter != list.end(); ++iter)
+ {
+ LocalUser* user = *iter;
+ if (user->nick != user->uuid && !duplicates.insert(user->nick).second)
+ {
+ user->WriteNumeric(RPL_SAVENICK, user->uuid, "Your nickname is no longer available.");
+ user->ChangeNick(user->uuid);
+ }
+ }
+ }
+
void CheckInvalidNick()
{
const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers();
@@ -83,7 +98,10 @@ class ModuleCodepage
{
LocalUser* user = *iter;
if (user->nick != user->uuid && !ServerInstance->IsNick(user->nick))
+ {
+ user->WriteNumeric(RPL_SAVENICK, user->uuid, "Your nickname is no longer valid.");
user->ChangeNick(user->uuid);
+ }
}
}
@@ -113,6 +131,7 @@ class ModuleCodepage
ServerInstance->Config->CaseMapping = origcasemapname;
national_case_insensitive_map = origcasemap;
+ CheckDuplicateNick();
CheckRehash(casemap);
}
diff --git a/src/modules/m_operchans.cpp b/src/modules/m_operchans.cpp
index 1cede6a61..ec3943638 100644
--- a/src/modules/m_operchans.cpp
+++ b/src/modules/m_operchans.cpp
@@ -53,11 +53,7 @@ class OperExtBan
if (!user->IsOper())
return false;
- // Check whether the oper's type matches the ban.
- if (InspIRCd::Match(user->oper->name, text))
- return true;
-
- // If the oper's type contains spaces recheck with underscores.
+ // Replace spaces with underscores as they're prohibited in mode parameters.
std::string opername(user->oper->name);
stdalgo::string::replace_all(opername, space, underscore);
return InspIRCd::Match(opername, text);
diff --git a/src/modules/m_spanningtree/override_map.cpp b/src/modules/m_spanningtree/override_map.cpp
index 276cdda6e..15f4ea10e 100644
--- a/src/modules/m_spanningtree/override_map.cpp
+++ b/src/modules/m_spanningtree/override_map.cpp
@@ -36,6 +36,7 @@
CommandMap::CommandMap(Module* Creator)
: Command(Creator, "MAP", 0, 1)
{
+ allow_empty_last_param = false;
Penalty = 2;
}
diff --git a/src/modules/m_spanningtree/svsnick.cpp b/src/modules/m_spanningtree/svsnick.cpp
index 2246bec7b..19066eede 100644
--- a/src/modules/m_spanningtree/svsnick.cpp
+++ b/src/modules/m_spanningtree/svsnick.cpp
@@ -67,6 +67,7 @@ CmdResult CommandSVSNick::Handle(User* user, Params& parameters)
if (!u->ChangeNick(nick, NickTS))
{
// Changing to 'nick' failed (it may already be in use), change to the uuid
+ u->WriteNumeric(RPL_SAVENICK, u->uuid, "Your nickname is in use by an older user on a new server.");
u->ChangeNick(u->uuid);
}
}