summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/commands/cmd_kill.cpp16
-rw-r--r--src/commands/cmd_list.cpp3
-rw-r--r--src/commands/cmd_oper.cpp2
-rw-r--r--src/commands/cmd_stats.cpp2
-rw-r--r--src/commands/cmd_who.cpp8
-rw-r--r--src/configparser.cpp16
-rw-r--r--src/configreader.cpp3
-rw-r--r--src/dns.cpp8
-rw-r--r--src/inspircd.cpp16
-rw-r--r--src/mode.cpp20
-rw-r--r--src/modules/extra/m_ldapauth.cpp47
-rw-r--r--src/modules/extra/m_sqlite3.cpp4
-rw-r--r--src/modules/extra/m_ssl_gnutls.cpp5
-rw-r--r--src/modules/extra/m_ssl_openssl.cpp24
-rw-r--r--src/modules/m_callerid.cpp9
-rw-r--r--src/modules/m_cap.cpp23
-rw-r--r--src/modules/m_cap.h5
-rw-r--r--src/modules/m_censor.cpp2
-rw-r--r--src/modules/m_cgiirc.cpp10
-rw-r--r--src/modules/m_check.cpp2
-rw-r--r--src/modules/m_cloaking.cpp11
-rw-r--r--src/modules/m_dccallow.cpp49
-rw-r--r--src/modules/m_dnsbl.cpp9
-rw-r--r--src/modules/m_hideoper.cpp42
-rw-r--r--src/modules/m_httpd_stats.cpp2
-rw-r--r--src/modules/m_ircv3.cpp2
-rw-r--r--src/modules/m_jumpserver.cpp2
-rw-r--r--src/modules/m_namedmodes.cpp9
-rw-r--r--src/modules/m_operprefix.cpp33
-rw-r--r--src/modules/m_permchannels.cpp6
-rw-r--r--src/modules/m_sakick.cpp8
-rw-r--r--src/modules/m_sasl.cpp65
-rw-r--r--src/modules/m_securelist.cpp2
-rw-r--r--src/modules/m_spanningtree/capab.cpp5
-rw-r--r--src/modules/m_spanningtree/fjoin.cpp2
-rw-r--r--src/modules/m_spanningtree/netburst.cpp25
-rw-r--r--src/modules/m_spanningtree/postcommand.cpp2
-rw-r--r--src/modules/m_spanningtree/protocolinterface.cpp15
-rw-r--r--src/modules/m_spanningtree/treesocket.h2
-rw-r--r--src/modules/m_sslinfo.cpp6
-rw-r--r--src/socketengines/socketengine_epoll.cpp9
-rw-r--r--src/usermanager.cpp1
-rw-r--r--src/users.cpp6
-rwxr-xr-xsrc/version.sh2
44 files changed, 392 insertions, 148 deletions
diff --git a/src/commands/cmd_kill.cpp b/src/commands/cmd_kill.cpp
index 17c8a76a0..7bdf32c74 100644
--- a/src/commands/cmd_kill.cpp
+++ b/src/commands/cmd_kill.cpp
@@ -111,7 +111,8 @@ CmdResult CommandKill::Handle (const std::vector<std::string>& parameters, User
if (!IS_LOCAL(u))
{
// remote kill
- ServerInstance->SNO->WriteToSnoMask('K', "Remote kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str());
+ if (!ServerInstance->Config->HideULineKills || !ServerInstance->ULine(user->server))
+ ServerInstance->SNO->WriteToSnoMask('K', "Remote kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str());
FOREACH_MOD(I_OnRemoteKill, OnRemoteKill(user, u, killreason, killreason));
}
else
@@ -121,10 +122,13 @@ CmdResult CommandKill::Handle (const std::vector<std::string>& parameters, User
* XXX - this isn't entirely correct, servers A - B - C, oper on A, client on C. Oper kills client, A and B will get remote kill
* snotices, C will get a local kill snotice. this isn't accurate, and needs fixing at some stage. -- w00t
*/
- if (IS_LOCAL(user))
- ServerInstance->SNO->WriteGlobalSno('k',"Local Kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str());
- else
- ServerInstance->SNO->WriteToSnoMask('k',"Local Kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str());
+ if (!ServerInstance->Config->HideULineKills || !ServerInstance->ULine(user->server))
+ {
+ if (IS_LOCAL(user))
+ ServerInstance->SNO->WriteGlobalSno('k',"Local Kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str());
+ else
+ ServerInstance->SNO->WriteToSnoMask('k',"Local Kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str());
+ }
ServerInstance->Logs->Log("KILL",DEFAULT,"LOCAL KILL: %s :%s!%s!%s (%s)", u->nick.c_str(), ServerInstance->Config->ServerName.c_str(), user->dhost.c_str(), user->nick.c_str(), parameters[1].c_str());
/* Bug #419, make sure this message can only occur once even in the case of multiple KILL messages crossing the network, and change to show
* hidekillsserver as source if possible
@@ -134,7 +138,7 @@ CmdResult CommandKill::Handle (const std::vector<std::string>& parameters, User
u->Write(":%s KILL %s :%s!%s!%s (%s)", ServerInstance->Config->HideKillsServer.empty() ? user->GetFullHost().c_str() : ServerInstance->Config->HideKillsServer.c_str(),
u->nick.c_str(),
ServerInstance->Config->ServerName.c_str(),
- user->dhost.c_str(),
+ ServerInstance->Config->HideKillsServer.empty() ? user->dhost.c_str() : ServerInstance->Config->HideKillsServer.c_str(),
ServerInstance->Config->HideKillsServer.empty() ? user->nick.c_str() : ServerInstance->Config->HideKillsServer.c_str(),
parameters[1].c_str());
}
diff --git a/src/commands/cmd_list.cpp b/src/commands/cmd_list.cpp
index 2c420d1dd..eb28fb89c 100644
--- a/src/commands/cmd_list.cpp
+++ b/src/commands/cmd_list.cpp
@@ -49,8 +49,7 @@ CmdResult CommandList::Handle (const std::vector<std::string>& parameters, User
user->WriteNumeric(321, "%s Channel :Users Name",user->nick.c_str());
- /* Work around mIRC suckyness. YOU SUCK, KHALED! */
- if (parameters.size() == 1)
+ if ((parameters.size() == 1) && (!parameters[0].empty()))
{
if (parameters[0][0] == '<')
{
diff --git a/src/commands/cmd_oper.cpp b/src/commands/cmd_oper.cpp
index 1a5e7e178..95f6b98df 100644
--- a/src/commands/cmd_oper.cpp
+++ b/src/commands/cmd_oper.cpp
@@ -69,7 +69,7 @@ CmdResult CommandOper::HandleLocal(const std::vector<std::string>& parameters, L
snprintf(TheIP, MAXBUF,"%s@%s",user->ident.c_str(),user->GetIPString());
OperIndex::iterator i = ServerInstance->Config->oper_blocks.find(parameters[0]);
- if (i != ServerInstance->Config->oper_blocks.end())
+ if ((i != ServerInstance->Config->oper_blocks.end()) && (i->second->oper_block))
{
OperInfo* ifo = i->second;
ConfigTag* tag = ifo->oper_block;
diff --git a/src/commands/cmd_stats.cpp b/src/commands/cmd_stats.cpp
index d547635ed..aa5bf44cd 100644
--- a/src/commands/cmd_stats.cpp
+++ b/src/commands/cmd_stats.cpp
@@ -39,7 +39,7 @@ class CommandStats : public Command
public:
/** Constructor for stats.
*/
- CommandStats ( Module* parent) : Command(parent,"STATS",1,2) { syntax = "<stats-symbol> [<servername>]"; }
+ CommandStats ( Module* parent) : Command(parent,"STATS",1,2) { allow_empty_last_param = false; syntax = "<stats-symbol> [<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_who.cpp b/src/commands/cmd_who.cpp
index 90c26a974..8438f8cdd 100644
--- a/src/commands/cmd_who.cpp
+++ b/src/commands/cmd_who.cpp
@@ -58,13 +58,15 @@ class CommandWho : public Command
};
-static Channel* get_first_visible_channel(User *u)
+static Channel* get_first_visible_channel(User *source, User *u)
{
UCListIter i = u->chans.begin();
while (i != u->chans.end())
{
Channel* c = *i++;
- if (!c->IsModeSet('s'))
+
+ /* XXX move the +I check into m_hidechans */
+ if (source == u || !(c->IsModeSet('s') || c->IsModeSet('p') || u->IsModeSet('I')) || c->HasUser(source))
return c;
}
return NULL;
@@ -189,7 +191,7 @@ bool CommandWho::CanView(Channel* chan, User* user)
void CommandWho::SendWhoLine(User* user, const std::vector<std::string>& parms, const std::string &initial, Channel* ch, User* u, std::vector<std::string> &whoresults)
{
if (!ch)
- ch = get_first_visible_channel(u);
+ ch = get_first_visible_channel(user, u);
std::string wholine = initial + (ch ? ch->name : "*") + " " + u->ident + " " +
(opt_showrealhost ? u->host : u->dhost) + " ";
diff --git a/src/configparser.cpp b/src/configparser.cpp
index 94192a71b..409ebdd39 100644
--- a/src/configparser.cpp
+++ b/src/configparser.cpp
@@ -388,19 +388,20 @@ bool ParseStack::ParseExec(const std::string& name, int flags, const std::string
return ok;
}
-bool ConfigTag::readString(const std::string& key, std::string& value, bool allow_lf)
-{
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wundefined-bool-conversion"
+#elif defined __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wpragmas"
+# pragma GCC diagnostic ignored "-Wnonnull-compare"
#endif
+bool ConfigTag::readString(const std::string& key, std::string& value, bool allow_lf)
+{
// TODO: this is undefined behaviour but changing the API is too risky for 2.0.
if (!this)
return false;
-#ifdef __clang__
-# pragma clang diagnostic pop
-#endif
for(std::vector<KeyVal>::iterator j = items.begin(); j != items.end(); ++j)
{
if(j->first != key)
@@ -418,6 +419,11 @@ bool ConfigTag::readString(const std::string& key, std::string& value, bool allo
}
return false;
}
+#ifdef __clang__
+# pragma clang diagnostic pop
+#elif defined __GNUC__
+# pragma GCC diagnostic pop
+#endif
std::string ConfigTag::getString(const std::string& key, const std::string& def)
{
diff --git a/src/configreader.cpp b/src/configreader.cpp
index bcee938d5..301db14e8 100644
--- a/src/configreader.cpp
+++ b/src/configreader.cpp
@@ -531,6 +531,7 @@ void ServerConfig::Fill()
HideBans = security->getBool("hidebans");
HideWhoisServer = security->getString("hidewhois");
HideKillsServer = security->getString("hidekills");
+ HideULineKills = security->getBool("hideulinekills");
RestrictBannedUsers = security->getBool("restrictbannedusers", true);
GenericOper = security->getBool("genericoper");
NoUserDns = ConfValue("performance")->getBool("nouserdns");
@@ -728,7 +729,7 @@ void ServerConfig::Apply(ServerConfig* old, const std::string &useruid)
// write once here, to try it out and make sure its ok
if (valid)
- ServerInstance->WritePID(this->PID);
+ ServerInstance->WritePID(this->PID, !old);
if (old && valid)
{
diff --git a/src/dns.cpp b/src/dns.cpp
index 14305ccab..3d3bc947f 100644
--- a/src/dns.cpp
+++ b/src/dns.cpp
@@ -121,7 +121,7 @@ class CacheTimer : public Timer
DNS* dns;
public:
CacheTimer(DNS* thisdns)
- : Timer(3600, ServerInstance->Time(), true), dns(thisdns) { }
+ : Timer(5*60, ServerInstance->Time(), true), dns(thisdns) { }
virtual void Tick(time_t)
{
@@ -162,6 +162,8 @@ class RequestTimeout : public Timer
CachedQuery::CachedQuery(const std::string &res, QueryType qt, unsigned int ttl) : data(res), type(qt)
{
+ if (ttl > 5*60)
+ ttl = 5*60;
expires = ServerInstance->Time() + ttl;
}
@@ -1058,7 +1060,11 @@ void DNS::HandleEvent(EventType, int)
ServerInstance->stats->statsDnsGood++;
if (!this->GetCache(res.original.c_str()))
+ {
+ if (cache->size() >= MAX_CACHE_SIZE)
+ cache->clear();
this->cache->insert(std::make_pair(res.original.c_str(), CachedQuery(res.result, res.type, res.ttl)));
+ }
Classes[res.id]->OnLookupComplete(res.result, res.ttl, false);
delete Classes[res.id];
diff --git a/src/inspircd.cpp b/src/inspircd.cpp
index 766aeaf8e..0fa90fca5 100644
--- a/src/inspircd.cpp
+++ b/src/inspircd.cpp
@@ -294,7 +294,7 @@ bool InspIRCd::DaemonSeed()
#endif
}
-void InspIRCd::WritePID(const std::string &filename)
+void InspIRCd::WritePID(const std::string& filename, bool exitonfail)
{
#ifndef _WIN32
std::string fname(filename);
@@ -307,10 +307,12 @@ void InspIRCd::WritePID(const std::string &filename)
outfile.close();
}
else
- {
- std::cout << "Failed to write PID-file '" << fname << "', exiting." << std::endl;
- this->Logs->Log("STARTUP",DEFAULT,"Failed to write PID-file '%s', exiting.",fname.c_str());
- Exit(EXIT_STATUS_PID);
+ {
+ if (exitonfail)
+ std::cout << "Failed to write PID-file '" << fname << "', exiting." << std::endl;
+ this->Logs->Log("STARTUP",DEFAULT,"Failed to write PID-file '%s'%s",fname.c_str(), (exitonfail ? ", exiting." : ""));
+ if (exitonfail)
+ Exit(EXIT_STATUS_PID);
}
#endif
}
@@ -814,11 +816,11 @@ int InspIRCd::Run()
/* Allow a buffer of two seconds drift on this so that ntpdate etc dont harass admins */
if (TIME.tv_sec < OLDTIME - 2)
{
- SNO->WriteToSnoMask('d', "\002EH?!\002 -- Time is flowing BACKWARDS in this dimension! Clock drifted backwards %lu secs.", (unsigned long)OLDTIME-TIME.tv_sec);
+ SNO->WriteToSnoMask('d', "\002EH?!\002 -- Time is flowing BACKWARDS in this dimension! Clock drifted backwards %lu secs.", (unsigned long)(OLDTIME-TIME.tv_sec));
}
else if (TIME.tv_sec > OLDTIME + 2)
{
- SNO->WriteToSnoMask('d', "\002EH?!\002 -- Time is jumping FORWARDS! Clock skipped %lu secs.", (unsigned long)TIME.tv_sec - OLDTIME);
+ SNO->WriteToSnoMask('d', "\002EH?!\002 -- Time is jumping FORWARDS! Clock skipped %lu secs.", (unsigned long)(TIME.tv_sec - OLDTIME));
}
OLDTIME = TIME.tv_sec;
diff --git a/src/mode.cpp b/src/mode.cpp
index 89ff37fa1..0f5d45783 100644
--- a/src/mode.cpp
+++ b/src/mode.cpp
@@ -837,11 +837,19 @@ std::string ModeParser::GiveModeList(ModeMasks m)
return type1 + "," + type2 + "," + type3 + "," + type4;
}
+struct PrefixModeSorter
+{
+ bool operator()(ModeHandler* lhs, ModeHandler* rhs)
+ {
+ return lhs->GetPrefixRank() < rhs->GetPrefixRank();
+ }
+};
+
std::string ModeParser::BuildPrefixes(bool lettersAndModes)
{
std::string mletters;
std::string mprefixes;
- std::map<int,std::pair<char,char> > prefixes;
+ std::vector<ModeHandler*> prefixes;
for (unsigned char mode = 'A'; mode <= 'z'; mode++)
{
@@ -849,15 +857,15 @@ std::string ModeParser::BuildPrefixes(bool lettersAndModes)
if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix()))
{
- prefixes[modehandlers[pos]->GetPrefixRank()] = std::make_pair(
- modehandlers[pos]->GetPrefix(), modehandlers[pos]->GetModeChar());
+ prefixes.push_back(modehandlers[pos]);
}
}
- for(std::map<int,std::pair<char,char> >::reverse_iterator n = prefixes.rbegin(); n != prefixes.rend(); n++)
+ std::sort(prefixes.begin(), prefixes.end(), PrefixModeSorter());
+ for (std::vector<ModeHandler*>::const_reverse_iterator n = prefixes.rbegin(); n != prefixes.rend(); ++n)
{
- mletters = mletters + n->second.first;
- mprefixes = mprefixes + n->second.second;
+ mletters += (*n)->GetPrefix();
+ mprefixes += (*n)->GetModeChar();
}
return lettersAndModes ? "(" + mprefixes + ")" + mletters : mletters;
diff --git a/src/modules/extra/m_ldapauth.cpp b/src/modules/extra/m_ldapauth.cpp
index 6c765fb2e..405bab082 100644
--- a/src/modules/extra/m_ldapauth.cpp
+++ b/src/modules/extra/m_ldapauth.cpp
@@ -310,36 +310,25 @@ public:
}
RAIILDAPMessage msg;
- std::string what = (attribute + "=" + (useusername ? user->ident : user->nick));
- if ((res = ldap_search_ext_s(conn, base.c_str(), searchscope, what.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msg)) != LDAP_SUCCESS)
+ std::string what;
+ std::string::size_type pos = user->password.find(':');
+ // If a username is provided in PASS, use it, othewrise user their nick or ident
+ if (pos != std::string::npos)
{
- // Do a second search, based on password, if it contains a :
- // That is, PASS <user>:<password> will work.
- size_t pos = user->password.find(":");
- if (pos != std::string::npos)
- {
- // manpage says we must deallocate regardless of success or failure
- // since we're about to do another query (and reset msg), first
- // free the old one.
- msg.dealloc();
-
- std::string cutpassword = user->password.substr(0, pos);
- res = ldap_search_ext_s(conn, base.c_str(), searchscope, cutpassword.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msg);
-
- if (res == LDAP_SUCCESS)
- {
- // Trim the user: prefix, leaving just 'pass' for later password check
- user->password = user->password.substr(pos + 1);
- }
- }
+ what = (attribute + "=" + user->password.substr(0, pos));
- // It may have found based on user:pass check above.
- if (res != LDAP_SUCCESS)
- {
- if (verbose)
- ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s (LDAP search failed: %s)", user->GetFullRealHost().c_str(), ldap_err2string(res));
- return false;
- }
+ // Trim the user: prefix, leaving just 'pass' for later password check
+ user->password = user->password.substr(pos + 1);
+ }
+ else
+ {
+ what = (attribute + "=" + (useusername ? user->ident : user->nick));
+ }
+ if ((res = ldap_search_ext_s(conn, base.c_str(), searchscope, what.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msg)) != LDAP_SUCCESS)
+ {
+ if (verbose)
+ ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s (LDAP search failed: %s)", user->GetFullRealHost().c_str(), ldap_err2string(res));
+ return false;
}
if (ldap_count_entries(conn, msg) > 1)
{
@@ -404,7 +393,7 @@ public:
std::string dnPart;
while (stream.GetToken(dnPart))
{
- std::string::size_type pos = dnPart.find('=');
+ pos = dnPart.find('=');
if (pos == std::string::npos) // malformed
continue;
diff --git a/src/modules/extra/m_sqlite3.cpp b/src/modules/extra/m_sqlite3.cpp
index 1e3a65a18..47880c02c 100644
--- a/src/modules/extra/m_sqlite3.cpp
+++ b/src/modules/extra/m_sqlite3.cpp
@@ -90,8 +90,10 @@ class SQLConn : public SQLProvider
std::string host = tag->getString("hostname");
if (sqlite3_open_v2(host.c_str(), &conn, SQLITE_OPEN_READWRITE, 0) != SQLITE_OK)
{
- ServerInstance->Logs->Log("m_sqlite3",DEFAULT, "WARNING: Could not open DB with id: " + tag->getString("id"));
+ // Even in case of an error conn must be closed
+ sqlite3_close(conn);
conn = NULL;
+ ServerInstance->Logs->Log("m_sqlite3",DEFAULT, "WARNING: Could not open DB with id: " + tag->getString("id"));
}
}
diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp
index 59ac1acb3..2f4acf3f0 100644
--- a/src/modules/extra/m_ssl_gnutls.cpp
+++ b/src/modules/extra/m_ssl_gnutls.cpp
@@ -28,7 +28,7 @@
#include "m_cap.h"
#ifdef _WIN32
-# pragma comment(lib, "libgnutls-28.lib")
+# pragma comment(lib, "libgnutls-30.lib")
#endif
/* $ModDesc: Provides SSL support for clients */
@@ -703,6 +703,9 @@ class ModuleSSLGnuTLS : public Module
if (ret > 0)
{
recvq.append(buffer, ret);
+ // Schedule a read if there is still data in the GnuTLS buffer
+ if (gnutls_record_check_pending(session->sess) > 0)
+ ServerInstance->SE->ChangeEventMask(user, FD_ADD_TRIAL_READ);
return 1;
}
else if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp
index b21091d3f..aee7a5e34 100644
--- a/src/modules/extra/m_ssl_openssl.cpp
+++ b/src/modules/extra/m_ssl_openssl.cpp
@@ -405,12 +405,19 @@ class ModuleSSLOpenSSL : public Module
#endif
ERR_clear_error();
- if ((SSL_CTX_set_tmp_dh(ctx, ret) < 0) || (SSL_CTX_set_tmp_dh(clictx, ret) < 0))
+ if (ret)
{
- ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so: Couldn't set DH parameters %s. SSL errors follow:", dhfile.c_str());
- ERR_print_errors_cb(error_callback, this);
+ if ((SSL_CTX_set_tmp_dh(ctx, ret) < 0) || (SSL_CTX_set_tmp_dh(clictx, ret) < 0))
+ {
+ ServerInstance->Logs->Log("m_ssl_openssl", DEFAULT, "m_ssl_openssl.so: Couldn't set DH parameters %s. SSL errors follow:", dhfile.c_str());
+ ERR_print_errors_cb(error_callback, this);
+ }
+ DH_free(ret);
+ }
+ else
+ {
+ ServerInstance->Logs->Log("m_ssl_openssl", DEFAULT, "m_ssl_openssl.so: Couldn't set DH parameters %s.", dhfile.c_str());
}
- DH_free(ret);
}
#ifndef _WIN32
@@ -591,8 +598,15 @@ class ModuleSSLOpenSSL : public Module
if (ret > 0)
{
recvq.append(buffer, ret);
+
+ int mask = 0;
+ // Schedule a read if there is still data in the OpenSSL buffer
+ if (SSL_pending(session->sess) > 0)
+ mask |= FD_ADD_TRIAL_READ;
if (session->data_to_write)
- ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_SINGLE_WRITE);
+ mask |= FD_WANT_POLL_READ | FD_WANT_SINGLE_WRITE;
+ if (mask != 0)
+ ServerInstance->SE->ChangeEventMask(user, mask);
return 1;
}
else if (ret == 0)
diff --git a/src/modules/m_callerid.cpp b/src/modules/m_callerid.cpp
index 4147f0b16..2df6d7af0 100644
--- a/src/modules/m_callerid.cpp
+++ b/src/modules/m_callerid.cpp
@@ -68,7 +68,12 @@ struct CallerIDExtInfo : public ExtensionItem
void unserialize(SerializeFormat format, Extensible* container, const std::string& value)
{
+ void* old = get_raw(container);
+ if (old)
+ this->free(old);
callerid_data* dat = new callerid_data;
+ set_raw(container, dat);
+
irc::commasepstream s(value);
std::string tok;
if (s.GetToken(tok))
@@ -89,10 +94,6 @@ struct CallerIDExtInfo : public ExtensionItem
}
}
}
-
- void* old = set_raw(container, dat);
- if (old)
- this->free(old);
}
callerid_data* get(User* user, bool create)
diff --git a/src/modules/m_cap.cpp b/src/modules/m_cap.cpp
index e9f4dae90..6b4387fdd 100644
--- a/src/modules/m_cap.cpp
+++ b/src/modules/m_cap.cpp
@@ -66,23 +66,28 @@ class CommandCAP : public Command
while (cap_stream.GetToken(cap_))
{
- Data.wanted.push_back(cap_);
+ // Whilst the handling of extraneous spaces is not currently defined in the CAP specification
+ // every single other implementation ignores extraneous spaces. Lets copy them for
+ // compatibility purposes.
+ trim(cap_);
+ if (!cap_.empty())
+ Data.wanted.push_back(cap_);
}
reghold.set(user, 1);
Data.Send();
- if (Data.ack.size() > 0)
+ if (Data.wanted.empty())
{
- std::string AckResult = irc::stringjoiner(" ", Data.ack, 0, Data.ack.size() - 1).GetJoined();
- user->WriteServ("CAP %s ACK :%s", user->nick.c_str(), AckResult.c_str());
+ user->WriteServ("CAP %s ACK :%s", user->nick.c_str(), parameters[1].c_str());
+ return CMD_SUCCESS;
}
- if (Data.wanted.size() > 0)
- {
- std::string NakResult = irc::stringjoiner(" ", Data.wanted, 0, Data.wanted.size() - 1).GetJoined();
- user->WriteServ("CAP %s NAK :%s", user->nick.c_str(), NakResult.c_str());
- }
+ // HACK: reset all of the caps which were enabled on this user because a cap request is atomic.
+ for (std::vector<std::pair<GenericCap*, int> >::iterator iter = Data.changed.begin(); iter != Data.changed.end(); ++iter)
+ iter->first->ext.set(user, iter->second);
+
+ user->WriteServ("CAP %s NAK :%s", user->nick.c_str(), parameters[1].c_str());
}
else if (subcommand == "END")
{
diff --git a/src/modules/m_cap.h b/src/modules/m_cap.h
index 409671f48..23cf8cf69 100644
--- a/src/modules/m_cap.h
+++ b/src/modules/m_cap.h
@@ -21,6 +21,8 @@
#ifndef M_CAP_H
#define M_CAP_H
+class GenericCap;
+
class CapEvent : public Event
{
public:
@@ -35,6 +37,7 @@ class CapEvent : public Event
CapEventType type;
std::vector<std::string> wanted;
std::vector<std::string> ack;
+ std::vector<std::pair<GenericCap*, int> > changed; // HACK: clean this up before 2.2
User* user;
CapEvent(Module* sender, User* u, CapEventType capevtype) : Event(sender, "cap_request"), type(capevtype), user(u) {}
};
@@ -67,7 +70,7 @@ class GenericCap
// we can handle this, so ACK it, and remove it from the wanted list
data->ack.push_back(*it);
data->wanted.erase(it);
- ext.set(data->user, enablecap ? 1 : 0);
+ data->changed.push_back(std::make_pair(this, ext.set(data->user, enablecap ? 1 : 0)));
break;
}
}
diff --git a/src/modules/m_censor.cpp b/src/modules/m_censor.cpp
index 50c8e22a7..65b965df2 100644
--- a/src/modules/m_censor.cpp
+++ b/src/modules/m_censor.cpp
@@ -101,7 +101,7 @@ class ModuleCensor : public Module
{
if (index->second.empty())
{
- user->WriteNumeric(ERR_WORDFILTERED, "%s %s %s :Your message contained a censored word, and was blocked", user->nick.c_str(), ((Channel*)dest)->name.c_str(), index->first.c_str());
+ user->WriteNumeric(ERR_WORDFILTERED, "%s %s %s :Your message contained a censored word, and was blocked", user->nick.c_str(), ((target_type == TYPE_CHANNEL) ? ((Channel*)dest)->name.c_str() : ((User*)dest)->nick.c_str()), index->first.c_str());
return MOD_RES_DENY;
}
diff --git a/src/modules/m_cgiirc.cpp b/src/modules/m_cgiirc.cpp
index cce2e7855..09f6a4659 100644
--- a/src/modules/m_cgiirc.cpp
+++ b/src/modules/m_cgiirc.cpp
@@ -73,6 +73,7 @@ class CommandWebirc : public Command
realhost("cgiirc_realhost", Creator), realip("cgiirc_realip", Creator),
webirc_hostname("cgiirc_webirc_hostname", Creator), webirc_ip("cgiirc_webirc_ip", Creator)
{
+ allow_empty_last_param = false;
works_before_reg = true;
this->syntax = "password client hostname ip";
}
@@ -81,6 +82,14 @@ class CommandWebirc : public Command
if(user->registered == REG_ALL)
return CMD_FAILURE;
+ irc::sockets::sockaddrs ipaddr;
+ if (!irc::sockets::aptosa(parameters[3], 0, ipaddr))
+ {
+ IS_LOCAL(user)->CommandFloodPenalty += 5000;
+ ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s tried to use WEBIRC but gave an invalid IP address.", user->GetFullRealHost().c_str());
+ return CMD_FAILURE;
+ }
+
for(CGIHostlist::iterator iter = Hosts.begin(); iter != Hosts.end(); iter++)
{
if(InspIRCd::Match(user->host, iter->hostmask, ascii_case_insensitive_map) || InspIRCd::MatchCIDR(user->GetIPString(), iter->hostmask, ascii_case_insensitive_map))
@@ -108,6 +117,7 @@ class CommandWebirc : public Command
}
}
+ IS_LOCAL(user)->CommandFloodPenalty += 5000;
ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s tried to use WEBIRC, but didn't match any configured webirc blocks.", user->GetFullRealHost().c_str());
return CMD_FAILURE;
}
diff --git a/src/modules/m_check.cpp b/src/modules/m_check.cpp
index 9c5c414f1..5063368b8 100644
--- a/src/modules/m_check.cpp
+++ b/src/modules/m_check.cpp
@@ -174,7 +174,7 @@ class CommandCheck : public Command
/* /check on a channel */
user->SendText(checkstr + " timestamp " + timestring(targchan->age));
- if (targchan->topic[0] != 0)
+ if (!targchan->topic.empty())
{
/* there is a topic, assume topic related information exists */
user->SendText(checkstr + " topic " + targchan->topic);
diff --git a/src/modules/m_cloaking.cpp b/src/modules/m_cloaking.cpp
index 105d68833..f4cfdb54f 100644
--- a/src/modules/m_cloaking.cpp
+++ b/src/modules/m_cloaking.cpp
@@ -96,6 +96,10 @@ class CloakUser : public ModeHandler
if (adding)
{
+ // assume this is more correct
+ if (user->registered != REG_ALL && user->host != user->dhost)
+ return MODEACTION_DENY;
+
std::string* cloak = ext.get(user);
if (!cloak)
@@ -493,11 +497,14 @@ class ModuleCloaking : public Module
{
std::string chost;
+ irc::sockets::sockaddrs hostip;
+ bool host_is_ip = irc::sockets::aptosa(host, ip.port(), hostip) && hostip == ip;
+
switch (mode)
{
case MODE_COMPAT_HOST:
{
- if (ipstr != host)
+ if (!host_is_ip)
{
std::string tail = LastTwoDomainParts(host);
@@ -520,7 +527,7 @@ class ModuleCloaking : public Module
break;
case MODE_HALF_CLOAK:
{
- if (ipstr != host)
+ if (!host_is_ip)
chost = prefix + SegmentCloak(host, 1, 6) + LastTwoDomainParts(host);
if (chost.empty() || chost.length() > 50)
chost = SegmentIP(ip, false);
diff --git a/src/modules/m_dccallow.cpp b/src/modules/m_dccallow.cpp
index 829c1d337..05fff8937 100644
--- a/src/modules/m_dccallow.cpp
+++ b/src/modules/m_dccallow.cpp
@@ -58,6 +58,7 @@ SimpleExtItem<dccallowlist>* ext;
class CommandDccallow : public Command
{
public:
+ unsigned int maxentries;
CommandDccallow(Module* parent) : Command(parent, "DCCALLOW", 0)
{
syntax = "[(+|-)<nick> [<time>]]|[LIST|HELP]";
@@ -140,6 +141,12 @@ class CommandDccallow : public Command
ul.push_back(user);
}
+ if (dl->size() >= maxentries)
+ {
+ user->WriteNumeric(996, "%s %s :Too many nicks on DCCALLOW list", user->nick.c_str(), user->nick.c_str());
+ return CMD_FAILURE;
+ }
+
for (dccallowlist::const_iterator k = dl->begin(); k != dl->end(); ++k)
{
if (k->nickname == target->nick)
@@ -264,7 +271,7 @@ class ModuleDCCAllow : public Module
ext = new SimpleExtItem<dccallowlist>("dccallow", this);
ServerInstance->Modules->AddService(*ext);
ServerInstance->Modules->AddService(cmd);
- ReadFileConf();
+ OnRehash(NULL);
Implementation eventlist[] = { I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserQuit, I_OnUserPostNick, I_OnRehash };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
@@ -272,6 +279,8 @@ class ModuleDCCAllow : public Module
virtual void OnRehash(User* user)
{
ReadFileConf();
+ ConfigTag* tag = ServerInstance->Config->ConfValue("dccallow");
+ cmd.maxentries = tag->getInt("maxentries", 20);
}
virtual void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message)
@@ -331,29 +340,43 @@ class ModuleDCCAllow : public Module
return MOD_RES_PASSTHRU;
}
- // tokenize
- std::stringstream ss(text);
- std::string buf;
- std::vector<std::string> tokens;
-
- while (ss >> buf)
- tokens.push_back(buf);
-
- if (tokens.size() < 2)
+ std::string buf = text.substr(5);
+ size_t s = buf.find(' ');
+ if (s == std::string::npos)
return MOD_RES_PASSTHRU;
- irc::string type = tokens[1].c_str();
+ irc::string type = assign(buf.substr(0, s));
ConfigTag* conftag = ServerInstance->Config->ConfValue("dccallow");
bool blockchat = conftag->getBool("blockchat");
if (type == "SEND")
{
- if (tokens.size() < 3)
+ size_t first;
+
+ buf = buf.substr(s + 1);
+
+ if (!buf.empty() && buf[0] == '"')
+ {
+ s = buf.find('"', 1);
+
+ if (s == std::string::npos || s <= 1)
+ return MOD_RES_PASSTHRU;
+
+ --s;
+ first = 1;
+ }
+ else
+ {
+ s = buf.find(' ');
+ first = 0;
+ }
+
+ if (s == std::string::npos)
return MOD_RES_PASSTHRU;
std::string defaultaction = conftag->getString("action");
- std::string filename = tokens[2];
+ std::string filename = buf.substr(first, s);
bool found = false;
for (unsigned int i = 0; i < bfl.size(); i++)
diff --git a/src/modules/m_dnsbl.cpp b/src/modules/m_dnsbl.cpp
index d4101686a..3dea080ce 100644
--- a/src/modules/m_dnsbl.cpp
+++ b/src/modules/m_dnsbl.cpp
@@ -70,8 +70,8 @@ class DNSBLResolver : public Resolver
int i = countExt.get(them);
if (i)
countExt.set(them, i - 1);
- // Now we calculate the bitmask: 256*(256*(256*a+b)+c)+d
- if(result.length())
+ // All replies should be in 127.0.0.0/8
+ if (result.compare(0, 4, "127.") == 0)
{
unsigned int bitmask = 0, record = 0;
bool match = false;
@@ -82,6 +82,7 @@ class DNSBLResolver : public Resolver
switch (ConfEntry->type)
{
case DNSBLConfEntry::A_BITMASK:
+ // Now we calculate the bitmask: 256*(256*(256*a+b)+c)+d
bitmask = resultip.s_addr >> 24; /* Last octet (network byte order) */
bitmask &= ConfEntry->bitmask;
match = (bitmask != 0);
@@ -196,7 +197,11 @@ class DNSBLResolver : public Resolver
ConfEntry->stats_misses++;
}
else
+ {
+ if (!result.empty())
+ ServerInstance->SNO->WriteGlobalSno('a', "DNSBL: %s returned address outside of acceptable subnet 127.0.0.0/8: %s", ConfEntry->domain.c_str(), result.c_str());
ConfEntry->stats_misses++;
+ }
}
}
diff --git a/src/modules/m_hideoper.cpp b/src/modules/m_hideoper.cpp
index 88b0c4cdf..32999d9f0 100644
--- a/src/modules/m_hideoper.cpp
+++ b/src/modules/m_hideoper.cpp
@@ -28,25 +28,43 @@
class HideOper : public SimpleUserModeHandler
{
public:
+ size_t opercount;
+
HideOper(Module* Creator) : SimpleUserModeHandler(Creator, "hideoper", 'H')
+ , opercount(0)
{
oper = true;
}
+
+ ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& parameter, bool adding)
+ {
+ if (SimpleUserModeHandler::OnModeChange(source, dest, channel, parameter, adding) == MODEACTION_DENY)
+ return MODEACTION_DENY;
+
+ if (adding)
+ opercount++;
+ else
+ opercount--;
+
+ return MODEACTION_ALLOW;
+ }
};
class ModuleHideOper : public Module
{
HideOper hm;
+ bool active;
public:
ModuleHideOper()
: hm(this)
+ , active(false)
{
}
void init()
{
ServerInstance->Modules->AddService(hm);
- Implementation eventlist[] = { I_OnWhoisLine, I_OnSendWhoLine, I_OnStats };
+ Implementation eventlist[] = { I_OnWhoisLine, I_OnSendWhoLine, I_OnStats, I_OnNumeric, I_OnUserQuit };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
@@ -60,6 +78,28 @@ class ModuleHideOper : public Module
return Version("Provides support for hiding oper status with user mode +H", VF_VENDOR);
}
+ void OnUserQuit(User* user, const std::string&, const std::string&)
+ {
+ if (user->IsModeSet('H'))
+ hm.opercount--;
+ }
+
+ ModResult OnNumeric(User* user, unsigned int numeric, const std::string& text)
+ {
+ if (numeric != 252 || active || user->HasPrivPermission("users/auspex"))
+ return MOD_RES_PASSTHRU;
+
+ // If there are no visible operators then we shouldn't send the numeric.
+ size_t opercount = ServerInstance->Users->all_opers.size() - hm.opercount;
+ if (opercount)
+ {
+ active = true;
+ user->WriteNumeric(252, "%s %lu :operator(s) online", user->nick.c_str(), static_cast<unsigned long>(opercount));
+ active = false;
+ }
+ return MOD_RES_DENY;
+ }
+
ModResult OnWhoisLine(User* user, User* dest, int &numeric, std::string &text)
{
/* Dont display numeric 313 (RPL_WHOISOPER) if they have +H set and the
diff --git a/src/modules/m_httpd_stats.cpp b/src/modules/m_httpd_stats.cpp
index 2fc7ca7de..e17bf514f 100644
--- a/src/modules/m_httpd_stats.cpp
+++ b/src/modules/m_httpd_stats.cpp
@@ -213,7 +213,7 @@ class ModuleHttpStats : public Module
data << "<server>";
data << "<servername>" << b->servername << "</servername>";
data << "<parentname>" << b->parentname << "</parentname>";
- data << "<gecos>" << b->gecos << "</gecos>";
+ data << "<gecos>" << Sanitize(b->gecos) << "</gecos>";
data << "<usercount>" << b->usercount << "</usercount>";
// This is currently not implemented, so, commented out.
// data << "<opercount>" << b->opercount << "</opercount>";
diff --git a/src/modules/m_ircv3.cpp b/src/modules/m_ircv3.cpp
index da42d823d..b7dd0e81b 100644
--- a/src/modules/m_ircv3.cpp
+++ b/src/modules/m_ircv3.cpp
@@ -222,7 +222,7 @@ class ModuleIRCv3 : public Module
{
// Send the away notify line if the current member is local, has the away-notify cap and isn't excepted
User* member = IS_LOCAL(it->first);
- if ((member) && (cap_awaynotify.ext.get(member)) && (last_excepts.find(member) == last_excepts.end()))
+ if ((member) && (cap_awaynotify.ext.get(member)) && (last_excepts.find(member) == last_excepts.end()) && (it->second != memb))
{
member->Write(line);
}
diff --git a/src/modules/m_jumpserver.cpp b/src/modules/m_jumpserver.cpp
index dce8f0bd5..44c6fc0d9 100644
--- a/src/modules/m_jumpserver.cpp
+++ b/src/modules/m_jumpserver.cpp
@@ -161,7 +161,7 @@ class ModuleJumpServer : public Module
user->WriteNumeric(10, "%s %s %d :Please use this Server/Port instead",
user->nick.c_str(), js.redirect_to.c_str(), js.port);
ServerInstance->Users->QuitUser(user, js.reason);
- return MOD_RES_PASSTHRU;
+ return MOD_RES_DENY;
}
return MOD_RES_PASSTHRU;
}
diff --git a/src/modules/m_namedmodes.cpp b/src/modules/m_namedmodes.cpp
index 4db1f70b9..46710946b 100644
--- a/src/modules/m_namedmodes.cpp
+++ b/src/modules/m_namedmodes.cpp
@@ -33,7 +33,12 @@ static void DisplayList(User* user, Channel* channel)
continue;
items << " +" << mh->name;
if (mh->GetNumParams(true))
- items << " " << channel->GetModeParameter(letter);
+ {
+ if ((letter == 'k') && (!channel->HasUser(user)) && (!user->HasPrivPermission("channels/auspex")))
+ items << " <key>";
+ else
+ items << " " << channel->GetModeParameter(letter);
+ }
}
char pfx[MAXBUF];
snprintf(pfx, MAXBUF, ":%s 961 %s %s", ServerInstance->Config->ServerName.c_str(), user->nick.c_str(), channel->name.c_str());
@@ -65,6 +70,8 @@ class CommandProp : public Command
while (i < parameters.size())
{
std::string prop = parameters[i++];
+ if (prop.empty())
+ continue;
bool plus = prop[0] != '-';
if (prop[0] == '+' || prop[0] == '-')
prop.erase(prop.begin());
diff --git a/src/modules/m_operprefix.cpp b/src/modules/m_operprefix.cpp
index 9f1f6cc5e..7d5e6d118 100644
--- a/src/modules/m_operprefix.cpp
+++ b/src/modules/m_operprefix.cpp
@@ -58,6 +58,39 @@ class OperPrefixMode : public ModeHandler
}
bool NeedsOper() { return true; }
+
+ void RemoveMode(Channel* chan, irc::modestacker* stack)
+ {
+ irc::modestacker modestack(false);
+ const UserMembList* users = chan->GetUsers();
+ for (UserMembCIter i = users->begin(); i != users->end(); ++i)
+ {
+ if (i->second->hasMode(mode))
+ {
+ if (stack)
+ stack->Push(this->GetModeChar(), i->first->nick);
+ else
+ modestack.Push(this->GetModeChar(), i->first->nick);
+ }
+ }
+
+ if (stack)
+ return;
+
+ std::deque<std::string> stackresult;
+ std::vector<std::string> mode_junk;
+ mode_junk.push_back(chan->name);
+ while (modestack.GetStackedLine(stackresult))
+ {
+ mode_junk.insert(mode_junk.end(), stackresult.begin(), stackresult.end());
+ ServerInstance->SendMode(mode_junk, ServerInstance->FakeClient);
+ mode_junk.erase(mode_junk.begin() + 1, mode_junk.end());
+ }
+ }
+
+ void RemoveMode(User* user, irc::modestacker* stack)
+ {
+ }
};
class ModuleOperPrefixMode;
diff --git a/src/modules/m_permchannels.cpp b/src/modules/m_permchannels.cpp
index e86b3cbf6..74a798356 100644
--- a/src/modules/m_permchannels.cpp
+++ b/src/modules/m_permchannels.cpp
@@ -298,6 +298,12 @@ public:
ServerInstance->Logs->Log("m_permchannels", DEBUG, "Added %s with topic %s", channel.c_str(), topic.c_str());
+ if (modes.find('P') == std::string::npos)
+ {
+ ServerInstance->Logs->Log("m_permchannels", DEFAULT, "%s (%s) does not have +P set in <permchannels:modes>; it will be deleted when empty!",
+ c->name.c_str(), tag->getTagLocation().c_str());
+ }
+
if (modes.empty())
continue;
diff --git a/src/modules/m_sakick.cpp b/src/modules/m_sakick.cpp
index 7dfcd8904..afca49e25 100644
--- a/src/modules/m_sakick.cpp
+++ b/src/modules/m_sakick.cpp
@@ -63,14 +63,6 @@ class CommandSakick : public Command
if (IS_LOCAL(dest))
{
channel->KickUser(ServerInstance->FakeClient, dest, reason);
-
- Channel *n = ServerInstance->FindChan(parameters[1]);
- if (n && n->HasUser(dest))
- {
- /* Sort-of-bug: If the command was issued remotely, this message won't be sent */
- user->WriteServ("NOTICE %s :*** Unable to kick %s from %s", user->nick.c_str(), dest->nick.c_str(), parameters[0].c_str());
- return CMD_FAILURE;
- }
}
if (IS_LOCAL(user))
diff --git a/src/modules/m_sasl.cpp b/src/modules/m_sasl.cpp
index 32c9afc79..5afab9502 100644
--- a/src/modules/m_sasl.cpp
+++ b/src/modules/m_sasl.cpp
@@ -51,10 +51,63 @@ class SaslAuthenticator
SaslResult result;
bool state_announced;
+ /* taken from m_services_account */
+ static bool ReadCGIIRCExt(const char* extname, User* user, std::string& out)
+ {
+ ExtensionItem* wiext = ServerInstance->Extensions.GetItem(extname);
+ if (!wiext)
+ return false;
+
+ if (wiext->creator->ModuleSourceFile != "m_cgiirc.so")
+ return false;
+
+ StringExtItem* stringext = static_cast<StringExtItem*>(wiext);
+ std::string* addr = stringext->get(user);
+ if (!addr)
+ return false;
+
+ out = *addr;
+ return true;
+ }
+
+
+ void SendHostIP()
+ {
+ std::string host, ip;
+
+ if (!ReadCGIIRCExt("cgiirc_webirc_hostname", user, host))
+ {
+ host = user->host;
+ }
+ if (!ReadCGIIRCExt("cgiirc_webirc_ip", user, ip))
+ {
+ ip = user->GetIPString();
+ }
+ else
+ {
+ /* IP addresses starting with a : on irc are a Bad Thing (tm) */
+ if (ip.c_str()[0] == ':')
+ ip.insert(ip.begin(),1,'0');
+ }
+
+ parameterlist params;
+ params.push_back(sasl_target);
+ params.push_back("SASL");
+ params.push_back(user->uuid);
+ params.push_back("*");
+ params.push_back("H");
+ params.push_back(host);
+ params.push_back(ip);
+
+ SendSASL(params);
+ }
+
public:
SaslAuthenticator(User* user_, const std::string& method)
: user(user_), state(SASL_INIT), state_announced(false)
{
+ SendHostIP();
+
parameterlist params;
params.push_back(sasl_target);
params.push_back("SASL");
@@ -147,7 +200,7 @@ class SaslAuthenticator
SendSASL(params);
- if (parameters[0][0] == '*')
+ if (parameters[0].c_str()[0] == '*')
{
this->Abort();
return false;
@@ -189,6 +242,7 @@ class CommandAuthenticate : public Command
: Command(Creator, "AUTHENTICATE", 1), authExt(ext), cap(Cap)
{
works_before_reg = true;
+ allow_empty_last_param = false;
}
CmdResult Handle (const std::vector<std::string>& parameters, User *user)
@@ -199,6 +253,9 @@ class CommandAuthenticate : public Command
if (!cap.ext.get(user))
return CMD_FAILURE;
+ if (parameters[0].find(' ') != std::string::npos || parameters[0][0] == ':')
+ return CMD_FAILURE;
+
SaslAuthenticator *sasl = authExt.get(user);
if (!sasl)
authExt.set(user, new SaslAuthenticator(user, parameters[0]));
@@ -264,7 +321,7 @@ class ModuleSASL : public Module
void init()
{
OnRehash(NULL);
- Implementation eventlist[] = { I_OnEvent, I_OnUserRegister, I_OnRehash };
+ Implementation eventlist[] = { I_OnEvent, I_OnUserConnect, I_OnRehash };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
ServiceProvider* providelist[] = { &auth, &sasl, &authExt };
@@ -279,7 +336,7 @@ class ModuleSASL : public Module
sasl_target = ServerInstance->Config->ConfValue("sasl")->getString("target", "*");
}
- ModResult OnUserRegister(LocalUser *user)
+ void OnUserConnect(LocalUser *user)
{
SaslAuthenticator *sasl_ = authExt.get(user);
if (sasl_)
@@ -287,8 +344,6 @@ class ModuleSASL : public Module
sasl_->Abort();
authExt.unset(user);
}
-
- return MOD_RES_PASSTHRU;
}
Version GetVersion()
diff --git a/src/modules/m_securelist.cpp b/src/modules/m_securelist.cpp
index 6013d1fd7..5d11d27f7 100644
--- a/src/modules/m_securelist.cpp
+++ b/src/modules/m_securelist.cpp
@@ -76,7 +76,7 @@ class ModuleSecureList : public Module
/* Not exempt, BOOK EM DANNO! */
user->WriteServ("NOTICE %s :*** You cannot list within the first %lu seconds of connecting. Please try again later.",user->nick.c_str(), (unsigned long) WaitTime);
- /* Some crap clients (read: mIRC, various java chat applets) muck up if they don't
+ /* Some clients (e.g. mIRC, various java chat applets) muck up if they don't
* receive these numerics whenever they send LIST, so give them an empty LIST to mull over.
*/
user->WriteNumeric(321, "%s Channel :Users Name",user->nick.c_str());
diff --git a/src/modules/m_spanningtree/capab.cpp b/src/modules/m_spanningtree/capab.cpp
index 7b6435898..0ab815fef 100644
--- a/src/modules/m_spanningtree/capab.cpp
+++ b/src/modules/m_spanningtree/capab.cpp
@@ -27,6 +27,7 @@
#include "utils.h"
#include "link.h"
#include "main.h"
+#include "../hash.h"
std::string TreeSocket::MyModules(int filter)
{
@@ -134,7 +135,7 @@ void TreeSocket::SendCapabilities(int phase)
std::string extra;
/* Do we have sha256 available? If so, we send a challenge */
- if (Utils->ChallengeResponse && (ServerInstance->Modules->Find("m_sha256.so")))
+ if (Utils->ChallengeResponse && (ServerInstance->Modules->FindDataService<HashProvider>("hash/sha256")))
{
SetOurChallenge(ServerInstance->GenRandomStr(20));
extra = " CHALLENGE=" + this->GetOurChallenge();
@@ -320,7 +321,7 @@ bool TreeSocket::Capab(const parameterlist &params)
/* Challenge response, store their challenge for our password */
std::map<std::string,std::string>::iterator n = this->capab->CapKeys.find("CHALLENGE");
- if (Utils->ChallengeResponse && (n != this->capab->CapKeys.end()) && (ServerInstance->Modules->Find("m_sha256.so")))
+ if (Utils->ChallengeResponse && (n != this->capab->CapKeys.end()) && (ServerInstance->Modules->FindDataService<HashProvider>("hash/sha256")))
{
/* Challenge-response is on now */
this->SetTheirChallenge(n->second);
diff --git a/src/modules/m_spanningtree/fjoin.cpp b/src/modules/m_spanningtree/fjoin.cpp
index 47b394522..4ec6e1dbb 100644
--- a/src/modules/m_spanningtree/fjoin.cpp
+++ b/src/modules/m_spanningtree/fjoin.cpp
@@ -201,7 +201,7 @@ CmdResult CommandFJoin::Handle(const std::vector<std::string>& params, User *src
}
else
{
- ServerInstance->Logs->Log("m_spanningtree",SPARSE, "Ignored nonexistant user %s in fjoin to %s (probably quit?)", usr, channel.c_str());
+ ServerInstance->Logs->Log("m_spanningtree",SPARSE, "Ignored nonexistent user %s in fjoin to %s (probably quit?)", usr, channel.c_str());
continue;
}
}
diff --git a/src/modules/m_spanningtree/netburst.cpp b/src/modules/m_spanningtree/netburst.cpp
index d508c092d..3bce90eda 100644
--- a/src/modules/m_spanningtree/netburst.cpp
+++ b/src/modules/m_spanningtree/netburst.cpp
@@ -140,25 +140,28 @@ void TreeSocket::SendFJoins(Channel* c)
buffer.append(list).append("\r\n");
}
- int linesize = 1;
+ unsigned int linesize = 1;
for (BanList::iterator b = c->bans.begin(); b != c->bans.end(); b++)
{
- int size = b->data.length() + 2;
- int currsize = linesize + size;
- if (currsize <= 350)
- {
- modes.append("b");
- params.append(" ").append(b->data);
- linesize += size;
- }
- if ((modes.length() >= ServerInstance->Config->Limits.MaxModes) || (currsize > 350))
+ unsigned int size = b->data.length() + 2; // "b" and " "
+ unsigned int nextsize = linesize + size;
+
+ if ((modes.length() >= ServerInstance->Config->Limits.MaxModes) || (nextsize > FMODE_MAX_LENGTH))
{
- /* Wrap at MAXMODES */
+ /* Wrap */
buffer.append(":").append(ServerInstance->Config->GetSID()).append(" FMODE ").append(c->name).append(" ").append(ConvToStr(c->age)).append(" +").append(modes).append(params).append("\r\n");
+
modes.clear();
params.clear();
linesize = 1;
}
+
+ modes.push_back('b');
+
+ params.push_back(' ');
+ params.append(b->data);
+
+ linesize += size;
}
/* Only send these if there are any */
diff --git a/src/modules/m_spanningtree/postcommand.cpp b/src/modules/m_spanningtree/postcommand.cpp
index 471bbfcb9..3f5d427e1 100644
--- a/src/modules/m_spanningtree/postcommand.cpp
+++ b/src/modules/m_spanningtree/postcommand.cpp
@@ -73,7 +73,7 @@ void SpanningTreeUtilities::RouteCommand(TreeServer* origin, const std::string &
TreeServer* sdest = FindServer(routing.serverdest);
if (!sdest)
{
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Trying to route ENCAP to nonexistant server %s",
+ ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Trying to route ENCAP to nonexistent server %s",
routing.serverdest.c_str());
return;
}
diff --git a/src/modules/m_spanningtree/protocolinterface.cpp b/src/modules/m_spanningtree/protocolinterface.cpp
index 3ab5dae9d..ca4147fea 100644
--- a/src/modules/m_spanningtree/protocolinterface.cpp
+++ b/src/modules/m_spanningtree/protocolinterface.cpp
@@ -137,9 +137,6 @@ void SpanningTreeProtocolInterface::PushToClient(User* target, const std::string
void SpanningTreeProtocolInterface::SendChannel(Channel* target, char status, const std::string &text)
{
- std::string cname = target->name;
- if (status)
- cname = status + cname;
TreeServerList list;
CUList exempt_list;
Utils->GetListOfServersForChannel(target,list,status,exempt_list);
@@ -154,12 +151,20 @@ void SpanningTreeProtocolInterface::SendChannel(Channel* target, char status, co
void SpanningTreeProtocolInterface::SendChannelPrivmsg(Channel* target, char status, const std::string &text)
{
- SendChannel(target, status, ":" + ServerInstance->Config->GetSID()+" PRIVMSG "+target->name+" :"+text);
+ std::string cname = target->name;
+ if (status)
+ cname.insert(0, 1, status);
+
+ SendChannel(target, status, ":" + ServerInstance->Config->GetSID()+" PRIVMSG "+cname+" :"+text);
}
void SpanningTreeProtocolInterface::SendChannelNotice(Channel* target, char status, const std::string &text)
{
- SendChannel(target, status, ":" + ServerInstance->Config->GetSID()+" NOTICE "+target->name+" :"+text);
+ std::string cname = target->name;
+ if (status)
+ cname.insert(0, 1, status);
+
+ SendChannel(target, status, ":" + ServerInstance->Config->GetSID()+" NOTICE "+cname+" :"+text);
}
void SpanningTreeProtocolInterface::SendUserPrivmsg(User* target, const std::string &text)
diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h
index abda28335..efcce5f7a 100644
--- a/src/modules/m_spanningtree/treesocket.h
+++ b/src/modules/m_spanningtree/treesocket.h
@@ -100,6 +100,8 @@ class TreeSocket : public BufferedSocket
int proto_version; /* Remote protocol version */
bool ConnectionFailureShown; /* Set to true if a connection failure message was shown */
+ static const unsigned int FMODE_MAX_LENGTH = 350;
+
/** Checks if the given servername and sid are both free
*/
bool CheckDuplicate(const std::string& servername, const std::string& sid);
diff --git a/src/modules/m_sslinfo.cpp b/src/modules/m_sslinfo.cpp
index 2bfe0e1c4..083ac0f04 100644
--- a/src/modules/m_sslinfo.cpp
+++ b/src/modules/m_sslinfo.cpp
@@ -180,6 +180,9 @@ class ModuleSSLInfo : public Module
if (i != ServerInstance->Config->oper_blocks.end())
{
OperInfo* ifo = i->second;
+ if (!ifo->oper_block)
+ return MOD_RES_PASSTHRU;
+
ssl_cert* cert = cmd.CertExt.get(user);
if (ifo->oper_block->getBool("sslonly") && !cert)
@@ -220,6 +223,9 @@ class ModuleSSLInfo : public Module
for(OperIndex::iterator i = ServerInstance->Config->oper_blocks.begin(); i != ServerInstance->Config->oper_blocks.end(); i++)
{
OperInfo* ifo = i->second;
+ if (!ifo->oper_block)
+ continue;
+
std::string fp = ifo->oper_block->getString("fingerprint");
if (fp == cert->fingerprint && ifo->oper_block->getBool("autologin"))
user->Oper(ifo);
diff --git a/src/socketengines/socketengine_epoll.cpp b/src/socketengines/socketengine_epoll.cpp
index f2837777a..d5f017347 100644
--- a/src/socketengines/socketengine_epoll.cpp
+++ b/src/socketengines/socketengine_epoll.cpp
@@ -25,7 +25,7 @@
#include "exitcodes.h"
#include "socketengine.h"
#include <sys/epoll.h>
-#include <ulimit.h>
+#include <sys/resource.h>
#include <iostream>
#define EP_DELAY 5
@@ -55,10 +55,11 @@ public:
EPollEngine::EPollEngine()
{
CurrentSetSize = 0;
- int max = ulimit(4, 0);
- if (max > 0)
+
+ struct rlimit limit;
+ if (!getrlimit(RLIMIT_NOFILE, &limit))
{
- MAX_DESCRIPTORS = max;
+ MAX_DESCRIPTORS = limit.rlim_cur;
}
else
{
diff --git a/src/usermanager.cpp b/src/usermanager.cpp
index 76446c5b5..2cb7ad511 100644
--- a/src/usermanager.cpp
+++ b/src/usermanager.cpp
@@ -143,6 +143,7 @@ void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs
{
ServerInstance->Logs->Log("USERS", DEBUG,"Internal error on new connection");
this->QuitUser(New, "Internal error handling connection");
+ return;
}
/* NOTE: even if dns lookups are *off*, we still need to display this.
diff --git a/src/users.cpp b/src/users.cpp
index 418f2c9aa..4dbb73a1f 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -837,6 +837,7 @@ void LocalUser::FullConnect()
void User::InvalidateCache()
{
/* Invalidate cache */
+ cachedip.clear();
cached_fullhost.clear();
cached_hostip.clear();
cached_makehost.clear();
@@ -1001,8 +1002,7 @@ irc::sockets::cidr_mask User::GetCIDRMask()
bool User::SetClientIP(const char* sip, bool recheck_eline)
{
- cachedip.clear();
- cached_hostip.clear();
+ this->InvalidateCache();
return irc::sockets::aptosa(sip, 0, client_sa);
}
@@ -1398,6 +1398,8 @@ void User::DoHostCycle(const std::string &quitline)
FOREACH_MOD(I_OnBuildNeighborList,OnBuildNeighborList(this, include_c, exceptions));
+ // Users shouldn't see themselves quitting when host cycling
+ exceptions.erase(this);
for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i)
{
LocalUser* u = IS_LOCAL(i->first);
diff --git a/src/version.sh b/src/version.sh
index 8686e33ae..74a583759 100755
--- a/src/version.sh
+++ b/src/version.sh
@@ -1,2 +1,2 @@
#!/bin/sh
-echo "InspIRCd-2.0.20"
+echo "InspIRCd-2.0.23"