aboutsummaryrefslogtreecommitdiffstats
path: root/src/modules/m_services.cpp
diff options
context:
space:
mode:
authorGravatar Sadie Powell2023-02-19 19:18:10 +0000
committerGravatar Sadie Powell2023-02-19 19:29:20 +0000
commit1a830b5679d3077a70bca4ffea62234eeeb33900 (patch)
tree7b1cf74f34186e9d61c29ff5e8275a2586b8a852 /src/modules/m_services.cpp
parentRename the mode fields in the services module. (diff)
Merge the servprotect module into the services module.
Diffstat (limited to 'src/modules/m_services.cpp')
-rw-r--r--src/modules/m_services.cpp74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/modules/m_services.cpp b/src/modules/m_services.cpp
index 1e49a1d9f..d43eb6c76 100644
--- a/src/modules/m_services.cpp
+++ b/src/modules/m_services.cpp
@@ -20,6 +20,12 @@
#include "inspircd.h"
#include "modules/account.h"
+enum
+{
+ // From UnrealIRCd.
+ ERR_KILLDENY = 485
+};
+
class RegisteredChannel final
: public SimpleChannelMode
{
@@ -43,6 +49,24 @@ public:
}
};
+class ServProtect final
+ : public SimpleUserMode
+{
+public:
+ ServProtect(Module* Creator)
+ : SimpleUserMode(Creator, "servprotect", 'k', true)
+ {
+ }
+
+ bool OnModeChange(User* source, User* dest, Channel* channel, Modes::Change& change) override
+ {
+ // As this mode is only intended for use by pseudoclients the only way
+ // to set it is by introducing a user with it.
+ return false;
+ }
+};
+
+
class RegisteredUser final
: public SimpleUserMode
{
@@ -74,6 +98,7 @@ private:
Account::API accountapi;
RegisteredChannel registeredcmode;
RegisteredUser registeredumode;
+ ServProtect servprotectmode;
public:
ModuleServices()
@@ -81,7 +106,56 @@ public:
, accountapi(this)
, registeredcmode(this)
, registeredumode(this)
+ , servprotectmode(this)
+ {
+ }
+
+ ModResult OnKill(User* source, User* dest, const std::string& reason) override
{
+ if (!source)
+ return MOD_RES_PASSTHRU;
+
+ if (dest->IsModeSet(servprotectmode))
+ {
+ source->WriteNumeric(ERR_KILLDENY, INSP_FORMAT("You are not permitted to kill {} services!", ServerInstance->Config->Network));
+ return MOD_RES_DENY;
+ }
+ return MOD_RES_PASSTHRU;
+ }
+
+ ModResult OnRawMode(User* user, Channel* chan, const Modes::Change& change) override
+ {
+ if (!IS_LOCAL(user) || change.adding || change.param.empty())
+ return MOD_RES_PASSTHRU; // We only care about local users removing prefix modes.
+
+ const PrefixMode* const pm = change.mh->IsPrefixMode();
+ if (!pm)
+ return MOD_RES_PASSTHRU; // Mode is not a prefix mode.
+
+ auto* target = ServerInstance->Users.Find(change.param);
+ if (!target)
+ return MOD_RES_PASSTHRU; // Target does not exist.
+
+ Membership* memb = chan->GetUser(target);
+ if (!memb || !memb->HasMode(pm))
+ return MOD_RES_PASSTHRU; // Target does not have the mode.
+
+ if (target->IsModeSet(servprotectmode))
+ {
+ user->WriteNumeric(ERR_RESTRICTED, chan->name, INSP_FORMAT("You are not permitted to remove privileges from {} services!", ServerInstance->Config->Network));
+ return MOD_RES_DENY;
+ }
+ return MOD_RES_PASSTHRU;
+ }
+
+ ModResult OnUserPreKick(User* source, Membership* memb, const std::string& reason) override
+ {
+ if (memb->user->IsModeSet(servprotectmode))
+ {
+ source->WriteNumeric(ERR_RESTRICTED, memb->chan->name, INSP_FORMAT("You are not permitted to kick {} services!", ServerInstance->Config->Network));
+ return MOD_RES_DENY;
+ }
+ return MOD_RES_PASSTHRU;
}
void OnUserPostNick(User* user, const std::string& oldnick) override