From 4fcbbbe4fbc137841b47c8e2372477b85649270a Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 17 Dec 2016 21:44:22 -0500 Subject: Split ircdproto send functions out into separate services This makes it easier to see which send functions a protocol module implements as they are all explicitly registered by the module, and avoids the problem of subtly breaking other protocol modules when using inheritance. Also split the old "core" send implementations out into a module, and the TS6 ID generator --- modules/protocol/bahamut.cpp | 436 +++++++++++++++++------------- modules/protocol/charybdis.cpp | 204 +++++++++----- modules/protocol/hybrid.cpp | 445 +++++++++++++++++------------- modules/protocol/inspircd20.cpp | 581 ++++++++++++++++++++++------------------ modules/protocol/ngircd.cpp | 188 ++++++------- modules/protocol/plexus.cpp | 219 +++++++++------ modules/protocol/ratbox.cpp | 207 +++++++++----- modules/protocol/rfc1459.cpp | 142 +++++++++- modules/protocol/ts6.cpp | 71 +++++ modules/protocol/unreal.cpp | 480 ++++++++++++++++++--------------- 10 files changed, 1822 insertions(+), 1151 deletions(-) create mode 100644 modules/protocol/ts6.cpp (limited to 'modules/protocol') diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp index 46ffb3ea2..cdb05e7f7 100644 --- a/modules/protocol/bahamut.cpp +++ b/modules/protocol/bahamut.cpp @@ -23,103 +23,175 @@ #include "modules/protocol/rfc1459.h" #include "modules/protocol/bahamut.h" -class ChannelModeFlood : public ChannelModeParam +void bahamut::senders::Akill::Send(User* u, XLine* x) { - public: - ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam("FLOOD", modeChar, minusNoArg) { } - - bool IsValid(Anope::string &value) const override + if (x->IsRegex() || x->HasNickOrReal()) { - try + if (!u) { - Anope::string rest; - if (!value.empty() && value[0] != ':' && convertTo(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo(rest.substr(1), rest, false) > 0 && rest.empty()) - return true; + /* No user (this akill was just added), and contains nick and/or realname. Find users that match and ban them */ + for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) + if (x->GetManager()->Check(it->second, x)) + this->Send(it->second, x); + return; } - catch (const ConvertException &) { } - return false; + XLine *old = x; + + if (old->GetManager()->HasEntry("*@" + u->host)) + return; + + /* We can't akill x as it has a nick and/or realname included, so create a new akill for *@host */ + x = Serialize::New(); + x->SetMask("*@" + u->host); + x->SetBy(old->GetBy()); + x->SetExpires(old->GetExpires()); + x->SetReason(old->GetReason()); + x->SetID(old->GetID()); + old->GetManager()->AddXLine(x); + + Log(Config->GetClient("OperServ"), "akill") << "AKILL: Added an akill for " << x->GetMask() << " because " << u->GetMask() << "#" << u->realname << " matches " << old->GetMask(); } -}; -bahamut::Proto::Proto(Module *creator) : IRCDProto(creator, "Bahamut 1.8.x") -{ - DefaultPseudoclientModes = "+"; - CanSVSNick = true; - CanSNLine = true; - CanSQLine = true; - CanSQLineChannel = true; - CanSZLine = true; - CanSVSHold = true; - MaxModes = 60; + /* ZLine if we can instead */ + if (x->GetUser() == "*") + { + cidr a(x->GetHost()); + if (a.valid()) + { + IRCD->Send(u, x); + return; + } + } + + // Calculate the time left before this would expire, capping it at 2 days + time_t timeleft = x->GetExpires() - Anope::CurTime; + if (timeleft > 172800) + timeleft = 172800; + + Uplink::Send("AKILL", x->GetHost(), x->GetUser(), timeleft, x->GetBy(), Anope::CurTime, x->GetReason()); } -void bahamut::Proto::SendMode(const MessageSource &source, Channel *dest, const Anope::string &buf) +void bahamut::senders::AkillDel::Send(XLine* x) { - if (Servers::Capab.count("TSMODE") > 0) + if (x->IsRegex() || x->HasNickOrReal()) + return; + + /* ZLine if we can instead */ + if (x->GetUser() == "*") { - IRCMessage message(source, "MODE", dest->name, dest->creation_time); - message.TokenizeAndPush(buf); - Uplink::SendMessage(message); + cidr a(x->GetHost()); + if (a.valid()) + { + IRCD->Send(x); + return; + } } - else + + Uplink::Send("RAKKILL", x->GetHost(), x->GetUser()); +} + +void bahamut::senders::MessageChannel::Send(Channel* c) +{ + Anope::string modes = c->GetModes(true, true); + if (modes.empty()) + modes = "+"; + Uplink::Send("SJOIN", c->creation_time, c->name, modes, ""); +} + +void bahamut::senders::Join::Send(User* user, Channel* c, const ChannelStatus* status) +{ + Uplink::Send(user, "SJOIN", c->creation_time, c->name); + + if (status) { - IRCDProto::SendMode(source, dest, buf); + /* First save the channel status incase uc->Status == status */ + ChannelStatus cs = *status; + /* If the user is internally on the channel with flags, kill them so that + * the stacker will allow this. + */ + ChanUserContainer *uc = c->FindUser(user); + if (uc != NULL) + uc->status.Clear(); + + ServiceBot *setter = ServiceBot::Find(user->GetUID()); + for (size_t i = 0; i < cs.Modes().length(); ++i) + c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false); + + if (uc != NULL) + uc->status = cs; } } -void bahamut::Proto::SendMode(const MessageSource &source, User *u, const Anope::string &buf) +void bahamut::senders::Kill::Send(const MessageSource &source, const Anope::string &target, const Anope::string &reason) { - IRCMessage message(source, "SVSMODE", u->nick, u->timestamp); - message.TokenizeAndPush(buf); - Uplink::SendMessage(message); + Uplink::Send(source, "SVSKILL", target, reason); +} + +/* + Note: if the stamp is null 0, the below usage is correct of Bahamut +*/ +void bahamut::senders::Kill::Send(const MessageSource &source, User *user, const Anope::string &reason) +{ + Uplink::Send(source, "SVSKILL", user->nick, reason); } -void bahamut::Proto::SendGlobalNotice(ServiceBot *bi, Server *dest, const Anope::string &msg) +void bahamut::senders::Login::Send(User *u, NickServ::Nick *na) { - Uplink::Send(bi, "NOTICE", "$" + dest->GetName(), msg); + IRCD->SendMode(Config->GetClient("NickServ"), u, "+d {0}", u->signon); } -void bahamut::Proto::SendGlobalPrivmsg(ServiceBot *bi, Server *dest, const Anope::string &msg) +void bahamut::senders::Logout::Send(User *u) { - Uplink::Send(bi, "PRIVMSG", "$" + dest->GetName(), msg); + IRCD->SendMode(Config->GetClient("NickServ"), u, "+d 1"); } -/* SVSHOLD - set */ -void bahamut::Proto::SendSVSHold(const Anope::string &nick, time_t time) +void bahamut::senders::ModeChannel::Send(const MessageSource &source, Channel *channel, const Anope::string &modes) { - Uplink::Send(Me, "SVSHOLD", nick, time, "Being held for registered user"); + IRCMessage message(source, "MODE", channel->name, channel->creation_time); + message.TokenizeAndPush(modes); + Uplink::SendMessage(message); } -/* SVSHOLD - release */ -void bahamut::Proto::SendSVSHoldDel(const Anope::string &nick) +void bahamut::senders::ModeUser::Send(const MessageSource &source, User *user, const Anope::string &modes) { - Uplink::Send(Me, "SVSHOLD", nick, 0); + IRCMessage message(source, "SVSMODE", user->nick, user->timestamp); + message.TokenizeAndPush(modes); + Uplink::SendMessage(message); } -/* SQLINE */ -void bahamut::Proto::SendSQLine(User *, XLine *x) +void bahamut::senders::NickIntroduction::Send(User *user) { - Uplink::Send(Me, "SQLINE", x->GetMask(), x->GetReason()); + Anope::string modes = "+" + user->GetModes(); + Uplink::Send("NICK", user->nick, 1, user->timestamp, modes, user->GetIdent(), user->host, user->server->GetName(), 0, 0, user->realname); +} + +void bahamut::senders::NOOP::Send(Server* server, bool set) +{ + Uplink::Send("SVSNOOP", server->GetSID(), set ? "+" : "-"); +} + +void bahamut::senders::SGLine::Send(User*, XLine* x) +{ + Uplink::Send("SGLINE", x->GetMask().length(), x->GetMask() + ":" + x->GetReason()); } -/* UNSLINE */ -void bahamut::Proto::SendSGLineDel(XLine *x) +void bahamut::senders::SGLineDel::Send(XLine* x) { Uplink::Send("UNSGLINE", 0, x->GetMask()); } -/* UNSZLINE */ -void bahamut::Proto::SendSZLineDel(XLine *x) +void bahamut::senders::SQLine::Send(User*, XLine* x) { - /* this will likely fail so its only here for legacy */ - Uplink::Send("UNSZLINE", 0, x->GetHost()); - /* this is how we are supposed to deal with it */ - Uplink::Send("RAKILL", x->GetHost(), "*"); + Uplink::Send(Me, "SQLINE", x->GetMask(), x->GetReason()); +} + +void bahamut::senders::SQLineDel::Send(XLine* x) +{ + Uplink::Send("UNSQLINE", x->GetMask()); } -/* SZLINE */ -void bahamut::Proto::SendSZLine(User *, XLine *x) +void bahamut::senders::SZLine::Send(User*, XLine* x) { // Calculate the time left before this would expire, capping it at 2 days time_t timeleft = x->GetExpires() - Anope::CurTime; @@ -131,130 +203,69 @@ void bahamut::Proto::SendSZLine(User *, XLine *x) Uplink::Send("AKILL", x->GetHost(), "*", timeleft, x->GetBy(), Anope::CurTime, x->GetReason()); } -/* SVSNOOP */ -void bahamut::Proto::SendSVSNOOP(Server *server, bool set) +void bahamut::senders::SZLineDel::Send(XLine* x) { - Uplink::Send("SVSNOOP", server->GetName(), set ? "+" : "-"); + /* this will likely fail so its only here for legacy */ + Uplink::Send("UNSZLINE", 0, x->GetHost()); + /* this is how we are supposed to deal with it */ + Uplink::Send("RAKILL", x->GetHost(), "*"); } -/* SGLINE */ -void bahamut::Proto::SendSGLine(User *, XLine *x) +void bahamut::senders::SVSHold::Send(const Anope::string& nick, time_t t) { - Uplink::Send("SGLINE", x->GetMask().length(), x->GetMask() + ":" + x->GetReason()); + Uplink::Send(Me, "SVSHOLD", nick, t, "Being held for registered user"); } -/* RAKILL */ -void bahamut::Proto::SendAkillDel(XLine *x) +void bahamut::senders::SVSHoldDel::Send(const Anope::string& nick) { - if (x->IsRegex() || x->HasNickOrReal()) - return; - - /* ZLine if we can instead */ - if (x->GetUser() == "*") - { - cidr a(x->GetHost()); - if (a.valid()) - { - IRCD->SendSZLineDel(x); - return; - } - } - - Uplink::Send("RAKKILL", x->GetHost(), x->GetUser()); + Uplink::Send(Me, "SVSHOLD", nick, 0); } -/* TOPIC */ -void bahamut::Proto::SendTopic(const MessageSource &source, Channel *c) +void bahamut::senders::SVSNick::Send(User* u, const Anope::string& newnick, time_t ts) { - Uplink::Send(source, "TOPIC", c->name, c->topic_setter, c->topic_ts, c->topic); + Uplink::Send("SVSNICK", u->GetUID(), newnick, ts); } -/* UNSQLINE */ -void bahamut::Proto::SendSQLineDel(XLine *x) +void bahamut::senders::Topic::Send(const MessageSource &source, Channel *channel, const Anope::string &topic, time_t topic_ts, const Anope::string &topic_setter) { - Uplink::Send("UNSQLINE", x->GetMask()); + Uplink::Send(source, "TOPIC", channel->name, topic_setter, topic_ts, topic); } -/* JOIN - SJOIN */ -void bahamut::Proto::SendJoin(User *user, Channel *c, const ChannelStatus *status) +void bahamut::senders::Wallops::Send(const MessageSource &source, const Anope::string &msg) { - Uplink::Send(user, "SJOIN", c->creation_time, c->name); - - if (status) - { - /* First save the channel status incase uc->Status == status */ - ChannelStatus cs = *status; - /* If the user is internally on the channel with flags, kill them so that - * the stacker will allow this. - */ - ChanUserContainer *uc = c->FindUser(user); - if (uc != NULL) - uc->status.Clear(); - - ServiceBot *setter = ServiceBot::Find(user->GetUID()); - for (size_t i = 0; i < cs.Modes().length(); ++i) - c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false); - - if (uc != NULL) - uc->status = cs; - } + Uplink::Send(source, "GLOBOPS", msg); } -void bahamut::Proto::SendAkill(User *u, XLine *x) +#warning "not used" +class ChannelModeFlood : public ChannelModeParam { - if (x->IsRegex() || x->HasNickOrReal()) - { - if (!u) - { - /* No user (this akill was just added), and contains nick and/or realname. Find users that match and ban them */ - for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - if (x->GetManager()->Check(it->second, x)) - this->SendAkill(it->second, x); - return; - } - - XLine *old = x; - - if (old->GetManager()->HasEntry("*@" + u->host)) - return; - - /* We can't akill x as it has a nick and/or realname included, so create a new akill for *@host */ - x = Serialize::New(); - x->SetMask("*@" + u->host); - x->SetBy(old->GetBy()); - x->SetExpires(old->GetExpires()); - x->SetReason(old->GetReason()); - x->SetID(old->GetID()); - old->GetManager()->AddXLine(x); - - Log(Config->GetClient("OperServ"), "akill") << "AKILL: Added an akill for " << x->GetMask() << " because " << u->GetMask() << "#" << u->realname << " matches " << old->GetMask(); - } + public: + ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam("FLOOD", modeChar, minusNoArg) { } - /* ZLine if we can instead */ - if (x->GetUser() == "*") + bool IsValid(Anope::string &value) const override { - cidr a(x->GetHost()); - if (a.valid()) + try { - IRCD->SendSZLine(u, x); - return; + Anope::string rest; + if (!value.empty() && value[0] != ':' && convertTo(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo(rest.substr(1), rest, false) > 0 && rest.empty()) + return true; } - } - - // Calculate the time left before this would expire, capping it at 2 days - time_t timeleft = x->GetExpires() - Anope::CurTime; - if (timeleft > 172800) - timeleft = 172800; + catch (const ConvertException &) { } - Uplink::Send("AKILL", x->GetHost(), x->GetUser(), timeleft, x->GetBy(), Anope::CurTime, x->GetReason()); -} + return false; + } +}; -/* - Note: if the stamp is null 0, the below usage is correct of Bahamut -*/ -void bahamut::Proto::SendSVSKill(const MessageSource &source, User *user, const Anope::string &buf) +bahamut::Proto::Proto(Module *creator) : IRCDProto(creator, "Bahamut 1.8.x") { - Uplink::Send(source, "SVSKILL", user->nick, buf); + DefaultPseudoclientModes = "+"; + CanSVSNick = true; + CanSNLine = true; + CanSQLine = true; + CanSQLineChannel = true; + CanSZLine = true; + CanSVSHold = true; + MaxModes = 60; } void bahamut::Proto::SendBOB() @@ -267,23 +278,11 @@ void bahamut::Proto::SendEOB() Uplink::Send("BURST", 0); } -void bahamut::Proto::SendClientIntroduction(User *u) -{ - Anope::string modes = "+" + u->GetModes(); - Uplink::Send("NICK", u->nick, 1, u->timestamp, modes, u->GetIdent(), u->host, u->server->GetName(), 0, 0, u->realname); -} - -/* SERVER */ -void bahamut::Proto::SendServer(Server *server) -{ - Uplink::Send("SERVER", server->GetName(), server->GetHops(), server->GetDescription()); -} - -void bahamut::Proto::SendConnect() +void bahamut::Proto::Handshake() { Uplink::Send("PASS", Config->Uplinks[Anope::CurrentUplink].password, "TS"); Uplink::Send("CAPAB", "SSJOIN NOQUIT BURST UNCONNECT NICKIP TSMODE TS3"); - SendServer(Me); + IRCD->Send(Me); /* * SVINFO * parv[0] = sender prefix @@ -296,24 +295,6 @@ void bahamut::Proto::SendConnect() this->SendBOB(); } -void bahamut::Proto::SendChannel(Channel *c) -{ - Anope::string modes = c->GetModes(true, true); - if (modes.empty()) - modes = "+"; - Uplink::Send("SJOIN", c->creation_time, c->name, modes, ""); -} - -void bahamut::Proto::SendLogin(User *u, NickServ::Nick *) -{ - IRCD->SendMode(Config->GetClient("NickServ"), u, "+d {0}", u->signon); -} - -void bahamut::Proto::SendLogout(User *u) -{ - IRCD->SendMode(Config->GetClient("NickServ"), u, "+d 1"); -} - void bahamut::Burst::Run(MessageSource &source, const std::vector ¶ms) { Server *s = source.GetServer(); @@ -522,6 +503,45 @@ class ProtoBahamut : public Module bahamut::SJoin message_sjoin; bahamut::Topic message_topic; + /* Core message senders */ + rfc1459::senders::GlobalNotice sender_global_notice; + rfc1459::senders::GlobalPrivmsg sender_global_privmsg; + rfc1459::senders::Invite sender_invite; + rfc1459::senders::Kick sender_kick; + rfc1459::senders::NickChange sender_nickchange; + rfc1459::senders::Notice sender_notice; + rfc1459::senders::Part sender_part; + rfc1459::senders::Ping sender_ping; + rfc1459::senders::Pong sender_pong; + rfc1459::senders::Privmsg sender_privmsg; + rfc1459::senders::Quit sender_quit; + rfc1459::senders::MessageServer sender_server; + rfc1459::senders::SQuit sender_squit; + + /* Our message senders */ + bahamut::senders::Akill sender_akill; + bahamut::senders::AkillDel sender_akill_del; + bahamut::senders::MessageChannel sender_channel; + bahamut::senders::Join sender_join; + bahamut::senders::Kill sender_kill; + bahamut::senders::Login sender_login; + bahamut::senders::Logout sender_logout; + bahamut::senders::ModeChannel sender_mode_channel; + bahamut::senders::ModeUser sender_mode_user; + bahamut::senders::NickIntroduction sender_nickintroduction; + bahamut::senders::NOOP sender_noop; + bahamut::senders::SGLine sender_sgline; + bahamut::senders::SGLineDel sender_sgline_del; + bahamut::senders::SQLine sender_sqline; + bahamut::senders::SQLineDel sender_sqline_del; + bahamut::senders::SZLine sender_szline; + bahamut::senders::SZLineDel sender_szline_del; + bahamut::senders::SVSHold sender_svshold; + bahamut::senders::SVSHoldDel sender_svsholddel; + bahamut::senders::SVSNick sender_svsnick; + bahamut::senders::Topic sender_topic; + bahamut::senders::Wallops sender_wallops; + public: ProtoBahamut(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR) , EventHook(this) @@ -552,13 +572,55 @@ class ProtoBahamut : public Module , message_server(this) , message_sjoin(this) , message_topic(this) + + , sender_akill(this) + , sender_akill_del(this) + , sender_channel(this) + , sender_global_notice(this) + , sender_global_privmsg(this) + , sender_invite(this) + , sender_join(this) + , sender_kick(this) + , sender_kill(this) + , sender_login(this) + , sender_logout(this) + , sender_mode_channel(this) + , sender_mode_user(this) + , sender_nickchange(this) + , sender_nickintroduction(this) + , sender_noop(this) + , sender_topic(this) + , sender_notice(this) + , sender_part(this) + , sender_ping(this) + , sender_pong(this) + , sender_privmsg(this) + , sender_quit(this) + , sender_server(this) + , sender_sgline(this) + , sender_sgline_del(this) + , sender_sqline(this) + , sender_sqline_del(this) + , sender_szline(this) + , sender_szline_del(this) + , sender_squit(this) + , sender_svshold(this) + , sender_svsholddel(this) + , sender_svsnick(this) + , sender_wallops(this) + { + IRCD = &ircd_proto; + } + + ~ProtoBahamut() { + IRCD = nullptr; } void OnUserNickChange(User *u, const Anope::string &) override { u->RemoveModeInternal(Me, ModeManager::FindUserModeByName("REGISTERED")); - IRCD->SendLogout(u); + sender_logout.Send(u); } }; diff --git a/modules/protocol/charybdis.cpp b/modules/protocol/charybdis.cpp index 4488f5425..a808bb594 100644 --- a/modules/protocol/charybdis.cpp +++ b/modules/protocol/charybdis.cpp @@ -23,7 +23,6 @@ #include "modules/sasl.h" #include "modules/protocol/hybrid.h" #include "modules/protocol/charybdis.h" -#include "modules/protocol/ratbox.h" #include "modules/chanserv/mode.h" static Anope::string UplinkSID; @@ -39,9 +38,57 @@ class ChannelModeLargeBan : public ChannelMode } }; +void charybdis::senders::NickIntroduction::Send(User *user) +{ + Anope::string modes = "+" + user->GetModes(); + Uplink::Send(Me, "EUID", user->nick, 1, user->timestamp, modes, user->GetIdent(), user->host, 0, user->GetUID(), "*", "*", user->realname); +} +void charybdis::senders::SASL::Send(const ::SASL::Message& message) +{ + Server *s = Server::Find(message.target.substr(0, 3)); + Uplink::Send(Me, "ENCAP", s ? s->GetName() : message.target.substr(0, 3), "SASL", message.source, message.target, message.type, message.data, message.ext.empty() ? "" : message.ext); +} -charybdis::Proto::Proto(Module *creator) : IRCDProto(creator, "Charybdis 3.4+") - , ratbox("ratbox") +void charybdis::senders::SASLMechanisms::Send(const std::vector& mechanisms) +{ + Anope::string mechlist; + + for (unsigned int i = 0; i < mechanisms.size(); ++i) + { + mechlist += "," + mechanisms[i]; + } + + Uplink::Send(Me, "ENCAP", "*", "MECHLIST", mechlist.empty() ? "" : mechlist.substr(1)); +} + +void charybdis::senders::SVSHold::Send(const Anope::string& nick, time_t delay) +{ + Uplink::Send(Me, "ENCAP", "*", "NICKDELAY", delay, nick); +} + +void charybdis::senders::SVSHoldDel::Send(const Anope::string& nick) +{ + Uplink::Send(Me, "ENCAP", "*", "NICKDELAY", 0, nick); +} + +void charybdis::senders::SVSLogin::Send(const Anope::string& uid, const Anope::string& acc, const Anope::string& vident, const Anope::string& vhost) +{ + Server *s = Server::Find(uid.substr(0, 3)); + Uplink::Send(Me, "ENCAP", s ? s->GetName() : uid.substr(0, 3), "SVSLOGIN", uid, "*", vident.empty() ? "*" : vident, vhost.empty() ? "*" : vhost, acc); +} + +void charybdis::senders::VhostDel::Send(User* u) +{ + IRCD->Send(u, "", u->host); +} + +void charybdis::senders::VhostSet::Send(User* u, const Anope::string& vident, const Anope::string& vhost) +{ + Uplink::Send(Me, "ENCAP", "*", "CHGHOST", u->GetUID(), vhost); +} + +charybdis::Proto::Proto(Module *creator) : ts6::Proto(creator, "Charybdis 3.4+") + , ratbox(creator) { DefaultPseudoclientModes = "+oiS"; CanCertFP = true; @@ -56,7 +103,7 @@ charybdis::Proto::Proto(Module *creator) : IRCDProto(creator, "Charybdis 3.4+") MaxModes = 4; } -void charybdis::Proto::SendConnect() +void charybdis::Proto::Handshake() { Uplink::Send("PASS", Config->Uplinks[Anope::CurrentUplink].password, "TS", 6, Me->GetSID()); @@ -86,7 +133,7 @@ void charybdis::Proto::SendConnect() Uplink::Send("CAPAB", "BAN CHW CLUSTER ENCAP EOPMOD EUID EX IE KLN KNOCK MLOCK QS RSFNC SERVICES TB UNKLN"); /* Make myself known to myself in the serverlist */ - SendServer(Me); + Uplink::Send("SERVER", Me->GetName(), Me->GetHops() + 1, Me->GetDescription()); /* * Received: SVINFO 6 6 0 :1353235537 @@ -95,66 +142,9 @@ void charybdis::Proto::SendConnect() * arg[2] = '0' * arg[3] = server's idea of UTC time */ - Uplink::Send("SVINFO", 6, 6, Anope::CurTime); -} - -void charybdis::Proto::SendClientIntroduction(User *u) -{ - Anope::string modes = "+" + u->GetModes(); - Uplink::Send(Me, "EUID", u->nick, 1, u->timestamp, modes, u->GetIdent(), u->host, 0, u->GetUID(), "*", "*", u->realname); -} - -void charybdis::Proto::SendForceNickChange(User *u, const Anope::string &newnick, time_t when) -{ - Uplink::Send(Me, "ENCAP", u->server->GetName(), "RSFNC", u->GetUID(), - newnick, when, u->timestamp); + Uplink::Send("SVINFO", 6, 6, 0, Anope::CurTime); } -void charybdis::Proto::SendSVSHold(const Anope::string &nick, time_t delay) -{ - Uplink::Send(Me, "ENCAP", "*", "NICKDELAY", delay, nick); -} - -void charybdis::Proto::SendSVSHoldDel(const Anope::string &nick) -{ - Uplink::Send(Me, "ENCAP", "*", "NICKDELAY", 0, nick); -} - -void charybdis::Proto::SendVhost(User *u, const Anope::string &ident, const Anope::string &host) -{ - Uplink::Send(Me, "ENCAP", "*", "CHGHOST", u->GetUID(), host); -} - -void charybdis::Proto::SendVhostDel(User *u) -{ - this->SendVhost(u, "", u->host); -} - -void charybdis::Proto::SendSASLMechanisms(std::vector &mechanisms) -{ - Anope::string mechlist; - - for (unsigned i = 0; i < mechanisms.size(); ++i) - { - mechlist += "," + mechanisms[i]; - } - - Uplink::Send(Me, "ENCAP", "*", "MECHLIST", mechlist.empty() ? "" : mechlist.substr(1)); -} - -void charybdis::Proto::SendSASLMessage(const SASL::Message &message) -{ - Server *s = Server::Find(message.target.substr(0, 3)); - Uplink::Send(Me, "ENCAP", s ? s->GetName() : message.target.substr(0, 3), "SASL", message.source, message.target, message.type, message.data, message.ext.empty() ? "" : message.ext); -} - -void charybdis::Proto::SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) -{ - Server *s = Server::Find(uid.substr(0, 3)); - Uplink::Send(Me, "ENCAP", s ? s->GetName() : uid.substr(0, 3), "SVSLOGIN", uid, "*", vident.empty() ? "*" : vident, vhost.empty() ? "*" : vhost, acc); -} - - void charybdis::Encap::Run(MessageSource &source, const std::vector ¶ms) { // In a burst, states that the source user is logged in as the account. @@ -228,7 +218,7 @@ void charybdis::ServerMessage::Run(MessageSource &source, const std::vectorSendPing(Me->GetName(), params[0]); + IRCD->Send(Me->GetName(), params[0]); } // we can't use this function from ratbox because we set a local variable here @@ -282,6 +272,48 @@ class ProtoCharybdis : public Module hybrid::TMode message_tmode; ratbox::UID message_uid; + /* Core message senders */ + rfc1459::senders::Invite sender_invite; + rfc1459::senders::Kick sender_kick; + rfc1459::senders::Kill sender_svskill; + rfc1459::senders::ModeChannel sender_mode_chan; + rfc1459::senders::ModeUser sender_mode_user; + rfc1459::senders::NickChange sender_nickchange; + rfc1459::senders::Notice sender_notice; + rfc1459::senders::Part sender_part; + rfc1459::senders::Ping sender_ping; + rfc1459::senders::Pong sender_pong; + rfc1459::senders::Privmsg sender_privmsg; + rfc1459::senders::Quit sender_quit; + rfc1459::senders::SQuit sender_squit; + + hybrid::senders::Akill sender_akill; + hybrid::senders::AkillDel sender_akill_del; + hybrid::senders::MessageChannel sender_channel; + hybrid::senders::GlobalNotice sender_global_notice; + hybrid::senders::GlobalPrivmsg sender_global_privmsg; + hybrid::senders::Join sender_join; + hybrid::senders::MessageServer sender_server; + hybrid::senders::SGLine sender_sgline; + hybrid::senders::SGLineDel sender_sgline_del; + hybrid::senders::SVSHold sender_svshold; + hybrid::senders::SVSHoldDel sender_svsholddel; + + ratbox::senders::Login sender_login; + ratbox::senders::Logout sender_logout; + ratbox::senders::SQLine sender_sqline; + ratbox::senders::SQLineDel sender_sqline_del; + ratbox::senders::SVSNick sender_svsnick; + ratbox::senders::Topic sender_topic; + ratbox::senders::Wallops sender_wallops; + + charybdis::senders::NickIntroduction sender_nickintroduction; + charybdis::senders::SASL sender_sasl; + charybdis::senders::SASLMechanisms sender_sasl_mechs; + charybdis::senders::SVSLogin sender_svslogin; + charybdis::senders::VhostDel sender_vhost_del; + charybdis::senders::VhostSet sender_vhost_set; + bool use_server_side_mlock; public: @@ -322,7 +354,51 @@ class ProtoCharybdis : public Module , message_tb(this) , message_tmode(this) , message_uid(this) + + , sender_akill(this) + , sender_akill_del(this) + , sender_channel(this) + , sender_global_notice(this) + , sender_global_privmsg(this) + , sender_invite(this) + , sender_join(this) + , sender_kick(this) + , sender_svskill(this) + , sender_login(this) + , sender_logout(this) + , sender_mode_chan(this) + , sender_mode_user(this) + , sender_nickchange(this) + , sender_nickintroduction(this) + , sender_notice(this) + , sender_part(this) + , sender_ping(this) + , sender_pong(this) + , sender_privmsg(this) + , sender_quit(this) + , sender_server(this) + , sender_sasl(this) + , sender_sasl_mechs(this) + , sender_sgline(this) + , sender_sgline_del(this) + , sender_sqline(this) + , sender_sqline_del(this) + , sender_squit(this) + , sender_svshold(this) + , sender_svsholddel(this) + , sender_svslogin(this) + , sender_svsnick(this) + , sender_topic(this) + , sender_vhost_del(this) + , sender_vhost_set(this) + , sender_wallops(this) + { + IRCD = &ircd_proto; + } + + ~ProtoCharybdis() { + IRCD = nullptr; } void OnReload(Configuration::Conf *conf) override diff --git a/modules/protocol/hybrid.cpp b/modules/protocol/hybrid.cpp index 922083587..2cb508f0e 100644 --- a/modules/protocol/hybrid.cpp +++ b/modules/protocol/hybrid.cpp @@ -18,134 +18,14 @@ * along with this program; if not, see see . */ -/* Dependencies: anope_protocol.rfc1459 */ +/* Dependencies: anope_protocol.rfc1459,anope_protocol.ts6 */ #include "module.h" #include "modules/protocol/hybrid.h" static Anope::string UplinkSID; - -ServiceBot *hybrid::Proto::FindIntroduced() -{ - ServiceBot *bi = Config->GetClient("OperServ"); - if (bi && bi->introduced) - return bi; - - for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - { - User *u = it->second; - if (u->type == UserType::BOT) - { - bi = anope_dynamic_static_cast(u); - if (bi->introduced) - return bi; - } - } - - return NULL; -} - -void hybrid::Proto::SendSVSKill(const MessageSource &source, User *u, const Anope::string &buf) -{ - IRCDProto::SendSVSKill(source, u, buf); - u->KillInternal(source, buf); -} - -hybrid::Proto::Proto(Module *creator) : IRCDProto(creator, "Hybrid 8.2.x") -{ - DefaultPseudoclientModes = "+oi"; - CanSVSNick = true; - CanSVSHold = true; - CanSVSJoin = true; - CanSNLine = true; - CanSQLine = true; - CanSQLineChannel = true; - CanSZLine = true; - CanCertFP = true; - CanSetVHost = true; - RequiresID = true; - MaxModes = 6; -} - -void hybrid::Proto::SendInvite(const MessageSource &source, Channel *c, User *u) -{ - Uplink::Send(source, "INVITE", u->GetUID(), c->name, c->creation_time); -} - -void hybrid::Proto::SendGlobalNotice(ServiceBot *bi, Server *dest, const Anope::string &msg) -{ - Uplink::Send(bi, "NOTICE", "$$" + dest->GetName(), msg); -} - -void hybrid::Proto::SendGlobalPrivmsg(ServiceBot *bi, Server *dest, const Anope::string &msg) -{ - Uplink::Send(bi, "PRIVMSG", "$$" + dest->GetName(), msg); -} - -void hybrid::Proto::SendSQLine(User *, XLine *x) -{ - Uplink::Send(FindIntroduced(), "RESV", "*", x->GetExpires() ? x->GetExpires() - Anope::CurTime : 0, x->GetMask(), x->GetReason()); -} - -void hybrid::Proto::SendSGLineDel(XLine *x) -{ - Uplink::Send(Config->GetClient("OperServ"), "UNXLINE", "*", x->GetMask()); -} - -void hybrid::Proto::SendSGLine(User *, XLine *x) -{ - Uplink::Send(Config->GetClient("OperServ"), "XLINE", "*", x->GetMask(), x->GetExpires() ? x->GetExpires() - Anope::CurTime : 0, x->GetReason()); -} - -void hybrid::Proto::SendSZLineDel(XLine *x) -{ - Uplink::Send(Config->GetClient("OperServ"), "UNDLINE", "*", x->GetHost()); -} - -void hybrid::Proto::SendSZLine(User *, XLine *x) -{ - /* Calculate the time left before this would expire, capping it at 2 days */ - time_t timeleft = x->GetExpires() - Anope::CurTime; - - if (timeleft > 172800 || !x->GetExpires()) - timeleft = 172800; - - Uplink::Send(Config->GetClient("OperServ"), "DLINE", "*", timeleft, x->GetHost(), x->GetReason()); -} - -void hybrid::Proto::SendAkillDel(XLine *x) -{ - if (x->IsRegex() || x->HasNickOrReal()) - return; - - Uplink::Send(Config->GetClient("OperServ"), "UNKLINE", "*", x->GetUser(), x->GetHost()); -} - -void hybrid::Proto::SendSQLineDel(XLine *x) -{ - Uplink::Send(Config->GetClient("OperServ"), "UNRESV", "*", x->GetMask()); -} - -void hybrid::Proto::SendJoin(User *u, Channel *c, const ChannelStatus *status) -{ - /* - * Note that we must send our modes with the SJOIN and can not add them to the - * mode stacker because ircd-hybrid does not allow *any* client to op itself - */ - Uplink::Send("SJOIN", c->creation_time, c->name, "+" + c->GetModes(true, true), (status != NULL ? status->BuildModePrefixList() : "") + u->GetUID()); - - /* And update our internal status for this user since this is not going through our mode handling system */ - if (status) - { - ChanUserContainer *uc = c->FindUser(u); - - if (uc) - uc->status = *status; - } -} - -void hybrid::Proto::SendAkill(User *u, XLine *x) +void hybrid::senders::Akill::Send(User* u, XLine* x) { if (x->IsRegex() || x->HasNickOrReal()) { @@ -157,7 +37,7 @@ void hybrid::Proto::SendAkill(User *u, XLine *x) */ for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) if (x->GetManager()->Check(it->second, x)) - this->SendAkill(it->second, x); + this->Send(it->second, x); return; } @@ -191,111 +71,132 @@ void hybrid::Proto::SendAkill(User *u, XLine *x) Uplink::Send(Config->GetClient("OperServ"), "KLINE", timeleft, x->GetUser(), x->GetHost(), x->GetReason()); } -void hybrid::Proto::SendServer(Server *server) +void hybrid::senders::AkillDel::Send(XLine* x) { - if (server == Me) - Uplink::Send("SERVER", server->GetName(), server->GetHops() + 1, server->GetDescription()); - else - Uplink::Send(Me, "SID", server->GetName(), server->GetHops() + 1, server->GetSID(), server->GetDescription()); + if (x->IsRegex() || x->HasNickOrReal()) + return; + + Uplink::Send(Config->GetClient("OperServ"), "UNKLINE", "*", x->GetUser(), x->GetHost()); } -void hybrid::Proto::SendConnect() +void hybrid::senders::MessageChannel::Send(Channel* c) { - Uplink::Send("PASS", Config->Uplinks[Anope::CurrentUplink].password, "TS", 6, Me->GetSID()); - - /* - * As of January 13, 2016, ircd-hybrid-8 supports the following capabilities - * which are required to work with IRC-services: - * - * QS - Can handle quit storm removal - * EX - Can do channel +e exemptions - * IE - Can do invite exceptions - * CHW - Can do channel wall @# - * TBURST - Supports topic burst - * ENCAP - Supports ENCAP - * HOPS - Supports HalfOps - * SVS - Supports services - * EOB - Supports End Of Burst message - */ - Uplink::Send("CAPAB", "QS EX CHW IE ENCAP TBURST SVS HOPS EOB"); + Anope::string modes = c->GetModes(true, true); - SendServer(Me); + if (modes.empty()) + modes = "+"; - Uplink::Send("SVINFO", 6, 6, 0, Anope::CurTime); + Uplink::Send("SJOIN", c->creation_time, c->name, modes, ""); } -void hybrid::Proto::SendClientIntroduction(User *u) +void hybrid::senders::GlobalNotice::Send(const MessageSource &source, Server *dest, const Anope::string &msg) { - Anope::string modes = "+" + u->GetModes(); + Uplink::Send(source, "NOTICE", "$$" + dest->GetName(), msg); +} - Uplink::Send(Me, "UID", u->nick, 1, u->timestamp, modes, u->GetIdent(), u->host, "0.0.0.0", u->GetUID(), "*", u->realname); +void hybrid::senders::GlobalPrivmsg::Send(const MessageSource& source, Server* dest, const Anope::string& msg) +{ + Uplink::Send(source, "PRIVMSG", "$$" + dest->GetName(), msg); } -void hybrid::Proto::SendEOB() +void hybrid::senders::Invite::Send(const MessageSource &source, Channel *chan, User *user) { - Uplink::Send(Me, "EOB"); + Uplink::Send(source, "INVITE", user->GetUID(), chan->name, chan->creation_time); } -void hybrid::Proto::SendMode(const MessageSource &source, User *u, const Anope::string &buf) +void hybrid::senders::Join::Send(User* u, Channel* c, const ChannelStatus* status) { - IRCMessage message(source, "SVSMODE", u->GetUID(), u->timestamp); - message.TokenizeAndPush(buf); - Uplink::SendMessage(message); + /* + * Note that we must send our modes with the SJOIN and can not add them to the + * mode stacker because ircd-hybrid does not allow *any* client to op itself + */ + Uplink::Send("SJOIN", c->creation_time, c->name, "+" + c->GetModes(true, true), (status != NULL ? status->BuildModePrefixList() : "") + u->GetUID()); + + /* And update our internal status for this user since this is not going through our mode handling system */ + if (status) + { + ChanUserContainer *uc = c->FindUser(u); + + if (uc) + uc->status = *status; + } } -void hybrid::Proto::SendLogin(User *u, NickServ::Nick *na) +void hybrid::senders::Login::Send(User *u, NickServ::Nick *na) { IRCD->SendMode(Config->GetClient("NickServ"), u, "+d {0}", na->GetAccount()->GetDisplay()); } -void hybrid::Proto::SendLogout(User *u) +void hybrid::senders::Logout::Send(User *u) { IRCD->SendMode(Config->GetClient("NickServ"), u, "+d *"); } -void hybrid::Proto::SendChannel(Channel *c) +void hybrid::senders::ModeUser::Send(const MessageSource &source, User *user, const Anope::string &modes) { - Anope::string modes = c->GetModes(true, true); + IRCMessage message(source, "SVSMODE", user->GetUID(), user->timestamp); + message.TokenizeAndPush(modes); + Uplink::SendMessage(message); +} - if (modes.empty()) - modes = "+"; +void hybrid::senders::NickIntroduction::Send(User *user) +{ + Anope::string modes = "+" + user->GetModes(); + Uplink::Send(Me, "UID", user->nick, 1, user->timestamp, modes, user->GetIdent(), user->host, "0.0.0.0", user->GetUID(), "*", user->realname); +} - Uplink::Send("SJOIN", c->creation_time, c->name, modes, ""); +void hybrid::senders::MessageServer::Send(Server* server) +{ + Uplink::Send(Me, "SID", server->GetName(), server->GetHops() + 1, server->GetSID(), server->GetDescription()); +} + +void hybrid::senders::SGLine::Send(User*, XLine* x) +{ + Uplink::Send(Config->GetClient("OperServ"), "XLINE", "*", x->GetMask(), x->GetExpires() ? x->GetExpires() - Anope::CurTime : 0, x->GetReason()); } -void hybrid::Proto::SendTopic(const MessageSource &source, Channel *c) +void hybrid::senders::SGLineDel::Send(XLine* x) { - Uplink::Send(source, "TBURST", c->creation_time, c->name, c->topic_ts, c->topic_setter, c->topic); + Uplink::Send(Config->GetClient("OperServ"), "UNXLINE", "*", x->GetMask()); } -void hybrid::Proto::SendForceNickChange(User *u, const Anope::string &newnick, time_t when) +void hybrid::senders::SQLine::Send(User*, XLine* x) { - Uplink::Send(Me, "SVSNICK", u->GetUID(), newnick, when); +#warning "findintroduced" + //Uplink::Send(FindIntroduced(), "RESV", "*", x->GetExpires() ? x->GetExpires() - Anope::CurTime : 0, x->GetMask(), x->GetReason()); } -void hybrid::Proto::SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &) +void hybrid::senders::SQLineDel::Send(XLine* x) { - Uplink::Send(source, "SVSJOIN", u->GetUID(), chan); + Uplink::Send(Config->GetClient("OperServ"), "UNRESV", "*", x->GetMask()); } -void hybrid::Proto::SendSVSPart(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string ¶m) +void hybrid::senders::SZLine::Send(User*, XLine* x) { - if (!param.empty()) - Uplink::Send(source, "SVSPART", u->GetUID(), chan, param); - else - Uplink::Send(source, "SVSPART", u->GetUID(), chan); + /* Calculate the time left before this would expire, capping it at 2 days */ + time_t timeleft = x->GetExpires() - Anope::CurTime; + + if (timeleft > 172800 || !x->GetExpires()) + timeleft = 172800; + + Uplink::Send(Config->GetClient("OperServ"), "DLINE", "*", timeleft, x->GetHost(), x->GetReason()); } -void hybrid::Proto::SendSVSHold(const Anope::string &nick, time_t t) +void hybrid::senders::SZLineDel::Send(XLine* x) +{ + Uplink::Send(Config->GetClient("OperServ"), "UNDLINE", "*", x->GetHost()); +} + +void hybrid::senders::SVSHold::Send(const Anope::string&, time_t) { #if 0 XLine x(nick, Me->GetName(), Anope::CurTime + t, "Being held for registered user"); this->SendSQLine(NULL, &x); #endif } -#warning "xline on stack" -void hybrid::Proto::SendSVSHoldDel(const Anope::string &nick) +#warning "xline on stack" +void hybrid::senders::SVSHoldDel::Send(const Anope::string&) { #if 0 XLine x(nick); @@ -303,19 +204,113 @@ void hybrid::Proto::SendSVSHoldDel(const Anope::string &nick) #endif } -void hybrid::Proto::SendVhost(User *u, const Anope::string &ident, const Anope::string &host) +void hybrid::senders::SVSJoin::Send(const MessageSource& source, User* u, const Anope::string& chan, const Anope::string& key) +{ + Uplink::Send(source, "SVSJOIN", u->GetUID(), chan); +} + +void hybrid::senders::SVSNick::Send(User* u, const Anope::string& newnick, time_t ts) { - u->SetMode(Config->GetClient("HostServ"), "CLOAK", host); + Uplink::Send(Me, "SVSNICK", u->GetUID(), newnick, ts); } -void hybrid::Proto::SendVhostDel(User *u) +void hybrid::senders::SVSPart::Send(const MessageSource& source, User* u, const Anope::string& chan, const Anope::string& reason) +{ + if (!reason.empty()) + Uplink::Send(source, "SVSPART", u->GetUID(), chan, reason); + else + Uplink::Send(source, "SVSPART", u->GetUID(), chan); +} + +void hybrid::senders::Topic::Send(const MessageSource &source, Channel *channel, const Anope::string &topic, time_t topic_ts, const Anope::string &topic_setter) +{ + Uplink::Send(source, "TBURST", channel->creation_time, channel->name, topic_ts, topic_setter, topic); +} + +void hybrid::senders::VhostDel::Send(User* u) { u->RemoveMode(Config->GetClient("HostServ"), "CLOAK", u->host); } +void hybrid::senders::VhostSet::Send(User* u, const Anope::string& vident, const Anope::string& vhost) +{ + u->SetMode(Config->GetClient("HostServ"), "CLOAK", vhost); +} + +void hybrid::senders::Wallops::Send(const MessageSource &source, const Anope::string &msg) +{ + Uplink::Send(source, "GLOBOPS", msg); +} + +ServiceBot *hybrid::Proto::FindIntroduced() +{ + ServiceBot *bi = Config->GetClient("OperServ"); + if (bi && bi->introduced) + return bi; + + for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) + { + User *u = it->second; + if (u->type == UserType::BOT) + { + bi = anope_dynamic_static_cast(u); + if (bi->introduced) + return bi; + } + } + + return NULL; +} + +hybrid::Proto::Proto(Module *creator) : ts6::Proto(creator, "Hybrid 8.2.x") +{ + DefaultPseudoclientModes = "+oi"; + CanSVSNick = true; + CanSVSHold = true; + CanSVSJoin = true; + CanSNLine = true; + CanSQLine = true; + CanSQLineChannel = true; + CanSZLine = true; + CanCertFP = true; + CanSetVHost = true; + RequiresID = true; + MaxModes = 6; +} + +void hybrid::Proto::Handshake() +{ + Uplink::Send("PASS", Config->Uplinks[Anope::CurrentUplink].password, "TS", 6, Me->GetSID()); + + /* + * As of January 13, 2016, ircd-hybrid-8 supports the following capabilities + * which are required to work with IRC-services: + * + * QS - Can handle quit storm removal + * EX - Can do channel +e exemptions + * IE - Can do invite exceptions + * CHW - Can do channel wall @# + * TBURST - Supports topic burst + * ENCAP - Supports ENCAP + * HOPS - Supports HalfOps + * SVS - Supports services + * EOB - Supports End Of Burst message + */ + Uplink::Send("CAPAB", "QS EX CHW IE ENCAP TBURST SVS HOPS EOB"); + + Uplink::Send("SERVER", Me->GetName(), Me->GetHops() + 1, Me->GetDescription()); + + Uplink::Send("SVINFO", 6, 6, 0, Anope::CurTime); +} + +void hybrid::Proto::SendEOB() +{ + Uplink::Send(Me, "EOB"); +} + bool hybrid::Proto::IsIdentValid(const Anope::string &ident) { - if (ident.empty() || ident.length() > Config->GetBlock("networkinfo")->Get("userlen")) + if (ident.empty() || ident.length() > Config->GetBlock("networkinfo")->Get("userlen")) return false; Anope::string chars = "~}|{ `_^]\\[ .-$"; @@ -410,7 +405,7 @@ void hybrid::ServerMessage::Run(MessageSource &source, const std::vectorSendPing(Me->GetName(), params[0]); + IRCD->Send(Me->GetName(), params[0]); } void hybrid::SID::Run(MessageSource &source, const std::vector ¶ms) @@ -425,7 +420,7 @@ void hybrid::SID::Run(MessageSource &source, const std::vector &p new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[3], params[2]); - IRCD->SendPing(Me->GetName(), params[0]); + IRCD->Send(Me->GetName(), params[0]); } void hybrid::SJoin::Run(MessageSource &source, const std::vector ¶ms) @@ -621,6 +616,45 @@ class ProtoHybrid : public Module hybrid::TMode message_tmode; hybrid::UID message_uid; + /* Core message senders */ + rfc1459::senders::Kick sender_kick; + rfc1459::senders::Kill sender_svskill; + rfc1459::senders::ModeChannel sender_mode_chan; + rfc1459::senders::NickChange sender_nickchange; + rfc1459::senders::Notice sender_notice; + rfc1459::senders::Part sender_part; + rfc1459::senders::Ping sender_ping; + rfc1459::senders::Pong sender_pong; + rfc1459::senders::Privmsg sender_privmsg; + rfc1459::senders::Quit sender_quit; + rfc1459::senders::SQuit sender_squit; + + hybrid::senders::Akill sender_akill; + hybrid::senders::AkillDel sender_akill_del; + hybrid::senders::MessageChannel sender_channel; + hybrid::senders::GlobalNotice sender_global_notice; + hybrid::senders::GlobalPrivmsg sender_global_privmsg; + hybrid::senders::Invite sender_invite; + hybrid::senders::Join sender_join; + hybrid::senders::Login sender_login; + hybrid::senders::Logout sender_logout; + hybrid::senders::ModeUser sender_mode_user; + hybrid::senders::NickIntroduction sender_nickintroduction; + hybrid::senders::MessageServer sender_server; + hybrid::senders::SGLine sender_sgline; + hybrid::senders::SGLineDel sender_sgline_del; + hybrid::senders::SQLine sender_sqline; + hybrid::senders::SQLineDel sender_sqline_del; + hybrid::senders::SZLine sender_szline; + hybrid::senders::SZLineDel sender_szline_del; + hybrid::senders::SVSHold sender_svshold; + hybrid::senders::SVSHoldDel sender_svsholddel; + hybrid::senders::SVSNick sender_svsnick; + hybrid::senders::Topic sender_topic; + hybrid::senders::VhostDel sender_vhost_del; + hybrid::senders::VhostSet sender_vhost_set; + hybrid::senders::Wallops sender_wallops; + public: ProtoHybrid(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR) , EventHook(this) @@ -658,7 +692,50 @@ public: , message_tmode(this) , message_uid(this) , message_certfp(this) + + , sender_akill(this) + , sender_akill_del(this) + , sender_channel(this) + , sender_global_notice(this) + , sender_global_privmsg(this) + , sender_invite(this) + , sender_join(this) + , sender_kick(this) + , sender_svskill(this) + , sender_login(this) + , sender_logout(this) + , sender_mode_chan(this) + , sender_mode_user(this) + , sender_nickchange(this) + , sender_nickintroduction(this) + , sender_notice(this) + , sender_part(this) + , sender_ping(this) + , sender_pong(this) + , sender_privmsg(this) + , sender_quit(this) + , sender_server(this) + , sender_sgline(this) + , sender_sgline_del(this) + , sender_sqline(this) + , sender_sqline_del(this) + , sender_szline(this) + , sender_szline_del(this) + , sender_squit(this) + , sender_svshold(this) + , sender_svsholddel(this) + , sender_svsnick(this) + , sender_topic(this) + , sender_vhost_del(this) + , sender_vhost_set(this) + , sender_wallops(this) + { + IRCD = &ircd_proto; + } + + ~ProtoHybrid() { + IRCD = nullptr; } void OnUserNickChange(User *u, const Anope::string &) override diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp index a8caac27a..011ecfd13 100644 --- a/modules/protocol/inspircd20.cpp +++ b/modules/protocol/inspircd20.cpp @@ -17,7 +17,7 @@ * along with this program; if not, see see . */ -/* Dependencies: anope_protocol.rfc1459 */ +/* Dependencies: anope_protocol.rfc1459,anope_protocol.ts6,anope_protocol.hybrid,anope_protocol.bahamut */ #include "module.h" #include "modules/sasl.h" @@ -25,6 +25,8 @@ #include "modules/chanserv/set.h" #include "modules/protocol/rfc1459.h" #include "modules/protocol/inspircd20.h" +#include "modules/protocol/bahamut.h" +#include "modules/protocol/hybrid.h" struct SASLUser { @@ -37,129 +39,7 @@ static std::list saslusers; static Anope::string rsquit_server, rsquit_id; static unsigned int spanningtree_proto_ver = 0; -void inspircd20::Proto::SendSVSKill(const MessageSource &source, User *user, const Anope::string &buf) -{ - IRCDProto::SendSVSKill(source, user, buf); - user->KillInternal(source, buf); -} - -void inspircd20::Proto::SendChgIdentInternal(const Anope::string &nick, const Anope::string &vIdent) -{ - if (!Servers::Capab.count("CHGIDENT")) - Log() << "CHGIDENT not loaded!"; - else - Uplink::Send(Me, "CHGIDENT", nick, vIdent); -} - -void inspircd20::Proto::SendChgHostInternal(const Anope::string &nick, const Anope::string &vhost) -{ - if (!Servers::Capab.count("CHGHOST")) - Log() << "CHGHOST not loaded!"; - else - Uplink::Send(Me, "CHGHOST", nick, vhost); -} - -void inspircd20::Proto::SendAddLine(const Anope::string &xtype, const Anope::string &mask, time_t duration, const Anope::string &addedby, const Anope::string &reason) -{ - Uplink::Send(Me, "ADDLINE", xtype, mask, addedby, Anope::CurTime, duration, reason); -} - -void inspircd20::Proto::SendDelLine(const Anope::string &xtype, const Anope::string &mask) -{ - Uplink::Send(Me, "DELLINE", xtype, mask); -} - -inspircd20::Proto::Proto(Module *creator) : IRCDProto(creator, "InspIRCd 2.0") -{ - DefaultPseudoclientModes = "+I"; - CanSVSNick = true; - CanSVSJoin = true; - CanSetVHost = true; - CanSetVIdent = true; - CanSQLine = true; - CanSZLine = true; - CanSVSHold = true; - CanCertFP = true; - RequiresID = true; - MaxModes = 20; -} - -void inspircd20::Proto::SendConnect() -{ - Uplink::Send("CAPAB START 1202"); - Uplink::Send("CAPAB CAPABILITIES :PROTOCOL=1202"); - Uplink::Send("CAPAB END"); - SendServer(Me); -} - -void inspircd20::Proto::SendGlobalNotice(ServiceBot *bi, Server *dest, const Anope::string &msg) -{ - Uplink::Send(bi, "NOTICE", "$" + dest->GetName(), msg); -} - -void inspircd20::Proto::SendGlobalPrivmsg(ServiceBot *bi, Server *dest, const Anope::string &msg) -{ - Uplink::Send(bi, "PRIVMSG", "$" + dest->GetName(), msg); -} - -void inspircd20::Proto::SendAkillDel(XLine *x) -{ - /* InspIRCd may support regex bans */ - if (x->IsRegex() && Servers::Capab.count("RLINE")) - { - Anope::string mask = x->GetMask(); - size_t h = mask.find('#'); - if (h != Anope::string::npos) - mask = mask.replace(h, 1, ' '); - SendDelLine("R", mask); - return; - } - else if (x->IsRegex() || x->HasNickOrReal()) - return; - - /* ZLine if we can instead */ - if (x->GetUser() == "*") - { - cidr addr(x->GetHost()); - if (addr.valid()) - { - IRCD->SendSZLineDel(x); - return; - } - } - - SendDelLine("G", x->GetUser() + "@" + x->GetHost()); -} - -void inspircd20::Proto::SendTopic(const MessageSource &source, Channel *c) -{ - if (Servers::Capab.count("SVSTOPIC")) - { - Uplink::Send(c->ci->WhoSends(), "SVSTOPIC", c->name, c->topic_ts, c->topic_setter, c->topic); - } - else - { - /* If the last time a topic was set is after the TS we want for this topic we must bump this topic's timestamp to now */ - time_t ts = c->topic_ts; - if (c->topic_time > ts) - ts = Anope::CurTime; - /* But don't modify c->topic_ts, it should remain set to the real TS we want as ci->last_topic_time pulls from it */ - Uplink::Send(source, "FTOPIC", c->name, ts, c->topic_setter, c->topic); - } -} - -void inspircd20::Proto::SendVhostDel(User *u) -{ - if (u->HasMode("CLOAK")) - this->SendChgHostInternal(u->nick, u->chost); - else - this->SendChgHostInternal(u->nick, u->host); - - if (Servers::Capab.count("CHGIDENT") && u->GetIdent() != u->GetVIdent()) - this->SendChgIdentInternal(u->nick, u->GetIdent()); -} - -void inspircd20::Proto::SendAkill(User *u, XLine *x) +void inspircd20::senders::Akill::Send(User* u, XLine* x) { // Calculate the time left before this would expire, capping it at 2 days time_t timeleft = x->GetExpires() - Anope::CurTime; @@ -173,7 +53,7 @@ void inspircd20::Proto::SendAkill(User *u, XLine *x) size_t h = mask.find('#'); if (h != Anope::string::npos) mask = mask.replace(h, 1, ' '); - SendAddLine("R", mask, timeleft, x->GetBy(), x->GetReason()); + proto->SendAddLine("R", mask, timeleft, x->GetBy(), x->GetReason()); return; } else if (x->IsRegex() || x->HasNickOrReal()) @@ -183,7 +63,7 @@ void inspircd20::Proto::SendAkill(User *u, XLine *x) /* No user (this akill was just added), and contains nick and/or realname. Find users that match and ban them */ for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) if (x->GetManager()->Check(it->second, x)) - this->SendAkill(it->second, x); + this->Send(it->second, x); return; } @@ -209,70 +89,49 @@ void inspircd20::Proto::SendAkill(User *u, XLine *x) cidr addr(x->GetHost()); if (addr.valid()) { - IRCD->SendSZLine(u, x); + IRCD->Send(u, x); return; } } - SendAddLine("G", x->GetUser() + "@" + x->GetHost(), timeleft, x->GetBy(), x->GetReason()); + proto->SendAddLine("G", x->GetUser() + "@" + x->GetHost(), timeleft, x->GetBy(), x->GetReason()); } -void inspircd20::Proto::SendNumeric(int numeric, User *dest, IRCMessage &message) +void inspircd20::senders::AkillDel::Send(XLine* x) { - std::vector params = message.GetParameters(); - if (params.empty()) + /* InspIRCd may support regex bans */ + if (x->IsRegex() && Servers::Capab.count("RLINE")) + { + Anope::string mask = x->GetMask(); + size_t h = mask.find('#'); + if (h != Anope::string::npos) + mask = mask.replace(h, 1, ' '); + proto->SendDelLine("R", mask); + return; + } + else if (x->IsRegex() || x->HasNickOrReal()) return; - /* First parameter is the UID, change it to nick because it is pushed */ - params[0] = dest->nick; - - IRCMessage m(message.GetSource(), message.GetCommand()); - for (const Anope::string &s : params) - m.Push(s); - - Uplink::Send("PUSH", dest->GetUID(), Format(m)); -} - -void inspircd20::Proto::SendMode(const MessageSource &source, Channel *dest, const Anope::string &buf) -{ - IRCMessage message(source, "FMODE", dest->name, dest->creation_time); - message.TokenizeAndPush(buf); - Uplink::SendMessage(message); -} - -void inspircd20::Proto::SendClientIntroduction(User *u) -{ - Anope::string modes = "+" + u->GetModes(); - Uplink::Send(Me, "UID", u->GetUID(), u->timestamp, u->nick, u->host, u->host, u->GetIdent(), "0.0.0.0", u->timestamp, modes, u->realname); - if (modes.find('o') != Anope::string::npos) - Uplink::Send(u, "OPERTYPE", "services"); -} + /* ZLine if we can instead */ + if (x->GetUser() == "*") + { + cidr addr(x->GetHost()); + if (addr.valid()) + { + IRCD->Send(x); + return; + } + } -/* SERVER services-dev.chatspike.net password 0 :Description here */ -void inspircd20::Proto::SendServer(Server *server) -{ - /* if rsquit is set then we are waiting on a squit */ - if (rsquit_id.empty() && rsquit_server.empty()) - Uplink::Send("SERVER", server->GetName(), Config->Uplinks[Anope::CurrentUplink].password, server->GetHops(), server->GetSID(), server->GetDescription()); + proto->SendDelLine("G", x->GetUser() + "@" + x->GetHost()); } -void inspircd20::Proto::SendSquit(Server *s, const Anope::string &message) +void inspircd20::senders::MessageChannel::Send(Channel* c) { - if (s != Me) - { - rsquit_id = s->GetSID(); - rsquit_server = s->GetName(); - - Uplink::Send("RSQUIT", s->GetName(), message); - } - else - { - Uplink::Send("SQUIT", s->GetName(), message); - } + Uplink::Send(Me, "FJOIN", c->name, c->creation_time, "+" + c->GetModes(true, true), ""); } -/* JOIN */ -void inspircd20::Proto::SendJoin(User *user, Channel *c, const ChannelStatus *status) +void inspircd20::senders::Join::Send(User* user, Channel* c, const ChannelStatus* status) { Uplink::Send(Me, "FJOIN", c->name, c->creation_time, "+" + c->GetModes(true, true), "," + user->GetUID()); @@ -300,159 +159,264 @@ void inspircd20::Proto::SendJoin(User *user, Channel *c, const ChannelStatus *st } } -/* UNSQLINE */ -void inspircd20::Proto::SendSQLineDel(XLine *x) +void inspircd20::senders::Login::Send(User *u, NickServ::Nick *na) { - SendDelLine("Q", x->GetMask()); + /* InspIRCd uses an account to bypass chmode +R, not umode +r, so we can't send this here */ + if (na->GetAccount()->IsUnconfirmed()) + return; + + Uplink::Send(Me, "METADATA", u->GetUID(), "accountname", na->GetAccount()->GetDisplay()); } -/* SQLINE */ -void inspircd20::Proto::SendSQLine(User *, XLine *x) +void inspircd20::senders::Logout::Send(User *u) { - // Calculate the time left before this would expire, capping it at 2 days - time_t timeleft = x->GetExpires() - Anope::CurTime; - if (timeleft > 172800 || !x->GetExpires()) - timeleft = 172800; - SendAddLine("Q", x->GetMask(), timeleft, x->GetBy(), x->GetReason()); + Uplink::Send(Me, "METADATA", u->GetUID(), "accountname", ""); } -void inspircd20::Proto::SendVhost(User *u, const Anope::string &vIdent, const Anope::string &vhost) +void inspircd20::senders::ModeChannel::Send(const MessageSource &source, Channel *channel, const Anope::string &modes) { - if (!vIdent.empty()) - this->SendChgIdentInternal(u->nick, vIdent); - if (!vhost.empty()) - this->SendChgHostInternal(u->nick, vhost); + IRCMessage message(source, "FMODE", channel->name, channel->creation_time); + message.TokenizeAndPush(modes); + Uplink::SendMessage(message); } -/* SVSHOLD - set */ -void inspircd20::Proto::SendSVSHold(const Anope::string &nick, time_t t) +void inspircd20::senders::NickIntroduction::Send(User *user) { - Uplink::Send(Config->GetClient("NickServ"), "SVSHOLD", nick, t, "Being held for registered user"); + Anope::string modes = "+" + user->GetModes(); + Uplink::Send(Me, "UID", user->GetUID(), user->timestamp, user->nick, user->host, user->host, user->GetIdent(), "0.0.0.0", user->timestamp, modes, user->realname); + if (modes.find('o') != Anope::string::npos) + Uplink::Send(user, "OPERTYPE", "services"); } -/* SVSHOLD - release */ -void inspircd20::Proto::SendSVSHoldDel(const Anope::string &nick) + +void inspircd20::senders::SASL::Send(const ::SASL::Message& message) { - Uplink::Send(Config->GetClient("NickServ"), "SVSHOLD", nick); + if (!message.ext.empty()) + Uplink::Send(Me, "ENCAP", message.target.substr(0, 3), "SASL", + message.source, message.target, + message.type, message.data, message.ext); + else + Uplink::Send(Me, "ENCAP", message.target.substr(0, 3), "SASL", + message.source, message.target, + message.type, message.data); } -/* UNSZLINE */ -void inspircd20::Proto::SendSZLineDel(XLine *x) +void inspircd20::senders::SASLMechanisms::Send(const std::vector& mechanisms) { - SendDelLine("Z", x->GetHost()); + Anope::string mechlist; + for (unsigned int i = 0; i < mechanisms.size(); ++i) + mechlist += "," + mechanisms[i]; + + Uplink::Send(Me, "METADATA", "*", "saslmechlist", mechlist.empty() ? "" : mechlist.substr(1)); +} + +void inspircd20::senders::MessageServer::Send(Server* server) +{ + /* if rsquit is set then we are waiting on a squit */ + if (rsquit_id.empty() && rsquit_server.empty()) + Uplink::Send("SERVER", server->GetName(), Config->Uplinks[Anope::CurrentUplink].password, server->GetHops(), server->GetSID(), server->GetDescription()); } -/* SZLINE */ -void inspircd20::Proto::SendSZLine(User *, XLine *x) +void inspircd20::senders::SQLine::Send(User*, XLine* x) { // Calculate the time left before this would expire, capping it at 2 days time_t timeleft = x->GetExpires() - Anope::CurTime; if (timeleft > 172800 || !x->GetExpires()) timeleft = 172800; - SendAddLine("Z", x->GetHost(), timeleft, x->GetBy(), x->GetReason()); + proto->SendAddLine("Q", x->GetMask(), timeleft, x->GetBy(), x->GetReason()); } -void inspircd20::Proto::SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &) +void inspircd20::senders::SQLineDel::Send(XLine* x) { - Uplink::Send(source, "SVSJOIN", u->GetUID(), chan); + proto->SendDelLine("Q", x->GetMask()); } -void inspircd20::Proto::SendSVSPart(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string ¶m) +void inspircd20::senders::SQuit::Send(Server *s, const Anope::string &message) { - if (!param.empty()) - Uplink::Send(source, "SVSPART", u->GetUID(), chan, param); + if (s != Me) + { + rsquit_id = s->GetSID(); + rsquit_server = s->GetName(); + + Uplink::Send("RSQUIT", s->GetName(), message); + } else - Uplink::Send(source, "SVSPART", u->GetUID(), chan); + { + Uplink::Send("SQUIT", s->GetName(), message); + } } -void inspircd20::Proto::SendSWhois(const MessageSource &, const Anope::string &who, const Anope::string &mask) +void inspircd20::senders::SZLine::Send(User*, XLine* x) { - User *u = User::Find(who); + // Calculate the time left before this would expire, capping it at 2 days + time_t timeleft = x->GetExpires() - Anope::CurTime; + if (timeleft > 172800 || !x->GetExpires()) + timeleft = 172800; + proto->SendAddLine("Z", x->GetHost(), timeleft, x->GetBy(), x->GetReason()); +} - Uplink::Send(Me, "METADATA", u->GetUID(), "swhois", mask); +void inspircd20::senders::SZLineDel::Send(XLine* x) +{ + proto->SendDelLine("Z", x->GetHost()); } -void inspircd20::Proto::SendBOB() +void inspircd20::senders::SVSHold::Send(const Anope::string& nick, time_t t) { - Uplink::Send(Me, "BURST", Anope::CurTime); - Module *enc = ModuleManager::FindFirstOf(ENCRYPTION); - Uplink::Send(Me, "VERSION", Anope::Format("Anope-{0} {1} {2} - {3} - Built: {4} - Flags: {5}", - Anope::Version(), Me->GetName(), IRCD->GetProtocolName(), enc ? enc->name : "(none)", Anope::VersionBuildTime(), Anope::VersionFlags())); + Uplink::Send(Config->GetClient("NickServ"), "SVSHOLD", nick, t, "Being held for registered user"); } -void inspircd20::Proto::SendEOB() +void inspircd20::senders::SVSHoldDel::Send(const Anope::string& nick) { - Uplink::Send(Me, "ENDBURST"); + Uplink::Send(Config->GetClient("NickServ"), "SVSHOLD", nick); } -void inspircd20::Proto::SendGlobops(const MessageSource &source, const Anope::string &buf) +void inspircd20::senders::SVSLogin::Send(const Anope::string& uid, const Anope::string& acc, const Anope::string& vident, const Anope::string& vhost) { - if (Servers::Capab.count("GLOBOPS")) - Uplink::Send(source, "SNONOTICE", "g", buf); - else - Uplink::Send(source, "SNONOTICE", "A", buf); + Uplink::Send(Me, "METADATA", uid, "accountname", acc); + + SASLUser su; + su.uid = uid; + su.acc = acc; + su.created = Anope::CurTime; + + for (std::list::iterator it = saslusers.begin(); it != saslusers.end();) + { + SASLUser &u = *it; + + if (u.created + 30 < Anope::CurTime || u.uid == uid) + it = saslusers.erase(it); + else + ++it; + } + + saslusers.push_back(su); } -void inspircd20::Proto::SendLogin(User *u, NickServ::Nick *na) +void inspircd20::senders::SWhois::Send(const MessageSource&, User *user, const Anope::string& swhois) { - /* InspIRCd uses an account to bypass chmode +R, not umode +r, so we can't send this here */ - if (na->GetAccount()->IsUnconfirmed()) - return; + Uplink::Send(Me, "METADATA", user->GetUID(), "swhois", swhois); +} - Uplink::Send(Me, "METADATA", u->GetUID(), "accountname", na->GetAccount()->GetDisplay()); +void inspircd20::senders::Topic::Send(const MessageSource &source, Channel *channel, const Anope::string &topic, time_t topic_ts, const Anope::string &topic_setter) +{ + if (Servers::Capab.count("SVSTOPIC")) + { + Uplink::Send(source, "SVSTOPIC", channel->name, topic_ts, topic_setter, topic); + } + else + { + /* If the last time a topic was set is after the TS we want for this topic we must bump this topic's timestamp to now */ + time_t ts = topic_ts; + if (channel->topic_time > ts) + ts = Anope::CurTime; + /* But don't modify c->topic_ts, it should remain set to the real TS we want as ci->last_topic_time pulls from it */ + Uplink::Send(source, "FTOPIC", channel->name, ts, topic_setter, topic); + } } -void inspircd20::Proto::SendLogout(User *u) +void inspircd20::senders::VhostDel::Send(User* u) { - Uplink::Send(Me, "METADATA", u->GetUID(), "accountname", ""); + if (u->HasMode("CLOAK")) + proto->SendChgHostInternal(u->nick, u->chost); + else + proto->SendChgHostInternal(u->nick, u->host); + + if (Servers::Capab.count("CHGIDENT") && u->GetIdent() != u->GetVIdent()) + proto->SendChgIdentInternal(u->nick, u->GetIdent()); } -void inspircd20::Proto::SendChannel(Channel *c) +void inspircd20::senders::VhostSet::Send(User* u, const Anope::string& vident, const Anope::string& vhost) { - Uplink::Send(Me, "FJOIN", c->name, c->creation_time, "+" + c->GetModes(true, true), ""); + if (!vident.empty()) + proto->SendChgIdentInternal(u->nick, vident); + if (!vhost.empty()) + proto->SendChgHostInternal(u->nick, vhost); } -void inspircd20::Proto::SendSASLMechanisms(std::vector &mechanisms) +void inspircd20::senders::Wallops::Send(const MessageSource &source, const Anope::string &msg) { - Anope::string mechlist; - for (unsigned i = 0; i < mechanisms.size(); ++i) - mechl