From b2c876c5779f044b110786b9860b9c8a6ea8464a Mon Sep 17 00:00:00 2001 From: Peter Powell Date: Wed, 13 Nov 2019 16:20:18 +0000 Subject: Get rid of some dead code in the MySQL module. --- src/modules/extra/m_mysql.cpp | 9 --------- 1 file changed, 9 deletions(-) (limited to 'src/modules') diff --git a/src/modules/extra/m_mysql.cpp b/src/modules/extra/m_mysql.cpp index fe9bb4cec..3b9bde4de 100644 --- a/src/modules/extra/m_mysql.cpp +++ b/src/modules/extra/m_mysql.cpp @@ -138,10 +138,6 @@ class DispatcherThread : public SocketThread void OnNotify() CXX11_OVERRIDE; }; -#if !defined(MYSQL_VERSION_ID) || MYSQL_VERSION_ID<32224 -#define mysql_field_count mysql_num_fields -#endif - /** Represents a mysql result set */ class MySQLresult : public SQL::Result @@ -372,11 +368,6 @@ class SQLConnection : public SQL::Provider return true; } - std::string GetError() - { - return mysql_error(connection); - } - void Close() { mysql_close(connection); -- cgit v1.3.1-10-gc9f91 From fe87ef196773cc9adf7aacc01e3efe094ed387a5 Mon Sep 17 00:00:00 2001 From: Peter Powell Date: Wed, 13 Nov 2019 15:55:18 +0000 Subject: Refactor the MySQL query and result queue classes. --- src/modules/extra/m_mysql.cpp | 85 ++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 33 deletions(-) (limited to 'src/modules') diff --git a/src/modules/extra/m_mysql.cpp b/src/modules/extra/m_mysql.cpp index 3b9bde4de..d94c75917 100644 --- a/src/modules/extra/m_mysql.cpp +++ b/src/modules/extra/m_mysql.cpp @@ -90,24 +90,43 @@ class SQLConnection; class MySQLresult; class DispatcherThread; -struct QQueueItem +struct QueryQueueItem { - SQL::Query* q; - std::string query; - SQLConnection* c; - QQueueItem(SQL::Query* Q, const std::string& S, SQLConnection* C) : q(Q), query(S), c(C) {} + // An SQL database which this query is executed on. + SQLConnection* connection; + + // An object which handles the result of the query. + SQL::Query* query; + + // The SQL query which is to be executed. + std::string querystr; + + QueryQueueItem(SQL::Query* q, const std::string& s, SQLConnection* c) + : connection(c) + , query(q) + , querystr(s) + { + } }; -struct RQueueItem +struct ResultQueueItem { - SQL::Query* q; - MySQLresult* r; - RQueueItem(SQL::Query* Q, MySQLresult* R) : q(Q), r(R) {} + // An object which handles the result of the query. + SQL::Query* query; + + // The result returned from executing the MySQL query. + MySQLresult* result; + + ResultQueueItem(SQL::Query* q, MySQLresult* r) + : query(q) + , result(r) + { + } }; typedef insp::flat_map ConnMap; -typedef std::deque QueryQueue; -typedef std::deque ResultQueue; +typedef std::deque QueryQueue; +typedef std::deque ResultQueue; /** MySQL module * */ @@ -377,7 +396,7 @@ class SQLConnection : public SQL::Provider { ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Executing MySQL query: " + qs); Parent()->Dispatcher->LockQueue(); - Parent()->qq.push_back(QQueueItem(q, qs, this)); + Parent()->qq.push_back(QueryQueueItem(q, qs, this)); Parent()->Dispatcher->UnlockQueueWakeup(); } @@ -486,10 +505,10 @@ void ModuleSQL::ReadConfig(ConfigStatus& status) for (size_t j = qq.size(); j > 0; j--) { size_t k = j - 1; - if (qq[k].c == i->second) + if (qq[k].connection == i->second) { - qq[k].q->OnError(err); - delete qq[k].q; + qq[k].query->OnError(err); + delete qq[k].query; qq.erase(qq.begin() + k); } } @@ -508,17 +527,17 @@ void ModuleSQL::OnUnloadModule(Module* mod) while (i > 0) { i--; - if (qq[i].q->creator == mod) + if (qq[i].query->creator == mod) { if (i == 0) { // need to wait until the query is done // (the result will be discarded) - qq[i].c->lock.Lock(); - qq[i].c->lock.Unlock(); + qq[i].connection->lock.Lock(); + qq[i].connection->lock.Unlock(); } - qq[i].q->OnError(err); - delete qq[i].q; + qq[i].query->OnError(err); + delete qq[i].query; qq.erase(qq.begin() + i); } } @@ -539,23 +558,23 @@ void DispatcherThread::Run() { if (!Parent->qq.empty()) { - QQueueItem i = Parent->qq.front(); - i.c->lock.Lock(); + QueryQueueItem i = Parent->qq.front(); + i.connection->lock.Lock(); this->UnlockQueue(); - MySQLresult* res = i.c->DoBlockingQuery(i.query); - i.c->lock.Unlock(); + MySQLresult* res = i.connection->DoBlockingQuery(i.querystr); + i.connection->lock.Unlock(); /* * At this point, the main thread could be working on: - * Rehash - delete i.c out from under us. We don't care about that. - * UnloadModule - delete i.q and the qq item. Need to avoid reporting results. + * Rehash - delete i.connection out from under us. We don't care about that. + * UnloadModule - delete i.query and the qq item. Need to avoid reporting results. */ this->LockQueue(); - if (!Parent->qq.empty() && Parent->qq.front().q == i.q) + if (!Parent->qq.empty() && Parent->qq.front().query == i.query) { Parent->qq.pop_front(); - Parent->rq.push_back(RQueueItem(i.q, res)); + Parent->rq.push_back(ResultQueueItem(i.query, res)); NotifyParent(); } else @@ -581,13 +600,13 @@ void DispatcherThread::OnNotify() this->LockQueue(); for(ResultQueue::iterator i = Parent->rq.begin(); i != Parent->rq.end(); i++) { - MySQLresult* res = i->r; + MySQLresult* res = i->result; if (res->err.code == SQL::SUCCESS) - i->q->OnResult(*res); + i->query->OnResult(*res); else - i->q->OnError(res->err); - delete i->q; - delete i->r; + i->query->OnError(res->err); + delete i->query; + delete i->result; } Parent->rq.clear(); this->UnlockQueue(); -- cgit v1.3.1-10-gc9f91 From 05066eb189e177c4385d3f19a5181473331e7f87 Mon Sep 17 00:00:00 2001 From: Matt Schatz Date: Wed, 13 Nov 2019 07:28:12 -0700 Subject: SSL modules: send SNOTICE upon successful rehash. --- src/modules/extra/m_ssl_gnutls.cpp | 1 + src/modules/extra/m_ssl_mbedtls.cpp | 1 + src/modules/extra/m_ssl_openssl.cpp | 1 + 3 files changed, 3 insertions(+) (limited to 'src/modules') diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp index a3690faae..fd8d62f83 100644 --- a/src/modules/extra/m_ssl_gnutls.cpp +++ b/src/modules/extra/m_ssl_gnutls.cpp @@ -1365,6 +1365,7 @@ class ModuleSSLGnuTLS : public Module try { ReadProfiles(); + ServerInstance->SNO->WriteToSnoMask('a', "SSL module %s rehashed.", MODNAME); } catch (ModuleException& ex) { diff --git a/src/modules/extra/m_ssl_mbedtls.cpp b/src/modules/extra/m_ssl_mbedtls.cpp index 5c7bcf9fa..0ad2bedf4 100644 --- a/src/modules/extra/m_ssl_mbedtls.cpp +++ b/src/modules/extra/m_ssl_mbedtls.cpp @@ -932,6 +932,7 @@ class ModuleSSLmbedTLS : public Module try { ReadProfiles(); + ServerInstance->SNO->WriteToSnoMask('a', "SSL module %s rehashed.", MODNAME); } catch (ModuleException& ex) { diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp index 08316f196..59e65f526 100644 --- a/src/modules/extra/m_ssl_openssl.cpp +++ b/src/modules/extra/m_ssl_openssl.cpp @@ -1055,6 +1055,7 @@ class ModuleSSLOpenSSL : public Module try { ReadProfiles(); + ServerInstance->SNO->WriteToSnoMask('a', "SSL module %s rehashed.", MODNAME); } catch (ModuleException& ex) { -- cgit v1.3.1-10-gc9f91 From e8b476bea986691e10f69b93343dd3f578fb00fb Mon Sep 17 00:00:00 2001 From: Peter Powell Date: Wed, 13 Nov 2019 17:00:11 +0000 Subject: Refactor the MySQL code slightly. --- src/modules/extra/m_mysql.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src/modules') diff --git a/src/modules/extra/m_mysql.cpp b/src/modules/extra/m_mysql.cpp index d94c75917..6c0493413 100644 --- a/src/modules/extra/m_mysql.cpp +++ b/src/modules/extra/m_mysql.cpp @@ -168,7 +168,10 @@ class MySQLresult : public SQL::Result std::vector colnames; std::vector fieldlists; - MySQLresult(MYSQL_RES* res, int affected_rows) : err(SQL::SUCCESS), currentrow(0), rows(0) + MySQLresult(MYSQL_RES* res, int affected_rows) + : err(SQL::SUCCESS) + , currentrow(0) + , rows(0) { if (affected_rows >= 1) { @@ -211,7 +214,10 @@ class MySQLresult : public SQL::Result } } - MySQLresult(SQL::Error& e) : err(e) + MySQLresult(SQL::Error& e) + : err(e) + , currentrow(0) + , rows(0) { } @@ -308,7 +314,7 @@ class SQLConnection : public SQL::Provider ~SQLConnection() { - Close(); + mysql_close(connection); } // This method connects to the database using the credentials supplied to the constructor, and returns @@ -387,11 +393,6 @@ class SQLConnection : public SQL::Provider return true; } - void Close() - { - mysql_close(connection); - } - void Submit(SQL::Query* q, const std::string& qs) CXX11_OVERRIDE { ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Executing MySQL query: " + qs); @@ -439,8 +440,8 @@ class SQLConnection : public SQL::Provider }; ModuleSQL::ModuleSQL() + : Dispatcher(NULL) { - Dispatcher = NULL; } void ModuleSQL::init() -- cgit v1.3.1-10-gc9f91 From 687778b72e31322a73b2e2e17af6bd0f2a2561bc Mon Sep 17 00:00:00 2001 From: Peter Powell Date: Sun, 17 Nov 2019 22:06:36 +0000 Subject: Allow Channel::WriteNotice send to other servers and status ranks. --- include/channels.h | 3 ++- src/channels.cpp | 5 +++-- src/modules/m_ojoin.cpp | 6 +----- src/modules/m_spanningtree/fjoin.cpp | 9 +++++++-- src/modules/m_timedbans.cpp | 8 ++------ src/modules/m_uninvite.cpp | 5 +---- 6 files changed, 16 insertions(+), 20 deletions(-) (limited to 'src/modules') diff --git a/include/channels.h b/include/channels.h index d346db8ef..5957ae668 100644 --- a/include/channels.h +++ b/include/channels.h @@ -283,8 +283,9 @@ class CoreExport Channel : public Extensible /** Write a NOTICE to all local users on the channel * @param text Text to send + * @param status The minimum status rank to send this message to. */ - void WriteNotice(const std::string& text); + void WriteNotice(const std::string& text, char status = 0); }; inline bool Channel::HasUser(User* user) diff --git a/src/channels.cpp b/src/channels.cpp index 282199718..5baaf03ee 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -473,10 +473,11 @@ const char* Channel::ChanModes(bool showsecret) return scratch.c_str(); } -void Channel::WriteNotice(const std::string& text) +void Channel::WriteNotice(const std::string& text, char status) { - ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, ServerInstance->FakeClient, this, text, MSG_NOTICE); + ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, ServerInstance->FakeClient, this, text, MSG_NOTICE, status); Write(ServerInstance->GetRFCEvents().privmsg, privmsg); + ServerInstance->PI->SendMessage(this, status, text, MSG_NOTICE); } /* returns the status character for a given user on a channel, e.g. @ for op, diff --git a/src/modules/m_ojoin.cpp b/src/modules/m_ojoin.cpp index c0626ec69..e3366056d 100644 --- a/src/modules/m_ojoin.cpp +++ b/src/modules/m_ojoin.cpp @@ -57,11 +57,7 @@ class CommandOjoin : public SplitCommand ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used OJOIN to join "+channel->name); if (notice) - { - const std::string msg = user->nick + " joined on official network business."; - channel->WriteNotice(msg); - ServerInstance->PI->SendChannelNotice(channel, 0, msg); - } + channel->WriteNotice(user->nick + " joined on official network business."); } else { diff --git a/src/modules/m_spanningtree/fjoin.cpp b/src/modules/m_spanningtree/fjoin.cpp index 6305e5af8..02d985ef3 100644 --- a/src/modules/m_spanningtree/fjoin.cpp +++ b/src/modules/m_spanningtree/fjoin.cpp @@ -276,8 +276,13 @@ void CommandFJoin::RemoveStatus(Channel* c) void CommandFJoin::LowerTS(Channel* chan, time_t TS, const std::string& newname) { if (Utils->AnnounceTSChange) - chan->WriteNotice(InspIRCd::Format("Creation time of %s changed from %s to %s", newname.c_str(), - InspIRCd::TimeString(chan->age).c_str(), InspIRCd::TimeString(TS).c_str())); + { + // WriteNotice is not used here because the message only needs to go to the local server. + const std::string tsmessage = InspIRCd::Format("Creation time of %s changed from %s to %s", newname.c_str(), + InspIRCd::TimeString(chan->age).c_str(), InspIRCd::TimeString(TS).c_str()); + ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, ServerInstance->FakeClient, chan, tsmessage, MSG_NOTICE); + chan->Write(ServerInstance->GetRFCEvents().privmsg, privmsg); + } // While the name is equal in case-insensitive compare, it might differ in case; use the remote version chan->name = newname; diff --git a/src/modules/m_timedbans.cpp b/src/modules/m_timedbans.cpp index ef3382e4b..eb3c47527 100644 --- a/src/modules/m_timedbans.cpp +++ b/src/modules/m_timedbans.cpp @@ -128,9 +128,7 @@ class CommandTban : public Command PrefixMode* mh = ServerInstance->Modes->FindPrefixMode('h'); char pfxchar = (mh && mh->name == "halfop") ? mh->GetPrefix() : '@'; - ClientProtocol::Messages::Privmsg notice(ServerInstance->FakeClient, channel, message, MSG_NOTICE); - channel->Write(ServerInstance->GetRFCEvents().privmsg, notice, pfxchar); - ServerInstance->PI->SendChannelNotice(channel, pfxchar, message); + channel->WriteNotice(message, pfxchar); return CMD_SUCCESS; } @@ -221,9 +219,7 @@ class ModuleTimedBans : public Module PrefixMode* mh = ServerInstance->Modes->FindPrefixMode('h'); char pfxchar = (mh && mh->name == "halfop") ? mh->GetPrefix() : '@'; - ClientProtocol::Messages::Privmsg notice(ClientProtocol::Messages::Privmsg::nocopy, ServerInstance->FakeClient, cr, message, MSG_NOTICE); - cr->Write(ServerInstance->GetRFCEvents().privmsg, notice, pfxchar); - ServerInstance->PI->SendChannelNotice(cr, pfxchar, message); + cr->WriteNotice(message, pfxchar); Modes::ChangeList setban; setban.push_remove(ServerInstance->Modes->FindMode('b', MODETYPE_CHANNEL), mask); diff --git a/src/modules/m_uninvite.cpp b/src/modules/m_uninvite.cpp index ae1553a23..ec5653806 100644 --- a/src/modules/m_uninvite.cpp +++ b/src/modules/m_uninvite.cpp @@ -100,10 +100,7 @@ class CommandUninvite : public Command user->WriteRemoteNumeric(n); lu->WriteNumeric(RPL_UNINVITED, InspIRCd::Format("You were uninvited from %s by %s", c->name.c_str(), user->nick.c_str())); - - std::string msg = "*** " + user->nick + " uninvited " + u->nick + "."; - c->WriteNotice(msg); - ServerInstance->PI->SendChannelNotice(c, 0, msg); + c->WriteNotice(InspIRCd::Format("*** %s uninvited %s.", user->nick.c_str(), u->nick.c_str())); } return CMD_SUCCESS; -- cgit v1.3.1-10-gc9f91 From 36d7ee44a8c697a702211bb767d7a5c912300dfd Mon Sep 17 00:00:00 2001 From: Matt Schatz Date: Sun, 17 Nov 2019 05:06:48 -0700 Subject: Change Config->CaseMapping back when unloading. Now that casemapping is configurable in the core and we set that Config variable rather than just modifying the ISupport output each time, we need to change the variable back when being unloaded. So we save the current value when loading and set it back when being unloaded. We also need to call the ISupport builder a second time as the core calls it before we destruct. --- src/modules/m_nationalchars.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/modules') diff --git a/src/modules/m_nationalchars.cpp b/src/modules/m_nationalchars.cpp index 2b7e66a50..dbeff6db9 100644 --- a/src/modules/m_nationalchars.cpp +++ b/src/modules/m_nationalchars.cpp @@ -222,6 +222,7 @@ class ModuleNationalChars : public Module TR1NS::function rememberer; bool forcequit; const unsigned char * lowermap_rememberer; + std::string casemapping_rememberer; unsigned char prev_map[256]; template @@ -248,7 +249,9 @@ class ModuleNationalChars : public Module public: ModuleNationalChars() - : rememberer(ServerInstance->IsNick), lowermap_rememberer(national_case_insensitive_map) + : rememberer(ServerInstance->IsNick) + , lowermap_rememberer(national_case_insensitive_map) + , casemapping_rememberer(ServerInstance->Config->CaseMapping) { memcpy(prev_map, national_case_insensitive_map, sizeof(prev_map)); } @@ -305,6 +308,9 @@ class ModuleNationalChars : public Module { ServerInstance->IsNick = rememberer; national_case_insensitive_map = lowermap_rememberer; + ServerInstance->Config->CaseMapping = casemapping_rememberer; + // The core rebuilds ISupport on module unload, but before the dtor. + ServerInstance->ISupport.Build(); CheckForceQuit("National characters module unloaded"); CheckRehash(); } -- cgit v1.3.1-10-gc9f91 From 7ae4ca1a238ba7598ce2cd1b3de116cfc7a89588 Mon Sep 17 00:00:00 2001 From: Matt Schatz Date: Mon, 18 Nov 2019 03:21:19 -0700 Subject: Split the channel mode and extban replies. Tell the user when they are extbanned rather than incorrectly say that the channel mode is set. Refactored the logic in m_nonotice to match that of the others. --- src/modules/m_blockcolor.cpp | 8 +++++--- src/modules/m_noctcp.cpp | 6 ++++-- src/modules/m_nokicks.cpp | 6 ++++-- src/modules/m_nonicks.cpp | 8 ++++---- src/modules/m_nonotice.cpp | 20 ++++++++++---------- 5 files changed, 27 insertions(+), 21 deletions(-) (limited to 'src/modules') diff --git a/src/modules/m_blockcolor.cpp b/src/modules/m_blockcolor.cpp index 25345506e..b514d3a1d 100644 --- a/src/modules/m_blockcolor.cpp +++ b/src/modules/m_blockcolor.cpp @@ -46,19 +46,21 @@ class ModuleBlockColor : public Module if ((target.type == MessageTarget::TYPE_CHANNEL) && (IS_LOCAL(user))) { Channel* c = target.Get(); - ModResult res = CheckExemption::Call(exemptionprov, user, c, "blockcolor"); + ModResult res = CheckExemption::Call(exemptionprov, user, c, "blockcolor"); if (res == MOD_RES_ALLOW) return MOD_RES_PASSTHRU; - if (!c->GetExtBanStatus(user, 'c').check(!c->IsModeSet(bc))) + bool modeset = c->IsModeSet(bc); + if (!c->GetExtBanStatus(user, 'c').check(!modeset)) { for (std::string::iterator i = details.text.begin(); i != details.text.end(); i++) { // Block all control codes except \001 for CTCP if ((*i >= 0) && (*i < 32) && (*i != 1)) { - user->WriteNumeric(ERR_CANNOTSENDTOCHAN, c->name, "Can't send colors to channel (+c is set)"); + user->WriteNumeric(ERR_CANNOTSENDTOCHAN, c->name, InspIRCd::Format("Can't send colors to channel (%s)", + modeset ? "+c is set" : "you're extbanned")); return MOD_RES_DENY; } } diff --git a/src/modules/m_noctcp.cpp b/src/modules/m_noctcp.cpp index 45f805ac9..1eedac203 100644 --- a/src/modules/m_noctcp.cpp +++ b/src/modules/m_noctcp.cpp @@ -81,9 +81,11 @@ class ModuleNoCTCP : public Module if (res == MOD_RES_ALLOW) return MOD_RES_PASSTHRU; - if (!c->GetExtBanStatus(user, 'C').check(!c->IsModeSet(nc))) + bool modeset = c->IsModeSet(nc); + if (!c->GetExtBanStatus(user, 'C').check(!modeset)) { - user->WriteNumeric(ERR_CANNOTSENDTOCHAN, c->name, "Can't send CTCP to channel (+C is set)"); + user->WriteNumeric(ERR_CANNOTSENDTOCHAN, c->name, InspIRCd::Format("Can't send CTCP to channel (%s)", + modeset ? "+C is set" : "you're extbanned")); return MOD_RES_DENY; } break; diff --git a/src/modules/m_nokicks.cpp b/src/modules/m_nokicks.cpp index 6cd91c55b..20951c18f 100644 --- a/src/modules/m_nokicks.cpp +++ b/src/modules/m_nokicks.cpp @@ -39,10 +39,12 @@ class ModuleNoKicks : public Module ModResult OnUserPreKick(User* source, Membership* memb, const std::string &reason) CXX11_OVERRIDE { - if (!memb->chan->GetExtBanStatus(source, 'Q').check(!memb->chan->IsModeSet(nk))) + bool modeset = memb->chan->IsModeSet(nk); + if (!memb->chan->GetExtBanStatus(source, 'Q').check(!modeset)) { // Can't kick with Q in place, not even opers with override, and founders - source->WriteNumeric(ERR_CHANOPRIVSNEEDED, memb->chan->name, InspIRCd::Format("Can't kick user %s from channel (+Q is set)", memb->user->nick.c_str())); + source->WriteNumeric(ERR_CHANOPRIVSNEEDED, memb->chan->name, InspIRCd::Format("Can't kick user %s from channel (%s)", + memb->user->nick.c_str(), modeset ? "+Q is set" : "you're extbanned")); return MOD_RES_DENY; } return MOD_RES_PASSTHRU; diff --git a/src/modules/m_nonicks.cpp b/src/modules/m_nonicks.cpp index a796495a8..df2d5db64 100644 --- a/src/modules/m_nonicks.cpp +++ b/src/modules/m_nonicks.cpp @@ -50,17 +50,17 @@ class ModuleNoNickChange : public Module Channel* curr = (*i)->chan; ModResult res = CheckExemption::Call(exemptionprov, user, curr, "nonick"); - if (res == MOD_RES_ALLOW) continue; if (user->HasPrivPermission("channels/ignore-nonicks")) continue; - if (!curr->GetExtBanStatus(user, 'N').check(!curr->IsModeSet(nn))) + bool modeset = curr->IsModeSet(nn); + if (!curr->GetExtBanStatus(user, 'N').check(!modeset)) { - user->WriteNumeric(ERR_CANTCHANGENICK, InspIRCd::Format("Cannot change nickname while on %s (+N is set)", - curr->name.c_str())); + user->WriteNumeric(ERR_CANTCHANGENICK, InspIRCd::Format("Can't change nickname while on %s (%s)", + curr->name.c_str(), modeset ? "+N is set" : "you're extbanned")); return MOD_RES_DENY; } } diff --git a/src/modules/m_nonotice.cpp b/src/modules/m_nonotice.cpp index 730b02716..2883a3c6d 100644 --- a/src/modules/m_nonotice.cpp +++ b/src/modules/m_nonotice.cpp @@ -41,20 +41,20 @@ class ModuleNoNotice : public Module ModResult OnUserPreMessage(User* user, const MessageTarget& target, MessageDetails& details) CXX11_OVERRIDE { - ModResult res; if ((details.type == MSG_NOTICE) && (target.type == MessageTarget::TYPE_CHANNEL) && (IS_LOCAL(user))) { Channel* c = target.Get(); - if (!c->GetExtBanStatus(user, 'T').check(!c->IsModeSet(nt))) + + ModResult res = CheckExemption::Call(exemptionprov, user, c, "nonotice"); + if (res == MOD_RES_ALLOW) + return MOD_RES_PASSTHRU; + + bool modeset = c->IsModeSet(nt); + if (!c->GetExtBanStatus(user, 'T').check(!modeset)) { - res = CheckExemption::Call(exemptionprov, user, c, "nonotice"); - if (res == MOD_RES_ALLOW) - return MOD_RES_PASSTHRU; - else - { - user->WriteNumeric(ERR_CANNOTSENDTOCHAN, c->name, "Can't send NOTICE to channel (+T is set)"); - return MOD_RES_DENY; - } + user->WriteNumeric(ERR_CANNOTSENDTOCHAN, c->name, InspIRCd::Format("Can't send NOTICE to channel (%s)", + modeset ? "+T is set" : "you're extbanned")); + return MOD_RES_DENY; } } return MOD_RES_PASSTHRU; -- cgit v1.3.1-10-gc9f91 From 478a092258718cd75fa23a0ba67af42a6e1a0fda Mon Sep 17 00:00:00 2001 From: Peter Powell Date: Fri, 22 Nov 2019 14:13:45 +0000 Subject: Rename ldapoper class to LDAPOper. This might be causing issues for some people? --- src/modules/m_ldapoper.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/modules') diff --git a/src/modules/m_ldapoper.cpp b/src/modules/m_ldapoper.cpp index cde5b00d7..b2a1c1f0d 100644 --- a/src/modules/m_ldapoper.cpp +++ b/src/modules/m_ldapoper.cpp @@ -180,14 +180,14 @@ class AdminBindInterface : public LDAPInterface } }; -class ModuleLDAPAuth : public Module +class ModuleLDAPOper : public Module { dynamic_reference LDAP; std::string base; std::string attribute; public: - ModuleLDAPAuth() + ModuleLDAPOper() : LDAP(this, "LDAP") { me = this; @@ -246,4 +246,4 @@ class ModuleLDAPAuth : public Module } }; -MODULE_INIT(ModuleLDAPAuth) +MODULE_INIT(ModuleLDAPOper) -- cgit v1.3.1-10-gc9f91 From 6f2d0b505f4715c696cc5d49874d442cf790b98a Mon Sep 17 00:00:00 2001 From: Peter Powell Date: Thu, 28 Nov 2019 17:06:11 +0000 Subject: Move WebSocket config to its own class. --- src/modules/m_websocket.cpp | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) (limited to 'src/modules') diff --git a/src/modules/m_websocket.cpp b/src/modules/m_websocket.cpp index 51dada299..3437fdb1a 100644 --- a/src/modules/m_websocket.cpp +++ b/src/modules/m_websocket.cpp @@ -31,12 +31,19 @@ static const char MagicGUID[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; static const char whitespace[] = " \t\r\n"; static dynamic_reference_nocheck* sha1; -class WebSocketHookProvider : public IOHookProvider +struct WebSocketConfig { - public: + // The HTTP origins that can connect to the server. OriginList allowedorigins; + + // Whether to send as UTF-8 text instead of binary data. bool sendastext; +}; +class WebSocketHookProvider : public IOHookProvider +{ + public: + WebSocketConfig config; WebSocketHookProvider(Module* mod) : IOHookProvider(mod, "websocket", IOHookProvider::IOH_UNKNOWN, true) { @@ -110,8 +117,7 @@ class WebSocketHook : public IOHookMiddle State state; time_t lastpingpong; - OriginList& allowedorigins; - bool& sendastext; + WebSocketConfig& config; static size_t FillHeader(unsigned char* outbuf, size_t sendlength, OpCode opcode) { @@ -318,7 +324,7 @@ class WebSocketHook : public IOHookMiddle if (originheader.Find(recvq, "Origin:", 7, reqend)) { const std::string origin = originheader.ExtractValue(recvq); - for (OriginList::const_iterator iter = allowedorigins.begin(); iter != allowedorigins.end(); ++iter) + for (OriginList::const_iterator iter = config.allowedorigins.begin(); iter != config.allowedorigins.end(); ++iter) { if (InspIRCd::Match(origin, *iter, ascii_case_insensitive_map)) { @@ -364,12 +370,11 @@ class WebSocketHook : public IOHookMiddle } public: - WebSocketHook(IOHookProvider* Prov, StreamSocket* sock, OriginList& AllowedOrigins, bool& SendAsText) + WebSocketHook(IOHookProvider* Prov, StreamSocket* sock, WebSocketConfig& cfg) : IOHookMiddle(Prov) , state(STATE_HTTPREQ) , lastpingpong(0) - , allowedorigins(AllowedOrigins) - , sendastext(SendAsText) + , config(cfg) { sock->AddIOHook(this); } @@ -390,7 +395,7 @@ class WebSocketHook : public IOHookMiddle if (*chr == '\n') { // We have found an entire message. Send it in its own frame. - if (sendastext) + if (config.sendastext) { // If we send messages as text then we need to ensure they are valid UTF-8. std::string encoded; @@ -451,7 +456,7 @@ class WebSocketHook : public IOHookMiddle void WebSocketHookProvider::OnAccept(StreamSocket* sock, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) { - new WebSocketHook(this, sock, allowedorigins, sendastext); + new WebSocketHook(this, sock, config); } class ModuleWebSocket : public Module @@ -473,7 +478,7 @@ class ModuleWebSocket : public Module if (tags.first == tags.second) throw ModuleException("You have loaded the websocket module but not configured any allowed origins!"); - OriginList allowedorigins; + WebSocketConfig config; for (ConfigIter i = tags.first; i != tags.second; ++i) { ConfigTag* tag = i->second; @@ -483,12 +488,14 @@ class ModuleWebSocket : public Module if (allow.empty()) throw ModuleException(" is a mandatory field, at " + tag->getTagLocation()); - allowedorigins.push_back(allow); + config.allowedorigins.push_back(allow); } ConfigTag* tag = ServerInstance->Config->ConfValue("websocket"); - hookprov->sendastext = tag->getBool("sendastext", true); - hookprov->allowedorigins.swap(allowedorigins); + config.sendastext = tag->getBool("sendastext", true); + + // Everything is okay; apply the new config. + hookprov->config = config; } void OnCleanup(ExtensionItem::ExtensibleType type, Extensible* item) CXX11_OVERRIDE -- cgit v1.3.1-10-gc9f91 From bb1f892f68cb70537b224bca85cc40f1ed23017d Mon Sep 17 00:00:00 2001 From: Peter Powell Date: Thu, 28 Nov 2019 17:59:35 +0000 Subject: Implement support for websocket connections via a proxy like nginx. --- docs/conf/modules.conf.example | 17 ++++++++++++----- src/modules/m_websocket.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 5 deletions(-) (limited to 'src/modules') diff --git a/docs/conf/modules.conf.example b/docs/conf/modules.conf.example index 639f02335..9cb78daee 100644 --- a/docs/conf/modules.conf.example +++ b/docs/conf/modules.conf.example @@ -2307,11 +2307,18 @@ # Requires SHA-1 hash support available in the sha1 module. # # -# Whether to re-encode messages as UTF-8 before sending to WebSocket -# clients. This is recommended as the WebSocket protocol requires all -# text frames to be sent as UTF-8. If you do not have this enabled -# messages will be sent as binary frames instead. -# +# behindproxy: Whether the server is behind a proxy that sends the +# X-Real-IP or X-Forwarded-For headers. If enabled the +# server will use the IP address specified by those HTTP +# headers. You should NOT enable this unless you are using +# a HTTP proxy like nginx as it will allow IP spoofing. +# sendastext: Whether to re-encode messages as UTF-8 before sending to +# WebSocket clients. This is recommended as the WebSocket +# protocol requires all text frames to be sent as UTF-8. +# If you do not have this enabled messages will be sent as +# binary frames instead. +# # # If you use the websocket module you MUST specify one or more origins # which are allowed to connect to the server. You should set this as diff --git a/src/modules/m_websocket.cpp b/src/modules/m_websocket.cpp index 3437fdb1a..79cabf4e5 100644 --- a/src/modules/m_websocket.cpp +++ b/src/modules/m_websocket.cpp @@ -36,6 +36,9 @@ struct WebSocketConfig // The HTTP origins that can connect to the server. OriginList allowedorigins; + // Whether to trust the X-Real-IP or X-Forwarded-For headers. + bool behindproxy; + // Whether to send as UTF-8 text instead of binary data. bool sendastext; }; @@ -340,6 +343,29 @@ class WebSocketHook : public IOHookMiddle return -1; } + if (config.behindproxy && sock->type == StreamSocket::SS_USER) + { + LocalUser* luser = static_cast(sock)->user; + irc::sockets::sockaddrs realsa(luser->client_sa); + + HTTPHeaderFinder proxyheader; + if (proxyheader.Find(recvq, "X-Real-IP:", 10, reqend) + && irc::sockets::aptosa(proxyheader.ExtractValue(recvq), realsa.port(), realsa)) + { + // Nothing to do here. + } + else if (proxyheader.Find(recvq, "X-Forwarded-For:", 16, reqend) + && irc::sockets::aptosa(proxyheader.ExtractValue(recvq), realsa.port(), realsa)) + { + // Nothing to do here. + } + + // Give the user their real IP address. + if (realsa != luser->client_sa) + luser->SetClientIP(realsa); + } + + HTTPHeaderFinder keyheader; if (!keyheader.Find(recvq, "Sec-WebSocket-Key:", 18, reqend)) { @@ -492,6 +518,7 @@ class ModuleWebSocket : public Module } ConfigTag* tag = ServerInstance->Config->ConfValue("websocket"); + config.behindproxy = tag->getBool("behindproxy"); config.sendastext = tag->getBool("sendastext", true); // Everything is okay; apply the new config. -- cgit v1.3.1-10-gc9f91 From afb5972ab54d64f8c4e7b09962fb2088e427920b Mon Sep 17 00:00:00 2001 From: Peter Powell Date: Fri, 29 Nov 2019 11:09:36 +0000 Subject: WebSocket: replace the behindproxy switch with a proxy IP list. --- docs/conf/modules.conf.example | 8 ++++---- src/modules/m_websocket.cpp | 26 +++++++++++++++++++------- 2 files changed, 23 insertions(+), 11 deletions(-) (limited to 'src/modules') diff --git a/docs/conf/modules.conf.example b/docs/conf/modules.conf.example index 9cb78daee..cee785436 100644 --- a/docs/conf/modules.conf.example +++ b/docs/conf/modules.conf.example @@ -2307,9 +2307,9 @@ # Requires SHA-1 hash support available in the sha1 module. # # -# behindproxy: Whether the server is behind a proxy that sends the -# X-Real-IP or X-Forwarded-For headers. If enabled the -# server will use the IP address specified by those HTTP +# proxyranges: A space-delimited list of glob or CIDR matches to trust +# the X-Real-IP or X-Forwarded-For headers from. If enabled +# the server will use the IP address specified by those HTTP # headers. You should NOT enable this unless you are using # a HTTP proxy like nginx as it will allow IP spoofing. # sendastext: Whether to re-encode messages as UTF-8 before sending to @@ -2317,7 +2317,7 @@ # protocol requires all text frames to be sent as UTF-8. # If you do not have this enabled messages will be sent as # binary frames instead. -# # # If you use the websocket module you MUST specify one or more origins diff --git a/src/modules/m_websocket.cpp b/src/modules/m_websocket.cpp index 79cabf4e5..ee1c00e97 100644 --- a/src/modules/m_websocket.cpp +++ b/src/modules/m_websocket.cpp @@ -33,11 +33,13 @@ static dynamic_reference_nocheck* sha1; struct WebSocketConfig { + typedef std::vector ProxyRanges; + // The HTTP origins that can connect to the server. OriginList allowedorigins; - // Whether to trust the X-Real-IP or X-Forwarded-For headers. - bool behindproxy; + // The IP ranges which send trustworthy X-Real-IP or X-Forwarded-For headers. + ProxyRanges proxyranges; // Whether to send as UTF-8 text instead of binary data. bool sendastext; @@ -343,7 +345,7 @@ class WebSocketHook : public IOHookMiddle return -1; } - if (config.behindproxy && sock->type == StreamSocket::SS_USER) + if (!config.proxyranges.empty() && sock->type == StreamSocket::SS_USER) { LocalUser* luser = static_cast(sock)->user; irc::sockets::sockaddrs realsa(luser->client_sa); @@ -360,9 +362,16 @@ class WebSocketHook : public IOHookMiddle // Nothing to do here. } - // Give the user their real IP address. - if (realsa != luser->client_sa) - luser->SetClientIP(realsa); + for (WebSocketConfig::ProxyRanges::const_iterator iter = config.proxyranges.begin(); iter != config.proxyranges.end(); ++iter) + { + if (InspIRCd::MatchCIDR(*iter, luser->GetIPString(), ascii_case_insensitive_map)) + { + // Give the user their real IP address. + if (realsa == luser->client_sa) + luser->SetClientIP(realsa); + break; + } + } } @@ -518,9 +527,12 @@ class ModuleWebSocket : public Module } ConfigTag* tag = ServerInstance->Config->ConfValue("websocket"); - config.behindproxy = tag->getBool("behindproxy"); config.sendastext = tag->getBool("sendastext", true); + irc::spacesepstream proxyranges(tag->getString("proxyranges")); + for (std::string proxyrange; proxyranges.GetToken(proxyrange); ) + config.proxyranges.push_back(proxyrange); + // Everything is okay; apply the new config. hookprov->config = config; } -- cgit v1.3.1-10-gc9f91 From 965460400b271a178cc415783414de43c89341bf Mon Sep 17 00:00:00 2001 From: Peter Powell Date: Fri, 29 Nov 2019 11:11:11 +0000 Subject: WebSocket: move the OriginList typedef inside WebSocketConfig. --- src/modules/m_websocket.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/modules') diff --git a/src/modules/m_websocket.cpp b/src/modules/m_websocket.cpp index ee1c00e97..5f0f9bcc8 100644 --- a/src/modules/m_websocket.cpp +++ b/src/modules/m_websocket.cpp @@ -25,14 +25,13 @@ #include -typedef std::vector OriginList; - static const char MagicGUID[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; static const char whitespace[] = " \t\r\n"; static dynamic_reference_nocheck* sha1; struct WebSocketConfig { + typedef std::vector OriginList; typedef std::vector ProxyRanges; // The HTTP origins that can connect to the server. @@ -329,7 +328,7 @@ class WebSocketHook : public IOHookMiddle if (originheader.Find(recvq, "Origin:", 7, reqend)) { const std::string origin = originheader.ExtractValue(recvq); - for (OriginList::const_iterator iter = config.allowedorigins.begin(); iter != config.allowedorigins.end(); ++iter) + for (WebSocketConfig::OriginList::const_iterator iter = config.allowedorigins.begin(); iter != config.allowedorigins.end(); ++iter) { if (InspIRCd::Match(origin, *iter, ascii_case_insensitive_map)) { -- cgit v1.3.1-10-gc9f91 From df2a3d6fc49ec91b2e0396667df8038fc33b8063 Mon Sep 17 00:00:00 2001 From: Peter Powell Date: Fri, 29 Nov 2019 13:43:49 +0000 Subject: Minor cleanup of the conn_umodes module. --- src/modules/m_conn_umodes.cpp | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) (limited to 'src/modules') diff --git a/src/modules/m_conn_umodes.cpp b/src/modules/m_conn_umodes.cpp index ceb1b66fa..d76e21d60 100644 --- a/src/modules/m_conn_umodes.cpp +++ b/src/modules/m_conn_umodes.cpp @@ -32,22 +32,18 @@ class ModuleModesOnConnect : public Module void OnUserConnect(LocalUser* user) CXX11_OVERRIDE { - ConfigTag* tag = user->MyClass->config; - std::string ThisModes = tag->getString("modes"); - if (!ThisModes.empty()) - { - std::string buf; - irc::spacesepstream ss(ThisModes); - - CommandBase::Params modes; - modes.push_back(user->nick); - - // split ThisUserModes into modes and mode params - while (ss.GetToken(buf)) - modes.push_back(buf); - - ServerInstance->Parser.CallHandler("MODE", modes, user); - } + const std::string modestr = user->MyClass->config->getString("modes"); + if (modestr.empty()) + return; + + CommandBase::Params params; + params.push_back(user->nick); + + irc::spacesepstream modestream(modestr); + for (std::string modetoken; modestream.GetToken(modetoken); ) + params.push_back(modetoken); + + ServerInstance->Parser.CallHandler("MODE", params, user); } }; -- cgit v1.3.1-10-gc9f91 From 694c121908d80844a679bbbdf875c639627ec73c Mon Sep 17 00:00:00 2001 From: Peter Powell Date: Fri, 29 Nov 2019 13:46:24 +0000 Subject: Change the default for to false. This message exists for an incredibly rare issue and just confuses the vast majority of people. --- docs/conf/modules.conf.example | 2 +- src/modules/m_conn_waitpong.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/modules') diff --git a/docs/conf/modules.conf.example b/docs/conf/modules.conf.example index cee785436..ae747e3a0 100644 --- a/docs/conf/modules.conf.example +++ b/docs/conf/modules.conf.example @@ -617,7 +617,7 @@ # killonbadreply - Whether to kill the user if they send the wrong # # PONG reply. # # # -# +# #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# # Channel cycle module: Adds the /CYCLE command which is a server-side diff --git a/src/modules/m_conn_waitpong.cpp b/src/modules/m_conn_waitpong.cpp index d2de63b3f..c093c6cd6 100644 --- a/src/modules/m_conn_waitpong.cpp +++ b/src/modules/m_conn_waitpong.cpp @@ -39,7 +39,7 @@ class ModuleWaitPong : public Module void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE { ConfigTag* tag = ServerInstance->Config->ConfValue("waitpong"); - sendsnotice = tag->getBool("sendsnotice", true); + sendsnotice = tag->getBool("sendsnotice", false); killonbadreply = tag->getBool("killonbadreply", true); } -- cgit v1.3.1-10-gc9f91 From aea5500b46890665ccb26d436217cb7014e93a32 Mon Sep 17 00:00:00 2001 From: iwalkalone Date: Fri, 6 Dec 2019 18:07:49 +0100 Subject: Fixing MatchCIDR call when checking proxy range --- src/modules/m_websocket.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/modules') diff --git a/src/modules/m_websocket.cpp b/src/modules/m_websocket.cpp index 5f0f9bcc8..8ec896847 100644 --- a/src/modules/m_websocket.cpp +++ b/src/modules/m_websocket.cpp @@ -363,10 +363,10 @@ class WebSocketHook : public IOHookMiddle for (WebSocketConfig::ProxyRanges::const_iterator iter = config.proxyranges.begin(); iter != config.proxyranges.end(); ++iter) { - if (InspIRCd::MatchCIDR(*iter, luser->GetIPString(), ascii_case_insensitive_map)) + if (InspIRCd::MatchCIDR(luser->GetIPString(), *iter, ascii_case_insensitive_map)) { // Give the user their real IP address. - if (realsa == luser->client_sa) + if (realsa != luser->client_sa) luser->SetClientIP(realsa); break; } -- cgit v1.3.1-10-gc9f91