From 1736775c766cddf9e1dc436aff6060bd8553c8c3 Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Sun, 16 Oct 2022 23:24:44 +0100 Subject: Rename the services_account module to account. --- src/modules/m_account.cpp | 353 ++++++++++++++++++++++++++++++++++++ src/modules/m_callerid.cpp | 2 +- src/modules/m_sasl.cpp | 4 +- src/modules/m_services_account.cpp | 354 ------------------------------------- 4 files changed, 356 insertions(+), 357 deletions(-) create mode 100644 src/modules/m_account.cpp delete mode 100644 src/modules/m_services_account.cpp (limited to 'src/modules') diff --git a/src/modules/m_account.cpp b/src/modules/m_account.cpp new file mode 100644 index 000000000..dd696f5fa --- /dev/null +++ b/src/modules/m_account.cpp @@ -0,0 +1,353 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2019 linuxdaemon + * Copyright (C) 2013, 2017-2022 Sadie Powell + * Copyright (C) 2012-2015 Attila Molnar + * Copyright (C) 2012, 2019 Robby + * Copyright (C) 2012 Shawn Smith + * Copyright (C) 2009-2010 Daniel De Graaf + * Copyright (C) 2009 Uli Schlachter + * Copyright (C) 2007 Dennis Friis + * Copyright (C) 2006, 2008 Robin Burchell + * Copyright (C) 2006, 2008 Craig Edwards + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" +#include "modules/account.h" +#include "modules/callerid.h" +#include "modules/ctctags.h" +#include "modules/extban.h" +#include "modules/exemption.h" +#include "modules/who.h" +#include "modules/whois.h" + +enum +{ + // From ircd-hybrid? + ERR_NEEDREGGEDNICK = 477, + + // From IRCv3 sasl-3.1. + RPL_LOGGEDIN = 900, + RPL_LOGGEDOUT = 901 +}; + +class AccountExtItemImpl final + : public StringExtItem +{ + Events::ModuleEventProvider eventprov; + +public: + AccountExtItemImpl(Module* mod) + : StringExtItem(mod, "accountname", ExtensionType::USER, true) + , eventprov(mod, "event/account") + { + } + + void FromNetwork(Extensible* container, const std::string& value) noexcept override + { + if (container->extype != this->extype) + return; + + StringExtItem::FromNetwork(container, value); + + User* user = static_cast(container); + if (IS_LOCAL(user)) + { + if (value.empty()) + { + // Logged out. + user->WriteNumeric(RPL_LOGGEDOUT, user->GetFullHost(), "You are now logged out"); + } + else + { + // Logged in. + user->WriteNumeric(RPL_LOGGEDIN, user->GetFullHost(), value, InspIRCd::Format("You are now logged in as %s", value.c_str())); + } + } + + eventprov.Call(&Account::EventListener::OnAccountChange, user, value); + } +}; + + +class AccountNicksExtItem final + : public SimpleExtItem +{ +public: + AccountNicksExtItem(Module* mod) + : SimpleExtItem(mod, "accountnicks", ExtensionType::USER, true) + { + } + + void FromInternal(Extensible* container, const std::string& value) noexcept override + { + if (container->extype != this->extype) + return; + + auto list = new Account::NickList(); + irc::spacesepstream nickstream(value); + for (std::string nick; nickstream.GetToken(nick); ) + list->insert(nick); + + if (list->empty()) + { + // The remote sent an empty list of nicknames for some reason. + delete list; + Unset(container); + } + else + { + // The remote sent a non-zero list of nicks; set it. + Set(container, list); + } + } + + std::string ToInternal(const Extensible* container, void* item) const noexcept override + { + auto list = static_cast(item); + return stdalgo::string::join(*list); + } +}; + + +class AccountAPIImpl final + : public Account::APIBase +{ +private: + AccountExtItemImpl accountext; + StringExtItem accountidext; + AccountNicksExtItem accountnicksext; + UserModeReference identifiedmode; + +public: + AccountAPIImpl(Module* mod) + : Account::APIBase(mod) + , accountext(mod) + , accountidext(mod, "accountid", ExtensionType::USER, true) + , accountnicksext(mod) + , identifiedmode(mod, "u_registered") + { + } + + std::string* GetAccountId(const User* user) const override + { + return accountidext.Get(user); + } + + std::string* GetAccountName(const User* user) const override + { + return accountext.Get(user); + } + + Account::NickList* GetAccountNicks(const User* user) const override + { + return accountnicksext.Get(user); + } + + bool IsIdentifiedToNick(const User* user) override + { + if (user->IsModeSet(identifiedmode)) + return true; // User has +r set. + + // Check whether their current nick is in their nick list. + Account::NickList* nicks = accountnicksext.Get(user); + return nicks && stdalgo::isin(*nicks, user->nick); + } +}; + +class AccountExtBan final + : public ExtBan::MatchingBase +{ +private: + AccountAPIImpl& accountapi; + +public: + AccountExtBan(Module* Creator, AccountAPIImpl& AccountAPI) + : ExtBan::MatchingBase(Creator, "account", 'R') + , accountapi(AccountAPI) + { + } + + bool IsMatch(User* user, Channel* channel, const std::string& text) override + { + const std::string* account = accountapi.GetAccountName(user); + return account && InspIRCd::Match(*account, text); + } +}; + +class UnauthedExtBan final + : public ExtBan::MatchingBase +{ +private: + AccountAPIImpl& accountapi; + +public: + UnauthedExtBan(Module* Creator, AccountAPIImpl& AccountAPI) + : ExtBan::MatchingBase(Creator, "unauthed", 'U') + , accountapi(AccountAPI) + { + } + + bool IsMatch(User* user, Channel* channel, const std::string& text) override + { + const std::string* account = accountapi.GetAccountName(user); + return !account && channel->CheckBan(user, text); + } +}; + +class ModuleAccount final + : public Module + , public CTCTags::EventListener + , public Who::EventListener + , public Whois::EventListener +{ +private: + CallerID::API calleridapi; + CheckExemption::EventProvider exemptionprov; + SimpleChannelMode reginvitemode; + SimpleChannelMode regmoderatedmode; + SimpleUserMode regdeafmode; + AccountAPIImpl accountapi; + AccountExtBan accountextban; + UnauthedExtBan unauthedextban; + +public: + ModuleAccount() + : Module(VF_VENDOR | VF_OPTCOMMON, "Adds various channel and user modes relating to accounts.") + , CTCTags::EventListener(this) + , Who::EventListener(this) + , Whois::EventListener(this) + , calleridapi(this) + , exemptionprov(this) + , reginvitemode(this, "reginvite", 'R') + , regmoderatedmode(this, "regmoderated", 'M') + , regdeafmode(this, "regdeaf", 'R') + , accountapi(this) + , accountextban(this, accountapi) + , unauthedextban(this, accountapi) + { + } + + ModResult OnWhoLine(const Who::Request& request, LocalUser* source, User* user, Membership* memb, Numeric::Numeric& numeric) override + { + size_t flag_index; + if (!request.GetFieldIndex('f', flag_index)) + return MOD_RES_PASSTHRU; + + if (accountapi.IsIdentifiedToNick(user)) + numeric.GetParams()[flag_index].push_back('r'); + + return MOD_RES_PASSTHRU; + } + + void OnWhois(Whois::Context& whois) override + { + const std::string* account = accountapi.GetAccountName(whois.GetTarget()); + if (account) + whois.SendLine(RPL_WHOISACCOUNT, *account, "is logged in as"); + + if (accountapi.IsIdentifiedToNick(whois.GetTarget())) + whois.SendLine(RPL_WHOISREGNICK, "is a registered nick"); + } + + ModResult HandleMessage(User* user, const MessageTarget& target) + { + if (!IS_LOCAL(user)) + return MOD_RES_PASSTHRU; + + + const std::string* account = accountapi.GetAccountName(user); + switch (target.type) + { + case MessageTarget::TYPE_CHANNEL: + { + Channel* targetchan = target.Get(); + + if (!targetchan->IsModeSet(regmoderatedmode) || account) + return MOD_RES_PASSTHRU; + + if (CheckExemption::Call(exemptionprov, user, targetchan, "regmoderated") == MOD_RES_ALLOW) + return MOD_RES_PASSTHRU; + + // User is messaging a +M channel and is not registered or exempt. + user->WriteNumeric(ERR_NEEDREGGEDNICK, targetchan->name, "You need to be identified to a registered account to message this channel"); + return MOD_RES_DENY; + } + case MessageTarget::TYPE_USER: + { + User* targetuser = target.Get(); + if (!targetuser->IsModeSet(regdeafmode) || account) + return MOD_RES_PASSTHRU; + + if (calleridapi && calleridapi->IsOnAcceptList(user, targetuser)) + return MOD_RES_PASSTHRU; + + // User is messaging a +R user and is not registered or on an accept list. + user->WriteNumeric(ERR_NEEDREGGEDNICK, targetuser->nick, "You need to be identified to a registered account to message this user"); + return MOD_RES_DENY; + } + case MessageTarget::TYPE_SERVER: + break; + } + return MOD_RES_PASSTHRU; + } + + ModResult OnUserPreMessage(User* user, const MessageTarget& target, MessageDetails& details) override + { + return HandleMessage(user, target); + } + + ModResult OnUserPreTagMessage(User* user, const MessageTarget& target, CTCTags::TagMessageDetails& details) override + { + return HandleMessage(user, target); + } + + ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven, bool override) override + { + if (override) + return MOD_RES_PASSTHRU; + + + const std::string* account = accountapi.GetAccountName(user); + if (chan) + { + if (chan->IsModeSet(reginvitemode)) + { + if (!account) + { + // joining a +R channel and not identified + user->WriteNumeric(ERR_NEEDREGGEDNICK, chan->name, "You need to be identified to a registered account to join this channel"); + return MOD_RES_DENY; + } + } + } + return MOD_RES_PASSTHRU; + } + + ModResult OnSetConnectClass(LocalUser* user, ConnectClass::Ptr myclass) override + { + if (myclass->config->getBool("requireaccount") && !accountapi.GetAccountName(user)) + { + ServerInstance->Logs.Debug("CONNECTCLASS", "The %s connect class is not suitable as it requires the user to be logged into an account", + myclass->GetName().c_str()); + return MOD_RES_DENY; + } + return MOD_RES_PASSTHRU; + } +}; + +MODULE_INIT(ModuleAccount) diff --git a/src/modules/m_callerid.cpp b/src/modules/m_callerid.cpp index 4fc1c114e..215b2648d 100644 --- a/src/modules/m_callerid.cpp +++ b/src/modules/m_callerid.cpp @@ -466,7 +466,7 @@ public: void Prioritize() override { - // Want to be after modules like silence or services_account + // Want to be after modules like account or silence ServerInstance->Modules.SetPriority(this, I_OnUserPreMessage, PRIORITY_LAST); } }; diff --git a/src/modules/m_sasl.cpp b/src/modules/m_sasl.cpp index 73dd21c2a..159d960ed 100644 --- a/src/modules/m_sasl.cpp +++ b/src/modules/m_sasl.cpp @@ -424,8 +424,8 @@ public: void init() override { - if (!ServerInstance->Modules.Find("services_account") || !ServerInstance->Modules.Find("cap")) - ServerInstance->Logs.Normal(MODNAME, "WARNING: m_services_account and m_cap are not loaded! m_sasl will NOT function correctly until these two modules are loaded!"); + if (!ServerInstance->Modules.Find("account") || !ServerInstance->Modules.Find("cap")) + ServerInstance->Logs.Normal(MODNAME, "WARNING: the cap and services modules are not loaded! The sasl module will NOT function correctly until these two modules are loaded!"); } void ReadConfig(ConfigStatus& status) override diff --git a/src/modules/m_services_account.cpp b/src/modules/m_services_account.cpp deleted file mode 100644 index 78b040755..000000000 --- a/src/modules/m_services_account.cpp +++ /dev/null @@ -1,354 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2019 linuxdaemon - * Copyright (C) 2013, 2017-2022 Sadie Powell - * Copyright (C) 2012-2015 Attila Molnar - * Copyright (C) 2012, 2019 Robby - * Copyright (C) 2012 Shawn Smith - * Copyright (C) 2009-2010 Daniel De Graaf - * Copyright (C) 2009 Uli Schlachter - * Copyright (C) 2007 Dennis Friis - * Copyright (C) 2006, 2008 Robin Burchell - * Copyright (C) 2006, 2008 Craig Edwards - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" -#include "modules/account.h" -#include "modules/callerid.h" -#include "modules/ctctags.h" -#include "modules/extban.h" -#include "modules/exemption.h" -#include "modules/who.h" -#include "modules/whois.h" - -enum -{ - // From ircd-hybrid? - ERR_NEEDREGGEDNICK = 477, - - // From IRCv3 sasl-3.1. - RPL_LOGGEDIN = 900, - RPL_LOGGEDOUT = 901 -}; - -class AccountExtItemImpl final - : public StringExtItem -{ - Events::ModuleEventProvider eventprov; - -public: - AccountExtItemImpl(Module* mod) - : StringExtItem(mod, "accountname", ExtensionType::USER, true) - , eventprov(mod, "event/account") - { - } - - void FromNetwork(Extensible* container, const std::string& value) noexcept override - { - if (container->extype != this->extype) - return; - - StringExtItem::FromNetwork(container, value); - - User* user = static_cast(container); - if (IS_LOCAL(user)) - { - if (value.empty()) - { - // Logged out. - user->WriteNumeric(RPL_LOGGEDOUT, user->GetFullHost(), "You are now logged out"); - } - else - { - // Logged in. - user->WriteNumeric(RPL_LOGGEDIN, user->GetFullHost(), value, InspIRCd::Format("You are now logged in as %s", value.c_str())); - } - } - - eventprov.Call(&Account::EventListener::OnAccountChange, user, value); - } -}; - - -class AccountNicksExtItem final - : public SimpleExtItem -{ -public: - AccountNicksExtItem(Module* mod) - : SimpleExtItem(mod, "accountnicks", ExtensionType::USER, true) - { - } - - void FromInternal(Extensible* container, const std::string& value) noexcept override - { - if (container->extype != this->extype) - return; - - auto list = new Account::NickList(); - irc::spacesepstream nickstream(value); - for (std::string nick; nickstream.GetToken(nick); ) - list->insert(nick); - - if (list->empty()) - { - // The remote sent an empty list of nicknames for some reason. - delete list; - Unset(container); - } - else - { - // The remote sent a non-zero list of nicks; set it. - Set(container, list); - } - } - - std::string ToInternal(const Extensible* container, void* item) const noexcept override - { - auto list = static_cast(item); - return stdalgo::string::join(*list); - } -}; - - -class AccountAPIImpl final - : public Account::APIBase -{ -private: - AccountExtItemImpl accountext; - StringExtItem accountidext; - AccountNicksExtItem accountnicksext; - UserModeReference identifiedmode; - -public: - AccountAPIImpl(Module* mod) - : Account::APIBase(mod) - , accountext(mod) - , accountidext(mod, "accountid", ExtensionType::USER, true) - , accountnicksext(mod) - , identifiedmode(mod, "u_registered") - { - } - - std::string* GetAccountId(const User* user) const override - { - return accountidext.Get(user); - } - - std::string* GetAccountName(const User* user) const override - { - return accountext.Get(user); - } - - Account::NickList* GetAccountNicks(const User* user) const override - { - return accountnicksext.Get(user); - } - - bool IsIdentifiedToNick(const User* user) override - { - if (user->IsModeSet(identifiedmode)) - return true; // User has +r set. - - // Check whether their current nick is in their nick list. - Account::NickList* nicks = accountnicksext.Get(user); - return nicks && stdalgo::isin(*nicks, user->nick); - } -}; - -class AccountExtBan final - : public ExtBan::MatchingBase -{ -private: - AccountAPIImpl& accountapi; - -public: - AccountExtBan(Module* Creator, AccountAPIImpl& AccountAPI) - : ExtBan::MatchingBase(Creator, "account", 'R') - , accountapi(AccountAPI) - { - } - - bool IsMatch(User* user, Channel* channel, const std::string& text) override - { - const std::string* account = accountapi.GetAccountName(user); - return account && InspIRCd::Match(*account, text); - } -}; - -class UnauthedExtBan final - : public ExtBan::MatchingBase -{ -private: - AccountAPIImpl& accountapi; - -public: - UnauthedExtBan(Module* Creator, AccountAPIImpl& AccountAPI) - : ExtBan::MatchingBase(Creator, "unauthed", 'U') - , accountapi(AccountAPI) - { - } - - bool IsMatch(User* user, Channel* channel, const std::string& text) override - { - const std::string* account = accountapi.GetAccountName(user); - return !account && channel->CheckBan(user, text); - } -}; - -class ModuleServicesAccount final - : public Module - , public CTCTags::EventListener - , public Who::EventListener - , public Whois::EventListener -{ -private: - CallerID::API calleridapi; - CheckExemption::EventProvider exemptionprov; - SimpleChannelMode reginvitemode; - SimpleChannelMode regmoderatedmode; - SimpleUserMode regdeafmode; - AccountAPIImpl accountapi; - AccountExtBan accountextban; - UnauthedExtBan unauthedextban; - -public: - ModuleServicesAccount() - : Module(VF_VENDOR | VF_OPTCOMMON, "Adds various channel and user modes relating to services accounts.") - , CTCTags::EventListener(this) - , Who::EventListener(this) - , Whois::EventListener(this) - , calleridapi(this) - , exemptionprov(this) - , reginvitemode(this, "reginvite", 'R') - , regmoderatedmode(this, "regmoderated", 'M') - , regdeafmode(this, "regdeaf", 'R') - , accountapi(this) - , accountextban(this, accountapi) - , unauthedextban(this, accountapi) - { - } - - - ModResult OnWhoLine(const Who::Request& request, LocalUser* source, User* user, Membership* memb, Numeric::Numeric& numeric) override - { - size_t flag_index; - if (!request.GetFieldIndex('f', flag_index)) - return MOD_RES_PASSTHRU; - - if (accountapi.IsIdentifiedToNick(user)) - numeric.GetParams()[flag_index].push_back('r'); - - return MOD_RES_PASSTHRU; - } - - void OnWhois(Whois::Context& whois) override - { - const std::string* account = accountapi.GetAccountName(whois.GetTarget()); - if (account) - whois.SendLine(RPL_WHOISACCOUNT, *account, "is logged in as"); - - if (accountapi.IsIdentifiedToNick(whois.GetTarget())) - whois.SendLine(RPL_WHOISREGNICK, "is a registered nick"); - } - - ModResult HandleMessage(User* user, const MessageTarget& target) - { - if (!IS_LOCAL(user)) - return MOD_RES_PASSTHRU; - - - const std::string* account = accountapi.GetAccountName(user); - switch (target.type) - { - case MessageTarget::TYPE_CHANNEL: - { - Channel* targetchan = target.Get(); - - if (!targetchan->IsModeSet(regmoderatedmode) || account) - return MOD_RES_PASSTHRU; - - if (CheckExemption::Call(exemptionprov, user, targetchan, "regmoderated") == MOD_RES_ALLOW) - return MOD_RES_PASSTHRU; - - // User is messaging a +M channel and is not registered or exempt. - user->WriteNumeric(ERR_NEEDREGGEDNICK, targetchan->name, "You need to be identified to a registered account to message this channel"); - return MOD_RES_DENY; - } - case MessageTarget::TYPE_USER: - { - User* targetuser = target.Get(); - if (!targetuser->IsModeSet(regdeafmode) || account) - return MOD_RES_PASSTHRU; - - if (calleridapi && calleridapi->IsOnAcceptList(user, targetuser)) - return MOD_RES_PASSTHRU; - - // User is messaging a +R user and is not registered or on an accept list. - user->WriteNumeric(ERR_NEEDREGGEDNICK, targetuser->nick, "You need to be identified to a registered account to message this user"); - return MOD_RES_DENY; - } - case MessageTarget::TYPE_SERVER: - break; - } - return MOD_RES_PASSTHRU; - } - - ModResult OnUserPreMessage(User* user, const MessageTarget& target, MessageDetails& details) override - { - return HandleMessage(user, target); - } - - ModResult OnUserPreTagMessage(User* user, const MessageTarget& target, CTCTags::TagMessageDetails& details) override - { - return HandleMessage(user, target); - } - - ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven, bool override) override - { - if (override) - return MOD_RES_PASSTHRU; - - - const std::string* account = accountapi.GetAccountName(user); - if (chan) - { - if (chan->IsModeSet(reginvitemode)) - { - if (!account) - { - // joining a +R channel and not identified - user->WriteNumeric(ERR_NEEDREGGEDNICK, chan->name, "You need to be identified to a registered account to join this channel"); - return MOD_RES_DENY; - } - } - } - return MOD_RES_PASSTHRU; - } - - ModResult OnSetConnectClass(LocalUser* user, ConnectClass::Ptr myclass) override - { - if (myclass->config->getBool("requireaccount") && !accountapi.GetAccountName(user)) - { - ServerInstance->Logs.Debug("CONNECTCLASS", "The %s connect class is not suitable as it requires the user to be logged into an account", - myclass->GetName().c_str()); - return MOD_RES_DENY; - } - return MOD_RES_PASSTHRU; - } -}; - -MODULE_INIT(ModuleServicesAccount) -- cgit v1.3.1-10-gc9f91