aboutsummaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
authorGravatar Sadie Powell2022-11-27 07:32:42 +0000
committerGravatar Sadie Powell2022-11-28 02:57:50 +0000
commitee44af8d04f23b4a16c9b377764f930d69e575f7 (patch)
tree4348a9d4b76ea65266875651d57d2ebf3e1d7894 /src/modules
parentMerge 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.cpp21
-rw-r--r--src/modules/m_httpd_stats.cpp2
-rw-r--r--src/modules/m_ldapoper.cpp16
-rw-r--r--src/modules/m_operchans.cpp2
-rw-r--r--src/modules/m_operjoin.cpp4
-rw-r--r--src/modules/m_operlevels.cpp4
-rw-r--r--src/modules/m_opermodes.cpp4
-rw-r--r--src/modules/m_opermotd.cpp2
-rw-r--r--src/modules/m_operprefix.cpp4
-rw-r--r--src/modules/m_override.cpp4
-rw-r--r--src/modules/m_spanningtree/commands.h2
-rw-r--r--src/modules/m_spanningtree/main.cpp6
-rw-r--r--src/modules/m_spanningtree/main.h2
-rw-r--r--src/modules/m_spanningtree/netburst.cpp2
-rw-r--r--src/modules/m_spanningtree/opertype.cpp24
-rw-r--r--src/modules/m_sqloper.cpp21
-rw-r--r--src/modules/m_sslinfo.cpp43
-rw-r--r--src/modules/m_swhois.cpp7
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)