/* add a tandem bot to our chain list */ void addbot(char *who, char *from, char *next, char flag, int vernum) { tand_t **ptr = &tandbot, *ptr2; Context; while (*ptr) { if (!strcasecmp((*ptr)->bot, who)) putlog(LOG_BOTS, "*", "!!! Duplicate botnet bot entry!!"); ptr = &((*ptr)->next); } ptr2 = nmalloc(sizeof(tand_t)); strncpy(ptr2->bot, who, HANDLEN); ptr2->bot[HANDLEN] = 0; ptr2->share = flag; ptr2->ver = vernum; ptr2->next = *ptr; *ptr = ptr2; /* may be via itself */ ptr2->via = findbot(from); if (!strcasecmp(next, botnetnick)) ptr2->uplink = (tand_t *) 1; else ptr2->uplink = findbot(next); tands++; }
static void bot_unlinked(int idx, char *par) { int i; char *bot = NULL; bot = newsplit(&par); i = nextbot(bot); if ((i >= 0) && (i != idx)) /* Bot is NOT downstream along idx, so * BOGUS! */ fake_alert(idx, "direction", bot, "unlinked"); else if (i >= 0) { /* Valid bot downstream of idx */ if (par[0]) /* #ifdef HUB */ chatout("*** (%s) %s\n", lastbot(bot), par); /* #else chatout("*** %s unlinked from botnet.\n", par); #endif */ botnet_send_unlinked(idx, bot, par); unvia(idx, findbot(bot)); rembot(bot); } /* Otherwise it's not even a valid bot, so just ignore! */ }
static void bot_linked(int idx, char *par) { char s[1024]; int bots, users; bots = bots_in_subtree(findbot(dcc[idx].nick)); users = users_in_subtree(findbot(dcc[idx].nick)); putlog(LOG_BOTS, "*", "%s", BOT_OLDBOT); simple_sprintf(s, "%s %s (%s) (lost %d bot%s and %d user%s", MISC_DISCONNECTED, dcc[idx].nick, MISC_OUTDATED, bots, (bots != 1) ? "s" : "", users, (users != 1) ? "s" : ""); chatout("*** %s\n", s); botnet_send_unlinked(idx, dcc[idx].nick, s); killsock(dcc[idx].sock); lostdcc(idx); }
/* ** 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<Anope::string> ¶ms) { if (params.size() != 2) { /* Currently bahamut has no ipv6 support */ sockaddrs ip; ip.ntop(AF_INET, params[8].c_str()); User *user = do_nick(source, params[0], params[4], params[5], params[6], params[9], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, ip.addr(), "", "", params[3]); if (user && nickserv) { NickAlias *na; if (user->timestamp == convertTo<time_t>(params[7]) && (na = findnick(user->nick))) { user->Login(na->nc); if (!Config->NoNicknameOwnership && na->nc->HasFlag(NI_UNCONFIRMED) == false) user->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); } else nickserv->Validate(user); } } else do_nick(source, params[0], "", "", "", "", Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0, "", "", "", ""); return true; }
int in_chain(char *who) { if (findbot(who)) return 1; if (!strcasecmp(who, botnetnick)) return 1; return 0; }
static void bot_bye(int idx, char *par) { char s[1024]; int users, bots; bots = bots_in_subtree(findbot(dcc[idx].nick)); users = users_in_subtree(findbot(dcc[idx].nick)); simple_sprintf(s, "%s %s. %s (lost %d bot%s and %d user%s)", BOT_DISCONNECTED, dcc[idx].nick, par[0] ? par : "No reason", bots, (bots != 1) ? "s" : "", users, (users != 1) ? "s" : ""); putlog(LOG_BOTS, "*", "%s", s); chatout("*** %s\n", s); botnet_send_unlinked(idx, dcc[idx].nick, s); dprintf(idx, "*bye\n"); killsock(dcc[idx].sock); lostdcc(idx); }
static void bot_bye(int idx, char *par) { char s[1024] = ""; int users, bots; bots = bots_in_subtree(findbot(dcc[idx].nick)); users = users_in_subtree(findbot(dcc[idx].nick)); simple_snprintf(s, sizeof(s), "%s %s. %s (lost %d bot%s and %d user%s)", "Disconnected from:", (conf.bot->hub || (conf.bot->localhub && bot_aggressive_to(dcc[idx].user))) ? dcc[idx].nick : "botnet", par[0] ? par : "No reason", bots, (bots != 1) ? "s" : "", users, (users != 1) ? "s" : ""); putlog(LOG_BOTS, "*", "%s", s); chatout("*** %s\n", s); botnet_send_unlinked(idx, dcc[idx].nick, s); dprintf(idx, "*bye\n"); killsock(dcc[idx].sock); lostdcc(idx); }
/** * add a bot to a channel */ void add_bot_to_chan(char *botname, char *chan) { bot *b = findbot(botname); botchan *bc = scalloc(sizeof(botchan),1); bc->next = b->chanlist; if (b->chanlist) { b->chanlist->prev = bc; } b->chanlist = bc; bc->chan = sstrdup(chan); }
/** * remove a bot from a channel */ void remove_bot_from_chan(char *botname, char *chan) { bot *b = findbot(botname); botchan *bc = b->chanlist; while (bc) { if (stricmp(bc->chan,chan)==0) { chan_del_bot(b,bc); } bc = bc->next; } }
ChanServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), expires(this) { this->SetAuthor("Anope"); BotInfo *ChanServ = findbot(Config->ChanServ); if (ChanServ == NULL) throw ModuleException("No bot named " + Config->ChanServ); Implementation i[] = { I_OnBotPrivmsg, I_OnDelCore, I_OnPreHelp, I_OnPostHelp }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); }
/* once a minute, send 'ping' to each bot -- no exceptions */ void check_botnet_pings() { int i; Context; for (i = 0; i < dcc_total; i++) if (dcc[i].type == &DCC_BOT) if (dcc[i].status & STAT_PINGED) { char s[1024]; putlog(LOG_BOTS, "*", "%s: %s", BOT_PINGTIMEOUT, dcc[i].nick); simple_sprintf(s, "%s: %s", BOT_PINGTIMEOUT, dcc[i].nick); chatout("*** %s\n", s); botnet_send_unlinked(i, dcc[i].nick, s); killsock(dcc[i].sock); lostdcc(i); } Context; for (i = 0; i < dcc_total; i++) if (dcc[i].type == &DCC_BOT) { botnet_send_ping(i); dcc[i].status |= STAT_PINGED; } Context; for (i = 0; i < dcc_total; i++) if ((dcc[i].type == &DCC_BOT) && (dcc[i].status & STAT_LEAF)) { tand_t *bot, *via = findbot(dcc[i].nick); for (bot = tandbot; bot; bot = bot->next) { if ((via == bot->via) && (bot != via)) { /* not leaflike behavior */ if (dcc[i].status & STAT_WARNED) { char s[1024]; putlog(LOG_BOTS, "*", "%s %s (%s).", BOT_DISCONNECTED, dcc[i].nick, BOT_BOTNOTLEAFLIKE); dprintf(i, "bye\n"); simple_sprintf(s, "%s %s (%s)", BOT_DISCONNECTED, dcc[i].nick, BOT_BOTNOTLEAFLIKE); chatout("*** %s\n", s); botnet_send_unlinked(i, dcc[i].nick, s); killsock(dcc[i].sock); lostdcc(i); } else { botnet_send_reject(i, botnetnick, NULL, bot->bot, NULL, NULL); dcc[i].status |= STAT_WARNED; } } else dcc[i].status &= ~STAT_WARNED; } } Context; }
/** * find a bot on a channel */ bot *findbot_onchan(char *botname,char *chan) { bot *b = findbot(botname); botchan *bc = b->chanlist; while (bc) { if (stricmp(bc->chan,chan)==0) { return b; } bc = bc->next; } return NULL; }
/* return name of the bot that is directly connected to bot X */ char *lastbot(char *who) { tand_t *bot = findbot(who); if (!bot) return "*"; else if (bot->uplink == (tand_t *) 1) return botnetnick; else return bot->uplink->bot; }
MemoServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), mymemoserv(this) { this->SetAuthor("Anope"); MemoServ = findbot(Config->MemoServ); if (MemoServ == NULL) throw ModuleException("No bot named " + Config->MemoServ); Implementation i[] = { I_OnNickIdentify, I_OnJoinChannel, I_OnUserAway, I_OnNickUpdate, I_OnPreHelp, I_OnPostHelp }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); }
EventReturn OnChannelModeSet(Channel *c, ChannelModeName Name, const Anope::string ¶m) { if (Name == CMODE_OP && c && c->ci && c->name.equals_ci(this->HelpChan)) { User *u = finduser(param); if (u && c->ci->AccessFor(u).HasPriv("OPDEOPME")) u->SetMode(findbot(Config->OperServ), UMODE_HELPOP); } return EVENT_CONTINUE; }
void updatebot(int idx, char *who, char share, int vernum) { tand_t *ptr = findbot(who); Context; if (ptr) { if (share) ptr->share = share; if (vernum) ptr->ver = vernum; botnet_send_update(idx, ptr); } }
/** * remove a bot from the botlist */ void delete_bot(char *botname) { bot *b = findbot(botname); if (b->prev) { b->prev->next = b->next; } else { botlist = b->next; } if (b->next) { b->next->prev = b->prev; } free(b); }
/* return index into dcc list of the bot that connects us to bot <x> */ int nextbot(char *who) { int j; tand_t *bot = findbot(who); if (!bot) return -1; for (j = 0; j < dcc_total; j++) if (bot->via && !strcasecmp(bot->via->bot, dcc[j].nick) && (dcc[j].type == &DCC_BOT)) return j; return -1; /* we're not connected to 'via' */ }
void Tick(time_t) { if (!session_service) return; for (unsigned i = session_service->GetExceptions().size(); i > 0; --i) { Exception *e = session_service->GetExceptions()[i - 1]; if (!e->expires || e->expires > Anope::CurTime) continue; BotInfo *bi = findbot(Config->OperServ); if (Config->WallExceptionExpire && bi) ircdproto->SendGlobops(bi, "Session exception for %s has expired.", e->mask.c_str()); session_service->DelException(e); delete e; } }
/* JOIN - SJOIN */ void SendJoin(User *user, Channel *c, const ChannelStatus *status) { UplinkSocket::Message(user->nick) << "SJOIN " << c->creation_time << " " << c->name; if (status) { /* First save the channel status incase uc->Status == status */ ChannelStatus cs = *status; /* If the user is internally on the channel with flags, kill them so that * the stacker will allow this. */ UserContainer *uc = c->FindUser(user); if (uc != NULL) uc->Status->ClearFlags(); BotInfo *setter = findbot(user->nick); for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) if (cs.HasFlag(ModeManager::ChannelModes[i]->Name)) c->SetMode(setter, ModeManager::ChannelModes[i], user->nick, false); } }
void DoCommand(XMLRPCServiceInterface *iface, XMLRPCClientSocket *source, XMLRPCRequest *request) { Anope::string service = request->data.size() > 0 ? request->data[0] : ""; Anope::string user = request->data.size() > 1 ? request->data[1] : ""; Anope::string command = request->data.size() > 2 ? request->data[2] : ""; if (service.empty() || user.empty() || command.empty()) request->reply("error", "Invalid parameters"); else { BotInfo *bi = findbot(service); if (!bi) request->reply("error", "Invalid service"); else { request->reply("result", "Success"); dynamic_reference<User> u = finduser(user); bool created = false; if (!u) { u = new XMLRPCUser(user); created = true; request->reply("online", "no"); } else request->reply("online", "yes"); bi->OnMessage(u, command); if (created && u) { User *useru = u; XMLRPCUser *myu = debug_cast<XMLRPCUser *>(useru); if (!myu->GetOut().empty()) request->reply("return", iface->Sanitize(myu->GetOut())); delete u; } } } }
/** * Is the given nick a network service * @param nick to check * @param int Check if botserv bots * @return int */ bool nickIsServices(const Anope::string &tempnick, bool bot) { if (tempnick.empty()) return false; Anope::string nick = tempnick; size_t at = nick.find('@'); if (at != Anope::string::npos) { Anope::string servername = nick.substr(at + 1); if (!servername.equals_ci(Config->ServerName)) return false; nick = nick.substr(0, at); } BotInfo *bi = findbot(nick); if (bi) return bot ? true : bi->HasFlag(BI_CORE); return false; }
bool IRCdMessage::OnWhois(const Anope::string &source, const std::vector<Anope::string> ¶ms) { if (!source.empty() && !params.empty()) { User *u = finduser(params[0]); if (u && u->server == Me) { BotInfo *bi = findbot(u->nick); ircdproto->SendNumeric(Config->ServerName, 311, source, "%s %s %s * :%s", u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str(), u->realname.c_str()); if (bi) ircdproto->SendNumeric(Config->ServerName, 307, source, "%s :is a registered nick", bi->nick.c_str()); ircdproto->SendNumeric(Config->ServerName, 312, source, "%s %s :%s", u->nick.c_str(), Config->ServerName.c_str(), Config->ServerDesc.c_str()); if (bi) ircdproto->SendNumeric(Config->ServerName, 317, source, "%s %ld %ld :seconds idle, signon time", bi->nick.c_str(), static_cast<long>(Anope::CurTime - bi->lastmsg), static_cast<long>(start_time)); ircdproto->SendNumeric(Config->ServerName, 318, source, "%s :End of /WHOIS list.", params[0].c_str()); } else ircdproto->SendNumeric(Config->ServerName, 401, source, "%s :No such user.", params[0].c_str()); } return true; }
static void bot_thisbot(int idx, char *par) { if (strcasecmp(par, dcc[idx].nick)) { char s[1024] = ""; putlog(LOG_BOTS, "*", "Wrong bot--wanted %s, got %s", dcc[idx].nick, par); dprintf(idx, "bye imposter\n"); simple_snprintf(s, sizeof(s), "Disconnected %s (imposter)", dcc[idx].nick); chatout("*** %s\n", s); botnet_send_unlinked(idx, dcc[idx].nick, s); unvia(idx, findbot(dcc[idx].nick)); killsock(dcc[idx].sock); lostdcc(idx); return; } /* Set capitalization the way they want it */ noshare = 1; change_handle(dcc[idx].user, par); noshare = 0; strlcpy(dcc[idx].nick, par, sizeof(dcc[idx].nick)); }
/** * The /bs assign command. * @param u The user who issued the command * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. **/ int do_assign(User * u) { char *chan = strtok(NULL, " "); char *nick = strtok(NULL, " "); BotInfo *bi; ChannelInfo *ci; if (readonly) notice_lang(s_BotServ, u, BOT_ASSIGN_READONLY); else if (!chan || !nick) syntax_error(s_BotServ, u, "ASSIGN", BOT_ASSIGN_SYNTAX); else if (!(bi = findbot(nick))) notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, nick); else if (bi->flags & BI_PRIVATE && !is_oper(u)) notice_lang(s_BotServ, u, PERMISSION_DENIED); else if (!(ci = cs_findchan(chan))) notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); else if (ci->flags & CI_VERBOTEN) notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); else if ((ci->bi) && (stricmp(ci->bi->nick, nick) == 0)) notice_lang(s_BotServ, u, BOT_ASSIGN_ALREADY, ci->bi->nick, chan); else if ((ci->botflags & BS_NOBOT) || (!check_access(u, ci, CA_ASSIGN) && !is_services_admin(u))) notice_lang(s_BotServ, u, PERMISSION_DENIED); else { if (ci->bi) unassign(u, ci); ci->bi = bi; bi->chancount++; if (ci->c && ci->c->usercount >= BSMinUsers) { bot_join(ci); } notice_lang(s_BotServ, u, BOT_ASSIGN_ASSIGNED, bi->nick, ci->name); send_event(EVENT_BOT_ASSIGN, 2, ci->name, bi->nick); } return MOD_CONT; }
static void bot_thisbot(int idx, char *par) { if (egg_strcasecmp(par, dcc[idx].nick)) { char s[1024]; putlog(LOG_BOTS, "*", NET_WRONGBOT, dcc[idx].nick, par); dprintf(idx, "bye %s\n", MISC_IMPOSTER); simple_sprintf(s, "%s %s (%s)", MISC_DISCONNECTED, dcc[idx].nick, MISC_IMPOSTER); chatout("*** %s\n", s); botnet_send_unlinked(idx, dcc[idx].nick, s); unvia(idx, findbot(dcc[idx].nick)); killsock(dcc[idx].sock); lostdcc(idx); return; } if (bot_flags(dcc[idx].user) & BOT_LEAF) dcc[idx].status |= BSTAT_LEAF; /* Set capitalization the way they want it */ noshare = 1; change_handle(dcc[idx].user, par); noshare = 0; strcpy(dcc[idx].nick, par); }
void SendLogout(User *u) { BotInfo *ns = findbot(Config->NickServ); ircdproto->SendMode(ns, u, "+d 1"); }
void SendLogin(User *u) { BotInfo *ns = findbot(Config->NickServ); ircdproto->SendMode(ns, u, "+d %d", u->timestamp); }
bool IRCdMessage::OnPrivmsg(const Anope::string &source, const std::vector<Anope::string> ¶ms) { const Anope::string &receiver = params.size() > 0 ? params[0] : ""; Anope::string message = params.size() > 1 ? params[1] : ""; /* Messages from servers can happen on some IRCds, check for . */ if (source.empty() || receiver.empty() || message.empty() || source.find('.') != Anope::string::npos) return true; User *u = finduser(source); if (!u) { Log() << message << ": user record for " << source << " not found"; BotInfo *bi = findbot(receiver); if (bi) ircdproto->SendMessage(bi, source, "%s", "Internal error - unable to process request."); return true; } if (receiver[0] == '#') { Channel *c = findchan(receiver); if (c) { FOREACH_MOD(I_OnPrivmsg, OnPrivmsg(u, c, message)); } } else { /* If a server is specified (nick@server format), make sure it matches * us, and strip it off. */ Anope::string botname = receiver; size_t s = receiver.find('@'); if (s != Anope::string::npos) { Anope::string servername(receiver.begin() + s + 1, receiver.end()); botname = botname.substr(0, s); if (!servername.equals_ci(Config->ServerName)) return true; } else if (Config->UseStrictPrivMsg) { BotInfo *bi = findbot(receiver); if (!bi) return true; Log(LOG_DEBUG) << "Ignored PRIVMSG without @ from " << source; u->SendMessage(bi, _("\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."), receiver.c_str(), receiver.c_str(), Config->ServerName.c_str(), receiver.c_str()); return true; } BotInfo *bi = findbot(botname); if (bi) { EventReturn MOD_RESULT; FOREACH_RESULT(I_OnBotPrivmsg, OnBotPrivmsg(u, bi, message)); if (MOD_RESULT == EVENT_STOP) return true; if (message[0] == '\1' && message[message.length() - 1] == '\1') { if (message.substr(0, 6).equals_ci("\1PING ")) { Anope::string buf = message; buf.erase(buf.begin()); buf.erase(buf.end() - 1); ircdproto->SendCTCP(bi, u->nick, "%s", buf.c_str()); } else if (message.substr(0, 9).equals_ci("\1VERSION\1")) { Module *enc = ModuleManager::FindFirstOf(ENCRYPTION); ircdproto->SendCTCP(bi, u->nick, "VERSION Anope-%s %s :%s - (%s) -- %s", Anope::Version().c_str(), Config->ServerName.c_str(), ircd->name, enc ? enc->name.c_str() : "unknown", Anope::VersionBuildString().c_str()); } return true; } bi->OnMessage(u, message); } } return true; }
void AddSession(User *u, bool exempt) { Session *session = this->ss.FindSession(u->host); if (session) { bool kill = false; if (Config->DefSessionLimit && session->count >= Config->DefSessionLimit) { kill = true; Exception *exception = this->ss.FindException(u); if (exception) { kill = false; if (exception->limit && session->count >= exception->limit) kill = true; } } /* Previously on IRCds that send a QUIT (InspIRCD) when a user is killed, the session for a host was * decremented in do_quit, which caused problems and fixed here * * Now, we create the user struture before calling this to fix some user tracking issues, * so we must increment this here no matter what because it will either be * decremented in do_kill or in do_quit - Adam */ ++session->count; if (kill && !exempt) { BotInfo *bi = findbot(Config->OperServ); if (bi) { if (!Config->SessionLimitExceeded.empty()) u->SendMessage(bi, Config->SessionLimitExceeded.c_str(), u->host.c_str()); if (!Config->SessionLimitDetailsLoc.empty()) u->SendMessage(bi, "%s", Config->SessionLimitDetailsLoc.c_str()); } u->Kill(Config->OperServ, "Session limit exceeded"); ++session->hits; if (Config->MaxSessionKill && session->hits >= Config->MaxSessionKill && akills) { const Anope::string &akillmask = "*@" + u->host; XLine *x = new XLine(akillmask, Config->OperServ, Anope::CurTime + Config->SessionAutoKillExpiry, "Session limit exceeded", XLineManager::GenerateUID()); akills->AddXLine(x); akills->Send(NULL, x); if (bi) ircdproto->SendGlobops(bi, "Added a temporary AKILL for \2%s\2 due to excessive connections", akillmask.c_str()); } } } else { session = new Session(); session->host = u->host; session->count = 1; session->hits = 0; this->ss.AddSession(session); } }