anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
bahamut.cpp (17509B)
1 /* Bahamut 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 class ChannelModeFlood : public ChannelModeParam 15 { 16 public: 17 ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam("FLOOD", modeChar, minusNoArg) { } 18 19 bool IsValid(Anope::string &value) const anope_override 20 { 21 try 22 { 23 Anope::string rest; 24 if (!value.empty() && value[0] != ':' && convertTo<int>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<int>(rest.substr(1), rest, false) > 0 && rest.empty()) 25 return true; 26 } 27 catch (const ConvertException &) { } 28 29 return false; 30 } 31 }; 32 33 class BahamutIRCdProto : public IRCDProto 34 { 35 public: 36 BahamutIRCdProto(Module *creator) : IRCDProto(creator, "Bahamut 1.8.x") 37 { 38 DefaultPseudoclientModes = "+"; 39 CanSVSNick = true; 40 CanSNLine = true; 41 CanSQLine = true; 42 CanSQLineChannel = true; 43 CanSZLine = true; 44 CanSVSHold = true; 45 MaxModes = 60; 46 } 47 48 void SendModeInternal(const MessageSource &source, const Channel *dest, const Anope::string &buf) anope_override 49 { 50 if (Servers::Capab.count("TSMODE") > 0) 51 { 52 UplinkSocket::Message(source) << "MODE " << dest->name << " " << dest->creation_time << " " << buf; 53 } 54 else 55 IRCDProto::SendModeInternal(source, dest, buf); 56 } 57 58 void SendModeInternal(const MessageSource &source, User *u, const Anope::string &buf) anope_override 59 { 60 UplinkSocket::Message(source) << "SVSMODE " << u->nick << " " << u->timestamp << " " << buf; 61 } 62 63 void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override 64 { 65 UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg; 66 } 67 68 void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override 69 { 70 UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg; 71 } 72 73 /* SVSHOLD - set */ 74 void SendSVSHold(const Anope::string &nick, time_t time) anope_override 75 { 76 UplinkSocket::Message(Me) << "SVSHOLD " << nick << " " << time << " :Being held for registered user"; 77 } 78 79 /* SVSHOLD - release */ 80 void SendSVSHoldDel(const Anope::string &nick) anope_override 81 { 82 UplinkSocket::Message(Me) << "SVSHOLD " << nick << " 0"; 83 } 84 85 /* SQLINE */ 86 void SendSQLine(User *, const XLine *x) anope_override 87 { 88 UplinkSocket::Message() << "SQLINE " << x->mask << " :" << x->GetReason(); 89 } 90 91 /* UNSLINE */ 92 void SendSGLineDel(const XLine *x) anope_override 93 { 94 UplinkSocket::Message() << "UNSGLINE 0 :" << x->mask; 95 } 96 97 /* UNSZLINE */ 98 void SendSZLineDel(const XLine *x) anope_override 99 { 100 /* this will likely fail so its only here for legacy */ 101 UplinkSocket::Message() << "UNSZLINE 0 " << x->GetHost(); 102 /* this is how we are supposed to deal with it */ 103 UplinkSocket::Message() << "RAKILL " << x->GetHost() << " *"; 104 } 105 106 /* SZLINE */ 107 void SendSZLine(User *, const XLine *x) anope_override 108 { 109 // Calculate the time left before this would expire, capping it at 2 days 110 time_t timeleft = x->expires - Anope::CurTime; 111 if (timeleft > 172800 || !x->expires) 112 timeleft = 172800; 113 /* this will likely fail so its only here for legacy */ 114 UplinkSocket::Message() << "SZLINE " << x->GetHost() << " :" << x->GetReason(); 115 /* this is how we are supposed to deal with it */ 116 UplinkSocket::Message() << "AKILL " << x->GetHost() << " * " << timeleft << " " << x->by << " " << Anope::CurTime << " :" << x->GetReason(); 117 } 118 119 /* SVSNOOP */ 120 void SendSVSNOOP(const Server *server, bool set) anope_override 121 { 122 UplinkSocket::Message() << "SVSNOOP " << server->GetName() << " " << (set ? "+" : "-"); 123 } 124 125 /* SGLINE */ 126 void SendSGLine(User *, const XLine *x) anope_override 127 { 128 UplinkSocket::Message() << "SGLINE " << x->mask.length() << " :" << x->mask << ":" << x->GetReason(); 129 } 130 131 /* RAKILL */ 132 void SendAkillDel(const XLine *x) anope_override 133 { 134 if (x->IsRegex() || x->HasNickOrReal()) 135 return; 136 137 /* ZLine if we can instead */ 138 if (x->GetUser() == "*") 139 { 140 cidr a(x->GetHost()); 141 if (a.valid()) 142 { 143 IRCD->SendSZLineDel(x); 144 return; 145 } 146 } 147 148 UplinkSocket::Message() << "RAKILL " << x->GetHost() << " " << x->GetUser(); 149 } 150 151 /* TOPIC */ 152 void SendTopic(const MessageSource &source, Channel *c) anope_override 153 { 154 UplinkSocket::Message(source) << "TOPIC " << c->name << " " << c->topic_setter << " " << c->topic_ts << " :" << c->topic; 155 } 156 157 /* UNSQLINE */ 158 void SendSQLineDel(const XLine *x) anope_override 159 { 160 UplinkSocket::Message() << "UNSQLINE " << x->mask; 161 } 162 163 /* JOIN - SJOIN */ 164 void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override 165 { 166 UplinkSocket::Message(user) << "SJOIN " << c->creation_time << " " << c->name; 167 if (status) 168 { 169 /* First save the channel status incase uc->Status == status */ 170 ChannelStatus cs = *status; 171 /* If the user is internally on the channel with flags, kill them so that 172 * the stacker will allow this. 173 */ 174 ChanUserContainer *uc = c->FindUser(user); 175 if (uc != NULL) 176 uc->status.Clear(); 177 178 BotInfo *setter = BotInfo::Find(user->GetUID()); 179 for (size_t i = 0; i < cs.Modes().length(); ++i) 180 c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false); 181 182 if (uc != NULL) 183 uc->status = cs; 184 } 185 } 186 187 void SendAkill(User *u, XLine *x) anope_override 188 { 189 if (x->IsRegex() || x->HasNickOrReal()) 190 { 191 if (!u) 192 { 193 /* No user (this akill was just added), and contains nick and/or realname. Find users that match and ban them */ 194 for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) 195 if (x->manager->Check(it->second, x)) 196 this->SendAkill(it->second, x); 197 return; 198 } 199 200 const XLine *old = x; 201 202 if (old->manager->HasEntry("*@" + u->host)) 203 return; 204 205 /* We can't akill x as it has a nick and/or realname included, so create a new akill for *@host */ 206 x = new XLine("*@" + u->host, old->by, old->expires, old->reason, old->id); 207 old->manager->AddXLine(x); 208 209 Log(Config->GetClient("OperServ"), "akill") << "AKILL: Added an akill for " << x->mask << " because " << u->GetMask() << "#" << u->realname << " matches " << old->mask; 210 } 211 212 /* ZLine if we can instead */ 213 if (x->GetUser() == "*") 214 { 215 cidr a(x->GetHost()); 216 if (a.valid()) 217 { 218 IRCD->SendSZLine(u, x); 219 return; 220 } 221 } 222 223 // Calculate the time left before this would expire, capping it at 2 days 224 time_t timeleft = x->expires - Anope::CurTime; 225 if (timeleft > 172800) 226 timeleft = 172800; 227 UplinkSocket::Message() << "AKILL " << x->GetHost() << " " << x->GetUser() << " " << timeleft << " " << x->by << " " << Anope::CurTime << " :" << x->GetReason(); 228 } 229 230 /* 231 Note: if the stamp is null 0, the below usage is correct of Bahamut 232 */ 233 void SendSVSKillInternal(const MessageSource &source, User *user, const Anope::string &buf) anope_override 234 { 235 UplinkSocket::Message(source) << "SVSKILL " << user->nick << " :" << buf; 236 } 237 238 void SendBOB() anope_override 239 { 240 UplinkSocket::Message() << "BURST"; 241 } 242 243 void SendEOB() anope_override 244 { 245 UplinkSocket::Message() << "BURST 0"; 246 } 247 248 void SendClientIntroduction(User *u) anope_override 249 { 250 Anope::string modes = "+" + u->GetModes(); 251 UplinkSocket::Message() << "NICK " << u->nick << " 1 " << u->timestamp << " " << modes << " " << u->GetIdent() << " " << u->host << " " << u->server->GetName() << " 0 0 :" << u->realname; 252 } 253 254 /* SERVER */ 255 void SendServer(const Server *server) anope_override 256 { 257 UplinkSocket::Message() << "SERVER " << server->GetName() << " " << server->GetHops() << " :" << server->GetDescription(); 258 } 259 260 void SendConnect() anope_override 261 { 262 UplinkSocket::Message() << "PASS " << Config->Uplinks[Anope::CurrentUplink].password << " :TS"; 263 UplinkSocket::Message() << "CAPAB SSJOIN NOQUIT BURST UNCONNECT NICKIP TSMODE TS3"; 264 SendServer(Me); 265 /* 266 * SVINFO 267 * parv[0] = sender prefix 268 * parv[1] = TS_CURRENT for the server 269 * parv[2] = TS_MIN for the server 270 * parv[3] = server is standalone or connected to non-TS only 271 * parv[4] = server's idea of UTC time 272 */ 273 UplinkSocket::Message() << "SVINFO 3 1 0 :" << Anope::CurTime; 274 this->SendBOB(); 275 } 276 277 void SendChannel(Channel *c) anope_override 278 { 279 Anope::string modes = c->GetModes(true, true); 280 if (modes.empty()) 281 modes = "+"; 282 UplinkSocket::Message() << "SJOIN " << c->creation_time << " " << c->name << " " << modes << " :"; 283 } 284 285 void SendLogin(User *u, NickAlias *) anope_override 286 { 287 IRCD->SendMode(Config->GetClient("NickServ"), u, "+d %d", u->signon); 288 } 289 290 void SendLogout(User *u) anope_override 291 { 292 IRCD->SendMode(Config->GetClient("NickServ"), u, "+d 1"); 293 } 294 }; 295 296 struct IRCDMessageBurst : IRCDMessage 297 { 298 IRCDMessageBurst(Module *creator) : IRCDMessage(creator, "BURST", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 299 300 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 301 { 302 /* If we found a server with the given source, that one just 303 * finished bursting. If there was no source, then our uplink 304 * server finished bursting. -GD 305 */ 306 Server *s = source.GetServer(); 307 if (!s) 308 s = Me->GetLinks().front(); 309 if (s) 310 s->Sync(true); 311 } 312 }; 313 314 struct IRCDMessageMode : IRCDMessage 315 { 316 IRCDMessageMode(Module *creator, const Anope::string &sname) : IRCDMessage(creator, sname, 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 317 318 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 319 { 320 if (params.size() > 2 && IRCD->IsChannelValid(params[0])) 321 { 322 Channel *c = Channel::Find(params[0]); 323 time_t ts = 0; 324 325 try 326 { 327 ts = convertTo<time_t>(params[1]); 328 } 329 catch (const ConvertException &) { } 330 331 Anope::string modes = params[2]; 332 for (unsigned int i = 3; i < params.size(); ++i) 333 modes += " " + params[i]; 334 335 if (c) 336 c->SetModesInternal(source, modes, ts); 337 } 338 else 339 { 340 User *u = User::Find(params[0]); 341 if (u) 342 u->SetModesInternal(source, "%s", params[1].c_str()); 343 } 344 } 345 }; 346 347 /* 348 ** NICK - new 349 ** source = NULL 350 ** parv[0] = nickname 351 ** parv[1] = hopcount 352 ** parv[2] = timestamp 353 ** parv[3] = modes 354 ** parv[4] = username 355 ** parv[5] = hostname 356 ** parv[6] = server 357 ** parv[7] = servicestamp 358 ** parv[8] = IP 359 ** parv[9] = info 360 ** NICK - change 361 ** source = oldnick 362 ** parv[0] = new nickname 363 ** parv[1] = hopcount 364 */ 365 struct IRCDMessageNick : IRCDMessage 366 { 367 IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 368 369 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 370 { 371 if (params.size() == 10) 372 { 373 Server *s = Server::Find(params[6]); 374 if (s == NULL) 375 { 376 Log(LOG_DEBUG) << "User " << params[0] << " introduced from nonexistent server " << params[6] << "?"; 377 return; 378 } 379 380 NickAlias *na = NULL; 381 time_t signon = params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, 382 stamp = params[7].is_pos_number_only() ? convertTo<time_t>(params[7]) : 0; 383 if (signon && signon == stamp) 384 na = NickAlias::Find(params[0]); 385 386 User::OnIntroduce(params[0], params[4], params[5], "", params[8], s, params[9], signon, params[3], "", na ? *na->nc : NULL); 387 } 388 else 389 { 390 User *u = source.GetUser(); 391 392 if (u) 393 u->ChangeNick(params[0]); 394 } 395 } 396 }; 397 398 struct IRCDMessageServer : IRCDMessage 399 { 400 IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } 401 402 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 403 { 404 unsigned int hops = Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0; 405 new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[2]); 406 } 407 }; 408 409 struct IRCDMessageSJoin : IRCDMessage 410 { 411 IRCDMessageSJoin(Module *creator) : IRCDMessage(creator, "SJOIN", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 412 413 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 414 { 415 Anope::string modes; 416 if (params.size() >= 4) 417 for (unsigned i = 2; i < params.size(); ++i) 418 modes += " " + params[i]; 419 if (!modes.empty()) 420 modes.erase(modes.begin()); 421 422 std::list<Message::Join::SJoinUser> users; 423 424 /* For some reason, bahamut will send a SJOIN from the user joining a channel 425 * if the channel already existed 426 */ 427 if (source.GetUser()) 428 { 429 Message::Join::SJoinUser sju; 430 sju.second = source.GetUser(); 431 users.push_back(sju); 432 } 433 else 434 { 435 spacesepstream sep(params[params.size() - 1]); 436 Anope::string buf; 437 438 while (sep.GetToken(buf)) 439 { 440 Message::Join::SJoinUser sju; 441 442 /* Get prefixes from the nick */ 443 for (char ch; (ch = ModeManager::GetStatusChar(buf[0]));) 444 { 445 buf.erase(buf.begin()); 446 sju.first.AddMode(ch); 447 } 448 449 sju.second = User::Find(buf); 450 if (!sju.second) 451 { 452 Log(LOG_DEBUG) << "SJOIN for nonexistent user " << buf << " on " << params[1]; 453 continue; 454 } 455 456 users.push_back(sju); 457 } 458 } 459 460 time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : Anope::CurTime; 461 Message::Join::SJoin(source, params[1], ts, modes, users); 462 } 463 }; 464 465 struct IRCDMessageTopic : IRCDMessage 466 { 467 IRCDMessageTopic(Module *creator) : IRCDMessage(creator, "TOPIC", 4) { } 468 469 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 470 { 471 Channel *c = Channel::Find(params[0]); 472 if (c) 473 c->ChangeTopicInternal(source.GetUser(), params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); 474 } 475 }; 476 477 class ProtoBahamut : public Module 478 { 479 BahamutIRCdProto ircd_proto; 480 481 /* Core message handlers */ 482 Message::Away message_away; 483 Message::Capab message_capab; 484 Message::Error message_error; 485 Message::Invite message_invite; 486 Message::Join message_join; 487 Message::Kick message_kick; 488 Message::Kill message_kill; 489 Message::MOTD message_motd; 490 Message::Notice message_notice; 491 Message::Part message_part; 492 Message::Ping message_ping; 493 Message::Privmsg message_privmsg; 494 Message::Quit message_quit; 495 Message::SQuit message_squit; 496 Message::Stats message_stats; 497 Message::Time message_time; 498 Message::Version message_version; 499 Message::Whois message_whois; 500 501 /* Our message handlers */ 502 IRCDMessageBurst message_burst; 503 IRCDMessageMode message_mode, message_svsmode; 504 IRCDMessageNick message_nick; 505 IRCDMessageServer message_server; 506 IRCDMessageSJoin message_sjoin; 507 IRCDMessageTopic message_topic; 508 509 void AddModes() 510 { 511 /* Add user modes */ 512 ModeManager::AddUserMode(new UserModeOperOnly("SERV_ADMIN", 'A')); 513 ModeManager::AddUserMode(new UserMode("REGPRIV", 'R')); 514 ModeManager::AddUserMode(new UserModeOperOnly("ADMIN", 'a')); 515 ModeManager::AddUserMode(new UserMode("INVIS", 'i')); 516 ModeManager::AddUserMode(new UserModeOperOnly("OPER", 'o')); 517 ModeManager::AddUserMode(new UserModeNoone("REGISTERED", 'r')); 518 ModeManager::AddUserMode(new UserModeOperOnly("SNOMASK", 's')); 519 ModeManager::AddUserMode(new UserModeOperOnly("WALLOPS", 'w')); 520 ModeManager::AddUserMode(new UserMode("DEAF", 'd')); 521 522 /* b/e/I */ 523 ModeManager::AddChannelMode(new ChannelModeList("BAN", 'b')); 524 525 /* v/h/o/a/q */ 526 ModeManager::AddChannelMode(new ChannelModeStatus("VOICE", 'v', '+', 0)); 527 ModeManager::AddChannelMode(new ChannelModeStatus("HALFOP", 'h', '%', 1)); 528 ModeManager::AddChannelMode(new ChannelModeStatus("OP", 'o', '@', 1)); 529 530 /* Add channel modes */ 531 ModeManager::AddChannelMode(new ChannelMode("BLOCKCOLOR", 'c')); 532 ModeManager::AddChannelMode(new ChannelMode("INVITE", 'i')); 533 ModeManager::AddChannelMode(new ChannelModeFlood('f', false)); 534 ModeManager::AddChannelMode(new ChannelModeKey('k')); 535 ModeManager::AddChannelMode(new ChannelModeParam("LIMIT", 'l', true)); 536 ModeManager::AddChannelMode(new ChannelMode("MODERATED", 'm')); 537 ModeManager::AddChannelMode(new ChannelMode("NOEXTERNAL", 'n')); 538 ModeManager::AddChannelMode(new ChannelMode("PRIVATE", 'p')); 539 ModeManager::AddChannelMode(new ChannelModeNoone("REGISTERED", 'r')); 540 ModeManager::AddChannelMode(new ChannelMode("SECRET", 's')); 541 ModeManager::AddChannelMode(new ChannelMode("TOPIC", 't')); 542 ModeManager::AddChannelMode(new ChannelMode("REGMODERATED", 'M')); 543 ModeManager::AddChannelMode(new ChannelModeOperOnly("OPERONLY", 'O')); 544 ModeManager::AddChannelMode(new ChannelMode("REGISTEREDONLY", 'R')); 545 } 546 547 public: 548 ProtoBahamut(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR), 549 ircd_proto(this), 550 message_away(this), message_capab(this), message_error(this), message_invite(this), 551 message_join(this), message_kick(this), message_kill(this), message_motd(this), message_notice(this), 552 message_part(this), message_ping(this), message_privmsg(this), message_quit(this), 553 message_squit(this), message_stats(this), message_time(this), message_version(this), message_whois(this), 554 555 message_burst(this), message_mode(this, "MODE"), message_svsmode(this, "SVSMODE"), 556 message_nick(this), message_server(this), message_sjoin(this), message_topic(this) 557 { 558 559 this->AddModes(); 560 561 } 562 563 void OnUserNickChange(User *u, const Anope::string &) anope_override 564 { 565 u->RemoveModeInternal(Me, ModeManager::FindUserModeByName("REGISTERED")); 566 IRCD->SendLogout(u); 567 } 568 }; 569 570 MODULE_INIT(ProtoBahamut)