From 89428a9d1032e3c2a6e397629a32862b3e58d708 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 1 Oct 2012 01:56:57 -0400 Subject: Cleanup of all of the protocol modules, rewrote message handling system to be a bit more C++ ish --- modules/protocol/bahamut.cpp | 322 +++++++++-------- modules/protocol/inspircd-ts6.h | 386 +++++++++++++++----- modules/protocol/inspircd11.cpp | 571 ++++++++++++++--------------- modules/protocol/inspircd12.cpp | 389 +++++--------------- modules/protocol/inspircd20.cpp | 399 +++++--------------- modules/protocol/plexus.cpp | 538 +++++++++++++++------------ modules/protocol/ratbox.cpp | 445 ++++++++++++----------- modules/protocol/unreal.cpp | 783 +++++++++++++++++++--------------------- 8 files changed, 1848 insertions(+), 1985 deletions(-) (limited to 'modules/protocol') diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp index 73955149d..8aeee39c8 100644 --- a/modules/protocol/bahamut.cpp +++ b/modules/protocol/bahamut.cpp @@ -13,34 +13,40 @@ #include "module.h" -IRCDVar myIrcd = { - "Bahamut 1.8.x", /* ircd name */ - "+", /* Modes used by pseudoclients */ - 1, /* SVSNICK */ - 0, /* Vhost */ - 1, /* Supports SNlines */ - 1, /* Supports SQlines */ - 1, /* Supports SZlines */ - 0, /* Join 2 Message */ - 1, /* Chan SQlines */ - 1, /* Quit on Kill */ - 0, /* vidents */ - 1, /* svshold */ - 1, /* time stamp on mode */ - 0, /* O:LINE */ - 1, /* UMODE */ - 1, /* No Knock requires +i */ - 0, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 0, /* ts6 */ - "$", /* TLD Prefix for Global */ - 6, /* Max number of modes we can send per line */ - 0 /* IRCd sends a SSL users certificate fingerprint */ -}; +class ChannelModeFlood : public ChannelModeParam +{ + public: + ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam(CMODE_FLOOD, modeChar, minusNoArg) { } + bool IsValid(const Anope::string &value) const anope_override + { + try + { + 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; + } + catch (const ConvertException &) { } + + return false; + } +}; class BahamutIRCdProto : public IRCDProto { + public: + BahamutIRCdProto() : IRCDProto("Bahamut 1.8.x") + { + DefaultPseudoclientModes = "+"; + CanSVSNick = true; + CanSNLine = true; + CanSQLine = true; + CanSQLineChannel = true; + CanSZLine = true; + CanSVSHold = true; + MaxModes = 60; + } + void SendModeInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) anope_override { if (Capab.count("TSMODE") > 0) @@ -62,6 +68,16 @@ class BahamutIRCdProto : public IRCDProto UplinkSocket::Message(Me) << "SVSMODE " << u->nick << " " << u->timestamp << " " << buf; } + void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg; + } + + void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg; + } + /* SVSHOLD - set */ void SendSVSHold(const Anope::string &nick) anope_override { @@ -290,46 +306,82 @@ class BahamutIRCdProto : public IRCDProto } }; -class BahamutIRCdMessage : public IRCdMessage +struct IRCDMessageBurst : IRCDMessage { - public: - bool OnMode(const Anope::string &source, const std::vector ¶ms) anope_override - { - if (params.size() > 2 && (params[0][0] == '#' || params[0][0] == '&')) - do_cmode(source, params[0], params[2], params[1]); - else if (params.size() > 1) - do_umode(params[0], params[1]); + IRCDMessageBurst() : IRCDMessage("BURST", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + /* If we found a server with the given source, that one just + * finished bursting. If there was no source, then our uplink + * server finished bursting. -GD + */ + Server *s = source.GetServer(); + if (!s) + s = Me->GetLinks().front(); + if (s) + s->Sync(true); return true; } +}; - /* - ** NICK - new - ** source = NULL - ** parv[0] = nickname - ** parv[1] = hopcount - ** parv[2] = timestamp - ** parv[3] = modes - ** parv[4] = username - ** parv[5] = hostname - ** parv[6] = server - ** parv[7] = servicestamp - ** parv[8] = IP - ** parv[9] = info - ** NICK - change - ** source = oldnick - ** parv[0] = new nickname - ** parv[1] = hopcount - */ - bool OnNick(const Anope::string &source, const std::vector ¶ms) anope_override - { - if (params.size() != 2) +struct IRCDMessageMode : IRCDMessage +{ + IRCDMessageMode(const Anope::string &n) : IRCDMessage(n, 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + if (params.size() > 2 && ircdproto->IsChannelValid(params[0])) + { + Channel *c = findchan(params[0]); + time_t ts = Anope::CurTime; + try + { + ts = convertTo(params[1]); + } + catch (const ConvertException &) { } + + if (c) + c->SetModesInternal(source, params[2], ts); + } + else { - /* Currently bahamut has no ipv6 support */ - sockaddrs ip; - ip.ntop(AF_INET, params[8].c_str()); + User *u = finduser(params[0]); + if (u) + u->SetModesInternal("%s", params[1].c_str()); + } + + return true; + } +}; + +/* + ** NICK - new + ** source = NULL + ** parv[0] = nickname + ** parv[1] = hopcount + ** parv[2] = timestamp + ** parv[3] = modes + ** parv[4] = username + ** parv[5] = hostname + ** parv[6] = server + ** parv[7] = servicestamp + ** parv[8] = IP + ** parv[9] = info + ** NICK - change + ** source = oldnick + ** parv[0] = new nickname + ** parv[1] = hopcount + */ +struct IRCDMessageNick : IRCDMessage +{ + IRCDMessageNick() : IRCDMessage("NICK", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - User *user = do_nick(source, params[0], params[4], params[5], params[6], params[9], Anope::string(params[2]).is_pos_number_only() ? convertTo(params[2]) : 0, ip.addr(), "", "", params[3]); + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + if (params.size() == 10) + { + User *user = new User(params[0], params[4], params[5], "", params[8], source.GetServer(), params[9], params[2].is_pos_number_only() ? convertTo(params[2]) : 0, params[3]); if (user && nickserv) { const NickAlias *na; @@ -345,35 +397,29 @@ class BahamutIRCdMessage : public IRCdMessage } } else - do_nick(source, params[0], "", "", "", "", Anope::string(params[1]).is_pos_number_only() ? convertTo(params[1]) : 0, "", "", "", ""); + source.GetUser()->ChangeNick(params[0]); return true; } +}; - bool OnServer(const Anope::string &source, const std::vector ¶ms) anope_override - { - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo(params[1]) : 0, params[2], ""); - return true; - } +struct IRCDMessageServer : IRCDMessage +{ + IRCDMessageServer() : IRCDMessage("SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } - bool OnTopic(const Anope::string &, const std::vector ¶ms) anope_override + bool Run(MessageSource &source, const std::vector ¶ms) anope_override { - if (params.size() < 4) - return true; - - Channel *c = findchan(params[0]); - if (!c) - { - Log() << "TOPIC for nonexistant channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo(params[2]) : Anope::CurTime); - + unsigned int hops = Anope::string(params[1]).is_pos_number_only() ? convertTo(params[1]) : 0; + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[2]); return true; } +}; - bool OnSJoin(const Anope::string &source, const std::vector ¶ms) anope_override +struct IRCDMessageSJoin : IRCDMessage +{ + IRCDMessageSJoin() : IRCDMessage("SJOIN", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override { Channel *c = findchan(params[1]); time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo(params[0]) : 0; @@ -403,7 +449,7 @@ class BahamutIRCdMessage : public IRCdMessage modes += " " + params[i]; if (!modes.empty()) modes.erase(modes.begin()); - c->SetModesInternal(NULL, modes); + c->SetModesInternal(source, modes); } /* For some reason, bahamut will send a SJOIN from the user joining a channel @@ -411,28 +457,24 @@ class BahamutIRCdMessage : public IRCdMessage */ if (!c->HasFlag(CH_SYNCING) && params.size() == 2) { - User *u = finduser(source); - if (!u) - Log(LOG_DEBUG) << "SJOIN for nonexistant user " << source << " on " << c->name; - else - { - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); + User *u = source.GetUser(); - /* Add the user to the channel */ - c->JoinUser(u); + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); - /* Now set whatever modes this user is allowed to have on the channel */ - chan_set_correct_modes(u, c, 1, true); + /* Add the user to the channel */ + c->JoinUser(u); - /* Check to see if modules want the user to join, if they do - * check to see if they are allowed to join (CheckKick will kick/ban them) - * Don't trigger OnJoinChannel event then as the user will be destroyed - */ - if (MOD_RESULT == EVENT_STOP && (!c->ci || !c->ci->CheckKick(u))) - { - FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); - } + /* Now set whatever modes this user is allowed to have on the channel */ + chan_set_correct_modes(u, c, 1, true); + + /* Check to see if modules want the user to join, if they do + * check to see if they are allowed to join (CheckKick will kick/ban them) + * Don't trigger OnJoinChannel event then as the user will be destroyed + */ + if (MOD_RESULT == EVENT_STOP && (!c->ci || !c->ci->CheckKick(u))) + { + FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); } } else @@ -476,7 +518,7 @@ class BahamutIRCdMessage : public IRCdMessage * This will enforce secureops etc on the user */ for (std::list::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it) - c->SetModeInternal(NULL, *it, buf); + c->SetModeInternal(source, *it, buf); /* Now set whatever modes this user is allowed to have on the channel */ chan_set_correct_modes(u, c, 1, true); @@ -504,53 +546,48 @@ class BahamutIRCdMessage : public IRCdMessage } }; -bool event_burst(const Anope::string &source, const std::vector ¶ms) -{ - Server *s = Server::Find(source); - - if (params.empty()) - { - /* for future use - start burst */ - } - else - { - /* If we found a server with the given source, that one just - * finished bursting. If there was no source, then our uplink - * server finished bursting. -GD - */ - if (!s) - s = Me->GetLinks().front(); - if (s) - s->Sync(true); - } - return true; -} - -class ChannelModeFlood : public ChannelModeParam +struct IRCDMessageTopic : IRCDMessage { - public: - ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam(CMODE_FLOOD, modeChar, minusNoArg) { } + IRCDMessageTopic() : IRCDMessage("TOPIC", 4) { } - bool IsValid(const Anope::string &value) const anope_override + bool Run(MessageSource &, const std::vector ¶ms) anope_override { - try - { - 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; - } - catch (const ConvertException &) { } - - return false; + Channel *c = findchan(params[0]); + if (c) + c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo(params[2]) : Anope::CurTime); + return true; } }; class ProtoBahamut : public Module { - Message message_svsmode, message_burst; - BahamutIRCdProto ircd_proto; - BahamutIRCdMessage ircd_message; + + /* Core message handlers */ + CoreIRCDMessageAway core_message_away; + CoreIRCDMessageCapab core_message_capab; + CoreIRCDMessageError core_message_error; + CoreIRCDMessageJoin core_message_join; + CoreIRCDMessageKill core_message_kill; + CoreIRCDMessageMOTD core_message_motd; + CoreIRCDMessagePart core_message_part; + CoreIRCDMessagePing core_message_ping; + CoreIRCDMessagePrivmsg core_message_privmsg; + CoreIRCDMessageQuit core_message_quit; + CoreIRCDMessageSQuit core_message_squit; + CoreIRCDMessageStats core_message_stats; + CoreIRCDMessageTime core_message_time; + CoreIRCDMessageTopic core_message_topic; + CoreIRCDMessageVersion core_message_version; + CoreIRCDMessageWhois core_message_whois; + + /* Our message handlers */ + IRCDMessageBurst message_burst; + IRCDMessageMode message_mode, message_svsmode; + IRCDMessageNick message_nick; + IRCDMessageServer message_server; + IRCDMessageSJoin message_sjoin; + IRCDMessageTopic message_topic; void AddModes() { @@ -591,26 +628,15 @@ class ProtoBahamut : public Module public: ProtoBahamut(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_svsmode("SVSMODE", OnMode), message_burst("BURST", event_burst) + message_mode("MODE"), message_svsmode("SVSMODE") { this->SetAuthor("Anope"); - pmodule_ircd_var(&myIrcd); - pmodule_ircd_proto(&this->ircd_proto); - pmodule_ircd_message(&this->ircd_message); - this->AddModes(); ModuleManager::Attach(I_OnUserNickChange, this); } - ~ProtoBahamut() - { - pmodule_ircd_var(NULL); - pmodule_ircd_proto(NULL); - pmodule_ircd_message(NULL); - } - void OnUserNickChange(User *u, const Anope::string &) anope_override { u->RemoveModeInternal(ModeManager::FindUserModeByName(UMODE_REGISTERED)); diff --git a/modules/protocol/inspircd-ts6.h b/modules/protocol/inspircd-ts6.h index 0ce5be921..f0af01cc9 100644 --- a/modules/protocol/inspircd-ts6.h +++ b/modules/protocol/inspircd-ts6.h @@ -47,7 +47,30 @@ class InspIRCdTS6Proto : public IRCDProto UplinkSocket::Message(Me) << "CHGHOST " << nick << " " << vhost; } - public: + protected: + InspIRCdTS6Proto(const Anope::string &name) : IRCDProto(name) + { + DefaultPseudoclientModes = "+I"; + CanSVSNick = true; + CanSetVHost = true; + CanSetVIdent = true; + CanSQLine = true; + CanSZLine = true; + CanSVSHold = true; + CanCertFP = true; + RequiresID = true; + MaxModes = 20; + } + + void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg; + } + + void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg; + } void SendAkillDel(const XLine *x) anope_override { @@ -225,7 +248,7 @@ class InspIRCdTS6Proto : public IRCDProto SendServer(Me); UplinkSocket::Message(Me) << "BURST"; Module *enc = ModuleManager::FindFirstOf(ENCRYPTION); - UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Config->ServerName << " :" << ircd->name << " - (" << (enc ? enc->name : "unknown") << ") -- " << Anope::VersionBuildString(); + UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Config->ServerName << " :" << ircdproto->GetProtocolName() << " - (" << (enc ? enc->name : "unknown") << ") -- " << Anope::VersionBuildString(); } /* SVSHOLD - set */ @@ -319,83 +342,37 @@ class InspIRCdTS6Proto : public IRCDProto } }; -class InspircdIRCdMessage : public IRCdMessage +struct IRCDMessageEndburst : IRCDMessage { - public: - bool OnMode(const Anope::string &source, const std::vector ¶ms) anope_override - { - if (params[0][0] == '#' || params[0][0] == '&') - do_cmode(source, params[0], params[2], params[1]); - else - { - /* InspIRCd lets opers change another - users modes, we have to kludge this - as it slightly breaks RFC1459 - */ - User *u = finduser(source); - // This can happen with server-origin modes. - if (!u) - u = finduser(params[0]); - // if it's still null, drop it like fire. - // most likely situation was that server introduced a nick which we subsequently akilled - if (!u) - return true; + IRCDMessageEndburst() : IRCDMessage("ENDBURST", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } - do_umode(u->nick, params[1]); - } - - return true; - } - - virtual bool OnUID(const Anope::string &source, const std::vector ¶ms) anope_override = 0; - - bool OnNick(const Anope::string &source, const std::vector ¶ms) anope_override + bool Run(MessageSource &source, const std::vector ¶ms) anope_override { - do_nick(source, params[0], "", "", "", "", 0, "", "", "", ""); - return true; - } - - bool OnPrivmsg(const Anope::string &source, const std::vector ¶ms) anope_override - { - /* Ignore privmsgs from the server, which can happen. */ - if (Server::Find(source) != NULL) - return true; + Server *s = source.GetServer(); - return IRCdMessage::OnPrivmsg(source, params); - } + Log(LOG_DEBUG) << "Processed ENDBURST for " << s->GetName(); - /* - * [Nov 04 00:08:46.308435 2009] debug: Received: SERVER irc.inspircd.com pass 0 964 :Testnet Central! - * 0: name - * 1: pass - * 2: hops - * 3: numeric - * 4: desc - */ - bool OnServer(const Anope::string &source, const std::vector ¶ms) anope_override - { - do_server(source, params[0], Anope::string(params[2]).is_pos_number_only() ? convertTo(params[2]) : 0, params[4], params[3]); + s->Sync(true); return true; } +}; - bool OnTopic(const Anope::string &source, const std::vector ¶ms) anope_override - { - Channel *c = findchan(params[0]); - - if (!c) - { - Log() << "TOPIC " << params[1] << " for nonexistent channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(source, (params.size() > 1 ? params[1] : ""), Anope::CurTime); +struct IRCDMessageFHost : IRCDMessage +{ + IRCDMessageFHost(const Anope::string &n) : IRCDMessage(n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + source.GetUser()->SetDisplayedHost(params[0]); return true; } +}; - virtual bool OnCapab(const Anope::string &, const std::vector &) anope_override = 0; +struct IRCDMessageFJoin : IRCDMessage +{ + IRCDMessageFJoin() : IRCDMessage("FJOIN", 2) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - bool OnSJoin(const Anope::string &source, const std::vector ¶ms) anope_override + bool Run(MessageSource &source, const std::vector ¶ms) anope_override { Channel *c = findchan(params[0]); time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo(params[1]) : 0; @@ -425,7 +402,7 @@ class InspircdIRCdMessage : public IRCdMessage if (!modes.empty()) modes.erase(modes.begin()); /* Set the modes internally */ - c->SetModesInternal(NULL, modes); + c->SetModesInternal(source, modes); } spacesepstream sep(params[params.size() - 1]); @@ -468,7 +445,7 @@ class InspircdIRCdMessage : public IRCdMessage * This will enforce secureops etc on the user */ for (std::list::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it) - c->SetModeInternal(NULL, *it, buf); + c->SetModeInternal(source, *it, buf); /* Now set whatever modes this user is allowed to have on the channel */ chan_set_correct_modes(u, c, 1, true); @@ -495,33 +472,268 @@ class InspircdIRCdMessage : public IRCdMessage } }; -bool event_idle(const Anope::string &source, const std::vector ¶ms) +struct IRCDMessageFMode : IRCDMessage +{ + IRCDMessageFMode() : IRCDMessage("FMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + /* :source FMODE #test 12345678 +nto foo */ + + Anope::string modes = params[2]; + for (unsigned n = 3; n < params.size(); ++n) + modes += " " + params[n]; + + Channel *c = findchan(params[0]); + time_t ts; + + try + { + ts = convertTo(params[1]); + } + catch (const ConvertException &) + { + ts = Anope::CurTime; + } + + if (c) + c->SetModesInternal(source, modes, ts); + + return true; + } +}; + +struct IRCDMessageFTopic : IRCDMessage +{ + IRCDMessageFTopic() : IRCDMessage("FTOPIC", 4) { } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + /* :source FTOPIC channel ts setby :topic */ + + Channel *c = findchan(params[0]); + if (c) + c->ChangeTopicInternal(params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo(params[1]) : Anope::CurTime); + + return true; + } +}; + +struct IRCDMessageIdle : IRCDMessage +{ + IRCDMessageIdle() : IRCDMessage("IDLE", 1) { } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + const BotInfo *bi = findbot(params[0]); + if (bi) + UplinkSocket::Message(bi) << "IDLE " << source.GetSource() << " " << start_time << " " << (Anope::CurTime - bi->lastmsg); + return true; + } +}; + +/* + * source = numeric of the sending server + * params[0] = uuid + * params[1] = metadata name + * params[2] = data + */ +struct IRCDMessageMetadata : IRCDMessage +{ + IRCDMessageMetadata() : IRCDMessage("METADATA", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + if (params[1].equals_cs("accountname")) + { + User *u = finduser(params[0]); + NickCore *nc = findcore(params[2]); + if (u && nc) + { + u->Login(nc); + + const NickAlias *user_na = findnick(u->nick); + if (!Config->NoNicknameOwnership && nickserv && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) + u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); + } + } + + /* + * possible incoming ssl_cert messages: + * Received: :409 METADATA 409AAAAAA ssl_cert :vTrSe c38070ce96e41cc144ed6590a68d45a6 <...> <...> + * Received: :409 METADATA 409AAAAAC ssl_cert :vTrSE Could not get peer certificate: error:00000000:lib(0):func(0):reason(0) + */ + else if (params[1].equals_cs("ssl_cert")) + { + User *u = finduser(params[0]); + if (!u) + return true; + std::string data = params[2].c_str(); + size_t pos1 = data.find(' ') + 1; + size_t pos2 = data.find(' ', pos1); + if ((pos2 - pos1) >= 32) // inspircd supports md5 and sha1 fingerprint hashes -> size 32 or 40 bytes. + { + u->fingerprint = data.substr(pos1, pos2 - pos1); + FOREACH_MOD(I_OnFingerprint, OnFingerprint(u)); + } + } + return true; + } +}; + +struct IRCDMessageMode : IRCDMessage +{ + IRCDMessageMode() : IRCDMessage("MODE", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + if (ircdproto->IsChannelValid(params[0])) + { + Channel *c = findchan(params[0]); + time_t ts; + + try + { + ts = convertTo(params[1]); + } + catch (const ConvertException &) + { + ts = Anope::CurTime; + } + + if (c) + c->SetModesInternal(source, params[2], ts); + } + else + { + /* InspIRCd lets opers change another + users modes, we have to kludge this + as it slightly breaks RFC1459 + */ + User *u = source.GetUser(); + // This can happen with server-origin modes. + if (!u) + u = finduser(params[0]); + // if it's still null, drop it like fire. + // most likely situation was that server introduced a nick which we subsequently akilled + if (u) + u->SetModesInternal("%s", params[1].c_str()); + } + + return true; + } +}; + +struct IRCDMessageNick : IRCDMessage +{ + IRCDMessageNick() : IRCDMessage("NICK", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + source.GetUser()->ChangeNick(params[0]); + return true; + } +}; + +struct IRCDMessageOperType : IRCDMessage +{ + IRCDMessageOperType() : IRCDMessage("OPERTYPE", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + /* opertype is equivalent to mode +o because servers + dont do this directly */ + User *u = source.GetUser(); + if (!u->HasMode(UMODE_OPER)) + u->SetModesInternal("+o"); + + return true; + } +}; + +struct IRCDMessageRSQuit : IRCDMessage { - const BotInfo *bi = findbot(params[0]); - if (bi) - UplinkSocket::Message(bi) << "IDLE " << source << " " << start_time << " " << (Anope::CurTime - bi->lastmsg); - return true; -} + IRCDMessageRSQuit() : IRCDMessage("RSQUIT", 1) { } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + Server *s = Server::Find(params[0]); + if (!s) + return true; + + /* On InspIRCd we must send a SQUIT when we recieve RSQUIT for a server we have juped */ + if (s->HasFlag(SERVER_JUPED)) + UplinkSocket::Message(Me) << "SQUIT " << s->GetSID() << " :" << (params.size() > 1 ? params[1].c_str() : ""); + + FOREACH_MOD(I_OnServerQuit, OnServerQuit(s)); + + s->Delete(s->GetName() + " " + s->GetUplink()->GetName()); + + return true; + } +}; -bool event_time(const Anope::string &source, const std::vector ¶ms) +struct IRCDMessageServer : IRCDMessage { - if (params.size() < 2) + IRCDMessageServer() : IRCDMessage("SERVER", 5) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + /* + * [Nov 04 00:08:46.308435 2009] debug: Received: SERVER irc.inspircd.com pass 0 964 :Testnet Central! + * 0: name + * 1: pass + * 2: hops + * 3: numeric + * 4: desc + */ + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + unsigned int hops = Anope::string(params[2]).is_pos_number_only() ? convertTo(params[2]) : 0; + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[4], params[3]); return true; + } +}; - UplinkSocket::Message(Me) << "TIME " << source << " " << params[1] << " " << Anope::CurTime; - return true; -} +struct IRCDMessageTime : IRCDMessage +{ + IRCDMessageTime() : IRCDMessage("TIME", 2) { } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + UplinkSocket::Message(Me) << "TIME " << source.GetSource() << " " << params[1] << " " << Anope::CurTime; + return true; + } +}; -bool event_rsquit(const Anope::string &source, const std::vector ¶ms) +struct IRCDMessageUID : IRCDMessage { - /* On InspIRCd we must send a SQUIT when we recieve RSQUIT for a server we have juped */ - Server *s = Server::Find(params[0]); - if (s && s->HasFlag(SERVER_JUPED)) - UplinkSocket::Message(Me) << "SQUIT " << s->GetSID() << " :" << (params.size() > 1 ? params[1].c_str() : ""); + IRCDMessageUID() : IRCDMessage("UID", 8) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + /* + * [Nov 03 22:09:58.176252 2009] debug: Received: :964 UID 964AAAAAC 1225746297 w00t2 localhost testnet.user w00t 127.0.0.1 1225746302 +iosw +ACGJKLNOQcdfgjklnoqtx :Robin Burchell + * 0: uid + * 1: ts + * 2: nick + * 3: host + * 4: dhost + * 5: ident + * 6: ip + * 7: signon + * 8+: modes and params -- IMPORTANT, some modes (e.g. +s) may have parameters. So don't assume a fixed position of realname! + * last: realname + */ + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + time_t ts = convertTo(params[1]); - ircdmessage->OnSQuit(source, params); + Anope::string modes = params[8]; + for (unsigned i = 9; i < params.size() - 1; ++i) + modes += " " + params[i]; - return true; -} + User *u = new User(params[2], params[5], params[3], params[4], params[6], source.GetServer(), params[params.size() - 1], ts, modes, params[0]); + if (u->server->IsSynced() && nickserv) + nickserv->Validate(u); + return true; + } +}; diff --git a/modules/protocol/inspircd11.cpp b/modules/protocol/inspircd11.cpp index 7470d61aa..1eba8321f 100644 --- a/modules/protocol/inspircd11.cpp +++ b/modules/protocol/inspircd11.cpp @@ -13,31 +13,6 @@ #include "module.h" -IRCDVar myIrcd = { - "InspIRCd 1.1", /* ircd name */ - "+I", /* Modes used by pseudoclients */ - 1, /* SVSNICK */ - 1, /* Vhost */ - 1, /* Supports SNlines */ - 1, /* Supports SQlines */ - 1, /* Supports SZlines */ - 1, /* Join 2 Message */ - 0, /* Chan SQlines */ - 0, /* Quit on Kill */ - 1, /* vidents */ - 1, /* svshold */ - 0, /* time stamp on mode */ - 1, /* O:LINE */ - 1, /* UMODE */ - 1, /* No Knock requires +i */ - 0, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 0, /* ts6 */ - "$", /* TLD Prefix for Global */ - 20, /* Max number of modes we can send per line */ - 0 /* IRCd sends a SSL users certificate fingerprint */ -}; - static bool has_servicesmod = false; static bool has_globopsmod = false; static bool has_svsholdmod = false; @@ -45,40 +20,60 @@ static bool has_chghostmod = false; static bool has_chgidentmod = false; static bool has_hidechansmod = false; -/* CHGHOST */ -void inspircd_cmd_chghost(const Anope::string &nick, const Anope::string &vhost) +class InspIRCdProto : public IRCDProto { - const BotInfo *bi = findbot(Config->OperServ); - if (has_chghostmod) + public: + InspIRCdProto() : IRCDProto("InspIRCd 1.1") { - if (nick.empty() || vhost.empty()) - return; - UplinkSocket::Message(bi) << "CHGHOST " << nick << " " << vhost; + DefaultPseudoclientModes = "+I"; + CanSVSNick = true; + CanSetVHost = true; + CanSetVIdent = true; + CanSNLine = true; + CanSQLine = true; + CanSZLine = true; + CanSVSHold = true; + CanSVSO = true; + MaxModes = 20; } - else + private: + + Anope::string current_pass; + + void inspircd_cmd_chgident(const Anope::string &nick, const Anope::string &vIdent) { - if (bi) - ircdproto->SendGlobops(bi, "CHGHOST not loaded!"); + if (has_chgidentmod) + { + if (nick.empty() || vIdent.empty()) + return; + UplinkSocket::Message(findbot(Config->OperServ)) << "CHGIDENT " << nick << " " << vIdent; + } + else + Log() << "CHGIDENT not loaded!"; } -} -bool event_idle(const Anope::string &source, const std::vector ¶ms) -{ - const BotInfo *bi = findbot(params[0]); - UplinkSocket::Message(bi) << "IDLE " << source << " " << start_time << " " << (bi ? Anope::CurTime - bi->lastmsg : 0); - return true; -} + void inspircd_cmd_chghost(const Anope::string &nick, const Anope::string &vhost) + { + if (has_chghostmod) + { + if (nick.empty() || vhost.empty()) + return; + UplinkSocket::Message(findbot(Config->OperServ)) << "CHGHOST " << nick << " " << vhost; + } + else + Log() << "CHGHOST not loaded!"; + } -static Anope::string currentpass; + void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg; + } -/* PASS */ -void inspircd_cmd_pass(const Anope::string &pass) -{ - currentpass = pass; -} + void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg; + } -class InspIRCdProto : public IRCDProto -{ void SendAkillDel(const XLine *x) anope_override { if (x->IsRegex() || x->HasNickOrReal()) @@ -159,12 +154,18 @@ class InspIRCdProto : public IRCDProto UplinkSocket::Message(Me) << "ADDLINE G " << x->Mask << " " << x->By << " " << Anope::CurTime << " " << timeleft << " :" << x->GetReason(); } - void SendSVSKillInternal(const BotInfo *source, const User *user, const Anope::string &buf) anope_override + void SendSVSKillInternal(const BotInfo *source, User *user, const Anope::string &buf) anope_override { if (source) + { UplinkSocket::Message(source) << "KILL " << user->nick << " :" << buf; + user->KillInternal(source->nick, buf); + } else + { UplinkSocket::Message(Me) << "KILL " << user->nick << " :" << buf; + user->KillInternal(Me->GetName(), buf); + } } void SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf) anope_override @@ -206,7 +207,7 @@ class InspIRCdProto : public IRCDProto /* SERVER services-dev.chatspike.net password 0 :Description here */ void SendServer(const Server *server) anope_override { - UplinkSocket::Message(Me) << "SERVER " << server->GetName() << " " << currentpass << " " << server->GetHops() << " :" << server->GetDescription(); + UplinkSocket::Message(Me) << "SERVER " << server->GetName() << " " << current_pass << " " << server->GetHops() << " :" << server->GetDescription(); } /* JOIN */ @@ -259,24 +260,11 @@ class InspIRCdProto : public IRCDProto void SendConnect() anope_override { - inspircd_cmd_pass(Config->Uplinks[CurrentUplink]->password); + current_pass = Config->Uplinks[CurrentUplink]->password; SendServer(Me); UplinkSocket::Message() << "BURST"; Module *enc = ModuleManager::FindFirstOf(ENCRYPTION); - UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Me->GetName() << " :" << ircd->name << " - (" << (enc ? enc->name : "unknown") << ") -- " << Anope::VersionBuildString(); - } - - /* CHGIDENT */ - void inspircd_cmd_chgident(const Anope::string &nick, const Anope::string &vIdent) - { - if (has_chgidentmod) - { - if (nick.empty() || vIdent.empty()) - return; - UplinkSocket::Message(findbot(Config->OperServ)) << "CHGIDENT " << nick << " " << vIdent; - } - else - Log() << "CHGIDENT not loaded!"; + UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Me->GetName() << " :" << this->GetProtocolName() << " - (" << (enc ? enc->name : "unknown") << ") -- " << Anope::VersionBuildString(); } /* SVSHOLD - set */ @@ -355,73 +343,11 @@ class ChannelModeFlood : public ChannelModeParam } }; -class InspircdIRCdMessage : public IRCdMessage +struct IRCDMessageCapab : IRCDMessage { - public: - bool OnMode(const Anope::string &source, const std::vector ¶ms) anope_override - { - if (params.size() < 2) - return true; - - if (params[0][0] == '#' || params[0][0] == '&') - do_cmode(source, params[0], params[1], params[2]); - else - do_umode(params[0], params[1]); - - return true; - } - - bool OnNick(const Anope::string &source, const std::vector ¶ms) anope_override - { - if (params.size() == 8) - { - time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo(params[0]) : 0; - - User *user = do_nick("", params[1], params[4], params[2], source, params[7], ts, params[6], params[3], "", params[5]); - if (user && nickserv) - { - user->SetCloakedHost(params[3]); - - NickAlias *na = findnick(user->nick); - Anope::string *svidbuf = na ? na->nc->GetExt *>("authenticationtoken") : NULL; - if (na && svidbuf && *svidbuf == params[0]) - { - NickCore *nc = na->nc; - user->Login(nc); - if (!Config->NoNicknameOwnership && na->nc->HasFlag(NI_UNCONFIRMED) == false) - user->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); - } - else if (nickserv) - nickserv->Validate(user); - } - } - else if (params.size() == 1) - do_nick(source, params[0], "", "", "", "", 0, "", "", "", ""); - return true; - } - - bool OnServer(const Anope::string &source, const std::vector ¶ms) anope_override - { - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo(params[1]) : 0, params[2], ""); - return true; - } - - bool OnTopic(const Anope::string &source, const std::vector ¶ms) anope_override - { - Channel *c = findchan(params[0]); - - if (!c) - { - Log() << "TOPIC " << (params.size() > 1 ? params[1] : "") << " for nonexistent channel " << params[0]; - return true; - } + IRCDMessageCapab() : IRCDMessage("CAPAB", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - c->ChangeTopicInternal(source, (params.size() > 1 ? params[1] : ""), Anope::CurTime); - - return true; - } - - bool OnCapab(const Anope::string &source, const std::vector ¶ms) anope_override + bool Run(MessageSource &, const std::vector ¶ms) anope_override { if (params[0].equals_cs("START")) { @@ -433,7 +359,7 @@ class InspircdIRCdMessage : public IRCdMessage has_chgidentmod = false; has_hidechansmod = false; } - else if (params[0].equals_cs("MODULES")) + else if (params[0].equals_cs("MODULES") && params.size() > 1) { if (params[1].find("m_globops.so") != Anope::string::npos) has_globopsmod = true; @@ -448,7 +374,7 @@ class InspircdIRCdMessage : public IRCdMessage if (params[1].find("m_hidechans.so") != Anope::string::npos) has_hidechansmod = true; } - else if (params[0].equals_cs("CAPABILITIES")) + else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1) { spacesepstream ssep(params[1]); Anope::string capab; @@ -614,7 +540,7 @@ class InspircdIRCdMessage : public IRCdMessage else if (capab.find("MAXMODES=") != Anope::string::npos) { Anope::string maxmodes(capab.begin() + 9, capab.end()); - ircd->maxmodes = maxmodes.is_pos_number_only() ? convertTo(maxmodes) : 3; + ircdproto->MaxModes = maxmodes.is_pos_number_only() ? convertTo(maxmodes) : 3; } } } @@ -647,15 +573,69 @@ class InspircdIRCdMessage : public IRCdMessage Log() << "CHGHOST missing, Usage disabled until module is loaded."; if (!has_chgidentmod) Log() << "CHGIDENT missing, Usage disabled until module is loaded."; - ircd->svshold = has_svsholdmod; + ircdproto->CanSVSHold = has_svsholdmod; } - IRCdMessage::OnCapab(source, params); + return true; + } +}; + +struct IRCDMessageChgIdent : IRCDMessage +{ + IRCDMessageChgIdent(const Anope::string &n) : IRCDMessage(n, 2) { } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + User *u = finduser(params[0]); + if (!u) + { + Log(LOG_DEBUG) << "CHGIDENT for nonexistent user " << params[0]; + return true; + } + + u->SetIdent(params[1]); + return true; + } +}; + +struct IRCDMessageChgName : IRCDMessage +{ + IRCDMessageChgName(const Anope::string &n) : IRCDMessage(n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + source.GetUser()->SetRealname(params[0]); + return true; + } +}; + +struct IRCDMessageEndBurst : IRCDMessage +{ + IRCDMessageEndBurst() : IRCDMessage("ENDBURST", 0) { } + bool Run(MessageSource &, const std::vector ¶ms) anope_override + { + Me->GetLinks().front()->Sync(true); return true; } +}; + +struct IRCDMessageFHost : IRCDMessage +{ + IRCDMessageFHost(const Anope::string &n) : IRCDMessage(n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } - bool OnSJoin(const Anope::string &source, const std::vector ¶ms) anope_override + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + source.GetUser()->SetDisplayedHost(params[0]); + return true; + } +}; + +struct IRCDMessageFJoin : IRCDMessage +{ + IRCDMessageFJoin() : IRCDMessage("FJOIN", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override { Channel *c = findchan(params[0]); time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo(params[1]) : 0; @@ -719,7 +699,7 @@ class InspircdIRCdMessage : public IRCdMessage * This will enforce secureops etc on the user */ for (std::list::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it) - c->SetModeInternal(NULL, *it, buf); + c->SetModeInternal(source, *it, buf); /* Now set whatever modes this user is allowed to have on the channel */ chan_set_correct_modes(u, c, 1, true); @@ -746,206 +726,209 @@ class InspircdIRCdMessage : public IRCdMessage } }; -bool event_ftopic(const Anope::string &source, const std::vector ¶ms) +struct IRCDMessageFMode : IRCDMessage { - /* :source FTOPIC channel ts setby :topic */ - if (params.size() < 4) - return true; - - Channel *c = findchan(params[0]); - if (!c) + IRCDMessageFMode() : IRCDMessage("FMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override { - Log() << "TOPIC for nonexistant channel " << params[0]; - return true; - } + /* :source FMODE #test 12345678 +nto foo */ - c->ChangeTopicInternal(params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo(params[1]) : Anope::CurTime); + Channel *c = findchan(params[0]); + if (!c) + return true; + time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo(params[1]) : 0; - return true; -} + /* TS's are equal now, so we can proceed with parsing */ + // For fun, modes sometimes get sent without a mode prefix + Anope::string modes = "+" + params[2]; + for (unsigned n = 3; n < params.size(); ++n) + modes += " " + params[n]; -bool event_opertype(const Anope::string &source, const std::vector ¶ms) -{ - /* opertype is equivalent to mode +o because servers - dont do this directly */ - User *u = finduser(source); - if (u && !u->HasMode(UMODE_OPER)) - { - std::vector newparams; - newparams.push_back(source); - newparams.push_back("+o"); - return ircdmessage->OnMode(source, newparams); - } - else + c->SetModesInternal(source, modes, ts); return true; -} + } +}; -bool event_fmode(const Anope::string &source, const std::vector ¶ms) +struct IRCDMessageFTopic : IRCDMessage { - /* :source FMODE #test 12345678 +nto foo */ - if (params.size() < 3) - return true; + IRCDMessageFTopic() : IRCDMessage("FTOPIC", 4) { } - Channel *c = findchan(params[0]); - /* Checking the TS for validity to avoid desyncs */ - if (c) + bool Run(MessageSource &source, const std::vector ¶ms) anope_override { - time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo(params[1]) : 0; - if (c->creation_time > ts) - { - /* Our TS is bigger, we should lower it */ - c->creation_time = ts; - c->Reset(); - } - else if (c->creation_time < ts) - /* The TS we got is bigger, we should ignore this message. */ - return true; - } - else - /* Got FMODE for a non-existing channel */ - return true; - - /* TS's are equal now, so we can proceed with parsing */ - std::vector newparams; // channel, modes, ts - newparams.push_back(params[0]); - // For fun, modes sometimes get sent without a mode prefix - Anope::string modes = "+" + params[2]; - for (unsigned n = 3; n < params.size(); ++n) - modes += " " + params[n]; - newparams.push_back(modes); - newparams.push_back(params[1]); - - return ircdmessage->OnMode(source, newparams); -} + Channel *c = findchan(params[0]); + if (c) + c->ChangeTopicInternal(params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo(params[1]) : Anope::CurTime); -bool event_rsquit(const Anope::string &source, const std::vector ¶ms) -{ - if (params.empty() || params.size() > 3) return true; + } +}; - std::vector p; - /* Horrible workaround to an insp bug (#) in how RSQUITs are sent - mark */ - if (params.size() > 1 && Config->ServerName.equals_cs(params[0])) - p.push_back(params[1]); - else - p.push_back(params[0]); - - ircdmessage->OnSQuit(source, p); - - return true; -} - -bool event_setname(const Anope::string &source, const std::vector ¶ms) +struct IRCDMessageIdle : IRCDMessage { - if (params.empty()) - return true; + IRCDMessageIdle() : IRCDMessage("IDLE", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } - User *u = finduser(source); - if (!u) + bool Run(MessageSource &source, const std::vector ¶ms) anope_override { - Log(LOG_DEBUG) << "SETNAME for nonexistent user " << source; + const BotInfo *bi = findbot(params[0]); + UplinkSocket::Message(bi) << "IDLE " << source.GetSource() << " " << start_time << " " << (bi ? Anope::CurTime - bi->lastmsg : 0); return true; } +}; - u->SetRealname(params[0]); - return true; -} - -bool event_chgname(const Anope::string &source, const std::vector ¶ms) +struct IRCDMessageMode : IRCDMessage { - if (params.size() < 2) - return true; + IRCDMessageMode() : IRCDMessage("MODE", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - User *u = finduser(source); - if (!u) + bool Run(MessageSource &source, const std::vector ¶ms) anope_override { - Log(LOG_DEBUG) << "FNAME for nonexistent user " << source; + if (ircdproto->IsChannelValid(params[0])) + { + Channel *c = findchan(params[0]); + time_t ts; + + try + { + ts = convertTo(params[2]); + } + catch (const ConvertException &) + { + ts = Anope::CurTime; + } + + if (c) + c->SetModesInternal(source, params[1], ts); + } + else + { + User *u = finduser(params[0]); + if (u) + u->SetModesInternal("%s", params[1].c_str()); + } + return true; } +}; - u->SetRealname(params[0]); - return true; -} - -bool event_setident(const Anope::string &source, const std::vector ¶ms) +struct IRCDMessageNick : IRCDMessage { - if (!params.empty()) - return true; + IRCDMessageNick() : IRCDMessage("NICK", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - User *u = finduser(source); - if (!u) + bool Run(MessageSource &source, const std::vector ¶ms) anope_override { - Log(LOG_DEBUG) << "SETIDENT for nonexistent user " << source; + if (params.size() == 8 && source.GetServer()) + { + time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo(params[0]) : Anope::CurTime; + + User *user = new User(params[1], params[4], params[2], params[3], params[6], source.GetServer(), params[7], ts, params[5]); + if (nickserv) + { + NickAlias *na = findnick(user->nick); + Anope::string *svidbuf = na ? na->nc->GetExt *>("authenticationtoken") : NULL; + if (na && svidbuf && *svidbuf == params[0]) + { + NickCore *nc = na->nc; + user->Login(nc); + if (!Config->NoNicknameOwnership && na->nc->HasFlag(NI_UNCONFIRMED) == false) + user->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); + } + else if (nickserv) + nickserv->Validate(user); + } + } + else if (params.size() == 1 && source.GetUser()) + source.GetUser()->ChangeNick(params[0]); + return true; } +}; - u->SetIdent(params[0]); - return true; -} - -bool event_chgident(const Anope::string &source, const std::vector ¶ms) +struct IRCDMessageOperType : IRCDMessage { - if (params.size() < 2) - return true; + IRCDMessageOperType() : IRCDMessage("OPERTYPE", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_USER); } - User *u = finduser(params[0]); - if (!u) + bool Run(MessageSource &source, const std::vector ¶ms) anope_override { - Log(LOG_DEBUG) << "CHGIDENT for nonexistent user " << params[0]; + /* opertype is equivalent to mode +o because servers + dont do this directly */ + User *u = source.GetUser(); + if (!u->HasMode(UMODE_OPER)) + u->SetModesInternal("+o"); + return true; } +}; - u->SetIdent(params[1]); - return true; -} - -bool event_sethost(const Anope::string &source, const std::vector ¶ms) +struct IRCDMessageRSQuit : IRCDMessage { - if (params.empty()) - return true; + IRCDMessageRSQuit() : IRCDMessage("RSQUIT", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } - User *u = finduser(source); - if (!u) + bool Run(MessageSource &source, const std::vector ¶ms) anope_override { - Log(LOG_DEBUG) << "SETHOST for nonexistent user " << source; - return true; - } + if (params.empty() || params.size() > 3) + return true; - u->SetDisplayedHost(params[0]); - return true; -} + Server *s; + /* Horrible workaround to an insp bug (#) in how RSQUITs are sent - mark */ + if (params.size() > 1 && Config->ServerName.equals_cs(params[0])) + s = Server::Find(params[1]); + else + s = Server::Find(params[0]); + source.GetServer()->Delete(source.GetServer()->GetName() + " " + source.GetServer()->GetUplink()->GetName()); -bool event_chghost(const Anope::string &source, const std::vector ¶ms) -{ - if (params.empty()) return true; + } +}; - User *u = finduser(source); - if (!u) +struct IRCDMessageServer : IRCDMessage +{ + IRCDMessageServer() : IRCDMessage("SERVER", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override { - Log(LOG_DEBUG) << "FHOST for nonexistent user " << source; + unsigned int hops = Anope::string(params[1]).is_pos_number_only() ? convertTo(params[1]) : 0; + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[2]); return true; } - - u->SetDisplayedHost(params[0]); - return true; -} - -bool event_endburst(const Anope::string &source, const std::vector ¶ms) -{ - Me->GetLinks().front()->Sync(true); - return true; -} +}; class ProtoInspIRCd : public Module { - Message message_endburst, message_rsquit, message_svsmode, message_chghost, message_chgident, message_chgname, - message_sethost, message_setident, message_setname, message_fmode, message_ftopic, message_opertype, - message_idle, message_fjoin; - InspIRCdProto ircd_proto; - InspircdIRCdMessage ircd_message; + + /* Core message handlers */ + CoreIRCDMessageAway core_message_away; + CoreIRCDMessageCapab core_message_capab; + CoreIRCDMessageError core_message_error; + CoreIRCDMessageJoin core_message_join; + CoreIRCDMessageKill core_message_kill; + CoreIRCDMessageMOTD core_message_motd; + CoreIRCDMessagePart core_message_part; + CoreIRCDMessagePing core_message_ping; + CoreIRCDMessagePrivmsg core_message_privmsg; + CoreIRCDMessageQuit core_message_quit; + CoreIRCDMessageSQuit core_message_squit; + CoreIRCDMessageStats core_message_stats; + CoreIRCDMessageTime core_message_time; + CoreIRCDMessageTopic core_message_topic; + CoreIRCDMessageVersion core_message_version; + + /* Our message handlers */ + IRCDMessageCapab message_capab; + IRCDMessageChgIdent message_chgident, message_setident; + IRCDMessageChgName message_chgname, message_setname; + IRCDMessageEndBurst message_endburst; + IRCDMessageFHost message_fhost, message_sethost; + IRCDMessageFJoin message_fjoin; + IRCDMessageFMode message_fmode; + IRCDMessageFTopic message_ftopic; + IRCDMessageIdle message_idle; + IRCDMessageMode message_mode; + IRCDMessageNick message_nick; + IRCDMessageOperType message_opertype; + IRCDMessageRSQuit message_rsquit; + IRCDMessageServer message_server; void AddModes() { @@ -960,20 +943,12 @@ class ProtoInspIRCd : public Module public: ProtoInspIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_endburst("ENDBURST", event_endburst), message_rsquit("RSQUIT", event_rsquit), - message_svsmode("SVSMODE", OnMode), message_chghost("CHGHOST", event_chghost), - message_chgident("CHGIDENT", event_chgident), message_chgname("CHGNAME", event_chgname), - message_sethost("SETHOST", event_sethost), message_setident("SETIDENT", event_setident), - message_setname("SETNAME", event_setname), message_fmode("FMODE", event_fmode), - message_ftopic("FTOPIC", event_ftopic), message_opertype("OPERTYPE", event_opertype), - message_idle("IDLE", event_idle), message_fjoin("FJOIN", OnSJoin) + message_chgident("CHGIDENT"), message_setident("SETIDENT"), + message_chgname("CHGNAME"), message_setname("SETNAME"), + message_fhost("FHOST"), message_sethost("SETHOST") { this->SetAuthor("Anope"); - pmodule_ircd_var(&myIrcd); - pmodule_ircd_proto(&this->ircd_proto); - pmodule_ircd_message(&this->ircd_message); - Capab.insert("NOQUIT"); this->AddModes(); diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp index e20e9c87d..c780e8299 100644 --- a/modules/protocol/inspircd12.cpp +++ b/modules/protocol/inspircd12.cpp @@ -20,250 +20,15 @@ static bool has_chgidentmod = false; static bool has_rlinemod = false; #include "inspircd-ts6.h" -IRCDVar myIrcd = { - "InspIRCd 1.2", /* ircd name */ - "+I", /* Modes used by pseudoclients */ - 1, /* SVSNICK */ - 1, /* Vhost */ - 0, /* Supports SNlines */ - 1, /* Supports SQlines */ - 1, /* Supports SZlines */ - 0, /* Join 2 Message */ - 0, /* Chan SQlines */ - 0, /* Quit on Kill */ - 1, /* vidents */ - 1, /* svshold */ - 0, /* time stamp on mode */ - 0, /* O:LINE */ - 1, /* UMODE */ - 1, /* No Knock requires +i */ - 0, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 1, /* ts6 */ - "$", /* TLD Prefix for Global */ - 20, /* Max number of modes we can send per line */ - 1, /* IRCd sends a SSL users certificate fingerprint */ -}; - static bool has_servicesmod = false; static bool has_svsholdmod = false; static bool has_hidechansmod = false; -bool event_ftopic(const Anope::string &source, const std::vector ¶ms) -{ - /* :source FTOPIC channel ts setby :topic */ - if (params.size() < 4) - return true; - - Channel *c = findchan(params[0]); - if (!c) - { - Log(LOG_DEBUG) << "TOPIC " << params[3] << " for nonexistent channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo(params[1]) : Anope::CurTime); - - return true; -} - -bool event_opertype(const Anope::string &source, const std::vector ¶ms) -{ - /* opertype is equivalent to mode +o because servers - dont do this directly */ - User *u = finduser(source); - if (u && !u->HasMode(UMODE_OPER)) - { - std::vector newparams; - newparams.push_back(source); - newparams.push_back("+o"); - return ircdmessage->OnMode(source, newparams); - } - - return true; -} - -bool event_fmode(const Anope::string &source, const std::vector ¶ms) -{ - /* :source FMODE #test 12345678 +nto foo */ - if (params.size() < 3) - return true; - - Channel *c = findchan(params[0]); - if (!c) - return true; - - /* Checking the TS for validity to avoid desyncs */ - time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo(params[1]) : 0; - if (c->creation_time > ts) - { - /* Our TS is bigger, we should lower it */ - c->creation_time = ts; - c->Reset(); - } - else if (c->creation_time < ts) - /* The TS we got is bigger, we should ignore this message. */ - return true; - - /* TS's are equal now, so we can proceed with parsing */ - std::vector newparams; - newparams.push_back(params[0]); - newparams.push_back(params[1]); - Anope::string modes = params[2]; - for (unsigned n = 3; n < params.size(); ++n) - modes += " " + params[n]; - newparams.push_back(modes); - - return ircdmessage->OnMode(source, newparams); -} - -bool event_setname(const Anope::string &source, const std::vector ¶ms) -{ - User *u = finduser(source); - if (!u) - { - Log(LOG_DEBUG) << "SETNAME for nonexistent user " << source; - return true; - } - else if (params.empty()) - return true; - - u->SetRealname(params[0]); - return true; -} - -bool event_chgname(const Anope::string &source, const std::vector ¶ms) -{ - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "FNAME for nonexistent user " << source; - return true; - } - else if (params.empty()) - return true; - - u->SetRealname(params[0]); - return true; -} - -bool event_setident(const Anope::string &source, const std::vector ¶ms) +class InspIRCd12Proto : public InspIRCdTS6Proto { - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "SETIDENT for nonexistent user " << source; - return true; - } - - u->SetIdent(params[0]); - return true; -} - -bool event_chgident(const Anope::string &source, const std::vector ¶ms) -{ - User *u = finduser(params[0]); - - if (!u) - { - Log(LOG_DEBUG) << "CHGIDENT for nonexistent user " << params[0]; - return true; - } - - u->SetIdent(params[1]); - return true; -} - -bool event_sethost(const Anope::string &source, const std::vector ¶ms) -{ - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "SETHOST for nonexistent user " << source; - return true; - } - - u->SetDisplayedHost(params[0]); - return true; -} - - -bool event_chghost(const Anope::string &source, const std::vector ¶ms) -{ - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "FHOST for nonexistent user " << source; - return true; - } - - u->SetDisplayedHost(params[0]); - return true; -} - - -/* - * source = numeric of the sending server - * params[0] = uuid - * params[1] = metadata name - * params[2] = data - */ -bool event_metadata(const Anope::string &source, const std::vector ¶ms) -{ - if (params.size() < 3) - return true; - else if (params[1].equals_cs("accountname")) - { - User *u = finduser(params[0]); - NickCore *nc = findcore(params[2]); - if (u && nc) - { - u->Login(nc); - - const NickAlias *user_na = findnick(u->nick); - if (!Config->NoNicknameOwnership && nickserv && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); - } - } - - /* - * possible incoming ssl_cert messages: - * Received: :409 METADATA 409AAAAAA ssl_cert :vTrSe c38070ce96e41cc144ed6590a68d45a6 <...> <...> - * Received: :409 METADATA 409AAAAAC ssl_cert :vTrSE Could not get peer certificate: error:00000000:lib(0):func(0):reason(0) - */ - else if (params[1].equals_cs("ssl_cert")) - { - User *u = finduser(params[0]); - if (!u) - return true; - std::string data = params[2].c_str(); - size_t pos1 = data.find(' ') + 1; - size_t pos2 = data.find(' ', pos1); - if ((pos2 - pos1) >= 32) // inspircd supports md5 and sha1 fingerprint hashes -> size 32 or 40 bytes. - { - u->fingerprint = data.substr(pos1, pos2 - pos1); - FOREACH_MOD(I_OnFingerprint, OnFingerprint(u)); - } - } - return true; -} - -bool event_endburst(const Anope::string &source, const std::vector ¶ms) -{ - Server *s = Server::Find(source); - - if (!s) - throw CoreException("Got ENDBURST without a source"); - - Log(LOG_DEBUG) << "Processed ENDBURST for " << s->GetName(); - - s->Sync(true); - return true; -} + public: + InspIRCd12Proto() : InspIRCdTS6Proto("InspIRCd 1.2") { } +}; class InspIRCdExtBan : public ChannelModeList { @@ -316,37 +81,11 @@ class InspIRCdExtBan : public ChannelModeList } }; -class Inspircd12IRCdMessage : public InspircdIRCdMessage +struct IRCDMessageCapab : IRCDMessage { - public: - /* - * [Nov 03 22:09:58.176252 2009] debug: Received: :964 UID 964AAAAAC 1225746297 w00t2 localhost testnet.user w00t 127.0.0.1 1225746302 +iosw +ACGJKLNOQcdfgjklnoqtx :Robin Burchell - * 0: uid - * 1: ts - * 2: nick - * 3: host - * 4: dhost - * 5: ident - * 6: ip - * 7: signon - * 8+: modes and params -- IMPORTANT, some modes (e.g. +s) may have parameters. So don't assume a fixed position of realname! - * last: realname - */ - bool OnUID(const Anope::string &source, const std::vector ¶ms) anope_override - { - time_t ts = convertTo(params[1]); + IRCDMessageCapab() : IRCDMessage("CAPAB", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - Anope::string modes = params[8]; - for (unsigned i = 9; i < params.size() - 1; ++i) - modes += " " + params[i]; - User *user = do_nick("", params[2], params[5], params[3], source, params[params.size() - 1], ts, params[6], params[4], params[0], modes); - if (user && user->server->IsSynced() && nickserv) - nickserv->Validate(user); - - return true; - } - - bool OnCapab(const Anope::string &source, const std::vector ¶ms) anope_override + bool Run(MessageSource &source, const std::vector ¶ms) anope_override { if (params[0].equals_cs("START")) { @@ -358,7 +97,7 @@ class Inspircd12IRCdMessage : public InspircdIRCdMessage has_chgidentmod = false; has_hidechansmod = false; } - else if (params[0].equals_cs("MODULES")) + else if (params[0].equals_cs("MODULES") && params.size() > 1) { if (params[1].find("m_globops.so") != Anope::string::npos) has_globopsmod = true; @@ -373,11 +112,11 @@ class Inspircd12IRCdMessage : public InspircdIRCdMessage if (params[1].find("m_hidechans.so") != Anope::string::npos) has_hidechansmod = true; if (params[1].find("m_servprotect.so") != Anope::string::npos) - ircd->pseudoclient_mode = "+Ik"; + ircdproto->DefaultPseudoclientModes = "+Ik"; if (params[1].find("m_rline.so") != Anope::string::npos) has_rlinemod = true; } - else if (params[0].equals_cs("CAPABILITIES")) + else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1) { spacesepstream ssep(params[1]); Anope::string capab; @@ -643,7 +382,7 @@ class Inspircd12IRCdMessage : public InspircdIRCdMessage else if (capab.find("MAXMODES=") != Anope::string::npos) { Anope::string maxmodes(capab.begin() + 9, capab.end()); - ircd->maxmodes = maxmodes.is_pos_number_only() ? convertTo(maxmodes) : 3; + ircdproto->MaxModes = maxmodes.is_pos_number_only() ? convertTo(maxmodes) : 3; } } } @@ -676,43 +415,97 @@ class Inspircd12IRCdMessage : public InspircdIRCdMessage Log() << "CHGHOST missing, Usage disabled until module is loaded."; if (!has_chgidentmod) Log() << "CHGIDENT missing, Usage disabled until module is loaded."; - ircd->svshold = has_svsholdmod; + ircdproto->CanSVSHold = has_svsholdmod; } - IRCdMessage::OnCapab(source, params); + return true; + } +}; + +struct IRCDMessageChgIdent : IRCDMessage +{ + IRCDMessageChgIdent() : IRCDMessage("CHGIDENT", 2) { } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + User *u = finduser(params[0]); + if (u) + u->SetIdent(params[1]); + return true; + } +}; + +struct IRCDMessageChgName : IRCDMessage +{ + IRCDMessageChgName(const Anope::string &n) : IRCDMessage(n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + source.GetUser()->SetRealname(params[0]); + return true; + } +}; + +struct IRCDMessageSetIdent : IRCDMessage +{ + IRCDMessageSetIdent() : IRCDMessage("SETIDENT", 0) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector ¶ms) anope_override + { + source.GetUser()->SetIdent(params[0]); return true; } }; class ProtoInspIRCd : public Module { - Message message_endburst, message_time, - message_rsquit, message_svsmode, message_fhost, - message_chgident, message_fname, message_sethost, message_setident, message_setname, message_fjoin, message_fmode, - message_ftopic,