00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef lint
00021 static const char rcsid[] = "$Id: oldbotnet.c,v 1.25 2007-11-06 00:05:40 sven Exp $";
00022 #endif
00023
00024 #include <eggdrop/eggdrop.h>
00025
00026 #include "oldbotnet.h"
00027
00028 EXPORT_SCOPE int oldbotnet_LTX_start(egg_module_t *modinfo);
00029 static int oldbotnet_close(int why);
00030 static int do_link(user_t *u, const char *text);
00031 static int bot_on_delete(event_owner_t *owner, void *client_data);
00032 static int anonymous_on_delete(event_owner_t *owner, void *client_data);
00033
00034
00035
00036 static int party_plus_obot(partymember_t *p, char *nick, user_t *u, char *cmd, char *text);
00037 static int party_minus_obot(partymember_t *p, char *nick, user_t *u, char *cmd, char *text);
00038
00039
00040 static int got_actchan(botnet_bot_t *bot, const char *cmd, const char *next);
00041 static int got_away(botnet_bot_t *bot, const char *cmd, const char *next);
00042 static int got_bcast(botnet_bot_t *bot, const char *cmd, const char *next);
00043 static int got_botmsg(botnet_bot_t *bot, const char *cmd, const char *next);
00044 static int got_botbroadcast(botnet_bot_t *bot, const char *cmd, const char *next);
00045 static int got_bye(botnet_bot_t *bot, const char *cmd, const char *text);
00046 static int got_chat(botnet_bot_t *bot, const char *cmd, const char *next);
00047 static int got_endlink(botnet_bot_t *bot, const char *cmd, const char *next);
00048 static int got_handshake(botnet_bot_t *bot, const char *cmd, const char *next);
00049 static int got_idle(botnet_bot_t *bot, const char *cmd, const char *next);
00050 static int got_join(botnet_bot_t *bot, const char *cmd, const char *next);
00051 static int got_motd(botnet_bot_t *bot, const char *cmd, const char *next);
00052 static int got_nickchange(botnet_bot_t *bot, const char *cmd, const char *next);
00053 static int got_part(botnet_bot_t *bot, const char *cmd, const char *next);
00054 static int got_ping(botnet_bot_t *bot, const char *cmd, const char *next);
00055 static int got_pong(botnet_bot_t *bot, const char *cmd, const char *next);
00056 static int got_link(botnet_bot_t *bot, const char *cmd, const char *next);
00057 static int got_nlinked(botnet_bot_t *bot, const char *cmd, const char *next);
00058 static int got_unlink(botnet_bot_t *bot, const char *cmd, const char *next);
00059 static int got_unlinked(botnet_bot_t *bot, const char *cmd, const char *next);
00060 static int got_versions(botnet_bot_t *bot, const char *cmd, const char *next);
00061 static int got_thisbot(botnet_bot_t *bot, const char *cmd, const char *next);
00062 static int got_privmsg(botnet_bot_t *bot, const char *cmd, const char *next);
00063 static int got_who(botnet_bot_t *bot, const char *cmd, const char *next);
00064
00065
00066 static int oldbotnet_on_connect(void *client_data, int idx, const char *peer_ip, int peer_port);
00067 static int oldbotnet_on_read(void *client_data, int idx, char *data, int len);
00068 static int oldbotnet_on_eof(void *client_data, int idx, int err, const char *errmsg);
00069 static int oldbotnet_on_delete(event_owner_t *owner, void *client_data);
00070
00071 static event_owner_t bot_owner = {
00072 "oldbotnet", NULL,
00073 NULL, NULL,
00074 bot_on_delete
00075 };
00076
00077 static event_owner_t anonymous_owner = {
00078 "oldbotnet", NULL,
00079 NULL, NULL,
00080 anonymous_on_delete
00081 };
00082
00083 static event_owner_t generic_owner = {
00084 "oldbotnet", NULL,
00085 NULL, NULL,
00086 NULL
00087 };
00088
00089 static event_owner_t sock_owner = {
00090 "oldbotnet", NULL,
00091 NULL, NULL,
00092 oldbotnet_on_delete
00093 };
00094
00095 typedef struct assoc {
00096 char *name;
00097 int id;
00098 int dynamic;
00099 time_t last_bounced;
00100 struct assoc *next;
00101 } assoc_t;
00102
00103 static assoc_t assocs = {
00104 "*",
00105 0,
00106 0,
00107 0,
00108 NULL
00109 };
00110
00111 static bind_list_t party_binds[] = {
00112 {"n", "+obot", party_plus_obot},
00113 {"n", "-obot", party_minus_obot},
00114 {0}
00115 };
00116
00117 static bind_list_t obot_binds[] = {
00118 {NULL, "a", got_actchan},
00119 {NULL, "actchan", got_actchan},
00120
00121 {NULL, "aw", got_away},
00122 {NULL, "away", got_away},
00123 {NULL, "unaway", got_away},
00124
00125 {NULL, "bye", got_bye},
00126
00127 {NULL, "c", got_chat},
00128 {NULL, "chan", got_chat},
00129
00130 {NULL, "ct", got_bcast},
00131 {NULL, "chat", got_bcast},
00132
00133 {NULL, "el", got_endlink},
00134
00135 {NULL, "h", got_handshake},
00136 {NULL, "handshake", got_handshake},
00137
00138 {NULL, "i", got_idle},
00139 {NULL, "idle", got_idle},
00140
00141 {NULL, "j", got_join},
00142 {NULL, "join", got_join},
00143
00144 {NULL, "l", got_link},
00145 {NULL, "link", got_link},
00146
00147 {NULL, "m", got_motd},
00148 {NULL, "motd", got_motd},
00149
00150 {NULL, "n", got_nlinked},
00151 {NULL, "nlinked", got_nlinked},
00152
00153 {NULL, "nc", got_nickchange},
00154
00155 {NULL, "p", got_privmsg},
00156 {NULL, "priv", got_privmsg},
00157
00158 {NULL, "pi", got_ping},
00159 {NULL, "ping", got_ping},
00160
00161 {NULL, "po", got_pong},
00162 {NULL, "pong", got_pong},
00163
00164 {NULL, "pt", got_part},
00165 {NULL, "part", got_part},
00166
00167 {NULL, "tb", got_thisbot},
00168 {NULL, "thisbot", got_thisbot},
00169
00170 {NULL, "ul", got_unlink},
00171 {NULL, "unlink", got_unlink},
00172
00173 {NULL, "v", got_versions},
00174
00175 {NULL, "un", got_unlinked},
00176 {NULL, "unlinked", got_unlinked},
00177
00178 {NULL, "w", got_who},
00179 {NULL, "who", got_who},
00180
00181 {NULL, "z", got_botmsg},
00182 {NULL, "zapf", got_botmsg},
00183
00184 {NULL, "zb", got_botbroadcast},
00185 {NULL, "zapf-broad", got_botbroadcast},
00186 {0}
00187 };
00188
00189 static sockbuf_handler_t oldbotnet_handler = {
00190 "oldbotnet",
00191 oldbotnet_on_connect, oldbotnet_on_eof, NULL,
00192 oldbotnet_on_read, NULL
00193 };
00194
00195 static bind_table_t *BT_obot = NULL;
00196
00197 const char *assoc_get_name(int id)
00198 {
00199 int try = 0;
00200 assoc_t *a;
00201
00202 for (a = &assocs; a; a = a->next) {
00203 if (a->id == id) break;
00204 }
00205 if (a) return a->name;
00206
00207 a = malloc(sizeof(*a));
00208 do {
00209 if (!try) {
00210 a->name = egg_mprintf("%d", id);
00211 } else {
00212 free(a->name);
00213 a->name = egg_mprintf("%d_%d", id, try + 1);
00214 }
00215 ++try;
00216 } while (partychan_lookup_name(a->name));
00217 a->id = id;
00218 a->next = assocs.next;
00219 a->dynamic = 1;
00220 a->last_bounced = 0;
00221 assocs.next = a;
00222 return a->name;
00223 }
00224
00225 int assoc_get_id(const char *name)
00226 {
00227 int highest_id = 0;
00228 assoc_t *a;
00229
00230 for (a = &assocs; a; a = a->next) {
00231 if (!strcmp(a->name, name)) break;
00232 if (a->id > highest_id) highest_id = a->id;
00233 }
00234 if (a) return a->id;
00235
00236 a = malloc(sizeof(*a));
00237 a->name = strdup(name);
00238 a->id = highest_id + 1;
00239 a->last_bounced = 0;
00240 a->dynamic = 0;
00241 a->next = assocs.next;
00242 assocs.next = a;
00243 return a->id;
00244 }
00245
00246 static int get_entity(botnet_bot_t *bot, botnet_entity_t *src, char *word)
00247 {
00248 oldbotnet_t *obot = bot->client_data;
00249
00250 if (!strchr(word, '@')) {
00251 botnet_bot_t *b = botnet_lookup(word);
00252 if (botnet_check_direction(bot, b)) return -1;
00253 set_bot_entity(src, b);
00254 return 0;
00255 }
00256
00257 partymember_t *p = partymember_lookup(word, NULL, -1);
00258 if (p) {
00259 set_user_entity(src, p);
00260 return 0;
00261 }
00262
00263 int id = -1;
00264 char *nick = word, *ptr = strchr(word, '@');
00265 botnet_bot_t *srcbot = botnet_lookup(ptr + 1);
00266
00267 if (botnet_check_direction(bot, srcbot)) return -1;
00268 *ptr = 0;
00269 ptr = strchr(word, ':');
00270 if (ptr) {
00271 *ptr = 0;
00272 id = atoi(word);
00273 nick = ptr + 1;
00274 }
00275 if (obot->anonymous) partymember_delete(obot->anonymous, NULL, "Temp user expired");
00276 obot->anonymous = p = partymember_new(id, NULL, srcbot, nick, "temp", "user.on.an.old.bot", NULL, obot, &anonymous_owner);
00277 if (!p) return 0;
00278 set_user_entity(src, p);
00279 return 1;
00280 }
00281
00282
00283 static int party_plus_obot(partymember_t *p, char *nick, user_t *u, char *cmd, char *text)
00284 {
00285 char *name, *host, *port, *username, *password;
00286 user_t *obot;
00287
00288 egg_get_words(text, NULL, &name, &host, &port, &username, &password, NULL);
00289 if (!port) {
00290 partymember_printf(p, _("Syntax: +obot <obot> <host> <port> [username] [password]"));
00291 goto done;
00292 }
00293
00294 obot = user_new(name);
00295 if (!obot) {
00296 partymember_printf(p, _("Could not create obot '%s'."), name);
00297 goto done;
00298 }
00299
00300 user_set_flags_str(obot, NULL, "+b");
00301 user_set_setting(obot, "bot", "type", "old-eggdrop");
00302 user_set_setting(obot, "bot", "host", host);
00303 user_set_setting(obot, "bot", "port", port);
00304 if (username) user_set_setting(obot, "bot", "username", username);
00305 if (password) user_set_setting(obot, "bot", "password", password);
00306
00307 done:
00308 if (name) free(name);
00309 if (host) free(host);
00310 if (port) free(port);
00311 if (username) free(username);
00312 if (password) free(password);
00313 return 0;
00314 }
00315
00316
00317 static int party_minus_obot(partymember_t *p, char *nick, user_t *u, char *cmd, char *text)
00318 {
00319 char *host;
00320 user_t *obot;
00321
00322 while (isspace(*text)) text++;
00323
00324 if (!text || !*text) {
00325 partymember_printf(p, "Syntax: -obot <obot>");
00326 return(0);
00327 }
00328
00329 obot = user_lookup_by_handle(text);
00330 if (!obot) {
00331 partymember_printf(p, _("Could not find user '%s'."), text);
00332 return(0);
00333 }
00334
00335 user_get_setting(obot, "oldbotnet", "host", &host);
00336 if (!host) {
00337 partymember_printf(p, _("Error: '%s' is not an obot."), obot->handle);
00338 return(0);
00339 }
00340
00341 partymember_printf(p, _("Deleting user '%s'."), obot->handle);
00342 user_delete(obot);
00343 return(BIND_RET_LOG);
00344 }
00345
00346 static int do_link(user_t *user, const char *type)
00347 {
00348 char *host = NULL, *portstr = NULL, *un = NULL, *password = NULL;
00349 const char *username;
00350 int port;
00351 oldbotnet_t *data;
00352
00353 user_get_setting(user, NULL, "bot.host", &host);
00354 user_get_setting(user, NULL, "bot.port", &portstr);
00355 user_get_setting(user, NULL, "bot.username", &un);
00356 user_get_setting(user, NULL, "bot.password", &password);
00357 if (un) username = un;
00358 else username = botnet_get_name();
00359 if (portstr) port = atoi(portstr);
00360 if (!host || !portstr || port < 0 || port > 65535) {
00361 putlog(LOG_MISC, "*", _("Error linking %s: Invalid telnet address:port stored."), user->handle);
00362 return BIND_RET_BREAK;
00363 }
00364
00365 data = malloc(sizeof(*data));
00366 data->bot = NULL;
00367 data->user = user;
00368 data->name = strdup(username);
00369 if (password) data->password = strdup(password);
00370 else data->password = NULL;
00371 data->idx = egg_connect(host, port, -1);
00372 data->idle = 0;
00373 data->anonymous = NULL;
00374
00375 sockbuf_set_handler(data->idx, &oldbotnet_handler, data, &sock_owner);
00376 linemode_on(data->idx);
00377 socktimer_on(data->idx, 30, 0, NULL, NULL, &generic_owner);
00378
00379 putlog(LOG_MISC, "*", _("Linking to %s (%s %d) on idx %d as %s."), user->handle, host, port, data->idx, data->name);
00380 return BIND_RET_BREAK;
00381 }
00382
00383 static void do_ping(int idx, void *client_data)
00384 {
00385 oldbotnet_t *obot = client_data;
00386
00387 if (obot->idle == -1) {
00388 botnet_delete(obot->bot, _("Ping timeout"));
00389 } else if (obot->idle == 0) {
00390 obot->idle = 1;
00391 } else {
00392 obot->idle = -1;
00393 egg_iprintf(obot->idx, "pi\n");
00394 }
00395 }
00396
00408 static void got_passreq(oldbotnet_t *bot, const char *next)
00409 {
00410 if (!bot->password) {
00411 putlog(LOG_MISC, "*", _("oldbotnet error: password on %s needs to be reset."), bot->user->handle);
00412 sockbuf_delete(bot->idx);
00413 return;
00414 }
00415
00416 if (next && *next == '<') {
00417 MD5_CTX md5;
00418 unsigned char hash[16];
00419 char hex[33];
00420
00421 MD5_Init(&md5);
00422 MD5_Update(&md5, next, strlen(next));
00423 MD5_Update(&md5, bot->password, strlen(bot->password));
00424 MD5_Final(hash, &md5);
00425 MD5_Hex(hash, hex);
00426 putlog(LOG_MISC, "*", _("Received challenge from %s... sending response ..."), bot->user->handle);
00427 egg_iprintf(bot->idx, "digest %s\n", hex);
00428 } else {
00429 egg_iprintf(bot->idx, "%s\n", bot->password);
00430 }
00431 }
00432
00445 static int got_handshake(botnet_bot_t *bot, const char *cmd, const char *text)
00446 {
00447 if (!text || !*text) return BIND_RET_BREAK;
00448 putlog(LOG_MISC, "*", "Saving password '%s'", text);
00449 user_set_setting(bot->user, NULL, "botnet.password", text);
00450 return BIND_RET_BREAK;
00451 }
00452
00469 static void got_version(oldbotnet_t *bot, const char *next)
00470 {
00471 char buf[32];
00472 xml_node_t *info;
00473
00474 sscanf(next, "%d %d", &bot->version, &bot->handlen);
00475
00476
00477 egg_iprintf(bot->idx, "version 1090000 %d eggdrop v1.9 <alrighty.then>\n", bot->handlen);
00478 egg_iprintf(bot->idx, "tb %s\n", bot->name);
00479
00480 if (bot->version % 100) sprintf(buf, "eggdrop%d.%d.%d.%d", bot->version / 1000000, bot->version / 10000 % 100, bot->version / 100 % 100, bot->version % 100);
00481 else sprintf(buf, "eggdrop%d.%d.%d", bot->version / 1000000, bot->version / 10000 % 100, bot->version / 100 % 100);
00482
00483 info = xml_node_new();
00484 xml_node_set_str("eggdrop", info, "type", 0, (void *) 0);
00485 xml_node_set_int(bot->version, info, "numversion", 0, (void *) 0);
00486 xml_node_set_str(buf, info, "version", 0, (void *) 0);
00487
00488
00489 bot->linking = 1;
00490 bot->bot = botnet_new(bot->user->handle, bot->user, NULL, NULL, info, &bothandler, bot, &bot_owner, 0);
00491 if (!bot->bot) {
00492 botnet_link_failed(bot->user, "Could not create bot.");
00493 bot->user = NULL;
00494 sockbuf_delete(bot->idx);
00495 xml_node_delete(info);
00496 return;
00497 }
00498 socktimer_on(bot->idx, 90, TIMER_REPEAT, do_ping, bot, &generic_owner);
00499 botnet_replay_net(bot->bot);
00500 egg_iprintf(bot->idx, "el\n");
00501 }
00502
00503 static int got_actchan(botnet_bot_t *bot, const char *cmd, const char *next)
00504 {
00505 char *word[2], buf[1024], *action;
00506 partymember_t *p;
00507 int n, len;
00508
00509 n = egg_get_word_array(next, &next, word, 2);
00510 if (n != 2 || !next) {
00511 egg_free_word_array(word, 2);
00512 return BIND_RET_BREAK;
00513 }
00514
00515 p = partymember_lookup(word[0], NULL, -1);
00516 if (!p || botnet_check_direction(bot, p->bot)) {
00517 egg_free_word_array(word, 2);
00518 return BIND_RET_BREAK;
00519 }
00520 botnet_entity_t src = user_entity(p);
00521
00522 while (isspace(*next)) next++;
00523 action = egg_msprintf(buf, sizeof(buf), &len, "\1ACTION %s\1", next);
00524 partychan_msg_name(assoc_get_name(b64dec_int(word[1])), &src, action, len);
00525 if (action != buf) free(action);
00526
00527 egg_free_word_array(word, 2);
00528 return BIND_RET_BREAK;
00529 }
00530
00531 static int got_bcast(botnet_bot_t *bot, const char *cmd, const char *text)
00532 {
00533 char *srcname;
00534 botnet_bot_t *srcbot;
00535
00536 if (egg_get_word(text, &text, &srcname)) return BIND_RET_BREAK;
00537 while (isspace(*text)) text++;
00538
00539 srcbot = botnet_lookup(srcname);
00540 free(srcname);
00541 if (!botnet_check_direction(bot, srcbot)) return BIND_RET_BREAK;
00542
00543 botnet_entity_t src = bot_entity(srcbot);
00544 botnet_broadcast(&src, text, -1);
00545
00546 return BIND_RET_BREAK;
00547 }
00548
00559 static int got_ping(botnet_bot_t *bot, const char *cmd, const char *next)
00560 {
00561 oldbotnet_t *obot = bot->client_data;
00562
00563 egg_iprintf(obot->idx, "po\n");
00564 return BIND_RET_BREAK;
00565 }
00566
00567 static int got_endlink(botnet_bot_t *bot, const char *cmd, const char *next)
00568 {
00569 oldbotnet_t *obot = bot->client_data;
00570
00571 obot->linking = 0;
00572 botnet_link_success(obot->bot);
00573 return BIND_RET_BREAK;
00574 }
00575
00576 static int got_thisbot(botnet_bot_t *bot, const char *cmd, const char *next)
00577 {
00578 if (strcmp(bot->name, next)) {
00579 putlog(LOG_MISC, "*", "Wrong bot--wanted %s, got %s", bot->name, next);
00580 botnet_delete(bot, "imposer");
00581 }
00582 return BIND_RET_BREAK;
00583 }
00584
00585 static int got_motd(botnet_bot_t *bot, const char *cmd, const char *next)
00586 {
00587 char *word[2];
00588 int n;
00589 botnet_bot_t *dst;
00590 botnet_entity_t src;
00591
00592 n = egg_get_word_array(next, NULL, word, 2);
00593 if (n != 2) {
00594 egg_free_word_array(word, 2);
00595 return BIND_RET_BREAK;
00596 }
00597
00598 dst = botnet_lookup(word[1]);
00599 if (!dst && strcmp(word[1], botnet_get_name())) {
00600 egg_free_word_array(word, 2);
00601 return BIND_RET_BREAK;
00602 }
00603
00604 n = get_entity(bot, &src, word[0]);
00605 if (n < 0 || src.what != ENTITY_PARTYMEMBER || botnet_check_direction(bot, src.user->bot)) {
00606 egg_free_word_array(word, 2);
00607 return BIND_RET_BREAK;
00608 }
00609
00610 botnet_extension(EXTENSION_ONE, &src, dst, NULL, "motd", "", 0);
00611 return BIND_RET_BREAK;
00612 }
00613
00614 static int got_versions(botnet_bot_t *bot, const char *cmd, const char *next)
00615 {
00616 char *word[3];
00617 int n;
00618 botnet_bot_t *dst, *srcbot;
00619 partymember_t *src;
00620
00621 n = egg_get_word_array(next, NULL, word, 3);
00622 if (n != 3) {
00623 egg_free_word_array(word, 3);
00624 return BIND_RET_BREAK;
00625 }
00626
00627 srcbot = botnet_lookup(word[0]);
00628 dst = botnet_lookup(word[1]);
00629 if (!srcbot || botnet_check_direction(bot, srcbot) || (!dst && strcmp(word[1], botnet_get_name()))) {
00630 egg_free_word_array(word, 3);
00631 return BIND_RET_BREAK;
00632 }
00633
00634 src = partymember_lookup(word[2], srcbot, -1);
00635 if (!src) {
00636 int id = -1;
00637 char *ptr = strchr(word[2], ':');
00638 oldbotnet_t *obot = bot->client_data;
00639
00640 if (ptr) {
00641 *ptr = 0;
00642 id = atoi(word[2]);
00643 ++ptr;
00644 } else {
00645 ptr = word[2];
00646 }
00647 if (obot->anonymous) partymember_delete(obot->anonymous, NULL, "Temp user expired");
00648 obot->anonymous = src = partymember_new(id, NULL, srcbot, ptr, "temp", "user.on.an.old.bot", NULL, obot, &anonymous_owner);
00649 }
00650 botnet_entity_t e = user_entity(src);
00651
00652 botnet_extension(EXTENSION_ONE, &e, dst, NULL, "versions", "", 0);
00653 return BIND_RET_BREAK;
00654 }
00655
00656 static int got_nickchange(botnet_bot_t *bot, const char *cmd, const char *next)
00657 {
00658 char *word[3];
00659 int n, id;
00660 botnet_bot_t *srcbot;
00661 partymember_t *src;
00662
00663 n = egg_get_word_array(next, NULL, word, 3);
00664 if (n != 3) {
00665 egg_free_word_array(word, 3);
00666 return BIND_RET_BREAK;
00667 }
00668
00669 srcbot = botnet_lookup(word[0]);
00670 if (botnet_check_direction(bot, srcbot)) {
00671 egg_free_word_array(word, 3);
00672 return BIND_RET_BREAK;
00673 }
00674
00675 id = b64dec_int(word[1]);
00676 src = partymember_lookup(NULL, srcbot, id);
00677 if (!src) {
00678 egg_free_word_array(word, 3);
00679 return BIND_RET_BREAK;
00680 }
00681
00682 partymember_set_nick(src, word[2]);
00683
00684 return BIND_RET_BREAK;
00685 }
00686
00702 static int got_nlinked(botnet_bot_t *bot, const char *cmd, const char *next)
00703 {
00704 char *word[3], buf[32];
00705 int n, linking = 1, version;
00706 botnet_bot_t *src, *new;
00707 xml_node_t *info;
00708 oldbotnet_t *obot = bot->client_data;
00709
00710 n = egg_get_word_array(next, NULL, word, 3);
00711 if (n != 3) {
00712 egg_free_word_array(word, 3);
00713 return BIND_RET_BREAK;
00714 }
00715
00716 src = botnet_lookup(word[1]);
00717 if (botnet_check_direction(bot, src)) {
00718 egg_free_word_array(word, 3);
00719 return BIND_RET_BREAK;
00720 }
00721
00722 new = botnet_lookup(word[0]);
00723 if (new) {
00724 putlog(LOG_MISC, "*", "Botnet loop detected! %s introduced %s from %s but it exists from %s\n", bot->name, new->name, src->name, new->direction->name);
00725 egg_iprintf(obot->idx, "error Loop! (%s exists from %s)\nbye Loop (%s)\n", new->name, new->direction->name, new->name);
00726 botnet_delete(bot, "Loop detected!");
00727 return BIND_RET_BREAK;
00728 }
00729
00730 if (word[2][0] == '!') {
00731 linking = 0;
00732 version = b64dec_int(word[2] + 1);
00733 } else {
00734 version = b64dec_int(word[2]);
00735 }
00736
00737 if (version % 100) sprintf(buf, "eggdrop%d.%d.%d.%d", version / 1000000, version / 10000 % 100, version / 100 % 100, version % 100);
00738 else sprintf(buf, "eggdrop%d.%d.%d", version / 1000000, version / 10000 % 100, version / 100 % 100);
00739 info = xml_node_new();
00740 xml_node_set_str("eggdrop", info, "type", 0, (void *) 0);
00741 xml_node_set_int(version, info, "numversion", 0, (void *) 0);
00742 xml_node_set_str(buf, info, "version", 0, (void *) 0);
00743
00744 new = botnet_new(word[0], NULL, src, bot, info, NULL, NULL, &generic_owner, linking);
00745 if (!new) {
00746
00747 char obuf[512];
00748 snprintf(obuf, sizeof(obuf), "Botname incompatiblity: %s linked from %s", word[0], src->name);
00749 botnet_delete(bot, obuf);
00750
00751 xml_node_delete(info);
00752 }
00753 return BIND_RET_BREAK;
00754 }
00755
00756 static int got_bye(botnet_bot_t *bot, const char *cmd, const char *text)
00757 {
00758 botnet_delete(bot, text);
00759 return BIND_RET_BREAK;
00760 }
00761
00776 static int got_pong(botnet_bot_t *bot, const char *cmd, const char *next)
00777 {
00778 return BIND_RET_BREAK;
00779 }
00780
00795 static int got_unlink(botnet_bot_t *bot, const char *cmd, const char *text)
00796 {
00797 int n;
00798 char *word[3];
00799 const char *reason;
00800 botnet_bot_t *target;
00801 botnet_entity_t src;
00802
00803 n = egg_get_word_array(text, &text, word, 3);
00804 if (n != 3) {
00805 egg_free_word_array(word, 3);
00806 return BIND_RET_BREAK;
00807 }
00808 while (isspace(*text)) text++;
00809 if (text && *text) reason = text;
00810 else reason = "No reason.";
00811
00812 target = botnet_lookup(word[2]);
00813
00814 if (!target) {
00815 egg_free_word_array(word, 3);
00816 return BIND_RET_BREAK;
00817 }
00818
00819 n = get_entity(bot, &src, word[0]);
00820 if (n < 0) {
00821 egg_free_word_array(word, 3);
00822 return BIND_RET_BREAK;
00823 }
00824
00825 botnet_unlink(&src, target, reason);
00826 return BIND_RET_BREAK;
00827 }
00828
00829 static int got_away(botnet_bot_t *bot, const char *cmd, const char *next)
00830 {
00831 char *word[2];
00832 int n, linking = 0;
00833 botnet_bot_t *src;
00834 partymember_t *p;
00835
00836 n = egg_get_word_array(next, &next, word, 2);
00837 if (n != 2) {
00838 egg_free_word_array(word, 2);
00839 return BIND_RET_BREAK;
00840 }
00841
00842 if (word[0][0] == '!') {
00843 linking = 1;
00844 src = botnet_lookup(word[0] + 1);
00845 } else {
00846 src = botnet_lookup(word[0]);
00847 }
00848 if (botnet_check_direction(bot, src)) {
00849 egg_free_word_array(word, 2);
00850 return BIND_RET_BREAK;
00851 }
00852
00853 p = partymember_lookup(NULL, src, b64dec_int(word[1]));
00854 if (!p) {
00855 egg_free_word_array(word, 2);
00856 return BIND_RET_BREAK;
00857 }
00858
00859 while (isspace(*next)) ++next;
00860
00861 botnet_entity_t s = user_entity(p);
00862 botnet_extension(EXTENSION_ALL, &s, NULL, NULL, "away", next, -1);
00863
00864 return BIND_RET_BREAK;
00865 }
00866
00867 static int got_unlinked(botnet_bot_t *bot, const char *cmd, const char *text)
00868 {
00869 char *lostname;
00870 botnet_bot_t *lost;
00871
00872 if (egg_get_word(text, &text, &lostname)) return BIND_RET_BREAK;
00873
00874 lost = botnet_lookup(lostname);
00875 free(lostname);
00876 if (botnet_check_direction(bot, lost)) return BIND_RET_BREAK;
00877
00878 while (isspace(*text)) ++text;
00879 botnet_delete(lost, text);
00880 return BIND_RET_BREAK;
00881 }
00882
00883 static int got_idle(botnet_bot_t *bot, const char *cmd, const char *next)
00884 {
00887 return BIND_RET_BREAK;
00888 }
00889
00890 static int got_join(botnet_bot_t *bot, const char *cmd, const char *next)
00891 {
00892 char *word[5];
00893 partymember_t *p;
00894 char *ident, *sep, *host, *from;
00895 botnet_bot_t *frombot;
00896 oldbotnet_t *obot = bot->client_data;
00897 int n, id, linking = obot->linking;
00898
00899 n = egg_get_word_array(next, NULL, word, 5);
00900 if (n != 5) {
00901 egg_free_word_array(word, 5);
00902 return BIND_RET_BREAK;
00903 }
00904
00905 from = word[0];
00906 if (*from == '!') {
00907 from++;
00908 linking = 1;
00909 }
00910 frombot = botnet_lookup(from);
00911
00912 if (botnet_check_direction(bot, frombot)) {
00913 egg_free_word_array(word, 5);
00914 return BIND_RET_BREAK;
00915 }
00916
00917 id = b64dec_int(word[3] + 1);
00918
00919 p = partymember_lookup(NULL, frombot, id);
00920 if (p) {
00921 if (p == obot->anonymous) {
00922 partymember_delete(p, NULL, "Temp user expired");
00923 p = NULL;
00924 } else if (strcmp(p->nick, word[1])) {
00925 partymember_delete(p, NULL, "Botnet desync");
00926 p = NULL;
00927 }
00928 }
00929
00930 if (p) {
00931
00932 partychan_t *chan;
00933 chan = partychan_get_default(p);
00934 partychan_part(chan, p, "joining another channel");
00935 }
00936 else {
00937
00938 ident = word[4];
00939 sep = strchr(ident,'@');
00940 if (sep) {
00941 *sep = 0;
00942 host = sep+1;
00943 }
00944 else host = word[0];
00945
00946 p = partymember_new(id, NULL, frombot, word[1], ident, host, NULL, NULL, &generic_owner);
00947 }
00948 partychan_join_name(assoc_get_name(b64dec_int(word[2])), p, linking);
00949 egg_free_word_array(word, 5);
00950 return BIND_RET_BREAK;
00951 }
00952
00953 static int got_part(botnet_bot_t *bot, const char *cmd, const char *next)
00954 {
00955 int id, n;
00956 char *word[3];
00957 const char *reason;
00958 botnet_bot_t *src;
00959 partymember_t *p;
00960
00961 n = egg_get_word_array(next, &next, word, 3);
00962 if (n != 3) {
00963 egg_free_word_array(word, 3);
00964 return BIND_RET_BREAK;
00965 }
00966 while (isspace(*next)) next++;
00967 if (next && *next) reason = next;
00968 else reason = "No reason.";
00969
00970 src = botnet_lookup(word[0]);
00971 id = b64dec_int(word[2]);
00972 if (botnet_check_direction(bot, src)) {
00973 egg_free_word_array(word, 3);
00974 return BIND_RET_BREAK;
00975 }
00976
00977 p = partymember_lookup(word[1], src, id);
00978 if (p) partymember_delete(p, NULL, reason);
00979 egg_free_word_array(word, 3);
00980 return BIND_RET_BREAK;
00981 }
00982
00996 static int got_privmsg(botnet_bot_t *bot, const char *cmd, const char *next)
00997 {
00998 int n;
00999 char *word[2];
01000 const char *original = next;
01001 botnet_entity_t src;
01002 partymember_t *dst;
01003
01004 n = egg_get_word_array(next, &next, word, 2);
01005 if (n != 2) {
01006 egg_free_word_array(word, 2);
01007 return BIND_RET_BREAK;
01008 }
01009 while (isspace(*next)) next++;
01010 if (!next || !*next) {
01011 egg_free_word_array(word, 2);
01012 return BIND_RET_BREAK;
01013 }
01014
01015 n = get_entity(bot, &src, word[0]);
01016 if (n < 0) {
01017 egg_free_word_array(word, 2);
01018 return BIND_RET_BREAK;
01019 }
01020
01021 dst = partymember_lookup(word[1], NULL, -1);
01022
01023 if (!dst) {
01024 char *p = strchr(word[1], '@');
01025 if (p) {
01026 botnet_bot_t *dstbot = botnet_lookup(p + 1);
01027 if (dstbot || !strcmp(p + 1, botnet_get_name())) {
01028 botnet_extension(EXTENSION_ONE, &src, dstbot, NULL, "note", strchr(original, ' ') + 1, -1);
01029 }
01030 }
01031 egg_free_word_array(word, 2);
01032 return BIND_RET_BREAK;
01033 }
01034
01035 partymember_msg(dst, &src, next, -1);
01036 return BIND_RET_BREAK;
01037 }
01038
01039 static int got_chat(botnet_bot_t *bot, const char *cmd, const char *next)
01040 {
01041 char *word[2];
01042 int n;
01043 botnet_entity_t src;
01044
01045 n = egg_get_word_array(next, &next, word, 2);
01046 if (n != 2 || !next) {
01047 egg_free_word_array(word, 2);
01048 return BIND_RET_BREAK;
01049 }
01050
01051 if (strchr(word[0], '@')) {
01052 partymember_t *p = partymember_lookup(word[0], NULL, -1);
01053 if (!p || botnet_check_direction(bot, p->bot)) {
01054 egg_free_word_array(word, 2);
01055 return BIND_RET_BREAK;
01056 }
01057 set_user_entity(&src, p);
01058 } else {
01059 botnet_bot_t *b = botnet_lookup(word[0]);
01060 if (!b || !botnet_check_direction(bot, b)) {
01061 egg_free_word_array(word, 2);
01062 return BIND_RET_BREAK;
01063 }
01064 set_bot_entity(&src, b);
01065 }
01066
01067 while (isspace(*next)) next++;
01068 partychan_msg_name(assoc_get_name(b64dec_int(word[1])), &src, next, strlen(next));
01069
01070 egg_free_word_array(word, 2);
01071 return BIND_RET_BREAK;
01072 }
01073
01074 static void got_assoc(botnet_bot_t *src, const char *text)
01075 {
01076
01077 }
01078
01094 static int got_botmsg(botnet_bot_t *bot, const char *cmd, const char *next)
01095 {
01096 int n;
01097 char *word[3];
01098 botnet_bot_t *src, *dst;
01099
01100 n = egg_get_word_array(next, &next, word, 3);
01101 if (n != 3) {
01102 egg_free_word_array(word, 3);
01103 return BIND_RET_BREAK;
01104 }
01105
01106 src = botnet_lookup(word[0]);
01107 if (!src || botnet_check_direction(bot, src)) {
01108 egg_free_word_array(word, 3);
01109 return BIND_RET_BREAK;
01110 }
01111
01112 dst = botnet_lookup(word[1]);
01113 if (!dst && strcmp(word[1], botnet_get_name())) {
01114 egg_free_word_array(word, 3);
01115 return BIND_RET_BREAK;
01116 }
01117
01118 while (isspace(*next)) next++;
01119 if (!dst && !strcmp(word[2], "assoc") && next && *next) got_assoc(src, next);
01120 botnet_botmsg(src, dst, word[2], next, -1);
01121 egg_free_word_array(word, 3);
01122 return BIND_RET_BREAK;
01123 }
01124
01125 static int got_link(botnet_bot_t *bot, const char *cmd, const char *next)
01126 {
01127 int n;
01128 char *word[3];
01129 botnet_bot_t *dst;
01130 botnet_entity_t src;
01131
01132 n = egg_get_word_array(next, &next, word, 3);
01133 if (n != 3) {
01134 egg_free_word_array(word, 3);
01135 return BIND_RET_BREAK;
01136 }
01137
01138 n = get_entity(bot, &src, word[0]);
01139 dst = botnet_lookup(word[1]);
01140 if (n < 0 || botnet_check_direction(bot, src.what == ENTITY_BOT ? src.bot : src.user->bot) || (!dst && strcmp(word[1], botnet_get_name()))) {
01141 egg_free_word_array(word, 3);
01142 return BIND_RET_BREAK;
01143 }
01144
01145 botnet_link(&src, dst, word[2]);
01146
01147 return BIND_RET_BREAK;
01148 }
01149
01165 static int got_botbroadcast(botnet_bot_t *bot, const char *cmd, const char *next)
01166 {
01167 int n;
01168 char *word[2];
01169 botnet_bot_t *src;
01170
01171 n = egg_get_word_array(next, &next, word, 2);
01172 if (n != 2) {
01173 egg_free_word_array(word, 2);
01174 return BIND_RET_BREAK;
01175 }
01176
01177 src = botnet_lookup(word[0]);
01178 if (botnet_check_direction(bot, src)) {
01179 egg_free_word_array(word, 2);
01180 return BIND_RET_BREAK;
01181 }
01182
01183 while (isspace(*next)) next++;
01184 botnet_botbroadcast(src, word[1], next, -1);
01185 egg_free_word_array(word, 2);
01186 return BIND_RET_BREAK;
01187 }
01188
01189 static int got_who(botnet_bot_t *bot, const char *cmd, const char *next)
01190 {
01191 int n;
01192 char *word[2];
01193 botnet_entity_t src;
01194 botnet_bot_t *dst;
01195
01196 n = egg_get_word_array(next, &next, word, 2);
01197 if (n != 2) {
01198 egg_free_word_array(word, 2);
01199 return BIND_RET_BREAK;
01200 }
01201
01202 dst = botnet_lookup(word[1]);
01203 if (!dst && strcmp(word[1], botnet_get_name())) {
01204 egg_free_word_array(word, 2);
01205 return BIND_RET_BREAK;
01206 }
01207
01208 n = get_entity(bot, &src, word[0]);
01209 if (n < 0 || src.what == ENTITY_BOT || botnet_check_direction(bot, src.user->bot)) {
01210 egg_free_word_array(word, 2);
01211 return BIND_RET_BREAK;
01212 }
01213
01214 while (isspace(*next)) next++;
01215 botnet_extension(EXTENSION_ONE, &src, dst, NULL, "who", next, -1);
01216 egg_free_word_array(word, 2);
01217 return BIND_RET_BREAK;
01218 }
01219
01220 static int oldbotnet_on_connect(void *client_data, int idx, const char *peer_ip, int peer_port)
01221 {
01222 oldbotnet_t *data = client_data;
01223
01224 egg_iprintf(idx, "%s\n", data->name);
01225
01226 return 0;
01227 }
01228
01229 static int oldbotnet_on_read(void *client_data, int idx, char *data, int len)
01230 {
01231 char *cmd;
01232 const char *next;
01233 oldbotnet_t *bot = client_data;
01234
01235 bot->idle = 0;
01236 egg_get_word(data, &next, &cmd);
01237 if (!cmd) return(0);
01238
01239 if (next) while (isspace(*next)) next++;
01240
01241 if (!strcasecmp(cmd, "e") || !strcasecmp(cmd, "error") || (!bot->bot && !strcasecmp(cmd, "bye"))) {
01242 char buf[512];
01243 snprintf(buf, sizeof(buf), _("Botnet error from %s: %s"), bot->user->handle, next);
01244 if (bot->bot) {
01245 botnet_delete(bot->bot, buf);
01246 } else {
01247 botnet_link_failed(bot->user, buf);
01248 bot->user = NULL;
01249 sockbuf_delete(bot->idx);
01250 }
01251 free(cmd);
01252 return 0;
01253 }
01254
01255 if (!bot->bot) {
01256 if (!strcasecmp(cmd, "passreq")) {
01257 got_passreq(bot, next);
01258 } else if (!strcasecmp(cmd, "badpass")) {
01259 botnet_link_failed(bot->user, _("Botnet error: Password was rejected."));
01260 bot->user = NULL;
01261 sockbuf_delete(bot->idx);
01262 } else if (!strcasecmp(cmd, "version") || !strcasecmp(cmd, "v")) {
01263 got_version(bot, next);
01264 }
01265 free(cmd);
01266 return 0;
01267 }
01268
01269 if (!bind_check(BT_obot, NULL, cmd, bot->bot, cmd, next)) {
01270 putlog(LOG_MISC, "*", "%s said \"%s\" but noone cared :( (parameters: %s)", bot->bot->name, cmd, next);
01271 }
01272
01273 free(cmd);
01274 return(0);
01275 }
01276
01277 static int oldbotnet_on_eof(void *client_data, int idx, int err, const char *errmsg)
01278 {
01279 oldbotnet_t *bot = client_data;
01280
01281 if (!bot->bot) {
01282 if (bot->user->flags & USER_LINKING_BOT) botnet_link_failed(bot->user, errmsg ? errmsg : "no error");
01283 bot->user = NULL;
01284 sockbuf_delete(idx);
01285 } else {
01286 putlog(LOG_MISC, "*", _("eof from %s (%s)."), bot->bot->name, errmsg ? errmsg : "no error");
01287 botnet_delete(bot->bot, errmsg ? errmsg : "eof");
01288 }
01289 return 0;
01290 }
01291
01292 static int bot_on_delete(event_owner_t *owner, void *client_data)
01293 {
01294 oldbotnet_t *bot = client_data;
01295
01296 bot->bot = NULL;
01297 if (bot->idx >= 0) sockbuf_delete(bot->idx);
01298
01299 return 0;
01300 }
01301
01302 static int anonymous_on_delete(event_owner_t *owner, void *client_data)
01303 {
01304 oldbotnet_t *bot = client_data;
01305
01306 bot->anonymous = NULL;
01307
01308 return 0;
01309 }
01310
01311 static int oldbotnet_on_delete(event_owner_t *owner, void *client_data)
01312 {
01313 oldbotnet_t *bot = client_data;
01314
01315 bot->idx = -1;
01316 if (bot->bot) botnet_delete(bot->bot, _("Socket deleted."));
01317 else if (bot->user && bot->user->flags & USER_LINKING_BOT) botnet_link_failed(bot->user, _("Socket deleted."));
01318
01319 if (bot->name) free(bot->name);
01320 if (bot->password) free(bot->password);
01321 free(bot);
01322
01323 return 0;
01324 }
01325
01326 static int oldbotnet_init()
01327 {
01328 BT_obot = bind_table_add("obot", 3, "Bss", MATCH_MASK, BIND_STACKABLE);
01329 bind_add_list("obot", obot_binds);
01330 bind_add_list("party", party_binds);
01331 bind_add_simple(BTN_BOTNET_REQUEST_LINK, NULL, "old-eggdrop", do_link);
01332 return 0;
01333 }
01334
01335 static int oldbotnet_close(int why)
01336 {
01337 assoc_t *a, *next;
01338
01339 for (a = assocs.next; a; a = next) {
01340 next = a->next;
01341 free(a->name);
01342 free(a);
01343 }
01344 assocs.next = NULL;
01345
01346 bind_table_del(BT_obot);
01347 bind_rem_list("obot", obot_binds);
01348 bind_rem_list("party", party_binds);
01349 bind_rem_simple(BTN_BOTNET_REQUEST_LINK, NULL, "old-eggdrop", do_link);
01350
01351 return 0;
01352 }
01353
01354 int oldbotnet_LTX_start(egg_module_t *modinfo)
01355 {
01356 sock_owner.module = bot_owner.module = anonymous_owner.module = generic_owner.module = modinfo;
01357 modinfo->name = "oldbotnet";
01358 modinfo->author = "eggdev";
01359 modinfo->version = "1.0.0";
01360 modinfo->description = "oldbotnet support for most things excluding shares";
01361 modinfo->close_func = oldbotnet_close;
01362
01363 oldbotnet_init();
01364
01365 return(0);
01366 }