summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAttila Molnar <attilamolnar@hush.com>2015-04-20 17:40:12 +0200
committerAttila Molnar <attilamolnar@hush.com>2015-04-20 17:40:12 +0200
commit8f5efbc7aa33b792e02d01e3288f553e6e98ccaa (patch)
tree54a67ebd11fac07d630fa03acad7797b2f781e80 /src
parentdda1d696c1316b09d65763b4f12bc2b63cfbbe72 (diff)
parent1548078e5dc304814669cd1ea052f92be9d1ac40 (diff)
Merge insp20
Diffstat (limited to 'src')
-rw-r--r--src/command_parse.cpp17
-rw-r--r--src/configreader.cpp4
-rw-r--r--src/coremods/core_dns.cpp8
-rw-r--r--src/coremods/core_info/cmd_motd.cpp6
-rw-r--r--src/coremods/core_list.cpp15
-rw-r--r--src/coremods/core_reloadmodule.cpp2
-rw-r--r--src/coremods/core_stats.cpp8
-rw-r--r--src/coremods/core_user/cmd_user.cpp1
-rw-r--r--src/coremods/core_user/core_user.cpp13
-rw-r--r--src/coremods/core_userhost.cpp19
-rw-r--r--src/coremods/core_who.cpp2
-rw-r--r--src/hashcomp.cpp4
-rw-r--r--src/modmanager_dynamic.cpp3
-rw-r--r--src/modules/m_abbreviation.cpp2
-rw-r--r--src/modules/m_check.cpp6
-rw-r--r--src/modules/m_dccallow.cpp6
-rw-r--r--src/modules/m_globalload.cpp2
-rw-r--r--src/modules/m_hideoper.cpp6
-rw-r--r--src/modules/m_httpd.cpp14
-rw-r--r--src/modules/m_md5.cpp2
-rw-r--r--src/modules/m_operprefix.cpp14
-rw-r--r--src/modules/m_sasl.cpp5
-rw-r--r--src/modules/m_spanningtree/fjoin.cpp4
-rw-r--r--src/modules/m_spanningtree/treeserver.cpp2
-rw-r--r--src/modules/m_timedbans.cpp51
-rw-r--r--src/threadengines/threadengine_pthread.cpp4
-rw-r--r--src/usermanager.cpp21
27 files changed, 207 insertions, 34 deletions
diff --git a/src/command_parse.cpp b/src/command_parse.cpp
index c93dac65f..7998d9cc3 100644
--- a/src/command_parse.cpp
+++ b/src/command_parse.cpp
@@ -182,11 +182,21 @@ void CommandParser::ProcessCommand(LocalUser *user, std::string &cmd)
/* find the command, check it exists */
Command* handler = GetHandler(command);
+ // Penalty to give if the command fails before the handler is executed
+ unsigned int failpenalty = 0;
+
/* Modify the user's penalty regardless of whether or not the command exists */
if (!user->HasPrivPermission("users/flood/no-throttle"))
{
// If it *doesn't* exist, give it a slightly heftier penalty than normal to deter flooding us crap
- user->CommandFloodPenalty += handler ? handler->Penalty * 1000 : 2000;
+ unsigned int penalty = (handler ? handler->Penalty * 1000 : 2000);
+ user->CommandFloodPenalty += penalty;
+
+ // Increase their penalty later if we fail and the command has 0 penalty by default (i.e. in Command::Penalty) to
+ // throttle sending ERR_* from the command parser. If the command does have a non-zero penalty then this is not
+ // needed because we've increased their penalty above.
+ if (penalty == 0)
+ failpenalty = 1000;
}
if (!handler)
@@ -257,12 +267,14 @@ void CommandParser::ProcessCommand(LocalUser *user, std::string &cmd)
{
if (!user->IsModeSet(handler->flags_needed))
{
+ user->CommandFloodPenalty += failpenalty;
user->WriteNumeric(ERR_NOPRIVILEGES, ":Permission Denied - You do not have the required operator privileges");
return;
}
if (!user->HasPermission(command))
{
+ user->CommandFloodPenalty += failpenalty;
user->WriteNumeric(ERR_NOPRIVILEGES, ":Permission Denied - Oper type %s does not have access to command %s",
user->oper->name.c_str(), command.c_str());
return;
@@ -272,6 +284,7 @@ void CommandParser::ProcessCommand(LocalUser *user, std::string &cmd)
if ((user->registered == REG_ALL) && (!user->IsOper()) && (handler->IsDisabled()))
{
/* command is disabled! */
+ user->CommandFloodPenalty += failpenalty;
if (ServerInstance->Config->DisabledDontExist)
{
user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s :Unknown command", command.c_str());
@@ -291,6 +304,7 @@ void CommandParser::ProcessCommand(LocalUser *user, std::string &cmd)
if (command_p.size() < handler->min_params)
{
+ user->CommandFloodPenalty += failpenalty;
user->WriteNumeric(ERR_NEEDMOREPARAMS, "%s :Not enough parameters.", command.c_str());
if ((ServerInstance->Config->SyntaxHints) && (user->registered == REG_ALL) && (handler->syntax.length()))
user->WriteNumeric(RPL_SYNTAX, ":SYNTAX %s %s", handler->name.c_str(), handler->syntax.c_str());
@@ -299,6 +313,7 @@ void CommandParser::ProcessCommand(LocalUser *user, std::string &cmd)
if ((user->registered != REG_ALL) && (!handler->WorksBeforeReg()))
{
+ user->CommandFloodPenalty += failpenalty;
user->WriteNumeric(ERR_NOTREGISTERED, "%s :You have not registered",command.c_str());
}
else
diff --git a/src/configreader.cpp b/src/configreader.cpp
index d52f3de13..68495623c 100644
--- a/src/configreader.cpp
+++ b/src/configreader.cpp
@@ -53,6 +53,7 @@ static ConfigTag* CreateEmptyTag()
ServerConfig::ServerConfig()
: EmptyTag(CreateEmptyTag())
, Limits(EmptyTag)
+ , NoSnoticeStack(false)
{
RawLog = HideBans = HideSplits = UndernetMsgPrefix = false;
WildcardIPv6 = InvBypassModes = true;
@@ -575,7 +576,7 @@ void ServerConfig::Apply(ServerConfig* old, const std::string &useruid)
errstr << "Possible configuration error: you have not defined any <bind> blocks." << std::endl
<< "You will need to do this if you want clients to be able to connect!" << std::endl;
- if (old)
+ if (old && valid)
{
// On first run, ports are bound later on
FailedPortList pl;
@@ -784,6 +785,7 @@ void ConfigReaderThread::Finish()
* XXX: The order of these is IMPORTANT, do not reorder them without testing
* thoroughly!!!
*/
+ ServerInstance->Users.RehashCloneCounts();
ServerInstance->XLines->CheckELines();
ServerInstance->XLines->ApplyLines();
ChanModeReference ban(NULL, "ban");
diff --git a/src/coremods/core_dns.cpp b/src/coremods/core_dns.cpp
index de8dedd4a..9aca8b338 100644
--- a/src/coremods/core_dns.cpp
+++ b/src/coremods/core_dns.cpp
@@ -33,6 +33,11 @@ using namespace DNS;
*/
class Packet : public Query
{
+ static bool IsValidName(const std::string& name)
+ {
+ return (name.find_first_not_of("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-") == std::string::npos);
+ }
+
void PackName(unsigned char* output, unsigned short output_size, unsigned short& pos, const std::string& name)
{
if (pos + name.length() + 2 > output_size)
@@ -183,6 +188,9 @@ class Packet : public Query
case QUERY_PTR:
{
record.rdata = this->UnpackName(input, input_size, pos);
+ if (!IsValidName(record.rdata))
+ throw Exception("Invalid name"); // XXX: Causes the request to time out
+
break;
}
default:
diff --git a/src/coremods/core_info/cmd_motd.cpp b/src/coremods/core_info/cmd_motd.cpp
index 2d396858f..57616094e 100644
--- a/src/coremods/core_info/cmd_motd.cpp
+++ b/src/coremods/core_info/cmd_motd.cpp
@@ -32,7 +32,13 @@ CommandMotd::CommandMotd(Module* parent)
CmdResult CommandMotd::Handle (const std::vector<std::string>& parameters, User *user)
{
if (parameters.size() > 0 && parameters[0] != ServerInstance->Config->ServerName)
+ {
+ // Give extra penalty if a non-oper queries the /MOTD of a remote server
+ LocalUser* localuser = IS_LOCAL(user);
+ if ((localuser) && (!user->IsOper()))
+ localuser->CommandFloodPenalty += 2000;
return CMD_SUCCESS;
+ }
ConfigTag* tag = ServerInstance->Config->EmptyTag;
LocalUser* localuser = IS_LOCAL(user);
diff --git a/src/coremods/core_list.cpp b/src/coremods/core_list.cpp
index 745f019f2..278e6044d 100644
--- a/src/coremods/core_list.cpp
+++ b/src/coremods/core_list.cpp
@@ -94,14 +94,15 @@ CmdResult CommandList::Handle (const std::vector<std::string>& parameters, User
// if the channel is not private/secret, OR the user is on the channel anyway
bool n = (has_privs || chan->HasUser(user));
- if ((!n) && (chan->IsModeSet(privatemode)))
+ // If we're not in the channel and +s is set on it, we want to ignore it
+ if ((n) || (!chan->IsModeSet(secretmode)))
{
- /* Channel is +p and user is outside/not privileged */
- user->WriteNumeric(RPL_LIST, "* %ld :", users);
- }
- else
- {
- if ((n) || (!chan->IsModeSet(secretmode)))
+ if ((!n) && (chan->IsModeSet(privatemode)))
+ {
+ // Channel is private (+p) and user is outside/not privileged
+ user->WriteNumeric(RPL_LIST, "* %ld :", users);
+ }
+ else
{
/* User is in the channel/privileged, channel is not +s */
user->WriteNumeric(RPL_LIST, "%s %ld :[+%s] %s", chan->name.c_str(), users, chan->ChanModes(n), chan->topic.c_str());
diff --git a/src/coremods/core_reloadmodule.cpp b/src/coremods/core_reloadmodule.cpp
index 1561131dc..7f0f15e77 100644
--- a/src/coremods/core_reloadmodule.cpp
+++ b/src/coremods/core_reloadmodule.cpp
@@ -65,7 +65,7 @@ CmdResult CommandReloadmodule::Handle (const std::vector<std::string>& parameter
if (m)
{
- ServerInstance->Modules->Reload(m, new ReloadModuleWorker(user->uuid, parameters[0]));
+ ServerInstance->Modules->Reload(m, (creator->dying ? NULL : new ReloadModuleWorker(user->uuid, parameters[0])));
return CMD_SUCCESS;
}
else
diff --git a/src/coremods/core_stats.cpp b/src/coremods/core_stats.cpp
index 997dd3afe..180ece9b3 100644
--- a/src/coremods/core_stats.cpp
+++ b/src/coremods/core_stats.cpp
@@ -58,7 +58,7 @@ static void GenerateStatsLl(User* user, string_list& results, char c)
for (UserManager::LocalList::const_iterator i = list.begin(); i != list.end(); ++i)
{
LocalUser* u = *i;
- results.push_back("211 "+user->nick+" "+u->nick+"["+u->ident+"@"+(c == 'l' ? u->dhost : u->GetIPString())+"] "+ConvToStr(u->eh.getSendQSize())+" "+ConvToStr(u->cmds_out)+" "+ConvToStr(u->bytes_out)+" "+ConvToStr(u->cmds_in)+" "+ConvToStr(u->bytes_in)+" "+ConvToStr(ServerInstance->Time() - u->age));
+ results.push_back("211 "+user->nick+" "+u->nick+"["+u->ident+"@"+(c == 'l' ? u->dhost : u->GetIPString())+"] "+ConvToStr(u->eh.getSendQSize())+" "+ConvToStr(u->cmds_out)+" "+ConvToStr(u->bytes_out)+" "+ConvToStr(u->cmds_in)+" "+ConvToStr(u->bytes_in)+" "+ConvToStr(ServerInstance->Time() - u->signon));
}
}
@@ -378,7 +378,13 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
CmdResult CommandStats::Handle (const std::vector<std::string>& parameters, User *user)
{
if (parameters.size() > 1 && parameters[1] != ServerInstance->Config->ServerName)
+ {
+ // Give extra penalty if a non-oper does /STATS <remoteserver>
+ LocalUser* localuser = IS_LOCAL(user);
+ if ((localuser) && (!user->IsOper()))
+ localuser->CommandFloodPenalty += 2000;
return CMD_SUCCESS;
+ }
string_list values;
char search = parameters[0][0];
DoStats(search, user, values);
diff --git a/src/coremods/core_user/cmd_user.cpp b/src/coremods/core_user/cmd_user.cpp
index d593d7f4b..cbf4f5e08 100644
--- a/src/coremods/core_user/cmd_user.cpp
+++ b/src/coremods/core_user/cmd_user.cpp
@@ -58,6 +58,7 @@ CmdResult CommandUser::HandleLocal(const std::vector<std::string>& parameters, L
else
{
user->WriteNumeric(ERR_ALREADYREGISTERED, ":You may not reregister");
+ user->CommandFloodPenalty += 1000;
return CMD_FAILURE;
}
diff --git a/src/coremods/core_user/core_user.cpp b/src/coremods/core_user/core_user.cpp
index ffa6aa2ff..dd778548a 100644
--- a/src/coremods/core_user/core_user.cpp
+++ b/src/coremods/core_user/core_user.cpp
@@ -45,6 +45,7 @@ class CommandPass : public SplitCommand
// Check to make sure they haven't registered -- Fix by FCS
if (user->registered == REG_ALL)
{
+ user->CommandFloodPenalty += 1000;
user->WriteNumeric(ERR_ALREADYREGISTERED, ":You may not reregister");
return CMD_FAILURE;
}
@@ -64,7 +65,6 @@ class CommandPing : public Command
CommandPing(Module* parent)
: Command(parent, "PING", 1, 2)
{
- Penalty = 0;
syntax = "<servername> [:<servername>]";
}
@@ -102,8 +102,15 @@ class CommandPong : public Command
CmdResult Handle(const std::vector<std::string>& parameters, User* user)
{
// set the user as alive so they survive to next ping
- if (IS_LOCAL(user))
- IS_LOCAL(user)->lastping = 1;
+ LocalUser* localuser = IS_LOCAL(user);
+ if (localuser)
+ {
+ // Increase penalty unless we've sent a PING and this is the reply
+ if (localuser->lastping)
+ localuser->CommandFloodPenalty += 1000;
+ else
+ localuser->lastping = 1;
+ }
return CMD_SUCCESS;
}
};
diff --git a/src/coremods/core_userhost.cpp b/src/coremods/core_userhost.cpp
index a67824194..eae6e51ce 100644
--- a/src/coremods/core_userhost.cpp
+++ b/src/coremods/core_userhost.cpp
@@ -24,10 +24,15 @@
*/
class CommandUserhost : public Command
{
+ UserModeReference hideopermode;
+
public:
/** Constructor for userhost.
*/
- CommandUserhost ( Module* parent) : Command(parent,"USERHOST", 1, 5) {
+ CommandUserhost(Module* parent)
+ : Command(parent,"USERHOST", 1)
+ , hideopermode(parent, "hideoper")
+ {
syntax = "<nick> [<nick> ...]";
}
/** Handle command.
@@ -44,7 +49,11 @@ CmdResult CommandUserhost::Handle (const std::vector<std::string>& parameters, U
std::string retbuf = "302 " + user->nick + " :";
- for (unsigned int i = 0; i < parameters.size(); i++)
+ unsigned int max = parameters.size();
+ if (max > 5)
+ max = 5;
+
+ for (unsigned int i = 0; i < max; i++)
{
User *u = ServerInstance->FindNickOnly(parameters[i]);
@@ -53,7 +62,11 @@ CmdResult CommandUserhost::Handle (const std::vector<std::string>& parameters, U
retbuf += u->nick;
if (u->IsOper())
- retbuf += '*';
+ {
+ // XXX: +H hidden opers must not be shown as opers
+ if ((u == user) || (has_privs) || (!u->IsModeSet(hideopermode)))
+ retbuf += '*';
+ }
retbuf += '=';
retbuf += (u->IsAway() ? '-' : '+');
diff --git a/src/coremods/core_who.cpp b/src/coremods/core_who.cpp
index 39ea347dc..8b9258d71 100644
--- a/src/coremods/core_who.cpp
+++ b/src/coremods/core_who.cpp
@@ -144,7 +144,7 @@ bool CommandWho::whomatch(User* cuser, User* user, const char* matchtext)
long seconds = InspIRCd::Duration(matchtext);
// Okay, so time matching, we want all users connected `seconds' ago
- if (user->age >= ServerInstance->Time() - seconds)
+ if (user->signon >= ServerInstance->Time() - seconds)
match = true;
}
diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp
index 42e25f8f6..35e5f3671 100644
--- a/src/hashcomp.cpp
+++ b/src/hashcomp.cpp
@@ -153,7 +153,7 @@ unsigned const char rfc_case_sensitive_map[256] = {
size_t CoreExport irc::hash::operator()(const irc::string &s) const
{
- register size_t t = 0;
+ size_t t = 0;
for (irc::string::const_iterator x = s.begin(); x != s.end(); ++x) /* ++x not x++, as its faster */
t = 5 * t + national_case_insensitive_map[(unsigned char)*x];
return t;
@@ -196,7 +196,7 @@ size_t irc::insensitive::operator()(const std::string &s) const
* only with *x replaced with national_case_insensitive_map[*x].
* This avoids a copy to use hash<const char*>
*/
- register size_t t = 0;
+ size_t t = 0;
for (std::string::const_iterator x = s.begin(); x != s.end(); ++x) /* ++x not x++, as its faster */
t = 5 * t + national_case_insensitive_map[(unsigned char)*x];
return t;
diff --git a/src/modmanager_dynamic.cpp b/src/modmanager_dynamic.cpp
index 184013a4e..fc6161e31 100644
--- a/src/modmanager_dynamic.cpp
+++ b/src/modmanager_dynamic.cpp
@@ -31,7 +31,10 @@ bool ModuleManager::Load(const std::string& filename, bool defer)
{
/* Don't allow people to specify paths for modules, it doesn't work as expected */
if (filename.find('/') != std::string::npos)
+ {
+ LastModuleError = "You can't load modules with a path: " + filename;
return false;
+ }
const std::string moduleFile = ServerInstance->Config->Paths.PrependModule(filename);
diff --git a/src/modules/m_abbreviation.cpp b/src/modules/m_abbreviation.cpp
index 77d86cb31..d2fa09c4e 100644
--- a/src/modules/m_abbreviation.cpp
+++ b/src/modules/m_abbreviation.cpp
@@ -67,7 +67,7 @@ class ModuleAbbreviation : public Module
/* Ambiguous command, list the matches */
if (!matchlist.empty())
{
- user->WriteNumeric(420, ":Ambiguous abbreviation, posssible matches: %s%s", foundcommand.c_str(), matchlist.c_str());
+ user->WriteNumeric(420, ":Ambiguous abbreviation, possible matches: %s%s", foundcommand.c_str(), matchlist.c_str());
return MOD_RES_DENY;
}
diff --git a/src/modules/m_check.cpp b/src/modules/m_check.cpp
index 8ae30bfed..6f9c32fb1 100644
--- a/src/modules/m_check.cpp
+++ b/src/modules/m_check.cpp
@@ -73,8 +73,10 @@ class CommandCheck : public Command
{
char timebuf[60];
struct tm *mytime = gmtime(&time);
- strftime(timebuf, 59, "%Y-%m-%d %H:%M:%S UTC (%s)", mytime);
- return std::string(timebuf);
+ strftime(timebuf, 59, "%Y-%m-%d %H:%M:%S UTC (", mytime);
+ std::string ret(timebuf);
+ ret.append(ConvToStr(time)).push_back(')');
+ return ret;
}
void dumpExt(User* user, const std::string& checkstr, Extensible* ext)
diff --git a/src/modules/m_dccallow.cpp b/src/modules/m_dccallow.cpp
index 2b8d1306c..f011fa449 100644
--- a/src/modules/m_dccallow.cpp
+++ b/src/modules/m_dccallow.cpp
@@ -318,6 +318,9 @@ class ModuleDCCAllow : public Module
while (ss >> buf)
tokens.push_back(buf);
+ if (tokens.size() < 2)
+ return MOD_RES_PASSTHRU;
+
irc::string type = tokens[1].c_str();
ConfigTag* conftag = ServerInstance->Config->ConfValue("dccallow");
@@ -325,6 +328,9 @@ class ModuleDCCAllow : public Module
if (type == "SEND")
{
+ if (tokens.size() < 3)
+ return MOD_RES_PASSTHRU;
+
std::string defaultaction = conftag->getString("action");
std::string filename = tokens[2];
diff --git a/src/modules/m_globalload.cpp b/src/modules/m_globalload.cpp
index 8ee8472e6..a3f3242f0 100644
--- a/src/modules/m_globalload.cpp
+++ b/src/modules/m_globalload.cpp
@@ -155,7 +155,7 @@ class CommandGreloadmodule : public Command
if (m)
{
GReloadModuleWorker* worker = NULL;
- if (m != creator)
+ if ((m != creator) && (!creator->dying))
worker = new GReloadModuleWorker(user->nick, user->uuid, parameters[0]);
ServerInstance->Modules->Reload(m, worker);
}
diff --git a/src/modules/m_hideoper.cpp b/src/modules/m_hideoper.cpp
index 5b226f3b8..81b9b888f 100644
--- a/src/modules/m_hideoper.cpp
+++ b/src/modules/m_hideoper.cpp
@@ -68,7 +68,11 @@ class ModuleHideOper : public Module
if (user->IsModeSet(hm) && !source->HasPrivPermission("users/auspex"))
{
// hide the "*" that marks the user as an oper from the /WHO line
- std::string::size_type pos = line.find("*");
+ std::string::size_type spcolon = line.find(" :");
+ if (spcolon == std::string::npos)
+ return; // Another module hid the user completely
+ std::string::size_type sp = line.rfind(' ', spcolon-1);
+ std::string::size_type pos = line.find('*', sp);
if (pos != std::string::npos)
line.erase(pos, 1);
// hide the line completely if doing a "/who * o" query
diff --git a/src/modules/m_httpd.cpp b/src/modules/m_httpd.cpp
index e09ca3fa2..aa83b120c 100644
--- a/src/modules/m_httpd.cpp
+++ b/src/modules/m_httpd.cpp
@@ -407,6 +407,20 @@ class ModuleHttpServer : public Module
return MOD_RES_ALLOW;
}
+ void OnUnloadModule(Module* mod)
+ {
+ for (insp::intrusive_list<HttpServerSocket>::const_iterator i = sockets.begin(); i != sockets.end(); ++i)
+ {
+ HttpServerSocket* sock = *i;
+ ++i;
+ if (sock->GetIOHook() && sock->GetIOHook()->prov->creator == mod)
+ {
+ sock->cull();
+ delete sock;
+ }
+ }
+ }
+
CullResult cull() CXX11_OVERRIDE
{
for (insp::intrusive_list<HttpServerSocket>::const_iterator i = sockets.begin(); i != sockets.end(); ++i)
diff --git a/src/modules/m_md5.cpp b/src/modules/m_md5.cpp
index 6e6f5006f..6cec05a18 100644
--- a/src/modules/m_md5.cpp
+++ b/src/modules/m_md5.cpp
@@ -154,7 +154,7 @@ class MD5Provider : public HashProvider
void MD5Transform(word32 buf[4], word32 const in[16])
{
- register word32 a, b, c, d;
+ word32 a, b, c, d;
a = buf[0];
b = buf[1];
diff --git a/src/modules/m_operprefix.cpp b/src/modules/m_operprefix.cpp
index 4c63e53d1..51281a528 100644
--- a/src/modules/m_operprefix.cpp
+++ b/src/modules/m_operprefix.cpp
@@ -72,6 +72,20 @@ class ModuleOperPrefixMode : public Module
return MOD_RES_PASSTHRU;
}
+ void OnPostJoin(Membership* memb)
+ {
+ if ((!IS_LOCAL(memb->user)) || (!memb->user->IsOper()) || (memb->user->IsModeSet(hideopermode)))
+ return;
+
+ if (memb->hasMode(opm.GetModeChar()))
+ return;
+
+ // The user was force joined and OnUserPreJoin() did not run. Set the operprefix now.
+ Modes::ChangeList changelist;
+ changelist.push_add(&opm, memb->user->nick);
+ ServerInstance->Modes.Process(ServerInstance->FakeClient, memb->chan, NULL, changelist);
+ }
+
void SetOperPrefix(User* user, bool add)
{
Modes::ChangeList changelist;
diff --git a/src/modules/m_sasl.cpp b/src/modules/m_sasl.cpp
index c96b87034..341b3aea7 100644
--- a/src/modules/m_sasl.cpp
+++ b/src/modules/m_sasl.cpp
@@ -96,6 +96,9 @@ class SaslAuthenticator
if (msg[0] != this->agent)
return this->state;
+ if (msg.size() < 4)
+ return this->state;
+
if (msg[2] == "C")
this->user->Write("AUTHENTICATE %s", msg[3].c_str());
else if (msg[2] == "D")
@@ -285,7 +288,7 @@ class ModuleSASL : public Module
Version GetVersion() CXX11_OVERRIDE
{
- return Version("Provides support for IRC Authentication Layer (aka: atheme SASL) via AUTHENTICATE.",VF_VENDOR);
+ return Version("Provides support for IRC Authentication Layer (aka: SASL) via AUTHENTICATE.", VF_VENDOR);
}
};
diff --git a/src/modules/m_spanningtree/fjoin.cpp b/src/modules/m_spanningtree/fjoin.cpp
index 25c1f6678..e29aa09d7 100644
--- a/src/modules/m_spanningtree/fjoin.cpp
+++ b/src/modules/m_spanningtree/fjoin.cpp
@@ -129,8 +129,8 @@ CmdResult CommandFJoin::Handle(User* srcuser, std::vector<std::string>& params)
time_t ourTS = chan->age;
if (TS != ourTS)
{
- ServerInstance->SNO->WriteToSnoMask('d', "Merge FJOIN received for %s, ourTS: %lu, TS: %lu, difference: %lu",
- chan->name.c_str(), (unsigned long)ourTS, (unsigned long)TS, (unsigned long)(ourTS - TS));
+ ServerInstance->SNO->WriteToSnoMask('d', "Merge FJOIN received for %s, ourTS: %lu, TS: %lu, difference: %ld",
+ chan->name.c_str(), (unsigned long)ourTS, (unsigned long)TS, (long)(ourTS - TS));
/* If our TS is less than theirs, we dont accept their modes */
if (ourTS < TS)
{
diff --git a/src/modules/m_spanningtree/treeserver.cpp b/src/modules/m_spanningtree/treeserver.cpp
index d0c6401cd..afd86c0ce 100644
--- a/src/modules/m_spanningtree/treeserver.cpp
+++ b/src/modules/m_spanningtree/treeserver.cpp
@@ -40,7 +40,7 @@ TreeServer::TreeServer()
, Socket(NULL), sid(ServerInstance->Config->GetSID()), behind_bursting(0), isdead(false)
, pingtimer(this)
, ServerUser(ServerInstance->FakeClient)
- , age(ServerInstance->Time()), UserCount(ServerInstance->Users.GetLocalUsers().size())
+ , age(ServerInstance->Time()), UserCount(ServerInstance->Users.LocalUserCount())
, OperCount(0), rtt(0), StartBurst(0), Hidden(false)
{
AddHashEntry();
diff --git a/src/modules/m_timedbans.cpp b/src/modules/m_timedbans.cpp
index 803156446..8196d37ba 100644
--- a/src/modules/m_timedbans.cpp
+++ b/src/modules/m_timedbans.cpp
@@ -21,6 +21,7 @@
#include "inspircd.h"
+#include "listmode.h"
/** Holds a timed ban
*/
@@ -30,6 +31,7 @@ class TimedBan
std::string channel;
std::string mask;
time_t expire;
+ Channel* chan;
};
typedef std::vector<TimedBan> timedbans;
@@ -39,8 +41,28 @@ timedbans TimedBanList;
*/
class CommandTban : public Command
{
+ ChanModeReference banmode;
+
+ bool IsBanSet(Channel* chan, const std::string& mask)
+ {
+ ListModeBase* banlm = static_cast<ListModeBase*>(*banmode);
+ const ListModeBase::ModeList* bans = banlm->GetList(chan);
+ if (bans)
+ {
+ for (ListModeBase::ModeList::const_iterator i = bans->begin(); i != bans->end(); ++i)
+ {
+ const ListModeBase::ListItem& ban = *i;
+ if (!strcasecmp(ban.mask.c_str(), mask.c_str()))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
public:
CommandTban(Module* Creator) : Command(Creator,"TBAN", 3)
+ , banmode(Creator, "ban")
{
syntax = "<channel> <duration> <banmask>";
}
@@ -75,6 +97,12 @@ class CommandTban : public Command
if (!isextban && !InspIRCd::IsValidMask(mask))
mask.append("!*@*");
+ if (IsBanSet(channel, mask))
+ {
+ user->WriteNotice("Ban already set");
+ return CMD_FAILURE;
+ }
+
Modes::ChangeList setban;
setban.push_add(ServerInstance->Modes->FindMode('b', MODETYPE_CHANNEL), mask);
// Pass the user (instead of ServerInstance->FakeClient) to ModeHandler::Process() to
@@ -90,6 +118,7 @@ class CommandTban : public Command
T.channel = channelname;
T.mask = mask;
T.expire = expire + (IS_REMOTE(user) ? 5 : 0);
+ T.chan = channel;
TimedBanList.push_back(T);
// If halfop is loaded, send notice to halfops and above, otherwise send to ops and above
@@ -134,6 +163,22 @@ class BanWatcher : public ModeWatcher
}
};
+class ChannelMatcher
+{
+ Channel* const chan;
+
+ public:
+ ChannelMatcher(Channel* ch)
+ : chan(ch)
+ {
+ }
+
+ bool operator()(const TimedBan& tb) const
+ {
+ return (tb.chan == chan);
+ }
+};
+
class ModuleTimedBans : public Module
{
CommandTban cmd;
@@ -179,6 +224,12 @@ class ModuleTimedBans : public Module
}
}
+ void OnChannelDelete(Channel* chan)
+ {
+ // Remove all timed bans affecting the channel from internal bookkeeping
+ TimedBanList.erase(std::remove_if(TimedBanList.begin(), TimedBanList.end(), ChannelMatcher(chan)), TimedBanList.end());
+ }
+
Version GetVersion() CXX11_OVERRIDE
{
return Version("Adds timed bans", VF_COMMON | VF_VENDOR);
diff --git a/src/threadengines/threadengine_pthread.cpp b/src/threadengines/threadengine_pthread.cpp
index 6456d6df5..3249f442b 100644
--- a/src/threadengines/threadengine_pthread.cpp
+++ b/src/threadengines/threadengine_pthread.cpp
@@ -95,7 +95,7 @@ SocketThread::SocketThread()
signal.sock = NULL;
int fd = eventfd(0, EFD_NONBLOCK);
if (fd < 0)
- throw new CoreException("Could not create pipe " + std::string(strerror(errno)));
+ throw CoreException("Could not create pipe " + std::string(strerror(errno)));
signal.sock = new ThreadSignalSocket(this, fd);
}
#else
@@ -148,7 +148,7 @@ SocketThread::SocketThread()
signal.sock = NULL;
int fds[2];
if (pipe(fds))
- throw new CoreException("Could not create pipe " + std::string(strerror(errno)));
+ throw CoreException("Could not create pipe " + std::string(strerror(errno)));
signal.sock = new ThreadSignalSocket(this, fds[0], fds[1]);
}
#endif
diff --git a/src/usermanager.cpp b/src/usermanager.cpp
index 1966c9b47..4ebc3b583 100644
--- a/src/usermanager.cpp
+++ b/src/usermanager.cpp
@@ -93,7 +93,7 @@ void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs
this->clientlist[New->nick] = New;
New->registered = REG_NONE;
- New->signon = ServerInstance->Time() + ServerInstance->Config->dns_timeout;
+ New->signon = ServerInstance->Time();
New->lastping = 1;
this->AddClone(New);
@@ -254,6 +254,18 @@ void UserManager::RemoveCloneCounts(User *user)
}
}
+void UserManager::RehashCloneCounts()
+{
+ clonemap.clear();
+
+ const user_hash& hash = ServerInstance->Users.GetUsers();
+ for (user_hash::const_iterator i = hash.begin(); i != hash.end(); ++i)
+ {
+ User* u = i->second;
+ AddClone(u);
+ }
+}
+
const UserManager::CloneCounts& UserManager::GetCloneCounts(User* user) const
{
CloneMap::const_iterator it = clonemap.find(user->GetCIDRMask());
@@ -348,10 +360,15 @@ void UserManager::DoBackgroundUserStuff()
curr->FullConnect();
continue;
}
+
+ // If the user has been quit in OnCheckReady then we shouldn't
+ // quit them again for having a registration timeout.
+ if (curr->quitting)
+ continue;
break;
}
- if (curr->registered != REG_ALL && (ServerInstance->Time() > (curr->age + curr->MyClass->GetRegTimeout())))
+ if (curr->registered != REG_ALL && curr->MyClass && (ServerInstance->Time() > (curr->signon + curr->MyClass->GetRegTimeout())))
{
/*
* registration timeout -- didnt send USER/NICK/HOST