diff options
| author | 2019-01-24 15:58:57 +0000 | |
|---|---|---|
| committer | 2019-01-24 15:58:57 +0000 | |
| commit | 1799bcff97e8018156df809fd3cae3ed3d663591 (patch) | |
| tree | e8ed9f51b8d52f188c9b3d18abab4ebde915c3d4 /src | |
| parent | Add translation for casemapping between 2.0/3.0 (#1544) (diff) | |
| parent | Add translation for casemapping between 2.0/3.0 (#1544) (diff) | |
| download | inspircd++-1799bcff97e8018156df809fd3cae3ed3d663591.tar.gz inspircd++-1799bcff97e8018156df809fd3cae3ed3d663591.tar.bz2 inspircd++-1799bcff97e8018156df809fd3cae3ed3d663591.zip | |
Merge branch 'insp3' into master
Diffstat (limited to 'src')
46 files changed, 470 insertions, 291 deletions
diff --git a/src/clientprotocol.cpp b/src/clientprotocol.cpp index a732855a5..212d65d6b 100644 --- a/src/clientprotocol.cpp +++ b/src/clientprotocol.cpp @@ -35,7 +35,7 @@ bool ClientProtocol::Serializer::HandleTag(LocalUser* user, const std::string& t for (::Events::ModuleEventProvider::SubscriberList::const_iterator i = list.begin(); i != list.end(); ++i) { MessageTagProvider* const tagprov = static_cast<MessageTagProvider*>(*i); - const ModResult res = tagprov->OnClientProtocolProcessTag(user, tagname, tagvalue); + const ModResult res = tagprov->OnProcessTag(user, tagname, tagvalue); if (res == MOD_RES_ALLOW) return tags.insert(std::make_pair(tagname, MessageTagData(tagprov, tagvalue))).second; else if (res == MOD_RES_DENY) diff --git a/src/command_parse.cpp b/src/command_parse.cpp index c2ae39d49..7a732f8b5 100644 --- a/src/command_parse.cpp +++ b/src/command_parse.cpp @@ -266,24 +266,6 @@ void CommandParser::ProcessCommand(LocalUser* user, std::string& command, Comman } } - if ((user->registered == REG_ALL) && (!user->IsOper()) && (handler->IsDisabled())) - { - /* command is disabled! */ - user->CommandFloodPenalty += failpenalty; - if (ServerInstance->Config->DisabledDontExist) - { - user->WriteNumeric(ERR_UNKNOWNCOMMAND, command, "Unknown command"); - } - else - { - user->WriteNumeric(ERR_UNKNOWNCOMMAND, command, "This command has been disabled."); - } - - ServerInstance->SNO->WriteToSnoMask('a', "%s denied for %s (%s@%s)", - command.c_str(), user->nick.c_str(), user->ident.c_str(), user->GetRealHost().c_str()); - return; - } - if ((!command_p.empty()) && (command_p.back().empty()) && (!handler->allow_empty_last_param)) command_p.pop_back(); @@ -333,7 +315,6 @@ CommandBase::CommandBase(Module* mod, const std::string& cmd, unsigned int minpa , min_params(minpara) , max_params(maxpara) , use_count(0) - , disabled(false) , works_before_reg(false) , allow_empty_last_param(true) , Penalty(1) diff --git a/src/configreader.cpp b/src/configreader.cpp index ce03f1d9e..5a0ceff06 100644 --- a/src/configreader.cpp +++ b/src/configreader.cpp @@ -72,31 +72,6 @@ ServerConfig::~ServerConfig() delete EmptyTag; } -bool ServerConfig::ApplyDisabledCommands() -{ - // Enable everything first. - const CommandParser::CommandMap& commands = ServerInstance->Parser.GetCommands(); - for (CommandParser::CommandMap::const_iterator x = commands.begin(); x != commands.end(); ++x) - x->second->Disable(false); - - // Now disable the commands specified in the config. - std::string command; - irc::spacesepstream commandlist(ConfValue("disabled")->getString("commands")); - while (commandlist.GetToken(command)) - { - Command* handler = ServerInstance->Parser.GetHandler(command); - if (!handler) - { - ServerInstance->Logs->Log("CONFIG", LOG_DEBUG, "Unable to disable the %s command as it does not exist!", command.c_str()); - continue; - } - - ServerInstance->Logs->Log("CONFIG", LOG_DEBUG, "The %s command has been disabled", command.c_str()); - handler->Disable(true); - } - return true; -} - static void ReadXLine(ServerConfig* conf, const std::string& tag, const std::string& key, XLineFactory* make) { ConfigTagList tags = conf->ConfTags(tag); @@ -378,7 +353,6 @@ void ServerConfig::Fill() ServerDesc = server->getString("description", "Configure Me"); Network = server->getString("network", "Network"); NetBufferSize = ConfValue("performance")->getInt("netbuffersize", 10240, 1024, 65534); - DisabledDontExist = ConfValue("disabled")->getBool("fakenonexistant"); CustomVersion = security->getString("customversion"); HideBans = security->getBool("hidebans"); HideServer = security->getString("hideserver", security->getString("hidewhois")); @@ -429,25 +403,6 @@ void ServerConfig::Fill() RestrictBannedUsers = ServerConfig::BUT_RESTRICT_NOTIFY; else throw CoreException(restrictbannedusers + " is an invalid <options:restrictbannedusers> value, at " + options->getTagLocation()); - - DisabledUModes.reset(); - std::string modes = ConfValue("disabled")->getString("usermodes"); - for (std::string::const_iterator p = modes.begin(); p != modes.end(); ++p) - { - // Complain when the character is not a valid mode character. - if (!ModeParser::IsModeChar(*p)) - throw CoreException("Invalid usermode " + std::string(1, *p) + " was found."); - DisabledUModes.set(*p - 'A'); - } - - DisabledCModes.reset(); - modes = ConfValue("disabled")->getString("chanmodes"); - for (std::string::const_iterator p = modes.begin(); p != modes.end(); ++p) - { - if (!ModeParser::IsModeChar(*p)) - throw CoreException("Invalid chanmode " + std::string(1, *p) + " was found."); - DisabledCModes.set(*p - 'A'); - } } // WARNING: it is not safe to use most of the codebase in this function, as it @@ -723,7 +678,6 @@ void ConfigReaderThread::Finish() ServerInstance->Users.RehashCloneCounts(); ServerInstance->XLines->CheckELines(); ServerInstance->XLines->ApplyLines(); - Config->ApplyDisabledCommands(); User* user = ServerInstance->FindNick(TheUserUID); ConfigStatus status(user); diff --git a/src/coremods/core_hostname_lookup.cpp b/src/coremods/core_hostname_lookup.cpp index ec93732b1..85d0f530c 100644 --- a/src/coremods/core_hostname_lookup.cpp +++ b/src/coremods/core_hostname_lookup.cpp @@ -193,18 +193,14 @@ class ModuleHostnameLookup : public Module void OnSetUserIP(LocalUser* user) CXX11_OVERRIDE { + // If core_dns is not loaded or hostname resolution is disabled for the user's + // connect class then the logic in this function does not apply. if (!DNS || !user->MyClass->resolvehostnames) - { - user->WriteNotice("*** Skipping host resolution (disabled by server administrator)"); return; - } // Clients can't have a DNS hostname if they aren't connected via IPv4 or IPv6. if (user->client_sa.family() != AF_INET && user->client_sa.family() != AF_INET6) - { - user->WriteNotice("*** Skipping host resolution (connected via a non-IP socket)"); return; - } user->WriteNotice("*** Looking up your hostname..."); diff --git a/src/coremods/core_info/cmd_version.cpp b/src/coremods/core_info/cmd_version.cpp index 29d96169e..57f9b05cf 100644 --- a/src/coremods/core_info/cmd_version.cpp +++ b/src/coremods/core_info/cmd_version.cpp @@ -29,8 +29,12 @@ CommandVersion::CommandVersion(Module* parent) CmdResult CommandVersion::Handle(User* user, const Params& parameters) { - std::string version = ServerInstance->GetVersionString((user->IsOper())); - user->WriteNumeric(RPL_VERSION, version); + Numeric::Numeric numeric(RPL_VERSION); + irc::tokenstream tokens(ServerInstance->GetVersionString(user->IsOper())); + for (std::string token; tokens.GetTrailing(token); ) + numeric.push(token); + user->WriteNumeric(numeric); + LocalUser *lu = IS_LOCAL(user); if (lu != NULL) { diff --git a/src/coremods/core_privmsg.cpp b/src/coremods/core_privmsg.cpp index dae770abe..692a661b3 100644 --- a/src/coremods/core_privmsg.cpp +++ b/src/coremods/core_privmsg.cpp @@ -95,12 +95,24 @@ class MessageCommandBase : public Command ChanModeReference noextmsgmode; /** Send a PRIVMSG or NOTICE message to all local users from the given user - * @param user User sending the message - * @param msg The message to send - * @param mt Type of the message (MSG_PRIVMSG or MSG_NOTICE) - * @param tags Message tags to include in the outgoing protocol message + * @param source The user sending the message. + * @param msg The details of the message to send. */ - static void SendAll(User* user, const std::string& msg, MessageType mt, const ClientProtocol::TagMap& tags); + static void SendAll(User* source, const MessageDetails& details) + { + ClientProtocol::Messages::Privmsg message(ClientProtocol::Messages::Privmsg::nocopy, source, "$*", details.text, details.type); + message.AddTags(details.tags_out); + message.SetSideEffect(true); + ClientProtocol::Event messageevent(ServerInstance->GetRFCEvents().privmsg, message); + + const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers(); + for (UserManager::LocalList::const_iterator i = list.begin(); i != list.end(); ++i) + { + LocalUser* user = *i; + if ((user->registered == REG_ALL) && (!details.exemptions.count(user))) + user->Send(messageevent); + } + } public: MessageCommandBase(Module* parent, MessageType mt) @@ -128,21 +140,6 @@ class MessageCommandBase : public Command } }; -void MessageCommandBase::SendAll(User* user, const std::string& msg, MessageType mt, const ClientProtocol::TagMap& tags) -{ - ClientProtocol::Messages::Privmsg message(ClientProtocol::Messages::Privmsg::nocopy, user, "$*", msg, mt); - message.AddTags(tags); - message.SetSideEffect(true); - ClientProtocol::Event messageevent(ServerInstance->GetRFCEvents().privmsg, message); - - const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers(); - for (UserManager::LocalList::const_iterator i = list.begin(); i != list.end(); ++i) - { - if ((*i)->registered == REG_ALL) - (*i)->Send(messageevent); - } -} - CmdResult MessageCommandBase::HandleMessage(User* user, const Params& parameters, MessageType mt) { User *dest; @@ -171,7 +168,7 @@ CmdResult MessageCommandBase::HandleMessage(User* user, const Params& parameters FOREACH_MOD(OnUserMessage, (user, msgtarget, msgdetails)); if (InspIRCd::Match(ServerInstance->Config->ServerName, servername, NULL)) { - SendAll(user, msgdetails.text, mt, msgdetails.tags_out); + SendAll(user, msgdetails); } FOREACH_MOD(OnUserPostMessage, (user, msgtarget, msgdetails)); return CMD_SUCCESS; diff --git a/src/coremods/core_serialize_rfc.cpp b/src/coremods/core_serialize_rfc.cpp index 1ba330146..23a4c2052 100644 --- a/src/coremods/core_serialize_rfc.cpp +++ b/src/coremods/core_serialize_rfc.cpp @@ -19,11 +19,20 @@ #include "inspircd.h" +enum +{ + // From ircu. + ERR_INPUTTOOLONG = 417 +}; + class RFCSerializer : public ClientProtocol::Serializer { - /** Maximum size of the message tags portion of the message, including the `@` and the trailing space characters. - */ - static const std::string::size_type MAX_MESSAGE_TAG_LENGTH = 512; + + /** The maximum size of client-originated message tags in an incoming message including the `@`. */ + static const std::string::size_type MAX_CLIENT_MESSAGE_TAG_LENGTH = 4095; + + /** The maximum size of server-originated message tags in an outgoing message including the `@`. */ + static const std::string::size_type MAX_SERVER_MESSAGE_TAG_LENGTH = 511; static void SerializeTags(const ClientProtocol::TagMap& tags, const ClientProtocol::TagSelection& tagwl, std::string& line); @@ -47,15 +56,32 @@ bool RFCSerializer::Parse(LocalUser* user, const std::string& line, ClientProtoc return false; } - ServerInstance->Logs->Log("USERINPUT", LOG_RAWIO, "C[%s] I %s", user->uuid.c_str(), line.c_str()); + // Work out how long the message can actually be. + size_t maxline = ServerInstance->Config->Limits.MaxLine - start - 2; + if (line[start] == '@') + maxline += MAX_CLIENT_MESSAGE_TAG_LENGTH + 1; - irc::tokenstream tokens(line, start); - std::string token; + irc::tokenstream tokens(line, start, maxline); + ServerInstance->Logs->Log("USERINPUT", LOG_RAWIO, "C[%s] I %s", user->uuid.c_str(), tokens.GetMessage().c_str()); // This will always exist because of the check at the start of the function. + std::string token; tokens.GetMiddle(token); if (token[0] == '@') { + // Check that the client tags fit within the client tag space. + if (token.length() > MAX_CLIENT_MESSAGE_TAG_LENGTH) + { + user->WriteNumeric(ERR_INPUTTOOLONG, "Input line was too long"); + user->CommandFloodPenalty += 2000; + return false; + } + + // Truncate the RFC part of the message if it is too long. + size_t maxrfcline = token.length() + ServerInstance->Config->Limits.MaxLine - 1; + if (tokens.GetMessage().length() > maxrfcline) + tokens.GetMessage().erase(maxrfcline); + // Line begins with message tags, parse them. std::string tagval; irc::sepstream ss(token.substr(1), ';'); @@ -78,7 +104,6 @@ bool RFCSerializer::Parse(LocalUser* user, const std::string& line, ClientProtoc HandleTag(user, token, tagval, parseoutput.tags); } - // Try to read the prefix or command name. if (!tokens.GetMiddle(token)) { @@ -114,17 +139,29 @@ bool RFCSerializer::Parse(LocalUser* user, const std::string& line, ClientProtoc return true; } +namespace +{ + void CheckTagLength(std::string& line, size_t prevsize, size_t& length, size_t maxlength) + { + const std::string::size_type diffsize = line.size() - prevsize; + if (length + diffsize > maxlength) + line.erase(prevsize); + else + length += diffsize; + } +} + void RFCSerializer::SerializeTags(const ClientProtocol::TagMap& tags, const ClientProtocol::TagSelection& tagwl, std::string& line) { - char prefix = '@'; // First tag name is prefixed with a '@' + size_t client_tag_length = 0; + size_t server_tag_length = 0; for (ClientProtocol::TagMap::const_iterator i = tags.begin(); i != tags.end(); ++i) { if (!tagwl.IsSelected(tags, i)) continue; const std::string::size_type prevsize = line.size(); - line.push_back(prefix); - prefix = ';'; // Remaining tags are prefixed with ';' + line.push_back(prevsize ? ';' : '@'); line.append(i->first); const std::string& val = i->second.value; if (!val.empty()) @@ -133,16 +170,14 @@ void RFCSerializer::SerializeTags(const ClientProtocol::TagMap& tags, const Clie line.append(val); } - // The tags part of the message mustn't grow longer than what is allowed by the spec. If it does, - // remove last tag and stop adding more tags. - // - // One is subtracted from the limit before comparing because there must be a ' ' char after the last tag - // which also counts towards the limit. - if (line.size() > MAX_MESSAGE_TAG_LENGTH-1) - { - line.erase(prevsize); - break; - } + // The tags part of the message must not contain more client and server tags than allowed by the + // message tags specification. This is complicated by the tag space having separate limits for + // both server-originated and client-originated tags. If either of the tag limits is exceeded then + // the most recently added tag is removed. + if (i->first[0] == '+') + CheckTagLength(line, prevsize, client_tag_length, MAX_CLIENT_MESSAGE_TAG_LENGTH); + else + CheckTagLength(line, prevsize, server_tag_length, MAX_SERVER_MESSAGE_TAG_LENGTH); } if (!line.empty()) diff --git a/src/coremods/core_xline/cmd_eline.cpp b/src/coremods/core_xline/cmd_eline.cpp index a3a4d9466..3010e0f61 100644 --- a/src/coremods/core_xline/cmd_eline.cpp +++ b/src/coremods/core_xline/cmd_eline.cpp @@ -50,7 +50,7 @@ CmdResult CommandEline::Handle(User* user, const Params& parameters) if (ih.first.empty()) { - user->WriteNotice("*** Target not found"); + user->WriteNotice("*** Target not found."); return CMD_FAILURE; } @@ -61,7 +61,7 @@ CmdResult CommandEline::Handle(User* user, const Params& parameters) unsigned long duration; if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for E-line"); + user->WriteNotice("*** Invalid duration for E-line."); return CMD_FAILURE; } ELine* el = new ELine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str()); @@ -82,7 +82,7 @@ CmdResult CommandEline::Handle(User* user, const Params& parameters) else { delete el; - user->WriteNotice("*** E-Line for " + target + " already exists"); + user->WriteNotice("*** E-line for " + target + " already exists."); } } else @@ -93,7 +93,7 @@ CmdResult CommandEline::Handle(User* user, const Params& parameters) } else { - user->WriteNotice("*** E-Line " + target + " not found in list, try /stats e"); + user->WriteNotice("*** E-line " + target + " not found in list, try /stats e."); } } diff --git a/src/coremods/core_xline/cmd_gline.cpp b/src/coremods/core_xline/cmd_gline.cpp index a9de707c4..60dcd714a 100644 --- a/src/coremods/core_xline/cmd_gline.cpp +++ b/src/coremods/core_xline/cmd_gline.cpp @@ -50,7 +50,7 @@ CmdResult CommandGline::Handle(User* user, const Params& parameters) if (ih.first.empty()) { - user->WriteNotice("*** Target not found"); + user->WriteNotice("*** Target not found."); return CMD_FAILURE; } @@ -60,14 +60,14 @@ CmdResult CommandGline::Handle(User* user, const Params& parameters) else if (target.find('!') != std::string::npos) { - user->WriteNotice("*** G-Line cannot operate on nick!user@host masks"); + user->WriteNotice("*** G-line cannot operate on nick!user@host masks."); return CMD_FAILURE; } unsigned long duration; if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for G-line"); + user->WriteNotice("*** Invalid duration for G-line."); return CMD_FAILURE; } GLine* gl = new GLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str()); @@ -90,7 +90,7 @@ CmdResult CommandGline::Handle(User* user, const Params& parameters) else { delete gl; - user->WriteNotice("** G-Line for " + target + " already exists"); + user->WriteNotice("** G-line for " + target + " already exists."); } } @@ -102,7 +102,7 @@ CmdResult CommandGline::Handle(User* user, const Params& parameters) } else { - user->WriteNotice("*** G-Line " + target + " not found in list, try /stats g."); + user->WriteNotice("*** G-line " + target + " not found in list, try /stats g."); } } diff --git a/src/coremods/core_xline/cmd_kline.cpp b/src/coremods/core_xline/cmd_kline.cpp index 9b474d16c..813b9afa6 100644 --- a/src/coremods/core_xline/cmd_kline.cpp +++ b/src/coremods/core_xline/cmd_kline.cpp @@ -50,7 +50,7 @@ CmdResult CommandKline::Handle(User* user, const Params& parameters) if (ih.first.empty()) { - user->WriteNotice("*** Target not found"); + user->WriteNotice("*** Target not found."); return CMD_FAILURE; } @@ -60,14 +60,14 @@ CmdResult CommandKline::Handle(User* user, const Params& parameters) if (target.find('!') != std::string::npos) { - user->WriteNotice("*** K-Line cannot operate on nick!user@host masks"); + user->WriteNotice("*** K-line cannot operate on nick!user@host masks."); return CMD_FAILURE; } unsigned long duration; if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for K-line"); + user->WriteNotice("*** Invalid duration for K-line."); return CMD_FAILURE; } KLine* kl = new KLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str()); @@ -90,7 +90,7 @@ CmdResult CommandKline::Handle(User* user, const Params& parameters) else { delete kl; - user->WriteNotice("*** K-Line for " + target + " already exists"); + user->WriteNotice("*** K-line for " + target + " already exists."); } } else @@ -101,7 +101,7 @@ CmdResult CommandKline::Handle(User* user, const Params& parameters) } else { - user->WriteNotice("*** K-Line " + target + " not found in list, try /stats k."); + user->WriteNotice("*** K-line " + target + " not found in list, try /stats k."); } } diff --git a/src/coremods/core_xline/cmd_qline.cpp b/src/coremods/core_xline/cmd_qline.cpp index 893c8d213..086d860fc 100644 --- a/src/coremods/core_xline/cmd_qline.cpp +++ b/src/coremods/core_xline/cmd_qline.cpp @@ -40,14 +40,14 @@ CmdResult CommandQline::Handle(User* user, const Params& parameters) if (parameters[0].find('@') != std::string::npos || parameters[0].find('!') != std::string::npos || parameters[0].find('.') != std::string::npos) { - user->WriteNotice("*** A Q-Line only bans a nick pattern, not a nick!user@host pattern."); + user->WriteNotice("*** A Q-line only bans a nick pattern, not a nick!user@host pattern."); return CMD_FAILURE; } unsigned long duration; if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for Q-line"); + user->WriteNotice("*** Invalid duration for Q-line."); return CMD_FAILURE; } QLine* ql = new QLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), parameters[0].c_str()); @@ -69,7 +69,7 @@ CmdResult CommandQline::Handle(User* user, const Params& parameters) else { delete ql; - user->WriteNotice("*** Q-Line for " + parameters[0] + " already exists"); + user->WriteNotice("*** Q-line for " + parameters[0] + " already exists."); } } else @@ -80,7 +80,7 @@ CmdResult CommandQline::Handle(User* user, const Params& parameters) } else { - user->WriteNotice("*** Q-Line " + parameters[0] + " not found in list, try /stats q."); + user->WriteNotice("*** Q-line " + parameters[0] + " not found in list, try /stats q."); return CMD_FAILURE; } } diff --git a/src/coremods/core_xline/cmd_zline.cpp b/src/coremods/core_xline/cmd_zline.cpp index e81fc727f..31030adce 100644 --- a/src/coremods/core_xline/cmd_zline.cpp +++ b/src/coremods/core_xline/cmd_zline.cpp @@ -38,7 +38,7 @@ CmdResult CommandZline::Handle(User* user, const Params& parameters) { if (target.find('!') != std::string::npos) { - user->WriteNotice("*** You cannot include a nickname in a zline, a zline must ban only an IP mask"); + user->WriteNotice("*** You cannot include a nickname in a Z-line, a Z-line must ban only an IP mask."); return CMD_FAILURE; } @@ -65,7 +65,7 @@ CmdResult CommandZline::Handle(User* user, const Params& parameters) unsigned long duration; if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for Z-line"); + user->WriteNotice("*** Invalid duration for Z-line."); return CMD_FAILURE; } ZLine* zl = new ZLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ipaddr); @@ -87,7 +87,7 @@ CmdResult CommandZline::Handle(User* user, const Params& parameters) else { delete zl; - user->WriteNotice("*** Z-Line for " + std::string(ipaddr) + " already exists"); + user->WriteNotice("*** Z-line for " + std::string(ipaddr) + " already exists."); } } else @@ -98,7 +98,7 @@ CmdResult CommandZline::Handle(User* user, const Params& parameters) } else { - user->WriteNotice("*** Z-Line " + target + " not found in list, try /stats Z."); + user->WriteNotice("*** Z-line " + target + " not found in list, try /stats Z."); return CMD_FAILURE; } } diff --git a/src/coremods/core_xline/core_xline.cpp b/src/coremods/core_xline/core_xline.cpp index ab80ab4ed..c53834fc0 100644 --- a/src/coremods/core_xline/core_xline.cpp +++ b/src/coremods/core_xline/core_xline.cpp @@ -64,18 +64,27 @@ class CoreModXLine : public Module { } + void OnSetUserIP(LocalUser* user) CXX11_OVERRIDE + { + if (user->quitting) + return; + + user->exempt = (ServerInstance->XLines->MatchesLine("E", user) != NULL); + user->CheckLines(true); + } + ModResult OnUserPreNick(LocalUser* user, const std::string& newnick) CXX11_OVERRIDE { - // Check Q-Lines (for local nick changes only, remote servers have our Q-Lines to enforce themselves) + // Check Q-lines (for local nick changes only, remote servers have our Q-lines to enforce themselves) XLine* xline = ServerInstance->XLines->MatchesLine("Q", newnick); if (!xline) return MOD_RES_PASSTHRU; // No match - // A Q-Line matched the new nick, tell opers if the user is registered + // A Q-line matched the new nick, tell opers if the user is registered if (user->registered == REG_ALL) { - ServerInstance->SNO->WriteGlobalSno('a', "Q-Lined nickname %s from %s: %s", + ServerInstance->SNO->WriteGlobalSno('a', "Q-lined nickname %s from %s: %s", newnick.c_str(), user->GetFullRealHost().c_str(), xline->reason.c_str()); } diff --git a/src/coremods/core_xline/core_xline.h b/src/coremods/core_xline/core_xline.h index 1e0bc74cc..c607797f1 100644 --- a/src/coremods/core_xline/core_xline.h +++ b/src/coremods/core_xline/core_xline.h @@ -70,7 +70,7 @@ class InsaneBan class CommandEline : public Command { public: - /** Constructor for eline. + /** Constructor for E-line. */ CommandEline(Module* parent); @@ -87,7 +87,7 @@ class CommandEline : public Command class CommandGline : public Command { public: - /** Constructor for gline. + /** Constructor for G-line. */ CommandGline(Module* parent); @@ -104,7 +104,7 @@ class CommandGline : public Command class CommandKline : public Command { public: - /** Constructor for kline. + /** Constructor for K-line. */ CommandKline(Module* parent); @@ -127,7 +127,7 @@ class CommandQline : public Command }; public: - /** Constructor for qline. + /** Constructor for Q-line. */ CommandQline(Module* parent); @@ -150,7 +150,7 @@ class CommandZline : public Command }; public: - /** Constructor for zline. + /** Constructor for Z-line. */ CommandZline(Module* parent); diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp index 8febcbb5f..a51430a4b 100644 --- a/src/hashcomp.cpp +++ b/src/hashcomp.cpp @@ -193,8 +193,8 @@ size_t irc::insensitive::operator()(const std::string &s) const return t; } -irc::tokenstream::tokenstream(const std::string& msg, size_t start) - : message(msg, start) +irc::tokenstream::tokenstream(const std::string& msg, size_t start, size_t end) + : message(msg, start, end) , position(0) { } diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 7e299700b..09e48ea1f 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -442,7 +442,6 @@ InspIRCd::InspIRCd(int argc, char** argv) : // Build ISupport as ModuleManager::LoadAll() does not do it this->ISupport.Build(); - Config->ApplyDisabledCommands(); if (!pl.empty()) { diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp index 69c427212..ebbff448e 100644 --- a/src/inspsocket.cpp +++ b/src/inspsocket.cpp @@ -358,6 +358,11 @@ void StreamSocket::FlushSendQ(SendQueue& sq) } } +bool StreamSocket::OnSetEndPoint(const irc::sockets::sockaddrs& local, const irc::sockets::sockaddrs& remote) +{ + return false; +} + void StreamSocket::WriteData(const std::string &data) { if (fd < 0) diff --git a/src/mode.cpp b/src/mode.cpp index 0bb97cc9e..459eb21c8 100644 --- a/src/mode.cpp +++ b/src/mode.cpp @@ -312,17 +312,6 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, Mode } } - if (IS_LOCAL(user) && !user->IsOper()) - { - const std::bitset<64>& disabled = (type == MODETYPE_CHANNEL) ? ServerInstance->Config->DisabledCModes : ServerInstance->Config->DisabledUModes; - if (disabled.test(modechar - 'A')) - { - user->WriteNumeric(ERR_NOPRIVILEGES, InspIRCd::Format("Permission Denied - %s mode %c has been locked by the administrator", - type == MODETYPE_CHANNEL ? "channel" : "user", modechar)); - return MODEACTION_DENY; - } - } - if ((adding) && (IS_LOCAL(user)) && (mh->NeedsOper()) && (!user->HasModePermission(mh))) { /* It's an oper only mode, and they don't have access to it. */ @@ -587,7 +576,8 @@ ModeHandler::Id ModeParser::AllocateModeId(ModeType mt) void ModeParser::AddMode(ModeHandler* mh) { if (!ModeParser::IsModeChar(mh->GetModeChar())) - throw ModuleException("Invalid letter for mode " + mh->name); + throw ModuleException(InspIRCd::Format("Mode letter for %s is invalid: %c", + mh->name.c_str(), mh->GetModeChar())); /* A mode prefix of ',' is not acceptable, it would fuck up server to server. * A mode prefix of ':' will fuck up both server to server, and client to server. @@ -597,15 +587,19 @@ void ModeParser::AddMode(ModeHandler* mh) if (pm) { if ((pm->GetPrefix() > 126) || (pm->GetPrefix() == ',') || (pm->GetPrefix() == ':') || (pm->GetPrefix() == '#')) - throw ModuleException("Invalid prefix for mode " + mh->name); + throw ModuleException(InspIRCd::Format("Mode prefix for %s is invalid: %c", + mh->name.c_str(), pm->GetPrefix())); - if (FindPrefix(pm->GetPrefix())) - throw ModuleException("Prefix already exists for mode " + mh->name); + PrefixMode* otherpm = FindPrefix(pm->GetPrefix()); + if (otherpm) + throw ModuleException(InspIRCd::Format("Mode prefix for %s already by used by %s from %s: %c", + mh->name.c_str(), otherpm->name.c_str(), otherpm->creator->ModuleSourceFile.c_str(), pm->GetPrefix())); } ModeHandler*& slot = modehandlers[mh->GetModeType()][mh->GetModeChar()-65]; if (slot) - throw ModuleException("Letter is already in use for mode " + mh->name); + throw ModuleException(InspIRCd::Format("Mode letter for %s already by used by %s from %s: %c", + mh->name.c_str(), slot->name.c_str(), slot->creator->ModuleSourceFile.c_str(), mh->GetModeChar())); // The mode needs an id if it is either a user mode, a simple mode (flag) or a parameter mode. // Otherwise (for listmodes and prefix modes) the id remains MODEID_MAX, which is invalid. @@ -613,8 +607,13 @@ void ModeParser::AddMode(ModeHandler* mh) if ((mh->GetModeType() == MODETYPE_USER) || (mh->IsParameterMode()) || (!mh->IsListMode())) modeid = AllocateModeId(mh->GetModeType()); - if (!modehandlersbyname[mh->GetModeType()].insert(std::make_pair(mh->name, mh)).second) - throw ModuleException("Mode name already in use: " + mh->name); + std::pair<ModeHandlerMap::iterator, bool> res = modehandlersbyname[mh->GetModeType()].insert(std::make_pair(mh->name, mh)); + if (!res.second) + { + ModeHandler* othermh = res.first->second; + throw ModuleException(InspIRCd::Format("Mode name %s already used by %c from %s", + mh->name.c_str(), othermh->GetModeChar(), othermh->creator->ModuleSourceFile.c_str())); + } // Everything is fine, add the mode diff --git a/src/modules/m_alias.cpp b/src/modules/m_alias.cpp index 4d1dd65c9..3e00db765 100644 --- a/src/modules/m_alias.cpp +++ b/src/modules/m_alias.cpp @@ -107,6 +107,7 @@ class ModuleAlias : public Module ModuleAlias() : botmode(this, "bot") + , active(false) { } diff --git a/src/modules/m_cban.cpp b/src/modules/m_cban.cpp index e0768aa88..3cdbbbdfb 100644 --- a/src/modules/m_cban.cpp +++ b/src/modules/m_cban.cpp @@ -114,7 +114,7 @@ class CommandCBan : public Command unsigned long duration; if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for CBan"); + user->WriteNotice("*** Invalid duration for CBan."); return CMD_FAILURE; } const char *reason = (parameters.size() > 2) ? parameters[2].c_str() : "No reason supplied"; @@ -202,7 +202,7 @@ class ModuleCBan : public Module, public Stats::EventListener Version GetVersion() CXX11_OVERRIDE { - return Version("Gives /cban, aka C:lines. Think Q:lines, for channels.", VF_COMMON | VF_VENDOR); + return Version("Gives /cban, aka C-lines. Think Q-lines, for channels.", VF_COMMON | VF_VENDOR); } }; diff --git a/src/modules/m_cgiirc.cpp b/src/modules/m_cgiirc.cpp index 4a5a4fb03..df8201bde 100644 --- a/src/modules/m_cgiirc.cpp +++ b/src/modules/m_cgiirc.cpp @@ -34,29 +34,6 @@ enum RPL_WHOISGATEWAY = 350 }; -// We need this method up here so that it can be accessed from anywhere -static void ChangeIP(LocalUser* user, const irc::sockets::sockaddrs& sa) -{ - // Set the users IP address and make sure they are in the right clone pool. - ServerInstance->Users->RemoveCloneCounts(user); - user->SetClientIP(sa); - ServerInstance->Users->AddClone(user); - if (user->quitting) - return; - - // Recheck the connect class. - user->MyClass = NULL; - user->SetClass(); - user->CheckClass(); - if (user->quitting) - return; - - // Check if this user matches any XLines. - user->CheckLines(true); - if (user->quitting) - return; -} - // Encapsulates information about an ident host. class IdentHost { @@ -215,7 +192,7 @@ class CommandWebIRC : public SplitCommand // Set the IP address sent via WEBIRC. We ignore the hostname and lookup // instead do our own DNS lookups because of unreliable gateways. - ChangeIP(user, ipaddr); + user->SetClientIP(ipaddr); return CMD_SUCCESS; } @@ -391,7 +368,7 @@ class ModuleCgiIRC user->uuid.c_str(), user->GetIPString().c_str(), address.addr().c_str(), user->ident.c_str(), newident.c_str()); user->ChangeIdent(newident); - ChangeIP(user, address); + user->SetClientIP(address); break; } return MOD_RES_PASSTHRU; diff --git a/src/modules/m_check.cpp b/src/modules/m_check.cpp index f820f2bd0..1d030acc6 100644 --- a/src/modules/m_check.cpp +++ b/src/modules/m_check.cpp @@ -200,7 +200,7 @@ class CommandCheck : public Command opcmdlist.Add(oper->AllowedOperCommands.ToString()); opcmdlist.Flush(); CheckContext::List privlist(context, "permissions"); - opcmdlist.Add(oper->AllowedPrivs.ToString()); + privlist.Add(oper->AllowedPrivs.ToString()); privlist.Flush(); } } diff --git a/src/modules/m_clearchan.cpp b/src/modules/m_clearchan.cpp index 016d28737..dec49866c 100644 --- a/src/modules/m_clearchan.cpp +++ b/src/modules/m_clearchan.cpp @@ -211,7 +211,7 @@ class ModuleClearChan : public Module Version GetVersion() CXX11_OVERRIDE { - return Version("Adds /CLEARCHAN that allows opers to masskick, masskill or mass-G/ZLine users on a channel", VF_VENDOR|VF_OPTCOMMON); + return Version("Adds /CLEARCHAN that allows opers to masskick, masskill or mass G/Z-line users on a channel.", VF_VENDOR|VF_OPTCOMMON); } }; diff --git a/src/modules/m_conn_umodes.cpp b/src/modules/m_conn_umodes.cpp index 1f2fe7455..3132aed40 100644 --- a/src/modules/m_conn_umodes.cpp +++ b/src/modules/m_conn_umodes.cpp @@ -38,10 +38,6 @@ class ModuleModesOnConnect : public Module void OnUserConnect(LocalUser* user) CXX11_OVERRIDE { - // Backup and zero out the disabled usermodes, so that we can override them here. - const std::bitset<64> save = ServerInstance->Config->DisabledUModes; - ServerInstance->Config->DisabledUModes.reset(); - ConfigTag* tag = user->MyClass->config; std::string ThisModes = tag->getString("modes"); if (!ThisModes.empty()) @@ -58,8 +54,6 @@ class ModuleModesOnConnect : public Module ServerInstance->Parser.CallHandler("MODE", modes, user); } - - ServerInstance->Config->DisabledUModes = save; } }; diff --git a/src/modules/m_connectban.cpp b/src/modules/m_connectban.cpp index d57ffca02..20121f5f9 100644 --- a/src/modules/m_connectban.cpp +++ b/src/modules/m_connectban.cpp @@ -73,7 +73,7 @@ class ModuleConnectBan : public Module if (i->second >= threshold) { - // Create zline for set duration. + // Create Z-line for set duration. ZLine* zl = new ZLine(ServerInstance->Time(), banduration, ServerInstance->Config->ServerName, banmessage, mask.str()); if (!ServerInstance->XLines->AddLine(zl, NULL)) { @@ -83,7 +83,7 @@ class ModuleConnectBan : public Module ServerInstance->XLines->ApplyLines(); std::string maskstr = mask.str(); std::string timestr = InspIRCd::TimeString(zl->expiry); - ServerInstance->SNO->WriteGlobalSno('x',"Module m_connectban added Z:line on *@%s to expire on %s: Connect flooding", + ServerInstance->SNO->WriteGlobalSno('x',"Module m_connectban added Z-line on %s to expire on %s: Connect flooding", maskstr.c_str(), timestr.c_str()); ServerInstance->SNO->WriteGlobalSno('a', "Connect flooding from IP range %s (%d)", maskstr.c_str(), threshold); connects.erase(i); diff --git a/src/modules/m_disable.cpp b/src/modules/m_disable.cpp new file mode 100644 index 000000000..203f9ee64 --- /dev/null +++ b/src/modules/m_disable.cpp @@ -0,0 +1,189 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2019 Peter Powell <petpow@saberuk.com> + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#include "inspircd.h" + +enum +{ + // From ircu. + ERR_DISABLED = 517 +}; + +// Holds a list of disabled commands. +typedef std::vector<std::string> CommandList; + +// Holds whether modes are disabled or not. +typedef std::bitset<64> ModeStatus; + +class ModuleDisable : public Module +{ + private: + CommandList commands; + ModeStatus chanmodes; + bool fakenonexistent; + bool notifyopers; + ModeStatus usermodes; + + void ReadModes(ConfigTag* tag, const std::string& field, ModeType type, ModeStatus& status) + { + const std::string modes = tag->getString(field); + for (std::string::const_iterator iter = modes.begin(); iter != modes.end(); ++iter) + { + const char& chr = *iter; + + // Check that the character is a valid mode letter. + if (!ModeParser::IsModeChar(chr)) + throw ModuleException(InspIRCd::Format("Invalid mode '%c' was specified in <disabled:%s> at %s", + chr, field.c_str(), tag->getTagLocation().c_str())); + + // Check that the mode actually exists. + ModeHandler* mh = ServerInstance->Modes->FindMode(chr, type); + if (!chr) + throw ModuleException(InspIRCd::Format("Non-existent mode '%c' was specified in <disabled:%s> at %s", + chr, field.c_str(), tag->getTagLocation().c_str())); + + // Disable the mode. + ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "The %c (%s) %s mode has been disabled", + mh->GetModeChar(), mh->name.c_str(), type == MODETYPE_CHANNEL ? "channel" : "user"); + status.set(chr - 'A'); + } + } + + void WriteLog(const char* message, ...) CUSTOM_PRINTF(2, 3) + { + std::string buffer; + VAFORMAT(buffer, message, message); + + if (notifyopers) + ServerInstance->SNO->WriteToSnoMask('a', buffer); + else + ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, buffer); + } + + public: + void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE + { + ConfigTag* tag = ServerInstance->Config->ConfValue("disabled"); + + // Parse the disabled commands. + CommandList newcommands; + irc::spacesepstream commandlist(tag->getString("commands")); + for (std::string command; commandlist.GetToken(command); ) + { + // Check that the command actually exists. + Command* handler = ServerInstance->Parser.GetHandler(command); + if (!handler) + throw ModuleException(InspIRCd::Format("Non-existent command '%s' was specified in <disabled:commands> at %s", + command.c_str(), tag->getTagLocation().c_str())); + + // Prevent admins from disabling COMMANDS and MODULES for transparency reasons. + if (handler->name == "COMMANDS" || handler->name == "MODULES") + continue; + + // Disable the command. + ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "The %s command has been disabled", handler->name.c_str()); + newcommands.push_back(handler->name); + } + + // Parse the disabled channel modes. + ModeStatus newchanmodes; + ReadModes(tag, "chanmodes", MODETYPE_CHANNEL, newchanmodes); + + // Parse the disabled user modes. + ModeStatus newusermodes; + ReadModes(tag, "usermodes", MODETYPE_USER, newusermodes); + + // The server config was valid so we can use these now. + chanmodes = newchanmodes; + usermodes = newusermodes; + commands.swap(newcommands); + + // Whether we should fake the non-existence of disabled things. + fakenonexistent = tag->getBool("fakenonexistent", tag->getBool("fakenonexistant")); + + // Whether to notify server operators via snomask `a` about the attempted use of disabled commands/modes. + notifyopers = tag->getBool("notifyopers"); + } + + ModResult OnPreCommand(std::string& command, CommandBase::Params& parameters, LocalUser* user, bool validated) CXX11_OVERRIDE + { + // If a command is unvalidated or the source is not registered we do nothing. + if (!validated || user->registered != REG_ALL) + return MOD_RES_PASSTHRU; + + // If the command is not disabled or the user has the servers/use-disabled-commands priv we do nothing. + if (!stdalgo::isin(commands, command) || user->HasPrivPermission("servers/use-disabled-commands")) + return MOD_RES_PASSTHRU; + + // The user has tried to execute a disabled command! + user->CommandFloodPenalty += 2000; + WriteLog("%s was blocked from executing the disabled %s command", user->GetFullRealHost().c_str(), command.c_str()); + + if (fakenonexistent) + { + // The server administrator has specified that disabled commands should be + // treated as if they do not exist. + user->WriteNumeric(ERR_UNKNOWNCOMMAND, command, "Unknown command"); + ServerInstance->stats.Unknown++; + return MOD_RES_DENY; + } + + // Inform the user that the command they executed has been disabled. + user->WriteNumeric(ERR_DISABLED, command, "Command disabled"); + return MOD_RES_DENY; + } + + ModResult OnRawMode(User* user, Channel* chan, ModeHandler* mh, const std::string& param, bool adding) CXX11_OVERRIDE + { + // If a mode change is remote or the source is not registered we do nothing. + if (!IS_LOCAL(user) || user->registered != REG_ALL) + return MOD_RES_PASSTHRU; + + // If the mode is not disabled or the user has the servers/use-disabled-modes priv we do nothing. + const std::bitset<64>& disabled = (mh->GetModeType() == MODETYPE_CHANNEL) ? chanmodes : usermodes; + if (!disabled.test(mh->GetModeChar() - 'A') || user->HasPrivPermission("servers/use-disabled-modes")) + return MOD_RES_PASSTHRU; + + // The user has tried to change a disabled mode! + const char* what = mh->GetModeType() == MODETYPE_CHANNEL ? "channel" : "user"; + WriteLog("%s was blocked from executing the disabled %s mode %c (%s)", + user->GetFullRealHost().c_str(), what, mh->GetModeChar(), mh->name.c_str()); + + if (fakenonexistent) + { + // The server administrator has specified that disabled modes should be + // treated as if they do not exist. + user->WriteNumeric(mh->GetModeType() == MODETYPE_CHANNEL ? ERR_UNKNOWNMODE : ERR_UNKNOWNSNOMASK, + mh->GetModeChar(), "is unknown mode char to me"); + return MOD_RES_DENY; + } + + // Inform the user that the mode they changed has been disabled. + user->WriteNumeric(ERR_NOPRIVILEGES, InspIRCd::Format("Permission Denied - %s mode %c (%s) is disabled", + what, mh->GetModeChar(), mh->name.c_str())); + return MOD_RES_DENY; + } + + Version GetVersion() CXX11_OVERRIDE + { + return Version("Provides support for disabling commands and modes", VF_VENDOR); + } +}; + +MODULE_INIT(ModuleDisable) diff --git a/src/modules/m_dnsbl.cpp b/src/modules/m_dnsbl.cpp index d1ca800b3..eade39bd7 100644 --- a/src/modules/m_dnsbl.cpp +++ b/src/modules/m_dnsbl.cpp @@ -148,7 +148,7 @@ class DNSBLResolver : public DNS::Request if (ServerInstance->XLines->AddLine(kl,NULL)) { std::string timestr = InspIRCd::TimeString(kl->expiry); - ServerInstance->SNO->WriteGlobalSno('x',"K:line added due to DNSBL match on *@%s to expire on %s: %s", + ServerInstance->SNO->WriteGlobalSno('x', "K-line added due to DNSBL match on *@%s to expire on %s: %s", them->GetIPString().c_str(), timestr.c_str(), reason.c_str()); ServerInstance->XLines->ApplyLines(); } @@ -166,7 +166,7 @@ class DNSBLResolver : public DNS::Request if (ServerInstance->XLines->AddLine(gl,NULL)) { std::string timestr = InspIRCd::TimeString(gl->expiry); - ServerInstance->SNO->WriteGlobalSno('x',"G:line added due to DNSBL match on *@%s to expire on %s: %s", + ServerInstance->SNO->WriteGlobalSno('x', "G-line added due to DNSBL match on *@%s to expire on %s: %s", them->GetIPString().c_str(), timestr.c_str(), reason.c_str()); ServerInstance->XLines->ApplyLines(); } @@ -184,7 +184,7 @@ class DNSBLResolver : public DNS::Request if (ServerInstance->XLines->AddLine(zl,NULL)) { std::string timestr = InspIRCd::TimeString(zl->expiry); - ServerInstance->SNO->WriteGlobalSno('x',"Z:line added due to DNSBL match on %s to expire on %s: %s", + ServerInstance->SNO->WriteGlobalSno('x', "Z-line added due to DNSBL match on %s to expire on %s: %s", them->GetIPString().c_str(), timestr.c_str(), reason.c_str()); ServerInstance->XLines->ApplyLines(); } @@ -420,10 +420,14 @@ class ModuleDNSBL : public Module, public Stats::EventListener std::string dnsbl; if (!myclass->config->readString("dnsbl", dnsbl)) return MOD_RES_PASSTHRU; + std::string* match = nameExt.get(user); - std::string myname = match ? *match : ""; - if (dnsbl == myname) + if (!match) + return MOD_RES_PASSTHRU; + + if (InspIRCd::Match(*match, dnsbl)) return MOD_RES_PASSTHRU; + return MOD_RES_DENY; } diff --git a/src/modules/m_filter.cpp b/src/modules/m_filter.cpp index 0c8b81e4b..849f99086 100644 --- a/src/modules/m_filter.cpp +++ b/src/modules/m_filter.cpp @@ -421,7 +421,7 @@ ModResult ModuleFilter::OnUserPreMessage(User* user, const MessageTarget& msgtar else if (f->action == FA_GLINE) { GLine* gl = new GLine(ServerInstance->Time(), f->duration, ServerInstance->Config->ServerName.c_str(), f->reason.c_str(), "*", user->GetIPString()); - ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was glined because their message to %s matched %s (%s)", + ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was G-lined because their message to %s matched %s (%s)", user->nick.c_str(), target.c_str(), f->freeform.c_str(), f->reason.c_str())); if (ServerInstance->XLines->AddLine(gl,NULL)) { @@ -433,7 +433,7 @@ ModResult ModuleFilter::OnUserPreMessage(User* user, const MessageTarget& msgtar else if (f->action == FA_ZLINE) { ZLine* zl = new ZLine(ServerInstance->Time(), f->duration, ServerInstance->Config->ServerName.c_str(), f->reason.c_str(), user->GetIPString()); - ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was zlined because their message to %s matched %s (%s)", + ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was Z-lined because their message to %s matched %s (%s)", user->nick.c_str(), target.c_str(), f->freeform.c_str(), f->reason.c_str())); if (ServerInstance->XLines->AddLine(zl,NULL)) { @@ -506,9 +506,9 @@ ModResult ModuleFilter::OnPreCommand(std::string& command, CommandBase::Params& } if (f->action == FA_GLINE) { - /* Note: We gline *@IP so that if their host doesnt resolve the gline still applies. */ + /* Note: We G-line *@IP so that if their host doesn't resolve the G-line still applies. */ GLine* gl = new GLine(ServerInstance->Time(), f->duration, ServerInstance->Config->ServerName.c_str(), f->reason.c_str(), "*", user->GetIPString()); - ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was glined because their %s message matched %s (%s)", + ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was G-lined because their %s message matched %s (%s)", user->nick.c_str(), command.c_str(), f->freeform.c_str(), f->reason.c_str())); if (ServerInstance->XLines->AddLine(gl,NULL)) @@ -521,7 +521,7 @@ ModResult ModuleFilter::OnPreCommand(std::string& command, CommandBase::Params& if (f->action == FA_ZLINE) { ZLine* zl = new ZLine(ServerInstance->Time(), f->duration, ServerInstance->Config->ServerName.c_str(), f->reason.c_str(), user->GetIPString()); - ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was zlined because their %s message matched %s (%s)", + ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was Z-lined because their %s message matched %s (%s)", user->nick.c_str(), command.c_str(), f->freeform.c_str(), f->reason.c_str())); if (ServerInstance->XLines->AddLine(zl,NULL)) diff --git a/src/modules/m_haproxy.cpp b/src/modules/m_haproxy.cpp index e92c45686..ee9079cbf 100644 --- a/src/modules/m_haproxy.cpp +++ b/src/modules/m_haproxy.cpp @@ -240,7 +240,7 @@ class HAProxyHook : public IOHookMiddle { case AF_INET: memcpy(&client.in4.sin_addr.s_addr, &recvq[0], 4); - memcpy(&server.in4.sin_addr.s_addr, &recvq[4], 8); + memcpy(&server.in4.sin_addr.s_addr, &recvq[4], 4); memcpy(&client.in4.sin_port, &recvq[8], 2); memcpy(&server.in4.sin_port, &recvq[10], 2); tlv_index = 12; @@ -256,12 +256,13 @@ class HAProxyHook : public IOHookMiddle case AF_UNIX: memcpy(client.un.sun_path, &recvq[0], 108); - memcpy(client.un.sun_path, &recvq[108], 108); + memcpy(server.un.sun_path, &recvq[108], 108); tlv_index = 216; break; } - sock->OnSetEndPoint(server, client); + if (!sock->OnSetEndPoint(server, client)) + return -1; // Parse any available TLVs. while (tlv_index < address_length) diff --git a/src/modules/m_hostchange.cpp b/src/modules/m_hostchange.cpp index 201c4b59b..4c9b24140 100644 --- a/src/modules/m_hostchange.cpp +++ b/src/modules/m_hostchange.cpp @@ -47,7 +47,7 @@ class HostRule std::string suffix; public: - HostRule(const std::string& Host, const std::string& Mask, const insp::flat_set<int>& Ports) + HostRule(const std::string& Mask, const std::string& Host, const insp::flat_set<int>& Ports) : action(HCA_SET) , host(Host) , mask(Mask) diff --git a/src/modules/m_ident.cpp b/src/modules/m_ident.cpp index ca12a9ba3..803c19846 100644 --- a/src/modules/m_ident.cpp +++ b/src/modules/m_ident.cpp @@ -275,12 +275,24 @@ class ModuleIdent : public Module NoLookupPrefix = tag->getBool("nolookupprefix", false); } - void OnUserInit(LocalUser *user) CXX11_OVERRIDE + void OnSetUserIP(LocalUser* user) CXX11_OVERRIDE { + IdentRequestSocket* isock = ext.get(user); + if (isock) + { + // If an ident lookup request was in progress then cancel it. + isock->Close(); + ext.unset(user); + } + // The ident protocol requires that clients are connecting over a protocol with ports. if (user->client_sa.family() != AF_INET && user->client_sa.family() != AF_INET6) return; + // We don't want to look this up once the user has connected. + if (user->registered == REG_ALL) + return; + ConfigTag* tag = user->MyClass->config; if (!tag->getBool("useident", true)) return; @@ -289,7 +301,7 @@ class ModuleIdent : public Module try { - IdentRequestSocket *isock = new IdentRequestSocket(user); + isock = new IdentRequestSocket(user); ext.set(user, isock); } catch (ModuleException &e) diff --git a/src/modules/m_ircv3_echomessage.cpp b/src/modules/m_ircv3_echomessage.cpp index f6eae5a00..b407aece4 100644 --- a/src/modules/m_ircv3_echomessage.cpp +++ b/src/modules/m_ircv3_echomessage.cpp @@ -40,25 +40,26 @@ class ModuleIRCv3EchoMessage : public Module LocalUser* const localuser = static_cast<LocalUser*>(user); const std::string& text = details.echo_original ? details.original_text : details.text; + const ClientProtocol::TagMap& tags = details.echo_original ? details.tags_in : details.tags_out; if (target.type == MessageTarget::TYPE_USER) { User* destuser = target.Get<User>(); ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, user, destuser, text, details.type); - privmsg.AddTags(details.tags_in); + privmsg.AddTags(tags); localuser->Send(ServerInstance->GetRFCEvents().privmsg, privmsg); } else if (target.type == MessageTarget::TYPE_CHANNEL) { Channel* chan = target.Get<Channel>(); ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, user, chan, text, details.type, target.status); - privmsg.AddTags(details.tags_in); + privmsg.AddTags(tags); localuser->Send(ServerInstance->GetRFCEvents().privmsg, privmsg); } else { const std::string* servername = target.Get<std::string>(); ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, user, *servername, text, details.type); - privmsg.AddTags(details.tags_in); + privmsg.AddTags(tags); localuser->Send(ServerInstance->GetRFCEvents().privmsg, privmsg); } } diff --git a/src/modules/m_passforward.cpp b/src/modules/m_passforward.cpp index 08d3533cd..37efec02b 100644 --- a/src/modules/m_passforward.cpp +++ b/src/modules/m_passforward.cpp @@ -18,6 +18,7 @@ #include "inspircd.h" +#include "modules/account.h" class ModulePassForward : public Module { @@ -82,6 +83,13 @@ class ModulePassForward : public Module if (!user->MyClass->config->getString("password").empty()) return; + AccountExtItem* actext = GetAccountExtItem(); + if (actext && actext->get(user)) + { + // User is logged in already (probably via SASL) don't forward the password + return; + } + if (!nickrequired.empty()) { /* Check if nick exists and its server is ulined */ diff --git a/src/modules/m_rline.cpp b/src/modules/m_rline.cpp index 77b3bc3aa..1247e81d3 100644 --- a/src/modules/m_rline.cpp +++ b/src/modules/m_rline.cpp @@ -32,7 +32,7 @@ class RLine : public XLine { public: - /** Create a R-Line. + /** Create a R-line. * @param s_time The set time * @param d The duration of the xline * @param src The sender of the xline @@ -81,7 +81,7 @@ class RLine : public XLine if (ServerInstance->XLines->AddLine(zl, NULL)) { std::string timestr = InspIRCd::TimeString(zl->expiry); - ServerInstance->SNO->WriteToSnoMask('x', "Z-line added due to R-line match on *@%s%s%s: %s", + ServerInstance->SNO->WriteToSnoMask('x', "Z-line added due to R-line match on %s%s%s: %s", zl->ipaddr.c_str(), zl->duration ? " to expire on " : "", zl->duration ? timestr.c_str() : "", zl->reason.c_str()); added_zline = true; } @@ -150,7 +150,7 @@ class CommandRLine : public Command unsigned long duration; if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for R-line"); + user->WriteNotice("*** Invalid duration for R-line."); return CMD_FAILURE; } XLine *r = NULL; @@ -184,7 +184,7 @@ class CommandRLine : public Command else { delete r; - user->WriteNotice("*** R-Line for " + parameters[0] + " already exists"); + user->WriteNotice("*** R-line for " + parameters[0] + " already exists."); } } } @@ -196,7 +196,7 @@ class CommandRLine : public Command } else { - user->WriteNotice("*** R-Line " + parameters[0] + " not found in list, try /stats R."); + user->WriteNotice("*** R-line " + parameters[0] + " not found in list, try /stats R."); } } @@ -279,15 +279,15 @@ class ModuleRLine : public Module, public Stats::EventListener if (!rxfactory) { if (newrxengine.empty()) - ServerInstance->SNO->WriteToSnoMask('a', "WARNING: No regex engine loaded - R-Line functionality disabled until this is corrected."); + ServerInstance->SNO->WriteToSnoMask('a', "WARNING: No regex engine loaded - R-line functionality disabled until this is corrected."); else - ServerInstance->SNO->WriteToSnoMask('a', "WARNING: Regex engine '%s' is not loaded - R-Line functionality disabled until this is corrected.", newrxengine.c_str()); + ServerInstance->SNO->WriteToSnoMask('a', "WARNING: Regex engine '%s' is not loaded - R-line functionality disabled until this is corrected.", newrxengine.c_str()); ServerInstance->XLines->DelAll(f.GetType()); } else if ((!initing) && (rxfactory.operator->() != factory)) { - ServerInstance->SNO->WriteToSnoMask('a', "Regex engine has changed, removing all R-Lines"); + ServerInstance->SNO->WriteToSnoMask('a', "Regex engine has changed, removing all R-lines."); ServerInstance->XLines->DelAll(f.GetType()); } @@ -331,7 +331,7 @@ class ModuleRLine : public Module, public Stats::EventListener void OnUnloadModule(Module* mod) CXX11_OVERRIDE { - // If the regex engine became unavailable or has changed, remove all rlines + // If the regex engine became unavailable or has changed, remove all R-lines. if (!rxfactory) { ServerInstance->XLines->DelAll(f.GetType()); diff --git a/src/modules/m_samode.cpp b/src/modules/m_samode.cpp index 8f28a7e9c..db3345b98 100644 --- a/src/modules/m_samode.cpp +++ b/src/modules/m_samode.cpp @@ -124,6 +124,9 @@ class ModuleSaMode : public Module void Prioritize() CXX11_OVERRIDE { + Module* disabled = ServerInstance->Modules->Find("m_disabled.so"); + ServerInstance->Modules->SetPriority(this, I_OnRawMode, PRIORITY_BEFORE, disabled); + Module *override = ServerInstance->Modules->Find("m_override.so"); ServerInstance->Modules->SetPriority(this, I_OnPreMode, PRIORITY_BEFORE, override); } diff --git a/src/modules/m_shun.cpp b/src/modules/m_shun.cpp index e4fb2c11d..6453ace81 100644 --- a/src/modules/m_shun.cpp +++ b/src/modules/m_shun.cpp @@ -92,7 +92,7 @@ class CommandShun : public Command { if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for SHUN"); + user->WriteNotice("*** Invalid duration for SHUN."); return CMD_FAILURE; } expr = parameters[2]; @@ -122,7 +122,7 @@ class CommandShun : public Command else { delete r; - user->WriteNotice("*** Shun for " + target + " already exists"); + user->WriteNotice("*** Shun for " + target + " already exists."); return CMD_FAILURE; } } diff --git a/src/modules/m_spanningtree/away.cpp b/src/modules/m_spanningtree/away.cpp index 13972589b..62300580f 100644 --- a/src/modules/m_spanningtree/away.cpp +++ b/src/modules/m_spanningtree/away.cpp @@ -47,6 +47,6 @@ CmdResult CommandAway::HandleRemote(::RemoteUser* u, Params& params) CommandAway::Builder::Builder(User* user) : CmdBuilder(user, "AWAY") { - if (user->awaymsg.empty()) + if (!user->awaymsg.empty()) push_int(user->awaytime).push_last(user->awaymsg); } diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp index 985762872..de1e8eb19 100644 --- a/src/modules/m_spanningtree/main.cpp +++ b/src/modules/m_spanningtree/main.cpp @@ -324,8 +324,12 @@ ModResult ModuleSpanningTree::HandleVersion(const CommandBase::Params& parameter // If it's empty it might be that the server is still syncing (full version hasn't arrived yet) // or the server is a 2.0 server and does not send a full version. bool showfull = ((user->IsOper()) && (!found->GetFullVersion().empty())); - const std::string& Version = (showfull ? found->GetFullVersion() : found->GetVersion()); - user->WriteNumeric(RPL_VERSION, Version); + + Numeric::Numeric numeric(RPL_VERSION); + irc::tokenstream tokens(showfull ? found->GetFullVersion() : found->GetVersion()); + for (std::string token; tokens.GetTrailing(token); ) + numeric.push(token); + user->WriteNumeric(numeric); } else { diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h index 878b34ad7..6206448c1 100644 --- a/src/modules/m_spanningtree/treesocket.h +++ b/src/modules/m_spanningtree/treesocket.h @@ -259,7 +259,7 @@ class TreeSocket : public BufferedSocket */ void SendFJoins(Channel* c); - /** Send G, Q, Z and E lines */ + /** Send G-, Q-, Z- and E-lines */ void SendXLines(); /** Send all known information about a channel */ diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp index dc24802fb..45f8a380f 100644 --- a/src/modules/m_spanningtree/treesocket2.cpp +++ b/src/modules/m_spanningtree/treesocket2.cpp @@ -292,7 +292,7 @@ void TreeSocket::ProcessTag(User* source, const std::string& tag, ClientProtocol for (Events::ModuleEventProvider::SubscriberList::const_iterator i = list.begin(); i != list.end(); ++i) { ClientProtocol::MessageTagProvider* const tagprov = static_cast<ClientProtocol::MessageTagProvider*>(*i); - const ModResult res = tagprov->OnClientProtocolProcessTag(source, tagkey, tagval); + const ModResult res = tagprov->OnProcessTag(source, tagkey, tagval); if (res == MOD_RES_ALLOW) tags.insert(std::make_pair(tagkey, ClientProtocol::MessageTagData(tagprov, tagval))); else if (res == MOD_RES_DENY) diff --git a/src/modules/m_sslinfo.cpp b/src/modules/m_sslinfo.cpp index 54aeb9755..30dfd9a76 100644 --- a/src/modules/m_sslinfo.cpp +++ b/src/modules/m_sslinfo.cpp @@ -54,8 +54,7 @@ class SSLCertExt : public ExtensionItem void unset(Extensible* container) { - void* old = unset_raw(container); - delete static_cast<std::string*>(old); + free(container, unset_raw(container)); } std::string serialize(SerializeFormat format, const Extensible* container, void* item) const CXX11_OVERRIDE diff --git a/src/modules/m_svshold.cpp b/src/modules/m_svshold.cpp index 52c250fef..0aaf113f0 100644 --- a/src/modules/m_svshold.cpp +++ b/src/modules/m_svshold.cpp @@ -76,7 +76,7 @@ class SVSHoldFactory : public XLineFactory public: SVSHoldFactory() : XLineFactory("SVSHOLD") { } - /** Generate a shun + /** Generate an SVSHOLD */ XLine* Generate(time_t set_time, unsigned long duration, const std::string& source, const std::string& reason, const std::string& xline_specific_mask) CXX11_OVERRIDE { @@ -130,7 +130,7 @@ class CommandSvshold : public Command unsigned long duration; if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for SVSHOLD"); + user->WriteNotice("*** Invalid duration for SVSHOLD."); return CMD_FAILURE; } SVSHold* r = new SVSHold(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), parameters[0].c_str()); @@ -221,7 +221,7 @@ class ModuleSVSHold : public Module, public Stats::EventListener Version GetVersion() CXX11_OVERRIDE { - return Version("Implements SVSHOLD. Like Q:Lines, but can only be added/removed by Services.", VF_COMMON | VF_VENDOR); + return Version("Implements SVSHOLD. Like Q-lines, but can only be added/removed by Services.", VF_COMMON | VF_VENDOR); } }; diff --git a/src/snomasks.cpp b/src/snomasks.cpp index 0b266ff7e..e39fb84fb 100644 --- a/src/snomasks.cpp +++ b/src/snomasks.cpp @@ -69,8 +69,8 @@ SnomaskManager::SnomaskManager() EnableSnomask('q',"QUIT"); /* Local quit notices */ EnableSnomask('k',"KILL"); /* Kill notices */ EnableSnomask('o',"OPER"); /* Oper up/down notices */ - EnableSnomask('a',"ANNOUNCEMENT"); /* formerly WriteOpers() - generic notices to all opers */ - EnableSnomask('x',"XLINE"); /* Xline notice (g/z/q/k/e) */ + EnableSnomask('a',"ANNOUNCEMENT"); /* formerly WriteOpers() - generic notices to all opers */ + EnableSnomask('x',"XLINE"); /* X-line notices (G/Z/Q/K/E/R/SHUN/CBan) */ EnableSnomask('t',"STATS"); /* Local or remote stats request */ } diff --git a/src/usermanager.cpp b/src/usermanager.cpp index 6f9d15502..053a308cb 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -76,6 +76,7 @@ void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs this->clientlist[New->nick] = New; this->AddClone(New); this->local_users.push_front(New); + FOREACH_MOD(OnUserInit, (New)); if (!SocketEngine::AddFd(eh, FD_WANT_FAST_READ | FD_WANT_EDGE_WRITE)) { @@ -132,7 +133,7 @@ void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs New->WriteNumeric(ERR_YOUREBANNEDCREEP, ServerInstance->Config->XLineMessage); if (ServerInstance->Config->HideBans) - this->QuitUser(New, b->Type + "-Lined", &b->Reason); + this->QuitUser(New, b->Type + "-lined", &b->Reason); else this->QuitUser(New, b->Reason); return; @@ -162,8 +163,6 @@ void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs FOREACH_MOD(OnSetUserIP, (New)); if (New->quitting) return; - - FOREACH_MOD(OnUserInit, (New)); } void UserManager::QuitUser(User* user, const std::string& quitreason, const std::string* operreason) diff --git a/src/users.cpp b/src/users.cpp index f11a7a380..506cdf6d8 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -239,23 +239,30 @@ void UserIOHandler::OnDataReady() if (!user->HasPrivPermission("users/flood/no-fakelag")) penaltymax = user->MyClass->GetPenaltyThreshold() * 1000; - // The maximum size of an IRC message minus the terminating CR+LF. - const size_t maxmessage = ServerInstance->Config->Limits.MaxLine - 2; + // The cleaned message sent by the user or empty if not found yet. std::string line; - line.reserve(maxmessage); - bool eol_found; + // The position of the most \n character or npos if not found yet. + std::string::size_type eolpos; + + // The position within the recvq of the current character. std::string::size_type qpos; while (user->CommandFloodPenalty < penaltymax && getSendQSize() < sendqmax) { - qpos = 0; - eol_found = false; + // Check the newly received data for an EOL. + eolpos = recvq.find('\n', checked_until); + if (eolpos == std::string::npos) + { + checked_until = recvq.length(); + return; + } - const size_t qlen = recvq.length(); - while (qpos < qlen) + // We've found a line! Clean it up and move it to the line buffer. + line.reserve(eolpos); + for (qpos = 0; qpos < eolpos; ++qpos) { - char c = recvq[qpos++]; + char c = recvq[qpos]; switch (c) { case '\0': @@ -263,25 +270,14 @@ void UserIOHandler::OnDataReady() break; case '\r': continue; - case '\n': - eol_found = true; - break; } - if (eol_found) - break; - - if (line.length() < maxmessage) - line.push_back(c); + line.push_back(c); } - // if we return here, we haven't found a newline and make no modifications to recvq - // so we can wait for more data - if (!eol_found) - return; - // just found a newline. Terminate the string, and pull it out of recvq - recvq.erase(0, qpos); + recvq.erase(0, eolpos + 1); + checked_until = 0; // TODO should this be moved to when it was inserted in recvq? ServerInstance->stats.Recv += qpos; @@ -318,10 +314,11 @@ void UserIOHandler::AddWriteBuf(const std::string &data) WriteData(data); } -void UserIOHandler::OnSetEndPoint(const irc::sockets::sockaddrs& server, const irc::sockets::sockaddrs& client) +bool UserIOHandler::OnSetEndPoint(const irc::sockets::sockaddrs& server, const irc::sockets::sockaddrs& client) { memcpy(&user->server_sa, &server, sizeof(irc::sockets::sockaddrs)); user->SetClientIP(client); + return !user->quitting; } void UserIOHandler::OnError(BufferedSocketError) @@ -723,17 +720,17 @@ irc::sockets::cidr_mask User::GetCIDRMask() return irc::sockets::cidr_mask(client_sa, range); } -bool User::SetClientIP(const std::string& address, bool recheck_eline) +bool User::SetClientIP(const std::string& address) { irc::sockets::sockaddrs sa; if (!irc::sockets::aptosa(address, client_sa.port(), sa)) return false; - User::SetClientIP(sa, recheck_eline); + User::SetClientIP(sa); return true; } -void User::SetClientIP(const irc::sockets::sockaddrs& sa, bool recheck_eline) +void User::SetClientIP(const irc::sockets::sockaddrs& sa) { const std::string oldip(GetIPString()); memcpy(&client_sa, &sa, sizeof(irc::sockets::sockaddrs)); @@ -746,26 +743,33 @@ void User::SetClientIP(const irc::sockets::sockaddrs& sa, bool recheck_eline) ChangeDisplayedHost(GetIPString()); } -bool LocalUser::SetClientIP(const std::string& address, bool recheck_eline) +bool LocalUser::SetClientIP(const std::string& address) { irc::sockets::sockaddrs sa; if (!irc::sockets::aptosa(address, client_sa.port(), sa)) return false; - LocalUser::SetClientIP(sa, recheck_eline); + LocalUser::SetClientIP(sa); return true; } -void LocalUser::SetClientIP(const irc::sockets::sockaddrs& sa, bool recheck_eline) +void LocalUser::SetClientIP(const irc::sockets::sockaddrs& sa) { - if (sa != client_sa) - { - User::SetClientIP(sa); - if (recheck_eline) - this->exempt = (ServerInstance->XLines->MatchesLine("E", this) != NULL); + if (sa == client_sa) + return; - FOREACH_MOD(OnSetUserIP, (this)); - } + ServerInstance->Users->RemoveCloneCounts(this); + + User::SetClientIP(sa); + + FOREACH_MOD(OnSetUserIP, (this)); + + ServerInstance->Users->AddClone(this); + + // Recheck the connect class. + this->MyClass = NULL; + this->SetClass(); + this->CheckClass(); } void LocalUser::Write(const ClientProtocol::SerializedMessage& text) @@ -796,7 +800,11 @@ void LocalUser::Write(const ClientProtocol::SerializedMessage& text) void LocalUser::Send(ClientProtocol::Event& protoev) { if (!serializer) + { + ServerInstance->Logs->Log("USERS", LOG_DEBUG, "BUG: LocalUser::Send() called on %s who does not have a serializer!", + GetFullRealHost().c_str()); return; + } // In the most common case a static LocalUser field, sendmsglist, is passed to the event to be // populated. The list is cleared before returning. diff --git a/src/xline.cpp b/src/xline.cpp index 9c84101e1..55496b424 100644 --- a/src/xline.cpp +++ b/src/xline.cpp @@ -329,7 +329,7 @@ void ELine::Unset() ServerInstance->XLines->CheckELines(); } -// returns a pointer to the reason if a nickname matches a qline, NULL if it didnt match +// returns a pointer to the reason if a nickname matches a Q-line, NULL if it didn't match XLine* XLineManager::MatchesLine(const std::string &type, User* user) { @@ -523,13 +523,13 @@ bool XLine::IsBurstable() void XLine::DefaultApply(User* u, const std::string &line, bool bancache) { - const std::string banReason = line + "-Lined: " + reason; + const std::string banReason = line + "-lined: " + reason; if (!ServerInstance->Config->XLineMessage.empty()) u->WriteNumeric(ERR_YOUREBANNEDCREEP, ServerInstance->Config->XLineMessage); if (ServerInstance->Config->HideBans) - ServerInstance->Users->QuitUser(u, line + "-Lined", &banReason); + ServerInstance->Users->QuitUser(u, line + "-lined", &banReason); else ServerInstance->Users->QuitUser(u, banReason); @@ -629,7 +629,7 @@ bool QLine::Matches(User *u) void QLine::Apply(User* u) { - /* Force to uuid on apply of qline, no need to disconnect any more :) */ + /* Force to uuid on apply of Q-line, no need to disconnect anymore :) */ u->ChangeNick(u->uuid); } @@ -667,7 +667,7 @@ bool GLine::Matches(const std::string &str) void ELine::OnAdd() { - /* When adding one eline, only check the one eline */ + /* When adding one E-line, only check the one E-line */ const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers(); for (UserManager::LocalList::const_iterator u2 = list.begin(); u2 != list.end(); u2++) { @@ -681,7 +681,7 @@ void XLine::DisplayExpiry() { bool onechar = (type.length() == 1); ServerInstance->SNO->WriteToSnoMask('x', "Removing expired %s%s %s (set by %s %ld seconds ago): %s", - type.c_str(), (onechar ? "-Line" : ""), Displayable().c_str(), source.c_str(), (long)(ServerInstance->Time() - set_time), reason.c_str()); + type.c_str(), (onechar ? "-line" : ""), Displayable().c_str(), source.c_str(), (long)(ServerInstance->Time() - set_time), reason.c_str()); } const std::string& ELine::Displayable() |
