diff options
| author | 2022-11-27 07:32:42 +0000 | |
|---|---|---|
| committer | 2022-11-28 02:57:50 +0000 | |
| commit | ee44af8d04f23b4a16c9b377764f930d69e575f7 (patch) | |
| tree | 4348a9d4b76ea65266875651d57d2ebf3e1d7894 /src/modules | |
| parent | Merge branch 'insp3' into master. (diff) | |
Refactor the internals of the oper system.
- Allow overriding privileges from the <class> blocks in the <type>
and <oper> blocks.
- Separate oper types from oper accounts in the code. This enables
moving some core stuff out of the config tag later.
- Merge the config tags together to make a synthetic tag that can
have getXXX called on it instead of using getConfig and then
converting it.
- Move the details of Have*Permission into the oper type class.
- Improve oper events to allow modules to easily hook into the oper
system.
Diffstat (limited to 'src/modules')
| -rw-r--r-- | src/modules/m_check.cpp | 21 | ||||
| -rw-r--r-- | src/modules/m_httpd_stats.cpp | 2 | ||||
| -rw-r--r-- | src/modules/m_ldapoper.cpp | 16 | ||||
| -rw-r--r-- | src/modules/m_operchans.cpp | 2 | ||||
| -rw-r--r-- | src/modules/m_operjoin.cpp | 4 | ||||
| -rw-r--r-- | src/modules/m_operlevels.cpp | 4 | ||||
| -rw-r--r-- | src/modules/m_opermodes.cpp | 4 | ||||
| -rw-r--r-- | src/modules/m_opermotd.cpp | 2 | ||||
| -rw-r--r-- | src/modules/m_operprefix.cpp | 4 | ||||
| -rw-r--r-- | src/modules/m_override.cpp | 4 | ||||
| -rw-r--r-- | src/modules/m_spanningtree/commands.h | 2 | ||||
| -rw-r--r-- | src/modules/m_spanningtree/main.cpp | 6 | ||||
| -rw-r--r-- | src/modules/m_spanningtree/main.h | 2 | ||||
| -rw-r--r-- | src/modules/m_spanningtree/netburst.cpp | 2 | ||||
| -rw-r--r-- | src/modules/m_spanningtree/opertype.cpp | 24 | ||||
| -rw-r--r-- | src/modules/m_sqloper.cpp | 21 | ||||
| -rw-r--r-- | src/modules/m_sslinfo.cpp | 43 | ||||
| -rw-r--r-- | src/modules/m_swhois.cpp | 7 |
18 files changed, 69 insertions, 101 deletions
diff --git a/src/modules/m_check.cpp b/src/modules/m_check.cpp index c924f55e5..10ec6ca4b 100644 --- a/src/modules/m_check.cpp +++ b/src/modules/m_check.cpp @@ -134,6 +134,19 @@ class CommandCheck final return ret; } + static std::string GetAllowedOperOnlyCommands(LocalUser* user) + { + std::string ret; + for (const auto& [_, cmd] : ServerInstance->Parser.GetCommands()) + { + if (cmd->access_needed == CmdAccess::OPERATOR && user->HasCommandPermission(cmd->name)) + ret += cmd->name + " "; + } + if (!ret.empty()) + ret.pop_back(); + return ret; + } + static std::string GetAllowedOperOnlyModes(LocalUser* user, ModeType modetype) { std::string ret; @@ -209,15 +222,15 @@ public: if (targetuser->IsOper()) { - /* user is an oper of type ____ */ - context.Write("opertype", targetuser->oper->name); + context.Write("oper", targetuser->oper->GetName()); + context.Write("opertype", targetuser->oper->GetType()); if (localtarget) { context.Write("chanmodeperms", GetAllowedOperOnlyModes(localtarget, MODETYPE_CHANNEL)); context.Write("usermodeperms", GetAllowedOperOnlyModes(localtarget, MODETYPE_USER)); context.Write("snomaskperms", GetAllowedOperOnlySnomasks(localtarget)); - context.Write("commandperms", targetuser->oper->AllowedOperCommands.ToString()); - context.Write("permissions", targetuser->oper->AllowedPrivs.ToString()); + context.Write("commandperms", GetAllowedOperOnlyCommands(localtarget)); + context.Write("permissions", localtarget->oper->GetPrivileges()); } } diff --git a/src/modules/m_httpd_stats.cpp b/src/modules/m_httpd_stats.cpp index bcad9bf31..cb8b3a462 100644 --- a/src/modules/m_httpd_stats.cpp +++ b/src/modules/m_httpd_stats.cpp @@ -274,7 +274,7 @@ namespace Stats } if (u->IsOper()) - serializer.Attribute("opertype", u->oper->name); + serializer.Attribute("opertype", u->oper->GetType()); LocalUser* lu = IS_LOCAL(u); if (lu) diff --git a/src/modules/m_ldapoper.cpp b/src/modules/m_ldapoper.cpp index 78a235919..57e570d31 100644 --- a/src/modules/m_ldapoper.cpp +++ b/src/modules/m_ldapoper.cpp @@ -85,16 +85,16 @@ public: void OnResult(const LDAPResult& r) override { auto user = ServerInstance->Users.FindUUID(uid); - ServerConfig::OperIndex::const_iterator iter = ServerInstance->Config->oper_blocks.find(opername); + auto iter = ServerInstance->Config->OperAccounts.find(opername); - if (!user || iter == ServerInstance->Config->oper_blocks.end()) + if (!user || iter == ServerInstance->Config->OperAccounts.end()) { Fallback(); delete this; return; } - user->Oper(iter->second); + user->OperLogin(iter->second); delete this; } }; @@ -219,15 +219,11 @@ public: const std::string& opername = parameters[0]; const std::string& password = parameters[1]; - ServerConfig::OperIndex::const_iterator it = ServerInstance->Config->oper_blocks.find(opername); - if (it == ServerInstance->Config->oper_blocks.end()) + auto it = ServerInstance->Config->OperAccounts.find(opername); + if (it == ServerInstance->Config->OperAccounts.end()) return MOD_RES_PASSTHRU; - std::shared_ptr<ConfigTag> tag = it->second->oper_block; - if (!tag) - return MOD_RES_PASSTHRU; - - std::string acceptedhosts = tag->getString("host"); + std::string acceptedhosts = it->second->GetConfig()->getString("host"); if (!InspIRCd::MatchMask(acceptedhosts, user->MakeHost(), user->MakeHostIP())) return MOD_RES_PASSTHRU; diff --git a/src/modules/m_operchans.cpp b/src/modules/m_operchans.cpp index 61e430633..e6c53bb12 100644 --- a/src/modules/m_operchans.cpp +++ b/src/modules/m_operchans.cpp @@ -54,7 +54,7 @@ public: return false; // Replace spaces with underscores as they're prohibited in mode parameters. - std::string opername(user->oper->name); + std::string opername(user->oper->GetType()); stdalgo::string::replace_all(opername, space, underscore); return InspIRCd::Match(opername, text); } diff --git a/src/modules/m_operjoin.cpp b/src/modules/m_operjoin.cpp index e44224f4c..2608dcca3 100644 --- a/src/modules/m_operjoin.cpp +++ b/src/modules/m_operjoin.cpp @@ -52,7 +52,7 @@ public: operChans.push_back(channame); } - void OnPostOper(User* user) override + void OnPostOperLogin(User* user) override { LocalUser* localuser = IS_LOCAL(user); if (!localuser) @@ -64,7 +64,7 @@ public: Channel::JoinUser(localuser, operchan, override); } - irc::commasepstream ss(localuser->oper->getConfig("autojoin")); + irc::commasepstream ss(localuser->oper->GetConfig()->getString("autojoin")); for (std::string channame; ss.GetToken(channame); ) { if (ServerInstance->Channels.IsChannel(channame)) diff --git a/src/modules/m_operlevels.cpp b/src/modules/m_operlevels.cpp index 04c8e32e0..7b0c7a903 100644 --- a/src/modules/m_operlevels.cpp +++ b/src/modules/m_operlevels.cpp @@ -41,8 +41,8 @@ public: // oper killing an oper? if (dest->IsOper() && source->IsOper()) { - unsigned long dest_level = ConvToNum<unsigned long>(dest->oper->getConfig("level")); - unsigned long source_level = ConvToNum<unsigned long>(source->oper->getConfig("level")); + unsigned long dest_level = dest->oper->GetConfig()->getUInt("level", 0); + unsigned long source_level = source->oper->GetConfig()->getUInt("level", 0); if (dest_level > source_level) { diff --git a/src/modules/m_opermodes.cpp b/src/modules/m_opermodes.cpp index 2d7c39539..e0911986c 100644 --- a/src/modules/m_opermodes.cpp +++ b/src/modules/m_opermodes.cpp @@ -35,12 +35,12 @@ public: { } - void OnPostOper(User* user) override + void OnPostOperLogin(User* user) override { if (!IS_LOCAL(user)) return; // We don't handle remote users. - const std::string opermodes = user->oper->getConfig("modes"); + const std::string opermodes = user->oper->GetConfig()->getString("modes"); if (opermodes.empty()) return; // We don't have any modes to set. diff --git a/src/modules/m_opermotd.cpp b/src/modules/m_opermotd.cpp index 208496eae..c6cdd691d 100644 --- a/src/modules/m_opermotd.cpp +++ b/src/modules/m_opermotd.cpp @@ -93,7 +93,7 @@ public: { } - void OnOper(User* user) override + void OnPostOperLogin(User* user) override { if (onoper && IS_LOCAL(user)) cmd.ShowOperMOTD(user, false); diff --git a/src/modules/m_operprefix.cpp b/src/modules/m_operprefix.cpp index e44408f03..a3fae72e4 100644 --- a/src/modules/m_operprefix.cpp +++ b/src/modules/m_operprefix.cpp @@ -104,7 +104,7 @@ public: ServerInstance->Modes.Process(ServerInstance->FakeClient, memb->chan, nullptr, changelist); } - void OnPostOper(User* user) override + void OnPostOperLogin(User* user) override { if (IS_LOCAL(user) && (!user->IsModeSet(hideopermode))) SetOperPrefix(user, true); @@ -114,7 +114,7 @@ public: { // m_opermodes may set +H on the oper to hide him, we don't want to set the oper prefix in that case Module* opermodes = ServerInstance->Modules.Find("opermodes"); - ServerInstance->Modules.SetPriority(this, I_OnPostOper, PRIORITY_AFTER, opermodes); + ServerInstance->Modules.SetPriority(this, I_OnPostOperLogin, PRIORITY_AFTER, opermodes); } }; diff --git a/src/modules/m_override.cpp b/src/modules/m_override.cpp index f74453a65..348889de5 100644 --- a/src/modules/m_override.cpp +++ b/src/modules/m_override.cpp @@ -162,9 +162,7 @@ public: if (!source->IsModeSet(ou)) return false; - std::string tokenlist = source->oper->getConfig("override"); - // its defined or * is set, return its value as a boolean for if the token is set - return ((tokenlist.find(token, 0) != std::string::npos) || (tokenlist.find('*', 0) != std::string::npos)); + return TokenList(source->oper->GetConfig()->getString("override")).Contains(token); } ModResult OnPreTopicChange(User* source, Channel* channel, const std::string& topic) override diff --git a/src/modules/m_spanningtree/commands.h b/src/modules/m_spanningtree/commands.h index 8e8e31f94..3acbea5f6 100644 --- a/src/modules/m_spanningtree/commands.h +++ b/src/modules/m_spanningtree/commands.h @@ -139,7 +139,7 @@ public: : public CmdBuilder { public: - Builder(User* user); + Builder(User* user, const std::shared_ptr<OperAccount>& oper); }; }; diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp index efcac01c7..1cfaae9c7 100644 --- a/src/modules/m_spanningtree/main.cpp +++ b/src/modules/m_spanningtree/main.cpp @@ -505,7 +505,7 @@ void ModuleSpanningTree::OnUserConnect(LocalUser* user) CommandUID::Builder(user).Broadcast(); if (user->IsOper()) - CommandOpertype::Builder(user).Broadcast(); + CommandOpertype::Builder(user, user->oper).Broadcast(); for (const auto& [item, obj] : user->GetExtList()) { @@ -772,14 +772,14 @@ restart: } } -void ModuleSpanningTree::OnOper(User* user) +void ModuleSpanningTree::OnOperLogin(User* user, const std::shared_ptr<OperAccount>& oper) { if (!user->IsFullyConnected() || !IS_LOCAL(user)) return; // Note: The protocol does not allow direct umode +o; // sending OPERTYPE infers +o modechange locally. - CommandOpertype::Builder(user).Broadcast(); + CommandOpertype::Builder(user, oper).Broadcast(); } void ModuleSpanningTree::OnAddLine(User* user, XLine* x) diff --git a/src/modules/m_spanningtree/main.h b/src/modules/m_spanningtree/main.h index dd2805557..539803a68 100644 --- a/src/modules/m_spanningtree/main.h +++ b/src/modules/m_spanningtree/main.h @@ -196,7 +196,7 @@ public: void OnUserKick(User* source, Membership* memb, const std::string& reason, CUList& excepts) override; void OnPreRehash(User* user, const std::string& parameter) override; void ReadConfig(ConfigStatus& status) override; - void OnOper(User* user) override; + void OnOperLogin(User* user, const std::shared_ptr<OperAccount>& oper) override; void OnAddLine(User* u, XLine* x) override; void OnDelLine(User* u, XLine* x) override; ModResult OnStats(Stats::Context& stats) override; diff --git a/src/modules/m_spanningtree/netburst.cpp b/src/modules/m_spanningtree/netburst.cpp index 5dcc88504..4664111c2 100644 --- a/src/modules/m_spanningtree/netburst.cpp +++ b/src/modules/m_spanningtree/netburst.cpp @@ -282,7 +282,7 @@ void TreeSocket::SendUsers(BurstState& bs) this->WriteLine(CommandUID::Builder(user)); if (user->IsOper()) - this->WriteLine(CommandOpertype::Builder(user)); + this->WriteLine(CommandOpertype::Builder(user, user->oper)); if (user->IsAway()) this->WriteLine(CommandAway::Builder(user)); diff --git a/src/modules/m_spanningtree/opertype.cpp b/src/modules/m_spanningtree/opertype.cpp index 066913e0c..0dcfdc4d4 100644 --- a/src/modules/m_spanningtree/opertype.cpp +++ b/src/modules/m_spanningtree/opertype.cpp @@ -32,19 +32,11 @@ */ CmdResult CommandOpertype::HandleRemote(RemoteUser* u, CommandBase::Params& params) { - const std::string& opertype = params[0]; - if (!u->IsOper()) - ServerInstance->Users.all_opers.push_back(u); - - ModeHandler* opermh = ServerInstance->Modes.FindMode('o', MODETYPE_USER); - if (opermh) - u->SetMode(opermh, true); - - ServerConfig::OperIndex::const_iterator iter = ServerInstance->Config->OperTypes.find(opertype); - if (iter != ServerInstance->Config->OperTypes.end()) - u->oper = iter->second; + auto type = ServerInstance->Config->OperTypes.find(params[0]); + if (type != ServerInstance->Config->OperTypes.end()) + u->OperLogin(std::make_shared<OperAccount>(type->first, type->second, ServerInstance->Config->EmptyTag)); else - u->oper = std::make_shared<OperInfo>(opertype); + u->OperLogin(std::make_shared<OperAccount>(params[0], nullptr, ServerInstance->Config->EmptyTag)); if (Utils->quiet_bursts) { @@ -57,13 +49,13 @@ CmdResult CommandOpertype::HandleRemote(RemoteUser* u, CommandBase::Params& para return CmdResult::SUCCESS; } - ServerInstance->SNO.WriteToSnoMask('O', "From %s: User %s (%s) is now a server operator of type %s", - u->server->GetName().c_str(), u->nick.c_str(), u->MakeHost().c_str(), opertype.c_str()); + ServerInstance->SNO.WriteToSnoMask('O', "From %s: %s (%s) is now a server operator of type %s", + u->server->GetName().c_str(), u->nick.c_str(), u->MakeHost().c_str(), u->oper->GetType().c_str()); return CmdResult::SUCCESS; } -CommandOpertype::Builder::Builder(User* user) +CommandOpertype::Builder::Builder(User* user, const std::shared_ptr<OperAccount>& oper) : CmdBuilder(user, "OPERTYPE") { - push_last(user->oper->name); + push_last(oper->GetType()); } diff --git a/src/modules/m_sqloper.cpp b/src/modules/m_sqloper.cpp index 6323d1ef2..8eb295222 100644 --- a/src/modules/m_sqloper.cpp +++ b/src/modules/m_sqloper.cpp @@ -54,11 +54,9 @@ public: void OnResult(SQL::Result& res) override { - ServerConfig::OperIndex& oper_blocks = ServerInstance->Config->oper_blocks; - - // Remove our previous blocks from oper_blocks for a clean update + // Remove our previous blocks from the core for a clean update for (const auto& block : my_blocks) - oper_blocks.erase(block); + ServerInstance->Config->OperAccounts.erase(block); my_blocks.clear(); SQL::Row row; @@ -82,11 +80,11 @@ public: const std::string name = tag->getString("name"); // Skip both duplicate sqloper blocks and sqloper blocks that attempt to override conf blocks. - if (oper_blocks.find(name) != oper_blocks.end()) + if (ServerInstance->Config->OperAccounts.find(name) != ServerInstance->Config->OperAccounts.end()) continue; const std::string type = tag->getString("type"); - ServerConfig::OperIndex::iterator tblk = ServerInstance->Config->OperTypes.find(type); + auto tblk = ServerInstance->Config->OperTypes.find(type); if (tblk == ServerInstance->Config->OperTypes.end()) { ServerInstance->Logs.Normal(MODNAME, "Sqloper block " + name + " has missing type " + type); @@ -94,12 +92,7 @@ public: continue; } - auto ifo = std::make_shared<OperInfo>(type); - - ifo->type_block = tblk->second->type_block; - ifo->oper_block = std::move(tag); - ifo->class_blocks.assign(tblk->second->class_blocks.begin(), tblk->second->class_blocks.end()); - oper_blocks[name] = ifo; + ServerInstance->Config->OperAccounts[name] = std::make_shared<OperAccount>(name, tblk->second, tag); my_blocks.push_back(name); row.clear(); } @@ -123,7 +116,7 @@ public: } } - // Call /oper after placing all blocks from the SQL table into the config->oper_blocks list. + // Call /oper after placing all blocks from the SQL table into the Config->OperAccounts list. void OperExec() { auto user = ServerInstance->Users.Find(uid); @@ -199,7 +192,7 @@ public: { // Remove all oper blocks that were from the DB for (const auto& block : my_blocks) - ServerInstance->Config->oper_blocks.erase(block); + ServerInstance->Config->OperAccounts.erase(block); } ModResult OnPreCommand(std::string& command, CommandBase::Params& parameters, LocalUser* user, bool validated) override diff --git a/src/modules/m_sslinfo.cpp b/src/modules/m_sslinfo.cpp index 5366f4ddd..15b76e4f3 100644 --- a/src/modules/m_sslinfo.cpp +++ b/src/modules/m_sslinfo.cpp @@ -323,36 +323,16 @@ public: return MOD_RES_PASSTHRU; } - ModResult OnPreCommand(std::string& command, CommandBase::Params& parameters, LocalUser* user, bool validated) override + ModResult OnPreOperLogin(LocalUser* user, const std::shared_ptr<OperAccount>& oper) override { - if ((command == "OPER") && (validated)) - { - ServerConfig::OperIndex::const_iterator i = ServerInstance->Config->oper_blocks.find(parameters[0]); - if (i != ServerInstance->Config->oper_blocks.end()) - { - std::shared_ptr<OperInfo> ifo = i->second; - ssl_cert* cert = cmd.sslapi.GetCertificate(user); - - if (ifo->oper_block->getBool("sslonly") && !cert) - { - user->WriteNumeric(ERR_NOOPERHOST, "Invalid oper credentials"); - user->CommandFloodPenalty += 10000; - ServerInstance->SNO.WriteGlobalSno('o', "WARNING! Failed oper attempt by %s using login '%s': a secure connection is required.", user->GetFullRealHost().c_str(), parameters[0].c_str()); - return MOD_RES_DENY; - } + auto cert = cmd.sslapi.GetCertificate(user); + if (oper->GetConfig()->getBool("sslonly") && !cert) + return MOD_RES_DENY; - std::string fingerprint; - if (ifo->oper_block->readString("fingerprint", fingerprint) && (!cert || !MatchFP(cert, fingerprint))) - { - user->WriteNumeric(ERR_NOOPERHOST, "Invalid oper credentials"); - user->CommandFloodPenalty += 10000; - ServerInstance->SNO.WriteGlobalSno('o', "WARNING! Failed oper attempt by %s using login '%s': their TLS client certificate fingerprint does not match.", user->GetFullRealHost().c_str(), parameters[0].c_str()); - return MOD_RES_DENY; - } - } - } + const std::string fingerprint = oper->GetConfig()->getString("fingerprint"); + if (!fingerprint.empty() && (!cert || !MatchFP(cert, fingerprint))) + return MOD_RES_DENY; - // Let core handle it for extra stuff return MOD_RES_PASSTHRU; } @@ -382,19 +362,16 @@ public: return; // Find an auto-oper block for this user - for (const auto& [_, info] : ServerInstance->Config->oper_blocks) + for (const auto& [_, info] : ServerInstance->Config->OperAccounts) { - auto oper = info->oper_block; + const auto& oper = info->GetConfig(); if (!oper->getBool("autologin")) continue; // No autologin for this block. if (!InspIRCd::MatchMask(oper->getString("host"), localuser->MakeHost(), localuser->MakeHostIP())) continue; // Host doesn't match. - if (!MatchFP(cert, oper->getString("fingerprint"))) - continue; // Fingerprint doesn't match. - - user->Oper(info); + user->OperLogin(info); } } diff --git a/src/modules/m_swhois.cpp b/src/modules/m_swhois.cpp index 99f9007d0..06e101746 100644 --- a/src/modules/m_swhois.cpp +++ b/src/modules/m_swhois.cpp @@ -116,13 +116,12 @@ public: return MOD_RES_PASSTHRU; } - void OnPostOper(User* user) override + void OnPostOperLogin(User* user) override { if (!IS_LOCAL(user)) return; - std::string swhois = user->oper->getConfig("swhois"); - + const std::string swhois = user->oper->GetConfig()->getString("swhois"); if (!swhois.length()) return; @@ -130,7 +129,7 @@ public: cmd.swhois.Set(user, swhois); } - void OnPostDeoper(User* user) override + void OnPostOperLogout(User* user, const std::shared_ptr<OperAccount>& oper) override { std::string* swhois = cmd.swhois.Get(user); if (!swhois) |
