diff options
-rwxr-xr-x | configure | 6 | ||||
-rw-r--r-- | include/modules.h | 3 | ||||
-rw-r--r-- | src/command_parse.cpp | 17 | ||||
-rw-r--r-- | src/commands/cmd_list.cpp | 15 | ||||
-rw-r--r-- | src/commands/cmd_motd.cpp | 6 | ||||
-rw-r--r-- | src/commands/cmd_pass.cpp | 1 | ||||
-rw-r--r-- | src/commands/cmd_ping.cpp | 2 | ||||
-rw-r--r-- | src/commands/cmd_pong.cpp | 11 | ||||
-rw-r--r-- | src/commands/cmd_rules.cpp | 6 | ||||
-rw-r--r-- | src/commands/cmd_stats.cpp | 10 | ||||
-rw-r--r-- | src/commands/cmd_user.cpp | 1 | ||||
-rw-r--r-- | src/commands/cmd_who.cpp | 2 | ||||
-rw-r--r-- | src/configreader.cpp | 3 | ||||
-rw-r--r-- | src/modmanager_dynamic.cpp | 3 | ||||
-rw-r--r-- | src/modules/m_check.cpp | 6 | ||||
-rw-r--r-- | src/modules/m_hideoper.cpp | 6 | ||||
-rw-r--r-- | src/modules/m_operprefix.cpp | 18 | ||||
-rw-r--r-- | src/usermanager.cpp | 2 | ||||
-rw-r--r-- | src/userprocess.cpp | 2 | ||||
-rw-r--r-- | src/xline.cpp | 3 | ||||
-rw-r--r-- | win/inspircd.rc.cmake | 2 |
21 files changed, 93 insertions, 32 deletions
@@ -33,12 +33,6 @@ BEGIN { use strict; use warnings FATAL => qw(all); -use Data::Dumper; -BEGIN { - $Data::Dumper::Sortkeys = 1; - $Data::Dumper::Useqq = 1; -}; - use File::Copy (); use Socket; use Cwd; diff --git a/include/modules.h b/include/modules.h index cd0d5aad0..9857012fc 100644 --- a/include/modules.h +++ b/include/modules.h @@ -1717,7 +1717,8 @@ struct AllModuleList { break; \ } \ return TRUE; \ - } + } \ + extern "C" DllExport const char inspircd_src_version[] = VERSION " r" REVISION; #else diff --git a/src/command_parse.cpp b/src/command_parse.cpp index 1c72c7de4..0dd793592 100644 --- a/src/command_parse.cpp +++ b/src/command_parse.cpp @@ -204,12 +204,22 @@ bool CommandParser::ProcessCommand(LocalUser *user, std::string &cmd) /* find the command, check it exists */ Commandtable::iterator cm = cmdlist.find(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 */ bool do_more = true; 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 += cm != cmdlist.end() ? cm->second->Penalty * 1000 : 2000; + unsigned int penalty = (cm != cmdlist.end() ? cm->second->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; } @@ -290,11 +300,13 @@ bool CommandParser::ProcessCommand(LocalUser *user, std::string &cmd) { if (!user->IsModeSet(cm->second->flags_needed)) { + user->CommandFloodPenalty += failpenalty; user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - You do not have the required operator privileges",user->nick.c_str()); return do_more; } if (!user->HasPermission(command)) { + user->CommandFloodPenalty += failpenalty; user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Oper type %s does not have access to command %s", user->nick.c_str(), user->oper->NameStr(), command.c_str()); return do_more; @@ -303,6 +315,7 @@ bool CommandParser::ProcessCommand(LocalUser *user, std::string &cmd) if ((user->registered == REG_ALL) && (!IS_OPER(user)) && (cm->second->IsDisabled())) { /* command is disabled! */ + user->CommandFloodPenalty += failpenalty; if (ServerInstance->Config->DisabledDontExist) { user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s %s :Unknown command",user->nick.c_str(),command.c_str()); @@ -323,6 +336,7 @@ bool CommandParser::ProcessCommand(LocalUser *user, std::string &cmd) if (command_p.size() < cm->second->min_params) { + user->CommandFloodPenalty += failpenalty; user->WriteNumeric(ERR_NEEDMOREPARAMS, "%s %s :Not enough parameters.", user->nick.c_str(), command.c_str()); if ((ServerInstance->Config->SyntaxHints) && (user->registered == REG_ALL) && (cm->second->syntax.length())) user->WriteNumeric(RPL_SYNTAX, "%s :SYNTAX %s %s", user->nick.c_str(), cm->second->name.c_str(), cm->second->syntax.c_str()); @@ -330,6 +344,7 @@ bool CommandParser::ProcessCommand(LocalUser *user, std::string &cmd) } if ((user->registered != REG_ALL) && (!cm->second->WorksBeforeReg())) { + user->CommandFloodPenalty += failpenalty; user->WriteNumeric(ERR_NOTREGISTERED, "%s :You have not registered",command.c_str()); return do_more; } diff --git a/src/commands/cmd_list.cpp b/src/commands/cmd_list.cpp index 2f417bc04..2c420d1dd 100644 --- a/src/commands/cmd_list.cpp +++ b/src/commands/cmd_list.cpp @@ -82,14 +82,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 = (i->second->HasUser(user) || user->HasPrivPermission("channels/auspex")); - if (!n && i->second->IsModeSet('p')) + // If we're not in the channel and +s is set on it, we want to ignore it + if (n || !i->second->IsModeSet('s')) { - /* Channel is +p and user is outside/not privileged */ - user->WriteNumeric(322, "%s * %ld :",user->nick.c_str(), users); - } - else - { - if (n || !i->second->IsModeSet('s')) + if (!n && i->second->IsModeSet('p')) + { + /* Channel is +p and user is outside/not privileged */ + user->WriteNumeric(322, "%s * %ld :",user->nick.c_str(), users); + } + else { /* User is in the channel/privileged, channel is not +s */ user->WriteNumeric(322, "%s %s %ld :[+%s] %s",user->nick.c_str(),i->second->name.c_str(),users,i->second->ChanModes(n),i->second->topic.c_str()); diff --git a/src/commands/cmd_motd.cpp b/src/commands/cmd_motd.cpp index 869a9c353..9ed5ff188 100644 --- a/src/commands/cmd_motd.cpp +++ b/src/commands/cmd_motd.cpp @@ -51,7 +51,13 @@ class CommandMotd : public Command 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) && (!IS_OPER(user))) + localuser->CommandFloodPenalty += 2000; return CMD_SUCCESS; + } ConfigTag* tag = ServerInstance->Config->EmptyTag; if (IS_LOCAL(user)) diff --git a/src/commands/cmd_pass.cpp b/src/commands/cmd_pass.cpp index f082a4ce8..9fc758874 100644 --- a/src/commands/cmd_pass.cpp +++ b/src/commands/cmd_pass.cpp @@ -46,6 +46,7 @@ CmdResult CommandPass::HandleLocal(const std::vector<std::string>& parameters, L // Check to make sure they haven't registered -- Fix by FCS if (user->registered == REG_ALL) { + user->CommandFloodPenalty += 1000; user->WriteNumeric(ERR_ALREADYREGISTERED, "%s :You may not reregister",user->nick.c_str()); return CMD_FAILURE; } diff --git a/src/commands/cmd_ping.cpp b/src/commands/cmd_ping.cpp index 3ccadd929..dd14b52c8 100644 --- a/src/commands/cmd_ping.cpp +++ b/src/commands/cmd_ping.cpp @@ -30,7 +30,7 @@ class CommandPing : public Command public: /** Constructor for ping. */ - CommandPing ( Module* parent) : Command(parent,"PING", 1, 2) { Penalty = 0; syntax = "<servername> [:<servername>]"; } + CommandPing ( Module* parent) : Command(parent,"PING", 1, 2) { syntax = "<servername> [:<servername>]"; } /** Handle command. * @param parameters The parameters to the comamnd * @param pcnt The number of parameters passed to teh command diff --git a/src/commands/cmd_pong.cpp b/src/commands/cmd_pong.cpp index 825168de7..3b6f17f3b 100644 --- a/src/commands/cmd_pong.cpp +++ b/src/commands/cmd_pong.cpp @@ -43,8 +43,15 @@ class CommandPong : public Command CmdResult CommandPong::Handle (const std::vector<std::string>&, 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/commands/cmd_rules.cpp b/src/commands/cmd_rules.cpp index 17de9f3f2..7aacf8c31 100644 --- a/src/commands/cmd_rules.cpp +++ b/src/commands/cmd_rules.cpp @@ -49,7 +49,13 @@ class CommandRules : public Command CmdResult CommandRules::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 /RULES of a remote server + LocalUser* localuser = IS_LOCAL(user); + if ((localuser) && (!IS_OPER(user))) + localuser->CommandFloodPenalty += 2000; return CMD_SUCCESS; + } ConfigTag* tag = ServerInstance->Config->EmptyTag; if (IS_LOCAL(user)) diff --git a/src/commands/cmd_stats.cpp b/src/commands/cmd_stats.cpp index 9399b7bea..d547635ed 100644 --- a/src/commands/cmd_stats.cpp +++ b/src/commands/cmd_stats.cpp @@ -368,7 +368,7 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results) for (LocalUserList::iterator n = ServerInstance->Users->local_users.begin(); n != ServerInstance->Users->local_users.end(); n++) { LocalUser* i = *n; - results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->dhost+"] "+ConvToStr(i->eh.getSendQSize())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(ServerInstance->Time() - i->age)); + results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->dhost+"] "+ConvToStr(i->eh.getSendQSize())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(ServerInstance->Time() - i->signon)); } break; @@ -378,7 +378,7 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results) for (LocalUserList::iterator n = ServerInstance->Users->local_users.begin(); n != ServerInstance->Users->local_users.end(); n++) { LocalUser* i = *n; - results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->GetIPString()+"] "+ConvToStr(i->eh.getSendQSize())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(ServerInstance->Time() - i->age)); + results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->GetIPString()+"] "+ConvToStr(i->eh.getSendQSize())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(ServerInstance->Time() - i->signon)); } break; @@ -420,7 +420,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) && (!IS_OPER(user))) + localuser->CommandFloodPenalty += 2000; return CMD_SUCCESS; + } string_list values; char search = parameters[0][0]; DoStats(search, user, values); diff --git a/src/commands/cmd_user.cpp b/src/commands/cmd_user.cpp index 305d0847f..09e1e3319 100644 --- a/src/commands/cmd_user.cpp +++ b/src/commands/cmd_user.cpp @@ -68,6 +68,7 @@ CmdResult CommandUser::HandleLocal(const std::vector<std::string>& parameters, L } else { + user->CommandFloodPenalty += 1000; user->WriteNumeric(462, "%s :You may not reregister", user->nick.c_str()); return CMD_FAILURE; } diff --git a/src/commands/cmd_who.cpp b/src/commands/cmd_who.cpp index 2b3242211..90c26a974 100644 --- a/src/commands/cmd_who.cpp +++ b/src/commands/cmd_who.cpp @@ -141,7 +141,7 @@ bool CommandWho::whomatch(User* cuser, User* user, const char* matchtext) long seconds = ServerInstance->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/configreader.cpp b/src/configreader.cpp index b5d2fdb16..b3caf8c75 100644 --- a/src/configreader.cpp +++ b/src/configreader.cpp @@ -35,6 +35,7 @@ #endif ServerConfig::ServerConfig() + : NoSnoticeStack(false) { WhoWasGroupSize = WhoWasMaxGroups = WhoWasMaxKeep = 0; RawLog = NoUserDns = HideBans = HideSplits = UndernetMsgPrefix = false; @@ -729,7 +730,7 @@ void ServerConfig::Apply(ServerConfig* old, const std::string &useruid) if (valid) ServerInstance->WritePID(this->PID); - if (old) + if (old && valid) { // On first run, ports are bound later on FailedPortList pl; diff --git a/src/modmanager_dynamic.cpp b/src/modmanager_dynamic.cpp index 045b488b5..050f41c75 100644 --- a/src/modmanager_dynamic.cpp +++ b/src/modmanager_dynamic.cpp @@ -36,7 +36,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; + } char modfile[MAXBUF]; snprintf(modfile,MAXBUF,"%s/%s",ServerInstance->Config->ModPath.c_str(),filename.c_str()); diff --git a/src/modules/m_check.cpp b/src/modules/m_check.cpp index 96b357f20..9c5c414f1 100644 --- a/src/modules/m_check.cpp +++ b/src/modules/m_check.cpp @@ -38,8 +38,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_hideoper.cpp b/src/modules/m_hideoper.cpp index b83c7de1a..88b0c4cdf 100644 --- a/src/modules/m_hideoper.cpp +++ b/src/modules/m_hideoper.cpp @@ -82,7 +82,11 @@ class ModuleHideOper : public Module if (user->IsModeSet('H') && !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_operprefix.cpp b/src/modules/m_operprefix.cpp index 62ddb6c67..9f1f6cc5e 100644 --- a/src/modules/m_operprefix.cpp +++ b/src/modules/m_operprefix.cpp @@ -85,7 +85,7 @@ class ModuleOperPrefixMode : public Module { ServerInstance->Modules->AddService(opm); - Implementation eventlist[] = { I_OnUserPreJoin, I_OnPostOper, I_OnLoadModule, I_OnUnloadModule }; + Implementation eventlist[] = { I_OnUserPreJoin, I_OnPostOper, I_OnLoadModule, I_OnUnloadModule, I_OnPostJoin }; ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation)); /* To give clients a chance to learn about the new prefix we don't give +y to opers @@ -110,6 +110,22 @@ class ModuleOperPrefixMode : public Module return MOD_RES_PASSTHRU; } + void OnPostJoin(Membership* memb) + { + if ((!IS_LOCAL(memb->user)) || (!IS_OPER(memb->user)) || (((mw_added) && (memb->user->IsModeSet('H'))))) + return; + + if (memb->hasMode(opm.GetModeChar())) + return; + + // The user was force joined and OnUserPreJoin() did not run. Set the operprefix now. + std::vector<std::string> modechange; + modechange.push_back(memb->chan->name); + modechange.push_back("+y"); + modechange.push_back(memb->user->nick); + ServerInstance->SendGlobalMode(modechange, ServerInstance->FakeClient); + } + void SetOperPrefix(User* user, bool add) { std::vector<std::string> modechange; diff --git a/src/usermanager.cpp b/src/usermanager.cpp index 076277a33..1918b5c4c 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -72,7 +72,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; ServerInstance->Users->AddLocalClone(New); diff --git a/src/userprocess.cpp b/src/userprocess.cpp index 9cc2e7df7..0ef95e413 100644 --- a/src/userprocess.cpp +++ b/src/userprocess.cpp @@ -107,7 +107,7 @@ void InspIRCd::DoBackgroundUserStuff() break; } - if (curr->registered != REG_ALL && (Time() > (curr->age + curr->MyClass->GetRegTimeout()))) + if (curr->registered != REG_ALL && (Time() > (curr->signon + curr->MyClass->GetRegTimeout()))) { /* * registration timeout -- didnt send USER/NICK/HOST diff --git a/src/xline.cpp b/src/xline.cpp index 66d24f439..b710c5c43 100644 --- a/src/xline.cpp +++ b/src/xline.cpp @@ -598,9 +598,6 @@ void GLine::Apply(User* u) bool ELine::Matches(User *u) { - if (u->exempt) - return false; - if (InspIRCd::Match(u->ident, this->identmask, ascii_case_insensitive_map)) { if (InspIRCd::MatchCIDR(u->host, this->hostmask, ascii_case_insensitive_map) || diff --git a/win/inspircd.rc.cmake b/win/inspircd.rc.cmake index 20c7839fe..ba52ad5d2 100644 --- a/win/inspircd.rc.cmake +++ b/win/inspircd.rc.cmake @@ -22,7 +22,7 @@ BEGIN VALUE "FileDescription", "InspIRCd"
VALUE "FileVersion", "@FULL_VERSION@"
VALUE "InternalName", "InspIRCd"
- VALUE "LegalCopyright", "Copyright (c) 2014 InspIRCd Development Team"
+ VALUE "LegalCopyright", "Copyright (c) 2015 InspIRCd Development Team"
VALUE "OriginalFilename", "inspircd.exe"
VALUE "ProductName", "InspIRCd - The Inspire IRC Daemon"
VALUE "ProductVersion", "@FULL_VERSION@"
|