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: botnet.c,v 1.6 2007-11-06 00:05:40 sven Exp $";
00022 #endif
00023
00024 #include <eggdrop/eggdrop.h>
00025
00026 #include "botnet.h"
00027
00028 EXPORT_SCOPE int botnet_LTX_start(egg_module_t *modinfo);
00029
00030 typedef struct {
00031 char *ip;
00032 int port;
00033 } botnet_config_t;
00034
00035 static int bot_close(int why);
00036 static int do_link(user_t *u, const char *text);
00037
00038 static int bot_on_delete(event_owner_t *owner, void *client_data);
00039
00040
00041
00042 static int party_plus_bot(partymember_t *p, char *nick, user_t *u, char *cmd, char *text);
00043 static int party_minus_bot(partymember_t *p, char *nick, user_t *u, char *cmd, char *text);
00044
00045
00046 static int idx_on_newclient(void *client_data, int idx, int newidx, const char *peer_ip, int peer_port);
00047 static int idx_on_connect(void *client_data, int idx, const char *peer_ip, int peer_port);
00048 static int idx_on_read(void *client_data, int idx, char *data, int len);
00049 static int idx_on_eof(void *client_data, int idx, int err, const char *errmsg);
00050 static int idx_on_delete(event_owner_t *owner, void *client_data);
00051
00052 static int got_bbroadcast(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00053 static int got_botmsg(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00054 static int got_bquit(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00055 static int got_broadcast(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00056 static int got_chanmsg(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00057 static int got_endlink(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00058 static int got_extension(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00059 static int got_join(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00060 static int got_link(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00061 static int got_login(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00062 static int got_newbot(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00063 static int got_nick(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00064 static int got_part(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00065 static int got_ping(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00066 static int got_pong(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00067 static int got_privmsg(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00068 static int got_quit(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00069 static int got_unlink(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00070
00071 static struct {
00072 char *cmd;
00073 int source;
00074 int min_argc;
00075 int (*function)(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
00076 } cmd_mapping[] = {
00077 {"bbroadcast", ENTITY_BOT, 1, got_bbroadcast},
00078 {"botmsg", ENTITY_BOT, 1, got_botmsg},
00079 {"bquit", ENTITY_BOT, 0, got_bquit},
00080 {"broadcast", 0, 1, got_broadcast},
00081 {"chanmsg", 0, 2, got_chanmsg},
00082 {"el", ENTITY_BOT, 0, got_endlink},
00083 {"extension", 0, 2, got_extension},
00084 {"join", ENTITY_PARTYMEMBER, 1, got_join},
00085 {"link", 0, 2, got_link},
00086 {"login", ENTITY_BOT, 4, got_login},
00087 {"newbot", ENTITY_BOT, 4, got_newbot},
00088 {"nick", ENTITY_PARTYMEMBER, 1, got_nick},
00089 {"part", ENTITY_PARTYMEMBER, 1, got_part},
00090 {"ping", ENTITY_BOT, 0, got_ping},
00091 {"pong", ENTITY_BOT, 0, got_pong},
00092 {"privmsg", 0, 2, got_privmsg},
00093 {"quit", ENTITY_PARTYMEMBER, 0, got_quit},
00094 {"unlink", 0, 2, got_unlink}
00095 };
00096
00097 static int cmd_num = sizeof(cmd_mapping) / sizeof(cmd_mapping[0]);
00098
00099 static int listen_idx;
00100
00101 static botnet_config_t botnet_config;
00102
00103 static sockbuf_handler_t server_handler = {
00104 "botnet server",
00105 NULL, NULL, idx_on_newclient,
00106 NULL, NULL
00107 };
00108
00109 static config_var_t botnet_config_vars[] = {
00110 {"my-ip", &botnet_config.ip, CONFIG_STRING},
00111 {"port", &botnet_config.port, CONFIG_INT},
00112 {0}
00113 };
00114
00115 static event_owner_t bot_owner = {
00116 "botnet", NULL,
00117 NULL, NULL,
00118 bot_on_delete
00119 };
00120
00121 static event_owner_t sock_owner = {
00122 "botnet", NULL,
00123 NULL, NULL,
00124 idx_on_delete
00125 };
00126
00127 static event_owner_t generic_owner = {
00128 "botnet", NULL,
00129 NULL, NULL,
00130 NULL
00131 };
00132
00133
00134
00135
00136
00137
00138
00139 static bind_list_t party_binds[] = {
00140 {"n", "+bot", party_plus_bot},
00141 {"n", "-bot", party_minus_bot},
00142 {0}
00143 };
00144
00145 static sockbuf_handler_t client_handler = {
00146 "botnet",
00147 idx_on_connect, idx_on_eof, NULL,
00148 idx_on_read, NULL
00149 };
00150
00151
00152 static int party_plus_bot(partymember_t *p, char *nick, user_t *u, char *cmd, char *text)
00153 {
00154 char *name, *host, *port;
00155 user_t *bot;
00156
00157 egg_get_words(text, NULL, &name, &host, &port, NULL);
00158 if (!port) {
00159 partymember_printf(p, _("Syntax: +bot <bot> <host> <port>"));
00160 goto done;
00161 }
00162
00163 bot = user_new(name);
00164 if (!bot) {
00165 partymember_printf(p, _("Could not create bot '%s'."), name);
00166 goto done;
00167 }
00168
00169 user_set_flags_str(bot, NULL, "+b");
00170 user_set_setting(bot, "bot", "type", "eggdrop");
00171 user_set_setting(bot, "bot", "host", host);
00172 user_set_setting(bot, "bot", "port", port);
00173
00174 done:
00175 if (name) free(name);
00176 if (host) free(host);
00177 if (port) free(port);
00178 return 0;
00179 }
00180
00181
00182 static int party_minus_bot(partymember_t *p, char *nick, user_t *u, char *cmd, char *text)
00183 {
00184 char *type;
00185 user_t *bot;
00186
00187 while (isspace(*text)) text++;
00188
00189 if (!text || !*text) {
00190 partymember_printf(p, "Syntax: -bot <bot>");
00191 return(0);
00192 }
00193
00194 bot = user_lookup_by_handle(text);
00195 if (!bot) {
00196 partymember_printf(p, _("Could not find user '%s'."), text);
00197 return(0);
00198 }
00199
00200 user_get_setting(bot, "bot", "type", &type);
00201 if (!type || !(bot->flags | USER_BOT) || strcmp(type, "eggdrop")) {
00202 partymember_printf(p, _("Error: '%s' is not an eggdrop bot."), bot->handle);
00203 return(0);
00204 }
00205
00206 partymember_printf(p, _("Deleting user '%s'."), bot->handle);
00207 user_delete(bot);
00208 return(BIND_RET_LOG);
00209 }
00210
00211 static int get_entity(botnet_entity_t *ent, char *text)
00212 {
00213 char *p;
00214 int id = -1;
00215 botnet_bot_t *bot;
00216 partymember_t *pm;
00217
00218 p = strchr(text, '@');
00219 if (p) {
00220 *p = 0;
00221 id = b64dec_int(text);
00222 text = p + 1;
00223 }
00224 bot = botnet_lookup(text);
00225 if (!bot && strcmp(text, botnet_get_name())) return 1;
00226 if (id == -1) {
00227 set_bot_entity(ent, bot);
00228 return 0;
00229 }
00230 pm = partymember_lookup(NULL, bot, id);
00231 if (!pm) return 1;
00232 set_user_entity(ent, pm);
00233 return 0;
00234 }
00235
00236 static int do_link(user_t *user, const char *type)
00237 {
00238 char *host = NULL, *portstr = NULL, *password = NULL;
00239 int port;
00240 bot_t *data;
00241
00242 user_get_setting(user, NULL, "bot.host", &host);
00243 user_get_setting(user, NULL, "bot.port", &portstr);
00244 user_get_setting(user, NULL, "bot.password", &password);
00245
00246 if (portstr) port = atoi(portstr);
00247 if (!host || !portstr || port <= 0 || port > 65535) {
00248 putlog(LOG_MISC, "*", _("Error linking %s: Invalid telnet address:port stored."), user->handle);
00249 return BIND_RET_BREAK;
00250 }
00251
00252 data = malloc(sizeof(*data));
00253 data->bot = NULL;
00254 data->user = user;
00255 data->idx = egg_connect(host, port, -1);
00256 data->proto = NULL;
00257 if (password) data->pass = strdup(password);
00258 else data->pass = NULL;
00259 data->incoming = 0;
00260 data->linking = 1;
00261 data->idle = 0;
00262
00263 sockbuf_set_handler(data->idx, &client_handler, data, &sock_owner);
00264 netstring_on(data->idx);
00265 socktimer_on(data->idx, 30, 0, NULL, NULL, &generic_owner);
00266
00267 putlog(LOG_MISC, "*", _("Linking to %s (%s %d) on idx %d."), user->handle, host, port, data->idx);
00268 return BIND_RET_BREAK;
00269 }
00270
00271 static void do_ping(int idx, void *client_data)
00272 {
00273 bot_t *bot = client_data;
00274
00275 if (bot->idle == -1) {
00276 botnet_delete(bot->bot, _("Ping timeout"));
00277 } else if (bot->idle == 0) {
00278 bot->idle = 1;
00279 } else {
00280 bot->idle = -1;
00281 egg_iprintf(bot->idx, "ping\n");
00282 }
00283 }
00284
00285 static int got_bbroadcast(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00286 {
00287 if (argc <= 1) len = 0;
00288 botnet_botbroadcast(src->bot, argv[0], argv[argc - 1], len);
00289
00290 return 0;
00291 }
00292
00293 static int got_botmsg(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00294 {
00295 botnet_entity_t dst;
00296
00297 if (get_entity(&dst, argv[0])) return 0;
00298 if (dst.what != ENTITY_BOT) return 0;
00299
00300 if (argc <= 2) len = 0;
00301 botnet_botmsg(src->bot, dst.bot, argv[1], argv[argc - 1], len);
00302
00303 return 0;
00304 }
00305
00306 static int got_bquit(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00307 {
00308 botnet_delete(src->bot, len ? argv[0] : "No reason");
00309
00310 return 0;
00311 }
00312
00313 static int got_broadcast(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00314 {
00315 botnet_broadcast(src, argv[0], len);
00316
00317 return 0;
00318 }
00319
00320 static int got_chanmsg(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00321 {
00322 partychan_msg_name(argv[0], src, argv[1], len);
00323
00324 return 0;
00325 }
00326
00327 static int got_endlink(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00328 {
00329 botnet_link_success(src->bot);
00330
00331 return 0;
00332 }
00333
00334 static int got_extension(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00335 {
00336 botnet_entity_t dst;
00337
00338 if (argc <= 2) len = 0;
00339
00340 if (argv[0][0] == '*') {
00341 botnet_extension(EXTENSION_ALL, src, NULL, NULL, argv[1], argv[argc - 1], len);
00342 }
00343
00344 if (get_entity(&dst, argv[0])) return 0;
00345 if (dst.what != ENTITY_BOT) return 0;
00346
00347 botnet_extension(EXTENSION_ONE, src, dst.bot, NULL, argv[1], argv[argc - 1], len);
00348
00349 return 0;
00350 }
00351
00352
00353
00354 static int got_join(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00355 {
00356 int netburst = 0;
00357
00358 if (argc >= 2) netburst = b64dec_int(argv[1]) & 1;
00359 partychan_join_name(argv[0], src->user, netburst);
00360
00361 return 0;
00362 }
00363
00364 static int got_link(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00365 {
00366 botnet_entity_t dst;
00367
00368 if (get_entity(&dst, argv[0])) return 0;
00369 if (dst.what != ENTITY_BOT) return 0;
00370
00371 botnet_link(src, dst.bot, argv[1]);
00372 return 0;
00373 }
00374
00375
00376
00377 static int got_login(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00378 {
00379 partymember_new(b64dec_int(argv[3]), NULL, src->bot, argv[0], argv[1], argv[2], NULL, NULL, &generic_owner);
00380 return 0;
00381 }
00382
00383
00384
00385 static int got_newbot(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00386 {
00387 int flags = 0;
00388 xml_node_t *info;
00389 botnet_bot_t *new;
00390
00391 if (argc >= 5) flags = b64dec_int(argv[4]);
00392
00393 info = xml_node_new();
00394 xml_node_set_str(argv[1], info, "type", 0, (void *) 0);
00395 xml_node_set_int(b64dec_int(argv[2]), info, "numversion", 0, (void *) 0);
00396 xml_node_set_str(argv[3], info, "version", 0, (void *) 0);
00397
00398 new = botnet_new(argv[0], NULL, src->bot, bot->bot, info, NULL, NULL, &generic_owner, flags & 1);
00399 if (!new) {
00400 botnet_delete(bot->bot, _("Couldn't create introduced bot"));
00401 xml_node_delete(info);
00402 return 0;
00403 }
00404
00405 return 0;
00406 }
00407
00408 static int got_nick(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00409 {
00410 partymember_set_nick(src->user, argv[0]);
00411 return 0;
00412 }
00413
00414 static int got_part(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00415 {
00416 char *reason = NULL;
00417
00418 if (argc >= 2) reason = argv[argc - 1];
00419 partychan_part_name(argv[0], src->user, reason);
00420
00421 return 0;
00422 }
00423
00424 static int got_ping(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00425 {
00426 egg_iprintf(bot->idx, "pong\n");
00427
00428 return 0;
00429 }
00430
00431 static int got_pong(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00432 {
00433 return 0;
00434 }
00435
00436 static int got_privmsg(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00437 {
00438 partymember_t *dst;
00439 botnet_entity_t ent;
00440
00441 if (get_entity(&ent, argv[0])) return 0;
00442 if (ent.what != ENTITY_PARTYMEMBER) return 0;
00443 dst = ent.user;
00444 partymember_msg(dst, src, argv[1], len);
00445 return 0;
00446 }
00447
00448 static int got_quit(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00449 {
00450 partymember_delete(src->user, NULL, len ? argv[0] : "No reason.");
00451 return 0;
00452 }
00453
00454 static int got_unlink(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
00455 {
00456 botnet_entity_t dst;
00457
00458 if (get_entity(&dst, argv[0])) return 0;
00459 if (dst.what != ENTITY_BOT) return 0;
00460
00461 botnet_link(src, dst.bot, argv[1]);
00462 return 0;
00463 }
00464
00465 static int idx_on_newclient(void *client_data, int idx, int newidx, const char *peer_ip, int peer_port)
00466 {
00467 bot_t *session;
00468
00469 session = malloc(sizeof(*session));
00470 session->bot = NULL;
00471 session->user = NULL;
00472 session->idx = newidx;
00473 session->proto = NULL;
00474 session->pass = NULL;
00475 session->incoming = 1;
00476 session->linking = 1;
00477 session->idle = 0;
00478
00479 sockbuf_set_handler(newidx, &client_handler, session, &sock_owner);
00480 netstring_on(newidx);
00481 socktimer_on(newidx, 30, 0, NULL, NULL, &generic_owner);
00482
00483 return 0;
00484 }
00485
00486 static int idx_on_connect(void *client_data, int idx, const char *peer_ip, int peer_port)
00487 {
00488 bot_t *bot = client_data;
00489
00490
00491
00492 bot->proto = malloc(sizeof(*bot->proto));
00493 bot->proto->dummy = 0;
00494 egg_iprintf(idx, ":%s hello %s", botnet_get_name(), bot->user->handle);
00495
00496 return 0;
00497 }
00498
00512 static int recving_login(bot_t *bot, char *src, char *cmd, int argc, char *argv[], int len) {
00513 if (src) {
00514 if (!bot->user) {
00515 bot->user = user_lookup_by_handle(src);
00516 if (!bot->user || !(bot->user->flags & USER_BOT) || !strcmp(src, botnet_get_name())) {
00517 sockbuf_delete(bot->idx);
00518 return 0;
00519 }
00520 if (botnet_lookup(src) || bot->user->flags & (USER_LINKING_BOT | USER_LINKED_BOT)) {
00521 sockbuf_delete(bot->idx);
00522 return 0;
00523 }
00524 } else {
00525 if (src && strcmp(src, bot->user->handle)) {
00526 sockbuf_delete(bot->idx);
00527 return 0;
00528 }
00529 }
00530 }
00531 if (!strcasecmp(cmd, "PROTO")) {
00532 if (bot->proto) {
00533 sockbuf_delete(bot->idx);
00534 return 0;
00535 }
00536 bot->proto = malloc(sizeof(*bot->proto));
00537 bot->proto->dummy = 0;
00538 egg_iprintf(bot->idx, "PROTO");
00539 return 0;
00540 }
00541 if (!bot->user) {
00542 sockbuf_delete(bot->idx);
00543 return 0;
00544 }
00545 if (!bot->proto) {
00546 bot->proto = malloc(sizeof(*bot->proto));
00547 bot->proto->dummy = 0;
00548 }
00549
00550 if (!strcasecmp(cmd, "HELLO")) {
00551 int i;
00552 char salt[33], *pass = NULL;
00553 unsigned char hash[16];
00554 MD5_CTX md5;
00555
00556 if (bot->pass || argc != 1 || strcmp(argv[0], botnet_get_name())) {
00557 sockbuf_delete(bot->idx);
00558 return 0;
00559 }
00560 user_get_setting(bot->user, NULL, "bot.password", &pass);
00561 if (!pass || !*pass) {
00562 egg_iprintf(bot->idx, "thisbot eggdrop %s %s %s :%s", botnet_get_name(), "1090000", "eggdrop1.9.0+cvs", "some informative stuff");
00563 bot->pass = calloc(1, 1);
00564 return 0;
00565 }
00566 for (i = 0; i < 32; ++i) {
00567 salt[i] = random() % 62;
00568 if (salt[i] < 26) salt[i] += 'A';
00569 else if (salt[i] < 52) salt[i] += 'a' - 26;
00570 else salt[i] += '0' - 52;
00571 }
00572 salt[32] = 0;
00573 MD5_Init(&md5);
00574 MD5_Update(&md5, salt, 32);
00575 MD5_Update(&md5, pass, strlen(pass));
00576 MD5_Final(hash, &md5);
00577 bot->pass = malloc(33);
00578 MD5_Hex(hash, bot->pass);
00579 egg_iprintf(bot->idx, "passreq %s", salt);
00580 } else if (!strcasecmp(cmd, "PASS")) {
00581 if (!bot->pass || argc != 1 || strcmp(argv[0], bot->pass)) {
00582 sockbuf_delete(bot->idx);
00583 return 0;
00584 }
00585 *bot->pass = 0;
00586 egg_iprintf(bot->idx, ":%s thisbot eggdrop %s %s :%s", botnet_get_name(), b64enc_int(1090000), "eggdrop1.9.0+cvs", "some informative stuff");
00587 } else if (!strcasecmp(cmd, "THISBOT")) {
00588 xml_node_t *info;
00589
00590 if (!bot->pass || *bot->pass || argc != 4) {
00591 sockbuf_delete(bot->idx);
00592 return 0;
00593 }
00594 free(bot->pass);
00595 bot->pass = NULL;
00596 bot->linking = 0;
00597
00598 info = xml_node_new();
00599 xml_node_set_str(argv[0], info, "type", 0, (void *) 0);
00600 xml_node_set_int(b64dec_int(argv[1]), info, "numversion", 0, (void *) 0);
00601 xml_node_set_str(argv[2], info, "version", 0, (void *) 0);
00602
00603 bot->bot = botnet_new(bot->user->handle, bot->user, NULL, NULL, info, &bothandler, bot, &bot_owner, 0);
00604 socktimer_on(bot->idx, 90, TIMER_REPEAT, do_ping, bot, &generic_owner);
00605 botnet_replay_net(bot->bot);
00606 egg_iprintf(bot->idx, "el");
00607 } else {
00608 sockbuf_delete(bot->idx);
00609 }
00610 return 0;
00611 }
00612
00613 static int sending_login(bot_t *bot, char *src, char *cmd, int argc, char *argv[], int len)
00614 {
00615 if (src && strcmp(src, bot->user->handle)) {
00616 egg_iprintf(bot->idx, "error :Wrong bot.");
00617 sockbuf_delete(bot->idx);
00618 return 0;
00619 }
00620 if (!strcasecmp(cmd, "PROTO")) {
00621 if (bot->proto) {
00622 egg_iprintf(bot->idx, "error :Been there, done that.");
00623 sockbuf_delete(bot->idx);
00624 return 0;
00625 }
00626 bot->proto = malloc(sizeof(*bot->proto));
00627 bot->proto->dummy = 0;
00628 egg_iprintf(bot->idx, ":%s hello %s", botnet_get_name(), bot->user->handle);
00629 } else if (!strcasecmp(cmd, "PASSREQ")) {
00630 char buf[33];
00631 unsigned char hash[16];
00632 MD5_CTX md5;
00633 if (argc != 1 || !bot->proto || !bot->pass || !*bot->pass) {
00634 if (!bot->pass) putlog(LOG_MISC, "*", "botnet error: password on %s needs to be reset.", bot->user->handle);
00635 egg_iprintf(bot->idx, "error :Expected something else.");
00636 sockbuf_delete(bot->idx);
00637 return 0;
00638 }
00639 MD5_Init(&md5);
00640 MD5_Update(&md5, argv[0], len);
00641 MD5_Update(&md5, bot->pass, strlen(bot->pass));
00642 MD5_Final(hash, &md5);
00643 MD5_Hex(hash, buf);
00644 egg_iprintf(bot->idx, "pass %s", buf);
00645 *bot->pass = 0;
00646 } else if (!strcasecmp(cmd, "THISBOT")) {
00647 xml_node_t *info;
00648
00649 if (argc != 4) {
00650 sockbuf_delete(bot->idx);
00651 return 0;
00652 }
00653 egg_iprintf(bot->idx, ":%s thisbot eggdrop %s %s :%s", botnet_get_name(), b64enc_int(1090000), "eggdrop1.9.0+cvs", "some informative stuff");
00654 free(bot->pass);
00655 bot->pass = NULL;
00656 bot->linking = 0;
00657
00658 info = xml_node_new();
00659 xml_node_set_str(argv[0], info, "type", 0, (void *) 0);
00660 xml_node_set_int(b64dec_int(argv[1]), info, "numversion", 0, (void *) 0);
00661 xml_node_set_str(argv[2], info, "version", 0, (void *) 0);
00662
00663 bot->bot = botnet_new(bot->user->handle, bot->user, NULL, NULL, info, &bothandler, bot, &bot_owner, 0);
00664 socktimer_on(bot->idx, 90, TIMER_REPEAT, do_ping, bot, &generic_owner);
00665 botnet_replay_net(bot->bot);
00666 egg_iprintf(bot->idx, "el");
00667 } else {
00668 sockbuf_delete(bot->idx);
00669 }
00670 return 0;
00671 }
00672
00673 static int idx_on_read(void *client_data, int idx, char *data, int len)
00674 {
00675 int argc = 0;
00676 char *start = data, *p, *srcstr = NULL, *argv[22];
00677 bot_t *bot = client_data;
00678 botnet_entity_t src;
00679
00680 if (!len) return 0;
00681 if (*data == ':') {
00682 srcstr = data + 1;
00683 p = strchr(srcstr, ' ');
00684 if (!p) return 0;
00685 *p = 0;
00686 data = p + 1;
00687 while (isspace(*data)) ++data;
00688 }
00689
00690 while (*data) {
00691 argv[argc++] = data;
00692 if (*data == ':') {
00693 argv[argc - 1]++;
00694 break;
00695 }
00696 if (argc == 21) break;
00697 p = strchr(data, ' ');
00698 if (!p) break;
00699 *p = 0;
00700 data = p + 1;
00701 while (isspace(*data)) ++data;
00702 }
00703
00704 if (!argc) return 0;
00705
00706 len -= argv[argc - 1] - start;
00707 argv[argc] = NULL;
00708
00709 if (!strcasecmp(argv[0], "error")) {
00710 putlog(LOG_MISC, "*", _("Botnet: Error from %s: %s"), bot->user ? bot->user->handle : "unknown", argv[1] ? argv[1] : "no reason");
00711 if (bot->bot) botnet_delete(bot->bot, "Error from bot.");
00712 else sockbuf_delete(bot->idx);
00713 return 0;
00714 }
00715
00716 if (!bot->bot) {
00717 if (bot->incoming) return recving_login(bot, srcstr, argv[0], argc - 1, argv + 1, len);
00718 else return sending_login(bot, srcstr, argv[0], argc - 1, argv + 1, len);
00719 }
00720
00721 if (srcstr) {
00722 char *at;
00723 botnet_bot_t *srcbot;
00724
00725 at = strchr(srcstr, '@');
00726 if (get_entity(&src, srcstr)) {
00727 if (at && !*at) putlog(LOG_MISC, "*", _("Botnet: Desync! %s says %s came from %s@%s who doesn't exist!"), bot->bot->name, argv[0], srcstr, at + 1);
00728 else putlog(LOG_MISC, "*", _("Botnet: Desync! %s says %s came from %s who doesn't exist!"), bot->bot->name, argv[0], srcstr);
00729 return 0;
00730 }
00731 if (src.what == ENTITY_BOT) srcbot = src.bot;
00732 else srcbot = src.user->bot;
00733 if (botnet_check_direction(bot->bot, srcbot)) return 0;
00734 } else {
00735 set_bot_entity(&src, bot->bot);
00736 }
00737
00738 int min = 0, max = cmd_num - 1, cur = max / 2;
00739 while (min <= max) {
00740 int ret = strcasecmp(argv[0], cmd_mapping[cur].cmd);
00741 if (!ret) {
00742 if (argc < cmd_mapping[cur].min_argc) return 0;
00743 if (cmd_mapping[cur].source && cmd_mapping[cur].source != src.what) return 0;
00744 return cmd_mapping[cur].function(bot, &src, argv[0], argc - 1, argv + 1, len);
00745 } else if (ret < 0) {
00746 max = cur - 1;
00747 } else {
00748 min = cur + 1;
00749 }
00750 cur = (min + max) / 2;
00751 }
00752 putlog(LOG_MISC, "*", _("Botnet: Got unknown something from %s: %s"), bot->user->handle, argv[0]);
00753 return 0;
00754 }
00755
00756 static int idx_on_eof(void *client_data, int idx, int err, const char *errmsg)
00757 {
00758 bot_t *bot = client_data;
00759
00760 if (!bot->bot) {
00761 if (!bot->incoming) {
00762 if (bot->user->flags & USER_LINKING_BOT) botnet_link_failed(bot->user, errmsg ? errmsg : "no error");
00763 bot->user = NULL;
00764 }
00765 sockbuf_delete(idx);
00766 } else {
00767 putlog(LOG_MISC, "*", _("eof from %s (%s)."), bot->bot->name, errmsg ? errmsg : "no error");
00768 botnet_delete(bot->bot, errmsg ? errmsg : "eof");
00769 }
00770
00771 return 0;
00772 }
00773
00774 static int idx_on_delete(event_owner_t *owner, void *client_data)
00775 {
00776 bot_t *bot = client_data;
00777
00778 bot->idx = -1;
00779 if (bot->bot) botnet_delete(bot->bot, _("Socket deleted."));
00780 else if (!bot->incoming && bot->user && bot->user->flags & USER_LINKING_BOT) botnet_link_failed(bot->user, "Socket deleted.");
00781
00782 if (bot->pass) free(bot->pass);
00783 free(bot);
00784
00785 return 0;
00786 }
00787
00800 static int bot_on_delete(event_owner_t *owner, void *client_data)
00801 {
00802 bot_t *bot = client_data;
00803
00804 bot->bot = NULL;
00805 if (bot->idx >= 0) sockbuf_delete(bot->idx);
00806
00807 return 0;
00808 }
00809
00810 static void bot_init()
00811 {
00812 int real_port;
00813 void *config_root;
00814
00815 botnet_config.port = 3333;
00816
00817 config_root = config_get_root("eggdrop");
00818 config_link_table(botnet_config_vars, config_root, "botnet", 0, NULL);
00819 config_update_table(botnet_config_vars, config_root, "botnet", 0, NULL);
00820
00821 listen_idx = egg_server(botnet_config.ip, botnet_config.port, &real_port);
00822 sockbuf_set_handler(listen_idx, &server_handler, NULL, &generic_owner);
00823
00824 bind_add_simple(BTN_BOTNET_REQUEST_LINK, NULL, "eggdrop", do_link);
00825 }
00826
00827 static int bot_close(int why)
00828 {
00829 void *config_root;
00830
00831 config_root = config_get_root("eggdrop");
00832 config_unlink_table(botnet_config_vars, config_root, "botnet", 0, NULL);
00833
00834 sockbuf_delete(listen_idx);
00835
00836 bind_rem_simple(BTN_BOTNET_REQUEST_LINK, NULL, "eggdrop", do_link);
00837
00838 return 0;
00839 }
00840
00841 int botnet_LTX_start(egg_module_t *modinfo)
00842 {
00843 bot_owner.module = sock_owner.module = generic_owner.module = modinfo;
00844 modinfo->name = "botnet";
00845 modinfo->author = "eggdev";
00846 modinfo->version = "1.0.0";
00847 modinfo->description = "botnet support";
00848 modinfo->close_func = bot_close;
00849
00850 bot_init();
00851
00852 return 0;
00853 }