anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

ratbox.cpp (12727B)

      1 /* Ratbox IRCD functions
      2  *
      3  * (C) 2003-2022 Anope Team
      4  * Contact us at team@anope.org
      5  *
      6  * Please read COPYING and README for further details.
      7  *
      8  * Based on the original code of Epona by Lara.
      9  * Based on the original code of Services by Andy Church.
     10  */
     11 
     12 #include "module.h"
     13 
     14 static Anope::string UplinkSID;
     15 
     16 static ServiceReference<IRCDProto> hybrid("IRCDProto", "hybrid");
     17 
     18 class RatboxProto : public IRCDProto
     19 {
     20 	BotInfo *FindIntroduced()
     21 	{
     22 		BotInfo *bi = Config->GetClient("OperServ");
     23 
     24 		if (bi && bi->introduced)
     25 			return bi;
     26 
     27 		for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
     28 			if (it->second->introduced)
     29 				return it->second;
     30 
     31 		return NULL;
     32 	}
     33 
     34  public:
     35 	RatboxProto(Module *creator) : IRCDProto(creator, "Ratbox 3.0+")
     36 	{
     37 		DefaultPseudoclientModes = "+oiS";
     38 		CanSNLine = true;
     39 		CanSQLine = true;
     40 		CanSQLineChannel = true;
     41 		CanSZLine = true;
     42 		RequiresID = true;
     43 		MaxModes = 4;
     44 	}
     45 
     46 	void SendSVSKillInternal(const MessageSource &source, User *targ, const Anope::string &reason) anope_override { hybrid->SendSVSKillInternal(source, targ, reason); }
     47 	void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { hybrid->SendGlobalNotice(bi, dest, msg); }
     48 	void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { hybrid->SendGlobalPrivmsg(bi, dest, msg); }
     49 	void SendSGLine(User *u, const XLine *x) anope_override { hybrid->SendSGLine(u, x); }
     50 	void SendSGLineDel(const XLine *x) anope_override { hybrid->SendSGLineDel(x); }
     51 	void SendAkill(User *u, XLine *x) anope_override { hybrid->SendAkill(u, x); }
     52 	void SendAkillDel(const XLine *x) anope_override { hybrid->SendAkillDel(x); }
     53 	void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override { hybrid->SendJoin(user, c, status); }
     54 	void SendServer(const Server *server) anope_override { hybrid->SendServer(server); }
     55 	void SendModeInternal(const MessageSource &source, User *u, const Anope::string &buf) anope_override { hybrid->SendModeInternal(source, u, buf); }
     56 	void SendChannel(Channel *c) anope_override { hybrid->SendChannel(c); }
     57 	bool IsIdentValid(const Anope::string &ident) anope_override { return hybrid->IsIdentValid(ident); }
     58 
     59 	void SendGlobopsInternal(const MessageSource &source, const Anope::string &buf) anope_override
     60 	{
     61 		UplinkSocket::Message(source) << "OPERWALL :" << buf;
     62 	}
     63 
     64 	void SendSQLine(User *, const XLine *x) anope_override
     65 	{
     66 		/* Calculate the time left before this would expire, capping it at 2 days */
     67 		time_t timeleft = x->expires - Anope::CurTime;
     68 
     69 		if (timeleft > 172800 || !x->expires)
     70 			timeleft = 172800;
     71 
     72 		UplinkSocket::Message(FindIntroduced()) << "ENCAP * RESV " << timeleft << " " << x->mask << " 0 :" << x->GetReason();
     73 	}
     74 
     75 	void SendSQLineDel(const XLine *x) anope_override
     76 	{
     77 		UplinkSocket::Message(Config->GetClient("OperServ")) << "ENCAP * UNRESV " << x->mask;
     78 	}
     79 
     80 	void SendConnect() anope_override
     81 	{
     82 		UplinkSocket::Message() << "PASS " << Config->Uplinks[Anope::CurrentUplink].password << " TS 6 :" << Me->GetSID();
     83 		/*
     84 		  QS     - Can handle quit storm removal
     85 		  EX     - Can do channel +e exemptions
     86 		  CHW    - Can do channel wall @#
     87 		  IE     - Can do invite exceptions
     88 		  GLN    - Can do GLINE message
     89 		  KNOCK  - supports KNOCK
     90 		  TB     - supports topic burst
     91 		  ENCAP  - supports ENCAP
     92 		*/
     93 		UplinkSocket::Message() << "CAPAB :QS EX CHW IE GLN TB ENCAP";
     94 		/* Make myself known to myself in the serverlist */
     95 		SendServer(Me);
     96 		/*
     97 		 * SVINFO
     98 		 *	  parv[0] = sender prefix
     99 		 *	  parv[1] = TS_CURRENT for the server
    100 		 *	  parv[2] = TS_MIN for the server
    101 		 *	  parv[3] = server is standalone or connected to non-TS only
    102 		 *	  parv[4] = server's idea of UTC time
    103 		 */
    104 		UplinkSocket::Message() << "SVINFO 6 3 0 :" << Anope::CurTime;
    105 	}
    106 
    107 	void SendClientIntroduction(User *u) anope_override
    108 	{
    109 		Anope::string modes = "+" + u->GetModes();
    110 		UplinkSocket::Message(Me) << "UID " << u->nick << " 1 " << u->timestamp << " " << modes << " " << u->GetIdent() << " " << u->host << " 0 " << u->GetUID() << " :" << u->realname;
    111 	}
    112 
    113 	void SendLogin(User *u, NickAlias *na) anope_override
    114 	{
    115 		if (na->nc->HasExt("UNCONFIRMED"))
    116 			return;
    117 
    118 		UplinkSocket::Message(Me) << "ENCAP * SU " << u->GetUID() << " " << na->nc->display;
    119 	}
    120 
    121 	void SendLogout(User *u) anope_override
    122 	{
    123 		UplinkSocket::Message(Me) << "ENCAP * SU " << u->GetUID();
    124 	}
    125 
    126 	void SendTopic(const MessageSource &source, Channel *c) anope_override
    127 	{
    128 		BotInfo *bi = source.GetBot();
    129 		bool needjoin = c->FindUser(bi) == NULL;
    130 
    131 		if (needjoin)
    132 		{
    133 			ChannelStatus status;
    134 
    135 			status.AddMode('o');
    136 			bi->Join(c, &status);
    137 		}
    138 
    139 		IRCDProto::SendTopic(source, c);
    140 
    141 		if (needjoin)
    142 			bi->Part(c);
    143 	}
    144 };
    145 
    146 struct IRCDMessageEncap : IRCDMessage
    147 {
    148 	IRCDMessageEncap(Module *creator) : IRCDMessage(creator, "ENCAP", 3) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
    149 
    150 	// Debug: Received: :00BAAAAAB ENCAP * LOGIN Adam
    151 	void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
    152 	{
    153 		if (params[1] == "LOGIN" || params[1] == "SU")
    154 		{
    155 			User *u = source.GetUser();
    156 
    157 			NickCore *nc = NickCore::Find(params[2]);
    158 			if (!nc)
    159 				return;
    160 			u->Login(nc);
    161 
    162 			/* Sometimes a user connects, we send them the usual "this nickname is registered" mess (if
    163 			 * their server isn't syncing) and then we receive this.. so tell them about it.
    164 			 */
    165 			if (u->server->IsSynced())
    166 				u->SendMessage(Config->GetClient("NickServ"), _("You have been logged in as \002%s\002."), nc->display.c_str());
    167 		}
    168 	}
    169 };
    170 
    171 struct IRCDMessageJoin : Message::Join
    172 {
    173 	IRCDMessageJoin(Module *creator) : Message::Join(creator, "JOIN") { }
    174 
    175 	void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
    176 	{
    177 		if (params.size() == 1 && params[0] == "0")
    178 			return Message::Join::Run(source, params);
    179 
    180 		if (params.size() < 2)
    181 			return;
    182 
    183 		std::vector<Anope::string> p = params;
    184 		p.erase(p.begin());
    185 
    186 		return Message::Join::Run(source, p);
    187 	}
    188 };
    189 
    190 struct IRCDMessagePass : IRCDMessage
    191 {
    192 	IRCDMessagePass(Module *creator) : IRCDMessage(creator, "PASS", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
    193 
    194 	void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
    195 	{
    196 		UplinkSID = params[3];
    197 	}
    198 };
    199 
    200 struct IRCDMessageServer : IRCDMessage
    201 {
    202 	IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
    203 
    204 	// SERVER hades.arpa 1 :ircd-ratbox test server
    205 	void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
    206 	{
    207 		// Servers other then our immediate uplink are introduced via SID
    208 		if (params[1] != "1")
    209 			return;
    210 		new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], 1, params[2], UplinkSID);
    211 		IRCD->SendPing(Me->GetName(), params[0]);
    212 	}
    213 };
    214 
    215 struct IRCDMessageTBurst : IRCDMessage
    216 {
    217 	IRCDMessageTBurst(Module *creator) : IRCDMessage(creator, "TB", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
    218 
    219 	/*
    220 	 * params[0] = channel
    221 	 * params[1] = ts
    222 	 * params[2] = topic OR who set the topic
    223 	 * params[3] = topic if params[2] isn't the topic
    224 	 */
    225 	void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
    226 	{
    227 		time_t topic_time = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime;
    228 		Channel *c = Channel::Find(params[0]);
    229 
    230 		if (!c)
    231 			return;
    232 
    233 		const Anope::string &setter = params.size() == 4 ? params[2] : "",
    234 			topic = params.size() == 4 ? params[3] : params[2];
    235 
    236 		c->ChangeTopicInternal(NULL, setter, topic, topic_time);
    237 	}
    238 };
    239 
    240 struct IRCDMessageUID : IRCDMessage
    241 {
    242 	IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 9) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
    243 
    244 	// :42X UID Adam 1 1348535644 +aow Adam 192.168.0.5 192.168.0.5 42XAAAAAB :Adam
    245 	void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
    246 	{
    247 		/* Source is always the server */
    248 		User::OnIntroduce(params[0], params[4], params[5], "", params[6], source.GetServer(), params[8], params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, params[3], params[7], NULL);
    249 	}
    250 };
    251 
    252 class ProtoRatbox : public Module
    253 {
    254 	Module *m_hybrid;
    255 
    256 	RatboxProto ircd_proto;
    257 
    258 	/* Core message handlers */
    259 	Message::Away message_away;
    260 	Message::Capab message_capab;
    261 	Message::Error message_error;
    262 	Message::Invite message_invite;
    263 	Message::Kick message_kick;
    264 	Message::Kill message_kill;
    265 	Message::Mode message_mode;
    266 	Message::MOTD message_motd;
    267 	Message::Notice message_notice;
    268 	Message::Part message_part;
    269 	Message::Ping message_ping;
    270 	Message::Privmsg message_privmsg;
    271 	Message::Quit message_quit;
    272 	Message::SQuit message_squit;
    273 	Message::Stats message_stats;
    274 	Message::Time message_time;
    275 	Message::Topic message_topic;
    276 	Message::Version message_version;
    277 	Message::Whois message_whois;
    278 
    279 	/* Hybrid message handlers */
    280 	ServiceAlias message_bmask, message_nick, message_pong, message_sid,
    281 			message_sjoin, message_tmode;
    282 
    283 	/* Our message handlers */
    284 	IRCDMessageEncap message_encap;
    285 	IRCDMessageJoin message_join;
    286 	IRCDMessagePass message_pass;
    287 	IRCDMessageServer message_server;
    288 	IRCDMessageTBurst message_tburst;
    289 	IRCDMessageUID message_uid;
    290 
    291 	void AddModes()
    292 	{
    293 		/* user modes */
    294 		ModeManager::AddUserMode(new UserModeOperOnly("ADMIN", 'a'));
    295 		ModeManager::AddUserMode(new UserModeOperOnly("BOT", 'b'));
    296 		// c/C = con
    297 		// d = debug?
    298 		ModeManager::AddUserMode(new UserMode("DEAF", 'D'));
    299 		// f = full?
    300 		ModeManager::AddUserMode(new UserMode("CALLERID", 'g'));
    301 		ModeManager::AddUserMode(new UserMode("INVIS", 'i'));
    302 		// k = skill?
    303 		ModeManager::AddUserMode(new UserModeOperOnly("LOCOPS", 'l'));
    304 		// n = nchange
    305 		ModeManager::AddUserMode(new UserModeOperOnly("OPER", 'o'));
    306 		// r = rej
    307 		ModeManager::AddUserMode(new UserModeOperOnly("SNOMASK", 's'));
    308 		ModeManager::AddUserMode(new UserModeNoone("PROTECTED", 'S'));
    309 		// u = unauth?
    310 		ModeManager::AddUserMode(new UserMode("WALLOPS", 'w'));
    311 		// x = external?
    312 		// y = spy?
    313 		ModeManager::AddUserMode(new UserModeOperOnly("OPERWALLS", 'z'));
    314 		// Z = spy?
    315 
    316 		/* b/e/I */
    317 		ModeManager::AddChannelMode(new ChannelModeList("BAN", 'b'));
    318 		ModeManager::AddChannelMode(new ChannelModeList("EXCEPT", 'e'));
    319 		ModeManager::AddChannelMode(new ChannelModeList("INVITEOVERRIDE", 'I'));
    320 
    321 		/* v/h/o/a/q */
    322 		ModeManager::AddChannelMode(new ChannelModeStatus("VOICE", 'v', '+', 0));
    323 		ModeManager::AddChannelMode(new ChannelModeStatus("OP", 'o', '@', 1));
    324 
    325 		/* l/k */
    326 		ModeManager::AddChannelMode(new ChannelModeParam("LIMIT", 'l', true));
    327 		ModeManager::AddChannelMode(new ChannelModeKey('k'));
    328 
    329 		/* channel modes */
    330 		ModeManager::AddChannelMode(new ChannelMode("INVITE", 'i'));
    331 		ModeManager::AddChannelMode(new ChannelMode("MODERATED", 'm'));
    332 		ModeManager::AddChannelMode(new ChannelMode("NOEXTERNAL", 'n'));
    333 		ModeManager::AddChannelMode(new ChannelMode("PRIVATE", 'p'));
    334 		ModeManager::AddChannelMode(new ChannelMode("REGISTEREDONLY", 'r'));
    335 		ModeManager::AddChannelMode(new ChannelMode("SECRET", 's'));
    336 		ModeManager::AddChannelMode(new ChannelMode("TOPIC", 't'));
    337 		ModeManager::AddChannelMode(new ChannelMode("SSL", 'S'));
    338 	}
    339 
    340  public:
    341 	ProtoRatbox(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR),
    342 		ircd_proto(this),
    343 		message_away(this), message_capab(this), message_error(this), message_invite(this), message_kick(this),
    344 		message_kill(this), message_mode(this), message_motd(this), message_notice(this), message_part(this),
    345 		message_ping(this), message_privmsg(this), message_quit(this), message_squit(this), message_stats(this),
    346 		message_time(this), message_topic(this), message_version(this), message_whois(this),
    347 
    348 		message_bmask("IRCDMessage", "ratbox/bmask", "hybrid/bmask"), message_nick("IRCDMessage", "ratbox/nick", "hybrid/nick"),
    349 		message_pong("IRCDMessage", "ratbox/pong", "hybrid/pong"), message_sid("IRCDMessage", "ratbox/sid", "hybrid/sid"),
    350 		message_sjoin("IRCDMessage", "ratbox/sjoin", "hybrid/sjoin"), message_tmode("IRCDMessage", "ratbox/tmode", "hybrid/tmode"),
    351 
    352 		message_encap(this), message_join(this), message_pass(this), message_server(this), message_tburst(this), message_uid(this)
    353 	{
    354 
    355 		if (ModuleManager::LoadModule("hybrid", User::Find(creator)) != MOD_ERR_OK)
    356 			throw ModuleException("Unable to load hybrid");
    357 		m_hybrid = ModuleManager::FindModule("hybrid");
    358 		if (!m_hybrid)
    359 			throw ModuleException("Unable to find hybrid");
    360 		if (!hybrid)
    361 			throw ModuleException("No protocol interface for hybrid");
    362 
    363 		this->AddModes();
    364 	}
    365 
    366 	~ProtoRatbox()
    367 	{
    368 		m_hybrid = ModuleManager::FindModule("hybrid");
    369 		ModuleManager::UnloadModule(m_hybrid, NULL);
    370 	}
    371 };
    372 
    373 MODULE_INIT(ProtoRatbox)