/* 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; }
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! */ }
void zapfbot(int idx) { char s[1024]; simple_sprintf(s, "%s: %s", BOT_BOTDROPPED, dcc[idx].nick); chatout("*** %s\n", s); botnet_send_unlinked(idx, dcc[idx].nick, s); killsock(dcc[idx].sock); lostdcc(idx); }
/* Kills the bot. s1 is the reason shown to other bots, * s2 the reason shown on the partyline. (Sup 25Jul2001) */ void kill_bot(char *s1, char *s2) { write_userfile(-1); if (!conf.bot->hub) server_die(); chatout("*** %s\n", s1); botnet_send_chat(-1, conf.bot->nick, s1); botnet_send_bye(s2); fatal(s2, 0); }
static int tcl_dccbroadcast(ClientData cd, Tcl_Interp *irp, int argc, char *argv[]) { char msg[401]; BADARGS(2, 2, " message"); strncpyz(msg, argv[1], sizeof msg); chatout("*** %s\n", msg); botnet_send_chat(-1, botnetnick, msg); check_tcl_bcst(botnetnick, -1, msg); return TCL_OK; }
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); }
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); }
/* this is only sent to hub bots */ static void bot_chat(int idx, char *par) { char *from = NULL; int i; from = newsplit(&par); if (strchr(from, '@') != NULL) { fake_alert(idx, "bot", from, "chat_i"); return; } /* Make sure the bot is valid */ i = nextbot(from); if (i != idx) { fake_alert(idx, "direction", from, "chat_ii"); return; } chatout("*** (%s) %s\n", from, par); botnet_send_chat(idx, from, par); }
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); }
/* chat <from> <notice> -- only from bots */ static void bot_chat(int idx, char *par) { char *from; int i; if (bot_flags(dcc[idx].user) & BOT_ISOLATE) return; from = newsplit(&par); if (strchr(from, '@') != NULL) { fake_alert(idx, "bot", from); return; } /* Make sure the bot is valid */ i = nextbot(from); if (i != idx) { fake_alert(idx, "direction", from); return; } chatout("*** (%s) %s\n", from, par); botnet_send_chat(idx, from, par); check_tcl_bcst(from, -1, par); }
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)); }
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); }
/* reject <from> <bot> */ static void bot_reject(int idx, char *par) { char *from = NULL, *who = NULL, *destbot = NULL, *frombot = NULL; struct userrec *u = NULL; int i; from = newsplit(&par); frombot = strchr(from, '@'); if (frombot) frombot++; else frombot = from; i = nextbot(frombot); if (i != idx) { fake_alert(idx, "direction", frombot, "reject"); return; } who = newsplit(&par); if (!(destbot = strchr(who, '@'))) { /* Rejecting a bot */ i = nextbot(who); if (i < 0) { botnet_send_priv(idx, conf.bot->nick, from, NULL, "Can't unlink %s (doesn't exist)", who); } else if (!strcasecmp(dcc[i].nick, who)) { char s[1024]; /* I'm the connection to the rejected bot */ putlog(LOG_BOTS, "*", "%s rejected %s", from, dcc[i].nick); dprintf(i, "bye %s\n", par[0] ? par : "rejected"); simple_sprintf(s, "Disconnected %s (%s: %s)", dcc[i].nick, from, par[0] ? par : "rejected"); chatout("*** %s\n", s); botnet_send_unlinked(i, dcc[i].nick, s); killsock(dcc[i].sock); lostdcc(i); } else { if (i >= 0) botnet_send_reject(i, from, NULL, who, NULL, par); } } else { /* Rejecting user */ *destbot++ = 0; if (!strcasecmp(destbot, conf.bot->nick)) { /* Kick someone here! */ int ok = 0; for (i = 0; i < dcc_total; i++) { if (dcc[i].type && dcc[i].simul == -1 && !strcasecmp(who, dcc[i].nick) && (dcc[i].type->flags & DCT_CHAT)) { u = get_user_by_handle(userlist, from); if (u) { if (!whois_access(u, dcc[idx].user)) { add_note(from, conf.bot->nick, "Sorry, you cannot boot them.", -1, 0); return; } do_boot(i, from, par); putlog(LOG_CMDS, "*", "#%s# boot %s (%s)", from, who, par[0] ? par : "No reason"); ok = 1; } } } } else { i = nextbot(destbot); *--destbot = '@'; if (i >= 0) botnet_send_reject(i, from, NULL, who, NULL, par); } } }
/* break link with a tandembot */ int botunlink(int idx, char *nick, char *reason) { char s[20]; register int i; tand_t *bot; Context; if (nick[0] == '*') dprintf(idx, "%s\n", BOT_UNLINKALL); for (i = 0; i < dcc_total; i++) { if ((nick[0] == '*') || !strcasecmp(dcc[i].nick, nick)) { if (dcc[i].type == &DCC_FORK_BOT) { if (idx >= 0) dprintf(idx, "%s: %s -> %s.\n", BOT_KILLLINKATTEMPT, dcc[i].nick, dcc[i].host); putlog(LOG_BOTS, "*", "%s: %s -> %s:%d", BOT_KILLLINKATTEMPT, dcc[i].nick, dcc[i].host, dcc[i].port); killsock(dcc[i].sock); lostdcc(i); if (nick[0] != '*') return 1; } else if (dcc[i].type == &DCC_BOT_NEW) { if (idx >= 0) dprintf(idx, "%s %s.\n", BOT_ENDLINKATTEMPT, dcc[i].nick); putlog(LOG_BOTS, "*", "%s %s @ %s:%d", "Stopped trying to link", dcc[i].nick, dcc[i].host, dcc[i].port); killsock(dcc[i].sock); lostdcc(i); if (nick[0] != '*') return 1; else i--; } else if (dcc[i].type == &DCC_BOT) { char s[1024]; Context; if (idx >= 0) dprintf(idx, "%s %s.\n", BOT_BREAKLINK, dcc[i].nick); else if ((idx == -3) && (b_status(i) & STAT_SHARE) && !share_unlinks) return -1; dprintf(i, "bye\n"); if (reason && reason[0]) { simple_sprintf(s, "%s %s (%s)", BOT_UNLINKEDFROM, dcc[i].nick, reason); } else { simple_sprintf(s, "%s %s", BOT_UNLINKEDFROM, dcc[i].nick); } chatout("*** %s\n", s); botnet_send_unlinked(i, dcc[i].nick, s); killsock(dcc[i].sock); lostdcc(i); if (nick[0] != '*') return 1; else i--; } } } Context; if ((idx >= 0) && (nick[0] != '*')) { dprintf(idx, "%s\n", BOT_NOTCONNECTED); /* The internal bot list is desynched from the dcc list * sometimes. While we still search for the bug, provide * an easy way to clear out those `ghost'-bots. -FK */ bot = findbot(nick); if (bot) { dprintf(idx, "BUG: Found bot `%s' in internal bot list! Removing.\n", nick); rembot(bot->bot); } } if (nick[0] == '*') { dprintf(idx, "%s\n", BOT_WIPEBOTTABLE); while (tandbot) rembot(tandbot->bot); while (parties) { parties--; /* Assert? */ if (party[i].chan >= 0) check_tcl_chpt(party[i].bot, party[i].nick, party[i].sock, party[i].chan); } strcpy(s, "killassoc &"); Tcl_Eval(interp, s); } return 0; }
/* Newbot next share? */ static void bot_nlinked(int idx, char *par) { char *newbot = NULL, *next = NULL, *p = NULL, s[1024] = "", x = 0, *vversion = NULL, *vcommit = NULL; int i, vlocalhub = 0; time_t vbuildts = 0L; bool bogus = 0; newbot = newsplit(&par); next = newsplit(&par); s[0] = 0; if (!next[0]) { putlog(LOG_BOTS, "*", "Invalid eggnet protocol from %s (zapfing)", dcc[idx].nick); simple_snprintf(s, sizeof(s), "Disconnected %s (invalid bot)", dcc[idx].nick); dprintf(idx, "error invalid eggnet protocol for 'nlinked'\n"); } else if ((in_chain(newbot)) || (!strcasecmp(newbot, conf.bot->nick))) { /* Loop! */ putlog(LOG_BOTS, "*", "Loop detected %s (mutual: %s)", dcc[idx].nick, newbot); simple_snprintf(s, sizeof(s), "Detected loop: two bots exist named %s: disconnecting %s", newbot, dcc[idx].nick); dprintf(idx, "error Loop (%s)\n", newbot); } if (!s[0]) { for (p = newbot; *p; p++) if ((*p < 32) || (*p == 127)) bogus = 1; i = nextbot(next); if (i != idx) bogus = 1; if (bogus) { putlog(LOG_BOTS, "*", "Bogus link notice from %s! (%s -> %s)", dcc[idx].nick, next, newbot); simple_snprintf(s, sizeof(s), "Bogus link notice from: %s Disconnected", dcc[idx].nick); dprintf(idx, "error Bogus link notice from (%s -> %s)\n", next, newbot); } } if (s[0]) { chatout("*** %s\n", s); botnet_send_unlinked(idx, dcc[idx].nick, s); dprintf(idx, "bye %s\n", s); killsock(dcc[idx].sock); lostdcc(idx); return; } x = par[0]; if (x) par++; else x = '-'; if (par[0]) newsplit(&par); /* vnum */ if (par[0]) vlocalhub = atoi(newsplit(&par)); if (par[0]) vbuildts = atol(newsplit(&par)); if (par[0]) vcommit = newsplit(&par); if (par[0]) vversion = newsplit(&par); botnet_send_nlinked(idx, newbot, next, x, vlocalhub, vbuildts, vcommit, vversion); if (x == '!') { if (conf.bot->hub) chatout("*** (%s) %s %s.\n", next, "Linked to", newbot); else chatout("*** %s linked to botnet.\n", newbot); x = '-'; } addbot(newbot, dcc[idx].nick, next, x, vlocalhub, vbuildts, vcommit, vversion ? vversion : (char *) ""); }
/* Newbot next share? */ static void bot_nlinked(int idx, char *par) { char *newbot, *next, *p, s[1024], x; int bogus = 0, i; struct userrec *u; newbot = newsplit(&par); next = newsplit(&par); s[0] = 0; if (!next[0]) { putlog(LOG_BOTS, "*", "Invalid eggnet protocol from %s (zapfing)", dcc[idx].nick); simple_sprintf(s, "%s %s (%s)", MISC_DISCONNECTED, dcc[idx].nick, MISC_INVALIDBOT); dprintf(idx, "error invalid eggnet protocol for 'nlinked'\n"); } else if ((in_chain(newbot)) || (!egg_strcasecmp(newbot, botnetnick))) { /* Loop! */ putlog(LOG_BOTS, "*", "%s %s (mutual: %s)", BOT_LOOPDETECT, dcc[idx].nick, newbot); simple_sprintf(s, "%s %s: disconnecting %s", MISC_LOOP, newbot, dcc[idx].nick); dprintf(idx, "error Loop (%s)\n", newbot); } if (!s[0]) { for (p = newbot; *p; p++) if ((*p < 32) || (*p == 127) || ((p - newbot) >= HANDLEN)) bogus = 1; i = nextbot(next); if (i != idx) bogus = 1; } if (bogus) { putlog(LOG_BOTS, "*", "%s %s! (%s -> %s)", BOT_BOGUSLINK, dcc[idx].nick, next, newbot); simple_sprintf(s, "%s: %s %s", BOT_BOGUSLINK, dcc[idx].nick, MISC_DISCONNECTED); dprintf(idx, "error %s (%s -> %s)\n", BOT_BOGUSLINK, next, newbot); } if (bot_flags(dcc[idx].user) & BOT_LEAF) { putlog(LOG_BOTS, "*", "%s %s (%s %s)", BOT_DISCONNLEAF, dcc[idx].nick, newbot, BOT_LINKEDTO); simple_sprintf(s, "%s %s (to %s): %s", BOT_ILLEGALLINK, dcc[idx].nick, newbot, MISC_DISCONNECTED); dprintf(idx, "error %s\n", BOT_YOUREALEAF); } if (s[0]) { chatout("*** %s\n", s); botnet_send_unlinked(idx, dcc[idx].nick, s); dprintf(idx, "bye %s\n", BOT_ILLEGALLINK); killsock(dcc[idx].sock); lostdcc(idx); return; } x = par[0]; if (x) par++; else x = '-'; #ifndef NO_OLD_BOTNET if (dcc[idx].u.bot->numver < NEAT_BOTNET) i = atoi(par); else #endif i = base64_to_int(par); botnet_send_nlinked(idx, newbot, next, x, i); if (x == '!') { chatout("*** (%s) %s %s.\n", next, NET_LINKEDTO, newbot); x = '-'; } addbot(newbot, dcc[idx].nick, next, x, i); check_tcl_link(newbot, next); u = get_user_by_handle(userlist, newbot); if (bot_flags(u) & BOT_REJECT) { botnet_send_reject(idx, botnetnick, NULL, newbot, NULL, NULL); putlog(LOG_BOTS, "*", "%s %s %s %s", BOT_REJECTING, newbot, MISC_FROM, dcc[idx].nick); } }
/* reject <from> <bot> */ static void bot_reject(int idx, char *par) { char *from, *who, *destbot, *frombot; struct userrec *u; int i; if (bot_flags(dcc[idx].user) & BOT_ISOLATE) return; from = newsplit(&par); frombot = strchr(from, '@'); if (frombot) frombot++; else frombot = from; i = nextbot(frombot); if (i != idx) { fake_alert(idx, "direction", frombot); return; } who = newsplit(&par); if (!(destbot = strchr(who, '@'))) { /* Rejecting a bot */ i = nextbot(who); if (i < 0) { botnet_send_priv(idx, botnetnick, from, NULL, "%s %s (%s)", BOT_CANTUNLINK, who, BOT_DOESNTEXIST); } else if (!egg_strcasecmp(dcc[i].nick, who)) { char s[1024]; /* I'm the connection to the rejected bot */ putlog(LOG_BOTS, "*", "%s %s %s", from, MISC_REJECTED, dcc[i].nick); dprintf(i, "bye %s\n", par[0] ? par : MISC_REJECTED); simple_sprintf(s, "%s %s (%s: %s)", MISC_DISCONNECTED, dcc[i].nick, from, par[0] ? par : MISC_REJECTED); chatout("*** %s\n", s); botnet_send_unlinked(i, dcc[i].nick, s); killsock(dcc[i].sock); lostdcc(i); } else { if (i >= 0) botnet_send_reject(i, from, NULL, who, NULL, par); } } else { /* Rejecting user */ *destbot++ = 0; if (!egg_strcasecmp(destbot, botnetnick)) { /* Kick someone here! */ int ok = 0; if (remote_boots == 1) { frombot = strchr(from, '@'); if (frombot == NULL) frombot = from; else frombot++; u = get_user_by_handle(userlist, frombot); if (!(bot_flags(u) & BOT_SHARE)) { add_note(from, botnetnick, "No non sharebot boots.", -1, 0); ok = 1; } } else if (remote_boots == 0) { botnet_send_priv(idx, botnetnick, from, NULL, "%s", BOT_NOREMOTEBOOT); ok = 1; } for (i = 0; (i < dcc_total) && !ok; i++) if ((!egg_strcasecmp(who, dcc[i].nick)) && (dcc[i].type->flags & DCT_CHAT)) { u = get_user_by_handle(userlist, dcc[i].nick); if (u && (u->flags & USER_OWNER)) { add_note(from, botnetnick, BOT_NOOWNERBOOT, -1, 0); return; } do_boot(i, from, par); ok = 1; putlog(LOG_CMDS, "*", "#%s# boot %s (%s)", from, who, par[0] ? par : "No reason"); } } else { i = nextbot(destbot); *--destbot = '@'; if (i >= 0) botnet_send_reject(i, from, NULL, who, NULL, par); } } }