diff options
| author | 2021-01-07 13:13:58 +0000 | |
|---|---|---|
| committer | 2021-01-07 13:13:58 +0000 | |
| commit | 4f68d162cc55a8e35f9800a2ab85274876061861 (patch) | |
| tree | 8de0f196ab3447614a6481f9b356e5dc2bae5a27 /src | |
| parent | Add a function for shrinking module names. (diff) | |
| parent | Implement support for more XML and IRC colour code escapes. (diff) | |
Merge branch 'insp3' into master.
Diffstat (limited to 'src')
| -rw-r--r-- | src/modules/m_cgiirc.cpp | 70 | ||||
| -rw-r--r-- | src/modules/m_classban.cpp | 14 | ||||
| -rw-r--r-- | src/modules/m_codepage.cpp | 19 | ||||
| -rw-r--r-- | src/modules/m_operchans.cpp | 6 | ||||
| -rw-r--r-- | src/modules/m_spanningtree/override_map.cpp | 1 | ||||
| -rw-r--r-- | src/modules/m_spanningtree/svsnick.cpp | 1 | ||||
| -rw-r--r-- | src/xline.cpp | 1 |
7 files changed, 77 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); } } diff --git a/src/xline.cpp b/src/xline.cpp index 79164e3ea..1682e8864 100644 --- a/src/xline.cpp +++ b/src/xline.cpp @@ -661,6 +661,7 @@ bool QLine::Matches(User *u) void QLine::Apply(User* u) { /* Force to uuid on apply of Q-line, no need to disconnect anymore :) */ + u->WriteNumeric(RPL_SAVENICK, u->uuid, "Your nickname has been Q-lined."); u->ChangeNick(u->uuid); } |
