summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/channels.cpp2
-rw-r--r--src/commands/cmd_userhost.cpp11
-rw-r--r--src/configreader.cpp1
-rw-r--r--src/dns.cpp8
-rw-r--r--src/hashcomp.cpp4
-rw-r--r--src/modules/extra/m_ssl_gnutls.cpp9
-rw-r--r--src/modules/m_dccallow.cpp6
-rw-r--r--src/modules/m_md5.cpp2
-rw-r--r--src/modules/m_nationalchars.cpp19
-rw-r--r--src/modules/m_restrictmsg.cpp12
-rw-r--r--src/modules/m_sasl.cpp5
-rw-r--r--src/modules/m_timedbans.cpp51
-rw-r--r--src/usermanager.cpp16
-rwxr-xr-xsrc/version.sh2
-rw-r--r--src/xline.cpp3
15 files changed, 129 insertions, 22 deletions
diff --git a/src/channels.cpp b/src/channels.cpp
index 9f1eafd0c..6802e3d7d 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -412,7 +412,7 @@ Channel* Channel::ForceChan(Channel* Ptr, User* user, const std::string &privs,
if (IS_LOCAL(user))
{
- if (Ptr->topicset)
+ if (!Ptr->topic.empty())
{
user->WriteNumeric(RPL_TOPIC, "%s %s :%s", user->nick.c_str(), Ptr->name.c_str(), Ptr->topic.c_str());
user->WriteNumeric(RPL_TOPICTIME, "%s %s %s %lu", user->nick.c_str(), Ptr->name.c_str(), Ptr->setby.c_str(), (unsigned long)Ptr->topicset);
diff --git a/src/commands/cmd_userhost.cpp b/src/commands/cmd_userhost.cpp
index 79685388f..7e1efd637 100644
--- a/src/commands/cmd_userhost.cpp
+++ b/src/commands/cmd_userhost.cpp
@@ -49,6 +49,8 @@ CmdResult CommandUserhost::Handle (const std::vector<std::string>& parameters, U
unsigned int max = parameters.size();
if (max > 5)
max = 5;
+
+ bool has_privs = user->HasPrivPermission("users/auspex");
for (unsigned int i = 0; i < max; i++)
{
User *u = ServerInstance->FindNickOnly(parameters[i]);
@@ -58,7 +60,12 @@ CmdResult CommandUserhost::Handle (const std::vector<std::string>& parameters, U
retbuf = retbuf + u->nick;
if (IS_OPER(u))
- retbuf = retbuf + "*";
+ {
+ // XXX: +H hidden opers must not be shown as opers
+ ModeHandler* mh = ServerInstance->Modes->FindMode('H', MODETYPE_USER);
+ if ((u == user) || (has_privs) || (!mh) || (!u->IsModeSet('H')) || (mh->name != "hideoper"))
+ retbuf += '*';
+ }
retbuf = retbuf + "=";
@@ -69,7 +76,7 @@ CmdResult CommandUserhost::Handle (const std::vector<std::string>& parameters, U
retbuf = retbuf + u->ident + "@";
- if (user->HasPrivPermission("users/auspex"))
+ if (has_privs)
{
retbuf = retbuf + u->host;
}
diff --git a/src/configreader.cpp b/src/configreader.cpp
index b3caf8c75..bcee938d5 100644
--- a/src/configreader.cpp
+++ b/src/configreader.cpp
@@ -963,6 +963,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();
ServerInstance->Res->Rehash();
diff --git a/src/dns.cpp b/src/dns.cpp
index 75e5731fe..14305ccab 100644
--- a/src/dns.cpp
+++ b/src/dns.cpp
@@ -700,8 +700,16 @@ DNSResult DNS::GetResult()
/* Identical handling to PTR */
case DNS_QUERY_PTR:
+ {
/* Reverse lookups just come back as char* */
resultstr = std::string((const char*)data.first);
+ if (resultstr.find_first_not_of("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-") != std::string::npos)
+ {
+ std::string ro = req->orig;
+ delete req;
+ return DNSResult(this_id | ERROR_MASK, "Invalid char(s) in reply", 0, ro);
+ }
+ }
break;
default:
diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp
index 3fb7f84fb..e0347421b 100644
--- a/src/hashcomp.cpp
+++ b/src/hashcomp.cpp
@@ -140,7 +140,7 @@ void nspace::strlower(char *n)
* 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;
@@ -149,7 +149,7 @@ void nspace::strlower(char *n)
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;
diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp
index 3b67a6180..59ac1acb3 100644
--- a/src/modules/extra/m_ssl_gnutls.cpp
+++ b/src/modules/extra/m_ssl_gnutls.cpp
@@ -316,7 +316,7 @@ class ModuleSSLGnuTLS : public Module
ServerInstance->GenRandom = &randhandler;
Implementation eventlist[] = { I_On005Numeric, I_OnRehash, I_OnModuleRehash, I_OnUserConnect,
- I_OnEvent, I_OnHookIO };
+ I_OnEvent, I_OnHookIO, I_OnCheckReady };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
ServerInstance->Modules->AddService(iohook);
@@ -974,6 +974,13 @@ info_done_dealloc:
if (starttls.enabled)
capHandler.HandleEvent(ev);
}
+
+ ModResult OnCheckReady(LocalUser* user)
+ {
+ if ((user->eh.GetIOHook() == this) && (sessions[user->eh.GetFd()].status != ISSL_HANDSHAKEN))
+ return MOD_RES_DENY;
+ return MOD_RES_PASSTHRU;
+ }
};
MODULE_INIT(ModuleSSLGnuTLS)
diff --git a/src/modules/m_dccallow.cpp b/src/modules/m_dccallow.cpp
index b42d12968..829c1d337 100644
--- a/src/modules/m_dccallow.cpp
+++ b/src/modules/m_dccallow.cpp
@@ -339,6 +339,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");
@@ -346,6 +349,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_md5.cpp b/src/modules/m_md5.cpp
index 14ccf16a8..c902ee3cb 100644
--- a/src/modules/m_md5.cpp
+++ b/src/modules/m_md5.cpp
@@ -163,7 +163,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_nationalchars.cpp b/src/modules/m_nationalchars.cpp
index bf95f0f9f..bc90c9fad 100644
--- a/src/modules/m_nationalchars.cpp
+++ b/src/modules/m_nationalchars.cpp
@@ -284,11 +284,19 @@ class ModuleNationalChars : public Module
{
ConfigTag* tag = ServerInstance->Config->ConfValue("nationalchars");
charset = tag->getString("file");
- casemapping = tag->getString("casemapping", charset);
+ casemapping = tag->getString("casemapping", ServerConfig::CleanFilename(charset.c_str()));
+ if (casemapping.find(' ') != std::string::npos)
+ throw ModuleException("<nationalchars:casemapping> must not contain any spaces!");
+#if defined _WIN32
+ if (!ServerInstance->Config->StartsWithWindowsDriveLetter(charset))
+ charset.insert(0, "./locales/");
+#else
if(charset[0] != '/')
charset.insert(0, "../locales/");
+#endif
unsigned char * tables[8] = { m_additional, m_additionalMB, m_additionalUp, m_lower, m_upper, m_additionalUtf8, m_additionalUtf8range, m_additionalUtf8interval };
- loadtables(charset, tables, 8, 5);
+ if (!loadtables(charset, tables, 8, 5))
+ throw ModuleException("The locale file failed to load. Check your log file for more information.");
forcequit = tag->getBool("forcequit");
CheckForceQuit("National character set changed");
CheckRehash();
@@ -330,13 +338,13 @@ class ModuleNationalChars : public Module
}
/*so Bynets Unreal distribution stuff*/
- void loadtables(std::string filename, unsigned char ** tables, unsigned char cnt, char faillimit)
+ bool loadtables(std::string filename, unsigned char ** tables, unsigned char cnt, char faillimit)
{
std::ifstream ifs(filename.c_str());
if (ifs.fail())
{
ServerInstance->Logs->Log("m_nationalchars",DEFAULT,"loadtables() called for missing file: %s", filename.c_str());
- return;
+ return false;
}
for (unsigned char n=0; n< cnt; n++)
@@ -351,11 +359,12 @@ class ModuleNationalChars : public Module
if (loadtable(ifs, tables[n], 255) && (n < faillimit))
{
ServerInstance->Logs->Log("m_nationalchars",DEFAULT,"loadtables() called for illegal file: %s (line %d)", filename.c_str(), n+1);
- return;
+ return false;
}
}
makereverse(m_additional, m_reverse_additional, sizeof(m_additional));
+ return true;
}
unsigned char symtoi(const char *t,unsigned char base)
diff --git a/src/modules/m_restrictmsg.cpp b/src/modules/m_restrictmsg.cpp
index e814f3b16..2a9f1dc93 100644
--- a/src/modules/m_restrictmsg.cpp
+++ b/src/modules/m_restrictmsg.cpp
@@ -26,15 +26,22 @@
class ModuleRestrictMsg : public Module
{
+ private:
+ bool uline;
public:
void init()
{
- Implementation eventlist[] = { I_OnUserPreMessage, I_OnUserPreNotice };
+ OnRehash(NULL);
+ Implementation eventlist[] = { I_OnRehash, I_OnUserPreMessage, I_OnUserPreNotice };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
+ void OnRehash(User*)
+ {
+ uline = ServerInstance->Config->ConfValue("restrictmsg")->getBool("uline", false);
+ }
virtual ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
{
@@ -45,8 +52,9 @@ class ModuleRestrictMsg : public Module
// message allowed if:
// (1) the sender is opered
// (2) the recipient is opered
+ // (3) the recipient is on a ulined server
// anything else, blocked.
- if (IS_OPER(u) || IS_OPER(user))
+ if (IS_OPER(u) || IS_OPER(user) || (uline && ServerInstance->ULine(u->server)))
{
return MOD_RES_PASSTHRU;
}
diff --git a/src/modules/m_sasl.cpp b/src/modules/m_sasl.cpp
index 66efcfe4e..32c9afc79 100644
--- a/src/modules/m_sasl.cpp
+++ b/src/modules/m_sasl.cpp
@@ -99,6 +99,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")
@@ -290,7 +293,7 @@ class ModuleSASL : public Module
Version GetVersion()
{
- 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);
}
void OnEvent(Event &ev)
diff --git a/src/modules/m_timedbans.cpp b/src/modules/m_timedbans.cpp
index 497ac2569..b47327704 100644
--- a/src/modules/m_timedbans.cpp
+++ b/src/modules/m_timedbans.cpp
@@ -32,6 +32,7 @@ class TimedBan
std::string channel;
std::string mask;
time_t expire;
+ Channel* chan;
};
typedef std::vector<TimedBan> timedbans;
@@ -41,6 +42,16 @@ timedbans TimedBanList;
*/
class CommandTban : public Command
{
+ static bool IsBanSet(Channel* chan, const std::string& mask)
+ {
+ for (BanList::const_iterator i = chan->bans.begin(); i != chan->bans.end(); ++i)
+ {
+ if (!strcasecmp(i->data.c_str(), mask.c_str()))
+ return true;
+ }
+ return false;
+ }
+
public:
CommandTban(Module* Creator) : Command(Creator,"TBAN", 3)
{
@@ -85,19 +96,25 @@ class CommandTban : public Command
user->WriteServ("NOTICE "+user->nick+" :Invalid ban mask");
return CMD_FAILURE;
}
+
+ if (IsBanSet(channel, mask))
+ {
+ user->WriteServ("NOTICE %s :Ban already set", user->nick.c_str());
+ return CMD_FAILURE;
+ }
+
setban.push_back(mask);
// use CallHandler to make it so that the user sets the mode
// themselves
ServerInstance->Parser->CallHandler("MODE",setban,user);
- for (BanList::iterator i = channel->bans.begin(); i != channel->bans.end(); i++)
- if (!strcasecmp(i->data.c_str(), mask.c_str()))
- goto found;
- return CMD_FAILURE;
-found:
+ if (!IsBanSet(channel, mask))
+ return CMD_FAILURE;
+
CUList tmp;
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
@@ -114,6 +131,22 @@ found:
}
};
+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;
@@ -126,7 +159,7 @@ class ModuleTimedBans : public Module
void init()
{
ServerInstance->Modules->AddService(cmd);
- Implementation eventlist[] = { I_OnDelBan, I_OnBackgroundTimer };
+ Implementation eventlist[] = { I_OnDelBan, I_OnBackgroundTimer, I_OnChannelDelete };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
@@ -183,6 +216,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());
+ }
+
virtual Version GetVersion()
{
return Version("Adds timed bans", VF_COMMON | VF_VENDOR);
diff --git a/src/usermanager.cpp b/src/usermanager.cpp
index 1918b5c4c..76446c5b5 100644
--- a/src/usermanager.cpp
+++ b/src/usermanager.cpp
@@ -287,6 +287,22 @@ void UserManager::RemoveCloneCounts(User *user)
}
}
+void UserManager::RehashCloneCounts()
+{
+ local_clones.clear();
+ global_clones.clear();
+
+ const user_hash& hash = *ServerInstance->Users->clientlist;
+ for (user_hash::const_iterator i = hash.begin(); i != hash.end(); ++i)
+ {
+ User* u = i->second;
+
+ if (IS_LOCAL(u))
+ AddLocalClone(u);
+ AddGlobalClone(u);
+ }
+}
+
unsigned long UserManager::GlobalCloneCount(User *user)
{
clonemap::iterator x = global_clones.find(user->GetCIDRMask());
diff --git a/src/version.sh b/src/version.sh
index 7c54efc71..8686e33ae 100755
--- a/src/version.sh
+++ b/src/version.sh
@@ -1,2 +1,2 @@
#!/bin/sh
-echo "InspIRCd-2.0.18"
+echo "InspIRCd-2.0.20"
diff --git a/src/xline.cpp b/src/xline.cpp
index b710c5c43..66d24f439 100644
--- a/src/xline.cpp
+++ b/src/xline.cpp
@@ -598,6 +598,9 @@ 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) ||