plexus.cpp

Go to the documentation of this file.
00001 /* Plexus 3+ IRCD functions
00002  *
00003  * (C) 2003-2013 Anope Team
00004  * Contact us at team@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church.
00010  */
00011 
00012 #include "module.h"
00013 
00014 static Anope::string UplinkSID;
00015 
00016 static ServiceReference<IRCDProto> hybrid("IRCDProto", "hybrid");
00017 
00018 class PlexusProto : public IRCDProto
00019 {
00020  public:
00021         PlexusProto(Module *creator) : IRCDProto(creator, "hybrid-7.2.3+plexus-3.0.1")
00022         {
00023                 DefaultPseudoclientModes = "+oiU";
00024                 CanSVSNick = true;
00025                 CanSVSJoin = true;
00026                 CanSetVHost = true;
00027                 CanSetVIdent = true;
00028                 CanSNLine = true;
00029                 CanSQLine = true;
00030                 CanSQLineChannel = true;
00031                 CanSVSHold = true;
00032                 CanCertFP = true;
00033                 RequiresID = true;
00034                 MaxModes = 4;
00035         }
00036 
00037         void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { hybrid->SendGlobalNotice(bi, dest, msg); }
00038         void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { hybrid->SendGlobalPrivmsg(bi, dest, msg); }
00039         void SendGlobopsInternal(const BotInfo *source, const Anope::string &buf) anope_override { hybrid->SendGlobopsInternal(source, buf); }
00040         void SendSQLine(User *u, const XLine *x) anope_override { hybrid->SendSQLine(u, x); }
00041         void SendSQLineDel(const XLine *x) anope_override { hybrid->SendSQLineDel(x); }
00042         void SendSGLineDel(const XLine *x) anope_override { hybrid->SendSGLineDel(x); }
00043         void SendSGLine(User *u, const XLine *x) anope_override { hybrid->SendSGLine(u, x); }
00044         void SendAkillDel(const XLine *x) anope_override { hybrid->SendAkillDel(x); }
00045         void SendAkill(User *u, XLine *x) anope_override { hybrid->SendAkill(u, x); }
00046         void SendServer(const Server *server) anope_override { hybrid->SendServer(server); }
00047         void SendChannel(Channel *c) anope_override { hybrid->SendChannel(c); }
00048         void SendSVSHold(const Anope::string &nick) anope_override { hybrid->SendSVSHold(nick); }
00049         void SendSVSHoldDel(const Anope::string &nick) anope_override { hybrid->SendSVSHoldDel(nick); }
00050 
00051         void SendJoin(const User *user, Channel *c, const ChannelStatus *status) anope_override
00052         {
00053                 UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name << " +" << c->GetModes(true, true) << " :" << user->GetUID();
00054                 if (status)
00055                 {
00056                         /* First save the channel status incase uc->Status == status */
00057                         ChannelStatus cs = *status;
00058                         /* If the user is internally on the channel with flags, kill them so that
00059                          * the stacker will allow this.
00060                          */
00061                         ChanUserContainer *uc = c->FindUser(user);
00062                         if (uc != NULL)
00063                                 uc->status.modes.clear();
00064 
00065                         BotInfo *setter = BotInfo::Find(user->nick);
00066                         for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i)
00067                                 if (cs.modes.count(ModeManager::ChannelModes[i]->name))
00068                                         c->SetMode(setter, ModeManager::ChannelModes[i], user->GetUID(), false);
00069                 }
00070         }
00071 
00072         void SendForceNickChange(const User *u, const Anope::string &newnick, time_t when) anope_override
00073         {
00074                 UplinkSocket::Message(Me) << "ENCAP " << u->server->GetName() << " SVSNICK " << u->GetUID() << " " << u->timestamp << " " << newnick << " " << when;
00075         }
00076 
00077         void SendVhost(User *u, const Anope::string &ident, const Anope::string &host) anope_override
00078         {
00079                 if (!ident.empty())
00080                         UplinkSocket::Message(Me) << "ENCAP * CHGIDENT " << u->GetUID() << " " << ident;
00081                 UplinkSocket::Message(Me) << "ENCAP * CHGHOST " << u->GetUID() << " " << host;
00082         }
00083 
00084         void SendVhostDel(User *u) anope_override
00085         {
00086                 if (u->HasMode("CLOAK"))
00087                         u->RemoveMode(HostServ, "CLOAK");
00088                 else
00089                         this->SendVhost(u, u->GetIdent(), u->chost);
00090         }
00091 
00092         void SendConnect() anope_override
00093         {
00094                 UplinkSocket::Message() << "PASS " << Config->Uplinks[Anope::CurrentUplink]->password << " TS 6 :" << Me->GetSID();
00095                 /* CAPAB
00096                  * QS     - Can handle quit storm removal
00097                  * EX     - Can do channel +e exemptions
00098                  * CHW    - Can do channel wall @#
00099                  * LL     - Can do lazy links
00100                  * IE     - Can do invite exceptions
00101                  * EOB    - Can do EOB message
00102                  * KLN    - Can do KLINE message
00103                  * GLN    - Can do GLINE message
00104                  * HUB    - This server is a HUB
00105                  * AOPS   - Can do anon ops (+a)
00106                  * UID    - Can do UIDs
00107                  * ZIP    - Can do ZIPlinks
00108                  * ENC    - Can do ENCrypted links
00109                  * KNOCK  - Supports KNOCK
00110                  * TBURST - Supports TBURST
00111                  * PARA   - Supports invite broadcasting for +p
00112                  * ENCAP  - Supports encapsulization of protocol messages
00113                  * SVS    - Supports services protocol extensions
00114                  */
00115                 UplinkSocket::Message() << "CAPAB :QS EX CHW IE EOB KLN UNKLN GLN HUB KNOCK TBURST PARA ENCAP SVS";
00116                 /* Make myself known to myself in the serverlist */
00117                 SendServer(Me);
00118                 /*
00119                  * SVINFO
00120                  *        parv[0] = sender prefix
00121                  *        parv[1] = TS_CURRENT for the server
00122                  *        parv[2] = TS_MIN for the server
00123                  *        parv[3] = server is standalone or connected to non-TS only
00124                  *        parv[4] = server's idea of UTC time
00125                  */
00126                 UplinkSocket::Message() << "SVINFO 6 5 0 :" << Anope::CurTime;
00127         }
00128 
00129         void SendClientIntroduction(const User *u) anope_override
00130         {
00131                 Anope::string modes = "+" + u->GetModes();
00132                 UplinkSocket::Message(Me) << "UID " << u->nick << " 1 " << u->timestamp << " " << modes << " " << u->GetIdent() << " " << u->host << " 255.255.255.255 " << u->GetUID() << " 0 " << u->host << " :" << u->realname;
00133         }
00134 
00135         void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf) anope_override
00136         {
00137                 UplinkSocket::Message(bi) << "ENCAP * SVSMODE " << u->GetUID() << " " << u->timestamp << " " << buf;
00138         }
00139 
00140         void SendLogin(User *u) anope_override
00141         {
00142                 if (!u->Account())
00143                         return;
00144 
00145                 UplinkSocket::Message(Me) << "ENCAP * SU " << u->GetUID() << " " << u->Account()->display;
00146         }
00147 
00148         void SendLogout(User *u) anope_override
00149         {
00150                 UplinkSocket::Message(Me) << "ENCAP * SU " << u->GetUID();
00151         }
00152 
00153         void SendTopic(BotInfo *bi, Channel *c) anope_override
00154         {
00155                 UplinkSocket::Message(bi) << "ENCAP * TOPIC " << c->name << " " << c->topic_setter << " " << c->topic_ts << " :" << c->topic;
00156         }
00157 
00158         void SendSVSJoin(const BotInfo *source, const User *user, const Anope::string &chan, const Anope::string &param) anope_override
00159         {
00160                 UplinkSocket::Message(source) << "ENCAP " << user->server->GetName() << " SVSJOIN " << user->GetUID() << " " << chan;
00161         }
00162 
00163         void SendSVSPart(const BotInfo *source, const User *user, const Anope::string &chan, const Anope::string &param) anope_override
00164         {
00165                 UplinkSocket::Message(source) << "ENCAP " << user->server->GetName() << " SVSPART " << user->GetUID() << " " << chan;
00166         }
00167 };
00168 
00169 struct IRCDMessageEncap : IRCDMessage
00170 {
00171         IRCDMessageEncap(Module *creator) : IRCDMessage(creator, "ENCAP", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
00172 
00173         void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
00174         {
00175                 /*
00176                  * Received: :dev.anope.de ENCAP * SU DukePyrolator DukePyrolator
00177                  * params[0] = *
00178                  * params[1] = SU
00179                  * params[2] = nickname
00180                  * params[3] = account
00181                  */
00182                 if (params[1].equals_cs("SU"))
00183                 {
00184                         User *u = User::Find(params[2]);
00185                         const NickAlias *user_na = NickAlias::Find(params[2]);
00186                         NickCore *nc = NickCore::Find(params[3]);
00187                         if (u && nc)
00188                         {
00189                                 u->Login(nc);
00190                                 if (!Config->NoNicknameOwnership && user_na && user_na->nc == nc && user_na->nc->HasExt("UNCONFIRMED") == false)
00191                                         u->SetMode(NickServ, "REGISTERED");
00192                         }
00193                 }
00194 
00195                 /*
00196                  * Received: :dev.anope.de ENCAP * CERTFP DukePyrolator :3F122A9CC7811DBAD3566BF2CEC3009007C0868F
00197                  * params[0] = *
00198                  * params[1] = CERTFP
00199                  * params[2] = nickname
00200                  * params[3] = fingerprint
00201                  */
00202                 else if (params[1].equals_cs("CERTFP"))
00203                 {
00204                         User *u = User::Find(params[2]);
00205                         if (u)
00206                         {
00207                                 u->fingerprint = params[3];
00208                                 FOREACH_MOD(I_OnFingerprint, OnFingerprint(u));
00209                         }
00210                 }
00211                 return;
00212         }
00213 };
00214 
00215 struct IRCDMessagePass : IRCDMessage
00216 {
00217         IRCDMessagePass(Module *creator) : IRCDMessage(creator, "PASS", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
00218 
00219         void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
00220         {
00221                 UplinkSID = params[3];
00222         }
00223 };
00224 
00225 struct IRCDMessageServer : IRCDMessage
00226 {
00227         IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
00228 
00229         /*        0          1  2                       */
00230         /* SERVER hades.arpa 1 :ircd-hybrid test server */
00231         void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
00232         {
00233                 /* Servers other than our immediate uplink are introduced via SID */
00234                 if (params[1] != "1")
00235                         return;
00236 
00237                 new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], 1, params[2], UplinkSID);
00238         }
00239 };
00240 
00241 struct IRCDMessageUID : IRCDMessage
00242 {
00243         ServiceReference<NickServService> NSService;
00244 
00245         IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 11), NSService("NickServService", "NickServ") { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
00246 
00247         /*
00248            params[0] = nick
00249            params[1] = hop
00250            params[2] = ts
00251            params[3] = modes
00252            params[4] = user
00253            params[5] = host
00254            params[6] = IP
00255            params[7] = UID
00256            params[8] = services stamp
00257            params[9] = realhost
00258            params[10] = info
00259         */
00260         // :42X UID Adam 1 1348535644 +aow Adam 192.168.0.5 192.168.0.5 42XAAAAAB 0 192.168.0.5 :Adam
00261         void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
00262         {
00263                 /* An IP of 0 means the user is spoofed */
00264                 Anope::string ip = params[6];
00265                 if (ip == "0")
00266                         ip.clear();
00267 
00268                 time_t ts;
00269                 try
00270                 {
00271                         ts = convertTo<time_t>(params[2]);
00272                 }
00273                 catch (const ConvertException &)
00274                 {
00275                         ts = Anope::CurTime;
00276                 }
00277 
00278                 User *user = new User(params[0], params[4], params[9], params[5], ip, source.GetServer(), params[10], ts, params[3], params[7]);
00279                 try
00280                 {
00281                         if (NSService && params[8].is_pos_number_only() && convertTo<time_t>(params[8]) == user->timestamp)
00282                         {
00283                                 NickAlias *na = NickAlias::Find(user->nick);
00284                                 if (na)
00285                                         NSService->Login(user, na);
00286                         }
00287                 }
00288                 catch (const ConvertException &) { }
00289         }
00290 };
00291 
00292 class ProtoPlexus : public Module
00293 {
00294         Module *m_hybrid;
00295 
00296         PlexusProto ircd_proto;
00297 
00298         /* Core message handlers */
00299         Message::Away message_away;
00300         Message::Capab message_capab;
00301         Message::Error message_error;
00302         Message::Kick message_kick;
00303         Message::Kill message_kill;
00304         Message::Mode message_mode;
00305         Message::MOTD message_motd;
00306         Message::Part message_part;
00307         Message::Ping message_ping;
00308         Message::Privmsg message_privmsg;
00309         Message::Quit message_quit;
00310         Message::SQuit message_squit;
00311         Message::Stats message_stats;
00312         Message::Time message_time;
00313         Message::Topic message_topic;
00314         Message::Version message_version;
00315         Message::Whois message_whois;
00316         
00317         /* Hybrid message handlers */
00318         ServiceAlias message_bmask, message_eob, message_join, message_nick, message_sid, message_sjoin,
00319                         message_tburst, message_tmode;
00320 
00321         /* Our message handlers */
00322         IRCDMessageEncap message_encap;
00323         IRCDMessagePass message_pass;
00324         IRCDMessageServer message_server;
00325         IRCDMessageUID message_uid;
00326 
00327         void AddModes()
00328         {
00329                 /* Add user modes */
00330                 ModeManager::RemoveUserMode(ModeManager::FindUserModeByName("HIDEOPER"));
00331                 ModeManager::AddUserMode(new UserMode("NOCTCP", 'C'));
00332                 ModeManager::AddUserMode(new UserMode("DEAF", 'D'));
00333                 ModeManager::AddUserMode(new UserMode("SOFTCALLERID", 'G'));
00334                 ModeManager::AddUserMode(new UserMode("NETADMIN", 'N'));
00335                 ModeManager::AddUserMode(new UserMode("SSL", 'S'));
00336                 ModeManager::AddUserMode(new UserMode("WEBIRC", 'W'));
00337                 ModeManager::AddUserMode(new UserMode("CALLERID", 'g'));
00338                 ModeManager::AddUserMode(new UserMode("PRIV", 'p'));
00339                 ModeManager::AddUserMode(new UserMode("CLOAK", 'x'));
00340                 ModeManager::AddUserMode(new UserMode("PROTECTED", 'U'));
00341 
00342                 /* v/h/o/a/q */
00343                 ModeManager::AddChannelMode(new ChannelModeStatus("PROTECT", 'a', '&', 3));
00344                 ModeManager::AddChannelMode(new ChannelModeStatus("OWNER", 'q', '~', 4));
00345 
00346                 /* Add channel modes */
00347                 ModeManager::RemoveChannelMode(ModeManager::FindChannelModeByName("REGISTERED"));
00348                 ModeManager::AddChannelMode(new ChannelMode("BANDWIDTH", 'B'));
00349                 ModeManager::AddChannelMode(new ChannelMode("NOCTCP", 'C'));
00350                 ModeManager::AddChannelMode(new ChannelMode("REGMODERATED", 'M'));
00351                 ModeManager::AddChannelMode(new ChannelMode("NONOTICE", 'N'));
00352                 ModeManager::AddChannelMode(new ChannelMode("BLOCKCOLOR", 'c'));
00353                 ModeManager::AddChannelMode(new ChannelMode("PERM", 'z'));
00354         }
00355 
00356  public:
00357         ProtoPlexus(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL),
00358                 ircd_proto(this),
00359                 message_away(this), message_capab(this), message_error(this), message_kick(this), message_kill(this),
00360                 message_mode(this), message_motd(this), message_part(this), message_ping(this), message_privmsg(this), message_quit(this),
00361                 message_squit(this), message_stats(this), message_time(this), message_topic(this), message_version(this), message_whois(this),
00362 
00363                 message_bmask("IRCDMessage", "plexus/bmask", "hybrid/bmask"), message_eob("IRCDMessage", "plexus/eob", "hybrid/eob"),
00364                 message_join("IRCDMessage", "plexus/join", "hybrid/join"), message_nick("IRCDMessage", "plexus/nick", "hybrid/nick"),
00365                 message_sid("IRCDMessage", "plexus/sid", "hybrid/sid"),
00366                 message_sjoin("IRCDMessage", "plexus/sjoin", "hybrid/sjoin"), message_tburst("IRCDMessage", "plexus/tburst", "hybrid/tburst"),
00367                 message_tmode("IRCDMessage", "plexus/tmode", "hybrid/tmode"),
00368 
00369                 message_encap(this), message_pass(this), message_server(this), message_uid(this)
00370         {
00371                 this->SetAuthor("Anope");
00372 
00373                 if (ModuleManager::LoadModule("hybrid", User::Find(creator)) != MOD_ERR_OK)
00374                         throw ModuleException("Unable to load hybrid");
00375                 m_hybrid = ModuleManager::FindModule("hybrid");
00376                 if (!m_hybrid)
00377                         throw ModuleException("Unable to find hybrid");
00378                 if (!hybrid)
00379                         throw ModuleException("No protocol interface for hybrid");
00380 
00381                 this->AddModes();
00382         }
00383 
00384         ~ProtoPlexus()
00385         {
00386                 ModuleManager::UnloadModule(m_hybrid, NULL);
00387         }
00388 };
00389 
00390 MODULE_INIT(ProtoPlexus)